diff --git a/docs/OSD.md b/docs/OSD.md index 5787496687a..b492e537cef 100644 --- a/docs/OSD.md +++ b/docs/OSD.md @@ -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 diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index c8ae27f270d..2749f016761 100644 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -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) @@ -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); @@ -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) { @@ -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) { @@ -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: diff --git a/src/main/fc/settings.yaml b/src/main/fc/settings.yaml index 6c16ce93b21..00119727f34 100644 --- a/src/main/fc/settings.yaml +++ b/src/main/fc/settings.yaml @@ -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 @@ -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"] diff --git a/src/main/io/osd.c b/src/main/io/osd.c index d682c0299ff..249359d4b6d 100644 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -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; @@ -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(); @@ -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; diff --git a/src/main/io/osd.h b/src/main/io/osd.h index a73db015793..0cf93b69162 100644 --- a/src/main/io/osd.h +++ b/src/main/io/osd.h @@ -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; @@ -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. diff --git a/src/main/io/osd/custom_elements.c b/src/main/io/osd/custom_elements.c index fbd05e2be61..df84ddd76b0 100644 --- a/src/main/io/osd/custom_elements.c +++ b/src/main/io/osd/custom_elements.c @@ -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; @@ -138,4 +236,3 @@ void customElementDrawElement(char *buff, uint8_t customElementIndex){ } prevLength[customElementIndex] = buffSeek; } - diff --git a/src/main/io/osd/custom_elements.h b/src/main/io/osd/custom_elements.h index a55b010f01a..9c12ede6734 100644 --- a/src/main/io/osd/custom_elements.h +++ b/src/main/io/osd/custom_elements.h @@ -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 { diff --git a/src/main/msp/msp_protocol_v2_inav.h b/src/main/msp/msp_protocol_v2_inav.h index 8b4a09e87af..02c8c979aae 100755 --- a/src/main/msp/msp_protocol_v2_inav.h +++ b/src/main/msp/msp_protocol_v2_inav.h @@ -109,7 +109,8 @@ #define MSP2_ADSB_VEHICLE_LIST 0x2090 #define MSP2_INAV_CUSTOM_OSD_ELEMENTS 0x2100 -#define MSP2_INAV_SET_CUSTOM_OSD_ELEMENTS 0x2101 +#define MSP2_INAV_CUSTOM_OSD_ELEMENT 0x2101 +#define MSP2_INAV_SET_CUSTOM_OSD_ELEMENTS 0x2102 #define MSP2_INAV_SERVO_CONFIG 0x2200 #define MSP2_INAV_SET_SERVO_CONFIG 0x2201 \ No newline at end of file