1
0
Fork 0
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:
jflyper 2019-11-22 23:52:01 +09:00
parent f9dacff668
commit 104990c507
6 changed files with 59 additions and 20 deletions

View file

@ -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) },

View file

@ -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 {

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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