1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-15 20:35:33 +03:00

Add support for character attribute rich displayport

This commit is contained in:
jflyper 2019-11-21 10:26:37 +09:00
parent e1244af09a
commit 2e84b0c442
17 changed files with 123 additions and 70 deletions

View file

@ -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_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_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_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 #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", 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) }, { "displayport_msp_vendor_init_length", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 252 }, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, vendorInitLength) },

View file

@ -361,7 +361,7 @@ static int cmsDrawMenuItemValue(displayPort_t *pDisplay, char *buff, uint8_t row
#else #else
colpos = smallScreen ? rightMenuColumn - maxSize : rightMenuColumn; colpos = smallScreen ? rightMenuColumn - maxSize : rightMenuColumn;
#endif #endif
cnt = displayWrite(pDisplay, colpos, row, buff); cnt = displayWrite(pDisplay, colpos, row, DISPLAYPORT_ATTR_NONE, buff);
return cnt; return cnt;
} }
@ -510,7 +510,7 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, const OSD_Entry *p, uint8_t
case OME_Label: case OME_Label:
if (IS_PRINTVALUE(*flags) && p->data) { if (IS_PRINTVALUE(*flags) && p->data) {
// A label with optional string, immediately following text // 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); CLR_PRINTVALUE(*flags);
} }
break; break;
@ -526,9 +526,9 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, const OSD_Entry *p, uint8_t
#ifdef CMS_MENU_DEBUG #ifdef CMS_MENU_DEBUG
// Shouldn't happen. Notify creator of this menu content // Shouldn't happen. Notify creator of this menu content
#ifdef CMS_OSD_RIGHT_ALIGNED_VALUES #ifdef CMS_OSD_RIGHT_ALIGNED_VALUES
cnt = displayWrite(pDisplay, rightMenuColumn - 6, row, "BADENT"); cnt = displayWrite(pDisplay, rightMenuColumn - 6, row, DISPLAYPORT_ATTR_NONE, "BADENT");
#else #else
cnt = displayWrite(pDisplay, rightMenuColumn, row, "BADENT"); cnt = displayWrite(pDisplay, rightMenuColumn, row, DISPLAYPORT_ATTR_NONE, "BADENT");
#endif #endif
#endif #endif
break; break;
@ -582,7 +582,7 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs)
cmsPageDebug(); cmsPageDebug();
if (pDisplay->cursorRow >= 0 && currentCtx.cursorRow != pDisplay->cursorRow) { 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) { if (room < 30) {
@ -590,7 +590,7 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs)
} }
if (pDisplay->cursorRow != currentCtx.cursorRow) { 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; pDisplay->cursorRow = currentCtx.cursorRow;
} }
@ -612,7 +612,7 @@ static void cmsDrawMenu(displayPort_t *pDisplay, uint32_t currentTimeUs)
if (IS_PRINTLABEL(runtimeEntryFlags[i])) { if (IS_PRINTLABEL(runtimeEntryFlags[i])) {
uint8_t coloff = leftMenuColumn; uint8_t coloff = leftMenuColumn;
coloff += (p->type == OME_Label) ? 0 : 1; 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]); CLR_PRINTLABEL(runtimeEntryFlags[i]);
if (room < 30) { if (room < 30) {
return; 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)) { if ((exitType == CMS_EXIT_SAVEREBOOT) || (exitType == CMS_POPUP_SAVEREBOOT) || (exitType == CMS_POPUP_EXITREBOOT)) {
displayClearScreen(pDisplay); displayClearScreen(pDisplay);
displayWrite(pDisplay, 5, 3, "REBOOTING..."); displayWrite(pDisplay, 5, 3, DISPLAYPORT_ATTR_NONE, "REBOOTING...");
displayResync(pDisplay); // Was max7456RefreshAll(); why at this timing? displayResync(pDisplay); // Was max7456RefreshAll(); why at this timing?

View file

@ -157,7 +157,7 @@ static long cmsx_EraseFlash(displayPort_t *pDisplay, const void *ptr)
} }
displayClearScreen(pDisplay); 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? displayResync(pDisplay); // Was max7456RefreshAll(); Why at this timing?
flashfsEraseCompletely(); flashfsEraseCompletely();

View file

@ -76,18 +76,18 @@ void displaySetXY(displayPort_t *instance, uint8_t x, uint8_t y)
instance->posY = 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->posX = x + strlen(s);
instance->posY = y; 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->posX = x + 1;
instance->posY = y; 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) bool displayIsTransferInProgress(const displayPort_t *instance)

View file

@ -20,6 +20,15 @@
#pragma once #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 { typedef enum {
DISPLAYPORT_LAYER_FOREGROUND, DISPLAYPORT_LAYER_FOREGROUND,
DISPLAYPORT_LAYER_BACKGROUND, DISPLAYPORT_LAYER_BACKGROUND,
@ -49,8 +58,8 @@ typedef struct displayPortVTable_s {
int (*clearScreen)(displayPort_t *displayPort); int (*clearScreen)(displayPort_t *displayPort);
int (*drawScreen)(displayPort_t *displayPort); int (*drawScreen)(displayPort_t *displayPort);
int (*screenSize)(const displayPort_t *displayPort); int (*screenSize)(const displayPort_t *displayPort);
int (*writeString)(displayPort_t *displayPort, uint8_t x, uint8_t y, const char *text); 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 c); int (*writeChar)(displayPort_t *displayPort, uint8_t x, uint8_t y, uint8_t attr, uint8_t c);
bool (*isTransferInProgress)(const displayPort_t *displayPort); bool (*isTransferInProgress)(const displayPort_t *displayPort);
int (*heartbeat)(displayPort_t *displayPort); int (*heartbeat)(displayPort_t *displayPort);
void (*resync)(displayPort_t *displayPort); void (*resync)(displayPort_t *displayPort);
@ -69,8 +78,8 @@ void displayClearScreen(displayPort_t *instance);
void displayDrawScreen(displayPort_t *instance); void displayDrawScreen(displayPort_t *instance);
int displayScreenSize(const displayPort_t *instance); int displayScreenSize(const displayPort_t *instance);
void displaySetXY(displayPort_t *instance, uint8_t x, uint8_t y); 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 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 c); int displayWriteChar(displayPort_t *instance, uint8_t x, uint8_t y, uint8_t attr, uint8_t c);
bool displayIsTransferInProgress(const displayPort_t *instance); bool displayIsTransferInProgress(const displayPort_t *instance);
void displayHeartbeat(displayPort_t *instance); void displayHeartbeat(displayPort_t *instance);
void displayResync(displayPort_t *instance); void displayResync(displayPort_t *instance);

View file

@ -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(displayPort);
UNUSED(attr);
if (row >= crsfScreen.rows || col >= crsfScreen.cols) { if (row >= crsfScreen.rows || col >= crsfScreen.cols) {
return 0; return 0;
} }
@ -89,11 +90,11 @@ static int crsfWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row,
return 0; 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]; char s[1];
tfp_sprintf(s, "%c", c); 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) static bool crsfIsTransferInProgress(const displayPort_t *displayPort)

View file

@ -42,18 +42,21 @@ static int hottScreenSize(const displayPort_t *displayPort)
return displayPort->rows * displayPort->cols; 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(displayPort);
UNUSED(attr);
hottTextmodeWriteChar(col, row, c); hottTextmodeWriteChar(col, row, c);
return 0; 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) { while (*s) {
hottWriteChar(displayPort, col++, row, *(s++)); hottWriteChar(displayPort, col++, row, 0, *(s++));
} }
return 0; return 0;
} }
@ -62,7 +65,7 @@ static int hottClearScreen(displayPort_t *displayPort)
{ {
for (int row = 0; row < displayPort->rows; row++) { for (int row = 0; row < displayPort->rows; row++) {
for (int col= 0; col < displayPort->cols; col++) { for (int col= 0; col < displayPort->cols; col++) {
hottWriteChar(displayPort, col, row, ' '); hottWriteChar(displayPort, col, row, 0, ' ');
} }
} }
return 0; return 0;

View file

@ -86,17 +86,21 @@ static int screenSize(const displayPort_t *displayPort)
return maxScreenSize; 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(displayPort);
UNUSED(attr);
max7456Write(x, y, s); max7456Write(x, y, s);
return 0; 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(displayPort);
UNUSED(attr);
max7456WriteChar(x, y, c); max7456WriteChar(x, y, c);
return 0; return 0;

View file

@ -29,6 +29,9 @@
#include "common/utils.h" #include "common/utils.h"
#include "pg/pg.h"
#include "pg/pg_ids.h"
#include "drivers/display.h" #include "drivers/display.h"
#include "io/displayport_msp.h" #include "io/displayport_msp.h"
@ -37,7 +40,6 @@
#include "msp/msp_protocol.h" #include "msp/msp_protocol.h"
#include "msp/msp_serial.h" #include "msp/msp_serial.h"
// no template required since defaults are zero
static displayPort_t mspDisplayPort; static displayPort_t mspDisplayPort;
#ifdef USE_CLI #ifdef USE_CLI
@ -97,7 +99,7 @@ static int screenSize(const displayPort_t *displayPort)
return displayPort->rows * displayPort->cols; 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 #define MSP_OSD_MAX_STRING_LENGTH 30 // FIXME move this
uint8_t buf[MSP_OSD_MAX_STRING_LENGTH + 4]; 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[0] = 3;
buf[1] = row; buf[1] = row;
buf[2] = col; buf[2] = col;
buf[3] = 0; buf[3] = displayPortProfileMsp()->attrValues[attr];
memcpy(&buf[4], string, len); memcpy(&buf[4], string, len);
return output(displayPort, MSP_DISPLAYPORT, buf, len + 4); 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]; char buf[2];
buf[0] = c; buf[0] = c;
buf[1] = 0; 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) static bool isTransferInProgress(const displayPort_t *displayPort)

View file

@ -59,15 +59,19 @@ static int oledScreenSize(const displayPort_t *displayPort)
return displayPort->rows * displayPort->cols; 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_set_xy(displayPort->device, x, y);
i2c_OLED_send_string(displayPort->device, s); i2c_OLED_send_string(displayPort->device, s);
return 0; 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_set_xy(displayPort->device, x, y);
i2c_OLED_send_char(displayPort->device, c); i2c_OLED_send_char(displayPort->device, c);
return 0; return 0;

View file

@ -45,17 +45,19 @@ static int srxlScreenSize(const displayPort_t *displayPort)
return displayPort->rows * displayPort->cols; 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(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) { while (*s) {
srxlWriteChar(displayPort, col++, row, *(s++)); srxlWriteChar(displayPort, col++, row, attr, *(s++));
} }
return 0; 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 row = 0; row < SPEKTRUM_SRXL_TEXTGEN_BUFFER_ROWS; row++) {
for (int col= 0; col < SPEKTRUM_SRXL_TEXTGEN_BUFFER_COLS; col++) { 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) { if (displayPort->grabCount == 0) {
srxlWriteString(displayPort, 0, 2, CMS_STARTUP_HELP_TEXT1); srxlWriteString(displayPort, 0, 2, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT1);
srxlWriteString(displayPort, 2, 3, CMS_STARTUP_HELP_TEXT2); srxlWriteString(displayPort, 2, 3, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT2);
srxlWriteString(displayPort, 2, 4, CMS_STARTUP_HELP_TEXT3); srxlWriteString(displayPort, 2, 4, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT3);
} }
return 0; return 0;
} }

View file

@ -341,7 +341,7 @@ static void osdDrawLogo(int x, int y)
for (int row = 0; row < 4; row++) { for (int row = 0; row < 4; row++) {
for (int column = 0; column < 24; column++) { for (int column = 0; column < 24; column++) {
if (fontOffset <= SYM_END_OF_FONT) 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]; char string_buffer[30];
tfp_sprintf(string_buffer, "V%s", FC_VERSION_STRING); 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 #ifdef USE_CMS
displayWrite(osdDisplayPort, 7, 8, CMS_STARTUP_HELP_TEXT1); displayWrite(osdDisplayPort, 7, 8, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT1);
displayWrite(osdDisplayPort, 11, 9, CMS_STARTUP_HELP_TEXT2); displayWrite(osdDisplayPort, 11, 9, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT2);
displayWrite(osdDisplayPort, 11, 10, CMS_STARTUP_HELP_TEXT3); displayWrite(osdDisplayPort, 11, 10, DISPLAYPORT_ATTR_NONE, CMS_STARTUP_HELP_TEXT3);
#endif #endif
#ifdef USE_RTC_TIME #ifdef USE_RTC_TIME
char dateTimeBuffer[FORMATTED_DATE_TIME_BUFSIZE]; char dateTimeBuffer[FORMATTED_DATE_TIME_BUFSIZE];
if (osdFormatRtcDateTime(&dateTimeBuffer[0])) { if (osdFormatRtcDateTime(&dateTimeBuffer[0])) {
displayWrite(osdDisplayPort, 5, 12, dateTimeBuffer); displayWrite(osdDisplayPort, 5, 12, DISPLAYPORT_ATTR_NONE, dateTimeBuffer);
} }
#endif #endif
@ -541,9 +541,9 @@ static void osdGetBlackboxStatusString(char * buff)
static void osdDisplayStatisticLabel(uint8_t y, const char * text, const char * value) static void osdDisplayStatisticLabel(uint8_t y, const char * text, const char * value)
{ {
displayWrite(osdDisplayPort, 2, y, text); displayWrite(osdDisplayPort, 2, y, DISPLAYPORT_ATTR_NONE, text);
displayWrite(osdDisplayPort, 20, y, ":"); displayWrite(osdDisplayPort, 20, y, DISPLAYPORT_ATTR_NONE, ":");
displayWrite(osdDisplayPort, 22, y, value); 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"); tfp_sprintf(buff, "NO RTC");
} }
displayWrite(osdDisplayPort, 2, displayRow, buff); displayWrite(osdDisplayPort, 2, displayRow, DISPLAYPORT_ATTR_NONE, buff);
return true; return true;
} }
@ -779,7 +779,7 @@ static uint8_t osdShowStats(int statsRowCount)
} }
if (displayLabel) { if (displayLabel) {
displayWrite(osdDisplayPort, 2, top++, " --- STATS ---"); displayWrite(osdDisplayPort, 2, top++, DISPLAYPORT_ATTR_NONE, " --- STATS ---");
} }
for (int i = 0; i < OSD_STAT_COUNT; i++) { for (int i = 0; i < OSD_STAT_COUNT; i++) {
@ -809,7 +809,7 @@ static void osdRefreshStats(void)
static void osdShowArmed(void) static void osdShowArmed(void)
{ {
displayClearScreen(osdDisplayPort); displayClearScreen(osdDisplayPort);
displayWrite(osdDisplayPort, 12, 7, "ARMED"); displayWrite(osdDisplayPort, 12, 7, DISPLAYPORT_ATTR_NONE, "ARMED");
} }
STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs) STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs)

View file

@ -22,6 +22,8 @@
#include "common/time.h" #include "common/time.h"
#include "drivers/display.h"
#include "pg/pg.h" #include "pg/pg.h"
#include "sensors/esc_sensor.h" #include "sensors/esc_sensor.h"
@ -300,7 +302,6 @@ extern float osdGForce;
extern escSensorData_t *osdEscDataCombined; extern escSensorData_t *osdEscDataCombined;
#endif #endif
struct displayPort_s; struct displayPort_s;
void osdInit(struct displayPort_s *osdDisplayPort); void osdInit(struct displayPort_s *osdDisplayPort);
bool osdInitialized(void); bool osdInitialized(void);

View file

@ -211,7 +211,7 @@ static void renderOsdEscRpmOrFreq(getEscRpmOrFreqFnPtr escFnPtr, osdElementParms
const int rpm = MIN((*escFnPtr)(i),99999); const int rpm = MIN((*escFnPtr)(i),99999);
const int len = tfp_sprintf(rpmStr, "%d", rpm); const int len = tfp_sprintf(rpmStr, "%d", rpm);
rpmStr[len] = '\0'; rpmStr[len] = '\0';
displayWrite(element->osdDisplayPort, x, y + i, rpmStr); displayWrite(element->osdDisplayPort, x, y + i, DISPLAYPORT_ATTR_NONE, rpmStr);
} }
element->drawElement = false; element->drawElement = false;
} }
@ -568,7 +568,7 @@ static void osdElementArtificialHorizon(osdElementParms_t *element)
for (int x = -4; x <= 4; x++) { for (int x = -4; x <= 4; x++) {
const int y = ((-rollAngle * x) / 64) - pitchAngle; const int y = ((-rollAngle * x) / 64) - pitchAngle;
if (y >= 0 && y <= 81) { 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 hudwidth = AH_SIDEBAR_WIDTH_POS;
const int8_t hudheight = AH_SIDEBAR_HEIGHT_POS; const int8_t hudheight = AH_SIDEBAR_HEIGHT_POS;
for (int y = -hudheight; y <= hudheight; y++) { 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, DISPLAYPORT_ATTR_NONE, 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);
} }
// AH level indicators // AH level indicators
displayWriteChar(element->osdDisplayPort, element->elemPosX - hudwidth + 1, element->elemPosY, SYM_AH_LEFT); displayWriteChar(element->osdDisplayPort, element->elemPosX - hudwidth + 1, element->elemPosY, DISPLAYPORT_ATTR_NONE, 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_RIGHT);
element->drawElement = false; // element already drawn 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. // Decimal notation can be added when tfp_sprintf supports float among fancy options.
char fmtbuf[6]; char fmtbuf[6];
tfp_sprintf(fmtbuf, "%5d", data); 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++) { for (unsigned y = 0; y < OSD_STICK_OVERLAY_HEIGHT; y++) {
// draw the axes, vertical and horizonal // draw the axes, vertical and horizonal
if ((x == ((OSD_STICK_OVERLAY_WIDTH - 1) / 2)) && (y == (OSD_STICK_OVERLAY_HEIGHT - 1) / 2)) { 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)) { } 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)) { } 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 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); 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 element->drawElement = false; // element already drawn
} }
@ -1235,6 +1235,7 @@ static void osdElementWarnings(osdElementParms_t *element)
} }
tfp_sprintf(element->buff, "%s", armingDisableFlagNames[armingDisabledDisplayIndex]); tfp_sprintf(element->buff, "%s", armingDisableFlagNames[armingDisabledDisplayIndex]);
element->attr = DISPLAYPORT_ATTR_WARNING;
return; return;
} else { } else {
armingDisabledUpdateTimeUs = 0; armingDisabledUpdateTimeUs = 0;
@ -1252,11 +1253,13 @@ static void osdElementWarnings(osdElementParms_t *element)
} else { } else {
tfp_sprintf(element->buff, "ARM IN %d.%d", armingDelayTime / 10, armingDelayTime % 10); tfp_sprintf(element->buff, "ARM IN %d.%d", armingDelayTime / 10, armingDelayTime % 10);
} }
element->attr = DISPLAYPORT_ATTR_INFO;
return; return;
} }
#endif // USE_DSHOT #endif // USE_DSHOT
if (osdWarnGetState(OSD_WARNING_FAIL_SAFE) && failsafeIsActive()) { if (osdWarnGetState(OSD_WARNING_FAIL_SAFE) && failsafeIsActive()) {
tfp_sprintf(element->buff, "FAIL SAFE"); tfp_sprintf(element->buff, "FAIL SAFE");
element->attr = DISPLAYPORT_ATTR_CRITICAL;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1264,6 +1267,7 @@ static void osdElementWarnings(osdElementParms_t *element)
// Warn when in flip over after crash mode // Warn when in flip over after crash mode
if (osdWarnGetState(OSD_WARNING_CRASH_FLIP) && isFlipOverAfterCrashActive()) { if (osdWarnGetState(OSD_WARNING_CRASH_FLIP) && isFlipOverAfterCrashActive()) {
tfp_sprintf(element->buff, "CRASH FLIP"); tfp_sprintf(element->buff, "CRASH FLIP");
element->attr = DISPLAYPORT_ATTR_INFO;
return; return;
} }
@ -1284,6 +1288,8 @@ static void osdElementWarnings(osdElementParms_t *element)
if ( calculateThrottlePercent() >= MAX(currentPidProfile->launchControlThrottlePercent - 10, 0)) { if ( calculateThrottlePercent() >= MAX(currentPidProfile->launchControlThrottlePercent - 10, 0)) {
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
} }
element->attr = DISPLAYPORT_ATTR_INFO;
return; return;
} }
#endif // USE_LAUNCH_CONTROL #endif // USE_LAUNCH_CONTROL
@ -1291,6 +1297,7 @@ static void osdElementWarnings(osdElementParms_t *element)
// RSSI // RSSI
if (osdWarnGetState(OSD_WARNING_RSSI) && (getRssiPercent() < osdConfig()->rssi_alarm)) { if (osdWarnGetState(OSD_WARNING_RSSI) && (getRssiPercent() < osdConfig()->rssi_alarm)) {
tfp_sprintf(element->buff, "RSSI LOW"); tfp_sprintf(element->buff, "RSSI LOW");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1298,6 +1305,7 @@ static void osdElementWarnings(osdElementParms_t *element)
// rssi dbm // rssi dbm
if (osdWarnGetState(OSD_WARNING_RSSI_DBM) && (getRssiDbm() > osdConfig()->rssi_dbm_alarm)) { if (osdWarnGetState(OSD_WARNING_RSSI_DBM) && (getRssiDbm() > osdConfig()->rssi_dbm_alarm)) {
tfp_sprintf(element->buff, "RSSI DBM"); tfp_sprintf(element->buff, "RSSI DBM");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1307,6 +1315,7 @@ static void osdElementWarnings(osdElementParms_t *element)
// Link Quality // Link Quality
if (osdWarnGetState(OSD_WARNING_LINK_QUALITY) && (rxGetLinkQualityPercent() < osdConfig()->link_quality_alarm)) { if (osdWarnGetState(OSD_WARNING_LINK_QUALITY) && (rxGetLinkQualityPercent() < osdConfig()->link_quality_alarm)) {
tfp_sprintf(element->buff, "LINK QUALITY"); tfp_sprintf(element->buff, "LINK QUALITY");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1314,6 +1323,7 @@ static void osdElementWarnings(osdElementParms_t *element)
if (osdWarnGetState(OSD_WARNING_BATTERY_CRITICAL) && batteryState == BATTERY_CRITICAL) { if (osdWarnGetState(OSD_WARNING_BATTERY_CRITICAL) && batteryState == BATTERY_CRITICAL) {
tfp_sprintf(element->buff, " LAND NOW"); tfp_sprintf(element->buff, " LAND NOW");
element->attr = DISPLAYPORT_ATTR_CRITICAL;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1325,6 +1335,7 @@ static void osdElementWarnings(osdElementParms_t *element)
!gpsRescueIsDisabled() && !gpsRescueIsDisabled() &&
!gpsRescueIsAvailable()) { !gpsRescueIsAvailable()) {
tfp_sprintf(element->buff, "RESCUE N/A"); tfp_sprintf(element->buff, "RESCUE N/A");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1337,6 +1348,7 @@ static void osdElementWarnings(osdElementParms_t *element)
statistic_t *stats = osdGetStats(); statistic_t *stats = osdGetStats();
if (cmpTimeUs(stats->armed_time, OSD_GPS_RESCUE_DISABLED_WARNING_DURATION_US) < 0) { if (cmpTimeUs(stats->armed_time, OSD_GPS_RESCUE_DISABLED_WARNING_DURATION_US) < 0) {
tfp_sprintf(element->buff, "RESCUE OFF"); tfp_sprintf(element->buff, "RESCUE OFF");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1347,6 +1359,7 @@ static void osdElementWarnings(osdElementParms_t *element)
// Show warning if in HEADFREE flight mode // Show warning if in HEADFREE flight mode
if (FLIGHT_MODE(HEADFREE_MODE)) { if (FLIGHT_MODE(HEADFREE_MODE)) {
tfp_sprintf(element->buff, "HEADFREE"); tfp_sprintf(element->buff, "HEADFREE");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1355,6 +1368,7 @@ static void osdElementWarnings(osdElementParms_t *element)
const int16_t coreTemperature = getCoreTemperatureCelsius(); const int16_t coreTemperature = getCoreTemperatureCelsius();
if (osdWarnGetState(OSD_WARNING_CORE_TEMPERATURE) && coreTemperature >= osdConfig()->core_temp_alarm) { if (osdWarnGetState(OSD_WARNING_CORE_TEMPERATURE) && coreTemperature >= osdConfig()->core_temp_alarm) {
tfp_sprintf(element->buff, "CORE %c: %3d%c", SYM_TEMPERATURE, osdConvertTemperatureToSelectedUnit(coreTemperature), osdGetTemperatureSymbolForSelectedUnit()); tfp_sprintf(element->buff, "CORE %c: %3d%c", SYM_TEMPERATURE, osdConvertTemperatureToSelectedUnit(coreTemperature), osdGetTemperatureSymbolForSelectedUnit());
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1406,6 +1420,7 @@ static void osdElementWarnings(osdElementParms_t *element)
if (escWarningCount > 0) { if (escWarningCount > 0) {
tfp_sprintf(element->buff, "%s", escWarningMsg); tfp_sprintf(element->buff, "%s", escWarningMsg);
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1414,6 +1429,7 @@ static void osdElementWarnings(osdElementParms_t *element)
if (osdWarnGetState(OSD_WARNING_BATTERY_WARNING) && batteryState == BATTERY_WARNING) { if (osdWarnGetState(OSD_WARNING_BATTERY_WARNING) && batteryState == BATTERY_WARNING) {
tfp_sprintf(element->buff, "LOW BATTERY"); tfp_sprintf(element->buff, "LOW BATTERY");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; return;
} }
@ -1422,6 +1438,7 @@ static void osdElementWarnings(osdElementParms_t *element)
// Show warning if rc smoothing hasn't initialized the filters // Show warning if rc smoothing hasn't initialized the filters
if (osdWarnGetState(OSD_WARNING_RC_SMOOTHING) && ARMING_FLAG(ARMED) && !rcSmoothingInitializationComplete()) { if (osdWarnGetState(OSD_WARNING_RC_SMOOTHING) && ARMING_FLAG(ARMED) && !rcSmoothingInitializationComplete()) {
tfp_sprintf(element->buff, "RCSMOOTHING"); tfp_sprintf(element->buff, "RCSMOOTHING");
element->attr = DISPLAYPORT_ATTR_WARNING;
SET_BLINK(OSD_WARNINGS); SET_BLINK(OSD_WARNINGS);
return; 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) if (osdWarnGetState(OSD_WARNING_BATTERY_NOT_FULL) && !ARMING_FLAG(WAS_EVER_ARMED) && (getBatteryState() == BATTERY_OK)
&& getBatteryAverageCellVoltage() < batteryConfig()->vbatfullcellvoltage) { && getBatteryAverageCellVoltage() < batteryConfig()->vbatfullcellvoltage) {
tfp_sprintf(element->buff, "BATT < FULL"); tfp_sprintf(element->buff, "BATT < FULL");
element->attr = DISPLAYPORT_ATTR_INFO;
return; return;
} }
// Visual beeper // Visual beeper
if (osdWarnGetState(OSD_WARNING_VISUAL_BEEPER) && osdGetVisualBeeperState()) { if (osdWarnGetState(OSD_WARNING_VISUAL_BEEPER) && osdGetVisualBeeperState()) {
tfp_sprintf(element->buff, " * * * *"); tfp_sprintf(element->buff, " * * * *");
element->attr = DISPLAYPORT_ATTR_INFO;
return; return;
} }
@ -1709,11 +1728,12 @@ static void osdDrawSingleElement(displayPort_t *osdDisplayPort, uint8_t item)
element.buff = (char *)&buff; element.buff = (char *)&buff;
element.osdDisplayPort = osdDisplayPort; element.osdDisplayPort = osdDisplayPort;
element.drawElement = true; element.drawElement = true;
element.attr = DISPLAYPORT_ATTR_NONE;
// Call the element drawing function // Call the element drawing function
osdElementDrawFunction[item](&element); osdElementDrawFunction[item](&element);
if (element.drawElement) { 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 // Call the element background drawing function
osdElementBackgroundFunction[item](&element); osdElementBackgroundFunction[item](&element);
if (element.drawElement) { if (element.drawElement) {
displayWrite(osdDisplayPort, elemPosX, elemPosY, buff); displayWrite(osdDisplayPort, elemPosX, elemPosY, DISPLAYPORT_ATTR_NONE, buff);
} }
} }

View file

@ -31,6 +31,7 @@ typedef struct osdElementParms_s {
char *buff; char *buff;
displayPort_t *osdDisplayPort; displayPort_t *osdDisplayPort;
bool drawElement; bool drawElement;
uint8_t attr;
} osdElementParms_t; } osdElementParms_t;
typedef void (*osdElementDrawFn)(osdElementParms_t *element); typedef void (*osdElementDrawFn)(osdElementParms_t *element);

View file

@ -30,6 +30,9 @@ typedef struct displayPortProfile_s {
uint8_t whiteBrightness; uint8_t whiteBrightness;
int8_t displayPortSerial; // serialPortIdentifier_e int8_t displayPortSerial; // serialPortIdentifier_e
// For attribute-rich OSDs
uint8_t attrValues[4]; // NORMAL, INFORMATIONAL, WARNING, CRITICAL
#ifdef USE_DISPLAYPORT_MSP_VENDOR_SPECIFIC #ifdef USE_DISPLAYPORT_MSP_VENDOR_SPECIFIC
uint8_t vendorInitLength; // Actual length of vendorInit byte string uint8_t vendorInitLength; // Actual length of vendorInit byte string
uint8_t vendorInit[253]; // Max 253 bytes of vendor specific initialization byte string uint8_t vendorInit[253]; // Max 253 bytes of vendor specific initialization byte string

View file

@ -67,18 +67,20 @@ static int displayPortTestScreenSize(const displayPort_t *displayPort)
return 0; 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(displayPort);
UNUSED(attr);
for (unsigned int i = 0; i < strlen(s); i++) { for (unsigned int i = 0; i < strlen(s); i++) {
testDisplayPortBuffer[(y * UNITTEST_DISPLAYPORT_COLS) + x + i] = s[i]; testDisplayPortBuffer[(y * UNITTEST_DISPLAYPORT_COLS) + x + i] = s[i];
} }
return 0; 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(displayPort);
UNUSED(attr);
testDisplayPortBuffer[(y * UNITTEST_DISPLAYPORT_COLS) + x] = c; testDisplayPortBuffer[(y * UNITTEST_DISPLAYPORT_COLS) + x] = c;
return 0; return 0;
} }