67 Commits
v0.14 ... v0.18

Author SHA1 Message Date
Krzysiek Egzmont
a0d052b68b Spectrum refactor 2023-11-25 19:28:21 +01:00
Krzysiek Egzmont
9a3249a667 FIX #121: Rise tones volume 2023-11-23 21:20:24 +01:00
Krzysiek Egzmont
ffdc0e03b5 FIX #114, #120: Restart monitor mode on PTT release, long press EXIT exits monitor mode 2023-11-23 21:02:47 +01:00
Krzysiek Egzmont
d8d4384b20 Refactoring 2023-11-23 19:48:47 +01:00
Krzysiek Egzmont
0ce7d7bdc3 FIX #129: Bug in radio initialization after reset. 2023-11-22 23:40:39 +01:00
Krzysiek Egzmont
fb30ec8c86 Refactor 2023-11-22 23:40:20 +01:00
Krzysiek Egzmont
67307463e2 FIX #92: Adjust s-meter values 2023-11-22 14:52:16 +01:00
Krzysiek Egzmont
fdd7fc063e Cleanup docker container after build 2023-11-22 14:51:53 +01:00
Krzysiek Egzmont
592810b7d7 FIX #125: Frequency input on the first VFO blanks the display on the second 2023-11-20 22:32:39 +01:00
Krzysiek Egzmont
6e5e7e7aef FIX #85: Equalize tones volume in DTMF codes, fix wrong DTMF frequency values 2023-11-20 21:24:09 +01:00
ErikS-web
cd0dc71de6 Update README.md
Type error corrected
2023-11-18 21:26:37 +01:00
Krzysiek Egzmont
a43a3f949f READ MANUAL prompt for unlocking TX 2023-11-09 10:33:28 +01:00
Krzysiek Egzmont
d7b6cdf444 Modify release GH action 2023-11-08 18:57:50 +01:00
BG8LGP
7916d79ff1 Add github actions #86 2023-11-08 02:35:59 +01:00
Krzysiek Egzmont
49cec54cd3 TX on all bands #68 2023-11-08 01:43:06 +01:00
Krzysiek Egzmont
f154aebd38 Refactoring 2023-11-08 01:29:14 +01:00
ErikS-web
aaa55c5742 Update README.md
Cosmetic corrections
2023-11-07 21:49:20 +01:00
ErikS-web
345f1444f5 Update README.md
spelling mistake corrected
2023-11-07 21:39:22 +01:00
Krzysiek Egzmont
7e91d67b53 Mic bar in the same style as an s-meter 2023-11-07 17:11:25 +01:00
Krzysiek Egzmont
ba29176f33 Don't display mic bar over low the battery popup 2023-11-07 17:11:25 +01:00
Krzysiek Egzmont
05feff432e Rename build option 2023-11-07 17:11:24 +01:00
egzumer
cf4f85cb22 Update README.md 2023-11-07 17:09:07 +01:00
Krzysiek Egzmont
a0c2181197 Fix build error 2023-11-06 21:58:27 +01:00
Krzysiek Egzmont
b4abf369e1 FIX #76: Apollo Quindar mutes microphone 2023-11-06 16:20:45 +01:00
Krzysiek Egzmont
be0636d69b Readme update 2023-11-06 15:57:22 +01:00
wrobepio
23986a8648 Add "BLMIN TMP OFF" function for programmable buttons 2023-11-06 15:55:13 +01:00
Krzysiek Egzmont
b1d3a95ca2 Replace RX CSS menu scanning procedure with BK scanning method 2023-11-06 01:25:44 +01:00
Krzysiek Egzmont
1238bf090c Refactoring of cxcss and channel/frequency scanner code 2023-11-06 01:23:36 +01:00
Krzysiek Egzmont
5987e03141 Change names of some submenu items #80 2023-11-04 17:53:33 +01:00
Krzysiek Egzmont
c5e34c4be9 Delete immediate applying of CTCSS/DCS while scrolling options in the menu.
This also caused the option change not to be discarded on EXIT
2023-11-03 16:39:25 +01:00
Krzysiek Egzmont
b0a01cd8cf BYP/RAW removed by default, can be enabled by compile option 2023-11-03 12:51:06 +01:00
Krzysiek Egzmont
21535c9ca0 Don't use AM fix for USB/BYP/RAW 2023-11-03 12:18:31 +01:00
Krzysiek Egzmont
8c9bdaacbc Add "switch demodulation mode" function for programmable buttons 2023-11-03 01:15:29 +01:00
Krzysiek Egzmont
388c3dadf1 SSB, BYP, RAW demodulation modes added #64 2023-11-03 01:15:29 +01:00
Krzysiek Egzmont
72fc4bf52f FIX #60: LCD interference glitch 2023-11-03 01:13:28 +01:00
Krzysiek Egzmont
def555678d Refactoring 2023-11-02 21:56:48 +01:00
Krzysiek Egzmont
16e79bee7d Change the overvoltage level back to 8.9V 2023-11-02 21:34:10 +01:00
Krzysiek Egzmont
9777b5df8b Modified battery icon levels 2023-11-02 02:44:05 +01:00
Krzysiek Egzmont
c057f8a097 FIX #74: limit spectrum analyzer RSSI trigger values 2023-11-02 01:46:21 +01:00
Krzysiek Egzmont
034139d7d5 Battery curve, slight modification 2023-11-02 00:54:48 +01:00
Krzysiek Egzmont
03a51525b6 Fix s-meter over S9 values calculation 2023-11-01 23:37:31 +01:00
Krzysiek Egzmont
f074114d13 Makefile improvements 2023-11-01 22:35:13 +01:00
Krzysiek Egzmont
8a60535f9d Updated wiki 2023-11-01 20:36:19 +01:00
Krzysiek Egzmont
c2be853ef1 Low battery popup 2023-11-01 01:43:09 +01:00
Krzysiek Egzmont
9f1e6ab91f Extra UI helper functions 2023-11-01 00:10:03 +01:00
Krzysiek Egzmont
25334823e5 Refactoring 2023-10-31 19:58:10 +01:00
Krzysiek Egzmont
2796973ad3 Use the custom battery percentage calculations for battery icon and low battery beeping 2023-10-31 19:40:00 +01:00
Krzysiek Egzmont
2344478301 fix build error 2023-10-31 17:34:09 +01:00
Krzysiek Egzmont
61527d1281 More frequency steps 2023-10-31 14:33:05 +01:00
Krzysiek Egzmont
140b5f4b4a Added second discharge curve for 2200mAh type battery and hidden BatTyp menu entry 2023-10-31 00:41:53 +01:00
Krzysiek Egzmont
3e0ea6f7de Backlight setting 1 was fully off for some reason on higher freq PWM 2023-10-30 18:57:35 +01:00
Krzysiek Egzmont
ed64c7fb49 Mid, low power reduction mod from 1o11 2023-10-30 18:17:54 +01:00
Krzysiek Egzmont
d70fa1b7b4 Refactor 2023-10-30 16:39:18 +01:00
Krzysiek Egzmont
a41628410e FIX #65: code refactoring 2023-10-30 13:26:16 +01:00
Krzysiek Egzmont
f7c25b482d FIX #55: Broken DTMF calling (D Decd) 2023-10-29 22:26:48 +01:00
Krzysiek Egzmont
ac3cd08163 serial debugging helper 2023-10-28 23:11:52 +02:00
Krzysiek Egzmont
c1657a37f2 Refactor 2023-10-28 22:50:42 +02:00
Krzysiek Egzmont
a2580d5d8d Increase backlight PWM frequency to reduce flicker 2023-10-28 16:10:37 +02:00
Krzysiek Egzmont
5d4f7529ed Refactor 2023-10-28 16:09:49 +02:00
Krzysiek Egzmont
20a3e3b605 Fix STE not working when TX CTCSS/DCS is off
Reverts:
fde690a74a: app.c
50a55e34ab: radio.c
2023-10-28 14:41:47 +02:00
Krzysiek Egzmont
f3cc0f5acf Comments, refactor 2023-10-28 14:39:13 +02:00
Krzysiek Egzmont
2086bd6aaa Comments, refactor 2023-10-28 10:53:07 +02:00
Krzysiek Egzmont
3b3db88e5e Fix s-meter displaying for overpowering signals 2023-10-28 10:50:51 +02:00
Krzysiek Egzmont
f6791395cc Modified displaying of little sbar 2023-10-28 10:45:56 +02:00
Krzysiek Egzmont
8739996668 Changed little sbar back to factory 2023-10-27 15:32:14 +02:00
Krzysiek Egzmont
1740583ccc Set the backlight to minimum on reboot 2023-10-27 11:08:28 +02:00
Krzysiek Egzmont
b12244e352 Fix the RX buzzing problem after reboot 2023-10-27 10:53:22 +02:00
60 changed files with 2446 additions and 2232 deletions

33
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
on:
push:
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: arm-none-eabi-gcc
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
release: '10.3-2021.10'
- name: Install Python dependencies
run: python -m pip install --upgrade pip crcmod
- name: Checkout
uses: actions/checkout@v3
- name: Submodules
run: git submodule update --init --recursive --depth 1
- name: Make
run: make
- name: size
run: arm-none-eabi-size firmware
- name: 'Upload Artifact'
uses: actions/upload-artifact@v3
with:
name: firmware
path: firmware*.bin

45
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,45 @@
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: arm-none-eabi-gcc
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
release: '10.3-2021.10'
- name: Install Python dependencies
run: python3 -m pip install --upgrade pip crcmod
- name: Checkout
uses: actions/checkout@v3
- name: Submodules
run: git submodule update --init --recursive --depth 1
- name: Make
run: make
- name: size
run: arm-none-eabi-size firmware
- name: 'Upload Artifact'
uses: actions/upload-artifact@v3
with:
name: firmware
path: firmware*.bin
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: firmware.packed.bin
asset_name: egzumer_$tag.packed.bin
tag: ${{ github.ref }}
overwrite: true
release_name: release ${{ github.ref_name }}

View File

@@ -26,7 +26,7 @@ ENABLE_CTCSS_TAIL_PHASE_SHIFT := 0
ENABLE_BOOT_BEEPS := 0
ENABLE_SHOW_CHARGE_LEVEL := 1
ENABLE_REVERSE_BAT_SYMBOL := 0
ENABLE_CODE_SCAN_TIMEOUT := 0
ENABLE_NO_CODE_SCAN_TIMEOUT := 1
ENABLE_AM_FIX := 1
ENABLE_AM_FIX_SHOW_DATA := 0
ENABLE_SQUELCH_MORE_SENSITIVE := 1
@@ -35,9 +35,9 @@ ENABLE_RSSI_BAR := 1
ENABLE_AUDIO_BAR := 1
ENABLE_COPY_CHAN_TO_VFO := 1
ENABLE_SPECTRUM := 1
#ENABLE_SINGLE_VFO_CHAN := 1
#ENABLE_BAND_SCOPE := 1
ENABLE_REDUCE_LOW_MID_TX_POWER:= 0
ENABLE_BYP_RAW_DEMODULATORS := 0
ENABLE_BLMIN_TMP_OFF := 0
#############################################################
TARGET = firmware
@@ -99,12 +99,13 @@ ifeq ($(ENABLE_AIRCOPY),1)
OBJS += app/aircopy.o
endif
OBJS += app/app.o
OBJS += app/chFrScanner.o
OBJS += app/common.o
OBJS += app/dtmf.o
ifeq ($(ENABLE_FMRADIO),1)
OBJS += app/fm.o
endif
OBJS += app/generic.o
OBJS += app/common.o
OBJS += app/main.o
OBJS += app/menu.o
ifeq ($(ENABLE_SPECTRUM), 1)
@@ -211,6 +212,7 @@ endif
# catch any and all warnings
CFLAGS += -Wextra
#CFLAGS += -Wpedantic
CFLAGS += -DPRINTF_INCLUDE_CONFIG_H
CFLAGS += -DGIT_HASH=\"$(GIT_HASH)\"
@@ -281,7 +283,7 @@ endif
ifeq ($(ENABLE_REVERSE_BAT_SYMBOL),1)
CFLAGS += -DENABLE_REVERSE_BAT_SYMBOL
endif
ifeq ($(ENABLE_CODE_SCAN_TIMEOUT),1)
ifeq ($(ENABLE_NO_CODE_SCAN_TIMEOUT),1)
CFLAGS += -DENABLE_CODE_SCAN_TIMEOUT
endif
ifeq ($(ENABLE_AM_FIX),1)
@@ -317,6 +319,15 @@ endif
ifeq ($(ENABLE_BAND_SCOPE),1)
CFLAGS += -DENABLE_BAND_SCOPE
endif
ifeq ($(ENABLE_REDUCE_LOW_MID_TX_POWER),1)
CFLAGS += -DENABLE_REDUCE_LOW_MID_TX_POWER
endif
ifeq ($(ENABLE_BYP_RAW_DEMODULATORS),1)
CFLAGS += -DENABLE_BYP_RAW_DEMODULATORS
endif
ifeq ($(ENABLE_BLMIN_TMP_OFF),1)
CFLAGS += -DENABLE_BLMIN_TMP_OFF
endif
LDFLAGS =
ifeq ($(ENABLE_CLANG),0)
@@ -349,10 +360,44 @@ LIBS =
DEPS = $(OBJS:.o=.d)
ifdef OS
RM = del /Q
FixPath = $(subst /,\,$1)
WHERE = where
else
ifeq ($(shell uname), Linux)
RM = rm -f
FixPath = $1
WHERE = which
endif
endif
ifneq (, $(shell $(WHERE) python))
MY_PYTHON := python
else ifneq (, $(shell $(WHERE) python3))
MY_PYTHON := python3
endif
ifdef MY_PYTHON
HAS_CRCMOD := $(shell $(MY_PYTHON) -c "import crcmod" 2>&1)
endif
all: $(TARGET)
$(OBJCOPY) -O binary $< $<.bin
-python fw-pack.py $<.bin $(GIT_HASH) $<.packed.bin
-python3 fw-pack.py $<.bin $(GIT_HASH) $<.packed.bin
ifndef MY_PYTHON
$(info )
$(info !!!!!!!! PYTHON NOT FOUND, *.PACKED.BIN WON'T BE BUILT)
$(info )
else ifneq (,$(HAS_CRCMOD))
$(info )
$(info !!!!!!!! CRCMOD NOT INSTALLED, *.PACKED.BIN WON'T BE BUILT)
$(info !!!!!!!! run: pip install crcmod)
$(info )
else
-$(MY_PYTHON) fw-pack.py $<.bin $(GIT_HASH) $<.packed.bin
endif
$(SIZE) $<
debug:
@@ -379,4 +424,4 @@ bsp/dp32g030/%.h: hardware/dp32g030/%.def
-include $(DEPS)
clean:
rm -f $(TARGET).bin $(TARGET).packed.bin $(TARGET) $(OBJS) $(DEPS)
$(RM) $(call FixPath, $(TARGET).bin $(TARGET).packed.bin $(TARGET) $(OBJS) $(DEPS))

View File

@@ -1,22 +1,47 @@
# Main features:
- many of OneOfEleven mods, including AM fix
- fagci spectrum analyzer (**F+5** to turn on)
- some other smaller mods introduced by me
* many of OneOfEleven mods:
* AM fix, huge improvement in reception quality
* longpress buttons functions replicating F+ action
* fast scanning
* channel name editing in the menu
* channel name + frequency display option
* shortcut for scannlist assignment (longpress `5 NOAA`)
* scannlist toggle (longpress `* Scan` while scanning)
* configurable button function selectable from menu
* battery percentage/voltage on status bar, selectable from menu
* longer backlight times
* mic bar
* RSSI s-meter
* more frequency steps
* squelch more sensitive
* fagci spectrum analyzer (**F+5** to turn on)
* some other mods introduced by me:
* SSB demodulation (adopted from fagci)
* backlight dimming
* battery voltage callibration from menu
* better battery percentage calculation, selectable for 1600mAh or 2200mAh
* more configurable button functions
* longpress MENU as another configurable button
* better DCS/CTCSS scanning in the menu (`* SCAN` while in RX DCS/CTCSS menu item)
* Piotr022 s-meter style
* restore initial freq/channel when scanning stopped with EXIT, remember last found transmission with MENU button
* reordered and renamed menu entries
* LCD interference crash fix
Go to [Wiki](https://github.com/egzumer/uv-k5-firmware-custom/wiki) to learn more.
# Manual
* [Radio operation](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Radio-operation)
* [Menu](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Menu)
* [Button functions](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Button-functions)
* [Spectrum analyzer](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Spectrum-analyzer)
* [Flashing the firmware](https://github.com/egzumer/uv-k5-firmware-custom/wiki/Flashing-the-firmware)
<img src="images/main.jpg" width=300 /><img src="images/spectrum.jpg" width=300 /><img src="images/audiobar.jpg" width=300 /><img src="images/rssibar.jpg" width=300 />
❗❗❗You can now calibrate the battery voltage reading in the radio menu.
<img src="images/batcal.jpg" width=300 />
To enter the calibration:
1. turn the radio on while holding PTT and the first side button
2. go to BATCAL option and adjust the voltage with UP/DOWN buttons
3. confirm the setting, calibration will be saved to EEPROM
# Open reimplementation of the Quan Sheng UV-K5 v2.1.27 firmware
@@ -73,45 +98,25 @@ ENABLE_SMALL_BOLD := 1 bold channel name/no. (when name + freq
ENABLE_KEEP_MEM_NAME := 1 maintain channel name when (re)saving memory channel
ENABLE_WIDE_RX := 1 full 18MHz to 1300MHz RX (though front-end/PA not designed for full range)
ENABLE_TX_WHEN_AM := 0 allow TX (always FM) when RX is set to AM
ENABLE_F_CAL_MENU := 0 enable/disable the radios hidden frequency calibration menu
ENABLE_F_CAL_MENU := 0 enable the radios hidden frequency calibration menu
ENABLE_CTCSS_TAIL_PHASE_SHIFT := 1 standard CTCSS tail phase shift rather than QS's own 55Hz tone method
ENABLE_BOOT_BEEPS := 0 gives user audio feedback on volume knob position at boot-up
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_CODE_SCAN_TIMEOUT := 0 enable/disable 32-sec CTCSS/DCS scan timeout (press exit butt instead of time-out to end scan)
ENABLE_NO_CODE_SCAN_TIMEOUT := 1 disable 32-sec CTCSS/DCS scan timeout (press exit butt instead of time-out to end scan)
ENABLE_AM_FIX := 1 dynamically adjust the front end gains when in AM mode to helo prevent AM demodulator saturation, ignore the on-screen RSSI level (for now)
ENABLE_AM_FIX_SHOW_DATA := 1 show debug data for the AM fix (still tweaking it)
ENABLE_SQUELCH_MORE_SENSITIVE := 0 make squelch levels a little bit more sensitive - I plan to let user adjust the values themselves
ENABLE_FASTER_CHANNEL_SCAN := 0 increases the channel scan speed, but the squelch is also made more twitchy
ENABLE_RSSI_BAR := 1 enable a dBm/Sn RSSI bar graph level inplace of the little antenna symbols
ENABLE_AUDIO_BAR := 0 experimental, display an audo bar level when TX'ing
ENABLE_COPY_CHAN_TO_VFO := 1 copy current channel into the other VFO. Long press Menu key ('M')
#ENABLE_SINGLE_VFO_CHAN := 1 not yet implemented - single VFO on display when possible
#ENABLE_BAND_SCOPE := 1 not yet implemented - spectrum/pan-adapter
ENABLE_AUDIO_BAR := 0 experimental, display an audio bar level when TX'ing
ENABLE_COPY_CHAN_TO_VFO := 1 copy current channel into the other VFO. Long press `1 BAND` when in channel mode
ENABLE_SPECTRUM := 1 fagci spectrum analizer, activated with `F` + `5 NOAA`
ENABLE_REDUCE_LOW_MID_TX_POWER:= 0 makes medium and low power settings even lower
ENABLE_BYP_RAW_DEMODULATORS := 0 additional BYP (bypass?) and RAW demodulation options, prooved not to be very usefull, but it is there if you want to experiment
ENABLE_BLMIN_TMP_OFF := 0 additional function for configurable buttons that toggles `BLMin` on and off wihout saving it to the EEPROM
```
# New/modified function keys
* Long-press 'M' .. Copy selected channel into same VFO, then switch VFO to frequency mode
*
* Long-press '7' .. Toggle selected channel scanlist setting .. if VOX is disabled in Makefile
* or
* Long-press '5' .. Toggle selected channel scanlist setting .. if NOAA is disabled in Makefile
*
* Long-press '*' .. Start scanning, then toggles the scanning between scanlists 1, 2 or ALL channels
# Some changes made from the Quansheng firmware
* Various Quansheng firmware bugs fixed
* Added new bugs
* Mic menu includes max gain possible
* AM RX everywhere (left the TX as is)
* An attempt to improve the AM RX audio (demodulator getting saturated/overloaded in Quansheng firmware)
* keypad-5/NOAA button now toggles scanlist-1 on/off for current channel when held down - IF NOAA not used
* Better backlight times (inc always on)
* Live DTMF decoder option, though the decoder needs some coeff tuning changes to decode other radios it seems
* Various menu re-wordings (trying to reduce 'WTH does that mean ?')
* ..
# Compiler

View File

@@ -18,6 +18,7 @@
#include "app/action.h"
#include "app/app.h"
#include "app/chFrScanner.h"
#include "app/common.h"
#include "app/dtmf.h"
#ifdef ENABLE_FMRADIO
@@ -31,6 +32,7 @@
#endif
#include "driver/bk4819.h"
#include "driver/gpio.h"
#include "driver/backlight.h"
#include "functions.h"
#include "misc.h"
#include "settings.h"
@@ -61,24 +63,22 @@ void ACTION_Power(void)
gTxVfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
gRequestSaveChannel = 1;
//gRequestSaveChannel = 2; // auto save the channel
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_POWER;
#endif
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_POWER;
#endif
gRequestDisplayScreen = gScreenToDisplay;
}
void ACTION_Monitor(void)
{
if (gCurrentFunction != FUNCTION_MONITOR)
{ // enable the monitor
if (gCurrentFunction != FUNCTION_MONITOR) { // enable the monitor
RADIO_SelectVfos();
#ifdef ENABLE_NOAA
if (gRxVfo->CHANNEL_SAVE >= NOAA_CHANNEL_FIRST && gIsNoaaMode)
gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST;
#endif
#ifdef ENABLE_NOAA
if (gRxVfo->CHANNEL_SAVE >= NOAA_CHANNEL_FIRST && gIsNoaaMode)
gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST;
#endif
RADIO_SetupRegisters(true);
APP_StartListening(FUNCTION_MONITOR, false);
return;
@@ -86,36 +86,34 @@ void ACTION_Monitor(void)
gMonitor = false;
if (gScanStateDir != SCAN_OFF)
{
if (gScanStateDir != SCAN_OFF) {
gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms;
gScheduleScanListen = false;
gScanPauseMode = true;
}
#ifdef ENABLE_NOAA
if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode)
{
gNOAA_Countdown_10ms = NOAA_countdown_10ms;
gScheduleNOAA = false;
}
#endif
#ifdef ENABLE_NOAA
if (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gIsNoaaMode) {
gNOAA_Countdown_10ms = NOAA_countdown_10ms;
gScheduleNOAA = false;
}
#endif
RADIO_SetupRegisters(true);
#ifdef ENABLE_FMRADIO
if (gFmRadioMode)
{
FM_Start();
gRequestDisplayScreen = DISPLAY_FM;
}
else
#endif
gRequestDisplayScreen = gScreenToDisplay;
#ifdef ENABLE_FMRADIO
if (gFmRadioMode) {
FM_Start();
gRequestDisplayScreen = DISPLAY_FM;
}
else
#endif
gRequestDisplayScreen = gScreenToDisplay;
}
void ACTION_Scan(bool bRestart)
{
(void)bRestart;
#ifdef ENABLE_FMRADIO
if (gFmRadioMode)
{
@@ -164,7 +162,7 @@ void ACTION_Scan(bool bRestart)
}
#endif
if (gScreenToDisplay != DISPLAY_SCANNER)
if (!SCANNER_IsScanning())
{ // not scanning
gMonitor = false;
@@ -192,7 +190,7 @@ void ACTION_Scan(bool bRestart)
gEeprom.SCAN_LIST_DEFAULT = (gEeprom.SCAN_LIST_DEFAULT + 1) % 3;
// jump to the next channel
SCANNER_ScanChannels(false, gScanStateDir);
CHFRSCANNER_Start(false, gScanStateDir);
gScanPauseDelayIn_10ms = 1;
gScheduleScanListen = false;
@@ -201,7 +199,7 @@ void ACTION_Scan(bool bRestart)
else
{ // stop scanning
SCANNER_Stop();
CHFRSCANNER_Stop();
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
@@ -211,7 +209,7 @@ void ACTION_Scan(bool bRestart)
else
{ // start scanning
SCANNER_ScanChannels(true, SCAN_FWD);
CHFRSCANNER_Start(true, SCAN_FWD);
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_SCANNING_BEGIN);
@@ -227,31 +225,6 @@ void ACTION_Scan(bool bRestart)
}
}
}
else
// if (!bRestart)
if (!bRestart && IS_MR_CHANNEL(gNextMrChannel))
{ // channel mode, keep scanning but toggle between scan lists
gEeprom.SCAN_LIST_DEFAULT = (gEeprom.SCAN_LIST_DEFAULT + 1) % 3;
// jump to the next channel
SCANNER_ScanChannels(false, gScanStateDir);
gScanPauseDelayIn_10ms = 1;
gScheduleScanListen = false;
gUpdateStatus = true;
}
else
{ // stop scanning
gMonitor = false;
SCANNER_Stop();
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
gRequestDisplayScreen = DISPLAY_MAIN;
}
}
#ifdef ENABLE_VOX
@@ -270,6 +243,7 @@ void ACTION_Scan(bool bRestart)
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
static void ACTION_AlarmOr1750(const bool b1750)
{
(void)b1750;
gInputBoxIndex = 0;
#if defined(ENABLE_ALARM) && defined(ENABLE_TX1750)
@@ -323,6 +297,28 @@ void ACTION_Scan(bool bRestart)
}
#endif
void ACTION_SwitchDemodul(void)
{
gTxVfo->Modulation++;
if(gTxVfo->Modulation == MODULATION_UKNOWN)
gTxVfo->Modulation = MODULATION_FM;
gRequestSaveChannel = 1;
}
#ifdef ENABLE_BLMIN_TMP_OFF
void ACTION_BlminTmpOff(void)
{
if(++gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_UNKNOWN)
{
gEeprom.BACKLIGHT_MIN_STAT = BLMIN_STAT_ON;
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN);
} else
{
BACKLIGHT_SetBrightness(0);
}
}
#endif
void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
if (gScreenToDisplay == DISPLAY_MAIN && gDTMF_InputMode) // entering DTMF code
@@ -438,5 +434,13 @@ void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
case ACTION_OPT_VFO_MR:
COMMON_SwitchVFOMode();
break;
case ACTION_OPT_SWITCH_DEMODUL:
ACTION_SwitchDemodul();
break;
#ifdef ENABLE_BLMIN_TMP_OFF
case ACTION_OPT_BLMIN_TMP_OFF:
ACTION_BlminTmpOff();
break;
#endif
}
}

View File

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

618
app/app.c

File diff suppressed because it is too large Load Diff

262
app/chFrScanner.c Normal file
View File

@@ -0,0 +1,262 @@
#include "app/app.h"
#include "app/chFrScanner.h"
#include "functions.h"
#include "misc.h"
#include "settings.h"
int8_t gScanStateDir;
bool gScanKeepResult;
bool gScanPauseMode;
typedef enum {
SCAN_NEXT_CHAN_SCANLIST1 = 0,
SCAN_NEXT_CHAN_SCANLIST2,
SCAN_NEXT_CHAN_DUAL_WATCH,
SCAN_NEXT_CHAN_MR,
SCAN_NEXT_NUM
} scan_next_chan_t;
scan_next_chan_t currentScanList;
uint32_t initialFrqOrChan;
uint8_t initialCROSS_BAND_RX_TX;
uint32_t lastFoundFrqOrChan;
static void NextFreqChannel(void);
static void NextMemChannel(void);
void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction)
{
if (storeBackupSettings) {
initialCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gScanKeepResult = false;
}
RADIO_SelectVfos();
gNextMrChannel = gRxVfo->CHANNEL_SAVE;
currentScanList = SCAN_NEXT_CHAN_SCANLIST1;
gScanStateDir = scan_direction;
if (IS_MR_CHANNEL(gNextMrChannel))
{ // channel mode
if (storeBackupSettings) {
initialFrqOrChan = gRxVfo->CHANNEL_SAVE;
lastFoundFrqOrChan = initialFrqOrChan;
}
NextMemChannel();
}
else
{ // frequency mode
if (storeBackupSettings) {
initialFrqOrChan = gRxVfo->freq_config_RX.Frequency;
lastFoundFrqOrChan = initialFrqOrChan;
}
NextFreqChannel();
}
gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms;
gScheduleScanListen = false;
gRxReceptionMode = RX_MODE_NONE;
gScanPauseMode = false;
}
void CHFRSCANNER_ContinueScanning(void)
{
if (IS_FREQ_CHANNEL(gNextMrChannel))
{
if (gCurrentFunction == FUNCTION_INCOMING)
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true);
else
NextFreqChannel(); // switch to next frequency
}
else
{
if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING)
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true);
else
NextMemChannel(); // switch to next channel
}
gScanPauseMode = false;
gRxReceptionMode = RX_MODE_NONE;
gScheduleScanListen = false;
}
void CHFRSCANNER_Found(void)
{
switch (gEeprom.SCAN_RESUME_MODE)
{
case SCAN_RESUME_TO:
if (!gScanPauseMode)
{
gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms;
gScheduleScanListen = false;
gScanPauseMode = true;
}
break;
case SCAN_RESUME_CO:
case SCAN_RESUME_SE:
gScanPauseDelayIn_10ms = 0;
gScheduleScanListen = false;
break;
}
if (IS_MR_CHANNEL(gRxVfo->CHANNEL_SAVE)) { //memory scan
lastFoundFrqOrChan = gRxVfo->CHANNEL_SAVE;
}
else { // frequency scan
lastFoundFrqOrChan = gRxVfo->freq_config_RX.Frequency;
}
gScanKeepResult = true;
}
void CHFRSCANNER_Stop(void)
{
if(initialCROSS_BAND_RX_TX != CROSS_BAND_OFF) {
gEeprom.CROSS_BAND_RX_TX = initialCROSS_BAND_RX_TX;
initialCROSS_BAND_RX_TX = CROSS_BAND_OFF;
}
gScanStateDir = SCAN_OFF;
const uint32_t chFr = gScanKeepResult ? lastFoundFrqOrChan : initialFrqOrChan;
const bool channelChanged = chFr != initialFrqOrChan;
if (IS_MR_CHANNEL(gNextMrChannel)) {
gEeprom.MrChannel[gEeprom.RX_VFO] = chFr;
gEeprom.ScreenChannel[gEeprom.RX_VFO] = chFr;
RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD);
if(channelChanged) {
SETTINGS_SaveVfoIndices();
gUpdateStatus = true;
}
}
else {
gRxVfo->freq_config_RX.Frequency = chFr;
RADIO_ApplyOffset(gRxVfo);
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
if(channelChanged) {
SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_VFO, gRxVfo, 1);
}
}
RADIO_SetupRegisters(true);
gUpdateDisplay = true;
}
static void NextFreqChannel(void)
{
gRxVfo->freq_config_RX.Frequency = APP_SetFrequencyByStep(gRxVfo, gScanStateDir);
RADIO_ApplyOffset(gRxVfo);
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
RADIO_SetupRegisters(true);
#ifdef ENABLE_FASTER_CHANNEL_SCAN
gScanPauseDelayIn_10ms = 9; // 90ms
#else
gScanPauseDelayIn_10ms = scan_pause_delay_in_6_10ms;
#endif
gUpdateDisplay = true;
}
static void NextMemChannel(void)
{
static unsigned int prev_mr_chan = 0;
const bool enabled = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCAN_LIST_ENABLED[gEeprom.SCAN_LIST_DEFAULT] : true;
const int chan1 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH1[gEeprom.SCAN_LIST_DEFAULT] : -1;
const int chan2 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH2[gEeprom.SCAN_LIST_DEFAULT] : -1;
const unsigned int prev_chan = gNextMrChannel;
unsigned int chan = 0;
if (enabled)
{
switch (currentScanList)
{
case SCAN_NEXT_CHAN_SCANLIST1:
prev_mr_chan = gNextMrChannel;
if (chan1 >= 0)
{
if (RADIO_CheckValidChannel(chan1, false, 0))
{
currentScanList = SCAN_NEXT_CHAN_SCANLIST1;
gNextMrChannel = chan1;
break;
}
}
[[fallthrough]];
case SCAN_NEXT_CHAN_SCANLIST2:
if (chan2 >= 0)
{
if (RADIO_CheckValidChannel(chan2, false, 0))
{
currentScanList = SCAN_NEXT_CHAN_SCANLIST2;
gNextMrChannel = chan2;
break;
}
}
[[fallthrough]];
// this bit doesn't yet work if the other VFO is a frequency
case SCAN_NEXT_CHAN_DUAL_WATCH:
// dual watch is enabled - include the other VFO in the scan
// if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
// {
// chan = (gEeprom.RX_VFO + 1) & 1u;
// chan = gEeprom.ScreenChannel[chan];
// if (IS_MR_CHANNEL(chan))
// {
// currentScanList = SCAN_NEXT_CHAN_DUAL_WATCH;
// gNextMrChannel = chan;
// break;
// }
// }
default:
case SCAN_NEXT_CHAN_MR:
currentScanList = SCAN_NEXT_CHAN_MR;
gNextMrChannel = prev_mr_chan;
chan = 0xff;
break;
}
}
if (!enabled || chan == 0xff)
{
chan = RADIO_FindNextChannel(gNextMrChannel + gScanStateDir, gScanStateDir, (gEeprom.SCAN_LIST_DEFAULT < 2) ? true : false, gEeprom.SCAN_LIST_DEFAULT);
if (chan == 0xFF)
{ // no valid channel found
chan = MR_CHANNEL_FIRST;
}
gNextMrChannel = chan;
}
if (gNextMrChannel != prev_chan)
{
gEeprom.MrChannel[ gEeprom.RX_VFO] = gNextMrChannel;
gEeprom.ScreenChannel[gEeprom.RX_VFO] = gNextMrChannel;
RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD);
RADIO_SetupRegisters(true);
gUpdateDisplay = true;
}
#ifdef ENABLE_FASTER_CHANNEL_SCAN
gScanPauseDelayIn_10ms = 9; // 90ms .. <= ~60ms it misses signals (squelch response and/or PLL lock time) ?
#else
gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms;
#endif
if (enabled)
if (++currentScanList >= SCAN_NEXT_NUM)
currentScanList = SCAN_NEXT_CHAN_SCANLIST1; // back round we go
}

18
app/chFrScanner.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef APP_CHFRSCANNER_H
#define APP_CHFRSCANNER_H
#include <stdbool.h>
#include <stdint.h>
// scan direction, if not equal SCAN_OFF indicates
// that we are in a process of scanning channels/frequencies
extern int8_t gScanStateDir;
extern bool gScanKeepResult;
extern bool gScanPauseMode;
void CHFRSCANNER_Found(void);
void CHFRSCANNER_Stop(void);
void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_direction);
void CHFRSCANNER_ContinueScanning(void);
#endif

View File

@@ -17,6 +17,7 @@
#include <string.h>
#include <stdio.h> // NULL
#include "app/chFrScanner.h"
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
#endif
@@ -209,7 +210,7 @@ void DTMF_HandleRequest(void)
if (!gDTMF_RX_pending)
return; // nothing new received
if (gScanStateDir != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF)
if (gScanStateDir != SCAN_OFF || gCssBackgroundScan)
{ // we're busy scanning
DTMF_clear_RX();
return;
@@ -434,7 +435,7 @@ void DTMF_Reply(void)
if (gEeprom.DTMF_SIDE_TONE)
{ // the user will also hear the transmitted tones
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
}
@@ -450,7 +451,7 @@ void DTMF_Reply(void)
gEeprom.DTMF_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_INTERVAL_TIME);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;

View File

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

View File

@@ -17,6 +17,7 @@
#include <string.h>
#include "app/app.h"
#include "app/chFrScanner.h"
#include "app/common.h"
#ifdef ENABLE_FMRADIO
@@ -142,36 +143,21 @@ void GENERIC_Key_PTT(bool bKeyPressed)
// PTT pressed
if (gScanStateDir != SCAN_OFF || // frequency/channel scanning
gScreenToDisplay == DISPLAY_SCANNER || // CTCSS/CDCSS scanning
gCssScanMode != CSS_SCAN_MODE_OFF) // " "
{ // we're scanning .. stop
if (gScreenToDisplay == DISPLAY_SCANNER)
{ // CTCSS/CDCSS scanning .. stop
gEeprom.CROSS_BAND_RX_TX = gBackup_CROSS_BAND_RX_TX;
gFlagStopScan = true;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
gFlagResetVfos = true;
}
else
if (gScanStateDir != SCAN_OFF)
{ // frequency/channel scanning . .stop
SCANNER_Stop();
}
else
if (gCssScanMode != CSS_SCAN_MODE_OFF)
{ // CTCSS/CDCSS scanning .. stop
MENU_StopCssScan();
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
}
if (SCANNER_IsScanning())
{ // CTCSS/CDCSS scanning .. stop
SCANNER_Stop();
goto cancel_tx;
}
if (gScanStateDir != SCAN_OFF)
{ // frequency/channel scanning . .stop
CHFRSCANNER_Stop();
goto cancel_tx;
}
#ifdef ENABLE_FMRADIO
if (gFM_ScanState != FM_SCAN_OFF)
{ // FM radio is scanning .. stop
@@ -212,21 +198,12 @@ void GENERIC_Key_PTT(bool bKeyPressed)
if (gDTMF_InputBox_Index < sizeof(gDTMF_InputBox))
gDTMF_InputBox[gDTMF_InputBox_Index] = 0; // NULL term the string
#if 0
// append our DTMF ID to the inputted DTMF code -
// IF the user inputted code is exactly 3 digits long
if (gDTMF_InputBox_Index == 3)
gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3);
else
gDTMF_CallMode = DTMF_CALL_MODE_DTMF;
#else
// append our DTMF ID to the inputted DTMF code -
// IF the user inputted code is exactly 3 digits long and D-DCD is enabled
if (gDTMF_InputBox_Index == 3 && gTxVfo->DTMF_DECODING_ENABLE > 0)
gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3);
else
gDTMF_CallMode = DTMF_CALL_MODE_DTMF;
#endif
// append our DTMF ID to the inputted DTMF code -
// IF the user inputted code is exactly 3 digits long and D-DCD is enabled
if (gDTMF_InputBox_Index == 3 && gTxVfo->DTMF_DECODING_ENABLE > 0)
gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3);
else
gDTMF_CallMode = DTMF_CALL_MODE_DTMF;
// remember the DTMF string
gDTMF_PreviousIndex = gDTMF_InputBox_Index;

View File

@@ -18,6 +18,7 @@
#include "app/action.h"
#include "app/app.h"
#include "app/chFrScanner.h"
#include "app/common.h"
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
@@ -45,7 +46,7 @@
void toggle_chan_scanlist(void)
{ // toggle the selected channels scanlist setting
if (gScreenToDisplay == DISPLAY_SCANNER || !IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
if ( SCANNER_IsScanning() || !IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
return;
if (gTxVfo->SCANLIST1_PARTICIPATION)
@@ -105,7 +106,7 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
#ifdef ENABLE_COPY_CHAN_TO_VFO
if (gEeprom.VFO_OPEN && gCssScanMode == CSS_SCAN_MODE_OFF)
if (gEeprom.VFO_OPEN && !gCssBackgroundScan)
{
if (gScanStateDir != SCAN_OFF)
@@ -192,15 +193,15 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
case KEY_4:
gWasFKeyPressed = false;
gFlagStartScan = true;
gScanSingleFrequency = false;
gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gUpdateStatus = true;
if (beep)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
SCANNER_Start(false);
gRequestDisplayScreen = DISPLAY_SCANNER;
break;
case KEY_5:
@@ -506,7 +507,7 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
else
{
gScanKeepResult = false;
SCANNER_Stop();
CHFRSCANNER_Stop();
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
@@ -579,7 +580,7 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
if (bFlag)
{
if (gScanStateDir != SCAN_OFF) {
SCANNER_Stop();
CHFRSCANNER_Stop();
return;
}
@@ -651,19 +652,18 @@ static void MAIN_Key_STAR(bool bKeyPressed, bool bKeyHeld)
{ // with the F-key
gWasFKeyPressed = false;
#ifdef ENABLE_NOAA
if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
#endif
#ifdef ENABLE_NOAA
if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
#endif
// scan the CTCSS/DCS code
gFlagStartScan = true;
gScanSingleFrequency = true;
gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
SCANNER_Start(true);
gRequestDisplayScreen = DISPLAY_SCANNER;
}
gPttWasReleased = true;
@@ -764,7 +764,7 @@ static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
}
// jump to the next channel
SCANNER_ScanChannels(false, Direction);
CHFRSCANNER_Start(false, Direction);
gScanPauseDelayIn_10ms = 1;
gScheduleScanListen = false;

View File

@@ -47,6 +47,8 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
uint8_t gUnlockAllTxConfCnt;
#ifdef ENABLE_F_CAL_MENU
void writeXtalFreqCal(const int32_t value, const bool update_eeprom)
{
@@ -75,27 +77,39 @@
}
#endif
void MENU_StartCssScan(int8_t Direction)
void MENU_StartCssScan(void)
{
gCssScanMode = CSS_SCAN_MODE_SCANNING;
SCANNER_Start(true);
gUpdateStatus = true;
gCssBackgroundScan = true;
gMenuScrollDirection = Direction;
gRequestDisplayScreen = DISPLAY_MENU;
}
RADIO_SelectVfos();
void MENU_CssScanFound(void)
{
if(gScanCssResultType == CODE_TYPE_DIGITAL || gScanCssResultType == CODE_TYPE_REVERSE_DIGITAL) {
gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_DCS);
}
else if(gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) {
gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_CTCS);
}
MENU_SelectNextCode();
MENU_ShowCurrentSetting();
gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms;
gScheduleScanListen = false;
gUpdateStatus = true;
gUpdateDisplay = true;
}
void MENU_StopCssScan(void)
{
gCssScanMode = CSS_SCAN_MODE_OFF;
gUpdateStatus = true;
gCssBackgroundScan = false;
RADIO_SetupRegisters(true);
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
gUpdateDisplay = true;
gUpdateStatus = true;
}
int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
@@ -109,7 +123,7 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
case MENU_STEP:
*pMin = 0;
*pMax = ARRAY_SIZE(StepFrequencyTable) - 1;
*pMax = ARRAY_SIZE(gStepFrequencyTable) - 1;
break;
case MENU_ABR:
@@ -232,7 +246,6 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
case MENU_D_ST:
case MENU_D_DCD:
case MENU_D_LIVE_DEC:
case MENU_AM:
#ifdef ENABLE_NOAA
case MENU_NOAA_S:
#endif
@@ -241,11 +254,15 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
case MENU_500TX:
case MENU_350EN:
case MENU_SCREN:
case MENU_TX_EN:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1;
break;
case MENU_AM:
*pMin = 0;
*pMax = ARRAY_SIZE(gModulationStr) - 1;
break;
case MENU_SCR:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1;
@@ -331,8 +348,13 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
#endif
case MENU_BATCAL:
*pMin = 1600; // 0
*pMax = 2200; // 2300
*pMin = 1600;
*pMax = 2200;
break;
case MENU_BATTYP:
*pMin = 0;
*pMax = 1;
break;
case MENU_F1SHRT:
@@ -358,14 +380,14 @@ void MENU_AcceptSetting(void)
uint8_t Code;
FREQ_Config_t *pConfig = &gTxVfo->freq_config_RX;
if (!MENU_GetLimits(GetCurrentMenuId(), &Min, &Max))
if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max))
{
if (gSubMenuSelection < Min) gSubMenuSelection = Min;
else
if (gSubMenuSelection > Max) gSubMenuSelection = Max;
}
switch (GetCurrentMenuId())
switch (UI_MENU_GetCurrentMenuId())
{
default:
return;
@@ -376,7 +398,7 @@ void MENU_AcceptSetting(void)
break;
case MENU_STEP:
gTxVfo->STEP_SETTING = gSubMenuSelection;
gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection);
if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
gRequestSaveChannel = 1;
@@ -594,7 +616,7 @@ void MENU_AcceptSetting(void)
return;
case MENU_STE:
gEeprom.TAIL_NOTE_ELIMINATION = gSubMenuSelection;
gEeprom.TAIL_TONE_ELIMINATION = gSubMenuSelection;
break;
case MENU_RP_STE:
@@ -697,7 +719,7 @@ void MENU_AcceptSetting(void)
break;
case MENU_AM:
gTxVfo->AM_mode = gSubMenuSelection;
gTxVfo->Modulation = gSubMenuSelection;
gRequestSaveChannel = 1;
return;
@@ -738,10 +760,18 @@ void MENU_AcceptSetting(void)
gSetting_350TX = gSubMenuSelection;
break;
case MENU_F_LOCK:
case MENU_F_LOCK: {
if(gSubMenuSelection == F_LOCK_NONE) { // select 10 times to enable
gUnlockAllTxConfCnt++;
if(gUnlockAllTxConfCnt < 10)
return;
}
else
gUnlockAllTxConfCnt = 0;
gSetting_F_LOCK = gSubMenuSelection;
break;
}
case MENU_200TX:
gSetting_200TX = gSubMenuSelection;
break;
@@ -761,10 +791,6 @@ void MENU_AcceptSetting(void)
gFlagReconfigureVfos = true;
break;
case MENU_TX_EN:
gSetting_TX_EN = gSubMenuSelection;
break;
#ifdef ENABLE_F_CAL_MENU
case MENU_F_CALI:
writeXtalFreqCal(gSubMenuSelection, true);
@@ -772,17 +798,21 @@ void MENU_AcceptSetting(void)
#endif
case MENU_BATCAL:
{
gBatteryCalibration[0] = (520ul * gSubMenuSelection) / 760; // 5.20V empty, blinking above this value, reduced functionality below
gBatteryCalibration[1] = (700ul * gSubMenuSelection) / 760; // 7.00V, ~5%, 1 bars above this value
gBatteryCalibration[2] = (745ul * gSubMenuSelection) / 760; // 7.45V, ~17%, 2 bars above this value
{ // voltages are averages between discharge curves of 1600 and 2200 mAh
// gBatteryCalibration[0] = (520ul * gSubMenuSelection) / 760; // 5.20V empty, blinking above this value, reduced functionality below
// gBatteryCalibration[1] = (689ul * gSubMenuSelection) / 760; // 6.89V, ~5%, 1 bars above this value
// gBatteryCalibration[2] = (724ul * gSubMenuSelection) / 760; // 7.24V, ~17%, 2 bars above this value
gBatteryCalibration[3] = gSubMenuSelection; // 7.6V, ~29%, 3 bars above this value
gBatteryCalibration[4] = (788ul * gSubMenuSelection) / 760; // 7.88V, ~65%, 4 bars above this value
gBatteryCalibration[5] = 2300;
// gBatteryCalibration[4] = (771ul * gSubMenuSelection) / 760; // 7.71V, ~65%, 4 bars above this value
// gBatteryCalibration[5] = 2300;
SETTINGS_SaveBatteryCalibration(gBatteryCalibration);
return;
}
case MENU_BATTYP:
gEeprom.BATTERY_TYPE = gSubMenuSelection;
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
@@ -795,7 +825,7 @@ void MENU_AcceptSetting(void)
&gEeprom.KEY_2_SHORT_PRESS_ACTION,
&gEeprom.KEY_2_LONG_PRESS_ACTION,
&gEeprom.KEY_M_LONG_PRESS_ACTION};
*fun[GetCurrentMenuId()-MENU_F1SHRT] = gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].id;
*fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT] = gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].id;
}
break;
@@ -804,53 +834,12 @@ void MENU_AcceptSetting(void)
gRequestSaveSettings = true;
}
void MENU_SelectNextCode(void)
{
int32_t UpperLimit;
if (GetCurrentMenuId() == MENU_R_DCS)
UpperLimit = 208;
//UpperLimit = ARRAY_SIZE(DCS_Options);
else if (GetCurrentMenuId() == MENU_R_CTCS)
UpperLimit = ARRAY_SIZE(CTCSS_Options) - 1;
else
return;
gSubMenuSelection = NUMBER_AddWithWraparound(gSubMenuSelection, gMenuScrollDirection, 1, UpperLimit);
if (GetCurrentMenuId() == MENU_R_DCS)
{
if (gSubMenuSelection > 104)
{
gSelectedCodeType = CODE_TYPE_REVERSE_DIGITAL;
gSelectedCode = gSubMenuSelection - 105;
}
else
{
gSelectedCodeType = CODE_TYPE_DIGITAL;
gSelectedCode = gSubMenuSelection - 1;
}
}
else
{
gSelectedCodeType = CODE_TYPE_CONTINUOUS_TONE;
gSelectedCode = gSubMenuSelection - 1;
}
RADIO_SetupRegisters(true);
gScanPauseDelayIn_10ms = (gSelectedCodeType == CODE_TYPE_CONTINUOUS_TONE) ? scan_pause_delay_in_3_10ms : scan_pause_delay_in_4_10ms;
gUpdateDisplay = true;
}
static void MENU_ClampSelection(int8_t Direction)
{
int32_t Min;
int32_t Max;
if (!MENU_GetLimits(GetCurrentMenuId(), &Min, &Max))
if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max))
{
int32_t Selection = gSubMenuSelection;
if (Selection < Min) Selection = Min;
@@ -862,42 +851,55 @@ static void MENU_ClampSelection(int8_t Direction)
void MENU_ShowCurrentSetting(void)
{
switch (GetCurrentMenuId())
switch (UI_MENU_GetCurrentMenuId())
{
case MENU_SQL:
gSubMenuSelection = gEeprom.SQUELCH_LEVEL;
break;
case MENU_STEP:
gSubMenuSelection = gTxVfo->STEP_SETTING;
gSubMenuSelection = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING);
break;
case MENU_TXP:
gSubMenuSelection = gTxVfo->OUTPUT_POWER;
break;
case MENU_RESET:
gSubMenuSelection = 0;
break;
case MENU_R_DCS:
switch (gTxVfo->freq_config_RX.CodeType)
{
case MENU_R_CTCS:
{
DCS_CodeType_t type = gTxVfo->freq_config_RX.CodeType;
uint8_t code = gTxVfo->freq_config_RX.Code;
int menuid = UI_MENU_GetCurrentMenuId();
if(gScanUseCssResult) {
gScanUseCssResult = false;
type = gScanCssResultType;
code = gScanCssResultCode;
}
if((menuid==MENU_R_CTCS) ^ (type==CODE_TYPE_CONTINUOUS_TONE)) { //not the same type
gSubMenuSelection = 0;
break;
}
switch (type) {
case CODE_TYPE_CONTINUOUS_TONE:
case CODE_TYPE_DIGITAL:
gSubMenuSelection = gTxVfo->freq_config_RX.Code + 1;
gSubMenuSelection = code + 1;
break;
case CODE_TYPE_REVERSE_DIGITAL:
gSubMenuSelection = gTxVfo->freq_config_RX.Code + 105;
gSubMenuSelection = code + 105;
break;
default:
gSubMenuSelection = 0;
break;
}
break;
case MENU_RESET:
gSubMenuSelection = 0;
break;
case MENU_R_CTCS:
gSubMenuSelection = (gTxVfo->freq_config_RX.CodeType == CODE_TYPE_CONTINUOUS_TONE) ? gTxVfo->freq_config_RX.Code + 1 : 0;
break;
break;
}
case MENU_T_DCS:
switch (gTxVfo->freq_config_TX.CodeType)
@@ -1015,7 +1017,7 @@ void MENU_ShowCurrentSetting(void)
break;
case MENU_STE:
gSubMenuSelection = gEeprom.TAIL_NOTE_ELIMINATION;
gSubMenuSelection = gEeprom.TAIL_TONE_ELIMINATION;
break;
case MENU_RP_STE:
@@ -1103,7 +1105,7 @@ void MENU_ShowCurrentSetting(void)
break;
case MENU_AM:
gSubMenuSelection = gTxVfo->AM_mode;
gSubMenuSelection = gTxVfo->Modulation;
break;
#ifdef ENABLE_AM_FIX
@@ -1156,10 +1158,6 @@ void MENU_ShowCurrentSetting(void)
gSubMenuSelection = gSetting_ScrambleEnable;
break;
case MENU_TX_EN:
gSubMenuSelection = gSetting_TX_EN;
break;
#ifdef ENABLE_F_CAL_MENU
case MENU_F_CALI:
gSubMenuSelection = gEeprom.BK4819_XTAL_FREQ_LOW;
@@ -1170,6 +1168,10 @@ void MENU_ShowCurrentSetting(void)
gSubMenuSelection = gBatteryCalibration[3];
break;
case MENU_BATTYP:
gSubMenuSelection = gEeprom.BATTERY_TYPE;
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
@@ -1182,7 +1184,7 @@ void MENU_ShowCurrentSetting(void)
&gEeprom.KEY_2_SHORT_PRESS_ACTION,
&gEeprom.KEY_2_LONG_PRESS_ACTION,
&gEeprom.KEY_M_LONG_PRESS_ACTION};
uint8_t id = *fun[GetCurrentMenuId()-MENU_F1SHRT];
uint8_t id = *fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT];
for(int i = 0; i < gSubMenu_SIDEFUNCTIONS_size; i++) {
if(gSubMenu_SIDEFUNCTIONS[i].id==id) {
@@ -1211,7 +1213,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
{ // currently editing the channel name
if (edit_index < 10)
@@ -1276,7 +1278,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
return;
}
if (GetCurrentMenuId() == MENU_OFFSET)
if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET)
{
uint32_t Frequency;
@@ -1299,10 +1301,10 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
return;
}
if (GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_DEL_CH ||
GetCurrentMenuId() == MENU_1_CALL ||
GetCurrentMenuId() == MENU_MEM_NAME)
if (UI_MENU_GetCurrentMenuId() == MENU_MEM_CH ||
UI_MENU_GetCurrentMenuId() == MENU_DEL_CH ||
UI_MENU_GetCurrentMenuId() == MENU_1_CALL ||
UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME)
{ // enter 3-digit channel number
if (gInputBoxIndex < 3)
@@ -1331,7 +1333,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
return;
}
if (MENU_GetLimits(GetCurrentMenuId(), &Min, &Max))
if (MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max))
{
gInputBoxIndex = 0;
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
@@ -1372,11 +1374,11 @@ static void MENU_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (gCssScanMode == CSS_SCAN_MODE_OFF)
if (!gCssBackgroundScan)
{
if (gIsInSubMenu)
{
if (gInputBoxIndex == 0 || GetCurrentMenuId() != MENU_OFFSET)
if (gInputBoxIndex == 0 || UI_MENU_GetCurrentMenuId() != MENU_OFFSET)
{
gAskForConfirmation = 0;
gIsInSubMenu = false;
@@ -1432,12 +1434,12 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
if (!gIsInSubMenu)
{
#ifdef ENABLE_VOICE
if (GetCurrentMenuId() != MENU_SCR)
if (UI_MENU_GetCurrentMenuId() != MENU_SCR)
gAnotherVoiceID = MenuList[gMenuCursor].voice_id;
#endif
#if 1
if (GetCurrentMenuId() == MENU_DEL_CH || GetCurrentMenuId() == MENU_MEM_NAME)
if (UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME)
if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0))
return; // invalid channel
#endif
@@ -1445,7 +1447,7 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
gAskForConfirmation = 0;
gIsInSubMenu = true;
// if (GetCurrentMenuId() != MENU_D_LIST)
// if (UI_MENU_GetCurrentMenuId() != MENU_D_LIST)
{
gInputBoxIndex = 0;
edit_index = -1;
@@ -1454,7 +1456,7 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
return;
}
if (GetCurrentMenuId() == MENU_MEM_NAME)
if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME)
{
if (edit_index < 0)
{ // enter channel name edit mode
@@ -1501,10 +1503,10 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
if (gIsInSubMenu)
{
if (GetCurrentMenuId() == MENU_RESET ||
GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_DEL_CH ||
GetCurrentMenuId() == MENU_MEM_NAME)
if (UI_MENU_GetCurrentMenuId() == MENU_RESET ||
UI_MENU_GetCurrentMenuId() == MENU_MEM_CH ||
UI_MENU_GetCurrentMenuId() == MENU_DEL_CH ||
UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME)
{
switch (gAskForConfirmation)
{
@@ -1517,7 +1519,7 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
UI_DisplayMenu();
if (GetCurrentMenuId() == MENU_RESET)
if (UI_MENU_GetCurrentMenuId() == MENU_RESET)
{
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_CONFIRM);
@@ -1545,14 +1547,10 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
}
}
if (gCssScanMode != CSS_SCAN_MODE_OFF)
{
gCssScanMode = CSS_SCAN_MODE_OFF;
gUpdateStatus = true;
}
SCANNER_Stop();
#ifdef ENABLE_VOICE
if (GetCurrentMenuId() == MENU_SCR)
if (UI_MENU_GetCurrentMenuId() == MENU_SCR)
gAnotherVoiceID = (gSubMenuSelection == 0) ? VOICE_ID_SCRAMBLER_OFF : VOICE_ID_SCRAMBLER_ON;
else
gAnotherVoiceID = VOICE_ID_CONFIRM;
@@ -1568,7 +1566,7 @@ static void MENU_Key_STAR(const bool bKeyPressed, const bool bKeyHeld)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
{ // currently editing the channel name
if (edit_index < 10)
@@ -1590,31 +1588,17 @@ static void MENU_Key_STAR(const bool bKeyPressed, const bool bKeyHeld)
RADIO_SelectVfos();
#ifdef ENABLE_NOAA
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gRxVfo->AM_mode == 0)
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gRxVfo->Modulation == MODULATION_FM)
#else
if (gRxVfo->AM_mode == 0)
if (gRxVfo->Modulation == MODULATION_FM)
#endif
{
if (GetCurrentMenuId() == MENU_R_CTCS || GetCurrentMenuId() == MENU_R_DCS)
if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gIsInSubMenu)
{ // scan CTCSS or DCS to find the tone/code of the incoming signal
if (gCssScanMode == CSS_SCAN_MODE_OFF)
{
MENU_StartCssScan(1);
gRequestDisplayScreen = DISPLAY_MENU;
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_SCANNING_BEGIN);
AUDIO_PlaySingleVoice(1);
#endif
}
if (!SCANNER_IsScanning())
MENU_StartCssScan();
else
{
MENU_StopCssScan();
gRequestDisplayScreen = DISPLAY_MENU;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
}
}
gPttWasReleased = true;
@@ -1630,7 +1614,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
uint8_t Channel;
bool bCheckScanList;
if (GetCurrentMenuId() == MENU_MEM_NAME && gIsInSubMenu && edit_index >= 0)
if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && gIsInSubMenu && edit_index >= 0)
{ // change the character
if (bKeyPressed && edit_index < 10 && Direction != 0)
{
@@ -1665,12 +1649,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
if (!bKeyPressed)
return;
if (gCssScanMode != CSS_SCAN_MODE_OFF)
{
MENU_StartCssScan(Direction);
gPttWasReleased = true;
gRequestDisplayScreen = DISPLAY_MENU;
if (SCANNER_IsScanning()) {
return;
}
@@ -1682,7 +1661,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
gRequestDisplayScreen = DISPLAY_MENU;
if (GetCurrentMenuId() != MENU_ABR && gEeprom.BACKLIGHT_TIME == 0) // backlight always off and not in the backlight menu
if (UI_MENU_GetCurrentMenuId() != MENU_ABR && gEeprom.BACKLIGHT_TIME == 0) // backlight always off and not in the backlight menu
{
BACKLIGHT_TurnOff();
}
@@ -1690,7 +1669,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
return;
}
if (GetCurrentMenuId() == MENU_OFFSET)
if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET)
{
int32_t Offset = (Direction * gTxVfo->StepFrequency) + gSubMenuSelection;
if (Offset < 99999990)
@@ -1708,7 +1687,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
VFO = 0;
switch (GetCurrentMenuId())
switch (UI_MENU_GetCurrentMenuId())
{
case MENU_DEL_CH:
case MENU_1_CALL:
@@ -1768,7 +1747,7 @@ void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
MENU_Key_STAR(bKeyPressed, bKeyHeld);
break;
case KEY_F:
if (GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
{ // currently editing the channel name
if (!bKeyHeld && bKeyPressed)
{
@@ -1800,11 +1779,11 @@ void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
if (gScreenToDisplay == DISPLAY_MENU)
{
if (GetCurrentMenuId() == MENU_VOL ||
if (UI_MENU_GetCurrentMenuId() == MENU_VOL ||
#ifdef ENABLE_F_CAL_MENU
GetCurrentMenuId() == MENU_F_CALI ||
UI_MENU_GetCurrentMenuId() == MENU_F_CALI ||
#endif
GetCurrentMenuId() == MENU_BATCAL)
UI_MENU_GetCurrentMenuId() == MENU_BATCAL)
{
gMenuCountdown = menu_timeout_long_500ms;
}

View File

@@ -23,11 +23,13 @@
void writeXtalFreqCal(const int32_t value, const bool update_eeprom);
#endif
extern uint8_t gUnlockAllTxConfCnt;
int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax);
void MENU_AcceptSetting(void);
void MENU_SelectNextCode(void);
void MENU_ShowCurrentSetting(void);
void MENU_StartCssScan(int8_t Direction);
void MENU_StartCssScan(void);
void MENU_CssScanFound(void);
void MENU_StopCssScan(void);
void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);

View File

@@ -17,6 +17,7 @@
#include "app/app.h"
#include "app/dtmf.h"
#include "app/generic.h"
#include "app/menu.h"
#include "app/scanner.h"
#include "audio.h"
#include "driver/bk4819.h"
@@ -29,68 +30,45 @@
DCS_CodeType_t gScanCssResultType;
uint8_t gScanCssResultCode;
bool gFlagStartScan;
bool gFlagStopScan;
bool gScanSingleFrequency;
uint8_t gScannerEditState;
bool gScanSingleFrequency; // scan CTCSS/DCS codes for current frequency
SCAN_SaveState_t gScannerSaveState;
uint8_t gScanChannel;
uint32_t gScanFrequency;
bool gScanPauseMode;
SCAN_CssState_t gScanCssState;
volatile bool gScheduleScanListen = true;
volatile uint16_t gScanPauseDelayIn_10ms;
uint8_t gScanProgressIndicator;
uint8_t gScanHitCount;
bool gScanUseCssResult;
int8_t gScanStateDir;
bool gScanKeepResult;
typedef enum {
SCAN_NEXT_CHAN_SCANLIST1 = 0,
SCAN_NEXT_CHAN_SCANLIST2,
SCAN_NEXT_CHAN_DUAL_WATCH,
SCAN_NEXT_CHAN_MR,
SCAN_NEXT_NUM
} scan_next_chan_t;
STEP_Setting_t stepSetting;
uint8_t scanHitCount;
scan_next_chan_t currentScanList;
uint32_t initialFrqOrChan;
uint8_t initialCROSS_BAND_RX_TX;
uint32_t lastFoundFrqOrChan;
static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
if (gScannerEditState == 1)
{
uint16_t Channel;
if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) {
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
INPUTBOX_Append(Key);
gRequestDisplayScreen = DISPLAY_SCANNER;
if (gInputBoxIndex < 3)
{
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
if (gInputBoxIndex < 3) {
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
return;
}
gInputBoxIndex = 0;
Channel = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;
if (IS_MR_CHANNEL(Channel))
{
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
gShowChPrefix = RADIO_CheckValidChannel(Channel, false, 0);
gScanChannel = (uint8_t)Channel;
uint16_t chan = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;
if (IS_MR_CHANNEL(chan)) {
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
gShowChPrefix = RADIO_CheckValidChannel(chan, false, 0);
gScanChannel = (uint8_t)chan;
return;
}
}
@@ -101,28 +79,17 @@ static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
static void SCANNER_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
if (!bKeyHeld && bKeyPressed) { // short pressed
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
switch (gScannerEditState)
{
case 0:
switch (gScannerSaveState) {
case SCAN_SAVE_NO_PROMPT:
SCANNER_Stop();
gRequestDisplayScreen = DISPLAY_MAIN;
gEeprom.CROSS_BAND_RX_TX = gBackup_CROSS_BAND_RX_TX;
gUpdateStatus = true;
gFlagStopScan = true;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
gFlagResetVfos = true;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_CANCEL;
#endif
break;
case 1:
if (gInputBoxIndex > 0)
{
case SCAN_SAVE_CHAN_SEL:
if (gInputBoxIndex > 0) {
gInputBox[--gInputBoxIndex] = 10;
gRequestDisplayScreen = DISPLAY_SCANNER;
break;
@@ -130,11 +97,11 @@ static void SCANNER_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
// Fallthrough
case 2:
gScannerEditState = 0;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_CANCEL;
#endif
case SCAN_SAVE_CHANNEL:
gScannerSaveState = SCAN_SAVE_NO_PROMPT;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_CANCEL;
#endif
gRequestDisplayScreen = DISPLAY_SCANNER;
break;
}
@@ -143,40 +110,28 @@ static void SCANNER_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
{
uint8_t Channel;
if (bKeyHeld)
if (bKeyHeld || !bKeyPressed) // ignore long press or release button events
return;
if (!bKeyPressed)
return;
if (gScanCssState == SCAN_CSS_STATE_OFF && !gScanSingleFrequency)
{
if (gScanCssState == SCAN_CSS_STATE_OFF && !gScanSingleFrequency) {
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
if (gScanCssState == SCAN_CSS_STATE_SCANNING)
{
if (gScanSingleFrequency)
{
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
if (gScanCssState == SCAN_CSS_STATE_SCANNING && gScanSingleFrequency) {
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
if (gScanCssState == SCAN_CSS_STATE_FAILED)
{
if (gScanCssState == SCAN_CSS_STATE_FAILED) {
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
switch (gScannerEditState)
{
case 0:
switch (gScannerSaveState) {
case SCAN_SAVE_NO_PROMPT:
if (!gScanSingleFrequency)
{
uint32_t freq250 = FREQUENCY_RoundToStep(gScanFrequency, 250);
@@ -186,60 +141,54 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
uint32_t diff625 = gScanFrequency > freq625 ? gScanFrequency - freq625 : freq625 - gScanFrequency;
if(diff250 > diff625) {
gStepSetting = STEP_6_25kHz;
stepSetting = STEP_6_25kHz;
gScanFrequency = freq625;
}
else {
gStepSetting = STEP_2_5kHz;
stepSetting = STEP_2_5kHz;
gScanFrequency = freq250;
}
}
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
gScannerEditState = 1;
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
gScannerSaveState = SCAN_SAVE_CHAN_SEL;
gScanChannel = gTxVfo->CHANNEL_SAVE;
gShowChPrefix = RADIO_CheckValidChannel(gTxVfo->CHANNEL_SAVE, false, 0);
}
else
{
gScannerEditState = 2;
else {
gScannerSaveState = SCAN_SAVE_CHANNEL;
}
gScanCssState = SCAN_CSS_STATE_FOUND;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_MEMORY_CHANNEL;
#endif
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_MEMORY_CHANNEL;
#endif
gRequestDisplayScreen = DISPLAY_SCANNER;
gUpdateStatus = true;
break;
case 1:
if (gInputBoxIndex == 0)
{
case SCAN_SAVE_CHAN_SEL:
if (gInputBoxIndex == 0) {
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
gRequestDisplayScreen = DISPLAY_SCANNER;
gScannerEditState = 2;
gScannerSaveState = SCAN_SAVE_CHANNEL;
}
break;
case 2:
if (!gScanSingleFrequency)
{
case SCAN_SAVE_CHANNEL:
if (!gScanSingleFrequency) {
RADIO_InitInfo(gTxVfo, gTxVfo->CHANNEL_SAVE, gScanFrequency);
if (gScanUseCssResult)
{
if (gScanUseCssResult) {
gTxVfo->freq_config_RX.CodeType = gScanCssResultType;
gTxVfo->freq_config_RX.Code = gScanCssResultCode;
}
gTxVfo->freq_config_TX = gTxVfo->freq_config_RX;
gTxVfo->STEP_SETTING = gStepSetting;
gTxVfo->STEP_SETTING = stepSetting;
}
else
{
else {
RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD);
RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD);
@@ -249,25 +198,24 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
gTxVfo->freq_config_TX.Code = gScanCssResultCode;
}
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
Channel = gScanChannel;
gEeprom.MrChannel[gEeprom.TX_VFO] = Channel;
uint8_t chan;
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
chan = gScanChannel;
gEeprom.MrChannel[gEeprom.TX_VFO] = chan;
}
else
{
Channel = gTxVfo->Band + FREQ_CHANNEL_FIRST;
gEeprom.FreqChannel[gEeprom.TX_VFO] = Channel;
else {
chan = gTxVfo->Band + FREQ_CHANNEL_FIRST;
gEeprom.FreqChannel[gEeprom.TX_VFO] = chan;
}
gTxVfo->CHANNEL_SAVE = Channel;
gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_CONFIRM;
#endif
gRequestDisplayScreen = DISPLAY_SCANNER;
gRequestSaveChannel = 2;
gScannerEditState = 0;
gTxVfo->CHANNEL_SAVE = chan;
gEeprom.ScreenChannel[gEeprom.TX_VFO] = chan;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_CONFIRM;
#endif
gRequestDisplayScreen = DISPLAY_SCANNER;
gRequestSaveChannel = 2;
gScannerSaveState = SCAN_SAVE_NO_PROMPT;
break;
default:
@@ -278,23 +226,20 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
static void SCANNER_Key_STAR(bool bKeyPressed, bool bKeyHeld)
{
if (!bKeyHeld && bKeyPressed)
{
if (!bKeyHeld && bKeyPressed) {
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
gFlagStartScan = true;
SCANNER_Start(gScanSingleFrequency);
}
return;
}
static void SCANNER_Key_UP_DOWN(bool bKeyPressed, bool pKeyHeld, int8_t Direction)
{
if (pKeyHeld)
{
if (pKeyHeld) {
if (!bKeyPressed)
return;
}
else
{
else {
if (!bKeyPressed)
return;
@@ -302,8 +247,7 @@ static void SCANNER_Key_UP_DOWN(bool bKeyPressed, bool pKeyHeld, int8_t Directio
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
}
if (gScannerEditState == 1)
{
if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) {
gScanChannel = NUMBER_AddWithWraparound(gScanChannel, Direction, 0, MR_CHANNEL_LAST);
gShowChPrefix = RADIO_CheckValidChannel(gScanChannel, false, 0);
gRequestDisplayScreen = DISPLAY_SCANNER;
@@ -314,8 +258,7 @@ static void SCANNER_Key_UP_DOWN(bool bKeyPressed, bool pKeyHeld, int8_t Directio
void SCANNER_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
switch (Key)
{
switch (Key) {
case KEY_0:
case KEY_1:
case KEY_2:
@@ -353,13 +296,16 @@ void SCANNER_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
}
void SCANNER_Start(void)
void SCANNER_Start(bool singleFreq)
{
uint8_t BackupStep;
uint16_t BackupFrequency;
gScanSingleFrequency = singleFreq;
gMonitor = false;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_BEGIN;
#endif
BK4819_StopScan();
RADIO_SelectVfos();
#ifdef ENABLE_NOAA
@@ -367,13 +313,13 @@ void SCANNER_Start(void)
gRxVfo->CHANNEL_SAVE = FREQ_CHANNEL_FIRST + BAND6_400MHz;
#endif
BackupStep = gRxVfo->STEP_SETTING;
BackupFrequency = gRxVfo->StepFrequency;
uint8_t backupStep = gRxVfo->STEP_SETTING;
uint16_t backupFrequency = gRxVfo->StepFrequency;
RADIO_InitInfo(gRxVfo, gRxVfo->CHANNEL_SAVE, gRxVfo->pRX->Frequency);
gRxVfo->STEP_SETTING = BackupStep;
gRxVfo->StepFrequency = BackupFrequency;
gRxVfo->STEP_SETTING = backupStep;
gRxVfo->StepFrequency = backupFrequency;
RADIO_SetupRegisters(true);
@@ -381,23 +327,21 @@ void SCANNER_Start(void)
gIsNoaaMode = false;
#endif
if (gScanSingleFrequency)
{
if (gScanSingleFrequency) {
gScanCssState = SCAN_CSS_STATE_SCANNING;
gScanFrequency = gRxVfo->pRX->Frequency;
gStepSetting = gRxVfo->STEP_SETTING;
stepSetting = gRxVfo->STEP_SETTING;
BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency);
BK4819_SetScanFrequency(gScanFrequency);
gUpdateStatus = true;
}
else
{
else {
gScanCssState = SCAN_CSS_STATE_OFF;
gScanFrequency = 0xFFFFFFFF;
BK4819_PickRXFilterPathBasedOnFrequency(0xFFFFFFFF);
BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency);
BK4819_EnableFrequencyScan();
gUpdateStatus = true;
@@ -408,7 +352,7 @@ void SCANNER_Start(void)
gScanDelay_10ms = scan_delay_10ms;
gScanCssResultCode = 0xFF;
gScanCssResultType = 0xFF;
gScanHitCount = 0;
scanHitCount = 0;
gScanUseCssResult = false;
g_CxCSS_TAIL_Found = false;
g_CDCSS_Lost = false;
@@ -418,242 +362,165 @@ void SCANNER_Start(void)
g_VOX_Lost = false;
#endif
g_SquelchLost = false;
gScannerEditState = 0;
gScannerSaveState = SCAN_SAVE_NO_PROMPT;
gScanProgressIndicator = 0;
}
void SCANNER_Found()
{
switch (gEeprom.SCAN_RESUME_MODE)
{
case SCAN_RESUME_TO:
if (!gScanPauseMode)
{
gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms;
gScheduleScanListen = false;
gScanPauseMode = true;
}
break;
case SCAN_RESUME_CO:
case SCAN_RESUME_SE:
gScanPauseDelayIn_10ms = 0;
gScheduleScanListen = false;
break;
}
if (IS_MR_CHANNEL(gRxVfo->CHANNEL_SAVE)) { //memory scan
lastFoundFrqOrChan = gRxVfo->CHANNEL_SAVE;
}
else { // frequency scan
lastFoundFrqOrChan = gRxVfo->freq_config_RX.Frequency;
}
gScanKeepResult = true;
}
void SCANNER_Stop(void)
{
if(initialCROSS_BAND_RX_TX != CROSS_BAND_OFF) {
gEeprom.CROSS_BAND_RX_TX = initialCROSS_BAND_RX_TX;
initialCROSS_BAND_RX_TX = CROSS_BAND_OFF;
if(SCANNER_IsScanning()) {
gEeprom.CROSS_BAND_RX_TX = gBackup_CROSS_BAND_RX_TX;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
gFlagResetVfos = true;
gUpdateStatus = true;
gCssBackgroundScan = false;
gScanUseCssResult = false;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_CANCEL;
#endif
BK4819_StopScan();
}
}
void SCANNER_TimeSlice10ms(void)
{
if (!SCANNER_IsScanning())
return;
if (gScanDelay_10ms > 0) {
gScanDelay_10ms--;
return;
}
gScanStateDir = SCAN_OFF;
if (gScannerSaveState != SCAN_SAVE_NO_PROMPT) {
return;
}
const uint32_t chFr = gScanKeepResult ? lastFoundFrqOrChan : initialFrqOrChan;
const bool channelChanged = chFr != initialFrqOrChan;
if (IS_MR_CHANNEL(gNextMrChannel)) {
gEeprom.MrChannel[gEeprom.RX_VFO] = chFr;
gEeprom.ScreenChannel[gEeprom.RX_VFO] = chFr;
RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD);
switch (gScanCssState) {
case SCAN_CSS_STATE_OFF: {
// must be RF frequency scanning if we're here ?
uint32_t result;
if (!BK4819_GetFrequencyScanResult(&result))
break;
int32_t delta = result - gScanFrequency;
gScanFrequency = result;
if (delta < 0)
delta = -delta;
if (delta < 100)
scanHitCount++;
else
scanHitCount = 0;
BK4819_DisableFrequencyScan();
if (scanHitCount < 3) {
BK4819_EnableFrequencyScan();
}
else {
BK4819_SetScanFrequency(gScanFrequency);
gScanCssResultCode = 0xFF;
gScanCssResultType = 0xFF;
scanHitCount = 0;
gScanUseCssResult = false;
gScanProgressIndicator = 0;
gScanCssState = SCAN_CSS_STATE_SCANNING;
if(!gCssBackgroundScan)
GUI_SelectNextDisplay(DISPLAY_SCANNER);
gUpdateStatus = true;
}
gScanDelay_10ms = scan_delay_10ms;
//gScanDelay_10ms = 1; // 10ms
break;
}
case SCAN_CSS_STATE_SCANNING: {
uint32_t cdcssFreq;
uint16_t ctcssFreq;
BK4819_CssScanResult_t scanResult = BK4819_GetCxCSSScanResult(&cdcssFreq, &ctcssFreq);
if (scanResult == BK4819_CSS_RESULT_NOT_FOUND)
break;
BK4819_Disable();
if (scanResult == BK4819_CSS_RESULT_CDCSS) {
const uint8_t Code = DCS_GetCdcssCode(cdcssFreq);
if (Code != 0xFF)
{
gScanCssResultCode = Code;
gScanCssResultType = CODE_TYPE_DIGITAL;
gScanCssState = SCAN_CSS_STATE_FOUND;
gScanUseCssResult = true;
gUpdateStatus = true;
}
}
else if (scanResult == BK4819_CSS_RESULT_CTCSS) {
const uint8_t Code = DCS_GetCtcssCode(ctcssFreq);
if (Code != 0xFF) {
if (Code == gScanCssResultCode && gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) {
if (++scanHitCount >= 2) {
gScanCssState = SCAN_CSS_STATE_FOUND;
gScanUseCssResult = true;
gUpdateStatus = true;
}
}
else
scanHitCount = 0;
gScanCssResultType = CODE_TYPE_CONTINUOUS_TONE;
gScanCssResultCode = Code;
}
}
if (gScanCssState < SCAN_CSS_STATE_FOUND) { // scanning or off
BK4819_SetScanFrequency(gScanFrequency);
gScanDelay_10ms = scan_delay_10ms;
break;
}
if(gCssBackgroundScan) {
gCssBackgroundScan = false;
if(gScanUseCssResult)
MENU_CssScanFound();
}
else
GUI_SelectNextDisplay(DISPLAY_SCANNER);
break;
}
default:
gCssBackgroundScan = false;
break;
}
}
void SCANNER_TimeSlice500ms(void)
{
if (SCANNER_IsScanning() && gScannerSaveState == SCAN_SAVE_NO_PROMPT && gScanCssState < SCAN_CSS_STATE_FOUND) {
gScanProgressIndicator++;
#ifdef ENABLE_NO_CODE_SCAN_TIMEOUT
if (gScanProgressIndicator > 32) {
if (gScanCssState == SCAN_CSS_STATE_SCANNING && !gScanSingleFrequency)
gScanCssState = SCAN_CSS_STATE_FOUND;
else
gScanCssState = SCAN_CSS_STATE_FAILED;
if(channelChanged) {
SETTINGS_SaveVfoIndices();
gUpdateStatus = true;
}
}
else {
gRxVfo->freq_config_RX.Frequency = chFr;
RADIO_ApplyOffset(gRxVfo);
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
if(channelChanged) {
SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_VFO, gRxVfo, 1);
}
}
RADIO_SetupRegisters(true);
gUpdateDisplay = true;
}
static void NextFreqChannel(void)
{
gRxVfo->freq_config_RX.Frequency = APP_SetFrequencyByStep(gRxVfo, gScanStateDir);
RADIO_ApplyOffset(gRxVfo);
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
RADIO_SetupRegisters(true);
#ifdef ENABLE_FASTER_CHANNEL_SCAN
gScanPauseDelayIn_10ms = 9; // 90ms
#else
gScanPauseDelayIn_10ms = scan_pause_delay_in_6_10ms;
#endif
gUpdateDisplay = true;
}
static void NextMemChannel(void)
{
static unsigned int prev_mr_chan = 0;
const bool enabled = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCAN_LIST_ENABLED[gEeprom.SCAN_LIST_DEFAULT] : true;
const int chan1 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH1[gEeprom.SCAN_LIST_DEFAULT] : -1;
const int chan2 = (gEeprom.SCAN_LIST_DEFAULT < 2) ? gEeprom.SCANLIST_PRIORITY_CH2[gEeprom.SCAN_LIST_DEFAULT] : -1;
const unsigned int prev_chan = gNextMrChannel;
unsigned int chan = 0;
if (enabled)
{
switch (currentScanList)
{
case SCAN_NEXT_CHAN_SCANLIST1:
prev_mr_chan = gNextMrChannel;
if (chan1 >= 0)
{
if (RADIO_CheckValidChannel(chan1, false, 0))
{
currentScanList = SCAN_NEXT_CHAN_SCANLIST1;
gNextMrChannel = chan1;
break;
}
}
[[fallthrough]];
case SCAN_NEXT_CHAN_SCANLIST2:
if (chan2 >= 0)
{
if (RADIO_CheckValidChannel(chan2, false, 0))
{
currentScanList = SCAN_NEXT_CHAN_SCANLIST2;
gNextMrChannel = chan2;
break;
}
}
[[fallthrough]];
// this bit doesn't yet work if the other VFO is a frequency
case SCAN_NEXT_CHAN_DUAL_WATCH:
// dual watch is enabled - include the other VFO in the scan
// if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
// {
// chan = (gEeprom.RX_VFO + 1) & 1u;
// chan = gEeprom.ScreenChannel[chan];
// if (IS_MR_CHANNEL(chan))
// {
// currentScanList = SCAN_NEXT_CHAN_DUAL_WATCH;
// gNextMrChannel = chan;
// break;
// }
// }
default:
case SCAN_NEXT_CHAN_MR:
currentScanList = SCAN_NEXT_CHAN_MR;
gNextMrChannel = prev_mr_chan;
chan = 0xff;
break;
}
}
if (!enabled || chan == 0xff)
{
chan = RADIO_FindNextChannel(gNextMrChannel + gScanStateDir, gScanStateDir, (gEeprom.SCAN_LIST_DEFAULT < 2) ? true : false, gEeprom.SCAN_LIST_DEFAULT);
if (chan == 0xFF)
{ // no valid channel found
chan = MR_CHANNEL_FIRST;
}
gNextMrChannel = chan;
}
if (gNextMrChannel != prev_chan)
{
gEeprom.MrChannel[ gEeprom.RX_VFO] = gNextMrChannel;
gEeprom.ScreenChannel[gEeprom.RX_VFO] = gNextMrChannel;
RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD);
RADIO_SetupRegisters(true);
gUpdateDisplay = true;
}
#ifdef ENABLE_FASTER_CHANNEL_SCAN
gScanPauseDelayIn_10ms = 9; // 90ms .. <= ~60ms it misses signals (squelch response and/or PLL lock time) ?
#else
gScanPauseDelayIn_10ms = scan_pause_delay_in_3_10ms;
#endif
if (enabled)
if (++currentScanList >= SCAN_NEXT_NUM)
currentScanList = SCAN_NEXT_CHAN_SCANLIST1; // back round we go
else if(gCssBackgroundScan) {
gUpdateDisplay = true;
}
}
void SCANNER_ScanChannels(const bool storeBackupSettings, const int8_t scan_direction)
bool SCANNER_IsScanning(void)
{
if (storeBackupSettings) {
initialCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gScanKeepResult = false;
}
RADIO_SelectVfos();
gNextMrChannel = gRxVfo->CHANNEL_SAVE;
currentScanList = SCAN_NEXT_CHAN_SCANLIST1;
gScanStateDir = scan_direction;
if (IS_MR_CHANNEL(gNextMrChannel))
{ // channel mode
if (storeBackupSettings) {
initialFrqOrChan = gRxVfo->CHANNEL_SAVE;
lastFoundFrqOrChan = initialFrqOrChan;
}
NextMemChannel();
}
else
{ // frequency mode
if (storeBackupSettings) {
initialFrqOrChan = gRxVfo->freq_config_RX.Frequency;
lastFoundFrqOrChan = initialFrqOrChan;
}
NextFreqChannel();
}
gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms;
gScheduleScanListen = false;
gRxReceptionMode = RX_MODE_NONE;
gScanPauseMode = false;
}
void SCANNER_ContinueScanning()
{
if (IS_FREQ_CHANNEL(gNextMrChannel))
{
if (gCurrentFunction == FUNCTION_INCOMING)
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true);
else
NextFreqChannel(); // switch to next frequency
}
else
{
if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING)
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true);
else
NextMemChannel(); // switch to next channel
}
gScanPauseMode = false;
gRxReceptionMode = RX_MODE_NONE;
gScheduleScanListen = false;
return gCssBackgroundScan || (gScreenToDisplay == DISPLAY_SCANNER);
}

View File

@@ -20,47 +20,38 @@
#include "dcs.h"
#include "driver/keyboard.h"
enum SCAN_CssState_t
typedef enum
{
SCAN_CSS_STATE_OFF = 0,
SCAN_CSS_STATE_OFF,
SCAN_CSS_STATE_SCANNING,
SCAN_CSS_STATE_FOUND,
SCAN_CSS_STATE_FAILED
};
} SCAN_CssState_t;
typedef enum SCAN_CssState_t SCAN_CssState_t;
enum
typedef enum
{
SCAN_REV = -1,
SCAN_OFF = 0,
SCAN_FWD = +1
};
SCAN_SAVE_NO_PROMPT, // saving process not initiated
SCAN_SAVE_CHAN_SEL, // "SAVE: ", channel select prompt, actives only in channel mode
SCAN_SAVE_CHANNEL, // "SAVE?" prompt, waits for confirmation to save settings to channel, or current VFO
} SCAN_SaveState_t;
extern DCS_CodeType_t gScanCssResultType;
extern uint8_t gScanCssResultCode;
extern bool gFlagStartScan;
extern bool gFlagStopScan;
extern bool gScanSingleFrequency;
extern uint8_t gScannerEditState;
extern SCAN_SaveState_t gScannerSaveState;
extern uint8_t gScanChannel;
extern uint32_t gScanFrequency;
extern bool gScanPauseMode;
extern SCAN_CssState_t gScanCssState;
extern volatile bool gScheduleScanListen;
extern volatile uint16_t gScanPauseDelayIn_10ms;
extern uint8_t gScanProgressIndicator;
extern uint8_t gScanHitCount;
extern bool gScanUseCssResult;
extern int8_t gScanStateDir;
extern bool gScanKeepResult;
void SCANNER_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
void SCANNER_Start(void);
void SCANNER_Found();
void SCANNER_Start(bool singleFreq);
void SCANNER_Stop(void);
void SCANNER_ScanChannels(const bool storeBackupSettings, const int8_t scan_direction);
void SCANNER_ContinueScanning();
void SCANNER_TimeSlice10ms(void);
void SCANNER_TimeSlice500ms(void);
bool SCANNER_IsScanning(void);
#endif

View File

@@ -16,6 +16,8 @@
#include "app/spectrum.h"
#include "driver/backlight.h"
#include "audio.h"
#include "ui/helper.h"
struct FrequencyBandInfo {
uint32_t lower;
@@ -48,7 +50,6 @@ ScanInfo scanInfo;
KeyboardState kbd = {KEY_INVALID, KEY_INVALID, 0};
const char *bwOptions[] = {" 25k", "12.5k", "6.25k"};
const char *modulationTypeOptions[] = {" FM", " AM", "USB"};
const uint8_t modulationTypeTuneSteps[] = {100, 50, 10};
const uint8_t modTypeReg47Values[] = {1, 7, 5};
@@ -78,10 +79,10 @@ uint16_t listenT = 0;
RegisterSpec registerSpecs[] = {
{},
{"LNAs", 0x13, 8, 0b11, 1},
{"LNA", 0x13, 5, 0b111, 1},
{"PGA", 0x13, 0, 0b111, 1},
{"IF", 0x3D, 0, 0xFFFF, 0x2aaa},
{"LNAs", BK4819_REG_13, 8, 0b11, 1},
{"LNA", BK4819_REG_13, 5, 0b111, 1},
{"PGA", BK4819_REG_13, 0, 0b111, 1},
{"IF", BK4819_REG_3D, 0, 0xFFFF, 0x2aaa},
// {"MIX", 0x13, 3, 0b11, 1}, // TODO: hidden
};
@@ -102,7 +103,7 @@ static int Rssi2DBm(uint16_t rssi) { return (rssi >> 1) - 160; }
static uint16_t GetRegMenuValue(uint8_t st) {
RegisterSpec s = registerSpecs[st];
return (BK4819_ReadRegister(s.num) >> s.offset) & s.maxValue;
return (BK4819_ReadRegister(s.num) >> s.offset) & s.mask;
}
static void SetRegMenuValue(uint8_t st, bool add) {
@@ -110,14 +111,14 @@ static void SetRegMenuValue(uint8_t st, bool add) {
RegisterSpec s = registerSpecs[st];
uint16_t reg = BK4819_ReadRegister(s.num);
if (add && v <= s.maxValue - s.inc) {
if (add && v <= s.mask - s.inc) {
v += s.inc;
} else if (!add && v >= 0 + s.inc) {
v -= s.inc;
}
// TODO: use max value for bits count in max value, or reset by additional
// mask in spec
reg &= ~(s.maxValue << s.offset);
reg &= ~(s.mask << s.offset);
BK4819_WriteRegister(s.num, reg | (v << s.offset));
redrawScreen = true;
}
@@ -125,21 +126,13 @@ static void SetRegMenuValue(uint8_t st, bool add) {
// GUI functions
static void PutPixel(uint8_t x, uint8_t y, bool fill) {
if (fill) {
gFrameBuffer[y >> 3][x] |= 1 << (y & 7);
} else {
gFrameBuffer[y >> 3][x] &= ~(1 << (y & 7));
}
UI_DrawPixelBuffer(gFrameBuffer, x, y, fill);
}
static void PutPixelStatus(uint8_t x, uint8_t y, bool fill) {
if (fill) {
gStatusLine[x] |= 1 << y;
} else {
gStatusLine[x] &= ~(1 << y);
}
UI_DrawPixelBuffer(&gStatusLine, x, y, fill);
}
static void DrawHLine(int sy, int ey, int nx, bool fill) {
static void DrawVLine(int sy, int ey, int nx, bool fill) {
for (int i = sy; i <= ey; i++) {
if (i < 56 && nx < 128) {
PutPixel(nx, i, fill);
@@ -205,35 +198,23 @@ static void ToggleAFBit(bool on) {
}
static void BackupRegisters() {
R30 = BK4819_ReadRegister(0x30);
R37 = BK4819_ReadRegister(0x37);
R3D = BK4819_ReadRegister(0x3D);
R43 = BK4819_ReadRegister(0x43);
R47 = BK4819_ReadRegister(0x47);
R48 = BK4819_ReadRegister(0x48);
R7E = BK4819_ReadRegister(0x7E);
R30 = BK4819_ReadRegister(BK4819_REG_30);
R37 = BK4819_ReadRegister(BK4819_REG_37);
R3D = BK4819_ReadRegister(BK4819_REG_3D);
R43 = BK4819_ReadRegister(BK4819_REG_43);
R47 = BK4819_ReadRegister(BK4819_REG_47);
R48 = BK4819_ReadRegister(BK4819_REG_48);
R7E = BK4819_ReadRegister(BK4819_REG_7E);
}
static void RestoreRegisters() {
BK4819_WriteRegister(0x30, R30);
BK4819_WriteRegister(0x37, R37);
BK4819_WriteRegister(0x3D, R3D);
BK4819_WriteRegister(0x43, R43);
BK4819_WriteRegister(0x47, R47);
BK4819_WriteRegister(0x48, R48);
BK4819_WriteRegister(0x7E, R7E);
}
static void SetModulation(ModulationType type) {
RestoreRegisters();
uint16_t reg = BK4819_ReadRegister(BK4819_REG_47);
reg &= ~(0b111 << 8);
BK4819_WriteRegister(BK4819_REG_47, reg | (modTypeReg47Values[type] << 8));
if (type == MOD_USB) {
BK4819_WriteRegister(0x3D, 0b0010101101000101);
BK4819_WriteRegister(BK4819_REG_37, 0x160F);
BK4819_WriteRegister(0x48, 0b0000001110101000);
}
BK4819_WriteRegister(BK4819_REG_30, R30);
BK4819_WriteRegister(BK4819_REG_37, R37);
BK4819_WriteRegister(BK4819_REG_3D, R3D);
BK4819_WriteRegister(BK4819_REG_43, R43);
BK4819_WriteRegister(BK4819_REG_47, R47);
BK4819_WriteRegister(BK4819_REG_48, R48);
BK4819_WriteRegister(BK4819_REG_7E, R7E);
}
static void ToggleAFDAC(bool on) {
@@ -304,9 +285,9 @@ static void ToggleAudio(bool on) {
}
audioState = on;
if (on) {
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
} else {
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
}
}
@@ -400,11 +381,24 @@ static void Measure() { rssiHistory[scanInfo.i] = scanInfo.rssi = GetRssi(); }
// Update things by keypress
static uint16_t dbm2rssi(int dBm)
{
return (dBm + 160)*2;
}
static void ClampRssiTriggerLevel()
{
settings.rssiTriggerLevel = clamp(settings.rssiTriggerLevel, dbm2rssi(settings.dbMin), dbm2rssi(settings.dbMax));
}
static void UpdateRssiTriggerLevel(bool inc) {
if (inc)
settings.rssiTriggerLevel += 2;
settings.rssiTriggerLevel += 2;
else
settings.rssiTriggerLevel -= 2;
settings.rssiTriggerLevel -= 2;
ClampRssiTriggerLevel();
redrawScreen = true;
redrawStatus = true;
}
@@ -417,6 +411,8 @@ static void UpdateDBMax(bool inc) {
} else {
return;
}
ClampRssiTriggerLevel();
redrawStatus = true;
redrawScreen = true;
SYSTEM_DelayMs(20);
@@ -473,12 +469,12 @@ static void UpdateFreqChangeStep(bool inc) {
}
static void ToggleModulation() {
if (settings.modulationType < MOD_USB) {
if (settings.modulationType < MODULATION_UKNOWN - 1) {
settings.modulationType++;
} else {
settings.modulationType = MOD_FM;
settings.modulationType = MODULATION_FM;
}
SetModulation(settings.modulationType);
RADIO_SetModulation(settings.modulationType);
redrawScreen = true;
}
@@ -603,7 +599,7 @@ static void DrawSpectrum() {
for (uint8_t x = 0; x < 128; ++x) {
uint16_t rssi = rssiHistory[x >> settings.stepsCount];
if (rssi != RSSI_MAX_VALUE) {
DrawHLine(Rssi2Y(rssi), DrawingEndY, x, true);
DrawVLine(Rssi2Y(rssi), DrawingEndY, x, true);
}
}
}
@@ -617,43 +613,35 @@ static void DrawStatus() {
#endif
GUI_DisplaySmallest(String, 0, 1, true, true);
for (int i = 0; i < 4; i++) {
BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[i], &gBatteryCurrent);
}
BOARD_ADC_GetBatteryInfo(&gBatteryVoltages[gBatteryCheckCounter++ % 4], &gBatteryCurrent);
uint16_t Voltage;
uint8_t v = 0;
Voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + gBatteryVoltages[2] +
uint16_t voltage = (gBatteryVoltages[0] + gBatteryVoltages[1] + gBatteryVoltages[2] +
gBatteryVoltages[3]) /
4;
4 * 760 / gBatteryCalibration[3];
for(uint8_t i = 5; i > 0; i--) {
if(Voltage > gBatteryCalibration[i - 1]) {
v = i;
break;
}
}
unsigned perc = BATTERY_VoltsToPercent(voltage);
gStatusLine[127] = 0b01111110;
for (int i = 126; i >= 116; i--) {
gStatusLine[i] = 0b01000010;
// sprintf(String, "%d %d", voltage, perc);
// GUI_DisplaySmallest(String, 48, 1, true, true);
gStatusLine[116] = 0b00011100;
gStatusLine[117] = 0b00111110;
for (int i = 118; i <= 126; i++) {
gStatusLine[i] = 0b00100010;
}
v <<= 1;
for (int i = 125; i >= 116; i--) {
if (126 - i <= v) {
gStatusLine[i + 2] = 0b01111110;
for (unsigned i = 127; i >= 118; i--) {
if (127 - i <= (perc+5)*9/100) {
gStatusLine[i] = 0b00111110;
}
}
gStatusLine[117] = 0b01111110;
gStatusLine[116] = 0b00011000;
}
static void DrawF(uint32_t f) {
sprintf(String, "%u.%05u", f / 100000, f % 100000);
UI_PrintStringSmall(String, 8, 127, 0);
sprintf(String, "%s", modulationTypeOptions[settings.modulationType]);
sprintf(String, "%3s", gModulationStr[settings.modulationType]);
GUI_DisplaySmallest(String, 116, 1, false, true);
sprintf(String, "%s", bwOptions[settings.listenBw]);
GUI_DisplaySmallest(String, 108, 7, false, true);
@@ -709,19 +697,13 @@ static void DrawTicks() {
// center
if (IsCenterMode()) {
gFrameBuffer[5][62] = 0x80;
gFrameBuffer[5][63] = 0x80;
memset(gFrameBuffer[5] + 62, 0x80, 5);
gFrameBuffer[5][64] = 0xff;
gFrameBuffer[5][65] = 0x80;
gFrameBuffer[5][66] = 0x80;
} else {
memset(gFrameBuffer[5] + 1, 0x80, 3);
memset(gFrameBuffer[5] + 124, 0x80, 3);
gFrameBuffer[5][0] = 0xff;
gFrameBuffer[5][1] = 0x80;
gFrameBuffer[5][2] = 0x80;
gFrameBuffer[5][3] = 0x80;
gFrameBuffer[5][124] = 0x80;
gFrameBuffer[5][125] = 0x80;
gFrameBuffer[5][126] = 0x80;
gFrameBuffer[5][127] = 0xff;
}
}
@@ -1159,7 +1141,7 @@ void APP_RunSpectrum() {
newScanStart = true;
ToggleRX(true), ToggleRX(false); // hack to prevent noise when squelch off
SetModulation(settings.modulationType = MOD_FM);
RADIO_SetModulation(settings.modulationType = MODULATION_FM);
BK4819_SetFilterBandwidth(settings.listenBw = BK4819_FILTER_BW_WIDE, false);
RelaunchScan();

View File

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

19
audio.c
View File

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

11
audio.h
View File

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

View File

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

View File

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

45
board.c
View File

@@ -23,11 +23,10 @@
#include "board.h"
#include "bsp/dp32g030/gpio.h"
#include "bsp/dp32g030/portcon.h"
#include "bsp/dp32g030/pwmplus.h"
#include "bsp/dp32g030/saradc.h"
#include "bsp/dp32g030/syscon.h"
#include "driver/adc.h"
//#include "driver/backlight.h"
#include "driver/backlight.h"
#ifdef ENABLE_FMRADIO
#include "driver/bk1080.h"
#endif
@@ -182,14 +181,10 @@ void BOARD_PORTCON_Init(void)
// PORT B pin selection
PORTCON_PORTB_SEL0 &= ~(0
// Back light
| PORTCON_PORTB_SEL0_B6_MASK
// SPI0 SSN
| PORTCON_PORTB_SEL0_B7_MASK
);
PORTCON_PORTB_SEL0 |= 0
// Back light PWM
| PORTCON_PORTB_SEL0_B6_BITS_PWMP0_CH0
// SPI0 SSN
| PORTCON_PORTB_SEL0_B7_BITS_SPI0_SSN
;
@@ -470,23 +465,6 @@ void BOARD_PORTCON_Init(void)
;
}
static void BacklightPWM_Init()
{
// 48MHz / 94 / 1024 ~ 500Hz
PWM_PLUS0_CLKSRC |= ((94) << 16);
PWM_PLUS0_PERIOD = 1023;
PWM_PLUS0_GEN =
PWMPLUS_GEN_CH0_OE_BITS_ENABLE |
PWMPLUS_GEN_CH0_OUTINV_BITS_ENABLE |
0;
PWM_PLUS0_CFG =
PWMPLUS_CFG_CNT_REP_BITS_ENABLE |
PWMPLUS_CFG_COUNTER_EN_BITS_ENABLE |
0;
}
void BOARD_ADC_Init(void)
{
ADC_Config_t Config;
@@ -524,7 +502,7 @@ void BOARD_Init(void)
{
BOARD_PORTCON_Init();
BOARD_GPIO_Init();
BacklightPWM_Init();
BACKLIGHT_InitHardware();
BOARD_ADC_Init();
ST7565_Init(true);
#ifdef ENABLE_FMRADIO
@@ -559,12 +537,15 @@ void BOARD_EEPROM_Init(void)
EEPROM_ReadBuffer(0x0E78, Data, 8);
gEeprom.BACKLIGHT_MAX = (Data[0] & 0xF) <= 10 ? (Data[0] & 0xF) : 10;
gEeprom.BACKLIGHT_MIN = (Data[0] >> 4) < gEeprom.BACKLIGHT_MAX ? (Data[0] >> 4) : 0;
#ifdef ENABLE_BLMIN_TMP_OFF
gEeprom.BACKLIGHT_MIN_STAT = BLMIN_STAT_ON;
#endif
gEeprom.CHANNEL_DISPLAY_MODE = (Data[1] < 4) ? Data[1] : MDF_FREQUENCY; // 4 instead of 3 - extra display mode
gEeprom.CROSS_BAND_RX_TX = (Data[2] < 3) ? Data[2] : CROSS_BAND_OFF;
gEeprom.BATTERY_SAVE = (Data[3] < 5) ? Data[3] : 4;
gEeprom.DUAL_WATCH = (Data[4] < 3) ? Data[4] : DUAL_WATCH_CHAN_A;
gEeprom.BACKLIGHT_TIME = (Data[5] < ARRAY_SIZE(gSubMenu_BACKLIGHT)) ? Data[5] : 3;
gEeprom.TAIL_NOTE_ELIMINATION = (Data[6] < 2) ? Data[6] : false;
gEeprom.TAIL_TONE_ELIMINATION = (Data[6] < 2) ? Data[6] : false;
gEeprom.VFO_OPEN = (Data[7] < 2) ? Data[7] : true;
// 0E80..0E87
@@ -636,7 +617,8 @@ void BOARD_EEPROM_Init(void)
#endif
gEeprom.ROGER = (Data[1] < 3) ? Data[1] : ROGER_MODE_OFF;
gEeprom.REPEATER_TAIL_TONE_ELIMINATION = (Data[2] < 11) ? Data[2] : 0;
gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0;
gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0;
gEeprom.BATTERY_TYPE = (Data[4] < BATTERY_TYPE_UNKNOWN) ? Data[4] : BATTERY_TYPE_1600_MAH;
// 0ED0..0ED7
EEPROM_ReadBuffer(0x0ED0, Data, 8);
@@ -719,14 +701,14 @@ void BOARD_EEPROM_Init(void)
// 0F40..0F47
EEPROM_ReadBuffer(0x0F40, Data, 8);
gSetting_F_LOCK = (Data[0] < 6) ? Data[0] : F_LOCK_OFF;
gSetting_F_LOCK = (Data[0] < F_LOCK_LEN) ? Data[0] : F_LOCK_DEF;
gSetting_350TX = (Data[1] < 2) ? Data[1] : false; // was true
gSetting_KILLED = (Data[2] < 2) ? Data[2] : false;
gSetting_200TX = (Data[3] < 2) ? Data[3] : false;
gSetting_500TX = (Data[4] < 2) ? Data[4] : false;
gSetting_350EN = (Data[5] < 2) ? Data[5] : true;
gSetting_ScrambleEnable = (Data[6] < 2) ? Data[6] : true;
gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false;
//gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false;
gSetting_live_DTMF_decoder = (Data[7] & (1u << 1)) ? true : false;
gSetting_battery_text = (((Data[7] >> 2) & 3u) <= 2) ? (Data[7] >> 2) & 3 : 2;
#ifdef ENABLE_AUDIO_BAR
@@ -745,6 +727,13 @@ void BOARD_EEPROM_Init(void)
// 0D60..0E27
EEPROM_ReadBuffer(0x0D60, gMR_ChannelAttributes, sizeof(gMR_ChannelAttributes));
for(uint16_t i = 0; i < sizeof(gMR_ChannelAttributes); i++) {
ChannelAttributes_t *att = &gMR_ChannelAttributes[i];
if(att->__val == 0xff){
att->__val = 0;
att->band = 0xf;
}
}
// 0F30..0F3F
EEPROM_ReadBuffer(0x0F30, gCustomAesKey, sizeof(gCustomAesKey));

View File

@@ -1,4 +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/"
docker run --rm -v %CD%\compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make clean && make && cp firmware* compiled-firmware/"
pause

View File

@@ -1,3 +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/"
docker run --rm -v ${PWD}/compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/"

18
debugging.h Normal file
View File

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

View File

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

View File

@@ -23,6 +23,15 @@
extern uint16_t gBacklightCountdown;
extern uint8_t gBacklightBrightness;
#ifdef ENABLE_BLMIN_TMP_OFF
typedef enum {
BLMIN_STAT_ON,
BLMIN_STAT_OFF,
BLMIN_STAT_UNKNOWN
} BLMIN_STAT_t;
#endif
void BACKLIGHT_InitHardware();
void BACKLIGHT_TurnOn();
void BACKLIGHT_TurnOff();
bool BACKLIGHT_IsOn();

View File

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

View File

@@ -16,6 +16,7 @@
#include <stdio.h> // NULL
#include "audio.h"
#include "bk4819.h"
#include "bsp/dp32g030/gpio.h"
#include "bsp/dp32g030/portcon.h"
@@ -29,6 +30,9 @@
static const uint16_t FSK_RogerTable[7] = {0xF1A2, 0x7446, 0x61A4, 0x6544, 0x4E8A, 0xE044, 0xEA84};
static const uint8_t DTMF_TONE1_GAIN = 65;
static const uint8_t DTMF_TONE2_GAIN = 93;
static uint16_t gBK4819_GpioOutState;
bool gRxIdleMode;
@@ -234,26 +238,6 @@ void BK4819_WriteU16(uint16_t Data)
void BK4819_DisableAGC()
{
// REG_7E
//
// <15> 0 AGC Fix Mode.
// 1=Fix; 0=Auto.
//
// <14:12> 0b011 AGC Fix Index.
// 011=Max, then 010,001,000,111,110,101,100(min).
//
// <5:3> 0b101 DC Filter Band Width for Tx (MIC In).
// 000=Bypass DC filter;
//
// <2:0> 0b110 DC Filter Band Width for Rx (IF In).
// 000=Bypass DC filter;
//
BK4819_WriteRegister(0x7E,
(1u << 15) | // 0 AGC fix mode
(3u << 12) | // 3 AGC fix index
(5u << 3) | // 5 DC Filter band width for Tx (MIC In)
(6u << 0)); // 6 DC Filter band width for Rx (I.F In)
// REG_10
//
// 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1)
@@ -305,32 +289,6 @@ void BK4819_DisableAGC()
void BK4819_EnableAGC()
{
// TODO: See if this attenuates overloading
// signals as well as boosting weak ones
//
// REG_7E
//
// <15> 0 AGC Fix Mode.
// 1=Fix; 0=Auto.
//
// <14:12> 0b011 AGC Fix Index.
// 011=Max, then 010,001,000,111,110,101,100(min).
//
// <5:3> 0b101 DC Filter Band Width for Tx (MIC In).
// 000=Bypass DC filter;
//
// <2:0> 0b110 DC Filter Band Width for Rx (IF In).
// 000=Bypass DC filter;
// default fix index too strong, set to min (011->100)
//BK4819_WriteRegister(0x7E, (1u << 15) | (4u << 12) | (5u << 3) | (6u << 0));
BK4819_WriteRegister(0x7E,
(0u << 15) | // 0 AGC fix mode
(3u << 12) | // 3 AGC fix index
(5u << 3) | // 5 DC Filter band width for Tx (MIC In)
(6u << 0)); // 6 DC Filter band width for Rx (I.F In)
// REG_10
//
// 0x0038 Rx AGC Gain Table[0]. (Index Max->Min is 3,2,1,0,-1)
@@ -843,6 +801,12 @@ void BK4819_SetAF(BK4819_AF_Type_t AF)
BK4819_WriteRegister(BK4819_REG_47, (6u << 12) | (AF << 8) | (1u << 6));
}
void BK4819_SetRegValue(RegisterSpec s, uint16_t v) {
uint16_t reg = BK4819_ReadRegister(s.num);
reg &= ~(s.mask << s.offset);
BK4819_WriteRegister(s.num, reg | (v << s.offset));
}
void BK4819_RX_TurnOn(void)
{
// DSP Voltage Setting = 1
@@ -1023,15 +987,15 @@ void BK4819_EnableDTMF(void)
void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch)
{
uint16_t ToneConfig;
uint16_t ToneConfig = BK4819_REG_70_ENABLE_TONE1;
BK4819_EnterTxMute();
BK4819_SetAF(BK4819_AF_BEEP);
if (bTuningGainSwitch == 0)
ToneConfig = BK4819_REG_70_ENABLE_TONE1 | (96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN);
ToneConfig |= 96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN;
else
ToneConfig = BK4819_REG_70_ENABLE_TONE1 | (28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN);
ToneConfig |= 28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN;
BK4819_WriteRegister(BK4819_REG_70, ToneConfig);
BK4819_WriteRegister(BK4819_REG_30, 0);
@@ -1040,21 +1004,20 @@ void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch)
BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency));
}
// level 0 ~ 127
void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay, const unsigned int level, const bool play_speaker)
{
BK4819_EnterTxMute();
if (play_speaker)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
BK4819_SetAF(BK4819_AF_BEEP);
}
else
BK4819_SetAF(BK4819_AF_MUTE);
// level 0 ~ 127
// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | ((level & 0x7f) << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_EnableTXLink();
@@ -1068,12 +1031,13 @@ void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay,
if (play_speaker)
{
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
BK4819_SetAF(BK4819_AF_MUTE);
}
BK4819_WriteRegister(BK4819_REG_70, 0x0000);
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE);
BK4819_ExitTxMute();
}
void BK4819_EnterTxMute(void)
@@ -1247,9 +1211,9 @@ void BK4819_EnterDTMF_TX(bool bLocalLoopback)
BK4819_WriteRegister(BK4819_REG_70,
BK4819_REG_70_MASK_ENABLE_TONE1 |
(83u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) |
(DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) |
BK4819_REG_70_MASK_ENABLE_TONE2 |
(83u << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN));
(DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN));
BK4819_EnableTXLink();
}
@@ -1288,16 +1252,16 @@ void BK4819_PlayDTMF(char Code)
switch (Code)
{
case '0': tone1 = 941; tone2 = 1336; break;
case '1': tone1 = 679; tone2 = 1209; break;
case '1': tone1 = 697; tone2 = 1209; break;
case '2': tone1 = 697; tone2 = 1336; break;
case '3': tone1 = 679; tone2 = 1477; break;
case '3': tone1 = 697; tone2 = 1477; break;
case '4': tone1 = 770; tone2 = 1209; break;
case '5': tone1 = 770; tone2 = 1336; break;
case '6': tone1 = 770; tone2 = 1477; break;
case '7': tone1 = 852; tone2 = 1209; break;
case '8': tone1 = 852; tone2 = 1336; break;
case '9': tone1 = 852; tone2 = 1477; break;
case 'A': tone1 = 679; tone2 = 1633; break;
case 'A': tone1 = 697; tone2 = 1633; break;
case 'B': tone1 = 770; tone2 = 1633; break;
case 'C': tone1 = 852; tone2 = 1633; break;
case 'D': tone1 = 941; tone2 = 1633; break;
@@ -1358,8 +1322,7 @@ void BK4819_TransmitTone(bool bLocalLoopback, uint32_t Frequency)
//
// set the tone amplitude
//
// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_MASK_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_WriteRegister(BK4819_REG_71, scale_freq(Frequency));
@@ -1738,8 +1701,7 @@ void BK4819_PlayRoger(void)
BK4819_EnterTxMute();
BK4819_SetAF(BK4819_AF_MUTE);
// BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (96u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (28u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
BK4819_EnableTXLink();
SYSTEM_DelayMs(50);
@@ -1820,7 +1782,12 @@ void BK4819_PlayDTMFEx(bool bLocalLoopback, char Code)
BK4819_EnterTxMute();
BK4819_SetAF(bLocalLoopback ? BK4819_AF_BEEP : BK4819_AF_MUTE);
BK4819_WriteRegister(BK4819_REG_70, 0xD3D3);
BK4819_WriteRegister(BK4819_REG_70,
BK4819_REG_70_MASK_ENABLE_TONE1 |
(DTMF_TONE1_GAIN << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN) |
BK4819_REG_70_MASK_ENABLE_TONE2 |
(DTMF_TONE2_GAIN << BK4819_REG_70_SHIFT_TONE2_TUNING_GAIN));
BK4819_EnableTXLink();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -61,13 +61,29 @@ const freq_band_table_t frequencyBandTable[7] =
};
#endif
#ifndef ENABLE_12_5KHZ_STEP
// QS steps (*10 Hz)
const uint16_t StepFrequencyTable[7] = {250, 500, 625, 1000, 1250, 2500, 833};
#else
// includes 1.25kHz step
const uint16_t StepFrequencyTable[7] = {125, 250, 625, 1000, 1250, 2500, 833};
#endif
const uint16_t gStepFrequencyTable[] = {
250, 500, 625, 1000, 1250, 2500, 833,
1, 5, 10, 25, 50, 100, 125, 1500, 3000, 5000, 10000, 12500, 25000, 50000
};
const uint8_t StepSortedIndexes[] = {
STEP_0_01kHz, STEP_0_05kHz, STEP_0_1kHz, STEP_0_25kHz, STEP_0_5kHz, STEP_1kHz, STEP_1_25kHz, STEP_2_5kHz, STEP_5kHz, STEP_6_25kHz,
STEP_8_33kHz, STEP_10kHz, STEP_12_5kHz, STEP_15kHz, STEP_25kHz, STEP_30kHz, STEP_50kHz, STEP_100kHz,
STEP_125kHz, STEP_250kHz, STEP_500kHz
};
uint8_t FREQUENCY_GetStepIdxFromSortedIdx(uint8_t sortedIdx)
{
return StepSortedIndexes[sortedIdx];
}
uint8_t FREQUENCY_GetSortedIdxFromStepIdx(uint8_t stepIdx)
{
for(uint8_t i = 0; i < ARRAY_SIZE(gStepFrequencyTable); i++)
if(StepSortedIndexes[i] == stepIdx)
return i;
return 0;
}
FREQUENCY_Band_t FREQUENCY_GetBand(uint32_t Frequency)
{
@@ -102,6 +118,8 @@ uint8_t FREQUENCY_CalculateOutputPower(uint8_t TxpLow, uint8_t TxpMid, uint8_t T
static int32_t rnd(int32_t freq, uint16_t step)
{
if(step == 1)
return freq;
return (freq + (step + 1) / 2) / step * step;
}
@@ -129,7 +147,7 @@ int TX_freq_check(const uint32_t Frequency)
switch (gSetting_F_LOCK)
{
case F_LOCK_OFF:
case F_LOCK_DEF:
if (Frequency >= frequencyBandTable[BAND3_137MHz].lower && Frequency < frequencyBandTable[BAND3_137MHz].upper)
return 0;
if (Frequency >= frequencyBandTable[BAND4_174MHz].lower && Frequency < frequencyBandTable[BAND4_174MHz].upper)
@@ -179,6 +197,15 @@ int TX_freq_check(const uint32_t Frequency)
if (Frequency >= 40000000 && Frequency < 43800000)
return 0;
break;
case F_LOCK_ALL:
break;
case F_LOCK_NONE:
for (uint8_t i = 0; i < ARRAY_SIZE(frequencyBandTable); i++)
if (Frequency >= frequencyBandTable[i].lower && Frequency < frequencyBandTable[i].upper)
return 0;
break;
}
// dis-allowed TX frequency

View File

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

View File

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

View File

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

View File

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

10
misc.c
View File

@@ -82,7 +82,6 @@ bool gSetting_KILLED;
bool gSetting_200TX;
bool gSetting_500TX;
bool gSetting_350EN;
bool gSetting_TX_EN;
uint8_t gSetting_F_LOCK;
bool gSetting_ScrambleEnable;
@@ -112,7 +111,7 @@ uint16_t gEEPROM_RSSI_CALIB[7][4];
uint16_t gEEPROM_1F8A;
uint16_t gEEPROM_1F8C;
uint8_t gMR_ChannelAttributes[FREQ_CHANNEL_LAST + 1];
ChannelAttributes_t gMR_ChannelAttributes[FREQ_CHANNEL_LAST + 1];
volatile uint16_t gBatterySaveCountdown_10ms = battery_save_count_10ms;
@@ -154,7 +153,11 @@ uint8_t gVFO_RSSI_bar_level[2];
uint8_t gReducedService;
uint8_t gBatteryVoltageIndex;
CssScanMode_t gCssScanMode;
bool gCssBackgroundScan;
volatile bool gScheduleScanListen = true;
volatile uint16_t gScanPauseDelayIn_10ms;
bool gUpdateRSSI;
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
AlarmState_t gAlarmState;
@@ -197,7 +200,6 @@ bool g_SquelchLost;
uint8_t gFlashLightState;
volatile uint16_t gFlashLightBlinkCounter;
bool gFlagEndTransmission;
uint16_t gLowBatteryCountdown;
uint8_t gNextMrChannel;
ReceptionMode_t gRxReceptionMode;

42
misc.h
View File

@@ -75,14 +75,6 @@ enum ReceptionMode_t {
};
typedef enum ReceptionMode_t ReceptionMode_t;
enum CssScanMode_t
{
CSS_SCAN_MODE_OFF = 0,
CSS_SCAN_MODE_SCANNING,
CSS_SCAN_MODE_FOUND,
};
typedef enum CssScanMode_t CssScanMode_t;
enum BacklightOnRxTx_t {
BACKLIGHT_ON_TR_OFF,
BACKLIGHT_ON_TR_TX,
@@ -154,7 +146,6 @@ extern bool gSetting_KILLED;
extern bool gSetting_200TX;
extern bool gSetting_500TX;
extern bool gSetting_350EN;
extern bool gSetting_TX_EN;
extern uint8_t gSetting_F_LOCK;
extern bool gSetting_ScrambleEnable;
@@ -185,7 +176,18 @@ extern uint16_t gEEPROM_RSSI_CALIB[7][4];
extern uint16_t gEEPROM_1F8A;
extern uint16_t gEEPROM_1F8C;
extern uint8_t gMR_ChannelAttributes[207];
typedef union {
struct {
uint8_t
band : 4,
compander : 2,
scanlist2 : 1,
scanlist1 : 1;
};
uint8_t __val;
} ChannelAttributes_t;
extern ChannelAttributes_t gMR_ChannelAttributes[207];
extern volatile uint16_t gBatterySaveCountdown_10ms;
@@ -225,9 +227,24 @@ extern bool gEndOfRxDetectedMaybe;
extern int16_t gVFO_RSSI[2];
extern uint8_t gVFO_RSSI_bar_level[2];
// battery critical, limit functionality to minimum
extern uint8_t gReducedService;
extern uint8_t gBatteryVoltageIndex;
extern CssScanMode_t gCssScanMode;
// we are searching CTCSS/DCS inside RX ctcss/dcs menu
extern bool gCssBackgroundScan;
enum
{
SCAN_REV = -1,
SCAN_OFF = 0,
SCAN_FWD = +1
};
extern volatile bool gScheduleScanListen;
extern volatile uint16_t gScanPauseDelayIn_10ms;
extern bool gUpdateRSSI;
extern AlarmState_t gAlarmState;
extern uint16_t gMenuCountdown;
@@ -264,11 +281,12 @@ extern bool g_CxCSS_TAIL_Found;
extern uint16_t gVoxResumeCountdown;
extern uint16_t gVoxPauseCountdown;
#endif
// true means we are receiving signal
extern bool g_SquelchLost;
extern uint8_t gFlashLightState;
extern volatile uint16_t gFlashLightBlinkCounter;
extern bool gFlagEndTransmission;
extern uint16_t gLowBatteryCountdown;
extern uint8_t gNextMrChannel;
extern ReceptionMode_t gRxReceptionMode;

474
radio.c
View File

@@ -38,33 +38,40 @@
VFO_Info_t *gTxVfo;
VFO_Info_t *gRxVfo;
VFO_Info_t *gCurrentVfo;
DCS_CodeType_t gSelectedCodeType;
DCS_CodeType_t gCurrentCodeType;
uint8_t gSelectedCode;
STEP_Setting_t gStepSetting;
VfoState_t VfoState[2];
const char gModulationStr[][4] =
{
"FM",
"AM",
"USB",
#ifdef ENABLE_BYP_RAW_DEMODULATORS
"BYP",
"RAW"
#endif
};
bool RADIO_CheckValidChannel(uint16_t Channel, bool bCheckScanList, uint8_t VFO)
{ // return true if the channel appears valid
uint8_t Attributes;
ChannelAttributes_t att;
uint8_t PriorityCh1;
uint8_t PriorityCh2;
if (!IS_MR_CHANNEL(Channel))
return false;
Attributes = gMR_ChannelAttributes[Channel];
att = gMR_ChannelAttributes[Channel];
if ((Attributes & MR_CH_BAND_MASK) > BAND7_470MHz)
if (att.band > BAND7_470MHz)
return false;
if (bCheckScanList)
{
switch (VFO)
{
if (bCheckScanList) {
switch (VFO) {
case 0:
if ((Attributes & MR_CH_SCANLIST1) == 0)
if (!att.scanlist1)
return false;
PriorityCh1 = gEeprom.SCANLIST_PRIORITY_CH1[0];
@@ -72,7 +79,7 @@ bool RADIO_CheckValidChannel(uint16_t Channel, bool bCheckScanList, uint8_t VFO)
break;
case 1:
if ((Attributes & MR_CH_SCANLIST2) == 0)
if (!att.scanlist2)
return false;
PriorityCh1 = gEeprom.SCANLIST_PRIORITY_CH1[1];
@@ -119,10 +126,10 @@ void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t
memset(pInfo, 0, sizeof(*pInfo));
pInfo->Band = FREQUENCY_GetBand(Frequency);
pInfo->SCANLIST1_PARTICIPATION = true;
pInfo->SCANLIST2_PARTICIPATION = true;
pInfo->SCANLIST1_PARTICIPATION = false;
pInfo->SCANLIST2_PARTICIPATION = false;
pInfo->STEP_SETTING = STEP_12_5kHz;
pInfo->StepFrequency = StepFrequencyTable[pInfo->STEP_SETTING];
pInfo->StepFrequency = gStepFrequencyTable[pInfo->STEP_SETTING];
pInfo->CHANNEL_SAVE = ChannelSave;
pInfo->FrequencyReverse = false;
pInfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
@@ -133,38 +140,32 @@ void RADIO_InitInfo(VFO_Info_t *pInfo, const uint8_t ChannelSave, const uint32_t
pInfo->Compander = 0; // off
if (ChannelSave == (FREQ_CHANNEL_FIRST + BAND2_108MHz))
pInfo->AM_mode = 1;
pInfo->Modulation = MODULATION_AM;
else
pInfo->Modulation = MODULATION_FM;
RADIO_ConfigureSquelchAndOutputPower(pInfo);
}
void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure)
{
uint8_t Channel;
uint8_t Attributes;
uint8_t Band;
bool bParticipation2;
uint16_t Base;
uint32_t Frequency;
VFO_Info_t *pRadio = &gEeprom.VfoInfo[VFO];
VFO_Info_t *pVfo = &gEeprom.VfoInfo[VFO];
if (!gSetting_350EN)
{
if (gEeprom.FreqChannel[VFO] == (FREQ_CHANNEL_LAST - 2))
gEeprom.FreqChannel[VFO] = FREQ_CHANNEL_LAST - 1;
if (!gSetting_350EN) {
if (gEeprom.FreqChannel[VFO] == FREQ_CHANNEL_FIRST + BAND5_350MHz)
gEeprom.FreqChannel[VFO] = FREQ_CHANNEL_FIRST + BAND6_400MHz;
if (gEeprom.ScreenChannel[VFO] == (FREQ_CHANNEL_LAST - 2))
gEeprom.ScreenChannel[VFO] = FREQ_CHANNEL_LAST - 1;
if (gEeprom.ScreenChannel[VFO] == FREQ_CHANNEL_FIRST + BAND5_350MHz)
gEeprom.ScreenChannel[VFO] = FREQ_CHANNEL_FIRST + BAND6_400MHz;
}
Channel = gEeprom.ScreenChannel[VFO];
uint8_t channel = gEeprom.ScreenChannel[VFO];
if (IS_VALID_CHANNEL(Channel))
{
if (IS_VALID_CHANNEL(channel)) {
#ifdef ENABLE_NOAA
if (Channel >= NOAA_CHANNEL_FIRST)
if (channel >= NOAA_CHANNEL_FIRST)
{
RADIO_InitInfo(pRadio, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[Channel - NOAA_CHANNEL_FIRST]);
RADIO_InitInfo(pVfo, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[channel - NOAA_CHANNEL_FIRST]);
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF)
return;
@@ -176,248 +177,240 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
}
#endif
if (IS_MR_CHANNEL(Channel))
{
Channel = RADIO_FindNextChannel(Channel, RADIO_CHANNEL_UP, false, VFO);
if (Channel == 0xFF)
{
Channel = gEeprom.FreqChannel[VFO];
if (IS_MR_CHANNEL(channel)) {
channel = RADIO_FindNextChannel(channel, RADIO_CHANNEL_UP, false, VFO);
if (channel == 0xFF) {
channel = gEeprom.FreqChannel[VFO];
gEeprom.ScreenChannel[VFO] = gEeprom.FreqChannel[VFO];
}
else
{
gEeprom.ScreenChannel[VFO] = Channel;
gEeprom.MrChannel[VFO] = Channel;
else {
gEeprom.ScreenChannel[VFO] = channel;
gEeprom.MrChannel[VFO] = channel;
}
}
}
else
Channel = FREQ_CHANNEL_LAST - 1;
channel = FREQ_CHANNEL_LAST - 1;
Attributes = gMR_ChannelAttributes[Channel];
if (Attributes == 0xFF)
{ // invalid/unused channel
uint8_t Index;
if (IS_MR_CHANNEL(Channel))
{
Channel = gEeprom.FreqChannel[VFO];
gEeprom.ScreenChannel[VFO] = gEeprom.FreqChannel[VFO];
ChannelAttributes_t att = gMR_ChannelAttributes[channel];
if (att.__val == 0xFF) { // invalid/unused channel
if (IS_MR_CHANNEL(channel)) {
channel = gEeprom.FreqChannel[VFO];
gEeprom.ScreenChannel[VFO] = channel;
}
Index = Channel - FREQ_CHANNEL_FIRST;
RADIO_InitInfo(pRadio, Channel, frequencyBandTable[Index].lower);
uint8_t bandIdx = channel - FREQ_CHANNEL_FIRST;
RADIO_InitInfo(pVfo, channel, frequencyBandTable[bandIdx].lower);
return;
}
Band = Attributes & MR_CH_BAND_MASK;
if (Band > BAND7_470MHz)
{
Band = BAND6_400MHz;
uint8_t band = att.band;
if (band > BAND7_470MHz) {
band = BAND6_400MHz;
}
if (IS_MR_CHANNEL(Channel))
{
gEeprom.VfoInfo[VFO].Band = Band;
gEeprom.VfoInfo[VFO].SCANLIST1_PARTICIPATION = !!(Attributes & MR_CH_SCANLIST1);
bParticipation2 = !!(Attributes & MR_CH_SCANLIST2);
bool bParticipation1;
bool bParticipation2;
if (IS_MR_CHANNEL(channel)) {
bParticipation1 = att.scanlist1;
bParticipation2 = att.scanlist2;
}
else {
band = channel - FREQ_CHANNEL_FIRST;
bParticipation1 = true;
bParticipation2 = true;
}
pVfo->Band = band;
pVfo->SCANLIST1_PARTICIPATION = bParticipation1;
pVfo->SCANLIST2_PARTICIPATION = bParticipation2;
pVfo->CHANNEL_SAVE = channel;
uint16_t base;
if (IS_MR_CHANNEL(channel))
base = channel * 16;
else
base = 0x0C80 + ((channel - FREQ_CHANNEL_FIRST) * 32) + (VFO * 16);
if (configure == VFO_CONFIGURE_RELOAD || IS_FREQ_CHANNEL(channel))
{
Band = Channel - FREQ_CHANNEL_FIRST;
gEeprom.VfoInfo[VFO].Band = Band;
bParticipation2 = true;
gEeprom.VfoInfo[VFO].SCANLIST1_PARTICIPATION = true;
}
gEeprom.VfoInfo[VFO].SCANLIST2_PARTICIPATION = bParticipation2;
gEeprom.VfoInfo[VFO].CHANNEL_SAVE = Channel;
if (IS_MR_CHANNEL(Channel))
Base = Channel * 16;
else
Base = 0x0C80 + ((Channel - FREQ_CHANNEL_FIRST) * 32) + (VFO * 16);
if (configure == VFO_CONFIGURE_RELOAD || Channel >= FREQ_CHANNEL_FIRST)
{
uint8_t Tmp;
uint8_t Data[8];
uint8_t tmp;
uint8_t data[8];
// ***************
EEPROM_ReadBuffer(Base + 8, Data, sizeof(Data));
EEPROM_ReadBuffer(base + 8, data, sizeof(data));
Tmp = Data[3] & 0x0F;
if (Tmp > TX_OFFSET_FREQUENCY_DIRECTION_SUB)
Tmp = 0;
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY_DIRECTION = Tmp;
gEeprom.VfoInfo[VFO].AM_mode = (Data[3] >> 4) & 1u;
tmp = data[3] & 0x0F;
if (tmp > TX_OFFSET_FREQUENCY_DIRECTION_SUB)
tmp = 0;
pVfo->TX_OFFSET_FREQUENCY_DIRECTION = tmp;
tmp = data[3] >> 4;
if (tmp >= MODULATION_UKNOWN)
tmp = MODULATION_FM;
pVfo->Modulation = tmp;
Tmp = Data[6];
if (Tmp >= ARRAY_SIZE(StepFrequencyTable))
Tmp = STEP_12_5kHz;
gEeprom.VfoInfo[VFO].STEP_SETTING = Tmp;
gEeprom.VfoInfo[VFO].StepFrequency = StepFrequencyTable[Tmp];
tmp = data[6];
if (tmp >= ARRAY_SIZE(gStepFrequencyTable))
tmp = STEP_12_5kHz;
pVfo->STEP_SETTING = tmp;
pVfo->StepFrequency = gStepFrequencyTable[tmp];
Tmp = Data[7];
if (Tmp > (ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1))
Tmp = 0;
gEeprom.VfoInfo[VFO].SCRAMBLING_TYPE = Tmp;
tmp = data[7];
if (tmp > (ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1))
tmp = 0;
pVfo->SCRAMBLING_TYPE = tmp;
gEeprom.VfoInfo[VFO].freq_config_RX.CodeType = (Data[2] >> 0) & 0x0F;
gEeprom.VfoInfo[VFO].freq_config_TX.CodeType = (Data[2] >> 4) & 0x0F;
pVfo->freq_config_RX.CodeType = (data[2] >> 0) & 0x0F;
pVfo->freq_config_TX.CodeType = (data[2] >> 4) & 0x0F;
Tmp = Data[0];
switch (gEeprom.VfoInfo[VFO].freq_config_RX.CodeType)
tmp = data[0];
switch (pVfo->freq_config_RX.CodeType)
{
default:
case CODE_TYPE_OFF:
gEeprom.VfoInfo[VFO].freq_config_RX.CodeType = CODE_TYPE_OFF;
Tmp = 0;
pVfo->freq_config_RX.CodeType = CODE_TYPE_OFF;
tmp = 0;
break;
case CODE_TYPE_CONTINUOUS_TONE:
if (Tmp > (ARRAY_SIZE(CTCSS_Options) - 1))
Tmp = 0;
if (tmp > (ARRAY_SIZE(CTCSS_Options) - 1))
tmp = 0;
break;
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
if (Tmp > (ARRAY_SIZE(DCS_Options) - 1))
Tmp = 0;
if (tmp > (ARRAY_SIZE(DCS_Options) - 1))
tmp = 0;
break;
}
gEeprom.VfoInfo[VFO].freq_config_RX.Code = Tmp;
pVfo->freq_config_RX.Code = tmp;
Tmp = Data[1];
switch (gEeprom.VfoInfo[VFO].freq_config_TX.CodeType)
tmp = data[1];
switch (pVfo->freq_config_TX.CodeType)
{
default:
case CODE_TYPE_OFF:
gEeprom.VfoInfo[VFO].freq_config_TX.CodeType = CODE_TYPE_OFF;
Tmp = 0;
pVfo->freq_config_TX.CodeType = CODE_TYPE_OFF;
tmp = 0;
break;
case CODE_TYPE_CONTINUOUS_TONE:
if (Tmp > (ARRAY_SIZE(CTCSS_Options) - 1))
Tmp = 0;
if (tmp > (ARRAY_SIZE(CTCSS_Options) - 1))
tmp = 0;
break;
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
if (Tmp > (ARRAY_SIZE(DCS_Options) - 1))
Tmp = 0;
if (tmp > (ARRAY_SIZE(DCS_Options) - 1))
tmp = 0;
break;
}
gEeprom.VfoInfo[VFO].freq_config_TX.Code = Tmp;
pVfo->freq_config_TX.Code = tmp;
if (Data[4] == 0xFF)
if (data[4] == 0xFF)
{
gEeprom.VfoInfo[VFO].FrequencyReverse = false;
gEeprom.VfoInfo[VFO].CHANNEL_BANDWIDTH = BK4819_FILTER_BW_WIDE;
gEeprom.VfoInfo[VFO].OUTPUT_POWER = OUTPUT_POWER_LOW;
gEeprom.VfoInfo[VFO].BUSY_CHANNEL_LOCK = false;
pVfo->FrequencyReverse = false;
pVfo->CHANNEL_BANDWIDTH = BK4819_FILTER_BW_WIDE;
pVfo->OUTPUT_POWER = OUTPUT_POWER_LOW;
pVfo->BUSY_CHANNEL_LOCK = false;
}
else
{
const uint8_t d4 = Data[4];
gEeprom.VfoInfo[VFO].FrequencyReverse = !!((d4 >> 0) & 1u);
gEeprom.VfoInfo[VFO].CHANNEL_BANDWIDTH = !!((d4 >> 1) & 1u);
gEeprom.VfoInfo[VFO].OUTPUT_POWER = ((d4 >> 2) & 3u);
gEeprom.VfoInfo[VFO].BUSY_CHANNEL_LOCK = !!((d4 >> 4) & 1u);
const uint8_t d4 = data[4];
pVfo->FrequencyReverse = !!((d4 >> 0) & 1u);
pVfo->CHANNEL_BANDWIDTH = !!((d4 >> 1) & 1u);
pVfo->OUTPUT_POWER = ((d4 >> 2) & 3u);
pVfo->BUSY_CHANNEL_LOCK = !!((d4 >> 4) & 1u);
}
if (Data[5] == 0xFF)
if (data[5] == 0xFF)
{
gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = false;
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = PTT_ID_OFF;
pVfo->DTMF_DECODING_ENABLE = false;
pVfo->DTMF_PTT_ID_TX_MODE = PTT_ID_OFF;
}
else
{
gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = ((Data[5] >> 0) & 1u) ? true : false;
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = ((Data[5] >> 1) & 7u);
pVfo->DTMF_DECODING_ENABLE = ((data[5] >> 0) & 1u) ? true : false;
pVfo->DTMF_PTT_ID_TX_MODE = ((data[5] >> 1) & 7u);
}
// ***************
struct
{
struct {
uint32_t Frequency;
uint32_t Offset;
} __attribute__((packed)) Info;
} __attribute__((packed)) info;
EEPROM_ReadBuffer(base, &info, sizeof(info));
if(info.Frequency==0xFFFFFFFF)
pVfo->freq_config_RX.Frequency = frequencyBandTable[band].lower;
else
pVfo->freq_config_RX.Frequency = info.Frequency;
EEPROM_ReadBuffer(Base, &Info, sizeof(Info));
pRadio->freq_config_RX.Frequency = Info.Frequency;
if (Info.Offset >= 100000000)
Info.Offset = 1000000;
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY = Info.Offset;
if (info.Offset >= 100000000)
info.Offset = 1000000;
pVfo->TX_OFFSET_FREQUENCY = info.Offset;
// ***************
}
Frequency = pRadio->freq_config_RX.Frequency;
uint32_t frequency = pVfo->freq_config_RX.Frequency;
// fix previously set incorrect band
Band = FREQUENCY_GetBand(Frequency);
band = FREQUENCY_GetBand(frequency);
if (Frequency < frequencyBandTable[Band].lower)
Frequency = frequencyBandTable[Band].lower;
else
if (Frequency > frequencyBandTable[Band].upper)
Frequency = frequencyBandTable[Band].upper;
else
if (Channel >= FREQ_CHANNEL_FIRST)
Frequency = FREQUENCY_RoundToStep(Frequency, gEeprom.VfoInfo[VFO].StepFrequency);
if (frequency < frequencyBandTable[band].lower)
frequency = frequencyBandTable[band].lower;
else if (frequency > frequencyBandTable[band].upper)
frequency = frequencyBandTable[band].upper;
else if (channel >= FREQ_CHANNEL_FIRST)
frequency = FREQUENCY_RoundToStep(frequency, pVfo->StepFrequency);
pRadio->freq_config_RX.Frequency = Frequency;
pVfo->freq_config_RX.Frequency = frequency;
if (Frequency >= frequencyBandTable[BAND2_108MHz].upper && Frequency < frequencyBandTable[BAND2_108MHz].upper)
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF;
else if (!IS_MR_CHANNEL(Channel))
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY = FREQUENCY_RoundToStep(gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY, gEeprom.VfoInfo[VFO].StepFrequency);
if (frequency >= frequencyBandTable[BAND2_108MHz].upper && frequency < frequencyBandTable[BAND2_108MHz].upper)
pVfo->TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF;
else if (!IS_MR_CHANNEL(channel))
pVfo->TX_OFFSET_FREQUENCY = FREQUENCY_RoundToStep(pVfo->TX_OFFSET_FREQUENCY, pVfo->StepFrequency);
RADIO_ApplyOffset(pRadio);
RADIO_ApplyOffset(pVfo);
memset(gEeprom.VfoInfo[VFO].Name, 0, sizeof(gEeprom.VfoInfo[VFO].Name));
if (IS_MR_CHANNEL(Channel))
memset(pVfo->Name, 0, sizeof(pVfo->Name));
if (IS_MR_CHANNEL(channel))
{ // 16 bytes allocated to the channel name but only 10 used, the rest are 0's
EEPROM_ReadBuffer(0x0F50 + (Channel * 16), gEeprom.VfoInfo[VFO].Name + 0, 8);
EEPROM_ReadBuffer(0x0F58 + (Channel * 16), gEeprom.VfoInfo[VFO].Name + 8, 2);
EEPROM_ReadBuffer(0x0F50 + (channel * 16), pVfo->Name + 0, 8);
EEPROM_ReadBuffer(0x0F58 + (channel * 16), pVfo->Name + 8, 2);
}
if (!gEeprom.VfoInfo[VFO].FrequencyReverse)
if (!pVfo->FrequencyReverse)
{
gEeprom.VfoInfo[VFO].pRX = &gEeprom.VfoInfo[VFO].freq_config_RX;
gEeprom.VfoInfo[VFO].pTX = &gEeprom.VfoInfo[VFO].freq_config_TX;
pVfo->pRX = &pVfo->freq_config_RX;
pVfo->pTX = &pVfo->freq_config_TX;
}
else
{
gEeprom.VfoInfo[VFO].pRX = &gEeprom.VfoInfo[VFO].freq_config_TX;
gEeprom.VfoInfo[VFO].pTX = &gEeprom.VfoInfo[VFO].freq_config_RX;
pVfo->pRX = &pVfo->freq_config_TX;
pVfo->pTX = &pVfo->freq_config_RX;
}
if (!gSetting_350EN)
{
FREQ_Config_t *pConfig = gEeprom.VfoInfo[VFO].pRX;
FREQ_Config_t *pConfig = pVfo->pRX;
if (pConfig->Frequency >= 35000000 && pConfig->Frequency < 40000000)
pConfig->Frequency = 43300000;
}
if (gEeprom.VfoInfo[VFO].AM_mode)
if (pVfo->Modulation != MODULATION_FM)
{ // freq/chan is in AM mode
gEeprom.VfoInfo[VFO].SCRAMBLING_TYPE = 0;
// gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = false; // no reason to disable DTMF decoding, aircraft use it on SSB
gEeprom.VfoInfo[VFO].freq_config_RX.CodeType = CODE_TYPE_OFF;
gEeprom.VfoInfo[VFO].freq_config_TX.CodeType = CODE_TYPE_OFF;
pVfo->SCRAMBLING_TYPE = 0;
// pVfo->DTMF_DECODING_ENABLE = false; // no reason to disable DTMF decoding, aircraft use it on SSB
pVfo->freq_config_RX.CodeType = CODE_TYPE_OFF;
pVfo->freq_config_TX.CodeType = CODE_TYPE_OFF;
}
gEeprom.VfoInfo[VFO].Compander = (Attributes & MR_CH_COMPAND) >> 4;
pVfo->Compander = att.compander;
RADIO_ConfigureSquelchAndOutputPower(pRadio);
RADIO_ConfigureSquelchAndOutputPower(pVfo);
}
void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
@@ -513,6 +506,21 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
EEPROM_ReadBuffer(0x1ED0 + (Band * 16) + (pInfo->OUTPUT_POWER * 3), Txp, 3);
#ifdef ENABLE_REDUCE_LOW_MID_TX_POWER
// make low and mid even lower
if (pInfo->OUTPUT_POWER == OUTPUT_POWER_LOW) {
Txp[0] /= 5;
Txp[1] /= 5;
Txp[2] /= 5;
}
else if (pInfo->OUTPUT_POWER == OUTPUT_POWER_MID){
Txp[0] /= 3;
Txp[1] /= 3;
Txp[2] /= 3;
}
#endif
pInfo->TXP_CalculatedSetting = FREQUENCY_CalculateOutputPower(
Txp[0],
Txp[1],
@@ -570,13 +578,13 @@ void RADIO_SelectVfos(void)
RADIO_SelectCurrentVfo();
}
void RADIO_SetupRegisters(bool bSwitchToFunction0)
void RADIO_SetupRegisters(bool switchToForeground)
{
BK4819_FilterBandwidth_t Bandwidth = gRxVfo->CHANNEL_BANDWIDTH;
uint16_t InterruptMask;
uint32_t Frequency;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
@@ -590,7 +598,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
#ifdef ENABLE_AM_FIX
// BK4819_SetFilterBandwidth(Bandwidth, gRxVfo->AM_mode && gSetting_AM_fix);
// BK4819_SetFilterBandwidth(Bandwidth, gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix);
BK4819_SetFilterBandwidth(Bandwidth, true);
#else
BK4819_SetFilterBandwidth(Bandwidth, false);
@@ -639,7 +647,13 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_RX_ENABLE, true);
// AF RX Gain and DAC
BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000
//BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000
BK4819_WriteRegister(BK4819_REG_48,
(11u << 12) | // ??? .. 0 ~ 15, doesn't seem to make any difference
( 0u << 10) | // AF Rx Gain-1
(gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2
(gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2)
InterruptMask = BK4819_REG_3F_SQUELCH_FOUND | BK4819_REG_3F_SQUELCH_LOST;
@@ -647,15 +661,10 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
#endif
{
if (gRxVfo->AM_mode == 0)
if (gRxVfo->Modulation == MODULATION_FM)
{ // FM
uint8_t CodeType = gSelectedCodeType;
uint8_t Code = gSelectedCode;
if (gCssScanMode == CSS_SCAN_MODE_OFF)
{
CodeType = gRxVfo->pRX->CodeType;
Code = gRxVfo->pRX->Code;
}
uint8_t CodeType = gRxVfo->pRX->CodeType;
uint8_t Code = gRxVfo->pRX->Code;
switch (CodeType)
{
@@ -723,15 +732,15 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
#ifdef ENABLE_VOX
#ifdef ENABLE_NOAA
#ifdef ENABLE_FMRADIO
if (gEeprom.VOX_SWITCH && !gFmRadioMode && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && !gFmRadioMode && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->Modulation == MODULATION_FM)
#else
if (gEeprom.VOX_SWITCH && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && !IS_NOAA_CHANNEL(gCurrentVfo->CHANNEL_SAVE) && gCurrentVfo->Modulation == MODULATION_FM)
#endif
#else
#ifdef ENABLE_FMRADIO
if (gEeprom.VOX_SWITCH && !gFmRadioMode && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && !gFmRadioMode && gCurrentVfo->Modulation == MODULATION_FM)
#else
if (gEeprom.VOX_SWITCH && gCurrentVfo->AM_mode == 0)
if (gEeprom.VOX_SWITCH && gCurrentVfo->Modulation == MODULATION_FM)
#endif
#endif
{
@@ -743,7 +752,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
BK4819_DisableVox();
// RX expander
BK4819_SetCompander((gRxVfo->AM_mode == 0 && gRxVfo->Compander >= 2) ? gRxVfo->Compander : 0);
BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && gRxVfo->Compander >= 2) ? gRxVfo->Compander : 0);
#if 0
if (!gRxVfo->DTMF_DECODING_ENABLE && !gSetting_KILLED)
@@ -773,7 +782,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
FUNCTION_Init();
if (bSwitchToFunction0)
if (switchToForeground)
FUNCTION_Select(FUNCTION_FOREGROUND);
}
@@ -826,7 +835,7 @@ void RADIO_SetTxParameters(void)
{
BK4819_FilterBandwidth_t Bandwidth = gCurrentVfo->CHANNEL_BANDWIDTH;
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
@@ -840,7 +849,7 @@ void RADIO_SetTxParameters(void)
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
#ifdef ENABLE_AM_FIX
// BK4819_SetFilterBandwidth(Bandwidth, gCurrentVfo->AM_mode && gSetting_AM_fix);
// BK4819_SetFilterBandwidth(Bandwidth, gCurrentVfo->Modulation == MODULATION_AM && gSetting_AM_fix);
BK4819_SetFilterBandwidth(Bandwidth, true);
#else
BK4819_SetFilterBandwidth(Bandwidth, false);
@@ -851,7 +860,7 @@ void RADIO_SetTxParameters(void)
BK4819_SetFrequency(gCurrentVfo->pTX->Frequency);
// TX compressor
BK4819_SetCompander((gRxVfo->AM_mode == 0 && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0);
BK4819_SetCompander((gRxVfo->Modulation == MODULATION_FM && (gRxVfo->Compander == 1 || gRxVfo->Compander >= 3)) ? gRxVfo->Compander : 0);
BK4819_PrepareTransmit();
@@ -885,6 +894,37 @@ void RADIO_SetTxParameters(void)
}
}
void RADIO_SetModulation(ModulationMode_t modulation)
{
BK4819_AF_Type_t mod;
switch(modulation) {
default:
case MODULATION_FM:
mod = BK4819_AF_FM;
break;
case MODULATION_AM:
mod = BK4819_AF_AM;
break;
case MODULATION_USB:
mod = BK4819_AF_BASEBAND2;
break;
#ifdef ENABLE_BYP_RAW_DEMODULATORS
case MODULATION_BYP:
mod = BK4819_AF_UNKNOWN3;
break;
case MODULATION_RAW:
mod = BK4819_AF_BASEBAND1;
break;
#endif
}
BK4819_SetAF(mod);
BK4819_SetRegValue(afDacGainRegSpec, 0xF);
BK4819_WriteRegister(BK4819_REG_3D, modulation == MODULATION_USB ? 0 : 0x2AAB);
BK4819_SetRegValue(afcDisableRegSpec, modulation != MODULATION_FM);
}
void RADIO_SetVfoState(VfoState_t State)
{
if (State == VFO_STATE_NORMAL)
@@ -949,13 +989,13 @@ void RADIO_PrepareTX(void)
#endif
{
#ifndef ENABLE_TX_WHEN_AM
if (gCurrentVfo->AM_mode)
if (gCurrentVfo->Modulation != MODULATION_FM)
{ // not allowed to TX if in AM mode
State = VFO_STATE_TX_DISABLE;
}
else
#endif
if (!gSetting_TX_EN || gSerialConfigCountDown_500ms > 0)
if (gSerialConfigCountDown_500ms > 0)
{ // TX is disabled or config upload/download in progress
State = VFO_STATE_TX_DISABLE;
}
@@ -968,7 +1008,7 @@ void RADIO_PrepareTX(void)
if (gBatteryDisplayLevel == 0)
State = VFO_STATE_BAT_LOW; // charge your battery !
else
if (gBatteryDisplayLevel >= 6)
if (gBatteryDisplayLevel > 6)
State = VFO_STATE_VOLTAGE_HIGH; // over voltage .. this is being a pain
}
else
@@ -1031,23 +1071,17 @@ void RADIO_PrepareTX(void)
void RADIO_EnableCxCSS(void)
{
switch (gCurrentVfo->pTX->CodeType)
{
default:
case CODE_TYPE_OFF:
break;
case CODE_TYPE_CONTINUOUS_TONE:
BK4819_EnableCTCSS();
SYSTEM_DelayMs(200);
break;
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
BK4819_EnableCDCSS();
SYSTEM_DelayMs(200);
break;
switch (gCurrentVfo->pTX->CodeType) {
case CODE_TYPE_DIGITAL:
case CODE_TYPE_REVERSE_DIGITAL:
BK4819_EnableCDCSS();
break;
default:
BK4819_EnableCTCSS();
break;
}
SYSTEM_DelayMs(200);
}
void RADIO_PrepareCssTX(void)
@@ -1077,7 +1111,7 @@ void RADIO_SendEndOfTransmission(void)
{ // end-of-tx
if (gEeprom.DTMF_SIDE_TONE)
{
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOn();
gEnableSpeaker = true;
SYSTEM_DelayMs(60);
}
@@ -1092,7 +1126,7 @@ void RADIO_SendEndOfTransmission(void)
gEeprom.DTMF_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_INTERVAL_TIME);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
AUDIO_AudioPathOff();
gEnableSpeaker = false;
}

31
radio.h
View File

@@ -23,13 +23,6 @@
#include "dcs.h"
#include "frequencies.h"
enum {
MR_CH_BAND_MASK = 0x0F << 0,
MR_CH_COMPAND = 3u << 4, // new
MR_CH_SCANLIST2 = 1u << 6,
MR_CH_SCANLIST1 = 1u << 7
};
enum {
RADIO_CHANNEL_UP = 0x01u,
RADIO_CHANNEL_DOWN = 0xFFu,
@@ -61,6 +54,21 @@ enum VfoState_t
};
typedef enum VfoState_t VfoState_t;
typedef enum {
MODULATION_FM,
MODULATION_AM,
MODULATION_USB,
#ifdef ENABLE_BYP_RAW_DEMODULATORS
MODULATION_BYP,
MODULATION_RAW,
#endif
MODULATION_UKNOWN
} ModulationMode_t;
extern const char gModulationStr[MODULATION_UKNOWN][4];
typedef struct
{
uint32_t Frequency;
@@ -115,7 +123,7 @@ typedef struct VFO_Info_t
uint8_t BUSY_CHANNEL_LOCK;
uint8_t AM_mode;
ModulationMode_t Modulation;
uint8_t Compander;
@@ -134,11 +142,7 @@ extern VFO_Info_t *gRxVfo;
// Equal to gTxVfo unless dual watch changes it on incomming transmition (this can only happen when XB off and DW on)
extern VFO_Info_t *gCurrentVfo;
extern DCS_CodeType_t gSelectedCodeType;
extern DCS_CodeType_t gCurrentCodeType;
extern uint8_t gSelectedCode;
extern STEP_Setting_t gStepSetting;
extern VfoState_t VfoState[2];
@@ -154,11 +158,12 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0);
void RADIO_ConfigureNOAA(void);
#endif
void RADIO_SetTxParameters(void);
void RADIO_SetModulation(ModulationMode_t modulation);
void RADIO_SetVfoState(VfoState_t State);
void RADIO_PrepareTX(void);
void RADIO_EnableCxCSS(void);
void RADIO_PrepareCssTX(void);
void RADIO_SendEndOfTransmission(void);
#endif

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "app/chFrScanner.h"
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
#endif
@@ -77,18 +78,18 @@ void SystickHandler(void)
if (gCurrentFunction == FUNCTION_POWER_SAVE)
DECREMENT_AND_TRIGGER(gPowerSave_10ms, gPowerSaveCountdownExpired);
if (gScanStateDir == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
if (gScanStateDir == SCAN_OFF && !gCssBackgroundScan && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT && gCurrentFunction != FUNCTION_RECEIVE)
DECREMENT_AND_TRIGGER(gDualWatchCountdown_10ms, gScheduleDualWatch);
#ifdef ENABLE_NOAA
if (gScanStateDir == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && gEeprom.DUAL_WATCH == DUAL_WATCH_OFF)
if (gScanStateDir == SCAN_OFF && !gCssBackgroundScan && gEeprom.DUAL_WATCH == DUAL_WATCH_OFF)
if (gIsNoaaMode && gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT)
if (gCurrentFunction != FUNCTION_RECEIVE)
DECREMENT_AND_TRIGGER(gNOAA_Countdown_10ms, gScheduleNOAA);
#endif
if (gScanStateDir != SCAN_OFF || gCssScanMode == CSS_SCAN_MODE_SCANNING)
if (gScanStateDir != SCAN_OFF)
if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT)
DECREMENT_AND_TRIGGER(gScanPauseDelayIn_10ms, gScheduleScanListen);

View File

@@ -102,7 +102,7 @@ void SETTINGS_SaveSettings(void)
State[3] = gEeprom.BATTERY_SAVE;
State[4] = gEeprom.DUAL_WATCH;
State[5] = gEeprom.BACKLIGHT_TIME;
State[6] = gEeprom.TAIL_NOTE_ELIMINATION;
State[6] = gEeprom.TAIL_TONE_ELIMINATION;
State[7] = gEeprom.VFO_OPEN;
EEPROM_WriteBuffer(0x0E78, State);
@@ -137,6 +137,7 @@ void SETTINGS_SaveSettings(void)
State[1] = gEeprom.ROGER;
State[2] = gEeprom.REPEATER_TAIL_TONE_ELIMINATION;
State[3] = gEeprom.TX_VFO;
State[4] = gEeprom.BATTERY_TYPE;
EEPROM_WriteBuffer(0x0EA8, State);
State[0] = gEeprom.DTMF_SIDE_TONE;
@@ -173,7 +174,7 @@ void SETTINGS_SaveSettings(void)
State[4] = gSetting_500TX;
State[5] = gSetting_350EN;
State[6] = gSetting_ScrambleEnable;
if (!gSetting_TX_EN) State[7] &= ~(1u << 0);
//if (!gSetting_TX_EN) State[7] &= ~(1u << 0);
if (!gSetting_live_DTMF_decoder) State[7] &= ~(1u << 1);
State[7] = (State[7] & ~(3u << 2)) | ((gSetting_battery_text & 3u) << 2);
#ifdef ENABLE_AUDIO_BAR
@@ -214,7 +215,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
State[0] = pVFO->freq_config_RX.Code;
State[1] = pVFO->freq_config_TX.Code;
State[2] = (pVFO->freq_config_TX.CodeType << 4) | pVFO->freq_config_RX.CodeType;
State[3] = ((pVFO->AM_mode & 1u) << 4) | pVFO->TX_OFFSET_FREQUENCY_DIRECTION;
State[3] = (pVFO->Modulation << 4) | pVFO->TX_OFFSET_FREQUENCY_DIRECTION;
State[4] = 0
| (pVFO->BUSY_CHANNEL_LOCK << 4)
| (pVFO->OUTPUT_POWER << 2)
@@ -262,55 +263,45 @@ void SETTINGS_SaveBatteryCalibration(const uint16_t * batteryCalibration)
EEPROM_WriteBuffer(0x1F48, buf);
}
void SETTINGS_UpdateChannel(uint8_t Channel, const VFO_Info_t *pVFO, bool keep)
void SETTINGS_UpdateChannel(uint8_t channel, const VFO_Info_t *pVFO, bool keep)
{
#ifdef ENABLE_NOAA
if (!IS_NOAA_CHANNEL(Channel))
#endif
#ifdef ENABLE_NOAA
if (!IS_NOAA_CHANNEL(channel))
#endif
{
uint8_t State[8];
uint8_t Attributes = 0xFF; // default attributes
uint16_t Offset = 0x0D60 + (Channel & ~7u);
uint8_t state[8];
ChannelAttributes_t att = {
.band = 0xf,
.compander = 0,
.scanlist1 = 0,
.scanlist2 = 0,
}; // default attributes
Attributes &= (uint8_t)(~MR_CH_COMPAND); // default to '0' = compander disabled
uint16_t offset = 0x0D60 + (channel & ~7u);
EEPROM_ReadBuffer(offset, state, sizeof(state));
EEPROM_ReadBuffer(Offset, State, sizeof(State));
if (keep)
{
Attributes = (pVFO->SCANLIST1_PARTICIPATION << 7) | (pVFO->SCANLIST2_PARTICIPATION << 6) | (pVFO->Compander << 4) | (pVFO->Band << 0);
if (State[Channel & 7u] == Attributes)
if (keep) {
att.band = pVFO->Band;
att.scanlist1 = pVFO->SCANLIST1_PARTICIPATION;
att.scanlist2 = pVFO->SCANLIST2_PARTICIPATION;
att.compander = pVFO->Compander;
if (state[channel & 7u] == att.__val)
return; // no change in the attributes
}
State[Channel & 7u] = Attributes;
state[channel & 7u] = att.__val;
EEPROM_WriteBuffer(offset, state);
EEPROM_WriteBuffer(Offset, State);
gMR_ChannelAttributes[channel] = att;
gMR_ChannelAttributes[Channel] = Attributes;
// #ifndef ENABLE_KEEP_MEM_NAME
if (IS_MR_CHANNEL(Channel))
{ // it's a memory channel
const uint16_t OffsetMR = Channel * 16;
if (!keep)
{ // clear/reset the channel name
//memset(&State, 0xFF, sizeof(State));
memset(&State, 0x00, sizeof(State)); // follow the QS way
EEPROM_WriteBuffer(0x0F50 + OffsetMR, State);
EEPROM_WriteBuffer(0x0F58 + OffsetMR, State);
}
// else
// { // update the channel name
// memmove(State, pVFO->Name + 0, 8);
// EEPROM_WriteBuffer(0x0F50 + OffsetMR, State);
// //memset(State, 0xFF, sizeof(State));
// memset(State, 0x00, sizeof(State)); // follow the QS way
// memmove(State, pVFO->Name + 8, 2);
// EEPROM_WriteBuffer(0x0F58 + OffsetMR, State);
// }
if (IS_MR_CHANNEL(channel)) { // it's a memory channel
const uint16_t OffsetMR = channel * 16;
if (!keep) {
// clear/reset the channel name
memset(&state, 0x00, sizeof(state));
EEPROM_WriteBuffer(0x0F50 + OffsetMR, state);
EEPROM_WriteBuffer(0x0F58 + OffsetMR, state);
}
// #endif
}
}
}

View File

@@ -21,7 +21,9 @@
#include <stdint.h>
#include "frequencies.h"
#include <helper/battery.h>
#include "radio.h"
#include <driver/backlight.h>
enum POWER_OnDisplayMode_t {
POWER_ON_DISPLAY_MODE_FULL_SCREEN = 0,
@@ -32,12 +34,15 @@ enum POWER_OnDisplayMode_t {
typedef enum POWER_OnDisplayMode_t POWER_OnDisplayMode_t;
enum {
F_LOCK_OFF = 0,
F_LOCK_DEF, //all default frequencies + configurable
F_LOCK_FCC,
F_LOCK_CE,
F_LOCK_GB,
F_LOCK_430,
F_LOCK_438
F_LOCK_438,
F_LOCK_ALL, // disable TX on all frequencies
F_LOCK_NONE, // enable TX on all frequencies
F_LOCK_LEN
};
enum {
@@ -83,6 +88,10 @@ enum {
ACTION_OPT_KEYLOCK,
ACTION_OPT_A_B,
ACTION_OPT_VFO_MR,
ACTION_OPT_SWITCH_DEMODUL,
#ifdef ENABLE_BLMIN_TMP_OFF
ACTION_OPT_BLMIN_TMP_OFF, //BackLight Minimum Temporay OFF
#endif
ACTION_OPT_LEN
};
@@ -118,9 +127,9 @@ enum CHANNEL_DisplayMode_t {
typedef enum CHANNEL_DisplayMode_t CHANNEL_DisplayMode_t;
typedef struct {
uint8_t ScreenChannel[2];
uint8_t FreqChannel[2];
uint8_t MrChannel[2];
uint8_t ScreenChannel[2]; // current channels set in the radio (memory or frequency channels)
uint8_t FreqChannel[2]; // last frequency channels used
uint8_t MrChannel[2]; // last memory channels used
#ifdef ENABLE_NOAA
uint8_t NoaaChannel[2];
#endif
@@ -155,7 +164,7 @@ typedef struct {
#endif
bool BEEP_CONTROL;
uint8_t CHANNEL_DISPLAY_MODE;
bool TAIL_NOTE_ELIMINATION;
bool TAIL_TONE_ELIMINATION;
bool VFO_OPEN;
uint8_t DUAL_WATCH;
uint8_t CROSS_BAND_RX_TX;
@@ -229,7 +238,11 @@ typedef struct {
uint8_t KEY_M_LONG_PRESS_ACTION;
uint8_t BACKLIGHT_MIN;
#ifdef ENABLE_BLMIN_TMP_OFF
BLMIN_STAT_t BACKLIGHT_MIN_STAT;
#endif
uint8_t BACKLIGHT_MAX;
BATTERY_Type_t BATTERY_TYPE;
} EEPROM_Config_t;
extern EEPROM_Config_t gEeprom;
@@ -241,6 +254,6 @@ void SETTINGS_SaveVfoIndices(void);
void SETTINGS_SaveSettings(void);
void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO, uint8_t Mode);
void SETTINGS_SaveBatteryCalibration(const uint16_t * batteryCalibration);
void SETTINGS_UpdateChannel(uint8_t Channel, const VFO_Info_t *pVFO, bool keep);
void SETTINGS_UpdateChannel(uint8_t channel, const VFO_Info_t *pVFO, bool keep);
#endif

View File

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

View File

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

View File

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

321
ui/main.c
View File

@@ -40,21 +40,43 @@ center_line_t center_line = CENTER_LINE_NONE;
// ***************************************************************************
void UI_drawBars(uint8_t *p, const unsigned int level)
static void DrawSmallAntennaAndBars(uint8_t *p, unsigned int level)
{
switch (level)
{
default:
case 7: memmove(p + 20, BITMAP_AntennaLevel6, sizeof(BITMAP_AntennaLevel6)); [[fallthrough]];
case 6: memmove(p + 17, BITMAP_AntennaLevel5, sizeof(BITMAP_AntennaLevel5)); [[fallthrough]];
case 5: memmove(p + 14, BITMAP_AntennaLevel4, sizeof(BITMAP_AntennaLevel4)); [[fallthrough]];
case 4: memmove(p + 11, BITMAP_AntennaLevel3, sizeof(BITMAP_AntennaLevel3)); [[fallthrough]];
case 3: memmove(p + 8, BITMAP_AntennaLevel2, sizeof(BITMAP_AntennaLevel2)); [[fallthrough]];
case 2: memmove(p + 5, BITMAP_AntennaLevel1, sizeof(BITMAP_AntennaLevel1)); [[fallthrough]];
case 1: memmove(p + 0, BITMAP_Antenna, sizeof(BITMAP_Antenna)); break;
case 0: memset( p + 0, 0, sizeof(BITMAP_Antenna)); break;
if(level>6)
level = 6;
memcpy(p, BITMAP_Antenna, ARRAY_SIZE(BITMAP_Antenna));
for(uint8_t i = 1; i <= level; i++) {
char bar = (0xff << (6-i)) & 0x7F;
memset(p + 2 + i*3, bar, 2);
}
}
#if defined ENABLE_AUDIO_BAR || defined ENABLE_RSSI_BAR
static void DrawLevelBar(uint8_t xpos, uint8_t line, uint8_t level)
{
const char hollowBar[] = {
0b01111111,
0b01000001,
0b01000001,
0b01111111
};
uint8_t *p_line = gFrameBuffer[line];
level = MIN(level, 13);
for(uint8_t i = 0; i < level; i++) {
if(i < 9) {
for(uint8_t j = 0; j < 4; j++)
p_line[xpos + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F;
}
else {
memcpy(p_line + (xpos + i * 5), &hollowBar, ARRAY_SIZE(hollowBar));
}
}
}
#endif
#ifdef ENABLE_AUDIO_BAR
@@ -79,10 +101,10 @@ void UI_DisplayAudioBar(void)
{
if (gSetting_mic_bar)
{
if(gLowBattery && !gLowBatteryConfirmed)
return;
const unsigned int line = 3;
const unsigned int bar_x = 2;
const unsigned int bar_width = LCD_WIDTH - 2 - bar_x;
unsigned int i;
if (gCurrentFunction != FUNCTION_TRANSMIT ||
gScreenToDisplay != DISPLAY_MAIN ||
@@ -98,16 +120,14 @@ void UI_DisplayAudioBar(void)
const unsigned int voice_amp = BK4819_GetVoiceAmplitudeOut(); // 15:0
// make non-linear to make more sensitive at low values
const unsigned int level = voice_amp * 8;
const unsigned int sqrt_level = sqrt16((level < 65535) ? level : 65535);
const unsigned int len = (sqrt_level <= bar_width) ? sqrt_level : bar_width;
const unsigned int level = MIN(voice_amp * 8, 65535u);
const unsigned int sqrt_level = MIN(sqrt16(level), 124u);
uint8_t bars = 13 * sqrt_level / 124;
uint8_t *p_line = gFrameBuffer[line];
memset(p_line, 0, LCD_WIDTH);
for (i = 0; i < bar_width; i++)
p_line[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
DrawLevelBar(62, line, bars);
if (gCurrentFunction == FUNCTION_TRANSMIT)
ST7565_BlitFullScreen();
@@ -115,154 +135,110 @@ void UI_DisplayAudioBar(void)
}
#endif
#if defined(ENABLE_RSSI_BAR)
void UI_DisplayRSSIBar(const int16_t rssi, const bool now)
static void DisplayRSSIBar(const int16_t rssi, const bool now)
{
const int16_t s0_dBm = -147; // S0 .. base level
const unsigned int txt_width = 7 * 8; // 8 text chars
const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph
const int16_t rssi_dBm = (rssi / 2) - 160;
#if defined(ENABLE_RSSI_BAR)
const unsigned int line = 3;
uint8_t *p_line = gFrameBuffer[line];
char str[16];
if (center_line == CENTER_LINE_RSSI) {
const unsigned int txt_width = 7 * 8; // 8 text chars
const unsigned int bar_x = 2 + txt_width + 4; // X coord of bar graph
const char plus[] = {
0b00011000,
0b00011000,
0b01111110,
0b01111110,
0b01111110,
0b00011000,
0b00011000,
};
const unsigned int line = 3;
uint8_t *p_line = gFrameBuffer[line];
char str[16];
const char hollowBar[] = {
0b01111111,
0b01000001,
0b01000001,
0b01111111
};
const char plus[] = {
0b00011000,
0b00011000,
0b01111110,
0b01111110,
0b01111110,
0b00011000,
0b00011000,
};
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (gCurrentFunction == FUNCTION_TRANSMIT ||
gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return; // display is in use
if (gCurrentFunction == FUNCTION_TRANSMIT ||
gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return; // display is in use
if (now)
memset(p_line, 0, LCD_WIDTH);
const int8_t dBmCorrTable[7] = {
-15, // band 1
-15, // band 2
-25, // band 3
-20, // band 4
-20, // band 5
-20, // band 6
-7 // band 7
};
const int16_t s0_dBm = -147; // S0 .. base level
const int16_t rssi_dBm = (rssi / 2) - 160 + dBmCorrTable[gRxVfo->Band];
const uint8_t s_level = MIN(MAX((rssi_dBm - s0_dBm) / 6, 0), 9); // S0 - S9
uint8_t overS9dBm = MIN(MAX(rssi_dBm - (s0_dBm + 9*6), 0), 99);
uint8_t overS9Bars = MIN(overS9dBm/10, 4);
if(overS9Bars == 0) {
sprintf(str, "% 4d S%d", rssi_dBm, s_level);
}
else {
sprintf(str, "% 4d %2d", rssi_dBm, overS9dBm);
memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus));
}
UI_PrintStringSmall(str, 2, 0, line);
DrawLevelBar(bar_x, line, s_level + overS9Bars);
}
#else
uint8_t Level;
if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][3]) {
Level = 6;
} else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][2]) {
Level = 4;
} else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][1]) {
Level = 2;
} else if (rssi >= gEEPROM_RSSI_CALIB[gRxVfo->Band][0]) {
Level = 1;
} else {
Level = 0;
}
uint8_t *pLine = (gEeprom.RX_VFO == 0)? gFrameBuffer[2] : gFrameBuffer[6];
if (now)
memset(p_line, 0, LCD_WIDTH);
const uint8_t s_level = MIN(MAX((rssi_dBm - s0_dBm) / 6, 0), 9);
uint8_t overS9Bars = MAX(0, 73 + rssi_dBm)/10;
if(overS9Bars == 0) {
sprintf(str, "% 4d S%d", rssi_dBm, s_level);
}
else {
sprintf(str, "% 4d %d0", rssi_dBm, overS9Bars);
memcpy(p_line + 2 + 7*5, &plus, ARRAY_SIZE(plus));
}
UI_PrintStringSmall(str, 2, 0, line);
for(uint8_t i = 0; i < s_level; i++) { // S bars
for(uint8_t j = 0; j < 4; j++)
p_line[bar_x + i * 5 + j] = (~(0x7F >> (i+1))) & 0x7F;
}
overS9Bars = MIN(overS9Bars, 4);
for(uint8_t i = 0; i < overS9Bars; i++) { // +10 hollow bars
memcpy(p_line + (bar_x + (i + 9) * 5), &hollowBar, ARRAY_SIZE(hollowBar));
}
memset(pLine, 0, 23);
DrawSmallAntennaAndBars(pLine, Level);
#endif
if (now)
ST7565_BlitFullScreen();
}
#endif
void UI_UpdateRSSI(const int16_t rssi, const int vfo)
{
#ifdef ENABLE_RSSI_BAR
(void)vfo; // unused
// optional larger RSSI dBm, S-point and bar level
if (center_line != CENTER_LINE_RSSI)
return;
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING)
{
UI_DisplayRSSIBar(rssi, true);
DisplayRSSIBar(rssi, true);
}
#else
// original little RS bars
// const int16_t dBm = (rssi / 2) - 160;
const uint8_t Line = (vfo == 0) ? 3 : 7;
uint8_t *p_line = gFrameBuffer[Line - 1];
const unsigned int band = gRxVfo->Band;
const int16_t level0 = gEEPROM_RSSI_CALIB[band][0];
const int16_t level1 = gEEPROM_RSSI_CALIB[band][1];
const int16_t level2 = gEEPROM_RSSI_CALIB[band][2];
const int16_t level3 = gEEPROM_RSSI_CALIB[band][3];
const int16_t level01 = (level0 + level1) / 2;
const int16_t level12 = (level1 + level2) / 2;
const int16_t level23 = (level2 + level3) / 2;
gVFO_RSSI[vfo] = rssi;
uint8_t rssi_level = 0;
if (rssi >= level3) rssi_level = 7;
else
if (rssi >= level23) rssi_level = 6;
else
if (rssi >= level2) rssi_level = 5;
else
if (rssi >= level12) rssi_level = 4;
else
if (rssi >= level1) rssi_level = 3;
else
if (rssi >= level01) rssi_level = 2;
else
if (rssi >= level0) rssi_level = 1;
if (gVFO_RSSI_bar_level[vfo] == rssi_level)
return;
gVFO_RSSI_bar_level[vfo] = rssi_level;
// **********************************************************
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (gCurrentFunction == FUNCTION_TRANSMIT || gScreenToDisplay != DISPLAY_MAIN)
return; // display is in use
p_line = gFrameBuffer[Line - 1];
memset(p_line, 0, 23);
// untested !!!
if (rssi_level == 0)
p_line = NULL;
else
UI_drawBars(p_line, rssi_level);
ST7565_DrawLine(0, Line, 23, p_line);
#endif
}
// ***************************************************************************
@@ -279,6 +255,12 @@ void UI_DisplayMain(void)
// clear the screen
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
if(gLowBattery && !gLowBatteryConfirmed) {
UI_DisplayPopup("LOW BATTERY");
ST7565_BlitFullScreen();
return;
}
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
{ // tell user how to unlock the keyboard
UI_PrintString("Long press #", 0, LCD_WIDTH, 1, 8);
@@ -461,7 +443,7 @@ void UI_DisplayMain(void)
UI_PrintString(String, 32, 0, line, 8);
}
break;
continue;
}
else
{
@@ -475,15 +457,15 @@ void UI_DisplayMain(void)
{ // it's a channel
// show the scan list assigment symbols
const uint8_t attributes = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if (attributes & MR_CH_SCANLIST1)
const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if (att.scanlist1)
memmove(p_line0 + 113, BITMAP_ScanList1, sizeof(BITMAP_ScanList1));
if (attributes & MR_CH_SCANLIST2)
if (att.scanlist2)
memmove(p_line0 + 120, BITMAP_ScanList2, sizeof(BITMAP_ScanList2));
// compander symbol
#ifndef ENABLE_BIG_FREQ
if ((attributes & MR_CH_COMPAND) > 0)
if (att.compander)
memmove(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
#else
// TODO: // find somewhere else to put the symbol
@@ -561,8 +543,8 @@ void UI_DisplayMain(void)
}
// show the channel symbols
const uint8_t attributes = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if ((attributes & MR_CH_COMPAND) > 0)
const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if (att.compander)
#ifdef ENABLE_BIG_FREQ
memmove(p_line0 + 120, BITMAP_compand, sizeof(BITMAP_compand));
#else
@@ -594,26 +576,31 @@ void UI_DisplayMain(void)
Level = gVFO_RSSI_bar_level[vfo_num];
#endif
}
UI_drawBars(p_line1 + LCD_WIDTH, Level);
if(Level)
DrawSmallAntennaAndBars(p_line1 + LCD_WIDTH, Level);
}
// ************
String[0] = '\0';
if (gEeprom.VfoInfo[vfo_num].AM_mode)
{ // show the AM symbol
strcpy(String, "AM");
// show the modulation symbol
const char * s = "";
const ModulationMode_t mod = gEeprom.VfoInfo[vfo_num].Modulation;
switch (mod){
case MODULATION_FM: {
const FREQ_Config_t *pConfig = (mode == 1) ? gEeprom.VfoInfo[vfo_num].pTX : gEeprom.VfoInfo[vfo_num].pRX;
const unsigned int code_type = pConfig->CodeType;
const char *code_list[] = {"", "CT", "DCS", "DCR"};
if (code_type < ARRAY_SIZE(code_list))
s = code_list[code_type];
break;
}
default:
s = gModulationStr[mod];
break;
}
else
{ // or show the CTCSS/DCS symbol
const FREQ_Config_t *pConfig = (mode == 1) ? gEeprom.VfoInfo[vfo_num].pTX : gEeprom.VfoInfo[vfo_num].pRX;
const unsigned int code_type = pConfig->CodeType;
const char *code_list[] = {"", "CT", "DCS", "DCR"};
if (code_type < ARRAY_SIZE(code_list))
strcpy(String, code_list[code_type]);
}
UI_PrintStringSmall(String, LCD_WIDTH + 24, 0, line + 1);
UI_PrintStringSmall(s, LCD_WIDTH + 24, 0, line + 1);
if (state == VFO_STATE_NORMAL || state == VFO_STATE_ALARM)
{ // show the TX power
@@ -672,7 +659,7 @@ void UI_DisplayMain(void)
#endif
#if defined(ENABLE_AM_FIX) && defined(ENABLE_AM_FIX_SHOW_DATA)
if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].AM_mode && gSetting_AM_fix)
if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].Modulation == MODULATION_AM && gSetting_AM_fix)
{
if (gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
@@ -688,7 +675,7 @@ void UI_DisplayMain(void)
#ifdef ENABLE_RSSI_BAR
if (rx) {
center_line = CENTER_LINE_RSSI;
UI_DisplayRSSIBar(gCurrentRSSI[gEeprom.RX_VFO], false);
DisplayRSSIBar(gCurrentRSSI[gEeprom.RX_VFO], false);
}
else
#endif

189
ui/menu.c
View File

@@ -129,11 +129,11 @@ const t_menu_item MenuList[] =
{"Tx 500", VOICE_ID_INVALID, MENU_500TX }, // was "500TX"
{"350 En", VOICE_ID_INVALID, MENU_350EN }, // was "350EN"
{"ScraEn", VOICE_ID_INVALID, MENU_SCREN }, // was "SCREN"
{"TxEnab", VOICE_ID_INVALID, MENU_TX_EN }, // enable TX
#ifdef ENABLE_F_CAL_MENU
{"FrCali", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration
#endif
{"BatCal", VOICE_ID_INVALID, MENU_BATCAL }, // battery voltage calibration
{"BatTyp", VOICE_ID_INVALID, MENU_BATTYP }, // battery type 1600/2200mAh
{"Reset", VOICE_ID_INITIALISATION, MENU_RESET }, // might be better to move this to the hidden menu items ?
{"", VOICE_ID_INVALID, 0xff } // end of list - DO NOT delete or move this this
@@ -141,33 +141,33 @@ const t_menu_item MenuList[] =
const uint8_t FIRST_HIDDEN_MENU_ITEM = MENU_F_LOCK;
const char gSubMenu_TXP[3][5] =
const char gSubMenu_TXP[][5] =
{
"LOW",
"MID",
"HIGH"
};
const char gSubMenu_SFT_D[3][4] =
const char gSubMenu_SFT_D[][4] =
{
"OFF",
"+",
"-"
};
const char gSubMenu_W_N[2][7] =
const char gSubMenu_W_N[][7] =
{
"WIDE",
"NARROW"
};
const char gSubMenu_OFF_ON[2][4] =
const char gSubMenu_OFF_ON[][4] =
{
"OFF",
"ON"
};
const char gSubMenu_SAVE[5][4] =
const char gSubMenu_SAVE[][4] =
{
"OFF",
"1:1",
@@ -176,7 +176,7 @@ const char gSubMenu_SAVE[5][4] =
"1:4"
};
const char gSubMenu_TOT[11][7] =
const char gSubMenu_TOT[][7] =
{
"30 sec",
"1 min",
@@ -191,7 +191,7 @@ const char gSubMenu_TOT[11][7] =
"15 min"
};
const char* gSubMenu_RXMode[4] =
const char* gSubMenu_RXMode[] =
{
"MAIN\nONLY", // TX and RX on main only
"DUAL RX\nRESPOND", // Watch both and respond
@@ -200,7 +200,7 @@ const char* gSubMenu_RXMode[4] =
};
#ifdef ENABLE_VOICE
const char gSubMenu_VOICE[3][4] =
const char gSubMenu_VOICE[][4] =
{
"OFF",
"CHI",
@@ -208,14 +208,14 @@ const char* gSubMenu_RXMode[4] =
};
#endif
const char gSubMenu_SC_REV[3][8] =
const char gSubMenu_SC_REV[][8] =
{
"TIMEOUT",
"CARRIER",
"STOP"
};
const char* gSubMenu_MDF[4] =
const char* gSubMenu_MDF[] =
{
"FREQ",
"CHANNEL\nNUMBER",
@@ -224,14 +224,14 @@ const char* gSubMenu_MDF[4] =
};
#ifdef ENABLE_ALARM
const char gSubMenu_AL_MOD[2][5] =
const char gSubMenu_AL_MOD[][5] =
{
"SITE",
"TONE"
};
#endif
const char gSubMenu_D_RSP[4][11] =
const char gSubMenu_D_RSP[][11] =
{
"DO\nNOTHING",
"RING",
@@ -239,16 +239,16 @@ const char gSubMenu_D_RSP[4][11] =
"BOTH"
};
const char* gSubMenu_PTT_ID[5] =
const char* gSubMenu_PTT_ID[] =
{
"OFF",
"KEY\nUP",
"KEY\nDOWN",
"KEY\nUP+DOWN",
"UP CODE",
"DOWN CODE",
"UP+DOWN\nCODE",
"APOLLO\nQUINDAR"
};
const char gSubMenu_PONMSG[4][8] =
const char gSubMenu_PONMSG[][8] =
{
"FULL",
"MESSAGE",
@@ -256,30 +256,32 @@ const char gSubMenu_PONMSG[4][8] =
"NONE"
};
const char* gSubMenu_ROGER[3] =
const char gSubMenu_ROGER[][6] =
{
"OFF",
"ROGER",
"MDC\n1200"
"MDC"
};
const char gSubMenu_RESET[2][4] =
const char gSubMenu_RESET[][4] =
{
"VFO",
"ALL"
};
const char gSubMenu_F_LOCK[6][4] =
const char * gSubMenu_F_LOCK[] =
{
"OFF",
"FCC",
"CE",
"GB",
"430",
"438"
"DEFAULT+\n137-174\n400-470",
"FCC HAM\n144-148\n420-450",
"CE HAM\n144-146\n430-440",
"GB HAM\n144-148\n430-440",
"137-174\n400-430",
"137-174\n400-438",
"DISABLE\nALL",
"UNLOCK\nALL",
};
const char gSubMenu_BACKLIGHT[8][7] =
const char gSubMenu_BACKLIGHT[][7] =
{
"OFF",
"5 sec",
@@ -291,7 +293,7 @@ const char gSubMenu_BACKLIGHT[8][7] =
"ON"
};
const char gSubMenu_RX_TX[4][6] =
const char gSubMenu_RX_TX[][6] =
{
"OFF",
"TX",
@@ -300,7 +302,7 @@ const char gSubMenu_RX_TX[4][6] =
};
#ifdef ENABLE_AM_FIX_TEST1
const char gSubMenu_AM_fix_test1[4][8] =
const char gSubMenu_AM_fix_test1[][8] =
{
"LNA-S 0",
"LNA-S 1",
@@ -309,14 +311,20 @@ const char gSubMenu_RX_TX[4][6] =
};
#endif
const char gSubMenu_BAT_TXT[3][8] =
const char gSubMenu_BAT_TXT[][8] =
{
"NONE",
"VOLTAGE",
"PERCENT"
};
const char gSubMenu_SCRAMBLER[11][7] =
const char gSubMenu_BATTYP[][9] =
{
"1600mAh",
"2200mAh"
};
const char gSubMenu_SCRAMBLER[][7] =
{
"OFF",
"2600Hz",
@@ -331,7 +339,6 @@ const char gSubMenu_SCRAMBLER[11][7] =
"3500Hz"
};
const t_sidefunction SIDEFUNCTIONS[] =
{
{"NONE", ACTION_OPT_NONE},
@@ -353,20 +360,32 @@ const t_sidefunction SIDEFUNCTIONS[] =
#endif
{"LOCK\nKEYPAD", ACTION_OPT_KEYLOCK},
{"SWITCH\nVFO", ACTION_OPT_A_B},
{"VFO/MR", ACTION_OPT_VFO_MR},
{"VFO/MR", ACTION_OPT_VFO_MR},
{"SWITCH\nDEMODUL", ACTION_OPT_SWITCH_DEMODUL},
#ifdef ENABLE_BLMIN_TMP_OFF
{"BLMIN\nTMP OFF", ACTION_OPT_BLMIN_TMP_OFF}, //BackLight Minimum Temporay OFF
#endif
};
const t_sidefunction* gSubMenu_SIDEFUNCTIONS = SIDEFUNCTIONS;
const uint8_t gSubMenu_SIDEFUNCTIONS_size = ARRAY_SIZE(SIDEFUNCTIONS);
bool gIsInSubMenu;
uint8_t gMenuCursor;
int GetCurrentMenuId() {
int UI_MENU_GetCurrentMenuId() {
if(gMenuCursor < ARRAY_SIZE(MenuList))
return MenuList[gMenuCursor].menu_id;
else
return MenuList[ARRAY_SIZE(MenuList)-1].menu_id;
}
int8_t gMenuScrollDirection;
uint8_t UI_MENU_GetMenuIdx(uint8_t id)
{
for(uint8_t i = 0; i < ARRAY_SIZE(MenuList); i++)
if(MenuList[i].menu_id == id)
return i;
return 0;
}
int32_t gSubMenuSelection;
// edit box
@@ -469,7 +488,7 @@ void UI_DisplayMenu(void)
bool already_printed = false;
switch (GetCurrentMenuId())
switch (UI_MENU_GetCurrentMenuId())
{
case MENU_SQL:
sprintf(String, "%d", gSubMenuSelection);
@@ -488,9 +507,11 @@ void UI_DisplayMenu(void)
break;
#endif
case MENU_STEP:
sprintf(String, "%d.%02ukHz", StepFrequencyTable[gSubMenuSelection] / 100, abs(StepFrequencyTable[gSubMenuSelection]) % 100);
case MENU_STEP: {
uint16_t step = gStepFrequencyTable[FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection)];
sprintf(String, "%d.%02ukHz", step / 100, step % 100);
break;
}
case MENU_TXP:
strcpy(String, gSubMenu_TXP[gSubMenuSelection]);
@@ -500,8 +521,7 @@ void UI_DisplayMenu(void)
case MENU_T_DCS:
if (gSubMenuSelection == 0)
strcpy(String, "OFF");
else
if (gSubMenuSelection < 105)
else if (gSubMenuSelection < 105)
sprintf(String, "D%03oN", DCS_Options[gSubMenuSelection - 1]);
else
sprintf(String, "D%03oI", DCS_Options[gSubMenuSelection - 105]);
@@ -510,38 +530,10 @@ void UI_DisplayMenu(void)
case MENU_R_CTCS:
case MENU_T_CTCS:
{
#if 1
unsigned int Code;
FREQ_Config_t *pConfig = (GetCurrentMenuId() == MENU_R_CTCS) ? &gTxVfo->freq_config_RX : &gTxVfo->freq_config_TX;
if (gSubMenuSelection == 0)
{
strcpy(String, "OFF");
if (pConfig->CodeType != CODE_TYPE_CONTINUOUS_TONE)
break;
Code = 0;
pConfig->CodeType = CODE_TYPE_OFF;
pConfig->Code = Code;
BK4819_ExitSubAu();
}
else
{
sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10);
pConfig->CodeType = CODE_TYPE_CONTINUOUS_TONE;
Code = gSubMenuSelection - 1;
pConfig->Code = Code;
BK4819_SetCTCSSFrequency(CTCSS_Options[Code]);
}
#else
if (gSubMenuSelection == 0)
strcpy(String, "OFF");
else
sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10);
#endif
if (gSubMenuSelection == 0)
strcpy(String, "OFF");
else
sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10);
break;
}
@@ -605,7 +597,7 @@ void UI_DisplayMenu(void)
break;
case MENU_AM:
strcpy(String, (gSubMenuSelection == 0) ? "FM" : "AM");
strcpy(String, gModulationStr[gSubMenuSelection]);
break;
#ifdef ENABLE_AM_FIX_TEST1
@@ -643,7 +635,6 @@ void UI_DisplayMenu(void)
case MENU_500TX:
case MENU_350EN:
case MENU_SCREN:
case MENU_TX_EN:
strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]);
break;
@@ -811,7 +802,10 @@ void UI_DisplayMenu(void)
break;
case MENU_F_LOCK:
strcpy(String, gSubMenu_F_LOCK[gSubMenuSelection]);
if(!gIsInSubMenu && gUnlockAllTxConfCnt>0 && gUnlockAllTxConfCnt<10)
strcpy(String, "READ\nMANUAL");
else
strcpy(String, gSubMenu_F_LOCK[gSubMenuSelection]);
break;
#ifdef ENABLE_F_CAL_MENU
@@ -836,6 +830,10 @@ void UI_DisplayMenu(void)
break;
}
case MENU_BATTYP:
strcpy(String, gSubMenu_BATTYP[gSubMenuSelection]);
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
@@ -900,9 +898,9 @@ void UI_DisplayMenu(void)
}
}
if (GetCurrentMenuId() == MENU_SLIST1 || GetCurrentMenuId() == MENU_SLIST2)
if (UI_MENU_GetCurrentMenuId() == MENU_SLIST1 || UI_MENU_GetCurrentMenuId() == MENU_SLIST2)
{
i = (GetCurrentMenuId() == MENU_SLIST1) ? 0 : 1;
i = (UI_MENU_GetCurrentMenuId() == MENU_SLIST1) ? 0 : 1;
// if (gSubMenuSelection == 0xFF)
if (gSubMenuSelection < 0)
@@ -947,9 +945,9 @@ void UI_DisplayMenu(void)
}
}
if (GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_DEL_CH ||
GetCurrentMenuId() == MENU_1_CALL)
if (UI_MENU_GetCurrentMenuId() == MENU_MEM_CH ||
UI_MENU_GetCurrentMenuId() == MENU_DEL_CH ||
UI_MENU_GetCurrentMenuId() == MENU_1_CALL)
{ // display the channel name
char s[11];
BOARD_fetchChannelName(s, gSubMenuSelection);
@@ -958,18 +956,19 @@ void UI_DisplayMenu(void)
UI_PrintString(s, menu_item_x1, menu_item_x2, 2, 8);
}
if ((GetCurrentMenuId() == MENU_R_CTCS || GetCurrentMenuId() == MENU_R_DCS) && gCssScanMode != CSS_SCAN_MODE_OFF)
if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gCssBackgroundScan)
UI_PrintString("SCAN", menu_item_x1, menu_item_x2, 4, 8);
if (GetCurrentMenuId() == MENU_UPCODE)
if (UI_MENU_GetCurrentMenuId() == MENU_UPCODE)
if (strlen(gEeprom.DTMF_UP_CODE) > 8)
UI_PrintString(gEeprom.DTMF_UP_CODE + 8, menu_item_x1, menu_item_x2, 4, 8);
if (GetCurrentMenuId() == MENU_DWCODE)
if (UI_MENU_GetCurrentMenuId() == MENU_DWCODE)
if (strlen(gEeprom.DTMF_DOWN_CODE) > 8)
UI_PrintString(gEeprom.DTMF_DOWN_CODE + 8, menu_item_x1, menu_item_x2, 4, 8);
if (GetCurrentMenuId() == MENU_D_LIST && gIsDtmfContactValid)
if (UI_MENU_GetCurrentMenuId() == MENU_D_LIST && gIsDtmfContactValid)
{
Contact[11] = 0;
memmove(&gDTMF_ID, Contact + 8, 4);
@@ -977,20 +976,20 @@ void UI_DisplayMenu(void)
UI_PrintString(String, menu_item_x1, menu_item_x2, 4, 8);
}
if (GetCurrentMenuId() == MENU_R_CTCS ||
GetCurrentMenuId() == MENU_T_CTCS ||
GetCurrentMenuId() == MENU_R_DCS ||
GetCurrentMenuId() == MENU_T_DCS ||
GetCurrentMenuId() == MENU_D_LIST)
if (UI_MENU_GetCurrentMenuId() == MENU_R_CTCS ||
UI_MENU_GetCurrentMenuId() == MENU_T_CTCS ||
UI_MENU_GetCurrentMenuId() == MENU_R_DCS ||
UI_MENU_GetCurrentMenuId() == MENU_T_DCS ||
UI_MENU_GetCurrentMenuId() == MENU_D_LIST)
{
sprintf(String, "%2d", gSubMenuSelection);
UI_PrintStringSmall(String, 105, 0, 0);
}
if ((GetCurrentMenuId() == MENU_RESET ||
GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_MEM_NAME ||
GetCurrentMenuId() == MENU_DEL_CH) && gAskForConfirmation)
if ((UI_MENU_GetCurrentMenuId() == MENU_RESET ||
UI_MENU_GetCurrentMenuId() == MENU_MEM_CH ||
UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME ||
UI_MENU_GetCurrentMenuId() == MENU_DEL_CH) && gAskForConfirmation)
{ // display confirmation
strcpy(String, (gAskForConfirmation == 1) ? "SURE?" : "WAIT!");
UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8);

View File

@@ -21,6 +21,7 @@
#include <stdint.h>
#include "audio.h" // VOICE_ID_t
#include "settings.h"
typedef struct {
const char name[7]; // menu display area only has room for 6 characters
@@ -110,8 +111,6 @@ enum
MENU_500TX,
MENU_350EN,
MENU_SCREN,
MENU_TX_EN, // enable TX
#ifdef ENABLE_F_CAL_MENU
MENU_F_CALI, // reference xtal calibration
#endif
@@ -120,7 +119,8 @@ enum
MENU_F1LONG,
MENU_F2SHRT,
MENU_F2LONG,
MENU_MLONG
MENU_MLONG,
MENU_BATTYP
};
extern const uint8_t FIRST_HIDDEN_MENU_ITEM;
@@ -145,16 +145,16 @@ extern const char* gSubMenu_MDF[4];
extern const char gSubMenu_D_RSP[4][11];
extern const char* gSubMenu_PTT_ID[5];
extern const char gSubMenu_PONMSG[4][8];
extern const char* gSubMenu_ROGER[3];
extern const char gSubMenu_ROGER[3][6];
extern const char gSubMenu_RESET[2][4];
extern const char gSubMenu_F_LOCK[6][4];
extern const char* gSubMenu_F_LOCK[F_LOCK_LEN];
extern const char gSubMenu_BACKLIGHT[8][7];
extern const char gSubMenu_RX_TX[4][6];
#ifdef ENABLE_AM_FIX_TEST1
extern const char gSubMenu_AM_fix_test1[4][8];
#endif
extern const char gSubMenu_BAT_TXT[3][8];
extern const char gSubMenu_BATTYP[2][9];
extern const char gSubMenu_SCRAMBLER[11][7];
typedef struct {char* name; uint8_t id;} t_sidefunction;
@@ -164,8 +164,7 @@ extern const t_sidefunction* gSubMenu_SIDEFUNCTIONS;
extern bool gIsInSubMenu;
extern uint8_t gMenuCursor;
int GetCurrentMenuId();
extern int8_t gMenuScrollDirection;
extern int32_t gSubMenuSelection;
extern char edit_original[17];
@@ -173,5 +172,7 @@ extern char edit[17];
extern int edit_index;
void UI_DisplayMenu(void);
int UI_MENU_GetCurrentMenuId();
uint8_t UI_MENU_GetMenuIdx(uint8_t id);
#endif

View File

@@ -50,7 +50,7 @@ void UI_DisplayScanner(void)
UI_PrintString(String, 2, 0, 3, 8);
memset(String, 0, sizeof(String));
if (gScannerEditState == 2)
if (gScannerSaveState == SCAN_SAVE_CHANNEL)
{
strcpy(String, "SAVE?");
@@ -59,19 +59,15 @@ void UI_DisplayScanner(void)
}
else
{
if (gScannerEditState == 1)
{
if (gScannerSaveState == SCAN_SAVE_CHAN_SEL) {
strcpy(String, "SAVE:");
UI_GenerateChannelStringEx(String + 5, gShowChPrefix, gScanChannel);
}
else
if (gScanCssState < SCAN_CSS_STATE_FOUND)
{
else if (gScanCssState < SCAN_CSS_STATE_FOUND) {
strcpy(String, "SCAN");
memset(String + 4, '.', (gScanProgressIndicator & 7) + 1);
}
else
if (gScanCssState == SCAN_CSS_STATE_FOUND)
else if (gScanCssState == SCAN_CSS_STATE_FOUND)
strcpy(String, "SCAN CMP.");
else
strcpy(String, "SCAN FAIL.");

View File

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

View File

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

View File

@@ -16,11 +16,11 @@
#include <string.h>
#include "app/chFrScanner.h"
#include "app/dtmf.h"
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
#endif
#include "app/scanner.h"
#include "driver/keyboard.h"
#include "misc.h"
#ifdef ENABLE_AIRCOPY
@@ -86,7 +86,7 @@ void GUI_SelectNextDisplay(GUI_DisplayType_t Display)
gInputBoxIndex = 0;
gIsInSubMenu = false;
gCssScanMode = CSS_SCAN_MODE_OFF;
gCssBackgroundScan = false;
gScanStateDir = SCAN_OFF;
#ifdef ENABLE_FMRADIO
gFM_ScanState = FM_SCAN_OFF;

View File

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

View File

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