37 Commits
v0.1 ... v0.3

Author SHA1 Message Date
Krzysiek Egzmont
d86ccaafcd README updated 2023-10-02 03:31:02 +02:00
Krzysiek Egzmont
d826ecb0ae Merge remote-tracking branch 'remotes/OneOfEleven/main' 2023-10-02 03:21:18 +02:00
OneOfEleven
e0aa1a83be Fix ENABLE_KEEP_MEM_NAME stuff 2023-10-02 02:02:34 +01:00
Krzysiek Egzmont
e64bf6bbd6 Merge branch '1o11main' 2023-10-02 03:01:28 +02:00
OneOfEleven
aafc93c2ee Forgot to remove unrequired batcal code 2023-10-02 01:44:33 +01:00
OneOfEleven
58eced120e On-screen charge level bug fixed 2023-10-02 01:28:56 +01:00
OneOfEleven
bbf8a7061e Fixed CTCSS int overflow bug 2023-10-02 01:19:14 +01:00
OneOfEleven
aea80cb046 Updated menu battery cal from egzumer 2023-10-02 01:09:35 +01:00
OneOfEleven
4333fdeb3a Added menu battery calibration from egzumer (hidden menu option) 2023-10-02 00:38:59 +01:00
OneOfEleven
a9aa37e043 Pulled in egzumer's battery percentage ! 2023-10-01 22:14:45 +01:00
OneOfEleven
1fc1a102ea Merge pull request #85 from wutje/smaller_keyboard_handling
Keyboard: Save 240 bytes of flash.
2023-10-01 21:55:07 +01:00
OneOfEleven
86d2dade7a Menu update + PTT-ID fix 2023-10-01 21:50:05 +01:00
Wouter van Gulik
6f7bb75b52 Keyboard: Save 240 bytes of flash.
Move definition to a table.
Set and read the pins all at once.
Drop extra delays.
Use existing I2C_Stop to generate proper stop condition.
2023-10-01 22:34:03 +02:00
Krzysiek Egzmont
82b8f6755f docker build script 2023-10-01 22:09:52 +02:00
OneOfEleven
8caff25b7c Possible DW AM TX fix 2023-10-01 19:56:04 +01:00
OneOfEleven
c644b30b2f 1750 compile option + maybe DW AM TX fix 2023-10-01 19:17:51 +01:00
OneOfEleven
de174d072c Removed unneeded function call param (band) 2023-10-01 17:19:38 +01:00
OneOfEleven
c3c344daec Menu play + reduce AM AGC hysteresis very slightly. 2023-10-01 15:07:34 +01:00
OneOfEleven
fc1bc8791c Menu update, F-LOCK CE update, main screen fix 2023-10-01 14:34:51 +01:00
Krzysiek Egzmont
5c413eb7cd Calibration description readme 2023-10-01 14:12:37 +02:00
OneOfEleven
fa4ae2caa6 Fix what I did last 2023-10-01 12:44:22 +01:00
Krzysiek Egzmont
e092145542 Remove Alarm function to save space 2023-10-01 13:44:20 +02:00
Krzysiek Egzmont
5ba5b9f2eb Merge OneOfEleven at commit 'b7241f77efb42bca8443b1b129678c64bdb6dbab' 2023-10-01 13:42:05 +02:00
Krzysiek Egzmont
4fb8f7b0e7 Spectrum analyzer updated
ffe1573a4b
2023-10-01 12:38:55 +02:00
Krzysiek Egzmont
0f210ff872 Battery calibration function added 2023-10-01 12:17:49 +02:00
OneOfEleven
b45043aab2 Rename compile option ENABLE_NO_SCAN_TIMEOUT to ENABLE_CODE_SCAN_TIMEOUT 2023-10-01 10:27:10 +01:00
OneOfEleven
ba3decad78 Show "TX DISABLE" on the correct VFO/screen line 2023-10-01 10:15:24 +01:00
OneOfEleven
7df7461d31 Fix dual-watch so that TX only uses the main channel (black triangle) 2023-10-01 09:14:19 +01:00
OneOfEleven
b7241f77ef Forgot to save/update radio.c 2023-10-01 00:30:13 +01:00
OneOfEleven
ae6cf797cb Adjusted rssi bar to start at S4, end at S9+30 2023-10-01 00:10:45 +01:00
OneOfEleven
618a184bf1 S0 meter now -147dBm 2023-10-01 00:04:51 +01:00
OneOfEleven
b0f6be2c7c Make all 10 squelch settings slightly more sensitive 2023-09-30 23:56:31 +01:00
OneOfEleven
aba9e435f2 Fix lower squelch-1 setting bug 2023-09-30 20:21:37 +01:00
OneOfEleven
6546f9d4ce s-meter now shows S9+ in 1dB increments 2023-09-30 20:03:09 +01:00
OneOfEleven
1eac6018ba Even easier to change 'S0' base dBm level on the s-meter. 2023-09-30 17:14:48 +01:00
Krzysiek Egzmont
f32eeda636 README changed 2023-09-30 16:12:47 +02:00
OneOfEleven
9493f34c23 Various DTMF bug fixes and renames 2023-09-30 11:22:19 +01:00
48 changed files with 1167 additions and 791 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
firmware
/firmware.packed.bin
/firmware.bin
/compiled-firmware

12
Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM archlinux:latest
RUN pacman -Syyu base-devel --noconfirm
RUN pacman -Syyu arm-none-eabi-gcc --noconfirm
RUN pacman -Syyu arm-none-eabi-newlib --noconfirm
RUN pacman -Syyu git --noconfirm
RUN pacman -Syyu python-pip --noconfirm
RUN pacman -Syyu python-crcmod --noconfirm
WORKDIR /app
COPY . .
RUN git submodule update --init --recursive
#RUN make && cp firmware* compiled-firmware/

View File

@@ -4,13 +4,15 @@
# 1 = enable
#
ENABLE_SWD := 0
ENABLE_OVERLAY := 1
ENABLE_OVERLAY := 0
ENABLE_LTO := 1
ENABLE_UART := 1
ENABLE_AIRCOPY := 0
ENABLE_FMRADIO := 0
ENABLE_NOAA := 0
ENABLE_VOICE := 0
ENABLE_ALARM := 1
ENABLE_ALARM := 0
ENABLE_TX1750 := 0
ENABLE_BIG_FREQ := 1
ENABLE_SMALL_BOLD := 1
ENABLE_KEEP_MEM_NAME := 1
@@ -19,22 +21,28 @@ ENABLE_TX_WHEN_AM := 0
ENABLE_CTCSS_TAIL_PHASE_SHIFT := 1
ENABLE_MAIN_KEY_HOLD := 1
ENABLE_BOOT_BEEPS := 0
ENABLE_COMPANDER := 1
ENABLE_COMPANDER := 0
ENABLE_SHOW_CHARGE_LEVEL := 1
ENABLE_REVERSE_BAT_SYMBOL := 1
ENABLE_NO_SCAN_TIMEOUT := 1
ENABLE_CODE_SCAN_TIMEOUT := 0
ENABLE_AM_FIX := 1
ENABLE_AM_FIX_SHOW_DATA := 1
ENABLE_SQUELCH1_LOWER := 0
ENABLE_SQUELCH_LOWER := 1
ENABLE_RSSI_BAR := 1
ENABLE_AUDIO_BAR := 1
ENABLE_AUDIO_BAR := 0
ENABLE_SPECTRUM := 1
#ENABLE_COPY_CHAN_TO_VFO := 1
#ENABLE_SINGLE_VFO_CHAN := 1
#ENABLE_BAND_SCOPE := 1
#ENABLE_COPY_CHAN_TO_VFO := 1
#ENABLE_SINGLE_VFO_CHAN := 1
#ENABLE_BAND_SCOPE := 1
#############################################################
TARGET = firmware
ifeq ($(ENABLE_LTO),1)
ENABLE_OVERLAY := 0
endif
BSP_DEFINITIONS := $(wildcard hardware/*/*.def)
BSP_HEADERS := $(patsubst hardware/%,bsp/%,$(BSP_DEFINITIONS))
BSP_HEADERS := $(patsubst %.def,%.h,$(BSP_HEADERS))
@@ -158,6 +166,11 @@ CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delet
#CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu99 -MMD
#CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu11 -MMD
ifeq ($(ENABLE_LTO),1)
# CFLAGS += -flto
CFLAGS += -flto=2
endif
CFLAGS += -DPRINTF_INCLUDE_CONFIG_H
CFLAGS += -DGIT_HASH=\"$(GIT_HASH)\"
@@ -167,15 +180,15 @@ endif
ifeq ($(ENABLE_SWD),1)
CFLAGS += -DENABLE_SWD
endif
ifeq ($(ENABLE_OVERLAY),1)
CFLAGS += -DENABLE_OVERLAY
endif
ifeq ($(ENABLE_AIRCOPY),1)
CFLAGS += -DENABLE_AIRCOPY
endif
ifeq ($(ENABLE_FMRADIO),1)
CFLAGS += -DENABLE_FMRADIO
endif
ifeq ($(ENABLE_OVERLAY),1)
CFLAGS += -DENABLE_OVERLAY
endif
ifeq ($(ENABLE_UART),1)
CFLAGS += -DENABLE_UART
endif
@@ -194,8 +207,11 @@ endif
ifeq ($(ENABLE_ALARM),1)
CFLAGS += -DENABLE_ALARM
endif
ifeq ($(ENABLE_TX1750),1)
CFLAGS += -DENABLE_TX1750
endif
ifeq ($(ENABLE_KEEP_MEM_NAME),1)
CFLAGS += -DKEEP_MEM_NAME
CFLAGS += -DENABLE_KEEP_MEM_NAME
endif
ifeq ($(ENABLE_WIDE_RX),1)
CFLAGS += -DENABLE_WIDE_RX
@@ -221,8 +237,8 @@ endif
ifeq ($(ENABLE_REVERSE_BAT_SYMBOL),1)
CFLAGS += -DENABLE_REVERSE_BAT_SYMBOL
endif
ifeq ($(ENABLE_NO_SCAN_TIMEOUT),1)
CFLAGS += -DENABLE_NO_SCAN_TIMEOUT
ifeq ($(ENABLE_CODE_SCAN_TIMEOUT),1)
CFLAGS += -DENABLE_CODE_SCAN_TIMEOUT
endif
ifeq ($(ENABLE_AM_FIX),1)
CFLAGS += -DENABLE_AM_FIX
@@ -233,8 +249,8 @@ endif
ifeq ($(ENABLE_AM_FIX_TEST1),1)
CFLAGS += -DENABLE_AM_FIX_TEST1
endif
ifeq ($(ENABLE_SQUELCH1_LOWER),1)
CFLAGS += -DENABLE_SQUELCH1_LOWER
ifeq ($(ENABLE_SQUELCH_LOWER),1)
CFLAGS += -DENABLE_SQUELCH_LOWER
endif
ifeq ($(ENABLE_RSSI_BAR),1)
CFLAGS += -DENABLE_RSSI_BAR

View File

@@ -1,10 +1,20 @@
# Main features:
- OneOfEleven mods, including AM fix
- fagci spectrum analyzer
- better battery percentage calculation (based on real measurement)
- fagci spectrum analyzer (**F+5** to turn on)
- better battery percentage calculation (based on real measurement, battery calibration recommended)
- battery calibration option available available in the menu (instructions below)
<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
@@ -16,9 +26,10 @@ https://github.com/fagci/uv-k5-firmware-fagci-mod/tree/refactor
All is a cloned and customized version of DualTachyon's open firmware found here ..
https://github.com/DualTachyon/uv-k5-firmware
https://github.com/DualTachyon/uv-k5-firmware .. a cool achievement !
A cool achievement
Use this firmware at your own risk (entirely). There is absolutely no guarantee that it will work in any way shape or form on your radio(s), it may even brick your radio(s), in which case, you'd need to buy another radio.
Anyway, have fun.
# Radio performance
@@ -38,13 +49,15 @@ You'll find the options at the top of "Makefile" ('0' = disable, '1' = enable) .
```
ENABLE_SWD := 0 only needed if using CPU's SWD port (debugging/programming)
ENABLE_OVERLAY := 1 cpu FLASH stuff
ENABLE_OVERLAY := 0 cpu FLASH stuff
ENABLE_LTO := 0 **experimental, reduces size of compiled firmware but might break EEPROM reads - DISABLE overlay if you enable this
ENABLE_UART := 1 without this you can't configure radio via PC
ENABLE_AIRCOPY := 0 easier to just enter frequency
ENABLE_FMRADIO := 1 WBFM VHF band 2 RX
ENABLE_NOAA := 0 everything NOAA
ENABLE_VOICE := 0 want to hear voices ?
ENABLE_ALARM := 0 TX alarms
ENABLE_1750HZ := 0 side key 1750Hz TX tone
ENABLE_BIG_FREQ := 0 big font frequencies
ENABLE_SMALL_BOLD := 1 bold channel name/no. (when name + freq channel display mode)
ENABLE_KEEP_MEM_NAME := 1 maintain channel name when (re)saving memory channel
@@ -56,10 +69,10 @@ ENABLE_BOOT_BEEPS := 0 give user audio feedback on volume knob
ENABLE_COMPANDER := 1 compander option (per channel)
ENABLE_SHOW_CHARGE_LEVEL := 0 show the charge level when the radio is on charge
ENABLE_REVERSE_BAT_SYMBOL := 1 mirror the battery symbol on the status bar (+ pole on the right)
ENABLE_NO_SCAN_TIMEOUT := 1 remove the 32 sec timeout from the CTCSS/DCS scan (press exit butt to end scan)
ENABLE_CODE_SCAN_TIMEOUT := 0 enable/disable 32-sec CTCSS/DCS scan timeout (press exit butt to end scan if disabled)
ENABLE_AM_FIX := 1 dynamically adjust the front end gains when in AM mode to helo prevent AM demodulator saturation - ignore the on-screen RSSI (for now)
ENABLE_AM_FIX_SHOW_DATA := 1 show debug data for the AM fix
ENABLE_SQUELCH1_LOWER := 0 adjusts squelch setting '1' to be more sensitive - I plan to let user adjust it in the menu
ENABLE_SQUELCH_LOWER := 1 squelch settings more sensitive - plan to let user adjust it in the menu
ENABLE_RSSI_BAR := 1 enable a dBm/Sx RSSI bar graph level
ENABLE_AUDIO_BAR := 0 experimental, display an audo bar level when TX'ing
#ENABLE_COPY_CHAN_TO_VFO := 1 not yet implemented - copy the channel into the VFO

View File

@@ -438,7 +438,7 @@ const uint8_t orig_pga = 6; // -3dB
}
}
if (diff_dB >= -4) // 4dB hysterisis (help reduce gain hunting)
if (diff_dB >= -6) // 6dB hysterisis (help reduce gain hunting)
hold_counter[vfo] = 30; // 300ms hold
if (hold_counter[vfo] == 0)

View File

@@ -14,6 +14,8 @@
* limitations under the License.
*/
#include <string.h>
#include "app/action.h"
#include "app/app.h"
#include "app/dtmf.h"
@@ -167,6 +169,11 @@ void ACTION_Scan(bool bRestart)
gMonitor = false;
DTMF_clear_RX();
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
RADIO_SelectVfos();
#ifdef ENABLE_NOAA
@@ -228,17 +235,27 @@ void ACTION_Vox(void)
gUpdateStatus = true;
}
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
static void ACTION_AlarmOr1750(bool b1750)
{
gInputBoxIndex = 0;
gAlarmState = b1750 ? ALARM_STATE_TX1750 : ALARM_STATE_TXALARM;
gAlarmRunningCounter = 0;
gFlagPrepareTX = true;
gInputBoxIndex = 0;
#if defined(ENABLE_ALARM) && defined(ENABLE_TX1750)
gAlarmState = b1750 ? ALARM_STATE_TX1750 : ALARM_STATE_TXALARM;
gAlarmRunningCounter = 0;
#elif defined(ENABLE_ALARM)
gAlarmState = ALARM_STATE_TXALARM;
gAlarmRunningCounter = 0;
#else
gAlarmState = ALARM_STATE_TX1750;
#endif
gFlagPrepareTX = true;
gRequestDisplayScreen = DISPLAY_MAIN;
}
#endif
#ifdef ENABLE_FMRADIO
void ACTION_FM(void)
{
@@ -361,7 +378,7 @@ void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
break;
#endif
case ACTION_OPT_1750:
#ifdef ENABLE_ALARM
#ifdef ENABLE_TX1750
ACTION_AlarmOr1750(true);
#endif
break;

159
app/app.c
View File

@@ -182,6 +182,10 @@ static void APP_HandleIncoming(void)
if (!g_SquelchLost)
{ // squelch is closed
if (gDTMF_RX_index > 0)
DTMF_clear_RX();
if (gCurrentFunction != FUNCTION_FOREGROUND)
{
FUNCTION_Select(FUNCTION_FOREGROUND);
@@ -214,12 +218,13 @@ static void APP_HandleIncoming(void)
if (!bFlag)
return;
DTMF_HandleRequest();
if (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF)
{ // not scanning
if (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED)
{ // DTMF is enabled
{ // DTMF DCD is enabled
// DTMF_HandleRequest();
if (gDTMF_CallState == DTMF_CALL_STATE_NONE)
{
if (gRxReceptionMode == RX_MODE_DETECTED)
@@ -234,7 +239,6 @@ static void APP_HandleIncoming(void)
gUpdateStatus = true;
gUpdateDisplay = true;
return;
}
}
@@ -777,34 +781,40 @@ void APP_CheckRadioInterrupts(void)
// g_CTCSS_Lost = true;
if (interrupt_status_bits & BK4819_REG_02_DTMF_5TONE_FOUND)
{ // save the new DTMF RX'ed character
// fetch the RX'ed char
{ // save the RX'ed DTMF character
const char c = DTMF_GetCharacter(BK4819_GetDTMF_5TONE_Code());
if (c != 0xff)
{
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_INCOMING ||
gCurrentFunction == FUNCTION_MONITOR)
if (gCurrentFunction != FUNCTION_TRANSMIT)
{
gDTMF_RequestPending = true;
gDTMF_RecvTimeout = DTMF_RX_timeout_500ms;
// shift the RX buffer down one - if need be
if (gDTMF_WriteIndex >= sizeof(gDTMF_Received))
memmove(gDTMF_Received, &gDTMF_Received[1], --gDTMF_WriteIndex);
gDTMF_Received[gDTMF_WriteIndex++] = c;
if (gSetting_live_DTMF_decoder)
{
size_t len = strlen(gDTMF_RX_live);
if (len >= (sizeof(gDTMF_RX_live) - 1))
{ // make room
memmove(&gDTMF_RX_live[0], &gDTMF_RX_live[1], sizeof(gDTMF_RX_live) - 1);
len--;
}
gDTMF_RX_live[len++] = c;
gDTMF_RX_live[len] = 0;
gDTMF_RX_live_timeout = DTMF_RX_live_timeout_500ms; // time till we delete it
gUpdateDisplay = true;
}
// live DTMF decoder
size_t len = strlen(gDTMF_RX_live);
// shift the RX buffer down one - if need be
if (len >= (sizeof(gDTMF_RX_live) - 1))
memmove(&gDTMF_RX_live[0], &gDTMF_RX_live[1], --len);
gDTMF_RX_live[len++] = c;
gDTMF_RX_live[len] = 0;
gDTMF_RX_live_timeout = DTMF_RX_live_timeout_500ms; // time till we delete it
gUpdateDisplay = true;
if (gRxVfo->DTMF_DECODING_ENABLE || gSetting_KILLED)
{
if (gDTMF_RX_index >= (sizeof(gDTMF_RX) - 1))
{ // make room
memmove(&gDTMF_RX[0], &gDTMF_RX[1], sizeof(gDTMF_RX) - 1);
gDTMF_RX_index--;
}
gDTMF_RX[gDTMF_RX_index++] = c;
gDTMF_RX[gDTMF_RX_index] = 0;
gDTMF_RX_timeout = DTMF_RX_timeout_500ms; // time till we delete it
gDTMF_RX_pending = true;
DTMF_HandleRequest();
DTMF_HandleRequest();
}
}
}
}
@@ -1666,9 +1676,9 @@ void cancelUserInputModes(void)
gKeyInputCountdown = 0;
if (gDTMF_InputMode || gInputBoxIndex > 0)
{
memset(gDTMF_String, 0, sizeof(gDTMF_String));
gDTMF_InputMode = false;
gDTMF_InputIndex = 0;
memset(gDTMF_String, 0, sizeof(gDTMF_String));
gInputBoxIndex = 0;
gRequestDisplayScreen = DISPLAY_MAIN;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
@@ -1692,11 +1702,18 @@ void APP_TimeSlice500ms(void)
{
if (--gDTMF_RX_live_timeout == 0)
{
gDTMF_RX_live[0] = 0;
gUpdateDisplay = true;
if (gDTMF_RX_live[0] != 0)
{
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
gUpdateDisplay = true;
}
}
}
if (gDTMF_RX_timeout > 0)
if (--gDTMF_RX_timeout == 0)
DTMF_clear_RX();
// Skipped authentic device check
#ifdef ENABLE_FMRADIO
@@ -1711,8 +1728,16 @@ void APP_TimeSlice500ms(void)
if (gReducedService)
{
BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent);
if (gBatteryCurrent > 500 || gBatteryCalibration[3] < gBatteryCurrentVoltage)
overlay_FLASH_RebootToBootloader();
{
#ifdef ENABLE_OVERLAY
overlay_FLASH_RebootToBootloader();
#else
NVIC_SystemReset();
#endif
}
return;
}
@@ -1807,7 +1832,7 @@ void APP_TimeSlice500ms(void)
}
else
#endif
#ifdef ENABLE_NO_SCAN_TIMEOUT
#ifndef ENABLE_CODE_SCAN_TIMEOUT
if (gScreenToDisplay != DISPLAY_SCANNER)
#endif
GUI_SelectNextDisplay(DISPLAY_MAIN);
@@ -1893,7 +1918,7 @@ void APP_TimeSlice500ms(void)
{
gScanProgressIndicator++;
#ifndef ENABLE_NO_SCAN_TIMEOUT
#ifdef ENABLE_CODE_SCAN_TIMEOUT
if (gScanProgressIndicator > 32)
{
if (gScanCssState == SCAN_CSS_STATE_SCANNING && !gScanSingleFrequency)
@@ -1908,7 +1933,20 @@ void APP_TimeSlice500ms(void)
gUpdateDisplay = true;
}
if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE)
if (gCurrentFunction != FUNCTION_TRANSMIT)
{
if (gDTMF_DecodeRingCountdown_500ms > 0)
{ // make "ring-ring" sound
gDTMF_DecodeRingCountdown_500ms--;
AUDIO_PlayBeep(BEEP_880HZ_200MS);
}
}
else
gDTMF_DecodeRingCountdown_500ms = 0;
if (gDTMF_CallState != DTMF_CALL_STATE_NONE &&
gCurrentFunction != FUNCTION_TRANSMIT &&
gCurrentFunction != FUNCTION_RECEIVE)
{
if (gDTMF_AUTO_RESET_TIME > 0)
{
@@ -1918,15 +1956,6 @@ void APP_TimeSlice500ms(void)
gUpdateDisplay = true;
}
}
if (gDTMF_DecodeRing && gDTMF_DecodeRingCountdown_500ms > 0)
{
if ((--gDTMF_DecodeRingCountdown_500ms % 3) == 0)
AUDIO_PlayBeep(BEEP_440HZ_500MS);
if (gDTMF_DecodeRingCountdown_500ms == 0)
gDTMF_DecodeRing = false;
}
}
if (gDTMF_IsTx && gDTMF_TxStopCountdown_500ms > 0)
@@ -1937,18 +1966,9 @@ void APP_TimeSlice500ms(void)
gUpdateDisplay = true;
}
}
if (gDTMF_RecvTimeout > 0)
{
if (--gDTMF_RecvTimeout == 0)
{
gDTMF_WriteIndex = 0;
memset(gDTMF_Received, 0, sizeof(gDTMF_Received));
}
}
}
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
static void ALARM_Off(void)
{
gAlarmState = ALARM_STATE_OFF;
@@ -2022,9 +2042,13 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
if (Key == KEY_EXIT && bKeyPressed && bKeyHeld && gDTMF_RX_live[0] != 0)
{ // clear the live DTMF decoder if the EXIT key is held
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live[0] = 0;
gUpdateDisplay = true;
if (gDTMF_RX_live[0] != 0)
{
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
gUpdateDisplay = true;
}
}
if (!bKeyPressed)
@@ -2065,10 +2089,12 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
BACKLIGHT_TurnOn();
if (gDTMF_DecodeRing)
{
gDTMF_DecodeRing = false;
if (gDTMF_DecodeRingCountdown_500ms > 0)
{ // cancel the ringing
gDTMF_DecodeRingCountdown_500ms = 0;
AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL);
if (Key != KEY_PTT)
{
gPttWasReleased = true;
@@ -2115,7 +2141,8 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
Key != KEY_EXIT &&
Key != KEY_SIDE1 &&
Key != KEY_SIDE2 &&
Key != KEY_STAR)
Key != KEY_STAR &&
Key != KEY_MENU)
{
if (gScanState != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF)
{ // frequency or CTCSS/DCS scanning
@@ -2147,21 +2174,19 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
}
if (gWasFKeyPressed && Key > KEY_9 && Key != KEY_F && Key != KEY_STAR && Key != KEY_MENU)
if (gWasFKeyPressed && Key > KEY_9 && Key != KEY_F && Key != KEY_STAR)
// if (gWasFKeyPressed && Key > KEY_9 && Key != KEY_F && Key != KEY_STAR && Key != KEY_MENU)
{
gWasFKeyPressed = false;
gUpdateStatus = true;
}
if (gF_LOCK && (Key == KEY_PTT || Key == KEY_SIDE2 || Key == KEY_SIDE1))
return;
if (!bFlag)
{
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // transmitting
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState == ALARM_STATE_OFF)
#endif
{
@@ -2203,7 +2228,7 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
else
{
if (gEeprom.DTMF_SIDE_TONE)
{
{ // user will here the DTMF tones in speaker
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gEnableSpeaker = true;
}
@@ -2217,7 +2242,7 @@ static void APP_ProcessKey(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
}
}
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
else
if (!bKeyHeld && bKeyPressed)
{
@@ -2409,8 +2434,8 @@ Skip:
if (gFlagRefreshSetting)
{
MENU_ShowCurrentSetting();
gFlagRefreshSetting = false;
MENU_ShowCurrentSetting();
}
if (gFlagStartScan)

View File

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

View File

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

View File

@@ -458,9 +458,17 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
{ // exit key pressed
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (gDTMF_CallState != DTMF_CALL_STATE_NONE && gCurrentFunction != FUNCTION_TRANSMIT)
{ // clear CALL mode being displayed
gDTMF_CallState = DTMF_CALL_STATE_NONE;
gUpdateDisplay = true;
return;
}
#ifdef ENABLE_FMRADIO
if (!gFmRadioMode)
#endif
@@ -499,7 +507,8 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
}
if (bKeyHeld && bKeyPressed)
{
{ // exit key held down
if (gInputBoxIndex > 0)
{ // cancel key input mode (channel/frequency entry)
gDTMF_InputMode = false;
@@ -515,7 +524,7 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
{
if (bKeyHeld)
{ // key held down (long press)
{ // menu key held down (long press)
if (bKeyPressed)
{
@@ -566,6 +575,7 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
// TODO: finish this
//gEeprom.RX_CHANNEL = () & 1; // swap to the VFO
@@ -583,17 +593,20 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
return;
}
if (!bKeyPressed)
{
bool bFlag;
if (!bKeyPressed && !gDTMF_InputMode)
{ // menu key released
const bool bFlag = (gInputBoxIndex == 0);
gInputBoxIndex = 0;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
bFlag = (gInputBoxIndex == 0);
gInputBoxIndex = 0;
if (bFlag)
{
gFlagRefreshSetting = true;
gFlagRefreshSetting = true;
gFlagBackupSetting = true;
gRequestDisplayScreen = DISPLAY_MENU;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_MENU;
#endif
@@ -725,7 +738,7 @@ static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
{ // step/down in frequency
const uint32_t frequency = APP_SetFrequencyByStep(gTxVfo, Direction);
if (RX_FREQUENCY_Check(frequency) < 0)
if (RX_freq_check(frequency) < 0)
{ // frequency not allowed
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;

View File

@@ -32,6 +32,7 @@
#include "driver/gpio.h"
#include "driver/keyboard.h"
#include "frequencies.h"
#include "helper/battery.h"
#include "misc.h"
#include "settings.h"
#if defined(ENABLE_OVERLAY)
@@ -46,6 +47,27 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
void writeXtalFreqCal(const int32_t value)
{
struct
{
int16_t BK4819_XtalFreqLow;
uint16_t EEPROM_1F8A;
uint16_t EEPROM_1F8C;
uint8_t VOLUME_GAIN;
uint8_t DAC_GAIN;
} __attribute__((packed)) Misc;
gEeprom.BK4819_XTAL_FREQ_LOW = value;
BK4819_WriteRegister(BK4819_REG_3B, 22656 + gEeprom.BK4819_XTAL_FREQ_LOW);
// radio 1 .. 04 00 46 00 50 00 2C 0E
// radio 2 .. 05 00 46 00 50 00 2C 0E
EEPROM_ReadBuffer(0x1F88, &Misc, 8);
Misc.BK4819_XtalFreqLow = gEeprom.BK4819_XTAL_FREQ_LOW;
EEPROM_WriteBuffer(0x1F88, &Misc);
}
void MENU_StartCssScan(int8_t Direction)
{
gCssScanMode = CSS_SCAN_MODE_SCANNING;
@@ -109,11 +131,15 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
break;
case MENU_TDR:
case MENU_XB:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_CHAN) - 1;
break;
case MENU_XB:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_XB) - 1;
break;
#ifdef ENABLE_VOICE
case MENU_VOICE:
*pMin = 0;
@@ -264,6 +290,11 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
*pMax = ARRAY_SIZE(gSubMenu_PTT_ID) - 1;
break;
case MENU_VOL:
*pMin = 0;
*pMax = 2300;
break;
case MENU_BAT_TXT:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_BAT_TXT) - 1;
@@ -289,6 +320,11 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
*pMax = +50;
break;
case MENU_BATCAL:
*pMin = 1760; // 0
*pMax = 2000; // 2300
break;
default:
return -1;
}
@@ -585,19 +621,26 @@ void MENU_AcceptSetting(void)
gRequestSaveChannel = 1;
return;
case MENU_VOL:
if(gF_LOCK) {
EEPROM_WriteBuffer(0x1F40, gBatteryCalibration);
}
break;
case MENU_BAT_TXT:
gSetting_battery_text = gSubMenuSelection;
break;
case MENU_D_DCD:
gTxVfo->DTMF_DECODING_ENABLE = gSubMenuSelection;
gRequestSaveChannel = 1;
DTMF_clear_RX();
gRequestSaveChannel = 1;
return;
case MENU_D_LIVE_DEC:
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live[0] = '\0';
gSetting_live_DTMF_decoder = gSubMenuSelection;
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
if (!gSetting_live_DTMF_decoder)
BK4819_DisableDTMF();
gFlagReconfigureVfos = true;
@@ -694,25 +737,14 @@ void MENU_AcceptSetting(void)
break;
case MENU_F_CALI:
gEeprom.BK4819_XTAL_FREQ_LOW = gSubMenuSelection;
BK4819_WriteRegister(BK4819_REG_3B, 22656 + gEeprom.BK4819_XTAL_FREQ_LOW);
{
struct
{
int16_t BK4819_XtalFreqLow;
uint16_t EEPROM_1F8A;
uint16_t EEPROM_1F8C;
uint8_t VOLUME_GAIN;
uint8_t DAC_GAIN;
} __attribute__((packed)) Misc;
// radio 1 .. 04 00 46 00 50 00 2C 0E
// radio 2 .. 05 00 46 00 50 00 2C 0E
EEPROM_ReadBuffer(0x1F88, &Misc, 8);
Misc.BK4819_XtalFreqLow = gEeprom.BK4819_XTAL_FREQ_LOW;
EEPROM_WriteBuffer(0x1F88, &Misc);
}
//if (gF_LOCK)
writeXtalFreqCal(gSubMenuSelection);
return;
case MENU_BATCAL:
gBatteryCalibration[3] = gSubMenuSelection;
EEPROM_WriteBuffer(0x1F40, gBatteryCalibration);
break;
}
gRequestSaveSettings = true;
@@ -988,6 +1020,10 @@ void MENU_ShowCurrentSetting(void)
gSubMenuSelection = gTxVfo->DTMF_PTT_ID_TX_MODE;
break;
case MENU_VOL:
gSubMenuSelection = gBatteryCalibration[3];
return;
case MENU_BAT_TXT:
gSubMenuSelection = gSetting_battery_text;
return;
@@ -1073,6 +1109,19 @@ void MENU_ShowCurrentSetting(void)
case MENU_F_CALI:
gSubMenuSelection = gEeprom.BK4819_XTAL_FREQ_LOW;
break;
case MENU_BATCAL:
gSubMenuSelection = gBatteryCalibration[3];
break;
default:
return;
}
// if (gFlagBackupSetting)
{ // save a copy incase the user wants to back out
// gFlagBackupSetting = false;
gSubMenuSelection_original = gSubMenuSelection;
}
}
@@ -1127,6 +1176,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
gMenuCursor = Value - 1;
gFlagRefreshSetting = true;
gFlagBackupSetting = true;
return;
}
@@ -1142,6 +1192,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
gMenuCursor = Value - 1;
gFlagRefreshSetting = true;
gFlagBackupSetting = true;
return;
}
break;
@@ -1250,6 +1301,17 @@ static void MENU_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{
if (gIsInSubMenu)
{
// ***********************
// restore original value
if (gMenuCursor == MENU_F_CALI)
{
// if (gF_LOCK)
// writeXtalFreqCal(gSubMenuSelection_original);
}
// ***********************
if (gInputBoxIndex == 0 || gMenuCursor != MENU_OFFSET)
{
gAskForConfirmation = 0;
@@ -1264,6 +1326,8 @@ static void MENU_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
else
gInputBox[--gInputBoxIndex] = 10;
// ***********************
gRequestDisplayScreen = DISPLAY_MENU;
return;
}
@@ -1317,8 +1381,12 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
gAskForConfirmation = 0;
gIsInSubMenu = true;
gInputBoxIndex = 0;
edit_index = -1;
// if (gMenuCursor != MENU_D_LIST)
{
gInputBoxIndex = 0;
edit_index = -1;
}
return;
}
@@ -1545,8 +1613,11 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
if (!gIsInSubMenu)
{
gMenuCursor = NUMBER_AddWithWraparound(gMenuCursor, -Direction, 0, gMenuListCount - 1);
gFlagRefreshSetting = true;
gMenuCursor = NUMBER_AddWithWraparound(gMenuCursor, -Direction, 0, gMenuListCount - 1);
gFlagRefreshSetting = true;
gFlagBackupSetting = true;
gRequestDisplayScreen = DISPLAY_MENU;
if (gMenuCursor != MENU_ABR && gEeprom.BACKLIGHT == 0)

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "app/dtmf.h"
#include "app/generic.h"
#include "app/scanner.h"
#include "audio.h"
@@ -223,7 +224,7 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
case 2:
if (!gScanSingleFrequency)
{
RADIO_InitInfo(gTxVfo, gTxVfo->CHANNEL_SAVE, FREQUENCY_GetBand(gScanFrequency), gScanFrequency);
RADIO_InitInfo(gTxVfo, gTxVfo->CHANNEL_SAVE, gScanFrequency);
if (gScanUseCssResult)
{
@@ -366,7 +367,7 @@ void SCANNER_Start(void)
BackupStep = gRxVfo->STEP_SETTING;
BackupFrequency = gRxVfo->StepFrequency;
RADIO_InitInfo(gRxVfo, gRxVfo->CHANNEL_SAVE, gRxVfo->Band, gRxVfo->pRX->Frequency);
RADIO_InitInfo(gRxVfo, gRxVfo->CHANNEL_SAVE, gRxVfo->pRX->Frequency);
gRxVfo->STEP_SETTING = BackupStep;
gRxVfo->StepFrequency = BackupFrequency;
@@ -399,12 +400,13 @@ void SCANNER_Start(void)
gUpdateStatus = true;
}
DTMF_clear_RX();
gScanDelay_10ms = scan_delay_10ms;
gScanCssResultCode = 0xFF;
gScanCssResultType = 0xFF;
gScanHitCount = 0;
gScanUseCssResult = false;
gDTMF_RequestPending = false;
g_CxCSS_TAIL_Found = false;
g_CDCSS_Lost = false;
gCDCSSCodeType = 0;

View File

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

15
audio.c
View File

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

View File

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

View File

@@ -324,7 +324,7 @@ const uint8_t BITMAP_AntennaLevel6[3] =
0b00000000
};
const uint8_t BITMAP_CurrentIndicator[8] =
const uint8_t BITMAP_MARKER[8] =
{
0b11111111,
0b11111111,

View File

@@ -52,7 +52,7 @@ 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_CurrentIndicator[8];
extern const uint8_t BITMAP_MARKER[8];
extern const uint8_t BITMAP_VFO_Default[8];
extern const uint8_t BITMAP_VFO_NotDefault[8];

View File

@@ -861,7 +861,7 @@ void BOARD_FactoryReset(bool bIsAll)
if (bIsAll)
{
RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_FIRST + BAND6_400MHz, BAND6_400MHz, 43350000);
RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_FIRST + BAND6_400MHz, 43350000);
// set the first few memory channels
for (i = 0; i < ARRAY_SIZE(gDefaultFrequencyTable); i++)

4
compile-with-docker.bat Normal file
View File

@@ -0,0 +1,4 @@
@echo off
docker build -t uvk5 .
docker run -v %CD%\compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make clean && make && cp firmware* compiled-firmware/"
pause

3
compile-with-docker.sh Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
docker build -t uvk5 .
docker run -v $(PWD)/compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/"

2
dcs.c
View File

@@ -91,7 +91,7 @@ uint8_t DCS_GetCdcssCode(uint32_t Code)
return 0xFF;
}
uint8_t DCS_GetCtcssCode(uint16_t Code)
uint8_t DCS_GetCtcssCode(int Code)
{
unsigned int i;
uint8_t Result = 0xFF;

2
dcs.h
View File

@@ -39,7 +39,7 @@ extern const uint16_t DCS_Options[104];
uint32_t DCS_GetGolayCodeWord(DCS_CodeType_t CodeType, uint8_t Option);
uint8_t DCS_GetCdcssCode(uint32_t Code);
uint8_t DCS_GetCtcssCode(uint16_t Code);
uint8_t DCS_GetCtcssCode(int Code);
#endif

View File

@@ -465,7 +465,7 @@ void BK4819_SetCTCSSFrequency(uint32_t FreqControlWord)
// freq(Hz) * 20.64888 for XTAL 13M/26M or
// freq(Hz) * 20.97152 for XTAL 12.8M/19.2M/25.6M/38.4M
//
BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | (((FreqControlWord * 2064888u) + 500000u) / 1000000u)); // with rounding
BK4819_WriteRegister(BK4819_REG_07, BK4819_REG_07_MODE_CTC1 | (((FreqControlWord * 206488u) + 50000u) / 100000u)); // with rounding
}
// freq_10Hz is CTCSS Hz * 10
@@ -891,7 +891,7 @@ void BK4819_EnableDTMF(void)
// REG_24 <3:0> 14 Max symbol number for SelCall detection
// const uint16_t threshold = 24; // doesn't decode non-QS radios
const uint16_t threshold = 200; // but 128 ~ 247 does
const uint16_t threshold = 140; // but 128 ~ 247 does
BK4819_WriteRegister(BK4819_REG_24, // 1 00011000 1 1 1 1110
(1u << BK4819_REG_24_SHIFT_UNKNOWN_15)
| (threshold << BK4819_REG_24_SHIFT_THRESHOLD) // 0 ~ 255

View File

@@ -19,180 +19,122 @@
#include "driver/gpio.h"
#include "driver/keyboard.h"
#include "driver/systick.h"
#include "driver/i2c.h"
#include "misc.h"
KEY_Code_t gKeyReading0 = KEY_INVALID;
KEY_Code_t gKeyReading1 = KEY_INVALID;
uint16_t gDebounceCounter;
bool gWasFKeyPressed;
static const struct {
// Using a 16 bit pre-calculated shift and invert is cheaper
// than using 8 bit and doing shift and invert in code.
uint16_t set_to_zero_mask;
//We are very fortunate.
//The key and pin defines fit together in a single u8,
//making this very efficient
struct {
uint8_t key : 5; //Key 23 is highest
uint8_t pin : 3; //Pin 6 is highest
} pins[4];
} keyboard[5] = {
/* Zero row */
{
//Set to zero to handle special case of nothing pulled down.
.set_to_zero_mask = ~(0),
.pins = {
{ .key = KEY_SIDE1, .pin = GPIOA_PIN_KEYBOARD_0},
{ .key = KEY_SIDE2, .pin = GPIOA_PIN_KEYBOARD_1},
/* Duplicate to fill the array with valid values */
{ .key = KEY_SIDE2, .pin = GPIOA_PIN_KEYBOARD_1},
{ .key = KEY_SIDE2, .pin = GPIOA_PIN_KEYBOARD_1},
}
},
/* First row */
{
.set_to_zero_mask = ~(1 << GPIOA_PIN_KEYBOARD_4),
.pins = {
{ .key = KEY_MENU, .pin = GPIOA_PIN_KEYBOARD_0},
{ .key = KEY_1, .pin = GPIOA_PIN_KEYBOARD_1},
{ .key = KEY_4, .pin = GPIOA_PIN_KEYBOARD_2},
{ .key = KEY_7, .pin = GPIOA_PIN_KEYBOARD_3},
}
},
/* Second row */
{
.set_to_zero_mask = ~(1 << GPIOA_PIN_KEYBOARD_5),
.pins = {
{ .key = KEY_UP, .pin = GPIOA_PIN_KEYBOARD_0},
{ .key = KEY_2 , .pin = GPIOA_PIN_KEYBOARD_1},
{ .key = KEY_5 , .pin = GPIOA_PIN_KEYBOARD_2},
{ .key = KEY_8 , .pin = GPIOA_PIN_KEYBOARD_3},
}
},
/* Third row */
{
.set_to_zero_mask = ~(1 << GPIOA_PIN_KEYBOARD_6),
.pins = {
{ .key = KEY_DOWN, .pin = GPIOA_PIN_KEYBOARD_0},
{ .key = KEY_3 , .pin = GPIOA_PIN_KEYBOARD_1},
{ .key = KEY_6 , .pin = GPIOA_PIN_KEYBOARD_2},
{ .key = KEY_9 , .pin = GPIOA_PIN_KEYBOARD_3},
}
},
/* Fourth row */
{
.set_to_zero_mask = ~(1 << GPIOA_PIN_KEYBOARD_7),
.pins = {
{ .key = KEY_EXIT, .pin = GPIOA_PIN_KEYBOARD_0},
{ .key = KEY_STAR, .pin = GPIOA_PIN_KEYBOARD_1},
{ .key = KEY_0 , .pin = GPIOA_PIN_KEYBOARD_2},
{ .key = KEY_F , .pin = GPIOA_PIN_KEYBOARD_3},
}
},
};
KEY_Code_t KEYBOARD_Poll(void)
{
KEY_Code_t Key = KEY_INVALID;
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);
// if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT))
// return KEY_PTT;
SYSTICK_DelayUs(1);
// *****************
// Keys connected to gnd
for(int j = 0; j < ARRAY_SIZE(keyboard); j++) {
//Set all high
GPIOA->DATA |= 1 << GPIOA_PIN_KEYBOARD_4 |
1 << GPIOA_PIN_KEYBOARD_5 |
1 << GPIOA_PIN_KEYBOARD_6 |
1 << GPIOA_PIN_KEYBOARD_7 ;
//Clear the pin we are selecting
GPIOA->DATA &= keyboard[j].set_to_zero_mask;
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0))
{
Key = KEY_SIDE1;
goto Bye;
}
//Wait for the pins to stabilize. 1 works for me.
SYSTICK_DelayUs(2);
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1))
{
Key = KEY_SIDE2;
goto Bye;
}
// Read all 4 GPIO pins at once
uint16_t reg = GPIOA->DATA;
for(int i = 0; i < ARRAY_SIZE(keyboard[j].pins); i++)
{
uint16_t mask = 1 << keyboard[j].pins[i].pin;
if(! (reg & mask)) {
Key = keyboard[j].pins[i].key;
break;
}
}
// Original doesn't do PTT
if (Key != KEY_INVALID)
break;
}
// *****************
// First row
//Create I2C stop condition. Since we might have toggled I2C pins.
//This leaves GPIOA_PIN_KEYBOARD_4 and GPIOA_PIN_KEYBOARD_5 high
I2C_Stop();
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
SYSTICK_DelayUs(1);
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0))
{
Key = KEY_MENU;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1))
{
Key = KEY_1;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2))
{
Key = KEY_4;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3))
{
Key = KEY_7;
goto Bye;
}
// *****************
// Second row
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
SYSTICK_DelayUs(1);
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0))
{
Key = KEY_UP;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1))
{
Key = KEY_2;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2))
{
Key = KEY_5;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3))
{
Key = KEY_8;
goto Bye;
}
// *****************
// Third row
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
SYSTICK_DelayUs(1);
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
SYSTICK_DelayUs(1);
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0))
{
Key = KEY_DOWN;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1))
{
Key = KEY_3;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2))
{
Key = KEY_6;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3))
{
Key = KEY_9;
goto Bye;
}
// *****************
// Fourth row
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);
SYSTICK_DelayUs(1);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
SYSTICK_DelayUs(1);
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_0))
{
Key = KEY_EXIT;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_1))
{
Key = KEY_STAR;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_2))
{
Key = KEY_0;
goto Bye;
}
if (!GPIO_CheckBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_3))
{
Key = KEY_F;
goto Bye;
}
// *****************
Bye:
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_4);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_5);
// Reset VOICE pins
GPIO_ClearBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_6);
GPIO_SetBit(&GPIOA->DATA, GPIOA_PIN_KEYBOARD_7);

BIN
firmware.bin Normal file

Binary file not shown.

BIN
firmware.packed.bin Normal file

Binary file not shown.

View File

@@ -157,7 +157,7 @@ uint32_t FREQUENCY_FloorToStep(uint32_t Upper, uint32_t Step, uint32_t Lower)
return Lower + (Step * Index);
}
/*
int TX_FREQUENCY_Check(VFO_Info_t *pInfo)
int TX_freq_check(VFO_Info_t *pInfo)
{ // return '0' if TX frequency is allowed
// otherwise return '-1'
@@ -168,7 +168,7 @@ int TX_FREQUENCY_Check(VFO_Info_t *pInfo)
return -1;
#endif
*/
int TX_FREQUENCY_Check(const uint32_t Frequency)
int TX_freq_check(const uint32_t Frequency)
{ // return '0' if TX frequency is allowed
// otherwise return '-1'
@@ -205,6 +205,8 @@ int TX_FREQUENCY_Check(const uint32_t Frequency)
case F_LOCK_CE:
if (Frequency >= 14400000 && Frequency < 14600000)
return 0;
if (Frequency >= 43000000 && Frequency < 44000000)
return 0;
break;
case F_LOCK_GB:
@@ -233,7 +235,7 @@ int TX_FREQUENCY_Check(const uint32_t Frequency)
return -1;
}
int RX_FREQUENCY_Check(const uint32_t Frequency)
int RX_freq_check(const uint32_t Frequency)
{ // return '0' if RX frequency is allowed
// otherwise return '-1'

View File

@@ -55,9 +55,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_FloorToStep(uint32_t Upper, uint32_t Step, uint32_t Lower);
//int TX_FREQUENCY_Check(VFO_Info_t *pInfo);
int TX_FREQUENCY_Check(const uint32_t Frequency);
int RX_FREQUENCY_Check(const uint32_t Frequency);
//int TX_freq_check(VFO_Info_t *pInfo);
int TX_freq_check(const uint32_t Frequency);
int RX_freq_check(const uint32_t Frequency);
#endif

View File

@@ -53,14 +53,7 @@ void FUNCTION_Init(void)
gCurrentCodeType = CODE_TYPE_CONTINUOUS_TONE;
#endif
gDTMF_RequestPending = false;
gDTMF_RecvTimeout = 0;
gDTMF_WriteIndex = 0;
memset(gDTMF_Received, 0, sizeof(gDTMF_Received));
// gDTMF_RX_timeout_live = 0;
// gDTMF_RX_timeout_live[0] = '\0';
DTMF_clear_RX();
g_CxCSS_TAIL_Found = false;
g_CDCSS_Lost = false;
@@ -152,8 +145,13 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
// if DTMF is enabled when TX'ing, it changes the TX audio filtering !! .. 1of11
BK4819_DisableDTMF();
// clear the DTMF RX buffer
DTMF_clear_RX();
// clear the DTMF RX live decoder buffer
gDTMF_RX_live_timeout = 0;
gDTMF_RX_live[0] = 0;
gDTMF_RX_live_timeout = 0;
memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
#if defined(ENABLE_FMRADIO)
if (gFmRadioMode)
@@ -189,19 +187,28 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
RADIO_SetTxParameters();
// turn the LED on RED
// turn the RED LED on
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_RED, true);
DTMF_Reply();
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState != ALARM_STATE_OFF)
{
BK4819_TransmitTone(true, (gAlarmState == ALARM_STATE_TX1750) ? 1750 : 500);
#ifdef ENABLE_TX1750
if (gAlarmState == ALARM_STATE_TX1750)
BK4819_TransmitTone(true, 1750);
#endif
#ifdef ENABLE_ALARM
if (gAlarmState == ALARM_STATE_TXALARM)
BK4819_TransmitTone(true, 500);
#endif
SYSTEM_DelayMs(2);
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gAlarmToneCounter = 0;
gEnableSpeaker = true;
#ifdef ENABLE_ALARM
gAlarmToneCounter = 0;
#endif
gEnableSpeaker = true;
break;
}
#endif

