1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-21 07:15:18 +03:00

Add OSD Stick Overlay feature - fix issue 3988

This commit is contained in:
Pieter Kruger 2018-12-08 23:56:12 +10:00
parent 586eef94e5
commit ef459cb161
5 changed files with 124 additions and 10 deletions

View file

@ -1088,6 +1088,13 @@ const clivalue_t valueTable[] = {
{ "osd_log_status_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_LOG_STATUS]) },
#endif
#ifdef USE_OSD_STICK_OVERLAY
{ "osd_stick_overlay_left_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_STICK_OVERLAY_LEFT]) },
{ "osd_stick_overlay_right_pos", VAR_UINT16 | MASTER_VALUE, .config.minmax = { 0, OSD_POSCFG_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, item_pos[OSD_STICK_OVERLAY_RIGHT]) },
{ "osd_stick_overlay_radio_mode", VAR_UINT8 | MASTER_VALUE, .config.minmax = { 1, 4 }, PG_OSD_CONFIG, offsetof(osdConfig_t, overlay_radio_mode) },
#endif
// OSD stats enabled flags are stored as bitmapped values inside a 32bit parameter
// It is recommended to keep the settings order the same as the enumeration. This way the settings are displayed in the cli in the same order making it easier on the users
{ "osd_stat_rtc_date_time", VAR_UINT32 | MASTER_VALUE | MODE_BITSET, .config.bitpos = OSD_STAT_RTC_DATE_TIME, PG_OSD_CONFIG, offsetof(osdConfig_t, enabled_stats)},

View file

@ -103,6 +103,11 @@
#define VIDEO_BUFFER_CHARS_PAL 480
#define FULL_CIRCLE 360
#define STICK_OVERLAY_HORIZONTAL_CHAR '-'
#define STICK_OVERLAY_VERTICAL_CHAR '|'
#define STICK_OVERLAY_CROSS_CHAR '+'
#define STICK_OVERLAY_CURSOR_CHAR '0'
const char * const osdTimerSourceNames[] = {
"ON TIME ",
"TOTAL ARM",
@ -143,8 +148,29 @@ typedef struct statistic_s {
uint8_t min_link_quality;
} statistic_t;
static statistic_t stats;
typedef struct radioControls_s {
uint8_t left_vertical;
uint8_t left_horizontal;
uint8_t right_vertical;
uint8_t right_horizontal;
} radioControls_t;
typedef enum radioModes_e {
MODE1,
MODE2,
MODE3,
MODE4
} radioModes_t;
static statistic_t stats;
#ifdef USE_OSD_STICK_OVERLAY
static const radioControls_t radioModes[4] = {
{ PITCH, YAW, THROTTLE, ROLL }, // Mode 1
{ THROTTLE, YAW, PITCH, ROLL }, // Mode 2
{ PITCH, ROLL, THROTTLE, YAW }, // Mode 3
{ THROTTLE, ROLL, PITCH, YAW }, // Mode 4
};
#endif
timeUs_t resumeRefreshAt = 0;
#define REFRESH_1S 1000 * 1000
@ -227,7 +253,7 @@ static const uint8_t osdElementDisplayOrder[] = {
#endif
};
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 3);
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 4);
/**
* Gets the correct altitude symbol for the current unit system
@ -505,15 +531,10 @@ void changeOsdProfileIndex(uint8_t profileIndex)
static bool osdDrawSingleElement(uint8_t item)
{
#ifdef USE_OSD_PROFILES
if ((OSD_ELEMENT_PROFILE(osdConfig()->item_pos[item]) & osdProfile) == 0) {
return false;
}
#else
if (!VISIBLE(osdConfig()->item_pos[item]) || BLINK(item)) {
return false;
}
#endif
uint8_t elemPosX = OSD_X(osdConfig()->item_pos[item]);
uint8_t elemPosY = OSD_Y(osdConfig()->item_pos[item]);
char buff[OSD_ELEMENT_BUFFER_LENGTH] = "";
@ -1184,6 +1205,58 @@ static bool osdDrawSingleElement(uint8_t item)
return true;
}
#ifdef USE_OSD_STICK_OVERLAY
static void osdDrawStickOverlayAxis(uint8_t xpos, uint8_t ypos)
{
for (unsigned x = 0; x < OSD_STICK_OVERLAY_WIDTH; x++) {
for (unsigned y = 0; y < OSD_STICK_OVERLAY_HEIGHT; y++) {
// draw the axes, vertical and horizonal
if ((x == ((OSD_STICK_OVERLAY_WIDTH - 1) / 2)) && (y == (OSD_STICK_OVERLAY_HEIGHT - 1) / 2)) {
displayWriteChar(osdDisplayPort, xpos + x, ypos + y, STICK_OVERLAY_CROSS_CHAR);
} else if (x == ((OSD_STICK_OVERLAY_WIDTH - 1) / 2)) {
displayWriteChar(osdDisplayPort, xpos + x, ypos + y, STICK_OVERLAY_VERTICAL_CHAR);
} else if (y == ((OSD_STICK_OVERLAY_HEIGHT - 1) / 2)) {
displayWriteChar(osdDisplayPort, xpos + x, ypos + y, STICK_OVERLAY_HORIZONTAL_CHAR);
}
}
}
}
static void osdDrawStickOverlayAxisItem(osd_items_e osd_item)
{
osdDrawStickOverlayAxis(OSD_X(osdConfig()->item_pos[osd_item]),
OSD_Y(osdConfig()->item_pos[osd_item]));
}
static void osdDrawStickOverlayPos(osd_items_e osd_item, uint8_t xpos, uint8_t ypos)
{
uint8_t elemPosX = OSD_X(osdConfig()->item_pos[osd_item]);
uint8_t elemPosY = OSD_Y(osdConfig()->item_pos[osd_item]);
displayWriteChar(osdDisplayPort, elemPosX + xpos, elemPosY + ypos, STICK_OVERLAY_CURSOR_CHAR);
}
static void osdDrawStickOverlayCursor(osd_items_e osd_item)
{
rc_alias_e vertical_channel, horizontal_channel;
if (osd_item == OSD_STICK_OVERLAY_LEFT) {
vertical_channel = radioModes[osdConfig()->overlay_radio_mode-1].left_vertical;
horizontal_channel = radioModes[osdConfig()->overlay_radio_mode-1].left_horizontal;
} else {
vertical_channel = radioModes[osdConfig()->overlay_radio_mode-1].right_vertical;
horizontal_channel = radioModes[osdConfig()->overlay_radio_mode-1].right_horizontal;
}
uint8_t x_pos = (uint8_t)scaleRange(constrain(rcData[horizontal_channel], PWM_RANGE_MIN, PWM_RANGE_MAX), PWM_RANGE_MIN, PWM_RANGE_MAX, 0, OSD_STICK_OVERLAY_WIDTH);
uint8_t y_pos = (uint8_t)scaleRange(PWM_RANGE_MAX - constrain(rcData[vertical_channel], PWM_RANGE_MIN, PWM_RANGE_MAX), PWM_RANGE_MIN, PWM_RANGE_MAX, 0, OSD_STICK_OVERLAY_HEIGHT) + OSD_STICK_OVERLAY_HEIGHT - 1;
osdDrawStickOverlayPos(osd_item, x_pos, y_pos);
}
#endif
static void osdDrawElements(void)
{
displayClearScreen(osdDisplayPort);
@ -1236,6 +1309,18 @@ static void osdDrawElements(void)
osdDrawSingleElement(OSD_LOG_STATUS);
}
#endif
#ifdef USE_OSD_STICK_OVERLAY
if (VISIBLE(osdConfig()->item_pos[OSD_STICK_OVERLAY_LEFT])) {
osdDrawStickOverlayAxisItem(OSD_STICK_OVERLAY_LEFT);
osdDrawStickOverlayCursor(OSD_STICK_OVERLAY_LEFT);
}
if (VISIBLE(osdConfig()->item_pos[OSD_STICK_OVERLAY_RIGHT])) {
osdDrawStickOverlayAxisItem(OSD_STICK_OVERLAY_RIGHT);
osdDrawStickOverlayCursor(OSD_STICK_OVERLAY_RIGHT);
}
#endif
}
void pgResetFn_osdConfig(osdConfig_t *osdConfig)
@ -1274,6 +1359,8 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
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->overlay_radio_mode = 2;
osdConfig->rssi_alarm = 20;
osdConfig->cap_alarm = 2200;
osdConfig->alt_alarm = 100; // meters or feet depend on configuration
@ -1872,4 +1959,11 @@ void osdSuppressStats(bool flag)
{
suppressStatsDisplay = flag;
}
#ifdef USE_OSD_PROFILES
bool osdElementVisible(uint16_t value)
{
return (bool)((((value & OSD_PROFILE_MASK) >> OSD_PROFILE_BITS_POS) & osdProfile) != 0);
}
#endif
#endif // USE_OSD

View file

@ -33,10 +33,13 @@ extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES];
#define OSD_PROFILE_BITS_POS 11
#define OSD_PROFILE_1_FLAG (1 << OSD_PROFILE_BITS_POS)
#define OSD_PROFILE_MASK (((1 << OSD_PROFILE_COUNT) - 1) << OSD_PROFILE_BITS_POS)
#define VISIBLE(x) ((x) & OSD_PROFILE_MASK)
#define OSD_POS_MAX 0x3FF
#define OSD_POSCFG_MAX (OSD_PROFILE_MASK | 0x3FF) // For CLI values
#define OSD_ELEMENT_PROFILE(x) (((x) & OSD_PROFILE_MASK) >> OSD_PROFILE_BITS_POS)
#ifdef USE_OSD_PROFILES
#define VISIBLE(x) osdElementVisible(x)
#else
#define VISIBLE(x) ((x) & OSD_PROFILE_MASK)
#endif
// Character coordinate
@ -46,6 +49,10 @@ extern const char * const osdTimerSourceNames[OSD_NUM_TIMER_TYPES];
#define OSD_X(x) (x & OSD_POSITION_XY_MASK)
#define OSD_Y(x) ((x >> OSD_POSITION_BITS) & OSD_POSITION_XY_MASK)
// Stick overlay size
#define OSD_STICK_OVERLAY_WIDTH 7
#define OSD_STICK_OVERLAY_HEIGHT 7
// 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))
@ -107,6 +114,8 @@ typedef enum {
OSD_FLIP_ARROW,
OSD_LINK_QUALITY,
OSD_FLIGHT_DIST,
OSD_STICK_OVERLAY_LEFT,
OSD_STICK_OVERLAY_RIGHT,
OSD_ITEM_COUNT // MUST BE LAST
} osd_items_e;
@ -213,6 +222,7 @@ typedef struct osdConfig_s {
uint8_t core_temp_alarm;
uint8_t ahInvert; // invert the artificial horizon
uint8_t osdProfileIndex;
uint8_t overlay_radio_mode;
} osdConfig_t;
PG_DECLARE(osdConfig_t, osdConfig);
@ -233,3 +243,4 @@ void osdSuppressStats(bool flag);
void setOsdProfile(uint8_t value);
uint8_t getCurrentOsdProfileIndex(void);
void changeOsdProfileIndex(uint8_t profileIndex);
bool osdElementVisible(uint16_t value);

View file

@ -127,6 +127,7 @@
#if !defined(USE_OSD)
#undef USE_RX_LINK_QUALITY_INFO
#undef USE_OSD_PROFILES
#undef USE_OSD_STICK_OVERLAY
#endif
/* If either VTX_CONTROL or VTX_COMMON is undefined then remove common code and device drivers */

View file

@ -235,4 +235,5 @@
#define USE_RX_LINK_QUALITY_INFO
#define USE_ESC_SENSOR_TELEMETRY
#define USE_OSD_PROFILES
#define USE_OSD_STICK_OVERLAY
#endif