diff --git a/MDUV380_firmware/application/include/functions/settings.h b/MDUV380_firmware/application/include/functions/settings.h index e1b5996..4306891 100644 --- a/MDUV380_firmware/application/include/functions/settings.h +++ b/MDUV380_firmware/application/include/functions/settings.h @@ -139,7 +139,7 @@ typedef enum BIT_POWEROFF_SUSPEND = (SETTINGS_BITS_BANK_0 | (1 << 8)), #endif BIT_SATELLITE_MANUAL_AUTO = (SETTINGS_BITS_BANK_0 | (1 << 9)), - BIT_UNUSED_1 = (SETTINGS_BITS_BANK_0 | (1 << 10)), + BIT_SCREEN_DIM_0 = (SETTINGS_BITS_BANK_0 | (1 << 10)), // low bit of the 2-bit screen-dim level #if defined(PLATFORM_MD9600) BIT_SPEAKER_CLICK_SUPPRESS = (SETTINGS_BITS_BANK_0 | (1 << 11)), #endif @@ -153,7 +153,7 @@ typedef enum BIT_VISUAL_VOLUME = (SETTINGS_BITS_BANK_0 | (1 << 18)), #endif BIT_SECONDARY_LANGUAGE = (SETTINGS_BITS_BANK_0 | (1 << 19)), - BIT_UNUSED_3 = (SETTINGS_BITS_BANK_0 | (1 << 20)), + BIT_SCREEN_DIM_1 = (SETTINGS_BITS_BANK_0 | (1 << 20)), // high bit of the 2-bit screen-dim level BIT_DISPLAY_CHANNEL_DISTANCE = (SETTINGS_BITS_BANK_0 | (1 << 21)), #if defined(PLATFORM_MD2017) BIT_TRACKBALL_ENABLED = (SETTINGS_BITS_BANK_0 | (1 << 22)), @@ -413,6 +413,18 @@ bool settingsIsOptionBitSet(bitfieldOptions_t bit); void settingsSetDirty(void); void settingsSetVFODirty(void); void settingsSaveIfNeeded(bool immediately); +// Screen dimming: idle backlight as a fraction of the configured brightness. +typedef enum +{ + SCREEN_DIM_OFF = 0, // feature disabled (use the normal backlight-off level) + SCREEN_DIM_100, // stay at 100% of configured brightness when idle + SCREEN_DIM_50, // dim to 50% + SCREEN_DIM_30, // dim to 30% + SCREEN_DIM_NUM +} screenDimLevel_t; +uint8_t settingsGetScreenDimLevel(void); +void settingsSetScreenDimLevel(uint8_t level); + bool settingsSaveSettings(bool includeVFOs); bool settingsLoadSettings(bool reset); bool settingsRestoreDefaultSettings(void); diff --git a/MDUV380_firmware/application/include/io/display.h b/MDUV380_firmware/application/include/io/display.h index af869d9..8cca8df 100644 --- a/MDUV380_firmware/application/include/io/display.h +++ b/MDUV380_firmware/application/include/io/display.h @@ -43,6 +43,7 @@ extern uint8_t displayLCD_Type; void displayInit(bool isInverted, bool SPIFlashAvailable); void displaySetInvertedState(bool isInverted); void displayEnableBacklight(bool enable, int displayBacklightPercentageOff); +int displayGetIdleBacklightPercentage(void); bool displayIsBacklightLit(void); void displayWriteCmd(uint8_t cmd); void displayWriteData(uint8_t val); diff --git a/MDUV380_firmware/application/source/applicationMain.c b/MDUV380_firmware/application/source/applicationMain.c index 93d4db7..bd5493d 100644 --- a/MDUV380_firmware/application/source/applicationMain.c +++ b/MDUV380_firmware/application/source/applicationMain.c @@ -963,6 +963,13 @@ void applicationMainTask(void) } } + // Screen dimming: an incoming signal counts as activity, so keep the backlight + // at full brightness while receiving (Auto backlight mode + dimming enabled). + if (hasSignal && (nonVolatileSettings.backlightMode == BACKLIGHT_MODE_AUTO) && (settingsGetScreenDimLevel() != SCREEN_DIM_OFF)) + { + displayLightTrigger(false); + } + if (!trxTransmissionEnabled && updateLastHeard) { lastHeardListUpdate((uint8_t *)DMR_frame_buffer, false); @@ -1361,7 +1368,7 @@ void applicationMainTask(void) if (menuDataGlobal.lightTimer == 0) { - displayEnableBacklight(false, nonVolatileSettings.displayBacklightPercentageOff); + displayEnableBacklight(false, displayGetIdleBacklightPercentage()); } } diff --git a/MDUV380_firmware/application/source/functions/settings.c b/MDUV380_firmware/application/source/functions/settings.c index 1ecd20a..498c87f 100644 --- a/MDUV380_firmware/application/source/functions/settings.c +++ b/MDUV380_firmware/application/source/functions/settings.c @@ -603,6 +603,19 @@ bool settingsIsOptionBitSet(bitfieldOptions_t bit) return (settingsIsOptionBitSetFromSettings(&nonVolatileSettings, bit)); } +// Screen dim level is stored as a 2-bit value across two option bits, so it needs +// no new settings field (existing codeplugs keep both bits clear = SCREEN_DIM_OFF). +uint8_t settingsGetScreenDimLevel(void) +{ + return (settingsIsOptionBitSet(BIT_SCREEN_DIM_0) ? 1 : 0) | (settingsIsOptionBitSet(BIT_SCREEN_DIM_1) ? 2 : 0); +} + +void settingsSetScreenDimLevel(uint8_t level) +{ + settingsSetOptionBit(BIT_SCREEN_DIM_0, ((level & 1) != 0)); + settingsSetOptionBit(BIT_SCREEN_DIM_1, ((level & 2) != 0)); +} + void settingsSetDirty(void) { settingsDirty = true; diff --git a/MDUV380_firmware/application/source/io/display.c b/MDUV380_firmware/application/source/io/display.c index f34eeff..9121174 100644 --- a/MDUV380_firmware/application/source/io/display.c +++ b/MDUV380_firmware/application/source/io/display.c @@ -460,3 +460,21 @@ bool displayIsBacklightLit(void) { return (gpioGetDisplayBacklightIntensityPercentage() != nonVolatileSettings.displayBacklightPercentageOff); } + +// Backlight level to use when idle. If screen dimming is enabled (Auto mode only), +// dim to a fraction of the configured brightness; otherwise use the normal off level. +int displayGetIdleBacklightPercentage(void) +{ + if (nonVolatileSettings.backlightMode == BACKLIGHT_MODE_AUTO) + { + static const uint8_t dimPercent[SCREEN_DIM_NUM] = { 0, 100, 50, 30 }; + uint8_t level = settingsGetScreenDimLevel(); + + if (level != SCREEN_DIM_OFF) + { + return ((nonVolatileSettings.displayBacklightPercentage[DAYTIME_CURRENT] * dimPercent[level]) / 100); + } + } + + return nonVolatileSettings.displayBacklightPercentageOff; +} diff --git a/MDUV380_firmware/application/source/user_interface/menuDisplayOptions.c b/MDUV380_firmware/application/source/user_interface/menuDisplayOptions.c index 27dd223..d9d5c64 100644 --- a/MDUV380_firmware/application/source/user_interface/menuDisplayOptions.c +++ b/MDUV380_firmware/application/source/user_interface/menuDisplayOptions.c @@ -103,6 +103,7 @@ enum DISPLAY_TIME_UTC_OR_LOCAL, DISPLAY_SHOW_DISTANCE, DISPLAY_DMR_LAST_TALKER_ON_SCREEN, + DISPLAY_SCREEN_DIM, NUM_DISPLAY_MENU_ITEMS }; @@ -246,6 +247,14 @@ static void updateScreen(bool isFirstRun) rightSideConst = settingsIsOptionBitSet(BIT_INVERSE_VIDEO) ? currentLanguage->screen_invert : currentLanguage->screen_normal; break; + case DISPLAY_SCREEN_DIM: + { + const char *dimOpts[] = { currentLanguage->off, "100%", "50%", "30%" }; + leftSide = "Screen Dim"; + rightSideConst = dimOpts[settingsGetScreenDimLevel()]; + } + break; + #if ! defined(PLATFORM_GD77S) case DISPLAY_AUTO_NIGHT: leftSide = currentLanguage->auto_night; @@ -600,6 +609,13 @@ static void handleEvent(uiEvent_t *ev) setDisplayInvert(true); break; + case DISPLAY_SCREEN_DIM: + if (settingsGetScreenDimLevel() < (SCREEN_DIM_NUM - 1)) + { + settingsSetScreenDimLevel(settingsGetScreenDimLevel() + 1); + } + break; + #if ! defined(PLATFORM_GD77S) case DISPLAY_AUTO_NIGHT: if (settingsIsOptionBitSet(BIT_AUTO_NIGHT) == false) @@ -802,6 +818,13 @@ static void handleEvent(uiEvent_t *ev) setDisplayInvert(false); break; + case DISPLAY_SCREEN_DIM: + if (settingsGetScreenDimLevel() > SCREEN_DIM_OFF) + { + settingsSetScreenDimLevel(settingsGetScreenDimLevel() - 1); + } + break; + #if ! defined(PLATFORM_GD77S) case DISPLAY_AUTO_NIGHT: if (settingsIsOptionBitSet(BIT_AUTO_NIGHT))