77 Commits
v0.7 ... v0.13

Author SHA1 Message Date
Krzysiek Egzmont
5c3eea2fcb Restart dual watch after VFO switched 2023-10-22 02:24:04 +02:00
Krzysiek Egzmont
ffb26a1f86 Refactoring 2023-10-22 02:23:16 +02:00
Krzysiek Egzmont
a8ae1b7739 Add menu configurable long-press function for MENU button 2023-10-22 02:11:26 +02:00
Krzysiek Egzmont
b59df11bd6 Refactoring 2023-10-21 06:12:59 +02:00
Krzysiek Egzmont
146c8dede4 Move copy channel to frequency mode from long press M to 1/BAND 2023-10-21 06:11:28 +02:00
Krzysiek Egzmont
c2090676d8 Side-key functions added: key lock, switch VFOs 2023-10-21 06:11:02 +02:00
Krzysiek Egzmont
b29bae88f1 Change SC_REV menu items names 2023-10-20 19:11:30 +02:00
Krzysiek Egzmont
c55a40481d Spectrum refactoring 2023-10-20 17:23:45 +02:00
Krzysiek Egzmont
a37a1ca6ef Fonts trimmed to save quite a bit of space 2023-10-20 16:52:15 +02:00
Krzysiek Egzmont
8629b1b867 Refactoring 2023-10-20 16:49:53 +02:00
Krzysiek Egzmont
f7c0d4149b Reduce EEPROM wear, don't check if changed before write. 2023-10-20 12:01:06 +02:00
Krzysiek Egzmont
87fd5c19d0 README.md updated 2023-10-20 01:35:11 +02:00
Krzysiek Egzmont
d132969c91 Support for >1GHz frequencies input 2023-10-20 00:15:11 +02:00
Krzysiek Egzmont
a5fa0b1e4b Refactoring, cleanup, comments 2023-10-19 21:42:56 +02:00
Krzysiek Egzmont
a21c8a62ac Small changes 2023-10-19 21:29:54 +02:00
Krzysiek Egzmont
9fd3701f46 Don't activate RX VFO when crossband is active 2023-10-19 17:00:22 +02:00
Krzysiek Egzmont
1d95737088 Refactoring, cleanup, comments 2023-10-19 16:58:12 +02:00
Krzysiek Egzmont
2f7042056a Display frequencies >=1GHz 2023-10-19 02:35:34 +02:00
Krzysiek Egzmont
13b41abce6 REFACTORING: Fixed correct BK4819 GPIO pin names 2023-10-18 17:27:18 +02:00
Krzysiek Egzmont
b9f9566158 Additional fix for RSSI calibration 2023-10-18 17:02:49 +02:00
Krzysiek Egzmont
710a417e12 FIX #31: Disable ENABLE_CTCSS_TAIL_PHASE_SHIFT that causes STE not to work 2023-10-18 00:29:20 +02:00
Krzysiek Egzmont
f11d0fbcda Code refactoring 2023-10-17 21:47:39 +02:00
Krzysiek Egzmont
96144af9e9 Added function buttons configuration to menu 2023-10-17 20:16:56 +02:00
Krzysiek Egzmont
4dd2445833 Menu items reordered 2023-10-17 13:34:18 +02:00
Krzysiek Egzmont
6172d942be Fix scanning on opposite VFO, ignore scan result on EXIT button, changed status bar while scanning 2023-10-17 02:57:55 +02:00
Krzysiek Egzmont
0c0cbb232c Refactoring 2023-10-17 02:26:20 +02:00
Krzysiek Egzmont
298ff29cf4 Fix restore VFO settings after scan 2023-10-16 22:59:17 +02:00
Krzysiek Egzmont
f70707e17f Fix copy channel to VFO function copying wrong VFO, clean VFO setup 2023-10-16 18:39:20 +02:00
Krzysiek Egzmont
f1fc04591c Fix compiler errors 2023-10-16 17:17:17 +02:00
Krzysiek Egzmont
a26c397417 Remove fall-through pragmas 2023-10-16 16:52:32 +02:00
Krzysiek Egzmont
d3a2a7bee9 Menu id fix 2023-10-16 16:02:39 +02:00
Krzysiek Egzmont
d817ff7e6a Fixed RSSI calibration 2023-10-16 13:01:24 +02:00
Krzysiek Egzmont
ec4bec5b1f Flashlight SOS function 2023-10-16 00:15:04 +02:00
Krzysiek Egzmont
d7c458839c Change menu items names 2023-10-15 22:07:55 +02:00
Krzysiek Egzmont
cff2f25e56 Consolidate "T VFO" and "DUALRX" into one "RXMODE" 2023-10-15 21:52:42 +02:00
Krzysiek Egzmont
63ac84883e add execute rights to compile-with-docker.sh 2023-10-15 21:12:06 +02:00
wrobepio
f8252df281 fixed: "compiled-firmware" folder missing under linux - fixed shell variable $PWD 2023-10-14 20:26:29 +02:00
Krzysiek Egzmont
be00bb99ad FIX #28: After entering item 51(BATVOL) of the menu, the automatic lock screen cannot be unlocked 2023-10-12 20:45:26 +02:00
Krzysiek Egzmont
7e6a78ab6c FIX #26: vfo state (TX DISABLE label) update issue when FM radio disabled in Makefile 2023-10-12 00:44:52 +02:00
Krzysiek Egzmont
06c2ddf543 BUG FIX: power save never activated 2023-10-10 19:36:12 +02:00
Krzysiek Egzmont
47f1e80252 Fix #25: When you stop the scan with the PTT the Walkie stays in permanent TX 2023-10-10 17:32:58 +02:00
Krzysiek Egzmont
64bc29d362 FIX #24: lock/unlock doesn't work when FM radio active 2023-10-10 14:29:51 +02:00
Krzysiek Egzmont
8d17f5922c FIX #21: Battery symbol fix of a fix 2023-10-10 02:39:02 +02:00
Krzysiek Egzmont
063dc61e65 Part of the recent changes form 1o11, including DTMF input box error #19 2023-10-09 21:47:06 +02:00
Krzysiek Egzmont
60ccd3372f FIX #8: This should fix compiler errors 2023-10-09 17:17:45 +02:00
Krzysiek Egzmont
149a0f5bdc Revert do not update battery level when TX 2023-10-09 16:57:52 +02:00
Krzysiek Egzmont
c7da7cf725 Battery symbol fix 2023-10-09 16:30:20 +02:00
Krzysiek Egzmont
4b9147327a Fix random upper/lower for TX, bring back TX on last RX 2023-10-09 16:02:57 +02:00
Krzysiek Egzmont
43f4790f5b BUG FIX #15: shifted numbers in spectrum freq input box 2023-10-06 19:57:08 +02:00
Krzysiek Egzmont
43ccce33da README: new build instructions 2023-10-06 12:15:01 +02:00
Krzysiek Egzmont
b2839de2a5 Merge remote-tracking branch 'remotes/OneOfEleven/main' 2023-10-06 11:28:19 +02:00
OneOfEleven
5397b3ee88 Fixed key number offset bug added yesterday 2023-10-06 07:48:45 +01:00
OneOfEleven
9a0a75446a README.md 2023-10-06 00:19:21 +01:00
OneOfEleven
f25e0230f0 Added power-on compile option 2023-10-06 00:18:47 +01:00
OneOfEleven
16c908f0bf Channel/Frequency scanning updates 2023-10-05 23:58:55 +01:00
OneOfEleven
9c7d6a38e5 Remember scan ALL channels option across power cycles 2023-10-05 22:59:26 +01:00
OneOfEleven
ec5e9dde66 Squelch tuning 2023-10-05 22:44:44 +01:00
OneOfEleven
5c346c8466 Fic typing in keys bug 2023-10-05 17:38:25 +01:00
OneOfEleven
40d09591b3 Fixed silly error I made 2023-10-05 16:28:20 +01:00
OneOfEleven
bd9f337a5b Make all warnings vanish over to bricky's house ! 2023-10-05 15:26:08 +01:00
OneOfEleven
cb05a5881f Try again to calm the type warnings 2023-10-05 14:40:34 +01:00
OneOfEleven
6b44659419 Mzybe clear up some signed/unsigned compile warnings 2023-10-05 14:33:05 +01:00
Krzysiek Egzmont
81f18aa281 build errors fix 2023-10-05 15:10:12 +02:00
Krzysiek Egzmont
410c0e47cb Merge remote-tracking branch 'remotes/OneOfEleven/main' 2023-10-05 15:05:54 +02:00
OneOfEleven
2372949eb9 RX bandwidth and squelch update 2023-10-05 13:42:14 +01:00
OneOfEleven
0cf4e1fe36 Merge pull request #123 from bricky149/clang-build
Add support for clang builds
2023-10-05 12:44:47 +01:00
OneOfEleven
9b2ce88a72 RX fixed bandwidth adjustments + squelch sensitivity adjustments 2023-10-05 12:42:40 +01:00
bricky149
a23f359735 Add support for clang builds 2023-10-05 12:22:09 +01:00
OneOfEleven
b343993a72 Don't use fast scan option - for now 2023-10-05 10:19:50 +01:00
OneOfEleven
4d8db8f0b9 Updated 5/7 function key operation (see README.md) 2023-10-05 10:03:07 +01:00
OneOfEleven
609df5f279 Ignore all long-press/function keys whilst in menu 2023-10-05 09:17:38 +01:00
OneOfEleven
e042b21e65 Rename RX_CHANNEL and TX_CHANNEL to RX_VFO and TX_VFO to be much less confusing 2023-10-05 01:07:04 +01:00
OneOfEleven
d632698428 Clean up copy-chan-to-vfo 2023-10-05 00:26:37 +01:00
OneOfEleven
eba4bf9c80 Fix copy-chan-to-vfo 2023-10-05 00:07:35 +01:00
OneOfEleven
56fc929921 Let copy-chan-to-vfo work when dual-watch enabled 2023-10-05 00:01:13 +01:00
Krzysiek Egzmont
2cff29e6db Merge remote-tracking branch 'remotes/OneOfEleven/main' 2023-10-05 00:11:29 +02:00
OneOfEleven
a6324ffcf8 Fix for when channel scan has no scanlisted channels to scan 2023-10-04 23:09:55 +01:00
76 changed files with 3720 additions and 3396 deletions

View File

@@ -3,6 +3,7 @@
# 0 = disable
# 1 = enable
#
ENABLE_CLANG := 0
ENABLE_SWD := 0
ENABLE_OVERLAY := 0
ENABLE_LTO := 1
@@ -13,35 +14,40 @@ ENABLE_NOAA := 0
ENABLE_VOICE := 0
ENABLE_VOX := 1
ENABLE_ALARM := 0
ENABLE_TX1750 := 1
ENABLE_TX1750 := 0
ENABLE_PWRON_PASSWORD := 0
ENABLE_BIG_FREQ := 1
ENABLE_SMALL_BOLD := 1
ENABLE_KEEP_MEM_NAME := 1
ENABLE_WIDE_RX := 1
ENABLE_TX_WHEN_AM := 0
ENABLE_F_CAL_MENU := 0
ENABLE_CTCSS_TAIL_PHASE_SHIFT := 1
ENABLE_MAIN_KEY_HOLD := 1
ENABLE_CTCSS_TAIL_PHASE_SHIFT := 0
ENABLE_BOOT_BEEPS := 0
ENABLE_SHOW_CHARGE_LEVEL := 1
ENABLE_REVERSE_BAT_SYMBOL := 1
ENABLE_REVERSE_BAT_SYMBOL := 0
ENABLE_CODE_SCAN_TIMEOUT := 0
ENABLE_AM_FIX := 1
ENABLE_AM_FIX_SHOW_DATA := 0
ENABLE_SQUELCH_LOWER := 0
ENABLE_SQUELCH_MORE_SENSITIVE := 1
ENABLE_FASTER_CHANNEL_SCAN := 1
ENABLE_RSSI_BAR := 1
ENABLE_AUDIO_BAR := 1
ENABLE_COPY_CHAN_TO_VFO := 1
#ENABLE_SINGLE_VFO_CHAN := 1
ENABLE_SPECTRUM := 1
#ENABLE_SINGLE_VFO_CHAN := 1
#ENABLE_BAND_SCOPE := 1
#############################################################
TARGET = firmware
ifeq ($(ENABLE_LTO), 1)
ifeq ($(ENABLE_CLANG),1)
# GCC's linker, ld, doesn't understand LLVM's generated bytecode
ENABLE_LTO := 0
endif
ifeq ($(ENABLE_LTO),1)
# can't have LTO and OVERLAY enabled at same time
ENABLE_OVERLAY := 0
endif
@@ -98,6 +104,7 @@ 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)
@@ -132,7 +139,9 @@ ifeq ($(ENABLE_FMRADIO),1)
endif
OBJS += ui/helper.o
OBJS += ui/inputbox.o
OBJS += ui/lock.o
ifeq ($(ENABLE_PWRON_PASSWORD),1)
OBJS += ui/lock.o
endif
OBJS += ui/main.o
OBJS += ui/menu.o
OBJS += ui/scanner.o
@@ -149,8 +158,21 @@ else
endif
AS = arm-none-eabi-gcc
CC = arm-none-eabi-gcc
CC =
LD = arm-none-eabi-gcc
ifeq ($(ENABLE_CLANG),0)
CC += arm-none-eabi-gcc
# Use GCC's linker to avoid undefined symbol errors
# LD += arm-none-eabi-gcc
else
# May need to adjust this to match your system
CC += clang --sysroot=/usr/arm-none-eabi --target=arm-none-eabi
# Bloats binaries to 512MB
# LD = ld.lld
endif
OBJCOPY = arm-none-eabi-objcopy
SIZE = arm-none-eabi-size
@@ -166,22 +188,30 @@ ifeq ($(ENABLE_OVERLAY),1)
ASFLAGS += -DENABLE_OVERLAY
endif
CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD
#CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c99 -MMD
#CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu99 -MMD
#CFLAGS = -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu11 -MMD
CFLAGS =
ifeq ($(ENABLE_CLANG),0)
CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD
#CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c99 -MMD
#CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu99 -MMD
#CFLAGS += -Os -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=gnu11 -MMD
else
# Oz needed to make it fit on flash
CFLAGS += -Oz -Wall -Werror -mcpu=cortex-m0 -fno-builtin -fshort-enums -fno-delete-null-pointer-checks -std=c11 -MMD
endif
ifeq ($(ENABLE_LTO), 1)
# CFLAGS += -flto
ifeq ($(ENABLE_LTO),1)
CFLAGS += -flto=2
else
# We get most of the space savings if LTO creates problems
# We get most of the space savings if LTO creates problems
CFLAGS += -ffunction-sections -fdata-sections
endif
# May cause unhelpful build failures
#CFLAGS += -Wpadded
# catch any and all warnings
CFLAGS += -Wextra
CFLAGS += -DPRINTF_INCLUDE_CONFIG_H
CFLAGS += -DGIT_HASH=\"$(GIT_HASH)\"
@@ -224,6 +254,9 @@ endif
ifeq ($(ENABLE_TX1750),1)
CFLAGS += -DENABLE_TX1750
endif
ifeq ($(ENABLE_PWRON_PASSWORD),1)
CFLAGS += -DENABLE_PWRON_PASSWORD
endif
ifeq ($(ENABLE_KEEP_MEM_NAME),1)
CFLAGS += -DENABLE_KEEP_MEM_NAME
endif
@@ -239,9 +272,6 @@ endif
ifeq ($(ENABLE_CTCSS_TAIL_PHASE_SHIFT),1)
CFLAGS += -DENABLE_CTCSS_TAIL_PHASE_SHIFT
endif
ifeq ($(ENABLE_MAIN_KEY_HOLD),1)
CFLAGS += -DENABLE_MAIN_KEY_HOLD
endif
ifeq ($(ENABLE_BOOT_BEEPS),1)
CFLAGS += -DENABLE_BOOT_BEEPS
endif
@@ -288,19 +318,25 @@ ifeq ($(ENABLE_BAND_SCOPE),1)
CFLAGS += -DENABLE_BAND_SCOPE
endif
LDFLAGS = -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld
LDFLAGS =
ifeq ($(ENABLE_CLANG),0)
LDFLAGS += -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld
else
# Fix warning about implied executable stack
LDFLAGS += -z noexecstack -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld
endif
# Use newlib-nano instead of newlib
LDFLAGS += --specs=nano.specs
ifeq ($(ENABLE_LTO), 0)
# Throw away unneeded func/data sections like LTO does
ifeq ($(ENABLE_LTO),0)
# Throw away unneeded func/data sections like LTO does
LDFLAGS += -Wl,--gc-sections
endif
ifeq ($(DEBUG),1)
ASFLAGS += -g
CFLAGS += -g
CFLAGS += -g
LDFLAGS += -g
endif

View File

@@ -1,8 +1,9 @@
# Main features:
- OneOfEleven mods, including AM fix
- many of OneOfEleven mods, including AM fix
- fagci spectrum analyzer (**F+5** to turn on)
- better battery percentage calculation (based on real measurement, battery calibration recommended)
- battery calibration option available available in the menu (instructions below)
- some other smaller mods introduced by me
Go to [Wiki](https://github.com/egzumer/uv-k5-firmware-custom/wiki) to learn more.
<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 />
@@ -33,26 +34,31 @@ Anyway, have fun.
# Radio performance
Please note that the Quansheng uv-k radios are not professional quality transceivers, their
performance is strictly limited, somewhat below that of a decent transceiver. The RX front
end has no track-tuned band pass filtering at all, and so are wide band/wide open to any
and all signals over a wide frequency range.
Using the radio in high intensity RF environments will nearly always destroy your reception,
the receiver simply doesn't have a great dynamic range, which means distorted AM audio with
strong received signals, there is nothing more anyone can do in firmware/software to stop that
happening once the RX gain adjustment I do (AM fix) reaches the hardwares limit.
Please note that the Quansheng UV-Kx radios are not professional quality transceivers, their
performance is strictly limited. The RX front end has no track-tuned band pass filtering
at all, and so are wide band/wide open to any and all signals over a large frequency range.
Saying that, they are nice toys for the price, fun to play with.
Using the radio in high intensity RF environments will most likely make reception anything but
easy (AM mode will suffer far more than FM ever will), the receiver simply doesn't have a
great dynamic range, which results in distorted AM audio with stronger RX'ed signals.
There is nothing more anyone can do in firmware/software to improve that, once the RX gain
adjustment I do (AM fix) reaches the hardwares limit, your AM RX audio will be all but
non-existant (just like Quansheng's firmware).
On the other hand, FM RX audio will/should be fine.
But, they are nice toys for the price, fun to play with.
# User customization
You can customize the firmware by enabling/disabling various compile options.
You can customize the firmware by enabling/disabling various compile options, this allows
us to remove certain firmware features in order to make room in the flash for others.
You'll find the options at the top of "Makefile" ('0' = disable, '1' = enable) ..
```
ENABLE_CLANG := 0 **experimental, builds with clang instead of gcc (LTO will be disabled if you enable this)
ENABLE_SWD := 0 only needed if using CPU's SWD port (debugging/programming)
ENABLE_OVERLAY := 0 cpu FLASH stuff, not needed
ENABLE_LTO := 0 **experimental, reduces size of compiled firmware but might break EEPROM reads (overlay will be disabled if you enable this)
ENABLE_LTO := 0 **experimental, reduces size of compiled firmware but might break EEPROM reads (OVERLAY will be disabled if you enable this)
ENABLE_UART := 1 without this you can't configure radio via PC !
ENABLE_AIRCOPY := 0 easier to just enter frequency with butts
ENABLE_FMRADIO := 0 WBFM VHF broadcast band receiver
@@ -61,6 +67,7 @@ ENABLE_VOICE := 0 want to hear voices ?
ENABLE_VOX := 0
ENABLE_ALARM := 0 TX alarms
ENABLE_1750HZ := 0 side key 1750Hz TX tone (older style repeater access)
ENABLE_PWRON_PASSWORD := 1 power-on password stuff
ENABLE_BIG_FREQ := 0 big font frequencies (like original QS firmware)
ENABLE_SMALL_BOLD := 1 bold channel name/no. (when name + freq channel display mode)
ENABLE_KEEP_MEM_NAME := 1 maintain channel name when (re)saving memory channel
@@ -68,7 +75,6 @@ ENABLE_WIDE_RX := 1 full 18MHz to 1300MHz RX (though front-
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_CTCSS_TAIL_PHASE_SHIFT := 1 standard CTCSS tail phase shift rather than QS's own 55Hz tone method
ENABLE_MAIN_KEY_HOLD := 1 initial F-key press not needed, instead just hold down keys 0-9 to access the secondary butt functions
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)
@@ -86,9 +92,13 @@ ENABLE_COPY_CHAN_TO_VFO := 1 copy current channel into the other VFO
# New/modified function keys
* Long-press 'M' = Copy selected channel into the same VFO, then switches to frequency mode
* Long-press '5' = Toggle a selected channels scanlist setting .. if NOAA is disable in Makefile
* Long-press '*' = Toggles the scanlist number 1, 2 or ALL channels .. if in channel scan mode
* 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
@@ -109,28 +119,38 @@ arm-none-eabi GCC version 10.3.1 is recommended, which is the current version on
Other versions may generate a flash file that is too big.
You can get an appropriate version from: https://developer.arm.com/downloads/-/gnu-rm
clang may be used but isn't fully supported. Resulting binaries may also be bigger.
You can get it from: https://releases.llvm.org/download.html
# Building
To build the firmware, you need to fetch the submodules and then run make:
```
git submodule update --init --recursive --depth=1
make
```
If you have docker installed you can use `compile-with-docker.bat`, the output files are created in `compiled-firmware` folder. This method gives significantly smaller binaries, I've seen differences up to 1kb, so it can fit more functionalities this way. The challange can be (or not) installing the docker itself.
To compile directly in windows without the need of a linux virtual machine:
```
1. Download and install "gcc-arm-none-eabi-10.3-2021.10-win32.exe" from https://developer.arm.com/downloads/-/gnu-rm
2. Download and install "gnu_make-3.81.exe" from https://gnuwin32.sourceforge.net/packages/make.htm
To compile directly in windows:
3. You may (or not) need to manualy add gcc path to you OS environment PATH.
ie add C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin
4. You may (or not) need to reboot your PC after installing the above
```
Then you can run 'win_make.bat' from the directory you saved this source code too.
You may need to edit the bat file (path to make.exe) depending on where you installed the above two packages too.
1. Open windows command line and run:
```
winget install -e -h git.git Python.Python.3.8 GnuWin32.Make
winget install -e -h Arm.GnuArmEmbeddedToolchain -v "10 2021.10"
```
2. Close command line, open a new one and run:
```
pip install --user --upgrade pip
pip install crcmod
mkdir c:\projects & cd /D c:/projects
git clone https://github.com/egzumer/uv-k5-firmware-custom.git
```
3. From now on you can build the firmware by going to `c:\projects\uv-k5-firmware-custom` and running `win_make.bat` or by running a command line:
```
cd /D c:\projects\uv-k5-firmware-custom
win_make.bat
```
4. To reset the repository and pull new changes run (!!! it will delete all your changes !!!):
```
cd /D c:\projects\uv-k5-firmware-custom
git reset --hard & git clean -fd & git pull
```
I've left some notes in the win_make.bat file to maybe help with stuff.
@@ -138,6 +158,7 @@ I've left some notes in the win_make.bat file to maybe help with stuff.
Many thanks to various people on Telegram for putting up with me during this effort and helping:
* [OneOfEleven](https://github.com/OneOfEleven)
* [DualTachyon](https://github.com/DualTachyon)
* [Mikhail](https://github.com/fagci)
* [Andrej](https://github.com/Tunas1337)
@@ -171,13 +192,13 @@ You may obtain a copy of the License at
# Example changes/updates
<p float="left">
<img src="/image1.png" width=300 />
<img src="/image2.png" width=300 />
<img src="/image3.png" width=300 />
<img src="/images/image1.png" width=300 />
<img src="/images/image2.png" width=300 />
<img src="/images/image3.png" width=300 />
</p>
Video showing the AM fix working ..
<video src="/AM_fix.mp4"></video>
<video src="/images/AM_fix.mp4"></video>
<video src="https://github.com/OneOfEleven/uv-k5-firmware-custom/assets/51590168/2a3a9cdc-97da-4966-bf0d-1ce6ad09779c"></video>

View File

@@ -475,7 +475,7 @@
void AM_fix_print_data(const int vfo, char *s)
{
if (s != NULL && vfo >= 0 && vfo < ARRAY_SIZE(gain_table_index))
if (s != NULL && vfo >= 0 && vfo < (int)ARRAY_SIZE(gain_table_index))
{
const unsigned int index = gain_table_index[vfo];
// sprintf(s, "%2u.%u %4ddB %3u", index, ARRAY_SIZE(gain_table) - 1, gain_table[index].gain_dB, prev_rssi[vfo]);

View File

@@ -18,6 +18,7 @@
#include "app/action.h"
#include "app/app.h"
#include "app/common.h"
#include "app/dtmf.h"
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
@@ -45,6 +46,7 @@ static void ACTION_FlashLight(void)
GPIO_SetBit(&GPIOC->DATA, GPIOC_PIN_FLASHLIGHT);
break;
case 1:
case 2:
gFlashLightState++;
break;
default:
@@ -84,11 +86,11 @@ void ACTION_Monitor(void)
gMonitor = false;
if (gScanState != SCAN_OFF)
if (gScanStateDir != SCAN_OFF)
{
ScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms;
gScheduleScanListen = false;
gScanPauseMode = true;
gScanPauseDelayIn_10ms = scan_pause_delay_in_1_10ms;
gScheduleScanListen = false;
gScanPauseMode = true;
}
#ifdef ENABLE_NOAA
@@ -182,23 +184,36 @@ void ACTION_Scan(bool bRestart)
{
GUI_SelectNextDisplay(DISPLAY_MAIN);
if (gScanState != SCAN_OFF)
{
#if 1
if (gScanStateDir != SCAN_OFF)
{ // already scanning
if (gNextMrChannel <= MR_CHANNEL_LAST)
{ // 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_NextChannel(false, gScanStateDir);
gScanPauseDelayIn_10ms = 1;
gScheduleScanListen = false;
gUpdateStatus = true;
#else
}
else
{ // stop scanning
SCANNER_Stop();
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
#endif
}
}
else
{
CHANNEL_Next(true, 1);
{ // start scanning
SCANNER_NextChannel(true, SCAN_FWD);
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_SCANNING_BEGIN);
@@ -206,7 +221,7 @@ void ACTION_Scan(bool bRestart)
#endif
// clear the other vfo's rssi level (to hide the antenna symbol)
gVFO_RSSI_bar_level[(gEeprom.RX_CHANNEL + 1) & 1u] = 0;
gVFO_RSSI_bar_level[(gEeprom.RX_VFO + 1) & 1u] = 0;
// let the user see DW is not active
gDualWatchActive = false;
@@ -215,9 +230,16 @@ void ACTION_Scan(bool bRestart)
}
}
else
if (!bRestart)
{ // keep scanning but toggle between scan lists
// if (!bRestart)
if (!bRestart && gNextMrChannel <= MR_CHANNEL_LAST)
{ // 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_NextChannel(false, gScanStateDir);
gScanPauseDelayIn_10ms = 1;
gScheduleScanListen = false;
gUpdateStatus = true;
}
else
@@ -305,18 +327,16 @@ void ACTION_Scan(bool bRestart)
void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
uint8_t Short = ACTION_OPT_NONE;
uint8_t Long = ACTION_OPT_NONE;
if (gScreenToDisplay == DISPLAY_MAIN && gDTMF_InputMode)
if (gScreenToDisplay == DISPLAY_MAIN && gDTMF_InputMode) // entering DTMF code
{
if (Key == KEY_SIDE1 && !bKeyHeld && bKeyPressed)
if (Key == KEY_SIDE1 && !bKeyHeld && bKeyPressed) // side1 btn pressed
{
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (gDTMF_InputIndex > 0)
if (gDTMF_InputBox_Index > 0) // DTMF codes are in the input box
{
gDTMF_InputBox[--gDTMF_InputIndex] = '-';
if (gDTMF_InputIndex > 0)
gDTMF_InputBox[--gDTMF_InputBox_Index] = '-'; // delete one code
if (gDTMF_InputBox_Index > 0)
{
gPttWasReleased = true;
gRequestDisplayScreen = DISPLAY_MAIN;
@@ -329,43 +349,52 @@ void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
#endif
gRequestDisplayScreen = DISPLAY_MAIN;
gDTMF_InputMode = false;
gDTMF_InputMode = false; // turn off DTMF input box if no codes left
}
gPttWasReleased = true;
return;
}
if (Key == KEY_SIDE1)
{
Short = gEeprom.KEY_1_SHORT_PRESS_ACTION;
Long = gEeprom.KEY_1_LONG_PRESS_ACTION;
}
else
if (Key == KEY_SIDE2)
{
Short = gEeprom.KEY_2_SHORT_PRESS_ACTION;
Long = gEeprom.KEY_2_LONG_PRESS_ACTION;
uint8_t funcShort = ACTION_OPT_NONE;
uint8_t funcLong = ACTION_OPT_NONE;
switch(Key) {
case KEY_SIDE1:
funcShort = gEeprom.KEY_1_SHORT_PRESS_ACTION;
funcLong = gEeprom.KEY_1_LONG_PRESS_ACTION;
break;
case KEY_SIDE2:
funcShort = gEeprom.KEY_2_SHORT_PRESS_ACTION;
funcLong = gEeprom.KEY_2_LONG_PRESS_ACTION;
break;
case KEY_MENU:
funcLong = gEeprom.KEY_M_LONG_PRESS_ACTION;
break;
default:
break;
}
if (!bKeyHeld && bKeyPressed)
if (!bKeyHeld && bKeyPressed) // button pushed
{
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
return;
}
if (bKeyHeld || bKeyPressed)
// held or released beyond this point
if(!(bKeyHeld && !bKeyPressed)) // don't beep on released after hold
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (bKeyHeld || bKeyPressed) // held
{
if (!bKeyHeld)
return;
funcShort = funcLong;
Short = Long;
if (!bKeyPressed)
if (!bKeyPressed) //ignore release if held
return;
}
switch (Short)
// held or released after short press beyond this point
switch (funcShort)
{
default:
case ACTION_OPT_NONE:
@@ -383,24 +412,30 @@ void ACTION_Handle(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
ACTION_Scan(true);
break;
case ACTION_OPT_VOX:
#ifdef ENABLE_VOX
ACTION_Vox();
#endif
#ifdef ENABLE_VOX
ACTION_Vox();
#endif
break;
case ACTION_OPT_ALARM:
#ifdef ENABLE_ALARM
ACTION_AlarmOr1750(false);
#endif
#ifdef ENABLE_ALARM
ACTION_AlarmOr1750(false);
#endif
break;
#ifdef ENABLE_FMRADIO
case ACTION_OPT_FM:
ACTION_FM();
break;
#endif
#ifdef ENABLE_FMRADIO
case ACTION_OPT_FM:
ACTION_FM();
break;
#endif
case ACTION_OPT_1750:
#ifdef ENABLE_TX1750
ACTION_AlarmOr1750(true);
#endif
break;
case ACTION_OPT_KEYLOCK:
COMMON_KeypadLockToggle();
break;
case ACTION_OPT_A_B:
COMMON_SwitchVFOs();
break;
}
}

View File

@@ -22,7 +22,7 @@
//static void ACTION_FlashLight(void)
void ACTION_Power(void);
void ACTION_Monitor(void);
void ACTION_Scan(bool bFlag);
void ACTION_Scan(bool bRestart);
#ifdef ENABLE_VOX
void ACTION_Vox(void);
#endif

View File

@@ -57,7 +57,7 @@ void AIRCOPY_SendMessage(void)
BK4819_SendFSKData(g_FSK_Buffer);
BK4819_SetupPowerAmplifier(0, 0);
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1, false);
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29, false);
gAircopySendCountdown = 30;
}
@@ -131,8 +131,7 @@ static void AIRCOPY_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
gInputBoxIndex = 0;
NUMBER_Get(gInputBox, &Frequency);
Frequency = StrToUL(INPUTBOX_GetAscii()) * 100;
for (i = 0; i < ARRAY_SIZE(frequencyBandTable); i++)
{

994
app/app.c

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@ extern const uint8_t orig_mixer;
extern const uint8_t orig_pga;
void APP_EndTransmission(void);
void CHANNEL_Next(bool bFlag, int8_t Direction);
void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix);
uint32_t APP_SetFrequencyByStep(VFO_Info_t *pInfo, int8_t Step);
void APP_Update(void);

37
app/common.c Normal file
View File

@@ -0,0 +1,37 @@
#include "functions.h"
#include "misc.h"
#include "settings.h"
#include "ui/ui.h"
void COMMON_KeypadLockToggle()
{
if (gScreenToDisplay != DISPLAY_MENU &&
gCurrentFunction != FUNCTION_TRANSMIT)
{ // toggle the keyboad lock
#ifdef ENABLE_VOICE
gAnotherVoiceID = gEeprom.KEY_LOCK ? VOICE_ID_UNLOCK : VOICE_ID_LOCK;
#endif
gEeprom.KEY_LOCK = !gEeprom.KEY_LOCK;
gRequestSaveSettings = true;
}
}
void COMMON_SwitchVFOs()
{
gEeprom.TX_VFO ^= 1;
if (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF)
gEeprom.CROSS_BAND_RX_TX = gEeprom.TX_VFO + 1;
if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
gEeprom.DUAL_WATCH = gEeprom.TX_VFO + 1;
gRequestSaveSettings = 1;
gFlagReconfigureVfos = true;
gScheduleDualWatch = true;
gRequestDisplayScreen = DISPLAY_MAIN;
}

12
app/common.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef APP_COMMON_H
#define APP_COMMON_H
#include "functions.h"
#include "settings.h"
#include "ui/ui.h"
void COMMON_KeypadLockToggle();
void COMMON_SwitchVFOs();
#endif

View File

@@ -36,9 +36,9 @@
char gDTMF_String[15];
char gDTMF_InputBox[15];
uint8_t gDTMF_InputIndex = 0;
bool gDTMF_InputMode = false;
uint8_t gDTMF_PreviousIndex = 0;
uint8_t gDTMF_InputBox_Index = 0;
bool gDTMF_InputMode = false;
uint8_t gDTMF_PreviousIndex = 0;
char gDTMF_RX[17];
uint8_t gDTMF_RX_index = 0;
@@ -133,8 +133,26 @@ bool DTMF_FindContact(const char *pContact, char *pResult)
char DTMF_GetCharacter(const unsigned int code)
{
const char list[] = "0123456789ABCD*#";
return (code < ARRAY_SIZE(list)) ? list[code] : 0xFF;
switch (code)
{
case KEY_0: return '0';
case KEY_1: return '1';
case KEY_2: return '2';
case KEY_3: return '3';
case KEY_4: return '4';
case KEY_5: return '5';
case KEY_6: return '6';
case KEY_7: return '7';
case KEY_8: return '8';
case KEY_9: return '9';
case KEY_MENU: return 'A';
case KEY_UP: return 'B';
case KEY_DOWN: return 'C';
case KEY_EXIT: return 'D';
case KEY_STAR: return '*';
case KEY_F: return '#';
default: return 0xff;
}
}
bool DTMF_CompareMessage(const char *pMsg, const char *pTemplate, const unsigned int size, const bool bCheckGroup)
@@ -163,16 +181,23 @@ DTMF_CallMode_t DTMF_CheckGroupCall(const char *pMsg, const unsigned int size)
return (i < size) ? DTMF_CALL_MODE_GROUP : DTMF_CALL_MODE_NOT_GROUP;
}
void DTMF_clear_input_box(void)
{
memset(gDTMF_InputBox, 0, sizeof(gDTMF_InputBox));
gDTMF_InputBox_Index = 0;
gDTMF_InputMode = false;
}
void DTMF_Append(const char code)
{
if (gDTMF_InputIndex == 0)
if (gDTMF_InputBox_Index == 0)
{
memset(gDTMF_InputBox, '-', sizeof(gDTMF_InputBox));
memset(gDTMF_InputBox, '-', sizeof(gDTMF_InputBox) - 1);
gDTMF_InputBox[sizeof(gDTMF_InputBox) - 1] = 0;
}
if (gDTMF_InputIndex < sizeof(gDTMF_InputBox))
gDTMF_InputBox[gDTMF_InputIndex++] = code;
if (gDTMF_InputBox_Index < (sizeof(gDTMF_InputBox) - 1))
gDTMF_InputBox[gDTMF_InputBox_Index++] = code;
}
void DTMF_HandleRequest(void)
@@ -184,7 +209,7 @@ void DTMF_HandleRequest(void)
if (!gDTMF_RX_pending)
return; // nothing new received
if (gScanState != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF)
if (gScanStateDir != SCAN_OFF || gCssScanMode != CSS_SCAN_MODE_OFF)
{ // we're busy scanning
DTMF_clear_RX();
return;
@@ -335,6 +360,7 @@ void DTMF_HandleRequest(void)
{
case DTMF_DEC_RESPONSE_BOTH:
gDTMF_DecodeRingCountdown_500ms = DTMF_decode_ring_countdown_500ms;
[[fallthrough]];
case DTMF_DEC_RESPONSE_REPLY:
gDTMF_ReplyState = DTMF_REPLY_AAAAA;
break;
@@ -385,8 +411,9 @@ void DTMF_Reply(void)
default:
case DTMF_REPLY_NONE:
if (gDTMF_CallState != DTMF_CALL_STATE_NONE ||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_OFF ||
if (gDTMF_CallState != DTMF_CALL_STATE_NONE ||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO ||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_OFF ||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN)
{
gDTMF_ReplyState = DTMF_REPLY_NONE;

View File

@@ -33,7 +33,8 @@ typedef enum DTMF_State_t DTMF_State_t;
enum DTMF_CallState_t {
DTMF_CALL_STATE_NONE = 0,
DTMF_CALL_STATE_CALL_OUT,
DTMF_CALL_STATE_RECEIVED
DTMF_CALL_STATE_RECEIVED,
DTMF_CALL_STATE_RECEIVED_STAY
};
enum DTMF_DecodeResponse_t {
@@ -60,12 +61,17 @@ enum DTMF_CallMode_t {
DTMF_CALL_MODE_DTMF
};
enum { // seconds
DTMF_HOLD_MIN = 5,
DTMF_HOLD_MAX = 60
};
typedef enum DTMF_CallMode_t DTMF_CallMode_t;
extern char gDTMF_String[15];
extern char gDTMF_InputBox[15];
extern uint8_t gDTMF_InputIndex;
extern uint8_t gDTMF_InputBox_Index;
extern bool gDTMF_InputMode;
extern uint8_t gDTMF_PreviousIndex;
@@ -98,6 +104,7 @@ bool DTMF_FindContact(const char *pContact, char *pResult);
char DTMF_GetCharacter(const unsigned int code);
bool DTMF_CompareMessage(const char *pDTMF, const char *pTemplate, const unsigned int size, const bool bFlag);
DTMF_CallMode_t DTMF_CheckGroupCall(const char *pDTMF, const unsigned int size);
void DTMF_clear_input_box(void);
void DTMF_Append(const char vode);
void DTMF_HandleRequest(void);
void DTMF_Reply(void);

View File

@@ -45,7 +45,6 @@ bool gFM_AutoScan;
uint8_t gFM_ChannelPosition;
bool gFM_FoundFrequency;
bool gFM_AutoScan;
uint8_t gFM_ResumeCountdown_500ms;
uint16_t gFM_RestoreCountdown_10ms;
bool FM_CheckValidChannel(uint8_t Channel)
@@ -278,8 +277,7 @@ static void FM_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
uint32_t Frequency;
gInputBoxIndex = 0;
NUMBER_Get(gInputBox, &Frequency);
Frequency /= 10000;
Frequency = StrToUL(INPUTBOX_GetAscii());
if (Frequency < gEeprom.FM_LowerLimit || gEeprom.FM_UpperLimit < Frequency)
{

View File

@@ -39,7 +39,6 @@ extern uint8_t gFM_ChannelPosition;
extern uint16_t gFM_FrequencyDeviation;
extern bool gFM_FoundFrequency;
extern bool gFM_AutoScan;
extern uint8_t gFM_ResumeCountdown_500ms;
extern uint16_t gFM_RestoreCountdown_10ms;
bool FM_CheckValidChannel(uint8_t Channel);

View File

@@ -17,9 +17,12 @@
#include <string.h>
#include "app/app.h"
#include "app/common.h"
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
#endif
#include "app/generic.h"
#include "app/menu.h"
#include "app/scanner.h"
@@ -37,29 +40,24 @@ void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld)
{
if (gInputBoxIndex > 0)
{
if (!bKeyHeld && bKeyPressed)
if (!bKeyHeld && bKeyPressed) // short pressed
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
if (bKeyHeld || !bKeyPressed)
if (bKeyHeld || !bKeyPressed) // held or released
{
if (bKeyHeld || bKeyPressed)
if (bKeyHeld || bKeyPressed) // held or pressed (cannot be held and not pressed I guess, so it checks only if HELD?)
{
if (!bKeyHeld)
if (!bKeyHeld) // won't ever pass
return;
if (!bKeyPressed)
if (!bKeyPressed) // won't ever pass
return;
#ifdef ENABLE_VOICE
gAnotherVoiceID = gEeprom.KEY_LOCK ? VOICE_ID_UNLOCK : VOICE_ID_LOCK;
#endif
gEeprom.KEY_LOCK = !gEeprom.KEY_LOCK;
gRequestSaveSettings = true;
COMMON_KeypadLockToggle();
}
else
else // released
{
#ifdef ENABLE_FMRADIO
if ((gFmRadioMode || gScreenToDisplay != DISPLAY_MAIN) && gScreenToDisplay != DISPLAY_FM)
@@ -69,7 +67,10 @@ void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld)
return;
#endif
gWasFKeyPressed = !gWasFKeyPressed;
gWasFKeyPressed = !gWasFKeyPressed; // toggle F function
if (gWasFKeyPressed)
gKeyInputCountdown = key_input_timeout_500ms;
#ifdef ENABLE_VOICE
if (!gWasFKeyPressed)
@@ -79,7 +80,7 @@ void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld)
gUpdateStatus = true;
}
}
else
else // short pressed
{
if (gScreenToDisplay != DISPLAY_FM)
{
@@ -88,7 +89,7 @@ void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld)
}
#ifdef ENABLE_FMRADIO
if (gFM_ScanState == FM_SCAN_OFF)
if (gFM_ScanState == FM_SCAN_OFF) // not scanning
{
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
return;
@@ -96,6 +97,7 @@ void GENERIC_Key_F(bool bKeyPressed, bool bKeyHeld)
#endif
gBeepToPlay = BEEP_440HZ_500MS;
gPttWasReleased = true;
}
}
@@ -105,161 +107,152 @@ void GENERIC_Key_PTT(bool bKeyPressed)
gInputBoxIndex = 0;
if (!bKeyPressed || gSerialConfigCountDown_500ms > 0)
{
//if (gScreenToDisplay == DISPLAY_MAIN)
{
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // PTT released
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // we are transmitting .. stop
if (gFlagEndTransmission)
{
if (gFlagEndTransmission)
{
FUNCTION_Select(FUNCTION_FOREGROUND);
}
else
{
APP_EndTransmission();
if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0)
{
FUNCTION_Select(FUNCTION_FOREGROUND);
}
else
gRTTECountdown = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10;
}
gFlagEndTransmission = false;
#ifdef ENABLE_VOX
gVOX_NoiseDetected = false;
#endif
FUNCTION_Select(FUNCTION_FOREGROUND);
}
else
{
APP_EndTransmission();
if (gEeprom.REPEATER_TAIL_TONE_ELIMINATION == 0)
FUNCTION_Select(FUNCTION_FOREGROUND);
else
gRTTECountdown = gEeprom.REPEATER_TAIL_TONE_ELIMINATION * 10;
}
gFlagEndTransmission = false;
#ifdef ENABLE_VOX
gVOX_NoiseDetected = false;
#endif
RADIO_SetVfoState(VFO_STATE_NORMAL);
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MAIN;
return;
}
gInputBoxIndex = 0;
return;
}
if (gScanState != SCAN_OFF)
{
SCANNER_Stop();
// PTT pressed
gPttDebounceCounter = 0;
gPttIsPressed = false;
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_MENU) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MAIN;
return;
}
#ifdef ENABLE_FMRADIO
if (gFM_ScanState == FM_SCAN_OFF)
#endif
{
if (gCssScanMode == CSS_SCAN_MODE_OFF)
{
#ifdef ENABLE_FMRADIO
if (gScreenToDisplay == DISPLAY_FM)
{
gRequestDisplayScreen = DISPLAY_MAIN;
gInputBoxIndex = 0;
gPttIsPressed = false;
gPttDebounceCounter = 0;
return;
}
#endif
if (gScreenToDisplay != DISPLAY_SCANNER)
{
if (gCurrentFunction == FUNCTION_TRANSMIT && gRTTECountdown == 0)
{
gInputBoxIndex = 0;
return;
}
gFlagPrepareTX = true;
if (gDTMF_InputMode)
{
if (gDTMF_InputIndex > 0 || gDTMF_PreviousIndex > 0)
{
if (gDTMF_InputIndex == 0)
gDTMF_InputIndex = gDTMF_PreviousIndex;
gDTMF_InputBox[gDTMF_InputIndex] = 0;
#if 0
// append our DTMF ID to the inputted DTMF code -
// IF the user inputted code is exactly 3 digits long
if (gDTMF_InputIndex == 3)
gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3);
else
#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_InputIndex == 3 && gTxVfo->DTMF_DECODING_ENABLE > 0)
gDTMF_CallMode = DTMF_CheckGroupCall(gDTMF_InputBox, 3);
else
#endif
gDTMF_CallMode = DTMF_CALL_MODE_DTMF;
strcpy(gDTMF_String, gDTMF_InputBox);
gDTMF_PreviousIndex = gDTMF_InputIndex;
gDTMF_ReplyState = DTMF_REPLY_ANI;
gDTMF_State = DTMF_STATE_0;
}
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MAIN;
gDTMF_InputMode = false;
gDTMF_InputIndex = 0;
return;
}
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MAIN;
gFlagPrepareTX = true;
gInputBoxIndex = 0;
return;
}
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MAIN;
gEeprom.CROSS_BAND_RX_TX = gBackupCROSS_BAND_RX_TX;
gUpdateStatus = true;
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();
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MENU;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
}
goto cancel_tx;
}
#ifdef ENABLE_FMRADIO
else
{
FM_PlayAndUpdate();
gRequestDisplayScreen = DISPLAY_FM;
}
#endif
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
#ifdef ENABLE_FMRADIO
if (gFM_ScanState != FM_SCAN_OFF)
{ // FM radio is scanning .. stop
FM_PlayAndUpdate();
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_SCANNING_STOP;
#endif
gRequestDisplayScreen = DISPLAY_FM;
goto cancel_tx;
}
#endif
gPttWasPressed = true;
#ifdef ENABLE_FMRADIO
if (gScreenToDisplay == DISPLAY_FM)
goto start_tx; // listening to the FM radio .. start TX'ing
#endif
if (gCurrentFunction == FUNCTION_TRANSMIT && gRTTECountdown == 0)
{ // already transmitting
gInputBoxIndex = 0;
return;
}
if (gScreenToDisplay != DISPLAY_MENU) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MAIN;
if (!gDTMF_InputMode && gDTMF_InputBox_Index == 0)
goto start_tx; // wasn't entering a DTMF code .. start TX'ing (maybe)
// was entering a DTMF string
if (gDTMF_InputBox_Index > 0 || gDTMF_PreviousIndex > 0)
{ // going to transmit a DTMF string
if (gDTMF_InputBox_Index == 0 && gDTMF_PreviousIndex > 0)
gDTMF_InputBox_Index = gDTMF_PreviousIndex; // use the previous DTMF string
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
// remember the DTMF string
gDTMF_PreviousIndex = gDTMF_InputBox_Index;
strcpy(gDTMF_String, gDTMF_InputBox);
gDTMF_ReplyState = DTMF_REPLY_ANI;
gDTMF_State = DTMF_STATE_0;
}
DTMF_clear_input_box();
start_tx:
// request start TX
gFlagPrepareTX = true;
goto done;
cancel_tx:
if (gPttIsPressed)
{
gPttWasPressed = true;
}
done:
gPttDebounceCounter = 0;
if (gScreenToDisplay != DISPLAY_MENU && gRequestDisplayScreen != DISPLAY_FM) // 1of11 .. don't close the menu
gRequestDisplayScreen = DISPLAY_MAIN;
gUpdateStatus = true;
gUpdateDisplay = true;
}

View File

@@ -18,15 +18,18 @@
#include "app/action.h"
#include "app/app.h"
#include "app/common.h"
#ifdef ENABLE_FMRADIO
#include "app/fm.h"
#endif
#include "app/generic.h"
#include "app/main.h"
#include "app/scanner.h"
#ifdef ENABLE_SPECTRUM
#include "app/spectrum.h"
#endif
#include "audio.h"
#include "board.h"
#include "driver/bk4819.h"
@@ -37,11 +40,49 @@
#include "settings.h"
#include "ui/inputbox.h"
#include "ui/ui.h"
#include <stdlib.h>
void toggle_chan_scanlist(void)
{ // toggle the selected channels scanlist setting
if (gScreenToDisplay == DISPLAY_SCANNER || !IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
return;
if (gTxVfo->SCANLIST1_PARTICIPATION)
{
if (gTxVfo->SCANLIST2_PARTICIPATION)
gTxVfo->SCANLIST1_PARTICIPATION = 0;
else
gTxVfo->SCANLIST2_PARTICIPATION = 1;
}
else
{
if (gTxVfo->SCANLIST2_PARTICIPATION)
gTxVfo->SCANLIST2_PARTICIPATION = 0;
else
gTxVfo->SCANLIST1_PARTICIPATION = 1;
}
SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true);
gVfoConfigureMode = VFO_CONFIGURE;
gFlagResetVfos = true;
}
static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
{
uint8_t Band;
uint8_t Vfo = gEeprom.TX_CHANNEL;
uint8_t Vfo = gEeprom.TX_VFO;
if (gScreenToDisplay == DISPLAY_MENU)
{
// if (beep)
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
// if (beep)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
switch (Key)
{
@@ -58,26 +99,71 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
break;
case KEY_1:
if (!IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
if (!IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
gWasFKeyPressed = false;
gUpdateStatus = true;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
#ifdef ENABLE_COPY_CHAN_TO_VFO
if (gEeprom.VFO_OPEN && gCssScanMode == CSS_SCAN_MODE_OFF)
{
if (gScanStateDir != SCAN_OFF)
{
if (gCurrentFunction != FUNCTION_INCOMING ||
gRxReceptionMode == RX_MODE_NONE ||
gScanPauseDelayIn_10ms == 0)
{ // scan is running (not paused)
return;
}
}
const uint8_t vfo = gEeprom.TX_VFO;
if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo]))
{ // copy channel to VFO, then swap to the VFO
const unsigned int channel = FREQ_CHANNEL_FIRST + gEeprom.VfoInfo[vfo].Band;
gEeprom.ScreenChannel[vfo] = channel;
gEeprom.VfoInfo[vfo].CHANNEL_SAVE = channel;
RADIO_SelectVfos();
RADIO_ApplyOffset(gRxVfo);
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
RADIO_SetupRegisters(true);
//SETTINGS_SaveChannel(channel, gEeprom.RX_VFO, gRxVfo, 1);
gUpdateDisplay = true;
}
}
else
{
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
}
#endif
return;
}
Band = gTxVfo->Band + 1;
if (gSetting_350EN || Band != BAND5_350MHz)
{
if (Band > BAND7_470MHz)
Band = BAND1_50MHz;
if(gTxVfo->Band == 6 && gTxVfo->pRX->Frequency < 100000000) {
gTxVfo->pRX->Frequency = 100000000;
return;
}
else
Band = BAND6_400MHz;
gTxVfo->Band = Band;
else {
Band = gTxVfo->Band + 1;
if (gSetting_350EN || Band != BAND5_350MHz) {
if (Band > BAND7_470MHz)
Band = BAND1_50MHz;
}
else
Band = BAND6_400MHz;
gEeprom.ScreenChannel[Vfo] = FREQ_CHANNEL_FIRST + Band;
gEeprom.FreqChannel[Vfo] = FREQ_CHANNEL_FIRST + Band;
gTxVfo->Band = Band;
gEeprom.ScreenChannel[Vfo] = FREQ_CHANNEL_FIRST + Band;
gEeprom.FreqChannel[Vfo] = FREQ_CHANNEL_FIRST + Band;
}
gRequestSaveVFO = true;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
@@ -90,28 +176,10 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
break;
case KEY_2:
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_CHAN_A)
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_CHAN_B;
else
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_CHAN_B)
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_CHAN_A;
else
if (gEeprom.DUAL_WATCH == DUAL_WATCH_CHAN_A)
gEeprom.DUAL_WATCH = DUAL_WATCH_CHAN_B;
else
if (gEeprom.DUAL_WATCH == DUAL_WATCH_CHAN_B)
gEeprom.DUAL_WATCH = DUAL_WATCH_CHAN_A;
else
gEeprom.TX_CHANNEL = (Vfo + 1) & 1u;
gRequestSaveSettings = 1;
gFlagReconfigureVfos = true;
gRequestDisplayScreen = DISPLAY_MAIN;
COMMON_SwitchVFOs();
if (beep)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
break;
case KEY_3:
@@ -125,7 +193,7 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
{ // swap to frequency mode
gEeprom.ScreenChannel[Vfo] = gEeprom.FreqChannel[gEeprom.TX_CHANNEL];
gEeprom.ScreenChannel[Vfo] = gEeprom.FreqChannel[gEeprom.TX_VFO];
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_FREQUENCY_MODE;
#endif
@@ -134,7 +202,7 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
break;
}
Channel = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_CHANNEL], 1, false, 0);
Channel = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_VFO], 1, false, 0);
if (Channel != 0xFF)
{ // swap to channel mode
gEeprom.ScreenChannel[Vfo] = Channel;
@@ -158,7 +226,7 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
gWasFKeyPressed = false;
gFlagStartScan = true;
gScanSingleFrequency = false;
gBackupCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gBackup_CROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gUpdateStatus = true;
@@ -169,53 +237,32 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
case KEY_5:
if(beep) {
#ifdef ENABLE_NOAA
#ifdef ENABLE_NOAA
if (IS_NOT_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
gEeprom.ScreenChannel[Vfo] = gEeprom.NoaaChannel[gEeprom.TX_CHANNEL];
gEeprom.ScreenChannel[Vfo] = gEeprom.NoaaChannel[gEeprom.TX_VFO];
}
else
{
gEeprom.ScreenChannel[Vfo] = gEeprom.FreqChannel[gEeprom.TX_CHANNEL];
#ifdef ENABLE_VOICE
gEeprom.ScreenChannel[Vfo] = gEeprom.FreqChannel[gEeprom.TX_VFO];
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_FREQUENCY_MODE;
#endif
#endif
}
gRequestSaveVFO = true;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
#elif defined(ENABLE_SPECTRUM)
#elif defined(ENABLE_SPECTRUM)
APP_RunSpectrum();
gRequestDisplayScreen = DISPLAY_MAIN;
#endif
#endif
}
else {
// toggle the selected channels scanlist setting
if (gScreenToDisplay != DISPLAY_SCANNER)
{
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
if (gTxVfo->SCANLIST1_PARTICIPATION)
{
if (gTxVfo->SCANLIST2_PARTICIPATION)
gTxVfo->SCANLIST1_PARTICIPATION = 0;
else
gTxVfo->SCANLIST2_PARTICIPATION = 1;
}
else
{
if (gTxVfo->SCANLIST2_PARTICIPATION)
gTxVfo->SCANLIST2_PARTICIPATION = 0;
else
gTxVfo->SCANLIST1_PARTICIPATION = 1;
}
SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true);
gVfoConfigureMode = VFO_CONFIGURE;
gFlagResetVfos = true;
}
}
#ifdef ENABLE_VOX
toggle_chan_scanlist();
#endif
}
break;
case KEY_6:
@@ -223,15 +270,11 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
break;
case KEY_7:
#ifdef ENABLE_VOX
ACTION_Vox();
#else
// TODO: make use of this function key
#endif
#ifdef ENABLE_VOX
ACTION_Vox();
#else
toggle_chan_scanlist();
#endif
break;
case KEY_8:
@@ -244,11 +287,11 @@ static void processFKeyFunction(const KEY_Code_t Key, const bool beep)
{
gEeprom.MrChannel[Vfo] = gEeprom.CHAN_1_CALL;
gEeprom.ScreenChannel[Vfo] = gEeprom.CHAN_1_CALL;
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_CHANNEL_MODE);
AUDIO_SetDigitVoice(1, gEeprom.CHAN_1_CALL + 1);
gAnotherVoiceID = (VOICE_ID_t)0xFE;
#endif
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_CHANNEL_MODE);
AUDIO_SetDigitVoice(1, gEeprom.CHAN_1_CALL + 1);
gAnotherVoiceID = (VOICE_ID_t)0xFE;
#endif
gRequestSaveVFO = true;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
break;
@@ -273,45 +316,36 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
if (bKeyHeld)
{ // key held down
#ifdef ENABLE_MAIN_KEY_HOLD
if (bKeyPressed)
if (bKeyPressed)
{
if (gScreenToDisplay == DISPLAY_MAIN)
{
if (gScreenToDisplay == DISPLAY_MAIN)
{
if (gInputBoxIndex > 0)
{ // delete any inputted chars
gInputBoxIndex = 0;
gRequestDisplayScreen = DISPLAY_MAIN;
}
gWasFKeyPressed = false;
gUpdateStatus = true;
processFKeyFunction(Key, false);
if (gInputBoxIndex > 0)
{ // delete any inputted chars
gInputBoxIndex = 0;
gRequestDisplayScreen = DISPLAY_MAIN;
}
gWasFKeyPressed = false;
gUpdateStatus = true;
processFKeyFunction(Key, false);
}
#endif
}
return;
}
#ifdef ENABLE_MAIN_KEY_HOLD
if (bKeyPressed)
{ // key is pressed
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; // beep when key is pressed
return; // don't use the key till it's released
}
#else
if (!bKeyPressed)
return;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
#endif
if (bKeyPressed)
{ // key is pressed
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; // beep when key is pressed
return; // don't use the key till it's released
}
if (!gWasFKeyPressed)
{ // F-key wasn't pressed
const uint8_t Vfo = gEeprom.TX_CHANNEL;
const uint8_t Vfo = gEeprom.TX_VFO;
gKeyInputCountdown = key_input_timeout_500ms;
@@ -359,11 +393,11 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
// if (IS_NOT_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
// #endif
if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE))
{ // user is entering frequency
{ // user is entering a frequency
uint32_t Frequency;
if (gInputBoxIndex < 6)
bool isGigaF = gTxVfo->pRX->Frequency >= 100000000;
if (gInputBoxIndex < 6 + isGigaF)
{
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
@@ -373,8 +407,7 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
gInputBoxIndex = 0;
NUMBER_Get(gInputBox, &Frequency);
Frequency = StrToUL(INPUTBOX_GetAscii()) * 100;
// clamp the frequency entered to some valid value
if (Frequency < frequencyBandTable[0].lower)
@@ -492,7 +525,7 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
if (!gFmRadioMode)
#endif
{
if (gScanState == SCAN_OFF)
if (gScanStateDir == SCAN_OFF)
{
if (gInputBoxIndex == 0)
return;
@@ -507,6 +540,7 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
}
else
{
bScanKeepFrequency = false;
SCANNER_Stop();
#ifdef ENABLE_VOICE
@@ -528,10 +562,10 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
if (bKeyHeld && bKeyPressed)
{ // exit key held down
if (gInputBoxIndex > 0)
if (gInputBoxIndex > 0 || gDTMF_InputBox_Index > 0 || gDTMF_InputMode)
{ // cancel key input mode (channel/frequency entry)
gDTMF_InputMode = false;
gDTMF_InputIndex = 0;
gDTMF_InputBox_Index = 0;
memset(gDTMF_String, 0, sizeof(gDTMF_String));
gInputBoxIndex = 0;
gRequestDisplayScreen = DISPLAY_MAIN;
@@ -542,12 +576,18 @@ static void MAIN_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
{
if (bKeyPressed && !bKeyHeld)
// menu key pressed
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (bKeyHeld)
{ // menu key held down (long press)
if (bKeyPressed)
{ // long press MENU key
gWasFKeyPressed = false;
if (gScreenToDisplay == DISPLAY_MAIN)
{
if (gInputBoxIndex > 0)
@@ -559,72 +599,7 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
gWasFKeyPressed = false;
gUpdateStatus = true;
#ifdef ENABLE_COPY_CHAN_TO_VFO
if (gEeprom.VFO_OPEN &&
gEeprom.DUAL_WATCH == DUAL_WATCH_OFF &&
gScanState == SCAN_OFF &&
gCssScanMode == CSS_SCAN_MODE_OFF)
{ // copy channel to VFO
int channel = -1;
int vfo = -1;
#if 0
// copy channel to opposite VFO
if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[0]) &&
IS_MR_CHANNEL(gEeprom.ScreenChannel[1]))
{
channel = gEeprom.ScreenChannel[1];
vfo = 0;
}
else
if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[1]) &&
IS_MR_CHANNEL(gEeprom.ScreenChannel[0]))
{
channel = gEeprom.ScreenChannel[0];
vfo = 1;
}
#else
// copy channel to same VFO
if (IS_MR_CHANNEL(gEeprom.ScreenChannel[gEeprom.RX_CHANNEL]))
{
channel = gEeprom.ScreenChannel[gEeprom.RX_CHANNEL];
vfo = gEeprom.RX_CHANNEL;
}
#endif
if (channel >= 0 && vfo >= 0)
{ // copy the channel into the VFO
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
gEeprom.MrChannel[vfo] = channel;
gEeprom.ScreenChannel[vfo] = channel;
RADIO_ConfigureChannel(vfo, VFO_CONFIGURE_RELOAD);
channel = FREQ_CHANNEL_FIRST + gEeprom.VfoInfo[vfo].Band;
gEeprom.MrChannel[vfo] = channel;
gEeprom.ScreenChannel[vfo] = channel;
gEeprom.VfoInfo[vfo].CHANNEL_SAVE = channel;
// swap to the VFO
gEeprom.TX_CHANNEL = vfo;
gEeprom.RX_CHANNEL = vfo;
RADIO_SelectVfos();
RADIO_ApplyOffset(gRxVfo);
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
RADIO_SetupRegisters(true);
// SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_CHANNEL, gRxVfo, 1);
gUpdateStatus = true;
gUpdateDisplay = true;
}
}
#endif
ACTION_Handle(KEY_MENU, bKeyPressed, bKeyHeld);
}
}
@@ -636,14 +611,10 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
const bool bFlag = (gInputBoxIndex == 0);
gInputBoxIndex = 0;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (bFlag)
{
gFlagRefreshSetting = true;
gRequestDisplayScreen = DISPLAY_MENU;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_MENU;
#endif
@@ -657,6 +628,9 @@ static void MAIN_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
static void MAIN_Key_STAR(bool bKeyPressed, bool bKeyHeld)
{
if (gCurrentFunction == FUNCTION_TRANSMIT)
return;
if (gInputBoxIndex)
{
if (!bKeyHeld && bKeyPressed)
@@ -664,74 +638,72 @@ static void MAIN_Key_STAR(bool bKeyPressed, bool bKeyHeld)
return;
}
if (bKeyHeld || !bKeyPressed)
if (bKeyHeld && !gWasFKeyPressed) // long press
{
if (bKeyHeld || bKeyPressed)
{
if (!bKeyHeld)
return;
if (!bKeyPressed)
return;
ACTION_Scan(false);
if (!bKeyPressed) // released
return;
}
ACTION_Scan(false);// toggle scanning
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
return;
}
if (bKeyPressed) // just pressed
{
// gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
gBeepToPlay = BEEP_880HZ_40MS_OPTIONAL;
return;
}
// just released
if (!gWasFKeyPressed) // pressed without the F-key
{
#ifdef ENABLE_NOAA
if (gScanState == SCAN_OFF && IS_NOT_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
if (gScanStateDir == SCAN_OFF && IS_NOT_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
#else
if (gScanState == SCAN_OFF)
if (gScanStateDir == SCAN_OFF)
#endif
{
gKeyInputCountdown = key_input_timeout_500ms;
{ // start entering a DTMF string
memmove(gDTMF_InputBox, gDTMF_String, MIN(sizeof(gDTMF_InputBox), sizeof(gDTMF_String) - 1));
gDTMF_InputBox_Index = 0;
gDTMF_InputMode = true;
memmove(gDTMF_InputBox, gDTMF_String, sizeof(gDTMF_InputBox));
gDTMF_InputIndex = 0;
gKeyInputCountdown = key_input_timeout_500ms;
gRequestDisplayScreen = DISPLAY_MAIN;
return;
}
}
else
{
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (!gWasFKeyPressed)
{
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
return;
}
{ // with the F-key
gWasFKeyPressed = false;
gUpdateStatus = true;
#ifdef ENABLE_NOAA
if (IS_NOT_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
gFlagStartScan = true;
gScanSingleFrequency = true;
gBackupCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
}
else
if (IS_NOAA_CHANNEL(gTxVfo->CHANNEL_SAVE))
{
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
#else
gFlagStartScan = true;
gScanSingleFrequency = true;
gBackupCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
#endif
gPttWasReleased = true;
// 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;
}
gPttWasReleased = true;
gUpdateStatus = true;
}
static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
{
uint8_t Channel = gEeprom.ScreenChannel[gEeprom.TX_CHANNEL];
uint8_t Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO];
if (bKeyHeld || !bKeyPressed)
{
@@ -765,7 +737,7 @@ static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
}
if (gScanState == SCAN_OFF)
if (gScanStateDir == SCAN_OFF)
{
#ifdef ENABLE_NOAA
if (IS_NOT_NOAA_CHANNEL(Channel))
@@ -796,8 +768,8 @@ static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
if (Channel == Next)
return;
gEeprom.MrChannel[gEeprom.TX_CHANNEL] = Next;
gEeprom.ScreenChannel[gEeprom.TX_CHANNEL] = Next;
gEeprom.MrChannel[gEeprom.TX_VFO] = Next;
gEeprom.ScreenChannel[gEeprom.TX_VFO] = Next;
if (!bKeyHeld)
{
@@ -810,9 +782,9 @@ static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
#ifdef ENABLE_NOAA
else
{
Channel = NOAA_CHANNEL_FIRST + NUMBER_AddWithWraparound(gEeprom.ScreenChannel[gEeprom.TX_CHANNEL] - NOAA_CHANNEL_FIRST, Direction, 0, 9);
gEeprom.NoaaChannel[gEeprom.TX_CHANNEL] = Channel;
gEeprom.ScreenChannel[gEeprom.TX_CHANNEL] = Channel;
Channel = NOAA_CHANNEL_FIRST + NUMBER_AddWithWraparound(gEeprom.ScreenChannel[gEeprom.TX_VFO] - NOAA_CHANNEL_FIRST, Direction, 0, 9);
gEeprom.NoaaChannel[gEeprom.TX_VFO] = Channel;
gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel;
}
#endif
@@ -821,7 +793,10 @@ static void MAIN_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
return;
}
CHANNEL_Next(false, Direction);
// jump to the next channel
SCANNER_NextChannel(false, Direction);
gScanPauseDelayIn_10ms = 1;
gScheduleScanListen = false;
gPttWasReleased = true;
}
@@ -837,31 +812,25 @@ void MAIN_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
#endif
if (gDTMF_InputMode && bKeyPressed)
if (gDTMF_InputMode && bKeyPressed && !bKeyHeld)
{
if (!bKeyHeld)
{
const char Character = DTMF_GetCharacter(Key);
if (Character != 0xFF)
{ // add key to DTMF string
DTMF_Append(Character);
gKeyInputCountdown = key_input_timeout_500ms;
gRequestDisplayScreen = DISPLAY_MAIN;
gPttWasReleased = true;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
return;
}
const char Character = DTMF_GetCharacter(Key);
if (Character != 0xFF)
{ // add key to DTMF string
DTMF_Append(Character);
gKeyInputCountdown = key_input_timeout_500ms;
gRequestDisplayScreen = DISPLAY_MAIN;
gPttWasReleased = true;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
return;
}
}
// TODO: ???
if (Key > KEY_PTT)
{
Key = KEY_SIDE2;
}
// if (Key > KEY_PTT)
// {
// Key = KEY_SIDE2; // what's this doing ???
// }
switch (Key)
{

View File

@@ -86,8 +86,8 @@ void MENU_StartCssScan(int8_t Direction)
MENU_SelectNextCode();
ScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms;
gScheduleScanListen = false;
gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms;
gScheduleScanListen = false;
}
void MENU_StopCssScan(void)
@@ -98,9 +98,9 @@ void MENU_StopCssScan(void)
RADIO_SetupRegisters(true);
}
int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
{
switch (Cursor)
switch (menu_id)
{
case MENU_SQL:
*pMin = 0;
@@ -139,12 +139,7 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
case MENU_TDR:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_CHAN) - 1;
break;
case MENU_XB:
*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_XB) - 1;
*pMax = ARRAY_SIZE(gSubMenu_RXMode) - 1;
break;
#ifdef ENABLE_VOICE
@@ -285,7 +280,6 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
case MENU_S_LIST:
*pMin = 0;
// *pMax = 1;
*pMax = 2;
break;
@@ -331,6 +325,15 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax)
*pMax = 2200; // 2300
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
case MENU_F2LONG:
case MENU_MLONG:
*pMin = 0;
*pMax = gSubMenu_SIDEFUNCTIONS_size-1;
break;
default:
return -1;
}
@@ -345,14 +348,14 @@ void MENU_AcceptSetting(void)
uint8_t Code;
FREQ_Config_t *pConfig = &gTxVfo->freq_config_RX;
if (!MENU_GetLimits(gMenuCursor, &Min, &Max))
if (!MENU_GetLimits(GetCurrentMenuId(), &Min, &Max))
{
if (gSubMenuSelection < Min) gSubMenuSelection = Min;
else
if (gSubMenuSelection > Max) gSubMenuSelection = Max;
}
switch (gMenuCursor)
switch (GetCurrentMenuId())
{
default:
return;
@@ -410,6 +413,7 @@ void MENU_AcceptSetting(void)
case MENU_T_CTCS:
pConfig = &gTxVfo->freq_config_TX;
[[fallthrough]];
case MENU_R_CTCS:
if (gSubMenuSelection == 0)
{
@@ -472,7 +476,7 @@ void MENU_AcceptSetting(void)
#if 0
gEeprom.MrChannel[0] = gSubMenuSelection;
#else
gEeprom.MrChannel[gEeprom.TX_CHANNEL] = gSubMenuSelection;
gEeprom.MrChannel[gEeprom.TX_VFO] = gSubMenuSelection;
#endif
gRequestSaveChannel = 2;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
@@ -492,7 +496,7 @@ void MENU_AcceptSetting(void)
// save the channel name
memset(gTxVfo->Name, 0, sizeof(gTxVfo->Name));
memmove(gTxVfo->Name, edit, 10);
SETTINGS_SaveChannel(gSubMenuSelection, gEeprom.TX_CHANNEL, gTxVfo, 3);
SETTINGS_SaveChannel(gSubMenuSelection, gEeprom.TX_VFO, gTxVfo, 3);
gFlagReconfigureVfos = true;
return;
@@ -505,7 +509,7 @@ void MENU_AcceptSetting(void)
gEeprom.VOX_SWITCH = gSubMenuSelection != 0;
if (gEeprom.VOX_SWITCH)
gEeprom.VOX_LEVEL = gSubMenuSelection - 1;
BOARD_EEPROM_LoadMoreSettings();
BOARD_EEPROM_LoadCalibration();
gFlagReconfigureVfos = true;
gUpdateStatus = true;
break;
@@ -520,24 +524,13 @@ void MENU_AcceptSetting(void)
break;
case MENU_TDR:
gEeprom.DUAL_WATCH = gSubMenuSelection;
gEeprom.DUAL_WATCH = (gEeprom.TX_VFO + 1) * (gSubMenuSelection & 1);
gEeprom.CROSS_BAND_RX_TX = (gEeprom.TX_VFO + 1) * ((gSubMenuSelection & 2) > 0);
gFlagReconfigureVfos = true;
gUpdateStatus = true;
break;
case MENU_XB:
#ifdef ENABLE_NOAA
if (IS_NOAA_CHANNEL(gEeprom.ScreenChannel[0]))
return;
if (IS_NOAA_CHANNEL(gEeprom.ScreenChannel[1]))
return;
#endif
gEeprom.CROSS_BAND_RX_TX = gSubMenuSelection;
gFlagReconfigureVfos = true;
gUpdateStatus = true;
break;
case MENU_BEEP:
gEeprom.BEEP_CONTROL = gSubMenuSelection;
break;
@@ -590,7 +583,7 @@ void MENU_AcceptSetting(void)
case MENU_MIC:
gEeprom.MIC_SENSITIVITY = gSubMenuSelection;
BOARD_EEPROM_LoadMoreSettings();
BOARD_EEPROM_LoadCalibration();
gFlagReconfigureVfos = true;
break;
@@ -669,7 +662,7 @@ void MENU_AcceptSetting(void)
{
GUI_SelectNextDisplay(DISPLAY_MAIN);
gDTMF_InputMode = true;
gDTMF_InputIndex = 3;
gDTMF_InputBox_Index = 3;
memmove(gDTMF_InputBox, gDTMF_ID, 4);
gRequestDisplayScreen = DISPLAY_INVALID;
}
@@ -760,23 +753,32 @@ void MENU_AcceptSetting(void)
case MENU_BATCAL:
{
uint16_t buf[4];
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
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;
EEPROM_WriteBuffer(0x1F40, gBatteryCalibration);
EEPROM_ReadBuffer( 0x1F48, buf, sizeof(buf));
buf[0] = gBatteryCalibration[4];
buf[1] = gBatteryCalibration[5];
EEPROM_WriteBuffer(0x1F48, buf);
break;
SETTINGS_SaveBatteryCalibration(gBatteryCalibration);
return;
}
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
case MENU_F2LONG:
case MENU_MLONG:
{
uint8_t * fun[]= {
&gEeprom.KEY_1_SHORT_PRESS_ACTION,
&gEeprom.KEY_1_LONG_PRESS_ACTION,
&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;
}
break;
}
gRequestSaveSettings = true;
@@ -786,18 +788,17 @@ void MENU_SelectNextCode(void)
{
int32_t UpperLimit;
if (gMenuCursor == MENU_R_DCS)
if (GetCurrentMenuId() == MENU_R_DCS)
UpperLimit = 208;
//UpperLimit = ARRAY_SIZE(DCS_Options);
else
if (gMenuCursor == MENU_R_CTCS)
else if (GetCurrentMenuId() == MENU_R_CTCS)
UpperLimit = ARRAY_SIZE(CTCSS_Options) - 1;
else
return;
gSubMenuSelection = NUMBER_AddWithWraparound(gSubMenuSelection, gMenuScrollDirection, 1, UpperLimit);
if (gMenuCursor == MENU_R_DCS)
if (GetCurrentMenuId() == MENU_R_DCS)
{
if (gSubMenuSelection > 104)
{
@@ -819,7 +820,7 @@ void MENU_SelectNextCode(void)
RADIO_SetupRegisters(true);
ScanPauseDelayIn_10ms = (gSelectedCodeType == CODE_TYPE_CONTINUOUS_TONE) ? scan_pause_delay_in_3_10ms : scan_pause_delay_in_4_10ms;
gScanPauseDelayIn_10ms = (gSelectedCodeType == CODE_TYPE_CONTINUOUS_TONE) ? scan_pause_delay_in_3_10ms : scan_pause_delay_in_4_10ms;
gUpdateDisplay = true;
}
@@ -829,7 +830,7 @@ static void MENU_ClampSelection(int8_t Direction)
int32_t Min;
int32_t Max;
if (!MENU_GetLimits(gMenuCursor, &Min, &Max))
if (!MENU_GetLimits(GetCurrentMenuId(), &Min, &Max))
{
int32_t Selection = gSubMenuSelection;
if (Selection < Min) Selection = Min;
@@ -841,7 +842,7 @@ static void MENU_ClampSelection(int8_t Direction)
void MENU_ShowCurrentSetting(void)
{
switch (gMenuCursor)
switch (GetCurrentMenuId())
{
case MENU_SQL:
gSubMenuSelection = gEeprom.SQUELCH_LEVEL;
@@ -921,12 +922,12 @@ void MENU_ShowCurrentSetting(void)
#if 0
gSubMenuSelection = gEeprom.MrChannel[0];
#else
gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_CHANNEL];
gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO];
#endif
break;
case MENU_MEM_NAME:
gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_CHANNEL];
gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO];
break;
case MENU_SAVE:
@@ -951,11 +952,7 @@ void MENU_ShowCurrentSetting(void)
break;
case MENU_TDR:
gSubMenuSelection = gEeprom.DUAL_WATCH;
break;
case MENU_XB:
gSubMenuSelection = gEeprom.CROSS_BAND_RX_TX;
gSubMenuSelection = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2;
break;
case MENU_BEEP:
@@ -1106,7 +1103,7 @@ void MENU_ShowCurrentSetting(void)
#if 0
gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[0], 1, false, 1);
#else
gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_CHANNEL], 1, false, 1);
gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_VFO], 1, false, 1);
#endif
break;
@@ -1148,6 +1145,30 @@ void MENU_ShowCurrentSetting(void)
gSubMenuSelection = gBatteryCalibration[3];
break;
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
case MENU_F2LONG:
case MENU_MLONG:
{
uint8_t * fun[]= {
&gEeprom.KEY_1_SHORT_PRESS_ACTION,
&gEeprom.KEY_1_LONG_PRESS_ACTION,
&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];
for(int i = 0; i < gSubMenu_SIDEFUNCTIONS_size; i++) {
if(gSubMenu_SIDEFUNCTIONS[i].id==id) {
gSubMenuSelection = i;
break;
}
}
break;
}
default:
return;
}
@@ -1165,12 +1186,12 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (gMenuCursor == MENU_MEM_NAME && edit_index >= 0)
if (GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
{ // currently editing the channel name
if (edit_index < 10)
{
if (Key >= KEY_0 && Key <= KEY_9)
if (Key <= KEY_9)
{
edit[edit_index] = '0' + Key - KEY_0;
@@ -1212,7 +1233,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
gInputBox[0] = gInputBox[1];
gInputBoxIndex = 1;
[[fallthrough]];
case 1:
Value = gInputBox[0];
if (Value > 0 && Value <= gMenuListCount)
@@ -1230,7 +1251,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
return;
}
if (gMenuCursor == MENU_OFFSET)
if (GetCurrentMenuId() == MENU_OFFSET)
{
uint32_t Frequency;
@@ -1246,14 +1267,17 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
gAnotherVoiceID = (VOICE_ID_t)Key;
#endif
NUMBER_Get(gInputBox, &Frequency);
Frequency = StrToUL(INPUTBOX_GetAscii());
gSubMenuSelection = FREQUENCY_FloorToStep(Frequency + 75, gTxVfo->StepFrequency, 0);
gInputBoxIndex = 0;
return;
}
if (gMenuCursor == MENU_MEM_CH || gMenuCursor == MENU_DEL_CH || gMenuCursor == MENU_1_CALL || gMenuCursor == MENU_MEM_NAME)
if (GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_DEL_CH ||
GetCurrentMenuId() == MENU_1_CALL ||
GetCurrentMenuId() == MENU_MEM_NAME)
{ // enter 3-digit channel number
if (gInputBoxIndex < 3)
@@ -1269,7 +1293,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
Value = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;
if (IS_MR_CHANNEL(Value))
if (Value <= MR_CHANNEL_LAST)
{
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
@@ -1282,7 +1306,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
return;
}
if (MENU_GetLimits(gMenuCursor, &Min, &Max))
if (MENU_GetLimits(GetCurrentMenuId(), &Min, &Max))
{
gInputBoxIndex = 0;
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
@@ -1327,7 +1351,7 @@ static void MENU_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{
if (gIsInSubMenu)
{
if (gInputBoxIndex == 0 || gMenuCursor != MENU_OFFSET)
if (gInputBoxIndex == 0 || GetCurrentMenuId() != MENU_OFFSET)
{
gAskForConfirmation = 0;
gIsInSubMenu = false;
@@ -1384,12 +1408,12 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
if (!gIsInSubMenu)
{
#ifdef ENABLE_VOICE
if (gMenuCursor != MENU_SCR)
if (GetCurrentMenuId() != MENU_SCR)
gAnotherVoiceID = MenuList[gMenuCursor].voice_id;
#endif
#if 1
if (gMenuCursor == MENU_DEL_CH || gMenuCursor == MENU_MEM_NAME)
if (GetCurrentMenuId() == MENU_DEL_CH || GetCurrentMenuId() == MENU_MEM_NAME)
if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0))
return; // invalid channel
#endif
@@ -1397,7 +1421,7 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
gAskForConfirmation = 0;
gIsInSubMenu = true;
// if (gMenuCursor != MENU_D_LIST)
// if (GetCurrentMenuId() != MENU_D_LIST)
{
gInputBoxIndex = 0;
edit_index = -1;
@@ -1406,7 +1430,7 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
return;
}
if (gMenuCursor == MENU_MEM_NAME)
if (GetCurrentMenuId() == MENU_MEM_NAME)
{
if (edit_index < 0)
{ // enter channel name edit mode
@@ -1453,10 +1477,10 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
if (gIsInSubMenu)
{
if (gMenuCursor == MENU_RESET ||
gMenuCursor == MENU_MEM_CH ||
gMenuCursor == MENU_DEL_CH ||
gMenuCursor == MENU_MEM_NAME)
if (GetCurrentMenuId() == MENU_RESET ||
GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_DEL_CH ||
GetCurrentMenuId() == MENU_MEM_NAME)
{
switch (gAskForConfirmation)
{
@@ -1469,7 +1493,7 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
UI_DisplayMenu();
if (gMenuCursor == MENU_RESET)
if (GetCurrentMenuId() == MENU_RESET)
{
#ifdef ENABLE_VOICE
AUDIO_SetVoiceID(0, VOICE_ID_CONFIRM);
@@ -1504,7 +1528,7 @@ static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
}
#ifdef ENABLE_VOICE
if (gMenuCursor == MENU_SCR)
if (GetCurrentMenuId() == MENU_SCR)
gAnotherVoiceID = (gSubMenuSelection == 0) ? VOICE_ID_SCRAMBLER_OFF : VOICE_ID_SCRAMBLER_ON;
else
gAnotherVoiceID = VOICE_ID_CONFIRM;
@@ -1520,7 +1544,7 @@ static void MENU_Key_STAR(const bool bKeyPressed, const bool bKeyHeld)
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
if (gMenuCursor == MENU_MEM_NAME && edit_index >= 0)
if (GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
{ // currently editing the channel name
if (edit_index < 10)
@@ -1547,7 +1571,7 @@ static void MENU_Key_STAR(const bool bKeyPressed, const bool bKeyHeld)
if (gRxVfo->AM_mode == 0)
#endif
{
if (gMenuCursor == MENU_R_CTCS || gMenuCursor == MENU_R_DCS)
if (GetCurrentMenuId() == MENU_R_CTCS || GetCurrentMenuId() == MENU_R_DCS)
{ // scan CTCSS or DCS to find the tone/code of the incoming signal
if (gCssScanMode == CSS_SCAN_MODE_OFF)
@@ -1582,7 +1606,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
uint8_t Channel;
bool bCheckScanList;
if (gMenuCursor == MENU_MEM_NAME && gIsInSubMenu && edit_index >= 0)
if (GetCurrentMenuId() == MENU_MEM_NAME && gIsInSubMenu && edit_index >= 0)
{ // change the character
if (bKeyPressed && edit_index < 10 && Direction != 0)
{
@@ -1634,7 +1658,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
gRequestDisplayScreen = DISPLAY_MENU;
if (gMenuCursor != MENU_ABR && gEeprom.BACKLIGHT == 0)
if (GetCurrentMenuId() != MENU_ABR && gEeprom.BACKLIGHT == 0)
{
gBacklightCountdown = 0;
GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT); // turn the backlight OFF
@@ -1643,7 +1667,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
return;
}
if (gMenuCursor == MENU_OFFSET)
if (GetCurrentMenuId() == MENU_OFFSET)
{
int32_t Offset = (Direction * gTxVfo->StepFrequency) + gSubMenuSelection;
if (Offset < 99999990)
@@ -1661,7 +1685,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
VFO = 0;
switch (gMenuCursor)
switch (GetCurrentMenuId())
{
case MENU_DEL_CH:
case MENU_1_CALL:
@@ -1671,6 +1695,7 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
case MENU_SLIST2:
VFO = 1;
[[fallthrough]];
case MENU_SLIST1:
bCheckScanList = true;
break;
@@ -1720,7 +1745,7 @@ void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
MENU_Key_STAR(bKeyPressed, bKeyHeld);
break;
case KEY_F:
if (gMenuCursor == MENU_MEM_NAME && edit_index >= 0)
if (GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
{ // currently editing the channel name
if (!bKeyHeld && bKeyPressed)
{
@@ -1752,11 +1777,11 @@ void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
if (gScreenToDisplay == DISPLAY_MENU)
{
if (gMenuCursor == MENU_VOL ||
if (GetCurrentMenuId() == MENU_VOL ||
#ifdef ENABLE_F_CAL_MENU
gMenuCursor == MENU_F_CALI ||
GetCurrentMenuId() == MENU_F_CALI ||
#endif
gMenuCursor == MENU_BATCAL)
GetCurrentMenuId() == MENU_BATCAL)
{
gMenuCountdown = menu_timeout_long_500ms;
}

View File

@@ -23,7 +23,7 @@
void writeXtalFreqCal(const int32_t value, const bool update_eeprom);
#endif
int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax);
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);

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "app/app.h"
#include "app/dtmf.h"
#include "app/generic.h"
#include "app/scanner.h"
@@ -37,12 +38,14 @@ uint32_t gScanFrequency;
bool gScanPauseMode;
SCAN_CssState_t gScanCssState;
volatile bool gScheduleScanListen = true;
volatile uint16_t ScanPauseDelayIn_10ms;
volatile uint16_t gScanPauseDelayIn_10ms;
uint8_t gScanProgressIndicator;
uint8_t gScanHitCount;
bool gScanUseCssResult;
int8_t gScanState;
int8_t gScanStateDir;
bool bScanKeepFrequency;
uint8_t gRestoreMrChannel;
uint8_t gRestoreCROSS_BAND_RX_TX;
static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
@@ -53,7 +56,9 @@ static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
uint16_t Channel;
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
INPUTBOX_Append(Key);
gRequestDisplayScreen = DISPLAY_SCANNER;
if (gInputBoxIndex < 3)
@@ -65,9 +70,9 @@ static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
}
gInputBoxIndex = 0;
Channel = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;
if (IS_MR_CHANNEL(Channel))
Channel = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;
if (Channel <= MR_CHANNEL_LAST)
{
#ifdef ENABLE_VOICE
gAnotherVoiceID = (VOICE_ID_t)Key;
@@ -93,7 +98,7 @@ static void SCANNER_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
case 0:
gRequestDisplayScreen = DISPLAY_MAIN;
gEeprom.CROSS_BAND_RX_TX = gBackupCROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = gBackup_CROSS_BAND_RX_TX;
gUpdateStatus = true;
gFlagStopScan = true;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
@@ -193,7 +198,7 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
}
}
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
if (gTxVfo->CHANNEL_SAVE <= MR_CHANNEL_LAST)
{
gScannerEditState = 1;
gScanChannel = gTxVfo->CHANNEL_SAVE;
@@ -247,19 +252,19 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
gTxVfo->freq_config_TX.Code = gScanCssResultCode;
}
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE))
if (gTxVfo->CHANNEL_SAVE <= MR_CHANNEL_LAST)
{
Channel = gScanChannel;
gEeprom.MrChannel[gEeprom.TX_CHANNEL] = Channel;
gEeprom.MrChannel[gEeprom.TX_VFO] = Channel;
}
else
{
Channel = gTxVfo->Band + FREQ_CHANNEL_FIRST;
gEeprom.FreqChannel[gEeprom.TX_CHANNEL] = Channel;
gEeprom.FreqChannel[gEeprom.TX_VFO] = Channel;
}
gTxVfo->CHANNEL_SAVE = Channel;
gEeprom.ScreenChannel[gEeprom.TX_CHANNEL] = Channel;
gEeprom.ScreenChannel[gEeprom.TX_VFO] = Channel;
#ifdef ENABLE_VOICE
gAnotherVoiceID = VOICE_ID_CONFIRM;
#endif
@@ -360,10 +365,10 @@ void SCANNER_Start(void)
RADIO_SelectVfos();
#ifdef ENABLE_NOAA
if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
gRxVfo->CHANNEL_SAVE = FREQ_CHANNEL_FIRST + BAND6_400MHz;
#endif
#ifdef ENABLE_NOAA
if (IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE))
gRxVfo->CHANNEL_SAVE = FREQ_CHANNEL_FIRST + BAND6_400MHz;
#endif
BackupStep = gRxVfo->STEP_SETTING;
BackupFrequency = gRxVfo->StepFrequency;
@@ -375,9 +380,9 @@ void SCANNER_Start(void)
RADIO_SetupRegisters(true);
#ifdef ENABLE_NOAA
gIsNoaaMode = false;
#endif
#ifdef ENABLE_NOAA
gIsNoaaMode = false;
#endif
if (gScanSingleFrequency)
{
@@ -412,9 +417,9 @@ void SCANNER_Start(void)
g_CDCSS_Lost = false;
gCDCSSCodeType = 0;
g_CTCSS_Lost = false;
#ifdef ENABLE_VOX
g_VOX_Lost = false;
#endif
#ifdef ENABLE_VOX
g_VOX_Lost = false;
#endif
g_SquelchLost = false;
gScannerEditState = 0;
gScanProgressIndicator = 0;
@@ -422,18 +427,21 @@ void SCANNER_Start(void)
void SCANNER_Stop(void)
{
const uint8_t Previous = gRestoreMrChannel;
if(gRestoreCROSS_BAND_RX_TX != CROSS_BAND_OFF) {
gEeprom.CROSS_BAND_RX_TX = gRestoreCROSS_BAND_RX_TX;
gRestoreCROSS_BAND_RX_TX = CROSS_BAND_OFF;
}
gScanState = SCAN_OFF;
gScanStateDir = SCAN_OFF;
if (!bScanKeepFrequency)
{
if (IS_MR_CHANNEL(gNextMrChannel))
if (gNextMrChannel <= MR_CHANNEL_LAST)
{
gEeprom.MrChannel[gEeprom.RX_CHANNEL] = gRestoreMrChannel;
gEeprom.ScreenChannel[gEeprom.RX_CHANNEL] = Previous;
gEeprom.MrChannel[gEeprom.RX_VFO] = gRestoreMrChannel;
gEeprom.ScreenChannel[gEeprom.RX_VFO] = gRestoreMrChannel;
RADIO_ConfigureChannel(gEeprom.RX_CHANNEL, VFO_CONFIGURE_RELOAD);
RADIO_ConfigureChannel(gEeprom.RX_VFO, VFO_CONFIGURE_RELOAD);
}
else
{
@@ -446,11 +454,11 @@ void SCANNER_Stop(void)
return;
}
if (!IS_MR_CHANNEL(gRxVfo->CHANNEL_SAVE))
if (gRxVfo->CHANNEL_SAVE > MR_CHANNEL_LAST)
{
RADIO_ApplyOffset(gRxVfo);
RADIO_ConfigureSquelchAndOutputPower(gRxVfo);
SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_CHANNEL, gRxVfo, 1);
SETTINGS_SaveChannel(gRxVfo->CHANNEL_SAVE, gEeprom.RX_VFO, gRxVfo, 1);
return;
}
@@ -458,3 +466,175 @@ void SCANNER_Stop(void)
gUpdateStatus = true;
}
static void SCANNER_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
bScanKeepFrequency = false;
gUpdateDisplay = true;
}
static void SCANNER_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 (gCurrentScanList)
{
case SCAN_NEXT_CHAN_SCANLIST1:
prev_mr_chan = gNextMrChannel;
if (chan1 >= 0)
{
if (RADIO_CheckValidChannel(chan1, false, 0))
{
gCurrentScanList = SCAN_NEXT_CHAN_SCANLIST1;
gNextMrChannel = chan1;
break;
}
}
[[fallthrough]];
case SCAN_NEXT_CHAN_SCANLIST2:
if (chan2 >= 0)
{
if (RADIO_CheckValidChannel(chan2, false, 0))
{
gCurrentScanList = 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 (chan <= MR_CHANNEL_LAST)
// {
// gCurrentScanList = SCAN_NEXT_CHAN_DUAL_WATCH;
// gNextMrChannel = chan;
// break;
// }
// }
default:
case SCAN_NEXT_CHAN_MR:
gCurrentScanList = 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;
// return;
}
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
bScanKeepFrequency = false;
if (enabled)
if (++gCurrentScanList >= SCAN_NEXT_NUM)
gCurrentScanList = SCAN_NEXT_CHAN_SCANLIST1; // back round we go
}
void SCANNER_NextChannel(const bool storeBackupSettings, const int8_t scan_direction)
{
if (storeBackupSettings) {
gRestoreCROSS_BAND_RX_TX = gEeprom.CROSS_BAND_RX_TX;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
}
RADIO_SelectVfos();
gNextMrChannel = gRxVfo->CHANNEL_SAVE;
gCurrentScanList = SCAN_NEXT_CHAN_SCANLIST1;
gScanStateDir = scan_direction;
if (gNextMrChannel <= MR_CHANNEL_LAST)
{ // channel mode
if (storeBackupSettings)
gRestoreMrChannel = gNextMrChannel;
SCANNER_NextMemChannel();
}
else
{ // frequency mode
if (storeBackupSettings)
gRestoreFrequency = gRxVfo->freq_config_RX.Frequency;
SCANNER_NextFreqChannel();
}
gScanPauseDelayIn_10ms = scan_pause_delay_in_2_10ms;
gScheduleScanListen = false;
gRxReceptionMode = RX_MODE_NONE;
gScanPauseMode = false;
bScanKeepFrequency = false;
}
void SCANNER_ContinueScanning()
{
if (IS_FREQ_CHANNEL(gNextMrChannel))
{
if (gCurrentFunction == FUNCTION_INCOMING)
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true);
else
SCANNER_NextFreqChannel(); // switch to next frequency
}
else
{
if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING)
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true);
else
SCANNER_NextMemChannel(); // switch to next channel
}
gScanPauseMode = false;
gRxReceptionMode = RX_MODE_NONE;
gScheduleScanListen = false;
}

View File

@@ -32,7 +32,9 @@ typedef enum SCAN_CssState_t SCAN_CssState_t;
enum
{
SCAN_OFF = 0,
SCAN_REV = -1,
SCAN_OFF = 0,
SCAN_FWD = +1
};
extern DCS_CodeType_t gScanCssResultType;
@@ -46,16 +48,18 @@ extern uint32_t gScanFrequency;
extern bool gScanPauseMode;
extern SCAN_CssState_t gScanCssState;
extern volatile bool gScheduleScanListen;
extern volatile uint16_t ScanPauseDelayIn_10ms;
extern volatile uint16_t gScanPauseDelayIn_10ms;
extern uint8_t gScanProgressIndicator;
extern uint8_t gScanHitCount;
extern bool gScanUseCssResult;
extern int8_t gScanState;
extern int8_t gScanStateDir;
extern bool bScanKeepFrequency;
void SCANNER_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
void SCANNER_Start(void);
void SCANNER_Stop(void);
void SCANNER_NextChannel(const bool storeBackupSettings, const int8_t scan_direction);
void SCANNER_ContinueScanning();
#endif

View File

@@ -22,19 +22,8 @@ struct FrequencyBandInfo {
uint32_t middle;
};
const struct FrequencyBandInfo FrequencyBandTable[7] = {
[BAND1_50MHz ] = {.lower = 1600000, .middle = 6500000, .upper = 7600000},
[BAND2_108MHz] = {.lower = 10800000, .middle = 12200000, .upper = 13599990},
[BAND3_136MHz] = {.lower = 13600000, .middle = 15000000, .upper = 17399990},
[BAND4_174MHz] = {.lower = 17400000, .middle = 26000000, .upper = 34999990},
[BAND5_350MHz] = {.lower = 35000000, .middle = 37000000, .upper = 39999990},
[BAND6_400MHz] = {.lower = 40000000, .middle = 43500000, .upper = 46999990},
[BAND7_470MHz] = {.lower = 47000000, .middle = 55000000, .upper = 130000000},
};
#define F_MIN FrequencyBandTable[0].lower
#define F_MAX FrequencyBandTable[ARRAY_SIZE(FrequencyBandTable) - 1].upper
#define F_MIN frequencyBandTable[0].lower
#define F_MAX frequencyBandTable[ARRAY_SIZE(frequencyBandTable) - 1].upper
const uint16_t RSSI_MAX_VALUE = 65535;
@@ -76,12 +65,12 @@ SpectrumSettings settings = {stepsCount: STEPS_64,
uint32_t fMeasure = 0;
uint32_t currentFreq, tempFreq;
uint16_t rssiHistory[128] = {};
uint16_t rssiHistory[128];
uint8_t freqInputIndex = 0;
uint8_t freqInputDotIndex = 0;
KEY_Code_t freqInputArr[10];
char freqInputString[11] = "----------\0"; // XXXX.XXXXX\0
char freqInputString[11];
uint8_t menuState = 0;
uint16_t listenT = 0;
@@ -323,7 +312,7 @@ static void ToggleAudio(bool on) {
static void ToggleRX(bool on) {
isListening = on;
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_GREEN, on);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, on);
ToggleAudio(on);
ToggleAFDAC(on);
@@ -561,7 +550,7 @@ static void UpdateFreqInput(KEY_Code_t key) {
for (int i = 0; i < 10; ++i) {
if (i < freqInputIndex) {
digitKey = freqInputArr[i];
freqInputString[i] = digitKey <= KEY_9 ? '0' + digitKey : '.';
freqInputString[i] = digitKey <= KEY_9 ? '0' + digitKey-KEY_0 : '.';
} else {
freqInputString[i] = '-';
}
@@ -569,14 +558,14 @@ static void UpdateFreqInput(KEY_Code_t key) {
uint32_t base = 100000; // 1MHz in BK units
for (int i = dotIndex - 1; i >= 0; --i) {
tempFreq += freqInputArr[i] * base;
tempFreq += (freqInputArr[i]-KEY_0) * base;
base *= 10;
}
base = 10000; // 0.1MHz in BK units
if (dotIndex < freqInputIndex) {
for (int i = dotIndex + 1; i < freqInputIndex; ++i) {
tempFreq += freqInputArr[i] * base;
tempFreq += (freqInputArr[i]-KEY_0) * base;
base /= 10;
}
}
@@ -638,19 +627,12 @@ static void DrawStatus() {
gBatteryVoltages[3]) /
4;
if (gBatteryCalibration[5] < Voltage) {
v = 5;
} else if (gBatteryCalibration[4] < Voltage) {
v = 5;
} else if (gBatteryCalibration[3] < Voltage) {
v = 4;
} else if (gBatteryCalibration[2] < Voltage) {
v = 3;
} else if (gBatteryCalibration[1] < Voltage) {
v = 2;
} else if (gBatteryCalibration[0] < Voltage) {
v = 1;
for(uint8_t i = 5; i > 0; i--) {
if(Voltage > gBatteryCalibration[i - 1]) {
v = i;
break;
}
}
gStatusLine[127] = 0b01111110;
for (int i = 126; i >= 116; i--) {
@@ -686,7 +668,7 @@ static void DrawNums() {
}
if (IsCenterMode()) {
sprintf(String, "%u.%05u \xB1%u.%02uk", currentFreq / 100000,
sprintf(String, "%u.%05u \x7F%u.%02uk", currentFreq / 100000,
currentFreq % 100000, settings.frequencyChangeStep / 100,
settings.frequencyChangeStep % 100);
GUI_DisplaySmallest(String, 36, 49, false, true);
@@ -694,7 +676,7 @@ static void DrawNums() {
sprintf(String, "%u.%05u", GetFStart() / 100000, GetFStart() % 100000);
GUI_DisplaySmallest(String, 0, 49, false, true);
sprintf(String, "\xB1%u.%02uk", settings.frequencyChangeStep / 100,
sprintf(String, "\x7F%u.%02uk", settings.frequencyChangeStep / 100,
settings.frequencyChangeStep % 100);
GUI_DisplaySmallest(String, 48, 49, false, true);
@@ -905,8 +887,8 @@ void OnKeyDownStill(KEY_Code_t key) {
break;
case KEY_PTT:
// TODO: start transmit
/* BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_GREEN, false);
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_RED, true); */
/* BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true); */
break;
case KEY_MENU:
if (menuState == ARRAY_SIZE(registerSpecs) - 1) {
@@ -1166,7 +1148,7 @@ static void Tick() {
void APP_RunSpectrum() {
// TX here coz it always? set to active VFO
currentFreq = initialFreq =
gEeprom.VfoInfo[gEeprom.TX_CHANNEL].pRX->Frequency;
gEeprom.VfoInfo[gEeprom.TX_VFO].pRX->Frequency;
BackupRegisters();

View File

@@ -48,7 +48,7 @@ typedef struct {
} Header_t;
typedef struct {
uint8_t Padding[2];
uint8_t Padding[2];
uint16_t ID;
} Footer_t;
@@ -60,10 +60,10 @@ typedef struct {
typedef struct {
Header_t Header;
struct {
char Version[16];
bool bHasCustomAesKey;
bool bIsInLockScreen;
uint8_t Padding[2];
char Version[16];
bool bHasCustomAesKey;
bool bIsInLockScreen;
uint8_t Padding[2];
uint32_t Challenge[4];
} Data;
} REPLY_0514_t;
@@ -71,8 +71,8 @@ typedef struct {
typedef struct {
Header_t Header;
uint16_t Offset;
uint8_t Size;
uint8_t Padding;
uint8_t Size;
uint8_t Padding;
uint32_t Timestamp;
} CMD_051B_t;
@@ -80,19 +80,19 @@ typedef struct {
Header_t Header;
struct {
uint16_t Offset;
uint8_t Size;
uint8_t Padding;
uint8_t Data[128];
uint8_t Size;
uint8_t Padding;
uint8_t Data[128];
} Data;
} REPLY_051B_t;
typedef struct {
Header_t Header;
uint16_t Offset;
uint8_t Size;
bool bAllowPassword;
uint8_t Size;
bool bAllowPassword;
uint32_t Timestamp;
uint8_t Data[0];
uint8_t Data[0];
} CMD_051D_t;
typedef struct {
@@ -106,8 +106,8 @@ typedef struct {
Header_t Header;
struct {
uint16_t RSSI;
uint8_t ExNoiseIndicator;
uint8_t GlitchIndicator;
uint8_t ExNoiseIndicator;
uint8_t GlitchIndicator;
} Data;
} REPLY_0527_t;
@@ -137,7 +137,10 @@ typedef struct {
uint32_t Timestamp;
} CMD_052F_t;
static const uint8_t Obfuscation[16] = { 0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80 };
static const uint8_t Obfuscation[16] =
{
0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80
};
static union
{
@@ -157,12 +160,11 @@ static void SendReply(void *pReply, uint16_t Size)
{
Header_t Header;
Footer_t Footer;
uint8_t *pBytes;
uint16_t i;
if (bIsEncrypted)
{
pBytes = (uint8_t *)pReply;
uint8_t *pBytes = (uint8_t *)pReply;
unsigned int i;
for (i = 0; i < Size; i++)
pBytes[i] ^= Obfuscation[i % 16];
}
@@ -171,6 +173,7 @@ static void SendReply(void *pReply, uint16_t Size)
Header.Size = Size;
UART_Send(&Header, sizeof(Header));
UART_Send(pReply, Size);
if (bIsEncrypted)
{
Footer.Padding[0] = Obfuscation[(Size + 0) % 16] ^ 0xFF;
@@ -205,14 +208,16 @@ static void SendVersion(void)
static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse)
{
uint8_t i;
uint32_t IV[4];
unsigned int i;
uint32_t IV[4];
IV[0] = 0;
IV[1] = 0;
IV[2] = 0;
IV[3] = 0;
AES_Encrypt(pKey, IV, pIn, IV, true);
for (i = 0; i < 4; i++)
if (IV[i] != pResponse[i])
return true;
@@ -254,10 +259,10 @@ static void CMD_051B(const uint8_t *pBuffer)
#endif
memset(&Reply, 0, sizeof(Reply));
Reply.Header.ID = 0x051C;
Reply.Header.ID = 0x051C;
Reply.Header.Size = pCmd->Size + 4;
Reply.Data.Offset = pCmd->Offset;
Reply.Data.Size = pCmd->Size;
Reply.Data.Size = pCmd->Size;
if (bHasCustomAesKey)
bLocked = gIsLocked;
@@ -294,7 +299,7 @@ static void CMD_051D(const uint8_t *pBuffer)
if (!bIsLocked)
{
uint16_t i;
unsigned int i;
for (i = 0; i < (pCmd->Size / 8); i++)
{
const uint16_t Offset = pCmd->Offset + (i * 8U);
@@ -331,23 +336,25 @@ static void CMD_0529(void)
{
REPLY_0529_t Reply;
Reply.Header.ID = 0x52A;
Reply.Header.ID = 0x52A;
Reply.Header.Size = sizeof(Reply.Data);
// Original doesn't actually send current!
BOARD_ADC_GetBatteryInfo(&Reply.Data.Voltage, &Reply.Data.Current);
SendReply(&Reply, sizeof(Reply));
}
static void CMD_052D(const uint8_t *pBuffer)
{
const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer;
REPLY_052D_t Reply;
bool bIsLocked;
REPLY_052D_t Reply;
bool bIsLocked;
#ifdef ENABLE_FMRADIO
gFmRadioCountdown_500ms = fm_radio_countdown_500ms;
#endif
Reply.Header.ID = 0x052E;
Reply.Header.ID = 0x052E;
Reply.Header.Size = sizeof(Reply.Data);
bIsLocked = bHasCustomAesKey;
@@ -385,7 +392,7 @@ static void CMD_052F(const uint8_t *pBuffer)
gEeprom.DUAL_WATCH = DUAL_WATCH_OFF;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gEeprom.RX_CHANNEL = 0;
gEeprom.RX_VFO = 0;
gEeprom.DTMF_SIDE_TONE = false;
gEeprom.VfoInfo[0].FrequencyReverse = false;
gEeprom.VfoInfo[0].pRX = &gEeprom.VfoInfo[0].freq_config_RX;
@@ -413,15 +420,13 @@ static void CMD_052F(const uint8_t *pBuffer)
bool UART_IsCommandAvailable(void)
{
uint16_t DmaLength;
uint16_t CommandLength;
uint16_t Index;
uint16_t TailIndex;
uint16_t Size;
uint16_t CRC;
uint16_t i;
uint16_t CommandLength;
uint16_t DmaLength = DMA_CH0->ST & 0xFFFU;
DmaLength = DMA_CH0->ST & 0xFFFU;
while (1)
{
if (gUART_WriteIndex == DmaLength)
@@ -450,7 +455,7 @@ bool UART_IsCommandAvailable(void)
Index = DMA_INDEX(gUART_WriteIndex, 2);
Size = (UART_DMA_Buffer[DMA_INDEX(Index, 1)] << 8) | UART_DMA_Buffer[Index];
if ((Size + 8) > sizeof(UART_DMA_Buffer))
if ((Size + 8u) > sizeof(UART_DMA_Buffer))
{
gUART_WriteIndex = DmaLength;
return false;
@@ -495,8 +500,11 @@ bool UART_IsCommandAvailable(void)
bIsEncrypted = true;
if (bIsEncrypted)
for (i = 0; i < Size + 2; i++)
{
unsigned int i;
for (i = 0; i < (Size + 2u); i++)
UART_Command.Buffer[i] ^= Obfuscation[i % 16];
}
CRC = UART_Command.Buffer[Size] | (UART_Command.Buffer[Size + 1] << 8);

View File

@@ -149,14 +149,14 @@ void AUDIO_PlayBeep(BEEP_Type_t Beep)
SYSTEM_DelayMs(60);
BK4819_EnterTxMute();
SYSTEM_DelayMs(20);
[[fallthrough]];
case BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL:
case BEEP_500HZ_60MS_DOUBLE_BEEP:
BK4819_ExitTxMute();
SYSTEM_DelayMs(60);
BK4819_EnterTxMute();
SYSTEM_DelayMs(20);
[[fallthrough]];
case BEEP_1KHZ_60MS_OPTIONAL:
BK4819_ExitTxMute();
Duration = 60;

View File

@@ -197,26 +197,27 @@ const uint8_t BITMAP_F_Key[6] =
};
#endif
const uint8_t BITMAP_TDR1[12] =
{ // "DW"
0b00000000,
const uint8_t BITMAP_TDR1[15] =
{ // "DWR"
0b01111111,
0b01000001,
0b01000001,
0b01000001,
0b00111110,
0b00000000,
0b01111111,
0b00100000,
0b00011000,
0b00100000,
0b01111111
0b01111111,
0b00000000,
0b01111111,
0b00011001,
0b00101001,
0b01000110
};
const uint8_t BITMAP_TDR2[12] =
const uint8_t BITMAP_TDR2[9] =
{ // "><" .. DW on hold
0b00000000,
0b00000000,
0b00100010,
0b00110110,
0b00011100,
@@ -226,7 +227,6 @@ const uint8_t BITMAP_TDR2[12] =
0b00011100,
0b00110110,
0b00100010,
0b00000000
};
#ifdef ENABLE_VOICE
@@ -244,27 +244,8 @@ const uint8_t BITMAP_TDR2[12] =
};
#endif
#ifdef ENABLE_FMRADIO
const uint8_t BITMAP_FM[12] =
{ // "FM"
0b00000000,
0b01111111,
0b00001001,
0b00001001,
0b00001001,
0b00000001,
0b00000000,
0b01111111,
0b00000010,
0b00001100,
0b00000010,
0b01111111
};
#endif
#ifdef ENABLE_NOAA
const uint8_t BITMAP_NOAA[12] =
const uint8_t BITMAP_NOAA[11] =
{ // "NS"
0b00000000,
0b01111111,
@@ -272,63 +253,14 @@ const uint8_t BITMAP_TDR2[12] =
0b00001000,
0b00010000,
0b01111111,
0b00000000,
0b01000110,
0b01001001,
0b01001001,
0b01001001,
0b00110001
};
#endif
/*
const uint8_t BITMAP_SC1[8] =
{ // "I"
0b01000001,
0b01000001,
0b01111111,
0b01111111,
0b01111111,
0b01000001,
0b01000001,
0b00000000
};
const uint8_t BITMAP_SC2[8] =
{ // "II"
0b01000001,
0b01111111,
0b01111111,
0b01000001,
0b01111111,
0b01111111,
0b01000001,
0b00000000
};
*/
/*
const uint8_t BITMAP_SC1[7] =
{ // "1"
0b01000000,
0b01000000,
0b01000110,
0b01111111,
0b01000000,
0b01000000,
0b00000000
};
const uint8_t BITMAP_SC2[7] =
{ // "2"
0b01000010,
0b01100001,
0b01010001,
0b01001001,
0b01001001,
0b01000110,
0b00000000
};
*/
const uint8_t BITMAP_Antenna[5] =
{
0b00000011,

View File

@@ -25,32 +25,19 @@ extern const uint8_t BITMAP_F_Key[6];
extern const uint8_t BITMAP_VOX[18];
#endif
#if 0
extern const uint8_t BITMAP_WX[12];
#else
extern const uint8_t BITMAP_XB[12];
#endif
extern const uint8_t BITMAP_XB[12];
extern const uint8_t BITMAP_TDR1[12];
extern const uint8_t BITMAP_TDR2[12];
extern const uint8_t BITMAP_TDR1[15];
extern const uint8_t BITMAP_TDR2[9];
#ifdef ENABLE_VOICE
extern const uint8_t BITMAP_VoicePrompt[9];
#endif
#ifdef ENABLE_FMRADIO
extern const uint8_t BITMAP_FM[12];
#endif
#ifdef ENABLE_NOAA
extern const uint8_t BITMAP_NOAA[12];
extern const uint8_t BITMAP_NOAA[11];
#endif
//extern const uint8_t BITMAP_SC1[8];
//extern const uint8_t BITMAP_SC2[8];
//extern const uint8_t BITMAP_SC1[7];
//extern const uint8_t BITMAP_SC2[7];
extern const uint8_t BITMAP_Antenna[5];
extern const uint8_t BITMAP_AntennaLevel1[3];
extern const uint8_t BITMAP_AntennaLevel2[3];

26
board.c
View File

@@ -509,7 +509,7 @@ void BOARD_Init(void)
BOARD_PORTCON_Init();
BOARD_GPIO_Init();
BOARD_ADC_Init();
ST7565_Init();
ST7565_Init(true);
#ifdef ENABLE_FMRADIO
BK1080_Init(0, false);
#endif
@@ -590,7 +590,8 @@ void BOARD_EEPROM_Init(void)
// 0E90..0E97
EEPROM_ReadBuffer(0x0E90, Data, 8);
gEeprom.BEEP_CONTROL = (Data[0] < 2) ? Data[0] : true;
gEeprom.BEEP_CONTROL = Data[0] & 1;
gEeprom.KEY_M_LONG_PRESS_ACTION = ((Data[0] >> 1) < ACTION_OPT_LEN) ? (Data[0] >> 1) : ACTION_OPT_NONE;
gEeprom.KEY_1_SHORT_PRESS_ACTION = (Data[1] < ACTION_OPT_LEN) ? Data[1] : ACTION_OPT_MONITOR;
gEeprom.KEY_1_LONG_PRESS_ACTION = (Data[2] < ACTION_OPT_LEN) ? Data[2] : ACTION_OPT_FLASHLIGHT;
gEeprom.KEY_2_SHORT_PRESS_ACTION = (Data[3] < ACTION_OPT_LEN) ? Data[3] : ACTION_OPT_SCAN;
@@ -616,7 +617,7 @@ 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_CHANNEL = (Data[3] < 2) ? Data[3] : 0;
gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0;
// 0ED0..0ED7
EEPROM_ReadBuffer(0x0ED0, Data, 8);
@@ -687,7 +688,8 @@ void BOARD_EEPROM_Init(void)
// 0F18..0F1F
EEPROM_ReadBuffer(0x0F18, Data, 8);
gEeprom.SCAN_LIST_DEFAULT = (Data[0] < 2) ? Data[0] : false;
// gEeprom.SCAN_LIST_DEFAULT = (Data[0] < 2) ? Data[0] : false;
gEeprom.SCAN_LIST_DEFAULT = (Data[0] < 3) ? Data[0] : false; // we now have 'all' channel scan option
for (i = 0; i < 2; i++)
{
const unsigned int j = 1 + (i * 3);
@@ -738,18 +740,18 @@ void BOARD_EEPROM_Init(void)
}
}
void BOARD_EEPROM_LoadMoreSettings(void)
void BOARD_EEPROM_LoadCalibration(void)
{
// uint8_t Mic;
EEPROM_ReadBuffer(0x1EC0, gEEPROM_1EC0_0, 8);
memmove(gEEPROM_1EC0_1, gEEPROM_1EC0_0, 8);
memmove(gEEPROM_1EC0_2, gEEPROM_1EC0_0, 8);
memmove(gEEPROM_1EC0_3, gEEPROM_1EC0_0, 8);
EEPROM_ReadBuffer(0x1EC0, gEEPROM_RSSI_CALIB[3], 8);
memcpy(gEEPROM_RSSI_CALIB[4], gEEPROM_RSSI_CALIB[3], 8);
memcpy(gEEPROM_RSSI_CALIB[5], gEEPROM_RSSI_CALIB[3], 8);
memcpy(gEEPROM_RSSI_CALIB[6], gEEPROM_RSSI_CALIB[3], 8);
// 8 * 16-bit values
EEPROM_ReadBuffer(0x1EC0, gEEPROM_RSSI_CALIB[0], 8);
EEPROM_ReadBuffer(0x1EC8, gEEPROM_RSSI_CALIB[1], 8);
EEPROM_ReadBuffer(0x1EC8, gEEPROM_RSSI_CALIB[0], 8);
memcpy(gEEPROM_RSSI_CALIB[1], gEEPROM_RSSI_CALIB[0], 8);
memcpy(gEEPROM_RSSI_CALIB[2], gEEPROM_RSSI_CALIB[0], 8);
EEPROM_ReadBuffer(0x1F40, gBatteryCalibration, 12);
if (gBatteryCalibration[0] >= 5000)

View File

@@ -27,7 +27,7 @@ void BOARD_ADC_Init(void);
void BOARD_ADC_GetBatteryInfo(uint16_t *pVoltage, uint16_t *pCurrent);
void BOARD_Init(void);
void BOARD_EEPROM_Init(void);
void BOARD_EEPROM_LoadMoreSettings(void);
void BOARD_EEPROM_LoadCalibration(void);
uint32_t BOARD_fetchChannelFrequency(const int channel);
void BOARD_fetchChannelName(char *s, const int channel);
void BOARD_FactoryReset(bool bIsAll);

2
compile-with-docker.sh Normal file → Executable file
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 -v ${PWD}/compiled-firmware:/app/compiled-firmware uvk5 /bin/bash -c "cd /app && make && cp firmware* compiled-firmware/"

View File

@@ -134,9 +134,9 @@ void ADC_Configure(ADC_Config_t *pAdc)
;
if (SARADC_IE == 0) {
NVIC_DisableIRQ(DP32_SARADC_IRQn);
NVIC_DisableIRQ((IRQn_Type)DP32_SARADC_IRQn);
} else {
NVIC_EnableIRQ(DP32_SARADC_IRQn);
NVIC_EnableIRQ((IRQn_Type)DP32_SARADC_IRQn);
}
}

View File

@@ -24,6 +24,8 @@ static void AES_Setup_ENC_CBC(bool IsDecrypt, const void *pKey, const void *pIv)
const uint32_t *pK = (const uint32_t *)pKey;
const uint32_t *pI = (const uint32_t *)pIv;
(void)IsDecrypt; // unused
AES_CR = (AES_CR & ~AES_CR_EN_MASK) | AES_CR_EN_BITS_DISABLE;
AES_CR = AES_CR_CHMOD_BITS_CBC;
AES_KEYR3 = pK[0];

View File

@@ -95,13 +95,12 @@ enum BK4819_REGISTER_t {
typedef enum BK4819_REGISTER_t BK4819_REGISTER_t;
enum BK4819_GPIO_PIN_t {
BK4819_GPIO6_PIN2 = 0,
BK4819_GPIO5_PIN1 = 1,
BK4819_GPIO4_PIN32 = 2,
BK4819_GPIO0_PIN28 = 0,
BK4819_GPIO1_PIN29 = 1,
BK4819_GPIO3_PIN31 = 3,
BK4819_GPIO2_PIN30 = 4,
BK4819_GPIO1_PIN29_RED = 5,
BK4819_GPIO0_PIN28_GREEN = 6,
BK4819_GPIO4_PIN32 = 4,
BK4819_GPIO5_PIN1_RED = 5,
BK4819_GPIO6_PIN2_GREEN = 6,
};
typedef enum BK4819_GPIO_PIN_t BK4819_GPIO_PIN_t;

File diff suppressed because it is too large Load Diff

View File

@@ -102,6 +102,7 @@ void BK4819_DisableVox(void);
void BK4819_DisableDTMF(void);
void BK4819_EnableDTMF(void);
void BK4819_PlayTone(uint16_t Frequency, bool bTuningGainSwitch);
void BK4819_PlaySingleTone(const unsigned int tone_Hz, const unsigned int delay, const unsigned int level, const bool play_speaker);
void BK4819_EnterTxMute(void);
void BK4819_ExitTxMute(void);
void BK4819_Sleep(void);

View File

@@ -14,6 +14,9 @@
* limitations under the License.
*/
#include <stddef.h>
#include <string.h>
#include "driver/eeprom.h"
#include "driver/i2c.h"
#include "driver/system.h"
@@ -38,16 +41,22 @@ void EEPROM_ReadBuffer(uint16_t Address, void *pBuffer, uint8_t Size)
void EEPROM_WriteBuffer(uint16_t Address, const void *pBuffer)
{
I2C_Start();
if (pBuffer == NULL || Address >= 0x2000)
return;
I2C_Write(0xA0);
I2C_Write((Address >> 8) & 0xFF);
I2C_Write((Address >> 0) & 0xFF);
uint8_t buffer[8];
EEPROM_ReadBuffer(Address, buffer, 8);
if (memcmp(pBuffer, buffer, 8) != 0)
{
I2C_Start();
I2C_Write(0xA0);
I2C_Write((Address >> 8) & 0xFF);
I2C_Write((Address >> 0) & 0xFF);
I2C_WriteBuffer(pBuffer, 8);
I2C_Stop();
}
I2C_WriteBuffer(pBuffer, 8);
I2C_Stop();
SYSTEM_DelayMs(10);
// give the EEPROM time to burn the data in (apparently takes 5ms)
SYSTEM_DelayMs(8);
}

View File

@@ -58,10 +58,10 @@ enum GPIOC_PINS {
GPIOC_PIN_PTT = 5
};
void GPIO_ClearBit(volatile uint32_t *pReg, uint8_t Bit);
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);
void GPIO_FlipBit( volatile uint32_t *pReg, uint8_t Bit);
void GPIO_SetBit( volatile uint32_t *pReg, uint8_t Bit);
#endif

View File

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

View File

@@ -21,30 +21,29 @@
#include <stdbool.h>
#include <stdint.h>
enum KEY_Code_t {
KEY_0 = 0,
KEY_1 = 1,
KEY_2 = 2,
KEY_3 = 3,
KEY_4 = 4,
KEY_5 = 5,
KEY_6 = 6,
KEY_7 = 7,
KEY_8 = 8,
KEY_9 = 9,
KEY_MENU = 10,
KEY_UP = 11,
KEY_DOWN = 12,
KEY_EXIT = 13,
KEY_STAR = 14,
KEY_F = 15,
KEY_PTT = 21,
KEY_SIDE2 = 22,
KEY_SIDE1 = 23,
KEY_INVALID = 255
enum KEY_Code_e {
KEY_0 = 0, // 0
KEY_1, // 1
KEY_2, // 2
KEY_3, // 3
KEY_4, // 4
KEY_5, // 5
KEY_6, // 6
KEY_7, // 7
KEY_8, // 8
KEY_9, // 9
KEY_MENU, // A
KEY_UP, // B
KEY_DOWN, // C
KEY_EXIT, // D
KEY_STAR, // *
KEY_F, // #
KEY_PTT, //
KEY_SIDE2, //
KEY_SIDE1, //
KEY_INVALID //
};
typedef enum KEY_Code_t KEY_Code_t;
typedef enum KEY_Code_e KEY_Code_t;
extern KEY_Code_t gKeyReading0;
extern KEY_Code_t gKeyReading1;

View File

@@ -93,9 +93,9 @@ void SPI_Configure(volatile SPI_Port_t *pPort, SPI_Config_t *pConfig)
if (pPort->IE) {
if (pPort == SPI0) {
NVIC_EnableIRQ(DP32_SPI0_IRQn);
NVIC_EnableIRQ((IRQn_Type)DP32_SPI0_IRQn);
} else if (pPort == SPI1) {
NVIC_EnableIRQ(DP32_SPI1_IRQn);
NVIC_EnableIRQ((IRQn_Type)DP32_SPI1_IRQn);
}
}
}

View File

@@ -82,10 +82,10 @@ void ST7565_BlitFullScreen(void)
}
#if 0
// whats the delay for I wonder ? .. it slows down scanning :(
// whats the delay for I wonder, it holds things up :(
SYSTEM_DelayMs(20);
#else
SYSTEM_DelayMs(1);
// SYSTEM_DelayMs(1);
#endif
SPI_ToggleMasterMode(&SPI0->CR, true);
@@ -119,7 +119,11 @@ void ST7565_FillScreen(uint8_t Value)
{
unsigned int i;
// reset some of the displays settings to try and overcome the radios hardware problem - RF corrupting the display
ST7565_Init(false);
SPI_ToggleMasterMode(&SPI0->CR, false);
for (i = 0; i < 8; i++)
{
unsigned int j;
@@ -132,20 +136,26 @@ void ST7565_FillScreen(uint8_t Value)
}
SPI_WaitForUndocumentedTxFifoStatusBit();
}
SPI_ToggleMasterMode(&SPI0->CR, true);
}
void ST7565_Init(void)
void ST7565_Init(const bool full)
{
SPI0_Init();
if (full)
{
SPI0_Init();
ST7565_Configure_GPIO_B11();
ST7565_HardwareReset();
SPI_ToggleMasterMode(&SPI0->CR, false);
SPI_ToggleMasterMode(&SPI0->CR, false);
ST7565_WriteByte(0xE2); // internal reset
ST7565_WriteByte(0xE2); // internal reset
SYSTEM_DelayMs(120);
SYSTEM_DelayMs(120);
}
else
SPI_ToggleMasterMode(&SPI0->CR, false);
ST7565_WriteByte(0xA2); // bias 9
ST7565_WriteByte(0xC0); // com normal
@@ -157,21 +167,26 @@ void ST7565_Init(void)
ST7565_WriteByte(0xA4); // all points normal
ST7565_WriteByte(0x24); //
ST7565_WriteByte(0x81); // volume first ?
ST7565_WriteByte(0x1f); // contrast ?
ST7565_WriteByte(0x2B); // power control ?
SYSTEM_DelayMs(1);
if (full)
{
ST7565_WriteByte(0x2B); // power control ?
ST7565_WriteByte(0x2E); // power control ?
SYSTEM_DelayMs(1);
SYSTEM_DelayMs(1);
ST7565_WriteByte(0x2E); // power control ?
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
SYSTEM_DelayMs(1);
SYSTEM_DelayMs(40);
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
ST7565_WriteByte(0x2F); //
SYSTEM_DelayMs(40);
}
ST7565_WriteByte(0x40); // start line ?
ST7565_WriteByte(0xAF); // display on ?
@@ -180,10 +195,11 @@ void ST7565_Init(void)
SPI_ToggleMasterMode(&SPI0->CR, true);
ST7565_FillScreen(0x00);
if (full)
ST7565_FillScreen(0x00);
}
void ST7565_Configure_GPIO_B11(void)
void ST7565_HardwareReset(void)
{
GPIO_SetBit(&GPIOB->DATA, GPIOB_PIN_ST7565_RES);
SYSTEM_DelayMs(1);

View File

@@ -30,8 +30,8 @@ void ST7565_DrawLine(const unsigned int Column, const unsigned int Line, const u
void ST7565_BlitFullScreen(void);
void ST7565_BlitStatusLine(void);
void ST7565_FillScreen(uint8_t Value);
void ST7565_Init(void);
void ST7565_Configure_GPIO_B11(void);
void ST7565_Init(const bool full);
void ST7565_HardwareReset(void);
void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line);
void ST7565_WriteByte(uint8_t Value);

View File

@@ -29,26 +29,17 @@ void SYSTICK_Init(void)
void SYSTICK_DelayUs(uint32_t Delay)
{
uint32_t i;
uint32_t Start;
uint32_t Previous;
uint32_t Current;
uint32_t Delta;
i = 0;
Start = SysTick->LOAD;
Previous = SysTick->VAL;
const uint32_t ticks = Delay * gTickMultiplier;
uint32_t i = 0;
uint32_t Start = SysTick->LOAD;
uint32_t Previous = SysTick->VAL;
do {
do {
Current = SysTick->VAL;
} while (Current == Previous);
if (Current < Previous) {
Delta = -Current;
} else {
Delta = Start - Current;
}
i += Delta + Previous;
uint32_t Current;
uint32_t Delta;
while ((Current = SysTick->VAL) == Previous) {}
Delta = (Current < Previous) ? -Current : Start - Current;
i += Delta + Previous;
Previous = Current;
} while (i < Delay * gTickMultiplier);
} while (i < ticks);
}

694
font.c
View File

@@ -16,104 +16,203 @@
#include "font.h"
//const uint8_t gFontBig[95][16] =
const uint8_t gFontBig[95][15] =
// removed last and middle column which was all 0x00
// also the space char is not needed
const uint8_t gFontBig[95 - 1][16 - 2] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // ' '
{0x00, 0x00, 0x70, 0xF8, 0xF8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '!'
{0x00, 0x1E, 0x3E, 0x00, 0x00, 0x3E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '"'
{0x40, 0xF0, 0xF0, 0x40, 0xF0, 0xF0, 0x40, 0x00, 0x04, 0x1F, 0x1F, 0x04, 0x1F, 0x1F, 0x04}, // , 0x00}, // '#'
{0x70, 0xF8, 0x88, 0x8F, 0x8F, 0x98, 0x30, 0x00, 0x06, 0x0C, 0x08, 0x38, 0x38, 0x0F, 0x07}, // , 0x00}, // '$'
{0x60, 0x60, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x00, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x18, 0x18}, // , 0x00}, // '%'
{0x00, 0xB0, 0xF8, 0xC8, 0x78, 0xB0, 0x80, 0x00, 0x0F, 0x1F, 0x10, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // '&'
{0x00, 0x20, 0x3E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '''
{0x00, 0x00, 0xE0, 0xF0, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x00}, // , 0x00}, // '('
{0x00, 0x00, 0x08, 0x18, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x0F, 0x07, 0x00}, // , 0x00}, // ')'
{0x00, 0x40, 0xC0, 0x80, 0x80, 0xC0, 0x40, 0x00, 0x01, 0x05, 0x07, 0x03, 0x03, 0x07, 0x05}, // , 0x01}, // '*'
{0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x07, 0x07, 0x01, 0x01}, // , 0x00}, // '+'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x1C, 0x00, 0x00}, // , 0x00}, // ','
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, // , 0x00}, // '-'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, // , 0x00}, // '.'
{0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x00, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00}, // , 0x00}, // '/'
{0xF0, 0xF8, 0x08, 0x88, 0x48, 0xF8, 0xF0, 0x00, 0x0F, 0x1F, 0x12, 0x11, 0x10, 0x1F, 0x0F}, // , 0x00}, // '0'
{0x00, 0x20, 0x30, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10}, // , 0x00}, // '1'
{0x10, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x30, 0x00, 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x18}, // , 0x00}, // '2'
{0x10, 0x18, 0x88, 0x88, 0x88, 0xF8, 0x70, 0x00, 0x08, 0x18, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '3'
{0x80, 0xC0, 0x60, 0x30, 0xF8, 0xF8, 0x00, 0x00, 0x01, 0x01, 0x01, 0x11, 0x1F, 0x1F, 0x11}, // , 0x00}, // '4'
{0xF8, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, 0x00, 0x08, 0x18, 0x10, 0x10, 0x11, 0x1F, 0x0F}, // , 0x00}, // '5'
{0xE0, 0xF0, 0x98, 0x88, 0x88, 0x80, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '6'
{0x18, 0x18, 0x08, 0x08, 0x88, 0xF8, 0x78, 0x00, 0x00, 0x00, 0x1E, 0x1F, 0x01, 0x00, 0x00}, // , 0x00}, // '7'
{0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0x70, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '8'
{0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0xF0, 0x00, 0x00, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // '9'
{0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // , 0x00}, // ':'
{0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x0C, 0x00, 0x00}, // , 0x00}, // ';'
{0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x10, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0C, 0x18, 0x10}, // , 0x00}, // '<'
{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, // , 0x00}, // '='
{0x00, 0x10, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x01}, // , 0x00}, // '>'
{0x30, 0x38, 0x08, 0x88, 0xC8, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '?'
{0xE0, 0xF0, 0x10, 0x90, 0x90, 0xF0, 0xE0, 0x00, 0x0F, 0x1F, 0x10, 0x17, 0x17, 0x17, 0x03}, // , 0x00}, // '@'
{0xC0, 0xE0, 0x30, 0x18, 0x30, 0xE0, 0xC0, 0x00, 0x1F, 0x1F, 0x01, 0x01, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'A'
{0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'B'
{0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x10, 0x18, 0x0C}, // , 0x00}, // 'C'
{0x08, 0xF8, 0xF8, 0x08, 0x18, 0xF0, 0xE0, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'D'
{0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x11, 0x18, 0x1C}, // , 0x00}, // 'E'
{0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x01, 0x00, 0x00}, // , 0x00}, // 'F'
{0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, 0x00, 0x07, 0x0F, 0x18, 0x11, 0x11, 0x0F, 0x1F}, // , 0x00}, // 'G'
{0xF8, 0xF8, 0x80, 0x80, 0x80, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'H'
{0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'I'
{0x00, 0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, 0x00, 0x0E, 0x1E, 0x10, 0x10, 0x1F, 0x0F, 0x00}, // , 0x00}, // 'J'
{0x08, 0xF8, 0xF8, 0x80, 0xE0, 0x78, 0x18, 0x00, 0x10, 0x1F, 0x1F, 0x01, 0x03, 0x1E, 0x1C}, // , 0x00}, // 'K'
{0x08, 0xF8, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x18, 0x1C}, // , 0x00}, // 'L'
{0xF8, 0xF8, 0x70, 0xE0, 0x70, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'M'
{0xF8, 0xF8, 0x70, 0xE0, 0xC0, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'N'
{0xE0, 0xF0, 0x18, 0x08, 0x18, 0xF0, 0xE0, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'O'
{0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'P'
{0xF0, 0xF8, 0x08, 0x08, 0x08, 0xF8, 0xF0, 0x00, 0x0F, 0x1F, 0x10, 0x1C, 0x78, 0x7F, 0x4F}, // , 0x00}, // 'Q'
{0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, 0x00, 0x10, 0x1F, 0x1F, 0x00, 0x01, 0x1F, 0x1E}, // , 0x00}, // 'R'
{0x30, 0x78, 0xC8, 0x88, 0x88, 0x38, 0x30, 0x00, 0x0C, 0x1C, 0x10, 0x10, 0x11, 0x1F, 0x0E}, // , 0x00}, // 'S'
{0x00, 0x38, 0x18, 0xF8, 0xF8, 0x18, 0x38, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'T'
{0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'U'
{0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x03, 0x07, 0x0C, 0x18, 0x0C, 0x07, 0x03}, // , 0x00}, // 'V'
{0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x07, 0x1F, 0x1C, 0x07, 0x1C, 0x1F, 0x07}, // , 0x00}, // 'W'
{0x18, 0x78, 0xE0, 0x80, 0xE0, 0x78, 0x18, 0x00, 0x18, 0x1E, 0x07, 0x01, 0x07, 0x1E, 0x18}, // , 0x00}, // 'X'
{0x00, 0x78, 0xF8, 0x80, 0x80, 0xF8, 0x78, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'Y'
{0x38, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x38, 0x00, 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x1C}, // , 0x00}, // 'Z'
{0x00, 0x00, 0xF8, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x10, 0x10, 0x00}, // , 0x00}, // '['
{0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x1C}, // , 0x00}, // '"\'
{0x00, 0x00, 0x08, 0x08, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x00}, // , 0x00}, // ']'
{0x10, 0x18, 0x0E, 0x07, 0x0E, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '^'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // , 0x40}, // '_'
{0x00, 0x00, 0x07, 0x0F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '`'
{0x00, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x0E, 0x1F, 0x11, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'a'
{0x08, 0xF8, 0xF8, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x10, 0x1F, 0x0F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'b'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x18, 0x08}, // , 0x00}, // 'c'
{0x00, 0x80, 0xC0, 0x48, 0xF8, 0xF8, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'd'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x0F, 0x1F, 0x11, 0x11, 0x11, 0x19, 0x09}, // , 0x00}, // 'e'
{0x80, 0xF0, 0xF8, 0x88, 0x18, 0x30, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'f'
{0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, 0x00, 0x4F, 0xDF, 0x90, 0x90, 0xFF, 0x7F, 0x00}, // , 0x00}, // 'g'
{0x08, 0xF8, 0xF8, 0x80, 0x40, 0xC0, 0x80, 0x00, 0x10, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'h'
{0x00, 0x00, 0x40, 0xD8, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'i'
{0x00, 0x00, 0x00, 0x00, 0x40, 0xD8, 0xD8, 0x00, 0x00, 0x60, 0xE0, 0x80, 0x80, 0xFF, 0x7F}, // , 0x00}, // 'j'
{0x08, 0xF8, 0xF8, 0x00, 0x80, 0xC0, 0x40, 0x00, 0x10, 0x1F, 0x1F, 0x03, 0x07, 0x1C, 0x18}, // , 0x00}, // 'k'
{0x00, 0x00, 0x08, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'l'
{0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x80, 0x00, 0x1F, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'm'
{0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'n'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'o'
{0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x80, 0xFF, 0xFF, 0x90, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'p'
{0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, 0x00, 0x0F, 0x1F, 0x10, 0x90, 0xFF, 0xFF, 0x80}, // , 0x00}, // 'q'
{0x40, 0xC0, 0x80, 0xC0, 0x40, 0xC0, 0x80, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x01}, // , 0x00}, // 'r'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x08, 0x19, 0x13, 0x12, 0x16, 0x1C, 0x08}, // , 0x00}, // 's'
{0x40, 0x40, 0xF0, 0xF8, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x18, 0x08}, // , 0x00}, // 't'
{0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'u'
{0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x07, 0x0F, 0x18, 0x18, 0x0F, 0x07}, // , 0x00}, // 'v'
{0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x0F, 0x1F, 0x18, 0x0E, 0x18, 0x1F, 0x0F}, // , 0x00}, // 'w'
{0x40, 0xC0, 0x80, 0x00, 0x80, 0xC0, 0x40, 0x00, 0x10, 0x18, 0x0F, 0x07, 0x0F, 0x18, 0x10}, // , 0x00}, // 'x'
{0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x8F, 0x9F, 0x90, 0x90, 0xD0, 0x7F, 0x3F}, // , 0x00}, // 'y'
{0xC0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0x40, 0x00, 0x18, 0x1C, 0x16, 0x13, 0x11, 0x18, 0x18}, // , 0x00}, // 'z'
{0x00, 0x80, 0x80, 0xF0, 0x78, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10}, // , 0x00}, // '{'
{0x00, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00}, // , 0x00}, // '|'
{0x00, 0x08, 0x08, 0x78, 0xF0, 0x80, 0x80, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x0F, 0x00, 0x00}, // , 0x00}, // '}'
{0x10, 0x18, 0x08, 0x18, 0x10, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // , 0x00} // '->'
#if 0
// {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // ' '
{0x00, 0x00, 0x70, 0xF8, 0xF8, 0x70, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '!'
{0x00, 0x1E, 0x3E, 0x00, 0x00, 0x3E, 0x1E, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '"'
{0x40, 0xF0, 0xF0, 0x40, 0xF0, 0xF0, 0x40, /*0x00,*/ 0x04, 0x1F, 0x1F, 0x04, 0x1F, 0x1F, 0x04}, // , 0x00}, // '#'
{0x70, 0xF8, 0x88, 0x8F, 0x8F, 0x98, 0x30, /*0x00,*/ 0x06, 0x0C, 0x08, 0x38, 0x38, 0x0F, 0x07}, // , 0x00}, // '$'
{0x60, 0x60, 0x00, 0x00, 0x80, 0xC0, 0x60, /*0x00,*/ 0x18, 0x0C, 0x06, 0x03, 0x01, 0x18, 0x18}, // , 0x00}, // '%'
{0x00, 0xB0, 0xF8, 0xC8, 0x78, 0xB0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // '&'
{0x00, 0x20, 0x3E, 0x1E, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '''
{0x00, 0x00, 0xE0, 0xF0, 0x18, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x07, 0x0F, 0x18, 0x10, 0x00}, // , 0x00}, // '('
{0x00, 0x00, 0x08, 0x18, 0xF0, 0xE0, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x18, 0x0F, 0x07, 0x00}, // , 0x00}, // ')'
{0x00, 0x40, 0xC0, 0x80, 0x80, 0xC0, 0x40, /*0x00,*/ 0x01, 0x05, 0x07, 0x03, 0x03, 0x07, 0x05}, // , 0x01}, // '*'
{0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, /*0x00,*/ 0x00, 0x01, 0x01, 0x07, 0x07, 0x01, 0x01}, // , 0x00}, // '+'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x20, 0x3C, 0x1C, 0x00, 0x00}, // , 0x00}, // ','
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, // , 0x00}, // '-'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00}, // , 0x00}, // '.'
{0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, /*0x00,*/ 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00}, // , 0x00}, // '/'
{0xF0, 0xF8, 0x08, 0x88, 0x48, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x1F, 0x12, 0x11, 0x10, 0x1F, 0x0F}, // , 0x00}, // '0'
{0x00, 0x20, 0x30, 0xF8, 0xF8, 0x00, 0x00, /*0x00,*/ 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10}, // , 0x00}, // '1'
{0x10, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x30, /*0x00,*/ 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x18}, // , 0x00}, // '2'
{0x10, 0x18, 0x88, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x08, 0x18, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '3'
{0x80, 0xC0, 0x60, 0x30, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x01, 0x01, 0x01, 0x11, 0x1F, 0x1F, 0x11}, // , 0x00}, // '4'
{0xF8, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, /*0x00,*/ 0x08, 0x18, 0x10, 0x10, 0x11, 0x1F, 0x0F}, // , 0x00}, // '5'
{0xE0, 0xF0, 0x98, 0x88, 0x88, 0x80, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '6'
{0x18, 0x18, 0x08, 0x08, 0x88, 0xF8, 0x78, /*0x00,*/ 0x00, 0x00, 0x1E, 0x1F, 0x01, 0x00, 0x00}, // , 0x00}, // '7'
{0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // '8'
{0x70, 0xF8, 0x88, 0x88, 0x88, 0xF8, 0xF0, /*0x00,*/ 0x00, 0x10, 0x10, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // '9'
{0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // , 0x00}, // ':'
{0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1C, 0x0C, 0x00, 0x00}, // , 0x00}, // ';'
{0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x10, /*0x00,*/ 0x00, 0x01, 0x03, 0x06, 0x0C, 0x18, 0x10}, // , 0x00}, // '<'
{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /*0x00,*/ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, // , 0x00}, // '='
{0x00, 0x10, 0x30, 0x60, 0xC0, 0x80, 0x00, /*0x00,*/ 0x00, 0x10, 0x18, 0x0C, 0x06, 0x03, 0x01}, // , 0x00}, // '>'
{0x30, 0x38, 0x08, 0x88, 0xC8, 0x78, 0x30, /*0x00,*/ 0x00, 0x00, 0x00, 0x1B, 0x1B, 0x00, 0x00}, // , 0x00}, // '?'
{0xE0, 0xF0, 0x10, 0x90, 0x90, 0xF0, 0xE0, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x17, 0x17, 0x17, 0x03}, // , 0x00}, // '@'
{0xC0, 0xE0, 0x30, 0x18, 0x30, 0xE0, 0xC0, /*0x00,*/ 0x1F, 0x1F, 0x01, 0x01, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'A'
{0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'B'
{0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, /*0x00,*/ 0x07, 0x0F, 0x18, 0x10, 0x10, 0x18, 0x0C}, // , 0x00}, // 'C'
{0x08, 0xF8, 0xF8, 0x08, 0x18, 0xF0, 0xE0, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'D'
{0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x11, 0x18, 0x1C}, // , 0x00}, // 'E'
{0x08, 0xF8, 0xF8, 0x88, 0xC8, 0x18, 0x38, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x01, 0x00, 0x00}, // , 0x00}, // 'F'
{0xE0, 0xF0, 0x18, 0x08, 0x08, 0x18, 0x30, /*0x00,*/ 0x07, 0x0F, 0x18, 0x11, 0x11, 0x0F, 0x1F}, // , 0x00}, // 'G'
{0xF8, 0xF8, 0x80, 0x80, 0x80, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'H'
{0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'I'
{0x00, 0x00, 0x00, 0x08, 0xF8, 0xF8, 0x08, /*0x00,*/ 0x0E, 0x1E, 0x10, 0x10, 0x1F, 0x0F, 0x00}, // , 0x00}, // 'J'
{0x08, 0xF8, 0xF8, 0x80, 0xE0, 0x78, 0x18, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x01, 0x03, 0x1E, 0x1C}, // , 0x00}, // 'K'
{0x08, 0xF8, 0xF8, 0x08, 0x00, 0x00, 0x00, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x18, 0x1C}, // , 0x00}, // 'L'
{0xF8, 0xF8, 0x70, 0xE0, 0x70, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'M'
{0xF8, 0xF8, 0x70, 0xE0, 0xC0, 0xF8, 0xF8, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x00, 0x01, 0x1F, 0x1F}, // , 0x00}, // 'N'
{0xE0, 0xF0, 0x18, 0x08, 0x18, 0xF0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x18, 0x10, 0x18, 0x0F, 0x07}, // , 0x00}, // 'O'
{0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'P'
{0xF0, 0xF8, 0x08, 0x08, 0x08, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x1C, 0x78, 0x7F, 0x4F}, // , 0x00}, // 'Q'
{0x08, 0xF8, 0xF8, 0x88, 0x88, 0xF8, 0x70, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x00, 0x01, 0x1F, 0x1E}, // , 0x00}, // 'R'
{0x30, 0x78, 0xC8, 0x88, 0x88, 0x38, 0x30, /*0x00,*/ 0x0C, 0x1C, 0x10, 0x10, 0x11, 0x1F, 0x0E}, // , 0x00}, // 'S'
{0x00, 0x38, 0x18, 0xF8, 0xF8, 0x18, 0x38, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'T'
{0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'U'
{0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x03, 0x07, 0x0C, 0x18, 0x0C, 0x07, 0x03}, // , 0x00}, // 'V'
{0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, /*0x00,*/ 0x07, 0x1F, 0x1C, 0x07, 0x1C, 0x1F, 0x07}, // , 0x00}, // 'W'
{0x18, 0x78, 0xE0, 0x80, 0xE0, 0x78, 0x18, /*0x00,*/ 0x18, 0x1E, 0x07, 0x01, 0x07, 0x1E, 0x18}, // , 0x00}, // 'X'
{0x00, 0x78, 0xF8, 0x80, 0x80, 0xF8, 0x78, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'Y'
{0x38, 0x18, 0x08, 0x88, 0xC8, 0x78, 0x38, /*0x00,*/ 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x18, 0x1C}, // , 0x00}, // 'Z'
{0x00, 0x00, 0xF8, 0xF8, 0x08, 0x08, 0x00, /*0x00,*/ 0x00, 0x00, 0x1F, 0x1F, 0x10, 0x10, 0x00}, // , 0x00}, // '['
{0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x1C}, // , 0x00}, // '"\'
{0x00, 0x00, 0x08, 0x08, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x00}, // , 0x00}, // ']'
{0x10, 0x18, 0x0E, 0x07, 0x0E, 0x18, 0x10, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '^'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}, // , 0x40}, // '_'
{0x00, 0x00, 0x07, 0x0F, 0x08, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // , 0x00}, // '`'
{0x00, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, /*0x00,*/ 0x0E, 0x1F, 0x11, 0x11, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'a'
{0x08, 0xF8, 0xF8, 0x40, 0xC0, 0x80, 0x00, /*0x00,*/ 0x10, 0x1F, 0x0F, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'b'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x18, 0x08}, // , 0x00}, // 'c'
{0x00, 0x80, 0xC0, 0x48, 0xF8, 0xF8, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'd'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x11, 0x11, 0x11, 0x19, 0x09}, // , 0x00}, // 'e'
{0x80, 0xF0, 0xF8, 0x88, 0x18, 0x30, 0x00, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x00}, // , 0x00}, // 'f'
{0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, /*0x00,*/ 0x4F, 0xDF, 0x90, 0x90, 0xFF, 0x7F, 0x00}, // , 0x00}, // 'g'
{0x08, 0xF8, 0xF8, 0x80, 0x40, 0xC0, 0x80, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'h'
{0x00, 0x00, 0x40, 0xD8, 0xD8, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'i'
{0x00, 0x00, 0x00, 0x00, 0x40, 0xD8, 0xD8, /*0x00,*/ 0x00, 0x60, 0xE0, 0x80, 0x80, 0xFF, 0x7F}, // , 0x00}, // 'j'
{0x08, 0xF8, 0xF8, 0x00, 0x80, 0xC0, 0x40, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x03, 0x07, 0x1C, 0x18}, // , 0x00}, // 'k'
{0x00, 0x00, 0x08, 0xF8, 0xF8, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1F, 0x1F, 0x10, 0x00}, // , 0x00}, // 'l'
{0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x80, /*0x00,*/ 0x1F, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'm'
{0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F}, // , 0x00}, // 'n'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'o'
{0x40, 0xC0, 0x80, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x80, 0xFF, 0xFF, 0x90, 0x10, 0x1F, 0x0F}, // , 0x00}, // 'p'
{0x80, 0xC0, 0x40, 0x40, 0x80, 0xC0, 0x40, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x90, 0xFF, 0xFF, 0x80}, // , 0x00}, // 'q'
{0x40, 0xC0, 0x80, 0xC0, 0x40, 0xC0, 0x80, /*0x00,*/ 0x10, 0x1F, 0x1F, 0x10, 0x00, 0x00, 0x01}, // , 0x00}, // 'r'
{0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, /*0x00,*/ 0x08, 0x19, 0x13, 0x12, 0x16, 0x1C, 0x08}, // , 0x00}, // 's'
{0x40, 0x40, 0xF0, 0xF8, 0x40, 0x40, 0x00, /*0x00,*/ 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x18, 0x08}, // , 0x00}, // 't'
{0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, /*0x00,*/ 0x0F, 0x1F, 0x10, 0x10, 0x0F, 0x1F, 0x10}, // , 0x00}, // 'u'
{0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x00, 0x07, 0x0F, 0x18, 0x18, 0x0F, 0x07}, // , 0x00}, // 'v'
{0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x0F, 0x1F, 0x18, 0x0E, 0x18, 0x1F, 0x0F}, // , 0x00}, // 'w'
{0x40, 0xC0, 0x80, 0x00, 0x80, 0xC0, 0x40, /*0x00,*/ 0x10, 0x18, 0x0F, 0x07, 0x0F, 0x18, 0x10}, // , 0x00}, // 'x'
{0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, /*0x00,*/ 0x8F, 0x9F, 0x90, 0x90, 0xD0, 0x7F, 0x3F}, // , 0x00}, // 'y'
{0xC0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0x40, /*0x00,*/ 0x18, 0x1C, 0x16, 0x13, 0x11, 0x18, 0x18}, // , 0x00}, // 'z'
{0x00, 0x80, 0x80, 0xF0, 0x78, 0x08, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x10, 0x10}, // , 0x00}, // '{'
{0x00, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00}, // , 0x00}, // '|'
{0x00, 0x08, 0x08, 0x78, 0xF0, 0x80, 0x80, /*0x00,*/ 0x00, 0x10, 0x10, 0x1F, 0x0F, 0x00, 0x00}, // , 0x00}, // '}'
{0x10, 0x18, 0x08, 0x18, 0x10, 0x18, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // , 0x00} // '->'
#else
// {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' '
{0x00, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00}, // '!'
{0x00, 0x0F, 0x1F, 0x00, 0x00, 0x1F, 0x0F, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '"'
{0x20, 0xF8, 0xF8, 0x20, 0xF8, 0xF8, 0x20, /*0x00,*/ 0x02, 0x0F, 0x0F, 0x02, 0x0F, 0x0F, 0x02}, // '#'
{0x70, 0xF8, 0x88, 0x8E, 0x8E, 0x98, 0x10, /*0x00,*/ 0x04, 0x0C, 0x08, 0x38, 0x38, 0x0F, 0x07}, // '$'
{0x30, 0x30, 0x00, 0x80, 0xC0, 0x60, 0x30, /*0x00,*/ 0x0C, 0x06, 0x03, 0x01, 0x00, 0x0C, 0x0C}, // '%'
{0x80, 0xD8, 0x7C, 0xE4, 0xBC, 0xD8, 0x40, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x07, 0x0F, 0x08}, // '&'
{0x00, 0x10, 0x1F, 0x0F, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '''
{0x00, 0x00, 0xF0, 0xF8, 0x0C, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x03, 0x07, 0x0C, 0x08, 0x00}, // '('
{0x00, 0x00, 0x04, 0x0C, 0xF8, 0xF0, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0C, 0x07, 0x03, 0x00}, // ')'
{0x00, 0x80, 0xA0, 0xE0, 0xC0, 0xE0, 0xA0, /*0x80,*/ 0x00, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02}, // '*'
{0x00, 0x80, 0x80, 0xE0, 0xE0, 0x80, 0x80, /*0x00,*/ 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00}, // '+'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x10, 0x1E, 0x0E, 0x00, 0x00}, // ','
{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '-'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, // '.'
{0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, /*0x00,*/ 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00}, // '/'
{0xF8, 0xFC, 0x84, 0xC4, 0x64, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x09, 0x08, 0x08, 0x0F, 0x07}, // '0'
{0x00, 0x10, 0x18, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x08, 0x08, 0x0F, 0x0F, 0x08, 0x08}, // '1'
{0x18, 0x1C, 0x04, 0x84, 0xC4, 0x7C, 0x38, /*0x00,*/ 0x0C, 0x0E, 0x0B, 0x09, 0x08, 0x08, 0x08}, // '2'
{0x18, 0x1C, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '3'
{0x80, 0xC0, 0x60, 0x30, 0x18, 0xFC, 0xFC, /*0x00,*/ 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x0F}, // '4'
{0x7C, 0x7C, 0x44, 0x44, 0x44, 0xC4, 0x84, /*0x00,*/ 0x04, 0x0C, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '5'
{0xF0, 0xF8, 0x4C, 0x44, 0x44, 0xC4, 0x80, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '6'
{0x04, 0x04, 0x04, 0x84, 0xE4, 0x7C, 0x1C, /*0x00,*/ 0x00, 0x00, 0x0E, 0x0F, 0x01, 0x00, 0x00}, // '7'
{0xB8, 0xFC, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // '8'
{0x78, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0xF8, /*0x00,*/ 0x00, 0x08, 0x08, 0x08, 0x0C, 0x07, 0x03}, // '9'
{0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00}, // ':'
{0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0E, 0x06, 0x00, 0x00}, // ';'
{0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x08, /*0x00,*/ 0x00, 0x00, 0x01, 0x03, 0x06, 0x0C, 0x08}, // '<'
{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /*0x00,*/ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}, // '='
{0x00, 0x08, 0x18, 0x30, 0x60, 0xC0, 0x80, /*0x00,*/ 0x00, 0x08, 0x0C, 0x06, 0x03, 0x01, 0x00}, // '>'
{0x38, 0x3C, 0x04, 0x84, 0xC4, 0x7C, 0x38, /*0x00,*/ 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00}, // '?'
{0xF0, 0xF8, 0x08, 0xC8, 0xC8, 0xF8, 0xF0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0B, 0x0B, 0x0B, 0x01}, // '@'
{0xF8, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0xF8, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'A'
{0xFC, 0xFC, 0x44, 0x44, 0x44, 0xFC, 0xB8, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'B'
{0xF8, 0xFC, 0x04, 0x04, 0x04, 0x1C, 0x18, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0E, 0x06}, // 'C'
{0xFC, 0xFC, 0x04, 0x04, 0x0C, 0xF8, 0xF0, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x0C, 0x07, 0x03}, // 'D'
{0xFC, 0xFC, 0x44, 0x44, 0x44, 0x04, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08}, // 'E'
{0xFC, 0xFC, 0x44, 0x44, 0x44, 0x04, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'F'
{0xF8, 0xFC, 0x04, 0x84, 0x84, 0x9C, 0x98, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'G'
{0xFC, 0xFC, 0x40, 0x40, 0x40, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'H'
{0x00, 0x00, 0x04, 0xFC, 0xFC, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'I'
{0x00, 0x00, 0x00, 0x04, 0xFC, 0xFC, 0x04, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x0F, 0x07, 0x00}, // 'J'
{0xFC, 0xFC, 0xE0, 0x30, 0x18, 0x0C, 0x04, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'K'
{0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08}, // 'L'
{0xFC, 0xFC, 0x18, 0x70, 0x18, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'M'
{0xFC, 0xFC, 0x60, 0xC0, 0x80, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0F}, // 'N'
{0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'O'
{0xFC, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0x78, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'P'
{0xF8, 0xFC, 0x04, 0x04, 0x04, 0xFC, 0xF8, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0C, 0x0C, 0x1F, 0x17}, // 'Q'
{0xFC, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0x78, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'R'
{0x38, 0x7C, 0x44, 0x44, 0x44, 0xCC, 0x88, /*0x00,*/ 0x06, 0x0E, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'S'
{0x00, 0x04, 0x04, 0xFC, 0xFC, 0x04, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // 'T'
{0xFC, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0xFC, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'U'
{0x7C, 0xFC, 0x80, 0x00, 0x80, 0xFC, 0x7C, /*0x00,*/ 0x00, 0x03, 0x0F, 0x0C, 0x0F, 0x03, 0x00}, // 'V'
{0xFC, 0xFC, 0x00, 0x80, 0x00, 0xFC, 0xFC, /*0x00,*/ 0x0F, 0x0F, 0x06, 0x03, 0x06, 0x0F, 0x0F}, // 'W'
{0x0C, 0x3C, 0xF0, 0xC0, 0xF0, 0x3C, 0x0C, /*0x00,*/ 0x0C, 0x0F, 0x03, 0x00, 0x03, 0x0F, 0x0C}, // 'X'
{0x00, 0x3C, 0x7C, 0xC0, 0xC0, 0x7C, 0x3C, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // 'Y'
{0x04, 0x04, 0x84, 0xC4, 0x64, 0x3C, 0x1C, /*0x00,*/ 0x0E, 0x0F, 0x09, 0x08, 0x08, 0x08, 0x08}, // 'Z'
{0x00, 0x00, 0xFC, 0xFC, 0x04, 0x04, 0x00, /*0x00,*/ 0x00, 0x00, 0x0F, 0x0F, 0x08, 0x08, 0x00}, // '['
{0x38, 0x70, 0xE0, 0xC0, 0x80, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0E}, // '"\'
{0x00, 0x00, 0x04, 0x04, 0xFC, 0xFC, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x08, 0x0F, 0x0F, 0x00}, // ']'
{0x08, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x08, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '^'
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, // '_'
{0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // '`'
{0x00, 0xA0, 0xA0, 0xA0, 0xA0, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'a'
{0xFC, 0xFC, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'b'
{0xC0, 0xE0, 0x20, 0x20, 0x20, 0x60, 0x40, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0C, 0x04}, // 'c'
{0xC0, 0xE0, 0x20, 0x20, 0x20, 0xFC, 0xFC, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'd'
{0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x09, 0x09, 0x09, 0x09, 0x01}, // 'e'
{0x20, 0x20, 0xF8, 0xFC, 0x24, 0x24, 0x04, /*0x00,*/ 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00}, // 'f'
{0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x4F, 0x48, 0x48, 0x48, 0x7F, 0x3F}, // 'g'
{0xFC, 0xFC, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'h'
{0x00, 0x00, 0x20, 0xEC, 0xEC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'i'
{0x00, 0x00, 0x00, 0x00, 0x20, 0xEC, 0xEC, /*0x00,*/ 0x00, 0x30, 0x70, 0x40, 0x40, 0x7F, 0x3F}, // 'j'
{0xFC, 0xFC, 0x00, 0x80, 0xC0, 0x60, 0x20, /*0x00,*/ 0x0F, 0x0F, 0x01, 0x03, 0x06, 0x0C, 0x08}, // 'k'
{0x00, 0x00, 0x04, 0xFC, 0xFC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x08, 0x0F, 0x0F, 0x08, 0x00}, // 'l'
{0xE0, 0xE0, 0x20, 0xE0, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x0F, 0x00, 0x0F, 0x0F}, // 'm'
{0xE0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F}, // 'n'
{0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'o'
{0xE0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, /*0x00,*/ 0x7F, 0x7F, 0x08, 0x08, 0x08, 0x0F, 0x07}, // 'p'
{0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x7F, 0x7F}, // 'q'
{0xE0, 0xE0, 0x60, 0x20, 0x20, 0x20, 0x20, /*0x00,*/ 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00}, // 'r'
{0xC0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, /*0x00,*/ 0x08, 0x09, 0x09, 0x09, 0x09, 0x0F, 0x06}, // 's'
{0x20, 0x20, 0xFC, 0xFC, 0x20, 0x20, 0x00, /*0x00,*/ 0x00, 0x00, 0x07, 0x0F, 0x08, 0x08, 0x08}, // 't'
{0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x08, 0x08, 0x0F, 0x0F}, // 'u'
{0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x00, 0x03, 0x0F, 0x0C, 0x0F, 0x03, 0x00}, // 'v'
{0xE0, 0xE0, 0x00, 0x80, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x0F, 0x08, 0x0F, 0x08, 0x0F, 0x07}, // 'w'
{0x60, 0xE0, 0x80, 0x00, 0x80, 0xE0, 0x60, /*0x00,*/ 0x0C, 0x0E, 0x03, 0x01, 0x03, 0x0E, 0x0C}, // 'x'
{0xE0, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0xE0, /*0x00,*/ 0x07, 0x4F, 0x48, 0x48, 0x48, 0x7F, 0x3F}, // 'y'
{0x20, 0x20, 0x20, 0xA0, 0xE0, 0x60, 0x20, /*0x00,*/ 0x0C, 0x0E, 0x0B, 0x09, 0x08, 0x08, 0x08}, // 'z'
{0x00, 0x00, 0x40, 0xF8, 0xBC, 0x04, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x07, 0x0F, 0x08, 0x08}, // '{'
{0x00, 0x00, 0x00, 0xBC, 0xBC, 0x00, 0x00, /*0x00,*/ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00}, // '|'
{0x00, 0x04, 0x04, 0xBC, 0xF8, 0x40, 0x00, /*0x00,*/ 0x00, 0x08, 0x08, 0x0F, 0x07, 0x00, 0x00}, // '}'
{0x08, 0x0C, 0x04, 0x0C, 0x08, 0x0C, 0x04, /*0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // '->'
#endif
};
#if 0
@@ -132,21 +231,40 @@ const uint8_t gFontBig[95][15] =
{0x00, 0xF0, 0xF8, 0xB8, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1C, 0xB8, 0xF0, 0xE0, 0x00, 0x11, 0x33, 0x77, 0x67, 0x66, 0x66, 0x66, 0x76, 0x33, 0x3F, 0x1F, 0x07},
{0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00}
};
#else
// 6 Empty columns removed
#elif 0
// VCR font
const uint8_t gFontBigDigits[11][26] =
const uint8_t gFontBigDigits[11][26 - 6] =
{
{0x00, 0x00, 0xF8, 0xFC, 0x06, 0x86, 0xC6, 0xE6, 0xF6, 0x76, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x77, 0x67, 0x63, 0x61, 0x60, 0x70, 0x3F, 0x1F, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x7F, 0x7F, 0x60, 0x60, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x1C, 0x86, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, 0x00, 0x00, 0x00, 0x7E, 0x7F, 0x63, 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x60, 0x00},
{0x00, 0x00, 0x18, 0x1C, 0x06, 0x06, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, 0x00, 0x00, 0x00, 0x18, 0x38, 0x70, 0x60, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, 0x00},
{0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x7F, 0x7F, 0x06, 0x06, 0x00},
{0x00, 0x00, 0x7E, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x18, 0x38, 0x70, 0x60, 0x60, 0x60, 0x60, 0x70, 0x3F, 0x1F, 0x00},
{0x00, 0x00, 0xF8, 0xFC, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x1F, 0x3F, 0x71, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, 0x00},
{0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0xC6, 0xE6, 0x7E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, 0x00},
{0x00, 0x00, 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0x86, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x18, 0x38, 0x71, 0x61, 0x61, 0x61, 0x61, 0x71, 0x3F, 0x1F, 0x00},
{0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}
{/*0x00, 0x00,*/ 0xF8, 0xFC, 0x06, 0x86, 0xC6, 0xE6, 0xF6, 0x76, 0xFC, 0xF8, /*0x00,*/ /*0x00, 0x00,*/ 0x1F, 0x3F, 0x77, 0x67, 0x63, 0x61, 0x60, 0x70, 0x3F, 0x1F, /*0x00*/},
{/*0x00, 0x00,*/ 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x60, 0x60, 0x7F, 0x7F, 0x60, 0x60, 0x00, 0x00, /*0x00*/},
{/*0x00, 0x00,*/ 0x18, 0x1C, 0x86, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x7E, 0x7F, 0x63, 0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x60, /*0x00*/},
{/*0x00, 0x00,*/ 0x18, 0x1C, 0x06, 0x06, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x70, 0x60, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/},
{/*0x00, 0x00,*/ 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0xFE, 0xFE, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x7F, 0x7F, 0x06, 0x06, /*0x00*/},
{/*0x00, 0x00,*/ 0x7E, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0xC6, 0x86, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x70, 0x60, 0x60, 0x60, 0x60, 0x70, 0x3F, 0x1F, /*0x00*/},
{/*0x00, 0x00,*/ 0xF8, 0xFC, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x1C, 0x18, /*0x00,*/ /*0x00, 0x00,*/ 0x1F, 0x3F, 0x71, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/},
{/*0x00, 0x00,*/ 0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0xC6, 0xE6, 0x7E, 0x3E, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x01, 0x00, 0x00, 0x00, /*0x00*/},
{/*0x00, 0x00,*/ 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0xC6, 0xFC, 0x78, /*0x00,*/ /*0x00, 0x00,*/ 0x1E, 0x3F, 0x73, 0x61, 0x61, 0x61, 0x61, 0x73, 0x3F, 0x1E, /*0x00*/},
{/*0x00, 0x00,*/ 0x78, 0xFC, 0xC6, 0x86, 0x86, 0x86, 0x86, 0x86, 0xFC, 0xF8, /*0x00,*/ /*0x00, 0x00,*/ 0x18, 0x38, 0x71, 0x61, 0x61, 0x61, 0x61, 0x71, 0x3F, 0x1F, /*0x00*/},
{/*0x00, 0x00,*/ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*0x00*/}
};
#else
// Terminus font
const uint8_t gFontBigDigits[11][26 - 6] =
{
{/*0x00, 0x00,*/ 0xFC, 0xFE, 0xFE, 0x06, 0x86, 0xC6, 0xE6, 0xFE, 0xFE, 0xFC, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x67, 0x63, 0x61, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/},
{/*0x00, 0x00,*/ 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x60, 0x60, 0x7F, 0x7F, 0x7F, 0x60, 0x60, 0x00, /*0x00*/},
{/*0x00, 0x00,*/ 0x1C, 0x1E, 0x1E, 0x06, 0x06, 0x06, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x60, 0x70, 0x78, 0x7C, 0x6E, 0x67, 0x63, 0x61, 0x60, 0x60, /*0x00*/},
{/*0x00, 0x00,*/ 0x0C, 0x0E, 0x0E, 0x86, 0x86, 0x86, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x30, 0x70, 0x70, 0x61, 0x61, 0x61, 0x61, 0x7F, 0x7F, 0x3E, /*0x00*/},
{/*0x00, 0x00,*/ 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0xFE, 0xFE, 0xFE, /*0x00,*/ /*0x00, 0x00,*/ 0x0F, 0x0F, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x7F, 0x7F, 0x7F, /*0x00*/},
{/*0x00, 0x00,*/ 0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x86, /*0x00,*/ /*0x00, 0x00,*/ 0x30, 0x70, 0x70, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/},
{/*0x00, 0x00,*/ 0xF8, 0xFC, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x80, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x3F, /*0x00*/},
{/*0x00, 0x00,*/ 0x0E, 0x0E, 0x0E, 0x06, 0x06, 0x86, 0xE6, 0xFE, 0x7E, 0x1E, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7F, 0x7F, 0x03, 0x00, 0x00, /*0x00*/},
{/*0x00, 0x00,*/ 0x7C, 0xFE, 0xFE, 0x86, 0x86, 0x86, 0x86, 0xFE, 0xFE, 0x7C, /*0x00,*/ /*0x00, 0x00,*/ 0x3F, 0x7F, 0x7F, 0x61, 0x61, 0x61, 0x61, 0x7F, 0x7F, 0x3F, /*0x00*/},
{/*0x00, 0x00,*/ 0xFC, 0xFE, 0xFE, 0x06, 0x06, 0x06, 0x06, 0xFE, 0xFE, 0xFC, /*0x00,*/ /*0x00, 0x00,*/ 0x01, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7F, 0x3F, 0x1F, /*0x00*/},
{/*0x00, 0x00,*/ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, /*0x00,*/ /*0x00, 0x00,*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*0x00*/}
};
#endif
/*
@@ -165,177 +283,9 @@ const uint8_t gFontSmallDigits[11][7] =
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00} // '-'
};
*/
#ifdef ENABLE_SPECTRUM
const uint8_t gFont3x5[160][3] = {
{0x00, 0x00, 0x00}, // 32 - space
{0x00, 0x17, 0x00}, // 33 - exclam
{0x03, 0x00, 0x03}, // 34 - quotedbl
{0x1f, 0x0a, 0x1f}, // 35 - numbersign
{0x0a, 0x1f, 0x05}, // 36 - dollar
{0x09, 0x04, 0x12}, // 37 - percent
{0x0f, 0x17, 0x1c}, // 38 - ampersand
{0x00, 0x03, 0x00}, // 39 - quotesingle
{0x00, 0x0e, 0x11}, // 40 - parenleft
{0x11, 0x0e, 0x00}, // 41 - parenright
{0x05, 0x02, 0x05}, // 42 - asterisk
{0x04, 0x0e, 0x04}, // 43 - plus
{0x10, 0x08, 0x00}, // 44 - comma
{0x04, 0x04, 0x04}, // 45 - hyphen
{0x00, 0x10, 0x00}, // 46 - period
{0x18, 0x04, 0x03}, // 47 - slash
{0x1e, 0x11, 0x0f}, // 48 - zero
{0x02, 0x1f, 0x00}, // 49 - one
{0x19, 0x15, 0x12}, // 50 - two
{0x11, 0x15, 0x0a}, // 51 - three
{0x07, 0x04, 0x1f}, // 52 - four
{0x17, 0x15, 0x09}, // 53 - five
{0x1e, 0x15, 0x1d}, // 54 - six
{0x19, 0x05, 0x03}, // 55 - seven
{0x1f, 0x15, 0x1f}, // 56 - eight
{0x17, 0x15, 0x0f}, // 57 - nine
{0x00, 0x0a, 0x00}, // 58 - colon
{0x10, 0x0a, 0x00}, // 59 - semicolon
{0x04, 0x0a, 0x11}, // 60 - less
{0x0a, 0x0a, 0x0a}, // 61 - equal
{0x11, 0x0a, 0x04}, // 62 - greater
{0x01, 0x15, 0x03}, // 63 - question
{0x0e, 0x15, 0x16}, // 64 - at
{0x1e, 0x05, 0x1e}, // 65 - A
{0x1f, 0x15, 0x0a}, // 66 - B
{0x0e, 0x11, 0x11}, // 67 - C
{0x1f, 0x11, 0x0e}, // 68 - D
{0x1f, 0x15, 0x15}, // 69 - E
{0x1f, 0x05, 0x05}, // 70 - F
{0x0e, 0x15, 0x1d}, // 71 - G
{0x1f, 0x04, 0x1f}, // 72 - H
{0x11, 0x1f, 0x11}, // 73 - I
{0x08, 0x10, 0x0f}, // 74 - J
{0x1f, 0x04, 0x1b}, // 75 - K
{0x1f, 0x10, 0x10}, // 76 - L
{0x1f, 0x06, 0x1f}, // 77 - M
{0x1f, 0x0e, 0x1f}, // 78 - N
{0x0e, 0x11, 0x0e}, // 79 - O
{0x1f, 0x05, 0x02}, // 80 - P
{0x0e, 0x19, 0x1e}, // 81 - Q
{0x1f, 0x0d, 0x16}, // 82 - R
{0x12, 0x15, 0x09}, // 83 - S
{0x01, 0x1f, 0x01}, // 84 - T
{0x0f, 0x10, 0x1f}, // 85 - U
{0x07, 0x18, 0x07}, // 86 - V
{0x1f, 0x0c, 0x1f}, // 87 - W
{0x1b, 0x04, 0x1b}, // 88 - X
{0x03, 0x1c, 0x03}, // 89 - Y
{0x19, 0x15, 0x13}, // 90 - Z
{0x1f, 0x11, 0x11}, // 91 - bracketleft
{0x02, 0x04, 0x08}, // 92 - backslash
{0x11, 0x11, 0x1f}, // 93 - bracketright
{0x02, 0x01, 0x02}, // 94 - asciicircum
{0x10, 0x10, 0x10}, // 95 - underscore
{0x01, 0x02, 0x00}, // 96 - grave
{0x1a, 0x16, 0x1c}, // 97 - a
{0x1f, 0x12, 0x0c}, // 98 - b
{0x0c, 0x12, 0x12}, // 99 - c
{0x0c, 0x12, 0x1f}, // 100 - d
{0x0c, 0x1a, 0x16}, // 101 - e
{0x04, 0x1e, 0x05}, // 102 - f
{0x0c, 0x2a, 0x1e}, // 103 - g
{0x1f, 0x02, 0x1c}, // 104 - h
{0x00, 0x1d, 0x00}, // 105 - i
{0x10, 0x20, 0x1d}, // 106 - j
{0x1f, 0x0c, 0x12}, // 107 - k
{0x11, 0x1f, 0x10}, // 108 - l
{0x1e, 0x0e, 0x1e}, // 109 - m
{0x1e, 0x02, 0x1c}, // 110 - n
{0x0c, 0x12, 0x0c}, // 111 - o
{0x3e, 0x12, 0x0c}, // 112 - p
{0x0c, 0x12, 0x3e}, // 113 - q
{0x1c, 0x02, 0x02}, // 114 - r
{0x14, 0x1e, 0x0a}, // 115 - s
{0x02, 0x1f, 0x12}, // 116 - t
{0x0e, 0x10, 0x1e}, // 117 - u
{0x0e, 0x18, 0x0e}, // 118 - v
{0x1e, 0x1c, 0x1e}, // 119 - w
{0x12, 0x0c, 0x12}, // 120 - x
{0x06, 0x28, 0x1e}, // 121 - y
{0x1a, 0x1e, 0x16}, // 122 - z
{0x04, 0x1b, 0x11}, // 123 - braceleft
{0x00, 0x1b, 0x00}, // 124 - bar
{0x11, 0x1b, 0x04}, // 125 - braceright
{0x02, 0x03, 0x01}, // 126 - asciitilde
{0x00, 0x00, 0x00}, // 127 - empty
{0x00, 0x00, 0x00}, // 128 - empty
{0x00, 0x00, 0x00}, // 129 - empty
{0x00, 0x00, 0x00}, // 130 - empty
{0x00, 0x00, 0x00}, // 131 - empty
{0x00, 0x00, 0x00}, // 132 - empty
{0x00, 0x00, 0x00}, // 133 - empty
{0x00, 0x00, 0x00}, // 134 - empty
{0x00, 0x00, 0x00}, // 135 - empty
{0x00, 0x00, 0x00}, // 136 - empty
{0x00, 0x00, 0x00}, // 137 - empty
{0x00, 0x00, 0x00}, // 138 - empty
{0x00, 0x00, 0x00}, // 139 - empty
{0x00, 0x00, 0x00}, // 140 - empty
{0x00, 0x00, 0x00}, // 141 - empty
{0x00, 0x00, 0x00}, // 142 - empty
{0x00, 0x00, 0x00}, // 143 - empty
{0x00, 0x00, 0x00}, // 144 - empty
{0x00, 0x00, 0x00}, // 145 - empty
{0x00, 0x00, 0x00}, // 146 - empty
{0x00, 0x00, 0x00}, // 147 - empty
{0x00, 0x00, 0x00}, // 148 - empty
{0x00, 0x00, 0x00}, // 149 - empty
{0x00, 0x00, 0x00}, // 150 - empty
{0x00, 0x00, 0x00}, // 151 - empty
{0x00, 0x00, 0x00}, // 152 - empty
{0x00, 0x00, 0x00}, // 153 - empty
{0x00, 0x00, 0x00}, // 154 - empty
{0x00, 0x00, 0x00}, // 155 - empty
{0x00, 0x00, 0x00}, // 156 - empty
{0x00, 0x00, 0x00}, // 157 - empty
{0x00, 0x00, 0x00}, // 158 - empty
{0x00, 0x00, 0x00}, // 159 - empty
{0x00, 0x00, 0x00}, // 160 - empty
{0x00, 0x1d, 0x00}, // 161 - exclamdown
{0x0e, 0x1b, 0x0a}, // 162 - cent
{0x14, 0x1f, 0x15}, // 163 - sterling
{0x15, 0x0e, 0x15}, // 164 - currency
{0x0b, 0x1c, 0x0b}, // 165 - yen
{0x00, 0x1b, 0x00}, // 166 - brokenbar
{0x14, 0x1b, 0x05}, // 167 - section
{0x01, 0x00, 0x01}, // 168 - dieresis
{0x02, 0x05, 0x05}, // 169 - copyright
{0x16, 0x15, 0x17}, // 170 - ordfeminine
{0x02, 0x05, 0x00}, // 171 - guillemotleft
{0x02, 0x02, 0x06}, // 172 - logicalnot
{0x04, 0x04, 0x00}, // 173 - softhyphen
{0x07, 0x03, 0x04}, // 174 - registered
{0x01, 0x01, 0x01}, // 175 - macron
{0x02, 0x05, 0x02}, // 176 - degree
{0x12, 0x17, 0x12}, // 177 - plusminus
{0x01, 0x07, 0x04}, // 178 - twosuperior
{0x05, 0x07, 0x07}, // 179 - threesuperior
{0x00, 0x02, 0x01}, // 180 - acute
{0x1f, 0x08, 0x07}, // 181 - mu
{0x02, 0x1d, 0x1f}, // 182 - paragraph
{0x0e, 0x0e, 0x0e}, // 183 - periodcentered
{0x10, 0x14, 0x08}, // 184 - cedilla
{0x00, 0x07, 0x00}, // 185 - onesuperior
{0x12, 0x15, 0x12}, // 186 - ordmasculine
{0x00, 0x05, 0x02}, // 187 - guillemotright
{0x03, 0x08, 0x18}, // 188 - onequarter
{0x0b, 0x18, 0x10}, // 189 - onehalf
{0x03, 0x0b, 0x18}, // 190 - threequarters
{0x18, 0x15, 0x10}, // 191 - questiondown
};
#endif
const uint8_t gFontSmall[95][6] =
const uint8_t gFontSmall[95-1][6] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' '
// {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' '
{0x00, 0x00, 0x5E, 0x00, 0x00, 0x00}, // '!'
{0x00, 0x06, 0x00, 0x06, 0x00, 0x00}, // '"'
{0x14, 0x3E, 0x14, 0x3E, 0x14, 0x00}, // '#'
@@ -433,9 +383,9 @@ const uint8_t gFontSmall[95][6] =
};
#ifdef ENABLE_SMALL_BOLD
const uint8_t gFontSmallBold[95][6] =
const uint8_t gFontSmallBold[95 - 1][6] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x5E, 0x5E, 0x00, 0x00},
{0x06, 0x06, 0x00, 0x06, 0x06, 0x00},
{0x14, 0x3E, 0x14, 0x3E, 0x14, 0x00},
@@ -502,10 +452,10 @@ const uint8_t gFontSmall[95][6] =
{0x00, 0x03, 0x07, 0x06, 0x00, 0x00},
{0x20, 0x76, 0x56, 0x56, 0x7E, 0x3C},
{0x7F, 0x7F, 0x6C, 0x6C, 0x7C, 0x38},
{0x3C, 0x7E, 0x66, 0x66, 0x66, 0x24},
{0x38, 0x7C, 0x6C, 0x6C, 0x6C, 0x00},
{0x38, 0x7C, 0x6C, 0x6C, 0x7F, 0x7F},
{0x3C, 0x7E, 0x56, 0x56, 0x5E, 0x0C},
{0x7C, 0x7E, 0x36, 0x36, 0x06, 0x00},
{0x7E, 0x7F, 0x1B, 0x1B, 0x02, 0x00},
{0x0C, 0x5E, 0x56, 0x56, 0x7E, 0x3C},
{0x7F, 0x7F, 0x0C, 0x0C, 0x7C, 0x78},
{0x00, 0x00, 0x7A, 0x7A, 0x00, 0x00},
@@ -516,7 +466,7 @@ const uint8_t gFontSmall[95][6] =
{0x7C, 0x7C, 0x0C, 0x0C, 0x7C, 0x78},
{0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x3C},
{0x7E, 0x7E, 0x36, 0x36, 0x3E, 0x1C},
{0x1C, 0x3E, 0x36, 0x3E, 0x7E, 0x40},
{0x1C, 0x3E, 0x36, 0x7E, 0x7E, 0x60},
{0x7C, 0x7C, 0x0C, 0x0C, 0x18, 0x00},
{0x4C, 0x5E, 0x56, 0x56, 0x76, 0x20},
{0x3F, 0x7F, 0x6C, 0x6C, 0x60, 0x00},
@@ -524,11 +474,181 @@ const uint8_t gFontSmall[95][6] =
{0x0C, 0x3C, 0x70, 0x70, 0x3C, 0x0C},
{0x3C, 0x7C, 0x30, 0x30, 0x7C, 0x3C},
{0x44, 0x6C, 0x38, 0x38, 0x6C, 0x44},
{0x06, 0x6E, 0x6C, 0x6C, 0x7E, 0x3E},
{0x06, 0x6E, 0x68, 0x68, 0x7E, 0x3E},
{0x66, 0x76, 0x7E, 0x6E, 0x66, 0x00},
{0x08, 0x3E, 0x77, 0x41, 0x00, 0x00},
{0x00, 0x00, 0x7F, 0x00, 0x00, 0x00},
{0x00, 0x41, 0x77, 0x3E, 0x08, 0x00},
{0x0C, 0x06, 0x0C, 0x18, 0x0C, 0x00},
{0x0C, 0x06, 0x0C, 0x18, 0x0C, 0x00}
};
#endif
#ifdef ENABLE_SPECTRUM
const uint8_t gFont3x5[][3] =
{
{0x00, 0x00, 0x00}, // 32 - space
{0x00, 0x17, 0x00}, // 33 - exclam
{0x03, 0x00, 0x03}, // 34 - quotedbl
{0x1f, 0x0a, 0x1f}, // 35 - numbersign
{0x0a, 0x1f, 0x05}, // 36 - dollar
{0x09, 0x04, 0x12}, // 37 - percent
{0x0f, 0x17, 0x1c}, // 38 - ampersand
{0x00, 0x03, 0x00}, // 39 - quotesingle
{0x00, 0x0e, 0x11}, // 40 - parenleft
{0x11, 0x0e, 0x00}, // 41 - parenright
{0x05, 0x02, 0x05}, // 42 - asterisk
{0x04, 0x0e, 0x04}, // 43 - plus
{0x10, 0x08, 0x00}, // 44 - comma
{0x04, 0x04, 0x04}, // 45 - hyphen
{0x00, 0x10, 0x00}, // 46 - period
{0x18, 0x04, 0x03}, // 47 - slash
{0x1e, 0x11, 0x0f}, // 48 - zero
{0x02, 0x1f, 0x00}, // 49 - one
{0x19, 0x15, 0x12}, // 50 - two
{0x11, 0x15, 0x0a}, // 51 - three
{0x07, 0x04, 0x1f}, // 52 - four
{0x17, 0x15, 0x09}, // 53 - five
{0x1e, 0x15, 0x1d}, // 54 - six
{0x19, 0x05, 0x03}, // 55 - seven
{0x1f, 0x15, 0x1f}, // 56 - eight
{0x17, 0x15, 0x0f}, // 57 - nine
{0x00, 0x0a, 0x00}, // 58 - colon
{0x10, 0x0a, 0x00}, // 59 - semicolon
{0x04, 0x0a, 0x11}, // 60 - less
{0x0a, 0x0a, 0x0a}, // 61 - equal
{0x11, 0x0a, 0x04}, // 62 - greater
{0x01, 0x15, 0x03}, // 63 - question
{0x0e, 0x15, 0x16}, // 64 - at
{0x1e, 0x05, 0x1e}, // 65 - A
{0x1f, 0x15, 0x0a}, // 66 - B
{0x0e, 0x11, 0x11}, // 67 - C
{0x1f, 0x11, 0x0e}, // 68 - D
{0x1f, 0x15, 0x15}, // 69 - E
{0x1f, 0x05, 0x05}, // 70 - F
{0x0e, 0x15, 0x1d}, // 71 - G
{0x1f, 0x04, 0x1f}, // 72 - H
{0x11, 0x1f, 0x11}, // 73 - I
{0x08, 0x10, 0x0f}, // 74 - J
{0x1f, 0x04, 0x1b}, // 75 - K
{0x1f, 0x10, 0x10}, // 76 - L
{0x1f, 0x06, 0x1f}, // 77 - M
{0x1f, 0x0e, 0x1f}, // 78 - N
{0x0e, 0x11, 0x0e}, // 79 - O
{0x1f, 0x05, 0x02}, // 80 - P
{0x0e, 0x19, 0x1e}, // 81 - Q
{0x1f, 0x0d, 0x16}, // 82 - R
{0x12, 0x15, 0x09}, // 83 - S
{0x01, 0x1f, 0x01}, // 84 - T
{0x0f, 0x10, 0x1f}, // 85 - U
{0x07, 0x18, 0x07}, // 86 - V
{0x1f, 0x0c, 0x1f}, // 87 - W
{0x1b, 0x04, 0x1b}, // 88 - X
{0x03, 0x1c, 0x03}, // 89 - Y
{0x19, 0x15, 0x13}, // 90 - Z
{0x1f, 0x11, 0x11}, // 91 - bracketleft
{0x02, 0x04, 0x08}, // 92 - backslash
{0x11, 0x11, 0x1f}, // 93 - bracketright
{0x02, 0x01, 0x02}, // 94 - asciicircum
{0x10, 0x10, 0x10}, // 95 - underscore
{0x01, 0x02, 0x00}, // 96 - grave
{0x1a, 0x16, 0x1c}, // 97 - a
{0x1f, 0x12, 0x0c}, // 98 - b
{0x0c, 0x12, 0x12}, // 99 - c
{0x0c, 0x12, 0x1f}, // 100 - d
{0x0c, 0x1a, 0x16}, // 101 - e
{0x04, 0x1e, 0x05}, // 102 - f
{0x0c, 0x2a, 0x1e}, // 103 - g
{0x1f, 0x02, 0x1c}, // 104 - h
{0x00, 0x1d, 0x00}, // 105 - i
{0x10, 0x20, 0x1d}, // 106 - j
{0x1f, 0x0c, 0x12}, // 107 - k
{0x11, 0x1f, 0x10}, // 108 - l
{0x1e, 0x0e, 0x1e}, // 109 - m
{0x1e, 0x02, 0x1c}, // 110 - n
{0x0c, 0x12, 0x0c}, // 111 - o
{0x3e, 0x12, 0x0c}, // 112 - p
{0x0c, 0x12, 0x3e}, // 113 - q
{0x1c, 0x02, 0x02}, // 114 - r
{0x14, 0x1e, 0x0a}, // 115 - s
{0x02, 0x1f, 0x12}, // 116 - t
{0x0e, 0x10, 0x1e}, // 117 - u
{0x0e, 0x18, 0x0e}, // 118 - v
{0x1e, 0x1c, 0x1e}, // 119 - w
{0x12, 0x0c, 0x12}, // 120 - x
{0x06, 0x28, 0x1e}, // 121 - y
{0x1a, 0x1e, 0x16}, // 122 - z
{0x04, 0x1b, 0x11}, // 123 - braceleft
{0x00, 0x1b, 0x00}, // 124 - bar
{0x11, 0x1b, 0x04}, // 125 - braceright
{0x02, 0x03, 0x01}, // 126 - asciitilde
{0x12, 0x17, 0x12}, // 127 - plusminus
// {0x00, 0x00, 0x00}, // 127 - empty
// {0x00, 0x00, 0x00}, // 128 - empty
// {0x00, 0x00, 0x00}, // 129 - empty
// {0x00, 0x00, 0x00}, // 130 - empty
// {0x00, 0x00, 0x00}, // 131 - empty
// {0x00, 0x00, 0x00}, // 132 - empty
// {0x00, 0x00, 0x00}, // 133 - empty
// {0x00, 0x00, 0x00}, // 134 - empty
// {0x00, 0x00, 0x00}, // 135 - empty
// {0x00, 0x00, 0x00}, // 136 - empty
// {0x00, 0x00, 0x00}, // 137 - empty
// {0x00, 0x00, 0x00}, // 138 - empty
// {0x00, 0x00, 0x00}, // 139 - empty
// {0x00, 0x00, 0x00}, // 140 - empty
// {0x00, 0x00, 0x00}, // 141 - empty
// {0x00, 0x00, 0x00}, // 142 - empty
// {0x00, 0x00, 0x00}, // 143 - empty
// {0x00, 0x00, 0x00}, // 144 - empty
// {0x00, 0x00, 0x00}, // 145 - empty
// {0x00, 0x00, 0x00}, // 146 - empty
// {0x00, 0x00, 0x00}, // 147 - empty
// {0x00, 0x00, 0x00}, // 148 - empty
// {0x00, 0x00, 0x00}, // 149 - empty
// {0x00, 0x00, 0x00}, // 150 - empty
// {0x00, 0x00, 0x00}, // 151 - empty
// {0x00, 0x00, 0x00}, // 152 - empty
// {0x00, 0x00, 0x00}, // 153 - empty
// {0x00, 0x00, 0x00}, // 154 - empty
// {0x00, 0x00, 0x00}, // 155 - empty
// {0x00, 0x00, 0x00}, // 156 - empty
// {0x00, 0x00, 0x00}, // 157 - empty
// {0x00, 0x00, 0x00}, // 158 - empty
// {0x00, 0x00, 0x00}, // 159 - empty
// {0x00, 0x00, 0x00}, // 160 - empty
// {0x00, 0x1d, 0x00}, // 161 - exclamdown
// {0x0e, 0x1b, 0x0a}, // 162 - cent
// {0x14, 0x1f, 0x15}, // 163 - sterling
// {0x15, 0x0e, 0x15}, // 164 - currency
// {0x0b, 0x1c, 0x0b}, // 165 - yen
// {0x00, 0x1b, 0x00}, // 166 - brokenbar
// {0x14, 0x1b, 0x05}, // 167 - section
// {0x01, 0x00, 0x01}, // 168 - dieresis
// {0x02, 0x05, 0x05}, // 169 - copyright
// {0x16, 0x15, 0x17}, // 170 - ordfeminine
// {0x02, 0x05, 0x00}, // 171 - guillemotleft
// {0x02, 0x02, 0x06}, // 172 - logicalnot
// {0x04, 0x04, 0x00}, // 173 - softhyphen
// {0x07, 0x03, 0x04}, // 174 - registered
// {0x01, 0x01, 0x01}, // 175 - macron
// {0x02, 0x05, 0x02}, // 176 - degree
// {0x12, 0x17, 0x12}, // 177 - plusminus
// {0x01, 0x07, 0x04}, // 178 - twosuperior
// {0x05, 0x07, 0x07}, // 179 - threesuperior
// {0x00, 0x02, 0x01}, // 180 - acute
// {0x1f, 0x08, 0x07}, // 181 - mu
// {0x02, 0x1d, 0x1f}, // 182 - paragraph
// {0x0e, 0x0e, 0x0e}, // 183 - periodcentered
// {0x10, 0x14, 0x08}, // 184 - cedilla
// {0x00, 0x07, 0x00}, // 185 - onesuperior
// {0x12, 0x15, 0x12}, // 186 - ordmasculine
// {0x00, 0x05, 0x02}, // 187 - guillemotright
// {0x03, 0x08, 0x18}, // 188 - onequarter
// {0x0b, 0x18, 0x10}, // 189 - onehalf
// {0x03, 0x0b, 0x18}, // 190 - threequarters
// {0x18, 0x15, 0x10}, // 191 - questiondown
};
#endif

13
font.h
View File

@@ -19,14 +19,13 @@
#include <stdint.h>
//extern const uint8_t gFontBig[95][16];
extern const uint8_t gFontBig[95][15];
extern const uint8_t gFontBigDigits[11][26];
//extern const uint8_t gFontSmallDigits[11][7];
extern const uint8_t gFont3x5[160][3];
extern const uint8_t gFontSmall[95][6];
extern const uint8_t gFontBig[95 - 1][16 - 2];
extern const uint8_t gFontBigDigits[11][26 - 6];
extern const uint8_t gFont3x5[96][3];
extern const uint8_t gFontSmall[95 - 1][6];
#ifdef ENABLE_SMALL_BOLD
extern const uint8_t gFontSmallBold[95][6];
extern const uint8_t gFontSmallBold[95 - 1][6];
#endif
#endif

View File

@@ -116,8 +116,12 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
gFM_RestoreCountdown_10ms = fm_restore_countdown_10ms;
#endif
if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT || gDTMF_CallState == DTMF_CALL_STATE_RECEIVED)
gDTMF_auto_reset_time_500ms = 1 + (gEeprom.DTMF_auto_reset_time * 2);
if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT ||
gDTMF_CallState == DTMF_CALL_STATE_RECEIVED ||
gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY)
{
gDTMF_auto_reset_time_500ms = gEeprom.DTMF_auto_reset_time * 2;
}
gUpdateStatus = true;
return;
@@ -141,7 +145,7 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
BK4819_DisableVox();
BK4819_Sleep();
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2, false);
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28, false);
gUpdateStatus = true;
@@ -200,10 +204,13 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
RADIO_SetTxParameters();
// turn the RED LED on
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_RED, true);
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, true);
DTMF_Reply();
if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO)
BK4819_PlaySingleTone(2525, 250, 0, gEeprom.DTMF_SIDE_TONE);
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState != ALARM_STATE_OFF)
{
@@ -230,7 +237,8 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
else
BK4819_DisableScramble();
if (gSetting_backlight_on_tx_rx == 1 || gSetting_backlight_on_tx_rx == 3)
if (gSetting_backlight_on_tx_rx == BACKLIGHT_ON_TR_TX ||
gSetting_backlight_on_tx_rx == BACKLIGHT_ON_TR_TXRX)
BACKLIGHT_TurnOn();
break;

View File

@@ -86,27 +86,16 @@ void BATTERY_GetReadings(const bool bDisplayBatteryLevel)
gBatteryDisplayLevel = 0;
if (gBatteryCalibration[5] < Voltage)
gBatteryDisplayLevel = 6;
else
if (gBatteryCalibration[4] < Voltage)
gBatteryDisplayLevel = 5;
else
if (gBatteryCalibration[3] < Voltage)
gBatteryDisplayLevel = 4;
else
if (gBatteryCalibration[2] < Voltage)
gBatteryDisplayLevel = 3;
else
if (gBatteryCalibration[1] < Voltage)
gBatteryDisplayLevel = 2;
else
if (gBatteryCalibration[0] < Voltage)
gBatteryDisplayLevel = 1;
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) && gMenuCursor == MENU_VOL)
if ((gScreenToDisplay == DISPLAY_MENU) && GetCurrentMenuId() == MENU_VOL)
gUpdateDisplay = true;
if (gBatteryCurrent < 501)

View File

@@ -84,6 +84,7 @@ void BOOT_ProcessMode(BOOT_Mode_t Mode)
gEeprom.KEY_1_LONG_PRESS_ACTION = ACTION_OPT_NONE;
gEeprom.KEY_2_SHORT_PRESS_ACTION = ACTION_OPT_NONE;
gEeprom.KEY_2_LONG_PRESS_ACTION = ACTION_OPT_NONE;
gEeprom.KEY_M_LONG_PRESS_ACTION = ACTION_OPT_NONE;
RADIO_InitInfo(gRxVfo, FREQ_CHANNEL_LAST - 1, 41002500);

View File

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

View File

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

14
init.c
View File

@@ -30,21 +30,17 @@ void DATA_Init(void);
void BSS_Init(void)
{
uint32_t *pBss;
for (pBss = __bss_start__; pBss < __bss_end__; pBss++) {
for (pBss = __bss_start__; pBss < __bss_end__; pBss++)
*pBss = 0;
}
}
void DATA_Init(void)
{
volatile uint32_t *pDataRam = (volatile uint32_t *)sram_data_start;
volatile uint32_t *pDataRam = (volatile uint32_t *)sram_data_start;
volatile uint32_t *pDataFlash = (volatile uint32_t *)flash_data_start;
uint32_t Size = (uint32_t)sram_data_end - (uint32_t)sram_data_start;
uint32_t i;
uint32_t Size = (uint32_t)sram_data_end - (uint32_t)sram_data_start;
unsigned int i;
for (i = 0; i < Size / 4; i++) {
for (i = 0; i < (Size / 4); i++)
*pDataRam++ = *pDataFlash++;
}
}

44
main.c
View File

@@ -84,7 +84,7 @@ void Main(void)
BOARD_EEPROM_Init();
BOARD_EEPROM_LoadMoreSettings();
BOARD_EEPROM_LoadCalibration();
RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD);
RADIO_ConfigureChannel(1, VFO_CONFIGURE_RELOAD);
@@ -104,23 +104,18 @@ void Main(void)
BootMode = BOOT_GetMode();
// count the number of menu items
gMenuListCount = 0;
while (MenuList[gMenuListCount].name[0] != '\0')
gMenuListCount++;
if (BootMode == BOOT_MODE_F_LOCK)
{
gF_LOCK = true; // flag to say include the hidden menu items
}
else
{ // hide the hidden menu items
gMenuListCount -= 9;
// count the number of menu items
gMenuListCount = 0;
while (MenuList[gMenuListCount].name[0] != '\0') {
if(!gF_LOCK && MenuList[gMenuListCount].menu_id == FIRST_HIDDEN_MENU_ITEM)
break;
#ifndef ENABLE_F_CAL_MENU
gMenuListCount++;
#endif
gMenuListCount++;
}
// wait for user to release all butts before moving on
@@ -167,19 +162,21 @@ void Main(void)
boot_counter_10ms = 0;
break;
}
#ifdef ENABLE_BOOT_BEEPS
if ((boot_counter_10ms % 25) == 0)
AUDIO_PlayBeep(BEEP_880HZ_40MS_OPTIONAL);
#endif
#ifdef ENABLE_BOOT_BEEPS
if ((boot_counter_10ms % 25) == 0)
AUDIO_PlayBeep(BEEP_880HZ_40MS_OPTIONAL);
#endif
}
}
#ifdef ENABLE_PWRON_PASSWORD
if (gEeprom.POWER_ON_PASSWORD < 1000000)
{
bIsInLockScreen = true;
UI_DisplayLock();
bIsInLockScreen = false;
}
#endif
BOOT_ProcessMode(BootMode);
@@ -187,29 +184,28 @@ void Main(void)
gUpdateStatus = true;
#ifdef ENABLE_VOICE
#ifdef ENABLE_VOICE
{
uint8_t Channel;
AUDIO_SetVoiceID(0, VOICE_ID_WELCOME);
Channel = gEeprom.ScreenChannel[gEeprom.TX_CHANNEL];
Channel = gEeprom.ScreenChannel[gEeprom.TX_VFO];
if (IS_MR_CHANNEL(Channel))
{
AUDIO_SetVoiceID(1, VOICE_ID_CHANNEL_MODE);
AUDIO_SetDigitVoice(2, Channel + 1);
}
else
if (IS_FREQ_CHANNEL(Channel))
else if (IS_FREQ_CHANNEL(Channel))
AUDIO_SetVoiceID(1, VOICE_ID_FREQUENCY_MODE);
AUDIO_PlaySingleVoice(0);
}
#endif
#endif
#ifdef ENABLE_NOAA
RADIO_ConfigureNOAA();
#endif
#ifdef ENABLE_NOAA
RADIO_ConfigureNOAA();
#endif
// ******************
}

59
misc.c
View File

@@ -17,13 +17,15 @@
#include <string.h>
#include "misc.h"
#include "settings.h"
const uint8_t fm_resume_countdown_500ms = 2500 / 500; // 2.5 seconds
const uint8_t fm_radio_countdown_500ms = 2000 / 500; // 2 seconds
const uint16_t fm_play_countdown_scan_10ms = 100 / 10; // 100ms
const uint16_t fm_play_countdown_noscan_10ms = 1200 / 10; // 1.2 seconds
const uint16_t fm_restore_countdown_10ms = 5000 / 10; // 5 seconds
const uint8_t vfo_state_resume_countdown_500ms = 2500 / 500; // 2.5 seconds
const uint8_t menu_timeout_500ms = 20000 / 500; // 20 seconds
const uint16_t menu_timeout_long_500ms = 120000 / 500; // 2 minutes
@@ -71,9 +73,6 @@ const uint16_t NOAA_countdown_10ms = 5000 / 10; // 5 seconds
const uint16_t NOAA_countdown_2_10ms = 500 / 10; // 500ms
const uint16_t NOAA_countdown_3_10ms = 200 / 10; // 200ms
//const uint16_t gMax_bat_v = 840; // 8.4V
//const uint16_t gMin_bat_v = 660; // 6.6V
const uint32_t gDefaultAesKey[4] = {0x4AA5CC60, 0x0312CC5F, 0xFFD2DABB, 0x6BBA7F92};
const uint8_t gMicGain_dB2[5] = {3, 8, 16, 24, 31};
@@ -108,12 +107,7 @@ bool bHasCustomAesKey;
uint32_t gChallenge[4];
uint8_t gTryCount;
uint8_t gEEPROM_1EC0_0[8];
uint8_t gEEPROM_1EC0_1[8];
uint8_t gEEPROM_1EC0_2[8];
uint8_t gEEPROM_1EC0_3[8];
uint16_t gEEPROM_RSSI_CALIB[2][4];
uint16_t gEEPROM_RSSI_CALIB[7][4];
uint16_t gEEPROM_1F8A;
uint16_t gEEPROM_1F8C;
@@ -128,7 +122,6 @@ volatile bool gSchedulePowerSave;
volatile bool gScheduleDualWatch = true;
volatile uint16_t gDualWatchCountdown_10ms;
volatile bool gDualWatchCountdownExpired = true;
bool gDualWatchActive = false;
volatile uint8_t gSerialConfigCountDown_500ms;
@@ -140,6 +133,8 @@ volatile bool gTxTimeoutReached;
volatile uint16_t gTailNoteEliminationCountdown_10ms;
volatile uint8_t gVFOStateResumeCountdown_500ms;
#ifdef ENABLE_NOAA
volatile uint16_t gNOAA_Countdown_10ms;
#endif
@@ -206,7 +201,6 @@ uint16_t gLowBatteryCountdown;
uint8_t gNextMrChannel;
ReceptionMode_t gRxReceptionMode;
uint8_t gRestoreMrChannel;
enum scan_next_chan_t gCurrentScanList;
uint32_t gRestoreFrequency;
@@ -219,7 +213,7 @@ bool gKeyBeingHeld;
bool gPttIsPressed;
uint8_t gPttDebounceCounter;
uint8_t gMenuListCount;
uint8_t gBackupCROSS_BAND_RX_TX;
uint8_t gBackup_CROSS_BAND_RX_TX;
uint8_t gScanDelay_10ms;
#ifdef ENABLE_AIRCOPY
uint8_t gAircopySendCountdown;
@@ -259,34 +253,7 @@ int16_t gCurrentRSSI[2] = {0, 0}; // now one per VFO
uint8_t gIsLocked = 0xFF;
// --------
void NUMBER_Get(char *pDigits, uint32_t *pInteger)
{
unsigned int i;
uint32_t Multiplier = 10000000;
uint32_t Value = 0;
for (i = 0; i < 8; i++)
{
if (pDigits[i] > 9)
break;
Value += pDigits[i] * Multiplier;
Multiplier /= 10U;
}
*pInteger = Value;
}
void NUMBER_ToDigits(uint32_t Value, char *pDigits)
{
unsigned int i;
for (i = 0; i < 8; i++)
{
const uint32_t Result = Value / 10U;
pDigits[7 - i] = Value - (Result * 10U);
Value = Result;
}
pDigits[8] = 0;
}
int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit, int32_t UpperLimit)
{
@@ -300,3 +267,15 @@ int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit,
return Base;
}
unsigned long StrToUL(const char * str)
{
unsigned long ul = 0;
for(uint8_t i = 0; i < strlen(str); i++){
char c = str[i];
if(c < '0' || c > '9')
break;
ul = ul * 10 + (uint8_t)(c-'0');
}
return ul;
}

55
misc.h
View File

@@ -24,31 +24,36 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
#define IS_MR_CHANNEL(x) ((x) >= MR_CHANNEL_FIRST && (x) <= MR_CHANNEL_LAST)
#define IS_FREQ_CHANNEL(x) ((x) >= FREQ_CHANNEL_FIRST && (x) <= FREQ_CHANNEL_LAST)
#define IS_VALID_CHANNEL(x) ((x) < LAST_CHANNEL)
#ifdef ENABLE_NOAA
#define IS_NOAA_CHANNEL(x) ((x) >= NOAA_CHANNEL_FIRST && (x) <= NOAA_CHANNEL_LAST)
#define IS_NOT_NOAA_CHANNEL(x) ((x) >= MR_CHANNEL_FIRST && (x) <= FREQ_CHANNEL_LAST)
#ifndef MAX
#define MAX(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
#endif
#ifndef MIN
#define MIN(a, b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
#endif
#define IS_MR_CHANNEL(x) ((x) <= MR_CHANNEL_LAST)
#define IS_FREQ_CHANNEL(x) ((x) >= FREQ_CHANNEL_FIRST && (x) <= FREQ_CHANNEL_LAST)
#define IS_VALID_CHANNEL(x) ((x) < LAST_CHANNEL)
#define IS_NOAA_CHANNEL(x) ((x) >= NOAA_CHANNEL_FIRST && (x) <= NOAA_CHANNEL_LAST)
#define IS_NOT_NOAA_CHANNEL(x) ((x) <= FREQ_CHANNEL_LAST)
enum {
MR_CHANNEL_FIRST = 0,
MR_CHANNEL_LAST = 199u,
FREQ_CHANNEL_FIRST = 200u,
FREQ_CHANNEL_LAST = 206u,
#ifdef ENABLE_NOAA
NOAA_CHANNEL_FIRST = 207u,
NOAA_CHANNEL_LAST = 216u,
#endif
NOAA_CHANNEL_FIRST = 207u,
NOAA_CHANNEL_LAST = 216u,
LAST_CHANNEL
};
enum {
FLASHLIGHT_OFF = 0,
FLASHLIGHT_ON,
FLASHLIGHT_BLINK
FLASHLIGHT_BLINK,
FLASHLIGHT_SOS
};
enum {
@@ -89,12 +94,20 @@ enum scan_next_chan_t {
};
typedef enum scan_next_chan_t scan_next_chan_t;
extern const uint8_t fm_resume_countdown_500ms;
enum BacklightOnRxTx_t {
BACKLIGHT_ON_TR_OFF,
BACKLIGHT_ON_TR_TX,
BACKLIGHT_ON_TR_RX,
BACKLIGHT_ON_TR_TXRX
};
extern const uint8_t fm_radio_countdown_500ms;
extern const uint16_t fm_play_countdown_scan_10ms;
extern const uint16_t fm_play_countdown_noscan_10ms;
extern const uint16_t fm_restore_countdown_10ms;
extern const uint8_t vfo_state_resume_countdown_500ms;
extern const uint8_t menu_timeout_500ms;
extern const uint16_t menu_timeout_long_500ms;
@@ -178,12 +191,7 @@ extern bool bHasCustomAesKey;
extern uint32_t gChallenge[4];
extern uint8_t gTryCount;
extern uint8_t gEEPROM_1EC0_0[8];
extern uint8_t gEEPROM_1EC0_1[8];
extern uint8_t gEEPROM_1EC0_2[8];
extern uint8_t gEEPROM_1EC0_3[8];
extern uint16_t gEEPROM_RSSI_CALIB[2][4];
extern uint16_t gEEPROM_RSSI_CALIB[7][4];
extern uint16_t gEEPROM_1F8A;
extern uint16_t gEEPROM_1F8C;
@@ -198,7 +206,6 @@ extern volatile bool gSchedulePowerSave;
extern volatile bool gScheduleDualWatch;
extern volatile uint16_t gDualWatchCountdown_10ms;
extern volatile bool gDualWatchCountdownExpired;
extern bool gDualWatchActive;
extern volatile uint8_t gSerialConfigCountDown_500ms;
@@ -276,10 +283,10 @@ extern uint16_t gLowBatteryCountdown;
extern uint8_t gNextMrChannel;
extern ReceptionMode_t gRxReceptionMode;
extern uint8_t gRestoreMrChannel;
extern scan_next_chan_t gCurrentScanList;
extern uint32_t gRestoreFrequency;
//TRUE when dual watch is momentarly suspended and RX_VFO is locked to either last TX or RX
extern bool gRxVfoIsActive;
extern uint8_t gAlarmToneCounter;
extern uint16_t gAlarmRunningCounter;
@@ -287,7 +294,7 @@ extern bool gKeyBeingHeld;
extern bool gPttIsPressed;
extern uint8_t gPttDebounceCounter;
extern uint8_t gMenuListCount;
extern uint8_t gBackupCROSS_BAND_RX_TX;
extern uint8_t gBackup_CROSS_BAND_RX_TX;
extern uint8_t gScanDelay_10ms;
#ifdef ENABLE_AIRCOPY
extern uint8_t gAircopySendCountdown;
@@ -315,6 +322,7 @@ extern volatile bool gNextTimeslice40ms;
extern volatile bool gScheduleNOAA;
#endif
extern volatile bool gFlagTailNoteEliminationComplete;
extern volatile uint8_t gVFOStateResumeCountdown_500ms;
#ifdef ENABLE_FMRADIO
extern volatile bool gScheduleFM;
#endif
@@ -322,9 +330,8 @@ extern int16_t gCurrentRSSI[2]; // now one per VFO
extern uint8_t gIsLocked;
extern volatile uint8_t boot_counter_10ms;
void NUMBER_Get(char *pDigits, uint32_t *pInteger);
void NUMBER_ToDigits(uint32_t Value, char *pDigits);
int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit, int32_t UpperLimit);
unsigned long StrToUL(const char * str);
#endif

211
radio.c
View File

@@ -51,7 +51,7 @@ bool RADIO_CheckValidChannel(uint16_t Channel, bool bCheckScanList, uint8_t VFO)
uint8_t PriorityCh1;
uint8_t PriorityCh2;
if (!IS_MR_CHANNEL(Channel))
if (Channel > MR_CHANNEL_LAST)
return false;
Attributes = gMR_ChannelAttributes[Channel];
@@ -161,22 +161,22 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
if (IS_VALID_CHANNEL(Channel))
{
#ifdef ENABLE_NOAA
if (Channel >= NOAA_CHANNEL_FIRST)
{
RADIO_InitInfo(pRadio, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[Channel - NOAA_CHANNEL_FIRST]);
#ifdef ENABLE_NOAA
if (Channel >= NOAA_CHANNEL_FIRST)
{
RADIO_InitInfo(pRadio, gEeprom.ScreenChannel[VFO], NoaaFrequencyTable[Channel - NOAA_CHANNEL_FIRST]);
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF)
return;
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gUpdateStatus = true;
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF)
return;
}
#endif
if (IS_MR_CHANNEL(Channel))
gEeprom.CROSS_BAND_RX_TX = CROSS_BAND_OFF;
gUpdateStatus = true;
return;
}
#endif
if (Channel <= MR_CHANNEL_LAST)
{
Channel = RADIO_FindNextChannel(Channel, RADIO_CHANNEL_UP, false, VFO);
if (Channel == 0xFF)
@@ -200,7 +200,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
uint8_t Index;
if (IS_MR_CHANNEL(Channel))
if (Channel <= MR_CHANNEL_LAST)
{
Channel = gEeprom.FreqChannel[VFO];
gEeprom.ScreenChannel[VFO] = gEeprom.FreqChannel[VFO];
@@ -218,7 +218,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
Band = BAND6_400MHz;
}
if (IS_MR_CHANNEL(Channel))
if (Channel <= MR_CHANNEL_LAST)
{
gEeprom.VfoInfo[VFO].Band = Band;
gEeprom.VfoInfo[VFO].SCANLIST1_PARTICIPATION = !!(Attributes & MR_CH_SCANLIST1);
@@ -235,7 +235,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
gEeprom.VfoInfo[VFO].SCANLIST2_PARTICIPATION = bParticipation2;
gEeprom.VfoInfo[VFO].CHANNEL_SAVE = Channel;
if (IS_MR_CHANNEL(Channel))
if (Channel <= MR_CHANNEL_LAST)
Base = Channel * 16;
else
Base = 0x0C80 + ((Channel - FREQ_CHANNEL_FIRST) * 32) + (VFO * 16);
@@ -332,12 +332,12 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
if (Data[5] == 0xFF)
{
gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = false;
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = 0;
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = PTT_ID_OFF;
}
else
{
gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = !!((Data[5] >> 0) & 1u);
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = ((Data[5] >> 1) & 3u);
gEeprom.VfoInfo[VFO].DTMF_DECODING_ENABLE = ((Data[5] >> 0) & 1u) ? true : false;
gEeprom.VfoInfo[VFO].DTMF_PTT_ID_TX_MODE = ((Data[5] >> 1) & 7u);
}
// ***************
@@ -380,13 +380,13 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
if (Frequency >= 10800000 && Frequency < 13600000)
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY_DIRECTION = TX_OFFSET_FREQUENCY_DIRECTION_OFF;
else
if (!IS_MR_CHANNEL(Channel))
if (Channel > MR_CHANNEL_LAST)
gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY = FREQUENCY_FloorToStep(gEeprom.VfoInfo[VFO].TX_OFFSET_FREQUENCY, gEeprom.VfoInfo[VFO].StepFrequency, 0);
RADIO_ApplyOffset(pRadio);
memset(gEeprom.VfoInfo[VFO].Name, 0, sizeof(gEeprom.VfoInfo[VFO].Name));
if (IS_MR_CHANNEL(Channel))
if (Channel < MR_CHANNEL_LAST)
{ // 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);
@@ -426,22 +426,27 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
{
uint8_t Txp[3];
FREQUENCY_Band_t Band = FREQUENCY_GetBand(pInfo->pRX->Frequency);
uint16_t Base = (Band < BAND4_174MHz) ? 0x1E60 : 0x1E00;
FREQUENCY_Band_t Band;
// *******************************
// squelch
Band = FREQUENCY_GetBand(pInfo->pRX->Frequency);
uint16_t Base = (Band < BAND4_174MHz) ? 0x1E60 : 0x1E00;
if (gEeprom.SQUELCH_LEVEL == 0)
{ // squelch == 0 (off)
pInfo->SquelchOpenRSSIThresh = 0;
pInfo->SquelchOpenNoiseThresh = 127;
pInfo->SquelchCloseGlitchThresh = 255;
pInfo->SquelchOpenRSSIThresh = 0; // 0 ~ 255
pInfo->SquelchOpenNoiseThresh = 127; // 127 ~ 0
pInfo->SquelchCloseGlitchThresh = 255; // 255 ~ 0
pInfo->SquelchCloseRSSIThresh = 0;
pInfo->SquelchCloseNoiseThresh = 127;
pInfo->SquelchOpenGlitchThresh = 255;
pInfo->SquelchCloseRSSIThresh = 0; // 0 ~ 255
pInfo->SquelchCloseNoiseThresh = 127; // 127 ~ 0
pInfo->SquelchOpenGlitchThresh = 255; // 255 ~ 0
}
else
{ // squelch >= 1
Base += gEeprom.SQUELCH_LEVEL; // my squelch-1
Base += gEeprom.SQUELCH_LEVEL; // my eeprom squelch-1
// VHF UHF
EEPROM_ReadBuffer(Base + 0x00, &pInfo->SquelchOpenRSSIThresh, 1); // 50 10
EEPROM_ReadBuffer(Base + 0x10, &pInfo->SquelchCloseRSSIThresh, 1); // 40 5
@@ -452,6 +457,13 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
EEPROM_ReadBuffer(Base + 0x40, &pInfo->SquelchCloseGlitchThresh, 1); // 90 90
EEPROM_ReadBuffer(Base + 0x50, &pInfo->SquelchOpenGlitchThresh, 1); // 100 100
uint16_t rssi_open = pInfo->SquelchOpenRSSIThresh;
uint16_t rssi_close = pInfo->SquelchCloseRSSIThresh;
uint16_t noise_open = pInfo->SquelchOpenNoiseThresh;
uint16_t noise_close = pInfo->SquelchCloseNoiseThresh;
uint16_t glitch_open = pInfo->SquelchOpenGlitchThresh;
uint16_t glitch_close = pInfo->SquelchCloseGlitchThresh;
#if ENABLE_SQUELCH_MORE_SENSITIVE
// make squelch a little more sensitive
//
@@ -459,23 +471,47 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
//
// note that 'noise' and 'glitch' values are inverted compared to 'rssi' values
pInfo->SquelchOpenRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 8) / 9;
pInfo->SquelchCloseRSSIThresh = ((uint16_t)pInfo->SquelchOpenRSSIThresh * 8) / 9;
#if 0
rssi_open = (rssi_open * 8) / 9;
noise_open = (noise_open * 9) / 8;
glitch_open = (glitch_open * 9) / 8;
#else
// even more sensitive .. use when RX bandwidths are fixed (no weak signal auto adjust)
rssi_open = (rssi_open * 1) / 2;
noise_open = (noise_open * 2) / 1;
glitch_open = (glitch_open * 2) / 1;
#endif
pInfo->SquelchOpenNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchCloseNoiseThresh = ((uint16_t)pInfo->SquelchOpenNoiseThresh * 9) / 8;
pInfo->SquelchOpenGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
pInfo->SquelchCloseGlitchThresh = ((uint16_t)pInfo->SquelchOpenGlitchThresh * 9) / 8;
#else
// more sensitive .. use when RX bandwidths are fixed (no weak signal auto adjust)
rssi_open = (rssi_open * 3) / 4;
noise_open = (noise_open * 4) / 3;
glitch_open = (glitch_open * 4) / 3;
#endif
if (pInfo->SquelchOpenNoiseThresh > 127)
pInfo->SquelchOpenNoiseThresh = 127;
rssi_close = (rssi_open * 9) / 10;
noise_close = (noise_open * 10) / 9;
glitch_close = (glitch_open * 10) / 9;
if (pInfo->SquelchCloseNoiseThresh > 127)
pInfo->SquelchCloseNoiseThresh = 127;
// ensure the 'close' threshold is lower than the 'open' threshold
if (rssi_close == rssi_open && rssi_close >= 2)
rssi_close -= 2;
if (noise_close == noise_open && noise_close <= 125)
noise_close += 2;
if (glitch_close == glitch_open && glitch_close <= 253)
glitch_close += 2;
pInfo->SquelchOpenRSSIThresh = (rssi_open > 255) ? 255 : rssi_open;
pInfo->SquelchCloseRSSIThresh = (rssi_close > 255) ? 255 : rssi_close;
pInfo->SquelchOpenNoiseThresh = (noise_open > 127) ? 127 : noise_open;
pInfo->SquelchCloseNoiseThresh = (noise_close > 127) ? 127 : noise_close;
pInfo->SquelchOpenGlitchThresh = (glitch_open > 255) ? 255 : glitch_open;
pInfo->SquelchCloseGlitchThresh = (glitch_close > 255) ? 255 : glitch_close;
}
// *******************************
// output power
Band = FREQUENCY_GetBand(pInfo->pTX->Frequency);
EEPROM_ReadBuffer(0x1ED0 + (Band * 16) + (pInfo->OUTPUT_POWER * 3), Txp, 3);
@@ -488,6 +524,8 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
(frequencyBandTable[Band].lower + frequencyBandTable[Band].upper) / 2,
frequencyBandTable[Band].upper,
pInfo->pTX->Frequency);
// *******************************
}
void RADIO_ApplyOffset(VFO_Info_t *pInfo)
@@ -517,30 +555,20 @@ void RADIO_ApplyOffset(VFO_Info_t *pInfo)
static void RADIO_SelectCurrentVfo(void)
{
gCurrentVfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gRxVfo : &gEeprom.VfoInfo[gEeprom.TX_CHANNEL];
// if crossband is active the gCurrentVfo is gTxVfo (gTxVfo/TX_VFO is only ever changed by the user)
// otherwise it is set to gRxVfo
// so in the end gCurrentVfo is equal to gTxVfo unless dual watch changes it on incomming transmition (again, this can only happen when XB off)
// note: it is called only in certain situations so could not by up-to-date
gCurrentVfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gRxVfo : gTxVfo;
}
void RADIO_SelectVfos(void)
{
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_CHAN_B)
gEeprom.TX_CHANNEL = 1;
else
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_CHAN_A)
gEeprom.TX_CHANNEL = 0;
else
if (gEeprom.DUAL_WATCH == DUAL_WATCH_CHAN_B)
gEeprom.TX_CHANNEL = 1;
else
if (gEeprom.DUAL_WATCH == DUAL_WATCH_CHAN_A)
gEeprom.TX_CHANNEL = 0;
// if crossband is used then RX_VFO is the opposite to the TX_VFO
gEeprom.RX_VFO = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.TX_VFO : !gEeprom.TX_VFO;
if (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF)
gEeprom.RX_CHANNEL = gEeprom.TX_CHANNEL;
else
gEeprom.RX_CHANNEL = (gEeprom.TX_CHANNEL == 0) ? 1 : 0;
gTxVfo = &gEeprom.VfoInfo[gEeprom.TX_CHANNEL];
gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_CHANNEL];
gTxVfo = &gEeprom.VfoInfo[gEeprom.TX_VFO];
gRxVfo = &gEeprom.VfoInfo[gEeprom.RX_VFO];
RADIO_SelectCurrentVfo();
}
@@ -555,12 +583,13 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
gEnableSpeaker = false;
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28_GREEN, false);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
switch (Bandwidth)
{
default:
Bandwidth = BK4819_FILTER_BW_WIDE;
[[fallthrough]];
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
#ifdef ENABLE_AM_FIX
@@ -572,11 +601,11 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
break;
}
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29_RED, false);
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1_RED, false);
BK4819_SetupPowerAmplifier(0, 0);
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1, false);
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29, false);
while (1)
{
@@ -610,7 +639,7 @@ void RADIO_SetupRegisters(bool bSwitchToFunction0)
BK4819_PickRXFilterPathBasedOnFrequency(Frequency);
// what does this in do ?
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2, true);
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28, true);
// AF RX Gain and DAC
BK4819_WriteRegister(BK4819_REG_48, 0xB3A8); // 1011 00 111010 1000
@@ -804,12 +833,13 @@ void RADIO_SetTxParameters(void)
gEnableSpeaker = false;
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2, false);
BK4819_ToggleGpioOut(BK4819_GPIO0_PIN28, false);
switch (Bandwidth)
{
default:
Bandwidth = BK4819_FILTER_BW_WIDE;
[[fallthrough]];
case BK4819_FILTER_BW_WIDE:
case BK4819_FILTER_BW_NARROW:
#ifdef ENABLE_AM_FIX
@@ -832,7 +862,7 @@ void RADIO_SetTxParameters(void)
BK4819_PickRXFilterPathBasedOnFrequency(gCurrentVfo->pTX->Frequency);
BK4819_ToggleGpioOut(BK4819_GPIO5_PIN1, true);
BK4819_ToggleGpioOut(BK4819_GPIO1_PIN29, true);
SYSTEM_DelayMs(5);
@@ -864,10 +894,7 @@ void RADIO_SetVfoState(VfoState_t State)
{
VfoState[0] = VFO_STATE_NORMAL;
VfoState[1] = VFO_STATE_NORMAL;
#ifdef ENABLE_FMRADIO
gFM_ResumeCountdown_500ms = 0;
#endif
gVFOStateResumeCountdown_500ms = 0;
}
else
{
@@ -877,15 +904,12 @@ void RADIO_SetVfoState(VfoState_t State)
VfoState[1] = VFO_STATE_TX_DISABLE;
}
else
{
unsigned int chan = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && gRxVfoIsActive) ? (gEeprom.RX_CHANNEL + 1) & 1 : gEeprom.RX_CHANNEL; // 1of11
chan = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.TX_CHANNEL : chan;
VfoState[chan] = State;
{ // 1of11
const unsigned int vfo = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_VFO : gEeprom.TX_VFO;
VfoState[vfo] = State;
}
#ifdef ENABLE_FMRADIO
gFM_ResumeCountdown_500ms = fm_resume_countdown_500ms;
#endif
gVFOStateResumeCountdown_500ms = vfo_state_resume_countdown_500ms;
}
gUpdateDisplay = true;
@@ -902,10 +926,10 @@ void RADIO_PrepareTX(void)
gScheduleDualWatch = false;
if (!gRxVfoIsActive)
{ // use the TX vfo
gEeprom.RX_CHANNEL = gEeprom.TX_CHANNEL;
gRxVfo = &gEeprom.VfoInfo[gEeprom.TX_CHANNEL];
gRxVfoIsActive = true;
{ // use the current RX vfo
gEeprom.RX_VFO = gEeprom.TX_VFO;
gRxVfo = gTxVfo;
gRxVfoIsActive = true;
}
// let the user see that DW is not active
@@ -939,7 +963,6 @@ void RADIO_PrepareTX(void)
State = VFO_STATE_TX_DISABLE;
}
else
//if (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0 || gCurrentVfo->CHANNEL_SAVE <= FREQ_CHANNEL_LAST)
if (TX_freq_check(gCurrentVfo->pTX->Frequency) == 0)
{ // TX frequency is allowed
if (gCurrentVfo->BUSY_CHANNEL_LOCK && gCurrentFunction == FUNCTION_RECEIVE)
@@ -958,10 +981,13 @@ void RADIO_PrepareTX(void)
if (State != VFO_STATE_NORMAL)
{ // TX not allowed
RADIO_SetVfoState(State);
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
gAlarmState = ALARM_STATE_OFF;
#endif
gDTMF_ReplyState = DTMF_REPLY_NONE;
AUDIO_PlayBeep(BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL);
return;
}
@@ -1045,8 +1071,12 @@ void RADIO_SendEndOfTransmission(void)
if (gEeprom.ROGER == ROGER_MODE_MDC)
BK4819_PlayRogerMDC();
if (gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_APOLLO)
BK4819_PlaySingleTone(2475, 250, 28, gEeprom.DTMF_SIDE_TONE);
if (gDTMF_CallState == DTMF_CALL_STATE_NONE &&
(gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN || gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH))
(gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_TX_DOWN ||
gCurrentVfo->DTMF_PTT_ID_TX_MODE == PTT_ID_BOTH))
{ // end-of-tx
if (gEeprom.DTMF_SIDE_TONE)
{
@@ -1058,15 +1088,14 @@ void RADIO_SendEndOfTransmission(void)
BK4819_EnterDTMF_TX(gEeprom.DTMF_SIDE_TONE);
BK4819_PlayDTMFString(
gEeprom.DTMF_DOWN_CODE,
0,
gEeprom.DTMF_FIRST_CODE_PERSIST_TIME,
gEeprom.DTMF_HASH_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_INTERVAL_TIME);
gEeprom.DTMF_DOWN_CODE,
0,
gEeprom.DTMF_FIRST_CODE_PERSIST_TIME,
gEeprom.DTMF_HASH_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_PERSIST_TIME,
gEeprom.DTMF_CODE_INTERVAL_TIME);
GPIO_ClearBit(&GPIOC->DATA, GPIOC_PIN_AUDIO_PATH);
gEnableSpeaker = false;
}

11
radio.h
View File

@@ -44,7 +44,8 @@ enum PTT_ID_t {
PTT_ID_OFF = 0, // OFF
PTT_ID_TX_UP, // BEGIN OF TX
PTT_ID_TX_DOWN, // END OF TX
PTT_ID_BOTH // BOTH
PTT_ID_BOTH, // BOTH
PTT_ID_APOLLO // Apolo quindar tones
};
typedef enum PTT_ID_t PTT_ID_t;
@@ -114,8 +115,16 @@ typedef struct VFO_Info_t
char Name[16];
} VFO_Info_t;
// Settings of the main VFO that is selected by the user
// The pointer follows gEeprom.RX_VFO index
extern VFO_Info_t *gTxVfo;
// Settings of the actual VFO that is now used for RX,
// It is being alternated by dual watch, and flipped by crossband
// The pointer follows gEeprom.RX_VFO
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;

View File

@@ -77,20 +77,20 @@ void SystickHandler(void)
if (gCurrentFunction == FUNCTION_POWER_SAVE)
DECREMENT_AND_TRIGGER(gPowerSave_10ms, gPowerSaveCountdownExpired);
if (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && gEeprom.DUAL_WATCH != DUAL_WATCH_OFF)
if (gScanStateDir == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && 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 (gScanState == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && gEeprom.DUAL_WATCH == DUAL_WATCH_OFF)
if (gScanStateDir == SCAN_OFF && gCssScanMode == CSS_SCAN_MODE_OFF && 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 (gScanState != SCAN_OFF || gCssScanMode == CSS_SCAN_MODE_SCANNING)
if (gScanStateDir != SCAN_OFF || gCssScanMode == CSS_SCAN_MODE_SCANNING)
if (gCurrentFunction != FUNCTION_MONITOR && gCurrentFunction != FUNCTION_TRANSMIT)
DECREMENT_AND_TRIGGER(ScanPauseDelayIn_10ms, gScheduleScanListen);
DECREMENT_AND_TRIGGER(gScanPauseDelayIn_10ms, gScheduleScanListen);
DECREMENT_AND_TRIGGER(gTailNoteEliminationCountdown_10ms, gFlagTailNoteEliminationComplete);

View File

@@ -107,6 +107,7 @@ void SETTINGS_SaveSettings(void)
EEPROM_WriteBuffer(0x0E78, State);
State[0] = gEeprom.BEEP_CONTROL;
State[0] |= gEeprom.KEY_M_LONG_PRESS_ACTION << 1;
State[1] = gEeprom.KEY_1_SHORT_PRESS_ACTION;
State[2] = gEeprom.KEY_1_LONG_PRESS_ACTION;
State[3] = gEeprom.KEY_2_SHORT_PRESS_ACTION;
@@ -117,8 +118,10 @@ void SETTINGS_SaveSettings(void)
EEPROM_WriteBuffer(0x0E90, State);
memset(Password, 0xFF, sizeof(Password));
Password[0] = gEeprom.POWER_ON_PASSWORD;
EEPROM_WriteBuffer(0x0E98, State);
#ifdef ENABLE_PWRON_PASSWORD
Password[0] = gEeprom.POWER_ON_PASSWORD;
#endif
EEPROM_WriteBuffer(0x0E98, Password);
#ifdef ENABLE_VOICE
memset(State, 0xFF, sizeof(State));
@@ -133,7 +136,7 @@ void SETTINGS_SaveSettings(void)
#endif
State[1] = gEeprom.ROGER;
State[2] = gEeprom.REPEATER_TAIL_TONE_ELIMINATION;
State[3] = gEeprom.TX_CHANNEL;
State[3] = gEeprom.TX_VFO;
EEPROM_WriteBuffer(0x0EA8, State);
State[0] = gEeprom.DTMF_SIDE_TONE;
@@ -184,10 +187,6 @@ void SETTINGS_SaveSettings(void)
EEPROM_WriteBuffer(0x0F40, State);
}
void SETTINGS_LoadChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO)
{
}
void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO, uint8_t Mode)
{
#ifdef ENABLE_NOAA
@@ -197,13 +196,13 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
const uint16_t OffsetMR = Channel * 16;
uint16_t OffsetVFO = OffsetMR;
if (!IS_MR_CHANNEL(Channel))
if (Channel > MR_CHANNEL_LAST)
{ // it's a VFO, not a channel
OffsetVFO = (VFO == 0) ? 0x0C80 : 0x0C90;
OffsetVFO += (Channel - FREQ_CHANNEL_FIRST) * 32;
}
if (Mode >= 2 || !IS_MR_CHANNEL(Channel))
if (Mode >= 2 || Channel > MR_CHANNEL_LAST)
{ // copy VFO to a channel
uint8_t State[8];
@@ -221,15 +220,16 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
| (pVFO->OUTPUT_POWER << 2)
| (pVFO->CHANNEL_BANDWIDTH << 1)
| (pVFO->FrequencyReverse << 0);
State[5] = (pVFO->DTMF_PTT_ID_TX_MODE << 1) | (pVFO->DTMF_DECODING_ENABLE << 0);
State[5] = ((pVFO->DTMF_PTT_ID_TX_MODE & 7u) << 1) | ((pVFO->DTMF_DECODING_ENABLE & 1u) << 0);
State[6] = pVFO->STEP_SETTING;
State[7] = pVFO->SCRAMBLING_TYPE;
EEPROM_WriteBuffer(OffsetVFO + 8, State);
SETTINGS_UpdateChannel(Channel, pVFO, true);
if (IS_MR_CHANNEL(Channel))
{
if (Channel <= MR_CHANNEL_LAST)
{ // it's a memory channel
#ifndef ENABLE_KEEP_MEM_NAME
// clear/reset the channel name
//memset(&State, 0xFF, sizeof(State));
@@ -252,6 +252,16 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
}
}
void SETTINGS_SaveBatteryCalibration(const uint16_t * batteryCalibration)
{
uint16_t buf[4];
EEPROM_WriteBuffer(0x1F40, batteryCalibration);
EEPROM_ReadBuffer( 0x1F48, buf, sizeof(buf));
buf[0] = batteryCalibration[4];
buf[1] = batteryCalibration[5];
EEPROM_WriteBuffer(0x1F48, buf);
}
void SETTINGS_UpdateChannel(uint8_t Channel, const VFO_Info_t *pVFO, bool keep)
{
#ifdef ENABLE_NOAA
@@ -262,7 +272,7 @@ void SETTINGS_UpdateChannel(uint8_t Channel, const VFO_Info_t *pVFO, bool keep)
uint8_t Attributes = 0xFF; // default attributes
uint16_t Offset = 0x0D60 + (Channel & ~7u);
Attributes &= ~MR_CH_COMPAND; // default to '0' = compander disabled
Attributes &= (uint8_t)(~MR_CH_COMPAND); // default to '0' = compander disabled
EEPROM_ReadBuffer(Offset, State, sizeof(State));
@@ -280,8 +290,9 @@ void SETTINGS_UpdateChannel(uint8_t Channel, const VFO_Info_t *pVFO, bool keep)
gMR_ChannelAttributes[Channel] = Attributes;
// #ifndef ENABLE_KEEP_MEM_NAME
if (IS_MR_CHANNEL(Channel))
{
if (Channel <= MR_CHANNEL_LAST)
{ // it's a memory channel
const uint16_t OffsetMR = Channel * 16;
if (!keep)
{ // clear/reset the channel name

View File

@@ -80,6 +80,8 @@ enum {
ACTION_OPT_ALARM,
ACTION_OPT_FM,
ACTION_OPT_1750,
ACTION_OPT_KEYLOCK,
ACTION_OPT_A_B,
ACTION_OPT_LEN
};
@@ -121,8 +123,14 @@ typedef struct {
#ifdef ENABLE_NOAA
uint8_t NoaaChannel[2];
#endif
uint8_t RX_CHANNEL;
uint8_t TX_CHANNEL;
// The actual VFO index (0-upper/1-lower) that is now used for RX,
// It is being alternated by dual watch, and flipped by crossband
uint8_t RX_VFO;
// The main VFO index (0-upper/1-lower) selected by the user
//
uint8_t TX_VFO;
uint8_t field7_0xa;
uint8_t field8_0xb;
@@ -218,8 +226,9 @@ typedef struct {
uint8_t field78_0x96;
uint8_t field79_0x97;
uint8_t _pad[1];
uint8_t KEY_M_LONG_PRESS_ACTION;
} EEPROM_Config_t;
extern EEPROM_Config_t gEeprom;
#ifdef ENABLE_FMRADIO
@@ -228,6 +237,7 @@ extern EEPROM_Config_t gEeprom;
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);
#endif

View File

@@ -44,12 +44,19 @@ void UI_DisplayAircopy(void)
if (gInputBoxIndex == 0)
{
NUMBER_ToDigits(gRxVfo->freq_config_RX.Frequency, String);
UI_DisplayFrequency(String, 16, 2, 0, 0);
UI_DisplaySmallDigits(2, String + 6, 97, 3, true);
uint32_t frequency = gRxVfo->freq_config_RX.Frequency;
sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000);
// show the remaining 2 small frequency digits
UI_PrintStringSmall(String + 7, 97, 0, 3);
String[7] = 0;
// show the main large frequency digits
UI_DisplayFrequency(String, 16, 2, false);
}
else {
const char * ascii = INPUTBOX_GetAscii();
sprintf(String, "%.3s.%.3s",ascii, ascii + 3);
UI_DisplayFrequency(String, 16, 2, false);
}
else
UI_DisplayFrequency(gInputBox, 16, 2, 1, 0);
memset(String, 0, sizeof(String));
if (gAirCopyIsSendMode == 0)

View File

@@ -22,66 +22,35 @@
#include "functions.h"
#include "ui/battery.h"
void UI_DisplayBattery(const uint8_t level, const uint8_t blink)
void UI_DrawBattery(uint8_t* bitmap, uint8_t level, uint8_t blink)
{
// if (gCurrentFunction != FUNCTION_TRANSMIT)
if (level < 2 && blink == 1) {
memset(bitmap, 0, sizeof(BITMAP_BatteryLevel1));
}
else
{
uint8_t bitmap[sizeof(BITMAP_BatteryLevel1)];
#if 1
if (level >= 2)
memmove(bitmap, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1));
if (level > 1)
{
memmove(bitmap, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1));
#ifndef ENABLE_REVERSE_BAT_SYMBOL
uint8_t *pb = bitmap + sizeof(BITMAP_BatteryLevel1);
if (level >= 2)
memmove(pb - 4, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
if (level >= 5)
memmove(pb - 7, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
if (level >= 7)
memmove(pb - 10, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
if (level >= 9)
memmove(pb - 13, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
#else
if (level >= 2)
memmove(bitmap + 3, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
if (level >= 5)
memmove(bitmap + 6, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
if (level >= 7)
memmove(bitmap + 9, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
if (level >= 9)
memmove(bitmap + 12, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
#endif
unsigned int i;
uint8_t bars = level - 1;
if (bars > 4)
bars = 4;
for (i = 0; i < bars; i++)
{
#ifndef ENABLE_REVERSE_BAT_SYMBOL
memcpy(bitmap + sizeof(BITMAP_BatteryLevel1) - 4 - (i * 3), BITMAP_BatteryLevel, 2);
#else
memcpy(bitmap + 3 + (i * 3) + 0, BITMAP_BatteryLevel, 2);
#endif
}
}
else
if (blink == 1)
memmove(bitmap, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1));
else
memset(bitmap, 0, sizeof(bitmap));
#else
if (level > 0)
{
const uint8_t lev = (level <= 11) ? level : 11;
memmove(bitmap, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1));
#ifdef ENABLE_REVERSE_BAT_SYMBOL
for (uint8_t i = 0; i < lev; i++)
bitmap[3 + i] = (i & 1u) ? 0b01011101 : 0b01011101;
#else
for (uint8_t i = 0; i < lev; i++)
bitmap[sizeof(bitmap) - 3 - i] = (i & 1u) ? 0b01011101 : 0b01011101;
#endif
}
else
memset(bitmap, 0, sizeof(bitmap));
#endif
// col lne, siz, bm
ST7565_DrawLine(LCD_WIDTH - sizeof(bitmap), 0, sizeof(bitmap), bitmap);
}
}
void UI_DisplayBattery(uint8_t level, uint8_t blink)
{
uint8_t bitmap[sizeof(BITMAP_BatteryLevel1)];
UI_DrawBattery(bitmap, level, blink);
ST7565_DrawLine(LCD_WIDTH - sizeof(bitmap), 0, sizeof(bitmap), bitmap);
}

View File

@@ -18,8 +18,8 @@
#define UI_BATTERY_H
#include <stdint.h>
void UI_DisplayBattery(const uint8_t Level, const uint8_t blink);
void UI_DrawBattery(uint8_t* bitmap, uint8_t level, uint8_t blink);
void UI_DisplayBattery(uint8_t Level, uint8_t blink);
#endif

View File

@@ -90,11 +90,14 @@ void UI_DisplayFM(void)
{
if (gInputBoxIndex == 0)
{
NUMBER_ToDigits(gEeprom.FM_FrequencyPlaying * 10000, String);
UI_DisplayFrequency(String, 23, 4, false, true);
sprintf(String, "%3d.%d", gEeprom.FM_FrequencyPlaying / 10, gEeprom.FM_FrequencyPlaying % 10);
UI_DisplayFrequency(String, 32, 4, true);
}
else {
const char * ascii = INPUTBOX_GetAscii();
sprintf(String, "%.3s.%.1s",ascii, ascii + 3);
UI_DisplayFrequency(String, 32, 4, false);
}
else
UI_DisplayFrequency(gInputBox, 23, 4, true, false);
ST7565_BlitFullScreen();
return;

View File

@@ -72,12 +72,12 @@ void UI_PrintString(const char *pString, uint8_t Start, uint8_t End, uint8_t Lin
for (i = 0; i < Length; i++)
{
if (pString[i] >= ' ' && pString[i] < 127)
const unsigned int ofs = (unsigned int)Start + (i * Width);
if (pString[i] > ' ' && pString[i] < 127)
{
const unsigned int index = pString[i] - ' ';
const unsigned int ofs = (unsigned int)Start + (i * Width);
memmove(gFrameBuffer[Line + 0] + ofs, &gFontBig[index][0], 8);
memmove(gFrameBuffer[Line + 1] + ofs, &gFontBig[index][8], 7);
const unsigned int index = pString[i] - ' ' - 1;
memmove(gFrameBuffer[Line + 0] + ofs, &gFontBig[index][0], 7);
memmove(gFrameBuffer[Line + 1] + ofs, &gFontBig[index][7], 7);
}
}
}
@@ -95,9 +95,9 @@ void UI_PrintStringSmall(const char *pString, uint8_t Start, uint8_t End, uint8_
uint8_t *pFb = gFrameBuffer[Line] + Start;
for (i = 0; i < Length; i++)
{
if (pString[i] >= 32)
if (pString[i] > ' ')
{
const unsigned int index = (unsigned int)pString[i] - 32;
const unsigned int index = (unsigned int)pString[i] - ' ' - 1;
if (index < ARRAY_SIZE(gFontSmall))
memmove(pFb + (i * char_spacing) + 1, &gFontSmall[index], char_width);
}
@@ -118,9 +118,9 @@ void UI_PrintStringSmall(const char *pString, uint8_t Start, uint8_t End, uint8_
uint8_t *pFb = gFrameBuffer[Line] + Start;
for (i = 0; i < Length; i++)
{
if (pString[i] >= 32)
if (pString[i] > ' ')
{
const unsigned int index = (unsigned int)pString[i] - 32;
const unsigned int index = (unsigned int)pString[i] - ' ' - 1;
if (index < ARRAY_SIZE(gFontSmallBold))
memmove(pFb + (i * char_spacing) + 1, &gFontSmallBold[index], char_width);
}
@@ -135,126 +135,46 @@ void UI_PrintStringSmallBuffer(const char *pString, uint8_t *buffer)
const unsigned int char_spacing = char_width + 1;
for (i = 0; i < strlen(pString); i++)
{
if (pString[i] >= 32)
if (pString[i] > ' ')
{
const unsigned int index = (unsigned int)pString[i] - 32;
const unsigned int index = (unsigned int)pString[i] - ' ' - 1;
if (index < ARRAY_SIZE(gFontSmall))
memmove(buffer + (i * char_spacing) + 1, &gFontSmall[index], char_width);
}
}
}
void UI_DisplayFrequency(const char *pDigits, uint8_t X, uint8_t Y, bool bDisplayLeadingZero, bool bFlag)
void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center)
{
const unsigned int char_width = 13;
uint8_t *pFb0 = gFrameBuffer[Y] + X;
uint8_t *pFb1 = pFb0 + 128;
bool bCanDisplay = false;
unsigned int i = 0;
// MHz
while (i < 3)
{
const unsigned int Digit = pDigits[i++];
if (bDisplayLeadingZero || bCanDisplay || Digit > 0)
uint8_t len = strlen(string);
for(int i = 0; i < len; i++) {
char c = string[i];
if(c=='-') c = '9' + 1;
if (bCanDisplay || c != ' ')
{
bCanDisplay = true;
memmove(pFb0, gFontBigDigits[Digit], char_width);
memmove(pFb1, gFontBigDigits[Digit] + char_width, char_width);
if(c>='0' && c<='9' + 1) {
memcpy(pFb0 + 2, gFontBigDigits[c-'0'], char_width - 3);
memcpy(pFb1 + 2, gFontBigDigits[c-'0'] + char_width - 3, char_width - 3);
}
else if(c=='.') {
*pFb1 = 0x60; pFb0++; pFb1++;
*pFb1 = 0x60; pFb0++; pFb1++;
*pFb1 = 0x60; pFb0++; pFb1++;
continue;
}
}
else
if (bFlag)
{
else if (center) {
pFb0 -= 6;
pFb1 -= 6;
}
pFb0 += char_width;
pFb1 += char_width;
}
// decimal point
*pFb1 = 0x60; pFb0++; pFb1++;
*pFb1 = 0x60; pFb0++; pFb1++;
*pFb1 = 0x60; pFb0++; pFb1++;
// kHz
while (i < 6)
{
const unsigned int Digit = pDigits[i++];
memmove(pFb0, gFontBigDigits[Digit], char_width);
memmove(pFb1, gFontBigDigits[Digit] + char_width, char_width);
pFb0 += char_width;
pFb1 += char_width;
}
}
void UI_DisplayFrequencySmall(const char *pDigits, uint8_t X, uint8_t Y, bool bDisplayLeadingZero)
{
const unsigned int char_width = ARRAY_SIZE(gFontSmall[0]);
const unsigned int spacing = 1 + char_width;
uint8_t *pFb = gFrameBuffer[Y] + X;
bool bCanDisplay = false;
unsigned int i = 0;
// MHz
while (i < 3)
{
const unsigned int c = pDigits[i++];
if (bDisplayLeadingZero || bCanDisplay || c > 0)
{
#if 0
memmove(pFb + 1, gFontSmallDigits[c], char_width);
#else
const unsigned int index = (c < 10) ? '0' - 32 + c : '-' - 32;
memmove(pFb + 1, gFontSmall[index], char_width);
#endif
pFb += spacing;
bCanDisplay = true;
}
}
// decimal point
pFb++;
pFb++;
*pFb++ = 0x60;
*pFb++ = 0x60;
pFb++;
// kHz
while (i < 8)
{
const unsigned int c = pDigits[i++];
#if 0
memmove(pFb + 1, gFontSmallDigits[c], char_width);
#else
const unsigned int index = (c < 10) ? '0' - 32 + c : '-' - 32;
memmove(pFb + 1, gFontSmall[index], char_width);
#endif
pFb += spacing;
}
}
void UI_DisplaySmallDigits(const uint8_t size, const char *str, const uint8_t x, const uint8_t y, const bool display_leading_zeros)
{
const unsigned int char_width = ARRAY_SIZE(gFontSmall[0]);
const unsigned int spacing = 1 + char_width;
bool display = display_leading_zeros;
unsigned int xx;
unsigned int i;
for (i = 0, xx = x; i < size; i++)
{
const unsigned int c = (unsigned int)str[i];
if (c > 0)
display = true; // non '0'
if (display && c < 11)
{
#if 0
memmove(gFrameBuffer[y] + xx, gFontSmallDigits[c], char_width);
#else
const unsigned int index = (c < 10) ? '0' - 32 + c : '-' - 32;
memmove(gFrameBuffer[y] + xx + 1, gFontSmall[index], char_width);
#endif
xx += spacing;
}
}
}

View File

@@ -28,9 +28,7 @@ void UI_PrintStringSmall(const char *pString, uint8_t Start, uint8_t End, uint8_
void UI_PrintStringSmallBold(const char *pString, uint8_t Start, uint8_t End, uint8_t Line);
#endif
void UI_PrintStringSmallBuffer(const char *pString, uint8_t *buffer);
void UI_DisplayFrequency(const char *pDigits, uint8_t X, uint8_t Y, bool bDisplayLeadingZero, bool bFlag);
void UI_DisplayFrequencySmall(const char *pDigits, uint8_t X, uint8_t Y, bool bDisplayLeadingZero);
void UI_DisplaySmallDigits(const uint8_t size, const char *str, const uint8_t x, const uint8_t y, const bool display_leading_zeros);
void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center);
#endif

View File

@@ -19,9 +19,10 @@
#include "ui/inputbox.h"
char gInputBox[8];
char inputBoxAscii[9];
uint8_t gInputBoxIndex;
void INPUTBOX_Append(char Digit)
void INPUTBOX_Append(const KEY_Code_t Digit)
{
if (gInputBoxIndex >= sizeof(gInputBox))
return;
@@ -29,6 +30,15 @@ void INPUTBOX_Append(char Digit)
if (gInputBoxIndex == 0)
memset(gInputBox, 10, sizeof(gInputBox));
gInputBox[gInputBoxIndex++] = Digit;
if (Digit != KEY_INVALID)
gInputBox[gInputBoxIndex++] = (char)(Digit - KEY_0);
}
const char* INPUTBOX_GetAscii()
{
for(int i = 0; i < 8; i++) {
char c = gInputBox[i];
inputBoxAscii[i] = (c==10)? '-' : '0' + c;
}
return inputBoxAscii;
}

View File

@@ -19,10 +19,13 @@
#include <stdint.h>
#include "driver/keyboard.h"
extern char gInputBox[8];
extern uint8_t gInputBoxIndex;
void INPUTBOX_Append(char Digit);
void INPUTBOX_Append(const KEY_Code_t Digit);
const char* INPUTBOX_GetAscii();
#endif

View File

@@ -14,6 +14,8 @@
* limitations under the License.
*/
#ifdef ENABLE_PWRON_PASSWORD
#include <string.h>
#include "ARMCM0.h"
@@ -100,10 +102,9 @@ void UI_DisplayLock(void)
uint32_t Password;
gInputBoxIndex = 0;
Password = StrToUL(INPUTBOX_GetAscii());
NUMBER_Get(gInputBox, &Password);
if ((gEeprom.POWER_ON_PASSWORD * 100) == Password)
if ((gEeprom.POWER_ON_PASSWORD) == Password)
{
AUDIO_PlayBeep(BEEP_1KHZ_60MS_OPTIONAL);
return;
@@ -156,3 +157,5 @@ void UI_DisplayLock(void)
}
}
}
#endif

View File

@@ -17,7 +17,9 @@
#ifndef UI_LOCK_H
#define UI_LOCK_H
void UI_DisplayLock(void);
#ifdef ENABLE_PWRON_PASSWORD
void UI_DisplayLock(void);
#endif
#endif

732
ui/main.c
View File

@@ -45,259 +45,224 @@ void UI_drawBars(uint8_t *p, const unsigned int level)
switch (level)
{
default:
case 7: memmove(p + 20, BITMAP_AntennaLevel6, sizeof(BITMAP_AntennaLevel6));
case 6: memmove(p + 17, BITMAP_AntennaLevel5, sizeof(BITMAP_AntennaLevel5));
case 5: memmove(p + 14, BITMAP_AntennaLevel4, sizeof(BITMAP_AntennaLevel4));
case 4: memmove(p + 11, BITMAP_AntennaLevel3, sizeof(BITMAP_AntennaLevel3));
case 3: memmove(p + 8, BITMAP_AntennaLevel2, sizeof(BITMAP_AntennaLevel2));
case 2: memmove(p + 5, BITMAP_AntennaLevel1, sizeof(BITMAP_AntennaLevel1));
case 1: memmove(p + 0, BITMAP_Antenna, sizeof(BITMAP_Antenna));
case 0: break;
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;
}
}
#ifdef ENABLE_AUDIO_BAR
unsigned int sqrt16(unsigned int value)
{ // return square root of 'value'
unsigned int shift = 16; // number of bits supplied in 'value' .. 2 ~ 32
unsigned int bit = 1u << --shift;
unsigned int sqrti = 0;
while (bit)
{
const unsigned int temp = ((sqrti << 1) | bit) << shift--;
if (value >= temp)
{
value -= temp;
sqrti |= bit;
}
bit >>= 1;
}
return sqrti;
}
void UI_DisplayAudioBar(void)
unsigned int sqrt16(unsigned int value)
{ // return square root of 'value'
unsigned int shift = 16; // number of bits supplied in 'value' .. 2 ~ 32
unsigned int bit = 1u << --shift;
unsigned int sqrti = 0;
while (bit)
{
if (gSetting_mic_bar)
{
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 (gScreenToDisplay != DISPLAY_MAIN)
return;
#if 1
// TX audio level
if (gCurrentFunction != FUNCTION_TRANSMIT ||
gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return; // screen is in use
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState != ALARM_STATE_OFF)
return;
#endif
const unsigned int voice_amp = BK4819_GetVoiceAmplitudeOut(); // 15:0
// const unsigned int max = 65535;
// const unsigned int level = ((voice_amp * bar_width) + (max / 2)) / max; // with rounding
// const unsigned int len = (level <= bar_width) ? level : bar_width;
// 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;
#else
// TX/RX AF input level (dB)
const uint8_t af_tx_rx = BK4819_GetAfTxRx(); // 6:0
const unsigned int max = 63;
const unsigned int level = (((uint16_t)af_tx_rx * bar_width) + (max / 2)) / max; // with rounding
const unsigned int len = (level <= bar_width) ? level : bar_width;
#endif
uint8_t *p_line = gFrameBuffer[line];
memset(p_line, 0, LCD_WIDTH);
#if 1
// solid bar
for (i = 0; i < bar_width; i++)
p_line[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
#else
// knuled bar
for (i = 0; i < bar_width; i += 2)
p_line[bar_x + i] = (i <= len) ? 0x7f : 0x41;
#endif
if (gCurrentFunction == FUNCTION_TRANSMIT)
ST7565_BlitFullScreen();
const unsigned int temp = ((sqrti << 1) | bit) << shift--;
if (value >= temp) {
value -= temp;
sqrti |= bit;
}
bit >>= 1;
}
return sqrti;
}
void UI_DisplayAudioBar(void)
{
if (gSetting_mic_bar)
{
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 ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
{
return; // screen is in use
}
#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750)
if (gAlarmState != ALARM_STATE_OFF)
return;
#endif
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;
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;
if (gCurrentFunction == FUNCTION_TRANSMIT)
ST7565_BlitFullScreen();
}
}
#endif
#if defined(ENABLE_RSSI_BAR)
void UI_DisplayRSSIBar(const int16_t rssi, const bool now)
{
void UI_DisplayRSSIBar(const int16_t rssi, const bool now)
{
// const int16_t s0_dBm = -127; // S0 .. base level
const int16_t s0_dBm = -147; // S0 .. base level
const int16_t s0_dBm = -147; // S0 .. base level
const int16_t s9_dBm = s0_dBm + (6 * 9); // S9 .. 6dB/S-Point
const int16_t bar_max_dBm = s9_dBm + 30; // S9+30dB
const int16_t s9_dBm = s0_dBm + (6 * 9); // S9 .. 6dB/S-Point
const int16_t bar_max_dBm = s9_dBm + 30; // S9+30dB
// const int16_t bar_min_dBm = s0_dBm + (6 * 0); // S0
const int16_t bar_min_dBm = s0_dBm + (6 * 4); // S4
const int16_t bar_min_dBm = s0_dBm + (6 * 4); // S4
// ************
// ************
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 unsigned int bar_width = LCD_WIDTH - 1 - bar_x;
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 unsigned int bar_width = LCD_WIDTH - 1 - bar_x;
const int16_t rssi_dBm = (rssi / 2) - 160;
const int16_t clamped_dBm = (rssi_dBm <= bar_min_dBm) ? bar_min_dBm : (rssi_dBm >= bar_max_dBm) ? bar_max_dBm : rssi_dBm;
const unsigned int bar_range_dB = bar_max_dBm - bar_min_dBm;
const unsigned int len = ((clamped_dBm - bar_min_dBm) * bar_width) / bar_range_dB;
const int16_t rssi_dBm = (rssi / 2) - 160;
const int16_t clamped_dBm = (rssi_dBm <= bar_min_dBm) ? bar_min_dBm : (rssi_dBm >= bar_max_dBm) ? bar_max_dBm : rssi_dBm;
const unsigned int bar_range_dB = bar_max_dBm - bar_min_dBm;
const unsigned int len = ((clamped_dBm - bar_min_dBm) * bar_width) / bar_range_dB;
const unsigned int line = 3;
uint8_t *p_line = gFrameBuffer[line];
const unsigned int line = 3;
uint8_t *p_line = gFrameBuffer[line];
char s[16];
unsigned int i;
char s[16];
unsigned int i;
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 (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
if (now)
memset(p_line, 0, LCD_WIDTH);
if (gCurrentFunction == FUNCTION_TRANSMIT ||
gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return; // display is in use
if (rssi_dBm >= (s9_dBm + 6))
{ // S9+XXdB, 1dB increment
const char *fmt[] = {"%3d 9+%u ", "%3d 9+%2u "};
const unsigned int s9_dB = ((rssi_dBm - s9_dBm) <= 99) ? rssi_dBm - s9_dBm : 99;
sprintf(s, (s9_dB < 10) ? fmt[0] : fmt[1], rssi_dBm, s9_dB);
}
else
{ // S0 ~ S9, 6dB per S-point
const unsigned int s_level = (rssi_dBm >= s0_dBm) ? (rssi_dBm - s0_dBm) / 6 : 0;
sprintf(s, "%4d S%u ", rssi_dBm, s_level);
}
UI_PrintStringSmall(s, 2, 0, line);
if (now)
memset(p_line, 0, LCD_WIDTH);
#if 1
// solid bar
for (i = 0; i < bar_width; i++)
p_line[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
#else
// knuled bar
for (i = 0; i < bar_width; i += 2)
p_line[bar_x + i] = (i <= len) ? 0x7f : 0x41;
#endif
if (now)
ST7565_BlitFullScreen();
if (rssi_dBm >= (s9_dBm + 6))
{ // S9+XXdB, 1dB increment
const char *fmt[] = {"%3d 9+%u ", "%3d 9+%2u "};
const unsigned int s9_dB = ((rssi_dBm - s9_dBm) <= 99) ? rssi_dBm - s9_dBm : 99;
sprintf(s, (s9_dB < 10) ? fmt[0] : fmt[1], rssi_dBm, s9_dB);
}
else
{ // S0 ~ S9, 6dB per S-point
const unsigned int s_level = (rssi_dBm >= s0_dBm) ? (rssi_dBm - s0_dBm) / 6 : 0;
sprintf(s, "%4d S%u ", rssi_dBm, s_level);
}
UI_PrintStringSmall(s, 2, 0, line);
#if 1
// solid bar
for (i = 0; i < bar_width; i++)
p_line[bar_x + i] = (i > len) ? ((i & 1) == 0) ? 0x41 : 0x00 : ((i & 1) == 0) ? 0x7f : 0x3e;
#else
// knuled bar
for (i = 0; i < bar_width; i += 2)
p_line[bar_x + i] = (i <= len) ? 0x7f : 0x41;
#endif
if (now)
ST7565_BlitFullScreen();
}
#endif
void UI_UpdateRSSI(const int16_t rssi, const int vfo)
{
#ifdef ENABLE_RSSI_BAR
#ifdef ENABLE_RSSI_BAR
// optional larger RSSI dBm, S-point and bar level
(void)vfo; // unused
if (center_line != CENTER_LINE_RSSI)
return;
// optional larger RSSI dBm, S-point and bar level
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING)
{
UI_DisplayRSSIBar(rssi, true);
}
if (center_line != CENTER_LINE_RSSI)
return;
#else
if (gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING)
{
UI_DisplayRSSIBar(rssi, true);
}
// original little RS bars
#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 uint8_t Line = (vfo == 0) ? 3 : 7;
uint8_t *p_line = gFrameBuffer[Line - 1];
// TODO: sort out all 8 values from the eeprom
#if 0
// dBm -105 -100 -95 -90 -70 -65 -60 -55
// RSSI 110 120 130 140 180 190 200 210
// 0000C0 6E 00 78 00 82 00 8C 00 B4 00 BE 00 C8 00 D2 00
//
const unsigned int band = 1;
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];
#else
const int16_t level0 = (-115 + 160) * 2; // dB
const int16_t level1 = ( -89 + 160) * 2; // dB
const int16_t level2 = ( -64 + 160) * 2; // dB
const int16_t level3 = ( -39 + 160) * 2; // dB
#endif
const int16_t level01 = (level0 + level1) / 2;
const int16_t level12 = (level1 + level2) / 2;
const int16_t level23 = (level2 + level3) / 2;
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];
gVFO_RSSI[vfo] = rssi;
const int16_t level01 = (level0 + level1) / 2;
const int16_t level12 = (level1 + level2) / 2;
const int16_t level23 = (level2 + level3) / 2;
uint8_t rssi_level = 0;
gVFO_RSSI[vfo] = rssi;
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;
uint8_t rssi_level = 0;
if (gVFO_RSSI_bar_level[vfo] == rssi_level)
return;
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;
gVFO_RSSI_bar_level[vfo] = rssi_level;
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
if (gEeprom.KEY_LOCK && gKeypadLocked > 0)
return; // display is in use
p_line = gFrameBuffer[Line - 1];
if (gCurrentFunction == FUNCTION_TRANSMIT || gScreenToDisplay != DISPLAY_MAIN)
return; // display is in use
memset(p_line, 0, 23);
p_line = gFrameBuffer[Line - 1];
// untested !!!
memset(p_line, 0, 23);
if (rssi_level == 0)
p_line = NULL;
else
UI_drawBars(p_line, rssi_level);
// untested !!!
ST7565_DrawLine(0, Line, 23, p_line);
#endif
if (rssi_level == 0)
p_line = NULL;
else
UI_drawBars(p_line, rssi_level);
ST7565_DrawLine(0, Line, 23, p_line);
#endif
}
// ***************************************************************************
@@ -311,12 +276,6 @@ void UI_DisplayMain(void)
center_line = CENTER_LINE_NONE;
// #ifdef SINGLE_VFO_CHAN
// const bool single_vfo = (gEeprom.DUAL_WATCH == DUAL_WATCH_OFF && gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? true : false;
// #else
const bool single_vfo = false;
// #endif
// clear the screen
memset(gFrameBuffer, 0, sizeof(gFrameBuffer));
@@ -328,30 +287,17 @@ void UI_DisplayMain(void)
return;
}
unsigned int activeTxVFO = gRxVfoIsActive ? gEeprom.RX_VFO : gEeprom.TX_VFO;
for (vfo_num = 0; vfo_num < 2; vfo_num++)
{
const unsigned int line = (vfo_num == 0) ? line0 : line1;
uint8_t channel = gEeprom.TX_CHANNEL;
// uint8_t tx_channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
const bool same_vfo = (channel == vfo_num) ? true : false;
const bool isMainVFO = (vfo_num == gEeprom.TX_VFO);
uint8_t *p_line0 = gFrameBuffer[line + 0];
uint8_t *p_line1 = gFrameBuffer[line + 1];
uint8_t mode = 0;
uint8_t state;
unsigned int mode = 0;
if (single_vfo)
{ // we're in single VFO mode - screen is dedicated to just one VFO
if (!same_vfo)
continue; // skip the unused vfo
}
if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF && gRxVfoIsActive)
channel = gEeprom.RX_CHANNEL; // we're currently monitoring the other VFO
if (channel != vfo_num)
if (activeTxVFO != vfo_num) // this is not active TX VFO
{
if (gDTMF_CallState != DTMF_CALL_STATE_NONE || gDTMF_IsTx || gDTMF_InputMode)
{ // show DTMF stuff
@@ -364,7 +310,7 @@ void UI_DisplayMain(void)
if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT)
strcpy(String, (gDTMF_State == DTMF_STATE_CALL_OUT_RSP) ? "CALL OUT(RSP)" : "CALL OUT");
else
if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED)
if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY)
sprintf(String, "CALL FRM:%s", (DTMF_FindContact(gDTMF_Caller, Contact)) ? Contact : gDTMF_Caller);
else
if (gDTMF_IsTx)
@@ -373,10 +319,8 @@ void UI_DisplayMain(void)
else
{
sprintf(String, ">%s", gDTMF_InputBox);
center_line = CENTER_LINE_IN_USE;
}
UI_PrintString(String, 2, 0, vfo_num * 3, 8);
UI_PrintString(String, 2, 0, 0 + (vfo_num * 3), 8);
memset(String, 0, sizeof(String));
if (!gDTMF_InputMode)
@@ -385,16 +329,12 @@ void UI_DisplayMain(void)
if (gDTMF_CallState == DTMF_CALL_STATE_CALL_OUT)
sprintf(String, ">%s", (DTMF_FindContact(gDTMF_String, Contact)) ? Contact : gDTMF_String);
else
if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED)
if (gDTMF_CallState == DTMF_CALL_STATE_RECEIVED || gDTMF_CallState == DTMF_CALL_STATE_RECEIVED_STAY)
sprintf(String, ">%s", (DTMF_FindContact(gDTMF_Callee, Contact)) ? Contact : gDTMF_Callee);
else
if (gDTMF_IsTx)
sprintf(String, ">%s", gDTMF_String);
}
else
{
center_line = CENTER_LINE_IN_USE;
}
UI_PrintString(String, 2, 0, 2 + (vfo_num * 3), 8);
center_line = CENTER_LINE_IN_USE;
@@ -402,40 +342,34 @@ void UI_DisplayMain(void)
}
// highlight the selected/used VFO with a marker
if (!single_vfo && same_vfo)
if (isMainVFO)
memmove(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default));
else
if (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF)
memmove(p_line0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault));
}
else
if (!single_vfo)
else // active TX VFO
{ // highlight the selected/used VFO with a marker
if (same_vfo)
if (isMainVFO)
memmove(p_line0 + 0, BITMAP_VFO_Default, sizeof(BITMAP_VFO_Default));
else
//if (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF)
memmove(p_line0 + 0, BITMAP_VFO_NotDefault, sizeof(BITMAP_VFO_NotDefault));
}
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // transmitting
#ifdef ENABLE_ALARM
if (gAlarmState == ALARM_STATE_ALARM)
mode = 2;
else
#endif
#ifdef ENABLE_ALARM
if (gAlarmState == ALARM_STATE_ALARM)
mode = 2;
else
#endif
{
channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (channel == vfo_num)
if (activeTxVFO == vfo_num)
{ // show the TX symbol
mode = 1;
#ifdef ENABLE_SMALL_BOLD
UI_PrintStringSmallBold("TX", 14, 0, line);
#else
UI_PrintStringSmall("TX", 14, 0, line);
#endif
#ifdef ENABLE_SMALL_BOLD
UI_PrintStringSmallBold("TX", 14, 0, line);
#else
UI_PrintStringSmall("TX", 14, 0, line);
#endif
}
}
}
@@ -445,119 +379,135 @@ void UI_DisplayMain(void)
if ((gCurrentFunction == FUNCTION_RECEIVE ||
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING) &&
gEeprom.RX_CHANNEL == vfo_num)
gEeprom.RX_VFO == vfo_num)
{
#ifdef ENABLE_SMALL_BOLD
UI_PrintStringSmallBold("RX", 14, 0, line);
#else
UI_PrintStringSmall("RX", 14, 0, line);
#endif
#ifdef ENABLE_SMALL_BOLD
UI_PrintStringSmallBold("RX", 14, 0, line);
#else
UI_PrintStringSmall("RX", 14, 0, line);
#endif
}
}
if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo_num]))
if (gEeprom.ScreenChannel[vfo_num] <= MR_CHANNEL_LAST)
{ // channel mode
const unsigned int x = 2;
const bool inputting = (gInputBoxIndex == 0 || gEeprom.TX_CHANNEL != vfo_num) ? false : true;
const bool inputting = (gInputBoxIndex == 0 || gEeprom.TX_VFO != vfo_num) ? false : true;
if (!inputting)
NUMBER_ToDigits(gEeprom.ScreenChannel[vfo_num] + 1, String); // show the memory channel number
sprintf(String, "M%u", gEeprom.ScreenChannel[vfo_num] + 1);
else
memmove(String + 5, gInputBox, 3); // show the input text
UI_PrintStringSmall("M", x, 0, line + 1);
UI_DisplaySmallDigits(3, String + 5, x + 7, line + 1, inputting);
}
else
if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]))
{ // frequency mode
// show the frequency band number
const unsigned int x = 2; // was 14
// sprintf(String, "FB%u", 1 + gEeprom.ScreenChannel[vfo_num] - FREQ_CHANNEL_FIRST);
sprintf(String, "VFO%u", 1 + gEeprom.ScreenChannel[vfo_num] - FREQ_CHANNEL_FIRST);
sprintf(String, "M%.3s", INPUTBOX_GetAscii()); // show the input text
UI_PrintStringSmall(String, x, 0, line + 1);
}
#ifdef ENABLE_NOAA
else
{
if (gInputBoxIndex == 0 || gEeprom.TX_CHANNEL != vfo_num)
{ // channel number
sprintf(String, "N%u", 1 + gEeprom.ScreenChannel[vfo_num] - NOAA_CHANNEL_FIRST);
}
else
{ // user entering channel number
sprintf(String, "N%u%u", '0' + gInputBox[0], '0' + gInputBox[1]);
}
UI_PrintStringSmall(String, 7, 0, line + 1);
else if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]))
{ // frequency mode
// show the frequency band number
const unsigned int x = 2;
char * buf = gEeprom.VfoInfo[vfo_num].pRX->Frequency < 100000000 ? "" : "+";
sprintf(String, "F%u%s", 1 + gEeprom.ScreenChannel[vfo_num] - FREQ_CHANNEL_FIRST, buf);
UI_PrintStringSmall(String, x, 0, line + 1);
}
#ifdef ENABLE_NOAA
else
{
if (gInputBoxIndex == 0 || gEeprom.TX_VFO != vfo_num)
{ // channel number
sprintf(String, "N%u", 1 + gEeprom.ScreenChannel[vfo_num] - NOAA_CHANNEL_FIRST);
}
#endif
else
{ // user entering channel number
sprintf(String, "N%u%u", '0' + gInputBox[0], '0' + gInputBox[1]);
}
UI_PrintStringSmall(String, 7, 0, line + 1);
}
#endif
// ************
state = VfoState[vfo_num];
unsigned int state = VfoState[vfo_num];
#ifdef ENABLE_ALARM
if (gCurrentFunction == FUNCTION_TRANSMIT && gAlarmState == ALARM_STATE_ALARM)
{
channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (channel == vfo_num)
state = VFO_STATE_ALARM;
}
#endif
#ifdef ENABLE_ALARM
if (gCurrentFunction == FUNCTION_TRANSMIT && gAlarmState == ALARM_STATE_ALARM) {
if (activeTxVFO == vfo_num)
state = VFO_STATE_ALARM;
}
#endif
uint32_t frequency = gEeprom.VfoInfo[vfo_num].pRX->Frequency;
if (state != VFO_STATE_NORMAL)
{
const char *state_list[] = {"", "BUSY", "BAT LOW", "TX DISABLE", "TIMEOUT", "ALARM", "VOLT HIGH"};
if (state >= 0 && state < ARRAY_SIZE(state_list))
if (state < ARRAY_SIZE(state_list))
UI_PrintString(state_list[state], 31, 0, line, 8);
}
else
if (gInputBoxIndex > 0 && IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]) && gEeprom.TX_CHANNEL == vfo_num)
else if (gInputBoxIndex > 0 && IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]) && gEeprom.TX_VFO == vfo_num)
{ // user entering a frequency
UI_DisplayFrequency(gInputBox, 32, line, true, false);
const char * ascii = INPUTBOX_GetAscii();
bool isGigaF = frequency>=100000000;
sprintf(String, "%.*s.%.3s", 3 + isGigaF, ascii, ascii + 3 + isGigaF);
#ifdef ENABLE_BIG_FREQ
if(!isGigaF) {
// show the remaining 2 small frequency digits
UI_PrintStringSmall(String + 7, 113, 0, line + 1);
String[7] = 0;
// show the main large frequency digits
UI_DisplayFrequency(String, 32, line, false);
}
else
#endif
{
// show the frequency in the main font
UI_PrintString(String, 32, 0, line, 8);
}
// center_line = CENTER_LINE_IN_USE;
break;
}
else
{
uint32_t frequency = gEeprom.VfoInfo[vfo_num].pRX->Frequency;
if (gCurrentFunction == FUNCTION_TRANSMIT)
{ // transmitting
channel = (gEeprom.CROSS_BAND_RX_TX == CROSS_BAND_OFF) ? gEeprom.RX_CHANNEL : gEeprom.TX_CHANNEL;
if (channel == vfo_num)
if (activeTxVFO == vfo_num)
frequency = gEeprom.VfoInfo[vfo_num].pTX->Frequency;
}
if (IS_MR_CHANNEL(gEeprom.ScreenChannel[vfo_num]))
{ // channel mode
if (gEeprom.ScreenChannel[vfo_num] <= MR_CHANNEL_LAST)
{ // it's a channel
// show the channel symbols
// show the scan list assigment symbols
const uint8_t attributes = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if (attributes & MR_CH_SCANLIST1)
memmove(p_line0 + 113, BITMAP_ScanList1, sizeof(BITMAP_ScanList1));
if (attributes & MR_CH_SCANLIST2)
memmove(p_line0 + 120, BITMAP_ScanList2, sizeof(BITMAP_ScanList2));
#ifndef ENABLE_BIG_FREQ
if ((attributes & MR_CH_COMPAND) > 0)
memmove(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
#else
// TODO: // find somewhere else to put the symbol
#endif
// compander symbol
#ifndef ENABLE_BIG_FREQ
if ((attributes & MR_CH_COMPAND) > 0)
memmove(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
#else
// TODO: // find somewhere else to put the symbol
#endif
switch (gEeprom.CHANNEL_DISPLAY_MODE)
{
case MDF_FREQUENCY: // show the channel frequency
#ifdef ENABLE_BIG_FREQ
NUMBER_ToDigits(frequency, String);
// show the main large frequency digits
UI_DisplayFrequency(String, 32, line, false, false);
sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000);
#ifdef ENABLE_BIG_FREQ
if(frequency < 100000000) {
// show the remaining 2 small frequency digits
UI_DisplaySmallDigits(2, String + 6, 113, line + 1, true);
#else
UI_PrintStringSmall(String + 7, 113, 0, line + 1);
String[7] = 0;
// show the main large frequency digits
UI_DisplayFrequency(String, 32, line, false);
}
else
#endif
{
// show the frequency in the main font
sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000);
UI_PrintString(String, 32, 0, line, 8);
#endif
}
break;
case MDF_CHANNEL: // show the channel number
@@ -574,18 +524,15 @@ void UI_DisplayMain(void)
sprintf(String, "CH-%03u", gEeprom.ScreenChannel[vfo_num] + 1);
}
if (gEeprom.CHANNEL_DISPLAY_MODE == MDF_NAME)
{
if (gEeprom.CHANNEL_DISPLAY_MODE == MDF_NAME) {
UI_PrintString(String, 32, 0, line, 8);
}
else
{
#ifdef ENABLE_SMALL_BOLD
UI_PrintStringSmallBold(String, 32 + 4, 0, line);
#else
UI_PrintStringSmall(String, 32 + 4, 0, line);
#endif
else {
#ifdef ENABLE_SMALL_BOLD
UI_PrintStringSmallBold(String, 32 + 4, 0, line);
#else
UI_PrintStringSmall(String, 32 + 4, 0, line);
#endif
// show the channel frequency below the channel number/name
sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000);
UI_PrintStringSmall(String, 32 + 4, 0, line + 1);
@@ -596,26 +543,31 @@ void UI_DisplayMain(void)
}
else
{ // frequency mode
#ifdef ENABLE_BIG_FREQ
NUMBER_ToDigits(frequency, String); // 8 digits
// show the main large frequency digits
UI_DisplayFrequency(String, 32, line, false, false);
sprintf(String, "%3u.%05u", frequency / 100000, frequency % 100000);
#ifdef ENABLE_BIG_FREQ
if(frequency < 100000000) {
// show the remaining 2 small frequency digits
UI_DisplaySmallDigits(2, String + 6, 113, line + 1, true);
#else
UI_PrintStringSmall(String + 7, 113, 0, line + 1);
String[7] = 0;
// show the main large frequency digits
UI_DisplayFrequency(String, 32, line, false);
}
else
#endif
{
// show the frequency in the main font
sprintf(String, "%03u.%05u", frequency / 100000, frequency % 100000);
UI_PrintString(String, 32, 0, line, 8);
#endif
}
// show the channel symbols
const uint8_t attributes = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
if ((attributes & MR_CH_COMPAND) > 0)
#ifdef ENABLE_BIG_FREQ
memmove(p_line0 + 120, BITMAP_compand, sizeof(BITMAP_compand));
#else
memmove(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
#endif
#ifdef ENABLE_BIG_FREQ
memmove(p_line0 + 120, BITMAP_compand, sizeof(BITMAP_compand));
#else
memmove(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
#endif
}
}
@@ -658,7 +610,7 @@ void UI_DisplayMain(void)
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 >= 0 && code_type < ARRAY_SIZE(code_list))
if (code_type < ARRAY_SIZE(code_list))
strcpy(String, code_list[code_type]);
}
UI_PrintStringSmall(String, LCD_WIDTH + 24, 0, line + 1);
@@ -667,7 +619,7 @@ void UI_DisplayMain(void)
{ // show the TX power
const char pwr_list[] = "LMH";
const unsigned int i = gEeprom.VfoInfo[vfo_num].OUTPUT_POWER;
String[0] = (i >= 0 && i < ARRAY_SIZE(pwr_list)) ? pwr_list[i] : '\0';
String[0] = (i < ARRAY_SIZE(pwr_list)) ? pwr_list[i] : '\0';
String[1] = '\0';
UI_PrintStringSmall(String, LCD_WIDTH + 46, 0, line + 1);
}
@@ -711,38 +663,35 @@ void UI_DisplayMain(void)
gCurrentFunction == FUNCTION_MONITOR ||
gCurrentFunction == FUNCTION_INCOMING);
#ifdef ENABLE_AUDIO_BAR
if (gSetting_mic_bar && gCurrentFunction == FUNCTION_TRANSMIT)
{
center_line = CENTER_LINE_AUDIO_BAR;
UI_DisplayAudioBar();
}
else
#endif
#ifdef ENABLE_AUDIO_BAR
if (gSetting_mic_bar && gCurrentFunction == FUNCTION_TRANSMIT) {
center_line = CENTER_LINE_AUDIO_BAR;
UI_DisplayAudioBar();
}
else
#endif
#if defined(ENABLE_AM_FIX) && defined(ENABLE_AM_FIX_SHOW_DATA)
if (rx && gEeprom.VfoInfo[gEeprom.RX_CHANNEL].AM_mode && gSetting_AM_fix)
{
if (gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return;
#if defined(ENABLE_AM_FIX) && defined(ENABLE_AM_FIX_SHOW_DATA)
if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].AM_mode && gSetting_AM_fix)
{
if (gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return;
center_line = CENTER_LINE_AM_FIX_DATA;
AM_fix_print_data(gEeprom.RX_CHANNEL, String);
UI_PrintStringSmall(String, 2, 0, 3);
}
else
#endif
#ifdef ENABLE_RSSI_BAR
if (rx)
{
center_line = CENTER_LINE_RSSI;
UI_DisplayRSSIBar(gCurrentRSSI[gEeprom.RX_CHANNEL], false);
}
else
#endif
center_line = CENTER_LINE_AM_FIX_DATA;
AM_fix_print_data(gEeprom.RX_VFO, String);
UI_PrintStringSmall(String, 2, 0, 3);
}
else
#endif
#ifdef ENABLE_RSSI_BAR
if (rx) {
center_line = CENTER_LINE_RSSI;
UI_DisplayRSSIBar(gCurrentRSSI[gEeprom.RX_VFO], false);
}
else
#endif
if (rx || gCurrentFunction == FUNCTION_FOREGROUND || gCurrentFunction == FUNCTION_POWER_SAVE)
{
#if 1
@@ -779,22 +728,21 @@ void UI_DisplayMain(void)
}
#endif
#ifdef ENABLE_SHOW_CHARGE_LEVEL
else
if (gChargingWithTypeC)
{ // charging .. show the battery state
if (gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return;
#ifdef ENABLE_SHOW_CHARGE_LEVEL
else if (gChargingWithTypeC)
{ // charging .. show the battery state
if (gScreenToDisplay != DISPLAY_MAIN ||
gDTMF_CallState != DTMF_CALL_STATE_NONE)
return;
center_line = CENTER_LINE_CHARGE_DATA;
center_line = CENTER_LINE_CHARGE_DATA;
sprintf(String, "Charge %u.%02uV %u%%",
gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100,
BATTERY_VoltsToPercent(gBatteryVoltageAverage));
UI_PrintStringSmall(String, 2, 0, 3);
}
#endif
sprintf(String, "Charge %u.%02uV %u%%",
gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100,
BATTERY_VoltsToPercent(gBatteryVoltageAverage));
UI_PrintStringSmall(String, 2, 0, 3);
}
#endif
}
}

273
ui/menu.c
View File

@@ -36,106 +36,109 @@
#include "ui/menu.h"
#include "ui/ui.h"
// NOTE. this menu list is half way through a change, what might seem
// pointless at this time is for there for a reason.
//
const t_menu_item MenuList[] =
{
// text, voice ID, menu ID
{"SQL", VOICE_ID_SQUELCH, MENU_SQL },
{"STEP", VOICE_ID_FREQUENCY_STEP, MENU_STEP },
{"T PWR", VOICE_ID_POWER, MENU_TXP }, // was "TXP"
{"R DCS", VOICE_ID_DCS, MENU_R_DCS }, // was "R_DCS"
{"R CTCS", VOICE_ID_CTCSS, MENU_R_CTCS }, // was "R_CTCS"
{"T DCS", VOICE_ID_DCS, MENU_T_DCS }, // was "T_DCS"
{"T CTCS", VOICE_ID_CTCSS, MENU_T_CTCS }, // was "T_CTCS"
{"T DIR", VOICE_ID_TX_OFFSET_FREQUENCY_DIRECTION, MENU_SFT_D }, // was "SFT_D"
{"T OFFS", VOICE_ID_TX_OFFSET_FREQUENCY, MENU_OFFSET }, // was "OFFSET"
{"T VFO", VOICE_ID_INVALID, MENU_XB }, // was "WX"
{"T TOUT", VOICE_ID_TRANSMIT_OVER_TIME, MENU_TOT }, // was "TOT"
{"Step", VOICE_ID_FREQUENCY_STEP, MENU_STEP },
{"TxPwr", VOICE_ID_POWER, MENU_TXP }, // was "TXP"
{"RxDCS", VOICE_ID_DCS, MENU_R_DCS }, // was "R_DCS"
{"RxCTCS", VOICE_ID_CTCSS, MENU_R_CTCS }, // was "R_CTCS"
{"TxDCS", VOICE_ID_DCS, MENU_T_DCS }, // was "T_DCS"
{"TxCTCS", VOICE_ID_CTCSS, MENU_T_CTCS }, // was "T_CTCS"
{"TxODir", VOICE_ID_TX_OFFSET_FREQUENCY_DIRECTION, MENU_SFT_D }, // was "SFT_D"
{"TxOffs", VOICE_ID_TX_OFFSET_FREQUENCY, MENU_OFFSET }, // was "OFFSET"
{"W/N", VOICE_ID_CHANNEL_BANDWIDTH, MENU_W_N },
{"SCRAM", VOICE_ID_SCRAMBLER_ON, MENU_SCR }, // was "SCR"
{"BUSYCL", VOICE_ID_BUSY_LOCKOUT, MENU_BCL }, // was "BCL"
{"CH SAV", VOICE_ID_MEMORY_CHANNEL, MENU_MEM_CH }, // was "MEM-CH"
{"CH DEL", VOICE_ID_DELETE_CHANNEL, MENU_DEL_CH }, // was "DEL-CH"
{"CH NAM", VOICE_ID_INVALID, MENU_MEM_NAME },
{"CH DIS", VOICE_ID_INVALID, MENU_MDF }, // was "MDF"
{"BATSAV", VOICE_ID_SAVE_MODE, MENU_SAVE }, // was "SAVE"
#ifdef ENABLE_VOX
{"VOX", VOICE_ID_VOX, MENU_VOX },
{"Scramb", VOICE_ID_SCRAMBLER_ON, MENU_SCR }, // was "SCR"
{"BusyCL", VOICE_ID_BUSY_LOCKOUT, MENU_BCL }, // was "BCL"
{"Compnd", VOICE_ID_INVALID, MENU_COMPAND },
{"Demodu", VOICE_ID_INVALID, MENU_AM }, // was "AM"
{"ScAdd1", VOICE_ID_INVALID, MENU_S_ADD1 },
{"ScAdd2", VOICE_ID_INVALID, MENU_S_ADD2 },
{"ChSave", VOICE_ID_MEMORY_CHANNEL, MENU_MEM_CH }, // was "MEM-CH"
{"ChDele", VOICE_ID_DELETE_CHANNEL, MENU_DEL_CH }, // was "DEL-CH"
{"ChName", VOICE_ID_INVALID, MENU_MEM_NAME },
{"SList", VOICE_ID_INVALID, MENU_S_LIST },
{"SList1", VOICE_ID_INVALID, MENU_SLIST1 },
{"SList2", VOICE_ID_INVALID, MENU_SLIST2 },
{"ScnRev", VOICE_ID_INVALID, MENU_SC_REV },
#ifdef ENABLE_NOAA
{"NOAA-S", VOICE_ID_INVALID, MENU_NOAA_S },
#endif
{"BLT", VOICE_ID_INVALID, MENU_ABR }, // was "ABR"
{"BLTTRX", VOICE_ID_INVALID, MENU_ABR_ON_TX_RX },
{"DUALRX", VOICE_ID_DUAL_STANDBY, MENU_TDR }, // was "TDR"
{"BEEP", VOICE_ID_BEEP_PROMPT, MENU_BEEP },
{"F1Shrt", VOICE_ID_INVALID, MENU_F1SHRT },
{"F1Long", VOICE_ID_INVALID, MENU_F1LONG },
{"F2Shrt", VOICE_ID_INVALID, MENU_F2SHRT },
{"F2Long", VOICE_ID_INVALID, MENU_F2LONG },
{"M Long", VOICE_ID_INVALID, MENU_MLONG },
{"KeyLck", VOICE_ID_INVALID, MENU_AUTOLK }, // was "AUTOLk"
{"TxTOut", VOICE_ID_TRANSMIT_OVER_TIME, MENU_TOT }, // was "TOT"
{"BatSav", VOICE_ID_SAVE_MODE, MENU_SAVE }, // was "SAVE"
{"Mic", VOICE_ID_INVALID, MENU_MIC },
#ifdef ENABLE_AUDIO_BAR
{"MicBar", VOICE_ID_INVALID, MENU_MIC_BAR },
#endif
{"ChDisp", VOICE_ID_INVALID, MENU_MDF }, // was "MDF"
{"POnMsg", VOICE_ID_INVALID, MENU_PONMSG },
{"BatTxt", VOICE_ID_INVALID, MENU_BAT_TXT },
{"BackLt", VOICE_ID_INVALID, MENU_ABR }, // was "ABR"
{"BltTRX", VOICE_ID_INVALID, MENU_ABR_ON_TX_RX },
{"Beep", VOICE_ID_BEEP_PROMPT, MENU_BEEP },
#ifdef ENABLE_VOICE
{"VOICE", VOICE_ID_VOICE_PROMPT, MENU_VOICE },
{"Voice", VOICE_ID_VOICE_PROMPT, MENU_VOICE },
#endif
{"SC REV", VOICE_ID_INVALID, MENU_SC_REV },
{"KEYLOC", VOICE_ID_INVALID, MENU_AUTOLK }, // was "AUTOLk"
{"S ADD1", VOICE_ID_INVALID, MENU_S_ADD1 },
{"S ADD2", VOICE_ID_INVALID, MENU_S_ADD2 },
{"Roger", VOICE_ID_INVALID, MENU_ROGER },
{"STE", VOICE_ID_INVALID, MENU_STE },
{"RP STE", VOICE_ID_INVALID, MENU_RP_STE },
{"MIC", VOICE_ID_INVALID, MENU_MIC },
#ifdef ENABLE_AUDIO_BAR
{"MICBAR", VOICE_ID_INVALID, MENU_MIC_BAR },
#endif
{"COMPND", VOICE_ID_INVALID, MENU_COMPAND },
{"1 CALL", VOICE_ID_INVALID, MENU_1_CALL },
{"SLIST", VOICE_ID_INVALID, MENU_S_LIST },
{"SLIST1", VOICE_ID_INVALID, MENU_SLIST1 },
{"SLIST2", VOICE_ID_INVALID, MENU_SLIST2 },
{"1 Call", VOICE_ID_INVALID, MENU_1_CALL },
#ifdef ENABLE_ALARM
{"AL-MOD", VOICE_ID_INVALID, MENU_AL_MOD },
{"AlarmT", VOICE_ID_INVALID, MENU_AL_MOD },
#endif
{"ANI ID", VOICE_ID_ANI_CODE, MENU_ANI_ID },
{"UPCODE", VOICE_ID_INVALID, MENU_UPCODE },
{"DWCODE", VOICE_ID_INVALID, MENU_DWCODE },
{"UPCode", VOICE_ID_INVALID, MENU_UPCODE },
{"DWCode", VOICE_ID_INVALID, MENU_DWCODE },
{"PTT ID", VOICE_ID_INVALID, MENU_PTT_ID },
{"D ST", VOICE_ID_INVALID, MENU_D_ST },
{"D RSP", VOICE_ID_INVALID, MENU_D_RSP },
{"D HOLD", VOICE_ID_INVALID, MENU_D_HOLD },
{"D PRE", VOICE_ID_INVALID, MENU_D_PRE },
{"D DCD", VOICE_ID_INVALID, MENU_D_DCD },
{"D LIST", VOICE_ID_INVALID, MENU_D_LIST },
{"D LIVE", VOICE_ID_INVALID, MENU_D_LIVE_DEC }, // live DTMF decoder
{"PONMSG", VOICE_ID_INVALID, MENU_PONMSG },
{"ROGER", VOICE_ID_INVALID, MENU_ROGER },
{"BATVOL", VOICE_ID_INVALID, MENU_VOL }, // was "VOL"
{"BATTXT", VOICE_ID_INVALID, MENU_BAT_TXT },
{"MODE", VOICE_ID_INVALID, MENU_AM }, // was "AM"
{"D Resp", VOICE_ID_INVALID, MENU_D_RSP },
{"D Hold", VOICE_ID_INVALID, MENU_D_HOLD },
{"D Prel", VOICE_ID_INVALID, MENU_D_PRE },
{"D Decd", VOICE_ID_INVALID, MENU_D_DCD },
{"D List", VOICE_ID_INVALID, MENU_D_LIST },
{"D Live", VOICE_ID_INVALID, MENU_D_LIVE_DEC }, // live DTMF decoder
#ifdef ENABLE_AM_FIX
{"AM FIX", VOICE_ID_INVALID, MENU_AM_FIX },
{"AM Fix", VOICE_ID_INVALID, MENU_AM_FIX },
#endif
#ifdef ENABLE_AM_FIX_TEST1
{"AM FT1", VOICE_ID_INVALID, MENU_AM_FIX_TEST1 },
#endif
#ifdef ENABLE_NOAA
{"NOAA-S", VOICE_ID_INVALID, MENU_NOAA_S },
#ifdef ENABLE_VOX
{"VOX", VOICE_ID_VOX, MENU_VOX },
#endif
{"RESET", VOICE_ID_INITIALISATION, MENU_RESET }, // might be better to move this to the hidden menu items ?
{"BatVol", VOICE_ID_INVALID, MENU_VOL }, // was "VOL"
{"RxMode", VOICE_ID_DUAL_STANDBY, MENU_TDR },
{"Sql", VOICE_ID_SQUELCH, MENU_SQL },
// hidden menu items from here on
// enabled if pressing both the PTT and upper side button at power-on
{"F LOCK", VOICE_ID_INVALID, MENU_F_LOCK },
{"TX 200", VOICE_ID_INVALID, MENU_200TX }, // was "200TX"
{"TX 350", VOICE_ID_INVALID, MENU_350TX }, // was "350TX"
{"TX 500", VOICE_ID_INVALID, MENU_500TX }, // was "500TX"
{"350 EN", VOICE_ID_INVALID, MENU_350EN }, // was "350EN"
{"SCR EN", VOICE_ID_INVALID, MENU_SCREN }, // was "SCREN"
{"TX EN", VOICE_ID_INVALID, MENU_TX_EN }, // enable TX
{"F Lock", VOICE_ID_INVALID, MENU_F_LOCK },
{"Tx 200", VOICE_ID_INVALID, MENU_200TX }, // was "200TX"
{"Tx 350", VOICE_ID_INVALID, MENU_350TX }, // was "350TX"
{"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
{"F CALI", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration
{"FrCali", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration
#endif
{"BATCAL", VOICE_ID_INVALID, MENU_BATCAL }, // battery voltage calibration
{"BatCal", VOICE_ID_INVALID, MENU_BATCAL }, // battery voltage calibration
{"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
};
const uint8_t FIRST_HIDDEN_MENU_ITEM = MENU_F_LOCK;
const char gSubMenu_TXP[3][5] =
{
"LOW",
@@ -186,18 +189,12 @@ const char gSubMenu_TOT[11][7] =
"15 min"
};
const char gSubMenu_CHAN[3][10] =
const char* gSubMenu_RXMode[4] =
{
"OFF",
"UPPER\nVFO",
"LOWER\nVFO"
};
const char gSubMenu_XB[3][10] =
{
"MAIN\nVFO",
"UPPER\nVFO",
"LOWER\nVFO"
"MAIN\nONLY", // TX and RX on main only
"DUAL RX\nRESPOND", // Watch both and respond
"CROSS\nBAND", // TX on main, RX on secondary
"MAIN TX\nDUAL RX" // always TX on main, but RX on both
};
#ifdef ENABLE_VOICE
@@ -209,14 +206,14 @@ const char gSubMenu_XB[3][10] =
};
#endif
const char gSubMenu_SC_REV[3][13] =
const char gSubMenu_SC_REV[3][8] =
{
"TIME",
"TIMEOUT",
"CARRIER",
"SEARCH"
"STOP"
};
const char gSubMenu_MDF[4][15] =
const char* gSubMenu_MDF[4] =
{
"FREQ",
"CHANNEL\nNUMBER",
@@ -240,12 +237,13 @@ const char gSubMenu_D_RSP[4][11] =
"BOTH"
};
const char gSubMenu_PTT_ID[4][7] =
const char* gSubMenu_PTT_ID[5] =
{
"OFF",
"KEY UP",
"KEY DN",
"BOTH"
"KEY\nUP",
"KEY\nDOWN",
"KEY\nUP+DOWN",
"APOLLO\nQUINDAR"
};
const char gSubMenu_PONMSG[4][8] =
@@ -256,7 +254,7 @@ const char gSubMenu_PONMSG[4][8] =
"NONE"
};
const char gSubMenu_ROGER[3][9] =
const char* gSubMenu_ROGER[3] =
{
"OFF",
"ROGER",
@@ -331,8 +329,40 @@ const char gSubMenu_SCRAMBLER[11][7] =
"3500Hz"
};
const t_sidefunction SIDEFUNCTIONS[] =
{
{"NONE", ACTION_OPT_NONE},
{"FLASH\nLIGHT", ACTION_OPT_FLASHLIGHT},
{"POWER", ACTION_OPT_POWER},
{"MONITOR", ACTION_OPT_MONITOR},
{"SCAN", ACTION_OPT_SCAN},
#ifdef ENABLE_VOX
{"VOX", ACTION_OPT_VOX},
#endif
#ifdef ENABLE_ALARM
{"ALARM", ACTION_OPT_ALARM},
#endif
#ifdef ENABLE_FMRADIO
{"FM RADIO", ACTION_OPT_FM},
#endif
#ifdef ENABLE_TX1750
{"1750HZ", ACTION_OPT_1750},
#endif
{"LOCK\nKEYPAD", ACTION_OPT_KEYLOCK},
{"SWITCH\nVFO", ACTION_OPT_A_B},
};
const t_sidefunction* gSubMenu_SIDEFUNCTIONS = SIDEFUNCTIONS;
const uint8_t gSubMenu_SIDEFUNCTIONS_size = ARRAY_SIZE(SIDEFUNCTIONS);
bool gIsInSubMenu;
uint8_t gMenuCursor;
int GetCurrentMenuId() {
if(gMenuCursor < ARRAY_SIZE(MenuList))
return MenuList[gMenuCursor].menu_id;
else
return MenuList[ARRAY_SIZE(MenuList)-1].menu_id;
}
int8_t gMenuScrollDirection;
int32_t gSubMenuSelection;
@@ -436,7 +466,7 @@ void UI_DisplayMenu(void)
bool already_printed = false;
switch (gMenuCursor)
switch (GetCurrentMenuId())
{
case MENU_SQL:
sprintf(String, "%d", gSubMenuSelection);
@@ -479,7 +509,7 @@ void UI_DisplayMenu(void)
{
#if 1
unsigned int Code;
FREQ_Config_t *pConfig = (gMenuCursor == MENU_R_CTCS) ? &gTxVfo->freq_config_RX : &gTxVfo->freq_config_TX;
FREQ_Config_t *pConfig = (GetCurrentMenuId() == MENU_R_CTCS) ? &gTxVfo->freq_config_RX : &gTxVfo->freq_config_TX;
if (gSubMenuSelection == 0)
{
strcpy(String, "OFF");
@@ -676,11 +706,7 @@ void UI_DisplayMenu(void)
break;
case MENU_TDR:
strcpy(String, gSubMenu_CHAN[gSubMenuSelection]);
break;
case MENU_XB:
strcpy(String, gSubMenu_XB[gSubMenuSelection]);
strcpy(String, gSubMenu_RXMode[gSubMenuSelection]);
break;
case MENU_TOT:
@@ -804,6 +830,15 @@ void UI_DisplayMenu(void)
sprintf(String, "%u.%02uV\n%u", vol / 100, vol % 100, gSubMenuSelection);
break;
}
case MENU_F1SHRT:
case MENU_F1LONG:
case MENU_F2SHRT:
case MENU_F2LONG:
case MENU_MLONG:
strcpy(String, gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].name);
break;
}
if (!already_printed)
@@ -860,9 +895,9 @@ void UI_DisplayMenu(void)
}
}
if (gMenuCursor == MENU_SLIST1 || gMenuCursor == MENU_SLIST2)
if (GetCurrentMenuId() == MENU_SLIST1 || GetCurrentMenuId() == MENU_SLIST2)
{
i = (gMenuCursor == MENU_SLIST1) ? 0 : 1;
i = (GetCurrentMenuId() == MENU_SLIST1) ? 0 : 1;
// if (gSubMenuSelection == 0xFF)
if (gSubMenuSelection < 0)
@@ -907,9 +942,9 @@ void UI_DisplayMenu(void)
}
}
if (gMenuCursor == MENU_MEM_CH ||
gMenuCursor == MENU_DEL_CH ||
gMenuCursor == MENU_1_CALL)
if (GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_DEL_CH ||
GetCurrentMenuId() == MENU_1_CALL)
{ // display the channel name
char s[11];
BOARD_fetchChannelName(s, gSubMenuSelection);
@@ -918,18 +953,18 @@ void UI_DisplayMenu(void)
UI_PrintString(s, menu_item_x1, menu_item_x2, 2, 8);
}
if ((gMenuCursor == MENU_R_CTCS || gMenuCursor == MENU_R_DCS) && gCssScanMode != CSS_SCAN_MODE_OFF)
if ((GetCurrentMenuId() == MENU_R_CTCS || GetCurrentMenuId() == MENU_R_DCS) && gCssScanMode != CSS_SCAN_MODE_OFF)
UI_PrintString("SCAN", menu_item_x1, menu_item_x2, 4, 8);
if (gMenuCursor == MENU_UPCODE)
if (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 (gMenuCursor == MENU_DWCODE)
if (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 (gMenuCursor == MENU_D_LIST && gIsDtmfContactValid)
if (GetCurrentMenuId() == MENU_D_LIST && gIsDtmfContactValid)
{
Contact[11] = 0;
memmove(&gDTMF_ID, Contact + 8, 4);
@@ -937,22 +972,20 @@ void UI_DisplayMenu(void)
UI_PrintString(String, menu_item_x1, menu_item_x2, 4, 8);
}
if (gMenuCursor == MENU_R_CTCS ||
gMenuCursor == MENU_T_CTCS ||
gMenuCursor == MENU_R_DCS ||
gMenuCursor == MENU_T_DCS ||
gMenuCursor == MENU_D_LIST)
if (GetCurrentMenuId() == MENU_R_CTCS ||
GetCurrentMenuId() == MENU_T_CTCS ||
GetCurrentMenuId() == MENU_R_DCS ||
GetCurrentMenuId() == MENU_T_DCS ||
GetCurrentMenuId() == MENU_D_LIST)
{
unsigned int Offset;
NUMBER_ToDigits(gSubMenuSelection, String);
Offset = (gMenuCursor == MENU_D_LIST) ? 2 : 3;
UI_DisplaySmallDigits(Offset, String + (8 - Offset), 105, 0, false);
sprintf(String, "%2d", gSubMenuSelection);
UI_PrintStringSmall(String, 105, 0, 0);
}
if ((gMenuCursor == MENU_RESET ||
gMenuCursor == MENU_MEM_CH ||
gMenuCursor == MENU_MEM_NAME ||
gMenuCursor == MENU_DEL_CH) && gAskForConfirmation)
if ((GetCurrentMenuId() == MENU_RESET ||
GetCurrentMenuId() == MENU_MEM_CH ||
GetCurrentMenuId() == MENU_MEM_NAME ||
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

@@ -39,7 +39,6 @@ enum
MENU_T_CTCS,
MENU_SFT_D,
MENU_OFFSET,
MENU_XB,
MENU_TOT,
MENU_W_N,
MENU_SCR,
@@ -103,9 +102,6 @@ enum
MENU_NOAA_S,
#endif
MENU_RESET,
// items after here are normally hidden
MENU_F_LOCK,
MENU_200TX,
MENU_350TX,
@@ -117,9 +113,15 @@ enum
#ifdef ENABLE_F_CAL_MENU
MENU_F_CALI, // reference xtal calibration
#endif
MENU_BATCAL // battery voltage calibration
MENU_BATCAL, // battery voltage calibration
MENU_F1SHRT,
MENU_F1LONG,
MENU_F2SHRT,
MENU_F2LONG,
MENU_MLONG
};
extern const uint8_t FIRST_HIDDEN_MENU_ITEM;
extern const t_menu_item MenuList[];
extern const char gSubMenu_TXP[3][5];
@@ -128,20 +130,20 @@ extern const char gSubMenu_W_N[2][7];
extern const char gSubMenu_OFF_ON[2][4];
extern const char gSubMenu_SAVE[5][4];
extern const char gSubMenu_TOT[11][7];
extern const char gSubMenu_CHAN[3][10];
extern const char gSubMenu_XB[3][10];
extern const char* gSubMenu_RXMode[4];
#ifdef ENABLE_VOICE
extern const char gSubMenu_VOICE[3][4];
#endif
extern const char gSubMenu_SC_REV[3][13];
extern const char gSubMenu_MDF[4][15];
extern const char gSubMenu_SC_REV[3][8];
extern const char* gSubMenu_MDF[4];
#ifdef ENABLE_ALARM
extern const char gSubMenu_AL_MOD[2][5];
#endif
extern const char gSubMenu_D_RSP[4][11];
extern const char gSubMenu_PTT_ID[4][7];
extern const char* gSubMenu_PTT_ID[5];
extern const char gSubMenu_PONMSG[4][8];
extern const char gSubMenu_ROGER[3][9];
extern const char* gSubMenu_ROGER[3];
extern const char gSubMenu_RESET[2][4];
extern const char gSubMenu_F_LOCK[6][4];
extern const char gSubMenu_BACKLIGHT[8][7];
@@ -153,9 +155,14 @@ extern const char gSubMenu_BAT_TXT[3][8];
extern const char gSubMenu_SCRAMBLER[11][7];
typedef struct {char* name; uint8_t id;} t_sidefunction;
extern const uint8_t gSubMenu_SIDEFUNCTIONS_size;
extern const t_sidefunction* gSubMenu_SIDEFUNCTIONS;
extern bool gIsInSubMenu;
extern uint8_t gMenuCursor;
int GetCurrentMenuId();
extern int8_t gMenuScrollDirection;
extern int32_t gSubMenuSelection;

View File

@@ -28,6 +28,7 @@
#include "helper/battery.h"
#include "misc.h"
#include "settings.h"
#include "ui/battery.h"
#include "ui/helper.h"
#include "ui/ui.h"
#include "ui/status.h"
@@ -84,33 +85,26 @@ void UI_DisplayStatus(const bool test_display)
x1 = x + 10;
}
else
#ifdef ENABLE_FMRADIO
// FM indicator
if (gFmRadioMode || test_display)
{
memmove(line + x, BITMAP_FM, sizeof(BITMAP_FM));
x1 = x + sizeof(BITMAP_FM);
}
else
#endif
// SCAN indicator
if (gScanState != SCAN_OFF || gScreenToDisplay == DISPLAY_SCANNER || test_display)
if (gScanStateDir != SCAN_OFF || gScreenToDisplay == DISPLAY_SCANNER || test_display)
{
if (gEeprom.SCAN_LIST_DEFAULT == 0)
// memmove(line + x, BITMAP_SC1, sizeof(BITMAP_SC1));
UI_PrintStringSmallBuffer("1", line + x);
if (gNextMrChannel <= MR_CHANNEL_LAST && gScreenToDisplay != DISPLAY_SCANNER)
{ // channel mode
if (gEeprom.SCAN_LIST_DEFAULT == 0)
UI_PrintStringSmallBuffer("1", line + x);
else
if (gEeprom.SCAN_LIST_DEFAULT == 1)
UI_PrintStringSmallBuffer("2", line + x);
else
if (gEeprom.SCAN_LIST_DEFAULT == 2)
UI_PrintStringSmallBuffer("*", line + x);
}
else
if (gEeprom.SCAN_LIST_DEFAULT == 1)
// memmove(line + x, BITMAP_SC2, sizeof(BITMAP_SC2));
UI_PrintStringSmallBuffer("2", line + x);
else
if (gEeprom.SCAN_LIST_DEFAULT == 2)
// memmove(line + x, BITMAP_SCA, sizeof(BITMAP_SCA));
UI_PrintStringSmallBuffer("*", line + x);
// x1 = x + sizeof(BITMAP_SC1);
{ // frequency mode
UI_PrintStringSmallBuffer("S", line + x);
}
x1 = x + 7;
}
// x += sizeof(BITMAP_SC1);
x += 7; // font character width
#ifdef ENABLE_VOICE
@@ -120,28 +114,25 @@ void UI_DisplayStatus(const bool test_display)
memmove(line + x, BITMAP_VoicePrompt, sizeof(BITMAP_VoicePrompt));
x1 = x + sizeof(BITMAP_VoicePrompt);
}
x += sizeof(BITMAP_VoicePrompt);
x += sizeof(BITMAP_VoicePrompt) + 1;
#else
// hmmm, what to put in it's place
#endif
// DUAL-WATCH indicator
if (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF || test_display)
{
if (gDualWatchActive || test_display)
memmove(line + x, BITMAP_TDR1, sizeof(BITMAP_TDR1));
else
memmove(line + x, BITMAP_TDR2, sizeof(BITMAP_TDR2));
x++;
if(gScreenToDisplay != DISPLAY_SCANNER) {
uint8_t dw = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2;
if(dw == 1 || dw == 3 || test_display) { // DWR - dual watch + respond
if(gDualWatchActive || test_display)
memmove(line + x, BITMAP_TDR1, sizeof(BITMAP_TDR1) - (dw==1?0:5));
else
memmove(line + x + 3, BITMAP_TDR2, sizeof(BITMAP_TDR2));
}
else if(dw == 2) { // XB - crossband
memmove(line + x, BITMAP_XB, sizeof(BITMAP_XB));
}
}
x += sizeof(BITMAP_TDR1);
// CROSS-VFO indicator
if (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF || test_display)
{
memmove(line + x, BITMAP_XB, sizeof(BITMAP_XB));
x1 = x + sizeof(BITMAP_XB);
}
x += sizeof(BITMAP_XB);
x += sizeof(BITMAP_TDR1) + 2;
#ifdef ENABLE_VOX
// VOX indicator
@@ -150,9 +141,12 @@ void UI_DisplayStatus(const bool test_display)
memmove(line + x, BITMAP_VOX, sizeof(BITMAP_VOX));
x1 = x + sizeof(BITMAP_VOX);
}
x += sizeof(BITMAP_VOX);
x += sizeof(BITMAP_VOX) + 2;
#endif
x = MAX(x, 61u);
x1 = x;
// KEY-LOCK indicator
if (gEeprom.KEY_LOCK || test_display)
{
@@ -215,49 +209,7 @@ void UI_DisplayStatus(const bool test_display)
x += sizeof(BITMAP_USB_C);
// BATTERY LEVEL indicator
if (gBatteryDisplayLevel >= 2 && !gLowBattery)
{
line += x;
memmove(line, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1));
#ifndef ENABLE_REVERSE_BAT_SYMBOL
line += sizeof(BITMAP_BatteryLevel1);
{
const int8_t pos[] = {-4, -7, -10, 13};
for (unsigned int i = 0; i < ARRAY_SIZE(pos); i++)
if (gBatteryDisplayLevel >= (2 + i))
memmove(line + pos[i], BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
/* switch (gBatteryDisplayLevel)
{
default:
case 5: memmove(line - 13, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
case 4: memmove(line - 10, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
case 3: memmove(line - 7, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
case 2: memmove(line - 4, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
}
*/ }
#else
{
const int8_t pos[] = {3, 6, 9, 12};
for (unsigned int i = 0; i < ARRAY_SIZE(pos); i++)
if (gBatteryDisplayLevel >= (2 + i))
memmove(line + pos[i], BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
/*
switch (gBatteryDisplayLevel)
{
default:
case 5: memmove(line + 12, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
case 4: memmove(line + 9, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
case 3: memmove(line + 6, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
case 2: memmove(line + 3, BITMAP_BatteryLevel, sizeof(BITMAP_BatteryLevel));
}
*/ }
#endif
}
else
if (gLowBatteryBlink == 1)
memmove(line + x, BITMAP_BatteryLevel1, sizeof(BITMAP_BatteryLevel1));
UI_DrawBattery(line + x, gBatteryDisplayLevel, gLowBatteryBlink);
// **************

45
ui/ui.c
View File

@@ -77,33 +77,28 @@ void GUI_DisplayScreen(void)
void GUI_SelectNextDisplay(GUI_DisplayType_t Display)
{
if (Display != DISPLAY_INVALID)
if (Display == DISPLAY_INVALID)
return;
if (gScreenToDisplay != Display)
{
if (gScreenToDisplay != Display)
{
gInputBoxIndex = 0;
gIsInSubMenu = false;
gCssScanMode = CSS_SCAN_MODE_OFF;
gScanState = SCAN_OFF;
#ifdef ENABLE_FMRADIO
gFM_ScanState = FM_SCAN_OFF;
#endif
gAskForConfirmation = 0;
gDTMF_InputMode = false;
gDTMF_InputIndex = 0;
gAskToSave = false;
gAskToDelete = false;
DTMF_clear_input_box();
if (gWasFKeyPressed)
{
gWasFKeyPressed = false;
gUpdateStatus = true;
}
gInputBoxIndex = 0;
gIsInSubMenu = false;
gCssScanMode = CSS_SCAN_MODE_OFF;
gScanStateDir = SCAN_OFF;
#ifdef ENABLE_FMRADIO
gFM_ScanState = FM_SCAN_OFF;
#endif
gAskForConfirmation = 0;
gAskToSave = false;
gAskToDelete = false;
gWasFKeyPressed = false;
gUpdateStatus = true;
}
gUpdateDisplay = true;
gScreenToDisplay = Display;
gUpdateStatus = true;
}
gScreenToDisplay = Display;
gUpdateDisplay = true;
}

Binary file not shown.

Binary file not shown.