mirror of
https://github.com/armel/uv-k1-k5v3-firmware-custom.git
synced 2026-10-02 03:15:37 +00:00
14 files changed
+268
-72
No files matched your search
@@ -239,6 +239,9 @@ static bool ScreenSaverCanDisplay(void)
|
||||
gEeprom.BACKLIGHT_TIME == 0 ||
|
||||
gEeprom.BACKLIGHT_TIME >= 61 ||
|
||||
gScreenSaverDisplayed ||
|
||||
#ifdef ENABLE_FEAT_F4HWN_SLEEP
|
||||
gWakeUp ||
|
||||
#endif
|
||||
gCurrentFunction == FUNCTION_TRANSMIT ||
|
||||
FUNCTION_IsRx() ||
|
||||
gPttIsPressed
|
||||
@@ -1660,6 +1663,8 @@ void APP_TimeSlice10ms(void)
|
||||
#endif
|
||||
) {
|
||||
SCREENSHOT_Update(false);
|
||||
} else if (SCREENSHOT_HasPendingStateChange()) {
|
||||
SCREENSHOT_Update(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1915,6 +1920,9 @@ void APP_TimeSlice500ms(void)
|
||||
gBacklightCountdown_500ms = 0;
|
||||
gPowerSave_10ms = 1;
|
||||
gWakeUp = true;
|
||||
#ifdef ENABLE_FEAT_F4HWN_LOGO_SAV
|
||||
ScreenSaverExit();
|
||||
#endif
|
||||
// TODO:
|
||||
// PWM_PLUS0_CH0_COMP = 0;
|
||||
BACKLIGHT_SetBrightness(0);
|
||||
|
||||
+110
-14
@@ -41,6 +41,101 @@ bool gScanUseCssResult;
|
||||
STEP_Setting_t stepSetting;
|
||||
uint8_t scanHitCount;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCAN_FREQ_VERIFY_OFF,
|
||||
SCAN_FREQ_VERIFY_FUNDAMENTAL,
|
||||
SCAN_FREQ_VERIFY_HARMONIC
|
||||
} SCAN_FrequencyVerifyState_t;
|
||||
|
||||
static SCAN_FrequencyVerifyState_t scanFreqVerifyState;
|
||||
static uint32_t scanVerifyFundamental;
|
||||
static uint32_t scanVerifyHarmonic;
|
||||
static uint16_t scanVerifyFundamentalRssi;
|
||||
|
||||
static bool SCANNER_ShouldVerifyVhfSecondHarmonic(const uint32_t frequency)
|
||||
{
|
||||
const uint32_t fundamental = frequency / 2;
|
||||
|
||||
return frequency >= (frequencyBandTable[BAND3_137MHz].lower * 2) &&
|
||||
frequency < (frequencyBandTable[BAND4_174MHz].lower * 2) &&
|
||||
fundamental >= frequencyBandTable[BAND3_137MHz].lower &&
|
||||
fundamental < frequencyBandTable[BAND4_174MHz].lower;
|
||||
}
|
||||
|
||||
static void SCANNER_StartCssScanAtFrequency(const uint32_t frequency)
|
||||
{
|
||||
gScanFrequency = frequency;
|
||||
gScanCssResultCode = 0xFF;
|
||||
gScanCssResultType = 0xFF;
|
||||
scanHitCount = 0;
|
||||
gScanUseCssResult = false;
|
||||
gScanProgressIndicator = 0;
|
||||
gScanCssState = SCAN_CSS_STATE_SCANNING;
|
||||
gScanDelay_10ms = scan_delay_10ms;
|
||||
|
||||
BK4819_SetScanFrequency(gScanFrequency);
|
||||
|
||||
if (!gCssBackgroundScan)
|
||||
GUI_SelectNextDisplay(DISPLAY_SCANNER);
|
||||
|
||||
gUpdateStatus = true;
|
||||
}
|
||||
|
||||
static void SCANNER_TuneForFrequencyVerification(const uint32_t frequency)
|
||||
{
|
||||
BK4819_SetFrequency(frequency);
|
||||
BK4819_PickRXFilterPathBasedOnFrequency(frequency);
|
||||
BK4819_RX_TurnOn();
|
||||
}
|
||||
|
||||
static uint16_t SCANNER_ReadVerificationRssi(void)
|
||||
{
|
||||
(void)BK4819_GetRSSI();
|
||||
return BK4819_GetRSSI();
|
||||
}
|
||||
|
||||
static void SCANNER_StartFrequencyVerification(const uint32_t harmonic)
|
||||
{
|
||||
scanVerifyFundamental = harmonic / 2;
|
||||
scanVerifyHarmonic = harmonic;
|
||||
scanFreqVerifyState = SCAN_FREQ_VERIFY_FUNDAMENTAL;
|
||||
|
||||
SCANNER_TuneForFrequencyVerification(scanVerifyFundamental);
|
||||
gScanDelay_10ms = 2;
|
||||
}
|
||||
|
||||
static bool SCANNER_HandleFrequencyVerification(void)
|
||||
{
|
||||
switch (scanFreqVerifyState) {
|
||||
case SCAN_FREQ_VERIFY_FUNDAMENTAL:
|
||||
scanVerifyFundamentalRssi = SCANNER_ReadVerificationRssi();
|
||||
scanFreqVerifyState = SCAN_FREQ_VERIFY_HARMONIC;
|
||||
SCANNER_TuneForFrequencyVerification(scanVerifyHarmonic);
|
||||
gScanDelay_10ms = 2;
|
||||
return true;
|
||||
|
||||
case SCAN_FREQ_VERIFY_HARMONIC: {
|
||||
const uint16_t harmonicRssi = SCANNER_ReadVerificationRssi();
|
||||
const uint16_t margin = 4;
|
||||
uint32_t verifiedFrequency = scanVerifyHarmonic;
|
||||
|
||||
if (scanVerifyFundamentalRssi > harmonicRssi &&
|
||||
scanVerifyFundamentalRssi - harmonicRssi >= margin)
|
||||
{
|
||||
verifiedFrequency = scanVerifyFundamental;
|
||||
}
|
||||
|
||||
scanFreqVerifyState = SCAN_FREQ_VERIFY_OFF;
|
||||
SCANNER_StartCssScanAtFrequency(verifiedFrequency);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void SCANNER_Key_DIGITS(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if (!bKeyHeld && bKeyPressed)
|
||||
@@ -341,7 +436,8 @@ void SCANNER_Start(bool singleFreq)
|
||||
gScanCssState = SCAN_CSS_STATE_OFF;
|
||||
gScanFrequency = 0xFFFFFFFF;
|
||||
|
||||
BK4819_PickRXFilterPathBasedOnFrequency(gScanFrequency);
|
||||
// Keep the RX input path selected by RADIO_SetupRegisters().
|
||||
// 0xFFFFFFFF means "unknown frequency" here and would turn both LNAs off.
|
||||
BK4819_SetFrequencyScan(true);
|
||||
|
||||
gUpdateStatus = true;
|
||||
@@ -366,6 +462,7 @@ void SCANNER_Start(bool singleFreq)
|
||||
g_SquelchLost = false;
|
||||
gScannerSaveState = SCAN_SAVE_NO_PROMPT;
|
||||
gScanProgressIndicator = 0;
|
||||
scanFreqVerifyState = SCAN_FREQ_VERIFY_OFF;
|
||||
}
|
||||
|
||||
void SCANNER_Stop(void)
|
||||
@@ -377,6 +474,7 @@ void SCANNER_Stop(void)
|
||||
gUpdateStatus = true;
|
||||
gCssBackgroundScan = false;
|
||||
gScanUseCssResult = false;
|
||||
scanFreqVerifyState = SCAN_FREQ_VERIFY_OFF;
|
||||
#ifdef ENABLE_VOICE
|
||||
gAnotherVoiceID = VOICE_ID_CANCEL;
|
||||
#endif
|
||||
@@ -398,6 +496,10 @@ void SCANNER_TimeSlice10ms(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (SCANNER_HandleFrequencyVerification()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (gScanCssState) {
|
||||
case SCAN_CSS_STATE_OFF: {
|
||||
// must be RF frequency scanning if we're here ?
|
||||
@@ -420,22 +522,16 @@ void SCANNER_TimeSlice10ms(void)
|
||||
if (scanHitCount < 3) {
|
||||
BK4819_SetFrequencyScan(true);
|
||||
}
|
||||
else if (SCANNER_ShouldVerifyVhfSecondHarmonic(gScanFrequency)) {
|
||||
SCANNER_StartFrequencyVerification(gScanFrequency);
|
||||
}
|
||||
else {
|
||||
BK4819_SetScanFrequency(gScanFrequency);
|
||||
gScanCssResultCode = 0xFF;
|
||||
gScanCssResultType = 0xFF;
|
||||
scanHitCount = 0;
|
||||
gScanUseCssResult = false;
|
||||
gScanProgressIndicator = 0;
|
||||
gScanCssState = SCAN_CSS_STATE_SCANNING;
|
||||
|
||||
if(!gCssBackgroundScan)
|
||||
GUI_SelectNextDisplay(DISPLAY_SCANNER);
|
||||
|
||||
gUpdateStatus = true;
|
||||
SCANNER_StartCssScanAtFrequency(gScanFrequency);
|
||||
}
|
||||
|
||||
gScanDelay_10ms = scan_delay_10ms;
|
||||
if (scanFreqVerifyState == SCAN_FREQ_VERIFY_OFF) {
|
||||
gScanDelay_10ms = scan_delay_10ms;
|
||||
}
|
||||
//gScanDelay_10ms = 1; // 10ms
|
||||
break;
|
||||
}
|
||||
|
||||
+21
-5
@@ -411,6 +411,11 @@ void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet)
|
||||
BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState);
|
||||
}
|
||||
|
||||
bool BK4819_IsGpioOutSet(BK4819_GPIO_PIN_t Pin)
|
||||
{
|
||||
return (gBK4819_GpioOutState & (0x40u >> Pin)) != 0;
|
||||
}
|
||||
|
||||
void BK4819_SetCDCSSCodeWord(uint32_t CodeWord)
|
||||
{
|
||||
// REG_51
|
||||
@@ -1719,7 +1724,7 @@ void BK4819_PrepareFSKReceive(void)
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x3068);
|
||||
}
|
||||
|
||||
static void BK4819_PlayRogerNormal(void)
|
||||
static void BK4819_PlayRogerNormal(BK4819_FilterBandwidth_t Bandwidth)
|
||||
{
|
||||
#if 0
|
||||
const uint32_t tone1_Hz = 500;
|
||||
@@ -1734,12 +1739,19 @@ static void BK4819_PlayRogerNormal(void)
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_70, BK4819_REG_70_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
|
||||
const uint8_t rogerToneGain = (Bandwidth == BK4819_FILTER_BW_WIDE) ? 32u : 66u;
|
||||
|
||||
if (Bandwidth == BK4819_FILTER_BW_WIDE)
|
||||
BK4819_SetFilterBandwidth(BK4819_FILTER_BW_NARROW, true);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone1_Hz));
|
||||
|
||||
BK4819_EnableTXLink();
|
||||
SYSTEM_DelayMs(50);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone1_Hz));
|
||||
BK4819_WriteRegister(BK4819_REG_70,
|
||||
BK4819_REG_70_ENABLE_TONE1 |
|
||||
(rogerToneGain << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
|
||||
|
||||
BK4819_ExitTxMute();
|
||||
SYSTEM_DelayMs(80);
|
||||
@@ -1752,6 +1764,10 @@ static void BK4819_PlayRogerNormal(void)
|
||||
BK4819_EnterTxMute();
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0x0000);
|
||||
|
||||
if (Bandwidth == BK4819_FILTER_BW_WIDE)
|
||||
BK4819_SetFilterBandwidth(Bandwidth, true);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); // 1 1 0000 0 1 1111 1 1 1 0
|
||||
}
|
||||
|
||||
@@ -1804,10 +1820,10 @@ void BK4819_PlayRogerMDC(void)
|
||||
BK4819_WriteRegister(BK4819_REG_58, 0x0000);
|
||||
}
|
||||
|
||||
void BK4819_PlayRoger(void)
|
||||
void BK4819_PlayRoger(BK4819_FilterBandwidth_t Bandwidth)
|
||||
{
|
||||
if (gEeprom.ROGER == ROGER_MODE_ROGER) {
|
||||
BK4819_PlayRogerNormal();
|
||||
BK4819_PlayRogerNormal(Bandwidth);
|
||||
} else if (gEeprom.ROGER == ROGER_MODE_MDC) {
|
||||
BK4819_PlayRogerMDC();
|
||||
}
|
||||
|
||||
+2
-1
@@ -77,6 +77,7 @@ void BK4819_SetAGC(bool enable);
|
||||
void BK4819_InitAGC(bool amModulation);
|
||||
|
||||
void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet);
|
||||
bool BK4819_IsGpioOutSet(BK4819_GPIO_PIN_t Pin);
|
||||
|
||||
void BK4819_SetCDCSSCodeWord(uint32_t CodeWord);
|
||||
void BK4819_SetCTCSSFrequency(uint32_t BaudRate);
|
||||
@@ -169,7 +170,7 @@ uint8_t BK4819_GetCTCType(void);
|
||||
void BK4819_SendFSKData(uint16_t *pData);
|
||||
void BK4819_PrepareFSKReceive(void);
|
||||
|
||||
void BK4819_PlayRoger(void);
|
||||
void BK4819_PlayRoger(BK4819_FilterBandwidth_t Bandwidth);
|
||||
|
||||
void BK4819_Enable_AfDac_DiscMode_TxDsp(void);
|
||||
|
||||
|
||||
+30
-11
@@ -441,6 +441,11 @@ void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet)
|
||||
BK4819_WriteRegister(BK4819_REG_33, gBK4819_GpioOutState);
|
||||
}
|
||||
|
||||
bool BK4819_IsGpioOutSet(BK4819_GPIO_PIN_t Pin)
|
||||
{
|
||||
return (gBK4819_GpioOutState & (0x40u >> Pin)) != 0;
|
||||
}
|
||||
|
||||
void BK4819_SetCDCSSCodeWord(uint32_t CodeWord)
|
||||
{
|
||||
// REG_51
|
||||
@@ -696,11 +701,11 @@ void BK4819_SetFilterBandwidth(const BK4819_FilterBandwidth_t Bandwidth, const b
|
||||
break;
|
||||
|
||||
case BK4819_FILTER_BW_NARROWER: // 6.25kHz
|
||||
// 0x205C = (0b010 << 12) | (0b000 << 9) | (0b001 << 6) |
|
||||
// (0b01 << 4) | (1 << 3) | (1 << 2)
|
||||
// 0x2058 = (0b010 << 12) | (0b000 << 9) | (0b001 << 6) |
|
||||
// (0b01 << 4) | (1 << 3)
|
||||
// = RF 3.0 kHz, weak-RF 2.0 kHz, AF Tx LPF2 2.5 kHz,
|
||||
// 6.25k mode, FM gain +6 dB.
|
||||
val = 0x205C;
|
||||
// 6.25k mode, FM gain 0 dB.
|
||||
val = 0x2058;
|
||||
break;
|
||||
|
||||
case BK4819_FILTER_BW_AM: // Stock AM preset
|
||||
@@ -1754,7 +1759,7 @@ void BK4819_PrepareFSKReceive(void)
|
||||
BK4819_WriteRegister(BK4819_REG_59, 0x3068);
|
||||
}
|
||||
|
||||
static void BK4819_PlayRogerNormal(void)
|
||||
static void BK4819_PlayRogerNormal(BK4819_FilterBandwidth_t Bandwidth)
|
||||
{
|
||||
#if 0
|
||||
const uint32_t tone1_Hz = 500;
|
||||
@@ -1769,17 +1774,31 @@ static void BK4819_PlayRogerNormal(void)
|
||||
BK4819_EnterTxMute();
|
||||
BK4819_SetAF(BK4819_AF_MUTE);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_70, // BK4819_REG_70_ENABLE_TONE1 | (66u << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
|
||||
0xC300
|
||||
);
|
||||
const uint8_t rogerToneGain = (Bandwidth == BK4819_FILTER_BW_WIDE) ? 32u : 67u;
|
||||
|
||||
if (Bandwidth == BK4819_FILTER_BW_WIDE)
|
||||
BK4819_SetFilterBandwidth(BK4819_FILTER_BW_NARROW, true);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_71, scale_freq(tone1_Hz));
|
||||
|
||||
BK4819_EnableTXLink();
|
||||
SYSTEM_DelayMs(50);
|
||||
|
||||
BK4819_PlayToneRaw(tone1_Hz, 80);
|
||||
BK4819_WriteRegister(BK4819_REG_70,
|
||||
BK4819_REG_70_ENABLE_TONE1 |
|
||||
(rogerToneGain << BK4819_REG_70_SHIFT_TONE1_TUNING_GAIN));
|
||||
|
||||
BK4819_ExitTxMute();
|
||||
SYSTEM_DelayMs(80);
|
||||
BK4819_EnterTxMute();
|
||||
|
||||
BK4819_PlayToneRaw(tone2_Hz, 80);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_70, 0x0000);
|
||||
|
||||
if (Bandwidth == BK4819_FILTER_BW_WIDE)
|
||||
BK4819_SetFilterBandwidth(Bandwidth, true);
|
||||
|
||||
BK4819_WriteRegister(BK4819_REG_30, 0xC1FE); // 1 1 0000 0 1 1111 1 1 1 0
|
||||
}
|
||||
|
||||
@@ -1832,10 +1851,10 @@ void BK4819_PlayRogerMDC(void)
|
||||
BK4819_WriteRegister(BK4819_REG_58, 0x0000);
|
||||
}
|
||||
|
||||
void BK4819_PlayRoger(void)
|
||||
void BK4819_PlayRoger(BK4819_FilterBandwidth_t Bandwidth)
|
||||
{
|
||||
if (gEeprom.ROGER == ROGER_MODE_ROGER) {
|
||||
BK4819_PlayRogerNormal();
|
||||
BK4819_PlayRogerNormal(Bandwidth);
|
||||
} else if (gEeprom.ROGER == ROGER_MODE_MDC) {
|
||||
BK4819_PlayRogerMDC();
|
||||
}
|
||||
|
||||
+10
-1
@@ -1328,7 +1328,16 @@ void RADIO_SendCssTail(void)
|
||||
|
||||
void RADIO_SendEndOfTransmission(void)
|
||||
{
|
||||
BK4819_PlayRoger();
|
||||
BK4819_FilterBandwidth_t Bandwidth = gCurrentVfo->CHANNEL_BANDWIDTH;
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN_NARROWER
|
||||
if(Bandwidth == BK4819_FILTER_BW_NARROW && gSetting_set_nfm == 1)
|
||||
{
|
||||
Bandwidth = BK4819_FILTER_BW_NARROWER;
|
||||
}
|
||||
#endif
|
||||
|
||||
BK4819_PlayRoger(Bandwidth);
|
||||
DTMF_SendEndOfTransmission();
|
||||
|
||||
// send the CTCSS/DCS tail tone - allows the receivers to mute the usual FM squelch tail/crash
|
||||
|
||||
+48
-8
@@ -20,6 +20,7 @@
|
||||
#include "misc.h"
|
||||
#include "driver/vcp.h"
|
||||
#include "driver/keyboard.h"
|
||||
#include "driver/bk4819.h"
|
||||
|
||||
// SRAM optimization: minimize static allocations
|
||||
// - previousHash: one fingerprint per 8-byte chunk instead of a full
|
||||
@@ -35,8 +36,11 @@
|
||||
// transforming each transmitted chunk twice (negligible next to the
|
||||
// blocking UART transfer).
|
||||
static uint16_t previousHash[128];
|
||||
static uint8_t previousStateFlags = 0xFF;
|
||||
static uint8_t forcedBlock = 0;
|
||||
static uint8_t keepAlive = 3;
|
||||
static bool hasConnectionPing = false;
|
||||
static bool wasConnected = false;
|
||||
|
||||
// FNV-1a over one 8-byte chunk, folded to 16 bits
|
||||
static uint16_t SCREENSHOT_Hash(const uint8_t *data)
|
||||
@@ -55,10 +59,12 @@ void SCREENSHOT_ParseInput(void)
|
||||
|
||||
if (UART_IsCableConnected()) {
|
||||
keepAlive = 15;
|
||||
hasConnectionPing = true;
|
||||
gUSB_ScreenshotEnabled = false;
|
||||
}
|
||||
else if (VCP_ScreenshotPing()) {
|
||||
keepAlive = 15;
|
||||
hasConnectionPing = true;
|
||||
gUSB_ScreenshotEnabled = true;
|
||||
}
|
||||
}
|
||||
@@ -76,8 +82,38 @@ enum {
|
||||
SCREENSHOT_CHUNK_SIZE = 8,
|
||||
SCREENSHOT_CHUNKS_PER_LINE = 16,
|
||||
SCREENSHOT_HALF_LINE_COLUMNS = LCD_WIDTH / 2,
|
||||
SCREENSHOT_MARKER_BASE = 0xF0,
|
||||
SCREENSHOT_FLAG_DEEP_SLEEP = 1 << 0,
|
||||
SCREENSHOT_FLAG_LED_RED = 1 << 1,
|
||||
SCREENSHOT_FLAG_LED_GREEN = 1 << 2,
|
||||
};
|
||||
|
||||
static uint8_t SCREENSHOT_StateFlags(void)
|
||||
{
|
||||
uint8_t flags = 0;
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN_SLEEP
|
||||
if (gWakeUp)
|
||||
flags |= SCREENSHOT_FLAG_DEEP_SLEEP;
|
||||
#endif
|
||||
|
||||
if (BK4819_IsGpioOutSet(BK4819_GPIO5_PIN1_RED))
|
||||
flags |= SCREENSHOT_FLAG_LED_RED;
|
||||
|
||||
if (BK4819_IsGpioOutSet(BK4819_GPIO6_PIN2_GREEN))
|
||||
flags |= SCREENSHOT_FLAG_LED_GREEN;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool SCREENSHOT_HasPendingStateChange(void)
|
||||
{
|
||||
if (gUART_LockScreenshot > 0 || keepAlive == 0 || !hasConnectionPing)
|
||||
return false;
|
||||
|
||||
return !wasConnected || SCREENSHOT_StateFlags() != previousStateFlags;
|
||||
}
|
||||
|
||||
// Compute one 8-byte output chunk directly from the display buffers.
|
||||
// Frame layout: per line (status + 7 frame lines), 8 bit layers of
|
||||
// 16 bytes each. Each bit layer is split into two 64-column chunks.
|
||||
@@ -101,8 +137,6 @@ static void SCREENSHOT_Chunk(uint8_t chunkIdx, uint8_t *dest)
|
||||
|
||||
void SCREENSHOT_Update(bool force)
|
||||
{
|
||||
static bool wasConnected = false;
|
||||
|
||||
if (SCREENSHOT_IsLocked())
|
||||
return;
|
||||
|
||||
@@ -110,6 +144,8 @@ void SCREENSHOT_Update(bool force)
|
||||
if (--keepAlive == 0) {
|
||||
// Connection just lost → reset state for next reconnection
|
||||
wasConnected = false;
|
||||
hasConnectionPing = false;
|
||||
previousStateFlags = 0xFF;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -119,9 +155,11 @@ void SCREENSHOT_Update(bool force)
|
||||
// Connection is alive — detect reconnection and force full frame
|
||||
if (!wasConnected) {
|
||||
force = true;
|
||||
wasConnected = true;
|
||||
}
|
||||
|
||||
const uint8_t stateFlags = SCREENSHOT_StateFlags();
|
||||
const bool stateChanged = (stateFlags != previousStateFlags);
|
||||
|
||||
// ==== FIRST PASS: Count changed chunks ====
|
||||
uint16_t deltaLen = 0;
|
||||
uint8_t changedBitmap[16] = {0}; // 1 bit per chunk
|
||||
@@ -141,7 +179,7 @@ void SCREENSHOT_Update(bool force)
|
||||
|
||||
forcedBlock = (forcedBlock + 1) % 128;
|
||||
|
||||
if (deltaLen == 0)
|
||||
if (deltaLen == 0 && !stateChanged)
|
||||
return;
|
||||
|
||||
// Skip transmission if a key is currently pressed
|
||||
@@ -149,10 +187,9 @@ void SCREENSHOT_Update(bool force)
|
||||
if (gKeyReading0 != KEY_INVALID)
|
||||
return;
|
||||
|
||||
// ==== Send version marker (for backward compatibility detection) ====
|
||||
// New format: sends 0xFF before header
|
||||
// Old format: doesn't exist, so viewers can differentiate
|
||||
uint8_t versionMarker = 0xFF;
|
||||
// ==== Send version marker and state flags ====
|
||||
// 0xF0 keeps a resync-safe marker before the standard AA 55 header.
|
||||
uint8_t versionMarker = SCREENSHOT_MARKER_BASE | stateFlags;
|
||||
SCREENSHOT_Send(&versionMarker, 1);
|
||||
|
||||
// ==== Send header ====
|
||||
@@ -183,4 +220,7 @@ void SCREENSHOT_Update(bool force)
|
||||
|
||||
uint8_t end = 0x0A;
|
||||
SCREENSHOT_Send(&end, 1);
|
||||
|
||||
previousStateFlags = stateFlags;
|
||||
wasConnected = true;
|
||||
}
|
||||
+2
-1
@@ -19,5 +19,6 @@
|
||||
|
||||
void SCREENSHOT_Update(bool force);
|
||||
void SCREENSHOT_ParseInput(void);
|
||||
bool SCREENSHOT_HasPendingStateChange(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
+4
-3
@@ -455,15 +455,16 @@ gEeprom.FreqChannel[1] = IS_FREQ_CHANNEL(Data16[5]) ? Data16[5] : (FREQ_CHANNE
|
||||
// TODO: address TBD
|
||||
PY25Q16_ReadBuffer(0x00A158, Data, 8);
|
||||
const uint8_t set_ptt_scn_sav = Data[7] & 0x0F;
|
||||
const bool set_ptt_scn_sav_erased = Data[7] == 0xFF;
|
||||
#ifdef ENABLE_FEAT_F4HWN_LOGO_SAV
|
||||
const bool set_ptt_scn_sav_valid = set_ptt_scn_sav < (SET_SAV_LEN << 2);
|
||||
const bool set_ptt_scn_sav_valid = !set_ptt_scn_sav_erased && set_ptt_scn_sav < (SET_SAV_LEN << 2);
|
||||
#else
|
||||
const bool set_ptt_scn_sav_valid = set_ptt_scn_sav < 4;
|
||||
const bool set_ptt_scn_sav_valid = !set_ptt_scn_sav_erased && set_ptt_scn_sav < 4;
|
||||
#endif
|
||||
gSetting_set_pwr = (((Data[7] & 0xF0) >> 4) < 7) ? ((Data[7] & 0xF0) >> 4) : 0;
|
||||
gSetting_set_ptt = set_ptt_scn_sav_valid ? (set_ptt_scn_sav & 0x01) : 0;
|
||||
#ifdef ENABLE_FEAT_F4HWN_SCAN_FASTER
|
||||
gSetting_set_scn = set_ptt_scn_sav_valid ? ((set_ptt_scn_sav & 0x02) == 0) : 1;
|
||||
gSetting_set_scn = set_ptt_scn_sav_valid ? ((set_ptt_scn_sav & 0x02) == 0) : 0;
|
||||
#endif
|
||||
#ifdef ENABLE_FEAT_F4HWN_LOGO_SAV
|
||||
gSetting_set_sav = set_ptt_scn_sav_valid ? ((set_ptt_scn_sav >> 2) & 0x03) : SET_SAV_OFF;
|
||||
|
||||
+31
-26
@@ -262,9 +262,17 @@ void UI_DisplayStatus()
|
||||
else if (gBackLight) {
|
||||
// Distinguish the manual backlight sub-state: BACKLIGHT_TIME == 0
|
||||
// means the light is currently off (hollow bulb), otherwise it is
|
||||
// forced on (bulb with filament). Both glyphs share the same size.
|
||||
src = (gEeprom.BACKLIGHT_TIME == 0) ? gFontLightOff : gFontLight;
|
||||
size = sizeof(gFontLight);
|
||||
// forced on (bulb with filament).
|
||||
|
||||
if (gEeprom.BACKLIGHT_TIME == 0) {
|
||||
src = gFontLightOff;
|
||||
size = sizeof(gFontLightOff);
|
||||
}
|
||||
else
|
||||
{
|
||||
src = gFontLight;
|
||||
size = sizeof(gFontLight);
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_FEAT_F4HWN_CHARGING_C
|
||||
else if (gChargingWithTypeC) {
|
||||
@@ -283,38 +291,35 @@ void UI_DisplayStatus()
|
||||
|
||||
UI_DrawBattery(line + x2, gBatteryDisplayLevel, gLowBatteryBlink);
|
||||
|
||||
bool BatTxt = true;
|
||||
|
||||
switch (gSetting_battery_text) {
|
||||
default:
|
||||
case 0:
|
||||
BatTxt = false;
|
||||
break;
|
||||
|
||||
case 1: // voltage
|
||||
const uint16_t voltage = MIN(gBatteryVoltageAverage, 999); // limit to 9.99V
|
||||
sprintf(str, "%u.%02u", voltage / 100, voltage % 100);
|
||||
break;
|
||||
|
||||
case 1: // voltage
|
||||
case 2: // percentage
|
||||
//gBatteryVoltageAverage = 999;
|
||||
sprintf(str, "%02u%%", BATTERY_VoltsToPercent(gBatteryVoltageAverage));
|
||||
if (gSetting_battery_text == 1) {
|
||||
const uint16_t voltage = MIN(gBatteryVoltageAverage, 999); // limit to 9.99V
|
||||
sprintf(str, "%u.%02u", voltage / 100, voltage % 100);
|
||||
} else {
|
||||
//gBatteryVoltageAverage = 999;
|
||||
sprintf(str, "%02u%%", BATTERY_VoltsToPercent(gBatteryVoltageAverage));
|
||||
}
|
||||
|
||||
x2 -= (7 * strlen(str));
|
||||
UI_PrintStringSmallBufferNormal(str, line + x2);
|
||||
/*
|
||||
uint8_t shift = (strlen(str) < 5) ? 92 : 88;
|
||||
GUI_DisplaySmallest(str, shift, 1, true, true);
|
||||
|
||||
for (uint8_t i = shift - 2; i < 110; i++) {
|
||||
gStatusLine[i] ^= 0x7F; // invert
|
||||
}
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (BatTxt) {
|
||||
x2 -= (7 * strlen(str));
|
||||
UI_PrintStringSmallBufferNormal(str, line + x2);
|
||||
/*
|
||||
uint8_t shift = (strlen(str) < 5) ? 92 : 88;
|
||||
GUI_DisplaySmallest(str, shift, 1, true, true);
|
||||
|
||||
for (uint8_t i = shift - 2; i < 110; i++) {
|
||||
gStatusLine[i] ^= 0x7F; // invert
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// **************
|
||||
|
||||
ST7565_BlitStatusLine();
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@
|
||||
"ENABLE_UART_RW_BK_REGS": false,
|
||||
"ENABLE_SWD": false,
|
||||
"VERSION_STRING_1": "v0.22",
|
||||
"VERSION_STRING_2": "v5.6.0"
|
||||
"VERSION_STRING_2": "v5.6.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ Anyway, have fun.
|
||||
|
||||
# Donations
|
||||
|
||||
Special thanks to Jean-Cyrille F6IWW (3 times), Fabrice 14RC123, David F4BPP, Olivier 14RC206, Frédéric F4ESO, Stéphane F5LGW (2 times), 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 (4 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 (3 times), Johan F4WAT, Robert Wörle, Rafael Sundorf, Paul Harker, Peter Fintl, Pascal F4ICR (2 times), Mike DL2MF (3 times), Eric KI1C (2 times), Phil G0ELM, Jérôme Lambert, Eliot Vedel, Alfonso EA7KDF, Jean-François F1EVM, Robert DC1RDB (2 times), Ian KE2CHJ, Daryl VK3AWA, Roberto Brunelli, Robert Boardman, Stephen Oliver, Nicolas F4INE, William Bruno, Daniel OK2VLK, Tayler Chew, Peter DL7RFP, Philippe Kopp, Rune LA6YMA, Jeremy Luna, Steef Wagenaar (2 times), Zhuo BG7SGA, Jamie M0JLB, Antoine LIBERT, Vince K0DKR, Julia DF7JA, Ken 2E0UMK, Victor TI2SYS, Tobi DG9LAY, Deaglan K4DFQ, Catherine PALMER, Brian WA6JFK, Stéphane Hintzy, Roger F1HCN, Marcin Kusaj and Flavio Cottarelli for their [donations](https://www.paypal.com/paypalme/F4HWN). That’s so kind of them. Thanks so much 🙏🏻
|
||||
Special thanks to Jean-Cyrille F6IWW (3 times), Fabrice 14RC123, David F4BPP, Olivier 14RC206, Frédéric F4ESO, Stéphane F5LGW (2 times), 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 (4 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 (3 times), Johan F4WAT, Robert Wörle, Rafael Sundorf, Paul Harker, Peter Fintl, Pascal F4ICR (2 times), Mike DL2MF (3 times), Eric KI1C / F4WFS (3 times), Phil G0ELM, Jérôme Lambert, Eliot Vedel, Alfonso EA7KDF, Jean-François F1EVM, Robert DC1RDB (2 times), Ian KE2CHJ, Daryl VK3AWA, Roberto Brunelli, Robert Boardman, Stephen Oliver, Nicolas F4INE, William Bruno, Daniel OK2VLK, Tayler Chew, Peter DL7RFP, Philippe Kopp, Rune LA6YMA, Jeremy Luna, Steef Wagenaar (2 times), Zhuo BG7SGA, Jamie M0JLB, Antoine LIBERT, Vince K0DKR, Julia DF7JA, Ken 2E0UMK, Victor TI2SYS, Tobi DG9LAY, Deaglan K4DFQ, Catherine PALMER, Brian WA6JFK, Stéphane Hintzy, Roger F1HCN, Marcin Kusaj, Flavio Cottarelli and Bob N1MLZ for their [donations](https://www.paypal.com/paypalme/F4HWN). That’s so kind of them. Thanks so much 🙏🏻
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Reference in new issue
Block a user