2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
20 #include "common/time.h"
22 #include "config/parameter_group.h"
24 #include "drivers/osd.h"
25 #include "drivers/display.h"
27 #ifndef OSD_ALTERNATE_LAYOUT_COUNT
28 #define OSD_ALTERNATE_LAYOUT_COUNT 3
30 #define OSD_LAYOUT_COUNT (OSD_ALTERNATE_LAYOUT_COUNT + 1)
32 // 00vb yyyy yyxx xxxx
33 // (visible)(blink)(yCoord)(xCoord)
35 #define OSD_VISIBLE_FLAG 0x2000
36 #define OSD_VISIBLE(x) ((x) & OSD_VISIBLE_FLAG)
38 #define OSD_POS(x,y) (((x) & 0x3F) | (((y) & 0x3F) << 6))
39 #define OSD_X(x) ((x) & 0x3F)
40 #define OSD_Y(x) (((x) >> 6) & 0x3F)
41 #define OSD_POS_MAX 0xFFF
43 // For DJI compatibility
44 #define OSD_VISIBLE_FLAG_SD 0x0800
45 #define OSD_POS_SD(x,y) (((x) & 0x1F) | (((y) & 0x1F) << 5))
47 #define OSD_POS_MAX_CLI (OSD_POS_MAX | OSD_VISIBLE_FLAG)
49 #define OSD_HOMING_LIM_H1 6
50 #define OSD_HOMING_LIM_H2 16
51 #define OSD_HOMING_LIM_H3 38
52 #define OSD_HOMING_LIM_V1 5
53 #define OSD_HOMING_LIM_V2 10
54 #define OSD_HOMING_LIM_V3 15
56 // Message defines to be use in OSD and/or telemetry exports
57 #define OSD_MSG_RC_RX_LINK_LOST "!RC RX LINK LOST!"
58 #define OSD_MSG_TURN_ARM_SW_OFF "TURN ARM SWITCH OFF"
59 #define OSD_MSG_DISABLED_BY_FS "DISABLED BY FAILSAFE"
60 #define OSD_MSG_AIRCRAFT_UNLEVEL "AIRCRAFT IS NOT LEVEL"
61 #define OSD_MSG_SENSORS_CAL "SENSORS CALIBRATING"
62 #define OSD_MSG_SYS_OVERLOADED "SYSTEM OVERLOADED"
63 #define OSD_MSG_WAITING_GPS_FIX "WAITING FOR GPS FIX"
64 #define OSD_MSG_DISABLE_NAV_FIRST "DISABLE NAVIGATION FIRST"
65 #define OSD_MSG_JUMP_WP_MISCONFIG "JUMP WAYPOINT MISCONFIGURED"
66 #define OSD_MSG_MAG_NOT_CAL "COMPASS NOT CALIBRATED"
67 #define OSD_MSG_ACC_NOT_CAL "ACCELEROMETER NOT CALIBRATED"
68 #define OSD_MSG_DISARM_1ST "DISABLE ARM SWITCH FIRST"
69 #define OSD_MSG_GYRO_FAILURE "GYRO FAILURE"
70 #define OSD_MSG_ACC_FAIL "ACCELEROMETER FAILURE"
71 #define OSD_MSG_MAG_FAIL "COMPASS FAILURE"
72 #define OSD_MSG_BARO_FAIL "BAROMETER FAILURE"
73 #define OSD_MSG_GPS_FAIL "GPS FAILURE"
74 #define OSD_MSG_RANGEFINDER_FAIL "RANGE FINDER FAILURE"
75 #define OSD_MSG_PITOT_FAIL "PITOT METER FAILURE"
76 #define OSD_MSG_HW_FAIL "HARDWARE FAILURE"
77 #define OSD_MSG_FS_EN "FAILSAFE MODE ENABLED"
78 #define OSD_MSG_KILL_SW_EN "KILLSWITCH MODE ENABLED"
79 #define OSD_MSG_NO_RC_LINK "NO RC LINK"
80 #define OSD_MSG_THROTTLE_NOT_LOW "THROTTLE IS NOT LOW"
81 #define OSD_MSG_ROLLPITCH_OFFCENTER "ROLLPITCH NOT CENTERED"
82 #define OSD_MSG_AUTOTRIM_ACTIVE "AUTOTRIM IS ACTIVE"
83 #define OSD_MSG_NOT_ENOUGH_MEMORY "NOT ENOUGH MEMORY"
84 #define OSD_MSG_INVALID_SETTING "INVALID SETTING"
85 #define OSD_MSG_CLI_ACTIVE "CLI IS ACTIVE"
86 #define OSD_MSG_PWM_INIT_ERROR "PWM INIT ERROR"
87 #define OSD_MSG_NO_PREARM "NO PREARM"
88 #define OSD_MSG_DSHOT_BEEPER "MOTOR BEEPER ACTIVE"
89 #define OSD_MSG_RTH_FS "(RTH)"
90 #define OSD_MSG_EMERG_LANDING_FS "(EMERGENCY LANDING)"
91 #define OSD_MSG_MOVE_EXIT_FS "!MOVE STICKS TO EXIT FS!"
92 #define OSD_MSG_STARTING_RTH "STARTING RTH"
93 #define OSD_MSG_RTH_CLIMB "ADJUSTING RTH ALTITUDE"
94 #define OSD_MSG_RTH_TRACKBACK "RTH BACK TRACKING"
95 #define OSD_MSG_HEADING_HOME "EN ROUTE TO HOME"
96 #define OSD_MSG_WP_FINISHED "WP END>HOLDING POSITION"
97 #define OSD_MSG_WP_LANDED "WP END>LANDED"
98 #define OSD_MSG_PREPARE_NEXT_WP "PREPARING FOR NEXT WAYPOINT"
99 #define OSD_MSG_ADJUSTING_WP_ALT "ADJUSTING WP ALTITUDE"
100 #define OSD_MSG_MISSION_PLANNER "(WP MISSION PLANNER)"
101 #define OSD_MSG_WP_RTH_CANCEL "CANCEL WP TO EXIT RTH"
102 #define OSD_MSG_WP_MISSION_LOADED "* MISSION LOADED *"
103 #define OSD_MSG_EMERG_LANDING "EMERGENCY LANDING"
104 #define OSD_MSG_LANDING "LANDING"
105 #define OSD_MSG_LOITERING_HOME "LOITERING AROUND HOME"
106 #define OSD_MSG_HOVERING "HOVERING"
107 #define OSD_MSG_LANDED "LANDED"
108 #define OSD_MSG_PREPARING_LAND "PREPARING TO LAND"
109 #define OSD_MSG_AUTOLAUNCH "AUTOLAUNCH"
110 #define OSD_MSG_AUTOLAUNCH_MANUAL "AUTOLAUNCH (MANUAL)"
111 #define OSD_MSG_ALTITUDE_HOLD "(ALTITUDE HOLD)"
112 #define OSD_MSG_AUTOTRIM "(AUTOTRIM)"
113 #define OSD_MSG_AUTOTUNE "(AUTOTUNE)"
114 #define OSD_MSG_AUTOTUNE_ACRO "SWITCH TO ACRO"
115 #define OSD_MSG_AUTOLEVEL "(AUTOLEVEL)"
116 #define OSD_MSG_HEADFREE "(HEADFREE)"
117 #define OSD_MSG_NAV_SOARING "(SOARING)"
118 #define OSD_MSG_UNABLE_ARM "UNABLE TO ARM"
119 #define OSD_MSG_SAVING_SETTNGS "** SAVING SETTINGS **"
120 #define OSD_MSG_SETTINGS_SAVED "** SETTINGS SAVED **"
123 #define OSD_MSG_GRD_TEST_MODE "GRD TEST > MOTORS DISABLED"
126 #if defined(USE_SAFE_HOME)
127 #define OSD_MSG_DIVERT_SAFEHOME "DIVERTING TO SAFEHOME"
128 #define OSD_MSG_LOITERING_SAFEHOME "LOITERING AROUND SAFEHOME"
133 OSD_MAIN_BATT_VOLTAGE
,
135 OSD_ARTIFICIAL_HORIZON
,
136 OSD_HORIZON_SIDEBARS
,
164 OSD_MAIN_BATT_CELL_VOLTAGE
,
165 OSD_SCALED_THROTTLE_POS
,
167 OSD_EFFICIENCY_MAH_PER_KM
,
169 OSD_BATTERY_REMAINING_CAPACITY
,
170 OSD_BATTERY_REMAINING_PERCENT
,
171 OSD_EFFICIENCY_WH_PER_KM
,
178 OSD_WIND_SPEED_HORIZONTAL
,
179 OSD_WIND_SPEED_VERTICAL
,
180 OSD_REMAINING_FLIGHT_TIME_BEFORE_RTH
,
181 OSD_REMAINING_DISTANCE_BEFORE_RTH
,
182 OSD_HOME_HEADING_ERROR
,
183 OSD_COURSE_HOLD_ERROR
,
184 OSD_COURSE_HOLD_ADJUSTMENT
,
185 OSD_SAG_COMPENSATED_MAIN_BATT_VOLTAGE
,
186 OSD_MAIN_BATT_SAG_COMPENSATED_CELL_VOLTAGE
,
187 OSD_POWER_SUPPLY_IMPEDANCE
,
194 OSD_BOARD_ALIGN_ROLL
,
195 OSD_BOARD_ALIGN_PITCH
,
203 OSD_MANUAL_RC_YAW_EXPO
,
204 OSD_MANUAL_PITCH_RATE
,
205 OSD_MANUAL_ROLL_RATE
,
207 OSD_NAV_FW_CRUISE_THR
,
208 OSD_NAV_FW_PITCH2THR
,
209 OSD_FW_MIN_THROTTLE_DOWN_PITCH_ANGLE
,
210 OSD_DEBUG
, // Intentionally absent from configurator and CMS. Set it from CLI.
211 OSD_FW_ALT_PID_OUTPUTS
,
212 OSD_FW_POS_PID_OUTPUTS
,
213 OSD_MC_VEL_X_PID_OUTPUTS
,
214 OSD_MC_VEL_Y_PID_OUTPUTS
,
215 OSD_MC_VEL_Z_PID_OUTPUTS
,
216 OSD_MC_POS_XYZ_P_OUTPUTS
,
219 OSD_BARO_TEMPERATURE
,
220 OSD_TEMP_SENSOR_0_TEMPERATURE
,
221 OSD_TEMP_SENSOR_1_TEMPERATURE
,
222 OSD_TEMP_SENSOR_2_TEMPERATURE
,
223 OSD_TEMP_SENSOR_3_TEMPERATURE
,
224 OSD_TEMP_SENSOR_4_TEMPERATURE
,
225 OSD_TEMP_SENSOR_5_TEMPERATURE
,
226 OSD_TEMP_SENSOR_6_TEMPERATURE
,
227 OSD_TEMP_SENSOR_7_TEMPERATURE
,
250 OSD_NAV_FW_CONTROL_SMOOTHNESS
,
253 OSD_PLIMIT_REMAINING_BURST_TIME
,
254 OSD_PLIMIT_ACTIVE_CURRENT_LIMIT
,
255 OSD_PLIMIT_ACTIVE_POWER_LIMIT
,
262 OSD_SWITCH_INDICATOR_0
,
263 OSD_SWITCH_INDICATOR_1
,
264 OSD_SWITCH_INDICATOR_2
,
265 OSD_SWITCH_INDICATOR_3
,
266 OSD_TPA_TIME_CONSTANT
,
268 OSD_GLIDE_TIME_REMAINING
,
270 OSD_CLIMB_EFFICIENCY
,
271 OSD_NAV_WP_MULTI_MISSION_INDEX
,
272 OSD_GROUND_COURSE
, // 140
273 OSD_CROSS_TRACK_ERROR
,
275 OSD_PAN_SERVO_CENTRED
,
276 OSD_ITEM_COUNT
// MUST BE LAST
282 OSD_UNIT_METRIC_MPH
, // Old UK units, all metric except speed in mph
283 OSD_UNIT_UK
, // Show everything in imperial, temperature in C
284 OSD_UNIT_GA
, // General Aviation: Knots, Nautical Miles, Feet, Degrees C
286 OSD_UNIT_MAX
= OSD_UNIT_GA
,
290 OSD_STATS_ENERGY_UNIT_MAH
,
291 OSD_STATS_ENERGY_UNIT_WH
,
292 } osd_stats_energy_unit_e
;
295 OSD_STATS_MIN_VOLTAGE_UNIT_BATTERY
,
296 OSD_STATS_MIN_VOLTAGE_UNIT_CELL
,
297 } osd_stats_min_voltage_unit_e
;
300 OSD_CROSSHAIRS_STYLE_DEFAULT
,
301 OSD_CROSSHAIRS_STYLE_AIRCRAFT
,
302 OSD_CROSSHAIRS_STYLE_TYPE3
,
303 OSD_CROSSHAIRS_STYLE_TYPE4
,
304 OSD_CROSSHAIRS_STYLE_TYPE5
,
305 OSD_CROSSHAIRS_STYLE_TYPE6
,
306 OSD_CROSSHAIRS_STYLE_TYPE7
,
307 } osd_crosshairs_style_e
;
310 OSD_SIDEBAR_SCROLL_NONE
,
311 OSD_SIDEBAR_SCROLL_ALTITUDE
,
312 OSD_SIDEBAR_SCROLL_SPEED
,
313 OSD_SIDEBAR_SCROLL_HOME_DISTANCE
,
315 OSD_SIDEBAR_SCROLL_MAX
= OSD_SIDEBAR_SCROLL_HOME_DISTANCE
,
316 } osd_sidebar_scroll_e
;
324 OSD_AHI_STYLE_DEFAULT
,
332 } osd_crsf_lq_format_e
;
334 typedef struct osdLayoutsConfig_s
{
336 uint16_t item_pos
[OSD_LAYOUT_COUNT
][OSD_ITEM_COUNT
];
337 } osdLayoutsConfig_t
;
339 PG_DECLARE(osdLayoutsConfig_t
, osdLayoutsConfig
);
341 #define OSD_SWITCH_INDICATOR_NAME_LENGTH 4
343 typedef struct osdConfig_s
{
345 uint8_t rssi_alarm
; // rssi %
346 uint16_t time_alarm
; // fly minutes
347 uint16_t alt_alarm
; // positive altitude in m
348 uint16_t dist_alarm
; // home distance in m
349 uint16_t neg_alt_alarm
; // abs(negative altitude) in m
350 uint8_t current_alarm
; // current consumption in A
351 int16_t imu_temp_alarm_min
;
352 int16_t imu_temp_alarm_max
;
353 int16_t esc_temp_alarm_min
;
354 int16_t esc_temp_alarm_max
;
356 float gforce_axis_alarm_min
;
357 float gforce_axis_alarm_max
;
358 #ifdef USE_SERIALRX_CRSF
359 int8_t snr_alarm
; //CRSF SNR alarm in dB
360 int8_t link_quality_alarm
;
361 int16_t rssi_dbm_alarm
; // in dBm
362 int16_t rssi_dbm_max
; // Perfect RSSI. Set to High end of curve. RSSI at 100%
363 int16_t rssi_dbm_min
; // Worst RSSI. Set to low end of curve or RX sensitivity level. RSSI at 0%
366 int16_t baro_temp_alarm_min
;
367 int16_t baro_temp_alarm_max
;
369 #ifdef USE_TEMPERATURE_SENSOR
370 osd_alignment_e temp_label_align
;
373 float airspeed_alarm_min
;
374 float airspeed_alarm_max
;
377 videoSystem_e video_system
;
378 uint8_t row_shiftdown
;
379 int16_t msp_displayport_fullframe_interval
;
382 uint8_t main_voltage_decimals
;
383 uint8_t ahi_reverse_roll
;
384 uint8_t ahi_max_pitch
;
385 uint8_t crosshairs_style
; // from osd_crosshairs_style_e
386 int8_t horizon_offset
;
387 int8_t camera_uptilt
;
388 bool ahi_camera_uptilt_comp
;
389 uint8_t camera_fov_h
;
390 uint8_t camera_fov_v
;
391 uint8_t hud_margin_h
;
392 uint8_t hud_margin_v
;
395 uint8_t hud_radar_disp
;
396 uint16_t hud_radar_range_min
;
397 uint16_t hud_radar_range_max
;
398 uint8_t hud_radar_alt_difference_display_time
;
399 uint8_t hud_radar_distance_display_time
;
402 uint8_t left_sidebar_scroll
; // from osd_sidebar_scroll_e
403 uint8_t right_sidebar_scroll
; // from osd_sidebar_scroll_e
404 uint8_t sidebar_scroll_arrows
;
406 uint8_t units
; // from osd_unit_e
407 uint8_t stats_energy_unit
; // from osd_stats_energy_unit_e
408 uint8_t stats_min_voltage_unit
; // from osd_stats_min_voltage_unit_e
409 uint8_t stats_page_auto_swap_time
; // stats page auto swap interval time (seconds)
411 #ifdef USE_WIND_ESTIMATOR
412 bool estimations_wind_compensation
; // use wind compensation for estimated remaining flight/distance
415 uint8_t coordinate_digits
;
417 bool osd_failsafe_switch_layout
;
418 uint8_t plus_code_digits
; // Number of digits to use in OSD_PLUS_CODE
419 uint8_t plus_code_short
;
421 uint8_t force_grid
; // Force a pixel based OSD to use grid mode.
422 uint8_t ahi_bordered
; // Only used by the AHI widget
423 uint8_t ahi_width
; // In pixels, only used by the AHI widget
424 uint8_t ahi_height
; // In pixels, only used by the AHI widget
425 int8_t ahi_vertical_offset
; // Offset from center in pixels. Positive moves the AHI down. Widget only.
426 int8_t sidebar_horizontal_offset
; // Horizontal offset from default position. Units are grid slots for grid OSDs, pixels for pixel based OSDs. Positive values move sidebars closer to the edges.
427 uint8_t left_sidebar_scroll_step
; // How many units each sidebar step represents. 0 means the default value for the scroll type.
428 uint8_t right_sidebar_scroll_step
; // Same as left_sidebar_scroll_step, but for the right sidebar.
429 bool osd_home_position_arm_screen
;
430 uint8_t pan_servo_index
; // Index of the pan servo used for home direction offset
431 int8_t pan_servo_pwm2centideg
; // Centidegrees of servo rotation per us pwm
432 uint8_t pan_servo_offcentre_warning
; // Degrees around the centre, that is assumed camera is wanted to be facing forwards, but isn't centred
433 bool pan_servo_indicator_show_degrees
; // Show the degrees of offset for the pan servo
434 uint8_t crsf_lq_format
;
435 uint8_t sidebar_height
; // sidebar height in rows, 0 turns off sidebars leaving only level indicator arrows
436 uint8_t telemetry
; // use telemetry on displayed pixel line 0
437 uint8_t esc_rpm_precision
; // Number of characters used for the RPM numbers.
438 uint16_t system_msg_display_time
; // system message display time for multiple messages (ms)
439 uint8_t mAh_used_precision
; // Number of numbers used for mAh drawn. Plently of packs now are > 9999 mAh
440 uint8_t ahi_pitch_interval
; // redraws AHI at set pitch interval (Not pixel OSD)
441 char osd_switch_indicator0_name
[OSD_SWITCH_INDICATOR_NAME_LENGTH
+ 1]; // Name to use for switch indicator 0.
442 uint8_t osd_switch_indicator0_channel
; // RC Channel to use for switch indicator 0.
443 char osd_switch_indicator1_name
[OSD_SWITCH_INDICATOR_NAME_LENGTH
+ 1]; // Name to use for switch indicator 1.
444 uint8_t osd_switch_indicator1_channel
; // RC Channel to use for switch indicator 1.
445 char osd_switch_indicator2_name
[OSD_SWITCH_INDICATOR_NAME_LENGTH
+ 1]; // Name to use for switch indicator 2.
446 uint8_t osd_switch_indicator2_channel
; // RC Channel to use for switch indicator 2.
447 char osd_switch_indicator3_name
[OSD_SWITCH_INDICATOR_NAME_LENGTH
+ 1]; // Name to use for switch indicator 3.
448 uint8_t osd_switch_indicator3_channel
; // RC Channel to use for switch indicator 3.
449 bool osd_switch_indicators_align_left
; // Align switch indicator name to left of the switch.
452 PG_DECLARE(osdConfig_t
, osdConfig
);
454 typedef struct displayPort_s displayPort_t
;
455 typedef struct displayCanvas_s displayCanvas_t
;
457 void osdInit(displayPort_t
*osdDisplayPort
);
458 bool osdDisplayIsPAL(void);
459 void osdUpdate(timeUs_t currentTimeUs
);
460 void osdStartFullRedraw(void);
461 // Sets a fixed OSD layout ignoring the RC input. Set it
462 // to -1 to disable the override. If layout is >= 0 and
463 // duration is > 0, the override is automatically cleared by
464 // the OSD after the given duration. Otherwise, the caller must
465 // explicitely remove it.
466 void osdOverrideLayout(int layout
, timeMs_t duration
);
467 // Returns the current current layout as well as wether its
468 // set by the user configuration (modes, etc..) or by overriding it.
469 int osdGetActiveLayout(bool *overridden
);
470 bool osdItemIsFixed(osd_items_e item
);
471 uint8_t osdIncElementIndex(uint8_t elementIndex
);
473 displayPort_t
*osdGetDisplayPort(void);
474 displayCanvas_t
*osdGetDisplayPortCanvas(void);
476 int16_t osdGetHeading(void);
477 int32_t osdGetAltitude(void);
479 bool osdUsingScaledThrottle(void);
481 void osdStartedSaveProcess(void);
482 void osdShowEEPROMSavedNotification(void);
484 void osdCrosshairPosition(uint8_t *x
, uint8_t *y
);
485 bool osdFormatCentiNumber(char *buff
, int32_t centivalue
, uint32_t scale
, int maxDecimals
, int maxScaledDecimals
, int length
);
486 void osdFormatAltitudeSymbol(char *buff
, int32_t alt
);
487 void osdFormatVelocityStr(char* buff
, int32_t vel
, bool _3D
, bool _max
);
488 // Returns a heading angle in degrees normalized to [0, 360).
489 int osdGetHeadingAngle(int angle
);
491 int16_t osdGetPanServoOffset(void);
494 * @brief Get the OSD system message
495 * @param buff pointer to the message buffer
496 * @param buff_size size of the buffer array
497 * @param isCenteredText if true, centered text based on buff_size
498 * @return osd text attributes (Blink, Inverted, Solid)
500 textAttributes_t
osdGetSystemMessage(char *buff
, size_t buff_size
, bool isCenteredText
);