mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-23 00:05:33 +03:00
Add a common function used to print formatted floats in the OSD
Updated the OSD element and stats rendering code to use this fuction to print floating point values of varying precisions. Will make adding OSD element variants that provide different decimal precisions (like voltage, amperage, etc.) easy to implement since all that needs to change is the `decimalPlaces` passed to the function. As an example, see the `osdFormatAltitudeString()` function. If at some later date a more capable `printf` package is inplemented, then the guts of the `osdPrintFloat()` function could just be simplified while leaving the abstraction in place.
This commit is contained in:
parent
26b74c3350
commit
b5bf9c2b4c
5 changed files with 94 additions and 56 deletions
|
@ -186,6 +186,45 @@ const osd_stats_e osdStatsDisplayOrder[OSD_STAT_COUNT] = {
|
|||
OSD_STAT_TOTAL_DIST,
|
||||
};
|
||||
|
||||
// Format a float to the specified number of decimal places with optional rounding.
|
||||
// OSD symbols can optionally be placed before and after the formatted number (use SYM_NONE for no symbol).
|
||||
// The formatString can be used for customized formatting of the integer part. Follow the printf style.
|
||||
// Pass an empty formatString for default.
|
||||
int osdPrintFloat(char *buffer, char leadingSymbol, float value, char *formatString, unsigned decimalPlaces, bool round, char trailingSymbol)
|
||||
{
|
||||
char mask[7];
|
||||
int pos = 0;
|
||||
int multiplier = 1;
|
||||
for (unsigned i = 0; i < decimalPlaces; i++) {
|
||||
multiplier *= 10;
|
||||
}
|
||||
|
||||
value *= multiplier;
|
||||
const int scaledValueAbs = ABS(round ? lrintf(value) : value);
|
||||
const int integerPart = scaledValueAbs / multiplier;
|
||||
const int fractionalPart = scaledValueAbs % multiplier;
|
||||
|
||||
if (leadingSymbol != SYM_NONE) {
|
||||
buffer[pos++] = leadingSymbol;
|
||||
}
|
||||
if (value < 0 && (integerPart || fractionalPart)) {
|
||||
buffer[pos++] = '-';
|
||||
}
|
||||
|
||||
pos += tfp_sprintf(buffer + pos, (strlen(formatString) ? formatString : "%01u"), integerPart);
|
||||
if (decimalPlaces) {
|
||||
tfp_sprintf((char *)&mask, ".%%0%uu", decimalPlaces); // builds up the format string to be like ".%03u" for decimalPlaces == 3 as an example
|
||||
pos += tfp_sprintf(buffer + pos, mask, fractionalPart);
|
||||
}
|
||||
|
||||
if (trailingSymbol != SYM_NONE) {
|
||||
buffer[pos++] = trailingSymbol;
|
||||
}
|
||||
buffer[pos] = '\0';
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void osdStatSetState(uint8_t statIndex, bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
|
@ -658,8 +697,7 @@ static bool osdDisplayStat(int statistic, uint8_t displayRow)
|
|||
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());
|
||||
osdPrintFloat(buff, SYM_NONE, osdGetMetersToSelectedUnit(stats.max_altitude) / 100.0f, "", 1, true, osdGetMetersToSelectedUnitSymbol());
|
||||
osdDisplayStatisticLabel(displayRow, "MAX ALTITUDE", buff);
|
||||
return true;
|
||||
}
|
||||
|
@ -692,19 +730,19 @@ static bool osdDisplayStat(int statistic, uint8_t displayRow)
|
|||
#endif
|
||||
|
||||
case OSD_STAT_MIN_BATTERY:
|
||||
tfp_sprintf(buff, "%d.%02d%c", stats.min_voltage / 100, stats.min_voltage % 100, SYM_VOLT);
|
||||
osdPrintFloat(buff, SYM_NONE, stats.min_voltage / 100.0f, "", 2, true, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(displayRow, osdConfig()->stat_show_cell_value? "MIN AVG CELL" : "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);
|
||||
osdPrintFloat(buff, SYM_NONE, stats.end_voltage / 100.0f, "", 2, true, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(displayRow, osdConfig()->stat_show_cell_value ? "END AVG CELL" : "END BATTERY", buff);
|
||||
return true;
|
||||
|
||||
case OSD_STAT_BATTERY:
|
||||
{
|
||||
const uint16_t statsVoltage = getStatsVoltage();
|
||||
tfp_sprintf(buff, "%d.%02d%c", statsVoltage / 100, statsVoltage % 100, SYM_VOLT);
|
||||
osdPrintFloat(buff, SYM_NONE, statsVoltage / 100.0f, "", 2, true, SYM_VOLT);
|
||||
osdDisplayStatisticLabel(displayRow, osdConfig()->stat_show_cell_value ? "AVG BATT CELL" : "BATTERY", buff);
|
||||
return true;
|
||||
}
|
||||
|
@ -756,8 +794,7 @@ static bool osdDisplayStat(int statistic, uint8_t displayRow)
|
|||
#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);
|
||||
osdPrintFloat(buff, SYM_NONE, stats.max_g_force, "", 1, true, 'G');
|
||||
osdDisplayStatisticLabel(displayRow, "MAX G-FORCE", buff);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue