Merge pull request #367 from armel/feature_update_v4

Feature update v4
This commit is contained in:
Armel FAUVEAU
2025-02-22 02:48:10 +01:00
committed by GitHub
47 changed files with 895 additions and 240 deletions

View File

@@ -1,49 +1,24 @@
name: Build Firmware
on: on:
push: push:
branches: [ main ]
jobs: jobs:
build: build:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
container:
image: archlinux:latest
steps: steps:
- name: base-devel - name: Checkout code
run: pacman -Syyu base-devel --noconfirm uses: actions/checkout@v3
- name: arm-none-eabi-gcc
run: pacman -Syyu arm-none-eabi-gcc --noconfirm
- name: arm-none-eabi-newlib
run: pacman -Syyu arm-none-eabi-newlib --noconfirm
- name: git
run: pacman -Syyu git --noconfirm
- name: python-pip
run: pacman -Syyu python-pip --noconfirm
- name: python-crcmod
run: pacman -Syyu python-crcmod --noconfirm
- name: Checkout - name: Compile firmware
uses: actions/checkout@v3 run: |
chmod +x compile-with-docker.sh
- name: safe.directory ./compile-with-docker.sh
run: git config --global --add safe.directory /__w/uv-k5-firmware-custom/uv-k5-firmware-custom
- name: Make
run: make
- name: size
run: arm-none-eabi-size firmware
- name: 'Upload Artifact' - name: Upload firmware artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: firmware name: firmware-artifact
path: firmware*.bin path: compiled-firmware/f4hwn.packed.bin
- name: Upload binaries to release
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: firmware.packed.bin
asset_name: egzumer_$tag.packed.bin
tag: ${{ github.ref }}
overwrite: true
release_name: release ${{ github.ref_name }}

View File

@@ -3,7 +3,7 @@
# 0 = disable # 0 = disable
# 1 = enable # 1 = enable
# ---- STOCK QUANSHENG FERATURES ---- # ---- STOCK QUANSHENG FEATURES ----
ENABLE_FMRADIO ?= 0 ENABLE_FMRADIO ?= 0
ENABLE_UART ?= 1 ENABLE_UART ?= 1
ENABLE_AIRCOPY ?= 0 ENABLE_AIRCOPY ?= 0
@@ -46,15 +46,18 @@ ENABLE_FEAT_F4HWN_SPECTRUM ?= 1
ENABLE_FEAT_F4HWN_RX_TX_TIMER ?= 1 ENABLE_FEAT_F4HWN_RX_TX_TIMER ?= 1
ENABLE_FEAT_F4HWN_CHARGING_C ?= 0 ENABLE_FEAT_F4HWN_CHARGING_C ?= 0
ENABLE_FEAT_F4HWN_SLEEP ?= 1 ENABLE_FEAT_F4HWN_SLEEP ?= 1
ENABLE_FEAT_F4HWN_RESTORE_SCAN ?= 1 ENABLE_FEAT_F4HWN_RESUME_STATE ?= 1
ENABLE_FEAT_F4HWN_NARROWER ?= 1 ENABLE_FEAT_F4HWN_NARROWER ?= 1
ENABLE_FEAT_F4HWN_CONTRAST ?= 1 ENABLE_FEAT_F4HWN_INV ?= 1
ENABLE_FEAT_F4HWN_CTR ?= 1
ENABLE_FEAT_F4HWN_RESCUE_OPS ?= 0 ENABLE_FEAT_F4HWN_RESCUE_OPS ?= 0
ENABLE_FEAT_F4HWN_VOL ?= 0 ENABLE_FEAT_F4HWN_VOL ?= 0
ENABLE_FEAT_F4HWN_RESET_CHANNEL ?= 0 ENABLE_FEAT_F4HWN_RESET_CHANNEL ?= 0
ENABLE_FEAT_F4HWN_PMR ?= 0 ENABLE_FEAT_F4HWN_PMR ?= 0
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS ?= 0 ENABLE_FEAT_F4HWN_GMRS_FRS_MURS ?= 0
ENABLE_FEAT_F4HWN_CA ?= 1 ENABLE_FEAT_F4HWN_CA ?= 1
ENABLE_FEAT_F4HWN_DEBUG ?= 0
ENABLE_REGA ?= 0
# ---- DEBUGGING ---- # ---- DEBUGGING ----
ENABLE_AM_FIX_SHOW_DATA ?= 0 ENABLE_AM_FIX_SHOW_DATA ?= 0
@@ -135,6 +138,9 @@ OBJS += app/app.o
OBJS += app/chFrScanner.o OBJS += app/chFrScanner.o
OBJS += app/common.o OBJS += app/common.o
OBJS += app/dtmf.o OBJS += app/dtmf.o
ifeq ($(ENABLE_REGA),1)
OBJS += app/rega.o
endif
ifeq ($(ENABLE_FLASHLIGHT),1) ifeq ($(ENABLE_FLASHLIGHT),1)
OBJS += app/flashlight.o OBJS += app/flashlight.o
endif endif
@@ -224,7 +230,7 @@ ifeq ($(ENABLE_FEAT_F4HWN),1)
VERSION_STRING_1 ?= v0.22 VERSION_STRING_1 ?= v0.22
AUTHOR_STRING_2 ?= F4HWN AUTHOR_STRING_2 ?= F4HWN
VERSION_STRING_2 ?= v3.9 VERSION_STRING_2 ?= v4.0
EDITION_STRING ?= Custom EDITION_STRING ?= Custom
@@ -399,6 +405,9 @@ endif
ifeq ($(ENABLE_DTMF_CALLING),1) ifeq ($(ENABLE_DTMF_CALLING),1)
CFLAGS += -DENABLE_DTMF_CALLING CFLAGS += -DENABLE_DTMF_CALLING
endif endif
ifeq ($(ENABLE_REGA),1)
CFLAGS += -DENABLE_REGA
endif
ifeq ($(ENABLE_AGC_SHOW_DATA),1) ifeq ($(ENABLE_AGC_SHOW_DATA),1)
CFLAGS += -DENABLE_AGC_SHOW_DATA CFLAGS += -DENABLE_AGC_SHOW_DATA
endif endif
@@ -436,14 +445,17 @@ endif
ifeq ($(ENABLE_FEAT_F4HWN_SLEEP),1) ifeq ($(ENABLE_FEAT_F4HWN_SLEEP),1)
CFLAGS += -DENABLE_FEAT_F4HWN_SLEEP CFLAGS += -DENABLE_FEAT_F4HWN_SLEEP
endif endif
ifeq ($(ENABLE_FEAT_F4HWN_RESTORE_SCAN),1) ifeq ($(ENABLE_FEAT_F4HWN_RESUME_STATE),1)
CFLAGS += -DENABLE_FEAT_F4HWN_RESTORE_SCAN CFLAGS += -DENABLE_FEAT_F4HWN_RESUME_STATE
endif endif
ifeq ($(ENABLE_FEAT_F4HWN_NARROWER),1) ifeq ($(ENABLE_FEAT_F4HWN_NARROWER),1)
CFLAGS += -DENABLE_FEAT_F4HWN_NARROWER CFLAGS += -DENABLE_FEAT_F4HWN_NARROWER
endif endif
ifeq ($(ENABLE_FEAT_F4HWN_CONTRAST),1) ifeq ($(ENABLE_FEAT_F4HWN_INV),1)
CFLAGS += -DENABLE_FEAT_F4HWN_CONTRAST CFLAGS += -DENABLE_FEAT_F4HWN_INV
endif
ifeq ($(ENABLE_FEAT_F4HWN_CTR),1)
CFLAGS += -DENABLE_FEAT_F4HWN_CTR
endif endif
ifneq ($(filter $(ENABLE_FEAT_F4HWN_RESCUE_OPS),1 2),) ifneq ($(filter $(ENABLE_FEAT_F4HWN_RESCUE_OPS),1 2),)
CFLAGS += -DENABLE_FEAT_F4HWN_RESCUE_OPS=$(ENABLE_FEAT_F4HWN_RESCUE_OPS) CFLAGS += -DENABLE_FEAT_F4HWN_RESCUE_OPS=$(ENABLE_FEAT_F4HWN_RESCUE_OPS)
@@ -463,6 +475,9 @@ endif
ifeq ($(ENABLE_FEAT_F4HWN_CA),1) ifeq ($(ENABLE_FEAT_F4HWN_CA),1)
CFLAGS += -DENABLE_FEAT_F4HWN_CA CFLAGS += -DENABLE_FEAT_F4HWN_CA
endif endif
ifeq ($(ENABLE_FEAT_F4HWN_DEBUG),1)
CFLAGS += -DENABLE_FEAT_F4HWN_DEBUG
endif
LDFLAGS = LDFLAGS =
LDFLAGS += -z noexecstack -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld -Wl,--gc-sections LDFLAGS += -z noexecstack -mcpu=cortex-m0 -nostartfiles -Wl,-T,firmware.ld -Wl,--gc-sections

View File

@@ -26,7 +26,7 @@ Anyway, have fun.
# Donations # Donations
Special thanks to Jean-Cyrille F6IWW, Fabrice 14RC123, David F4BPP, Olivier 14RC206, Frédéric F4ESO, Stéphane F5LGW, Jorge Ornelas (4 times), Laurent F4AXK, Christophe Morel, Clayton W0LED, Pierre Antoine F6FWB, Jean-Claude 14FRS3306, Thierry F4GVO, Eric F1NOU, PricelessToolkit, Ady M6NYJ, Tom McGovern, Joseph Roth, Pierre-Yves Colin, Frank DJ7FG, Marcel Testaz, Brian Frobisher, Yannick F4JFO, Paolo Bussola, Dirk DL8DF, Levente Szőke (2 times), Bernard-Michel Herrera, Jérôme Saintespes, Paul Davies, RS, Johan F4WAT, Robert Wörle, Rafael Sundorf, Paul Harker, Peter Fintl, Pascal F4ICR (2 times), Mike DL2MF, Eric KI1C (2 times), Phil G0ELM, Jérôme Lambert, Meinhard Frank Günther and Eliot Vedel for their [donations](https://www.paypal.com/paypalme/F4HWN). Thats so kind of them. Thanks so much 🙏🏻 Special thanks to Jean-Cyrille F6IWW (2 times), Fabrice 14RC123, David F4BPP, Olivier 14RC206, Frédéric F4ESO, Stéphane F5LGW, Jorge Ornelas (4 times), Laurent F4AXK, Christophe Morel, Clayton W0LED, Pierre Antoine F6FWB, Jean-Claude 14FRS3306, Thierry F4GVO, Eric F1NOU, PricelessToolkit, Ady M6NYJ, Tom McGovern (3 times), Joseph Roth, Pierre-Yves Colin, Frank DJ7FG, Marcel Testaz, Brian Frobisher, Yannick F4JFO, Paolo Bussola, Dirk DL8DF, Levente Szőke (2 times), Bernard-Michel Herrera, Jérôme Saintespes, Paul Davies, RS, Johan F4WAT, Robert Wörle, Rafael Sundorf, Paul Harker, Peter Fintl, Pascal F4ICR (2 times), Mike DL2MF, Eric KI1C (2 times), Phil G0ELM, Jérôme Lambert, Meinhard Frank Günther, Eliot Vedel, Alfonso EA7KDF, Jean-François F1EVM and Robert DC1RDB for their [donations](https://www.paypal.com/paypalme/F4HWN). Thats so kind of them. Thanks so much 🙏🏻
## Table of Contents ## Table of Contents
@@ -97,6 +97,8 @@ Special thanks to Jean-Cyrille F6IWW, Fabrice 14RC123, David F4BPP, Olivier 14RC
* improve ScnRev menu (CARRIER from 250ms to 20s, STOP, TIMEOUT from 5s to 2m) * improve ScnRev menu (CARRIER from 250ms to 20s, STOP, TIMEOUT from 5s to 2m)
* improve KeyLck menu (OFF, delay from 15s to 10m) * improve KeyLck menu (OFF, delay from 15s to 10m)
* add HAM CA F Lock band (for Canadian zone), * add HAM CA F Lock band (for Canadian zone),
* add PMR 446 F Lock band,
* add FRS/GMRS/MURS F Lock band,
* remove blink and SOS functionality, * remove blink and SOS functionality,
* remove AM Fix menu (AM Fix is ENABLED by default), * remove AM Fix menu (AM Fix is ENABLED by default),
* add support of 3500mAh battery, * add support of 3500mAh battery,
@@ -116,13 +118,14 @@ Special thanks to Jean-Cyrille F6IWW, Fabrice 14RC123, David F4BPP, Olivier 14RC
* scan lists [1, 2, 3], * scan lists [1, 2, 3],
* scan all (all channels with ou without list), * scan all (all channels with ou without list),
* add scan list shortcuts, * add scan list shortcuts,
* add scan resume mode on startup, * add resume mode on startup (scan, bandscope and broadcast FM),
* new actions: * new actions:
* RX MODE, * RX MODE,
* MAIN ONLY, * MAIN ONLY,
* PTT, * PTT,
* WIDE NARROW, * WIDE NARROW,
* 1750Hz, * 1750Hz,
* MUTE,
* POWER HIGH (RescueOps), * POWER HIGH (RescueOps),
* REMOVE OFFSET (RescueOps), * REMOVE OFFSET (RescueOps),
* new key combinations: * new key combinations:
@@ -238,7 +241,10 @@ This is the least demanding option as you don't have to install enything on your
### Docker build method ### Docker build method
If you have docker installed you can use [compile-with-docker.bat](./compile-with-docker.bat) (Windows) or [compile-with-docker.sh](./compile-with-docker.sh) (Linux/Mac), 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 challenge can be (or not) installing docker itself. If you have docker installed you can use [compile-with-docker.bat](./compile-with-docker.bat) (Windows) or [compile-with-docker.sh](./compile-with-docker.sh) (Linux/Mac), 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 challenge can be (or not) installing docker itself.
> [!TIP]
> On Linux/Mac, you may need to uncomment and customize the DOCKER_NETWORK environment variable at the beginning of the [compile-with-docker.sh](./compile-with-docker.sh) script. Note: this can introduce security risks by removing network isolation. However, if you encounter issues and are using a specific network environment (with a proxy or a firewall), this may help.
### Windows environment build method ### Windows environment build method

View File

@@ -42,6 +42,9 @@
#include "settings.h" #include "settings.h"
#include "ui/inputbox.h" #include "ui/inputbox.h"
#include "ui/ui.h" #include "ui/ui.h"
#ifdef ENABLE_REGA
#include "app/rega.h"
#endif
#ifdef ENABLE_FEAT_F4HWN_SCREENSHOT #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT
#include "screenshot.h" #include "screenshot.h"
@@ -111,6 +114,11 @@ void (*action_opt_table[])(void) = {
[ACTION_OPT_PTT] = &ACTION_Ptt, [ACTION_OPT_PTT] = &ACTION_Ptt,
[ACTION_OPT_WN] = &ACTION_Wn, [ACTION_OPT_WN] = &ACTION_Wn,
[ACTION_OPT_BACKLIGHT] = &ACTION_BackLight, [ACTION_OPT_BACKLIGHT] = &ACTION_BackLight,
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
[ACTION_OPT_MUTE] = &ACTION_Mute,
#else
[ACTION_OPT_MUTE] = &FUNCTION_NOP,
#endif
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS #ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
[ACTION_OPT_POWER_HIGH] = &ACTION_Power_High, [ACTION_OPT_POWER_HIGH] = &ACTION_Power_High,
[ACTION_OPT_REMOVE_OFFSET] = &ACTION_Remove_Offset, [ACTION_OPT_REMOVE_OFFSET] = &ACTION_Remove_Offset,
@@ -118,6 +126,10 @@ void (*action_opt_table[])(void) = {
#else #else
[ACTION_OPT_RXMODE] = &FUNCTION_NOP, [ACTION_OPT_RXMODE] = &FUNCTION_NOP,
#endif #endif
#ifdef ENABLE_REGA
[ACTION_OPT_REGA_ALARM] = &ACTION_RegaAlarm,
[ACTION_OPT_REGA_TEST] = &ACTION_RegaTest,
#endif
}; };
static_assert(ARRAY_SIZE(action_opt_table) == ACTION_OPT_LEN); static_assert(ARRAY_SIZE(action_opt_table) == ACTION_OPT_LEN);
@@ -224,7 +236,7 @@ void ACTION_Scan(bool bRestart)
// channel mode. Keep scanning but toggle between scan lists // channel mode. Keep scanning but toggle between scan lists
gEeprom.SCAN_LIST_DEFAULT = (gEeprom.SCAN_LIST_DEFAULT + 1) % 6; gEeprom.SCAN_LIST_DEFAULT = (gEeprom.SCAN_LIST_DEFAULT + 1) % 6;
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
SETTINGS_WriteCurrentState(); SETTINGS_WriteCurrentState();
#endif #endif
@@ -233,7 +245,7 @@ void ACTION_Scan(bool bRestart)
gScanPauseDelayIn_10ms = 1; gScanPauseDelayIn_10ms = 1;
gScheduleScanListen = false; gScheduleScanListen = false;
} else { } else {
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
if(gScanRangeStart == 0) // No ScanRange if(gScanRangeStart == 0) // No ScanRange
{ {
gEeprom.CURRENT_STATE = 1; gEeprom.CURRENT_STATE = 1;
@@ -625,6 +637,27 @@ void ACTION_BackLightOnDemand(void)
BACKLIGHT_TurnOn(); BACKLIGHT_TurnOn();
} }
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
void ACTION_Mute(void)
{
// Toggle mute state
gMute = !gMute;
// Update the registers
#ifdef ENABLE_FMRADIO
BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, gMute ? 0x0A10 : 0x0A1F);
#endif
gEeprom.VOLUME_GAIN = gMute ? 0 : gEeprom.VOLUME_GAIN_BACKUP;
BK4819_WriteRegister(BK4819_REG_48,
(11u << 12) | // ??? .. 0 ~ 15, doesn't seem to make any difference
(0u << 10) | // AF Rx Gain-1
(gEeprom.VOLUME_GAIN << 4) | // AF Rx Gain-2
(gEeprom.DAC_GAIN << 0)); // AF DAC Gain (after Gain-1 and Gain-2)
gUpdateStatus = true;
}
#endif
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS #ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
void ACTION_Power_High(void) void ACTION_Power_High(void)
{ {

View File

@@ -42,6 +42,9 @@ void ACTION_SwitchDemodul(void);
void ACTION_Wn(void); void ACTION_Wn(void);
void ACTION_BackLightOnDemand(void); void ACTION_BackLightOnDemand(void);
void ACTION_BackLight(void); void ACTION_BackLight(void);
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
void ACTION_Mute(void);
#endif
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS #ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
void ACTION_Power_High(void); void ACTION_Power_High(void);
void ACTION_Remove_Offset(void); void ACTION_Remove_Offset(void);

View File

@@ -96,9 +96,12 @@ void (*ProcessKeysFunctions[])(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
#endif #endif
}; };
#ifdef ENABLE_REGA
// This is a hack for REGA as I need a special display element only for it with no key
static_assert(ARRAY_SIZE(ProcessKeysFunctions) == DISPLAY_N_ELEM-1);
#else
static_assert(ARRAY_SIZE(ProcessKeysFunctions) == DISPLAY_N_ELEM); static_assert(ARRAY_SIZE(ProcessKeysFunctions) == DISPLAY_N_ELEM);
#endif
static void CheckForIncoming(void) static void CheckForIncoming(void)
{ {
@@ -966,19 +969,10 @@ void APP_Update(void)
//if (gKeyReading1 != KEY_INVALID) //if (gKeyReading1 != KEY_INVALID)
// gPttWasReleased = true; // gPttWasReleased = true;
} }
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv(); ST7565_ContrastAndInv();
#endif
} }
/*
if (gSetting_set_ptt_session) // Improve OnePush if TOT
{
ProcessKey(KEY_PTT, false, false);
gPttIsPressed = false;
gPttOnePushCounter = 0;
if (gKeyReading1 != KEY_INVALID)
gPttWasReleased = true;
ST7565_ContrastAndInv();
}
*/
#endif #endif
APP_EndTransmission(); APP_EndTransmission();
@@ -1213,7 +1207,9 @@ static void CheckKeys(void)
if (gKeyReading1 != KEY_INVALID) if (gKeyReading1 != KEY_INVALID)
gPttWasReleased = true; gPttWasReleased = true;
gPttOnePushCounter = 0; gPttOnePushCounter = 0;
ST7565_ContrastAndInv(); #if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv();
#endif
} }
} }
else else
@@ -1233,7 +1229,9 @@ static void CheckKeys(void)
gPttIsPressed = false; gPttIsPressed = false;
if (gKeyReading1 != KEY_INVALID) if (gKeyReading1 != KEY_INVALID)
gPttWasReleased = true; gPttWasReleased = true;
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv(); ST7565_ContrastAndInv();
#endif
} }
} }
else else

View File

@@ -78,6 +78,7 @@ void CHFRSCANNER_Start(const bool storeBackupSettings, const int8_t scan_directi
gScanPauseMode = false; gScanPauseMode = false;
} }
/*
void CHFRSCANNER_ContinueScanning(void) void CHFRSCANNER_ContinueScanning(void)
{ {
if (IS_FREQ_CHANNEL(gNextMrChannel)) if (IS_FREQ_CHANNEL(gNextMrChannel))
@@ -99,6 +100,24 @@ void CHFRSCANNER_ContinueScanning(void)
gRxReceptionMode = RX_MODE_NONE; gRxReceptionMode = RX_MODE_NONE;
gScheduleScanListen = false; gScheduleScanListen = false;
} }
*/
void CHFRSCANNER_ContinueScanning(void)
{
if (gCurrentFunction == FUNCTION_INCOMING &&
(IS_FREQ_CHANNEL(gNextMrChannel) || gCurrentCodeType == CODE_TYPE_OFF))
{
APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE);
}
else
{
IS_FREQ_CHANNEL(gNextMrChannel) ? NextFreqChannel() : NextMemChannel();
}
gScanPauseMode = false;
gRxReceptionMode = RX_MODE_NONE;
gScheduleScanListen = false;
}
void CHFRSCANNER_Found(void) void CHFRSCANNER_Found(void)
{ {
@@ -196,7 +215,7 @@ void CHFRSCANNER_Stop(void)
} }
} }
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 0; gEeprom.CURRENT_STATE = 0;
SETTINGS_WriteCurrentState(); SETTINGS_WriteCurrentState();
#endif #endif

View File

@@ -111,6 +111,11 @@ void FM_TurnOff(void)
BK1080_Init0(); BK1080_Init0();
gUpdateStatus = true; gUpdateStatus = true;
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 0;
SETTINGS_WriteCurrentState();
#endif
} }
void FM_EraseChannels(void) void FM_EraseChannels(void)
@@ -617,6 +622,11 @@ void FM_Start(void)
gEnableSpeaker = true; gEnableSpeaker = true;
gUpdateStatus = true; gUpdateStatus = true;
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 3;
SETTINGS_WriteCurrentState();
#endif
} }
#endif #endif

View File

@@ -363,6 +363,7 @@ void channelMoveSwitch(void) {
if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { // user is entering channel number if (IS_MR_CHANNEL(gTxVfo->CHANNEL_SAVE)) { // user is entering channel number
uint16_t Channel = 0; uint16_t Channel = 0;
/*
switch (gInputBoxIndex) switch (gInputBoxIndex)
{ {
case 1: case 1:
@@ -375,6 +376,11 @@ void channelMoveSwitch(void) {
Channel = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]; Channel = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2];
break; break;
} }
*/
for (uint8_t i = 0; i < gInputBoxIndex; i++) {
Channel = (Channel * 10) + gInputBox[i];
}
if ((Channel == 0) && (gInputBoxIndex != 3)) { if ((Channel == 0) && (gInputBoxIndex != 3)) {
return; return;
@@ -425,7 +431,7 @@ static void MAIN_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
switch(Key) { switch(Key) {
case KEY_0...KEY_5: case KEY_0...KEY_5:
gEeprom.SCAN_LIST_DEFAULT = Key; gEeprom.SCAN_LIST_DEFAULT = Key;
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
SETTINGS_WriteCurrentState(); SETTINGS_WriteCurrentState();
#endif #endif
break; break;
@@ -741,7 +747,7 @@ static void MAIN_Key_STAR(bool bKeyPressed, bool bKeyHeld)
return; return;
/* /*
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
if(gScanRangeStart == 0) // No ScanRange if(gScanRangeStart == 0) // No ScanRange
{ {
gEeprom.CURRENT_STATE = 1; gEeprom.CURRENT_STATE = 1;

View File

@@ -400,17 +400,19 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
//*pMin = 0; //*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_SET_TOT) - 1; *pMax = ARRAY_SIZE(gSubMenu_SET_TOT) - 1;
break; break;
#ifdef ENABLE_FEAT_F4HWN_CONTRAST #ifdef ENABLE_FEAT_F4HWN_CTR
case MENU_SET_CTR: case MENU_SET_CTR:
*pMin = 1; *pMin = 1;
*pMax = 15; *pMax = 15;
break; break;
#endif #endif
case MENU_TX_LOCK: case MENU_TX_LOCK:
#ifdef ENABLE_FEAT_F4HWN_INV
case MENU_SET_INV: case MENU_SET_INV:
//*pMin = 0; //*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1; *pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1;
break; break;
#endif
case MENU_SET_LCK: case MENU_SET_LCK:
//*pMin = 0; //*pMin = 0;
*pMax = ARRAY_SIZE(gSubMenu_SET_LCK) - 1; *pMax = ARRAY_SIZE(gSubMenu_SET_LCK) - 1;
@@ -928,7 +930,7 @@ void MENU_AcceptSetting(void)
case MENU_SET_EOT: case MENU_SET_EOT:
gSetting_set_eot = gSubMenuSelection; gSetting_set_eot = gSubMenuSelection;
break; break;
#ifdef ENABLE_FEAT_F4HWN_CONTRAST #ifdef ENABLE_FEAT_F4HWN_CTR
case MENU_SET_CTR: case MENU_SET_CTR:
gSetting_set_ctr = gSubMenuSelection; gSetting_set_ctr = gSubMenuSelection;
break; break;
@@ -1205,15 +1207,9 @@ void MENU_ShowCurrentSetting(void)
break; break;
case MENU_SLIST1: case MENU_SLIST1:
gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 1);
break;
case MENU_SLIST2: case MENU_SLIST2:
gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 2);
break;
case MENU_SLIST3: case MENU_SLIST3:
gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 3); gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, UI_MENU_GetCurrentMenuId() - MENU_SLIST1 + 1);
break; break;
#ifdef ENABLE_ALARM #ifdef ENABLE_ALARM
@@ -1381,7 +1377,7 @@ void MENU_ShowCurrentSetting(void)
case MENU_SET_EOT: case MENU_SET_EOT:
gSubMenuSelection = gSetting_set_eot; gSubMenuSelection = gSetting_set_eot;
break; break;
#ifdef ENABLE_FEAT_F4HWN_CONTRAST #ifdef ENABLE_FEAT_F4HWN_CTR
case MENU_SET_CTR: case MENU_SET_CTR:
gSubMenuSelection = gSetting_set_ctr; gSubMenuSelection = gSetting_set_ctr;
break; break;
@@ -1567,6 +1563,7 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
Offset = (Max >= 100) ? 3 : (Max >= 10) ? 2 : 1; Offset = (Max >= 100) ? 3 : (Max >= 10) ? 2 : 1;
/*
switch (gInputBoxIndex) switch (gInputBoxIndex)
{ {
case 1: case 1:
@@ -1579,6 +1576,11 @@ static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
Value = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]; Value = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2];
break; break;
} }
*/
for (uint8_t i = 0; i < gInputBoxIndex; i++) {
Value = (Value * 10) + gInputBox[i];
}
if (Offset == gInputBoxIndex) if (Offset == gInputBoxIndex)
gInputBoxIndex = 0; gInputBoxIndex = 0;
@@ -1937,8 +1939,8 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
VFO = 2; VFO = 2;
break; break;
case MENU_SLIST1: case MENU_SLIST1:
VFO = 1;
bCheckScanList = true; bCheckScanList = true;
VFO = 1;
break; break;
default: default:

187
app/rega.c Normal file
View File

@@ -0,0 +1,187 @@
/*
* REGA Alam and Test
* ==================
*
* This bit of code is to implement the REGA test and alarm functions.
* This function sends out a fixed ZVEI tone sequence for testing or alarm purposes.
* Further information: https://www.rega.ch/en/our-missions/sites-and-infrastructure/emergency-radio
*
* There are two REGA ACTIONS: Test and Alarm.
* The Test action sends out a fixed ZVEI tone sequence for testing purposes.
* The Alarm action sends out a fixed ZVEI tone sequence for alarm purposes.
*
* These actions can be assigned to a key in the settings menu.
*
* The Test/Alarm function will perform the following actions:
* - Set the radio to transmit mode
* - Wait 100ms to allow the radio to switch to transmit mode and stabilize the tramsmitter
* - Send out the ZVEI tone sequence
* - Wait 100ms to allow the radio to finish transmitting
* - Set the radio back to receive mode
*
* The ZVEI tone squence for alarm is: 21414
* The ZVEI tone squence for test is: 21301
*
* To save space the two tone sequences are stored as precalculated register values.
* This avoids the need to calculate the register values at runtime.
* They are hardcoded as array of 32bit integers in the rega.h file.
*
* Copyright 2025 Markus Bärtschi
* https://github.com/markusb
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include "rega.h"
#include "radio.h"
#include "action.h"
#include "misc.h"
#include "settings.h"
#include "functions.h"
#include "driver/bk4819.h"
#include "driver/st7565.h"
#include "driver/system.h"
#include "driver/gpio.h"
#include "bsp/dp32g030/gpio.h"
#include "ui/helper.h"
#include "ui/ui.h"
const uint16_t rega_alarm_tones[5] = {
1160, // 2 1160Hz
1060, // 1 1060Hz
1400, // 4 1400Hz
1060, // 1 1060Hz
1400, // 4 1400Hz
};
const uint16_t rega_test_tones[5] = {
1160, // 2 1160Hz
1060, // 1 1060Hz
1260, // 3 1260Hz
2400, // 0 2400Hz
1060, // 1 1060Hz
};
// Global variable to pass the message to the display
char rega_message[16];
// Transmit the ZVEI tone sequence for alarm
void ACTION_RegaAlarm()
{
const char message[16] = "REGA Alarm";
REGA_TransmitZvei(rega_alarm_tones,message);
}
// Tranmit the ZVEI tone sequence for test
void ACTION_RegaTest()
{
const char message[16] = "REGA Test";
REGA_TransmitZvei(rega_test_tones,message);
}
// Display the REGA message on the screen
void UI_DisplayREGA()
{
UI_DisplayClear();
UI_DisplayPopup(rega_message);
ST7565_BlitFullScreen();
}
// Transmit a ZVEI tone sequence on the REGA frequency
// Configures the radio on VFO A with the required parameters
// tones: array of 5 ZVEI tones
// message: message to display on the screen
void REGA_TransmitZvei(const uint16_t tones[],const char message[])
{
// Copy the message text
strncpy(rega_message,message,16);
// Trigger the display
gScreenToDisplay = DISPLAY_REGA;
// Flash the green LED twice
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
SYSTEM_DelayMs(70);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
SYSTEM_DelayMs(50);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
SYSTEM_DelayMs(70);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
// Select VFO A
gEeprom.TX_VFO = 0;
gEeprom.ScreenChannel[gEeprom.TX_VFO] = gEeprom.FreqChannel[gEeprom.TX_VFO];
gRxVfo = gTxVfo;
gRequestSaveVFO = true;
gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
// Set the REGA frequency, no offset
gTxVfo->freq_config_RX.Frequency = REGA_FREQUENCY;
gTxVfo->freq_config_TX = gTxVfo->freq_config_RX;
gTxVfo->TX_OFFSET_FREQUENCY = 0;
// Set the modulation to FM narrow
gTxVfo->Modulation = MODULATION_FM;
gTxVfo->CHANNEL_BANDWIDTH = BK4819_FILTER_BW_NARROW;
// Set Tx Squelch Tone
gTxVfo->freq_config_TX.CodeType = CODE_TYPE_CONTINUOUS_TONE;
gTxVfo->freq_config_TX.Code = REGA_CTCSS_FREQ_INDEX;
BK4819_SetCTCSSFrequency(CTCSS_Options[gTxVfo->freq_config_TX.Code]);
// Turn Rx squelch tone off
gTxVfo->freq_config_RX.CodeType = CODE_TYPE_OFF;
// Set the transmit power to high
gTxVfo->OUTPUT_POWER = OUTPUT_POWER_HIGH;
// Lock the keyboard
gEeprom.KEY_LOCK = true;
gRequestSaveChannel = 1;
gRequestSaveSettings = true;
// Configure the receiver
BK4819_RX_TurnOn();
// Set the radio to transmit mode
RADIO_PrepareCssTX();
FUNCTION_Select(FUNCTION_TRANSMIT);
// Wait to allow the radio to switch to transmit mode and stabilize the transmitter
SYSTEM_DelayMs(ZVEI_PRE_LENGTH_MS);
// Send out the ZVEI2 tone sequence
for (int i = 0; i < ZVEI_NUM_TONES; i++)
{
BK4819_PlaySingleTone(tones[i], ZVEI_TONE_LENGTH_MS, 100, true);
SYSTEM_DelayMs(ZVEI_PAUSE_LENGTH_MS);
}
// Wait to allow the radio to finish transmitting
SYSTEM_DelayMs(ZVEI_POST_LENGTH_MS);
// Flash the green LED twice
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
SYSTEM_DelayMs(70);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
SYSTEM_DelayMs(70);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, true);
SYSTEM_DelayMs(70);
BK4819_ToggleGpioOut(BK4819_GPIO6_PIN2_GREEN, false);
// Display the normal screen
gRequestDisplayScreen = DISPLAY_MAIN;
}

65
app/rega.h Normal file
View File

@@ -0,0 +1,65 @@
/*
* REGA Alam and Test
* ==================
*
* This function sends out a fixed ZVEI tone sequence for testing or alarm purposes for the Alpine REGA alarm channel.
* Further information: https://www.rega.ch/en/our-missions/sites-and-infrastructure/emergency-radio
*
* There are two REGA ACTIONS: Test and Alarm.
* The Test action sends out a fixed ZVEI tone sequence for testing purposes.
* The Alarm action sends out a fixed ZVEI tone sequence for alarm purposes.
*
* These actions can be assigned to a key in the settings menu.
*
* The Test/Alarm function will perform the following actions:
* - Set the radio configuration to the REGA frequency, CTCSS, FM, full power etc.
* - Start transmitting
* - Wait 100ms to allow the radio to switch to transmit mode and stabilize the transmitter
* - Send out the ZVEI tone sequence
* - Wait 100ms to allow the radio to finish transmitting
* - Set the radio back to receive mode
*
* The REGA frequency is 161.300 Mhz
*
* The ZVEI tone squence for alarm is: 21414
* The ZVEI tone squence for test is: 21301
*
* The two tone sequences are hardcoded in two arrays
*
* Copyright 2025 Markus Bärtschi
*
* https://github.com/markusb
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef REGA_H
#define REGA_H
#include <stdint.h>
#define ZVEI_NUM_TONES 5
#define ZVEI_TONE_LENGTH_MS 70 // 70
#define ZVEI_PAUSE_LENGTH_MS 10 // 10
#define ZVEI_PRE_LENGTH_MS 300
#define ZVEI_POST_LENGTH_MS 100
#define REGA_CTCSS_FREQ_INDEX 18 // dcs.c: CTCSS_Options[18] = 1230
#define REGA_FREQUENCY 16130000 // 43370000 16130000
void ACTION_RegaAlarm(void);
void ACTION_RegaTest(void);
void UI_DisplayREGA(void);
void REGA_TransmitZvei(const uint16_t[], const char[]);
#endif

View File

@@ -112,6 +112,7 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
if (bKeyHeld || !bKeyPressed) // ignore long press or release button events if (bKeyHeld || !bKeyPressed) // ignore long press or release button events
return; return;
/*
if (gScanCssState == SCAN_CSS_STATE_OFF && !gScanSingleFrequency) { if (gScanCssState == SCAN_CSS_STATE_OFF && !gScanSingleFrequency) {
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return; return;
@@ -126,6 +127,15 @@ static void SCANNER_Key_MENU(bool bKeyPressed, bool bKeyHeld)
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL; gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return; return;
} }
*/
if (gScanCssState == SCAN_CSS_STATE_FAILED ||
(!gScanSingleFrequency && gScanCssState == SCAN_CSS_STATE_OFF) ||
(gScanSingleFrequency && gScanCssState == SCAN_CSS_STATE_SCANNING))
{
gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
return;
}
gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL; gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;

View File

@@ -867,16 +867,23 @@ uint8_t Rssi2Y(uint16_t rssi)
return DrawingEndY - Rssi2PX(rssi, 0, DrawingEndY); return DrawingEndY - Rssi2PX(rssi, 0, DrawingEndY);
} }
#ifdef ENABLE_FEAT_F4HWN_SPECTRUM #ifdef ENABLE_FEAT_F4HWN
static void DrawSpectrum() static void DrawSpectrum()
{ {
uint16_t steps = GetStepsCount();
// max bars at 128 to correctly draw larger numbers of samples
uint8_t bars = (steps > 128) ? 128 : steps;
// shift to center bar on freq marker
uint8_t shift_graph = 64 / steps + 1;
uint8_t ox = 0; uint8_t ox = 0;
for (uint8_t i = 0; i < 128; ++i) for (uint8_t i = 0; i < 128; ++i)
{ {
uint16_t rssi = rssiHistory[i >> settings.stepsCount]; uint16_t rssi = rssiHistory[i >> settings.stepsCount];
if (rssi != RSSI_MAX_VALUE) if (rssi != RSSI_MAX_VALUE)
{ {
uint8_t x = i * 128 / GetStepsCount(); // stretch bars to fill the screen width
uint8_t x = i * 128 / bars + shift_graph;
for (uint8_t xx = ox; xx < x; xx++) for (uint8_t xx = ox; xx < x; xx++)
{ {
DrawVLine(Rssi2Y(rssi), DrawingEndY, xx, true); DrawVLine(Rssi2Y(rssi), DrawingEndY, xx, true);
@@ -941,6 +948,7 @@ static void DrawStatus()
static void ShowChannelName(uint32_t f) static void ShowChannelName(uint32_t f)
{ {
unsigned int i; unsigned int i;
char String[12];
memset(String, 0, sizeof(String)); memset(String, 0, sizeof(String));
if (isListening) if (isListening)
@@ -963,10 +971,13 @@ static void ShowChannelName(uint32_t f)
} }
else else
{ {
/*
for (int i = 36; i < 100; i++) for (int i = 36; i < 100; i++)
{ {
gStatusLine[i] = 0b00000000; gStatusLine[i] = 0b00000000;
} }
*/
memset(&gStatusLine[36], 0, 100 - 28);
} }
ST7565_BlitStatusLine(); ST7565_BlitStatusLine();
} }
@@ -1152,6 +1163,10 @@ static void OnKeyDown(uint8_t key)
} }
#ifdef ENABLE_FEAT_F4HWN_SPECTRUM #ifdef ENABLE_FEAT_F4HWN_SPECTRUM
SaveSettings(); SaveSettings();
#endif
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 0;
SETTINGS_WriteCurrentState();
#endif #endif
DeInitSpectrum(); DeInitSpectrum();
break; break;
@@ -1628,11 +1643,22 @@ void APP_RunSpectrum()
} }
} }
settings.stepsCount = STEPS_128; settings.stepsCount = STEPS_128;
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 5;
#endif
} }
else else {
#endif #endif
currentFreq = initialFreq = gTxVfo->pRX->Frequency - currentFreq = initialFreq = gTxVfo->pRX->Frequency -
((GetStepsCount() / 2) * GetScanStep()); ((GetStepsCount() / 2) * GetScanStep());
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 4;
#endif
}
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
SETTINGS_WriteCurrentState();
#endif
BackupRegisters(); BackupRegisters();

View File

@@ -210,29 +210,26 @@ static void SendVersion(void)
SendReply(&Reply, sizeof(Reply)); SendReply(&Reply, sizeof(Reply));
} }
#ifndef ENABLE_FEAT_F4HWN
static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse) static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse)
{ {
#ifdef ENABLE_FEAT_F4HWN unsigned int i;
UNUSED(pKey); uint32_t IV[4];
UNUSED(pIn);
UNUSED(pResponse);
#else
unsigned int i;
uint32_t IV[4];
IV[0] = 0; IV[0] = 0;
IV[1] = 0; IV[1] = 0;
IV[2] = 0; IV[2] = 0;
IV[3] = 0; IV[3] = 0;
AES_Encrypt(pKey, IV, pIn, IV, true); AES_Encrypt(pKey, IV, pIn, IV, true);
for (i = 0; i < 4; i++)
if (IV[i] != pResponse[i])
return true;
for (i = 0; i < 4; i++)
if (IV[i] != pResponse[i])
return true;
#endif
return false; return false;
} }
#endif
// session init, sends back version info and state // session init, sends back version info and state
// timestamp is a session id really // timestamp is a session id really
@@ -360,6 +357,7 @@ static void CMD_0529(void)
SendReply(&Reply, sizeof(Reply)); SendReply(&Reply, sizeof(Reply));
} }
#ifndef ENABLE_FEAT_F4HWN
static void CMD_052D(const uint8_t *pBuffer) static void CMD_052D(const uint8_t *pBuffer)
{ {
const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer; const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer;
@@ -400,6 +398,7 @@ static void CMD_052D(const uint8_t *pBuffer)
SendReply(&Reply, sizeof(Reply)); SendReply(&Reply, sizeof(Reply));
} }
#endif
// session init, sends back version info and state // session init, sends back version info and state
// timestamp is a session id really // timestamp is a session id really
@@ -600,10 +599,12 @@ void UART_HandleCommand(void)
case 0x0529: case 0x0529:
CMD_0529(); CMD_0529();
break; break;
case 0x052D: #ifndef ENABLE_FEAT_F4HWN
CMD_052D(UART_Command.Buffer); case 0x052D:
break; CMD_052D(UART_Command.Buffer);
break;
#endif
case 0x052F: case 0x052F:
CMD_052F(UART_Command.Buffer); CMD_052F(UART_Command.Buffer);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -57,6 +57,22 @@ const uint8_t gFontLight[9] =
0b00001100, 0b00001100,
}; };
const uint8_t gFontMute[12] =
{
0b00011100,
0b00011100,
0b00010100,
0b00100010,
0b01000001,
0b01111111,
0b00000000,
0b00100010,
0b00010100,
0b00001000,
0b00010100,
0b00100010,
};
const uint8_t gFontXB[2][6] = const uint8_t gFontXB[2][6] =
{ // "XB" { // "XB"
{0x00, 0x63, 0x14, 0x8, 0x14, 0x63}, {0x00, 0x63, 0x14, 0x8, 0x14, 0x63},
@@ -240,7 +256,7 @@ const uint8_t BITMAP_ScanListE[7] =
const uint8_t BITMAP_ScanList123[19] = const uint8_t BITMAP_ScanList123[19] =
{ {
// 'All' symbol // '123' symbol
0b01111111, 0b01111111,
0b01111111, 0b01111111,
0b01111011, 0b01111011,

View File

@@ -12,6 +12,7 @@ extern const uint8_t gFontS[6];
extern const uint8_t gFontKeyLock[9]; extern const uint8_t gFontKeyLock[9];
extern const uint8_t gFontLight[9]; extern const uint8_t gFontLight[9];
extern const uint8_t gFontMute[12];
extern const uint8_t gFontXB[2][6]; extern const uint8_t gFontXB[2][6];
extern const uint8_t gFontMO[2][6]; extern const uint8_t gFontMO[2][6];

View File

@@ -1,8 +1,14 @@
#!/bin/sh #!/bin/sh
#export DOCKER_DEFAULT_PLATFORM=linux/amd64 #export DOCKER_DEFAULT_PLATFORM=linux/amd64
#export DOCKER_NETWORK="--network=host"
IMAGE_NAME="uvk5" IMAGE_NAME="uvk5"
rm "${PWD}/compiled-firmware/*" rm "${PWD}/compiled-firmware/*"
docker build -t $IMAGE_NAME . echo "Building docker image $IMAGE_NAME"
if ! docker build -t $DOCKER_NETWORK $IMAGE_NAME .
then
echo "Failed to build docker image"
exit 1
fi
custom() { custom() {
echo "Custom compilation..." echo "Custom compilation..."
@@ -30,6 +36,8 @@ bandscope() {
ENABLE_SPECTRUM=1 \ ENABLE_SPECTRUM=1 \
ENABLE_FMRADIO=0 \ ENABLE_FMRADIO=0 \
ENABLE_AIRCOPY=1 \ ENABLE_AIRCOPY=1 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=0 \ ENABLE_NOAA=0 \
ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \ ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \
EDITION_STRING=Bandscope \ EDITION_STRING=Bandscope \
@@ -43,6 +51,8 @@ broadcast() {
ENABLE_SPECTRUM=0 \ ENABLE_SPECTRUM=0 \
ENABLE_FMRADIO=1 \ ENABLE_FMRADIO=1 \
ENABLE_AIRCOPY=1 \ ENABLE_AIRCOPY=1 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=0 \ ENABLE_NOAA=0 \
EDITION_STRING=Broadcast \ EDITION_STRING=Broadcast \
ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \ ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \
@@ -50,8 +60,8 @@ broadcast() {
&& cp f4hwn.broadcast* compiled-firmware/" && cp f4hwn.broadcast* compiled-firmware/"
} }
voxless() { basic() {
echo "Voxless compilation..." echo "Basic compilation..."
docker run --rm -v "${PWD}/compiled-firmware:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "cd /app && make -s \ docker run --rm -v "${PWD}/compiled-firmware:/app/compiled-firmware" $IMAGE_NAME /bin/bash -c "cd /app && make -s \
ENABLE_SPECTRUM=1 \ ENABLE_SPECTRUM=1 \
ENABLE_FMRADIO=1 \ ENABLE_FMRADIO=1 \
@@ -59,14 +69,18 @@ voxless() {
ENABLE_AIRCOPY=0 \ ENABLE_AIRCOPY=0 \
ENABLE_AUDIO_BAR=0 \ ENABLE_AUDIO_BAR=0 \
ENABLE_FEAT_F4HWN_SPECTRUM=0 \ ENABLE_FEAT_F4HWN_SPECTRUM=0 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=0 \ ENABLE_NOAA=0 \
ENABLE_FEAT_F4HWN_RESTORE_SCAN=0 \ ENABLE_FEAT_F4HWN_RESUME_STATE=0 \
ENABLE_FEAT_F4HWN_CHARGING_C=0 \ ENABLE_FEAT_F4HWN_CHARGING_C=0 \
ENABLE_FEAT_F4HWN_INV=1 \
ENABLE_FEAT_F4HWN_CTR=0 \
ENABLE_FEAT_F4HWN_NARROWER=0 \ ENABLE_FEAT_F4HWN_NARROWER=0 \
ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \ ENABLE_FEAT_F4HWN_RESCUE_OPS=0 \
EDITION_STRING=Voxless \ EDITION_STRING=Basic \
TARGET=f4hwn.voxless \ TARGET=f4hwn.basic \
&& cp f4hwn.voxless* compiled-firmware/" && cp f4hwn.basic* compiled-firmware/"
} }
rescueops() { rescueops() {
@@ -75,6 +89,8 @@ rescueops() {
ENABLE_SPECTRUM=0 \ ENABLE_SPECTRUM=0 \
ENABLE_FMRADIO=0 \ ENABLE_FMRADIO=0 \
ENABLE_AIRCOPY=1 \ ENABLE_AIRCOPY=1 \
ENABLE_FEAT_F4HWN_PMR=1 \
ENABLE_FEAT_F4HWN_GMRS_FRS_MURS=1 \
ENABLE_NOAA=1 \ ENABLE_NOAA=1 \
ENABLE_FEAT_F4HWN_RESCUE_OPS=1 \ ENABLE_FEAT_F4HWN_RESCUE_OPS=1 \
EDITION_STRING=RescueOps \ EDITION_STRING=RescueOps \
@@ -95,8 +111,8 @@ case "$1" in
broadcast) broadcast)
broadcast broadcast
;; ;;
voxless) basic)
voxless basic
;; ;;
rescueops) rescueops)
rescueops rescueops
@@ -105,9 +121,10 @@ case "$1" in
bandscope bandscope
broadcast broadcast
rescueops rescueops
basic
;; ;;
*) *)
echo "Usage: $0 {custom|bandscope|broadcast|voxless|standard|all}" echo "Usage: $0 {custom|bandscope|broadcast|basic|standard|all}"
exit 1 exit 1
;; ;;
esac esac

View File

@@ -72,10 +72,9 @@ static void BACKLIGHT_Sound(void)
{ {
AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP);
AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP); AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP);
gK5startup = false;
} }
else
gK5startup = false; gK5startup = false;
} }

View File

@@ -68,7 +68,11 @@ void BK1080_Init(uint16_t freq, uint8_t band/*, uint8_t space*/)
BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201); BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201);
} }
BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, 0x0A1F); #ifdef ENABLE_FEAT_F4HWN
BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, gMute ? 0x0A10 : 0x0A1F);
#else
BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, 0x0A1F);
#endif
BK1080_SetFrequency(freq, band/*, space*/); BK1080_SetFrequency(freq, band/*, space*/);
} }
else { else {

View File

@@ -620,7 +620,6 @@ void BK4819_SetFilterBandwidth(const BK4819_FilterBandwidth_t Bandwidth, const b
// with weak RX signals the RX bandwidth is reduced // with weak RX signals the RX bandwidth is reduced
val = 0x3428; // Old value 0x45a8 < v3.6 val = 0x3428; // Old value 0x45a8 < v3.6
} }
break; break;
case BK4819_FILTER_BW_NARROW: // 12.5kHz case BK4819_FILTER_BW_NARROW: // 12.5kHz
@@ -631,7 +630,6 @@ void BK4819_SetFilterBandwidth(const BK4819_FilterBandwidth_t Bandwidth, const b
// with weak RX signals the RX bandwidth is reduced // with weak RX signals the RX bandwidth is reduced
val = 0x3448; // Old value 0x4408 < v3.6 val = 0x3448; // Old value 0x4408 < v3.6
} }
break; break;
case BK4819_FILTER_BW_NARROWER: // 6.25kHz case BK4819_FILTER_BW_NARROWER: // 6.25kHz
@@ -653,7 +651,6 @@ void BK4819_SetFilterBandwidth(const BK4819_FilterBandwidth_t Bandwidth, const b
// with weak RX signals the RX bandwidth is reduced // with weak RX signals the RX bandwidth is reduced
val = 0x4458; val = 0x4458;
} }
break; break;
*/ */
} }

View File

@@ -209,6 +209,7 @@ uint8_t cmds[] = {
} }
} }
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
void ST7565_ContrastAndInv(void) void ST7565_ContrastAndInv(void)
{ {
SPI_ToggleMasterMode(&SPI0->CR, false); SPI_ToggleMasterMode(&SPI0->CR, false);
@@ -219,11 +220,13 @@ uint8_t cmds[] = {
ST7565_Cmd(i); ST7565_Cmd(i);
} }
} }
#endif
int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) { int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
} }
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
void ST7565_Gauge(uint8_t line, uint8_t min, uint8_t max, uint8_t value) void ST7565_Gauge(uint8_t line, uint8_t min, uint8_t max, uint8_t value)
{ {
gFrameBuffer[line][54] = 0x0c; gFrameBuffer[line][54] = 0x0c;
@@ -238,6 +241,7 @@ uint8_t cmds[] = {
gFrameBuffer[line][i] = (i <= filled) ? 0x2d : 0x21; gFrameBuffer[line][i] = (i <= filled) ? 0x2d : 0x21;
} }
} }
#endif
#endif #endif
void ST7565_Init(void) void ST7565_Init(void)

View File

@@ -42,8 +42,12 @@ void ST7565_SelectColumnAndLine(uint8_t Column, uint8_t Line);
void ST7565_WriteByte(uint8_t Value); void ST7565_WriteByte(uint8_t Value);
#ifdef ENABLE_FEAT_F4HWN #ifdef ENABLE_FEAT_F4HWN
#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
void ST7565_ContrastAndInv(void); void ST7565_ContrastAndInv(void);
#endif
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
void ST7565_Gauge(uint8_t line, uint8_t min, uint8_t max, uint8_t value); void ST7565_Gauge(uint8_t line, uint8_t min, uint8_t max, uint8_t value);
#endif
int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max); int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max);
#endif #endif

View File

@@ -255,6 +255,7 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
UI_DisplayStatus(); UI_DisplayStatus();
} }
/*
switch (Function) { switch (Function) {
case FUNCTION_FOREGROUND: case FUNCTION_FOREGROUND:
FUNCTION_Foreground(PreviousFunction); FUNCTION_Foreground(PreviousFunction);
@@ -278,6 +279,23 @@ void FUNCTION_Select(FUNCTION_Type_t Function)
default: default:
break; break;
} }
*/
if (Function == FUNCTION_FOREGROUND) {
FUNCTION_Foreground(PreviousFunction);
return;
}
if (Function == FUNCTION_POWER_SAVE) {
FUNCTION_PowerSave();
return;
}
if (Function == FUNCTION_TRANSMIT) {
FUNCTION_Transmit();
} else if (Function == FUNCTION_MONITOR) {
gMonitor = true;
}
gBatterySaveCountdown_10ms = battery_save_count_10ms; gBatterySaveCountdown_10ms = battery_save_count_10ms;
gSchedulePowerSave = false; gSchedulePowerSave = false;

View File

@@ -74,6 +74,9 @@ void BOOT_ProcessMode(BOOT_Mode_t Mode)
{ {
if (Mode == BOOT_MODE_F_LOCK) if (Mode == BOOT_MODE_F_LOCK)
{ {
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 0; // Don't resume is active...
#endif
GUI_SelectNextDisplay(DISPLAY_MENU); GUI_SelectNextDisplay(DISPLAY_MENU);
} }
#ifdef ENABLE_AIRCOPY #ifdef ENABLE_AIRCOPY
@@ -111,8 +114,8 @@ void BOOT_ProcessMode(BOOT_Mode_t Mode)
gEeprom.BACKLIGHT_TIME = 61; gEeprom.BACKLIGHT_TIME = 61;
gEeprom.KEY_LOCK = 0; gEeprom.KEY_LOCK = 0;
#ifdef ENABLE_FEAT_F4HWN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.CURRENT_STATE = 0; // Don't scan if scan resume is active... gEeprom.CURRENT_STATE = 0; // Don't resume is active...
#endif #endif
GUI_SelectNextDisplay(DISPLAY_AIRCOPY); GUI_SelectNextDisplay(DISPLAY_AIRCOPY);

66
main.c
View File

@@ -31,7 +31,8 @@
#ifdef ENABLE_FEAT_F4HWN #ifdef ENABLE_FEAT_F4HWN
#ifdef ENABLE_FMRADIO #ifdef ENABLE_FMRADIO
#include "app/fm.h" #include "app/action.h"
#include "ui/ui.h"
#endif #endif
#ifdef ENABLE_SPECTRUM #ifdef ENABLE_SPECTRUM
#include "app/spectrum.h" #include "app/spectrum.h"
@@ -164,7 +165,7 @@ void Main(void)
gEeprom.KEY_LOCK = 0; gEeprom.KEY_LOCK = 0;
SETTINGS_SaveSettings(); SETTINGS_SaveSettings();
#ifndef ENABLE_VOX #ifndef ENABLE_VOX
gMenuCursor = 65; // move to hidden section, fix me if change... !!! Remove VOX and Mic Bar gMenuCursor = 67; // move to hidden section, fix me if change... !!! Remove VOX and Mic Bar
#else #else
gMenuCursor = 68; // move to hidden section, fix me if change... !!! gMenuCursor = 68; // move to hidden section, fix me if change... !!!
#endif #endif
@@ -290,35 +291,40 @@ void Main(void)
#endif #endif
} }
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN /*
switch (gEeprom.CURRENT_STATE) { #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
case 1: if(gEeprom.CURRENT_STATE == 2 || gEeprom.CURRENT_STATE == 5)
//gScanRangeStart = 0; {
//ACTION_Scan(false);
gEeprom.SCAN_LIST_DEFAULT = gEeprom.CURRENT_LIST;
CHFRSCANNER_Start(true, SCAN_FWD);
break;
case 2:
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency; gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency; gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
if(gScanRangeStart > gScanRangeStop) if(gScanRangeStart > gScanRangeStop)
{ {
SWAP(gScanRangeStart, gScanRangeStop); SWAP(gScanRangeStart, gScanRangeStop);
} }
//ACTION_Scan(false); }
switch (gEeprom.CURRENT_STATE) {
case 1:
gEeprom.SCAN_LIST_DEFAULT = gEeprom.CURRENT_LIST;
CHFRSCANNER_Start(true, SCAN_FWD);
break;
case 2:
CHFRSCANNER_Start(true, SCAN_FWD); CHFRSCANNER_Start(true, SCAN_FWD);
break; break;
#ifdef ENABLE_FMRADIO #ifdef ENABLE_FMRADIO
case 3: case 3:
FM_Start(); // For compiler alignments and paddings... ACTION_FM();
GUI_SelectNextDisplay(gRequestDisplayScreen);
break; break;
#endif #endif
#ifdef ENABLE_SPECTRUM #ifdef ENABLE_SPECTRUM
case 4: case 4:
APP_RunSpectrum(); // For compiler alignments and paddings... APP_RunSpectrum();
break;
case 5:
APP_RunSpectrum();
break; break;
#endif #endif
@@ -327,7 +333,37 @@ void Main(void)
break; break;
} }
#endif #endif
*/
#ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
if (gEeprom.CURRENT_STATE == 2 || gEeprom.CURRENT_STATE == 5) {
gScanRangeStart = gScanRangeStart ? 0 : gTxVfo->pRX->Frequency;
gScanRangeStop = gEeprom.VfoInfo[!gEeprom.TX_VFO].freq_config_RX.Frequency;
if (gScanRangeStart > gScanRangeStop) {
SWAP(gScanRangeStart, gScanRangeStop);
}
}
if (gEeprom.CURRENT_STATE == 1) {
gEeprom.SCAN_LIST_DEFAULT = gEeprom.CURRENT_LIST;
}
if (gEeprom.CURRENT_STATE == 1 || gEeprom.CURRENT_STATE == 2) {
CHFRSCANNER_Start(true, SCAN_FWD);
}
#ifdef ENABLE_FMRADIO
else if (gEeprom.CURRENT_STATE == 3) {
ACTION_FM();
GUI_SelectNextDisplay(gRequestDisplayScreen);
}
#endif
#ifdef ENABLE_SPECTRUM
else if (gEeprom.CURRENT_STATE == 4 || gEeprom.CURRENT_STATE == 5) {
APP_RunSpectrum();
}
#endif
#endif
while (true) { while (true) {
APP_Update(); APP_Update();

7
misc.c
View File

@@ -119,7 +119,7 @@ enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx;
uint8_t gSetting_set_pwr = 1; uint8_t gSetting_set_pwr = 1;
bool gSetting_set_ptt = 0; bool gSetting_set_ptt = 0;
uint8_t gSetting_set_tot = 0; uint8_t gSetting_set_tot = 0;
uint8_t gSetting_set_ctr = 11; uint8_t gSetting_set_ctr = 10;
bool gSetting_set_inv = false; bool gSetting_set_inv = false;
uint8_t gSetting_set_eot = 0; uint8_t gSetting_set_eot = 0;
bool gSetting_set_lck = false; bool gSetting_set_lck = false;
@@ -130,7 +130,9 @@ enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx;
#endif #endif
bool gSetting_set_tmr = 0; bool gSetting_set_tmr = 0;
bool gSetting_set_ptt_session; bool gSetting_set_ptt_session;
uint8_t gDebug; #ifdef ENABLE_FEAT_F4HWN_DEBUG
uint8_t gDebug;
#endif
uint8_t gDW = 0; uint8_t gDW = 0;
uint8_t gCB = 0; uint8_t gCB = 0;
bool gSaveRxMode = false; bool gSaveRxMode = false;
@@ -308,6 +310,7 @@ uint8_t gIsLocked = 0xFF;
#ifdef ENABLE_FEAT_F4HWN #ifdef ENABLE_FEAT_F4HWN
bool gK5startup = true; bool gK5startup = true;
bool gBackLight = false; bool gBackLight = false;
bool gMute = false;
uint8_t gBacklightTimeOriginal; uint8_t gBacklightTimeOriginal;
uint8_t gBacklightBrightnessOld; uint8_t gBacklightBrightnessOld;
uint8_t gPttOnePushCounter = 0; uint8_t gPttOnePushCounter = 0;

5
misc.h
View File

@@ -183,7 +183,9 @@ extern enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx;
#endif #endif
extern bool gSetting_set_tmr; extern bool gSetting_set_tmr;
extern bool gSetting_set_ptt_session; extern bool gSetting_set_ptt_session;
extern uint8_t gDebug; #ifdef ENABLE_FEAT_F4HWN_DEBUG
extern uint8_t gDebug;
#endif
extern uint8_t gDW; extern uint8_t gDW;
extern uint8_t gCB; extern uint8_t gCB;
extern bool gSaveRxMode; extern bool gSaveRxMode;
@@ -377,6 +379,7 @@ extern volatile uint8_t boot_counter_10ms;
#ifdef ENABLE_FEAT_F4HWN #ifdef ENABLE_FEAT_F4HWN
extern bool gK5startup; extern bool gK5startup;
extern bool gBackLight; extern bool gBackLight;
extern bool gMute;
extern uint8_t gBacklightTimeOriginal; extern uint8_t gBacklightTimeOriginal;
extern uint8_t gBacklightBrightnessOld; extern uint8_t gBacklightBrightnessOld;
extern uint8_t gPttOnePushCounter; extern uint8_t gPttOnePushCounter;

16
radio.c
View File

@@ -572,6 +572,7 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
} }
*/ */
/*
for(uint8_t p = 0; p < 3; p++) for(uint8_t p = 0; p < 3; p++)
{ {
switch (currentPower) switch (currentPower)
@@ -599,6 +600,21 @@ void RADIO_ConfigureSquelchAndOutputPower(VFO_Info_t *pInfo)
break; break;
} }
} }
*/
static const uint8_t dividers[6] = { 25, 19, 13, 10, 7, 4};
for (uint8_t p = 0; p < 3; p++)
{
if (currentPower < 6)
{
Txp[p] = (Txp[p] * (currentPower == 5 ? 3 : 4)) / dividers[currentPower];
}
else // case 6
{
Txp[p] += 30;
}
}
#else #else
#ifdef ENABLE_REDUCE_LOW_MID_TX_POWER #ifdef ENABLE_REDUCE_LOW_MID_TX_POWER
// make low and mid even lower // make low and mid even lower

View File

