diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index 849a60e306..596dbe4c50 100644 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -775,6 +775,9 @@ static bool mspCommonProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProce for (int i = 0; i < OSD_ITEM_COUNT; i++) { sbufWriteU16(dst, osdConfig()->item_pos[i]); } + for (int i = 0; i < OSD_STAT_COUNT; i++ ) { + sbufWriteU8(dst, osdConfig()->enabled_stats[i]); + } #endif break; } @@ -2039,8 +2042,9 @@ static mspResult_e mspCommonProcessInCommand(uint8_t cmdMSP, sbuf_t *src) case MSP_SET_OSD_CONFIG: { const uint8_t addr = sbufReadU8(src); - // set all the other settings + if ((int8_t)addr == -1) { + /* Set general OSD settings */ #ifdef USE_MAX7456 vcdProfileMutable()->video_system = sbufReadU8(src); #else @@ -2055,10 +2059,17 @@ static mspResult_e mspCommonProcessInCommand(uint8_t cmdMSP, sbuf_t *src) #endif } else { #if defined(OSD) - // set a position setting - const uint16_t pos = sbufReadU16(src); - if (addr < OSD_ITEM_COUNT) { - osdConfigMutable()->item_pos[addr] = pos; + const uint16_t value = sbufReadU16(src); + + /* Get screen index, 0 is post flight statsitsics, 1 and above are in flight OSD screens */ + const uint8_t screen = (sbufBytesRemaining(src) >= 1) ? sbufReadU8(src) : 1; + + if (screen == 0 && addr < OSD_STAT_COUNT) { + /* Set statistic item enable */ + osdConfigMutable()->enabled_stats[addr] = value; + } else if (addr < OSD_ITEM_COUNT) { + /* Set element positions */ + osdConfigMutable()->item_pos[addr] = value; } #else return MSP_RESULT_ERROR; diff --git a/src/main/fc/settings.c b/src/main/fc/settings.c index a2a631bae7..31ecc252cd 100644 --- a/src/main/fc/settings.c +++ b/src/main/fc/settings.c @@ -657,6 +657,16 @@ const clivalue_t valueTable[] = { { "osd_rol_ang_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_ROLL_ANGLE]) }, { "osd_battery_usage_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_MAIN_BATT_USAGE]) }, + { "osd_stat_max_spd", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_MAX_SPEED])}, + { "osd_stat_min_batt", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_MIN_BATTERY])}, + { "osd_stat_min_rssi", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_MIN_RSSI])}, + { "osd_stat_max_curr", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_MAX_CURRENT])}, + { "osd_stat_used_mah", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_USED_MAH])}, + { "osd_stat_max_alt", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_MAX_ALTITUDE])}, + { "osd_stat_bbox", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_BLACKBOX])}, + { "osd_stat_endbatt", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_END_BATTERY])}, + { "osd_stat_flytime", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_FLYTIME])}, + { "osd_stat_armtime", VAR_UINT8 | MASTER_VALUE, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_ARMEDTIME])}, #endif // PG_SYSTEM_CONFIG diff --git a/src/main/io/osd.c b/src/main/io/osd.c index 803d0aca6c..16658509ea 100755 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -120,6 +120,7 @@ typedef struct statistic_s { int16_t max_current; // /10 int16_t min_rssi; int16_t max_altitude; + uint16_t armed_time; } statistic_t; static statistic_t stats; @@ -274,6 +275,13 @@ static void osdDrawSingleElement(uint8_t item) break; } + case OSD_ARMED_TIME: + { + buff[0] = SYM_FLY_M; + tfp_sprintf(buff + 1, "%02d:%02d", stats.armed_time / 60, stats.armed_time % 60); + break; + } + case OSD_FLYMODE: { char *p = "ACRO"; @@ -564,6 +572,7 @@ void osdDrawElements(void) osdDrawSingleElement(OSD_PITCH_ANGLE); osdDrawSingleElement(OSD_ROLL_ANGLE); osdDrawSingleElement(OSD_MAIN_BATT_USAGE); + osdDrawSingleElement(OSD_ARMED_TIME); #ifdef GPS #ifdef CMS @@ -608,13 +617,23 @@ void pgResetFn_osdConfig(osdConfig_t *osdProfile) osdProfile->item_pos[OSD_DEBUG] = OSD_POS(7, 12) | VISIBLE_FLAG; osdProfile->item_pos[OSD_PITCH_ANGLE] = OSD_POS(1, 8) | VISIBLE_FLAG; osdProfile->item_pos[OSD_ROLL_ANGLE] = OSD_POS(1, 9) | VISIBLE_FLAG; - osdProfile->item_pos[OSD_GPS_LAT] = OSD_POS(18, 14) | VISIBLE_FLAG; osdProfile->item_pos[OSD_GPS_LON] = OSD_POS(18, 15) | VISIBLE_FLAG; osdProfile->item_pos[OSD_MAIN_BATT_USAGE] = OSD_POS(15, 10) | VISIBLE_FLAG; + osdProfile->enabled_stats[OSD_STAT_MAX_SPEED] = true; + osdProfile->enabled_stats[OSD_STAT_MIN_BATTERY] = true; + osdProfile->enabled_stats[OSD_STAT_MIN_RSSI] = true; + osdProfile->enabled_stats[OSD_STAT_MAX_CURRENT] = true; + osdProfile->enabled_stats[OSD_STAT_USED_MAH] = true; + osdProfile->enabled_stats[OSD_STAT_MAX_ALTITUDE] = false; + osdProfile->enabled_stats[OSD_STAT_BLACKBOX] = true; + osdProfile->enabled_stats[OSD_STAT_END_BATTERY] = false; + osdProfile->enabled_stats[OSD_STAT_FLYTIME] = false; + osdProfile->enabled_stats[OSD_STAT_ARMEDTIME] = true; osdProfile->units = OSD_UNIT_METRIC; + osdProfile->rssi_alarm = 20; osdProfile->cap_alarm = 2200; osdProfile->time_alarm = 10; // in minutes @@ -736,6 +755,7 @@ static void osdResetStats(void) stats.max_current = 0; stats.min_rssi = 99; stats.max_altitude = 0; + stats.armed_time = 0; } static void osdUpdateStats(void) @@ -804,6 +824,13 @@ static void osdGetBlackboxStatusString(char * buff, uint8_t len) } #endif +static void osdDisplayStatisticLabel(uint8_t y, const char * text, const char * value) +{ + displayWrite(osdDisplayPort, 2, y, text); + displayWrite(osdDisplayPort, 20, y, ":"); + displayWrite(osdDisplayPort, 22, y, value); +} + static void osdShowStats(void) { uint8_t top = 2; @@ -812,43 +839,60 @@ static void osdShowStats(void) displayClearScreen(osdDisplayPort); displayWrite(osdDisplayPort, 2, top++, " --- STATS ---"); - if (STATE(GPS_FIX)) { - displayWrite(osdDisplayPort, 2, top, "MAX SPEED :"); - itoa(stats.max_speed, buff, 10); - displayWrite(osdDisplayPort, 22, top++, buff); + if (osdConfig()->enabled_stats[OSD_STAT_ARMEDTIME]) { + tfp_sprintf(buff, "%02d:%02d", stats.armed_time / 60, stats.armed_time % 60); + osdDisplayStatisticLabel(top++, "ARMED TIME", buff); } - displayWrite(osdDisplayPort, 2, top, "MIN BATTERY :"); - tfp_sprintf(buff, "%d.%1dV", stats.min_voltage / 10, stats.min_voltage % 10); - displayWrite(osdDisplayPort, 22, top++, buff); + if (osdConfig()->enabled_stats[OSD_STAT_FLYTIME]) { + tfp_sprintf(buff, "%02d:%02d", flyTime / 60, flyTime % 60); + osdDisplayStatisticLabel(top++, "FLY TIME", buff); + } - displayWrite(osdDisplayPort, 2, top, "MIN RSSI :"); - itoa(stats.min_rssi, buff, 10); - strcat(buff, "%"); - displayWrite(osdDisplayPort, 22, top++, buff); + if (osdConfig()->enabled_stats[OSD_STAT_MAX_SPEED] && STATE(GPS_FIX)) { + itoa(stats.max_speed, buff, 10); + osdDisplayStatisticLabel(top++, "MAX SPEED", buff); + } + + if (osdConfig()->enabled_stats[OSD_STAT_MIN_BATTERY]) { + tfp_sprintf(buff, "%d.%1dV", stats.min_voltage / 10, stats.min_voltage % 10); + osdDisplayStatisticLabel(top++, "MIN BATTERY", buff); + } + + if (osdConfig()->enabled_stats[OSD_STAT_END_BATTERY]) { + tfp_sprintf(buff, "%d.%1dV", getBatteryVoltage() / 10, getBatteryVoltage() % 10); + osdDisplayStatisticLabel(top++, "END BATTERY", buff); + } + + if (osdConfig()->enabled_stats[OSD_STAT_MIN_RSSI]) { + itoa(stats.min_rssi, buff, 10); + strcat(buff, "%"); + osdDisplayStatisticLabel(top++, "MIN RSSI", buff); + } if (batteryConfig()->currentMeterSource != CURRENT_METER_NONE) { - displayWrite(osdDisplayPort, 2, top, "MAX CURRENT :"); - itoa(stats.max_current, buff, 10); - strcat(buff, "A"); - displayWrite(osdDisplayPort, 22, top++, buff); + if (osdConfig()->enabled_stats[OSD_STAT_MAX_CURRENT]) { + itoa(stats.max_current, buff, 10); + strcat(buff, "A"); + osdDisplayStatisticLabel(top++, "MAX CURRENT", buff); + } - displayWrite(osdDisplayPort, 2, top, "USED MAH :"); - itoa(getMAhDrawn(), buff, 10); - strcat(buff, "\x07"); - displayWrite(osdDisplayPort, 22, top++, buff); + if (osdConfig()->enabled_stats[OSD_STAT_USED_MAH]) { + tfp_sprintf(buff, "%d%c", getMAhDrawn(), SYM_MAH); + osdDisplayStatisticLabel(top++, "USED MAH", buff); + } } - displayWrite(osdDisplayPort, 2, top, "MAX ALTITUDE :"); - int32_t alt = osdGetAltitude(stats.max_altitude); - tfp_sprintf(buff, "%c%d.%01d%c", alt < 0 ? '-' : ' ', abs(alt / 100), abs((alt % 100) / 10), osdGetAltitudeSymbol()); - displayWrite(osdDisplayPort, 22, top++, buff); + if (osdConfig()->enabled_stats[OSD_STAT_MAX_ALTITUDE]) { + int32_t alt = osdGetAltitude(stats.max_altitude); + tfp_sprintf(buff, "%c%d.%01d%c", alt < 0 ? '-' : ' ', abs(alt / 100), abs((alt % 100) / 10), osdGetAltitudeSymbol()); + osdDisplayStatisticLabel(top++, "MAX ALTITUDE", buff); + } #ifdef BLACKBOX - if (blackboxConfig()->device && blackboxConfig()->device != BLACKBOX_DEVICE_SERIAL) { - displayWrite(osdDisplayPort, 2, top, "BLACKBOX :"); + if (osdConfig()->enabled_stats[OSD_STAT_BLACKBOX] && blackboxConfig()->device && blackboxConfig()->device != BLACKBOX_DEVICE_SERIAL) { osdGetBlackboxStatusString(buff, 10); - displayWrite(osdDisplayPort, 22, top++, buff); + osdDisplayStatisticLabel(top++, "BLACKBOX", buff); } #endif } @@ -884,6 +928,7 @@ static void osdRefresh(timeUs_t currentTimeUs) if (ARMING_FLAG(ARMED) && sec != lastSec) { flyTime++; + stats.armed_time++; lastSec = sec; } diff --git a/src/main/io/osd.h b/src/main/io/osd.h index fe5239ad19..0392c924de 100755 --- a/src/main/io/osd.h +++ b/src/main/io/osd.h @@ -56,9 +56,24 @@ typedef enum { OSD_PITCH_ANGLE, OSD_ROLL_ANGLE, OSD_MAIN_BATT_USAGE, + OSD_ARMED_TIME, OSD_ITEM_COUNT // MUST BE LAST } osd_items_e; +typedef enum { + OSD_STAT_MAX_SPEED, + OSD_STAT_MIN_BATTERY, + OSD_STAT_MIN_RSSI, + OSD_STAT_MAX_CURRENT, + OSD_STAT_USED_MAH, + OSD_STAT_MAX_ALTITUDE, + OSD_STAT_BLACKBOX, + OSD_STAT_END_BATTERY, + OSD_STAT_FLYTIME, + OSD_STAT_ARMEDTIME, + OSD_STAT_COUNT // MUST BE LAST +} osd_states_e; + typedef enum { OSD_UNIT_IMPERIAL, OSD_UNIT_METRIC @@ -66,6 +81,7 @@ typedef enum { typedef struct osdConfig_s { uint16_t item_pos[OSD_ITEM_COUNT]; + bool enabled_stats[OSD_STAT_COUNT]; // Alarms uint8_t rssi_alarm;