View File

@@ -66,21 +66,20 @@ Volts Percent Volts Percent Volts Percent Volts Percent
7.96478 75 7.72911 48 7.51285 21
7.95983 74 7.72097 47 7.49832 20
*/
uint8_t BATTERY_VoltsToPercent(uint16_t voltage_10mV)
unsigned int BATTERY_VoltsToPercent(const unsigned int voltage_10mV)
{
if(voltage_10mV>814)
return 100;
else if(voltage_10mV>756)
return 132*voltage_10mV/100-974;
else if(voltage_10mV>729)
return 63*voltage_10mV/100-452;
else if(voltage_10mV>600)
return 52*voltage_10mV/1000-31;
else
return 0;
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;
return 0;
}
void BATTERY_GetReadings(bool bDisplayBatteryLevel)
void BATTERY_GetReadings(const bool bDisplayBatteryLevel)
{
const uint8_t PreviousBatteryLevel = gBatteryDisplayLevel;
const uint16_t Voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + gBatteryVoltages[2] + gBatteryVoltages[3]) / 4;

View File

@@ -33,8 +33,8 @@ extern uint16_t gBatteryCheckCounter;
extern volatile uint16_t gPowerSave_10ms;
uint8_t BATTERY_VoltsToPercent(uint16_t voltage_10mV);
void BATTERY_GetReadings(bool bDisplayBatteryLevel);
unsigned int BATTERY_VoltsToPercent(const unsigned int voltage_10mV);
void BATTERY_GetReadings(const bool bDisplayBatteryLevel);
#endif

View File

@@ -39,15 +39,16 @@ BOOT_Mode_t BOOT_GetMode(void)
for (i = 0; i < 2; i++)
{
if (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT))
return BOOT_MODE_NORMAL;
return BOOT_MODE_NORMAL; // PTT not pressed
Keys[i] = KEYBOARD_Poll();
SYSTEM_DelayMs(20);
}
if (Keys[0] == Keys[1])
{
gKeyReading0 = Keys[0];
gKeyReading1 = Keys[0];
gKeyReading0 = Keys[0];
gKeyReading1 = Keys[0];
gDebounceCounter = 2;
if (Keys[0] == KEY_SIDE1)
@@ -66,16 +67,7 @@ void BOOT_ProcessMode(BOOT_Mode_t Mode)
{
if (Mode == BOOT_MODE_F_LOCK)
{
// enable all the menu items
gMenuListCount = 0;
// while (MenuList[gMenuListCount].name != NULL)
while (MenuList[gMenuListCount].name[0] != '\0')
gMenuListCount++;
gMenuCursor = MENU_350TX;
gSubMenuSelection = gSetting_350TX;
GUI_SelectNextDisplay(DISPLAY_MENU);
gF_LOCK = true;
}
#ifdef ENABLE_AIRCOPY
else
@@ -86,15 +78,15 @@ void BOOT_ProcessMode(BOOT_Mode_t Mode)
gEeprom.VOX_SWITCH = false;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gEeprom.AUTO_KEYPAD_LOCK = false;
gEeprom.KEY_1_SHORT_PRESS_ACTION = 0;
gEeprom.KEY_1_LONG_PRESS_ACTION = 0;
gEeprom.KEY_2_SHORT_PRESS_ACTION = 0;
gEeprom.KEY_2_LONG_PRESS_ACTION = 0;
gEeprom.KEY_1_SHORT_PRESS_ACTION = ACTION_OPT_NONE;
gEeprom.KEY_1_LONG_PRESS_ACTION = ACTION_OPT_NONE;
gEeprom.KEY_2_SHORT_PRESS_ACTION = ACTION_OPT_NONE;
gEeprom.KEY_2_LONG_PRESS_ACTION = ACTION_OPT_NONE;
RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_LAST - 1, 5, 41002500);
RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_LAST - 1, 41002500);
gRxVfo->CHANNEL_BANDWIDTH = BANDWIDTH_NARROW;
gRxVfo->OUTPUT_POWER = 0;
gRxVfo->CHANNEL_BANDWIDTH = BANDWIDTH_WIDE;
gRxVfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
@@ -105,6 +97,7 @@ void BOOT_ProcessMode(BOOT_Mode_t Mode)
BK4819_ResetFSK();
gAircopyState = AIRCOPY_READY;
GUI_SelectNextDisplay(DISPLAY_AIRCOPY);
}
#endif

BIN
images/batcal.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

36
main.c
View File

@@ -50,6 +50,7 @@ void _putchar(char c)
void Main(void)
{
unsigned int i;
BOOT_Mode_t BootMode;
// Enable clock gating of blocks we need
SYSCON_DEV_CLK_GATE = 0
@@ -101,11 +102,35 @@ void Main(void)
AM_fix_init();
#endif
// count the number of menu list items
BootMode = BOOT_GetMode();
// count the number of menu items
gMenuListCount = 0;
while (MenuList[gMenuListCount].name[0] != '\0')
gMenuListCount++;
gMenuListCount -= 8; // disable the last 'n' items
if (BootMode == BOOT_MODE_F_LOCK)
gF_LOCK = true; // flag to say use the hidden menu items
else
gMenuListCount -= 9; // hide the last few menu items
// wait for user to release all butts before moving on
if (!GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) ||
KEYBOARD_Poll() != KEY_INVALID ||
BootMode != BOOT_MODE_NORMAL)
{ // keys are pressed
UI_DisplayReleaseKeys();
BACKLIGHT_TurnOn();
i = 0;
while (i < 50) // 500ms
{
i = (GPIO_CheckBit(&GPIOC->DATA, GPIOC_PIN_PTT) && KEYBOARD_Poll() == KEY_INVALID) ? i + 1 : 0;
SYSTEM_DelayMs(10);
}
gKeyReading0 = KEY_INVALID;
gKeyReading1 = KEY_INVALID;
gDebounceCounter = 0;
}
if (!gChargingWithTypeC && !gBatteryDisplayLevel)
{
@@ -120,9 +145,8 @@ void Main(void)
}
else
{
BOOT_Mode_t BootMode;
UI_DisplayWelcome();
BACKLIGHT_TurnOn();
if (gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_NONE)
@@ -141,8 +165,6 @@ void Main(void)
}
}
BootMode = BOOT_GetMode();
if (gEeprom.POWER_ON_PASSWORD < 1000000)
{
bIsInLockScreen = true;
@@ -179,6 +201,8 @@ void Main(void)
#ifdef ENABLE_NOAA
RADIO_ConfigureNOAA();
#endif
// ******************
}
while (1)

17
misc.c
View File

@@ -28,7 +28,7 @@ const uint8_t menu_timeout_500ms = 20000 / 500; // 20 seconds
const uint8_t DTMF_RX_live_timeout_500ms = 6000 / 500; // 6 seconds live decoder on screen
const uint8_t DTMF_RX_timeout_500ms = 10000 / 500; // 10 seconds till we wipe the DTMF receiver
const uint8_t DTMF_decode_ring_countdown_500ms = 15000 / 500; // 15 seconds
const uint8_t DTMF_decode_ring_countdown_500ms = 15000 / 500; // 15 seconds .. time we sound the ringing for
const uint8_t DTMF_txstop_countdown_500ms = 3000 / 500; // 6 seconds
const uint8_t key_input_timeout_500ms = 8000 / 500; // 8 seconds
@@ -63,6 +63,9 @@ const uint16_t NOAA_countdown_10ms = 5000 / 10; // 5 seconds
const uint16_t NOAA_countdown_2_10ms = 500 / 10; // 500ms
const uint16_t NOAA_countdown_3_10ms = 200 / 10; // 200ms
//const uint16_t gMax_bat_v = 840; // 8.4V
//const uint16_t gMin_bat_v = 660; // 6.6V
const uint32_t gDefaultAesKey[4] = {0x4AA5CC60, 0x0312CC5F, 0xFFD2DABB, 0x6BBA7F92};
const uint8_t gMicGain_dB2[5] = {3, 8, 16, 24, 31};
@@ -146,7 +149,7 @@ uint8_t gReducedService;
uint8_t gBatteryVoltageIndex;
CssScanMode_t gCssScanMode;
bool gUpdateRSSI;
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
AlarmState_t gAlarmState;
#endif
uint8_t gVoltageMenuCountdown;
@@ -163,15 +166,17 @@ bool gRequestSaveSettings;
bool gRequestSaveFM;
#endif
bool gFlagPrepareTX;
bool gFlagAcceptSetting;
bool gFlagRefreshSetting;
bool gFlagBackupSetting;
bool gFlagSaveVfo;
bool gFlagSaveSettings;
bool gFlagSaveChannel;
#ifdef ENABLE_FMRADIO
bool gFlagSaveFM;
#endif
uint8_t gDTMF_RequestPending;
bool g_CDCSS_Lost;
uint8_t gCDCSSCodeType;
bool g_CTCSS_Lost;
@@ -191,7 +196,7 @@ uint8_t gRestoreMrChannel;
uint8_t gCurrentScanList;
uint8_t gPreviousMrChannel;
uint32_t gRestoreFrequency;
uint8_t gRxVfoIsActive;
bool gRxVfoIsActive;
#ifdef ENABLE_ALARM
uint8_t gAlarmToneCounter;
uint16_t gAlarmRunningCounter;
@@ -214,7 +219,9 @@ uint8_t gNeverUsed;
#endif
bool gUpdateDisplay;
bool gF_LOCK;
bool gF_LOCK = false;
uint8_t gShowChPrefix;
volatile bool gNextTimeslice;

15
misc.h
View File

@@ -128,6 +128,9 @@ extern const uint16_t scan_pause_delay_in_2_10ms;
extern const uint16_t scan_pause_delay_in_3_10ms;
extern const uint16_t scan_pause_delay_in_4_10ms;
//extern const uint16_t gMax_bat_v;
//extern const uint16_t gMin_bat_v;
extern const uint8_t gMicGain_dB2[5];
extern bool gSetting_350TX;
@@ -227,15 +230,17 @@ extern bool gRequestSaveSettings;
#endif
extern uint8_t gKeypadLocked;
extern bool gFlagPrepareTX;
extern bool gFlagAcceptSetting;
extern bool gFlagRefreshSetting;
extern bool gFlagAcceptSetting; // accept menu setting
extern bool gFlagRefreshSetting; // refresh menu display
extern bool gFlagBackupSetting; // save a copy of the current menu setting
extern bool gFlagSaveVfo;
extern bool gFlagSaveSettings;
extern bool gFlagSaveChannel;
#ifdef ENABLE_FMRADIO
extern bool gFlagSaveFM;
#endif
extern uint8_t gDTMF_RequestPending;
extern bool g_CDCSS_Lost;
extern uint8_t gCDCSSCodeType;
extern bool g_CTCSS_Lost;
@@ -255,7 +260,7 @@ extern uint8_t gRestoreMrChannel;
extern uint8_t gCurrentScanList;
extern uint8_t gPreviousMrChannel;
extern uint32_t gRestoreFrequency;
extern uint8_t gRxVfoIsActive;
extern bool gRxVfoIsActive;
extern uint8_t gAlarmToneCounter;
extern uint16_t gAlarmRunningCounter;
extern bool gKeyBeingHeld;
@@ -275,10 +280,10 @@ extern uint8_t gNeverUsed;
#endif
extern volatile bool gNextTimeslice;
extern bool gUpdateDisplay;
extern bool gF_LOCK;
#ifdef ENABLE_FMRADIO
extern uint8_t gFM_ChannelPosition;
#endif
extern bool gF_LOCK;
extern uint8_t gShowChPrefix;
extern volatile uint8_t gFoundCDCSSCountdown_10ms;
extern volatile uint8_t gFoundCTCSSCountdown_10ms;

115
radio.c
View File

@@ -114,25 +114,24 @@ uint8_t RADIO_FindNextChannel(uint8_t Channel, int8_t Direction, bool bCheckScan
return 0xFF;
}
void RADIO_InitInfo(VFO_Info_t *pInfo, uint8_t ChannelSave, uint8_t Band, uint32_t Frequency)
void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t Frequency)
{
memset(pInfo, 0, sizeof(*pInfo));
pInfo->Band = Band;
pInfo->SCANLIST1_PARTICIPATION = true;
pInfo->SCANLIST2_PARTICIPATION = true;
pInfo->STEP_SETTING = STEP_12_5kHz;
pInfo->StepFrequency = 2500;
pInfo->CHANNEL_SAVE = ChannelSave;
pInfo->FrequencyReverse = false;
pInfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
pInfo->freq_config_RX.Frequency = Frequency;
pInfo->freq_config_TX.Frequency = Frequency;
pInfo->pRX = &pInfo->freq_config_RX;
pInfo->pTX = &pInfo->freq_config_TX;
pInfo->TX_OFFSET_FREQUENCY = 1000000;
pInfo->Band = FREQUENCY_GetBand(Frequency);
pInfo->SCANLIST1_PARTICIPATION = true;
pInfo->SCANLIST2_PARTICIPATION = true;
pInfo->STEP_SETTING = STEP_12_5kHz;
pInfo->StepFrequency = 2500;
pInfo->CHANNEL_SAVE = ChannelSave;
pInfo->FrequencyReverse = false;
pInfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
pInfo->freq_config_RX.Frequency = Frequency;
pInfo->freq_config_TX.Frequency = Frequency;
pInfo->pRX = &pInfo->freq_config_RX;
pInfo->pTX = &pInfo->freq_config_TX;
#ifdef ENABLE_COMPANDER
pInfo->Compander = 0; // off
pInfo->Compander = 0; // off
#endif
if (ChannelSave == (FREQ_CHANNEL_FIRST + BAND2_108MHz))
@@ -167,7 +166,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
#ifdef ENABLE_NOAA
if (Channel >= NOAA_CHANNEL_FIRST)
{
RADIO_InitInfo(pRadio, gEeprom.ScreenChannel[VFO], 2, NoaaFrequencyTable[Channel - NOAA_CHANNEL_FIRST]);
RADIO_InitInfo(pRadio, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[Channel - NOAA_CHANNEL_FIRST]);
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF)
return;
@@ -211,7 +210,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
Index = Channel - FREQ_CHANNEL_FIRST;
RADIO_InitInfo(pRadio, Channel, Index, LowerLimitFrequencyBandTable[Index]);
RADIO_InitInfo(pRadio, Channel, LowerLimitFrequencyBandTable[Index]);
return;
}
@@ -436,7 +435,7 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
uint16_t Base = (Band < BAND4_174MHz) ? 0x1E60 : 0x1E00;
if (gEeprom.SQUELCH_LEVEL == 0)
{
{ // squelch == 0 (off)
pInfo->SquelchOpenRSSIThresh = 0;
pInfo->SquelchOpenNoiseThresh = 127;
pInfo->SquelchCloseGlitchThresh = 255;
@@ -446,9 +445,8 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
pInfo->SquelchOpenGlitchThresh = 255;
}
else
{
Base += gEeprom.SQUELCH_LEVEL;
// my squelch-1
{ // squelch >= 1
Base += gEeprom.SQUELCH_LEVEL; // my squelch-1
// VHF UHF
EEPROM_ReadBuffer(Base + 0x00, &pInfo->SquelchOpenRSSIThresh, 1); // 50 10
EEPROM_ReadBuffer(Base + 0x10, &pInfo->SquelchCloseRSSIThresh, 1); // 40 5
@@ -459,37 +457,22 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
EEPROM_ReadBuffer(Base + 0x40, &pInfo->SquelchCloseGlitchThresh, 1); // 90 90
EEPROM_ReadBuffer(Base + 0x50, &pInfo->SquelchOpenGlitchThresh, 1); // 100 100
#if ENABLE_SQUELCH1_LOWER
// make squelch-1 more sensitive
if (gEeprom.SQUELCH_LEVEL == 1)
{
if (Band < BAND4_174MHz)
{
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 11) / 12;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 9) / 10;
#if ENABLE_SQUELCH_LOWER
// make squelch more sensitive
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 10) / 9;
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 8) / 9;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 7) / 8;
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 10) / 9;
}
else
{
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 3) / 4;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 9) / 10;
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 8) / 7;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 4) / 3;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 10) / 9;
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 4) / 3;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 10) / 9;
}
}
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 8) / 7;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
#endif
if (pInfo->SquelchOpenNoiseThresh > 127)
pInfo->SquelchOpenNoiseThresh = 127;
if (pInfo->SquelchCloseNoiseThresh > 127)
pInfo->SquelchCloseNoiseThresh = 127;
}
@@ -747,9 +730,6 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
#endif
#if 0
// there's no reason the DTMF decoder can't be used in AM RX mode too
// aircraft comms use it on HF (AM and SSB)
// if (gRxVfo->AM_mode || (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED))
if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED)
{
BK4819_DisableDTMF();
@@ -760,7 +740,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND;
}
#else
if (gCurrentFunction != FUNCTION_TRANSMIT && gSetting_live_DTMF_decoder)
if (gCurrentFunction != FUNCTION_TRANSMIT)
{
BK4819_EnableDTMF();
InterruptMask |= BK4819_REG_3F_DTMF_5TONE_FOUND;
@@ -912,8 +892,9 @@ void RADIO_SetVfoState(VfoState_t State)
}
else
{
const uint8_t Channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
VfoState[Channel] = State;
unsigned int chan = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && gRxVfoIsActive) ? (gEeprom.RX_CHANNEL + 1) & 1 : gEeprom.RX_CHANNEL; // 1of11
chan = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.TX_CHANNEL : chan;
VfoState[chan] = State;
}
#ifdef ENABLE_FMRADIO
@@ -935,7 +916,7 @@ void RADIO_PrepareTX(void)
gScheduleDualWatch = false;
if (!gRxVfoIsActive)
{
{ // use the TX vfo
gEeprom.RX_CHANNEL = gEeprom.TX_CHANNEL;
gRxVfo = &gEeprom.VfoInfo[gEeprom.TX_CHANNEL];
gRxVfoIsActive = true;
@@ -948,10 +929,16 @@ void RADIO_PrepareTX(void)
RADIO_SelectCurrentVfo();
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) && defined(ENABLE_TX1750)
if (gAlarmState == ALARM_STATE_OFF ||
gAlarmState == ALARM_STATE_TX1750 ||
(gAlarmState == ALARM_STATE_ALARM && gEeprom.ALARM_MODE == ALARM_MODE_TONE))
#elif defined(ENABLE_ALARM)
if (gAlarmState == ALARM_STATE_OFF ||
(gAlarmState == ALARM_STATE_ALARM && gEeprom.ALARM_MODE == ALARM_MODE_TONE))
#elif defined(ENABLE_TX1750)
if (gAlarmState == ALARM_STATE_OFF ||
gAlarmState == ALARM_STATE_TX1750)
#endif
{
#ifndef ENABLE_TX_WHEN_AM
@@ -966,8 +953,8 @@ void RADIO_PrepareTX(void)
State = VFO_STATE_TX_DISABLE;
}
else
//if (TX_FREQUENCY_Check(gCurrentVfo->pTX->Frequency) == 0 || gCurrentVfo->CHANNEL_SAVE <= FREQ_CHANNEL_LAST)
if (TX_FREQUENCY_Check(gCurrentVfo->pTX->Frequency) == 0)
//if (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0 || gCurrentVfo->CHANNEL_SAVE <= FREQ_CHANNEL_LAST)
if (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0)
{ // TX frequency is allowed
if (gCurrentVfo->BUSY_CHANNEL_LOCK && gCurrentFunction == FUNCTION_RECEIVE)
State = VFO_STATE_BUSY; // busy RX'ing a station
@@ -986,7 +973,7 @@ void RADIO_PrepareTX(void)
if (State != VFO_STATE_NORMAL)
{ // TX not allowed
RADIO_SetVfoState(State);
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
gAlarmState = ALARM_STATE_OFF;
#endif
gDTMF_ReplyState = DTMF_REPLY_NONE;
@@ -1014,15 +1001,18 @@ void RADIO_PrepareTX(void)
FUNCTION_Select(FUNCTION_TRANSMIT);
gTxTimerCountdown_500ms = 0; // no timeout
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState == ALARM_STATE_OFF)
#endif
{
if (gEeprom.TX_TIMEOUT_TIMER == 1)
if (gEeprom.TX_TIMEOUT_TIMER == 0)
gTxTimerCountdown_500ms = 60; // 30 sec
else
if (gEeprom.TX_TIMEOUT_TIMER >= 2)
gTxTimerCountdown_500ms = (gEeprom.TX_TIMEOUT_TIMER - 1) * 120; // minutes
if (gEeprom.TX_TIMEOUT_TIMER < (ARRAY_SIZE(gSubMenu_TOT) - 1))
gTxTimerCountdown_500ms = 120 * gEeprom.TX_TIMEOUT_TIMER; // minutes
else
gTxTimerCountdown_500ms = 120 * 15; // 15 minutes
}
gTxTimeoutReached = false;
@@ -1070,8 +1060,9 @@ void RADIO_SendEndOfTransmission(void)
if (gEeprom.ROGER == ROGER_MODE_MDC)
BK4819_PlayRogerMDC();
if (gDTMF_CallState == DTMF_CALL_STATE_NONE && (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_EOT || gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH))
{
if (gDTMF_CallState == DTMF_CALL_STATE_NONE &&
(gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_EOT || gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH))
{ // end-of-tx
if (gEeprom.DTMF_SIDE_TONE)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);

View File

@@ -159,7 +159,7 @@ extern VfoState_t VfoState[2];
bool RADIO_CheckValidChannel(uint16_t ChNum, bool bCheckScanList, uint8_t RadioNum);
uint8_t RADIO_FindNextChannel(uint8_t ChNum, int8_t Direction, bool bCheckScanList, uint8_t RadioNum);
void RADIO_InitInfo(VFO_Info_t *pInfo, uint8_t ChannelSave, uint8_t ChIndex, uint32_t Frequency);
void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t Frequency);
void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure);
void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo);
void RADIO_ApplyOffset(VFO_Info_t *pInfo);

View File

@@ -121,7 +121,7 @@ void SETTINGS_SaveSettings(void)
EEPROM_WriteBuffer(0x0EA0, State);
#endif
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
State[0] = gEeprom.ALARM_MODE;
#else
State[0] = false;
@@ -214,7 +214,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
| (pVFO->OUTPUT_POWER << 2)
| (pVFO->CHANNEL_BANDWIDTH << 1)
| (pVFO->FrequencyReverse << 0);
State[5] = (pVFO->DTMF_PTT_ID_TX_MODE << 1) | (pVFO->DTMF_DECODING_ENABLE < 0);
State[5] = (pVFO->DTMF_PTT_ID_TX_MODE << 1) | (pVFO->DTMF_DECODING_ENABLE << 0);
State[6] = pVFO->STEP_SETTING;
State[7] = pVFO->SCRAMBLING_TYPE;
EEPROM_WriteBuffer(OffsetVFO + 8, State);
@@ -223,7 +223,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
if (IS_MR_CHANNEL(Channel))
{
#ifndef KEEP_MEM_NAME
#ifndef ENABLE_KEEP_MEM_NAME
// clear/reset the channel name
//memset(&State, 0xFF, sizeof(State));
memset(&State, 0x00, sizeof(State)); // follow the QS way
@@ -277,7 +277,7 @@ void SETTINGS_UpdateChannel(uint8_t Channel, const VFO_Info_t *pVFO, bool keep)
gMR_ChannelAttributes[Channel] = Attributes;
// #ifndef KEEP_MEM_NAME
// #ifndef ENABLE_KEEP_MEM_NAME
if (IS_MR_CHANNEL(Channel))
{
const uint16_t OffsetMR = Channel * 16;

View File

@@ -176,7 +176,7 @@ typedef struct {
#endif
bool AUTO_KEYPAD_LOCK;
#ifdef ENABLE_ALARM
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
ALARM_Mode_t ALARM_MODE;
#endif
POWER_OnDisplayMode_t POWER_ON_DISPLAY_MODE;

294
ui/main.c
View File

@@ -36,6 +36,8 @@
#include "ui/main.h"
#include "ui/ui.h"
bool center_line_is_free = true;
// ***************************************************************************
#ifdef ENABLE_AUDIO_BAR
@@ -94,18 +96,18 @@
#endif
uint8_t *pLine = gFrameBuffer[line];
uint8_t *p_line = gFrameBuffer[line];
memset(pLine, 0, LCD_WIDTH);
memset(p_line, 0, LCD_WIDTH);
#if 1
// solid bar
for (i = 0; i < bar_width; i++)
pLine[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
p_line[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
#else
// knuled bar
for (i = 0; i < bar_width; i += 2)
pLine[bar_x + i] = (i <= len) ? 0x7f : 0x41;
p_line[bar_x + i] = (i <= len) ? 0x7f : 0x41;
#endif
if (gCurrentFunction == FUNCTION_TRANSMIT)
@@ -117,11 +119,13 @@
#if defined(ENABLE_RSSI_BAR)
void UI_DisplayRSSIBar(const int16_t rssi, const bool now)
{
const int16_t s9_dBm = -73; // S9
const int16_t s0_dBm = -127; // S0
// const int16_t s0_dBm = -127; // S0 .. base level
const int16_t s0_dBm = -147; // S0 .. base level
const int16_t s9_dBm = s0_dBm + (6 * 9); // S9 .. 6dB/S-Point
const int16_t bar_max_dBm = s9_dBm + 30; // S9+30dB
const int16_t bar_min_dBm = s0_dBm; // S0
// const int16_t bar_min_dBm = s0_dBm + (6 * 0); // S0
const int16_t bar_min_dBm = s0_dBm + (6 * 4); // S4
// ************
@@ -129,46 +133,46 @@
const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph
const unsigned int bar_width = LCD_WIDTH - 1 - bar_x;
const int16_t dBm = (rssi / 2) - 160;
const int16_t clamped_dBm = (dBm <= bar_min_dBm) ? bar_min_dBm : (dBm >= bar_max_dBm) ? bar_max_dBm : dBm;
const int16_t rssi_dBm = (rssi / 2) - 160;
const int16_t clamped_dBm = (rssi_dBm <= bar_min_dBm) ? bar_min_dBm : (rssi_dBm >= bar_max_dBm) ? bar_max_dBm : rssi_dBm;
const unsigned int bar_range_dB = bar_max_dBm - bar_min_dBm;
const unsigned int len = ((clamped_dBm - bar_min_dBm) * bar_width) / bar_range_dB;
const unsigned int line = 3;
uint8_t *pLine = gFrameBuffer[line];
uint8_t *p_line = gFrameBuffer[line];
char s[16];
unsigned int i;
unsigned int s_level = 0; // S0
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (gCurrentFunction == FUNCTION_TRANSMIT || gScreenToDisplay != DISPLAY_MAIN)
return; // display is in use
if (dBm >= (s9_dBm + 10)) // S9+10dB
s_level = ((dBm - s9_dBm) / 10) * 10;
else
if (dBm >= s0_dBm) // S0
s_level = (dBm - s0_dBm) / 6; // 6dB per S point
if (now)
memset(pLine, 0, LCD_WIDTH);
memset(p_line, 0, LCD_WIDTH);
if (s_level < 10)
sprintf(s, "%-4d S%u ", dBm, s_level); // S0 ~ S9
if (rssi_dBm >= (s9_dBm + 6))
{ // S9+XXdB, 1dB increment
const char *fmt[] = {"%-4d +%u ", "%-4d +%2u "};
const unsigned int dB = ((rssi_dBm - s9_dBm) <= 99) ? rssi_dBm - s9_dBm : 99;
sprintf(s, (dB < 10) ? fmt[0] : fmt[1], rssi_dBm, dB);
}
else
sprintf(s, "%-4d +%2u", dBm, s_level); // S9+XX
{ // S0 ~ S9, 6dB per S-point
const unsigned int s_level = (rssi_dBm >= s0_dBm) ? (rssi_dBm - s0_dBm) / 6 : 0;
sprintf(s, "%-4d S%u ", rssi_dBm, s_level);
}
UI_PrintStringSmall(s, 2, 0, line);
#if 1
// solid bar
for (i = 0; i < bar_width; i++)
pLine[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
p_line[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
#else
// knuled bar
for (i = 0; i < bar_width; i += 2)
pLine[bar_x + i] = (i <= len) ? 0x7f : 0x41;
p_line[bar_x + i] = (i <= len) ? 0x7f : 0x41;
#endif
if (now)
@@ -180,24 +184,21 @@ void UI_UpdateRSSI(const int16_t rssi, const int vfo)
{
#ifdef ENABLE_RSSI_BAR
const bool rx = (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING);
if (!center_line_is_free)
return;
#if defined(ENABLE_AM_FIX) && defined(ENABLE_AM_FIX_SHOW_DATA)
if (gEeprom.VfoInfo[gEeprom.RX_CHANNEL].AM_mode && gSetting_AM_fix)
{ // AM test data is currently being shown
}
else
#endif
if (rx)
UI_DisplayRSSIBar(rssi, true);
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING)
{
UI_DisplayRSSIBar(rssi, true);
}
#else
// const int16_t dBm = (rssi / 2) - 160;
const uint8_t Line = (vfo == 0) ? 3 : 7;
uint8_t *pLine = gFrameBuffer[Line - 1];
uint8_t *p_line = gFrameBuffer[Line - 1];
// TODO: sort out all 8 values from the eeprom
@@ -252,31 +253,31 @@ void UI_UpdateRSSI(const int16_t rssi, const int vfo)
if (gCurrentFunction == FUNCTION_TRANSMIT || gScreenToDisplay != DISPLAY_MAIN)
return; // display is in use
pLine = gFrameBuffer[Line - 1];
p_line = gFrameBuffer[Line - 1];
memset(pLine, 0, 23);
memset(p_line, 0, 23);
if (rssi_level > 0)
{
//if (rssi_level >= 1)
memmove(pLine, BITMAP_Antenna, 5);
memmove(p_line, BITMAP_Antenna, 5);
if (rssi_level >= 2)
memmove(pLine + 5, BITMAP_AntennaLevel1, sizeof(BITMAP_AntennaLevel1));
memmove(p_line + 5, BITMAP_AntennaLevel1, sizeof(BITMAP_AntennaLevel1));
if (rssi_level >= 3)
memmove(pLine + 8, BITMAP_AntennaLevel2, sizeof(BITMAP_AntennaLevel2));
memmove(p_line + 8, BITMAP_AntennaLevel2, sizeof(BITMAP_AntennaLevel2));
if (rssi_level >= 4)
memmove(pLine + 11, BITMAP_AntennaLevel3, sizeof(BITMAP_AntennaLevel3));
memmove(p_line + 11, BITMAP_AntennaLevel3, sizeof(BITMAP_AntennaLevel3));
if (rssi_level >= 5)
memmove(pLine + 14, BITMAP_AntennaLevel4, sizeof(BITMAP_AntennaLevel4));
memmove(p_line + 14, BITMAP_AntennaLevel4, sizeof(BITMAP_AntennaLevel4));
if (rssi_level >= 6)
memmove(pLine + 17, BITMAP_AntennaLevel5, sizeof(BITMAP_AntennaLevel5));
memmove(p_line + 17, BITMAP_AntennaLevel5, sizeof(BITMAP_AntennaLevel5));
if (rssi_level >= 7)
memmove(pLine + 20, BITMAP_AntennaLevel6, sizeof(BITMAP_AntennaLevel6));
memmove(p_line + 20, BITMAP_AntennaLevel6, sizeof(BITMAP_AntennaLevel6));
}
else
pLine = NULL;
p_line = NULL;
ST7565_DrawLine(0, Line, 23, pLine);
ST7565_DrawLine(0, Line, 23, p_line);
#endif
}
@@ -284,9 +285,13 @@ void UI_UpdateRSSI(const int16_t rssi, const int vfo)
void UI_DisplayMain(void)
{
char String[16];
unsigned int vfo_num;
bool center_line_is_free = true;
const unsigned int line0 = 0; // text screen line
const unsigned int line1 = 4;
char String[16];
unsigned int vfo_num;
// true if the center screen line is available to use
center_line_is_free = true;
// #ifdef SINGLE_VFO_CHAN
// const bool single_vfo = (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? true : false;
@@ -294,6 +299,7 @@ void UI_DisplayMain(void)
const bool single_vfo = false;
// #endif
// clear the screen
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
@@ -306,25 +312,28 @@ void UI_DisplayMain(void)
for (vfo_num = 0; vfo_num < 2; vfo_num++)
{
uint8_t Channel = gEeprom.TX_CHANNEL;
bool bIsSameVfo = !!(Channel == vfo_num);
uint8_t Line = (vfo_num == 0) ? 0 : 4;
uint8_t *pLine0 = gFrameBuffer[Line + 0];
uint8_t *pLine1 = gFrameBuffer[Line + 1];
const unsigned int line = (vfo_num == 0) ? line0 : line1;
uint8_t channel = gEeprom.TX_CHANNEL;
// uint8_t tx_channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
const bool same_vfo = (channel == vfo_num) ? true : false;
uint8_t *p_line0 = gFrameBuffer[line + 0];
uint8_t *p_line1 = gFrameBuffer[line + 1];
uint32_t duff_beer = 0;
uint8_t state;
if (single_vfo)
{ // we're in single VFO mode - screen is dedicated to just one VFO
if (!bIsSameVfo)
if (!same_vfo)
continue; // skip the unused vfo
}
if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && gRxVfoIsActive)
Channel = gEeprom.RX_CHANNEL; // we're currently monitoring the other VFO
channel = gEeprom.RX_CHANNEL; // we're currently monitoring the other VFO
if (Channel != vfo_num)
if (channel != vfo_num)
{
if (gDTMF_CallState != DTMF_CALL_STATE_NONE || gDTMF_IsTx || gDTMF_InputMode)
{ // show DTMF stuff
@@ -338,7 +347,7 @@ void UI_DisplayMain(void)
strcpy(String, (gDTMF_State == DTMF_STATE_CALL_OUT_RSP) ? "CALL OUT(RSP)" : "CALL OUT");
else
if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED)
sprintf(String, "CALL:%s", (DTMF_FindContact(gDTMF_Caller, Contact)) ? Contact : gDTMF_Caller);
sprintf(String, "CALL FRM:%s", (DTMF_FindContact(gDTMF_Caller, Contact)) ? Contact : gDTMF_Caller);
else
if (gDTMF_IsTx)
strcpy(String, (gDTMF_State == DTMF_STATE_TX_SUCC) ? "DTMF TX(SUCC)" : "DTMF TX");
@@ -375,24 +384,22 @@ void UI_DisplayMain(void)
}
// highlight the selected/used VFO with a marker
if (!single_vfo && bIsSameVfo)
memmove(pLine0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default));
if (!single_vfo && same_vfo)
memmove(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default));
else
if (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF)
memmove(pLine0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault));
memmove(p_line0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault));
}
else
if (!single_vfo)
{ // highlight the selected/used VFO with a marker
if (bIsSameVfo)
memmove(pLine0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default));
if (same_vfo)
memmove(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default));
else
//if (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF)
memmove(pLine0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault));
memmove(p_line0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault));
}
uint32_t duff_beer = 0;
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // transmitting
@@ -402,11 +409,11 @@ void UI_DisplayMain(void)
else
#endif
{
Channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (Channel == vfo_num)
channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (channel == vfo_num)
{ // show the TX symbol
duff_beer = 1;
UI_PrintStringSmall("TX", 14, 0, Line);
UI_PrintStringSmall("TX", 14, 0, line);
}
}
}
@@ -414,7 +421,7 @@ void UI_DisplayMain(void)
{ // receiving .. show the RX symbol
duff_beer = 2;
if ((gCurrentFunction == FUNCTION_RECEIVE || gCurrentFunction == FUNCTION_MONITOR) && gEeprom.RX_CHANNEL == vfo_num)
UI_PrintStringSmall("RX", 14, 0, Line);
UI_PrintStringSmall("RX", 14, 0, line);
}
if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo_num]))
@@ -424,9 +431,9 @@ void UI_DisplayMain(void)
if (!inputting)
NUMBER_ToDigits(gEeprom.ScreenChannel[vfo_num] + 1, String); // show the memory channel number
else
memmove(String + 5, gInputBox, 3); // show the input text
UI_PrintStringSmall("M", x, 0, Line + 1);
UI_DisplaySmallDigits(3, String + 5, x + 7, Line + 1, inputting);
memmove(String + 5, gInputBox, 3); // show the input text
UI_PrintStringSmall("M", x, 0, line + 1);
UI_DisplaySmallDigits(3, String + 5, x + 7, line + 1, inputting);
}
else
if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]))
@@ -435,7 +442,7 @@ void UI_DisplayMain(void)
const unsigned int x = 2; // was 14
// sprintf(String, "FB%u", 1 + gEeprom.ScreenChannel[vfo_num] - FREQ_CHANNEL_FIRST);
sprintf(String, "VFO%u", 1 + gEeprom.ScreenChannel[vfo_num] - FREQ_CHANNEL_FIRST);
UI_PrintStringSmall(String, x, 0, Line + 1);
UI_PrintStringSmall(String, x, 0, line + 1);
}
#ifdef ENABLE_NOAA
else
@@ -448,40 +455,33 @@ void UI_DisplayMain(void)
{ // user entering channel number
sprintf(String, "N%u%u", '0' + gInputBox[0], '0' + gInputBox[1]);
}
UI_PrintStringSmall(String, 7, 0, Line + 1);
UI_PrintStringSmall(String, 7, 0, line + 1);
}
#endif
// ************
uint8_t State = VfoState[vfo_num];
state = VfoState[vfo_num];
#ifdef ENABLE_ALARM
if (gCurrentFunction == FUNCTION_TRANSMIT && gAlarmState == ALARM_STATE_ALARM)
{
Channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (Channel == vfo_num)
State = VFO_STATE_ALARM;
channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (channel == vfo_num)
state = VFO_STATE_ALARM;
}
#endif
if (State != VFO_STATE_NORMAL)
if (state != VFO_STATE_NORMAL)
{
const char *state_list[] = {"", "BUSY", "BAT LOW", "TX DISABLE", "TIMEOUT", "ALARM", "VOLT HIGH"};
if (State >= 0 && State < ARRAY_SIZE(state_list))
{
UI_PrintString(state_list[State], 31, 0, Line, 8);
}
//else
//{
// sprintf(String, "State %u ?", State);
// UI_PrintString(String, 31, 0, Line, 8);
//}
if (state >= 0 && state < ARRAY_SIZE(state_list))
UI_PrintString(state_list[state], 31, 0, line, 8);
}
else
if (gInputBoxIndex > 0 && IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]) && gEeprom.TX_CHANNEL == vfo_num)
{ // user entering a frequency
UI_DisplayFrequency(gInputBox, 32, Line, true, false);
UI_DisplayFrequency(gInputBox, 32, line, true, false);
center_line_is_free = false;
}
@@ -490,8 +490,8 @@ void UI_DisplayMain(void)
uint32_t frequency = gEeprom.VfoInfo[vfo_num].pRX->Frequency;
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // transmitting
Channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (Channel == vfo_num)
channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (channel == vfo_num)
frequency = gEeprom.VfoInfo[vfo_num].pTX->Frequency;
}
@@ -501,13 +501,13 @@ void UI_DisplayMain(void)
// show the channel symbols
const uint8_t attributes = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if (attributes & MR_CH_SCANLIST1)
memmove(pLine0 + 113, BITMAP_ScanList1, sizeof(BITMAP_ScanList1));
memmove(p_line0 + 113, BITMAP_ScanList1, sizeof(BITMAP_ScanList1));
if (attributes & MR_CH_SCANLIST2)
memmove(pLine0 + 120, BITMAP_ScanList2, sizeof(BITMAP_ScanList2));
memmove(p_line0 + 120, BITMAP_ScanList2, sizeof(BITMAP_ScanList2));
#ifndef ENABLE_BIG_FREQ
#ifdef ENABLE_COMPANDER
if ((attributes & MR_CH_COMPAND) > 0)
memmove(pLine0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
memmove(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
#endif
#endif
@@ -517,19 +517,19 @@ void UI_DisplayMain(void)
#ifdef ENABLE_BIG_FREQ
NUMBER_ToDigits(frequency, String);
// show the main large frequency digits
UI_DisplayFrequency(String, 32, Line, false, false);
UI_DisplayFrequency(String, 32, line, false, false);
// show the remaining 2 small frequency digits
UI_DisplaySmallDigits(2, String + 6, 113, Line + 1, true);
UI_DisplaySmallDigits(2, String + 6, 113, line + 1, true);
#else
// show the frequency in the main font
sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000);
UI_PrintString(String, 32, 0, Line, 8);
UI_PrintString(String, 32, 0, line, 8);
#endif
break;
case MDF_CHANNEL: // show the channel number
sprintf(String, "CH-%03u", gEeprom.ScreenChannel[vfo_num] + 1);
UI_PrintString(String, 32, 0, Line, 8);
UI_PrintString(String, 32, 0, line, 8);
break;
case MDF_NAME: // show the channel name
@@ -543,19 +543,19 @@ void UI_DisplayMain(void)
if (gEeprom.CHANNEL_DISPLAY_MODE == MDF_NAME)
{
UI_PrintString(String, 32, 0, Line, 8);
UI_PrintString(String, 32, 0, line, 8);
}
else
{
#ifdef ENABLE_SMALL_BOLD
UI_PrintStringSmallBold(String, 32 + 4, 0, Line);
UI_PrintStringSmallBold(String, 32 + 4, 0, line);
#else
UI_PrintStringSmall(String, 32 + 4, 0, Line);
UI_PrintStringSmall(String, 32 + 4, 0, line);
#endif
// show the channel frequency below the channel number/name
sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000);
UI_PrintStringSmall(String, 32 + 4, 0, Line + 1);
UI_PrintStringSmall(String, 32 + 4, 0, line + 1);
}
break;
@@ -566,13 +566,13 @@ void UI_DisplayMain(void)
#ifdef ENABLE_BIG_FREQ
NUMBER_ToDigits(frequency, String); // 8 digits
// show the main large frequency digits
UI_DisplayFrequency(String, 32, Line, false, false);
UI_DisplayFrequency(String, 32, line, false, false);
// show the remaining 2 small frequency digits
UI_DisplaySmallDigits(2, String + 6, 113, Line + 1, true);
UI_DisplaySmallDigits(2, String + 6, 113, line + 1, true);
#else
// show the frequency in the main font
sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000);
UI_PrintString(String, 32, 0, Line, 8);
UI_PrintString(String, 32, 0, line, 8);
#endif
#ifdef ENABLE_COMPANDER
@@ -580,9 +580,9 @@ void UI_DisplayMain(void)
const uint8_t attributes = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if ((attributes & MR_CH_COMPAND) > 0)
#ifdef ENABLE_BIG_FREQ
memmove(pLine0 + 120, BITMAP_compand, sizeof(BITMAP_compand));
memmove(p_line0 + 120, BITMAP_compand, sizeof(BITMAP_compand));
#else
memmove(pLine0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
memmove(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
#endif
#endif
}
@@ -614,20 +614,20 @@ void UI_DisplayMain(void)
if (Level >= 1)
{
uint8_t *pLine = pLine1 + LCD_WIDTH;
memmove(pLine + 0, BITMAP_Antenna, sizeof(BITMAP_Antenna));
uint8_t *p_line = p_line1 + LCD_WIDTH;
memmove(p_line + 0, BITMAP_Antenna, sizeof(BITMAP_Antenna));
if (Level >= 2)
memmove(pLine + 5, BITMAP_AntennaLevel1, sizeof(BITMAP_AntennaLevel1));
memmove(p_line + 5, BITMAP_AntennaLevel1, sizeof(BITMAP_AntennaLevel1));
if (Level >= 3)
memmove(pLine + 8, BITMAP_AntennaLevel2, sizeof(BITMAP_AntennaLevel2));
memmove(p_line + 8, BITMAP_AntennaLevel2, sizeof(BITMAP_AntennaLevel2));
if (Level >= 4)
memmove(pLine + 11, BITMAP_AntennaLevel3, sizeof(BITMAP_AntennaLevel3));
memmove(p_line + 11, BITMAP_AntennaLevel3, sizeof(BITMAP_AntennaLevel3));
if (Level >= 5)
memmove(pLine + 14, BITMAP_AntennaLevel4, sizeof(BITMAP_AntennaLevel4));
memmove(p_line + 14, BITMAP_AntennaLevel4, sizeof(BITMAP_AntennaLevel4));
if (Level >= 6)
memmove(pLine + 17, BITMAP_AntennaLevel5, sizeof(BITMAP_AntennaLevel5));
memmove(p_line + 17, BITMAP_AntennaLevel5, sizeof(BITMAP_AntennaLevel5));
if (Level >= 7)
memmove(pLine + 20, BITMAP_AntennaLevel6, sizeof(BITMAP_AntennaLevel6));
memmove(p_line + 20, BITMAP_AntennaLevel6, sizeof(BITMAP_AntennaLevel6));
}
}
@@ -646,15 +646,15 @@ void UI_DisplayMain(void)
if (code_type >= 0 && code_type < ARRAY_SIZE(code_list))
strcpy(String, code_list[code_type]);
}
UI_PrintStringSmall(String, LCD_WIDTH + 24, 0, Line + 1);
UI_PrintStringSmall(String, LCD_WIDTH + 24, 0, line + 1);
if (State != VFO_STATE_TX_DISABLE)
if (state == VFO_STATE_NORMAL || state == VFO_STATE_ALARM)
{ // show the TX power
const char pwr_list[] = "LMH";
const unsigned int i = gEeprom.VfoInfo[vfo_num].OUTPUT_POWER;
String[0] = (i >= 0 && i < ARRAY_SIZE(pwr_list)) ? pwr_list[i] : '\0';
String[1] = '\0';
UI_PrintStringSmall(String, LCD_WIDTH + 46, 0, Line + 1);
UI_PrintStringSmall(String, LCD_WIDTH + 46, 0, line + 1);
}
if (gEeprom.VfoInfo[vfo_num].freq_config_RX.Frequency != gEeprom.VfoInfo[vfo_num].freq_config_TX.Frequency)
@@ -663,12 +663,12 @@ void UI_DisplayMain(void)
const unsigned int i = gEeprom.VfoInfo[vfo_num].TX_OFFSET_FREQUENCY_DIRECTION;
String[0] = (i < sizeof(dir_list)) ? dir_list[i] : '?';
String[1] = '\0';
UI_PrintStringSmall(String, LCD_WIDTH + 54, 0, Line + 1);
UI_PrintStringSmall(String, LCD_WIDTH + 54, 0, line + 1);
}
// show the TX/RX reverse symbol
if (gEeprom.VfoInfo[vfo_num].FrequencyReverse)
UI_PrintStringSmall("R", LCD_WIDTH + 62, 0, Line + 1);
UI_PrintStringSmall("R", LCD_WIDTH + 62, 0, line + 1);
{ // show the narrow band symbol
String[0] = '\0';
@@ -677,16 +677,16 @@ void UI_DisplayMain(void)
String[0] = 'N';
String[1] = '\0';
}
UI_PrintStringSmall(String, LCD_WIDTH + 70, 0, Line + 1);
UI_PrintStringSmall(String, LCD_WIDTH + 70, 0, line + 1);
}
// show the DTMF decoding symbol(
// show the DTMF decoding symbol
if (gEeprom.VfoInfo[vfo_num].DTMF_DECODING_ENABLE || gSetting_KILLED)
UI_PrintStringSmall("DTMF", LCD_WIDTH + 78, 0, Line + 1);
UI_PrintStringSmall("DTMF", LCD_WIDTH + 78, 0, line + 1);
// show the audio scramble symbol
if (gEeprom.VfoInfo[vfo_num].SCRAMBLING_TYPE > 0 && gSetting_ScrambleEnable)
UI_PrintStringSmall("SCR", LCD_WIDTH + 106, 0, Line + 1);
UI_PrintStringSmall("SCR", LCD_WIDTH + 106, 0, line + 1);
}
if (center_line_is_free)
@@ -698,7 +698,10 @@ void UI_DisplayMain(void)
#ifdef ENABLE_AUDIO_BAR
if (gSetting_mic_bar && gCurrentFunction == FUNCTION_TRANSMIT)
{
UI_DisplayAudioBar();
center_line_is_free = false;
}
else
#endif
@@ -707,34 +710,53 @@ void UI_DisplayMain(void)
{
AM_fix_print_data(gEeprom.RX_CHANNEL, String);
UI_PrintStringSmall(String, 2, 0, 3);
center_line_is_free = false;
}
else
#endif
#ifdef ENABLE_RSSI_BAR
if (rx)
{
UI_DisplayRSSIBar(gCurrentRSSI[gEeprom.RX_CHANNEL], false);
center_line_is_free = false;
}
else
#endif
if (rx || gCurrentFunction == FUNCTION_FOREGROUND || gCurrentFunction == FUNCTION_POWER_SAVE)
{
if (gSetting_live_DTMF_decoder && gDTMF_RX_live[0] >= 32)
{ // show live DTMF decode
const unsigned int len = strlen(gDTMF_RX_live);
const unsigned int idx = (len > (17 - 5)) ? len - (17 - 5) : 0; // limit to last 'n' chars
strcpy(String, "DTMF ");
strcat(String, gDTMF_RX_live + idx);
UI_PrintStringSmall(String, 2, 0, 3);
}
#if 1
if (gSetting_live_DTMF_decoder && gDTMF_RX_live[0] != 0)
{ // show live DTMF decode
const unsigned int len = strlen(gDTMF_RX_live);
const unsigned int idx = (len > (17 - 5)) ? len - (17 - 5) : 0; // limit to last 'n' chars
strcpy(String, "DTMF ");
strcat(String, gDTMF_RX_live + idx);
UI_PrintStringSmall(String, 2, 0, 3);
center_line_is_free = false;
}
#else
if (gSetting_live_DTMF_decoder && gDTMF_RX_index > 0)
{ // show live DTMF decode
const unsigned int len = gDTMF_RX_index;
const unsigned int idx = (len > (17 - 5)) ? len - (17 - 5) : 0; // limit to last 'n' chars
strcpy(String, "DTMF ");
strcat(String, gDTMF_RX + idx);
UI_PrintStringSmall(String, 2, 0, 3);
center_line_is_free = false;
}
#endif
#ifdef ENABLE_SHOW_CHARGE_LEVEL
else
if (gChargingWithTypeC)
{ // charging .. show the battery state
const uint16_t percent = BATTERY_VoltsToPercent(gBatteryVoltageAverage);
sprintf(String, "Charge %u.%02uV %u%%", gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, percent);
UI_PrintStringSmall(String, 2, 0, 3);
sprintf(String, "Charge %u.%02uV %u%%",
gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100,
BATTERY_VoltsToPercent(gBatteryVoltageAverage));
UI_PrintStringSmall(String, 2, 0, 3);
center_line_is_free = false;
}
#endif
}

241
ui/menu.c
View File

@@ -91,11 +91,11 @@ const t_menu_item MenuList[] =
{"ANI-ID", VOICE_ID_ANI_CODE, MENU_ANI_ID },
{"UPCODE", VOICE_ID_INVALID, MENU_UPCODE },
{"DWCODE", VOICE_ID_INVALID, MENU_DWCODE },
{"PTT-ID", VOICE_ID_INVALID, MENU_PTT_ID },
{"D-ST", VOICE_ID_INVALID, MENU_D_ST },
{"D-RSP", VOICE_ID_INVALID, MENU_D_RSP },
{"D-HOLD", VOICE_ID_INVALID, MENU_D_HOLD },
{"D-PRE", VOICE_ID_INVALID, MENU_D_PRE },
{"PTT-ID", VOICE_ID_INVALID, MENU_PTT_ID },
{"D-DCD", VOICE_ID_INVALID, MENU_D_DCD },
{"D-LIST", VOICE_ID_INVALID, MENU_D_LIST },
{"D-LIVE", VOICE_ID_INVALID, MENU_D_LIVE_DEC }, // live DTMF decoder
@@ -127,6 +127,7 @@ const t_menu_item MenuList[] =
{"TX-EN", VOICE_ID_INVALID, MENU_TX_EN }, // enable TX
{"F-CALI", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration
{"BATCAL", VOICE_ID_INVALID, MENU_BATCAL }, // battery voltage calibration
{"", VOICE_ID_INVALID, 0xff } // end of list - DO NOT delete or move this this
};
@@ -168,7 +169,6 @@ const char gSubMenu_SAVE[5][4] =
const char gSubMenu_TOT[11][7] =
{
"OFF",
"30 sec",
"1 min",
"2 min",
@@ -178,14 +178,22 @@ const char gSubMenu_TOT[11][7] =
"6 min",
"7 min",
"8 min",
"9 min"
"9 min",
"15 min"
};
const char gSubMenu_CHAN[3][7] =
const char gSubMenu_CHAN[3][10] =
{
"OFF",
"CHAN_A",
"CHAN_B"
"UPPER\nVFO",
"LOWER\nVFO"
};
const char gSubMenu_XB[3][10] =
{
"MAIN\nVFO",
"UPPER\nVFO",
"LOWER\nVFO"
};
#ifdef ENABLE_VOICE
@@ -197,19 +205,22 @@ const char gSubMenu_CHAN[3][7] =
};
#endif
const char gSubMenu_SC_REV[3][3] =
const char gSubMenu_SC_REV[3][13] =
{
"TO",
"CO",
"SE"
// "TIME\nOPER",
// "CARRIER\nOPER",
// "SEARCH\nOPER"
"TIME",
"CARRIER",
"SEARCH"
};
const char gSubMenu_MDF[4][8] =
const char gSubMenu_MDF[4][15] =
{
"FREQ",
"CHAN",
"CHANNEL\nNUMBER",
"NAME",
"NAM+FRE"
"NAME\n+\nFREQ"
};
#ifdef ENABLE_ALARM
@@ -228,19 +239,19 @@ const char gSubMenu_D_RSP[4][6] =
"BOTH"
};
const char gSubMenu_PTT_ID[4][5] =
const char gSubMenu_PTT_ID[4][7] =
{
"OFF",
"BOT",
"EOT",
"KEY UP",
"KEY DN",
"BOTH"
};
const char gSubMenu_PONMSG[4][5] =
const char gSubMenu_PONMSG[4][8] =
{
"FULL",
"MSG",
"VOL",
"MESSAGE",
"VOLTAGE",
"NONE"
};
@@ -325,9 +336,10 @@ bool gIsInSubMenu;
uint8_t gMenuCursor;
int8_t gMenuScrollDirection;
int32_t gSubMenuSelection;
int32_t gSubMenuSelection_original = 0; // copy of the original value
// edit box
char edit_original[17]; // a copy of the text before editing so that we can easily test for changes/difference
char edit_original[17] = {0}; // a copy of the text before editing so that we can easily test for changes/difference
char edit[17];
int edit_index;
@@ -337,34 +349,89 @@ void UI_DisplayMenu(void)
const unsigned int menu_item_x1 = (8 * menu_list_width) + 2;
const unsigned int menu_item_x2 = LCD_WIDTH - 1;
unsigned int i;
char String[16];
char String[64];
char Contact[16];
// clear the screen
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
for (i = 0; i < 3; i++)
if (gMenuCursor > 0 || i > 0)
if ((gMenuListCount - 1) != gMenuCursor || i != 2)
UI_PrintString(MenuList[gMenuCursor + i - 1].name, 0, 0, i * 2, 8);
// draw the left menu list
#if 0
// invert the menu list text pixels
for (i = 0; i < (8 * menu_list_width); i++)
for (i = 0; i < 3; i++)
if (gMenuCursor > 0 || i > 0)
if ((gMenuListCount - 1) != gMenuCursor || i != 2)
UI_PrintString(MenuList[gMenuCursor + i - 1].name, 0, 0, i * 2, 8);
// invert the current menu list item text pixels
for (i = 0; i < (8 * menu_list_width); i++)
{
gFrameBuffer[2][i] ^= 0xFF;
gFrameBuffer[3][i] ^= 0xFF;
}
// draw vertical separating dotted line
for (i = 0; i < 7; i++)
gFrameBuffer[i][(8 * menu_list_width) + 1] = 0xAA;
// draw the little triangle marker if we're in the sub-menu
if (gIsInSubMenu)
memmove(gFrameBuffer[0] + (8 * menu_list_width) + 1, BITMAP_CurrentIndicator, sizeof(BITMAP_CurrentIndicator));
// draw the menu index number/count
sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount);
UI_PrintStringSmall(String, 2, 0, 6);
#else
{
gFrameBuffer[2][i] ^= 0xFF;
gFrameBuffer[3][i] ^= 0xFF;
const int menu_index = gMenuCursor; // current selected menu item
i = 1;
if (!gIsInSubMenu)
{
while (i < 2)
{ // leading menu items
const int k = menu_index + i - 2;
if (k < 0)
UI_PrintStringSmall(MenuList[gMenuListCount + k].name, 0, 0, i); // wrap-a-round
else
if (k >= 0 && k < (int)gMenuListCount)
UI_PrintStringSmall(MenuList[k].name, 0, 0, i);
i++;
}
// current menu item
if (menu_index >= 0 && menu_index < (int)gMenuListCount)
UI_PrintString(MenuList[menu_index].name, 0, 0, 2, 8);
i++;
while (i < 4)
{ // trailing menu item
const int k = menu_index + i - 2;
if (k >= 0 && k < (int)gMenuListCount)
UI_PrintStringSmall(MenuList[k].name, 0, 0, 1 + i);
else
if (k >= (int)gMenuListCount)
UI_PrintStringSmall(MenuList[gMenuListCount - k].name, 0, 0, 1 + i); // wrap-a-round
i++;
}
// draw the menu index number/count
sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount);
UI_PrintStringSmall(String, 2, 0, 6);
}
else
if (menu_index >= 0 && menu_index < (int)gMenuListCount)
{ // current menu item
strcpy(String, MenuList[menu_index].name);
// strcat(String, ":");
UI_PrintString(String, 0, 0, 0, 8);
// UI_PrintStringSmall(String, 0, 0, 0);
}
}
#endif
// draw vertical separating dotted line
for (i = 0; i < 7; i++)
gFrameBuffer[i][(8 * menu_list_width) + 1] = 0xAA;
// draw the menu index number/count
sprintf(String, "%2u.%u", 1 + gMenuCursor, gMenuListCount);
UI_PrintStringSmall(String, 8, 0, 6);
// draw the little marker
if (gIsInSubMenu)
memmove(gFrameBuffer[0] + (8 * menu_list_width) + 1, BITMAP_CurrentIndicator, sizeof(BITMAP_CurrentIndicator));
// **************
memset(String, 0, sizeof(String));
@@ -575,10 +642,13 @@ void UI_DisplayMenu(void)
break;
case MENU_TDR:
case MENU_XB:
strcpy(String, gSubMenu_CHAN[gSubMenuSelection]);
break;
case MENU_XB:
strcpy(String, gSubMenu_XB[gSubMenuSelection]);
break;
case MENU_TOT:
strcpy(String, gSubMenu_TOT[gSubMenuSelection]);
break;
@@ -663,22 +733,9 @@ void UI_DisplayMenu(void)
break;
case MENU_VOL:
// 1st text line
sprintf(String, "%u.%02uV", gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100);
UI_PrintString(String, menu_item_x1, menu_item_x2, 1, 8);
{ // 2nd text line .. percentage
UI_PrintString(String, menu_item_x1, menu_item_x2, 1, 8);
const uint16_t percent = BATTERY_VoltsToPercent(gBatteryVoltageAverage);
sprintf(String, "%u%%", percent);
UI_PrintString(String, menu_item_x1, menu_item_x2, 3, 8);
#if 0
sprintf(String, "Curr %u", gBatteryCurrent); // needs scaling into mA
UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8);
#endif
}
already_printed = true;
sprintf(String, "%u.%02uV\n%u%%",
gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100,
BATTERY_VoltsToPercent(gBatteryVoltageAverage));
break;
case MENU_RESET:
@@ -691,26 +748,72 @@ void UI_DisplayMenu(void)
case MENU_F_CALI:
{
const uint32_t value = 22656 + gSubMenuSelection;
const uint32_t value = 22656 + gSubMenuSelection;
const uint32_t xtal_Hz = (0x4f0000u + value) * 5;
//gEeprom.BK4819_XTAL_FREQ_LOW = gSubMenuSelection; // already set when the user was adjusting the value
BK4819_WriteRegister(BK4819_REG_3B, value);
sprintf(String, "%d", gSubMenuSelection);
UI_PrintString(String, menu_item_x1, menu_item_x2, 0, 8);
const uint32_t xtal_Hz = (0x4f0000u + value) * 5;
sprintf(String, "%u.%06u", xtal_Hz / 1000000, xtal_Hz % 1000000);
UI_PrintString(String, menu_item_x1, menu_item_x2, 2, 8);
UI_PrintString("MHz", menu_item_x1, menu_item_x2, 4, 8);
already_printed = true;
sprintf(String, "%d\n%u.%06u\nMHz",
gSubMenuSelection,
xtal_Hz / 1000000, xtal_Hz % 1000000);
}
break;
case MENU_BATCAL:
{
const uint16_t vol = (uint32_t)gBatteryVoltageAverage * gBatteryCalibration[3] / gSubMenuSelection;
sprintf(String, "%u.%02uV\n%u", vol / 100, vol % 100, gSubMenuSelection);
break;
}
}
if (!already_printed)
UI_PrintString(String, menu_item_x1, menu_item_x2, 2, 8);
{
unsigned int y;
unsigned int k = 0;
unsigned int lines = 1;
unsigned int len = strlen(String);
bool small = false;
if (len > 0)
{
// count number of lines
for (i = 0; i < len; i++)
{
if (String[i] == '\n' && i < (len - 1))
{
lines++;
String[i] = 0;
}
}
if (lines > 3)
{ // use small text
small = true;
if (lines > 7)
lines = 7;
}
// move the 1st line up
if (small)
y = 3 - ((lines + 0) / 2);
else
y = 2 - ((lines + 0) / 2);
for (i = 0; i < len && lines > 0; lines--)
{
if (small)
UI_PrintStringSmall(String + k, menu_item_x1, menu_item_x2, y);
else
UI_PrintString(String + k, menu_item_x1, menu_item_x2, y, 8);
while (i < len && String[i] >= 32)
i++;
k = ++i;
y += small ? 1 : 2;
}
}
}
if (gMenuCursor == MENU_SLIST1 || gMenuCursor == MENU_SLIST2)
{

View File

@@ -79,11 +79,11 @@ enum
MENU_ANI_ID,
MENU_UPCODE,
MENU_DWCODE,
MENU_PTT_ID,
MENU_D_ST,
MENU_D_RSP,
MENU_D_HOLD,
MENU_D_PRE,
MENU_PTT_ID,
MENU_D_DCD,
MENU_D_LIST,
MENU_D_LIVE_DEC,
@@ -113,7 +113,8 @@ enum
MENU_SCREN,
MENU_TX_EN, // enable TX
MENU_F_CALI // reference xtal calibration
MENU_F_CALI, // reference xtal calibration
MENU_BATCAL // battery voltage calibration
};
extern const t_menu_item MenuList[];
@@ -124,18 +125,19 @@ extern const char gSubMenu_W_N[2][7];
extern const char gSubMenu_OFF_ON[2][4];
extern const char gSubMenu_SAVE[5][4];
extern const char gSubMenu_TOT[11][7];
extern const char gSubMenu_CHAN[3][7];
extern const char gSubMenu_CHAN[3][10];
extern const char gSubMenu_XB[3][10];
#ifdef ENABLE_VOICE
extern const char gSubMenu_VOICE[3][4];
#endif
extern const char gSubMenu_SC_REV[3][3];
extern const char gSubMenu_MDF[4][8];
extern const char gSubMenu_SC_REV[3][13];
extern const char gSubMenu_MDF[4][15];
#ifdef ENABLE_ALARM
extern const char gSubMenu_AL_MOD[2][5];
#endif
extern const char gSubMenu_D_RSP[4][6];
extern const char gSubMenu_PTT_ID[4][5];
extern const char gSubMenu_PONMSG[4][5];
extern const char gSubMenu_PTT_ID[4][7];
extern const char gSubMenu_PONMSG[4][8];
extern const char gSubMenu_ROGER[3][6];
extern const char gSubMenu_RESET[2][4];
extern const char gSubMenu_F_LOCK[6][4];
@@ -155,6 +157,7 @@ extern bool gIsInSubMenu;
extern uint8_t gMenuCursor;
extern int8_t gMenuScrollDirection;
extern int32_t gSubMenuSelection;
extern int32_t gSubMenuSelection_original;
extern char edit_original[17];
extern char edit[17];

View File

@@ -169,8 +169,7 @@ void UI_DisplayStatus(const bool test_display)
case 2: // percentage
{
const uint16_t percent = BATTERY_VoltsToPercent(gBatteryVoltageAverage);
sprintf(s, "%u%%", percent);
sprintf(s, "%u%%", BATTERY_VoltsToPercent(gBatteryVoltageAverage));
space_needed = (7 * strlen(s));
if (x2 >= (x1 + space_needed))
UI_PrintStringSmallBuffer(s, line + x2 - space_needed);

View File

@@ -91,7 +91,6 @@ void GUI_SelectNextDisplay(GUI_DisplayType_t Display)
gAskForConfirmation = 0;
gDTMF_InputMode = false;
gDTMF_InputIndex = 0;
gF_LOCK = false;
gAskToSave = false;
gAskToDelete = false;

View File

@@ -27,6 +27,18 @@
#include "ui/status.h"
#include "version.h"
void UI_DisplayReleaseKeys(void)
{
memset(gStatusLine, 0, sizeof(gStatusLine));
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
UI_PrintString("RELEASE", 0, 127, 1, 10);
UI_PrintString("ALL KEYS", 0, 127, 3, 10);
ST7565_BlitStatusLine(); // blank status line
ST7565_BlitFullScreen();
}
void UI_DisplayWelcome(void)
{
char WelcomeString0[16];

View File

@@ -17,6 +17,7 @@
#ifndef UI_WELCOME_H
#define UI_WELCOME_H
void UI_DisplayReleaseKeys(void);
void UI_DisplayWelcome(void);
#endif

View File

@@ -4,7 +4,7 @@
#ifdef GIT_HASH
#define VER GIT_HASH
#else
#define VER "230929"
#define VER "231002"
#endif
#ifndef ONE_OF_ELEVEN_VER