1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-23 00:05:28 +03:00

Initial support for multiple OSD layouts

- Add 3 new boxes that can be controlled by a switch to toggle
between the default and 3 alternate layouts.
- Add new MSP cmds to retrieve/set the whole layouts, the OSD alarms
and the preferences.
- For now, CMS and settings just see the default layout. This
will be addressed on future commits.
This commit is contained in:
Alberto García Hierro 2018-03-21 13:01:03 +00:00
parent 3c4668c7ee
commit c5401d74d2
10 changed files with 258 additions and 103 deletions

View file

@ -352,7 +352,7 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, const OSD_Entry *p, uint8_t
#ifdef USE_OSD
case OME_VISIBLE:
if (IS_PRINTVALUE(p, screenRow) && p->data) {
uint16_t val = osdConfig()->item_pos[(int)p->data];
uint16_t val = osdConfig()->item_pos[0][(int)p->data];
if (VISIBLE(val)) {
cnt = displayWrite(pDisplay, RIGHT_MENU_COLUMN(pDisplay), row, "YES");
@ -904,7 +904,7 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key)
#ifdef USE_OSD
case OME_VISIBLE:
if (p->data) {
uint16_t *val = &osdConfigMutable()->item_pos[(int)p->data];
uint16_t *val = &osdConfigMutable()->item_pos[0][(int)p->data];
if (key == KEY_RIGHT)
*val |= VISIBLE_FLAG;

View file

@ -143,7 +143,7 @@ static const OSD_Entry menuMainEntries[] =
OSD_SUBMENU_ENTRY("PID TUNING", &cmsx_menuImu),
OSD_SUBMENU_ENTRY("FEATURES", &menuFeatures),
#ifdef USE_OSD
OSD_SUBMENU_ENTRY("SCR LAYOUT", &cmsx_menuOsdLayout),
OSD_SUBMENU_ENTRY("OSD LAYOUT", &cmsx_menuOsdLayout),
OSD_SUBMENU_ENTRY("ALARMS", &cmsx_menuAlarms),
#endif
OSD_SUBMENU_ENTRY("FC&FW INFO", &menuInfo),

View file

@ -968,7 +968,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
sbufWriteU16(dst, osdConfig()->dist_alarm);
sbufWriteU16(dst, osdConfig()->neg_alt_alarm);
for (int i = 0; i < OSD_ITEM_COUNT; i++) {
sbufWriteU16(dst, osdConfig()->item_pos[i]);
sbufWriteU16(dst, osdConfig()->item_pos[0][i]);
}
#else
sbufWriteU8(dst, 0); // OSD not supported
@ -1305,6 +1305,38 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
sbufWriteU8(dst, MAX_SUPPORTED_SERVOS);
break;
#if defined(USE_OSD)
case MSP2_INAV_OSD_LAYOUTS:
sbufWriteU8(dst, OSD_LAYOUT_COUNT);
sbufWriteU8(dst, OSD_ITEM_COUNT);
for (unsigned ii = 0; ii < OSD_LAYOUT_COUNT; ii++) {
for (unsigned jj = 0; jj < OSD_ITEM_COUNT; jj++) {
sbufWriteU16(dst, osdConfig()->item_pos[ii][jj]);
}
}
break;
case MSP2_INAV_OSD_ALARMS:
sbufWriteU8(dst, osdConfig()->rssi_alarm);
sbufWriteU16(dst, osdConfig()->time_alarm);
sbufWriteU16(dst, osdConfig()->alt_alarm);
sbufWriteU16(dst, osdConfig()->dist_alarm);
sbufWriteU16(dst, osdConfig()->neg_alt_alarm);
break;
case MSP2_INAV_OSD_PREFERENCES:
sbufWriteU8(dst, osdConfig()->video_system);
sbufWriteU8(dst, osdConfig()->main_voltage_decimals);
sbufWriteU8(dst, osdConfig()->ahi_reverse_roll);
sbufWriteU8(dst, osdConfig()->crosshairs_style);
sbufWriteU8(dst, osdConfig()->left_sidebar_scroll);
sbufWriteU8(dst, osdConfig()->right_sidebar_scroll);
sbufWriteU8(dst, osdConfig()->sidebar_scroll_arrows);
sbufWriteU8(dst, osdConfig()->units);
sbufWriteU8(dst, osdConfig()->stats_energy_unit);
break;
#endif
default:
return false;
}
@ -2018,7 +2050,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
} else {
// set a position setting
if ((dataSize >= 3) && (tmp_u8 < OSD_ITEM_COUNT)) // tmp_u8 == addr
osdConfigMutable()->item_pos[tmp_u8] = sbufReadU16(src);
osdConfigMutable()->item_pos[0][tmp_u8] = sbufReadU16(src);
else
return MSP_RESULT_ERROR;
}
@ -2389,6 +2421,52 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
mixerUpdateStateFlags();
break;
#if defined(USE_OSD)
case MSP2_INAV_OSD_SET_LAYOUT_ITEM:
{
uint8_t layout;
if (!sbufReadU8Safe(&layout, src)) {
return MSP_RESULT_ERROR;
}
uint8_t item;
if (!sbufReadU8Safe(&item, src)) {
return MSP_RESULT_ERROR;
}
if (!sbufReadU16Safe(&osdConfigMutable()->item_pos[layout][item], src)) {
return MSP_RESULT_ERROR;
}
osdStartFullRedraw();
}
break;
case MSP2_INAV_OSD_SET_ALARMS:
{
sbufReadU8Safe(&osdConfigMutable()->rssi_alarm, src);
sbufReadU16Safe(&osdConfigMutable()->time_alarm, src);
sbufReadU16Safe(&osdConfigMutable()->alt_alarm, src);
sbufReadU16Safe(&osdConfigMutable()->dist_alarm, src);
sbufReadU16Safe(&osdConfigMutable()->neg_alt_alarm, src);
osdStartFullRedraw();
}
break;
case MSP2_INAV_OSD_SET_PREFERENCES:
{
sbufReadU8Safe(&osdConfigMutable()->video_system, src);
sbufReadU8Safe(&osdConfigMutable()->main_voltage_decimals, src);
sbufReadU8Safe(&osdConfigMutable()->ahi_reverse_roll, src);
sbufReadU8Safe(&osdConfigMutable()->crosshairs_style, src);
sbufReadU8Safe(&osdConfigMutable()->left_sidebar_scroll, src);
sbufReadU8Safe(&osdConfigMutable()->right_sidebar_scroll, src);
sbufReadU8Safe(&osdConfigMutable()->sidebar_scroll_arrows, src);
sbufReadU8Safe(&osdConfigMutable()->units, src);
sbufReadU8Safe(&osdConfigMutable()->stats_energy_unit, src);
osdStartFullRedraw();
}
break;
#endif
default:
return MSP_RESULT_ERROR;
}

View file

@ -30,6 +30,8 @@
#include "fc/fc_msp_box.h"
#include "fc/runtime_config.h"
#include "io/osd.h"
#include "sensors/diagnostics.h"
#include "sensors/sensors.h"
@ -72,6 +74,9 @@ static const box_t boxes[CHECKBOX_ITEM_COUNT + 1] = {
{ BOXCAMERA1, "CAMERA CONTROL 1", 39 },
{ BOXCAMERA2, "CAMERA CONTROL 2", 40 },
{ BOXCAMERA3, "CAMERA CONTROL 3", 41 },
{ BOXOSDALT1, "OSD ALT 1", 42 },
{ BOXOSDALT2, "OSD ALT 2", 43 },
{ BOXOSDALT3, "OSD ALT 3", 43 },
{ CHECKBOX_ITEM_COUNT, NULL, 0xFF }
};
@ -240,6 +245,18 @@ void initActiveBoxIds(void)
activeBoxIds[activeBoxIdCount++] = BOXCAMERA2;
activeBoxIds[activeBoxIdCount++] = BOXCAMERA3;
#endif
#if defined(USE_OSD) && defined(OSD_LAYOUT_COUNT)
#if OSD_LAYOUT_COUNT > 0
activeBoxIds[activeBoxIdCount++] = BOXOSDALT1;
#if OSD_LAYOUT_COUNT > 1
activeBoxIds[activeBoxIdCount++] = BOXOSDALT2;
#if OSD_LAYOUT_COUNT > 2
activeBoxIds[activeBoxIdCount++] = BOXOSDALT3;
#endif
#endif
#endif
#endif
}
#define IS_ENABLED(mask) (mask == 0 ? 0 : 1)
@ -289,6 +306,9 @@ void packBoxModeFlags(boxBitmask_t * mspBoxModeFlags)
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXCAMERA1)), BOXCAMERA1);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXCAMERA2)), BOXCAMERA2);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXCAMERA3)), BOXCAMERA3);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXOSDALT1)), BOXOSDALT1);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXOSDALT2)), BOXOSDALT2);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXOSDALT3)), BOXOSDALT3);
memset(mspBoxModeFlags, 0, sizeof(boxBitmask_t));
for (uint32_t i = 0; i < activeBoxIdCount; i++) {

View file

@ -41,7 +41,15 @@ static bool isUsingNAVModes = false;
#endif
boxBitmask_t rcModeActivationMask; // one bit per mode defined in boxId_e
STATIC_ASSERT(CHECKBOX_ITEM_COUNT <= 32, too_many_box_modes);
// TODO(alberto): It looks like we can now safely remove this assert, since everything
// but BB is able to handle more than 32 boxes and all the definitions use
// CHECKBOX_ITEM_COUNT rather than hardcoded values. Note, however, that BB will only
// log the first 32 flight modes, so the ones affecting actual flight should be <= 32.
//
// Leaving the assert commented for now, just in case there are some unexpected issues
// and someone else has to debug it.
// STATIC_ASSERT(CHECKBOX_ITEM_COUNT <= 32, too_many_box_modes);
PG_REGISTER_ARRAY(modeActivationCondition_t, MAX_MODE_ACTIVATION_CONDITION_COUNT, modeActivationConditions, PG_MODE_ACTIVATION_PROFILE, 0);
PG_REGISTER(modeActivationOperatorConfig_t, modeActivationOperatorConfig, PG_MODE_ACTIVATION_OPERATOR_CONFIG, 0);

View file

@ -56,6 +56,9 @@ typedef enum {
BOXCAMERA1 = 29,
BOXCAMERA2 = 30,
BOXCAMERA3 = 31,
BOXOSDALT1 = 32,
BOXOSDALT2 = 33,
BOXOSDALT3 = 34,
CHECKBOX_ITEM_COUNT
} boxId_e;

View file

@ -1452,7 +1452,7 @@ groups:
type: bool
- name: osd_main_voltage_pos
field: item_pos[OSD_MAIN_BATT_VOLTAGE]
field: item_pos[0][OSD_MAIN_BATT_VOLTAGE]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_main_voltage_decimals
@ -1460,35 +1460,35 @@ groups:
min: 1
max: 2
- name: osd_rssi_pos
field: item_pos[OSD_RSSI_VALUE]
field: item_pos[0][OSD_RSSI_VALUE]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_flytimer_pos
field: item_pos[OSD_FLYTIME]
field: item_pos[0][OSD_FLYTIME]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_ontime_pos
field: item_pos[OSD_ONTIME]
field: item_pos[0][OSD_ONTIME]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_flymode_pos
field: item_pos[OSD_FLYMODE]
field: item_pos[0][OSD_FLYMODE]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_throttle_pos
field: item_pos[OSD_THROTTLE_POS]
field: item_pos[0][OSD_THROTTLE_POS]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_vtx_channel_pos
field: item_pos[OSD_VTX_CHANNEL]
field: item_pos[0][OSD_VTX_CHANNEL]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_crosshairs_pos
field: item_pos[OSD_CROSSHAIRS]
field: item_pos[0][OSD_CROSSHAIRS]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_artificial_horizon_pos
field: item_pos[OSD_ARTIFICIAL_HORIZON]
field: item_pos[0][OSD_ARTIFICIAL_HORIZON]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_horizon_sidebars_pos
@ -1496,111 +1496,111 @@ groups:
min: 0
max: OSD_POS_MAX_CLI
- name: osd_current_draw_pos
field: item_pos[OSD_CURRENT_DRAW]
field: item_pos[0][OSD_CURRENT_DRAW]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_mah_drawn_pos
field: item_pos[OSD_MAH_DRAWN]
field: item_pos[0][OSD_MAH_DRAWN]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_wh_drawn_pos
field: item_pos[OSD_WH_DRAWN]
field: item_pos[0][OSD_WH_DRAWN]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_bat_remaining_capacity_pos
field: item_pos[OSD_BATTERY_REMAINING_CAPACITY]
field: item_pos[0][OSD_BATTERY_REMAINING_CAPACITY]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_bat_remaining_percent_pos
field: item_pos[OSD_BATTERY_REMAINING_PERCENT]
field: item_pos[0][OSD_BATTERY_REMAINING_PERCENT]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_craft_name_pos
field: item_pos[OSD_CRAFT_NAME]
field: item_pos[0][OSD_CRAFT_NAME]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_gps_speed_pos
field: item_pos[OSD_GPS_SPEED]
field: item_pos[0][OSD_GPS_SPEED]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_gps_sats_pos
field: item_pos[OSD_GPS_SATS]
field: item_pos[0][OSD_GPS_SATS]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_gps_lon_pos
field: item_pos[OSD_GPS_LON]
field: item_pos[0][OSD_GPS_LON]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_gps_lat_pos
field: item_pos[OSD_GPS_LAT]
field: item_pos[0][OSD_GPS_LAT]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_home_dir_pos
field: item_pos[OSD_HOME_DIR]
field: item_pos[0][OSD_HOME_DIR]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_home_dist_pos
field: item_pos[OSD_HOME_DIST]
field: item_pos[0][OSD_HOME_DIST]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_altitude_pos
field: item_pos[OSD_ALTITUDE]
field: item_pos[0][OSD_ALTITUDE]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_vario_pos
field: item_pos[OSD_VARIO]
field: item_pos[0][OSD_VARIO]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_vario_num_pos
field: item_pos[OSD_VARIO_NUM]
field: item_pos[0][OSD_VARIO_NUM]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_pid_roll_pos
field: item_pos[OSD_ROLL_PIDS]
field: item_pos[0][OSD_ROLL_PIDS]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_pid_pitch_pos
field: item_pos[OSD_PITCH_PIDS]
field: item_pos[0][OSD_PITCH_PIDS]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_pid_yaw_pos
field: item_pos[OSD_YAW_PIDS]
field: item_pos[0][OSD_YAW_PIDS]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_power_pos
field: item_pos[OSD_POWER]
field: item_pos[0][OSD_POWER]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_air_speed_pos
field: item_pos[OSD_AIR_SPEED]
field: item_pos[0][OSD_AIR_SPEED]
min: 0
max: OSD_POS_MAX_CLI
- name: osd_ontime_flytime_pos
field: item_pos[OSD_ONTIME_FLYTIME]
field: item_pos[0][OSD_ONTIME_FLYTIME]
max: OSD_POS_MAX_CLI
- name: osd_rtc_time_pos
field: item_pos[OSD_RTC_TIME]
field: item_pos[0][OSD_RTC_TIME]
max: OSD_POS_MAX_CLI
- name: osd_messages_pos
field: item_pos[OSD_MESSAGES]
field: item_pos[0][OSD_MESSAGES]
max: OSD_POS_MAX_CLI
- name: osd_gps_hdop_pos
field: item_pos[OSD_GPS_HDOP]
field: item_pos[0][OSD_GPS_HDOP]
max: OSD_POS_MAX_CLI
- name: osd_main_cell_voltage_pos
field: item_pos[OSD_MAIN_BATT_CELL_VOLTAGE]
field: item_pos[0][OSD_MAIN_BATT_CELL_VOLTAGE]
max: OSD_POS_MAX_CLI
- name: osd_throttle_auto_thr_pos
field: item_pos[OSD_THROTTLE_POS_AUTO_THR]
field: item_pos[0][OSD_THROTTLE_POS_AUTO_THR]
max: OSD_POS_MAX_CLI
- name: osd_heading_graph_pos
field: item_pos[OSD_HEADING_GRAPH]
field: item_pos[0][OSD_HEADING_GRAPH]
max: OSD_POS_MAX_CLI
- name: osd_efficiency_mah_pos
field: item_pos[OSD_EFFICIENCY_MAH_PER_KM]
field: item_pos[0][OSD_EFFICIENCY_MAH_PER_KM]
max: OSD_POS_MAX_CLI
- name: osd_efficiency_wh_pos
field: item_pos[OSD_EFFICIENCY_WH_PER_KM]
field: item_pos[0][OSD_EFFICIENCY_WH_PER_KM]
max: OSD_POS_MAX_CLI
- name: PG_SYSTEM_CONFIG

View file

@ -120,6 +120,7 @@
})
static timeUs_t flyTime = 0;
static unsigned layout = 0;
typedef struct statistic_s {
uint16_t max_speed;
@ -161,7 +162,7 @@ static displayPort_t *osdDisplayPort;
#define AH_SIDEBAR_WIDTH_POS 7
#define AH_SIDEBAR_HEIGHT_POS 3
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 0);
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 1);
static int digitCount(int32_t value)
{
@ -265,7 +266,7 @@ static int digitCount(int32_t value)
*/
static void osdFormatDistanceSymbol(char *buff, int32_t dist)
{
switch (osdConfig()->units) {
switch ((osd_unit_e)osdConfig()->units) {
case OSD_UNIT_IMPERIAL:
if (osdFormatCentiNumber(buff + 1, CENTIMETERS_TO_CENTIFEET(dist), FEET_PER_MILE, 0, 3, 3)) {
buff[0] = SYM_DIST_MI;
@ -292,7 +293,7 @@ static void osdFormatDistanceSymbol(char *buff, int32_t dist)
static void osdFormatDistanceStr(char *buff, int32_t dist)
{
int32_t centifeet;
switch (osdConfig()->units) {
switch ((osd_unit_e)osdConfig()->units) {
case OSD_UNIT_IMPERIAL:
centifeet = CENTIMETERS_TO_CENTIFEET(dist);
if (abs(centifeet) < FEET_PER_MILE * 100 / 2) {
@ -325,7 +326,7 @@ static void osdFormatDistanceSymbol(char *buff, int32_t dist)
*/
static int32_t osdConvertVelocityToUnit(int32_t vel)
{
switch (osdConfig()->units) {
switch ((osd_unit_e)osdConfig()->units) {
case OSD_UNIT_UK:
FALLTHROUGH;
case OSD_UNIT_IMPERIAL:
@ -343,7 +344,7 @@ static int32_t osdConvertVelocityToUnit(int32_t vel)
*/
static void osdFormatVelocityStr(char* buff, int32_t vel)
{
switch (osdConfig()->units) {
switch ((osd_unit_e)osdConfig()->units) {
case OSD_UNIT_UK:
FALLTHROUGH;
case OSD_UNIT_IMPERIAL:
@ -362,7 +363,7 @@ static void osdFormatVelocityStr(char* buff, int32_t vel)
*/
static void osdFormatAltitudeSymbol(char *buff, int32_t alt)
{
switch (osdConfig()->units) {
switch ((osd_unit_e)osdConfig()->units) {
case OSD_UNIT_IMPERIAL:
if (osdFormatCentiNumber(buff + 1, CENTIMETERS_TO_CENTIFEET(alt), 1000, 0, 2, 3)) {
// Scaled to kft
@ -394,7 +395,7 @@ static void osdFormatAltitudeSymbol(char *buff, int32_t alt)
static void osdFormatAltitudeStr(char *buff, int32_t alt)
{
int32_t value;
switch (osdConfig()->units) {
switch ((osd_unit_e)osdConfig()->units) {
case OSD_UNIT_IMPERIAL:
value = CENTIMETERS_TO_FEET(alt);
tfp_sprintf(buff, "%d%c", value, SYM_FT);
@ -818,12 +819,13 @@ static int16_t osdGetHeading(void)
static bool osdDrawSingleElement(uint8_t item)
{
if (!VISIBLE(osdConfig()->item_pos[item])) {
uint16_t pos = osdConfig()->item_pos[layout][item];
if (!VISIBLE(pos)) {
return false;
}
uint8_t elemPosX = OSD_X(osdConfig()->item_pos[item]);
uint8_t elemPosY = OSD_Y(osdConfig()->item_pos[item]);
uint8_t elemPosX = OSD_X(pos);
uint8_t elemPosY = OSD_Y(pos);
textAttributes_t elemAttr = TEXT_ATTRIBUTES_NONE;
char buff[32];
@ -1082,7 +1084,7 @@ static bool osdDrawSingleElement(uint8_t item)
case OSD_CROSSHAIRS:
osdCrosshairsBounds(&elemPosX, &elemPosY, NULL);
switch (osdConfig()->crosshairs_style) {
switch ((osd_crosshairs_style_e)osdConfig()->crosshairs_style) {
case OSD_CROSSHAIRS_STYLE_DEFAULT:
buff[0] = SYM_AH_CENTER_LINE;
buff[1] = SYM_AH_CENTER;
@ -1128,7 +1130,7 @@ static bool osdDrawSingleElement(uint8_t item)
// Convert pitchAngle to y compensation value
pitchAngle = ((pitchAngle * 25) / AH_MAX_PITCH) - 41; // 41 = 4 * 9 + 5
crosshairsVisible = VISIBLE(osdConfig()->item_pos[OSD_CROSSHAIRS]);
crosshairsVisible = VISIBLE(osdConfig()->item_pos[layout][OSD_CROSSHAIRS]);
if (crosshairsVisible) {
uint8_t cx, cy, cl;
osdCrosshairsBounds(&cx, &cy, &cl);
@ -1271,7 +1273,7 @@ static bool osdDrawSingleElement(uint8_t item)
{
int16_t value = getEstimatedActualVelocity(Z);
char sym;
switch (osdConfig()->units) {
switch ((osd_unit_e)osdConfig()->units) {
case OSD_UNIT_IMPERIAL:
// Convert to centifeet/s
value = CENTIMETERS_TO_CENTIFEET(value);
@ -1610,60 +1612,66 @@ void osdDrawNextElement(void)
void pgResetFn_osdConfig(osdConfig_t *osdConfig)
{
osdConfig->item_pos[OSD_ALTITUDE] = OSD_POS(1, 0) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_MAIN_BATT_VOLTAGE] = OSD_POS(12, 0) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_RSSI_VALUE] = OSD_POS(23, 0) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_ALTITUDE] = OSD_POS(1, 0) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_MAIN_BATT_VOLTAGE] = OSD_POS(12, 0) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_RSSI_VALUE] = OSD_POS(23, 0) | VISIBLE_FLAG;
//line 2
osdConfig->item_pos[OSD_HOME_DIST] = OSD_POS(1, 1);
osdConfig->item_pos[OSD_TRIP_DIST] = OSD_POS(1, 2);
osdConfig->item_pos[OSD_MAIN_BATT_CELL_VOLTAGE] = OSD_POS(12, 1);
osdConfig->item_pos[OSD_GPS_SPEED] = OSD_POS(23, 1);
osdConfig->item_pos[0][OSD_HOME_DIST] = OSD_POS(1, 1);
osdConfig->item_pos[0][OSD_TRIP_DIST] = OSD_POS(1, 2);
osdConfig->item_pos[0][OSD_MAIN_BATT_CELL_VOLTAGE] = OSD_POS(12, 1);
osdConfig->item_pos[0][OSD_GPS_SPEED] = OSD_POS(23, 1);
osdConfig->item_pos[OSD_THROTTLE_POS] = OSD_POS(1, 2) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_THROTTLE_POS_AUTO_THR] = OSD_POS(6, 2);
osdConfig->item_pos[OSD_HEADING] = OSD_POS(12, 2);
osdConfig->item_pos[OSD_HEADING_GRAPH] = OSD_POS(18, 2);
osdConfig->item_pos[OSD_CURRENT_DRAW] = OSD_POS(1, 3) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_MAH_DRAWN] = OSD_POS(1, 4) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_WH_DRAWN] = OSD_POS(1, 5);
osdConfig->item_pos[OSD_BATTERY_REMAINING_CAPACITY] = OSD_POS(1, 6);
osdConfig->item_pos[OSD_BATTERY_REMAINING_PERCENT] = OSD_POS(1, 7);
osdConfig->item_pos[0][OSD_THROTTLE_POS] = OSD_POS(1, 2) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_THROTTLE_POS_AUTO_THR] = OSD_POS(6, 2);
osdConfig->item_pos[0][OSD_HEADING] = OSD_POS(12, 2);
osdConfig->item_pos[0][OSD_HEADING_GRAPH] = OSD_POS(18, 2);
osdConfig->item_pos[0][OSD_CURRENT_DRAW] = OSD_POS(1, 3) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_MAH_DRAWN] = OSD_POS(1, 4) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_WH_DRAWN] = OSD_POS(1, 5);
osdConfig->item_pos[0][OSD_BATTERY_REMAINING_CAPACITY] = OSD_POS(1, 6);
osdConfig->item_pos[0][OSD_BATTERY_REMAINING_PERCENT] = OSD_POS(1, 7);
osdConfig->item_pos[OSD_EFFICIENCY_MAH_PER_KM] = OSD_POS(1, 5);
osdConfig->item_pos[OSD_EFFICIENCY_WH_PER_KM] = OSD_POS(1, 5);
osdConfig->item_pos[0][OSD_EFFICIENCY_MAH_PER_KM] = OSD_POS(1, 5);
osdConfig->item_pos[0][OSD_EFFICIENCY_WH_PER_KM] = OSD_POS(1, 5);
// avoid OSD_VARIO under OSD_CROSSHAIRS
osdConfig->item_pos[OSD_VARIO] = OSD_POS(23, 5);
osdConfig->item_pos[0][OSD_VARIO] = OSD_POS(23, 5);
// OSD_VARIO_NUM at the right of OSD_VARIO
osdConfig->item_pos[OSD_VARIO_NUM] = OSD_POS(24, 7);
osdConfig->item_pos[OSD_HOME_DIR] = OSD_POS(14, 11);
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[0][OSD_VARIO_NUM] = OSD_POS(24, 7);
osdConfig->item_pos[0][OSD_HOME_DIR] = OSD_POS(14, 11);
osdConfig->item_pos[0][OSD_ARTIFICIAL_HORIZON] = OSD_POS(8, 6) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_HORIZON_SIDEBARS] = OSD_POS(8, 6) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_CRAFT_NAME] = OSD_POS(20, 2);
osdConfig->item_pos[OSD_VTX_CHANNEL] = OSD_POS(8, 6);
osdConfig->item_pos[0][OSD_CRAFT_NAME] = OSD_POS(20, 2);
osdConfig->item_pos[0][OSD_VTX_CHANNEL] = OSD_POS(8, 6);
osdConfig->item_pos[OSD_ONTIME] = OSD_POS(23, 8);
osdConfig->item_pos[OSD_FLYTIME] = OSD_POS(23, 9);
osdConfig->item_pos[OSD_ONTIME_FLYTIME] = OSD_POS(23, 11) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_RTC_TIME] = OSD_POS(23, 12);
osdConfig->item_pos[0][OSD_ONTIME] = OSD_POS(23, 8);
osdConfig->item_pos[0][OSD_FLYTIME] = OSD_POS(23, 9);
osdConfig->item_pos[0][OSD_ONTIME_FLYTIME] = OSD_POS(23, 11) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_RTC_TIME] = OSD_POS(23, 12);
osdConfig->item_pos[OSD_GPS_SATS] = OSD_POS(0, 11) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_GPS_HDOP] = OSD_POS(0, 10);
osdConfig->item_pos[0][OSD_GPS_SATS] = OSD_POS(0, 11) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_GPS_HDOP] = OSD_POS(0, 10);
osdConfig->item_pos[OSD_GPS_LAT] = OSD_POS(0, 12);
osdConfig->item_pos[OSD_FLYMODE] = OSD_POS(12, 12) | VISIBLE_FLAG;
osdConfig->item_pos[OSD_GPS_LON] = OSD_POS(18, 12);
osdConfig->item_pos[0][OSD_GPS_LAT] = OSD_POS(0, 12);
osdConfig->item_pos[0][OSD_FLYMODE] = OSD_POS(12, 12) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_GPS_LON] = OSD_POS(18, 12);
osdConfig->item_pos[OSD_ROLL_PIDS] = OSD_POS(2, 10);
osdConfig->item_pos[OSD_PITCH_PIDS] = OSD_POS(2, 11);
osdConfig->item_pos[OSD_YAW_PIDS] = OSD_POS(2, 12);
osdConfig->item_pos[OSD_POWER] = OSD_POS(15, 1);
osdConfig->item_pos[0][OSD_ROLL_PIDS] = OSD_POS(2, 10);
osdConfig->item_pos[0][OSD_PITCH_PIDS] = OSD_POS(2, 11);
osdConfig->item_pos[0][OSD_YAW_PIDS] = OSD_POS(2, 12);
osdConfig->item_pos[0][OSD_POWER] = OSD_POS(15, 1);
osdConfig->item_pos[OSD_AIR_SPEED] = OSD_POS(3, 5);
osdConfig->item_pos[0][OSD_AIR_SPEED] = OSD_POS(3, 5);
// Under OSD_FLYMODE. TODO: Might not be visible on NTSC?
osdConfig->item_pos[OSD_MESSAGES] = OSD_POS(1, 13) | VISIBLE_FLAG;
osdConfig->item_pos[0][OSD_MESSAGES] = OSD_POS(1, 13) | VISIBLE_FLAG;
for (unsigned ii = 1; ii < OSD_LAYOUT_COUNT; ii++) {
for (unsigned jj = 0; jj < ARRAYLEN(osdConfig->item_pos[0]); jj++) {
osdConfig->item_pos[ii][jj] = osdConfig->item_pos[0][jj] & ~VISIBLE_FLAG;
}
}
osdConfig->rssi_alarm = 20;
osdConfig->time_alarm = 10;
@ -2001,6 +2009,31 @@ void osdUpdate(timeUs_t currentTimeUs)
return;
}
#if defined(OSD_ALTERNATE_LAYOUT_COUNT) && OSD_ALTERNATE_LAYOUT_COUNT > 0
// Check if the layout has changed. Higher numbered
// boxes take priority.
unsigned activeLayout;
#if OSD_ALTERNATE_LAYOUT_COUNT > 2
if (IS_RC_MODE_ACTIVE(BOXOSDALT3))
activeLayout = 3;
else
#endif
#if OSD_ALTERNATE_LAYOUT_COUNT > 1
if (IS_RC_MODE_ACTIVE(BOXOSDALT2))
activeLayout = 2;
else
#endif
if (IS_RC_MODE_ACTIVE(BOXOSDALT1))
activeLayout = 1;
else
activeLayout = 0;
if (layout != activeLayout) {
layout = activeLayout;
osdStartFullRedraw();
}
#endif
#define DRAW_FREQ_DENOM 4
#define STATS_FREQ_DENOM 50
counter++;

View file

@ -20,6 +20,11 @@
#include "common/time.h"
#include "config/parameter_group.h"
#ifndef OSD_ALTERNATE_LAYOUT_COUNT
#define OSD_ALTERNATE_LAYOUT_COUNT 1
#endif
#define OSD_LAYOUT_COUNT (OSD_ALTERNATE_LAYOUT_COUNT + 1)
#define VISIBLE_FLAG 0x0800
#define VISIBLE(x) (x & VISIBLE_FLAG)
#define OSD_POS_MAX 0x3FF
@ -94,7 +99,8 @@ typedef enum {
} osd_sidebar_scroll_e;
typedef struct osdConfig_s {
uint16_t item_pos[OSD_ITEM_COUNT];
// Layouts
uint16_t item_pos[OSD_LAYOUT_COUNT][OSD_ITEM_COUNT];
// Alarms
uint8_t rssi_alarm; // rssi %
@ -109,13 +115,13 @@ typedef struct osdConfig_s {
// Preferences
uint8_t main_voltage_decimals;
uint8_t ahi_reverse_roll;
osd_crosshairs_style_e crosshairs_style;
osd_sidebar_scroll_e left_sidebar_scroll;
osd_sidebar_scroll_e right_sidebar_scroll;
uint8_t crosshairs_style; // from osd_crosshairs_style_e
uint8_t left_sidebar_scroll; // from osd_sidebar_scroll_e
uint8_t right_sidebar_scroll; // from osd_sidebar_scroll_e
uint8_t sidebar_scroll_arrows;
osd_unit_e units;
osd_stats_energy_unit_e stats_energy_unit;
uint8_t units; // from osd_unit_e
uint8_t stats_energy_unit; // from osd_stats_energy_unit_e
} osdConfig_t;
PG_DECLARE(osdConfig_t, osdConfig);

View file

@ -31,3 +31,10 @@
#define MSP2_INAV_MIXER 0x2010
#define MSP2_INAV_SET_MIXER 0x2011
#define MSP2_INAV_OSD_LAYOUTS 0x2012
#define MSP2_INAV_OSD_SET_LAYOUT_ITEM 0x2013
#define MSP2_INAV_OSD_ALARMS 0x2014
#define MSP2_INAV_OSD_SET_ALARMS 0x2015
#define MSP2_INAV_OSD_PREFERENCES 0x2016
#define MSP2_INAV_OSD_SET_PREFERENCES 0x2017