mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-25 17:25:20 +03:00
Add device local blinking support
This commit is contained in:
parent
f9dacff668
commit
104990c507
6 changed files with 59 additions and 20 deletions
|
@ -1451,6 +1451,7 @@ const clivalue_t valueTable[] = {
|
|||
{ "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) },
|
||||
{ "displayport_msp_use_device_blink", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, useDeviceBlink) },
|
||||
#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) },
|
||||
|
|
|
@ -59,6 +59,9 @@ typedef struct displayPort_s {
|
|||
bool cleared;
|
||||
int8_t cursorRow;
|
||||
int8_t grabCount;
|
||||
|
||||
// Displayport device capability
|
||||
bool useDeviceBlink;
|
||||
} displayPort_t;
|
||||
|
||||
typedef struct displayPortVTable_s {
|
||||
|
|
|
@ -109,7 +109,12 @@ static int writeString(displayPort_t *displayPort, uint8_t col, uint8_t row, uin
|
|||
buf[0] = 3;
|
||||
buf[1] = row;
|
||||
buf[2] = col;
|
||||
buf[3] = displayPortProfileMsp()->attrValues[attr];
|
||||
buf[3] = displayPortProfileMsp()->attrValues[attr] & ~DISPLAYPORT_MSP_ATTR_BLINK & DISPLAYPORT_MSP_ATTR_MASK;
|
||||
|
||||
if (attr & DISPLAYPORT_ATTR_BLINK) {
|
||||
buf[3] |= DISPLAYPORT_MSP_ATTR_BLINK;
|
||||
}
|
||||
|
||||
memcpy(&buf[4], string, len);
|
||||
|
||||
return output(displayPort, MSP_DISPLAYPORT, buf, len + 4);
|
||||
|
@ -185,6 +190,11 @@ displayPort_t *displayPortMspInit(void)
|
|||
#endif
|
||||
|
||||
displayInit(&mspDisplayPort, &mspDisplayPortVTable);
|
||||
|
||||
if (displayPortProfileMsp()->useDeviceBlink) {
|
||||
mspDisplayPort.useDeviceBlink = true;
|
||||
}
|
||||
|
||||
resync(&mspDisplayPort);
|
||||
return &mspDisplayPort;
|
||||
}
|
||||
|
|
|
@ -24,4 +24,9 @@
|
|||
|
||||
#include "pg/displayport_profiles.h"
|
||||
|
||||
displayPort_t *displayPortMspInit(void);
|
||||
// MSP displayport V2 attribute byte bit functions
|
||||
#define DISPLAYPORT_MSP_ATTR_VERSION BIT(7) // Format indicator; must be zero for V2 (and V1)
|
||||
#define DISPLAYPORT_MSP_ATTR_BLINK BIT(6) // Device local blink
|
||||
#define DISPLAYPORT_MSP_ATTR_MASK (~(DISPLAYPORT_MSP_ATTR_VERSION|DISPLAYPORT_MSP_ATTR_BLINK))
|
||||
|
||||
struct displayPort_s *displayPortMspInit(void);
|
||||
|
|
|
@ -180,6 +180,25 @@ static uint32_t blinkBits[(OSD_ITEM_COUNT + 31) / 32];
|
|||
#define IS_BLINK(item) (blinkBits[(item) / 32] & (1 << ((item) % 32)))
|
||||
#define BLINK(item) (IS_BLINK(item) && blinkState)
|
||||
|
||||
static int osdDisplayWrite(osdElementParms_t *element, uint8_t x, uint8_t y, uint8_t attr, const char *s)
|
||||
{
|
||||
if (IS_BLINK(element->item)) {
|
||||
attr |= DISPLAYPORT_ATTR_BLINK;
|
||||
}
|
||||
|
||||
return displayWrite(element->osdDisplayPort, x, y, attr, s);
|
||||
}
|
||||
|
||||
static int osdDisplayWriteChar(osdElementParms_t *element, uint8_t x, uint8_t y, uint8_t attr, char c)
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
|
||||
return osdDisplayWrite(element, x, y, attr, buf);
|
||||
}
|
||||
|
||||
#if defined(USE_ESC_SENSOR) || defined(USE_DSHOT_TELEMETRY)
|
||||
typedef int (*getEscRpmOrFreqFnPtr)(int i);
|
||||
|
||||
|
@ -212,7 +231,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, DISPLAYPORT_ATTR_NONE, rpmStr);
|
||||
osdDisplayWrite(element, x, y + i, DISPLAYPORT_ATTR_NONE, rpmStr);
|
||||
}
|
||||
element->drawElement = false;
|
||||
}
|
||||
|
@ -569,7 +588,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), DISPLAYPORT_ATTR_NONE, (SYM_AH_BAR9_0 + (y % AH_SYMBOL_COUNT)));
|
||||
osdDisplayWriteChar(element, element->elemPosX + x, element->elemPosY + (y / AH_SYMBOL_COUNT), DISPLAYPORT_ATTR_NONE, (SYM_AH_BAR9_0 + (y % AH_SYMBOL_COUNT)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -611,12 +630,12 @@ static void osdBackgroundCameraFrame(osdElementParms_t *element)
|
|||
element->buff[width - 1] = SYM_STICK_OVERLAY_CENTER;
|
||||
element->buff[width] = 0; // string terminator
|
||||
|
||||
displayWrite(element->osdDisplayPort, xpos, ypos, DISPLAYPORT_ATTR_NONE, element->buff);
|
||||
osdDisplayWrite(element, xpos, ypos, DISPLAYPORT_ATTR_NONE, element->buff);
|
||||
for (int i = 1; i < (height - 1); i++) {
|
||||
displayWriteChar(element->osdDisplayPort, xpos, ypos + i, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL);
|
||||
displayWriteChar(element->osdDisplayPort, xpos + width - 1, ypos + i, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL);
|
||||
osdDisplayWriteChar(element, xpos, ypos + i, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL);
|
||||
osdDisplayWriteChar(element, xpos + width - 1, ypos + i, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL);
|
||||
}
|
||||
displayWrite(element->osdDisplayPort, xpos, ypos + height - 1, DISPLAYPORT_ATTR_NONE, element->buff);
|
||||
osdDisplayWrite(element, xpos, ypos + height - 1, DISPLAYPORT_ATTR_NONE, element->buff);
|
||||
|
||||
element->drawElement = false; // element already drawn
|
||||
}
|
||||
|
@ -911,13 +930,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, DISPLAYPORT_ATTR_NONE, SYM_AH_DECORATION);
|
||||
displayWriteChar(element->osdDisplayPort, element->elemPosX + hudwidth, element->elemPosY + y, DISPLAYPORT_ATTR_NONE, SYM_AH_DECORATION);
|
||||
osdDisplayWriteChar(element, element->elemPosX - hudwidth, element->elemPosY + y, DISPLAYPORT_ATTR_NONE, SYM_AH_DECORATION);
|
||||
osdDisplayWriteChar(element, element->elemPosX + hudwidth, element->elemPosY + y, DISPLAYPORT_ATTR_NONE, SYM_AH_DECORATION);
|
||||
}
|
||||
|
||||
// AH level indicators
|
||||
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);
|
||||
osdDisplayWriteChar(element, element->elemPosX - hudwidth + 1, element->elemPosY, DISPLAYPORT_ATTR_NONE, SYM_AH_LEFT);
|
||||
osdDisplayWriteChar(element, element->elemPosX + hudwidth - 1, element->elemPosY, DISPLAYPORT_ATTR_NONE, SYM_AH_RIGHT);
|
||||
|
||||
element->drawElement = false; // element already drawn
|
||||
}
|
||||
|
@ -1081,7 +1100,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, DISPLAYPORT_ATTR_NONE, fmtbuf);
|
||||
osdDisplayWrite(element, xpos, ypos + i, DISPLAYPORT_ATTR_NONE, fmtbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1137,11 +1156,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, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_CENTER);
|
||||
osdDisplayWriteChar(element, 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, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_VERTICAL);
|
||||
osdDisplayWriteChar(element, 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, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_HORIZONTAL);
|
||||
osdDisplayWriteChar(element, xpos + x, ypos + y, DISPLAYPORT_ATTR_NONE, SYM_STICK_OVERLAY_HORIZONTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1169,7 +1188,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, DISPLAYPORT_ATTR_NONE, cursor);
|
||||
osdDisplayWriteChar(element, xpos + cursorX, ypos + cursorY / OSD_STICK_OVERLAY_SPRITE_HEIGHT, DISPLAYPORT_ATTR_NONE, cursor);
|
||||
|
||||
element->drawElement = false; // element already drawn
|
||||
}
|
||||
|
@ -1742,7 +1761,7 @@ static void osdDrawSingleElement(displayPort_t *osdDisplayPort, uint8_t item)
|
|||
// Element has no drawing function
|
||||
return;
|
||||
}
|
||||
if (BLINK(item)) {
|
||||
if (!osdDisplayPort->useDeviceBlink && BLINK(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1762,7 +1781,7 @@ static void osdDrawSingleElement(displayPort_t *osdDisplayPort, uint8_t item)
|
|||
// Call the element drawing function
|
||||
osdElementDrawFunction[item](&element);
|
||||
if (element.drawElement) {
|
||||
displayWrite(osdDisplayPort, elemPosX, elemPosY, element.attr, buff);
|
||||
osdDisplayWrite(&element, elemPosX, elemPosY, element.attr, buff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1788,7 +1807,7 @@ static void osdDrawSingleElementBackground(displayPort_t *osdDisplayPort, uint8_
|
|||
// Call the element background drawing function
|
||||
osdElementBackgroundFunction[item](&element);
|
||||
if (element.drawElement) {
|
||||
displayWrite(osdDisplayPort, elemPosX, elemPosY, DISPLAYPORT_ATTR_NONE, buff);
|
||||
osdDisplayWrite(&element, elemPosX, elemPosY, DISPLAYPORT_ATTR_NONE, buff);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ typedef struct displayPortProfile_s {
|
|||
// For attribute-rich OSDs
|
||||
|
||||
uint8_t attrValues[4]; // NORMAL, INFORMATIONAL, WARNING, CRITICAL
|
||||
uint8_t useDeviceBlink; // Use device local blink capability
|
||||
#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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue