Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance OSD Custom Elements #10282

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion docs/OSD.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,18 @@ Here are the OSD Elements provided by INAV.
| 144 | OSD_MULTI_FUNCTION | 7.0.0 | |
| 145 | OSD_ODOMETER | 7.0.0 | For this to work correctly, stats must be enabled (`set stats=ON`). Otherwise, this will show the total flight distance. |
| 146 | OSD_PILOT_LOGO | 7.0.0 | |
| 147 | OSD_BLACKBOX | 8.0.0 | The element will be hidden unless blackbox recording is attempted. |
| 147 | OSD_CUSTOM_ELEMENT_1 | 7.0.0 | |
| 148 | OSD_CUSTOM_ELEMENT_2 | 7.0.0 | |
| 149 | OSD_CUSTOM_ELEMENT_3 | 7.0.0 | |
| 150 | OSD_ADSB_WARNING | 7.0.0 | |
| 151 | OSD_ADSB_INFO | 7.0.0 | |
| 152 | OSD_BLACKBOX | 8.0.0 | The element will be hidden unless blackbox recording is attempted. |
| 153 | OSD_FORMATION_FLIGHT | 8.0.0 | |
| 154 | OSD_CUSTOM_ELEMENT_4 | 8.0.0 | |
| 155 | OSD_CUSTOM_ELEMENT_5 | 8.0.0 | |
| 156 | OSD_CUSTOM_ELEMENT_6 | 8.0.0 | |
| 157 | OSD_CUSTOM_ELEMENT_7 | 8.0.0 | |
| 158 | OSD_CUSTOM_ELEMENT_8 | 8.0.0 | |

# Pilot Logos

Expand Down
44 changes: 26 additions & 18 deletions src/main/fc/fc_msp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1706,28 +1706,19 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
#endif
#ifdef USE_PROGRAMMING_FRAMEWORK
case MSP2_INAV_CUSTOM_OSD_ELEMENTS:
sbufWriteU8(dst, MAX_CUSTOM_ELEMENTS);
sbufWriteU8(dst, OSD_CUSTOM_ELEMENT_TEXT_SIZE - 1);

for (int i = 0; i < MAX_CUSTOM_ELEMENTS; i++) {
const osdCustomElement_t *customElement = osdCustomElements(i);
for (int ii = 0; ii < CUSTOM_ELEMENTS_PARTS; ii++) {
sbufWriteU8(dst, customElement->part[ii].type);
sbufWriteU16(dst, customElement->part[ii].value);
}
sbufWriteU8(dst, customElement->visibility.type);
sbufWriteU16(dst, customElement->visibility.value);
for (int ii = 0; ii < OSD_CUSTOM_ELEMENT_TEXT_SIZE - 1; ii++) {
sbufWriteU8(dst, customElement->osdCustomElementText[ii]);
}
{
sbufWriteU8(dst, MAX_CUSTOM_ELEMENTS);
sbufWriteU8(dst, OSD_CUSTOM_ELEMENT_TEXT_SIZE - 1);
sbufWriteU8(dst, CUSTOM_ELEMENTS_PARTS);
}
break;
#endif
default:
return false;
}
return true;
}
#endif


#ifdef USE_SAFE_HOME
static mspResult_e mspFcSafeHomeOutCommand(sbuf_t *dst, sbuf_t *src)
Expand Down Expand Up @@ -3349,7 +3340,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
#ifdef USE_PROGRAMMING_FRAMEWORK
case MSP2_INAV_SET_CUSTOM_OSD_ELEMENTS:
sbufReadU8Safe(&tmp_u8, src);
if ((dataSize == (OSD_CUSTOM_ELEMENT_TEXT_SIZE - 1) + (MAX_CUSTOM_ELEMENTS * 3) + 4) && (tmp_u8 < MAX_CUSTOM_ELEMENTS)) {
if ((dataSize == (OSD_CUSTOM_ELEMENT_TEXT_SIZE - 1) + (CUSTOM_ELEMENTS_PARTS * 3) + 4) && (tmp_u8 < MAX_CUSTOM_ELEMENTS)) {
for (int i = 0; i < CUSTOM_ELEMENTS_PARTS; i++) {
osdCustomElementsMutable(tmp_u8)->part[i].type = sbufReadU8(src);
osdCustomElementsMutable(tmp_u8)->part[i].value = sbufReadU16(src);
Expand All @@ -3365,7 +3356,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
}

break;

#endif
case MSP2_BETAFLIGHT_BIND:
if (rxConfig()->receiverType == RX_TYPE_SERIAL) {
switch (rxConfig()->serialrx_provider) {
Expand All @@ -3392,7 +3383,6 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
}
return MSP_RESULT_ACK;
}
#endif

static const setting_t *mspReadSetting(sbuf_t *src)
{
Expand Down Expand Up @@ -3849,6 +3839,24 @@ bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResu
case MSP2_INAV_LOGIC_CONDITIONS_SINGLE:
*ret = mspFcLogicConditionCommand(dst, src);
break;
case MSP2_INAV_CUSTOM_OSD_ELEMENT:
{
const uint8_t idx = sbufReadU8(src);

if (idx < MAX_CUSTOM_ELEMENTS) {
const osdCustomElement_t *customElement = osdCustomElements(idx);
for (int ii = 0; ii < CUSTOM_ELEMENTS_PARTS; ii++) {
sbufWriteU8(dst, customElement->part[ii].type);
sbufWriteU16(dst, customElement->part[ii].value);
}
sbufWriteU8(dst, customElement->visibility.type);
sbufWriteU16(dst, customElement->visibility.value);
for (int ii = 0; ii < OSD_CUSTOM_ELEMENT_TEXT_SIZE - 1; ii++) {
sbufWriteU8(dst, customElement->osdCustomElementText[ii]);
}
}
}
break;
#endif
#ifdef USE_SAFE_HOME
case MSP2_INAV_SAFEHOME:
Expand Down
22 changes: 11 additions & 11 deletions src/main/fc/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3706,6 +3706,17 @@ groups:
min: 1000
max: 5000
default_value: 1500
- name: osd_system_msg_display_time
description: System message display cycle time for multiple messages (milliseconds).
field: system_msg_display_time
default_value: 1000
min: 500
max: 5000
- name: osd_highlight_djis_missing_font_symbols
description: Show question marks where there is no symbol in the DJI font to represent the INAV OSD element's symbol. When off, blank spaces will be used. Only relevent for DJICOMPAT modes.
field: highlight_djis_missing_characters
default_value: ON
type: bool
- name: osd_switch_indicator_zero_name
description: "Character to use for OSD switch incicator 0."
field: osd_switch_indicator0_name
Expand Down Expand Up @@ -3759,17 +3770,6 @@ groups:
field: osd_switch_indicators_align_left
type: bool
default_value: ON
- name: osd_system_msg_display_time
description: System message display cycle time for multiple messages (milliseconds).
field: system_msg_display_time
default_value: 1000
min: 500
max: 5000
- name: osd_highlight_djis_missing_font_symbols
description: Show question marks where there is no symbol in the DJI font to represent the INAV OSD element's symbol. When off, blank spaces will be used. Only relevent for DJICOMPAT modes.
field: highlight_djis_missing_characters
default_value: ON
type: bool
- name: PG_OSD_COMMON_CONFIG
type: osdCommonConfig_t
headers: ["io/osd_common.h"]
Expand Down
28 changes: 26 additions & 2 deletions src/main/io/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ static bool osdDisplayHasCanvas;
#define AH_MAX_PITCH_DEFAULT 20 // Specify default maximum AHI pitch value displayed (degrees)

PG_REGISTER_WITH_RESET_TEMPLATE(osdConfig_t, osdConfig, PG_OSD_CONFIG, 12);
PG_REGISTER_WITH_RESET_FN(osdLayoutsConfig_t, osdLayoutsConfig, PG_OSD_LAYOUTS_CONFIG, 1);
PG_REGISTER_WITH_RESET_FN(osdLayoutsConfig_t, osdLayoutsConfig, PG_OSD_LAYOUTS_CONFIG, 2);

void osdStartedSaveProcess(void) {
savingSettings = true;
Expand Down Expand Up @@ -1671,6 +1671,31 @@ static bool osdDrawSingleElement(uint8_t item)
customElementDrawElement(buff, 2);
break;
}
case OSD_CUSTOM_ELEMENT_4:
{
customElementDrawElement(buff, 3);
break;
}
case OSD_CUSTOM_ELEMENT_5:
{
customElementDrawElement(buff, 4);
break;
}
case OSD_CUSTOM_ELEMENT_6:
{
customElementDrawElement(buff, 5);
break;
}
case OSD_CUSTOM_ELEMENT_7:
{
customElementDrawElement(buff, 6);
break;
}
case OSD_CUSTOM_ELEMENT_8:
{
customElementDrawElement(buff, 7);
break;
}
case OSD_RSSI_VALUE:
{
uint16_t osdRssi = osdConvertRSSI();
Expand Down Expand Up @@ -2872,7 +2897,6 @@ static bool osdDrawSingleElement(uint8_t item)
break;
}
#endif

case OSD_SWITCH_INDICATOR_0:
osdDisplaySwitchIndicator(osdConfig()->osd_switch_indicator0_name, rxGetChannelValue(osdConfig()->osd_switch_indicator0_channel - 1), buff);
break;
Expand Down
9 changes: 7 additions & 2 deletions src/main/io/osd.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,12 @@ typedef enum {
OSD_ADSB_WARNING, //150
OSD_ADSB_INFO,
OSD_BLACKBOX,
OSD_FORMATION_FLIGHT, //153
OSD_FORMATION_FLIGHT,
OSD_CUSTOM_ELEMENT_4,
OSD_CUSTOM_ELEMENT_5,
OSD_CUSTOM_ELEMENT_6,
OSD_CUSTOM_ELEMENT_7,
OSD_CUSTOM_ELEMENT_8, // 158
OSD_ITEM_COUNT // MUST BE LAST
} osd_items_e;

Expand Down Expand Up @@ -444,7 +449,7 @@ typedef struct osdConfig_s {
uint8_t telemetry; // use telemetry on displayed pixel line 0
uint8_t esc_rpm_precision; // Number of characters used for the RPM numbers.
uint16_t system_msg_display_time; // system message display time for multiple messages (ms)
uint8_t mAh_precision; // Number of numbers used for mAh drawn. Plently of packs now are > 9999 mAh
uint8_t mAh_precision; // Number of numbers used for mAh drawn. Plently of packs now are > 9999 mAh
uint8_t ahi_pitch_interval; // redraws AHI at set pitch interval (Not pixel OSD)
char osd_switch_indicator0_name[OSD_SWITCH_INDICATOR_NAME_LENGTH + 1]; // Name to use for switch indicator 0.
uint8_t osd_switch_indicator0_channel; // RC Channel to use for switch indicator 0.
Expand Down
117 changes: 107 additions & 10 deletions src/main/io/osd/custom_elements.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,31 +68,129 @@ uint8_t customElementDrawPart(char *buff, uint8_t customElementIndex, uint8_t cu
const int customPartValue = osdCustomElements(customElementIndex)->part[customElementItemIndex].value;

switch (customPartType) {
case CUSTOM_ELEMENT_TYPE_GV:
case CUSTOM_ELEMENT_TYPE_GV_1:
{
osdFormatCentiNumber(buff, (int32_t) gvGet(customPartValue) * (int32_t) 100, 1, 0, 0, 6, false);
return 6;
osdFormatCentiNumber(buff,(int32_t) (constrain(gvGet(customPartValue), -9, 9) * (int32_t) 100), 1, 0, 0, 2, false);
return 2;
}
case CUSTOM_ELEMENT_TYPE_GV_2:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -99, 99) * (int32_t) 100), 1, 0, 0, 3, false);
return 3;
}
case CUSTOM_ELEMENT_TYPE_GV_3:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -999, 999) * (int32_t) 100), 1, 0, 0, 4, false);
return 4;
}
case CUSTOM_ELEMENT_TYPE_GV_FLOAT:
case CUSTOM_ELEMENT_TYPE_GV_4:
{
osdFormatCentiNumber(buff, (int32_t) gvGet(customPartValue), 1, 2, 0, 6, false);
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -9999, 9999) * (int32_t) 100), 1, 0, 0, 5, false);
return 5;
}
case CUSTOM_ELEMENT_TYPE_GV_5:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -99999, 99999) * (int32_t) 100), 1, 0, 0, 6, false);
return 6;
}
case CUSTOM_ELEMENT_TYPE_GV_SMALL:
case CUSTOM_ELEMENT_TYPE_GV_FLOAT_1_1:
{
osdFormatCentiNumber(buff, (int32_t) ((gvGet(customPartValue) % 1000 ) * (int32_t) 100), 1, 0, 0, 3, false);
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -99, 99) * (int32_t) 10), 1, 1, 0, 3, false);
return 3;
}
case CUSTOM_ELEMENT_TYPE_GV_SMALL_FLOAT:
case CUSTOM_ELEMENT_TYPE_GV_FLOAT_2_1:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -999, 999) * (int32_t) 10), 1, 1, 0, 4, false);
return 4;
}
case CUSTOM_ELEMENT_TYPE_GV_FLOAT_2_2:
{
osdFormatCentiNumber(buff, (int32_t) constrain(gvGet(customPartValue), -9999, 9999), 1, 2, 0, 5, false);
return 5;
}
case CUSTOM_ELEMENT_TYPE_GV_FLOAT_3_1:
{
osdFormatCentiNumber(buff, (int32_t) ((gvGet(customPartValue) % 100) * (int32_t) 10), 1, 1, 0, 2, false);
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -9999, 9999) * (int32_t) 10), 1, 1, 0, 5, false);
return 5;
}
case CUSTOM_ELEMENT_TYPE_GV_FLOAT_3_2:
{
osdFormatCentiNumber(buff, (int32_t) constrain(gvGet(customPartValue), -99999, 99999), 1, 2, 0, 6, false);
return 6;
}
case CUSTOM_ELEMENT_TYPE_GV_FLOAT_4_1:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(gvGet(customPartValue), -99999, 99999) * (int32_t) 10), 1, 1, 0, 6, false);
return 6;
}

case CUSTOM_ELEMENT_TYPE_LC_1:
{
osdFormatCentiNumber(buff,(int32_t) (constrain(logicConditionGetValue(customPartValue), -9, 9) * (int32_t) 100), 1, 0, 0, 2, false);
return 2;
}
case CUSTOM_ELEMENT_TYPE_LC_2:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -99, 99) * (int32_t) 100), 1, 0, 0, 3, false);
return 3;
}
case CUSTOM_ELEMENT_TYPE_LC_3:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -999, 999) * (int32_t) 100), 1, 0, 0, 4, false);
return 4;
}
case CUSTOM_ELEMENT_TYPE_LC_4:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -9999, 9999) * (int32_t) 100), 1, 0, 0, 5, false);
return 5;
}
case CUSTOM_ELEMENT_TYPE_LC_5:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -99999, 99999) * (int32_t) 100), 1, 0, 0, 6, false);
return 6;
}
case CUSTOM_ELEMENT_TYPE_LC_FLOAT_1_1:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -99, 99) * (int32_t) 10), 1, 1, 0, 3, false);
return 3;
}
case CUSTOM_ELEMENT_TYPE_LC_FLOAT_2_1:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -999, 999) * (int32_t) 10), 1, 1, 0, 4, false);
return 4;
}
case CUSTOM_ELEMENT_TYPE_LC_FLOAT_2_2:
{
osdFormatCentiNumber(buff, (int32_t) constrain(logicConditionGetValue(customPartValue), -9999, 9999), 1, 2, 0, 5, false);
return 5;
}
case CUSTOM_ELEMENT_TYPE_LC_FLOAT_3_1:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -9999, 9999) * (int32_t) 10), 1, 1, 0, 5, false);
return 5;
}
case CUSTOM_ELEMENT_TYPE_LC_FLOAT_3_2:
{
osdFormatCentiNumber(buff, (int32_t) constrain(logicConditionGetValue(customPartValue), -99999, 99999), 1, 2, 0, 6, false);
return 6;
}
case CUSTOM_ELEMENT_TYPE_LC_FLOAT_4_1:
{
osdFormatCentiNumber(buff, (int32_t) (constrain(logicConditionGetValue(customPartValue), -99999, 99999) * (int32_t) 10), 1, 1, 0, 6, false);
return 6;
}


case CUSTOM_ELEMENT_TYPE_ICON_GV:
{
*buff = (uint8_t)gvGet(customPartValue);
return 1;
}
case CUSTOM_ELEMENT_TYPE_ICON_LC:
{
*buff = (uint8_t)constrain(logicConditionGetValue(customPartValue), 1, 255);
return 1;
}
case CUSTOM_ELEMENT_TYPE_ICON_STATIC:
{
*buff = (uint8_t)customPartValue;
Expand Down Expand Up @@ -138,4 +236,3 @@ void customElementDrawElement(char *buff, uint8_t customElementIndex){
}
prevLength[customElementIndex] = buffSeek;
}

29 changes: 24 additions & 5 deletions src/main/io/osd/custom_elements.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,36 @@

#define OSD_CUSTOM_ELEMENT_TEXT_SIZE 16
#define CUSTOM_ELEMENTS_PARTS 3
#define MAX_CUSTOM_ELEMENTS 3
#define MAX_CUSTOM_ELEMENTS 8

typedef enum {
CUSTOM_ELEMENT_TYPE_NONE = 0,
CUSTOM_ELEMENT_TYPE_TEXT = 1,
CUSTOM_ELEMENT_TYPE_ICON_STATIC = 2,
CUSTOM_ELEMENT_TYPE_ICON_GV = 3,
CUSTOM_ELEMENT_TYPE_GV = 4,
CUSTOM_ELEMENT_TYPE_GV_FLOAT = 5,
CUSTOM_ELEMENT_TYPE_GV_SMALL = 6,
CUSTOM_ELEMENT_TYPE_GV_SMALL_FLOAT = 7,
CUSTOM_ELEMENT_TYPE_ICON_LC = 4,
CUSTOM_ELEMENT_TYPE_GV_1 = 5,
CUSTOM_ELEMENT_TYPE_GV_2 = 6,
CUSTOM_ELEMENT_TYPE_GV_3 = 7,
CUSTOM_ELEMENT_TYPE_GV_4 = 8,
CUSTOM_ELEMENT_TYPE_GV_5 = 9,
CUSTOM_ELEMENT_TYPE_GV_FLOAT_1_1 = 10,
CUSTOM_ELEMENT_TYPE_GV_FLOAT_2_1 = 11,
CUSTOM_ELEMENT_TYPE_GV_FLOAT_2_2 = 12,
CUSTOM_ELEMENT_TYPE_GV_FLOAT_3_1 = 13,
CUSTOM_ELEMENT_TYPE_GV_FLOAT_3_2 = 14,
CUSTOM_ELEMENT_TYPE_GV_FLOAT_4_1 = 15,
CUSTOM_ELEMENT_TYPE_LC_1 = 16,
CUSTOM_ELEMENT_TYPE_LC_2 = 17,
CUSTOM_ELEMENT_TYPE_LC_3 = 18,
CUSTOM_ELEMENT_TYPE_LC_4 = 19,
CUSTOM_ELEMENT_TYPE_LC_5 = 20,
CUSTOM_ELEMENT_TYPE_LC_FLOAT_1_1 = 21,
CUSTOM_ELEMENT_TYPE_LC_FLOAT_2_1 = 22,
CUSTOM_ELEMENT_TYPE_LC_FLOAT_2_2 = 23,
CUSTOM_ELEMENT_TYPE_LC_FLOAT_3_1 = 24,
CUSTOM_ELEMENT_TYPE_LC_FLOAT_3_2 = 25,
CUSTOM_ELEMENT_TYPE_LC_FLOAT_4_1 = 26,
} osdCustomElementType_e;

typedef enum {
Expand Down
Loading
Loading