Paparazzi UAS v7.1_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
max7456.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013-2020 Chris Efstathiou hendrixgr@gmail.com
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
28#include "std.h"
29//#include "stdio.h"
30
32
33#include "mcu_periph/sys_time.h"
34#include "mcu_periph/gpio.h"
35#include "mcu_periph/spi.h"
36
37#include "generated/flight_plan.h"
38#include "generated/airframe.h"
39#include "autopilot.h"
41#include "state.h"
42
43// for GetPosAlt, include correct header until we have unified API
44#if defined(FIXEDWING_FIRMWARE)
45//#include "modules/nav/nav.h"
47#elif defined(ROTORCRAFT_FIRMWARE)
49#endif
50#if DOWNLINK
52#endif
53
54// Peripherials
57
58#define OSD_STRING_SIZE 31
59#define osd_sprintf _osd_sprintf
60
61#if !defined(OSD_USE_FLOAT_LOW_PASS_FILTERING)
62#define OSD_USE_FLOAT_LOW_PASS_FILTERING
63#endif
64
65//LOW PASS filter strength, cannot be 0, MAX=16
66#if !defined(AMPS_LOW_PASS_FILTER_STRENGTH) || AMPS_LOW_PASS_FILTER_STRENGTH == 0
67#define AMPS_LOW_PASS_FILTER_STRENGTH 6
68#endif
69
70#if !defined(SPEED_LOW_PASS_FILTER_STRENGTH) || SPEED_LOW_PASS_FILTER_STRENGTH == 0
71#define SPEED_LOW_PASS_FILTER_STRENGTH 6
72#endif
73
74#if !defined(BAT_CAPACITY)
75#pragma message "BAT_CAPACITY not defined, 5000 mah will be used."
76#define BAT_CAPACITY 5000.0
77#endif
78
79#if defined(FIXEDWING_FIRMWARE)
80
81#if !defined(LOITER_BAT_CURRENT)
82#pragma message "LOITER_BAT_CURRENT not defined, 10 Amps will be used for LOITER current draw."
83#define LOITER_BAT_CURRENT 10.0
84#endif
85
86#if !defined(STALL_AIRSPEED)
87#pragma message "STALL_AIRSPEED not defined, 10 m/s will be used."
88#define STALL_AIRSPEED 10.0
89#endif
90
91#if !defined(MINIMUM_AIRSPEED)
92#pragma message "MINIMUM_AIRSPEED not defined, 1.3 * STALL_SPEED will be used"
93#define MINIMUM_AIRSPEED (1.3f * STALL_AIRSPEED)
94#endif
95
96#endif
97
98#if !defined(IMU_MAG_X_SIGN)
99#define IMU_MAG_X_SIGN 1
100#endif
101#if !defined(IMU_MAG_X_SIGN)
102#define IMU_MAG_Y_SIGN 1
103#endif
104#if !defined(IMU_MAG_X_SIGN)
105#define IMU_MAG_Z_SIGN 1
106#endif
107
108
109typedef struct {
110 float fx;
111 float fy;
112 float fz;
113} VECTOR;
114
115typedef struct {
116 float fx1; float fx2; float fx3;
117 float fy1; float fy2; float fy3;
118 float fz1; float fz2; float fz3;
119} MATRIX;
120
121#if defined(FIXEDWING_FIRMWARE)
122static void mag_compass(void);
123#endif
126static float home_direction(void);
127static char ascii_to_osd_c(char c);
128static void calc_flight_time_left(void);
129static void draw_osd(void);
130static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column);
131static bool _osd_sprintf(char *buffer, char *string, float value);
132
134
139char osd_char = ' ';
143
157
166
172
176float home_dir_deg = 0;
177
178#if defined(FIXEDWING_FIRMWARE)
179// Periodic function called with a frequency defined in the module .xml file
180void mag_compass(void)
181{
182
184 float cos_roll; float sin_roll; float cos_pitch; float sin_pitch; float mag_x; float mag_y;
185 static float mag_declination = 0;
186 static bool declination_calculated = false;
187
188 struct imu_mag_t *mag = imu_get_mag(ABI_BROADCAST, false);
189 if(mag == NULL)
190 return;
191
192 cos_roll = cosf(att->phi);
193 sin_roll = sinf(att->phi);
194 cos_pitch = cosf(att->theta);
195 sin_pitch = sinf(att->theta);
196 // Pitch&Roll Compensation:
197 mag_x = mag->scaled.x * cos_pitch + mag->scaled.y * sin_roll * sin_pitch + mag->scaled.z * cos_roll * sin_pitch;
198 mag_y = mag->scaled.y * cos_roll - mag->scaled.z * sin_roll;
199
200 // Magnetic Heading N = 0, E = 90, S = +-180, W = -90
202#if defined(AHRS_MAG_DECLINATION)
203 if (AHRS_MAG_DECLINATION != 0.0) {
204 //conversion from degrees to radians is done in the airframe.h file
206 }
207#endif
208 if (mag_heading_rad > M_PI) { // Angle normalization (-180 deg to 180 deg)
209 mag_heading_rad -= (2.0 * M_PI);
210 } else if (mag_heading_rad < -M_PI) { mag_heading_rad += (2.0 * M_PI); }
211
212 if (declination_calculated == false) {
213#if defined(NOMINAL_AIRSPEED)
215#else
216 if (gps.fix == GPS_FIX_3D && stateGetHorizontalSpeedNorm_f() > 10.0) {
217#endif
219 if (mag_declination > M_PI) { // Angle normalization (-180 deg to 180 deg)
220 mag_declination -= (2.0 * M_PI);
221 } else if (mag_declination < -M_PI) { mag_declination += (2.0 * M_PI); }
225 }
226 }
228 if (mag_heading_rad > M_PI) { // Angle normalization (-180 deg to 180 deg)
229 mag_heading_rad -= (2.0 * M_PI);
230 } else if (mag_heading_rad < -M_PI) { mag_heading_rad += (2.0 * M_PI); }
231 // Magnetic COMPASS Heading N = 0, E = 90, S = 180, W = 270
233 if (mag_course_deg < 0) { mag_course_deg += 360; }
234
235 return;
236}
237#endif
238
239//*******************************************************************
240// function name: vSubtractVectors
241// description: subtracts two vectors a = b - c
242// parameters:
243//*******************************************************************
245{
246 svA->fx = svB.fx - svC.fx;
247 svA->fy = svB.fy - svC.fy;
248 svA->fz = svB.fz - svC.fz;
249}
250
251//*******************************************************************
252// function name: vMultiplyMatrixByVector
253// description: multiplies matrix by vector svA = smB * svC
254// parameters:
255//*******************************************************************
257{
258 svA->fx = smB.fx1 * svC.fx + smB.fx2 * svC.fy + smB.fx3 * svC.fz;
259 svA->fy = smB.fy1 * svC.fx + smB.fy2 * svC.fy + smB.fy3 * svC.fz;
260 svA->fz = smB.fz1 * svC.fx + smB.fz2 * svC.fy + smB.fz3 * svC.fz;
261}
262
263
264static float home_direction(void)
265{
266
268 static MATRIX smRotation;
269 float home_dir = 0;
270
271
272 /*
273 By swapping coordinates (fx=fPlaneNorth, fy=fPlaneEast) we make the the circle angle go from 0 (0 is to the top of the circle)
274 to 360 degrees or from 0 radians to 2 PI radians in a clockwise rotation. This way the GPS reported angle can be directly
275 applied to the rotation matrices (in radians).
276 In standard mathematical notation 0 is to the right (East) of the circle, -90 is to the bottom, +-180 is to the left
277 and +90 is to the top (counterclockwise rotation).
278 When reading back the actual rotated coordinates fx has the y coordinate and fy has the x when
279 represented on a circle in standard mathematical notation.
280 */
281 if (gps.fix == GPS_FIX_3D && stateGetHorizontalSpeedNorm_f() > 5.0) { //Only when flying
285#if defined(FIXEDWING_FIRMWARE)
289#else
292 Home_Position.fz = 0;
293#endif
294
295 /* distance between plane and object */
297
298 /* yaw */
301 smRotation.fx3 = 0.;
302 smRotation.fy1 = -smRotation.fx2;
303 smRotation.fy2 = smRotation.fx1;
304 smRotation.fy3 = 0.;
305 smRotation.fz1 = 0.;
306 smRotation.fz2 = 0.;
307 smRotation.fz3 = 1.;
308
310
311 /* DEFAULT ORIENTATION IS 0 = FRONT, 90 = RIGHT, 180 = BACK, -90 = LEFT
312 *
313 * WHEN home_dir = (float)(atan2(Home_PositionForPlane2.fy, (Home_PositionForPlane2.fx)));
314 *
315 * plane front
316 * 0Ëš
317 * ^
318 * I
319 * -45Ëš I 45Ëš
320 * \ I /
321 * \I/
322 * -90Ëš-------I------- 90Ëš
323 * /I\
324 * / I \
325 * -135Ëš I 135Ëš
326 * I
327 * 180
328 * plane back
329 *
330 *
331 * When the home_dir variable goes to 0 the aircraft is headed straight back home
332 */
333
334 /* fixed to the plane*/
336 if (home_dir > M_PI) { // Angle normalization (-180 deg to 180 deg but still in radians)
337 home_dir -= (2.0 * M_PI);
338 } else if (home_dir < -M_PI) { home_dir += (2.0 * M_PI); }
339 home_dir_deg = DegOfRad(home_dir); // Now convert radians to degrees.
340
341 } // END OF if (gps.fix == GPS_FIX_3D) statement.
342
343 return (home_dir_deg);
344}
345
346static char ascii_to_osd_c(char c)
347{
348
349#if defined USE_MATEK_TYPE_OSD_CHIP && USE_MATEK_TYPE_OSD_CHIP == 1
350 PRINT_CONFIG_MSG("OSD USES THE CUSTOM MATEK TYPE OSD CHIP")
351
352 return (c);
353
354#else
355 PRINT_CONFIG_MSG("OSD USES THE STANDARF MAX7456 OSD CHIP")
356
357 if (c >= '0' && c <= '9') {
358 if (c == '0') { c -= 38; } else { c -= 48; }
359 } else if (c >= 'A' && c <= 'Z') {
360 c -= 54;
361 } else if (c >= 'a' && c <= 'z') {
362 c -= 60;
363
364 } else {
365 switch (c) {
366 case ('('): c = 0x3f; break;
367 case (')'): c = 0x40; break;
368 case ('.'): c = 0x41; break;
369 case ('?'): c = 0x42; break;
370 case (';'): c = 0x43; break;
371 case (':'): c = 0x44; break;
372 case (','): c = 0x45; break;
373 //case('''): c = 0x46; break;
374 case ('/'): c = 0x47; break;
375 case ('"'): c = 0x48; break;
376 case ('-'): c = 0x49; break;
377 case ('<'): c = 0x4A; break;
378 case ('>'): c = 0x4B; break;
379 case ('@'): c = 0x4C; break;
380 case (' '): c = 0x00; break;
381 case ('\0'): c = 0xFF; break;
382 default : break;
383 }
384 }
385
386 return (c);
387
388#endif
389}
390
391static void calc_flight_time_left(void)
392{
393 float current_amps = 0;
394 float horizontal_speed = 0;
395 float bat_capacity_left = 0;
396 static float bat_capacity_used = 0;
397
398
400 bat_capacity_used += (current_amps * 1000.) / (3600. * (float)MAX7456_PERIODIC_FREQ);
402 if (bat_capacity_left < 0) { bat_capacity_left = 0; }
404
405#if defined(FIXEDWING_FIRMWARE)
406 if (stateGetHorizontalSpeedNorm_f() < 5.0 || autopilot.launch == false) {
409 }
410#else // #if !FW
411 current_amps = 1.0; // FIXME, Find how to tell if the rotorcraft is on the ground or it is flying.
412 horizontal_speed = 10.0;
413#endif
414
415#if defined(OSD_USE_FLOAT_LOW_PASS_FILTERING)
416
417 static double current_amps_sum = 0;
418 static double horizontal_speed_sum = 0;
419 static float current_amps_filtered = 0;
420 static float horizontal_speed_filtered = 0;
421
425
429
430#else
431
434 static uint64_t current_amps_sum = 0;
438
439 // LOW PASS FILTERS for making the OSD 'max_flyable_distance_left' var change more gently.
442
446
450
453
454#endif
455
457
458 return;
459}
460
461
463{
464
465 int8_t x = 0, idx = 0, post_offset = 0, aft_offset = 0, string_len = 0;
467
468 if (row > 15) { column = 15; }
469 if (column > 29) { column = 29; }
470
471// translate the string and put it to the "osd_string" '\0' = 0xff
472 x = 0;
473 while (*(string + x) != '\0') { osd_string[x] = ascii_to_osd_c(*(string + x)); x++; }
474 osd_string[x] = 0xff;
475 string_len = x;
476 idx = x;
477
478 if (attributes & C_JUST) {
479 if (char_nb % 2 == 0) { char_nb++; }
482 if (((int8_t)column - (char_nb / 2)) >= 0) { column -= (char_nb / 2); }
483 for (x = 0; x < 30; x++) { osd_buf[x] = 0; } // FILL WITH SPACES
484 // COPY THE ORIGINAL STRING TO ITS NEW POSITION
485 for (x = 0; x < string_len; x++) { osd_buf[post_offset + x] = osd_string[x]; }
486 osd_buf[string_len + aft_offset] = 0xFF; // TERMINATE THE MODIFIED STRING
487 // COPY THE MODIFIED STRING TO MAIN OSD STRING
488 x = 0;
489 do { osd_string[x] = osd_buf[x]; } while (osd_buf[x++] != 0xFF);
490 } else if (attributes & R_JUST) {
491 //if(x){ x -= 1; }
492 //if (char_nb < string_len){ char_nb = string_len; }
493 if (((int8_t)column - char_nb) >= 0) { column -= char_nb; }
494 if (((int8_t)char_nb - string_len) >= 0) { post_offset = char_nb - string_len; } else {post_offset = 0; }
495 //ADD LEADING SPACES
496 //First shift right the string and then add spaces at the beggining
497 while (idx >= 0) { osd_string[idx + post_offset] = osd_string[idx]; idx--; }
498 idx = 0;
499 while (idx < post_offset) { osd_string[idx] = 0; idx++; }
500 //osd_string[idx] = 0xff;
501
502 } else {
503 //Adjust for the reserved character number.
504 for (x = 0; x < (int8_t)(sizeof(osd_string)); x++) { if (osd_string[x] == 0xFF) { break; } }
505 for (; x < char_nb; x++) { osd_string[x] = 0; }
506 osd_string[x] = 0xff;
507 }
508
511//TRIGGER THE SPI TRANSFERS. The rest of the spi transfers occur in the "max7456_event" function.
515 max7456_trans.output_buf[1] = (uint8_t)((osd_char_address >> 8) & 0x0001);
518
519 }
520
521 return;
522}
523
524
525static bool _osd_sprintf(char *buffer, char *string, float value)
526{
528 uint8_t param_end = 0;
529 uint8_t frac_nb = 0;
530 uint8_t digit = 0;
531 uint8_t x = 0, y = 0, z = 0;
532
533 uint16_t i_dec = 0;
534 uint16_t i_frac = 0;
535
536 char to_asc[10] = {48, 48, 48, 48, 48, 48, 48, 48, 48, 48};
538
539// Clear the osd string.
540 for (x = 0; x < sizeof(osd_string); x++) { osd_string[x] = 0; }
541 for (x = 0; x < sizeof(string_buf); x++) { string_buf[x] = 0; }
542
543//copy the string passed as parameter to a buffer
544 for (x = 0; x < sizeof(string_buf); x++) { string_buf[x] = *(string + x); if (string_buf[x] == '\0') { break; } }
545 do {
546 x = 0;
547 param_start = 0;
548 param_end = 0;
549 //Now check for any special character
550 while (string_buf[x] != '\0') {
551 // EXAMPLE: in "%160c"x is '%' x+4 = 'c' and x+1='1', x+2='6' and x+3='0'
552 if (string_buf[x] == '%') { if (string_buf[x + 4] == 'c') { (param_start = x + 1); param_end = x + 3; break; } }
553 x++;
554 }
555 if (param_end - param_start) {
556 //load the special character value where the % character was
557 string_buf[x] = ((string_buf[param_start] - 48) * 100) + ((string_buf[param_start + 1] - 48) * 10) +
558 (string_buf[param_start + 2] - 48);
559 x++; // increment x to the next character which should be the first special character's digit
560 //Move the rest of the buffer forward so only the special character remains,
561 // for example in %170c '%' now has the special character's code and x now points to '1'
562 // which will be overwritten with the rest of the string after the 'c'
563 for (y = (x + 4); y <= sizeof(string_buf); y++) { string_buf[x++] = string_buf[y]; }
564 }
565 } while ((param_end - param_start > 0));
566
567// RESET THE USED VARIABLES JUST TO BE SAFE.
568 x = 0;
569 y = 0;
570 param_start = 0;
571 param_end = 0;
572// Search for the prameter start and stop positions.
573 while (string_buf[x] != '\0') {
574 if (string_buf[x] == '%') {
575 param_start = x;
576
577 } else if (string_buf[x] == 'f') { param_end = x; break; }
578 x++;
579 }
580 if (param_end - param_start) {
581 // find and bound the precision specified.
582 frac_nb = string_buf[param_end - 1] - 48; // Convert to number, ASCII 48 = '0'
583 if (frac_nb > 3) { frac_nb = 3; } // Bound value.
584
585 y = (sizeof(to_asc) - 1); // Point y to the end of the array.
586 i_dec = abs((int16_t)value);
587 // Fist we will deal with the fractional part if specified.
588 if (frac_nb > 0 && frac_nb <= 3) {
589 i_frac = abs((int16_t)((value - (int16_t)value) * 1000)); // Max precision is 3 digits.
590 x = 100;
591 z = frac_nb;
592 do { // Example if frac_nb=2 then 952 will show as .95
593 z--;
594 digit = (i_frac / x);
595 to_asc[y + z] = digit + 48; // Convert to ASCII
596 i_frac -= digit * x; // Calculate the remainder.
597 x /= 10; // 952-(9*100) = 52, 52-(10*5)=2 etc.
598
599 } while (z > 0);
600
601 y -= frac_nb; // set y to point where the dot must be placed.
602 to_asc[y] = '.';
603 y--; // Set y to point where the rest of the numbers must be written.
604
605 } // if (frac_nb > 0 && frac_nb <= 3){
606
607 // Now it is time for the integer part. "y" already points to the position just before the dot.
608 do {
609 to_asc[y] = (i_dec % 10) + 48; //Write at least one digit even if value is zero.
610 i_dec /= 10;
611 if (i_dec <= 0) { // This way the leading zero is ommited.
612 if (value < 0) { y--; to_asc[y] = '-'; } // Place the minus sign if needed.
613 break;
614
615 } else { y--; }
616
617 } while (1);
618
619 // Fill the buffer with the characters in the beggining of the string if any.
620 for (x = 0; x < param_start; x++) { *(buffer + x) = string_buf[x]; }
621
622 // x is now pointing to the next character in osd_string.
623 // y is already pointing to the first digit or negative sign in "to_asc" array.
624 while (y < sizeof(to_asc)) { *(buffer + x) = to_asc[y]; x++; y++; }
625 // x is now pointing to the next character in osd_string.
626 // "param_end" is pointing to the last format character in the string.
627 do {
628 param_end++;
629 *(buffer + x++) = string_buf[param_end];
630
631 } while (string_buf[param_end] != '\0'); //Write the rest of the string including the terminating char.
632
633 // End of if (param_end - param_start)
634 } else {
635 for (x = 0; x < sizeof(string_buf); x++) {
636 *(buffer + x) = string_buf[x]; //Write the rest of the string including the terminating char.
637 if (*(buffer + x) == '\0') { break; }
638 }
639 }
640
641 return (0);
642}
643
644void draw_osd(void)
645{
646 float temp = 0;
647 float altitude = 0;
648 float distance_to_home = 0;
649 static float home_direction_degrees = 0;
650#if defined(BARO_ALTITUDE_VAR)
651 static float baro_alt_correction = 0;
652#endif
653
655 struct EnuCoor_f *pos = stateGetPositionEnu_f();
656#if defined(FIXEDWING_FIRMWARE)
657 float ph_x = waypoints[WP_HOME].x - pos->x;
658 float ph_y = waypoints[WP_HOME].y - pos->y;
660#else // FOR ROTORCRAFTS
661 float ph_x = waypoint_get_x(WP_HOME) - pos->x;
662 float ph_y = waypoint_get_y(WP_HOME) - pos->y;
663#endif //
664
667#if defined(FIXEDWING_FIRMWARE)
668 mag_compass();
669#endif
670
671 //THE SWITCH STATEMENT ENSURES THAT ONLY ONE SPI TRANSACTION WILL OCUUR IN EVERY PERIODIC FUNCTION CALL
672 switch (step) {
673
674 case (0):
675 if (gps.fix == GPS_FIX_3D && stateGetHorizontalSpeedNorm_f() > 10.0) { //Only when flying
678 } else {
679#if defined(FIXEDWING_FIRMWARE)
681#else
683#endif
684 }
686 osd_put_s(osd_string, C_JUST, 3, 1, 15);
687 step = 10;
688 break;
689
690 case (10):
691 //Only when flying because i need this indication to remain stable if the GPS is lost.
692 // This way i can still have the synchronized magnetic compass heading and the last bearing home.
693 if (gps.fix == GPS_FIX_3D && gps.pdop < 1000 && stateGetHorizontalSpeedNorm_f() > 5.0) { //Only when flying
694 home_direction_degrees = gps_course_deg + home_direction(); //home_direction returns degrees -180 to +180
695 if (home_direction_degrees < 0) { home_direction_degrees += 360; } // translate the -180, +180 to 0-360.
696 if (home_direction_degrees >= 360) { home_direction_degrees -= 360; }
697 }
698#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
699 // All special character codes must be in 3 digit format!
700 osd_sprintf(osd_string, "%191c%.0f", home_direction_degrees); // 0 when heading straight back home.
701 osd_put_s(osd_string, C_JUST, 5, 2, 15); // "false = L_JUST
702#else
704 osd_put_s(osd_string, C_JUST, 5, 2, 15); // "false = L_JUST
705
706#endif
707 step = 20;
708 break;
709
710 case (20):
711 temp = ((float)electrical.vsupply);
712 osd_sprintf(osd_string, "%.1fV", temp);
713 if (temp > LOW_BAT_LEVEL) {
714 osd_put_s(osd_string, L_JUST, 5, 1, 1);
715
716 } else { osd_put_s(osd_string, (L_JUST | BLINK | INVERT), 5, 1, 1); }
717 step = 30;
718 break;
719
720 case (30):
721 if (gps.fix == GPS_FIX_3D) {
722#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
723 //Since we only send one special character the float variable is replaced by a zero.
724 osd_sprintf(osd_string, "%030c%031c", 0);
725 osd_put_s(osd_string, false, 2, 2, 1);
726#else
727 osd_put_s("**", false, 2, 2, 1);
728#endif
729 } else {
730#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
731 //Since we only send one special character the float variable is replaced by a zero.
732 osd_sprintf(osd_string, "%030c%031c", 0); // ALL special osd chars must have 3 digits.
733 osd_put_s(osd_string, (L_JUST | BLINK), 2, 2, 1);
734#else
735 osd_put_s("**", (L_JUST | BLINK), 2, 2, 1);
736#endif
737 }
738 step = 40;
739 break;
740
741 case (40):
742#if defined(FIXEDWING_FIRMWARE)
744 osd_put_s("A2", L_JUST, 2, 2, 3);
745 } else if (autopilot.mode == AP_MODE_AUTO1) {
746 osd_put_s("A1", L_JUST, 2, 2, 3);
747 } else {
748 osd_put_s("MAN", L_JUST, 3, 2, 3);
749 }
750#endif
751 step = 50;
752 break;
753
754 case (50):
755#if defined(FIXEDWING_FIRMWARE)
756 osd_sprintf(osd_string, "THR%.0f", (((float)command_get(COMMAND_THROTTLE) / (float)MAX_PPRZ) * 100.));
757#else
758 osd_sprintf(osd_string, "THR%.0fTHR", (((float)stabilization.cmd[COMMAND_THRUST] / (float)MAX_PPRZ) * 100.));
759#endif
760 osd_put_s(osd_string, L_JUST, 6, 3, 1);
761 step = 60;
762 break;
763
764 case (60):
765#if defined(FIXEDWING_FIRMWARE)
766#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
768 osd_sprintf(osd_string, "STALL!", 0);
769 osd_put_s(osd_string, (R_JUST | BLINK), 6, 1, 30);
770 } else {
772 osd_put_s(osd_string, R_JUST, 6, 1, 30);
773 }
774#else
776 osd_sprintf(osd_string, "STALL!", 0);
777 osd_put_s(osd_string, (R_JUST | BLINK), 6, 1, 30);
778 } else {
780 osd_put_s(osd_string, R_JUST, 6, 1, 30);
781 }
782#endif
783
784#else // #if !FW
785
786#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
788#else
790#endif
791 osd_put_s(osd_string, R_JUST, 6, 1, 30);
792
793#endif
794 step = 70;
795 break;
796
797 case (70):
798#if defined(BARO_ALTITUDE_VAR)
799 if (gps.fix == GPS_FIX_3D && gps.pdop < 1000) {
802 } else {
804 }
805#else
807#endif
808#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
809 osd_sprintf(osd_string, "%.0f%177c", altitude);
810#else
812#endif
813 osd_put_s(osd_string, R_JUST, 6, 2, 30); // "false = L_JUST
814 step = 80;
815 break;
816
817 case (80):
818#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
819 osd_sprintf(osd_string, "%.1f%159c", stateGetSpeedEnu_f()->z);
820#else
822#endif
823 if (stateGetSpeedEnu_f()->z > 3.0) {
824 osd_put_s(osd_string, (R_JUST | BLINK), 6, 3, 30);
825 } else {
826 osd_put_s(osd_string, R_JUST, 6, 3, 30);
827 }
828 step = 90;
829 break;
830
831 case (90):
832#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
833 // ANY SPECIAL CHARACTER CODE MUST BE A 3 DIGIT NUMBER WITH THE LEADING ZEROS!!!!
834 // THE SPECIAL CHARACTER CAN BE PLACED BEFORE OR AFTER THE FLOAT OR ANY OTHER CHARACTER
835 osd_sprintf(osd_string, "%160c%.1fK%012c", (distance_to_home / 1000));
836 osd_put_s(osd_string, L_JUST, 7, 15, 1);
837#else
838 osd_sprintf(osd_string, "%.1fKM", (distance_to_home / 1000));
839 osd_put_s(osd_string, L_JUST, 7, 15, 1);
840#endif
841 step = 100;
842 break;
843
844 case (100):
845#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
846 osd_sprintf(osd_string, "%147c%.1fK%012c", (max_flyable_distance_left / 1000));
847#else
849#endif
851 osd_put_s(osd_string, (R_JUST | BLINK), 7, 15, 30);
852 } else {
853 osd_put_s(osd_string, (R_JUST), 7, 15, 30);
854 }
855 step = 110;
856 break;
857
858 // A Text PFD as graphics are not the strong point of the MAX7456
859 // In order to level the aircraft while fpving
860 // just move the stick to the opposite direction from the angles shown on the osd
861 // and that's why positive pitch (UP) is shown below the OSD center
862 case (110):
863 if (DegOfRad(att->theta) > 3) {
864 osd_sprintf(osd_string, "%.0f", DegOfRad(att->theta));
865 osd_put_s(osd_string, C_JUST, 5, 6, 15);
866
867 } else { osd_put_s(" ", C_JUST, 5, 6, 15); }
868 step = 112;
869 break;
870
871 case (112):
872 if (DegOfRad(att->theta) < -3) {
873 osd_sprintf(osd_string, "%.0f", DegOfRad(att->theta));
874 osd_put_s(osd_string, C_JUST, 5, 10, 15);
875
876 } else { osd_put_s(" ", C_JUST, 5, 10, 15); }
877 step = 114;
878 break;
879
880 case (114):
881 if (DegOfRad(att->phi) > 3) {
882 osd_sprintf(osd_string, "%.0f>", DegOfRad(att->phi));
883 osd_put_s(osd_string, false, 5, 8, 18);
884
885 } else { osd_put_s(" ", false, 5, 8, 18); }
886 step = 116;
887 break;
888
889 case (116):
890 if (DegOfRad(att->phi) < -3) {
891 osd_sprintf(osd_string, "<%.0f", DegOfRad(fabs(att->phi)));
892 osd_put_s(osd_string, R_JUST, 5, 8, 13);
893
894 } else { osd_put_s(" ", R_JUST, 5, 8, 13); }
895 step = 120;
896 break;
897
898 case (120):
899#if defined(USE_MATEK_TYPE_OSD_CHIP) && USE_MATEK_TYPE_OSD_CHIP == 1
900 osd_sprintf(osd_string, "%126c", 0);
901 osd_put_s(osd_string, false, 1, 8, 15); // false = L_JUST
902#else
903 osd_put_s("+", false, 1, 8, 15); // false = L_JUST
904#endif
905 step = 0;
906 break;
907
908 default: step = 0; break;
909 } // End of switch statement.
910
911 return;
912}
913
939
941{
942
943 //This code is executed always and checks if the "osd_enable" var has been changed by telemetry.
944 //If yes then it commands a reset but this time turns on or off the osd overlay, not the video.
946 if (osd_enable > 1) {
947 osd_enable = 1;
948 }
949 if ((osd_enable << 3) != osd_enable_val) {
950 osd_enable_val = (osd_enable << 3);
952 }
953 }
954
955 //INITIALIZATION OF THE OSD
957 step = 0;
960 //This operation needs at least 100us but when the periodic function will be invoked again
961 //sufficient time will have elapsed even with at a periodic frequency of 1000 Hz
963 //We give an extra delay step by going to the event function and back here for the Reset to complete.
966 } else if (max7456_osd_status == OSD_INIT2) {
972 } else if (max7456_osd_status == OSD_IDLE && osd_enable > 0) {
973 draw_osd();
974 } // End of if (max7456_osd_status == OSD_UNINIT)
975
976
977
978 return;
979}
980
982{
983
984 static uint8_t x = 0;
985
988
989 switch (max7456_osd_status) {
990 case (OSD_INIT1):
992 break;
993 case (OSD_INIT3):
997 //Max7456 requires that you read first and then change only bit4 of the OSDBL register.
998 //Reading was started in the periodic function and now we rerwrite the OSDBL register.
999 max7456_trans.output_buf[1] = max7456_trans.input_buf[1] & (~(1 << 4));
1002 break;
1003 case (OSD_INIT4):
1005#if USE_PAL_FOR_OSD_VIDEO
1006#pragma message "Camera and OSD must be both PAL or NTSC otherwise only the camera picture will be visible."
1008#else
1010#endif
1013 break;
1014 case (OSD_S_STEP1):
1020 break;
1021 case (OSD_S_STEP2):
1027 x = 0;
1028 break;
1029 case (OSD_S_STEP3):
1030 max7456_trans.output_length = 1; //1 byte tranfers, auto address incrementing.
1031 if (osd_string[x] != 0XFF) {
1034 } else {
1035 max7456_trans.output_buf[0] = 0xFF; //Exit the auto increment mode
1038 }
1039 break;
1040 case (OSD_FINISHED):
1046 break;
1047 case (OSD_READ_STATUS):
1055 } else {
1056 osd_attr = 0;
1059 }
1060 break;
1061
1062 default: break;
1063 }
1064 }
1065 return;
1066}
#define ABI_BROADCAST
Broadcast address.
Definition abi_common.h:59
static int32_t altitude
struct pprz_autopilot autopilot
Global autopilot structure.
Definition autopilot.c:49
Core autopilot interface common to all firmwares.
bool launch
request launch
Definition autopilot.h:71
uint8_t mode
current autopilot mode
Definition autopilot.h:63
Hardware independent code for commands handling.
struct point waypoints[NB_WAYPOINT]
size == nb_waypoint, waypoint 0 is a dummy waypoint
Definition common_nav.c:44
#define WaypointX(_wp)
Definition common_nav.h:45
float y
Definition common_nav.h:41
float x
Definition common_nav.h:40
#define WaypointY(_wp)
Definition common_nav.h:46
struct Electrical electrical
Definition electrical.c:92
Interface for electrical status: supply voltage, current, battery status, etc.
#define LOW_BAT_LEVEL
low battery level in Volts (for 3S LiPo)
Definition electrical.h:36
float current
current in A
Definition electrical.h:47
float vsupply
supply voltage in V
Definition electrical.h:45
#define STALL_AIRSPEED
#define AP_MODE_AUTO2
#define AP_MODE_AUTO1
Some architecture independent helper functions for GPIOs.
struct GpsState gps
global GPS state
Definition gps.c:74
int32_t course
GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
Definition gps.h:102
uint16_t pdop
position dilution of precision scaled by 100
Definition gps.h:108
#define GPS_FIX_3D
3D GPS fix
Definition gps.h:44
uint8_t fix
status of fix
Definition gps.h:110
float phi
in radians
float theta
in radians
float psi
in radians
euler angles
enum SPIClockPolarity cpol
clock polarity control
Definition spi.h:151
enum SPIClockPhase cpha
clock phase control
Definition spi.h:152
enum SPISlaveSelect select
slave selection behavior
Definition spi.h:150
SPICallback before_cb
NULL or function called before the transaction.
Definition spi.h:156
SPICallback after_cb
NULL or function called after the transaction.
Definition spi.h:157
enum SPIDataSizeSelect dss
data transfer word size
Definition spi.h:153
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition spi.h:146
uint16_t input_length
number of data words to read
Definition spi.h:147
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition spi.h:155
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition spi.h:145
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition spi.h:149
enum SPIBitOrder bitorder
MSB/LSB order.
Definition spi.h:154
uint16_t output_length
number of data words to write
Definition spi.h:148
enum SPITransactionStatus status
Definition spi.h:158
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition spi_arch.c:548
@ SPICphaEdge1
CPHA = 0.
Definition spi.h:70
@ SPITransSuccess
Definition spi.h:95
@ SPITransDone
Definition spi.h:97
@ SPICpolIdleLow
CPOL = 0.
Definition spi.h:79
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition spi.h:59
@ SPIMSBFirst
Definition spi.h:108
@ SPIDiv64
Definition spi.h:121
@ SPIDss8bit
Definition spi.h:86
SPI transaction structure.
Definition spi.h:144
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1314
static struct UtmCoor_f * stateGetPositionUtm_f(void)
Get position in UTM coordinates (float).
Definition state.h:821
static struct EnuCoor_f * stateGetPositionEnu_f(void)
Get position in local ENU coordinates (float).
Definition state.h:848
static float stateGetHorizontalSpeedNorm_f(void)
Get norm of horizontal ground speed (float).
Definition state.h:1076
static float stateGetHorizontalSpeedDir_f(void)
Get dir of horizontal ground speed (float).
Definition state.h:1085
static struct EnuCoor_f * stateGetSpeedEnu_f(void)
Get ground speed in local ENU coordinates (float).
Definition state.h:1058
struct imu_mag_t * imu_get_mag(uint8_t sender_id, bool create)
Find or create the mag in the imu structure.
Definition imu.c:992
struct Int32Vect3 scaled
Last scaled values in body frame.
Definition imu.h:88
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
int32_t mag_y
Definition mag_hmc5843.c:29
int32_t mag_x
Definition mag_hmc5843.c:29
uint16_t foo
Definition main_demo5.c:58
static void draw_osd(void)
Definition max7456.c:644
float fz1
Definition max7456.c:118
#define SPEED_LOW_PASS_FILTER_STRENGTH
Definition max7456.c:71
#define BAT_CAPACITY
Definition max7456.c:76
uint8_t max7456_osd_status
Definition max7456.c:167
void max7456_periodic(void)
Definition max7456.c:940
float fx1
Definition max7456.c:116
static bool _osd_sprintf(char *buffer, char *string, float value)
Definition max7456.c:525
static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column)
Definition max7456.c:462
static void calc_flight_time_left(void)
Definition max7456.c:391
static void vSubtractVectors(VECTOR *svA, VECTOR svB, VECTOR svC)
Definition max7456.c:244
static void vMultiplyMatrixByVector(VECTOR *svA, MATRIX smB, VECTOR svC)
Definition max7456.c:256
float gps_course_deg
Definition max7456.c:175
uint8_t step
Definition max7456.c:140
float fy1
Definition max7456.c:117
#define OSD_STRING_SIZE
Definition max7456.c:58
float mag_course_deg
Definition max7456.c:173
struct spi_transaction max7456_trans
Definition max7456.c:133
uint8_t osd_enable_val
Definition max7456.c:169
#define osd_sprintf
Definition max7456.c:59
float fx
Definition max7456.c:110
char osd_str_buf[OSD_STRING_SIZE]
Definition max7456.c:138
void max7456_init(void)
Definition max7456.c:914
max7456_osd_status_codes
Definition max7456.c:144
@ OSD_INIT2
Definition max7456.c:147
@ OSD_S_STEP1
Definition max7456.c:152
@ OSD_S_STEP3
Definition max7456.c:154
@ OSD_FINISHED
Definition max7456.c:155
@ OSD_S_STEP2
Definition max7456.c:153
@ OSD_UNINIT
Definition max7456.c:145
@ OSD_INIT4
Definition max7456.c:149
@ OSD_IDLE
Definition max7456.c:151
@ OSD_INIT1
Definition max7456.c:146
@ OSD_INIT3
Definition max7456.c:148
@ OSD_READ_STATUS
Definition max7456.c:150
void max7456_event(void)
Definition max7456.c:981
float mag_heading_rad
Definition max7456.c:174
uint32_t max_flyable_distance_left
Definition max7456.c:171
uint8_t osd_stat_reg
Definition max7456.c:170
uint8_t osd_attr
Definition max7456.c:142
float home_dir_deg
Definition max7456.c:176
static char ascii_to_osd_c(char c)
Definition max7456.c:346
float fy
Definition max7456.c:111
osd_attributes
Definition max7456.c:158
@ C_JUST
Definition max7456.c:163
@ BLINK
Definition max7456.c:159
@ L_JUST
Definition max7456.c:161
@ R_JUST
Definition max7456.c:162
@ INVERT
Definition max7456.c:160
char osd_string[OSD_STRING_SIZE]
Definition max7456.c:137
uint8_t osd_enable
Definition max7456.c:168
uint16_t osd_char_address
Definition max7456.c:141
#define AMPS_LOW_PASS_FILTER_STRENGTH
Definition max7456.c:67
char osd_char
Definition max7456.c:139
uint8_t osd_spi_rx_buffer[2]
Definition max7456.c:136
uint8_t osd_spi_tx_buffer[2]
Definition max7456.c:135
float fz
Definition max7456.c:112
static float home_direction(void)
Definition max7456.c:264
Maxim MAX7456 single-channel monochrome on-screen display driver.
Maxim MAX7456 single-channel monochrome on-screen display driver.
#define OSD_OSDBL_REG_R
#define OSD_AUTO_INCREMENT_MODE
#define OSD_NVRAM_BUSY_FLAG
#define OSD_VM0_REG
#define OSD_DMM_REG
#define OSD_DMAH_REG
#define OSD_IMAGE_ENABLE
#define OSD_DMAL_REG
#define OSD_BLINK_CHAR
#define OSD_OSDBL_REG
#define OSD_RESET_BUSY_FLAG
#define OSD_RESET
#define OSD_INVERT_PIXELS
#define OSD_VIDEO_MODE_PAL
#define OSD_STAT_REG
float waypoint_get_x(uint8_t wp_id)
Get X/East coordinate of waypoint in meters.
Definition waypoints.c:102
float waypoint_get_y(uint8_t wp_id)
Get Y/North coordinate of waypoint in meters.
Definition waypoints.c:110
#define GetPosAlt()
Get current altitude above MSL.
Definition nav.h:233
#define GetAltRef()
Get current altitude reference for local coordinates.
Definition nav.h:242
static uint32_t idx
#define MAX_PPRZ
Definition paparazzi.h:8
float y
in meters
float x
in meters
float alt
in meters (above WGS84 reference ellipsoid or above MSL)
float z
in meters
vector in East North Up coordinates Units: meters
Rotorcraft navigation functions.
Architecture independent SPI (Serial Peripheral Interface) API.
struct Stabilization stabilization
int32_t cmd[COMMANDS_NB]
output command vector, range from [-MAX_PPRZ:MAX_PPRZ] (store for messages)
API to get/set the generic vehicle states.
Architecture independent timing functions.
Periodic telemetry system header (includes downlink utility and generated code).
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
short int16_t
Typedef defining 16 bit short type.
unsigned long long uint64_t
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.