dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
panel.c
Go to the documentation of this file.
1 
15 /*
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24  * for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, see <http://www.gnu.org/licenses/>
28  *
29  * Additional note on redistribution: The copyright and license notices above
30  * must be maintained in each individual source file that is a derivative work
31  * of this source file; otherwise redistribution is prohibited.
32  */
33 
34 /* Imported from MultiOSD (https://github.com/UncleRus/MultiOSD/)
35  * Altered for use on STM32 Flight controllers by dRonin
36  */
37 
38 /*
39  * This file is part of MultiOSD <https://github.com/UncleRus/MultiOSD>
40  *
41  * MultiOSD is free software: you can redistribute it and/or modify
42  * it under the terms of the GNU General Public License as published by
43  * the Free Software Foundation, either version 3 of the License, or
44  * (at your option) any later version.
45  *
46  * This program is distributed in the hope that it will be useful,
47  * but WITHOUT ANY WARRANTY; without even the implied warranty of
48  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49  * GNU General Public License for more details.
50  *
51  * You should have received a copy of the GNU General Public License
52  * along with this program. If not, see <http://www.gnu.org/licenses/>.
53  */
54 
55 #include <openpilot.h>
56 #include <math.h>
57 #include <string.h>
58 #include <misc_math.h>
59 
60 #include "charosd.h"
61 
62 #include "physical_constants.h"
63 
64 #include "airspeedactual.h"
65 #include "flightstatus.h"
66 #include "systemalarms.h"
67 #include "modulesettings.h"
68 
69 static inline float pythag(float a, float b) {
70  return sqrtf(a * a + b * b);
71 }
72 
73 /*
74  * 012
75  * 3 7
76  * 456
77  */
78 static void draw_rect(charosd_state_t state, uint8_t l, uint8_t t, uint8_t w, uint8_t h, bool filled, uint8_t attr)
79 {
80  const uint8_t _rect_thin [] = {0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7};
81  const uint8_t _rect_fill [] = {0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf};
82 
83  if (w < 2 || h < 2) return;
84 
85  uint8_t r = w - 1;
86  uint8_t b = h - 1;
87 
88  const uint8_t *rect = filled ? _rect_fill : _rect_thin;
89 
90  char buffer [w + 1];
91 
92  for (uint8_t i = 0; i < h; i ++) {
93  char spacer;
94  if (i == 0) {
95  buffer [0] = rect [0];
96  buffer [r] = rect [2];
97  spacer = rect [1];
98  } else if (i == b) {
99  buffer [0] = rect [4];
100  buffer [r] = rect [6];
101  spacer = rect [5];
102  } else {
103  buffer [0] = rect [3];
104  buffer [r] = rect [7];
105  spacer = ' ';
106  }
107 
108  if (w > 2) {
109  memset(buffer + 1, spacer, w - 2);
110  }
111 
112  buffer [w] = 0;
113 
114  PIOS_MAX7456_puts(state->dev, l, t + i, buffer, attr);
115  }
116 }
117 #define ERR_STR "---"
118 
119 #define terminate_buffer() do { buffer [sizeof(buffer) - 1] = 0; } while (0)
120 
121 #define STD_UPDATE(__name, n, fmt, ...) static void __name ## _update(charosd_state_t state, uint8_t x, uint8_t y) \
122 { \
123  char buffer[n]; \
124  snprintf(buffer, sizeof (buffer), fmt, __VA_ARGS__); \
125  terminate_buffer(); \
126  PIOS_MAX7456_puts(state->dev, x, y, buffer, 0); \
127 }
128 
129 #define STD_PANEL(__name, bs, fmt, ...) \
130  STD_UPDATE(__name, bs, fmt, __VA_ARGS__);
131 
132 
133 /* Alt */
134 STD_PANEL(ALTITUDE, 8, "\x85%d\x8d", (int16_t)round(-state->telemetry.position_actual.Down));
135 
136 /* Climb */
137 #define _PAN_CLIMB_SYMB 0x03
138 
139 static void CLIMB_update(charosd_state_t state, uint8_t x, uint8_t y)
140 {
141  int8_t c = round(state->telemetry.velocity_actual.Down * -10);
142  uint8_t s;
143  char buffer[8];
144 
145  if (c >= 20) s = _PAN_CLIMB_SYMB + 5;
146  else if (c >= 10) s = _PAN_CLIMB_SYMB + 4;
147  else if (c >= 0) s = _PAN_CLIMB_SYMB + 3;
148  else if (c <= -20) s = _PAN_CLIMB_SYMB + 2;
149  else if (c <= -10) s = _PAN_CLIMB_SYMB + 1;
150  else s = _PAN_CLIMB_SYMB;
151  snprintf(buffer, sizeof (buffer), "%c%.1f\x8c", s,
152  -(double)state->telemetry.velocity_actual.Down);
154  PIOS_MAX7456_puts(state->dev, x, y, buffer, 0);
155 }
156 
157 /* FlightMode */
158 
159 static void FLIGHTMODE_update(charosd_state_t state, uint8_t x, uint8_t y)
160 {
161  const char *mode = "INIT";
162 
163  switch (state->telemetry.flight_status.mode) {
164  case FLIGHTSTATUS_FLIGHTMODE_MANUAL:
165  mode = "MAN";
166  break;
167  case FLIGHTSTATUS_FLIGHTMODE_ACRO:
168  mode = "ACRO";
169  break;
170  case FLIGHTSTATUS_FLIGHTMODE_ACROPLUS:
171  mode = "ACR+";
172  break;
173  case FLIGHTSTATUS_FLIGHTMODE_LEVELING:
174  mode = "LVL";
175  break;
176  case FLIGHTSTATUS_FLIGHTMODE_HORIZON:
177  mode = "HRZN";
178  break;
179  case FLIGHTSTATUS_FLIGHTMODE_AXISLOCK:
180  mode = "ALCK";
181  break;
182  case FLIGHTSTATUS_FLIGHTMODE_VIRTUALBAR:
183  mode = "VBAR";
184  break;
185  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED1:
186  mode = "ST1";
187  break;
188  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED2:
189  mode = "ST2";
190  break;
191  case FLIGHTSTATUS_FLIGHTMODE_STABILIZED3:
192  mode = "ST3";
193  break;
194  case FLIGHTSTATUS_FLIGHTMODE_AUTOTUNE:
195  mode = "TUNE";
196  break;
197  case FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD:
198  mode = "AHLD";
199  break;
200  case FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD:
201  mode = "PHLD";
202  break;
203  case FLIGHTSTATUS_FLIGHTMODE_RETURNTOHOME:
204  mode = "RTH";
205  break;
206  case FLIGHTSTATUS_FLIGHTMODE_PATHPLANNER:
207  mode = "PLAN";
208  break;
209  case FLIGHTSTATUS_FLIGHTMODE_ACRODYNE:
210  mode = "ACDN";
211  break;
212  case FLIGHTSTATUS_FLIGHTMODE_FAILSAFE:
213  mode = "FAIL";
214  break;
215  case FLIGHTSTATUS_FLIGHTMODE_TABLETCONTROL:
216  // There are many sub modes here that could be filled in.
217  mode = "TAB";
218  break;
219  case FLIGHTSTATUS_FLIGHTMODE_LQG:
220  mode = "LQGR";
221  break;
222  case FLIGHTSTATUS_FLIGHTMODE_LQGLEVELING:
223  mode = "LQGL";
224  break;
225  case FLIGHTSTATUS_FLIGHTMODE_FLIPREVERSED:
226  mode = "FLIP";
227  break;
228  }
229 
230  draw_rect(state, x, y, 6, 3, 0, 0);
231  PIOS_MAX7456_puts(state->dev, x + 1, y + 1, mode, 0);
232 }
233 
234 /* ArmedFlag */
235 static void ARMEDFLAG_update(charosd_state_t state, uint8_t x, uint8_t y)
236 {
237  uint8_t attr = state->telemetry.flight_status.arm_status == FLIGHTSTATUS_ARMED_ARMED ? 0 : MAX7456_ATTR_INVERT;
238  draw_rect(state, x, y, 3, 3, true, attr);
239  PIOS_MAX7456_put(state->dev, x + 1, y + 1, 0xe0, attr);
240 }
241 
242 static void FLIGHTTIME_update(charosd_state_t state, uint8_t x, uint8_t y) {
243  char buffer[10];
244  uint32_t time = state->telemetry.system.flight_time;
245  int min, sec;
246 
247  uint16_t hours = (time / 3600000); // hours
248  if (hours == 0) {
249  min = time / 60000;
250  sec = (time / 1000) - 60 * min;
251  sprintf(buffer, "%02d:%02d", (int)min, (int)sec);
252  } else {
253  min = time / 60000 - 60 * hours;
254  sec = (time / 1000) - 60 * min - 3600 * hours;
255  sprintf(buffer, "%02d:%02d:%02d", (int)hours, (int)min, (int)sec);
256  }
257 
259 
260  PIOS_MAX7456_puts(state->dev, x + 1, y + 1, buffer, 0);
261 }
262 
263 /* Roll */
264 STD_PANEL(ROLL, 7, "\xb2%d\xb0", (int16_t) state->telemetry.attitude_actual.Roll);
265 
266 /* Pitch */
267 STD_PANEL(PITCH, 7, "\xb1%d\xb0", (int16_t) state->telemetry.attitude_actual.Pitch);
268 
269 /* GPS */
270 
271 #define _PAN_GPS_2D 0x01
272 #define _PAN_GPS_3D 0x02
273 
274 static void GPS_update(charosd_state_t state, uint8_t x, uint8_t y)
275 {
276  char buffer[4];
277 
278  snprintf(buffer, sizeof(buffer), "%d", state->telemetry.gps_position.Satellites);
280  bool err = state->telemetry.gps_position.Status < GPSPOSITION_STATUS_FIX2D;
281  PIOS_MAX7456_puts(state->dev, x, y, "\x10\x11", err ? MAX7456_ATTR_INVERT : 0);
282  PIOS_MAX7456_put(state->dev, x + 2, y, state->telemetry.gps_position.Status < GPSPOSITION_STATUS_FIX3D ? _PAN_GPS_2D : _PAN_GPS_3D,
283  err ? MAX7456_ATTR_INVERT : (state->telemetry.gps_position.Status < GPSPOSITION_STATUS_FIX2D ? MAX7456_ATTR_BLINK : 0));
284  if (err) PIOS_MAX7456_puts (state->dev, x + 3, y, ERR_STR, MAX7456_ATTR_INVERT);
285  else PIOS_MAX7456_puts(state->dev, x + 3, y, buffer, 0);
286 }
287 
288 // Would be nice to convert these to fixed point in the future.
289 
290 /* Lat */
291 STD_PANEL(LATITUDE, 11, "\x83%02.6f", (double)state->telemetry.gps_position.Latitude / 10000000.0);
292 
293 /* Lon */
294 STD_PANEL(LONGITUDE, 11, "\x84%02.6f", (double)state->telemetry.gps_position.Longitude / 10000000.0);
295 
296 #define PANEL_HORIZON_WIDTH 14
297 #define PANEL_HORIZON_HEIGHT 5
298 
299 #define _PAN_HORZ_LINE 0x16
300 #define _PAN_HORZ_TOP 0x0e
301 
302 #define _PAN_HORZ_CHAR_LINES 18
303 #define _PAN_HORZ_VRES 9
304 #define _PAN_HORZ_INT_WIDTH (PANEL_HORIZON_WIDTH - 2)
305 #define _PAN_HORZ_LINES (PANEL_HORIZON_HEIGHT * _PAN_HORZ_VRES)
306 #define _PAN_HORZ_TOTAL_LINES (PANEL_HORIZON_HEIGHT * _PAN_HORZ_CHAR_LINES)
307 
308 const char _horz_line [PANEL_HORIZON_WIDTH + 1] = "\xb8 \xb9";
309 const char _horz_center [PANEL_HORIZON_WIDTH + 1] = "\xc8 \xc9";
310 
311 void HORIZON_update(charosd_state_t state, uint8_t x, uint8_t y)
312 {
313  char buffer [PANEL_HORIZON_HEIGHT][PANEL_HORIZON_WIDTH + 1];
314 
315  for (uint8_t i = 0; i < PANEL_HORIZON_HEIGHT; i ++) {
316  memcpy(buffer[i], i == PANEL_HORIZON_HEIGHT / 2 ? _horz_center : _horz_line, PANEL_HORIZON_WIDTH);
317  buffer[i][PANEL_HORIZON_WIDTH] = 0;
318  }
319 
320  // code below from minoposd
321  int16_t pitch_line = tanf(DEG2RAD * (-state->telemetry.attitude_actual.Pitch)) * _PAN_HORZ_LINES;
322  float roll = tanf(DEG2RAD * state->telemetry.attitude_actual.Roll);
323  for (uint8_t col = 1; col <= _PAN_HORZ_INT_WIDTH; col ++) {
324  // center X point at middle of each column
326  // calculating hit point on Y plus offset to eliminate negative values
327  int16_t hit = roll * middle + pitch_line + _PAN_HORZ_LINES;
328  if (hit > 0 && hit < _PAN_HORZ_TOTAL_LINES) {
329  int8_t row = PANEL_HORIZON_HEIGHT - ((hit - 1) / _PAN_HORZ_CHAR_LINES);
330  int8_t subval = (hit - (_PAN_HORZ_TOTAL_LINES - row * _PAN_HORZ_CHAR_LINES + 1)) * _PAN_HORZ_VRES / _PAN_HORZ_CHAR_LINES;
331  if (subval == _PAN_HORZ_VRES - 1)
332  buffer [row - 2][col] = _PAN_HORZ_TOP;
333  buffer[row - 1][col] = _PAN_HORZ_LINE + subval;
334  }
335  }
336 
337  for (uint8_t i = 0; i < PANEL_HORIZON_HEIGHT; i ++) {
338  PIOS_MAX7456_puts(state->dev, x, y + i, buffer[i], 0);
339  }
340 }
341 
342 /* Throttle */
343 STD_PANEL(THROTTLE, 7, "\x87%d%%", (int)MAX(-99, state->telemetry.manual.thrust*100));
344 
345 /* GroundSpeed */
346 STD_PANEL(GROUNDSPEED, 7, "\x80%d\x81",
347  (int)roundf(pythag(state->telemetry.velocity_actual.North,
348  state->telemetry.velocity_actual.East) * 3.6f));
349 // * 3.6 == m/s to km/hr
350 
351 STD_PANEL(BATTERYVOLT, 8, "%.2f\x8e", (double)state->telemetry.battery.Voltage);
352 
353 /* BatCurrent */
354 STD_PANEL(BATTERYCURRENT, 8, "%.2f\x8f", (double)state->telemetry.battery.Current);
355 
356 /* BatConsumed */
357 STD_PANEL(BATTERYCONSUMED, 8, "%u\x82", (uint16_t) state->telemetry.battery.ConsumedEnergy);
358 
359 /* RSSIFlag */
360 static void RSSIFLAG_update (charosd_state_t state, uint8_t x, uint8_t y)
361 {
362  if (state->telemetry.manual.rssi < 50) {
363  PIOS_MAX7456_put (state->dev, x, y, 0xb4, MAX7456_ATTR_BLINK);
364  }
365 }
366 
367 static void HOMEDISTANCE_update(charosd_state_t state, uint8_t x, uint8_t y)
368 {
369  char buffer[8];
370  float dist = pythag(state->telemetry.position_actual.North,
371  state->telemetry.position_actual.East);
372  if (dist > 1000) {
373  snprintf(buffer, sizeof(buffer), "%.2f%c",
374  (double)dist/1000, CHAROSD_CHAR_KM);
375  } else {
376  snprintf(buffer, sizeof(buffer), "%d%c",
377  (int)round(dist), CHAROSD_CHAR_M);
378  }
379 
381  PIOS_MAX7456_puts(state->dev, x, y, buffer, 0);
382 }
383 
384 #define _ARROWS CHAROSD_CHAR_ARROW_NL
385 
386 static void HOMEDIRECTION_update(charosd_state_t state, uint8_t x, uint8_t y)
387 {
388  if (HAS_SENSOR(state->available, HAS_COMPASS)) {
389  float home_dir = (atan2f(state->telemetry.position_actual.East,
390  state->telemetry.position_actual.North) * RAD2DEG) + 180;
391 
392  home_dir -= state->telemetry.attitude_actual.Yaw;
393 
394  uint8_t chr = _ARROWS + (0xf & (((uint8_t) (home_dir / 360.0f * 16.0f)) * 2));
395  PIOS_MAX7456_put(state->dev, x, y, chr, 0);
396  PIOS_MAX7456_put(state->dev, x + 1, y, chr + 1, 0);
397  }
398 }
399 
400 STD_PANEL(HEADING, 6, "%d%c", (int)(round(state->telemetry.attitude_actual.Yaw)+360) % 360, CHAROSD_CHAR_DEG);
401 
402 /* Callsign */
403 STD_PANEL(CALLSIGN, 11, "%s", state->custom_text);
404 
405 /* Temperature - XXX TODO */
406 STD_PANEL(TEMPERATURE, 9, "\xfd%.1f\x8a", /*XXX:telemetry::environment::temperature*/ 0.0);
407 
408 /* RSSI */
409 static void RSSI_update(charosd_state_t state, uint8_t x, uint8_t y)
410 {
411  const char _l0 [] = "\xe5\xe8\xe8";
412  const char _l1 [] = "\xe2\xe8\xe8";
413  const char _l2 [] = "\xe2\xe6\xe8";
414  const char _l3 [] = "\xe2\xe3\xe8";
415  const char _l4 [] = "\xe2\xe3\xe7";
416  const char _l5 [] = "\xe2\xe3\xe4";
417 
418  const char * const levels [] = { _l0, _l1, _l2, _l3, _l4, _l5 };
419 
420  uint8_t level = (state->telemetry.manual.rssi + 10) / 20;
421 
422  if (level == 0 && state->telemetry.manual.rssi > 0) level = 1;
423  if (level > 5) level = 5;
424 
425  PIOS_MAX7456_puts (state->dev, x, y, levels[level], 0);
426 }
427 
428 static void COMPASS_update(charosd_state_t state, uint8_t x, uint8_t y)
429 {
430  char buffer[12];
431  const uint8_t ruler [] = {
432  0xc2, 0xc0, 0xc1, 0xc0,
433  0xc4, 0xc0, 0xc1, 0xc0,
434  0xc3, 0xc0, 0xc1, 0xc0,
435  0xc5, 0xc0, 0xc1, 0xc0,
436  };
437 
438  const int8_t ruler_size = sizeof(ruler);
439 
440  int16_t offset = (int16_t)round(state->telemetry.attitude_actual.Yaw * ruler_size
441  / 360.0f) - (sizeof(buffer) - 1) / 2;
442  if (offset < 0) offset += ruler_size;
443  for (uint8_t i = 0; i < sizeof (buffer) - 1; i ++) {
444  buffer[i] = ruler[offset];
445  if (++offset >= ruler_size) offset = 0;
446  }
448 
449  PIOS_MAX7456_put(state->dev, x + (sizeof (buffer) - 1) / 2, y,
451  PIOS_MAX7456_puts(state->dev, x, y + 1, buffer, 0);
452 }
453 
454 /* Airspeed */
455 static void AIRSPEED_update(charosd_state_t state, uint8_t x, uint8_t y)
456 {
457  char buffer[7];
458  float airspeed;
459  AirspeedActualTrueAirspeedGet(&airspeed);
460  snprintf(buffer, sizeof(buffer), "\x88%d\x81", (int)(airspeed * 3.6f));
462  PIOS_MAX7456_puts(state->dev, x, y + 1, buffer, 0);
463 }
464 
465 
466 STD_PANEL(CROSSHAIR, 2, "%c", 0x0a);
467 
468 #define MAX_ALARM_LEN MAX7456_COLUMNS
469 
470 static void ALARMS_update(charosd_state_t state, uint8_t x, uint8_t y)
471 {
472  SystemAlarmsData alarm;
473  SystemAlarmsGet(&alarm);
474  char buffer[MAX_ALARM_LEN+1];
475 
476  uint8_t alarm_state;
477  AlarmString(&alarm, buffer, sizeof(buffer), false, &alarm_state);
478  PIOS_MAX7456_puts(state->dev, x, y, buffer, 0);
479 }
480 
481 #define declare_panel(__name, __req) [CHARONSCREENDISPLAYSETTINGS_PANELTYPE_ ## __name] = { \
482  __name ## _update, \
483  __req }
484 
485 const panel_t panels [CHARONSCREENDISPLAYSETTINGS_PANELTYPE_MAXOPTVAL+1] = {
486  declare_panel(AIRSPEED, HAS_PITOT),
487  declare_panel(ALTITUDE, HAS_ALT),
488  declare_panel(ARMEDFLAG, 0),
489  declare_panel(BATTERYVOLT, HAS_BATT),
490  declare_panel(BATTERYCURRENT, HAS_BATT),
491  declare_panel(BATTERYCONSUMED, HAS_BATT),
492  declare_panel(CALLSIGN, 0),
493  declare_panel(CLIMB, HAS_ALT),
494  declare_panel(COMPASS, HAS_COMPASS),
495  declare_panel(FLIGHTMODE, 0),
496  declare_panel(FLIGHTTIME, 0),
497  declare_panel(GROUNDSPEED, HAS_GPS),
498  declare_panel(GPS, HAS_GPS),
499  declare_panel(HEADING, HAS_COMPASS),
500  declare_panel(HOMEDISTANCE, HAS_NAV),
501  declare_panel(HOMEDIRECTION, HAS_NAV),
502  declare_panel(HORIZON, 0),
503  declare_panel(LATITUDE, HAS_GPS),
504  declare_panel(LONGITUDE, HAS_GPS),
505  declare_panel(PITCH, 0),
506  declare_panel(ROLL, 0),
507  declare_panel(RSSIFLAG, HAS_RSSI),
508  declare_panel(RSSI, HAS_RSSI),
509  declare_panel(TEMPERATURE, HAS_TEMP),
510  declare_panel(THROTTLE, 0),
511  declare_panel(CROSSHAIR, 0),
512  declare_panel(ALARMS, 0),
513 };
514 
515 const uint8_t count = sizeof (panels) / sizeof (panel_t);
516 
#define _PAN_HORZ_LINE
Definition: panel.c:299
static void ARMEDFLAG_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:235
const panel_t panels[CHARONSCREENDISPLAYSETTINGS_PANELTYPE_MAXOPTVAL+1]
Definition: panel.c:485
#define PANEL_HORIZON_WIDTH
Definition: panel.c:296
uint16_t middle
Definition: msp_messages.h:98
#define CHAROSD_CHAR_KM
Definition: charosd.h:132
#define MAX_ALARM_LEN
Definition: panel.c:468
telemetry_t telemetry
Definition: charosd.h:68
#define _ARROWS
Definition: panel.c:384
const uint8_t count
Definition: panel.c:515
static void ALARMS_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:470
struct telemetry_t::@9 system
#define _PAN_CLIMB_SYMB
Definition: panel.c:137
static void RSSI_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:409
int sprintf(char *out, const char *format,...)
static void RSSIFLAG_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:360
struct telemetry_t::@7 manual
VelocityActualData velocity_actual
Definition: charosd.h:50
max7456_dev_t dev
Definition: charosd.h:66
AttitudeActualData attitude_actual
Definition: charosd.h:48
struct _msp_pid_item roll
Definition: msp_messages.h:96
#define _PAN_HORZ_VRES
Definition: panel.c:303
#define HAS_NAV
Definition: charosd.h:90
GPSPositionData gps_position
Definition: charosd.h:51
static void AIRSPEED_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:455
static void draw_rect(charosd_state_t state, uint8_t l, uint8_t t, uint8_t w, uint8_t h, bool filled, uint8_t attr)
Definition: panel.c:78
#define HAS_RSSI
Definition: charosd.h:89
static void HOMEDIRECTION_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:386
FlightStatusArmedOptions arm_status
Definition: charosd.h:57
#define ERR_STR
Definition: panel.c:117
static void FLIGHTTIME_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:242
#define CHAROSD_CHAR_M
Definition: charosd.h:134
#define MAX7456_ATTR_INVERT
Definition: pios_max7456.h:44
uint32_t flight_time
Definition: charosd.h:61
void PIOS_MAX7456_put(max7456_dev_t dev, uint8_t col, uint8_t row, uint8_t chr, uint8_t attr)
Sets a position of character memory.
PositionActualData position_actual
Definition: charosd.h:49
#define _PAN_GPS_3D
Definition: panel.c:272
#define HAS_PITOT
Definition: charosd.h:86
static void HOMEDISTANCE_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:367
#define CHAROSD_CHAR_DEG
Definition: charosd.h:169
const char _horz_center[PANEL_HORIZON_WIDTH+1]
Definition: panel.c:309
void PIOS_MAX7456_puts(max7456_dev_t dev, uint8_t col, uint8_t row, const char *s, uint8_t attr)
Sets a string into character memory.
#define HAS_BATT
Definition: charosd.h:85
#define _PAN_HORZ_TOP
Definition: panel.c:300
#define MAX(a, b)
Definition: misc_math.h:40
#define PANEL_HORIZON_HEIGHT
Definition: panel.c:297
const char _horz_line[PANEL_HORIZON_WIDTH+1]
Definition: panel.c:308
struct telemetry_t::@8 flight_status
#define _PAN_GPS_2D
Definition: panel.c:271
#define HAS_GPS
Definition: charosd.h:84
uint8_t i
Definition: msp_messages.h:97
enum channel_mode mode
Definition: pios_servo.c:58
static void CLIMB_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:139
struct _msp_pid_item level
Definition: msp_messages.h:103
#define _PAN_HORZ_TOTAL_LINES
Definition: panel.c:306
int16_t rssi
Definition: charosd.h:53
#define _PAN_HORZ_INT_WIDTH
Definition: panel.c:304
#define HAS_ALT
Definition: charosd.h:87
#define terminate_buffer()
Definition: panel.c:119
static void FLIGHTMODE_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:159
uint32_t offset
Definition: uavtalk_priv.h:51
#define HAS_SENSOR(available, required)
Definition: charosd.h:93
tuple f
Definition: px_mkfw.py:81
#define _PAN_HORZ_LINES
Definition: panel.c:305
void HORIZON_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:311
static void GPS_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:274
#define declare_panel(__name, __req)
Definition: panel.c:481
#define HAS_TEMP
Definition: charosd.h:88
Includes PiOS and core architecture components.
static void COMPASS_update(charosd_state_t state, uint8_t x, uint8_t y)
Definition: panel.c:428
int snprintf(char *buf, size_t count, const char *format,...)
static float pythag(float a, float b)
Definition: panel.c:69
int32_t AlarmString(SystemAlarmsData *alarm, char *buf, size_t buflen, bool blink, uint8_t *state)
#define HAS_COMPASS
Definition: charosd.h:91
SharedDefsFlightModeOptions mode
Definition: charosd.h:58
#define STD_PANEL(__name, bs, fmt,...)
Definition: panel.c:129
#define MAX7456_ATTR_BLINK
Definition: pios_max7456.h:45
#define CHAROSD_CHAR_COMPASS_INTERNAL
Definition: charosd.h:189
#define _PAN_HORZ_CHAR_LINES
Definition: panel.c:302
uint16_t min
Definition: msp_messages.h:96
enum arena_state state