mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-24 16:55:36 +03:00
Disconnect OSD stats display from storage bit position order
Allows reordering OSD post-flight statistics without affecting the storage bit position and requiring Configurator changes. Previously the display order was one and the same with the enabled flag bit position. Additionally this ordering was also used by the configurator. So if the ordering was changed then the user settings would become corrupted (different stats would be enabled/disabled). Also the Configurator had an internal representation that had to match the definition enumeration otherwise the flags returned when saving would also set the wrong bits. Now the definition remains constant and unchanging. The bit positions for the enable flag will not be changed. A separate array defines the presentaion order of the permanent stats ID's. Added the display order to MSP to allow the configurator to also present the stats in the same order displayed in the firmware.
This commit is contained in:
parent
534938b943
commit
1b8fd99126
3 changed files with 256 additions and 174 deletions
|
@ -822,6 +822,12 @@ static bool mspCommonProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProce
|
|||
sbufWriteU8(dst, 0);
|
||||
#endif // USE_OSD_STICK_OVERLAY
|
||||
|
||||
// API >= 1.42
|
||||
// Post-flight stats display order
|
||||
for (int i = 0; i < OSD_STAT_COUNT; i++) {
|
||||
sbufWriteU8(dst, osdStatsDisplayOrder[i]);
|
||||
}
|
||||
|
||||
#endif // USE_OSD
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -130,6 +130,39 @@ escSensorData_t *osdEscDataCombined;
|
|||
|
||||
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 6);
|
||||
|
||||
// Controls the display order of the OSD post-flight statistics.
|
||||
// Adjust the ordering here to control how the post-flight stats are presented.
|
||||
// Every entry in osd_stats_e should be represented. Any that are missing will not
|
||||
// be shown on the the post-flight statistics page.
|
||||
// If you reorder the stats it's likely that you'll need to make likewise updates
|
||||
// to the unit tests.
|
||||
const osd_stats_e osdStatsDisplayOrder[OSD_STAT_COUNT] = {
|
||||
OSD_STAT_RTC_DATE_TIME,
|
||||
OSD_STAT_TIMER_1,
|
||||
OSD_STAT_TIMER_2,
|
||||
OSD_STAT_MAX_ALTITUDE,
|
||||
OSD_STAT_MAX_SPEED,
|
||||
OSD_STAT_MAX_DISTANCE,
|
||||
OSD_STAT_FLIGHT_DISTANCE,
|
||||
OSD_STAT_MIN_BATTERY,
|
||||
OSD_STAT_END_BATTERY,
|
||||
OSD_STAT_BATTERY,
|
||||
OSD_STAT_MIN_RSSI,
|
||||
OSD_STAT_MAX_CURRENT,
|
||||
OSD_STAT_USED_MAH,
|
||||
OSD_STAT_BLACKBOX,
|
||||
OSD_STAT_BLACKBOX_NUMBER,
|
||||
OSD_STAT_MAX_G_FORCE,
|
||||
OSD_STAT_MAX_ESC_TEMP,
|
||||
OSD_STAT_MAX_ESC_RPM,
|
||||
OSD_STAT_MIN_LINK_QUALITY,
|
||||
OSD_STAT_MAX_FFT,
|
||||
OSD_STAT_MIN_RSSI_DBM,
|
||||
OSD_STAT_TOTAL_FLIGHTS,
|
||||
OSD_STAT_TOTAL_TIME,
|
||||
OSD_STAT_TOTAL_DIST,
|
||||
};
|
||||
|
||||
void osdStatSetState(uint8_t statIndex, bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
|
@ -339,6 +372,7 @@ static void osdResetStats(void)
|
|||
stats.max_current = 0;
|
||||
stats.max_speed = 0;
|
||||
stats.min_voltage = 5000;
|
||||
stats.end_voltage = 0;
|
||||
stats.min_rssi = 99; // percent
|
||||
stats.max_altitude = 0;
|
||||
stats.max_distance = 0;
|
||||
|
@ -490,10 +524,207 @@ static bool isSomeStatEnabled(void)
|
|||
// on the stats screen will have to be more beneficial than the hassle of not matching exactly to the
|
||||
// configurator list.
|
||||
|
||||
static uint8_t osdShowStats(uint16_t endBatteryVoltage, int statsRowCount)
|
||||
static bool osdDisplayStat(int statistic, uint8_t displayRow)
|
||||
{
|
||||
char buff[OSD_ELEMENT_BUFFER_LENGTH];
|
||||
|
||||
switch (statistic) {
|
||||
case OSD_STAT_RTC_DATE_TIME: {
|
||||
bool success = false;
|
||||
#ifdef USE_RTC_TIME
|
||||
success = osdFormatRtcDateTime(&buff[0]);
|
||||
#endif
|
||||
if (!success) {
|
||||
tfp_sprintf(buff, "NO RTC");
|
||||
}
|
||||
|
||||
displayWrite(osdDisplayPort, 2, displayRow, buff);
|
||||
return true;
|
||||
}
|
||||
|
||||
case OSD_STAT_TIMER_1:
|
||||
osdFormatTimer(buff, false, (OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_1]) == OSD_TIMER_SRC_ON ? false : true), OSD_TIMER_1);
|
||||
osdDisplayStatisticLabel(displayRow, osdTimerSourceNames[OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_1])], buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_TIMER_2:
|
||||
osdFormatTimer(buff, false, (OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_2]) == OSD_TIMER_SRC_ON ? false : true), OSD_TIMER_2);
|
||||
osdDisplayStatisticLabel(displayRow, osdTimerSourceNames[OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_2])], buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_MAX_ALTITUDE: {
|
||||
const int alt = osdGetMetersToSelectedUnit(stats.max_altitude) / 10;
|
||||
tfp_sprintf(buff, "%d.%d%c", alt / 10, alt % 10, osdGetMetersToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(displayRow, "MAX ALTITUDE", buff);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_GPS
|
||||
case OSD_STAT_MAX_SPEED:
|
||||
if (featureIsEnabled(FEATURE_GPS)) {
|
||||
tfp_sprintf(buff, "%d%c", osdGetSpeedToSelectedUnit(stats.max_speed), osdGetSpeedToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(displayRow, "MAX SPEED", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSD_STAT_MAX_DISTANCE:
|
||||
if (featureIsEnabled(FEATURE_GPS)) {
|
||||
tfp_sprintf(buff, "%d%c", osdGetMetersToSelectedUnit(stats.max_distance), osdGetMetersToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(displayRow, "MAX DISTANCE", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSD_STAT_FLIGHT_DISTANCE:
|
||||
if (featureIsEnabled(FEATURE_GPS)) {
|
||||
const uint32_t distanceFlown = GPS_distanceFlownInCm / 100;
|
||||
tfp_sprintf(buff, "%d%c", osdGetMetersToSelectedUnit(distanceFlown), osdGetMetersToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(displayRow, "FLIGHT DISTANCE", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case OSD_STAT_MIN_BATTERY:
|
||||
tfp_sprintf(buff, "%d.%02d%c", stats.min_voltage / 100, stats.min_voltage % 100, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(displayRow, "MIN BATTERY", buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_END_BATTERY:
|
||||
tfp_sprintf(buff, "%d.%02d%c", stats.end_voltage / 100, stats.end_voltage % 100, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(displayRow, "END BATTERY", buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_BATTERY:
|
||||
tfp_sprintf(buff, "%d.%02d%c", getBatteryVoltage() / 100, getBatteryVoltage() % 100, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(displayRow, "BATTERY", buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_MIN_RSSI:
|
||||
itoa(stats.min_rssi, buff, 10);
|
||||
strcat(buff, "%");
|
||||
osdDisplayStatisticLabel(displayRow, "MIN RSSI", buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_MAX_CURRENT:
|
||||
if (batteryConfig()->currentMeterSource != CURRENT_METER_NONE) {
|
||||
tfp_sprintf(buff, "%d%c", stats.max_current, SYM_AMP);
|
||||
osdDisplayStatisticLabel(displayRow, "MAX CURRENT", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSD_STAT_USED_MAH:
|
||||
if (batteryConfig()->currentMeterSource != CURRENT_METER_NONE) {
|
||||
tfp_sprintf(buff, "%d%c", getMAhDrawn(), SYM_MAH);
|
||||
osdDisplayStatisticLabel(displayRow, "USED MAH", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef USE_BLACKBOX
|
||||
case OSD_STAT_BLACKBOX:
|
||||
if (blackboxConfig()->device && blackboxConfig()->device != BLACKBOX_DEVICE_SERIAL) {
|
||||
osdGetBlackboxStatusString(buff);
|
||||
osdDisplayStatisticLabel(displayRow, "BLACKBOX", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSD_STAT_BLACKBOX_NUMBER:
|
||||
if (blackboxConfig()->device && blackboxConfig()->device != BLACKBOX_DEVICE_SERIAL) {
|
||||
itoa(blackboxGetLogNumber(), buff, 10);
|
||||
osdDisplayStatisticLabel(displayRow, "BB LOG NUM", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(USE_ACC)
|
||||
case OSD_STAT_MAX_G_FORCE:
|
||||
if (sensors(SENSOR_ACC)) {
|
||||
const int gForce = lrintf(stats.max_g_force * 10);
|
||||
tfp_sprintf(buff, "%01d.%01dG", gForce / 10, gForce % 10);
|
||||
osdDisplayStatisticLabel(displayRow, "MAX G-FORCE", buff);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
case OSD_STAT_MAX_ESC_TEMP:
|
||||
tfp_sprintf(buff, "%d%c", osdConvertTemperatureToSelectedUnit(stats.max_esc_temp), osdGetTemperatureSymbolForSelectedUnit());
|
||||
osdDisplayStatisticLabel(displayRow, "MAX ESC TEMP", buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_MAX_ESC_RPM:
|
||||
itoa(stats.max_esc_rpm, buff, 10);
|
||||
osdDisplayStatisticLabel(displayRow, "MAX ESC RPM", buff);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
case OSD_STAT_MIN_LINK_QUALITY:
|
||||
tfp_sprintf(buff, "%d", stats.min_link_quality);
|
||||
strcat(buff, "%");
|
||||
osdDisplayStatisticLabel(displayRow, "MIN LINK", buff);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(USE_GYRO_DATA_ANALYSE)
|
||||
case OSD_STAT_MAX_FFT:
|
||||
if (featureIsEnabled(FEATURE_DYNAMIC_FILTER)) {
|
||||
int value = getMaxFFT();
|
||||
if (value > 0) {
|
||||
tfp_sprintf(buff, "%dHZ", value);
|
||||
osdDisplayStatisticLabel(displayRow, "PEAK FFT", buff);
|
||||
} else {
|
||||
osdDisplayStatisticLabel(displayRow, "PEAK FFT", "THRT<20%");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
case OSD_STAT_MIN_RSSI_DBM:
|
||||
tfp_sprintf(buff, "%3d", stats.min_rssi_dbm * -1);
|
||||
osdDisplayStatisticLabel(displayRow, "MIN RSSI DBM", buff);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef USE_PERSISTENT_STATS
|
||||
case OSD_STAT_TOTAL_FLIGHTS:
|
||||
itoa(statsConfig()->stats_total_flights, buff, 10);
|
||||
osdDisplayStatisticLabel(displayRow, "TOTAL FLIGHTS", buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_TOTAL_TIME: {
|
||||
int minutes = statsConfig()->stats_total_time_s / 60;
|
||||
tfp_sprintf(buff, "%d:%02dH", minutes / 60, minutes % 60);
|
||||
osdDisplayStatisticLabel(displayRow, "TOTAL FLIGHT TIME", buff);
|
||||
return true;
|
||||
}
|
||||
|
||||
case OSD_STAT_TOTAL_DIST:
|
||||
#define METERS_PER_KILOMETER 1000
|
||||
#define METERS_PER_MILE 1609
|
||||
if (osdConfig()->units == OSD_UNIT_IMPERIAL) {
|
||||
tfp_sprintf(buff, "%dMI", statsConfig()->stats_total_dist_m / METERS_PER_MILE);
|
||||
} else {
|
||||
tfp_sprintf(buff, "%dKM", statsConfig()->stats_total_dist_m / METERS_PER_KILOMETER);
|
||||
}
|
||||
osdDisplayStatisticLabel(displayRow, "TOTAL DISTANCE", buff);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t osdShowStats(int statsRowCount)
|
||||
{
|
||||
uint8_t top = 0;
|
||||
char buff[OSD_ELEMENT_BUFFER_LENGTH];
|
||||
bool displayLabel = false;
|
||||
|
||||
// if statsRowCount is 0 then we're running an initial analysis of the active stats items
|
||||
|
@ -511,182 +742,28 @@ static uint8_t osdShowStats(uint16_t endBatteryVoltage, int statsRowCount)
|
|||
displayWrite(osdDisplayPort, 2, top++, " --- STATS ---");
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_RTC_DATE_TIME)) {
|
||||
bool success = false;
|
||||
#ifdef USE_RTC_TIME
|
||||
success = osdFormatRtcDateTime(&buff[0]);
|
||||
#endif
|
||||
if (!success) {
|
||||
tfp_sprintf(buff, "NO RTC");
|
||||
}
|
||||
|
||||
displayWrite(osdDisplayPort, 2, top++, buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_TIMER_1)) {
|
||||
osdFormatTimer(buff, false, (OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_1]) == OSD_TIMER_SRC_ON ? false : true), OSD_TIMER_1);
|
||||
osdDisplayStatisticLabel(top++, osdTimerSourceNames[OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_1])], buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_TIMER_2)) {
|
||||
osdFormatTimer(buff, false, (OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_2]) == OSD_TIMER_SRC_ON ? false : true), OSD_TIMER_2);
|
||||
osdDisplayStatisticLabel(top++, osdTimerSourceNames[OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_2])], buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_MAX_ALTITUDE)) {
|
||||
const int alt = osdGetMetersToSelectedUnit(stats.max_altitude) / 10;
|
||||
tfp_sprintf(buff, "%d.%d%c", alt / 10, alt % 10, osdGetMetersToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(top++, "MAX ALTITUDE", buff);
|
||||
}
|
||||
|
||||
#ifdef USE_GPS
|
||||
if (featureIsEnabled(FEATURE_GPS)) {
|
||||
if (osdStatGetState(OSD_STAT_MAX_SPEED)) {
|
||||
tfp_sprintf(buff, "%d%c", osdGetSpeedToSelectedUnit(stats.max_speed), osdGetSpeedToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(top++, "MAX SPEED", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_MAX_DISTANCE)) {
|
||||
tfp_sprintf(buff, "%d%c", osdGetMetersToSelectedUnit(stats.max_distance), osdGetMetersToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(top++, "MAX DISTANCE", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_FLIGHT_DISTANCE)) {
|
||||
const uint32_t distanceFlown = GPS_distanceFlownInCm / 100;
|
||||
tfp_sprintf(buff, "%d%c", osdGetMetersToSelectedUnit(distanceFlown), osdGetMetersToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(top++, "FLIGHT DISTANCE", buff);
|
||||
for (int i = 0; i < OSD_STAT_COUNT; i++) {
|
||||
if (osdStatGetState(osdStatsDisplayOrder[i])) {
|
||||
if (osdDisplayStat(osdStatsDisplayOrder[i], top)) {
|
||||
top++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (osdStatGetState(OSD_STAT_MIN_BATTERY)) {
|
||||
tfp_sprintf(buff, "%d.%02d%c", stats.min_voltage / 100, stats.min_voltage % 100, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(top++, "MIN BATTERY", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_END_BATTERY)) {
|
||||
tfp_sprintf(buff, "%d.%02d%c", endBatteryVoltage / 100, endBatteryVoltage % 100, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(top++, "END BATTERY", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_BATTERY)) {
|
||||
tfp_sprintf(buff, "%d.%02d%c", getBatteryVoltage() / 100, getBatteryVoltage() % 100, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(top++, "BATTERY", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_MIN_RSSI)) {
|
||||
itoa(stats.min_rssi, buff, 10);
|
||||
strcat(buff, "%");
|
||||
osdDisplayStatisticLabel(top++, "MIN RSSI", buff);
|
||||
}
|
||||
|
||||
if (batteryConfig()->currentMeterSource != CURRENT_METER_NONE) {
|
||||
if (osdStatGetState(OSD_STAT_MAX_CURRENT)) {
|
||||
tfp_sprintf(buff, "%d%c", stats.max_current, SYM_AMP);
|
||||
osdDisplayStatisticLabel(top++, "MAX CURRENT", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_USED_MAH)) {
|
||||
tfp_sprintf(buff, "%d%c", getMAhDrawn(), SYM_MAH);
|
||||
osdDisplayStatisticLabel(top++, "USED MAH", buff);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_BLACKBOX
|
||||
if (osdStatGetState(OSD_STAT_BLACKBOX) && blackboxConfig()->device && blackboxConfig()->device != BLACKBOX_DEVICE_SERIAL) {
|
||||
osdGetBlackboxStatusString(buff);
|
||||
osdDisplayStatisticLabel(top++, "BLACKBOX", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_BLACKBOX_NUMBER) && blackboxConfig()->device && blackboxConfig()->device != BLACKBOX_DEVICE_SERIAL) {
|
||||
itoa(blackboxGetLogNumber(), buff, 10);
|
||||
osdDisplayStatisticLabel(top++, "BB LOG NUM", buff);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_ACC)
|
||||
if (osdStatGetState(OSD_STAT_MAX_G_FORCE) && sensors(SENSOR_ACC)) {
|
||||
const int gForce = lrintf(stats.max_g_force * 10);
|
||||
tfp_sprintf(buff, "%01d.%01dG", gForce / 10, gForce % 10);
|
||||
osdDisplayStatisticLabel(top++, "MAX G-FORCE", buff);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESC_SENSOR
|
||||
if (osdStatGetState(OSD_STAT_MAX_ESC_TEMP)) {
|
||||
tfp_sprintf(buff, "%d%c", osdConvertTemperatureToSelectedUnit(stats.max_esc_temp), osdGetTemperatureSymbolForSelectedUnit());
|
||||
osdDisplayStatisticLabel(top++, "MAX ESC TEMP", buff);
|
||||
}
|
||||
|
||||
if (osdStatGetState(OSD_STAT_MAX_ESC_RPM)) {
|
||||
itoa(stats.max_esc_rpm, buff, 10);
|
||||
osdDisplayStatisticLabel(top++, "MAX ESC RPM", buff);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
if (osdStatGetState(OSD_STAT_MIN_LINK_QUALITY)) {
|
||||
tfp_sprintf(buff, "%d", stats.min_link_quality);
|
||||
strcat(buff, "%");
|
||||
osdDisplayStatisticLabel(top++, "MIN LINK", buff);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_GYRO_DATA_ANALYSE)
|
||||
if (osdStatGetState(OSD_STAT_MAX_FFT) && featureIsEnabled(FEATURE_DYNAMIC_FILTER)) {
|
||||
int value = getMaxFFT();
|
||||
if (value > 0) {
|
||||
tfp_sprintf(buff, "%dHZ", value);
|
||||
osdDisplayStatisticLabel(top++, "PEAK FFT", buff);
|
||||
} else {
|
||||
osdDisplayStatisticLabel(top++, "PEAK FFT", "THRT<20%");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
if (osdStatGetState(OSD_STAT_MIN_RSSI_DBM)) {
|
||||
tfp_sprintf(buff, "%3d", stats.min_rssi_dbm * -1);
|
||||
osdDisplayStatisticLabel(top++, "MIN RSSI DBM", buff);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_PERSISTENT_STATS
|
||||
if (osdStatGetState(OSD_STAT_TOTAL_FLIGHTS)) {
|
||||
itoa(statsConfig()->stats_total_flights, buff, 10);
|
||||
osdDisplayStatisticLabel(top++, "TOTAL FLIGHTS", buff);
|
||||
}
|
||||
if (osdStatGetState(OSD_STAT_TOTAL_TIME)) {
|
||||
int minutes = statsConfig()->stats_total_time_s / 60;
|
||||
tfp_sprintf(buff, "%d:%02dH", minutes / 60, minutes % 60);
|
||||
osdDisplayStatisticLabel(top++, "TOTAL FLIGHT TIME", buff);
|
||||
}
|
||||
if (osdStatGetState(OSD_STAT_TOTAL_DIST)) {
|
||||
#define METERS_PER_KILOMETER 1000
|
||||
#define METERS_PER_MILE 1609
|
||||
if (osdConfig()->units == OSD_UNIT_IMPERIAL) {
|
||||
tfp_sprintf(buff, "%dMI", statsConfig()->stats_total_dist_m / METERS_PER_MILE);
|
||||
} else {
|
||||
tfp_sprintf(buff, "%dKM", statsConfig()->stats_total_dist_m / METERS_PER_KILOMETER);
|
||||
}
|
||||
osdDisplayStatisticLabel(top++, "TOTAL DISTANCE", buff);
|
||||
}
|
||||
#endif
|
||||
return top;
|
||||
}
|
||||
|
||||
static void osdRefreshStats(uint16_t endBatteryVoltage)
|
||||
static void osdRefreshStats(void)
|
||||
{
|
||||
displayClearScreen(osdDisplayPort);
|
||||
if (osdStatsRowCount == 0) {
|
||||
// No stats row count has been set yet.
|
||||
// Go through the logic one time to determine how many stats are actually displayed.
|
||||
osdStatsRowCount = osdShowStats(endBatteryVoltage, 0);
|
||||
osdStatsRowCount = osdShowStats(0);
|
||||
// Then clear the screen and commence with normal stats display which will
|
||||
// determine if the heading should be displayed and also center the content vertically.
|
||||
displayClearScreen(osdDisplayPort);
|
||||
}
|
||||
osdShowStats(endBatteryVoltage, osdStatsRowCount);
|
||||
osdShowStats(osdStatsRowCount);
|
||||
}
|
||||
|
||||
static void osdShowArmed(void)
|
||||
|
@ -701,7 +778,6 @@ STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs)
|
|||
static bool osdStatsEnabled = false;
|
||||
static bool osdStatsVisible = false;
|
||||
static timeUs_t osdStatsRefreshTimeUs;
|
||||
static uint16_t endBatteryVoltage;
|
||||
|
||||
// detect arm/disarm
|
||||
if (armState != ARMING_FLAG(ARMED)) {
|
||||
|
@ -717,7 +793,7 @@ STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs)
|
|||
|| !VISIBLE(osdConfig()->item_pos[OSD_WARNINGS]))) { // suppress stats if runaway takeoff triggered disarm and WARNINGS element is visible
|
||||
osdStatsEnabled = true;
|
||||
resumeRefreshAt = currentTimeUs + (60 * REFRESH_1S);
|
||||
endBatteryVoltage = getBatteryVoltage();
|
||||
stats.end_voltage = getBatteryVoltage();
|
||||
osdStatsRowCount = 0; // reset to 0 so it will be recalculated on the next stats refresh
|
||||
}
|
||||
|
||||
|
@ -746,7 +822,7 @@ STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs)
|
|||
}
|
||||
if (currentTimeUs >= osdStatsRefreshTimeUs) {
|
||||
osdStatsRefreshTimeUs = currentTimeUs + REFRESH_1S;
|
||||
osdRefreshStats(endBatteryVoltage);
|
||||
osdRefreshStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,14 +136,12 @@ typedef enum {
|
|||
} osd_items_e;
|
||||
|
||||
// *** IMPORTANT ***
|
||||
// If the stats enumeration is reordered then the PR version must be incremented. Otherwise there
|
||||
// is no indication that the stored config must be reset and the bitmapped values will be incorrect.
|
||||
// DO NOT REORDER THE STATS ENUMERATION. The order here cooresponds to the enabled flag bit position
|
||||
// storage and changing the order will corrupt user settings. Any new stats MUST be added to the end
|
||||
// just before the OSD_STAT_COUNT entry. YOU MUST ALSO add the new stat to the
|
||||
// osdStatsDisplayOrder array in osd.c.
|
||||
//
|
||||
// The stats display order was previously required to match the enumeration definition so it matched
|
||||
// the order shown in the configurator. However, to allow reordering this screen without breaking the
|
||||
// compatibility, this requirement has been relaxed to a best effort approach. Reordering the elements
|
||||
// on the stats screen will have to be more beneficial than the hassle of not matching exactly to the
|
||||
// configurator list.
|
||||
// IF YOU WANT TO REORDER THE STATS DISPLAY, then adjust the ordering of the osdStatsDisplayOrder array
|
||||
typedef enum {
|
||||
OSD_STAT_RTC_DATE_TIME,
|
||||
OSD_STAT_TIMER_1,
|
||||
|
@ -231,6 +229,7 @@ STATIC_ASSERT(OSD_WARNING_COUNT <= 32, osdwarnings_overflow);
|
|||
#define OSD_GPS_RESCUE_DISABLED_WARNING_DURATION_US 3000000 // 3 seconds
|
||||
|
||||
extern const uint16_t osdTimerDefault[OSD_TIMER_COUNT];
|
||||
extern const osd_stats_e osdStatsDisplayOrder[OSD_STAT_COUNT];
|
||||
|
||||
typedef struct osdConfig_s {
|
||||
uint16_t item_pos[OSD_ITEM_COUNT];
|
||||
|
@ -266,6 +265,7 @@ typedef struct statistic_s {
|
|||
timeUs_t armed_time;
|
||||
int16_t max_speed;
|
||||
int16_t min_voltage; // /100
|
||||
uint16_t end_voltage;
|
||||
int16_t max_current; // /10
|
||||
uint8_t min_rssi;
|
||||
int32_t max_altitude;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue