Mute: toggle audio mute with SK2 short-tap, with LED + header indicator
Add a one-tap audio mute on the VFO and Channel screens: - SK2 short-tap toggles mute via the built-in audioAmpMute()/audioAmpIsMuted(). The tap is only consumed by the existing "set TX TG to incoming" behaviour while a DMR QSO is on screen, so mute works everywhere else. - Header: a bold "M" is shown just left of the battery while muted (the firmware's built-in strike-through over the mode text also still shows). - LED: flashes red for 0.5s every 2s while muted (main loop), overriding the normal RX/TX LED. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fe9b8d4e10
commit
f67bb2fade
5 changed files with 57 additions and 0 deletions
|
|
@ -243,6 +243,7 @@ void acceptPrivateCall(uint32_t id, int timeslot);
|
|||
bool rebuildVoicePromptOnExtraLongSK1(uiEvent_t *ev);
|
||||
bool repeatVoicePromptOnSK1(uiEvent_t *ev);
|
||||
bool handleMonitorMode(uiEvent_t *ev);
|
||||
void toggleAudioMute(void);
|
||||
void uiUtilityDisplayInformation(const char *str, displayInformation_t line, int8_t yOverride);
|
||||
void uiUtilityRenderQSODataAndUpdateScreen(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "interfaces/adc.h"
|
||||
#include "interfaces/batteryRAM.h"
|
||||
#include "hardware/SPI_Flash.h"
|
||||
#include "io/Leds.h"
|
||||
#include "interfaces/adc.h"
|
||||
#include "hardware/radioHardwareInterface.h"
|
||||
|
||||
|
|
@ -1432,6 +1433,27 @@ void applicationMainTask(void)
|
|||
updateVolumeGain(currentMenu);
|
||||
}
|
||||
|
||||
// Mute indicator: while muted, flash the RED LED for 0.5s every 2s.
|
||||
// This overrides the normal RX/TX LED while muted.
|
||||
{
|
||||
static bool muteFlashActive = false;
|
||||
|
||||
if (audioAmpIsMuted())
|
||||
{
|
||||
bool flashOn = ((ticksGetMillis() % 2000) < 500);
|
||||
LedWrite(LED_GREEN, 0);
|
||||
LedWrite(LED_RED, (flashOn ? 1 : 0));
|
||||
muteFlashActive = true;
|
||||
}
|
||||
else if (muteFlashActive)
|
||||
{
|
||||
// Just unmuted: release our forced LED state.
|
||||
LedWrite(LED_RED, 0);
|
||||
LedWrite(LED_GREEN, 0);
|
||||
muteFlashActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
while(ticksGetMillis() < startTime + 1) // ensure this Task runs at 1ms intervals. Regardless of clock speed.
|
||||
{
|
||||
vTaskDelay(0U);
|
||||
|
|
|
|||
|
|
@ -1224,6 +1224,15 @@ static void handleEvent(uiEvent_t *ev)
|
|||
return;
|
||||
}
|
||||
|
||||
// SK2 short tap toggles audio mute. The DMR TG-set handler above consumes the
|
||||
// tap (and returns) only while a QSO is on screen, so this won't fire then.
|
||||
if (BUTTONCHECK_SHORTUP(ev, BUTTON_SK2) && (BUTTONCHECK_DOWN(ev, BUTTON_SK1) == 0) && (monitorModeData.isEnabled == false))
|
||||
{
|
||||
toggleAudioMute();
|
||||
uiChannelModeUpdateScreen(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Display channel settings (RX/TX/etc) while SK1 is pressed
|
||||
if ((uiDataGlobal.displayChannelSettings == false) && (monitorModeData.isEnabled == false) && BUTTONCHECK_DOWN(ev, BUTTON_SK1))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1852,6 +1852,14 @@ void uiUtilityRenderQSOData(void)
|
|||
displayThemeResetToDefault();
|
||||
}
|
||||
|
||||
// Toggle the audio mute (speaker) state. The header shows a mute icon and the LED
|
||||
// flashes amber (see the main loop) while muted.
|
||||
void toggleAudioMute(void)
|
||||
{
|
||||
audioAmpMute(!audioAmpIsMuted());
|
||||
headerRowIsDirty = true; // refresh the header so the mute icon appears/clears
|
||||
}
|
||||
|
||||
void uiUtilityRenderHeader(bool isVFODualWatchScanning, bool isVFOSweepScanning, bool forceBatteryDisplay)
|
||||
{
|
||||
const int MODE_TEXT_X_OFFSET = 1;
|
||||
|
|
@ -2176,6 +2184,14 @@ void uiUtilityRenderHeader(bool isVFODualWatchScanning, bool isVFOSweepScanning,
|
|||
bool displayTime = (settingsIsOptionBitSet(BIT_DISPLAY_TIME_IN_HEADER) && (forceBatteryDisplay == false) && (batteryIsLow == false));
|
||||
#endif
|
||||
#endif
|
||||
// Mute indicator: bold "M" just left of the battery indicator.
|
||||
if (audioAmpIsMuted())
|
||||
{
|
||||
displayThemeApply(THEME_ITEM_FG_HEADER_TEXT, THEME_ITEM_BG_HEADER_TEXT);
|
||||
displayPrintCore((DISPLAY_SIZE_X - 40), DISPLAY_Y_POS_HEADER, "M", FONT_SIZE_1_BOLD, TEXT_ALIGN_LEFT, false);
|
||||
displayThemeResetToDefault();
|
||||
}
|
||||
|
||||
// Display battery percentage/voltage
|
||||
bool apoEnabled = (nonVolatileSettings.apo > 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1161,6 +1161,15 @@ static void handleEvent(uiEvent_t *ev)
|
|||
return;
|
||||
}
|
||||
|
||||
// SK2 short tap toggles audio mute. The DMR TG-set handler above consumes the
|
||||
// tap (and returns) only while a QSO is on screen, so this won't fire then.
|
||||
if (BUTTONCHECK_SHORTUP(ev, BUTTON_SK2) && (BUTTONCHECK_DOWN(ev, BUTTON_SK1) == 0) && (monitorModeData.isEnabled == false))
|
||||
{
|
||||
toggleAudioMute();
|
||||
uiVFOModeUpdateScreen(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((uiVFOModeSweepScanning(true) == false) && (monitorModeData.isEnabled == false) && (uiDataGlobal.reverseRepeaterVFO == false) && (BUTTONCHECK_DOWN(ev, BUTTON_SK1) && BUTTONCHECK_DOWN(ev, BUTTON_SK2)))
|
||||
{
|
||||
int prevQSODisp = -1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue