Line data Source code
1 : /*
2 : * This file is free software: you can redistribute it and/or modify it
3 : * under the terms of the GNU General Public License as published by the
4 : * Free Software Foundation, either version 3 of the License, or
5 : * (at your option) any later version.
6 : *
7 : * This file is distributed in the hope that it will be useful, but
8 : * WITHOUT ANY WARRANTY; without even the implied warranty of
9 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 : * See the GNU General Public License for more details.
11 : *
12 : * You should have received a copy of the GNU General Public License along
13 : * with this program. If not, see <http://www.gnu.org/licenses/>.
14 : *
15 : * AP_OSD partially based on betaflight and inav osd.c implemention.
16 : * clarity.mcm font is taken from inav configurator.
17 : * Many thanks to their authors.
18 : */
19 : /*
20 : parameter settings for one screen
21 : */
22 : #include "AP_OSD_config.h"
23 :
24 : #if OSD_ENABLED
25 :
26 : #include "AP_OSD.h"
27 : #include "AP_OSD_Backend.h"
28 :
29 : #include <AP_HAL/AP_HAL.h>
30 : #include <AP_HAL/Util.h>
31 : #include <AP_AHRS/AP_AHRS.h>
32 : #include <AP_Math/AP_Math.h>
33 : #include <AP_RSSI/AP_RSSI.h>
34 : #include <AP_Notify/AP_Notify.h>
35 : #include <AP_Stats/AP_Stats.h>
36 : #include <AP_Common/Location.h>
37 : #include <AP_BattMonitor/AP_BattMonitor.h>
38 : #include <AP_GPS/AP_GPS.h>
39 : #include <AP_RTC/AP_RTC.h>
40 : #include <AP_MSP/msp.h>
41 : #include <AP_OLC/AP_OLC.h>
42 : #include <AP_VideoTX/AP_VideoTX.h>
43 : #include <AP_Terrain/AP_Terrain.h>
44 : #include <AP_RangeFinder/AP_RangeFinder.h>
45 : #include <AP_Vehicle/AP_Vehicle.h>
46 : #include <AP_RPM/AP_RPM.h>
47 : #include <AP_MSP/AP_MSP.h>
48 : #if APM_BUILD_TYPE(APM_BUILD_Rover)
49 : #include <AP_WindVane/AP_WindVane.h>
50 : #endif
51 : #include <AP_Filesystem/AP_Filesystem.h>
52 :
53 : #include <ctype.h>
54 : #include <GCS_MAVLink/GCS.h>
55 : #include <AC_Fence/AC_Fence.h>
56 :
57 : #if AP_OSD_EXTENDED_LNK_STATS
58 : // We need to this file to access the CRSF telemetry objects which contains the link stats data
59 : #include <AP_RCProtocol/AP_RCProtocol_CRSF.h>
60 : #endif
61 :
62 : const AP_Param::GroupInfo AP_OSD_Screen::var_info[] = {
63 :
64 : // @Param: ENABLE
65 : // @DisplayName: Enable screen
66 : // @Description: Enable this screen
67 : // @Values: 0:Disabled,1:Enabled
68 : // @User: Standard
69 : AP_GROUPINFO_FLAGS("ENABLE", 1, AP_OSD_Screen, enabled, 0, AP_PARAM_FLAG_ENABLE),
70 :
71 : // @Param: CHAN_MIN
72 : // @DisplayName: Transmitter switch screen minimum pwm
73 : // @Description: This sets the PWM lower limit for this screen
74 : // @Range: 900 2100
75 : // @User: Standard
76 : AP_GROUPINFO("CHAN_MIN", 2, AP_OSD_Screen, channel_min, 900),
77 :
78 : // @Param: CHAN_MAX
79 : // @DisplayName: Transmitter switch screen maximum pwm
80 : // @Description: This sets the PWM upper limit for this screen
81 : // @Range: 900 2100
82 : // @User: Standard
83 : AP_GROUPINFO("CHAN_MAX", 3, AP_OSD_Screen, channel_max, 2100),
84 :
85 : // @Param: ALTITUDE_EN
86 : // @DisplayName: ALTITUDE_EN
87 : // @Description: Enables display of altitude AGL
88 : // @Values: 0:Disabled,1:Enabled
89 :
90 : // @Param: ALTITUDE_X
91 : // @DisplayName: ALTITUDE_X
92 : // @Description: Horizontal position on screen
93 : // @Range: 0 59
94 :
95 : // @Param: ALTITUDE_Y
96 : // @DisplayName: ALTITUDE_Y
97 : // @Description: Vertical position on screen
98 : // @Range: 0 21
99 : AP_SUBGROUPINFO(altitude, "ALTITUDE", 4, AP_OSD_Screen, AP_OSD_Setting),
100 :
101 : // @Param: BAT_VOLT_EN
102 : // @DisplayName: BATVOLT_EN
103 : // @Description: Displays main battery voltage
104 : // @Values: 0:Disabled,1:Enabled
105 :
106 : // @Param: BAT_VOLT_X
107 : // @DisplayName: BATVOLT_X
108 : // @Description: Horizontal position on screen
109 : // @Range: 0 59
110 :
111 : // @Param: BAT_VOLT_Y
112 : // @DisplayName: BATVOLT_Y
113 : // @Description: Vertical position on screen
114 : // @Range: 0 21
115 : AP_SUBGROUPINFO(bat_volt, "BAT_VOLT", 5, AP_OSD_Screen, AP_OSD_Setting),
116 :
117 : // @Param: RSSI_EN
118 : // @DisplayName: RSSI_EN
119 : // @Description: Displays RC signal strength
120 : // @Values: 0:Disabled,1:Enabled
121 :
122 : // @Param: RSSI_X
123 : // @DisplayName: RSSI_X
124 : // @Description: Horizontal position on screen
125 : // @Range: 0 59
126 :
127 : // @Param: RSSI_Y
128 : // @DisplayName: RSSI_Y
129 : // @Description: Vertical position on screen
130 : // @Range: 0 21
131 : AP_SUBGROUPINFO(rssi, "RSSI", 6, AP_OSD_Screen, AP_OSD_Setting),
132 :
133 : // @Param: CURRENT_EN
134 : // @DisplayName: CURRENT_EN
135 : // @Description: Displays main battery current
136 : // @Values: 0:Disabled,1:Enabled
137 :
138 : // @Param: CURRENT_X
139 : // @DisplayName: CURRENT_X
140 : // @Description: Horizontal position on screen
141 : // @Range: 0 59
142 :
143 : // @Param: CURRENT_Y
144 : // @DisplayName: CURRENT_Y
145 : // @Description: Vertical position on screen
146 : // @Range: 0 21
147 : AP_SUBGROUPINFO(current, "CURRENT", 7, AP_OSD_Screen, AP_OSD_Setting),
148 :
149 : // @Param: BATUSED_EN
150 : // @DisplayName: BATUSED_EN
151 : // @Description: Displays primary battery mAh consumed
152 : // @Values: 0:Disabled,1:Enabled
153 :
154 : // @Param: BATUSED_X
155 : // @DisplayName: BATUSED_X
156 : // @Description: Horizontal position on screen
157 : // @Range: 0 59
158 :
159 : // @Param: BATUSED_Y
160 : // @DisplayName: BATUSED_Y
161 : // @Description: Vertical position on screen
162 : // @Range: 0 21
163 : AP_SUBGROUPINFO(batused, "BATUSED", 8, AP_OSD_Screen, AP_OSD_Setting),
164 :
165 : // @Param: SATS_EN
166 : // @DisplayName: SATS_EN
167 : // @Description: Displays number of acquired satellites
168 : // @Values: 0:Disabled,1:Enabled
169 :
170 : // @Param: SATS_X
171 : // @DisplayName: SATS_X
172 : // @Description: Horizontal position on screen
173 : // @Range: 0 59
174 :
175 : // @Param: SATS_Y
176 : // @DisplayName: SATS_Y
177 : // @Description: Vertical position on screen
178 : // @Range: 0 21
179 : AP_SUBGROUPINFO(sats, "SATS", 9, AP_OSD_Screen, AP_OSD_Setting),
180 :
181 : // @Param: FLTMODE_EN
182 : // @DisplayName: FLTMODE_EN
183 : // @Description: Displays flight mode
184 : // @Values: 0:Disabled,1:Enabled
185 :
186 : // @Param: FLTMODE_X
187 : // @DisplayName: FLTMODE_X
188 : // @Description: Horizontal position on screen
189 : // @Range: 0 59
190 :
191 : // @Param: FLTMODE_Y
192 : // @DisplayName: FLTMODE_Y
193 : // @Description: Vertical position on screen
194 : // @Range: 0 21
195 : AP_SUBGROUPINFO(fltmode, "FLTMODE", 10, AP_OSD_Screen, AP_OSD_Setting),
196 :
197 : // @Param: MESSAGE_EN
198 : // @DisplayName: MESSAGE_EN
199 : // @Description: Displays Mavlink messages
200 : // @Values: 0:Disabled,1:Enabled
201 :
202 : // @Param: MESSAGE_X
203 : // @DisplayName: MESSAGE_X
204 : // @Description: Horizontal position on screen
205 : // @Range: 0 59
206 :
207 : // @Param: MESSAGE_Y
208 : // @DisplayName: MESSAGE_Y
209 : // @Description: Vertical position on screen
210 : // @Range: 0 21
211 : AP_SUBGROUPINFO(message, "MESSAGE", 11, AP_OSD_Screen, AP_OSD_Setting),
212 :
213 : // @Param: GSPEED_EN
214 : // @DisplayName: GSPEED_EN
215 : // @Description: Displays GPS ground speed
216 : // @Values: 0:Disabled,1:Enabled
217 :
218 : // @Param: GSPEED_X
219 : // @DisplayName: GSPEED_X
220 : // @Description: Horizontal position on screen
221 : // @Range: 0 59
222 :
223 : // @Param: GSPEED_Y
224 : // @DisplayName: GSPEED_Y
225 : // @Description: Vertical position on screen
226 : // @Range: 0 21
227 : AP_SUBGROUPINFO(gspeed, "GSPEED", 12, AP_OSD_Screen, AP_OSD_Setting),
228 :
229 : // @Param: HORIZON_EN
230 : // @DisplayName: HORIZON_EN
231 : // @Description: Displays artificial horizon
232 : // @Values: 0:Disabled,1:Enabled
233 :
234 : // @Param: HORIZON_X
235 : // @DisplayName: HORIZON_X
236 : // @Description: Horizontal position on screen
237 : // @Range: 0 59
238 :
239 : // @Param: HORIZON_Y
240 : // @DisplayName: HORIZON_Y
241 : // @Description: Vertical position on screen
242 : // @Range: 0 21
243 : AP_SUBGROUPINFO(horizon, "HORIZON", 13, AP_OSD_Screen, AP_OSD_Setting),
244 :
245 : // @Param: HOME_EN
246 : // @DisplayName: HOME_EN
247 : // @Description: Displays distance and relative direction to HOME
248 : // @Values: 0:Disabled,1:Enabled
249 :
250 : // @Param: HOME_X
251 : // @DisplayName: HOME_X
252 : // @Description: Horizontal position on screen
253 : // @Range: 0 59
254 :
255 : // @Param: HOME_Y
256 : // @DisplayName: HOME_Y
257 : // @Description: Vertical position on screen
258 : // @Range: 0 21
259 : AP_SUBGROUPINFO(home, "HOME", 14, AP_OSD_Screen, AP_OSD_Setting),
260 :
261 : // @Param: HEADING_EN
262 : // @DisplayName: HEADING_EN
263 : // @Description: Displays heading
264 : // @Values: 0:Disabled,1:Enabled
265 :
266 : // @Param: HEADING_X
267 : // @DisplayName: HEADING_X
268 : // @Description: Horizontal position on screen
269 : // @Range: 0 59
270 :
271 : // @Param: HEADING_Y
272 : // @DisplayName: HEADING_Y
273 : // @Description: Vertical position on screen
274 : // @Range: 0 21
275 : AP_SUBGROUPINFO(heading, "HEADING", 15, AP_OSD_Screen, AP_OSD_Setting),
276 :
277 : // @Param: THROTTLE_EN
278 : // @DisplayName: THROTTLE_EN
279 : // @Description: Displays actual throttle percentage being sent to motor(s)
280 : // @Values: 0:Disabled,1:Enabled
281 :
282 : // @Param: THROTTLE_X
283 : // @DisplayName: THROTTLE_X
284 : // @Description: Horizontal position on screen
285 : // @Range: 0 59
286 :
287 : // @Param: THROTTLE_Y
288 : // @DisplayName: THROTTLE_Y
289 : // @Description: Vertical position on screen
290 : // @Range: 0 21
291 : AP_SUBGROUPINFO(throttle, "THROTTLE", 16, AP_OSD_Screen, AP_OSD_Setting),
292 :
293 : // @Param: COMPASS_EN
294 : // @DisplayName: COMPASS_EN
295 : // @Description: Enables display of compass rose
296 : // @Values: 0:Disabled,1:Enabled
297 :
298 : // @Param: COMPASS_X
299 : // @DisplayName: COMPASS_X
300 : // @Description: Horizontal position on screen
301 : // @Range: 0 59
302 :
303 : // @Param: COMPASS_Y
304 : // @DisplayName: COMPASS_Y
305 : // @Description: Vertical position on screen
306 : // @Range: 0 21
307 : AP_SUBGROUPINFO(compass, "COMPASS", 17, AP_OSD_Screen, AP_OSD_Setting),
308 :
309 : // @Param: WIND_EN
310 : // @DisplayName: WIND_EN
311 : // @Description: Displays wind speed and relative direction, on Rover this is the apparent wind speed and direction from the windvane, if fitted
312 : // @Values: 0:Disabled,1:Enabled
313 :
314 : // @Param: WIND_X
315 : // @DisplayName: WIND_X
316 : // @Description: Horizontal position on screen
317 : // @Range: 0 59
318 :
319 : // @Param: WIND_Y
320 : // @DisplayName: WIND_Y
321 : // @Description: Vertical position on screen
322 : // @Range: 0 21
323 : AP_SUBGROUPINFO(wind, "WIND", 18, AP_OSD_Screen, AP_OSD_Setting),
324 :
325 :
326 : // @Param: ASPEED_EN
327 : // @DisplayName: ASPEED_EN
328 : // @Description: Displays airspeed value being used by TECS (fused value)
329 : // @Values: 0:Disabled,1:Enabled
330 :
331 : // @Param: ASPEED_X
332 : // @DisplayName: ASPEED_X
333 : // @Description: Horizontal position on screen
334 : // @Range: 0 59
335 :
336 : // @Param: ASPEED_Y
337 : // @DisplayName: ASPEED_Y
338 : // @Description: Vertical position on screen
339 : // @Range: 0 21
340 : AP_SUBGROUPINFO(aspeed, "ASPEED", 19, AP_OSD_Screen, AP_OSD_Setting),
341 :
342 : // @Param: VSPEED_EN
343 : // @DisplayName: VSPEED_EN
344 : // @Description: Displays climb rate
345 : // @Values: 0:Disabled,1:Enabled
346 :
347 : // @Param: VSPEED_X
348 : // @DisplayName: VSPEED_X
349 : // @Description: Horizontal position on screen
350 : // @Range: 0 59
351 :
352 : // @Param: VSPEED_Y
353 : // @DisplayName: VSPEED_Y
354 : // @Description: Vertical position on screen
355 : // @Range: 0 21
356 : AP_SUBGROUPINFO(vspeed, "VSPEED", 20, AP_OSD_Screen, AP_OSD_Setting),
357 :
358 : #if HAL_WITH_ESC_TELEM
359 : // @Param: ESCTEMP_EN
360 : // @DisplayName: ESCTEMP_EN
361 : // @Description: Displays highest temp of all active ESCs, or of a specific ECS if OSDx_ESC_IDX is set
362 : // @Values: 0:Disabled,1:Enabled
363 :
364 : // @Param: ESCTEMP_X
365 : // @DisplayName: ESCTEMP_X
366 : // @Description: Horizontal position on screen
367 : // @Range: 0 59
368 :
369 : // @Param: ESCTEMP_Y
370 : // @DisplayName: ESCTEMP_Y
371 : // @Description: Vertical position on screen
372 : // @Range: 0 21
373 : AP_SUBGROUPINFO(esc_temp, "ESCTEMP", 21, AP_OSD_Screen, AP_OSD_Setting),
374 :
375 : // @Param: ESCRPM_EN
376 : // @DisplayName: ESCRPM_EN
377 : // @Description: Displays highest rpm of all active ESCs, or of a specific ESC if OSDx_ESC_IDX is set
378 : // @Values: 0:Disabled,1:Enabled
379 :
380 : // @Param: ESCRPM_X
381 : // @DisplayName: ESCRPM_X
382 : // @Description: Horizontal position on screen
383 : // @Range: 0 59
384 :
385 : // @Param: ESCRPM_Y
386 : // @DisplayName: ESCRPM_Y
387 : // @Description: Vertical position on screen
388 : // @Range: 0 21
389 : AP_SUBGROUPINFO(esc_rpm, "ESCRPM", 22, AP_OSD_Screen, AP_OSD_Setting),
390 :
391 : // @Param: ESCAMPS_EN
392 : // @DisplayName: ESCAMPS_EN
393 : // @Description: Displays the current of the ESC with the highest rpm of all active ESCs, or of a specific ESC if OSDx_ESC_IDX is set
394 : // @Values: 0:Disabled,1:Enabled
395 :
396 : // @Param: ESCAMPS_X
397 : // @DisplayName: ESCAMPS_X
398 : // @Description: Horizontal position on screen
399 : // @Range: 0 59
400 :
401 : // @Param: ESCAMPS_Y
402 : // @DisplayName: ESCAMPS_Y
403 : // @Description: Vertical position on screen
404 : // @Range: 0 21
405 : AP_SUBGROUPINFO(esc_amps, "ESCAMPS", 23, AP_OSD_Screen, AP_OSD_Setting),
406 : #endif
407 : // @Param: GPSLAT_EN
408 : // @DisplayName: GPSLAT_EN
409 : // @Description: Displays GPS latitude
410 : // @Values: 0:Disabled,1:Enabled
411 :
412 : // @Param: GPSLAT_X
413 : // @DisplayName: GPSLAT_X
414 : // @Description: Horizontal position on screen
415 : // @Range: 0 59
416 :
417 : // @Param: GPSLAT_Y
418 : // @DisplayName: GPSLAT_Y
419 : // @Description: Vertical position on screen
420 : // @Range: 0 21
421 : AP_SUBGROUPINFO(gps_latitude, "GPSLAT", 24, AP_OSD_Screen, AP_OSD_Setting),
422 :
423 : // @Param: GPSLONG_EN
424 : // @DisplayName: GPSLONG_EN
425 : // @Description: Displays GPS longitude
426 : // @Values: 0:Disabled,1:Enabled
427 :
428 : // @Param: GPSLONG_X
429 : // @DisplayName: GPSLONG_X
430 : // @Description: Horizontal position on screen
431 : // @Range: 0 59
432 :
433 : // @Param: GPSLONG_Y
434 : // @DisplayName: GPSLONG_Y
435 : // @Description: Vertical position on screen
436 : // @Range: 0 21
437 : AP_SUBGROUPINFO(gps_longitude, "GPSLONG", 25, AP_OSD_Screen, AP_OSD_Setting),
438 :
439 : // @Param: ROLL_EN
440 : // @DisplayName: ROLL_EN
441 : // @Description: Displays degrees of roll from level
442 : // @Values: 0:Disabled,1:Enabled
443 :
444 : // @Param: ROLL_X
445 : // @DisplayName: ROLL_X
446 : // @Description: Horizontal position on screen
447 : // @Range: 0 59
448 :
449 : // @Param: ROLL_Y
450 : // @DisplayName: ROLL_Y
451 : // @Description: Vertical position on screen
452 : // @Range: 0 21
453 : AP_SUBGROUPINFO(roll_angle, "ROLL", 26, AP_OSD_Screen, AP_OSD_Setting),
454 :
455 : // @Param: PITCH_EN
456 : // @DisplayName: PITCH_EN
457 : // @Description: Displays degrees of pitch from level
458 : // @Values: 0:Disabled,1:Enabled
459 :
460 : // @Param: PITCH_X
461 : // @DisplayName: PITCH_X
462 : // @Description: Horizontal position on screen
463 : // @Range: 0 59
464 :
465 : // @Param: PITCH_Y
466 : // @DisplayName: PITCH_Y
467 : // @Description: Vertical position on screen
468 : // @Range: 0 21
469 : AP_SUBGROUPINFO(pitch_angle, "PITCH", 27, AP_OSD_Screen, AP_OSD_Setting),
470 :
471 : // @Param: TEMP_EN
472 : // @DisplayName: TEMP_EN
473 : // @Description: Displays temperature reported by primary barometer
474 : // @Values: 0:Disabled,1:Enabled
475 :
476 : // @Param: TEMP_X
477 : // @DisplayName: TEMP_X
478 : // @Description: Horizontal position on screen
479 : // @Range: 0 59
480 :
481 : // @Param: TEMP_Y
482 : // @DisplayName: TEMP_Y
483 : // @Description: Vertical position on screen
484 : // @Range: 0 21
485 : AP_SUBGROUPINFO(temp, "TEMP", 28, AP_OSD_Screen, AP_OSD_Setting),
486 :
487 : // @Param: HDOP_EN
488 : // @DisplayName: HDOP_EN
489 : // @Description: Displays Horizontal Dilution Of Position
490 : // @Values: 0:Disabled,1:Enabled
491 :
492 : // @Param: HDOP_X
493 : // @DisplayName: HDOP_X
494 : // @Description: Horizontal position on screen
495 : // @Range: 0 59
496 :
497 : // @Param: HDOP_Y
498 : // @DisplayName: HDOP_Y
499 : // @Description: Vertical position on screen
500 : // @Range: 0 21
501 : AP_SUBGROUPINFO(hdop, "HDOP", 29, AP_OSD_Screen, AP_OSD_Setting),
502 :
503 : // @Param: WAYPOINT_EN
504 : // @DisplayName: WAYPOINT_EN
505 : // @Description: Displays bearing and distance to next waypoint
506 : // @Values: 0:Disabled,1:Enabled
507 :
508 : // @Param: WAYPOINT_X
509 : // @DisplayName: WAYPOINT_X
510 : // @Description: Horizontal position on screen
511 : // @Range: 0 59
512 :
513 : // @Param: WAYPOINT_Y
514 : // @DisplayName: WAYPOINT_Y
515 : // @Description: Vertical position on screen
516 : // @Range: 0 21
517 : AP_SUBGROUPINFO(waypoint, "WAYPOINT", 30, AP_OSD_Screen, AP_OSD_Setting),
518 :
519 : // @Param: XTRACK_EN
520 : // @DisplayName: XTRACK_EN
521 : // @Description: Displays crosstrack error
522 : // @Values: 0:Disabled,1:Enabled
523 :
524 : // @Param: XTRACK_X
525 : // @DisplayName: XTRACK_X
526 : // @Description: Horizontal position on screen
527 : // @Range: 0 59
528 :
529 : // @Param: XTRACK_Y
530 : // @DisplayName: XTRACK_Y
531 : // @Description: Vertical position on screen
532 : // @Range: 0 21
533 : AP_SUBGROUPINFO(xtrack_error, "XTRACK", 31, AP_OSD_Screen, AP_OSD_Setting),
534 :
535 : // @Param: DIST_EN
536 : // @DisplayName: DIST_EN
537 : // @Description: Displays total distance flown
538 : // @Values: 0:Disabled,1:Enabled
539 :
540 : // @Param: DIST_X
541 : // @DisplayName: DIST_X
542 : // @Description: Horizontal position on screen
543 : // @Range: 0 59
544 :
545 : // @Param: DIST_Y
546 : // @DisplayName: DIST_Y
547 : // @Description: Vertical position on screen
548 : // @Range: 0 21
549 : AP_SUBGROUPINFO(dist, "DIST", 32, AP_OSD_Screen, AP_OSD_Setting),
550 :
551 : // @Param: STATS_EN
552 : // @DisplayName: STATS_EN
553 : // @Description: Displays flight stats
554 : // @Values: 0:Disabled,1:Enabled
555 :
556 : // @Param: STATS_X
557 : // @DisplayName: STATS_X
558 : // @Description: Horizontal position on screen
559 : // @Range: 0 59
560 :
561 : // @Param: STATS_Y
562 : // @DisplayName: STATS_Y
563 : // @Description: Vertical position on screen
564 : // @Range: 0 21
565 : AP_SUBGROUPINFO(stat, "STATS", 33, AP_OSD_Screen, AP_OSD_Setting),
566 :
567 : // @Param: FLTIME_EN
568 : // @DisplayName: FLTIME_EN
569 : // @Description: Displays total flight time
570 : // @Values: 0:Disabled,1:Enabled
571 :
572 : // @Param: FLTIME_X
573 : // @DisplayName: FLTIME_X
574 : // @Description: Horizontal position on screen
575 : // @Range: 0 59
576 :
577 : // @Param: FLTIME_Y
578 : // @DisplayName: FLTIME_Y
579 : // @Description: Vertical position on screen
580 : // @Range: 0 21
581 : AP_SUBGROUPINFO(flightime, "FLTIME", 34, AP_OSD_Screen, AP_OSD_Setting),
582 :
583 : // @Param: CLIMBEFF_EN
584 : // @DisplayName: CLIMBEFF_EN
585 : // @Description: Displays climb efficiency (climb rate/current)
586 : // @Values: 0:Disabled,1:Enabled
587 :
588 : // @Param: CLIMBEFF_X
589 : // @DisplayName: CLIMBEFF_X
590 : // @Description: Horizontal position on screen
591 : // @Range: 0 59
592 :
593 : // @Param: CLIMBEFF_Y
594 : // @DisplayName: CLIMBEFF_Y
595 : // @Description: Vertical position on screen
596 : // @Range: 0 21
597 : AP_SUBGROUPINFO(climbeff, "CLIMBEFF", 35, AP_OSD_Screen, AP_OSD_Setting),
598 :
599 : // @Param: EFF_EN
600 : // @DisplayName: EFF_EN
601 : // @Description: Displays flight efficiency (mAh/km or /mi)
602 : // @Values: 0:Disabled,1:Enabled
603 :
604 : // @Param: EFF_X
605 : // @DisplayName: EFF_X
606 : // @Description: Horizontal position on screen
607 : // @Range: 0 59
608 :
609 : // @Param: EFF_Y
610 : // @DisplayName: EFF_Y
611 : // @Description: Vertical position on screen
612 : // @Range: 0 21
613 : AP_SUBGROUPINFO(eff, "EFF", 36, AP_OSD_Screen, AP_OSD_Setting),
614 :
615 : #if BARO_MAX_INSTANCES > 1
616 : // @Param: BTEMP_EN
617 : // @DisplayName: BTEMP_EN
618 : // @Description: Displays temperature reported by secondary barometer
619 : // @Values: 0:Disabled,1:Enabled
620 :
621 : // @Param: BTEMP_X
622 : // @DisplayName: BTEMP_X
623 : // @Description: Horizontal position on screen
624 : // @Range: 0 59
625 :
626 : // @Param: BTEMP_Y
627 : // @DisplayName: BTEMP_Y
628 : // @Description: Vertical position on screen
629 : // @Range: 0 21
630 : AP_SUBGROUPINFO(btemp, "BTEMP", 37, AP_OSD_Screen, AP_OSD_Setting),
631 : #endif
632 :
633 : // @Param: ATEMP_EN
634 : // @DisplayName: ATEMP_EN
635 : // @Description: Displays temperature reported by primary airspeed sensor
636 : // @Values: 0:Disabled,1:Enabled
637 :
638 : // @Param: ATEMP_X
639 : // @DisplayName: ATEMP_X
640 : // @Description: Horizontal position on screen
641 : // @Range: 0 59
642 :
643 : // @Param: ATEMP_Y
644 : // @DisplayName: ATEMP_Y
645 : // @Description: Vertical position on screen
646 : // @Range: 0 21
647 : AP_SUBGROUPINFO(atemp, "ATEMP", 38, AP_OSD_Screen, AP_OSD_Setting),
648 :
649 : // @Param: BAT2_VLT_EN
650 : // @DisplayName: BAT2VLT_EN
651 : // @Description: Displays battery2 voltage
652 : // @Values: 0:Disabled,1:Enabled
653 :
654 : // @Param: BAT2_VLT_X
655 : // @DisplayName: BAT2VLT_X
656 : // @Description: Horizontal position on screen
657 : // @Range: 0 59
658 :
659 : // @Param: BAT2_VLT_Y
660 : // @DisplayName: BAT2VLT_Y
661 : // @Description: Vertical position on screen
662 : // @Range: 0 21
663 : AP_SUBGROUPINFO(bat2_vlt, "BAT2_VLT", 39, AP_OSD_Screen, AP_OSD_Setting),
664 :
665 : // @Param: BAT2USED_EN
666 : // @DisplayName: BAT2USED_EN
667 : // @Description: Displays secondary battery mAh consumed
668 : // @Values: 0:Disabled,1:Enabled
669 :
670 : // @Param: BAT2USED_X
671 : // @DisplayName: BAT2USED_X
672 : // @Description: Horizontal position on screen
673 : // @Range: 0 59
674 :
675 : // @Param: BAT2USED_Y
676 : // @DisplayName: BAT2USED_Y
677 : // @Description: Vertical position on screen
678 : // @Range: 0 21
679 : AP_SUBGROUPINFO(bat2used, "BAT2USED", 40, AP_OSD_Screen, AP_OSD_Setting),
680 :
681 :
682 : // @Param: ASPD2_EN
683 : // @DisplayName: ASPD2_EN
684 : // @Description: Displays airspeed reported directly from secondary airspeed sensor
685 : // @Values: 0:Disabled,1:Enabled
686 :
687 : // @Param: ASPD2_X
688 : // @DisplayName: ASPD2_X
689 : // @Description: Horizontal position on screen
690 : // @Range: 0 59
691 :
692 : // @Param: ASPD2_Y
693 : // @DisplayName: ASPD2_Y
694 : // @Description: Vertical position on screen
695 : // @Range: 0 21
696 : AP_SUBGROUPINFO(aspd2, "ASPD2", 41, AP_OSD_Screen, AP_OSD_Setting),
697 :
698 : // @Param: ASPD1_EN
699 : // @DisplayName: ASPD1_EN
700 : // @Description: Displays airspeed reported directly from primary airspeed sensor
701 : // @Values: 0:Disabled,1:Enabled
702 :
703 : // @Param: ASPD1_X
704 : // @DisplayName: ASPD1_X
705 : // @Description: Horizontal position on screen
706 : // @Range: 0 59
707 :
708 : // @Param: ASPD1_Y
709 : // @DisplayName: ASPD1_Y
710 : // @Description: Vertical position on screen
711 : // @Range: 0 21
712 : AP_SUBGROUPINFO(aspd1, "ASPD1", 42, AP_OSD_Screen, AP_OSD_Setting),
713 :
714 : // @Param: CLK_EN
715 : // @DisplayName: CLK_EN
716 : // @Description: Displays a clock panel based on AP_RTC local time
717 : // @Values: 0:Disabled,1:Enabled
718 :
719 : // @Param: CLK_X
720 : // @DisplayName: CLK_X
721 : // @Description: Horizontal position on screen
722 : // @Range: 0 59
723 :
724 : // @Param: CLK_Y
725 : // @DisplayName: CLK_Y
726 : // @Description: Vertical position on screen
727 : // @Range: 0 21
728 : AP_SUBGROUPINFO(clk, "CLK", 43, AP_OSD_Screen, AP_OSD_Setting),
729 :
730 : #if HAL_OSD_SIDEBAR_ENABLE || HAL_MSP_ENABLED
731 : // @Param: SIDEBARS_EN
732 : // @DisplayName: SIDEBARS_EN
733 : // @Description: Displays artificial horizon side bars
734 : // @Values: 0:Disabled,1:Enabled
735 :
736 : // @Param: SIDEBARS_X
737 : // @DisplayName: SIDEBARS_X
738 : // @Description: Horizontal position on screen
739 : // @Range: 0 59
740 :
741 : // @Param: SIDEBARS_Y
742 : // @DisplayName: SIDEBARS_Y
743 : // @Description: Vertical position on screen
744 : // @Range: 0 21
745 : AP_SUBGROUPINFO(sidebars, "SIDEBARS", 44, AP_OSD_Screen, AP_OSD_Setting),
746 : #endif
747 :
748 : #if HAL_MSP_ENABLED
749 : // @Param: CRSSHAIR_EN
750 : // @DisplayName: CRSSHAIR_EN
751 : // @Description: Displays artificial horizon crosshair (MSP OSD only)
752 : // @Values: 0:Disabled,1:Enabled
753 :
754 : // @Param: CRSSHAIR_X
755 : // @DisplayName: CRSSHAIR_X
756 : // @Description: Horizontal position on screen (MSP OSD only)
757 : // @Range: 0 59
758 :
759 : // @Param: CRSSHAIR_Y
760 : // @DisplayName: CRSSHAIR_Y
761 : // @Description: Vertical position on screen (MSP OSD only)
762 : // @Range: 0 21
763 : AP_SUBGROUPINFO(crosshair, "CRSSHAIR", 45, AP_OSD_Screen, AP_OSD_Setting),
764 :
765 : // @Param: HOMEDIST_EN
766 : // @DisplayName: HOMEDIST_EN
767 : // @Description: Displays distance from HOME (MSP OSD only)
768 : // @Values: 0:Disabled,1:Enabled
769 :
770 : // @Param: HOMEDIST_X
771 : // @DisplayName: HOMEDIST_X
772 : // @Description: Horizontal position on screen (MSP OSD only)
773 : // @Range: 0 59
774 :
775 : // @Param: HOMEDIST_Y
776 : // @DisplayName: HOMEDIST_Y
777 : // @Description: Vertical position on screen (MSP OSD only)
778 : // @Range: 0 21
779 : AP_SUBGROUPINFO(home_dist, "HOMEDIST", 46, AP_OSD_Screen, AP_OSD_Setting),
780 :
781 : // @Param: HOMEDIR_EN
782 : // @DisplayName: HOMEDIR_EN
783 : // @Description: Displays relative direction to HOME (MSP OSD only)
784 : // @Values: 0:Disabled,1:Enabled
785 :
786 : // @Param: HOMEDIR_X
787 : // @DisplayName: HOMEDIR_X
788 : // @Description: Horizontal position on screen
789 : // @Range: 0 59
790 :
791 : // @Param: HOMEDIR_Y
792 : // @DisplayName: HOMEDIR_Y
793 : // @Description: Vertical position on screen
794 : // @Range: 0 21
795 : AP_SUBGROUPINFO(home_dir, "HOMEDIR", 47, AP_OSD_Screen, AP_OSD_Setting),
796 :
797 : // @Param: POWER_EN
798 : // @DisplayName: POWER_EN
799 : // @Description: Displays power (MSP OSD only)
800 : // @Values: 0:Disabled,1:Enabled
801 :
802 : // @Param: POWER_X
803 : // @DisplayName: POWER_X
804 : // @Description: Horizontal position on screen
805 : // @Range: 0 59
806 :
807 : // @Param: POWER_Y
808 : // @DisplayName: POWER_Y
809 : // @Description: Vertical position on screen
810 : // @Range: 0 21
811 : AP_SUBGROUPINFO(power, "POWER", 48, AP_OSD_Screen, AP_OSD_Setting),
812 :
813 : // @Param: CELLVOLT_EN
814 : // @DisplayName: CELL_VOLT_EN
815 : // @Description: Displays average cell voltage (MSP OSD only)
816 : // @Values: 0:Disabled,1:Enabled
817 :
818 : // @Param: CELLVOLT_X
819 : // @DisplayName: CELL_VOLT_X
820 : // @Description: Horizontal position on screen
821 : // @Range: 0 59
822 :
823 : // @Param: CELLVOLT_Y
824 : // @DisplayName: CELL_VOLT_Y
825 : // @Description: Vertical position on screen
826 : // @Range: 0 21
827 : AP_SUBGROUPINFO(cell_volt, "CELLVOLT", 49, AP_OSD_Screen, AP_OSD_Setting),
828 :
829 : // @Param: BATTBAR_EN
830 : // @DisplayName: BATT_BAR_EN
831 : // @Description: Displays battery usage bar (MSP OSD only)
832 : // @Values: 0:Disabled,1:Enabled
833 :
834 : // @Param: BATTBAR_X
835 : // @DisplayName: BATT_BAR_X
836 : // @Description: Horizontal position on screen
837 : // @Range: 0 59
838 :
839 : // @Param: BATTBAR_Y
840 : // @DisplayName: BATT_BAR_Y
841 : // @Description: Vertical position on screen
842 : // @Range: 0 21
843 : AP_SUBGROUPINFO(batt_bar, "BATTBAR", 50, AP_OSD_Screen, AP_OSD_Setting),
844 :
845 : // @Param: ARMING_EN
846 : // @DisplayName: ARMING_EN
847 : // @Description: Displays arming status (MSP OSD only)
848 : // @Values: 0:Disabled,1:Enabled
849 :
850 : // @Param: ARMING_X
851 : // @DisplayName: ARMING_X
852 : // @Description: Horizontal position on screen
853 : // @Range: 0 59
854 :
855 : // @Param: ARMING_Y
856 : // @DisplayName: ARMING_Y
857 : // @Description: Vertical position on screen
858 : // @Range: 0 21
859 : AP_SUBGROUPINFO(arming, "ARMING", 51, AP_OSD_Screen, AP_OSD_Setting),
860 : #endif //HAL_MSP_ENABLED
861 :
862 : #if HAL_PLUSCODE_ENABLE
863 : // @Param: PLUSCODE_EN
864 : // @DisplayName: PLUSCODE_EN
865 : // @Description: Displays pluscode (OLC) element
866 : // @Values: 0:Disabled,1:Enabled
867 :
868 : // @Param: PLUSCODE_X
869 : // @DisplayName: PLUSCODE_X
870 : // @Description: Horizontal position on screen
871 : // @Range: 0 59
872 :
873 : // @Param: PLUSCODE_Y
874 : // @DisplayName: PLUSCODE_Y
875 : // @Description: Vertical position on screen
876 : // @Range: 0 21
877 : AP_SUBGROUPINFO(pluscode, "PLUSCODE", 52, AP_OSD_Screen, AP_OSD_Setting),
878 : #endif
879 :
880 : #if AP_OSD_CALLSIGN_FROM_SD_ENABLED
881 : // @Param: CALLSIGN_EN
882 : // @DisplayName: CALLSIGN_EN
883 : // @Description: Displays callsign from callsign.txt on microSD card
884 : // @Values: 0:Disabled,1:Enabled
885 :
886 : // @Param: CALLSIGN_X
887 : // @DisplayName: CALLSIGN_X
888 : // @Description: Horizontal position on screen
889 : // @Range: 0 59
890 :
891 : // @Param: CALLSIGN_Y
892 : // @DisplayName: CALLSIGN_Y
893 : // @Description: Vertical position on screen
894 : // @Range: 0 21
895 : AP_SUBGROUPINFO(callsign, "CALLSIGN", 53, AP_OSD_Screen, AP_OSD_Setting),
896 : #endif
897 :
898 : // @Param: CURRENT2_EN
899 : // @DisplayName: CURRENT2_EN
900 : // @Description: Displays 2nd battery current
901 : // @Values: 0:Disabled,1:Enabled
902 :
903 : // @Param: CURRENT2_X
904 : // @DisplayName: CURRENT2_X
905 : // @Description: Horizontal position on screen
906 : // @Range: 0 59
907 :
908 : // @Param: CURRENT2_Y
909 : // @DisplayName: CURRENT2_Y
910 : // @Description: Vertical position on screen
911 : // @Range: 0 21
912 : AP_SUBGROUPINFO(current2, "CURRENT2", 54, AP_OSD_Screen, AP_OSD_Setting),
913 :
914 : #if AP_VIDEOTX_ENABLED
915 : // @Param: VTX_PWR_EN
916 : // @DisplayName: VTX_PWR_EN
917 : // @Description: Displays VTX Power
918 : // @Values: 0:Disabled,1:Enabled
919 :
920 : // @Param: VTX_PWR_X
921 : // @DisplayName: VTX_PWR_X
922 : // @Description: Horizontal position on screen
923 : // @Range: 0 59
924 :
925 : // @Param: VTX_PWR_Y
926 : // @DisplayName: VTX_PWR_Y
927 : // @Description: Vertical position on screen
928 : // @Range: 0 21
929 : AP_SUBGROUPINFO(vtx_power, "VTX_PWR", 55, AP_OSD_Screen, AP_OSD_Setting),
930 : #endif // AP_VIDEOTX_ENABLED
931 :
932 : #if AP_TERRAIN_AVAILABLE
933 : // @Param: TER_HGT_EN
934 : // @DisplayName: TER_HGT_EN
935 : // @Description: Displays Height above terrain
936 : // @Values: 0:Disabled,1:Enabled
937 :
938 : // @Param: TER_HGT_X
939 : // @DisplayName: TER_HGT_X
940 : // @Description: Horizontal position on screen
941 : // @Range: 0 59
942 :
943 : // @Param: TER_HGT_Y
944 : // @DisplayName: TER_HGT_Y
945 : // @Description: Vertical position on screen
946 : // @Range: 0 21
947 : AP_SUBGROUPINFO(hgt_abvterr, "TER_HGT", 56, AP_OSD_Screen, AP_OSD_Setting),
948 : #endif
949 :
950 : // @Param: AVGCELLV_EN
951 : // @DisplayName: AVGCELLV_EN
952 : // @Description: Displays average cell voltage. WARNING: this can be inaccurate if the cell count is not detected or set properly. If the the battery is far from fully charged the detected cell count might not be accurate if auto cell count detection is used (OSD_CELL_COUNT=0).
953 : // @Values: 0:Disabled,1:Enabled
954 :
955 : // @Param: AVGCELLV_X
956 : // @DisplayName: AVGCELLV_X
957 : // @Description: Horizontal position on screen
958 : // @Range: 0 59
959 :
960 : // @Param: AVGCELLV_Y
961 : // @DisplayName: AVGCELLV_Y
962 : // @Description: Vertical position on screen
963 : // @Range: 0 21
964 : AP_SUBGROUPINFO(avgcellvolt, "AVGCELLV", 57, AP_OSD_Screen, AP_OSD_Setting),
965 :
966 : // @Param: RESTVOLT_EN
967 : // @DisplayName: RESTVOLT_EN
968 : // @Description: Displays main battery resting voltage
969 : // @Values: 0:Disabled,1:Enabled
970 :
971 : // @Param: RESTVOLT_X
972 : // @DisplayName: RESTVOLT_X
973 : // @Description: Horizontal position on screen
974 : // @Range: 0 59
975 :
976 : // @Param: RESTVOLT_Y
977 : // @DisplayName: RESTVOLT_Y
978 : // @Description: Vertical position on screen
979 : // @Range: 0 21
980 : AP_SUBGROUPINFO(restvolt, "RESTVOLT", 58, AP_OSD_Screen, AP_OSD_Setting),
981 :
982 : // @Param: FENCE_EN
983 : // @DisplayName: FENCE_EN
984 : // @Description: Displays indication of fence enable and breach
985 : // @Values: 0:Disabled,1:Enabled
986 :
987 : // @Param: FENCE_X
988 : // @DisplayName: FENCE_X
989 : // @Description: Horizontal position on screen
990 : // @Range: 0 59
991 :
992 : // @Param: FENCE_Y
993 : // @DisplayName: FENCE_Y
994 : // @Description: Vertical position on screen
995 : // @Range: 0 21
996 : AP_SUBGROUPINFO(fence, "FENCE", 59, AP_OSD_Screen, AP_OSD_Setting),
997 :
998 : // @Param: RNGF_EN
999 : // @DisplayName: RNGF_EN
1000 : // @Description: Displays a rangefinder's distance in cm
1001 : // @Values: 0:Disabled,1:Enabled
1002 :
1003 : // @Param: RNGF_X
1004 : // @DisplayName: RNGF_X
1005 : // @Description: Horizontal position on screen
1006 : // @Range: 0 59
1007 :
1008 : // @Param: RNGF_Y
1009 : // @DisplayName: RNGF_Y
1010 : // @Description: Vertical position on screen
1011 : // @Range: 0 21
1012 : AP_SUBGROUPINFO(rngf, "RNGF", 60, AP_OSD_Screen, AP_OSD_Setting),
1013 :
1014 : // @Param: ACRVOLT_EN
1015 : // @DisplayName: ACRVOLT_EN
1016 : // @Description: Displays resting voltage for the average cell. WARNING: this can be inaccurate if the cell count is not detected or set properly. If the the battery is far from fully charged the detected cell count might not be accurate if auto cell count detection is used (OSD_CELL_COUNT=0).
1017 : // @Values: 0:Disabled,1:Enabled
1018 :
1019 : // @Param: ACRVOLT_X
1020 : // @DisplayName: ACRVOLT_X
1021 : // @Description: Horizontal position on screen
1022 : // @Range: 0 59
1023 :
1024 : // @Param: ACRVOLT_Y
1025 : // @DisplayName: ACRVOLT_Y
1026 : // @Description: Vertical position on screen
1027 : // @Range: 0 21
1028 : AP_SUBGROUPINFO(avgcellrestvolt, "ACRVOLT", 61, AP_OSD_Screen, AP_OSD_Setting),
1029 :
1030 : #if AP_RPM_ENABLED
1031 : // @Param: RPM_EN
1032 : // @DisplayName: RPM_EN
1033 : // @Description: Displays main rotor revs/min
1034 : // @Values: 0:Disabled,1:Enabled
1035 :
1036 : // @Param: RPM_X
1037 : // @DisplayName: RPM_X
1038 : // @Description: Horizontal position on screen
1039 : // @Range: 0 29
1040 :
1041 : // @Param: RPM_Y
1042 : // @DisplayName: RPM_Y
1043 : // @Description: Vertical position on screen
1044 : // @Range: 0 15
1045 : AP_SUBGROUPINFO(rrpm, "RPM", 62, AP_OSD_Screen, AP_OSD_Setting),
1046 : #endif
1047 :
1048 : AP_GROUPEND
1049 : };
1050 :
1051 : const AP_Param::GroupInfo AP_OSD_Screen::var_info2[] = {
1052 : // duplicate of OSDn_ENABLE to ensure params are hidden when not enabled
1053 : AP_GROUPINFO_FLAGS("ENABLE", 2, AP_OSD_Screen, enabled, 0, AP_PARAM_FLAG_ENABLE | AP_PARAM_FLAG_HIDDEN),
1054 :
1055 : // @Param: LINK_Q_EN
1056 : // @DisplayName: LINK_Q_EN
1057 : // @Description: Displays Receiver link quality
1058 : // @Values: 0:Disabled,1:Enabled
1059 :
1060 : // @Param: LINK_Q_X
1061 : // @DisplayName: LINK_Q_X
1062 : // @Description: Horizontal position on screen
1063 : // @Range: 0 59
1064 :
1065 : // @Param: LINK_Q_Y
1066 : // @DisplayName: LINK_Q_Y
1067 : // @Description: Vertical position on screen
1068 : // @Range: 0 21
1069 : AP_SUBGROUPINFO(link_quality, "LINK_Q", 1, AP_OSD_Screen, AP_OSD_Setting),
1070 :
1071 : #if HAL_WITH_MSP_DISPLAYPORT
1072 : // @Param: TXT_RES
1073 : // @DisplayName: Sets the overlay text resolution (MSP DisplayPort only)
1074 : // @Description: Sets the overlay text resolution for this screen to either SD 30x16 or HD 50x18/60x22 (MSP DisplayPort only)
1075 : // @Values: 0:30x16,1:50x18,2:60x22
1076 : // @User: Standard
1077 : AP_GROUPINFO("TXT_RES", 3, AP_OSD_Screen, txt_resolution, 0),
1078 :
1079 : // @Param: FONT
1080 : // @DisplayName: Sets the font index for this screen (MSP DisplayPort only)
1081 : // @Description: Sets the font index for this screen (MSP DisplayPort only)
1082 : // @Range: 0 21
1083 : // @User: Standard
1084 : AP_GROUPINFO("FONT", 4, AP_OSD_Screen, font_index, 0),
1085 : #endif
1086 :
1087 : #if AP_OSD_EXTENDED_LNK_STATS
1088 : // @Param: RC_PWR_EN
1089 : // @DisplayName: RC_PWR_EN
1090 : // @Description: Displays the RC link transmit (TX) power in mW or W, depending on level
1091 : // @Values: 0:Disabled,1:Enabled
1092 :
1093 : // @Param: RC_PWR_X
1094 : // @DisplayName: RC_PWR_X
1095 : // @Description: Horizontal position on screen
1096 : // @Range: 0 59
1097 :
1098 : // @Param: RC_PWR_Y
1099 : // @DisplayName: RC_PWR_Y
1100 : // @Description: Vertical position on screen
1101 : // @Range: 0 21
1102 : AP_SUBGROUPINFO(rc_tx_power, "RC_PWR", 5, AP_OSD_Screen, AP_OSD_Setting),
1103 :
1104 : // @Param: RSSIDBM_EN
1105 : // @DisplayName: RSSIDBM_EN
1106 : // @Description: Displays RC link signal strength in dBm
1107 : // @Values: 0:Disabled,1:Enabled
1108 :
1109 : // @Param: RSSIDBM_X
1110 : // @DisplayName: RSSIDBM_X
1111 : // @Description: Horizontal position on screen
1112 : // @Range: 0 59
1113 :
1114 : // @Param: RSSIDBM_Y
1115 : // @DisplayName: RSSIDBM_Y
1116 : // @Description: Vertical position on screen
1117 : // @Range: 0 21
1118 : AP_SUBGROUPINFO(rc_rssi_dbm, "RSSIDBM", 6, AP_OSD_Screen, AP_OSD_Setting),
1119 :
1120 : // @Param: RC_SNR_EN
1121 : // @DisplayName: RC_SNR_EN
1122 : // @Description: Displays RC link signal to noise ratio in dB
1123 : // @Values: 0:Disabled,1:Enabled
1124 :
1125 : // @Param: RC_SNR_X
1126 : // @DisplayName: RC_SNR_X
1127 : // @Description: Horizontal position on screen
1128 : // @Range: 0 59
1129 :
1130 : // @Param: RC_SNR_Y
1131 : // @DisplayName: RC_SNR_Y
1132 : // @Description: Vertical position on screen
1133 : // @Range: 0 21
1134 : AP_SUBGROUPINFO(rc_snr, "RC_SNR", 7, AP_OSD_Screen, AP_OSD_Setting),
1135 :
1136 : // @Param: RC_ANT_EN
1137 : // @DisplayName: RC_ANT_EN
1138 : // @Description: Displays the current RC link active antenna
1139 : // @Values: 0:Disabled,1:Enabled
1140 :
1141 : // @Param: RC_ANT_X
1142 : // @DisplayName: RC_ANT_X
1143 : // @Description: Horizontal position on screen
1144 : // @Range: 0 59
1145 :
1146 : // @Param: RC_ANT_Y
1147 : // @DisplayName: RC_ANT_Y
1148 : // @Description: Vertical position on screen
1149 : // @Range: 0 21
1150 : AP_SUBGROUPINFO(rc_active_antenna, "RC_ANT", 8, AP_OSD_Screen, AP_OSD_Setting),
1151 :
1152 : // @Param: RC_LQ_EN
1153 : // @DisplayName: RC_LQ_EN
1154 : // @Description: Displays the RC link quality (uplink, 0 to 100%) and also RF mode if bit 7 of OSD_OPTIONS is set
1155 : // @Values: 0:Disabled,1:Enabled
1156 :
1157 : // @Param: RC_LQ_X
1158 : // @DisplayName: RC_LQ_X
1159 : // @Description: Horizontal position on screen
1160 : // @Range: 0 59
1161 :
1162 : // @Param: RC_LQ_Y
1163 : // @DisplayName: RC_LQ_Y
1164 : // @Description: Vertical position on screen
1165 : // @Range: 0 21
1166 : AP_SUBGROUPINFO(rc_lq, "RC_LQ", 9, AP_OSD_Screen, AP_OSD_Setting),
1167 : #endif
1168 :
1169 : #if HAL_WITH_ESC_TELEM
1170 : // @Param: ESC_IDX
1171 : // @DisplayName: ESC_IDX
1172 : // @Description: Index of the ESC to use for displaying ESC information. 0 means use the ESC with the highest value.
1173 : // @Range: 0 32
1174 : AP_GROUPINFO("ESC_IDX", 10, AP_OSD_Screen, esc_index, 0),
1175 : #endif
1176 :
1177 : AP_GROUPEND
1178 : };
1179 :
1180 :
1181 : uint8_t AP_OSD_AbstractScreen::symbols_lookup_table[AP_OSD_NUM_SYMBOLS];
1182 :
1183 : // Symbol indexes to acces _symbols[index][set]
1184 : #define SYM_M 0
1185 : #define SYM_KM 1
1186 : #define SYM_FT 2
1187 : #define SYM_MI 3
1188 : #define SYM_ALT_M 4
1189 : #define SYM_ALT_FT 5
1190 : #define SYM_BATT_FULL 6
1191 : #define SYM_RSSI 7
1192 :
1193 : #define SYM_VOLT 8
1194 : #define SYM_AMP 9
1195 : #define SYM_MAH 10
1196 : #define SYM_MS 11
1197 : #define SYM_FS 12
1198 : #define SYM_KMH 13
1199 : #define SYM_MPH 14
1200 : #define SYM_DEGR 15
1201 : #define SYM_PCNT 16
1202 : #define SYM_RPM 17
1203 : #define SYM_ASPD 18
1204 : #define SYM_GSPD 19
1205 : #define SYM_WSPD 20
1206 : #define SYM_VSPD 21
1207 : #define SYM_WPNO 22
1208 : #define SYM_WPDIR 23
1209 : #define SYM_WPDST 24
1210 : #define SYM_FTMIN 25
1211 : #define SYM_FTSEC 26
1212 :
1213 : #define SYM_SAT_L 27
1214 : #define SYM_SAT_R 28
1215 : #define SYM_HDOP_L 29
1216 : #define SYM_HDOP_R 30
1217 :
1218 : #define SYM_HOME 31
1219 : #define SYM_WIND 32
1220 :
1221 : #define SYM_ARROW_START 33
1222 : #define SYM_ARROW_COUNT 34
1223 : #define SYM_AH_H_START 35
1224 : #define SYM_AH_H_COUNT 36
1225 :
1226 : #define SYM_AH_V_START 37
1227 : #define SYM_AH_V_COUNT 38
1228 :
1229 : #define SYM_AH_CENTER_LINE_LEFT 39
1230 : #define SYM_AH_CENTER_LINE_RIGHT 40
1231 : #define SYM_AH_CENTER 41
1232 :
1233 : #define SYM_HEADING_N 42
1234 : #define SYM_HEADING_S 43
1235 : #define SYM_HEADING_E 44
1236 : #define SYM_HEADING_W 45
1237 : #define SYM_HEADING_DIVIDED_LINE 46
1238 : #define SYM_HEADING_LINE 47
1239 :
1240 : #define SYM_UP_UP 48
1241 : #define SYM_UP 49
1242 : #define SYM_DOWN 50
1243 : #define SYM_DOWN_DOWN 51
1244 :
1245 : #define SYM_DEGREES_C 52
1246 : #define SYM_DEGREES_F 53
1247 : #define SYM_GPS_LAT 54
1248 : #define SYM_GPS_LONG 55
1249 : #define SYM_ARMED 56
1250 : #define SYM_DISARMED 57
1251 : #define SYM_ROLL0 58
1252 : #define SYM_ROLLR 59
1253 : #define SYM_ROLLL 60
1254 : #define SYM_PTCH0 61
1255 : #define SYM_PTCHUP 62
1256 : #define SYM_PTCHDWN 63
1257 : #define SYM_XERR 64
1258 : #define SYM_KN 65
1259 : #define SYM_NM 66
1260 : #define SYM_DIST 67
1261 : #define SYM_FLY 68
1262 : #define SYM_EFF 69
1263 : #define SYM_AH 70
1264 : #define SYM_MW 71
1265 : #define SYM_CLK 72
1266 : #define SYM_KILO 73
1267 : #define SYM_TERALT 74
1268 : #define SYM_FENCE_ENABLED 75
1269 : #define SYM_FENCE_DISABLED 76
1270 : #define SYM_RNGFD 77
1271 : #define SYM_LQ 78
1272 :
1273 : #define SYM_SIDEBAR_R_ARROW 79
1274 : #define SYM_SIDEBAR_L_ARROW 80
1275 : #define SYM_SIDEBAR_A 81
1276 : #define SYM_SIDEBAR_B 82
1277 : #define SYM_SIDEBAR_C 83
1278 : #define SYM_SIDEBAR_D 84
1279 : #define SYM_SIDEBAR_E 85
1280 : #define SYM_SIDEBAR_F 86
1281 : #define SYM_SIDEBAR_G 87
1282 : #define SYM_SIDEBAR_H 88
1283 : #define SYM_SIDEBAR_I 89
1284 : #define SYM_SIDEBAR_J 90
1285 :
1286 : #define SYM_WATT 91
1287 : #define SYM_WH 92
1288 : #define SYM_DB 93
1289 : #define SYM_DBM 94
1290 : #define SYM_SNR 95
1291 : #define SYM_ANT 96
1292 : #define SYM_ARROW_RIGHT 97
1293 : #define SYM_ARROW_LEFT 98
1294 :
1295 : #define SYM_G 99
1296 : #define SYM_BATT_UNKNOWN 100
1297 : #define SYM_ROLL 101
1298 : #define SYM_PITCH 102
1299 : #define SYM_DPS 103
1300 : #define SYM_HEADING 104
1301 : #define SYM_RADIUS 105
1302 : #define SYM_FLAP 106
1303 :
1304 : #define SYMBOL(n) AP_OSD_AbstractScreen::symbols_lookup_table[n]
1305 :
1306 : // constructor
1307 8244 : AP_OSD_Screen::AP_OSD_Screen()
1308 : {
1309 8244 : AP_Param::setup_object_defaults(this, var_info);
1310 8244 : AP_Param::setup_object_defaults(this, var_info2);
1311 8244 : }
1312 :
1313 548 : void AP_OSD_AbstractScreen::set_backend(AP_OSD_Backend *_backend)
1314 : {
1315 548 : backend = _backend;
1316 548 : osd = _backend->get_osd();
1317 548 : };
1318 :
1319 1934 : bool AP_OSD_AbstractScreen::check_option(uint32_t option)
1320 : {
1321 1934 : return osd?(osd->options & option) != 0 : false;
1322 : }
1323 :
1324 : /*
1325 : get the right units icon given a unit
1326 : */
1327 1934 : char AP_OSD_AbstractScreen::u_icon(enum unit_type unit)
1328 : {
1329 : static const uint8_t icons_metric[UNIT_TYPE_LAST] {
1330 : SYM_ALT_M, //ALTITUDE
1331 : SYM_KMH, //SPEED
1332 : SYM_MS, //VSPEED
1333 : SYM_M, //DISTANCE
1334 : SYM_KM, //DISTANCE_LONG
1335 : SYM_DEGREES_C //TEMPERATURE
1336 : };
1337 : static const uint8_t icons_imperial[UNIT_TYPE_LAST] {
1338 : SYM_ALT_FT, //ALTITUDE
1339 : SYM_MPH, //SPEED
1340 : SYM_FS, //VSPEED
1341 : SYM_FT, //DISTANCE
1342 : SYM_MI, //DISTANCE_LONG
1343 : SYM_DEGREES_F //TEMPERATURE
1344 : };
1345 : static const uint8_t icons_SI[UNIT_TYPE_LAST] {
1346 : SYM_ALT_M, //ALTITUDE
1347 : SYM_MS, //SPEED
1348 : SYM_MS, //VSPEED
1349 : SYM_M, //DISTANCE
1350 : SYM_KM, //DISTANCE_LONG
1351 : SYM_DEGREES_C //TEMPERATURE
1352 : };
1353 : static const uint8_t icons_aviation[UNIT_TYPE_LAST] {
1354 : SYM_ALT_FT, //ALTITUDE Ft
1355 : SYM_KN, //SPEED Knots
1356 : SYM_FTMIN, //VSPEED
1357 : SYM_FT, //DISTANCE
1358 : SYM_NM, //DISTANCE_LONG Nm
1359 : SYM_DEGREES_C //TEMPERATURE
1360 : };
1361 : static const uint8_t* icons[AP_OSD::UNITS_LAST] = {
1362 : icons_metric,
1363 : icons_imperial,
1364 : icons_SI,
1365 : icons_aviation,
1366 : };
1367 1934 : return (char)SYMBOL(icons[constrain_int16(osd->units, 0, AP_OSD::UNITS_LAST-1)][unit]);
1368 : }
1369 :
1370 : /*
1371 : scale a value for the user selected units
1372 : */
1373 2482 : float AP_OSD_AbstractScreen::u_scale(enum unit_type unit, float value)
1374 : {
1375 : static const float scale_metric[UNIT_TYPE_LAST] = {
1376 : 1.0, //ALTITUDE m
1377 : 3.6, //SPEED km/hr
1378 : 1.0, //VSPEED m/s
1379 : 1.0, //DISTANCE m
1380 : 1.0/1000, //DISTANCE_LONG km
1381 : 1.0, //TEMPERATURE C
1382 : };
1383 : static const float scale_imperial[UNIT_TYPE_LAST] = {
1384 : 3.28084, //ALTITUDE ft
1385 : 2.23694, //SPEED mph
1386 : 3.28084, //VSPEED ft/s
1387 : 3.28084, //DISTANCE ft
1388 : 1.0/1609.34, //DISTANCE_LONG miles
1389 : 1.8, //TEMPERATURE F
1390 : };
1391 : static const float offset_imperial[UNIT_TYPE_LAST] = {
1392 : 0.0, //ALTITUDE
1393 : 0.0, //SPEED
1394 : 0.0, //VSPEED
1395 : 0.0, //DISTANCE
1396 : 0.0, //DISTANCE_LONG
1397 : 32.0, //TEMPERATURE F
1398 : };
1399 : static const float scale_SI[UNIT_TYPE_LAST] = {
1400 : 1.0, //ALTITUDE m
1401 : 1.0, //SPEED m/s
1402 : 1.0, //VSPEED m/s
1403 : 1.0, //DISTANCE m
1404 : 1.0/1000, //DISTANCE_LONG km
1405 : 1.0, //TEMPERATURE C
1406 : };
1407 : static const float scale_aviation[UNIT_TYPE_LAST] = {
1408 : 3.28084, //ALTITUDE Ft
1409 : 1.94384, //SPEED Knots
1410 : 196.85, //VSPEED ft/min
1411 : 3.28084, //DISTANCE ft
1412 : 0.000539957, //DISTANCE_LONG Nm
1413 : 1.0, //TEMPERATURE C
1414 : };
1415 : static const float *scale[AP_OSD::UNITS_LAST] = {
1416 : scale_metric,
1417 : scale_imperial,
1418 : scale_SI,
1419 : scale_aviation
1420 : };
1421 : static const float *offsets[AP_OSD::UNITS_LAST] = {
1422 : nullptr,
1423 : offset_imperial,
1424 : nullptr,
1425 : nullptr
1426 : };
1427 2482 : uint8_t units = constrain_int16(osd->units, 0, AP_OSD::UNITS_LAST-1);
1428 2482 : return value * scale[units][unit] + (offsets[units]?offsets[units][unit]:0);
1429 : }
1430 :
1431 838 : char AP_OSD_Screen::get_arrow_font_index(int32_t angle_cd)
1432 : {
1433 838 : uint32_t interval = 36000 / SYMBOL(SYM_ARROW_COUNT);
1434 838 : angle_cd = wrap_360_cd(angle_cd);
1435 : // if using BF font table must translate arrows
1436 838 : if (check_option(AP_OSD::OPTION_BF_ARROWS)) {
1437 0 : angle_cd = angle_cd > 18000? 54000 - angle_cd : 18000- angle_cd;
1438 : }
1439 838 : return SYMBOL(SYM_ARROW_START) + ((angle_cd + interval / 2) / interval) % SYMBOL(SYM_ARROW_COUNT);
1440 : }
1441 :
1442 548 : void AP_OSD_Screen::draw_altitude(uint8_t x, uint8_t y)
1443 : {
1444 : float alt;
1445 548 : AP_AHRS &ahrs = AP::ahrs();
1446 548 : WITH_SEMAPHORE(ahrs.get_semaphore());
1447 548 : ahrs.get_relative_position_D_home(alt);
1448 548 : alt = -alt;
1449 548 : backend->write(x, y, false, "%4d%c", (int)u_scale(ALTITUDE, alt), u_icon(ALTITUDE));
1450 548 : }
1451 :
1452 : #if AP_BATTERY_ENABLED
1453 548 : void AP_OSD_Screen::draw_bat_volt(uint8_t instance, VoltageType type, uint8_t x, uint8_t y)
1454 : {
1455 548 : AP_BattMonitor &battery = AP::battery();
1456 548 : float v = battery.voltage(instance);
1457 548 : float blinkvolt = osd->warn_batvolt;
1458 : uint8_t pct;
1459 548 : bool show_remaining_pct = battery.capacity_remaining_pct(pct);
1460 548 : uint8_t p = (100 - pct) / 16.6;
1461 548 : switch (type) {
1462 548 : case VoltageType::VOLTAGE: {
1463 548 : break;
1464 : }
1465 0 : case VoltageType::RESTING_VOLTAGE: {
1466 0 : v = battery.voltage_resting_estimate(instance);
1467 0 : blinkvolt = osd->warn_restvolt;
1468 0 : break;
1469 : }
1470 0 : case VoltageType::RESTING_CELL: {
1471 0 : blinkvolt = osd->warn_avgcellrestvolt;
1472 0 : v = battery.voltage_resting_estimate(instance);
1473 : FALLTHROUGH;
1474 : }
1475 0 : case VoltageType::AVG_CELL: {
1476 0 : if (type == VoltageType::AVG_CELL) { //for fallthrough of RESTING_CELL
1477 0 : blinkvolt = osd->warn_avgcellvolt;
1478 : }
1479 : // calculate cell count - WARNING this can be inaccurate if the LIPO/LIION battery is far from
1480 : // fully charged when attached and is used in this panel
1481 0 : osd->max_battery_voltage.set(MAX(osd->max_battery_voltage,v));
1482 0 : if (osd->cell_count > 0) {
1483 0 : v = v / osd->cell_count;
1484 0 : } else if (osd->cell_count < 0) { // user must decide on autodetect cell count or manually entered to display this panel since default is -1
1485 0 : backend->write(x,y, false, "%c---%c", SYMBOL(SYM_BATT_FULL) + p, SYMBOL(SYM_VOLT));
1486 46 : return;
1487 : } else { // use autodetected cell count
1488 0 : v = v / (uint8_t)(osd->max_battery_voltage * 0.2381 + 1);
1489 : }
1490 0 : break;
1491 : }
1492 : }
1493 548 : if (!show_remaining_pct) {
1494 : // Do not show battery percentage
1495 46 : if (type == VoltageType::RESTING_CELL || type == VoltageType::AVG_CELL) {
1496 0 : backend->write(x,y, v < blinkvolt, "%1.2f%c", (double)v, SYMBOL(SYM_VOLT));
1497 : } else {
1498 46 : backend->write(x,y, v < blinkvolt, "%2.1f%c", (double)v, SYMBOL(SYM_VOLT));
1499 : }
1500 46 : return;
1501 : }
1502 502 : if (type == VoltageType::RESTING_CELL || type == VoltageType::AVG_CELL) {
1503 0 : backend->write(x,y, v < blinkvolt, "%c%1.2f%c", SYMBOL(SYM_BATT_FULL) + p, (double)v, SYMBOL(SYM_VOLT));
1504 : } else {
1505 502 : backend->write(x,y, v < blinkvolt, "%c%2.1f%c", SYMBOL(SYM_BATT_FULL) + p, (double)v, SYMBOL(SYM_VOLT));
1506 : }
1507 : }
1508 :
1509 548 : void AP_OSD_Screen::draw_bat_volt(uint8_t x, uint8_t y)
1510 : {
1511 548 : draw_bat_volt(0,VoltageType::VOLTAGE,x,y);
1512 548 : }
1513 :
1514 0 : void AP_OSD_Screen::draw_avgcellvolt(uint8_t x, uint8_t y)
1515 : {
1516 0 : draw_bat_volt(0,VoltageType::AVG_CELL,x,y);
1517 0 : }
1518 :
1519 0 : void AP_OSD_Screen::draw_avgcellrestvolt(uint8_t x, uint8_t y)
1520 : {
1521 0 : draw_bat_volt(0,VoltageType::RESTING_CELL,x, y);
1522 0 : }
1523 :
1524 0 : void AP_OSD_Screen::draw_restvolt(uint8_t x, uint8_t y)
1525 : {
1526 0 : draw_bat_volt(0,VoltageType::RESTING_VOLTAGE,x,y);
1527 0 : }
1528 : #endif // AP_BATTERY_ENABLED
1529 :
1530 : #if AP_RSSI_ENABLED
1531 548 : void AP_OSD_Screen::draw_rssi(uint8_t x, uint8_t y)
1532 : {
1533 548 : AP_RSSI *ap_rssi = AP_RSSI::get_singleton();
1534 548 : if (ap_rssi) {
1535 548 : const uint8_t rssiv = ap_rssi->read_receiver_rssi() * 100;
1536 548 : backend->write(x, y, rssiv < osd->warn_rssi, "%c%2d", SYMBOL(SYM_RSSI), rssiv);
1537 : }
1538 548 : }
1539 :
1540 0 : void AP_OSD_Screen::draw_link_quality(uint8_t x, uint8_t y)
1541 : {
1542 0 : AP_RSSI *ap_rssi = AP_RSSI::get_singleton();
1543 0 : if (ap_rssi) {
1544 0 : const int16_t lqv = ap_rssi->read_receiver_link_quality();
1545 0 : if (lqv < 0){
1546 0 : backend->write(x, y, false, "%c--", SYMBOL(SYM_LQ));
1547 : } else {
1548 0 : backend->write(x, y, false, "%c%2d", SYMBOL(SYM_LQ), lqv);
1549 : }
1550 : }
1551 0 : }
1552 : #endif // AP_RSSI_ENABLED
1553 :
1554 : #if AP_BATTERY_ENABLED
1555 548 : void AP_OSD_Screen::draw_current(uint8_t instance, uint8_t x, uint8_t y)
1556 : {
1557 : float amps;
1558 548 : if (!AP::battery().current_amps(amps, instance)) {
1559 0 : osd->_stats.avg_current_a = 0;
1560 : }
1561 : //filter current and display with autoranging for low values
1562 548 : osd->_stats.avg_current_a= osd->_stats.avg_current_a + (amps - osd->_stats.avg_current_a) * 0.33;
1563 548 : if (osd->_stats.avg_current_a < 10.0) {
1564 548 : backend->write(x, y, false, "%2.2f%c", osd->_stats.avg_current_a, SYMBOL(SYM_AMP));
1565 : }
1566 : else {
1567 0 : backend->write(x, y, false, "%2.1f%c", osd->_stats.avg_current_a, SYMBOL(SYM_AMP));
1568 : }
1569 548 : }
1570 :
1571 548 : void AP_OSD_Screen::draw_current(uint8_t x, uint8_t y)
1572 : {
1573 548 : draw_current(0, x, y);
1574 548 : }
1575 : #endif
1576 :
1577 548 : void AP_OSD_Screen::draw_fltmode(uint8_t x, uint8_t y)
1578 : {
1579 548 : AP_Notify * notify = AP_Notify::get_singleton();
1580 : char arm;
1581 548 : if (AP_Notify::flags.armed) {
1582 0 : arm = SYMBOL(SYM_ARMED);
1583 : } else {
1584 548 : arm = SYMBOL(SYM_DISARMED);
1585 : }
1586 548 : if (notify) {
1587 548 : backend->write(x, y, false, "%s%c", notify->get_flight_mode_str(), arm);
1588 : }
1589 548 : }
1590 :
1591 548 : void AP_OSD_Screen::draw_sats(uint8_t x, uint8_t y)
1592 : {
1593 548 : AP_GPS & gps = AP::gps();
1594 548 : uint8_t nsat = gps.num_sats();
1595 548 : bool flash = (nsat < osd->warn_nsat) || (gps.status() < AP_GPS_FixType::FIX_3D);
1596 548 : backend->write(x, y, flash, "%c%c%2u", SYMBOL(SYM_SAT_L), SYMBOL(SYM_SAT_R), nsat);
1597 548 : }
1598 :
1599 : #if AP_BATTERY_ENABLED
1600 548 : void AP_OSD_Screen::draw_batused(uint8_t instance, uint8_t x, uint8_t y)
1601 : {
1602 : float mah;
1603 548 : if (!AP::battery().consumed_mah(mah, instance)) {
1604 0 : mah = 0;
1605 : }
1606 548 : if (mah <= 9999) {
1607 548 : backend->write(x,y, false, "%4d%c", (int)mah, SYMBOL(SYM_MAH));
1608 : } else {
1609 0 : const float ah = mah * 1e-3f;
1610 0 : backend->write(x,y, false, "%2.2f%c", (double)ah, SYMBOL(SYM_AH));
1611 : }
1612 548 : }
1613 :
1614 548 : void AP_OSD_Screen::draw_batused(uint8_t x, uint8_t y)
1615 : {
1616 548 : draw_batused(0, x, y);
1617 548 : }
1618 : #endif
1619 :
1620 : //Autoscroll message is the same as in minimosd-extra.
1621 : //Thanks to night-ghost for the approach.
1622 548 : void AP_OSD_Screen::draw_message(uint8_t x, uint8_t y)
1623 : {
1624 548 : AP_Notify * notify = AP_Notify::get_singleton();
1625 548 : if (notify) {
1626 548 : int32_t visible_time = AP_HAL::millis() - notify->get_text_updated_millis();
1627 548 : if (visible_time < osd->msgtime_s *1000) {
1628 : char buffer[NOTIFY_TEXT_BUFFER_SIZE];
1629 434 : strncpy(buffer, notify->get_text(), sizeof(buffer));
1630 434 : int16_t len = strnlen(buffer, sizeof(buffer));
1631 :
1632 11073 : for (int16_t i=0; i<len; i++) {
1633 : //converted to uppercase,
1634 : //because we do not have small letter chars inside used font
1635 10639 : buffer[i] = toupper(buffer[i]);
1636 : //normalize whitespace
1637 10639 : if (isspace(buffer[i])) {
1638 1384 : buffer[i] = ' ';
1639 : }
1640 : }
1641 :
1642 434 : int16_t start_position = 0;
1643 : //scroll if required
1644 : //scroll pattern: wait, scroll to the left, wait, scroll to the right
1645 434 : if (len > message_visible_width) {
1646 98 : int16_t chars_to_scroll = len - message_visible_width;
1647 98 : int16_t total_cycles = 2*message_scroll_delay + 2*chars_to_scroll;
1648 98 : int16_t current_cycle = (visible_time / message_scroll_time_ms) % total_cycles;
1649 :
1650 : //calculate scroll start_position
1651 98 : if (current_cycle < total_cycles/2) {
1652 : //move to the left
1653 91 : start_position = current_cycle - message_scroll_delay;
1654 : } else {
1655 : //move to the right
1656 7 : start_position = total_cycles - current_cycle;
1657 : }
1658 98 : start_position = constrain_int16(start_position, 0, chars_to_scroll);
1659 98 : int16_t end_position = start_position + message_visible_width;
1660 :
1661 : //ensure array boundaries
1662 98 : start_position = MIN(start_position, int(sizeof(buffer)-1));
1663 98 : end_position = MIN(end_position, int(sizeof(buffer)-1));
1664 :
1665 : //trim invisible part
1666 98 : buffer[end_position] = 0;
1667 : }
1668 :
1669 434 : backend->write(x, y, buffer + start_position);
1670 : }
1671 : }
1672 548 : }
1673 :
1674 : // draw a arrow at the given angle, and print the given magnitude
1675 548 : void AP_OSD_Screen::draw_speed(uint8_t x, uint8_t y, float angle_rad, float magnitude)
1676 : {
1677 548 : int32_t angle_cd = rad_to_cd(angle_rad);
1678 548 : char arrow = get_arrow_font_index(angle_cd);
1679 548 : if (u_scale(SPEED, magnitude) < 9.95) {
1680 548 : backend->write(x, y, false, "%c %1.1f%c", arrow, u_scale(SPEED, magnitude), u_icon(SPEED));
1681 : } else {
1682 0 : backend->write(x, y, false, "%c%3d%c", arrow, (int)roundf(u_scale(SPEED, magnitude)), u_icon(SPEED));
1683 : }
1684 548 : }
1685 :
1686 548 : void AP_OSD_Screen::draw_gspeed(uint8_t x, uint8_t y)
1687 : {
1688 548 : AP_AHRS &ahrs = AP::ahrs();
1689 548 : WITH_SEMAPHORE(ahrs.get_semaphore());
1690 548 : Vector2f v = ahrs.groundspeed_vector();
1691 548 : backend->write(x, y, false, "%c", SYMBOL(SYM_GSPD));
1692 548 : float angle = 0;
1693 548 : const float length = v.length();
1694 548 : if (length > 1.0f) {
1695 : float roll_rad, pitch_rad, yaw_rad;
1696 0 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
1697 0 : angle = wrap_2PI(atan2f(v.y, v.x) - yaw_rad);
1698 : }
1699 548 : draw_speed(x + 1, y, angle, length);
1700 548 : }
1701 :
1702 : //Thanks to betaflight/inav for simple and clean artificial horizon visual design
1703 548 : void AP_OSD_Screen::draw_horizon(uint8_t x, uint8_t y)
1704 : {
1705 548 : AP_AHRS &ahrs = AP::ahrs();
1706 548 : WITH_SEMAPHORE(ahrs.get_semaphore());
1707 : float roll;
1708 : float pitch;
1709 : float yaw;
1710 548 : bool inverted = false;
1711 548 : AP::vehicle()->get_osd_attitude_rad(roll, pitch, yaw);
1712 548 : pitch *= -1;
1713 : // Are we inverted? then flash horizon line
1714 548 : if (abs(roll) >= radians(90)) {
1715 0 : inverted = true;
1716 : }
1717 : // Aviation style AH instead of Betaflight FPV style
1718 548 : if (inverted && check_option(AP_OSD::OPTION_AVIATION_AH)) {
1719 0 : pitch = -pitch;
1720 : }
1721 : //inverted roll AH (Russian HUD emulation)
1722 548 : if (check_option(AP_OSD::OPTION_INVERTED_AH_ROLL)) {
1723 0 : roll = -roll;
1724 : }
1725 :
1726 548 : pitch = constrain_float(pitch, -ah_max_pitch, ah_max_pitch);
1727 548 : float ky = sinf(roll);
1728 548 : float kx = cosf(roll);
1729 :
1730 548 : float ratio = backend->get_aspect_ratio_correction();
1731 :
1732 548 : if (fabsf(ky) < fabsf(kx)) {
1733 5480 : for (int dx = -4; dx <= 4; dx++) {
1734 4932 : float fy = (ratio * dx) * (ky/kx) + pitch * ah_pitch_rad_to_char + 0.5f;
1735 4932 : int dy = floorf(fy);
1736 4932 : char c = (fy - dy) * SYMBOL(SYM_AH_H_COUNT);
1737 : //chars in font in reversed order
1738 4932 : c = SYMBOL(SYM_AH_H_START) + ((SYMBOL(SYM_AH_H_COUNT) - 1) - c);
1739 4932 : if (dy >= -4 && dy <= 4) {
1740 4932 : backend->write(x + dx, y - dy, inverted, "%c", c);
1741 : }
1742 : }
1743 : } else {
1744 0 : for (int dy=-4; dy<=4; dy++) {
1745 0 : float fx = ((dy / ratio) - pitch * ah_pitch_rad_to_char) * (kx/ky) + 0.5f;
1746 0 : int dx = floorf(fx);
1747 0 : char c = (fx - dx) * SYMBOL(SYM_AH_V_COUNT);
1748 0 : c = SYMBOL(SYM_AH_V_START) + c;
1749 0 : if (dx >= -4 && dx <=4) {
1750 0 : backend->write(x + dx, y - dy, inverted, "%c", c);
1751 : }
1752 : }
1753 : }
1754 :
1755 548 : if (!check_option(AP_OSD::OPTION_DISABLE_CROSSHAIR)) {
1756 548 : backend->write(x-1,y, false, "%c%c%c", SYMBOL(SYM_AH_CENTER_LINE_LEFT), SYMBOL(SYM_AH_CENTER), SYMBOL(SYM_AH_CENTER_LINE_RIGHT));
1757 : }
1758 :
1759 548 : }
1760 :
1761 290 : void AP_OSD_Screen::draw_distance(uint8_t x, uint8_t y, float distance)
1762 : {
1763 290 : char unit_icon = u_icon(DISTANCE);
1764 290 : float distance_scaled = u_scale(DISTANCE, distance);
1765 290 : const char *fmt = "%4.0f%c";
1766 290 : if (distance_scaled > 9999.0f || (osd->units == AP_OSD::UNITS_IMPERIAL && distance_scaled > 5280.0f && (osd->options & AP_OSD::OPTION_IMPERIAL_MILES))) {
1767 0 : distance_scaled = u_scale(DISTANCE_LONG, distance);
1768 0 : unit_icon= u_icon(DISTANCE_LONG);
1769 : //try to pack as many useful info as possible
1770 0 : if (distance_scaled<9.0f) {
1771 0 : fmt = "%1.3f%c";
1772 0 : } else if (distance_scaled < 99.0f) {
1773 0 : fmt = "%2.2f%c";
1774 0 : } else if (distance_scaled < 999.0f) {
1775 0 : fmt = "%3.1f%c";
1776 : } else {
1777 0 : fmt = "%4.0f%c";
1778 : }
1779 290 : } else if (distance_scaled < 10.0f) {
1780 290 : fmt = "% 3.1f%c";
1781 : }
1782 290 : backend->write(x, y, false, fmt, (double)distance_scaled, unit_icon);
1783 290 : }
1784 :
1785 548 : void AP_OSD_Screen::draw_home(uint8_t x, uint8_t y)
1786 : {
1787 548 : AP_AHRS &ahrs = AP::ahrs();
1788 548 : WITH_SEMAPHORE(ahrs.get_semaphore());
1789 548 : Location loc;
1790 548 : if (ahrs.get_location(loc) && ahrs.home_is_set()) {
1791 290 : const Location &home_loc = ahrs.get_home();
1792 290 : float distance = home_loc.get_distance(loc);
1793 : float roll_rad, pitch_rad, yaw_rad;
1794 290 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
1795 290 : int32_t angle_cd = loc.get_bearing_to(home_loc) - rad_to_cd(yaw_rad);
1796 290 : if (distance < 2.0f) {
1797 : //avoid fast rotating arrow at small distances
1798 290 : angle_cd = 0;
1799 : }
1800 290 : char arrow = get_arrow_font_index(angle_cd);
1801 290 : backend->write(x, y, false, "%c%c", SYMBOL(SYM_HOME), arrow);
1802 290 : draw_distance(x+2, y, distance);
1803 : } else {
1804 258 : backend->write(x, y, true, "%c", SYMBOL(SYM_HOME));
1805 : }
1806 548 : }
1807 :
1808 548 : void AP_OSD_Screen::draw_heading(uint8_t x, uint8_t y)
1809 : {
1810 : float roll_rad, pitch_rad, yaw_rad;
1811 548 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
1812 548 : uint16_t yaw = degrees(wrap_2PI(yaw_rad));
1813 548 : backend->write(x, y, false, "%3d%c", yaw, SYMBOL(SYM_DEGR));
1814 548 : }
1815 :
1816 : #if AP_RPM_ENABLED
1817 0 : void AP_OSD_Screen::draw_rrpm(uint8_t x, uint8_t y)
1818 : {
1819 : float _rrpm;
1820 0 : const AP_RPM *rpm = AP_RPM::get_singleton();
1821 0 : if (rpm != nullptr) {
1822 0 : if (!rpm->get_rpm(0, _rrpm)) {
1823 : // No valid RPM data
1824 0 : _rrpm = -1;
1825 : }
1826 : } else {
1827 : // No RPM because pointer is null
1828 0 : _rrpm = -1;
1829 : }
1830 0 : int r_rpm = static_cast<int>(_rrpm);
1831 0 : backend->write(x, y, false, "%4d%c", (int)r_rpm, SYMBOL(SYM_RPM));
1832 0 : }
1833 : #endif
1834 :
1835 548 : void AP_OSD_Screen::draw_throttle(uint8_t x, uint8_t y)
1836 : {
1837 548 : backend->write(x, y, false, "%3d%c", gcs().get_hud_throttle(), SYMBOL(SYM_PCNT));
1838 548 : }
1839 :
1840 : #if HAL_OSD_SIDEBAR_ENABLE
1841 :
1842 0 : void AP_OSD_Screen::draw_sidebars(uint8_t x, uint8_t y)
1843 : {
1844 0 : const int8_t total_sectors = 18;
1845 : static const uint8_t sidebar_sectors[total_sectors] = {
1846 : SYM_SIDEBAR_A,
1847 : SYM_SIDEBAR_B,
1848 : SYM_SIDEBAR_C,
1849 : SYM_SIDEBAR_D,
1850 : SYM_SIDEBAR_E,
1851 : SYM_SIDEBAR_F,
1852 : SYM_SIDEBAR_G,
1853 : SYM_SIDEBAR_E,
1854 : SYM_SIDEBAR_F,
1855 : SYM_SIDEBAR_G,
1856 : SYM_SIDEBAR_E,
1857 : SYM_SIDEBAR_F,
1858 : SYM_SIDEBAR_G,
1859 : SYM_SIDEBAR_E,
1860 : SYM_SIDEBAR_F,
1861 : SYM_SIDEBAR_H,
1862 : SYM_SIDEBAR_I,
1863 : SYM_SIDEBAR_J,
1864 : };
1865 :
1866 : // Get altitude and airspeed, scaled to appropriate units
1867 0 : float aspd = 0.0f;
1868 0 : float alt = 0.0f;
1869 0 : AP_AHRS &ahrs = AP::ahrs();
1870 0 : WITH_SEMAPHORE(ahrs.get_semaphore());
1871 0 : bool have_speed_estimate = ahrs.airspeed_EAS(aspd);
1872 0 : if (!have_speed_estimate) { aspd = 0.0f; }
1873 0 : ahrs.get_relative_position_D_home(alt);
1874 0 : float scaled_aspd = u_scale(SPEED, aspd);
1875 0 : float scaled_alt = u_scale(ALTITUDE, -alt);
1876 : static const int aspd_interval = 10; //units between large tick marks
1877 0 : int alt_interval = (osd->units == AP_OSD::UNITS_AVIATION || osd->units == AP_OSD::UNITS_IMPERIAL) ? 20 : 10;
1878 :
1879 : // Height values taking into account configurable vertical extension
1880 0 : const int bar_total_height = 7 + (osd->sidebar_v_ext * 2);
1881 0 : const int bar_middle = bar_total_height / 2; // Integer division
1882 :
1883 : // render airspeed ladder
1884 0 : int aspd_symbol_index = fmodf(scaled_aspd, aspd_interval) / aspd_interval * total_sectors;
1885 0 : for (int i = 0; i < bar_total_height; i++){
1886 0 : if (i == bar_middle) {
1887 : // the middle section of the ladder with the currrent airspeed
1888 0 : backend->write(x, y+i, false, "%3d%c%c", (int) scaled_aspd, u_icon(SPEED), SYMBOL(SYM_SIDEBAR_R_ARROW));
1889 : } else {
1890 0 : backend->write(x+4, y+i, false, "%c", SYMBOL(sidebar_sectors[aspd_symbol_index]));
1891 : }
1892 0 : aspd_symbol_index = (aspd_symbol_index + 12) % 18;
1893 : }
1894 :
1895 : // render the altitude ladder
1896 : // similar formula to above, but accounts for negative altitudes
1897 0 : int alt_symbol_index = fmodf(fmodf(scaled_alt, alt_interval) + alt_interval, alt_interval) / alt_interval * total_sectors;
1898 0 : for (int i = 0; i < bar_total_height; i++){
1899 0 : if (i == bar_middle) {
1900 : // the middle section of the ladder with the currrent altitude
1901 0 : backend->write(x + 16 + osd->sidebar_h_offset, y+i, false, "%c%d%c", SYMBOL(SYM_SIDEBAR_L_ARROW), (int) scaled_alt, u_icon(ALTITUDE));
1902 : } else {
1903 0 : backend->write(x + 16 + osd->sidebar_h_offset, y+i, false, "%c", SYMBOL(sidebar_sectors[alt_symbol_index]));
1904 : }
1905 0 : alt_symbol_index = (alt_symbol_index + 12) % 18;
1906 : }
1907 0 : }
1908 :
1909 : #endif // HAL_OSD_SIDEBAR_ENABLE
1910 :
1911 : //Thanks to betaflight/inav for simple and clean compass visual design
1912 548 : void AP_OSD_Screen::draw_compass(uint8_t x, uint8_t y)
1913 : {
1914 548 : const int8_t total_sectors = 16;
1915 : static const uint8_t compass_circle[total_sectors] = {
1916 : SYM_HEADING_N,
1917 : SYM_HEADING_LINE,
1918 : SYM_HEADING_DIVIDED_LINE,
1919 : SYM_HEADING_LINE,
1920 : SYM_HEADING_E,
1921 : SYM_HEADING_LINE,
1922 : SYM_HEADING_DIVIDED_LINE,
1923 : SYM_HEADING_LINE,
1924 : SYM_HEADING_S,
1925 : SYM_HEADING_LINE,
1926 : SYM_HEADING_DIVIDED_LINE,
1927 : SYM_HEADING_LINE,
1928 : SYM_HEADING_W,
1929 : SYM_HEADING_LINE,
1930 : SYM_HEADING_DIVIDED_LINE,
1931 : SYM_HEADING_LINE,
1932 : };
1933 : float roll_rad, pitch_rad, yaw_rad;
1934 548 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
1935 548 : int32_t yaw = rad_to_cd(wrap_2PI(yaw_rad));
1936 548 : int32_t interval = 36000 / total_sectors;
1937 548 : int8_t center_sector = ((yaw + interval / 2) / interval) % total_sectors;
1938 5480 : for (int8_t i = -4; i <= 4; i++) {
1939 4932 : int8_t sector = center_sector + i;
1940 4932 : sector = (sector + total_sectors) % total_sectors;
1941 4932 : backend->write(x + i, y, false, "%c", SYMBOL(compass_circle[sector]));
1942 : }
1943 548 : }
1944 :
1945 0 : void AP_OSD_Screen::draw_wind(uint8_t x, uint8_t y)
1946 : {
1947 : #if !APM_BUILD_TYPE(APM_BUILD_Rover)
1948 0 : AP_AHRS &ahrs = AP::ahrs();
1949 0 : WITH_SEMAPHORE(ahrs.get_semaphore());
1950 0 : Vector3f v;
1951 : // draw the estimate even if it is not marked valid, to preserve
1952 : // existing behaviour
1953 0 : IGNORE_RETURN(ahrs.get_wind(v));
1954 0 : float angle = 0;
1955 0 : const float length = v.length();
1956 0 : if (length > 1.0f) {
1957 0 : if (check_option(AP_OSD::OPTION_INVERTED_WIND)) {
1958 0 : angle = M_PI;
1959 : }
1960 : float roll_rad, pitch_rad, yaw_rad;
1961 0 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
1962 0 : angle = wrap_2PI(angle + atan2f(v.y, v.x) - yaw_rad);
1963 : }
1964 0 : draw_speed(x + 1, y, angle, length);
1965 :
1966 : #else
1967 0 : const AP_WindVane* windvane = AP_WindVane::get_singleton();
1968 0 : if (windvane != nullptr) {
1969 0 : draw_speed(x + 1, y, windvane->get_apparent_wind_direction_rad() + M_PI, windvane->get_apparent_wind_speed());
1970 : }
1971 : #endif
1972 :
1973 0 : backend->write(x, y, false, "%c", SYMBOL(SYM_WSPD));
1974 0 : }
1975 :
1976 0 : void AP_OSD_Screen::draw_aspeed(uint8_t x, uint8_t y)
1977 : {
1978 0 : float aspd = 0.0f;
1979 0 : AP_AHRS &ahrs = AP::ahrs();
1980 0 : WITH_SEMAPHORE(ahrs.get_semaphore());
1981 0 : bool have_estimate = ahrs.airspeed_EAS(aspd);
1982 0 : if (have_estimate) {
1983 0 : backend->write(x, y, false, "%c%4d%c", SYMBOL(SYM_ASPD), (int)u_scale(SPEED, aspd), u_icon(SPEED));
1984 : } else {
1985 0 : backend->write(x, y, false, "%c ---%c", SYMBOL(SYM_ASPD), u_icon(SPEED));
1986 : }
1987 0 : }
1988 :
1989 548 : void AP_OSD_Screen::draw_vspeed(uint8_t x, uint8_t y)
1990 : {
1991 548 : Vector3f v;
1992 : float vspd;
1993 : float vs_scaled;
1994 548 : AP_AHRS &ahrs = AP::ahrs();
1995 548 : WITH_SEMAPHORE(ahrs.get_semaphore());
1996 548 : if (ahrs.get_velocity_NED(v)) {
1997 464 : vspd = -v.z;
1998 : } else {
1999 84 : auto &baro = AP::baro();
2000 84 : WITH_SEMAPHORE(baro.get_semaphore());
2001 84 : vspd = baro.get_climb_rate();
2002 84 : }
2003 : char sym;
2004 548 : if (vspd > 3.0f) {
2005 0 : sym = SYMBOL(SYM_UP_UP);
2006 548 : } else if (vspd >=0.0f) {
2007 413 : sym = SYMBOL(SYM_UP);
2008 135 : } else if (vspd >= -3.0f) {
2009 135 : sym = SYMBOL(SYM_DOWN);
2010 : } else {
2011 0 : sym = SYMBOL(SYM_DOWN_DOWN);
2012 : }
2013 548 : vs_scaled = u_scale(VSPEED, fabsf(vspd));
2014 548 : if ((osd->units != AP_OSD::UNITS_AVIATION) && (vs_scaled < 9.95f)) {
2015 548 : backend->write(x, y, false, "%c%.1f%c", sym, (float)vs_scaled, u_icon(VSPEED));
2016 : } else {
2017 0 : const char *fmt = osd->units == AP_OSD::UNITS_AVIATION ? "%c%4d%c" : "%c%2d%c";
2018 0 : backend->write(x, y, false, fmt, sym, (int)roundf(vs_scaled), u_icon(VSPEED));
2019 : }
2020 548 : }
2021 :
2022 : #if HAL_WITH_ESC_TELEM
2023 0 : void AP_OSD_Screen::draw_esc_temp(uint8_t x, uint8_t y)
2024 : {
2025 : int16_t etemp;
2026 :
2027 0 : if (esc_index > 0) {
2028 0 : if (!AP::esc_telem().get_temperature(esc_index-1, etemp)) {
2029 0 : return;
2030 : }
2031 : }
2032 0 : else if (!AP::esc_telem().get_highest_temperature(etemp)) {
2033 0 : return;
2034 : }
2035 :
2036 0 : backend->write(x, y, false, "%3d%c", (int)u_scale(TEMPERATURE, etemp / 100), u_icon(TEMPERATURE));
2037 : }
2038 :
2039 0 : void AP_OSD_Screen::draw_esc_rpm(uint8_t x, uint8_t y)
2040 : {
2041 : float rpm;
2042 0 : uint8_t esc = AP::esc_telem().get_max_rpm_esc();
2043 0 : if (esc_index > 0) {
2044 0 : if (!AP::esc_telem().get_rpm(esc_index-1, rpm)) {
2045 0 : return;
2046 : }
2047 0 : } else if (!AP::esc_telem().get_rpm(esc, rpm)) {
2048 0 : return;
2049 : }
2050 0 : float krpm = rpm * 0.001f;
2051 0 : const char *format = krpm < 9.995 ? "%.2f%c%c" : (krpm < 99.95 ? "%.1f%c%c" : "%.0f%c%c");
2052 0 : backend->write(x, y, false, format, krpm, SYMBOL(SYM_KILO), SYMBOL(SYM_RPM));
2053 : }
2054 :
2055 0 : void AP_OSD_Screen::draw_esc_amps(uint8_t x, uint8_t y)
2056 : {
2057 : float amps;
2058 0 : uint8_t esc = AP::esc_telem().get_max_rpm_esc();
2059 0 : if (esc_index > 0) {
2060 0 : if (!AP::esc_telem().get_current(esc_index-1, amps)) {
2061 0 : return;
2062 : }
2063 0 : } else if (!AP::esc_telem().get_current(esc, amps)) {
2064 0 : return;
2065 : }
2066 0 : backend->write(x, y, false, "%4.1f%c", amps, SYMBOL(SYM_AMP));
2067 : }
2068 : #endif
2069 :
2070 : #if AP_OSD_EXTENDED_LNK_STATS
2071 : bool AP_OSD_Screen::is_btfl_fonts()
2072 : {
2073 : const AP_MSP *p_msp = AP::msp();
2074 : return (p_msp != nullptr && p_msp->is_option_enabled(AP_MSP::Option::DISPLAYPORT_BTFL_SYMBOLS) && !p_msp->is_option_enabled(AP_MSP::Option::DISPLAYPORT_INAV_SYMBOLS));
2075 : }
2076 :
2077 : void AP_OSD_Screen::draw_rc_tx_power(uint8_t x, uint8_t y)
2078 : {
2079 : const int16_t tx_power = AP::RC().get_link_status().tx_power;
2080 : bool btfl = is_btfl_fonts();
2081 : if (tx_power > 0) {
2082 : if (tx_power < 1000) {
2083 : if (btfl) {
2084 : backend->write(x, y, false, "%3d%cW", tx_power, SYMBOL(SYM_ALT_M)); // SYM_ALT_M (0x0C) is the BTFL character for a small "m"
2085 : } else {
2086 : backend->write(x, y, false, "%3d%c", tx_power, SYMBOL(SYM_MW));
2087 : }
2088 : } else {
2089 : const float value_w = float(tx_power) * 0.001f;
2090 : if (btfl) {
2091 : backend->write(x, y, false, "%.2fW", value_w);
2092 : } else {
2093 : backend->write(x, y, false, "%.2f%c", value_w, SYMBOL(SYM_WATT));
2094 : }
2095 : }
2096 : } else {
2097 : if (btfl) {
2098 : backend->write(x, y, false, "---%cW", SYMBOL(SYM_ALT_M));
2099 : } else {
2100 : backend->write(x, y, false, "---%c", SYMBOL(SYM_MW));
2101 : }
2102 : }
2103 : }
2104 :
2105 : void AP_OSD_Screen::draw_rc_rssi_dbm(uint8_t x, uint8_t y)
2106 : {
2107 : const int8_t rssidbm = AP::RC().get_link_status().rssi_dbm;
2108 : const bool blink = -rssidbm < osd->warn_rssi;
2109 : bool btfl = is_btfl_fonts();
2110 :
2111 : backend->write(x, y, blink, "%c", SYMBOL(SYM_RSSI));
2112 : uint8_t new_x = x + 1;
2113 : if (rssidbm >= 0) {
2114 : if (btfl) {
2115 : backend->write(new_x, y, blink, "%4dDBM", -rssidbm);
2116 : } else {
2117 : backend->write(new_x, y, blink, "%4d%c", -rssidbm, SYMBOL(SYM_DBM));
2118 : }
2119 : } else {
2120 : if (btfl){
2121 : backend->write(new_x, y, blink, "----DBM");
2122 : } else {
2123 : backend->write(new_x, y, blink, "----%c", SYMBOL(SYM_DBM));
2124 : }
2125 : }
2126 : }
2127 :
2128 : void AP_OSD_Screen::draw_rc_snr(uint8_t x, uint8_t y)
2129 : {
2130 : const int8_t snr = AP::RC().get_link_status().snr;
2131 : const bool blink = snr < osd->warn_snr;
2132 : bool btfl = is_btfl_fonts();
2133 : if (snr == INT8_MIN) {
2134 : if (btfl) {
2135 : backend->write(x, y, blink, "SNR---DB");
2136 : } else {
2137 : backend->write(x, y, blink, "%c---%c", SYMBOL(SYM_SNR), SYMBOL(SYM_DB));
2138 : }
2139 : } else {
2140 : if (btfl) {
2141 : backend->write(x, y, blink, "SNR%3dDB", snr);
2142 : } else {
2143 : backend->write(x, y, blink, "%c%3d%c", SYMBOL(SYM_SNR), snr, SYMBOL(SYM_DB));
2144 : }
2145 : }
2146 : }
2147 :
2148 : void AP_OSD_Screen::draw_rc_active_antenna(uint8_t x, uint8_t y)
2149 : {
2150 : const int8_t active_antenna = AP::RC().get_link_status().active_antenna;
2151 : bool btfl = is_btfl_fonts();
2152 : if (active_antenna < 0) {
2153 : if (btfl) {
2154 : backend->write(x, y, false, "ANT-");
2155 : } else {
2156 : backend->write(x, y, false, "%c-", SYMBOL(SYM_ANT));
2157 : }
2158 : } else {
2159 : if (btfl) {
2160 : backend->write(x, y, false, "ANT%d", active_antenna + 1);
2161 : } else {
2162 : backend->write(x, y, false, "%c%d", SYMBOL(SYM_ANT), active_antenna + 1);
2163 : }
2164 : }
2165 : }
2166 :
2167 : void AP_OSD_Screen::draw_rc_lq(uint8_t x, uint8_t y)
2168 : {
2169 : const int16_t lqv = AP::RC().get_link_status().link_quality;
2170 : const bool blink = lqv < osd->warn_lq;
2171 : bool btfl = is_btfl_fonts();
2172 : bool prefix_rf = check_option(AP_OSD::OPTION_RF_MODE_ALONG_WITH_LQ);
2173 : const int16_t rf_mode = AP::crsf()->get_link_status().rf_mode;
2174 : if (lqv < 0) {
2175 : if (btfl) {
2176 : if (prefix_rf) {
2177 : backend->write(x, y, blink, "LQ--:--");
2178 : } else {
2179 : backend->write(x, y, blink, "LQ--");
2180 : }
2181 : } else {
2182 : if (prefix_rf) {
2183 : backend->write(x, y, blink, "%c--:--", SYMBOL(SYM_LQ));
2184 : } else {
2185 : backend->write(x, y, blink, "%c--", SYMBOL(SYM_LQ));
2186 : }
2187 : }
2188 : } else {
2189 : if (btfl) {
2190 : if (prefix_rf) {
2191 : backend->write(x, y, blink, "LQ%2d:%2d", rf_mode, lqv);
2192 : } else {
2193 : backend->write(x, y, blink, "LQ%2d", lqv);
2194 : }
2195 : } else {
2196 : if(prefix_rf) {
2197 : backend->write(x, y, blink, "%c%2d:%2d", SYMBOL(SYM_LQ), rf_mode, lqv);
2198 : } else {
2199 : backend->write(x, y, blink, "%c%2d", SYMBOL(SYM_LQ), lqv);
2200 : }
2201 : }
2202 : }
2203 : }
2204 : #endif // AP_OSD_EXTENDED_LNK_STATS
2205 :
2206 548 : void AP_OSD_Screen::draw_gps_latitude(uint8_t x, uint8_t y)
2207 : {
2208 548 : AP_GPS & gps = AP::gps();
2209 548 : const Location &loc = gps.location(); // loc.lat and loc.lng
2210 : int32_t dec_portion, frac_portion;
2211 548 : int32_t abs_lat = labs(loc.lat);
2212 :
2213 548 : dec_portion = loc.lat / 10000000L;
2214 548 : frac_portion = abs_lat - labs(dec_portion)*10000000UL;
2215 :
2216 548 : backend->write(x, y, false, "%c%4ld.%07ld", SYMBOL(SYM_GPS_LAT), (long)dec_portion,(long)frac_portion);
2217 548 : }
2218 :
2219 548 : void AP_OSD_Screen::draw_gps_longitude(uint8_t x, uint8_t y)
2220 : {
2221 548 : AP_GPS & gps = AP::gps();
2222 548 : const Location &loc = gps.location(); // loc.lat and loc.lng
2223 : int32_t dec_portion, frac_portion;
2224 548 : int32_t abs_lon = labs(loc.lng);
2225 :
2226 548 : dec_portion = loc.lng / 10000000L;
2227 548 : frac_portion = abs_lon - labs(dec_portion)*10000000UL;
2228 :
2229 548 : backend->write(x, y, false, "%c%4ld.%07ld", SYMBOL(SYM_GPS_LONG), (long)dec_portion,(long)frac_portion);
2230 548 : }
2231 :
2232 0 : void AP_OSD_Screen::draw_roll_angle(uint8_t x, uint8_t y)
2233 : {
2234 : float roll_rad, pitch_rad, yaw_rad;
2235 0 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
2236 0 : const float roll_deg = degrees(roll_rad);
2237 : char r;
2238 0 : if (roll_deg > 0.5) {
2239 0 : r = SYMBOL(SYM_ROLLR);
2240 0 : } else if (roll_deg < -0.5) {
2241 0 : r = SYMBOL(SYM_ROLLL);
2242 : } else {
2243 0 : r = SYMBOL(SYM_ROLL0);
2244 : }
2245 0 : backend->write(x, y, false, "%c%3d%c", r, int(fabsf(roll_deg)), SYMBOL(SYM_DEGR));
2246 0 : }
2247 :
2248 0 : void AP_OSD_Screen::draw_pitch_angle(uint8_t x, uint8_t y)
2249 : {
2250 : float roll_rad, pitch_rad, yaw_rad;
2251 0 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
2252 0 : const float pitch_deg = degrees(pitch_rad);
2253 : char p;
2254 0 : if (pitch_deg > 0.5) {
2255 0 : p = SYMBOL(SYM_PTCHUP);
2256 0 : } else if (pitch_deg < -0.5) {
2257 0 : p = SYMBOL(SYM_PTCHDWN);
2258 : } else {
2259 0 : p = SYMBOL(SYM_PTCH0);
2260 : }
2261 0 : backend->write(x, y, false, "%c%3d%c", p, int(fabsf(pitch_deg)), SYMBOL(SYM_DEGR));
2262 0 : }
2263 :
2264 0 : void AP_OSD_Screen::draw_temp(uint8_t x, uint8_t y)
2265 : {
2266 0 : AP_Baro &barometer = AP::baro();
2267 0 : float tmp = barometer.get_temperature();
2268 0 : backend->write(x, y, false, "%3d%c", (int)u_scale(TEMPERATURE, tmp), u_icon(TEMPERATURE));
2269 0 : }
2270 :
2271 :
2272 0 : void AP_OSD_Screen::draw_hdop(uint8_t x, uint8_t y)
2273 : {
2274 0 : AP_GPS & gps = AP::gps();
2275 0 : float hdp = gps.get_hdop() * 0.01f;
2276 0 : backend->write(x, y, false, "%c%c%3.2f", SYMBOL(SYM_HDOP_L), SYMBOL(SYM_HDOP_R), (double)hdp);
2277 0 : }
2278 :
2279 0 : void AP_OSD_Screen::draw_waypoint(uint8_t x, uint8_t y)
2280 : {
2281 : float roll_rad, pitch_rad, yaw_rad;
2282 0 : AP::vehicle()->get_osd_attitude_rad(roll_rad, pitch_rad, yaw_rad);
2283 0 : int32_t angle_cd = osd->nav_info.wp_bearing - rad_to_cd(yaw_rad);
2284 0 : if (osd->nav_info.wp_distance < 2.0f) {
2285 : //avoid fast rotating arrow at small distances
2286 0 : angle_cd = 0;
2287 : }
2288 0 : char arrow = get_arrow_font_index(angle_cd);
2289 0 : backend->write(x,y, false, "%c%2u%c",SYMBOL(SYM_WPNO), osd->nav_info.wp_number, arrow);
2290 0 : draw_distance(x+4, y, osd->nav_info.wp_distance);
2291 0 : }
2292 :
2293 0 : void AP_OSD_Screen::draw_xtrack_error(uint8_t x, uint8_t y)
2294 : {
2295 0 : backend->write(x, y, false, "%c", SYMBOL(SYM_XERR));
2296 0 : draw_distance(x+1, y, osd->nav_info.wp_xtrack_error);
2297 0 : }
2298 :
2299 0 : void AP_OSD_Screen::draw_stat(uint8_t x, uint8_t y)
2300 : {
2301 0 : backend->write(x+2, y, false, "%c%c%c", 0x4d,0x41,0x58);
2302 0 : backend->write(x, y+1, false, "%c",SYMBOL(SYM_GSPD));
2303 0 : backend->write(x+1, y+1, false, "%4d%c", (int)u_scale(SPEED, osd->_stats.max_speed_mps), u_icon(SPEED));
2304 0 : backend->write(x, y+2, false, "%5.1f%c", (double)osd->_stats.max_current_a, SYMBOL(SYM_AMP));
2305 0 : backend->write(x, y+3, false, "%5d%c", (int)u_scale(ALTITUDE, osd->_stats.max_alt_m), u_icon(ALTITUDE));
2306 0 : backend->write(x, y+4, false, "%c", SYMBOL(SYM_HOME));
2307 0 : draw_distance(x+1, y+4, osd->_stats.max_dist_m);
2308 0 : backend->write(x, y+5, false, "%c", SYMBOL(SYM_DIST));
2309 0 : draw_distance(x+1, y+5, osd->_stats.last_distance_m);
2310 0 : }
2311 :
2312 0 : void AP_OSD_Screen::draw_dist(uint8_t x, uint8_t y)
2313 : {
2314 0 : backend->write(x, y, false, "%c", SYMBOL(SYM_DIST));
2315 0 : draw_distance(x+1, y, osd->_stats.last_distance_m);
2316 0 : }
2317 :
2318 0 : void AP_OSD_Screen::draw_flightime(uint8_t x, uint8_t y)
2319 : {
2320 0 : AP_Stats *stats = AP::stats();
2321 0 : if (stats) {
2322 0 : uint32_t t = stats->get_flight_time_s();
2323 0 : backend->write(x, y, false, "%c%3u:%02u", SYMBOL(SYM_FLY), unsigned(t/60), unsigned(t%60));
2324 : }
2325 0 : }
2326 :
2327 : #if AP_BATTERY_ENABLED
2328 0 : void AP_OSD_Screen::draw_eff(uint8_t x, uint8_t y)
2329 : {
2330 0 : AP_BattMonitor &battery = AP::battery();
2331 0 : Vector2f v;
2332 : {
2333 0 : AP_AHRS &ahrs = AP::ahrs();
2334 0 : WITH_SEMAPHORE(ahrs.get_semaphore());
2335 0 : v = ahrs.groundspeed_vector();
2336 0 : }
2337 0 : float speed = u_scale(SPEED,v.length());
2338 : float current_amps;
2339 0 : if ((speed > 2.0) && battery.current_amps(current_amps)) {
2340 0 : backend->write(x, y, false, "%c%3d%c", SYMBOL(SYM_EFF),int(1000.0f*current_amps/speed),SYMBOL(SYM_MAH));
2341 : } else {
2342 0 : backend->write(x, y, false, "%c---%c", SYMBOL(SYM_EFF),SYMBOL(SYM_MAH));
2343 : }
2344 0 : }
2345 : #endif // AP_BATTERY_ENABLED
2346 :
2347 : #if AP_BATTERY_ENABLED
2348 0 : void AP_OSD_Screen::draw_climbeff(uint8_t x, uint8_t y)
2349 : {
2350 0 : char unit_icon = u_icon(DISTANCE);
2351 0 : Vector3f v;
2352 : float vspd;
2353 : do {
2354 : {
2355 0 : auto &ahrs = AP::ahrs();
2356 0 : WITH_SEMAPHORE(ahrs.get_semaphore());
2357 0 : if (ahrs.get_velocity_NED(v)) {
2358 0 : vspd = -v.z;
2359 0 : break;
2360 : }
2361 0 : }
2362 0 : auto &baro = AP::baro();
2363 0 : WITH_SEMAPHORE(baro.get_semaphore());
2364 0 : vspd = baro.get_climb_rate();
2365 0 : } while (false);
2366 0 : if (vspd < 0.0) {
2367 0 : vspd = 0.0;
2368 : }
2369 0 : AP_BattMonitor &battery = AP::battery();
2370 : float amps;
2371 0 : if (battery.current_amps(amps) && is_positive(amps)) {
2372 0 : backend->write(x, y, false,"%c%c%3.1f%c",SYMBOL(SYM_PTCHUP),SYMBOL(SYM_EFF),(double)(3.6f * u_scale(VSPEED,vspd)/amps),unit_icon);
2373 : } else {
2374 0 : backend->write(x, y, false,"%c%c---%c",SYMBOL(SYM_PTCHUP),SYMBOL(SYM_EFF),unit_icon);
2375 : }
2376 0 : }
2377 : #endif
2378 :
2379 : #if BARO_MAX_INSTANCES > 1
2380 0 : void AP_OSD_Screen::draw_btemp(uint8_t x, uint8_t y)
2381 : {
2382 0 : AP_Baro &barometer = AP::baro();
2383 0 : float btmp = barometer.get_temperature(1);
2384 0 : backend->write(x, y, false, "%3d%c", (int)u_scale(TEMPERATURE, btmp), u_icon(TEMPERATURE));
2385 0 : }
2386 : #endif
2387 :
2388 0 : void AP_OSD_Screen::draw_atemp(uint8_t x, uint8_t y)
2389 : {
2390 : #if AP_AIRSPEED_ENABLED
2391 0 : AP_Airspeed *airspeed = AP_Airspeed::get_singleton();
2392 0 : if (!airspeed) {
2393 0 : return;
2394 : }
2395 0 : float temperature = 0;
2396 0 : airspeed->get_temperature(temperature);
2397 0 : if (airspeed->healthy()) {
2398 0 : backend->write(x, y, false, "%3d%c", (int)u_scale(TEMPERATURE, temperature), u_icon(TEMPERATURE));
2399 : } else {
2400 0 : backend->write(x, y, false, "--%c", u_icon(TEMPERATURE));
2401 : }
2402 : #endif
2403 : }
2404 :
2405 0 : void AP_OSD_Screen::draw_bat2_vlt(uint8_t x, uint8_t y)
2406 : {
2407 0 : draw_bat_volt(1,VoltageType::VOLTAGE,x,y);
2408 0 : }
2409 :
2410 0 : void AP_OSD_Screen::draw_bat2used(uint8_t x, uint8_t y)
2411 : {
2412 0 : draw_batused(1, x, y);
2413 0 : }
2414 :
2415 0 : void AP_OSD_Screen::draw_aspd1(uint8_t x, uint8_t y)
2416 : {
2417 : #if AP_AIRSPEED_ENABLED
2418 0 : AP_Airspeed *airspeed = AP_Airspeed::get_singleton();
2419 0 : if (!airspeed) {
2420 0 : return;
2421 : }
2422 0 : float asp1 = airspeed->get_airspeed();
2423 0 : if (airspeed != nullptr && airspeed->healthy()) {
2424 0 : backend->write(x, y, false, "%c%4d%c", SYMBOL(SYM_ASPD), (int)u_scale(SPEED, asp1), u_icon(SPEED));
2425 : } else {
2426 0 : backend->write(x, y, false, "%c ---%c", SYMBOL(SYM_ASPD), u_icon(SPEED));
2427 : }
2428 : #endif
2429 : }
2430 :
2431 0 : void AP_OSD_Screen::draw_aspd2(uint8_t x, uint8_t y)
2432 : {
2433 : #if AP_AIRSPEED_ENABLED
2434 0 : AP_Airspeed *airspeed = AP_Airspeed::get_singleton();
2435 0 : if (!airspeed) {
2436 0 : return;
2437 : }
2438 0 : float asp2 = airspeed->get_airspeed(1);
2439 0 : if (airspeed != nullptr && airspeed->healthy(1)) {
2440 0 : backend->write(x, y, false, "%c%4d%c", SYMBOL(SYM_ASPD), (int)u_scale(SPEED, asp2), u_icon(SPEED));
2441 : } else {
2442 0 : backend->write(x, y, false, "%c ---%c", SYMBOL(SYM_ASPD), u_icon(SPEED));
2443 : }
2444 : #endif
2445 : }
2446 :
2447 : #if AP_RTC_ENABLED
2448 0 : void AP_OSD_Screen::draw_clk(uint8_t x, uint8_t y)
2449 : {
2450 0 : AP_RTC &rtc = AP::rtc();
2451 : uint8_t hour, min, sec;
2452 : uint16_t ms;
2453 0 : if (!rtc.get_local_time(hour, min, sec, ms)) {
2454 0 : backend->write(x, y, false, "%c--:--", SYMBOL(SYM_CLK));
2455 : } else {
2456 0 : backend->write(x, y, false, "%c%02u:%02u", SYMBOL(SYM_CLK), hour, min);
2457 : }
2458 0 : }
2459 : #endif
2460 :
2461 : #if HAL_PLUSCODE_ENABLE
2462 0 : void AP_OSD_Screen::draw_pluscode(uint8_t x, uint8_t y)
2463 : {
2464 0 : AP_GPS & gps = AP::gps();
2465 0 : const Location &loc = gps.location();
2466 : char buff[16];
2467 0 : if (gps.status() == AP_GPS_FixType::NO_GPS || gps.status() == AP_GPS_FixType::NONE){
2468 0 : backend->write(x, y, false, "--------+--");
2469 : } else {
2470 0 : AP_OLC::olc_encode(loc.lat, loc.lng, 10, buff, sizeof(buff));
2471 0 : backend->write(x, y, false, "%s", buff);
2472 : }
2473 0 : }
2474 : #endif
2475 :
2476 : /*
2477 : support callsign display from a file called callsign.txt
2478 : */
2479 0 : void AP_OSD_Screen::draw_callsign(uint8_t x, uint8_t y)
2480 : {
2481 : #if AP_OSD_CALLSIGN_FROM_SD_ENABLED
2482 0 : if (!callsign_data.load_attempted) {
2483 0 : callsign_data.load_attempted = true;
2484 0 : FileData *fd = AP::FS().load_file("callsign.txt");
2485 0 : if (fd != nullptr) {
2486 0 : uint32_t len = fd->length;
2487 : // trim off whitespace
2488 0 : while (len > 0 && isspace(fd->data[len-1])) {
2489 0 : len--;
2490 : }
2491 0 : callsign_data.str = strndup((const char *)fd->data, len);
2492 0 : delete fd;
2493 : }
2494 : }
2495 0 : if (callsign_data.str != nullptr) {
2496 0 : backend->write(x, y, false, "%s", callsign_data.str);
2497 : }
2498 : #endif
2499 0 : }
2500 :
2501 0 : void AP_OSD_Screen::draw_current2(uint8_t x, uint8_t y)
2502 : {
2503 0 : draw_current(1, x, y);
2504 0 : }
2505 :
2506 : #if AP_VIDEOTX_ENABLED
2507 0 : void AP_OSD_Screen::draw_vtx_power(uint8_t x, uint8_t y)
2508 : {
2509 0 : AP_VideoTX *vtx = AP_VideoTX::get_singleton();
2510 0 : if (!vtx) {
2511 0 : return;
2512 : }
2513 0 : uint16_t powr = 0;
2514 : // If currently in pit mode, just render 0mW to the screen
2515 0 : if(!vtx->has_option(AP_VideoTX::VideoOptions::VTX_PITMODE)){
2516 : // prefer VTX-reported actual; SmartAudio returns -1 here
2517 0 : const int32_t actual_mw = vtx->get_actual_power_mw();
2518 0 : powr = actual_mw >= 0 ? uint16_t(actual_mw) : vtx->get_power_mw();
2519 : }
2520 0 : backend->write(x, y, !vtx->is_configuration_finished(), "%4hu%c", powr, SYMBOL(SYM_MW));
2521 : }
2522 : #endif // AP_VIDEOTX_ENABLED
2523 :
2524 : #if AP_TERRAIN_AVAILABLE
2525 0 : void AP_OSD_Screen::draw_hgt_abvterr(uint8_t x, uint8_t y)
2526 : {
2527 0 : AP_Terrain *terrain = AP::terrain();
2528 :
2529 : float terrain_altitude;
2530 0 : if (terrain != nullptr && terrain->height_above_terrain(terrain_altitude,true)) {
2531 0 : bool blink = (osd->warn_terr != -1)? (terrain_altitude < osd->warn_terr) : false; //blink if warn_terr is not disabled and alt above terrain is below warning value
2532 0 : backend->write(x, y, blink, "%4d%c%c", (int)u_scale(ALTITUDE, terrain_altitude), u_icon(ALTITUDE), SYMBOL(SYM_TERALT));
2533 : } else {
2534 0 : backend->write(x, y, false, " ---%c%c", u_icon(ALTITUDE),SYMBOL(SYM_TERALT));
2535 : }
2536 0 : }
2537 : #endif
2538 :
2539 : #if AP_FENCE_ENABLED
2540 0 : void AP_OSD_Screen::draw_fence(uint8_t x, uint8_t y)
2541 : {
2542 0 : AC_Fence *fenceptr = AP::fence();
2543 0 : if (fenceptr == nullptr) {
2544 0 : return;
2545 : }
2546 0 : if (fenceptr->enabled() && fenceptr->present()) {
2547 0 : backend->write(x, y, fenceptr->get_breaches(), "%c", SYMBOL(SYM_FENCE_ENABLED));
2548 : } else {
2549 0 : backend->write(x, y, false, "%c", SYMBOL(SYM_FENCE_DISABLED));
2550 : }
2551 : }
2552 : #endif
2553 :
2554 : #if AP_RANGEFINDER_ENABLED
2555 0 : void AP_OSD_Screen::draw_rngf(uint8_t x, uint8_t y)
2556 : {
2557 0 : RangeFinder *rangefinder = RangeFinder::get_singleton();
2558 0 : if (rangefinder == nullptr) {
2559 0 : return;
2560 : }
2561 0 : if (rangefinder->status_orient(ROTATION_PITCH_270) != RangeFinder::Status::Good) {
2562 0 : backend->write(x, y, false, "%c---%c", SYMBOL(SYM_RNGFD), u_icon(DISTANCE));
2563 : } else {
2564 0 : const float distance = rangefinder->distance_orient(ROTATION_PITCH_270);
2565 0 : backend->write(x, y, false, "%c%4.1f%c", SYMBOL(SYM_RNGFD), u_scale(DISTANCE, distance), u_icon(DISTANCE));
2566 : }
2567 : }
2568 : #endif
2569 :
2570 : #define DRAW_SETTING(n) if (n.enabled) draw_ ## n(n.xpos, n.ypos)
2571 :
2572 : #if HAL_WITH_OSD_BITMAP || HAL_WITH_MSP_DISPLAYPORT
2573 548 : void AP_OSD_Screen::draw(void)
2574 : {
2575 548 : if (!enabled || !backend) {
2576 0 : return;
2577 : }
2578 : //Note: draw order should be optimized.
2579 : //Big and less important items should be drawn first,
2580 : //so they will not overwrite more important ones.
2581 : #if HAL_OSD_SIDEBAR_ENABLE
2582 548 : DRAW_SETTING(sidebars);
2583 : #endif
2584 :
2585 548 : DRAW_SETTING(message);
2586 548 : DRAW_SETTING(horizon);
2587 548 : DRAW_SETTING(compass);
2588 548 : DRAW_SETTING(altitude);
2589 :
2590 : #if AP_TERRAIN_AVAILABLE
2591 548 : DRAW_SETTING(hgt_abvterr);
2592 : #endif
2593 :
2594 : #if AP_RANGEFINDER_ENABLED
2595 548 : DRAW_SETTING(rngf);
2596 : #endif
2597 548 : DRAW_SETTING(waypoint);
2598 548 : DRAW_SETTING(xtrack_error);
2599 548 : DRAW_SETTING(bat_volt);
2600 548 : DRAW_SETTING(bat2_vlt);
2601 548 : DRAW_SETTING(avgcellvolt);
2602 548 : DRAW_SETTING(avgcellrestvolt);
2603 548 : DRAW_SETTING(restvolt);
2604 : #if AP_RSSI_ENABLED
2605 548 : DRAW_SETTING(rssi);
2606 548 : DRAW_SETTING(link_quality);
2607 : #endif
2608 548 : DRAW_SETTING(current);
2609 548 : DRAW_SETTING(batused);
2610 548 : DRAW_SETTING(bat2used);
2611 548 : DRAW_SETTING(sats);
2612 548 : DRAW_SETTING(fltmode);
2613 548 : DRAW_SETTING(gspeed);
2614 548 : DRAW_SETTING(aspeed);
2615 548 : DRAW_SETTING(aspd1);
2616 548 : DRAW_SETTING(aspd2);
2617 548 : DRAW_SETTING(vspeed);
2618 548 : DRAW_SETTING(throttle);
2619 548 : DRAW_SETTING(heading);
2620 548 : DRAW_SETTING(wind);
2621 548 : DRAW_SETTING(home);
2622 : #if AP_RPM_ENABLED
2623 548 : DRAW_SETTING(rrpm);
2624 : #endif
2625 : #if AP_FENCE_ENABLED
2626 548 : DRAW_SETTING(fence);
2627 : #endif
2628 548 : DRAW_SETTING(roll_angle);
2629 548 : DRAW_SETTING(pitch_angle);
2630 548 : DRAW_SETTING(temp);
2631 : #if BARO_MAX_INSTANCES > 1
2632 548 : DRAW_SETTING(btemp);
2633 : #endif
2634 548 : DRAW_SETTING(atemp);
2635 548 : DRAW_SETTING(hdop);
2636 548 : DRAW_SETTING(flightime);
2637 : #if AP_RTC_ENABLED
2638 548 : DRAW_SETTING(clk);
2639 : #endif
2640 : #if AP_VIDEOTX_ENABLED
2641 548 : DRAW_SETTING(vtx_power);
2642 : #endif
2643 :
2644 : #if HAL_WITH_ESC_TELEM
2645 548 : DRAW_SETTING(esc_temp);
2646 548 : DRAW_SETTING(esc_rpm);
2647 548 : DRAW_SETTING(esc_amps);
2648 : #endif
2649 :
2650 548 : DRAW_SETTING(gps_latitude);
2651 548 : DRAW_SETTING(gps_longitude);
2652 : #if HAL_PLUSCODE_ENABLE
2653 548 : DRAW_SETTING(pluscode);
2654 : #endif
2655 548 : DRAW_SETTING(dist);
2656 548 : DRAW_SETTING(stat);
2657 548 : DRAW_SETTING(climbeff);
2658 548 : DRAW_SETTING(eff);
2659 548 : DRAW_SETTING(callsign);
2660 548 : DRAW_SETTING(current2);
2661 :
2662 : #if AP_OSD_EXTENDED_LNK_STATS
2663 : DRAW_SETTING(rc_tx_power);
2664 : DRAW_SETTING(rc_rssi_dbm);
2665 : DRAW_SETTING(rc_snr);
2666 : DRAW_SETTING(rc_active_antenna);
2667 : DRAW_SETTING(rc_lq);
2668 : #endif
2669 : }
2670 : #endif
2671 : #endif // OSD_ENABLED
|