mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-20 06:45:16 +03:00
Merge pull request #3373 from DanNixon/generic_osd_timers
Generic OSD timers (plus high precision timer)
This commit is contained in:
commit
ea5a7cd998
8 changed files with 379 additions and 135 deletions
|
@ -134,7 +134,6 @@ static OSD_Entry menuMainEntries[] =
|
|||
{"FEATURES", OME_Submenu, cmsMenuChange, &menuFeatures, 0},
|
||||
#ifdef OSD
|
||||
{"OSD", OME_Submenu, cmsMenuChange, &cmsx_menuOsd, 0},
|
||||
{"ALARMS", OME_Submenu, cmsMenuChange, &cmsx_menuAlarms, 0},
|
||||
#endif
|
||||
{"FC&FW INFO", OME_Submenu, cmsMenuChange, &menuInfo, 0},
|
||||
{"MISC", OME_Submenu, cmsMenuChange, &cmsx_menuMisc, 0},
|
||||
|
|
|
@ -39,51 +39,6 @@
|
|||
#include "io/displayport_max7456.h"
|
||||
#include "io/osd.h"
|
||||
|
||||
static uint8_t osdConfig_rssi_alarm;
|
||||
static uint16_t osdConfig_cap_alarm;
|
||||
static uint16_t osdConfig_time_alarm;
|
||||
static uint16_t osdConfig_alt_alarm;
|
||||
|
||||
static long cmsx_menuAlarmsOnEnter(void)
|
||||
{
|
||||
osdConfig_rssi_alarm = osdConfig()->rssi_alarm;
|
||||
osdConfig_cap_alarm = osdConfig()->cap_alarm;
|
||||
osdConfig_time_alarm = osdConfig()->time_alarm;
|
||||
osdConfig_alt_alarm = osdConfig()->alt_alarm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_menuAlarmsOnExit(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
osdConfigMutable()->rssi_alarm = osdConfig_rssi_alarm;
|
||||
osdConfigMutable()->cap_alarm = osdConfig_cap_alarm;
|
||||
osdConfigMutable()->time_alarm = osdConfig_time_alarm;
|
||||
osdConfigMutable()->alt_alarm = osdConfig_alt_alarm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
OSD_Entry cmsx_menuAlarmsEntries[] =
|
||||
{
|
||||
{"--- ALARMS ---", OME_Label, NULL, NULL, 0},
|
||||
{"RSSI", OME_UINT8, NULL, &(OSD_UINT8_t){&osdConfig_rssi_alarm, 5, 90, 5}, 0},
|
||||
{"MAIN BAT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_cap_alarm, 50, 30000, 50}, 0},
|
||||
{"FLY TIME", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_time_alarm, 1, 200, 1}, 0},
|
||||
{"MAX ALT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_alt_alarm, 1, 200, 1}, 0},
|
||||
{"BACK", OME_Back, NULL, NULL, 0},
|
||||
{NULL, OME_END, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
CMS_Menu cmsx_menuAlarms = {
|
||||
.GUARD_text = "MENUALARMS",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = cmsx_menuAlarmsOnEnter,
|
||||
.onExit = cmsx_menuAlarmsOnExit,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = cmsx_menuAlarmsEntries,
|
||||
};
|
||||
|
||||
#ifndef DISABLE_EXTENDED_CMS_OSD_MENU
|
||||
static uint16_t osdConfig_item_pos[OSD_ITEM_COUNT];
|
||||
|
||||
|
@ -111,8 +66,8 @@ OSD_Entry menuOsdActiveElemsEntries[] =
|
|||
{"CROSSHAIRS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CROSSHAIRS], 0},
|
||||
{"HORIZON", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ARTIFICIAL_HORIZON], 0},
|
||||
{"HORIZON SIDEBARS", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_HORIZON_SIDEBARS], 0},
|
||||
{"UPTIME", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ONTIME], 0},
|
||||
{"FLY TIME", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLYTIME], 0},
|
||||
{"TIMER 1", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_TIMER_1], 0},
|
||||
{"TIMER 2", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_TIMER_2], 0},
|
||||
{"FLY MODE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_FLYMODE], 0},
|
||||
{"NAME", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_CRAFT_NAME], 0},
|
||||
{"THROTTLE", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_THROTTLE_POS], 0},
|
||||
|
@ -141,7 +96,6 @@ OSD_Entry menuOsdActiveElemsEntries[] =
|
|||
{"DISARMED", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_DISARMED], 0},
|
||||
{"PIT ANG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_PITCH_ANGLE], 0},
|
||||
{"ROL ANG", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ROLL_ANGLE], 0},
|
||||
{"ARMED TIME", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_ARMED_TIME], 0},
|
||||
{"HEADING", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_NUMERICAL_HEADING], 0},
|
||||
{"VARIO", OME_VISIBLE, NULL, &osdConfig_item_pos[OSD_NUMERICAL_VARIO], 0},
|
||||
{"BACK", OME_Back, NULL, NULL, 0},
|
||||
|
@ -156,6 +110,100 @@ CMS_Menu menuOsdActiveElems = {
|
|||
.onGlobalExit = NULL,
|
||||
.entries = menuOsdActiveElemsEntries
|
||||
};
|
||||
|
||||
static uint8_t osdConfig_rssi_alarm;
|
||||
static uint16_t osdConfig_cap_alarm;
|
||||
static uint16_t osdConfig_alt_alarm;
|
||||
|
||||
static long menuAlarmsOnEnter(void)
|
||||
{
|
||||
osdConfig_rssi_alarm = osdConfig()->rssi_alarm;
|
||||
osdConfig_cap_alarm = osdConfig()->cap_alarm;
|
||||
osdConfig_alt_alarm = osdConfig()->alt_alarm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long menuAlarmsOnExit(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
osdConfigMutable()->rssi_alarm = osdConfig_rssi_alarm;
|
||||
osdConfigMutable()->cap_alarm = osdConfig_cap_alarm;
|
||||
osdConfigMutable()->alt_alarm = osdConfig_alt_alarm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
OSD_Entry menuAlarmsEntries[] =
|
||||
{
|
||||
{"--- ALARMS ---", OME_Label, NULL, NULL, 0},
|
||||
{"RSSI", OME_UINT8, NULL, &(OSD_UINT8_t){&osdConfig_rssi_alarm, 5, 90, 5}, 0},
|
||||
{"MAIN BAT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_cap_alarm, 50, 30000, 50}, 0},
|
||||
{"MAX ALT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_alt_alarm, 1, 200, 1}, 0},
|
||||
{"BACK", OME_Back, NULL, NULL, 0},
|
||||
{NULL, OME_END, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
CMS_Menu menuAlarms = {
|
||||
.GUARD_text = "MENUALARMS",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = menuAlarmsOnEnter,
|
||||
.onExit = menuAlarmsOnExit,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = menuAlarmsEntries,
|
||||
};
|
||||
|
||||
osd_timer_source_e timerSource[OSD_TIMER_COUNT];
|
||||
osd_timer_precision_e timerPrecision[OSD_TIMER_COUNT];
|
||||
uint8_t timerAlarm[OSD_TIMER_COUNT];
|
||||
|
||||
static long menuTimersOnEnter(void)
|
||||
{
|
||||
for (int i = 0; i < OSD_TIMER_COUNT; i++) {
|
||||
const uint16_t timer = osdConfig()->timers[i];
|
||||
timerSource[i] = OSD_TIMER_SRC(timer);
|
||||
timerPrecision[i] = OSD_TIMER_PRECISION(timer);
|
||||
timerAlarm[i] = OSD_TIMER_ALARM(timer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long menuTimersOnExit(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
|
||||
for (int i = 0; i < OSD_TIMER_COUNT; i++) {
|
||||
osdConfigMutable()->timers[i] = OSD_TIMER(timerSource[i], timerPrecision[i], timerAlarm[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * osdTimerPrecisionNames[] = {"SCND", "HDTH"};
|
||||
|
||||
OSD_Entry menuTimersEntries[] =
|
||||
{
|
||||
{"--- TIMERS ---", OME_Label, NULL, NULL, 0},
|
||||
{"1 SRC", OME_TAB, NULL, &(OSD_TAB_t){&timerSource[OSD_TIMER_1], OSD_TIMER_SRC_COUNT - 1, osdTimerSourceNames}, 0 },
|
||||
{"1 PREC", OME_TAB, NULL, &(OSD_TAB_t){&timerPrecision[OSD_TIMER_1], OSD_TIMER_PREC_COUNT - 1, osdTimerPrecisionNames}, 0},
|
||||
{"1 ALARM", OME_UINT8, NULL, &(OSD_UINT8_t){&timerAlarm[OSD_TIMER_1], 0, 0xFF, 1}, 0},
|
||||
{"2 SRC", OME_TAB, NULL, &(OSD_TAB_t){&timerSource[OSD_TIMER_2], OSD_TIMER_SRC_COUNT - 1, osdTimerSourceNames}, 0 },
|
||||
{"2 PREC", OME_TAB, NULL, &(OSD_TAB_t){&timerPrecision[OSD_TIMER_2], OSD_TIMER_PREC_COUNT - 1, osdTimerPrecisionNames}, 0},
|
||||
{"2 ALARM", OME_UINT8, NULL, &(OSD_UINT8_t){&timerAlarm[OSD_TIMER_2], 0, 0xFF, 1}, 0},
|
||||
{"BACK", OME_Back, NULL, NULL, 0},
|
||||
{NULL, OME_END, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
CMS_Menu menuTimers = {
|
||||
.GUARD_text = "MENUTIMERS",
|
||||
.GUARD_type = OME_MENU,
|
||||
.onEnter = menuTimersOnEnter,
|
||||
.onExit = menuTimersOnExit,
|
||||
.onGlobalExit = NULL,
|
||||
.entries = menuTimersEntries,
|
||||
};
|
||||
#endif /* DISABLE_EXTENDED_CMS_OSD_MENU */
|
||||
|
||||
#ifdef USE_MAX7456
|
||||
|
@ -193,6 +241,8 @@ OSD_Entry cmsx_menuOsdEntries[] =
|
|||
{"---OSD---", OME_Label, NULL, NULL, 0},
|
||||
#ifndef DISABLE_EXTENDED_CMS_OSD_MENU
|
||||
{"ACTIVE ELEM", OME_Submenu, cmsMenuChange, &menuOsdActiveElems, 0},
|
||||
{"TIMERS", OME_Submenu, cmsMenuChange, &menuTimers, 0},
|
||||
{"ALARMS", OME_Submenu, cmsMenuChange, &menuAlarms, 0},
|
||||
#endif
|
||||
#ifdef USE_MAX7456
|
||||
{"INVERT", OME_Bool, NULL, &displayPortProfileMax7456_invert, 0},
|
||||
|
|
|
@ -17,5 +17,4 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
extern CMS_Menu cmsx_menuAlarms;
|
||||
extern CMS_Menu cmsx_menuOsd;
|
||||
|
|
|
@ -840,17 +840,32 @@ static bool mspCommonProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProce
|
|||
|
||||
#ifdef OSD
|
||||
// OSD specific, not applicable to OSD slaves.
|
||||
|
||||
// Configuration
|
||||
sbufWriteU8(dst, osdConfig()->units);
|
||||
|
||||
// Alarms
|
||||
sbufWriteU8(dst, osdConfig()->rssi_alarm);
|
||||
sbufWriteU16(dst, osdConfig()->cap_alarm);
|
||||
sbufWriteU16(dst, osdConfig()->time_alarm);
|
||||
sbufWriteU16(dst, 0);
|
||||
sbufWriteU16(dst, osdConfig()->alt_alarm);
|
||||
|
||||
// Element position and visibility
|
||||
for (int i = 0; i < OSD_ITEM_COUNT; i++) {
|
||||
sbufWriteU16(dst, osdConfig()->item_pos[i]);
|
||||
}
|
||||
|
||||
// Post flight statistics
|
||||
sbufWriteU8(dst, OSD_STAT_COUNT);
|
||||
for (int i = 0; i < OSD_STAT_COUNT; i++ ) {
|
||||
sbufWriteU8(dst, osdConfig()->enabled_stats[i]);
|
||||
}
|
||||
|
||||
// Timers
|
||||
sbufWriteU8(dst, OSD_TIMER_COUNT);
|
||||
for (int i = 0; i < OSD_TIMER_COUNT; i++) {
|
||||
sbufWriteU16(dst, osdConfig()->timers[i]);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -2154,11 +2169,23 @@ static mspResult_e mspCommonProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
|
|||
#endif
|
||||
#if defined(OSD)
|
||||
osdConfigMutable()->units = sbufReadU8(src);
|
||||
|
||||
// Alarms
|
||||
osdConfigMutable()->rssi_alarm = sbufReadU8(src);
|
||||
osdConfigMutable()->cap_alarm = sbufReadU16(src);
|
||||
osdConfigMutable()->time_alarm = sbufReadU16(src);
|
||||
sbufReadU16(src); // Skip unused (previously fly timer)
|
||||
osdConfigMutable()->alt_alarm = sbufReadU16(src);
|
||||
#endif
|
||||
} else if ((int8_t)addr == -2) {
|
||||
#if defined(OSD)
|
||||
// Timers
|
||||
uint8_t index = sbufReadU8(src);
|
||||
if (index > OSD_TIMER_COUNT) {
|
||||
return MSP_RESULT_ERROR;
|
||||
}
|
||||
osdConfigMutable()->timers[index] = sbufReadU16(src);
|
||||
#endif
|
||||
return MSP_RESULT_ERROR;
|
||||
} else {
|
||||
#if defined(OSD)
|
||||
const uint16_t value = sbufReadU16(src);
|
||||
|
@ -2172,6 +2199,8 @@ static mspResult_e mspCommonProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
|
|||
} else if (addr < OSD_ITEM_COUNT) {
|
||||
/* Set element positions */
|
||||
osdConfigMutable()->item_pos[addr] = value;
|
||||
} else {
|
||||
return MSP_RESULT_ERROR;
|
||||
}
|
||||
#else
|
||||
return MSP_RESULT_ERROR;
|
||||
|
|
|
@ -634,13 +634,15 @@ const clivalue_t valueTable[] = {
|
|||
|
||||
{ "osd_rssi_alarm", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 0, 100 }, PG_OSD_CONFIG, offsetof(osdConfig_t, rssi_alarm) },
|
||||
{ "osd_cap_alarm", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, 20000 }, PG_OSD_CONFIG, offsetof(osdConfig_t, cap_alarm) },
|
||||
{ "osd_time_alarm", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, 60 }, PG_OSD_CONFIG, offsetof(osdConfig_t, time_alarm) },
|
||||
{ "osd_alt_alarm", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, 10000 }, PG_OSD_CONFIG, offsetof(osdConfig_t, alt_alarm) },
|
||||
|
||||
{ "osd_tim1", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, (uint16_t)0xFFFF }, PG_OSD_CONFIG, offsetof(osdConfig_t, timers[OSD_TIMER_1]) },
|
||||
{ "osd_tim2", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, (uint16_t)0xFFFF }, PG_OSD_CONFIG, offsetof(osdConfig_t, timers[OSD_TIMER_2]) },
|
||||
|
||||
{ "osd_vbat_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_MAIN_BATT_VOLTAGE]) },
|
||||
{ "osd_rssi_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_RSSI_VALUE]) },
|
||||
{ "osd_flytimer_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_FLYTIME]) },
|
||||
{ "osd_ontimer_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_ONTIME]) },
|
||||
{ "osd_tim_1_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_ITEM_TIMER_1]) },
|
||||
{ "osd_tim_2_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_ITEM_TIMER_2]) },
|
||||
{ "osd_flymode_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_FLYMODE]) },
|
||||
{ "osd_throttle_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_THROTTLE_POS]) },
|
||||
{ "osd_vtx_channel_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_VTX_CHANNEL]) },
|
||||
|
@ -668,7 +670,6 @@ const clivalue_t valueTable[] = {
|
|||
{ "osd_pit_ang_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_PITCH_ANGLE]) },
|
||||
{ "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_arm_time_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_ARMED_TIME]) },
|
||||
{ "osd_disarmed_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_DISARMED]) },
|
||||
{ "osd_nheading_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_NUMERICAL_HEADING]) },
|
||||
{ "osd_nvario_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_NUMERICAL_VARIO]) },
|
||||
|
@ -684,9 +685,9 @@ const clivalue_t valueTable[] = {
|
|||
{ "osd_stat_max_alt", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_MAX_ALTITUDE])},
|
||||
{ "osd_stat_bbox", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_BLACKBOX])},
|
||||
{ "osd_stat_endbatt", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_END_BATTERY])},
|
||||
{ "osd_stat_flytime", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_FLYTIME])},
|
||||
{ "osd_stat_armtime", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_ARMEDTIME])},
|
||||
{ "osd_stat_bb_no", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_BLACKBOX_NUMBER])},
|
||||
{ "osd_stat_tim_1", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_TIMER_1])},
|
||||
{ "osd_stat_tim_2", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats[OSD_STAT_TIMER_2])},
|
||||
#endif
|
||||
|
||||
// PG_SYSTEM_CONFIG
|
||||
|
|
|
@ -89,6 +89,12 @@
|
|||
|
||||
#define VIDEO_BUFFER_CHARS_PAL 480
|
||||
|
||||
const char * const osdTimerSourceNames[] = {
|
||||
"ON TIME ",
|
||||
"TOTAL ARM",
|
||||
"LAST ARM "
|
||||
};
|
||||
|
||||
// Blink control
|
||||
|
||||
static bool blinkState = true;
|
||||
|
@ -106,7 +112,7 @@ static uint32_t blinkBits[(OSD_ITEM_COUNT + 31)/32];
|
|||
#define IS_LO(X) (rcData[X] < 1250)
|
||||
#define IS_MID(X) (rcData[X] > 1250 && rcData[X] < 1750)
|
||||
|
||||
static uint16_t flyTime = 0;
|
||||
static timeUs_t flyTime = 0;
|
||||
static uint8_t statRssi;
|
||||
|
||||
typedef struct statistic_s {
|
||||
|
@ -116,7 +122,7 @@ typedef struct statistic_s {
|
|||
int16_t min_rssi;
|
||||
int16_t max_altitude;
|
||||
int16_t max_distance;
|
||||
uint16_t armed_time;
|
||||
timeUs_t armed_time;
|
||||
} statistic_t;
|
||||
|
||||
static statistic_t stats;
|
||||
|
@ -226,6 +232,65 @@ static uint8_t osdGetDirectionSymbolFromHeading(int heading)
|
|||
return SYM_ARROW_SOUTH + heading;
|
||||
}
|
||||
|
||||
static char osdGetTimerSymbol(osd_timer_source_e src)
|
||||
{
|
||||
switch (src) {
|
||||
case OSD_TIMER_SRC_ON:
|
||||
return SYM_ON_M;
|
||||
case OSD_TIMER_SRC_TOTAL_ARMED:
|
||||
case OSD_TIMER_SRC_LAST_ARMED:
|
||||
return SYM_FLY_M;
|
||||
default:
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
static timeUs_t osdGetTimerValue(osd_timer_source_e src)
|
||||
{
|
||||
switch (src) {
|
||||
case OSD_TIMER_SRC_ON:
|
||||
return micros();
|
||||
case OSD_TIMER_SRC_TOTAL_ARMED:
|
||||
return flyTime;
|
||||
case OSD_TIMER_SRC_LAST_ARMED:
|
||||
return stats.armed_time;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED void osdFormatTime(char * buff, osd_timer_precision_e precision, timeUs_t time)
|
||||
{
|
||||
int seconds = time / 1000000;
|
||||
const int minutes = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
|
||||
switch (precision) {
|
||||
case OSD_TIMER_PREC_SECOND:
|
||||
default:
|
||||
tfp_sprintf(buff, "%02d:%02d", minutes, seconds);
|
||||
break;
|
||||
case OSD_TIMER_PREC_HUNDREDTHS:
|
||||
{
|
||||
const int hundredths = (time / 10000) % 100;
|
||||
tfp_sprintf(buff, "%02d:%02d.%02d", minutes, seconds, hundredths);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_UNIT_TESTED void osdFormatTimer(char *buff, bool showSymbol, int timerIndex)
|
||||
{
|
||||
const uint16_t timer = osdConfig()->timers[timerIndex];
|
||||
const uint8_t src = OSD_TIMER_SRC(timer);
|
||||
|
||||
if (showSymbol) {
|
||||
*(buff++) = osdGetTimerSymbol(src);
|
||||
}
|
||||
|
||||
osdFormatTime(buff, OSD_TIMER_PRECISION(timer), osdGetTimerValue(src));
|
||||
}
|
||||
|
||||
static void osdDrawSingleElement(uint8_t item)
|
||||
{
|
||||
if (!VISIBLE(osdConfig()->item_pos[item]) || BLINK(item)) {
|
||||
|
@ -235,7 +300,7 @@ static void osdDrawSingleElement(uint8_t item)
|
|||
uint8_t elemPosX = OSD_X(osdConfig()->item_pos[item]);
|
||||
uint8_t elemPosY = OSD_Y(osdConfig()->item_pos[item]);
|
||||
uint8_t elemOffsetX = 0;
|
||||
char buff[32];
|
||||
char buff[OSD_ELEMENT_BUFFER_LENGTH];
|
||||
|
||||
switch (item) {
|
||||
case OSD_RSSI_VALUE:
|
||||
|
@ -350,24 +415,14 @@ static void osdDrawSingleElement(uint8_t item)
|
|||
break;
|
||||
}
|
||||
|
||||
case OSD_ONTIME:
|
||||
case OSD_ITEM_TIMER_1:
|
||||
case OSD_ITEM_TIMER_2:
|
||||
{
|
||||
const uint32_t seconds = micros() / 1000000;
|
||||
buff[0] = SYM_ON_M;
|
||||
tfp_sprintf(buff + 1, "%02d:%02d", seconds / 60, seconds % 60);
|
||||
const int timer = item - OSD_ITEM_TIMER_1;
|
||||
osdFormatTimer(buff, true, timer);
|
||||
break;
|
||||
}
|
||||
|
||||
case OSD_FLYTIME:
|
||||
buff[0] = SYM_FLY_M;
|
||||
tfp_sprintf(buff + 1, "%02d:%02d", flyTime / 60, flyTime % 60);
|
||||
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";
|
||||
|
@ -658,8 +713,8 @@ static void osdDrawElements(void)
|
|||
osdDrawSingleElement(OSD_MAIN_BATT_VOLTAGE);
|
||||
osdDrawSingleElement(OSD_RSSI_VALUE);
|
||||
osdDrawSingleElement(OSD_CROSSHAIRS);
|
||||
osdDrawSingleElement(OSD_FLYTIME);
|
||||
osdDrawSingleElement(OSD_ONTIME);
|
||||
osdDrawSingleElement(OSD_ITEM_TIMER_1);
|
||||
osdDrawSingleElement(OSD_ITEM_TIMER_2);
|
||||
osdDrawSingleElement(OSD_FLYMODE);
|
||||
osdDrawSingleElement(OSD_THROTTLE_POS);
|
||||
osdDrawSingleElement(OSD_VTX_CHANNEL);
|
||||
|
@ -678,7 +733,6 @@ static void osdDrawElements(void)
|
|||
osdDrawSingleElement(OSD_PITCH_ANGLE);
|
||||
osdDrawSingleElement(OSD_ROLL_ANGLE);
|
||||
osdDrawSingleElement(OSD_MAIN_BATT_USAGE);
|
||||
osdDrawSingleElement(OSD_ARMED_TIME);
|
||||
osdDrawSingleElement(OSD_DISARMED);
|
||||
osdDrawSingleElement(OSD_NUMERICAL_HEADING);
|
||||
osdDrawSingleElement(OSD_NUMERICAL_VARIO);
|
||||
|
@ -710,8 +764,8 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
osdConfig->item_pos[OSD_CROSSHAIRS] = OSD_POS(8, 6) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_ARTIFICIAL_HORIZON] = OSD_POS(8, 6) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_HORIZON_SIDEBARS] = OSD_POS(8, 6) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_ONTIME] = OSD_POS(22, 1) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_FLYTIME] = OSD_POS(1, 1) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_ITEM_TIMER_1] = OSD_POS(22, 1) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_ITEM_TIMER_2] = OSD_POS(1, 1) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_FLYMODE] = OSD_POS(13, 10) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_CRAFT_NAME] = OSD_POS(10, 11) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_THROTTLE_POS] = OSD_POS(1, 7) | VISIBLE_FLAG;
|
||||
|
@ -737,7 +791,6 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
osdConfig->item_pos[OSD_HOME_DIR] = OSD_POS(14, 9) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_COMPASS_BAR] = OSD_POS(10, 8) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_MAIN_BATT_USAGE] = OSD_POS(8, 12) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_ARMED_TIME] = OSD_POS(1, 2) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_DISARMED] = OSD_POS(10, 4) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_NUMERICAL_HEADING] = OSD_POS(23, 9) | VISIBLE_FLAG;
|
||||
osdConfig->item_pos[OSD_NUMERICAL_VARIO] = OSD_POS(23, 8) | VISIBLE_FLAG;
|
||||
|
@ -752,16 +805,18 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
osdConfig->enabled_stats[OSD_STAT_MAX_ALTITUDE] = false;
|
||||
osdConfig->enabled_stats[OSD_STAT_BLACKBOX] = true;
|
||||
osdConfig->enabled_stats[OSD_STAT_END_BATTERY] = false;
|
||||
osdConfig->enabled_stats[OSD_STAT_FLYTIME] = false;
|
||||
osdConfig->enabled_stats[OSD_STAT_ARMEDTIME] = true;
|
||||
osdConfig->enabled_stats[OSD_STAT_MAX_DISTANCE] = false;
|
||||
osdConfig->enabled_stats[OSD_STAT_BLACKBOX_NUMBER] = true;
|
||||
osdConfig->enabled_stats[OSD_STAT_TIMER_1] = false;
|
||||
osdConfig->enabled_stats[OSD_STAT_TIMER_2] = true;
|
||||
|
||||
osdConfig->units = OSD_UNIT_METRIC;
|
||||
|
||||
osdConfig->timers[OSD_TIMER_1] = OSD_TIMER(OSD_TIMER_SRC_ON, OSD_TIMER_PREC_SECOND, 10);
|
||||
osdConfig->timers[OSD_TIMER_2] = OSD_TIMER(OSD_TIMER_SRC_TOTAL_ARMED, OSD_TIMER_PREC_SECOND, 10);
|
||||
|
||||
osdConfig->rssi_alarm = 20;
|
||||
osdConfig->cap_alarm = 2200;
|
||||
osdConfig->time_alarm = 10; // in minutes
|
||||
osdConfig->alt_alarm = 100; // meters or feet depend on configuration
|
||||
}
|
||||
|
||||
|
@ -837,10 +892,15 @@ void osdUpdateAlarms(void)
|
|||
else
|
||||
CLR_BLINK(OSD_GPS_SATS);
|
||||
|
||||
if (flyTime / 60 >= osdConfig()->time_alarm && ARMING_FLAG(ARMED))
|
||||
SET_BLINK(OSD_FLYTIME);
|
||||
else
|
||||
CLR_BLINK(OSD_FLYTIME);
|
||||
for (int i = 0; i < OSD_TIMER_COUNT; i++) {
|
||||
const uint16_t timer = osdConfig()->timers[i];
|
||||
const timeUs_t time = osdGetTimerValue(OSD_TIMER_SRC(timer));
|
||||
const timeUs_t alarmTime = OSD_TIMER_ALARM(timer) * 60000000; // convert from minutes to us
|
||||
if (alarmTime != 0 && time >= alarmTime)
|
||||
SET_BLINK(OSD_ITEM_TIMER_1 + i);
|
||||
else
|
||||
CLR_BLINK(OSD_ITEM_TIMER_1 + i);
|
||||
}
|
||||
|
||||
if (getMAhDrawn() >= osdConfig()->cap_alarm) {
|
||||
SET_BLINK(OSD_MAH_DRAWN);
|
||||
|
@ -862,11 +922,12 @@ void osdResetAlarms(void)
|
|||
CLR_BLINK(OSD_MAIN_BATT_VOLTAGE);
|
||||
CLR_BLINK(OSD_WARNINGS);
|
||||
CLR_BLINK(OSD_GPS_SATS);
|
||||
CLR_BLINK(OSD_FLYTIME);
|
||||
CLR_BLINK(OSD_MAH_DRAWN);
|
||||
CLR_BLINK(OSD_ALTITUDE);
|
||||
CLR_BLINK(OSD_AVG_CELL_VOLTAGE);
|
||||
CLR_BLINK(OSD_MAIN_BATT_USAGE);
|
||||
CLR_BLINK(OSD_ITEM_TIMER_1);
|
||||
CLR_BLINK(OSD_ITEM_TIMER_2);
|
||||
}
|
||||
|
||||
static void osdResetStats(void)
|
||||
|
@ -967,14 +1028,14 @@ static void osdShowStats(void)
|
|||
displayClearScreen(osdDisplayPort);
|
||||
displayWrite(osdDisplayPort, 2, top++, " --- STATS ---");
|
||||
|
||||
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);
|
||||
if (osdConfig()->enabled_stats[OSD_STAT_TIMER_1]) {
|
||||
osdFormatTimer(buff, false, OSD_TIMER_1);
|
||||
osdDisplayStatisticLabel(top++, osdTimerSourceNames[OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_1])], buff);
|
||||
}
|
||||
|
||||
if (osdConfig()->enabled_stats[OSD_STAT_FLYTIME]) {
|
||||
tfp_sprintf(buff, "%02d:%02d", flyTime / 60, flyTime % 60);
|
||||
osdDisplayStatisticLabel(top++, "FLY TIME", buff);
|
||||
if (osdConfig()->enabled_stats[OSD_STAT_TIMER_2]) {
|
||||
osdFormatTimer(buff, false, OSD_TIMER_2);
|
||||
osdDisplayStatisticLabel(top++, osdTimerSourceNames[OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_2])], buff);
|
||||
}
|
||||
|
||||
if (osdConfig()->enabled_stats[OSD_STAT_MAX_SPEED] && STATE(GPS_FIX)) {
|
||||
|
@ -1046,8 +1107,7 @@ static void osdShowArmed(void)
|
|||
|
||||
STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs)
|
||||
{
|
||||
static uint8_t lastSec = 0;
|
||||
uint8_t sec;
|
||||
static timeUs_t lastTimeUs = 0;
|
||||
|
||||
// detect arm/disarm
|
||||
if (armState != ARMING_FLAG(ARMED)) {
|
||||
|
@ -1067,13 +1127,12 @@ STATIC_UNIT_TESTED void osdRefresh(timeUs_t currentTimeUs)
|
|||
|
||||
osdUpdateStats();
|
||||
|
||||
sec = currentTimeUs / 1000000;
|
||||
|
||||
if (ARMING_FLAG(ARMED) && sec != lastSec) {
|
||||
flyTime++;
|
||||
stats.armed_time++;
|
||||
lastSec = sec;
|
||||
if (ARMING_FLAG(ARMED)) {
|
||||
timeUs_t deltaT = currentTimeUs - lastTimeUs;
|
||||
flyTime += deltaT;
|
||||
stats.armed_time += deltaT;
|
||||
}
|
||||
lastTimeUs = currentTimeUs;
|
||||
|
||||
if (resumeRefreshAt) {
|
||||
if (cmp32(currentTimeUs, resumeRefreshAt) < 0) {
|
||||
|
|
|
@ -21,27 +21,38 @@
|
|||
#include "common/time.h"
|
||||
#include "config/parameter_group.h"
|
||||
|
||||
#define OSD_NUM_TIMER_TYPES 3
|
||||
extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES];
|
||||
|
||||
#define OSD_ELEMENT_BUFFER_LENGTH 32
|
||||
|
||||
#define VISIBLE_FLAG 0x0800
|
||||
#define VISIBLE(x) (x & VISIBLE_FLAG)
|
||||
#define OSD_POS_MAX 0x3FF
|
||||
#define OSD_POSCFG_MAX (VISIBLE_FLAG|0x3FF) // For CLI values
|
||||
|
||||
// Character coordinate
|
||||
|
||||
#define OSD_POSITION_BITS 5 // 5 bits gives a range 0-31
|
||||
#define OSD_POSITION_XY_MASK ((1 << OSD_POSITION_BITS) - 1)
|
||||
#define OSD_POS(x,y) ((x & OSD_POSITION_XY_MASK) | ((y & OSD_POSITION_XY_MASK) << OSD_POSITION_BITS))
|
||||
#define OSD_X(x) (x & OSD_POSITION_XY_MASK)
|
||||
#define OSD_Y(x) ((x >> OSD_POSITION_BITS) & OSD_POSITION_XY_MASK)
|
||||
|
||||
// Timer configuration
|
||||
// Stored as 15[alarm:8][precision:4][source:4]0
|
||||
#define OSD_TIMER(src, prec, alarm) ((src & 0x0F) | ((prec & 0x0F) << 4) | ((alarm & 0xFF ) << 8))
|
||||
#define OSD_TIMER_SRC(timer) (timer & 0x0F)
|
||||
#define OSD_TIMER_PRECISION(timer) ((timer >> 4) & 0x0F)
|
||||
#define OSD_TIMER_ALARM(timer) ((timer >> 8) & 0xFF)
|
||||
|
||||
typedef enum {
|
||||
OSD_RSSI_VALUE,
|
||||
OSD_MAIN_BATT_VOLTAGE,
|
||||
OSD_CROSSHAIRS,
|
||||
OSD_ARTIFICIAL_HORIZON,
|
||||
OSD_HORIZON_SIDEBARS,
|
||||
OSD_ONTIME,
|
||||
OSD_FLYTIME,
|
||||
OSD_ITEM_TIMER_1,
|
||||
OSD_ITEM_TIMER_2,
|
||||
OSD_FLYMODE,
|
||||
OSD_CRAFT_NAME,
|
||||
OSD_THROTTLE_POS,
|
||||
|
@ -64,7 +75,6 @@ typedef enum {
|
|||
OSD_PITCH_ANGLE,
|
||||
OSD_ROLL_ANGLE,
|
||||
OSD_MAIN_BATT_USAGE,
|
||||
OSD_ARMED_TIME,
|
||||
OSD_DISARMED,
|
||||
OSD_HOME_DIR,
|
||||
OSD_HOME_DIST,
|
||||
|
@ -85,8 +95,8 @@ typedef enum {
|
|||
OSD_STAT_MAX_ALTITUDE,
|
||||
OSD_STAT_BLACKBOX,
|
||||
OSD_STAT_END_BATTERY,
|
||||
OSD_STAT_FLYTIME,
|
||||
OSD_STAT_ARMEDTIME,
|
||||
OSD_STAT_TIMER_1,
|
||||
OSD_STAT_TIMER_2,
|
||||
OSD_STAT_MAX_DISTANCE,
|
||||
OSD_STAT_BLACKBOX_NUMBER,
|
||||
OSD_STAT_COUNT // MUST BE LAST
|
||||
|
@ -97,6 +107,25 @@ typedef enum {
|
|||
OSD_UNIT_METRIC
|
||||
} osd_unit_e;
|
||||
|
||||
typedef enum {
|
||||
OSD_TIMER_1,
|
||||
OSD_TIMER_2,
|
||||
OSD_TIMER_COUNT
|
||||
} osd_timer_e;
|
||||
|
||||
typedef enum {
|
||||
OSD_TIMER_SRC_ON,
|
||||
OSD_TIMER_SRC_TOTAL_ARMED,
|
||||
OSD_TIMER_SRC_LAST_ARMED,
|
||||
OSD_TIMER_SRC_COUNT
|
||||
} osd_timer_source_e;
|
||||
|
||||
typedef enum {
|
||||
OSD_TIMER_PREC_SECOND,
|
||||
OSD_TIMER_PREC_HUNDREDTHS,
|
||||
OSD_TIMER_PREC_COUNT
|
||||
} osd_timer_precision_e;
|
||||
|
||||
typedef struct osdConfig_s {
|
||||
uint16_t item_pos[OSD_ITEM_COUNT];
|
||||
bool enabled_stats[OSD_STAT_COUNT];
|
||||
|
@ -104,10 +133,11 @@ typedef struct osdConfig_s {
|
|||
// Alarms
|
||||
uint8_t rssi_alarm;
|
||||
uint16_t cap_alarm;
|
||||
uint16_t time_alarm;
|
||||
uint16_t alt_alarm;
|
||||
|
||||
osd_unit_e units;
|
||||
|
||||
uint16_t timers[OSD_TIMER_COUNT];
|
||||
} osdConfig_t;
|
||||
|
||||
extern uint32_t resumeRefreshAt;
|
||||
|
|
|
@ -47,6 +47,8 @@ extern "C" {
|
|||
#include "rx/rx.h"
|
||||
|
||||
void osdRefresh(timeUs_t currentTimeUs);
|
||||
void osdFormatTime(char * buff, osd_timer_precision_e precision, timeUs_t time);
|
||||
void osdFormatTimer(char *buff, bool showSymbol, int timerIndex);
|
||||
|
||||
uint16_t rssi;
|
||||
attitudeEulerAngles_t attitude;
|
||||
|
@ -269,8 +271,8 @@ TEST(OsdTest, TestStatsImperial)
|
|||
osdConfigMutable()->enabled_stats[OSD_STAT_MAX_ALTITUDE] = true;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_BLACKBOX] = false;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_END_BATTERY] = true;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_FLYTIME] = true;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_ARMEDTIME] = true;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_TIMER_1] = true;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_TIMER_2] = true;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_MAX_DISTANCE] = true;
|
||||
osdConfigMutable()->enabled_stats[OSD_STAT_BLACKBOX_NUMBER] = false;
|
||||
|
||||
|
@ -278,6 +280,14 @@ TEST(OsdTest, TestStatsImperial)
|
|||
// using imperial unit system
|
||||
osdConfigMutable()->units = OSD_UNIT_IMPERIAL;
|
||||
|
||||
// and
|
||||
// this timer 1 configuration
|
||||
osdConfigMutable()->timers[OSD_TIMER_1] = OSD_TIMER(OSD_TIMER_SRC_TOTAL_ARMED, OSD_TIMER_PREC_HUNDREDTHS, 0);
|
||||
|
||||
// and
|
||||
// this timer 2 configuration
|
||||
osdConfigMutable()->timers[OSD_TIMER_2] = OSD_TIMER(OSD_TIMER_SRC_LAST_ARMED, OSD_TIMER_PREC_SECOND, 0);
|
||||
|
||||
// and
|
||||
// a GPS fix is present
|
||||
stateFlags |= GPS_FIX | GPS_FIX_HOME;
|
||||
|
@ -318,14 +328,15 @@ TEST(OsdTest, TestStatsImperial)
|
|||
|
||||
// then
|
||||
// statistics screen should display the following
|
||||
displayPortTestBufferSubstring(2, 3, "ARMED TIME : 00:04");
|
||||
displayPortTestBufferSubstring(2, 4, "FLY TIME : 00:07");
|
||||
displayPortTestBufferSubstring(2, 5, "MAX SPEED : 28");
|
||||
displayPortTestBufferSubstring(2, 6, "MAX DISTANCE : 328%c", SYM_FT);
|
||||
displayPortTestBufferSubstring(2, 7, "MIN BATTERY : 14.7%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, 8, "END BATTERY : 15.2%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, 9, "MIN RSSI : 25%%");
|
||||
displayPortTestBufferSubstring(2, 10, "MAX ALTITUDE : 6.5%c", SYM_FT);
|
||||
int row = 3;
|
||||
displayPortTestBufferSubstring(2, row++, "TOTAL ARM : 00:05.00");
|
||||
displayPortTestBufferSubstring(2, row++, "LAST ARM : 00:03");
|
||||
displayPortTestBufferSubstring(2, row++, "MAX SPEED : 28");
|
||||
displayPortTestBufferSubstring(2, row++, "MAX DISTANCE : 328%c", SYM_FT);
|
||||
displayPortTestBufferSubstring(2, row++, "MIN BATTERY : 14.7%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, row++, "END BATTERY : 15.2%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, row++, "MIN RSSI : 25%%");
|
||||
displayPortTestBufferSubstring(2, row++, "MAX ALTITUDE : 6.5%c", SYM_FT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -367,14 +378,15 @@ TEST(OsdTest, TestStatsMetric)
|
|||
|
||||
// then
|
||||
// statistics screen should display the following
|
||||
displayPortTestBufferSubstring(2, 3, "ARMED TIME : 00:02");
|
||||
displayPortTestBufferSubstring(2, 4, "FLY TIME : 00:09");
|
||||
displayPortTestBufferSubstring(2, 5, "MAX SPEED : 28");
|
||||
displayPortTestBufferSubstring(2, 6, "MAX DISTANCE : 100%c", SYM_M);
|
||||
displayPortTestBufferSubstring(2, 7, "MIN BATTERY : 14.7%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, 8, "END BATTERY : 15.2%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, 9, "MIN RSSI : 25%%");
|
||||
displayPortTestBufferSubstring(2, 10, "MAX ALTITUDE : 2.0%c", SYM_M);
|
||||
int row = 3;
|
||||
displayPortTestBufferSubstring(2, row++, "TOTAL ARM : 00:07.50");
|
||||
displayPortTestBufferSubstring(2, row++, "LAST ARM : 00:02");
|
||||
displayPortTestBufferSubstring(2, row++, "MAX SPEED : 28");
|
||||
displayPortTestBufferSubstring(2, row++, "MAX DISTANCE : 100%c", SYM_M);
|
||||
displayPortTestBufferSubstring(2, row++, "MIN BATTERY : 14.7%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, row++, "END BATTERY : 15.2%c", SYM_VOLT);
|
||||
displayPortTestBufferSubstring(2, row++, "MIN RSSI : 25%%");
|
||||
displayPortTestBufferSubstring(2, row++, "MAX ALTITUDE : 2.0%c", SYM_M);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -390,16 +402,30 @@ TEST(OsdTest, TestAlarms)
|
|||
// the following OSD elements are visible
|
||||
osdConfigMutable()->item_pos[OSD_RSSI_VALUE] = OSD_POS(8, 1) | VISIBLE_FLAG;
|
||||
osdConfigMutable()->item_pos[OSD_MAIN_BATT_VOLTAGE] = OSD_POS(12, 1) | VISIBLE_FLAG;
|
||||
osdConfigMutable()->item_pos[OSD_FLYTIME] = OSD_POS(1, 1) | VISIBLE_FLAG;
|
||||
osdConfigMutable()->item_pos[OSD_ITEM_TIMER_1] = OSD_POS(20, 1) | VISIBLE_FLAG;
|
||||
osdConfigMutable()->item_pos[OSD_ITEM_TIMER_2] = OSD_POS(1, 1) | VISIBLE_FLAG;
|
||||
osdConfigMutable()->item_pos[OSD_ALTITUDE] = OSD_POS(23, 7) | VISIBLE_FLAG;
|
||||
|
||||
// and
|
||||
// this set of alarm values
|
||||
osdConfigMutable()->rssi_alarm = 20;
|
||||
osdConfigMutable()->cap_alarm = 2200;
|
||||
osdConfigMutable()->time_alarm = 1; // in minutes
|
||||
osdConfigMutable()->alt_alarm = 100; // meters
|
||||
|
||||
// and
|
||||
// this timer 1 configuration
|
||||
osdConfigMutable()->timers[OSD_TIMER_1] = OSD_TIMER(OSD_TIMER_SRC_ON, OSD_TIMER_PREC_HUNDREDTHS, 2);
|
||||
EXPECT_EQ(OSD_TIMER_SRC_ON, OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_1]));
|
||||
EXPECT_EQ(OSD_TIMER_PREC_HUNDREDTHS, OSD_TIMER_PRECISION(osdConfig()->timers[OSD_TIMER_1]));
|
||||
EXPECT_EQ(2, OSD_TIMER_ALARM(osdConfig()->timers[OSD_TIMER_1]));
|
||||
|
||||
// and
|
||||
// this timer 2 configuration
|
||||
osdConfigMutable()->timers[OSD_TIMER_2] = OSD_TIMER(OSD_TIMER_SRC_TOTAL_ARMED, OSD_TIMER_PREC_SECOND, 1);
|
||||
EXPECT_EQ(OSD_TIMER_SRC_TOTAL_ARMED, OSD_TIMER_SRC(osdConfig()->timers[OSD_TIMER_2]));
|
||||
EXPECT_EQ(OSD_TIMER_PREC_SECOND, OSD_TIMER_PRECISION(osdConfig()->timers[OSD_TIMER_2]));
|
||||
EXPECT_EQ(1, OSD_TIMER_ALARM(osdConfig()->timers[OSD_TIMER_2]));
|
||||
|
||||
// and
|
||||
// using the metric unit system
|
||||
osdConfigMutable()->units = OSD_UNIT_METRIC;
|
||||
|
@ -421,6 +447,7 @@ TEST(OsdTest, TestAlarms)
|
|||
displayPortTestBufferSubstring(8, 1, "%c99", SYM_RSSI);
|
||||
displayPortTestBufferSubstring(12, 1, "%c16.8%c", SYM_BATT_FULL, SYM_VOLT);
|
||||
displayPortTestBufferSubstring(1, 1, "%c00:", SYM_FLY_M); // only test the minute part of the timer
|
||||
displayPortTestBufferSubstring(20, 1, "%c01:", SYM_ON_M); // only test the minute part of the timer
|
||||
displayPortTestBufferSubstring(23, 7, " 0.0%c", SYM_M);
|
||||
}
|
||||
|
||||
|
@ -430,11 +457,8 @@ TEST(OsdTest, TestAlarms)
|
|||
simulationBatteryState = BATTERY_CRITICAL;
|
||||
simulationBatteryVoltage = 135;
|
||||
simulationAltitude = 12000;
|
||||
// Fly timer is incremented on periodic calls to osdRefresh, can't simply just increment the simulated system clock
|
||||
for (int i = 0; i < 60; i++) {
|
||||
simulationTime += 1e6;
|
||||
osdRefresh(simulationTime);
|
||||
}
|
||||
simulationTime += 60e6;
|
||||
osdRefresh(simulationTime);
|
||||
|
||||
// then
|
||||
// elements showing values in alarm range should flash
|
||||
|
@ -451,6 +475,7 @@ TEST(OsdTest, TestAlarms)
|
|||
displayPortTestBufferSubstring(8, 1, "%c12", SYM_RSSI);
|
||||
displayPortTestBufferSubstring(12, 1, "%c13.5%c", SYM_MAIN_BATT, SYM_VOLT);
|
||||
displayPortTestBufferSubstring(1, 1, "%c01:", SYM_FLY_M); // only test the minute part of the timer
|
||||
displayPortTestBufferSubstring(20, 1, "%c02:", SYM_ON_M); // only test the minute part of the timer
|
||||
displayPortTestBufferSubstring(23, 7, " 120.0%c", SYM_M);
|
||||
} else {
|
||||
displayPortTestBufferIsEmpty();
|
||||
|
@ -492,6 +517,58 @@ TEST(OsdTest, TestElementRssi)
|
|||
displayPortTestBufferSubstring(8, 1, "%c50", SYM_RSSI);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests the time string formatting function with a series of precision settings and time values.
|
||||
*/
|
||||
TEST(OsdTest, TestFormatTimeString)
|
||||
{
|
||||
char buff[OSD_ELEMENT_BUFFER_LENGTH];
|
||||
|
||||
/* Seconds precision, 0 us */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_SECOND, 0);
|
||||
EXPECT_EQ(0, strcmp("00:00", buff));
|
||||
|
||||
/* Seconds precision, 0.9 seconds */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_SECOND, 0.9e6);
|
||||
EXPECT_EQ(0, strcmp("00:00", buff));
|
||||
|
||||
/* Seconds precision, 10 seconds */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_SECOND, 10e6);
|
||||
EXPECT_EQ(0, strcmp("00:10", buff));
|
||||
|
||||
/* Seconds precision, 1 minute */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_SECOND, 60e6);
|
||||
EXPECT_EQ(0, strcmp("01:00", buff));
|
||||
|
||||
/* Seconds precision, 1 minute 59 seconds */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_SECOND, 119e6);
|
||||
EXPECT_EQ(0, strcmp("01:59", buff));
|
||||
|
||||
/* Hundredths precision, 0 us */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_HUNDREDTHS, 0);
|
||||
EXPECT_EQ(0, strcmp("00:00.00", buff));
|
||||
|
||||
/* Hundredths precision, 10 milliseconds (one 100th of a second) */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_HUNDREDTHS, 10e3);
|
||||
EXPECT_EQ(0, strcmp("00:00.01", buff));
|
||||
|
||||
/* Hundredths precision, 0.9 seconds */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_HUNDREDTHS, 0.9e6);
|
||||
EXPECT_EQ(0, strcmp("00:00.90", buff));
|
||||
|
||||
/* Hundredths precision, 10 seconds */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_HUNDREDTHS, 10e6);
|
||||
EXPECT_EQ(0, strcmp("00:10.00", buff));
|
||||
|
||||
/* Hundredths precision, 1 minute */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_HUNDREDTHS, 60e6);
|
||||
EXPECT_EQ(0, strcmp("01:00.00", buff));
|
||||
|
||||
/* Hundredths precision, 1 minute 59 seconds */
|
||||
osdFormatTime(buff, OSD_TIMER_PREC_HUNDREDTHS, 119e6);
|
||||
EXPECT_EQ(0, strcmp("01:59.00", buff));
|
||||
}
|
||||
|
||||
|
||||
// STUBS
|
||||
extern "C" {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue