diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c index e4cebcb46c..3e3de79ac6 100644 --- a/src/main/cli/settings.c +++ b/src/main/cli/settings.c @@ -510,6 +510,12 @@ static const char* const lookupTableMixerType[] = { "LEGACY", "LINEAR", "DYNAMIC", }; +#ifdef USE_OSD +const char * const lookupTableCMSMenuBackgroundType[] = { + "TRANSPARENT", "BLACK", "GRAY", "LIGHT_GRAY" +}; +#endif + #define LOOKUP_TABLE_ENTRY(name) { name, ARRAYLEN(name) } const lookupTableEntry_t lookupTables[] = { @@ -633,6 +639,9 @@ const lookupTableEntry_t lookupTables[] = { #endif LOOKUP_TABLE_ENTRY(lookupTableMixerType), LOOKUP_TABLE_ENTRY(lookupTableSimplifiedTuningPidsMode), +#ifdef USE_OSD + LOOKUP_TABLE_ENTRY(lookupTableCMSMenuBackgroundType), +#endif }; #undef LOOKUP_TABLE_ENTRY @@ -1465,6 +1474,7 @@ const clivalue_t valueTable[] = { { "osd_camera_frame_width", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { OSD_CAMERA_FRAME_MIN_WIDTH, OSD_CAMERA_FRAME_MAX_WIDTH }, PG_OSD_CONFIG, offsetof(osdConfig_t, camera_frame_width) }, { "osd_camera_frame_height", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { OSD_CAMERA_FRAME_MIN_HEIGHT, OSD_CAMERA_FRAME_MAX_HEIGHT }, PG_OSD_CONFIG, offsetof(osdConfig_t, camera_frame_height) }, { "osd_task_frequency", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { OSD_TASK_FREQUENCY_MIN, OSD_TASK_FREQUENCY_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, task_frequency) }, + { "osd_menu_background", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_CMS_BACKGROUND }, PG_OSD_CONFIG, offsetof(osdConfig_t, cms_background_type) }, #endif // end of #ifdef USE_OSD // PG_SYSTEM_CONFIG diff --git a/src/main/cli/settings.h b/src/main/cli/settings.h index d4972c1e73..1a8b9c9bc6 100644 --- a/src/main/cli/settings.h +++ b/src/main/cli/settings.h @@ -143,7 +143,9 @@ typedef enum { #endif TABLE_MIXER_TYPE, TABLE_SIMPLIFIED_TUNING_PIDS_MODE, - +#ifdef USE_OSD + TABLE_CMS_BACKGROUND, +#endif LOOKUP_TABLE_COUNT } lookupTableIndex_e; @@ -265,3 +267,5 @@ extern const char * const lookupTableInterpolatedSetpoint[]; extern const char * const lookupTableOffOn[]; extern const char * const lookupTableSimplifiedTuningPidsMode[]; + +extern const char * const lookupTableCMSMenuBackgroundType[]; diff --git a/src/main/cms/cms.c b/src/main/cms/cms.c index e188413603..cd356f05e3 100644 --- a/src/main/cms/cms.c +++ b/src/main/cms/cms.c @@ -840,6 +840,9 @@ void cmsMenuOpen(void) menuStackIdx = 0; setArmingDisabled(ARMING_DISABLED_CMS_MENU); displayLayerSelect(pCurrentDisplay, DISPLAYPORT_LAYER_FOREGROUND); // make sure the foreground layer is active + if (osdConfig()->cms_background_type != DISPLAY_BACKGROUND_TRANSPARENT) { + displaySetBackgroundType(pCurrentDisplay, (displayPortBackground_e)osdConfig()->cms_background_type); // set the background type if not transparent + } } else { // Switch display displayPort_t *pNextDisplay = cmsDisplayPortSelectNext(); @@ -848,8 +851,10 @@ void cmsMenuOpen(void) // DisplayPort has been changed. // Convert cursorRow to absolute value currentCtx.cursorRow = cmsCursorAbsolute(pCurrentDisplay); + displaySetBackgroundType(pCurrentDisplay, DISPLAY_BACKGROUND_TRANSPARENT); // reset previous displayPort to transparent displayRelease(pCurrentDisplay); pCurrentDisplay = pNextDisplay; + displaySetBackgroundType(pCurrentDisplay, (displayPortBackground_e)osdConfig()->cms_background_type); // set the background type if not transparent } else { return; } @@ -930,6 +935,8 @@ const void *cmsMenuExit(displayPort_t *pDisplay, const void *ptr) cmsInMenu = false; + displaySetBackgroundType(pCurrentDisplay, DISPLAY_BACKGROUND_TRANSPARENT); // reset the background to transparent + displayRelease(pDisplay); currentCtx.menu = NULL; diff --git a/src/main/cms/cms_menu_osd.c b/src/main/cms/cms_menu_osd.c index 776f6e82b1..5f17a97475 100644 --- a/src/main/cms/cms_menu_osd.c +++ b/src/main/cms/cms_menu_osd.c @@ -29,6 +29,8 @@ #include "build/version.h" +#include "cli/settings.h" + #include "cms/cms.h" #include "cms/cms_types.h" #include "cms/cms_menu_osd.h" @@ -36,13 +38,17 @@ #include "common/utils.h" #include "config/feature.h" -#include "pg/pg.h" -#include "pg/pg_ids.h" + +#include "drivers/display.h" #include "io/displayport_max7456.h" #include "osd/osd.h" #include "osd/osd_elements.h" + +#include "pg/pg.h" +#include "pg/pg_ids.h" + #include "sensors/battery.h" #ifdef USE_EXTENDED_CMS_MENUS @@ -306,6 +312,8 @@ static uint8_t displayPortProfileMax7456_whiteBrightness; static uint8_t osdConfig_osdProfileIndex; #endif +static displayPortBackground_e osdMenuBackgroundType; + static const void *cmsx_menuOsdOnEnter(displayPort_t *pDisp) { UNUSED(pDisp); @@ -318,6 +326,7 @@ static const void *cmsx_menuOsdOnEnter(displayPort_t *pDisp) displayPortProfileMax7456_invert = displayPortProfileMax7456()->invert; displayPortProfileMax7456_blackBrightness = displayPortProfileMax7456()->blackBrightness; displayPortProfileMax7456_whiteBrightness = displayPortProfileMax7456()->whiteBrightness; + osdMenuBackgroundType = osdConfig()->cms_background_type; #endif return NULL; @@ -350,6 +359,14 @@ static const void *cmsx_max7456Update(displayPort_t *pDisp, const void *self) } #endif // USE_MAX7456 +static const void *cmsx_osdBackgroundUpdate(displayPort_t *pDisp, const void *self) +{ + UNUSED(self); + osdConfigMutable()->cms_background_type = osdMenuBackgroundType; + displaySetBackgroundType(pDisp, osdMenuBackgroundType); + return NULL; +} + const OSD_Entry cmsx_menuOsdEntries[] = { {"---OSD---", OME_Label, NULL, NULL, 0}, @@ -366,6 +383,7 @@ const OSD_Entry cmsx_menuOsdEntries[] = {"BRT BLACK", OME_UINT8, cmsx_max7456Update, &(OSD_UINT8_t){&displayPortProfileMax7456_blackBrightness, 0, 3, 1}, 0}, {"BRT WHITE", OME_UINT8, cmsx_max7456Update, &(OSD_UINT8_t){&displayPortProfileMax7456_whiteBrightness, 0, 3, 1}, 0}, #endif + {"BACKGROUND",OME_TAB, cmsx_osdBackgroundUpdate, &(OSD_TAB_t){&osdMenuBackgroundType, DISPLAY_BACKGROUND_COUNT - 1, lookupTableCMSMenuBackgroundType}, 0}, {"BACK", OME_Back, NULL, NULL, 0}, {NULL, OME_END, NULL, NULL, 0} }; diff --git a/src/main/drivers/display.c b/src/main/drivers/display.c index 55cf50c1ab..1ac9ca00d8 100644 --- a/src/main/drivers/display.c +++ b/src/main/drivers/display.c @@ -153,6 +153,13 @@ bool displayWriteFontCharacter(displayPort_t *instance, uint16_t addr, const osd return false; } +void displaySetBackgroundType(displayPort_t *instance, displayPortBackground_e backgroundType) +{ + if (instance->vTable->setBackgroundType) { + instance->vTable->setBackgroundType(instance, backgroundType); + } +} + bool displayCheckReady(displayPort_t *instance, bool rescan) { if (instance->vTable->checkReady) { diff --git a/src/main/drivers/display.h b/src/main/drivers/display.h index bab9b5d811..8990d1a052 100644 --- a/src/main/drivers/display.h +++ b/src/main/drivers/display.h @@ -41,6 +41,13 @@ typedef enum { DISPLAY_TRANSACTION_OPT_RESET_DRAWING = 1 << 1, } displayTransactionOption_e; +typedef enum { + DISPLAY_BACKGROUND_TRANSPARENT, + DISPLAY_BACKGROUND_BLACK, + DISPLAY_BACKGROUND_GRAY, + DISPLAY_BACKGROUND_LTGRAY, + DISPLAY_BACKGROUND_COUNT // must be the last entry +} displayPortBackground_e; struct displayCanvas_s; struct osdCharacter_s; @@ -85,6 +92,7 @@ typedef struct displayPortVTable_s { void (*beginTransaction)(displayPort_t *displayPort, displayTransactionOption_e opts); void (*commitTransaction)(displayPort_t *displayPort); bool (*getCanvas)(struct displayCanvas_s *canvas, const displayPort_t *displayPort); + void (*setBackgroundType)(displayPort_t *displayPort, displayPortBackground_e backgroundType); } displayPortVTable_t; void displayGrab(displayPort_t *instance); @@ -111,4 +119,4 @@ void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable); bool displayLayerSupported(displayPort_t *instance, displayPortLayer_e layer); bool displayLayerSelect(displayPort_t *instance, displayPortLayer_e layer); bool displayLayerCopy(displayPort_t *instance, displayPortLayer_e destLayer, displayPortLayer_e sourceLayer); - +void displaySetBackgroundType(displayPort_t *instance, displayPortBackground_e backgroundType); diff --git a/src/main/drivers/max7456.c b/src/main/drivers/max7456.c index d445a4dbce..d79a4e096b 100644 --- a/src/main/drivers/max7456.c +++ b/src/main/drivers/max7456.c @@ -100,7 +100,7 @@ #define BACKGROUND_BRIGHTNESS_42 0x06 #define BACKGROUND_BRIGHTNESS_49 0x07 -#define BACKGROUND_MODE_GRAY 0x40 +#define BACKGROUND_MODE_GRAY 0x80 // STAT register bits @@ -230,6 +230,8 @@ static bool fontIsLoading = false; static uint8_t max7456DeviceType; +static displayPortBackground_e deviceBackgroundType = DISPLAY_BACKGROUND_TRANSPARENT; + // previous states initialized outside the valid range to force update on first call #define INVALID_PREVIOUS_REGISTER_STATE 255 static uint8_t previousBlackWhiteRegister = INVALID_PREVIOUS_REGISTER_STATE; @@ -369,6 +371,29 @@ void max7456_dma_irq_handler(dmaChannelDescriptor_t* descriptor) #endif +static void max7456SetRegisterVM1(void) +{ + uint8_t backgroundGray = BACKGROUND_BRIGHTNESS_28; // this is the device default background gray level + uint8_t vm1Register = BLINK_TIME_1 | BLINK_DUTY_CYCLE_75_25; // device defaults + if (deviceBackgroundType != DISPLAY_BACKGROUND_TRANSPARENT) { + vm1Register |= BACKGROUND_MODE_GRAY; + switch (deviceBackgroundType) { + case DISPLAY_BACKGROUND_BLACK: + backgroundGray = BACKGROUND_BRIGHTNESS_0; + break; + case DISPLAY_BACKGROUND_LTGRAY: + backgroundGray = BACKGROUND_BRIGHTNESS_49; + break; + case DISPLAY_BACKGROUND_GRAY: + default: + backgroundGray = BACKGROUND_BRIGHTNESS_28; + break; + } + } + vm1Register |= (backgroundGray << 4); + max7456Send(MAX7456ADD_VM1, vm1Register); +} + uint8_t max7456GetRowsCount(void) { return (videoSignalReg & VIDEO_MODE_PAL) ? VIDEO_LINES_PAL : VIDEO_LINES_NTSC; @@ -435,6 +460,7 @@ void max7456ReInit(void) max7456Send(MAX7456ADD_VM0, videoSignalReg); max7456Send(MAX7456ADD_HOS, hosRegValue); max7456Send(MAX7456ADD_VOS, vosRegValue); + max7456SetRegisterVM1(); max7456Send(MAX7456ADD_DMM, displayMemoryModeReg | CLEAR_DISPLAY); __spiBusTransactionEnd(busdev); @@ -459,6 +485,7 @@ max7456InitStatus_e max7456Init(const max7456Config_t *max7456Config, const vcdP { max7456SpiClock = spiCalculateDivider(MAX7456_MAX_SPI_CLK_HZ); max7456DeviceDetected = false; + deviceBackgroundType = DISPLAY_BACKGROUND_TRANSPARENT; // initialize all layers for (unsigned i = 0; i < MAX7456_SUPPORTED_LAYER_COUNT; i++) { @@ -895,4 +922,14 @@ bool max7456IsDeviceDetected(void) { return max7456DeviceDetected; } + +void max7456SetBackgroundType(displayPortBackground_e backgroundType) +{ + deviceBackgroundType = backgroundType; + + __spiBusTransactionBegin(busdev); + max7456SetRegisterVM1(); + __spiBusTransactionEnd(busdev); +} + #endif // USE_MAX7456 diff --git a/src/main/drivers/max7456.h b/src/main/drivers/max7456.h index c89c49ad26..4ded7ac341 100644 --- a/src/main/drivers/max7456.h +++ b/src/main/drivers/max7456.h @@ -62,3 +62,4 @@ bool max7456LayerSupported(displayPortLayer_e layer); bool max7456LayerSelect(displayPortLayer_e layer); bool max7456LayerCopy(displayPortLayer_e destLayer, displayPortLayer_e sourceLayer); bool max7456IsDeviceDetected(void); +void max7456SetBackgroundType(displayPortBackground_e backgroundType); diff --git a/src/main/io/displayport_max7456.c b/src/main/io/displayport_max7456.c index e6ae616dc0..918603129d 100644 --- a/src/main/io/displayport_max7456.c +++ b/src/main/io/displayport_max7456.c @@ -186,6 +186,12 @@ static bool checkReady(displayPort_t *displayPort, bool rescan) return true; } +void setBackgroundType(displayPort_t *displayPort, displayPortBackground_e backgroundType) +{ + UNUSED(displayPort); + max7456SetBackgroundType(backgroundType); +} + static const displayPortVTable_t max7456VTable = { .grab = grab, .release = release, @@ -204,6 +210,7 @@ static const displayPortVTable_t max7456VTable = { .layerCopy = layerCopy, .writeFontCharacter = writeFontCharacter, .checkReady = checkReady, + .setBackgroundType = setBackgroundType, }; bool max7456DisplayPortInit(const vcdProfile_t *vcdProfile, displayPort_t **displayPort) diff --git a/src/main/osd/osd.c b/src/main/osd/osd.c index eb7cf1e904..a10f8755d9 100644 --- a/src/main/osd/osd.c +++ b/src/main/osd/osd.c @@ -341,6 +341,7 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig) osdConfig->camera_frame_height = 11; osdConfig->task_frequency = OSD_TASK_FREQUENCY_DEFAULT; + osdConfig->cms_background_type = DISPLAY_BACKGROUND_TRANSPARENT; } void pgResetFn_osdElementConfig(osdElementConfig_t *osdElementConfig) diff --git a/src/main/osd/osd.h b/src/main/osd/osd.h index c7af5310bb..518ed72c0f 100644 --- a/src/main/osd/osd.h +++ b/src/main/osd/osd.h @@ -297,6 +297,7 @@ typedef struct osdConfig_s { uint8_t camera_frame_width; // The width of the box for the camera frame element uint8_t camera_frame_height; // The height of the box for the camera frame element uint16_t task_frequency; + uint8_t cms_background_type; // For supporting devices, determines whether the CMS background is transparent or opaque } osdConfig_t; PG_DECLARE(osdConfig_t, osdConfig); diff --git a/src/test/unit/cms_unittest.cc b/src/test/unit/cms_unittest.cc index 836c45ead4..50ac8b193f 100644 --- a/src/test/unit/cms_unittest.cc +++ b/src/test/unit/cms_unittest.cc @@ -32,6 +32,11 @@ extern "C" { #include "cms/cms_types.h" #include "fc/rc_modes.h" #include "fc/runtime_config.h" + #include "osd/osd.h" + #include "pg/pg_ids.h" + + PG_REGISTER(osdConfig_t, osdConfig, PG_OSD_CONFIG, 0); + void cmsMenuOpen(void); const void *cmsMenuBack(displayPort_t *pDisplay); uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key);