@@ -77,13 +77,13 @@ void SETTINGS_InitEEPROM(void)
gEeprom.DUAL_WATCH = (Data[4] < 3) ? Data[4] : DUAL_WATCH_CHAN_A; gEeprom.DUAL_WATCH = (Data[4] < 3) ? Data[4] : DUAL_WATCH_CHAN_A;
gEeprom.BACKLIGHT_TIME = (Data[5] < 62) ? Data[5] : 12; gEeprom.BACKLIGHT_TIME = (Data[5] < 62) ? Data[5] : 12;
#ifdef ENABLE_FEAT_F4HWN_NARROWER #ifdef ENABLE_FEAT_F4HWN_NARROWER
gEeprom.TAIL_TONE_ELIMINATION = ((Data[6] & 0x01) < 2) ? (Data[6] & 0x01) : false; gEeprom.TAIL_TONE_ELIMINATION = Data[6] & 0x01;
gSetting_set_nfm = (((Data[6] >> 1) & 0x03) < 3) ? ((Data[6] >> 1) & 0x03) : 0; gSetting_set_nfm = (Data[6] >> 1) & 0x01;
#else #else
gEeprom.TAIL_TONE_ELIMINATION = (Data[6] < 2) ? Data[6] : false; gEeprom.TAIL_TONE_ELIMINATION = (Data[6] < 2) ? Data[6] : false;
#endif #endif
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
gEeprom.VFO_OPEN = Data[7] & 0x01; gEeprom.VFO_OPEN = Data[7] & 0x01;
gEeprom.CURRENT_STATE = (Data[7] >> 1) & 0x07; gEeprom.CURRENT_STATE = (Data[7] >> 1) & 0x07;
gEeprom.CURRENT_LIST = (Data[7] >> 4) & 0x07; gEeprom.CURRENT_LIST = (Data[7] >> 4) & 0x07;
@@ -326,17 +326,19 @@ void SETTINGS_InitEEPROM(void)
gMR_ChannelExclude[i] = false; gMR_ChannelExclude[i] = false;
} }
// 0F30..0F3F // 0F30..0F3F
EEPROM_ReadBuffer(0x0F30, gCustomAesKey, sizeof(gCustomAesKey)); EEPROM_ReadBuffer(0x0F30, gCustomAesKey, sizeof(gCustomAesKey));
bHasCustomAesKey = false; bHasCustomAesKey = false;
for (unsigned int i = 0; i < ARRAY_SIZE(gCustomAesKey); i++) #ifndef ENABLE_FEAT_F4HWN
{ for (unsigned int i = 0; i < ARRAY_SIZE(gCustomAesKey); i++)
if (gCustomAesKey[i] != 0xFFFFFFFFu) {
{ if (gCustomAesKey[i] != 0xFFFFFFFFu)
bHasCustomAesKey = true; {
return; bHasCustomAesKey = true;
} return;
} }
}
#endif
#ifdef ENABLE_FEAT_F4HWN #ifdef ENABLE_FEAT_F4HWN
// 1FF0..0x1FF7 // 1FF0..0x1FF7
@@ -361,13 +363,21 @@ void SETTINGS_InitEEPROM(void)
int tmp = (Data[5] & 0xF0) >> 4; int tmp = (Data[5] & 0xF0) >> 4;
#ifdef ENABLE_FEAT_F4HWN_INV
gSetting_set_inv = (tmp >> 0) & 0x01; gSetting_set_inv = (tmp >> 0) & 0x01;
#else
gSetting_set_inv = 0;
#endif
gSetting_set_lck = (tmp >> 1) & 0x01; gSetting_set_lck = (tmp >> 1) & 0x01;
gSetting_set_met = (tmp >> 2) & 0x01; gSetting_set_met = (tmp >> 2) & 0x01;
gSetting_set_gui = (tmp >> 3) & 0x01; gSetting_set_gui = (tmp >> 3) & 0x01;
#ifdef ENABLE_FEAT_F4HWN_CTR
int ctr_value = Data[5] & 0x0F; int ctr_value = Data[5] & 0x0F;
gSetting_set_ctr = (ctr_value > 0 && ctr_value < 16) ? ctr_value : 10; gSetting_set_ctr = (ctr_value > 0 && ctr_value < 16) ? ctr_value : 10;
#else
gSetting_set_ctr = 10;
#endif
gSetting_set_tmr = Data[4] & 0x01; gSetting_set_tmr = Data[4] & 0x01;
#ifdef ENABLE_FEAT_F4HWN_SLEEP #ifdef ENABLE_FEAT_F4HWN_SLEEP
@@ -434,6 +444,10 @@ void SETTINGS_LoadCalibration(void)
gEeprom.VOLUME_GAIN = (Misc.VOLUME_GAIN < 64) ? Misc.VOLUME_GAIN : 58; gEeprom.VOLUME_GAIN = (Misc.VOLUME_GAIN < 64) ? Misc.VOLUME_GAIN : 58;
gEeprom.DAC_GAIN = (Misc.DAC_GAIN < 16) ? Misc.DAC_GAIN : 8; gEeprom.DAC_GAIN = (Misc.DAC_GAIN < 16) ? Misc.DAC_GAIN : 8;
#ifdef ENABLE_FEAT_F4HWN
gEeprom.VOLUME_GAIN_BACKUP = gEeprom.VOLUME_GAIN;
#endif
BK4819_WriteRegister(BK4819_REG_3B, 22656 + gEeprom.BK4819_XTAL_FREQ_LOW); BK4819_WriteRegister(BK4819_REG_3B, 22656 + gEeprom.BK4819_XTAL_FREQ_LOW);
// BK4819_WriteRegister(BK4819_REG_3C, gEeprom.BK4819_XTAL_FREQ_HIGH); // BK4819_WriteRegister(BK4819_REG_3C, gEeprom.BK4819_XTAL_FREQ_HIGH);
} }
@@ -643,7 +657,7 @@ void SETTINGS_SaveSettings(void)
State[6] = gEeprom.TAIL_TONE_ELIMINATION; State[6] = gEeprom.TAIL_TONE_ELIMINATION;
#endif #endif
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
State[7] = (gEeprom.VFO_OPEN & 0x01) | ((gEeprom.CURRENT_STATE & 0x07) << 1) | ((gEeprom.SCAN_LIST_DEFAULT & 0x07) << 4); State[7] = (gEeprom.VFO_OPEN & 0x01) | ((gEeprom.CURRENT_STATE & 0x07) << 1) | ((gEeprom.SCAN_LIST_DEFAULT & 0x07) << 4);
#else #else
State[7] = gEeprom.VFO_OPEN; State[7] = gEeprom.VFO_OPEN;
@@ -1006,7 +1020,7 @@ State[1] = 0
EEPROM_WriteBuffer(0x1FF0, State); EEPROM_WriteBuffer(0x1FF0, State);
} }
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
void SETTINGS_WriteCurrentState(void) void SETTINGS_WriteCurrentState(void)
{ {
uint8_t State[8]; uint8_t State[8];

View File

@@ -117,10 +117,15 @@ enum ACTION_OPT_t {
ACTION_OPT_PTT, ACTION_OPT_PTT,
ACTION_OPT_WN, ACTION_OPT_WN,
ACTION_OPT_BACKLIGHT, ACTION_OPT_BACKLIGHT,
ACTION_OPT_MUTE,
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS #ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
ACTION_OPT_POWER_HIGH, ACTION_OPT_POWER_HIGH,
ACTION_OPT_REMOVE_OFFSET, ACTION_OPT_REMOVE_OFFSET,
#endif #endif
#endif
#ifdef ENABLE_REGA
ACTION_OPT_REGA_ALARM,
ACTION_OPT_REGA_TEST,
#endif #endif
ACTION_OPT_LEN ACTION_OPT_LEN
}; };
@@ -212,7 +217,7 @@ typedef struct {
bool SCAN_LIST_ENABLED[3]; bool SCAN_LIST_ENABLED[3];
uint8_t SCANLIST_PRIORITY_CH1[3]; uint8_t SCANLIST_PRIORITY_CH1[3];
uint8_t SCANLIST_PRIORITY_CH2[3]; uint8_t SCANLIST_PRIORITY_CH2[3];
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
uint8_t CURRENT_STATE; uint8_t CURRENT_STATE;
uint8_t CURRENT_LIST; uint8_t CURRENT_LIST;
#endif #endif
@@ -272,6 +277,9 @@ typedef struct {
bool NOAA_AUTO_SCAN; bool NOAA_AUTO_SCAN;
#endif #endif
uint8_t VOLUME_GAIN; uint8_t VOLUME_GAIN;
#ifdef ENABLE_FEAT_F4HWN
uint8_t VOLUME_GAIN_BACKUP;
#endif
uint8_t DAC_GAIN; uint8_t DAC_GAIN;
VFO_Info_t VfoInfo[2]; VFO_Info_t VfoInfo[2];
@@ -313,7 +321,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const VFO_Info_t *pVFO,
void SETTINGS_SaveBatteryCalibration(const uint16_t * batteryCalibration); void SETTINGS_SaveBatteryCalibration(const uint16_t * batteryCalibration);
void SETTINGS_UpdateChannel(uint8_t channel, const VFO_Info_t *pVFO, bool keep, bool check, bool save); void SETTINGS_UpdateChannel(uint8_t channel, const VFO_Info_t *pVFO, bool keep, bool check, bool save);
void SETTINGS_WriteBuildOptions(void); void SETTINGS_WriteBuildOptions(void);
#ifdef ENABLE_FEAT_F4HWN_RESTORE_SCAN #ifdef ENABLE_FEAT_F4HWN_RESUME_STATE
void SETTINGS_WriteCurrentState(void); void SETTINGS_WriteCurrentState(void);
#endif #endif
#ifdef ENABLE_FEAT_F4HWN_VOL #ifdef ENABLE_FEAT_F4HWN_VOL

View File

@@ -110,6 +110,7 @@ void UI_PrintStringSmall(const char *pString, uint8_t Start, uint8_t End, uint8_
UI_PrintStringBuffer(pString, gFrameBuffer[Line] + Start, char_width, font); UI_PrintStringBuffer(pString, gFrameBuffer[Line] + Start, char_width, font);
} }
void UI_PrintStringSmallNormal(const char *pString, uint8_t Start, uint8_t End, uint8_t Line) void UI_PrintStringSmallNormal(const char *pString, uint8_t Start, uint8_t End, uint8_t Line)
{ {
UI_PrintStringSmall(pString, Start, End, Line, ARRAY_SIZE(gFontSmall[0]), (const uint8_t *)gFontSmall); UI_PrintStringSmall(pString, Start, End, Line, ARRAY_SIZE(gFontSmall[0]), (const uint8_t *)gFontSmall);
@@ -180,6 +181,46 @@ void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center)
} }
} }
/*
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;
if (center) {
uint8_t len = 0;
for (const char *ptr = string; *ptr; ptr++)
if (*ptr != ' ') len++; // Ignores spaces for centering
X -= (len * char_width) / 2; // Centering adjustment
pFb0 = gFrameBuffer[Y] + X;
pFb1 = pFb0 + 128;
}
for (; *string; string++) {
char c = *string;
if (c == '-') c = '9' + 1; // Remap of '-' symbol
if (bCanDisplay || c != ' ') {
bCanDisplay = true;
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 == '.') {
memset(pFb1, 0x60, 3); // Replaces the three assignments
pFb0 += 3;
pFb1 += 3;
continue;
}
}
pFb0 += char_width;
pFb1 += char_width;
}
}
*/
void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black) void UI_DrawPixelBuffer(uint8_t (*buffer)[128], uint8_t x, uint8_t y, bool black)
{ {
const uint8_t pattern = 1 << (y % 8); const uint8_t pattern = 1 << (y % 8);

View File

@@ -1213,15 +1213,18 @@ void UI_DisplayMain(void)
if (gSetting_set_gui) if (gSetting_set_gui)
{ {
const char pwr_short[][3] = {"L1", "L2", "L3", "L4", "L5", "M", "H"}; const char pwr_short[][3] = {"L1", "L2", "L3", "L4", "L5", "M", "H"};
sprintf(String, "%s", pwr_short[currentPower]); //sprintf(String, "%s", pwr_short[currentPower]);
UI_PrintStringSmallNormal(String, LCD_WIDTH + 42, 0, line + 1); //UI_PrintStringSmallNormal(String, LCD_WIDTH + 42, 0, line + 1);
UI_PrintStringSmallNormal(pwr_short[currentPower], LCD_WIDTH + 42, 0, line + 1);
arrowPos = 38; arrowPos = 38;
} }
else else
{ {
const char pwr_long[][5] = {"LOW1", "LOW2", "LOW3", "LOW4", "LOW5", "MID", "HIGH"}; const char pwr_long[][5] = {"LOW1", "LOW2", "LOW3", "LOW4", "LOW5", "MID", "HIGH"};
sprintf(String, "%s", pwr_long[currentPower]); //sprintf(String, "%s", pwr_long[currentPower]);
GUI_DisplaySmallest(String, 24, line == 0 ? 17 : 49, false, true); //GUI_DisplaySmallest(String, 24, line == 0 ? 17 : 49, false, true);
GUI_DisplaySmallest(pwr_long[currentPower], 24, line == 0 ? 17 : 49, false, true);
} }
if(userPower == true) if(userPower == true)
@@ -1364,15 +1367,15 @@ void UI_DisplayMain(void)
*/ */
if (isMainVFO) { if (isMainVFO) {
if (gMonitor) { if (gMonitor) {
sprintf(String, "MONI"); strcpy(String, "MONI");
} else { } else {
sprintf(String, "SQL%d", gEeprom.SQUELCH_LEVEL); sprintf(String, "SQL%d", gEeprom.SQUELCH_LEVEL);
} }
if (gSetting_set_gui) { if (gSetting_set_gui) {
UI_PrintStringSmallNormal(String, LCD_WIDTH + 98, 0, line + 1); UI_PrintStringSmallNormal(String, LCD_WIDTH + 98, 0, line + 1);
} else { } else {
GUI_DisplaySmallest(String, 110, line == 0 ? 17 : 49, false, true); GUI_DisplaySmallest(String, 110, line == 0 ? 17 : 49, false, true);
} }
} }
#endif #endif

166
ui/menu.c
View File

@@ -86,9 +86,7 @@ const t_menu_item MenuList[] =
{"BatSav", MENU_SAVE }, // was "SAVE" {"BatSav", MENU_SAVE }, // was "SAVE"
{"BatTxt", MENU_BAT_TXT }, {"BatTxt", MENU_BAT_TXT },
{"Mic", MENU_MIC }, {"Mic", MENU_MIC },
#ifdef ENABLE_AUDIO_BAR
{"MicBar", MENU_MIC_BAR }, {"MicBar", MENU_MIC_BAR },
#endif
{"ChDisp", MENU_MDF }, // was "MDF" {"ChDisp", MENU_MDF }, // was "MDF"
{"POnMsg", MENU_PONMSG }, {"POnMsg", MENU_PONMSG },
{"BLTime", MENU_ABR }, // was "ABR" {"BLTime", MENU_ABR }, // was "ABR"
@@ -128,9 +126,7 @@ const t_menu_item MenuList[] =
{"AM Fix", MENU_AM_FIX }, {"AM Fix", MENU_AM_FIX },
#endif #endif
#endif #endif
#ifdef ENABLE_VOX
{"VOX", MENU_VOX }, {"VOX", MENU_VOX },
#endif
#ifdef ENABLE_FEAT_F4HWN #ifdef ENABLE_FEAT_F4HWN
{"SysInf", MENU_VOL }, // was "VOL" {"SysInf", MENU_VOL }, // was "VOL"
#else #else
@@ -143,9 +139,7 @@ const t_menu_item MenuList[] =
{"SetPTT", MENU_SET_PTT }, {"SetPTT", MENU_SET_PTT },
{"SetTOT", MENU_SET_TOT }, {"SetTOT", MENU_SET_TOT },
{"SetEOT", MENU_SET_EOT }, {"SetEOT", MENU_SET_EOT },
#ifdef ENABLE_FEAT_F4HWN_CONTRAST
{"SetCtr", MENU_SET_CTR }, {"SetCtr", MENU_SET_CTR },
#endif
{"SetInv", MENU_SET_INV }, {"SetInv", MENU_SET_INV },
{"SetLck", MENU_SET_LCK }, {"SetLck", MENU_SET_LCK },
{"SetMet", MENU_SET_MET }, {"SetMet", MENU_SET_MET },
@@ -222,6 +216,11 @@ const char gSubMenu_OFF_ON[][4] =
"ON" "ON"
}; };
const char gSubMenu_NA[4] =
{
"N/A"
};
const char* const gSubMenu_RXMode[] = const char* const gSubMenu_RXMode[] =
{ {
"MAIN\nONLY", // TX and RX on main only "MAIN\nONLY", // TX and RX on main only
@@ -438,6 +437,10 @@ const t_sidefunction gSubMenu_SIDEFUNCTIONS[] =
#endif #endif
#ifdef ENABLE_TX1750 #ifdef ENABLE_TX1750
{"1750Hz", ACTION_OPT_1750}, {"1750Hz", ACTION_OPT_1750},
#endif
#ifdef ENABLE_REGA
{"REGA\nALARM", ACTION_OPT_REGA_ALARM},
{"REGA\nTEST", ACTION_OPT_REGA_TEST},
#endif #endif
{"LOCK\nKEYPAD", ACTION_OPT_KEYLOCK}, {"LOCK\nKEYPAD", ACTION_OPT_KEYLOCK},
{"VFO A\nVFO B", ACTION_OPT_A_B}, {"VFO A\nVFO B", ACTION_OPT_A_B},
@@ -451,6 +454,9 @@ const t_sidefunction gSubMenu_SIDEFUNCTIONS[] =
{"MAIN ONLY", ACTION_OPT_MAINONLY}, {"MAIN ONLY", ACTION_OPT_MAINONLY},
{"PTT", ACTION_OPT_PTT}, {"PTT", ACTION_OPT_PTT},
{"WIDE\nNARROW", ACTION_OPT_WN}, {"WIDE\nNARROW", ACTION_OPT_WN},
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
{"MUTE", ACTION_OPT_MUTE},
#endif
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS #ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
{"POWER\nHIGH", ACTION_OPT_POWER_HIGH}, {"POWER\nHIGH", ACTION_OPT_POWER_HIGH},
{"REMOVE\nOFFSET", ACTION_OPT_REMOVE_OFFSET}, {"REMOVE\nOFFSET", ACTION_OPT_REMOVE_OFFSET},
@@ -598,6 +604,12 @@ void UI_DisplayMenu(void)
BACKLIGHT_TurnOn(); BACKLIGHT_TurnOn();
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
uint8_t gaugeLine = 0;
uint8_t gaugeMin = 0;
uint8_t gaugeMax = 0;
#endif
switch (UI_MENU_GetCurrentMenuId()) switch (UI_MENU_GetCurrentMenuId())
{ {
case MENU_SQL: case MENU_SQL:
@@ -611,11 +623,13 @@ void UI_DisplayMenu(void)
} }
break; break;
#ifdef ENABLE_AUDIO_BAR case MENU_MIC_BAR:
case MENU_MIC_BAR: #ifdef ENABLE_AUDIO_BAR
strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]);
break; #else
#endif strcpy(String, gSubMenu_NA);
#endif
break;
case MENU_STEP: { case MENU_STEP: {
uint16_t step = gStepFrequencyTable[FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection)]; uint16_t step = gStepFrequencyTable[FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection)];
@@ -637,7 +651,7 @@ void UI_DisplayMenu(void)
case MENU_R_DCS: case MENU_R_DCS:
case MENU_T_DCS: case MENU_T_DCS:
if (gSubMenuSelection == 0) if (gSubMenuSelection == 0)
strcpy(String, "OFF"); strcpy(String, gSubMenu_OFF_ON[0]);
else if (gSubMenuSelection < 105) else if (gSubMenuSelection < 105)
sprintf(String, "D%03oN", DCS_Options[gSubMenuSelection - 1]); sprintf(String, "D%03oN", DCS_Options[gSubMenuSelection - 1]);
else else
@@ -648,7 +662,7 @@ void UI_DisplayMenu(void)
case MENU_T_CTCS: case MENU_T_CTCS:
{ {
if (gSubMenuSelection == 0) if (gSubMenuSelection == 0)
strcpy(String, "OFF"); strcpy(String, gSubMenu_OFF_ON[0]);
else else
sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10); sprintf(String, "%u.%uHz", CTCSS_Options[gSubMenuSelection - 1] / 10, CTCSS_Options[gSubMenuSelection - 1] % 10);
break; break;
@@ -692,25 +706,32 @@ void UI_DisplayMenu(void)
break; break;
#endif #endif
#ifdef ENABLE_VOX case MENU_VOX:
case MENU_VOX: #ifdef ENABLE_VOX
sprintf(String, gSubMenuSelection == 0 ? "OFF" : "%u", gSubMenuSelection); sprintf(String, gSubMenuSelection == 0 ? gSubMenu_OFF_ON[0] : "%u", gSubMenuSelection);
break; #else
#endif strcpy(String, gSubMenu_NA);
#endif
break;
case MENU_ABR: case MENU_ABR:
if(gSubMenuSelection == 0) if(gSubMenuSelection == 0)
{ {
sprintf(String, "%s", "OFF"); strcpy(String, gSubMenu_OFF_ON[0]);
} }
else if(gSubMenuSelection < 61) else if(gSubMenuSelection < 61)
{ {
sprintf(String, "%02dm:%02ds", (((gSubMenuSelection) * 5) / 60), (((gSubMenuSelection) * 5) % 60)); sprintf(String, "%02dm:%02ds", (((gSubMenuSelection) * 5) / 60), (((gSubMenuSelection) * 5) % 60));
ST7565_Gauge(4, 1, 60, gSubMenuSelection); #if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
//ST7565_Gauge(4, 1, 60, gSubMenuSelection);
gaugeLine = 4;
gaugeMin = 1;
gaugeMax = 60;
#endif
} }
else else
{ {
sprintf(String, "%s", "ON"); strcpy(String, "ON");
} }
// Obsolete ??? // Obsolete ???
@@ -734,11 +755,16 @@ void UI_DisplayMenu(void)
case MENU_AUTOLK: case MENU_AUTOLK:
if (gSubMenuSelection == 0) if (gSubMenuSelection == 0)
strcpy(String, "OFF"); strcpy(String, gSubMenu_OFF_ON[0]);
else else
{ {
sprintf(String, "%02dm:%02ds", ((gSubMenuSelection * 15) / 60), ((gSubMenuSelection * 15) % 60)); sprintf(String, "%02dm:%02ds", ((gSubMenuSelection * 15) / 60), ((gSubMenuSelection * 15) % 60));
ST7565_Gauge(4, 1, 40, gSubMenuSelection); #if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
//ST7565_Gauge(4, 1, 40, gSubMenuSelection);
gaugeLine = 4;
gaugeMin = 1;
gaugeMax = 40;
#endif
} }
break; break;
@@ -844,7 +870,7 @@ void UI_DisplayMenu(void)
} }
case MENU_SAVE: case MENU_SAVE:
sprintf(String, gSubMenuSelection == 0 ? "OFF" : "1:%u", gSubMenuSelection); sprintf(String, gSubMenuSelection == 0 ? gSubMenu_OFF_ON[0] : "1:%u", gSubMenuSelection);
break; break;
case MENU_TDR: case MENU_TDR:
@@ -853,7 +879,12 @@ void UI_DisplayMenu(void)
case MENU_TOT: case MENU_TOT:
sprintf(String, "%02dm:%02ds", (((gSubMenuSelection + 1) * 5) / 60), (((gSubMenuSelection + 1) * 5) % 60)); sprintf(String, "%02dm:%02ds", (((gSubMenuSelection + 1) * 5) / 60), (((gSubMenuSelection + 1) * 5) % 60));
ST7565_Gauge(4, 5, 179, gSubMenuSelection); #if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
//ST7565_Gauge(4, 5, 179, gSubMenuSelection);
gaugeLine = 4;
gaugeMin = 5;
gaugeMax = 179;
#endif
break; break;
#ifdef ENABLE_VOICE #ifdef ENABLE_VOICE
@@ -870,12 +901,22 @@ void UI_DisplayMenu(void)
else if(gSubMenuSelection < 81) else if(gSubMenuSelection < 81)
{ {
sprintf(String, "CARRIER\n%02ds:%03dms", ((gSubMenuSelection * 250) / 1000), ((gSubMenuSelection * 250) % 1000)); sprintf(String, "CARRIER\n%02ds:%03dms", ((gSubMenuSelection * 250) / 1000), ((gSubMenuSelection * 250) % 1000));
ST7565_Gauge(5, 1, 80, gSubMenuSelection); #if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
//ST7565_Gauge(5, 1, 80, gSubMenuSelection);
gaugeLine = 5;
gaugeMin = 1;
gaugeMax = 80;
#endif
} }
else else
{ {
sprintf(String, "TIMEOUT\n%02dm:%02ds", (((gSubMenuSelection - 80) * 5) / 60), (((gSubMenuSelection - 80) * 5) % 60)); sprintf(String, "TIMEOUT\n%02dm:%02ds", (((gSubMenuSelection - 80) * 5) / 60), (((gSubMenuSelection - 80) * 5) % 60));
ST7565_Gauge(5, 80, 104, gSubMenuSelection); #if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
//ST7565_Gauge(5, 80, 104, gSubMenuSelection);
gaugeLine = 5;
gaugeMin = 80;
gaugeMax = 104;
#endif
} }
break; break;
@@ -884,7 +925,7 @@ void UI_DisplayMenu(void)
break; break;
case MENU_RP_STE: case MENU_RP_STE:
sprintf(String, gSubMenuSelection == 0 ? "OFF" : "%u*100ms", gSubMenuSelection); sprintf(String, gSubMenuSelection == 0 ? gSubMenu_OFF_ON[0] : "%u*100ms", gSubMenuSelection);
break; break;
case MENU_S_LIST: case MENU_S_LIST:
@@ -1022,12 +1063,17 @@ void UI_DisplayMenu(void)
case MENU_SET_OFF: case MENU_SET_OFF:
if(gSubMenuSelection == 0) if(gSubMenuSelection == 0)
{ {
sprintf(String, "%s", "OFF"); strcpy(String, gSubMenu_OFF_ON[0]);
} }
else if(gSubMenuSelection < 121) else if(gSubMenuSelection < 121)
{ {
sprintf(String, "%dh:%02dm", (gSubMenuSelection / 60), (gSubMenuSelection % 60)); sprintf(String, "%dh:%02dm", (gSubMenuSelection / 60), (gSubMenuSelection % 60));
ST7565_Gauge(4, 1, 120, gSubMenuSelection); #if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
//ST7565_Gauge(4, 1, 120, gSubMenuSelection);
gaugeLine = 4;
gaugeMin = 1;
gaugeMax = 120;
#endif
} }
break; break;
#endif #endif
@@ -1046,17 +1092,23 @@ void UI_DisplayMenu(void)
strcpy(String, gSubMenu_SET_TOT[gSubMenuSelection]); // Same as SET_TOT strcpy(String, gSubMenu_SET_TOT[gSubMenuSelection]); // Same as SET_TOT
break; break;
#ifdef ENABLE_FEAT_F4HWN_CONTRAST
case MENU_SET_CTR: case MENU_SET_CTR:
sprintf(String, "%d", gSubMenuSelection); #ifdef ENABLE_FEAT_F4HWN_CTR
gSetting_set_ctr = gSubMenuSelection; sprintf(String, "%d", gSubMenuSelection);
ST7565_ContrastAndInv(); gSetting_set_ctr = gSubMenuSelection;
ST7565_ContrastAndInv();
#else
strcpy(String, gSubMenu_NA);
#endif
break; break;
#endif
case MENU_SET_INV: case MENU_SET_INV:
strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); #ifdef ENABLE_FEAT_F4HWN_INV
ST7565_ContrastAndInv(); strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]);
ST7565_ContrastAndInv();
#else
strcpy(String, gSubMenu_NA);
#endif
break; break;
case MENU_TX_LOCK: case MENU_TX_LOCK:
@@ -1087,7 +1139,20 @@ void UI_DisplayMenu(void)
#ifdef ENABLE_FEAT_F4HWN_VOL #ifdef ENABLE_FEAT_F4HWN_VOL
case MENU_SET_VOL: case MENU_SET_VOL:
sprintf(String, gSubMenuSelection == 0 ? "OFF" : "%02u", gSubMenuSelection); if(gSubMenuSelection == 0)
{
strcpy(String, gSubMenu_OFF_ON[0]);
}
else if(gSubMenuSelection < 64)
{
sprintf(String, "%02u", gSubMenuSelection);
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
//ST7565_Gauge(4, 1, 63, gSubMenuSelection);
gaugeLine = 4;
gaugeMin = 1;
gaugeMax = 63;
#endif
}
gEeprom.VOLUME_GAIN = gSubMenuSelection; gEeprom.VOLUME_GAIN = gSubMenuSelection;
BK4819_WriteRegister(BK4819_REG_48, BK4819_WriteRegister(BK4819_REG_48,
(11u << 12) | // ??? .. 0 ~ 15, doesn't seem to make any difference (11u << 12) | // ??? .. 0 ~ 15, doesn't seem to make any difference
@@ -1106,6 +1171,13 @@ void UI_DisplayMenu(void)
} }
#if !defined(ENABLE_SPECTRUM) || !defined(ENABLE_FMRADIO)
if(gaugeLine != 0)
{
ST7565_Gauge(gaugeLine, gaugeMin, gaugeMax, gSubMenuSelection);
}
#endif
if (!already_printed) if (!already_printed)
{ // we now do multi-line text in a single string { // we now do multi-line text in a single string
@@ -1134,10 +1206,14 @@ void UI_DisplayMenu(void)
} }
// center vertically'ish // center vertically'ish
/*
if (small) if (small)
y = 3 - ((lines + 0) / 2); // untested y = 3 - ((lines + 0) / 2); // untested
else else
y = 2 - ((lines + 0) / 2); y = 2 - ((lines + 0) / 2);
*/
y = (small ? 3 : 2) - (lines / 2);
// only for SysInf // only for SysInf
if(UI_MENU_GetCurrentMenuId() == MENU_VOL) if(UI_MENU_GetCurrentMenuId() == MENU_VOL)
@@ -1150,7 +1226,7 @@ void UI_DisplayMenu(void)
UI_PrintStringSmallNormal(edit, 54, 127, 1); UI_PrintStringSmallNormal(edit, 54, 127, 1);
#if defined(ENABLE_SPECTRUM) && defined(ENABLE_FMRADIO) #if defined(ENABLE_SPECTRUM) && defined(ENABLE_FMRADIO)
UI_PrintStringSmallNormal("Voxless", 54, 127, 6); UI_PrintStringSmallNormal("Basic", 54, 127, 6);
#elif defined(ENABLE_SPECTRUM) #elif defined(ENABLE_SPECTRUM)
UI_PrintStringSmallNormal("Bandscope", 54, 127, 6); UI_PrintStringSmallNormal("Bandscope", 54, 127, 6);
#elif defined(ENABLE_FMRADIO) #elif defined(ENABLE_FMRADIO)
@@ -1206,6 +1282,7 @@ void UI_DisplayMenu(void)
if (gSubMenuSelection < 0 || !gEeprom.SCAN_LIST_ENABLED[i]) { if (gSubMenuSelection < 0 || !gEeprom.SCAN_LIST_ENABLED[i]) {
UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 2, 8); UI_PrintString(pPrintStr, menu_item_x1, menu_item_x2, 2, 8);
} else { } else {
/*
UI_PrintStringSmallNormal(pPrintStr, menu_item_x1, menu_item_x2, 2); UI_PrintStringSmallNormal(pPrintStr, menu_item_x1, menu_item_x2, 2);
if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH1[i])) { if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH1[i])) {
@@ -1217,6 +1294,19 @@ void UI_DisplayMenu(void)
sprintf(String, "PRI%d:%u", 2, gEeprom.SCANLIST_PRIORITY_CH2[i] + 1); sprintf(String, "PRI%d:%u", 2, gEeprom.SCANLIST_PRIORITY_CH2[i] + 1);
UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8); UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8);
} }
*/
UI_PrintStringSmallNormal(pPrintStr, menu_item_x1, menu_item_x2, 2);
for (uint8_t pri = 1; pri <= 2; pri++) {
uint8_t channel = (pri == 1) ? gEeprom.SCANLIST_PRIORITY_CH1[i] : gEeprom.SCANLIST_PRIORITY_CH2[i];
if (IS_MR_CHANNEL(channel)) {
sprintf(String, "PRI%d:%u", pri, channel + 1);
UI_PrintString(String, menu_item_x1, menu_item_x2, pri * 2 + 1, 8);
}
}
} }
} }

View File

@@ -53,9 +53,7 @@ enum
MENU_MEM_NAME, MENU_MEM_NAME,
MENU_MDF, MENU_MDF,
MENU_SAVE, MENU_SAVE,
#ifdef ENABLE_VOX
MENU_VOX, MENU_VOX,
#endif
MENU_ABR, MENU_ABR,
MENU_ABR_ON_TX_RX, MENU_ABR_ON_TX_RX,
MENU_ABR_MIN, MENU_ABR_MIN,
@@ -73,9 +71,7 @@ enum
MENU_STE, MENU_STE,
MENU_RP_STE, MENU_RP_STE,
MENU_MIC, MENU_MIC,
#ifdef ENABLE_AUDIO_BAR
MENU_MIC_BAR, MENU_MIC_BAR,
#endif
MENU_COMPAND, MENU_COMPAND,
MENU_1_CALL, MENU_1_CALL,
MENU_S_LIST, MENU_S_LIST,
@@ -172,6 +168,7 @@ extern const char gSubMenu_TXP[8][6];
extern const char gSubMenu_SFT_D[3][4]; extern const char gSubMenu_SFT_D[3][4];
extern const char gSubMenu_W_N[2][7]; extern const char gSubMenu_W_N[2][7];
extern const char gSubMenu_OFF_ON[2][4]; extern const char gSubMenu_OFF_ON[2][4];
extern const char gSubMenu_NA[4];
extern const char gSubMenu_TOT[11][7]; extern const char gSubMenu_TOT[11][7];
extern const char* const gSubMenu_RXMode[4]; extern const char* const gSubMenu_RXMode[4];

View File

@@ -35,6 +35,7 @@
#include "ui/status.h" #include "ui/status.h"
#ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER
#ifndef ENABLE_FEAT_F4HWN_DEBUG
static void convertTime(uint8_t *line, uint8_t type) static void convertTime(uint8_t *line, uint8_t type)
{ {
uint16_t t = (type == 0) ? (gTxTimerCountdown_500ms / 2) : (3600 - gRxTimerCountdown_500ms / 2); uint16_t t = (type == 0) ? (gTxTimerCountdown_500ms / 2) : (3600 - gRxTimerCountdown_500ms / 2);
@@ -51,6 +52,7 @@ static void convertTime(uint8_t *line, uint8_t type)
gUpdateStatus = true; gUpdateStatus = true;
} }
#endif #endif
#endif
void UI_DisplayStatus() void UI_DisplayStatus()
{ {
@@ -122,28 +124,23 @@ void UI_DisplayStatus()
} }
x += 10; // font character width x += 10; // font character width
// Only for debug #ifdef ENABLE_FEAT_F4HWN_DEBUG
// Only for debug // Only for debug
// Only for debug // Only for debug
// Only for debug
bool debug = false;
if(debug)
{
sprintf(str, "%d", gDebug); sprintf(str, "%d", gDebug);
UI_PrintStringSmallBufferNormal(str, line + x + 1); UI_PrintStringSmallBufferNormal(str, line + x + 1);
x += 16; x += 16;
} #else
else #ifdef ENABLE_VOICE
{
#ifdef ENABLE_VOICE
// VOICE indicator // VOICE indicator
if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF){ if (gEeprom.VOICE_PROMPT != VOICE_PROMPT_OFF){
memcpy(line + x, BITMAP_VoicePrompt, sizeof(BITMAP_VoicePrompt)); memcpy(line + x, BITMAP_VoicePrompt, sizeof(BITMAP_VoicePrompt));
x1 = x + sizeof(BITMAP_VoicePrompt); x1 = x + sizeof(BITMAP_VoicePrompt);
} }
x += sizeof(BITMAP_VoicePrompt); x += sizeof(BITMAP_VoicePrompt);
#endif #endif
if(!SCANNER_IsScanning()) { if(!SCANNER_IsScanning()) {
#ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER #ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER
@@ -185,7 +182,7 @@ void UI_DisplayStatus()
} }
} }
x += sizeof(gFontDWR) + 3; x += sizeof(gFontDWR) + 3;
} #endif
#ifdef ENABLE_VOX #ifdef ENABLE_VOX
// VOX indicator // VOX indicator
@@ -212,30 +209,47 @@ void UI_DisplayStatus()
x = MAX(x1, 69u); x = MAX(x1, 69u);
// KEY-LOCK indicator const void *src = NULL; // Pointer to the font/bitmap to copy
size_t size = 0; // Size of the font/bitmap
// Determine the source and size based on conditions
if (gEeprom.KEY_LOCK) { if (gEeprom.KEY_LOCK) {
memcpy(line + x + 1, gFontKeyLock, sizeof(gFontKeyLock)); src = gFontKeyLock;
size = sizeof(gFontKeyLock);
} }
else if (gWasFKeyPressed) { else if (gWasFKeyPressed) {
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS #ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
if(gEeprom.MENU_LOCK == false) { if (!gEeprom.MENU_LOCK) {
memcpy(line + x + 1, gFontF, sizeof(gFontF)); src = gFontF;
} size = sizeof(gFontF);
}
#else #else
memcpy(line + x + 1, gFontF, sizeof(gFontF)); src = gFontF;
size = sizeof(gFontF);
#endif #endif
} }
else if (gBackLight) #ifdef ENABLE_FEAT_F4HWN
{ else if (gMute) {
memcpy(line + x + 1, gFontLight, sizeof(gFontLight)); src = gFontMute;
size = sizeof(gFontMute);
}
#endif
else if (gBackLight) {
src = gFontLight;
size = sizeof(gFontLight);
} }
#ifdef ENABLE_FEAT_F4HWN_CHARGING_C #ifdef ENABLE_FEAT_F4HWN_CHARGING_C
else if (gChargingWithTypeC) else if (gChargingWithTypeC) {
{ src = BITMAP_USB_C;
memcpy(line + x + 1, BITMAP_USB_C, sizeof(BITMAP_USB_C)); size = sizeof(BITMAP_USB_C);
} }
#endif #endif
// Perform the memcpy if a source was selected
if (src) {
memcpy(line + x + 1, src, size);
}
// Battery // Battery
unsigned int x2 = LCD_WIDTH - sizeof(BITMAP_BatteryLevel1) - 0; unsigned int x2 = LCD_WIDTH - sizeof(BITMAP_BatteryLevel1) - 0;

View File

@@ -30,6 +30,9 @@
#ifdef ENABLE_FMRADIO #ifdef ENABLE_FMRADIO
#include "ui/fmradio.h" #include "ui/fmradio.h"
#endif #endif
#ifdef ENABLE_REGA
#include "app/rega.h"
#endif
#include "ui/inputbox.h" #include "ui/inputbox.h"
#include "ui/main.h" #include "ui/main.h"
#include "ui/menu.h" #include "ui/menu.h"
@@ -57,6 +60,10 @@ void (*UI_DisplayFunctions[])(void) = {
#ifdef ENABLE_AIRCOPY #ifdef ENABLE_AIRCOPY
[DISPLAY_AIRCOPY] = &UI_DisplayAircopy, [DISPLAY_AIRCOPY] = &UI_DisplayAircopy,
#endif #endif
#ifdef ENABLE_REGA
[DISPLAY_REGA] = &UI_DisplayREGA,
#endif
}; };
static_assert(ARRAY_SIZE(UI_DisplayFunctions) == DISPLAY_N_ELEM); static_assert(ARRAY_SIZE(UI_DisplayFunctions) == DISPLAY_N_ELEM);

View File

@@ -34,6 +34,10 @@ enum GUI_DisplayType_t
DISPLAY_AIRCOPY, DISPLAY_AIRCOPY,
#endif #endif
#ifdef ENABLE_REGA
DISPLAY_REGA,
#endif
DISPLAY_N_ELEM, DISPLAY_N_ELEM,
DISPLAY_INVALID = 0xFFu DISPLAY_INVALID = 0xFFu
}; };

View File

@@ -31,7 +31,7 @@
void UI_DisplayReleaseKeys(void) void UI_DisplayReleaseKeys(void)
{ {
memset(gStatusLine, 0, sizeof(gStatusLine)); memset(gStatusLine, 0, sizeof(gStatusLine));
#ifdef ENABLE_FEAT_F4HWN #if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv(); ST7565_ContrastAndInv();
#endif #endif
UI_DisplayClear(); UI_DisplayClear();
@@ -52,7 +52,7 @@ void UI_DisplayWelcome(void)
memset(gStatusLine, 0, sizeof(gStatusLine)); memset(gStatusLine, 0, sizeof(gStatusLine));
#ifdef ENABLE_FEAT_F4HWN #if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV)
ST7565_ContrastAndInv(); ST7565_ContrastAndInv();
#endif #endif
UI_DisplayClear(); UI_DisplayClear();