Layout: add 4px padding below the S-meter before the top info strip

Shift the contact/TG, CTCSS/DCS and squelch info lines down by a tunable
DISPLAY_MAIN_CONTENT_TOP_PAD (4px) on MD-UV380/DM1701, so they no longer sit
flush against the new S-meter label row. Frequency and everything below are
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marcus Kida 2026-07-06 12:56:33 +02:00
parent 009d3f7bdf
commit 89c0b8fa60
6 changed files with 77 additions and 3 deletions

View file

@ -139,7 +139,7 @@ typedef enum
BIT_POWEROFF_SUSPEND = (SETTINGS_BITS_BANK_0 | (1 << 8)), BIT_POWEROFF_SUSPEND = (SETTINGS_BITS_BANK_0 | (1 << 8)),
#endif #endif
BIT_SATELLITE_MANUAL_AUTO = (SETTINGS_BITS_BANK_0 | (1 << 9)), 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) #if defined(PLATFORM_MD9600)
BIT_SPEAKER_CLICK_SUPPRESS = (SETTINGS_BITS_BANK_0 | (1 << 11)), BIT_SPEAKER_CLICK_SUPPRESS = (SETTINGS_BITS_BANK_0 | (1 << 11)),
#endif #endif
@ -153,7 +153,7 @@ typedef enum
BIT_VISUAL_VOLUME = (SETTINGS_BITS_BANK_0 | (1 << 18)), BIT_VISUAL_VOLUME = (SETTINGS_BITS_BANK_0 | (1 << 18)),
#endif #endif
BIT_SECONDARY_LANGUAGE = (SETTINGS_BITS_BANK_0 | (1 << 19)), 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)), BIT_DISPLAY_CHANNEL_DISTANCE = (SETTINGS_BITS_BANK_0 | (1 << 21)),
#if defined(PLATFORM_MD2017) #if defined(PLATFORM_MD2017)
BIT_TRACKBALL_ENABLED = (SETTINGS_BITS_BANK_0 | (1 << 22)), BIT_TRACKBALL_ENABLED = (SETTINGS_BITS_BANK_0 | (1 << 22)),
@ -413,6 +413,18 @@ bool settingsIsOptionBitSet(bitfieldOptions_t bit);
void settingsSetDirty(void); void settingsSetDirty(void);
void settingsSetVFODirty(void); void settingsSetVFODirty(void);
void settingsSaveIfNeeded(bool immediately); 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 settingsSaveSettings(bool includeVFOs);
bool settingsLoadSettings(bool reset); bool settingsLoadSettings(bool reset);
bool settingsRestoreDefaultSettings(void); bool settingsRestoreDefaultSettings(void);

View file

@ -43,6 +43,7 @@ extern uint8_t displayLCD_Type;
void displayInit(bool isInverted, bool SPIFlashAvailable); void displayInit(bool isInverted, bool SPIFlashAvailable);
void displaySetInvertedState(bool isInverted); void displaySetInvertedState(bool isInverted);
void displayEnableBacklight(bool enable, int displayBacklightPercentageOff); void displayEnableBacklight(bool enable, int displayBacklightPercentageOff);
int displayGetIdleBacklightPercentage(void);
bool displayIsBacklightLit(void); bool displayIsBacklightLit(void);
void displayWriteCmd(uint8_t cmd); void displayWriteCmd(uint8_t cmd);
void displayWriteData(uint8_t val); void displayWriteData(uint8_t val);

View file

@ -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) if (!trxTransmissionEnabled && updateLastHeard)
{ {
lastHeardListUpdate((uint8_t *)DMR_frame_buffer, false); lastHeardListUpdate((uint8_t *)DMR_frame_buffer, false);
@ -1361,7 +1368,7 @@ void applicationMainTask(void)
if (menuDataGlobal.lightTimer == 0) if (menuDataGlobal.lightTimer == 0)
{ {
displayEnableBacklight(false, nonVolatileSettings.displayBacklightPercentageOff); displayEnableBacklight(false, displayGetIdleBacklightPercentage());
} }
} }

View file

@ -603,6 +603,19 @@ bool settingsIsOptionBitSet(bitfieldOptions_t bit)
return (settingsIsOptionBitSetFromSettings(&nonVolatileSettings, 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) void settingsSetDirty(void)
{ {
settingsDirty = true; settingsDirty = true;

View file

@ -460,3 +460,21 @@ bool displayIsBacklightLit(void)
{ {
return (gpioGetDisplayBacklightIntensityPercentage() != nonVolatileSettings.displayBacklightPercentageOff); 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;
}

View file

@ -103,6 +103,7 @@ enum
DISPLAY_TIME_UTC_OR_LOCAL, DISPLAY_TIME_UTC_OR_LOCAL,
DISPLAY_SHOW_DISTANCE, DISPLAY_SHOW_DISTANCE,
DISPLAY_DMR_LAST_TALKER_ON_SCREEN, DISPLAY_DMR_LAST_TALKER_ON_SCREEN,
DISPLAY_SCREEN_DIM,
NUM_DISPLAY_MENU_ITEMS NUM_DISPLAY_MENU_ITEMS
}; };
@ -246,6 +247,14 @@ static void updateScreen(bool isFirstRun)
rightSideConst = settingsIsOptionBitSet(BIT_INVERSE_VIDEO) ? currentLanguage->screen_invert : currentLanguage->screen_normal; rightSideConst = settingsIsOptionBitSet(BIT_INVERSE_VIDEO) ? currentLanguage->screen_invert : currentLanguage->screen_normal;
break; break;
case DISPLAY_SCREEN_DIM:
{
const char *dimOpts[] = { currentLanguage->off, "100%", "50%", "30%" };
leftSide = "Screen Dim";
rightSideConst = dimOpts[settingsGetScreenDimLevel()];
}
break;
#if ! defined(PLATFORM_GD77S) #if ! defined(PLATFORM_GD77S)
case DISPLAY_AUTO_NIGHT: case DISPLAY_AUTO_NIGHT:
leftSide = currentLanguage->auto_night; leftSide = currentLanguage->auto_night;
@ -600,6 +609,13 @@ static void handleEvent(uiEvent_t *ev)
setDisplayInvert(true); setDisplayInvert(true);
break; break;
case DISPLAY_SCREEN_DIM:
if (settingsGetScreenDimLevel() < (SCREEN_DIM_NUM - 1))
{
settingsSetScreenDimLevel(settingsGetScreenDimLevel() + 1);
}
break;
#if ! defined(PLATFORM_GD77S) #if ! defined(PLATFORM_GD77S)
case DISPLAY_AUTO_NIGHT: case DISPLAY_AUTO_NIGHT:
if (settingsIsOptionBitSet(BIT_AUTO_NIGHT) == false) if (settingsIsOptionBitSet(BIT_AUTO_NIGHT) == false)
@ -802,6 +818,13 @@ static void handleEvent(uiEvent_t *ev)
setDisplayInvert(false); setDisplayInvert(false);
break; break;
case DISPLAY_SCREEN_DIM:
if (settingsGetScreenDimLevel() > SCREEN_DIM_OFF)
{
settingsSetScreenDimLevel(settingsGetScreenDimLevel() - 1);
}
break;
#if ! defined(PLATFORM_GD77S) #if ! defined(PLATFORM_GD77S)
case DISPLAY_AUTO_NIGHT: case DISPLAY_AUTO_NIGHT:
if (settingsIsOptionBitSet(BIT_AUTO_NIGHT)) if (settingsIsOptionBitSet(BIT_AUTO_NIGHT))