diff --git a/src/main/cms/cms.c b/src/main/cms/cms.c index e5d1977196..ae03db3024 100644 --- a/src/main/cms/cms.c +++ b/src/main/cms/cms.c @@ -51,9 +51,10 @@ #include "config/config.h" #include "config/feature.h" +#include "drivers/motor.h" +#include "drivers/osd_symbols.h" #include "drivers/system.h" #include "drivers/time.h" -#include "drivers/motor.h" #include "fc/rc_controls.h" #include "fc/runtime_config.h" @@ -671,10 +672,13 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs) return; } + const bool displayWasCleared = pDisplay->cleared; uint8_t i; const OSD_Entry *p; uint8_t top = smallScreen ? 1 : (pDisplay->rows - pageMaxRow)/2; + pDisplay->cleared = false; + // Polled (dynamic) value display denominator. bool drawPolled = false; @@ -687,12 +691,11 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs) uint32_t room = displayTxBytesFree(pDisplay); - if (pDisplay->cleared) { + if (displayWasCleared) { for (p = pageTop, i= 0; (p <= pageTop + pageMaxRow); p++, i++) { SET_PRINTLABEL(runtimeEntryFlags[i]); SET_PRINTVALUE(runtimeEntryFlags[i]); } - pDisplay->cleared = false; } else if (drawPolled) { for (p = pageTop, i = 0; (p <= pageTop + pageMaxRow); p++, i++) { if (IS_DYNAMIC(p)) @@ -761,6 +764,22 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs) } } } + + // Draw the up/down page indicators if the display has space. + // Only draw the symbols when necessary after the screen has been cleared. Otherwise they're static. + // If the device supports OSD symbols then use the up/down arrows. Otherwise assume it's a + // simple text device and use the '^' (carat) and 'V' for arrow approximations. + if (displayWasCleared && leftMenuColumn > 0) { // make sure there's room to draw the symbol + if (currentCtx.page > 0) { + const uint8_t symbol = displaySupportsOsdSymbols(pDisplay) ? SYM_ARROW_NORTH : '^'; + displayWriteChar(pDisplay, leftMenuColumn - 1, top, DISPLAYPORT_ATTR_NONE, symbol); + } + if (currentCtx.page < pageCount - 1) { + const uint8_t symbol = displaySupportsOsdSymbols(pDisplay) ? SYM_ARROW_SOUTH : 'V'; + displayWriteChar(pDisplay, leftMenuColumn - 1, top + pageMaxRow, DISPLAYPORT_ATTR_NONE, symbol); + } + } + } const void *cmsMenuChange(displayPort_t *pDisplay, const void *ptr) diff --git a/src/main/drivers/display.c b/src/main/drivers/display.c index 1ac9ca00d8..d2b624f352 100644 --- a/src/main/drivers/display.c +++ b/src/main/drivers/display.c @@ -200,7 +200,19 @@ bool displayGetCanvas(displayCanvas_t *canvas, const displayPort_t *instance) return false; } -void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable) +bool displaySupportsOsdSymbols(displayPort_t *instance) +{ + // Assume device types that support OSD display will support the OSD symbols (since the OSD logic will use them) + if ((instance->deviceType == DISPLAYPORT_DEVICE_TYPE_MAX7456) + || (instance->deviceType == DISPLAYPORT_DEVICE_TYPE_MSP) + || (instance->deviceType == DISPLAYPORT_DEVICE_TYPE_FRSKYOSD)) { + return true; + } else { + return false; + } +} + +void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable, displayPortDeviceType_e deviceType) { instance->vTable = vTable; instance->vTable->clearScreen(instance); @@ -208,4 +220,5 @@ void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable) instance->cleared = true; instance->grabCount = 0; instance->cursorRow = -1; + instance->deviceType = deviceType; } diff --git a/src/main/drivers/display.h b/src/main/drivers/display.h index 8990d1a052..985fc0ac7f 100644 --- a/src/main/drivers/display.h +++ b/src/main/drivers/display.h @@ -20,6 +20,16 @@ #pragma once +typedef enum { + DISPLAYPORT_DEVICE_TYPE_MAX7456 = 0, + DISPLAYPORT_DEVICE_TYPE_OLED, + DISPLAYPORT_DEVICE_TYPE_MSP, + DISPLAYPORT_DEVICE_TYPE_FRSKYOSD, + DISPLAYPORT_DEVICE_TYPE_CRSF, + DISPLAYPORT_DEVICE_TYPE_HOTT, + DISPLAYPORT_DEVICE_TYPE_SRXL, +} displayPortDeviceType_e; + typedef enum { DISPLAYPORT_ATTR_NONE = 0, DISPLAYPORT_ATTR_INFO, @@ -69,6 +79,9 @@ typedef struct displayPort_s { // Displayport device capability bool useDeviceBlink; + + // The type of display device + displayPortDeviceType_e deviceType; } displayPort_t; typedef struct displayPortVTable_s { @@ -115,8 +128,9 @@ bool displayCheckReady(displayPort_t *instance, bool rescan); void displayBeginTransaction(displayPort_t *instance, displayTransactionOption_e opts); void displayCommitTransaction(displayPort_t *instance); bool displayGetCanvas(struct displayCanvas_s *canvas, const displayPort_t *instance); -void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable); +void displayInit(displayPort_t *instance, const displayPortVTable_t *vTable, displayPortDeviceType_e deviceType); 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); +bool displaySupportsOsdSymbols(displayPort_t *instance); diff --git a/src/main/io/displayport_crsf.c b/src/main/io/displayport_crsf.c index 4ac97c713a..f7641cdcd3 100644 --- a/src/main/io/displayport_crsf.c +++ b/src/main/io/displayport_crsf.c @@ -210,7 +210,7 @@ displayPort_t *displayPortCrsfInit() && (rxConfig()->serialrx_provider == SERIALRX_CRSF)) { crsfDisplayPortSetDimensions(CRSF_DISPLAY_PORT_ROWS_MAX, CRSF_DISPLAY_PORT_COLS_MAX); - displayInit(&crsfDisplayPort, &crsfDisplayPortVTable); + displayInit(&crsfDisplayPort, &crsfDisplayPortVTable, DISPLAYPORT_DEVICE_TYPE_CRSF); return &crsfDisplayPort; } else { return NULL; diff --git a/src/main/io/displayport_frsky_osd.c b/src/main/io/displayport_frsky_osd.c index 488077a4b5..0db8fa7198 100644 --- a/src/main/io/displayport_frsky_osd.c +++ b/src/main/io/displayport_frsky_osd.c @@ -494,7 +494,7 @@ static const displayPortVTable_t frskyOsdVTable = { displayPort_t *frskyOsdDisplayPortInit(const videoSystem_e videoSystem) { if (frskyOsdInit(videoSystem)) { - displayInit(&frskyOsdDisplayPort, &frskyOsdVTable); + displayInit(&frskyOsdDisplayPort, &frskyOsdVTable, DISPLAYPORT_DEVICE_TYPE_FRSKYOSD); redraw(&frskyOsdDisplayPort); return &frskyOsdDisplayPort; } diff --git a/src/main/io/displayport_hott.c b/src/main/io/displayport_hott.c index 7e23abf412..90b568962f 100644 --- a/src/main/io/displayport_hott.c +++ b/src/main/io/displayport_hott.c @@ -131,7 +131,7 @@ static const displayPortVTable_t hottVTable = { displayPort_t *displayPortHottInit() { hottDisplayPort.device = NULL; - displayInit(&hottDisplayPort, &hottVTable); + displayInit(&hottDisplayPort, &hottVTable, DISPLAYPORT_DEVICE_TYPE_HOTT); hottDisplayPort.useFullscreen = true; hottDisplayPort.rows = HOTT_TEXTMODE_DISPLAY_ROWS; hottDisplayPort.cols = HOTT_TEXTMODE_DISPLAY_COLUMNS; diff --git a/src/main/io/displayport_max7456.c b/src/main/io/displayport_max7456.c index 918603129d..c520610cda 100644 --- a/src/main/io/displayport_max7456.c +++ b/src/main/io/displayport_max7456.c @@ -231,7 +231,7 @@ bool max7456DisplayPortInit(const vcdProfile_t *vcdProfile, displayPort_t **disp // MAX7456 IO pins are defined, but we could not get a reply // from it at this time. Delay full initialization to // checkReady() with 'rescan' enabled - displayInit(&max7456DisplayPort, &max7456VTable); + displayInit(&max7456DisplayPort, &max7456VTable, DISPLAYPORT_DEVICE_TYPE_MAX7456); *displayPort = &max7456DisplayPort; return false; @@ -239,7 +239,7 @@ bool max7456DisplayPortInit(const vcdProfile_t *vcdProfile, displayPort_t **disp break; case MAX7456_INIT_OK: // MAX7456 configured and detected - displayInit(&max7456DisplayPort, &max7456VTable); + displayInit(&max7456DisplayPort, &max7456VTable, DISPLAYPORT_DEVICE_TYPE_MAX7456); redraw(&max7456DisplayPort); *displayPort = &max7456DisplayPort; diff --git a/src/main/io/displayport_msp.c b/src/main/io/displayport_msp.c index 56e4b015d3..1de4f03e6d 100644 --- a/src/main/io/displayport_msp.c +++ b/src/main/io/displayport_msp.c @@ -172,7 +172,7 @@ static const displayPortVTable_t mspDisplayPortVTable = { displayPort_t *displayPortMspInit(void) { - displayInit(&mspDisplayPort, &mspDisplayPortVTable); + displayInit(&mspDisplayPort, &mspDisplayPortVTable, DISPLAYPORT_DEVICE_TYPE_MSP); if (displayPortProfileMsp()->useDeviceBlink) { mspDisplayPort.useDeviceBlink = true; diff --git a/src/main/io/displayport_oled.c b/src/main/io/displayport_oled.c index 352159861f..2422e06bf9 100644 --- a/src/main/io/displayport_oled.c +++ b/src/main/io/displayport_oled.c @@ -127,7 +127,7 @@ static const displayPortVTable_t oledVTable = { displayPort_t *displayPortOledInit(void *device) { oledDisplayPort.device = device; - displayInit(&oledDisplayPort, &oledVTable); + displayInit(&oledDisplayPort, &oledVTable, DISPLAYPORT_DEVICE_TYPE_OLED); oledDisplayPort.rows = SCREEN_CHARACTER_ROW_COUNT; oledDisplayPort.cols = SCREEN_CHARACTER_COLUMN_COUNT; return &oledDisplayPort; diff --git a/src/main/io/displayport_srxl.c b/src/main/io/displayport_srxl.c index 9422cd9f4d..7af3d61e6b 100644 --- a/src/main/io/displayport_srxl.c +++ b/src/main/io/displayport_srxl.c @@ -150,7 +150,7 @@ displayPort_t *displayPortSrxlInit() && ((rxConfig()->serialrx_provider == SERIALRX_SRXL) || (rxConfig()->serialrx_provider == SERIALRX_SRXL2))) { srxlDisplayPort.device = NULL; - displayInit(&srxlDisplayPort, &srxlVTable); + displayInit(&srxlDisplayPort, &srxlVTable, DISPLAYPORT_DEVICE_TYPE_SRXL); srxlDisplayPort.rows = SPEKTRUM_SRXL_TEXTGEN_BUFFER_ROWS; srxlDisplayPort.cols = SPEKTRUM_SRXL_TEXTGEN_BUFFER_COLS; return &srxlDisplayPort; diff --git a/src/test/unit/unittest_displayport.h b/src/test/unit/unittest_displayport.h index e31c4deda2..bd0137238a 100644 --- a/src/test/unit/unittest_displayport.h +++ b/src/test/unit/unittest_displayport.h @@ -124,7 +124,7 @@ static const displayPortVTable_t testDisplayPortVTable = { displayPort_t *displayPortTestInit(void) { - displayInit(&testDisplayPort, &testDisplayPortVTable); + displayInit(&testDisplayPort, &testDisplayPortVTable, DISPLAYPORT_DEVICE_TYPE_MAX7456); testDisplayPort.rows = UNITTEST_DISPLAYPORT_ROWS; testDisplayPort.cols = UNITTEST_DISPLAYPORT_COLS; return &testDisplayPort;