diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c index 9bf11e2b7..ab55351b8 100644 --- a/src/main/cli/settings.c +++ b/src/main/cli/settings.c @@ -1428,6 +1428,7 @@ const clivalue_t valueTable[] = { { "displayport_msp_col_adjust", VAR_INT8 | MASTER_VALUE, .config.minmax = { -6, 0 }, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, colAdjust) }, { "displayport_msp_row_adjust", VAR_INT8 | MASTER_VALUE, .config.minmax = { -3, 0 }, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, rowAdjust) }, { "displayport_msp_serial", VAR_INT8 | MASTER_VALUE, .config.minmax = { SERIAL_PORT_NONE, SERIAL_PORT_IDENTIFIER_MAX }, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, displayPortSerial) }, + { "displayport_msp_attrs", VAR_UINT8 | MASTER_VALUE | MODE_ARRAY, .config.array.length = 4, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, attrValues) }, #ifdef USE_DISPLAYPORT_MSP_VENDOR_SPECIFIC { "displayport_msp_vendor_init", VAR_UINT8 | MASTER_VALUE | MODE_ARRAY, .config.array.length = 253, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, vendorInit) }, { "displayport_msp_vendor_init_length", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 252 }, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, vendorInitLength) }, diff --git a/src/main/cms/cms.c b/src/main/cms/cms.c index 72c888ffe..089d8d45d 100644 --- a/src/main/cms/cms.c +++ b/src/main/cms/cms.c @@ -361,7 +361,7 @@ static int cmsDrawMenuItemValue(displayPort_t *pDisplay, char *buff, uint8_t row #else colpos = smallScreen ? rightMenuColumn - maxSize : rightMenuColumn; #endif - cnt = displayWrite(pDisplay, colpos, row, buff); + cnt = displayWrite(pDisplay, colpos, row, DISPLAYPORT_ATTR_NONE, buff); return cnt; } @@ -510,7 +510,7 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, const OSD_Entry *p, uint8_t case OME_Label: if (IS_PRINTVALUE(*flags) && p->data) { // A label with optional string, immediately following text - cnt = displayWrite(pDisplay, leftMenuColumn + 1 + (uint8_t)strlen(p->text), row, p->data); + cnt = displayWrite(pDisplay, leftMenuColumn + 1 + (uint8_t)strlen(p->text), row, DISPLAYPORT_ATTR_NONE, p->data); CLR_PRINTVALUE(*flags); } break; @@ -526,9 +526,9 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, const OSD_Entry *p, uint8_t #ifdef CMS_MENU_DEBUG // Shouldn't happen. Notify creator of this menu content #ifdef CMS_OSD_RIGHT_ALIGNED_VALUES - cnt = displayWrite(pDisplay, rightMenuColumn - 6, row, "BADENT"); + cnt = displayWrite(pDisplay, rightMenuColumn - 6, row, DISPLAYPORT_ATTR_NONE, "BADENT"); #else - cnt = displayWrite(pDisplay, rightMenuColumn, row, "BADENT"); + cnt = displayWrite(pDisplay, rightMenuColumn, row, DISPLAYPORT_ATTR_NONE, "BADENT"); #endif #endif break; @@ -582,7 +582,7 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs) cmsPageDebug(); if (pDisplay->cursorRow >= 0 && currentCtx.cursorRow != pDisplay->cursorRow) { - room -= displayWrite(pDisplay, leftMenuColumn, top + pDisplay->cursorRow * linesPerMenuItem, " "); + room -= displayWrite(pDisplay, leftMenuColumn, top + pDisplay->cursorRow * linesPerMenuItem, DISPLAYPORT_ATTR_NONE, " "); } if (room < 30) { @@ -590,7 +590,7 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs) } if (pDisplay->cursorRow != currentCtx.cursorRow) { - room -= displayWrite(pDisplay, leftMenuColumn, top + currentCtx.cursorRow * linesPerMenuItem, ">"); + room -= displayWrite(pDisplay, leftMenuColumn, top + currentCtx.cursorRow * linesPerMenuItem, DISPLAYPORT_ATTR_NONE, ">"); pDisplay->cursorRow = currentCtx.cursorRow; } @@ -612,7 +612,7 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs) if (IS_PRINTLABEL(runtimeEntryFlags[i])) { uint8_t coloff = leftMenuColumn; coloff += (p->type == OME_Label) ? 0 : 1; - room -= displayWrite(pDisplay, coloff, top + i * linesPerMenuItem, p->text); + room -= displayWrite(pDisplay, coloff, top + i * linesPerMenuItem, DISPLAYPORT_ATTR_NONE, p->text); CLR_PRINTLABEL(runtimeEntryFlags[i]); if (room < 30) { return; @@ -832,7 +832,7 @@ long cmsMenuExit(displayPort_t *pDisplay, const void *ptr) if ((exitType == CMS_EXIT_SAVEREBOOT) || (exitType == CMS_POPUP_SAVEREBOOT) || (exitType == CMS_POPUP_EXITREBOOT)) { displayClearScreen(pDisplay); - displayWrite(pDisplay, 5, 3, "REBOOTING..."); + displayWrite(pDisplay, 5, 3, DISPLAYPORT_ATTR_NONE, "REBOOTING..."); displayResync(pDisplay); // Was max7456RefreshAll(); why at this timing? diff --git a/src/main/cms/cms_menu_blackbox.c b/src/main/cms/cms_menu_blackbox.c index 1e4e70bbb..9311f3e8b 100644 --- a/src/main/cms/cms_menu_blackbox.c +++ b/src/main/cms/cms_menu_blackbox.c @@ -157,7 +157,7 @@ static long cmsx_EraseFlash(displayPort_t *pDisplay, const void *ptr) } displayClearScreen(pDisplay); - displayWrite(pDisplay, 5, 3, "ERASING FLASH..."); + displayWrite(pDisplay, 5, 3, DISPLAYPORT_ATTR_INFO, "ERASING FLASH..."); displayResync(pDisplay); // Was max7456RefreshAll(); Why at this timing? flashfsEraseCompletely(); diff --git a/src/main/drivers/display.c b/src/main/drivers/display.c index 5e4b83906..718291082 100644 --- a/src/main/drivers/display.c +++ b/src/main/drivers/display.c @@ -76,18 +76,18 @@ void displaySetXY(displayPort_t *instance, uint8_t x, uint8_t y) instance->posY = y; } -int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, const char *s) +int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t attr, const char *s) { instance->posX = x + strlen(s); instance->posY = y; - return instance->vTable->writeString(instance, x, y, s); + return instance->vTable->writeString(instance, x, y, attr, s); } -int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t c) +int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t attr, uint8_t c) { instance->posX = x + 1; instance->posY = y; - return instance->vTable->writeChar(instance, x, y, c); + return instance->vTable->writeChar(instance, x, y, attr, c); } bool displayIsTransferInProgress(const displayPort_t *instance) diff --git a/src/main/drivers/display.h b/src/main/drivers/display.h index 8fa03f70a..fa2acf0f6 100644 --- a/src/main/drivers/display.h +++ b/src/main/drivers/display.h @@ -20,6 +20,15 @@ #pragma once +typedef enum { + DISPLAYPORT_ATTR_NONE = 0, + DISPLAYPORT_ATTR_INFO, + DISPLAYPORT_ATTR_WARNING, + DISPLAYPORT_ATTR_CRITICAL, +} displayPortAttr_e; + +#define DISPLAYPORT_ATTR_BLINK 0x80 // Device local blink bit or'ed into displayPortAttr_e + typedef enum { DISPLAYPORT_LAYER_FOREGROUND, DISPLAYPORT_LAYER_BACKGROUND, @@ -49,8 +58,8 @@ typedef struct displayPortVTable_s { int (*clearScreen)(displayPort_t *displayPort); int (*drawScreen)(displayPort_t *displayPort); int (*screenSize)(const displayPort_t *displayPort); - int (*writeString)(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *text); - int (*writeChar)(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c); + int (*writeString)(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, const char *text); + int (*writeChar)(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, uint8_t c); bool (*isTransferInProgress)(const displayPort_t *displayPort); int (*heartbeat)(displayPort_t *displayPort); void (*resync)(displayPort_t *displayPort); @@ -69,8 +78,8 @@ void displayClearScreen(displayPort_t *instance); void displayDrawScreen(displayPort_t *instance); int displayScreenSize(const displayPort_t *instance); void displaySetXY(displayPort_t *instance, uint8_t x, uint8_t y); -int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, const char *s); -int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t c); +int displayWrite(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t attr, const char *s); +int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t attr, uint8_t c); bool displayIsTransferInProgress(const displayPort_t *instance); void displayHeartbeat(displayPort_t *instance); void displayResync(displayPort_t *instance); diff --git a/src/main/io/displayport_crsf.c b/src/main/io/displayport_crsf.c index 7f5e3261c..3e26fbfea 100644 --- a/src/main/io/displayport_crsf.c +++ b/src/main/io/displayport_crsf.c @@ -74,9 +74,10 @@ static int crsfScreenSize(const displayPort_t *displayPort) } -static int crsfWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *s) +static int crsfWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, const char *s) { UNUSED(displayPort); + UNUSED(attr); if (row >= crsfScreen.rows || col >= crsfScreen.cols) { return 0; } @@ -89,11 +90,11 @@ static int crsfWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, return 0; } -static int crsfWriteChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t c) +static int crsfWriteChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, uint8_t c) { char s[1]; tfp_sprintf(s, "%c", c); - return crsfWriteString(displayPort, col, row, s); + return crsfWriteString(displayPort, col, row, attr, s); } static bool crsfIsTransferInProgress(const displayPort_t *displayPort) diff --git a/src/main/io/displayport_hott.c b/src/main/io/displayport_hott.c index 81dd7d14f..c12d3a066 100644 --- a/src/main/io/displayport_hott.c +++ b/src/main/io/displayport_hott.c @@ -42,18 +42,21 @@ static int hottScreenSize(const displayPort_t *displayPort) return displayPort->rows * displayPort->cols; } -static int hottWriteChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t c) +static int hottWriteChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, uint8_t c) { UNUSED(displayPort); + UNUSED(attr); hottTextmodeWriteChar(col, row, c); return 0; } -static int hottWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *s) +static int hottWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, const char *s) { + UNUSED(attr); + while (*s) { - hottWriteChar(displayPort, col++, row, *(s++)); + hottWriteChar(displayPort, col++, row, 0, *(s++)); } return 0; } @@ -62,7 +65,7 @@ static int hottClearScreen(displayPort_t *displayPort) { for (int row = 0; row < displayPort->rows; row++) { for (int col= 0; col < displayPort->cols; col++) { - hottWriteChar(displayPort, col, row, ' '); + hottWriteChar(displayPort, col, row, 0, ' '); } } return 0; diff --git a/src/main/io/displayport_max7456.c b/src/main/io/displayport_max7456.c index 0a5531e11..ea7108afd 100644 --- a/src/main/io/displayport_max7456.c +++ b/src/main/io/displayport_max7456.c @@ -86,17 +86,21 @@ static int screenSize(const displayPort_t *displayPort) return maxScreenSize; } -static int writeString(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s) +static int writeString(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, const char *s) { UNUSED(displayPort); + UNUSED(attr); + max7456Write(x, y, s); return 0; } -static int writeChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c) +static int writeChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, uint8_t c) { UNUSED(displayPort); + UNUSED(attr); + max7456WriteChar(x, y, c); return 0; diff --git a/src/main/io/displayport_msp.c b/src/main/io/displayport_msp.c index 5c481a7eb..bdc4e6e5e 100644 --- a/src/main/io/displayport_msp.c +++ b/src/main/io/displayport_msp.c @@ -29,6 +29,9 @@ #include "common/utils.h" +#include "pg/pg.h" +#include "pg/pg_ids.h" + #include "drivers/display.h" #include "io/displayport_msp.h" @@ -37,7 +40,6 @@ #include "msp/msp_protocol.h" #include "msp/msp_serial.h" -// no template required since defaults are zero static displayPort_t mspDisplayPort; #ifdef USE_CLI @@ -97,7 +99,7 @@ static int screenSize(const displayPort_t *displayPort) return displayPort->rows * displayPort->cols; } -static int writeString(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *string) +static int writeString(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, const char *string) { #define MSP_OSD_MAX_STRING_LENGTH 30 // FIXME move this uint8_t buf[MSP_OSD_MAX_STRING_LENGTH + 4]; @@ -110,19 +112,19 @@ static int writeString(displayPort_t *displayPort, uint8_t col, uint8_t row, con buf[0] = 3; buf[1] = row; buf[2] = col; - buf[3] = 0; + buf[3] = displayPortProfileMsp()->attrValues[attr]; memcpy(&buf[4], string, len); return output(displayPort, MSP_DISPLAYPORT, buf, len + 4); } -static int writeChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t c) +static int writeChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, uint8_t c) { char buf[2]; buf[0] = c; buf[1] = 0; - return writeString(displayPort, col, row, buf); //!!TODO - check if there is a direct MSP command to do this + return writeString(displayPort, col, row, attr, buf); //!!TODO - check if there is a direct MSP command to do this } static bool isTransferInProgress(const displayPort_t *displayPort) diff --git a/src/main/io/displayport_oled.c b/src/main/io/displayport_oled.c index 9ca006fa1..1774499c1 100644 --- a/src/main/io/displayport_oled.c +++ b/src/main/io/displayport_oled.c @@ -59,15 +59,19 @@ static int oledScreenSize(const displayPort_t *displayPort) return displayPort->rows * displayPort->cols; } -static int oledWriteString(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s) +static int oledWriteString(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, const char *s) { + UNUSED(attr); + i2c_OLED_set_xy(displayPort->device, x, y); i2c_OLED_send_string(displayPort->device, s); return 0; } -static int oledWriteChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c) +static int oledWriteChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, uint8_t c) { + UNUSED(attr); + i2c_OLED_set_xy(displayPort->device, x, y); i2c_OLED_send_char(displayPort->device, c); return 0; diff --git a/src/main/io/displayport_srxl.c b/src/main/io/displayport_srxl.c index 573e99168..54b7e9032 100644 --- a/src/main/io/displayport_srxl.c +++ b/src/main/io/displayport_srxl.c @@ -45,17 +45,19 @@ static int srxlScreenSize(const displayPort_t *displayPort) return displayPort->rows * displayPort->cols; } -static int srxlWriteChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t c) +static int srxlWriteChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, uint8_t c) { - return (spektrumTmTextGenPutChar(col, row, c)); UNUSED(displayPort); + UNUSED(attr); + + return (spektrumTmTextGenPutChar(col, row, c)); } -static int srxlWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *s) +static int srxlWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, uint8_t attr, const char *s) { while (*s) { - srxlWriteChar(displayPort, col++, row, *(s++)); + srxlWriteChar(displayPort, col++, row, attr, *(s++)); } return 0; } @@ -64,15 +66,15 @@ static int srxlClearScreen(displayPort_t *displayPort) { for (int row = 0; row < SPEKTRUM_SRXL_TEXTGEN_BUFFER_ROWS; row++) { for (int col= 0; col < SPEKTRUM_SRXL_TEXTGEN_BUFFER_COLS; col++) { - srxlWriteChar(displayPort, col, row, ' '); + srxlWriteChar(displayPort, col, row, DISPLAYPORT_ATTR_NONE, ' '); } } - srxlWriteString(displayPort, 1, 0, "BETAFLIGHT"); + srxlWriteString(displayPort, 1, 0, DISPLAYPORT_ATTR_NONE, "BETAFLIGHT"); if (displayPort->grabCount == 0) { - srxlWriteString(displayPort, 0, 2, CMS_STARTUP_HELP_TEXT1); - srxlWriteString(displayPort, 2, 3, CMS_STARTUP_HELP_TEXT2); - srxlWriteString(displayPort, 2, 4, CMS_STARTUP_HELP_TEXT3); + srxlWriteString(displayPort, 0, 2, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT1); + srxlWriteString(displayPort, 2, 3, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT2); + srxlWriteString(displayPort, 2, 4, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT3); } return 0; } diff --git a/src/main/osd/osd.c b/src/main/osd/osd.c index 1a1c84869..b43573dd9 100644 --- a/src/main/osd/osd.c +++ b/src/main/osd/osd.c @@ -341,7 +341,7 @@ static void osdDrawLogo(int x, int y) for (int row = 0; row < 4; row++) { for (int column = 0; column < 24; column++) { if (fontOffset <= SYM_END_OF_FONT) - displayWriteChar(osdDisplayPort, x + column, y + row, fontOffset++); + displayWriteChar(osdDisplayPort, x + column, y + row, DISPLAYPORT_ATTR_NONE, fontOffset++); } } } @@ -372,17 +372,17 @@ void osdInit(displayPort_t *osdDisplayPortToUse) char string_buffer[30]; tfp_sprintf(string_buffer, "V%s", FC_VERSION_STRING); - displayWrite(osdDisplayPort, 20, 6, string_buffer); + displayWrite(osdDisplayPort, 20, 6, DISPLAYPORT_ATTR_NONE, string_buffer); #ifdef USE_CMS - displayWrite(osdDisplayPort, 7, 8, CMS_STARTUP_HELP_TEXT1); - displayWrite(osdDisplayPort, 11, 9, CMS_STARTUP_HELP_TEXT2); - displayWrite(osdDisplayPort, 11, 10, CMS_STARTUP_HELP_TEXT3); + displayWrite(osdDisplayPort, 7, 8, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT1); + displayWrite(osdDisplayPort, 11, 9, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT2); + displayWrite(osdDisplayPort, 11, 10, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT3); #endif #ifdef USE_RTC_TIME char dateTimeBuffer[FORMATTED_DATE_TIME_BUFSIZE]; if (osdFormatRtcDateTime(&dateTimeBuffer[0])) { - displayWrite(osdDisplayPort, 5, 12, dateTimeBuffer); + displayWrite(osdDisplayPort, 5, 12, DISPLAYPORT_ATTR_NONE, dateTimeBuffer); } #endif @@ -541,9 +541,9 @@ static void osdGetBlackboxStatusString(char * buff) static void osdDisplayStatisticLabel(uint8_t y, const char * text, const char * value) { - displayWrite(osdDisplayPort, 2, y, text); - displayWrite(osdDisplayPort, 20, y, ":"); - displayWrite(osdDisplayPort, 22, y, value); + displayWrite(osdDisplayPort, 2, y, DISPLAYPORT_ATTR_NONE, text); + displayWrite(osdDisplayPort, 20, y, DISPLAYPORT_ATTR_NONE, ":"); + displayWrite(osdDisplayPort, 22, y, DISPLAYPORT_ATTR_NONE, value); } /* @@ -575,7 +575,7 @@ static bool osdDisplayStat(int statistic, uint8_t displayRow) tfp_sprintf(buff, "NO RTC"); } - displayWrite(osdDisplayPort, 2, displayRow, buff); + displayWrite(osdDisplayPort, 2, displayRow, DISPLAYPORT_ATTR_NONE, buff); return true; } @@ -779,7 +779,7 @@ static uint8_t osdShowStats(int statsRowCount) } if (displayLabel) { - displayWrite(osdDisplayPort, 2, top++, " --- STATS ---"); + displayWrite(osdDisplayPort, 2, top++, DISPLAYPORT_ATTR_NONE, " --- STATS ---"); } for (int i = 0; i < OSD_STAT_COUNT; i++) { @@ -809,7 +809,7 @@ static void osdRefreshStats(void) static void osdShowArmed(void) { displayClearScreen(osdDisplayPort); - displayWrite(osdDisplayPort, 12, 7, "ARMED"); + displayWrite(osdDisplayPort, 12, 7, DISPLAYPORT_ATTR_NONE, "ARMED"); } STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs) diff --git a/src/main/osd/osd.h b/src/main/osd/osd.h index 88a2dfc6b..39251347a 100644 --- a/src/main/osd/osd.h +++ b/src/main/osd/osd.h @@ -22,6 +22,8 @@ #include "common/time.h" +#include "drivers/display.h" + #include "pg/pg.h" #include "sensors/esc_sensor.h" @@ -300,7 +302,6 @@ extern float osdGForce; extern escSensorData_t *osdEscDataCombined; #endif - struct displayPort_s; void osdInit(struct displayPort_s *osdDisplayPort); bool osdInitialized(void); diff --git a/src/main/osd/osd_elements.c b/src/main/osd/osd_elements.c index 46973723f..0b65dff96 100644 --- a/src/main/osd/osd_elements.c +++ b/src/main/osd/osd_elements.c @@ -211,7 +211,7 @@ static void renderOsdEscRpmOrFreq(getEscRpmOrFreqFnPtr escFnPtr, osdElementParms const int rpm = MIN((*escFnPtr)(i),99999); const int len = tfp_sprintf(rpmStr, "%d", rpm); rpmStr[len] = '\0'; - displayWrite(element->osdDisplayPort, x, y + i, rpmStr); + displayWrite(element->osdDisplayPort, x, y + i, DISPLAYPORT_ATTR_NONE, rpmStr); } element->drawElement = false; } @@ -568,7 +568,7 @@ static void osdElementArtificialHorizon(osdElementParms_t *element) for (int x = -4; x <= 4; x++) { const int y = ((-rollAngle * x) / 64) - pitchAngle; if (y >= 0 && y <= 81) { - displayWriteChar(element->osdDisplayPort, element->elemPosX + x, element->elemPosY + (y / AH_SYMBOL_COUNT), (SYM_AH_BAR9_0 + (y % AH_SYMBOL_COUNT))); + displayWriteChar(element->osdDisplayPort, element->elemPosX + x, element->elemPosY + (y / AH_SYMBOL_COUNT), DISPLAYPORT_ATTR_NONE, (SYM_AH_BAR9_0 + (y % AH_SYMBOL_COUNT))); } } @@ -886,13 +886,13 @@ static void osdBackgroundHorizonSidebars(osdElementParms_t *element) const int8_t hudwidth = AH_SIDEBAR_WIDTH_POS; const int8_t hudheight = AH_SIDEBAR_HEIGHT_POS; for (int y = -hudheight; y <= hudheight; y++) { - displayWriteChar(element->osdDisplayPort, element->elemPosX - hudwidth, element->elemPosY + y, SYM_AH_DECORATION); - displayWriteChar(element->osdDisplayPort, element->elemPosX + hudwidth, element->elemPosY + y, SYM_AH_DECORATION); + displayWriteChar(element->osdDisplayPort, element->elemPosX - hudwidth, element->elemPosY + y, DISPLAYPORT_ATTR_NONE, SYM_AH_DECORATION); + displayWriteChar(element->osdDisplayPort, element->elemPosX + hudwidth, element->elemPosY + y, DISPLAYPORT_ATTR_NONE, SYM_AH_DECORATION); } // AH level indicators - displayWriteChar(element->osdDisplayPort, element->elemPosX - hudwidth + 1, element->elemPosY, SYM_AH_LEFT); - displayWriteChar(element->osdDisplayPort, element->elemPosX + hudwidth - 1, element->elemPosY, SYM_AH_RIGHT); + displayWriteChar(element->osdDisplayPort, element->elemPosX - hudwidth + 1, element->elemPosY, DISPLAYPORT_ATTR_NONE, SYM_AH_LEFT); + displayWriteChar(element->osdDisplayPort, element->elemPosX + hudwidth - 1, element->elemPosY, DISPLAYPORT_ATTR_NONE, SYM_AH_RIGHT); element->drawElement = false; // element already drawn } @@ -1055,7 +1055,7 @@ static void osdElementRcChannels(osdElementParms_t *element) // Decimal notation can be added when tfp_sprintf supports float among fancy options. char fmtbuf[6]; tfp_sprintf(fmtbuf, "%5d", data); - displayWrite(element->osdDisplayPort, xpos, ypos + i, fmtbuf); + displayWrite(element->osdDisplayPort, xpos, ypos + i, DISPLAYPORT_ATTR_NONE, fmtbuf); } } @@ -1111,11 +1111,11 @@ static void osdBackgroundStickOverlay(osdElementParms_t *element) for (unsigned y = 0; y < OSD_STICK_OVERLAY_HEIGHT; y++) { // draw the axes, vertical and horizonal if ((x == ((OSD_STICK_OVERLAY_WIDTH - 1) / 2)) && (y == (OSD_STICK_OVERLAY_HEIGHT - 1) / 2)) { - displayWriteChar(element->osdDisplayPort, xpos + x, ypos + y, SYM_STICK_OVERLAY_CENTER); + displayWriteChar(element->osdDisplayPort, xpos + x, ypos + y, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_CENTER); } else if (x == ((OSD_STICK_OVERLAY_WIDTH - 1) / 2)) { - displayWriteChar(element->osdDisplayPort, xpos + x, ypos + y, SYM_STICK_OVERLAY_VERTICAL); + displayWriteChar(element->osdDisplayPort, xpos + x, ypos + y, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL); } else if (y == ((OSD_STICK_OVERLAY_HEIGHT - 1) / 2)) { - displayWriteChar(element->osdDisplayPort, xpos + x, ypos + y, SYM_STICK_OVERLAY_HORIZONTAL); + displayWriteChar(element->osdDisplayPort, xpos + x, ypos + y, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_HORIZONTAL); } } } @@ -1143,7 +1143,7 @@ static void osdElementStickOverlay(osdElementParms_t *element) const uint8_t cursorY = OSD_STICK_OVERLAY_VERTICAL_POSITIONS - 1 - scaleRange(constrain(rcData[vertical_channel], PWM_RANGE_MIN, PWM_RANGE_MAX - 1), PWM_RANGE_MIN, PWM_RANGE_MAX, 0, OSD_STICK_OVERLAY_VERTICAL_POSITIONS); const char cursor = SYM_STICK_OVERLAY_SPRITE_HIGH + (cursorY % OSD_STICK_OVERLAY_SPRITE_HEIGHT); - displayWriteChar(element->osdDisplayPort, xpos + cursorX, ypos + cursorY / OSD_STICK_OVERLAY_SPRITE_HEIGHT, cursor); + displayWriteChar(element->osdDisplayPort, xpos + cursorX, ypos + cursorY / OSD_STICK_OVERLAY_SPRITE_HEIGHT, DISPLAYPORT_ATTR_NONE, cursor); element->drawElement = false; // element already drawn } @@ -1235,6 +1235,7 @@ static void osdElementWarnings(osdElementParms_t *element) } tfp_sprintf(element->buff, "%s", armingDisableFlagNames[armingDisabledDisplayIndex]); + element->attr = DISPLAYPORT_ATTR_WARNING; return; } else { armingDisabledUpdateTimeUs = 0; @@ -1252,11 +1253,13 @@ static void osdElementWarnings(osdElementParms_t *element) } else { tfp_sprintf(element->buff, "ARM IN %d.%d", armingDelayTime / 10, armingDelayTime % 10); } + element->attr = DISPLAYPORT_ATTR_INFO; return; } #endif // USE_DSHOT if (osdWarnGetState(OSD_WARNING_FAIL_SAFE) && failsafeIsActive()) { tfp_sprintf(element->buff, "FAIL SAFE"); + element->attr = DISPLAYPORT_ATTR_CRITICAL; SET_BLINK(OSD_WARNINGS); return; } @@ -1264,6 +1267,7 @@ static void osdElementWarnings(osdElementParms_t *element) // Warn when in flip over after crash mode if (osdWarnGetState(OSD_WARNING_CRASH_FLIP) && isFlipOverAfterCrashActive()) { tfp_sprintf(element->buff, "CRASH FLIP"); + element->attr = DISPLAYPORT_ATTR_INFO; return; } @@ -1284,6 +1288,8 @@ static void osdElementWarnings(osdElementParms_t *element) if ( calculateThrottlePercent() >= MAX(currentPidProfile->launchControlThrottlePercent - 10, 0)) { SET_BLINK(OSD_WARNINGS); } + + element->attr = DISPLAYPORT_ATTR_INFO; return; } #endif // USE_LAUNCH_CONTROL @@ -1291,6 +1297,7 @@ static void osdElementWarnings(osdElementParms_t *element) // RSSI if (osdWarnGetState(OSD_WARNING_RSSI) && (getRssiPercent() < osdConfig()->rssi_alarm)) { tfp_sprintf(element->buff, "RSSI LOW"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1298,6 +1305,7 @@ static void osdElementWarnings(osdElementParms_t *element) // rssi dbm if (osdWarnGetState(OSD_WARNING_RSSI_DBM) && (getRssiDbm() > osdConfig()->rssi_dbm_alarm)) { tfp_sprintf(element->buff, "RSSI DBM"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1307,6 +1315,7 @@ static void osdElementWarnings(osdElementParms_t *element) // Link Quality if (osdWarnGetState(OSD_WARNING_LINK_QUALITY) && (rxGetLinkQualityPercent() < osdConfig()->link_quality_alarm)) { tfp_sprintf(element->buff, "LINK QUALITY"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1314,6 +1323,7 @@ static void osdElementWarnings(osdElementParms_t *element) if (osdWarnGetState(OSD_WARNING_BATTERY_CRITICAL) && batteryState == BATTERY_CRITICAL) { tfp_sprintf(element->buff, " LAND NOW"); + element->attr = DISPLAYPORT_ATTR_CRITICAL; SET_BLINK(OSD_WARNINGS); return; } @@ -1325,6 +1335,7 @@ static void osdElementWarnings(osdElementParms_t *element) !gpsRescueIsDisabled() && !gpsRescueIsAvailable()) { tfp_sprintf(element->buff, "RESCUE N/A"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1337,6 +1348,7 @@ static void osdElementWarnings(osdElementParms_t *element) statistic_t *stats = osdGetStats(); if (cmpTimeUs(stats->armed_time, OSD_GPS_RESCUE_DISABLED_WARNING_DURATION_US) < 0) { tfp_sprintf(element->buff, "RESCUE OFF"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1347,6 +1359,7 @@ static void osdElementWarnings(osdElementParms_t *element) // Show warning if in HEADFREE flight mode if (FLIGHT_MODE(HEADFREE_MODE)) { tfp_sprintf(element->buff, "HEADFREE"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1355,6 +1368,7 @@ static void osdElementWarnings(osdElementParms_t *element) const int16_t coreTemperature = getCoreTemperatureCelsius(); if (osdWarnGetState(OSD_WARNING_CORE_TEMPERATURE) && coreTemperature >= osdConfig()->core_temp_alarm) { tfp_sprintf(element->buff, "CORE %c: %3d%c", SYM_TEMPERATURE, osdConvertTemperatureToSelectedUnit(coreTemperature), osdGetTemperatureSymbolForSelectedUnit()); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1406,6 +1420,7 @@ static void osdElementWarnings(osdElementParms_t *element) if (escWarningCount > 0) { tfp_sprintf(element->buff, "%s", escWarningMsg); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1414,6 +1429,7 @@ static void osdElementWarnings(osdElementParms_t *element) if (osdWarnGetState(OSD_WARNING_BATTERY_WARNING) && batteryState == BATTERY_WARNING) { tfp_sprintf(element->buff, "LOW BATTERY"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1422,6 +1438,7 @@ static void osdElementWarnings(osdElementParms_t *element) // Show warning if rc smoothing hasn't initialized the filters if (osdWarnGetState(OSD_WARNING_RC_SMOOTHING) && ARMING_FLAG(ARMED) && !rcSmoothingInitializationComplete()) { tfp_sprintf(element->buff, "RCSMOOTHING"); + element->attr = DISPLAYPORT_ATTR_WARNING; SET_BLINK(OSD_WARNINGS); return; } @@ -1431,12 +1448,14 @@ static void osdElementWarnings(osdElementParms_t *element) if (osdWarnGetState(OSD_WARNING_BATTERY_NOT_FULL) && !ARMING_FLAG(WAS_EVER_ARMED) && (getBatteryState() == BATTERY_OK) && getBatteryAverageCellVoltage() < batteryConfig()->vbatfullcellvoltage) { tfp_sprintf(element->buff, "BATT < FULL"); + element->attr = DISPLAYPORT_ATTR_INFO; return; } // Visual beeper if (osdWarnGetState(OSD_WARNING_VISUAL_BEEPER) && osdGetVisualBeeperState()) { tfp_sprintf(element->buff, " * * * *"); + element->attr = DISPLAYPORT_ATTR_INFO; return; } @@ -1709,11 +1728,12 @@ static void osdDrawSingleElement(displayPort_t *osdDisplayPort, uint8_t item) element.buff = (char *)&buff; element.osdDisplayPort = osdDisplayPort; element.drawElement = true; + element.attr = DISPLAYPORT_ATTR_NONE; // Call the element drawing function osdElementDrawFunction[item](&element); if (element.drawElement) { - displayWrite(osdDisplayPort, elemPosX, elemPosY, buff); + displayWrite(osdDisplayPort, elemPosX, elemPosY, element.attr, buff); } } @@ -1739,7 +1759,7 @@ static void osdDrawSingleElementBackground(displayPort_t *osdDisplayPort, uint8_ // Call the element background drawing function osdElementBackgroundFunction[item](&element); if (element.drawElement) { - displayWrite(osdDisplayPort, elemPosX, elemPosY, buff); + displayWrite(osdDisplayPort, elemPosX, elemPosY, DISPLAYPORT_ATTR_NONE, buff); } } diff --git a/src/main/osd/osd_elements.h b/src/main/osd/osd_elements.h index 251ed80d9..d7aca9047 100644 --- a/src/main/osd/osd_elements.h +++ b/src/main/osd/osd_elements.h @@ -31,6 +31,7 @@ typedef struct osdElementParms_s { char *buff; displayPort_t *osdDisplayPort; bool drawElement; + uint8_t attr; } osdElementParms_t; typedef void (*osdElementDrawFn)(osdElementParms_t *element); diff --git a/src/main/pg/displayport_profiles.h b/src/main/pg/displayport_profiles.h index 028758279..58a9cc434 100644 --- a/src/main/pg/displayport_profiles.h +++ b/src/main/pg/displayport_profiles.h @@ -30,6 +30,9 @@ typedef struct displayPortProfile_s { uint8_t whiteBrightness; int8_t displayPortSerial; // serialPortIdentifier_e + // For attribute-rich OSDs + + uint8_t attrValues[4]; // NORMAL, INFORMATIONAL, WARNING, CRITICAL #ifdef USE_DISPLAYPORT_MSP_VENDOR_SPECIFIC uint8_t vendorInitLength; // Actual length of vendorInit byte string uint8_t vendorInit[253]; // Max 253 bytes of vendor specific initialization byte string diff --git a/src/test/unit/unittest_displayport.h b/src/test/unit/unittest_displayport.h index 78be72a56..17a0013a3 100644 --- a/src/test/unit/unittest_displayport.h +++ b/src/test/unit/unittest_displayport.h @@ -67,18 +67,20 @@ static int displayPortTestScreenSize(const displayPort_t *displayPort) return 0; } -static int displayPortTestWriteString(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *s) +static int displayPortTestWriteString(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, const char *s) { UNUSED(displayPort); + UNUSED(attr); for (unsigned int i = 0; i < strlen(s); i++) { testDisplayPortBuffer[(y * UNITTEST_DISPLAYPORT_COLS) + x + i] = s[i]; } return 0; } -static int displayPortTestWriteChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t c) +static int displayPortTestWriteChar(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, uint8_t c) { UNUSED(displayPort); + UNUSED(attr); testDisplayPortBuffer[(y * UNITTEST_DISPLAYPORT_COLS) + x] = c; return 0; }