mirror of
https://github.com/armel/uv-k1-k5v3-firmware-custom.git
synced 2026-10-02 03:15:37 +00:00
Add Fox Hunt / Beacon keypad lock (long-press F, Discussion #498)
This commit is contained in:
1 parent
535ee80d2b
commit
debf67a027
2 files changed
+100
-5
No files matched your search
+97
-4
@@ -44,6 +44,14 @@
|
||||
#define FOXHUNT_TICK_MS 50
|
||||
#define FOXHUNT_TREND_TICKS 20 // compare the level roughly once per second
|
||||
|
||||
// Keypad lock: hold F for ~0.5 s to toggle it, mirroring the long-press F gesture of the
|
||||
// main screen. Tracked as an elapsed-time accumulator (not a tick count) so the same hold
|
||||
// fires in every loop — the 50 ms hunt/idle ticks and the 10 ms TX slices alike — letting
|
||||
// the pad be locked or unlocked at any moment, mid-burst included. While locked every key
|
||||
// is swallowed except this hold (and, in the hunt, the attenuation arrows), so a radio
|
||||
// carried by a child cannot be knocked out of the mode or its settings changed.
|
||||
#define FOXHUNT_LOCK_HOLD_MS 500
|
||||
|
||||
// Signal-history graph: a full-width scrolling trace of the level over the last
|
||||
// seconds, on the same 13-level S scale as the staircase (FOXHUNT_FillCount). It is
|
||||
// an alternate main gauge, toggled with the 2 key. The reading is EMA-smoothed each
|
||||
@@ -155,6 +163,9 @@ static const uint8_t FOXHUNT_ATT_DB[FOXHUNT_ATT_BYP0] = {0, 6, 15, 27}; // PGA
|
||||
static KeyboardState kbd = {KEY_INVALID, KEY_INVALID, 0};
|
||||
|
||||
static bool foxRunning;
|
||||
static bool foxLocked; // keypad lock (long-press F toggles it, hunt + beacon)
|
||||
static uint16_t fHoldMs; // elapsed time the F key has been held (ms)
|
||||
static bool fLongDone; // the long-press lock toggle already fired this hold
|
||||
static uint8_t foxAudioMode;
|
||||
static uint8_t foxGraphMode; // FOXHUNT_GRAPH_BAR / _HIST, cycled by the 2 key
|
||||
static uint8_t attStep;
|
||||
@@ -411,12 +422,14 @@ static void FOXHUNT_Tag(const char *s, uint8_t x, uint8_t line)
|
||||
GUI_DisplaySmallestInverse(s, x, line, false, true, (uint8_t)(x + strlen(s) * 4));
|
||||
}
|
||||
|
||||
// Mirror the firmware's status-bar F indicator: when the F key is armed, a number key
|
||||
// steps its setting backwards. Same glyph and column as the main screens (status.c), so
|
||||
// it reads identically — Fox Hunt just renders its own status line, hence the redraw.
|
||||
// Mirror the firmware's status-bar indicator at the same column as the main screens
|
||||
// (status.c), so it reads identically: the padlock when the keypad is locked, else the
|
||||
// F glyph when the reverse-step arm is set. Lock takes priority, exactly as on status.c.
|
||||
static void FOXHUNT_DrawFKey(void)
|
||||
{
|
||||
if (gWasFKeyPressed)
|
||||
if (foxLocked)
|
||||
memcpy(gStatusLine + 69, gFontKeyLock, sizeof(gFontKeyLock));
|
||||
else if (gWasFKeyPressed)
|
||||
memcpy(gStatusLine + 69, gFontF, sizeof(gFontF));
|
||||
}
|
||||
|
||||
@@ -692,17 +705,56 @@ static void FOXHUNT_IdleHousekeeping(void)
|
||||
BACKLIGHT_TurnOff();
|
||||
}
|
||||
|
||||
// Track a held F key and toggle the keypad lock once it crosses the long-press threshold.
|
||||
// Fed the time elapsed since the last call (a hunt/idle tick, or a TX slice), so it fires
|
||||
// after the same ~0.5 s hold in every loop and the pad can be (un)locked at any moment. A
|
||||
// non-F key resets the accumulator; the toggle fires once per physical hold. Returns true
|
||||
// exactly on the toggle so a caller that does not redraw every tick (the TX loop) can
|
||||
// refresh the padlock immediately.
|
||||
static bool FOXHUNT_LockHoldTrack(KEY_Code_t key, uint16_t elapsedMs)
|
||||
{
|
||||
if (key != KEY_F) {
|
||||
fHoldMs = 0;
|
||||
fLongDone = false;
|
||||
return false;
|
||||
}
|
||||
if (fLongDone) // already toggled once for this hold
|
||||
return false;
|
||||
fHoldMs += elapsedMs;
|
||||
if (fHoldMs < FOXHUNT_LOCK_HOLD_MS)
|
||||
return false;
|
||||
|
||||
fLongDone = true;
|
||||
foxLocked = !foxLocked;
|
||||
gWasFKeyPressed = false; // a lock toggle is not a reverse-step arm
|
||||
BACKLIGHT_TurnOn();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void FOXHUNT_HandleKeys(void)
|
||||
{
|
||||
kbd.prev = kbd.current;
|
||||
kbd.current = KEYBOARD_GetKey();
|
||||
|
||||
// Long-press F toggles the keypad lock; a short F press falls through to the reverse-
|
||||
// step arm on its rising edge below. One hunt tick has elapsed since the last call.
|
||||
FOXHUNT_LockHoldTrack(kbd.current, FOXHUNT_TICK_MS);
|
||||
|
||||
// Act only on the rising edge of a new key.
|
||||
if (kbd.current == KEY_INVALID || kbd.current == kbd.prev)
|
||||
return;
|
||||
|
||||
BACKLIGHT_TurnOn(); // any keypress wakes the screen and re-arms the timers
|
||||
|
||||
// While locked, swallow everything except the attenuation arrows — the lock is
|
||||
// released only by the long-press F handled above. Keeping ATT reachable is the whole
|
||||
// point: on the final approach the sensitivity still has to be pulled down by hand.
|
||||
if (foxLocked) {
|
||||
if (kbd.current == KEY_UP) FOXHUNT_AttCycle(+1); // more attenuation
|
||||
if (kbd.current == KEY_DOWN) FOXHUNT_AttCycle(-1); // less attenuation
|
||||
return;
|
||||
}
|
||||
|
||||
if (kbd.current == KEY_F) { // arm / disarm a reverse step for the next number key
|
||||
gWasFKeyPressed = !gWasFKeyPressed;
|
||||
return;
|
||||
@@ -728,6 +780,14 @@ static void FOXHUNT_HandleKeys(void)
|
||||
// Cycle the front-end ladder (ATT 0/-6/-15/-27 dB, then BYP/BYP+; F reverses).
|
||||
FOXHUNT_AttCycle(dir);
|
||||
break;
|
||||
case KEY_UP:
|
||||
// Attenuation up one step (also the locked-mode control).
|
||||
FOXHUNT_AttCycle(+1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
// Attenuation down one step.
|
||||
FOXHUNT_AttCycle(-1);
|
||||
break;
|
||||
case KEY_MENU:
|
||||
// Reset the peak / min hold and the trend reference (before each body scan).
|
||||
peakDbm = curDbm;
|
||||
@@ -857,11 +917,28 @@ static bool FOXHUNT_TxDelay(uint16_t ms)
|
||||
|
||||
kbd.prev = kbd.current;
|
||||
kbd.current = KEYBOARD_GetKey();
|
||||
|
||||
// Track a held F across slices (fed the real slice time, so the ~0.5 s threshold
|
||||
// matches hunt/idle). This runs before the rising-edge test below — a held key
|
||||
// reads the same every slice and would otherwise be skipped — so the pad can be
|
||||
// locked or unlocked mid-burst. On a toggle, repaint at once so the padlock
|
||||
// appears without waiting for the next ID repaint.
|
||||
if (FOXHUNT_LockHoldTrack(kbd.current, slice)) {
|
||||
FOXHUNT_BeaconDraw(true, 0);
|
||||
FOXHUNT_BlitScreen();
|
||||
}
|
||||
|
||||
if (kbd.current == KEY_INVALID || kbd.current == kbd.prev)
|
||||
continue; // rising edge only
|
||||
|
||||
BACKLIGHT_TurnOn(); // keep the screen awake during TX
|
||||
|
||||
// Locked: ignore every key for the rest of the burst; the long-press F unlock is
|
||||
// handled above, before this gate, so the reverse-arm F and the setting keys stay
|
||||
// inert until the pad is unlocked.
|
||||
if (foxLocked)
|
||||
continue;
|
||||
|
||||
if (kbd.current == KEY_EXIT) {
|
||||
foxRunning = false; // abort the burst and leave Fox Hunt
|
||||
return true;
|
||||
@@ -1123,11 +1200,21 @@ static void FOXHUNT_BeaconKeys(void)
|
||||
kbd.prev = kbd.current;
|
||||
kbd.current = KEYBOARD_GetKey();
|
||||
|
||||
// Long-press F toggles the keypad lock (same gesture as the hunt screen). One idle
|
||||
// tick has elapsed since the last call.
|
||||
FOXHUNT_LockHoldTrack(kbd.current, FOXHUNT_TICK_MS);
|
||||
|
||||
if (kbd.current == KEY_INVALID || kbd.current == kbd.prev)
|
||||
return;
|
||||
|
||||
BACKLIGHT_TurnOn(); // any keypress wakes the screen and re-arms the timers
|
||||
|
||||
// Locked: swallow every key (the beacon has no per-key control to keep live, unlike
|
||||
// the hunt's attenuation arrows); release with the long-press F handled above. A burst
|
||||
// in progress enforces the same lock in FOXHUNT_TxDelay.
|
||||
if (foxLocked)
|
||||
return;
|
||||
|
||||
if (kbd.current == KEY_F) { // arm / disarm a reverse step for the next number key
|
||||
gWasFKeyPressed = !gWasFKeyPressed;
|
||||
return;
|
||||
@@ -1336,6 +1423,12 @@ void APP_RunFoxHunt(void)
|
||||
kbd.prev = kbd.current = KEYBOARD_GetKey();
|
||||
gWasFKeyPressed = false; // start with the reverse-step arm cleared
|
||||
|
||||
// Always enter unlocked: the keypad lock is a transient safety toggle, not a
|
||||
// persisted setting, so a previous session must not leave the pad locked.
|
||||
foxLocked = false;
|
||||
fHoldMs = 0;
|
||||
fLongDone = false;
|
||||
|
||||
foxRunning = true;
|
||||
while (foxRunning) {
|
||||
#if defined(ENABLE_UART) || defined(ENABLE_USB)
|
||||
|
||||
@@ -177,7 +177,8 @@ Fusion is the reference edition of the project. It provides an all-in-one firmwa
|
||||
- scrolling signal-history graph,
|
||||
- peak, minimum and trend indicators,
|
||||
- selectable RF attenuation,
|
||||
- silent, Geiger-style and received-audio modes.
|
||||
- silent, Geiger-style and received-audio modes,
|
||||
- long-press `F` keypad lock (attenuation stays adjustable with the arrow keys).
|
||||
- Integrated Morse Beacon transmitter with:
|
||||
- `MOE`, `MOI`, `MOS`, `MOH`, `MO5` and `MO` identifiers,
|
||||
- optional callsign identification,
|
||||
@@ -185,6 +186,7 @@ Fusion is the reference edition of the project. It provides an all-in-one firmwa
|
||||
- live TX and idle countdowns,
|
||||
- persisted Beacon settings,
|
||||
- interactive control during transmission,
|
||||
- shared long-press `F` keypad lock,
|
||||
- TX-lock, modulation and battery-safety checks.
|
||||
- Fox Hunt and Beacon screens are mirrored to UV Studio's integrated K5Viewer.
|
||||
|
||||
|
||||
Reference in new issue
Block a user