dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
UAVOMSPBridge.c
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  *
30  * Additional note on redistribution: The copyright and license notices above
31  * must be maintained in each individual source file that is a derivative work
32  * of this source file; otherwise redistribution is prohibited.
33  */
34 
35 #include "openpilot.h"
36 #include "misc_math.h"
37 #include "physical_constants.h"
38 #include "pios_thread.h"
39 #include "pios_sensors.h"
40 #include "pios_modules.h"
41 #include <pios_hal.h>
42 
43 #include "actuatorsettings.h"
44 #include "actuatordesired.h"
45 #include "airspeedactual.h"
46 #include "attitudeactual.h"
47 #include "baroaltitude.h"
48 #include "flightbatterysettings.h"
49 #include "flightbatterystate.h"
50 #include "flightstatus.h"
51 #include "gpsposition.h"
52 #include "homelocation.h"
53 #include "manualcontrolcommand.h"
54 #include "modulesettings.h"
55 #include "positionactual.h"
56 #include "stabilizationsettings.h"
57 #include "systemalarms.h"
58 #include "systemsettings.h"
59 #include "systemstats.h"
60 
61 
62 #if defined(PIOS_INCLUDE_MSP_BRIDGE)
63 
64 #define MSP_SENSOR_ACC 1
65 #define MSP_SENSOR_BARO 2
66 #define MSP_SENSOR_MAG 4
67 #define MSP_SENSOR_GPS 8
68 
69 #define MSP_API_VERSION 1
70 #define MSP_FC_VARIANT 2
71 #define MSP_FC_VERSION 3
72 #define MSP_BOARD_INFO 4
73 #define MSP_BUILD_INFO2 5 // clean/betaflight extension :( (MSP_BUILD_INFO had room for a 28-bit hash + up to 36-bit time already!)
74 #define MSP_NAME 10
75 #define MSP_FEATURE 36
76 #define MSP_CONFIG 66 // baseflight
77 #define MSP_BUILD_INFO 69 // baseflight
78 #define MSP_IDENT 100 // multitype + multiwii version + protocol version + capability variable
79 #define MSP_STATUS 101 // cycletime & errors_count & sensor present & box activation & current setting number
80 #define MSP_RAW_IMU 102 // 9 DOF
81 #define MSP_SERVO 103 // 8 servos
82 #define MSP_MOTOR 104 // 8 motors
83 #define MSP_RC 105 // 8 rc chan and more
84 #define MSP_RAW_GPS 106 // fix, numsat, lat, lon, alt, speed, ground course
85 #define MSP_COMP_GPS 107 // distance home, direction home
86 #define MSP_ATTITUDE 108 // 2 angles 1 heading
87 #define MSP_ALTITUDE 109 // altitude, variometer
88 #define MSP_ANALOG 110 // vbat, powermetersum, rssi if available on RX
89 #define MSP_RC_TUNING 111 // rc rate, rc expo, rollpitch rate, yaw rate, dyn throttle PID
90 #define MSP_PID 112 // P I D coeff (9 are used currently)
91 #define MSP_BOX 113 // BOX setup (number is dependant of your setup)
92 #define MSP_MISC 114 // powermeter trig
93 #define MSP_MOTOR_PINS 115 // which pins are in use for motors & servos, for GUI
94 #define MSP_BOXNAMES 116 // the aux switch names
95 #define MSP_PIDNAMES 117 // the PID names
96 #define MSP_BOXIDS 119 // get the permanent IDs associated to BOXes
97 #define MSP_NAV_STATUS 121 // Returns navigation status
98 #define MSP_CELLS 130 // FrSky SPort Telemtry
99 #define MSP_UID 160 // Hardware serial number
100 #define MSP_SET_PID 202
101 #define MSP_ALARMS 242 // Alarm request
102 #define MSP_SET_4WAY_IF 245 // Sets ESC serial interface
103 
104 #define MSP_PROTOCOL_VERSION 0
105 #define MSP_API_VERSION_MAJOR 1
106 #define MSP_API_VERSION_MINOR 31 // Matches 3.1.6
107 
108 enum msp_handler {
109  MSP_HANDLER_MSP = 0,
110  MSP_HANDLER_IDLE,
111  MSP_HANDLER_4WIF
112 };
113 
114 enum msp_vehicle_type {
115  MSP_MULTITYPE_TRI = 1,
116  MSP_MULTITYPE_QUADP = 2,
117  MSP_MULTITYPE_QUADX = 3,
118  MSP_MULTITYPE_BI = 4,
119  MSP_MULTITYPE_GIMBAL = 5,
120  MSP_MULTITYPE_Y6 = 6,
121  MSP_MULTITYPE_HEX6 = 7,
122  MSP_MULTITYPE_FLYING_WING = 8,
123  MSP_MULTITYPE_Y4 = 9,
124  MSP_MULTITYPE_HEX6X = 10,
125  MSP_MULTITYPE_OCTOX8 = 11,
126  MSP_MULTITYPE_OCTOFLATP = 12,
127  MSP_MULTITYPE_OCTOFLATX = 13,
128  MSP_MULTITYPE_AIRPLANE = 14,
129  MSP_MULTITYPE_HELI_120_CCPM = 15,
130  MSP_MULTITYPE_HELI_90_DEG = 16,
131  MSP_MULTITYPE_VTAIL4 = 17,
132  MSP_MULTITYPE_HEX6H = 18,
133  MSP_MULTITYPE_PPM_TO_SERVO = 19,
134  MSP_MULTITYPE_DUALCOPTER = 20,
135  MSP_MULTITYPE_SINGLECOPTER = 21,
136  MSP_MULTITYPE_ATAIL4 = 22,
137  MSP_MULTITYPE_CUSTOM = 23,
138  MSP_MULTITYPE_CUSTOM_PLANE = 24,
139 };
140 
141 typedef enum {
142  MSP_BOX_ARM,
143  MSP_BOX_ANGLE,
144  MSP_BOX_HORIZON,
145  MSP_BOX_BARO,
146  MSP_BOX_VARIO,
147  MSP_BOX_MAG,
148  MSP_BOX_GPSHOME,
149  MSP_BOX_GPSHOLD,
150  MSP_BOX_LAST,
151 } msp_box_t;
152 
153 const static struct {
154  msp_box_t mode;
155  uint8_t mwboxid;
156  FlightStatusFlightModeOptions tlmode;
157 } msp_boxes[] = {
158  { MSP_BOX_ARM, 0, 0 },
159  { MSP_BOX_ANGLE, 1, FLIGHTSTATUS_FLIGHTMODE_LEVELING},
160  { MSP_BOX_HORIZON, 2, FLIGHTSTATUS_FLIGHTMODE_HORIZON},
161  { MSP_BOX_BARO, 3, FLIGHTSTATUS_FLIGHTMODE_ALTITUDEHOLD},
162  { MSP_BOX_VARIO, 4, 0},
163  { MSP_BOX_MAG, 5, 0},
164  { MSP_BOX_GPSHOME, 10, FLIGHTSTATUS_FLIGHTMODE_RETURNTOHOME},
165  { MSP_BOX_GPSHOLD, 11, FLIGHTSTATUS_FLIGHTMODE_POSITIONHOLD},
166  { MSP_BOX_LAST, 0xff, 0},
167 };
168 
169 typedef enum {
170  MSP_IDLE,
171  MSP_HEADER_START,
172  MSP_HEADER_M,
173  MSP_HEADER_SIZE,
174  MSP_HEADER_CMD,
175  MSP_FILLBUF,
176  MSP_CHECKSUM,
177  MSP_DISCARD,
178  MSP_MAYBE_UAVTALK2,
179  MSP_MAYBE_UAVTALK3,
180  MSP_MAYBE_UAVTALK4,
181 } msp_state;
182 
183 typedef enum __attribute__ ((__packed__)) {
184  PROTOCOL_SIMONK = 0,
185  PROTOCOL_BLHELI = 1,
186  PROTOCOL_KISS = 2,
187  PROTOCOL_KISSALL = 3,
188  PROTOCOL_CASTLE = 4,
189  PROTOCOL_4WAY = 0xff,
190 } msp_esc_protocol;
191 
192 struct msp_cmddata_escserial {
193  msp_esc_protocol protocol;
194  uint8_t esc_num;
195 };
196 
197 struct msp_bridge {
198  uintptr_t com;
199 
200  enum msp_handler handler;
202  uint8_t cmd_size;
203  uint8_t cmd_id;
204  uint8_t cmd_i;
205  uint8_t checksum;
206  union {
207  uint8_t data[128];
208  // Specific packed data structures go here.
209  struct msp_cmddata_escserial escserial;
210  } cmd_data;
211 };
212 
213 #if defined(PIOS_MSP_STACK_SIZE)
214 #define STACK_SIZE_BYTES PIOS_MSP_STACK_SIZE
215 #else
216 #define STACK_SIZE_BYTES 1500
217 #endif
218 #define TASK_PRIORITY PIOS_THREAD_PRIO_LOW
219 
220 #define MAX_ALARM_LEN 30
221 
222 #define BOOT_DISPLAY_TIME_MS (10*1000)
223 
224 static bool module_enabled = false;
225 extern uintptr_t pios_com_msp_id;
226 static struct msp_bridge *msp;
227 static int32_t uavoMSPBridgeInitialize(void);
228 static void uavoMSPBridgeTask(void *parameters);
229 void esc4wayProcess(void *mspPort);
230 
231 
232 static void msp_send_error(struct msp_bridge *m, uint8_t cmd)
233 {
234  uint8_t buf[6];
235 
236  buf[0] = '$';
237  buf[1] = 'M';
238  buf[2] = '!'; /* original multiwii spec says '|', everyone uses '!' */
239  buf[3] = 0;
240  buf[4] = cmd;
241  buf[5] = cmd; // Checksum == cmd
242 
243  PIOS_COM_SendBuffer(m->com, buf, sizeof(buf));
244 }
245 
246 static void msp_send(struct msp_bridge *m, uint8_t cmd, const uint8_t *data, size_t len)
247 {
248  uint8_t buf[5];
249  uint8_t cs = (uint8_t)(len) ^ cmd;
250 
251  buf[0] = '$';
252  buf[1] = 'M';
253  buf[2] = '>';
254  buf[3] = (uint8_t)(len);
255  buf[4] = cmd;
256 
257  PIOS_COM_SendBuffer(m->com, buf, sizeof(buf));
258  PIOS_COM_SendBuffer(m->com, data, len);
259 
260  for (int i = 0; i < len; i++) {
261  cs ^= data[i];
262  }
263  cs ^= 0;
264 
265  buf[0] = cs;
266  PIOS_COM_SendBuffer(m->com, buf, 1);
267 }
268 
269 static msp_state msp_state_size(struct msp_bridge *m, uint8_t b)
270 {
271  m->cmd_size = b;
272  m->checksum = b;
273  return MSP_HEADER_CMD;
274 }
275 
276 static msp_state msp_state_cmd(struct msp_bridge *m, uint8_t b)
277 {
278  m->cmd_i = 0;
279  m->cmd_id = b;
280  m->checksum ^= m->cmd_id;
281 
282  if (m->cmd_size > sizeof(m->cmd_data)) {
283  // Too large a body. Let's ignore it.
284  return MSP_DISCARD;
285  }
286 
287  return m->cmd_size == 0 ? MSP_CHECKSUM : MSP_FILLBUF;
288 }
289 
290 static msp_state msp_state_fill_buf(struct msp_bridge *m, uint8_t b)
291 {
292  m->cmd_data.data[m->cmd_i++] = b;
293  m->checksum ^= b;
294  return m->cmd_i == m->cmd_size ? MSP_CHECKSUM : MSP_FILLBUF;
295 }
296 
297 static void msp_send_name(struct msp_bridge *m)
298 {
299  const char hardcoded_name[] = "dRonin";
300 
301  msp_send(m, MSP_NAME, (uint8_t *) hardcoded_name, strlen(hardcoded_name));
302 }
303 
304 static void msp_send_motor(struct msp_bridge *m)
305 {
306  union {
307  uint8_t buf[0];
308  uint16_t mspeed[8];
309  } data;
310 
311  /* Tell me lies */
312  memset(&data, 0, sizeof(data));
313 
314  msp_send(m, MSP_MOTOR, data.buf, sizeof(data));
315 }
316 
317 static void msp_send_feature(struct msp_bridge *m)
318 {
319  union {
320  uint8_t buf[0];
321  uint32_t features;
322  } data;
323 
324 #define FEATURE_TELEMETRY (1 << 10)
325  data.features = FEATURE_TELEMETRY;
326 
327  msp_send(m, MSP_FEATURE, data.buf, sizeof(data));
328 }
329 
330 static void msp_send_misc(struct msp_bridge *m)
331 {
332  union {
333  uint8_t buf[0];
334  struct {
335  uint16_t mid_rc;
336  uint16_t min_throt;
337  uint16_t max_throt;
338  uint16_t min_command;
339  uint8_t gps[3];
340  uint8_t misc_cfg[3];
341  uint16_t compass;
342  uint8_t battery[4];
343  } fc_misc;
344  } data;
345 
346  /* Tell me sweet little lies */
347  memset(&data, 0, sizeof(data));
348 
349  data.fc_misc.mid_rc = 1500;
350  data.fc_misc.min_command = 1000;
351  data.fc_misc.min_throt = 1150;
352  data.fc_misc.max_throt = 2000; // 1850 in BF...
353 
354  msp_send(m, MSP_MISC, data.buf, sizeof(data));
355 }
356 
357 static void msp_send_fc_version(struct msp_bridge *m)
358 {
359  union {
360  uint8_t buf[0];
361  struct {
362  uint8_t major;
363  uint8_t minor;
364  uint8_t patch;
365  } fc_ver;
366  } data;
367 
368  /* Not very meaningful to us */
369  data.fc_ver.major = 1;
370  data.fc_ver.minor = 0;
371  data.fc_ver.patch = 0;
372 
373  msp_send(m, MSP_FC_VERSION, data.buf, sizeof(data));
374 }
375 
376 static void msp_send_fc_variant(struct msp_bridge *m)
377 {
378  union {
379  uint8_t buf[0];
380  struct {
381  char name[4];
382  } var;
383  } data;
384 
385  memset(&data, 0, sizeof(data));
386 
387  memcpy(data.var.name, "DRON", 4);
388 
389  msp_send(m, MSP_FC_VARIANT, data.buf, sizeof(data));
390 }
391 
392 static void msp_send_board_info(struct msp_bridge *m)
393 {
394  union {
395  uint8_t buf[0];
396  struct __attribute__((packed)) {
397  char name[4];
398  uint16_t revision;
399  } board;
400  } data;
401 
402  memset(&data, 0, sizeof(data));
403 
404  memcpy(data.board.name, DRONIN_TARGET, MIN(4, strlen(DRONIN_TARGET)));
405 
406  msp_send(m, MSP_BOARD_INFO, data.buf, sizeof(data));
407 }
408 
409 static void msp_send_config(struct msp_bridge *m)
410 {
411  union {
412  uint8_t buf[0];
413  struct {
414  uint8_t mixer_config;
415  uint32_t features;
416  uint8_t serial_rx;
417  uint16_t align_roll;
418  uint16_t align_pitch;
419  uint16_t align_yaw;
420  uint16_t current_scale;
421  uint16_t current_offset;
422  uint16_t motor_pwm_rate;
423  uint8_t roll_pitch_rate[2];
424  uint8_t power_adc_channel;
425  uint8_t small_angle;
426  uint16_t looptime;
427  uint8_t locked_in;
428  } __attribute__((packed)) config;
429  } data;
430 
431  memset(&data, 0, sizeof(data));
432 
433  data.config.locked_in = 1;
434 
435  msp_send(m, MSP_CONFIG, data.buf, sizeof(data));
436 }
437 
438 static void msp_send_build_info(struct msp_bridge *m)
439 {
440  union {
441  uint8_t buf[0];
442  struct __attribute__((packed)) {
443  char date[11];
444  uint32_t _future[2];
445  } build;
446  } data;
447 
448  memset(&data, 0, sizeof(data));
449 
450  // XXX: Not impl
451 
452  msp_send(m, MSP_BUILD_INFO, data.buf, sizeof(data));
453 }
454 
455 static void msp_send_build_info_cf(struct msp_bridge *m)
456 {
457  union {
458  uint8_t buf[0];
459  struct __attribute__((packed)) {
460  char date[11];
461  char time[8];
462  char short_rev[7];
463  } build;
464  } data;
465 
466  memset(&data, 0, sizeof(data));
467 
468  // XXX: Not impl
469 
470  msp_send(m, MSP_BUILD_INFO2, data.buf, sizeof(data));
471 }
472 
473 DONT_BUILD_IF(PIOS_SYS_SERIAL_NUM_BINARY_LEN != 4*3, SerialNumberAssumption);
474 
475 static void msp_send_uid(struct msp_bridge *m)
476 {
477  union {
478  uint8_t buf[0];
479  struct {
480  uint8_t serial[PIOS_SYS_SERIAL_NUM_BINARY_LEN];
481  } uid;
482  } data;
483 
484  PIOS_SYS_SerialNumberGetBinary(data.uid.serial);
485 
486  msp_send(m, MSP_UID, data.buf, sizeof(data));
487 }
488 
489 static void msp_send_api_version(struct msp_bridge *m)
490 {
491  union {
492  uint8_t buf[0];
493  struct {
494  uint8_t protocol_ver;
495  uint8_t api_version_major;
496  uint8_t api_version_minor;
497  } ident;
498  } data;
499 
500  data.ident.protocol_ver = MSP_PROTOCOL_VERSION;
501  data.ident.api_version_major = MSP_API_VERSION_MAJOR;
502  data.ident.api_version_minor = MSP_API_VERSION_MINOR;
503 
504  msp_send(m, MSP_API_VERSION, data.buf, sizeof(data));
505 }
506 
507 static void msp_send_attitude(struct msp_bridge *m)
508 {
509  union {
510  uint8_t buf[0];
511  struct {
512  int16_t x;
513  int16_t y;
514  int16_t h;
515  } att;
516  } data;
517  AttitudeActualData attActual;
518 
519  AttitudeActualGet(&attActual);
520 
521  // Roll and Pitch are in 10ths of a degree.
522  data.att.x = attActual.Roll * 10;
523  data.att.y = attActual.Pitch * -10;
524  // Yaw is just -180 -> 180
525  data.att.h = attActual.Yaw;
526 
527  msp_send(m, MSP_ATTITUDE, data.buf, sizeof(data));
528 }
529 
530 static void msp_send_ident(struct msp_bridge *m)
531 {
532  union {
533  uint8_t buf[0];
534  struct {
535  uint8_t multiwii_version;
536  uint8_t vehicle_type;
537  uint8_t msp_version;
538  uint32_t capabilities;
539  } __attribute__((packed)) ident;
540  } data;
541 
542  data.ident.multiwii_version = 255;
543  data.ident.msp_version = 4;
544  data.ident.capabilities = 0x80000004; /* 32-bit | DYNBALANCE */
545 
546  uint8_t type;
547  SystemSettingsAirframeTypeGet(&type);
548  switch (type) {
549  case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWING:
550  data.ident.vehicle_type = MSP_MULTITYPE_AIRPLANE;
551  break;
552  case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGELEVON:
553  data.ident.vehicle_type = MSP_MULTITYPE_FLYING_WING;
554  break;
555  case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGVTAIL:
556  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM_PLANE;
557  break;
558  case SYSTEMSETTINGS_AIRFRAMETYPE_VTOL:
559  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
560  break;
561  case SYSTEMSETTINGS_AIRFRAMETYPE_HELICP:
562  data.ident.vehicle_type = MSP_MULTITYPE_HELI_120_CCPM; /* maybe */
563  break;
564  case SYSTEMSETTINGS_AIRFRAMETYPE_QUADX:
565  data.ident.vehicle_type = MSP_MULTITYPE_QUADX;
566  break;
567  case SYSTEMSETTINGS_AIRFRAMETYPE_QUADP:
568  data.ident.vehicle_type = MSP_MULTITYPE_QUADP;
569  break;
570  case SYSTEMSETTINGS_AIRFRAMETYPE_HEXA:
571  data.ident.vehicle_type = MSP_MULTITYPE_HEX6H;
572  break;
573  case SYSTEMSETTINGS_AIRFRAMETYPE_OCTO:
574  data.ident.vehicle_type = MSP_MULTITYPE_OCTOFLATX; /* ? */
575  break;
576  case SYSTEMSETTINGS_AIRFRAMETYPE_CUSTOM:
577  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
578  break;
579  case SYSTEMSETTINGS_AIRFRAMETYPE_HEXAX:
580  data.ident.vehicle_type = MSP_MULTITYPE_HEX6X;
581  break;
582  case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOV:
583  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
584  break;
585  case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOCOAXP:
586  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
587  break;
588  case SYSTEMSETTINGS_AIRFRAMETYPE_OCTOCOAXX:
589  data.ident.vehicle_type = MSP_MULTITYPE_OCTOX8; /* ? */
590  break;
591  case SYSTEMSETTINGS_AIRFRAMETYPE_HEXACOAX:
592  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
593  break;
594  case SYSTEMSETTINGS_AIRFRAMETYPE_TRI:
595  data.ident.vehicle_type = MSP_MULTITYPE_TRI;
596  break;
597  case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLECAR:
598  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
599  break;
600  case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL:
601  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
602  break;
603  case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE:
604  data.ident.vehicle_type = MSP_MULTITYPE_CUSTOM;
605  break;
606  }
607 
608  msp_send(m, MSP_IDENT, data.buf, sizeof(data));
609 }
610 
611 static void msp_send_rc_tuning(struct msp_bridge *m)
612 {
613  union {
614  uint8_t buf[0];
615  struct {
616  uint8_t rc_rate;
617  uint8_t rx_expo;
618  uint8_t _roll_pitch_rate;
619  uint8_t yaw_rate;
620  uint8_t dyn_throttle_pid;
621  uint8_t throttle_mid;
622  uint8_t throttle_expo;
623  } __attribute__((packed)) tune;
624  } data;
625 
626  memset(&data, 0, sizeof(data));
627 
628  msp_send(m, MSP_RC_TUNING, data.buf, sizeof(data));
629 }
630 
631 #define PID_SCALE_KP 10000.0f
632 #define PID_SCALE_KI 1000.0f
633 #define PID_SCALE_KD 1000000.0f
634 
635 static void msp_set_pid(struct msp_bridge *m)
636 {
637  struct set_pid {
638  struct {
639  uint8_t P;
640  uint8_t I;
641  uint8_t D;
642  } __attribute__((packed)) axis[10];
643  } __attribute__((packed));
644 
645  struct set_pid *data = (struct set_pid *)m->cmd_data.data;
646 
647  uint8_t armed;
648  FlightStatusArmedGet(&armed);
649 
650  if (sizeof(*data) > m->cmd_i || armed != FLIGHTSTATUS_ARMED_DISARMED)
651  msp_send_error(m, MSP_SET_PID);
652 
653  StabilizationSettingsData stab;
654  StabilizationSettingsGet(&stab);
655 
656  #define SCALE_PID_DR(axisnum, pid) ((float)data->axis[axisnum].pid / PID_SCALE_K##pid)
657 
658  stab.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KP] = SCALE_PID_DR(0, P);
659  stab.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KI] = SCALE_PID_DR(0, I);
660  stab.RollRatePID[STABILIZATIONSETTINGS_ROLLRATEPID_KD] = SCALE_PID_DR(0, D);
661  stab.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KP] = SCALE_PID_DR(1, P);
662  stab.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KI] = SCALE_PID_DR(1, I);
663  stab.PitchRatePID[STABILIZATIONSETTINGS_PITCHRATEPID_KD] = SCALE_PID_DR(1, D);
664  stab.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KP] = SCALE_PID_DR(2, P);
665  stab.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KI] = SCALE_PID_DR(2, I);
666  stab.YawRatePID[STABILIZATIONSETTINGS_YAWRATEPID_KD] = SCALE_PID_DR(2, D);
667 
668  StabilizationSettingsSet(&stab);
669 
670  msp_send(m, MSP_SET_PID, NULL, 0);
671 }
672 
673 static void msp_send_pid(struct msp_bridge *m)
674 {
675  union {
676  uint8_t buf[0];
677  struct {
678  struct {
679  uint8_t p;
680  uint8_t i;
681  uint8_t d;
682  } __attribute__((packed)) axis[10];
683  } __attribute__((packed)) pid;
684  } data;
685 
686  memset(&data, 0, sizeof(data));
687 
688  StabilizationSettingsData stab;
689  StabilizationSettingsGet(&stab);
690 
691  #define SCALE_PID_MW(axis, axisu, pid) bound_min_max( \
692  stab.axis##RatePID[STABILIZATIONSETTINGS_##axisu##RATEPID_K##pid] \
693  * PID_SCALE_K##pid, 0.0f, 255.0f)
694 
695  data.pid.axis[0].p = SCALE_PID_MW(Roll, ROLL, P);
696  data.pid.axis[0].i = SCALE_PID_MW(Roll, ROLL, I);
697  data.pid.axis[0].d = SCALE_PID_MW(Roll, ROLL, D);
698  data.pid.axis[1].p = SCALE_PID_MW(Pitch, PITCH, P);
699  data.pid.axis[1].i = SCALE_PID_MW(Pitch, PITCH, I);
700  data.pid.axis[1].d = SCALE_PID_MW(Pitch, PITCH, D);
701  data.pid.axis[2].p = SCALE_PID_MW(Yaw, YAW, P);
702  data.pid.axis[2].i = SCALE_PID_MW(Yaw, YAW, I);
703  data.pid.axis[2].d = SCALE_PID_MW(Yaw, YAW, D);
704 
705  msp_send(m, MSP_PID, data.buf, sizeof(data));
706 }
707 
708 static void msp_send_pid_names(struct msp_bridge *m)
709 {
710  const char names[] = "ROLL;PITCH;YAW;";
711  msp_send(m, MSP_PIDNAMES, (const uint8_t *)names, sizeof(names));
712 }
713 
714 static void msp_send_status(struct msp_bridge *m)
715 {
716  union {
717  uint8_t buf[0];
718  struct {
719  uint16_t cycleTime;
720  uint16_t i2cErrors;
721  uint16_t sensors;
722  uint32_t flags;
723  uint8_t setting;
724  } __attribute__((packed)) status;
725  } data;
726 
727  float cycle_time;
728  ActuatorDesiredUpdateTimeGet(&cycle_time);
729  data.status.cycleTime = cycle_time * 1000;
730 
731  data.status.i2cErrors = 0;
732 
733  GPSPositionData gpsData = {};
734 
735  if (GPSPositionHandle() != NULL)
736  GPSPositionGet(&gpsData);
737 
738  data.status.sensors = (PIOS_SENSORS_IsRegistered(PIOS_SENSOR_ACCEL) ? MSP_SENSOR_ACC : 0) |
739  (PIOS_SENSORS_IsRegistered(PIOS_SENSOR_BARO) ? MSP_SENSOR_BARO : 0) |
740  (PIOS_SENSORS_IsRegistered(PIOS_SENSOR_MAG) ? MSP_SENSOR_MAG : 0) |
741  (gpsData.Status != GPSPOSITION_STATUS_NOGPS ? MSP_SENSOR_GPS : 0);
742 
743  data.status.flags = 0;
744  data.status.setting = 0;
745 
746  if (FlightStatusHandle() != NULL) {
747  FlightStatusData flight_status;
748  FlightStatusGet(&flight_status);
749 
750  data.status.flags = flight_status.Armed == FLIGHTSTATUS_ARMED_ARMED;
751 
752  for (int i = 1; msp_boxes[i].mode != MSP_BOX_LAST; i++) {
753  if (flight_status.FlightMode == msp_boxes[i].tlmode) {
754  data.status.flags |= (1 << i);
755  }
756  }
757  }
758 
759  msp_send(m, MSP_STATUS, data.buf, sizeof(data));
760 }
761 
762 static void msp_send_analog(struct msp_bridge *m)
763 {
764  union {
765  uint8_t buf[0];
766  struct {
767  uint8_t vbat;
768  uint16_t powerMeterSum;
769  uint16_t rssi;
770  uint16_t current;
771  } __attribute__((packed)) status;
772  } data;
773  data.status.powerMeterSum = 0;
774 
775  FlightBatterySettingsData batSettings = {};
776  FlightBatteryStateData batState = {};
777 
778  if (FlightBatteryStateHandle() != NULL)
779  FlightBatteryStateGet(&batState);
780  if (FlightBatterySettingsHandle() != NULL) {
781  FlightBatterySettingsGet(&batSettings);
782  }
783 
784  if (batSettings.VoltagePin != FLIGHTBATTERYSETTINGS_VOLTAGEPIN_NONE)
785  data.status.vbat = (uint8_t)lroundf(batState.Voltage * 10);
786 
787  if (batSettings.CurrentPin != FLIGHTBATTERYSETTINGS_CURRENTPIN_NONE) {
788  data.status.current = lroundf(batState.Current * 100);
789  data.status.powerMeterSum = lroundf(batState.ConsumedEnergy);
790  }
791 
792  ManualControlCommandData manualState;
793  ManualControlCommandGet(&manualState);
794 
795  // MSP RSSI's range is 0-1023
796  if (manualState.Rssi <= 0) {
797  data.status.rssi = 0;
798  } else if (manualState.Rssi >= 100) {
799  data.status.rssi = 1023;
800  } else {
801  data.status.rssi = manualState.Rssi * 10;
802  }
803 
804  msp_send(m, MSP_ANALOG, data.buf, sizeof(data));
805 }
806 
807 static void msp_send_raw_gps(struct msp_bridge *m)
808 {
809  union {
810  uint8_t buf[0];
811  struct {
812  uint8_t fix; // 0 or 1
813  uint8_t num_sat;
814  int32_t lat; // 1 / 10 000 000 deg
815  int32_t lon; // 1 / 10 000 000 deg
816  uint16_t alt; // meter
817  uint16_t speed; // cm/s
818  int16_t ground_course; // degree * 10
819  } __attribute__((packed)) raw_gps;
820  } data;
821 
822  GPSPositionData gps_data = {};
823 
824  if (GPSPositionHandle() != NULL)
825  {
826  GPSPositionGet(&gps_data);
827  data.raw_gps.fix = (gps_data.Status >= GPSPOSITION_STATUS_FIX2D ? 1 : 0); // Data will display on OSD if 2D fix or better
828  data.raw_gps.num_sat = gps_data.Satellites;
829  data.raw_gps.lat = gps_data.Latitude;
830  data.raw_gps.lon = gps_data.Longitude;
831  data.raw_gps.alt = (uint16_t)gps_data.Altitude;
832  data.raw_gps.speed = (uint16_t)(gps_data.Groundspeed * 100.0f);
833  data.raw_gps.ground_course = (int16_t)(gps_data.Heading * 10.0f);
834  }
835  else
836  {
837  data.raw_gps.fix = 0; // Data won't display on OSD
838  data.raw_gps.num_sat = 0;
839  data.raw_gps.lat = 0;
840  data.raw_gps.lon = 0;
841  data.raw_gps.alt = 0;
842  data.raw_gps.speed = 0;
843  data.raw_gps.ground_course = 0;
844  }
845 
846  msp_send(m, MSP_RAW_GPS, data.buf, sizeof(data));
847 }
848 
849 static void msp_send_comp_gps(struct msp_bridge *m)
850 {
851  union {
852  uint8_t buf[0];
853  struct {
854  uint16_t distance_to_home; // meter
855  int16_t direction_to_home; // degree [-180:180]
856  uint8_t home_position_valid; // 0 = Invalid, Dronin MSP specific
857  } __attribute__((packed)) comp_gps;
858  } data;
859 
860  GPSPositionData gps_data = {};
861  HomeLocationData home_data = {};
862 
863  if ((GPSPositionHandle() == NULL) || (HomeLocationHandle() == NULL))
864  {
865  data.comp_gps.distance_to_home = 0;
866  data.comp_gps.direction_to_home = 0;
867  data.comp_gps.home_position_valid = 0; // Home distance and direction will not display on OSD
868  }
869  else
870  {
871  GPSPositionGet(&gps_data);
872  HomeLocationGet(&home_data);
873 
874  if((gps_data.Status < GPSPOSITION_STATUS_FIX2D) || (home_data.Set == HOMELOCATION_SET_FALSE))
875  {
876  data.comp_gps.distance_to_home = 0;
877  data.comp_gps.direction_to_home = 0;
878  data.comp_gps.home_position_valid = 0; // Home distance and direction will not display on OSD
879  }
880  else
881  {
882  data.comp_gps.home_position_valid = 1; // Home distance and direction will display on OSD
883 
884  int32_t delta_lon = (home_data.Longitude - gps_data.Longitude); // degrees * 1e7
885  int32_t delta_lat = (home_data.Latitude - gps_data.Latitude ); // degrees * 1e7
886 
887  float delta_y = (float)delta_lon * WGS84_RADIUS_EARTH_KM * DEG2RAD; // KM * 1e7
888  float delta_x = (float)delta_lat * WGS84_RADIUS_EARTH_KM * DEG2RAD; // KM * 1e7
889 
890  delta_y *= cosf((float)home_data.Latitude * 1e-7f * (float)DEG2RAD); // Latitude compression correction
891 
892  data.comp_gps.distance_to_home = (uint16_t)(sqrtf(delta_x * delta_x + delta_y * delta_y) * 1e-4f); // meters
893 
894  if ((delta_lon == 0) && (delta_lat == 0))
895  data.comp_gps.direction_to_home = 0;
896  else
897  data.comp_gps.direction_to_home = (int16_t)(atan2f(delta_y, delta_x) * RAD2DEG); // degrees;
898  }
899  }
900 
901  msp_send(m, MSP_COMP_GPS, data.buf, sizeof(data));
902 }
903 
904 static void msp_send_altitude(struct msp_bridge *m)
905 {
906  union {
907  uint8_t buf[0];
908  struct {
909  int32_t alt; // cm
910  uint16_t vario; // cm/s
911  } __attribute__((packed)) baro;
912  } data;
913 
914  float tmp;
915 
916  if (PositionActualHandle() != NULL) {
917  PositionActualDownGet(&tmp);
918  tmp = -tmp;
919  } else {
920  return;
921  }
922 
923  data.baro.alt = (int32_t)roundf(tmp * 100.0f);
924 
925  msp_send(m, MSP_ALTITUDE, data.buf, sizeof(data));
926 }
927 
928 // Scale stick values whose input range is -1 to 1 to MSP's expected
929 // PWM range of 1000-2000.
930 static uint16_t msp_scale_rc(float percent) {
931  return percent*500 + 1500;
932 }
933 
934 // Throttle maps to 1100-1900 and a bit differently as -1 == 1000 and
935 // then jumps immediately to 0 -> 1 for the rest of the range. MWOSD
936 // can learn ranges as wide as they are sent, but defaults to
937 // 1100-1900 so the throttle indicator will vary for the same stick
938 // position unless we send it what it wants right away.
939 static uint16_t msp_scale_rc_thr(float percent) {
940  return percent <= 0 ? 1100 : percent*800 + 1100;
941 }
942 
943 // MSP RC order is Roll/Pitch/Yaw/Throttle/AUX1/AUX2/AUX3/AUX4
944 static void msp_send_channels(struct msp_bridge *m)
945 {
946  ManualControlCommandData manualState;
947  ManualControlCommandGet(&manualState);
948 
949  union {
950  uint8_t buf[0];
951  uint16_t channels[8];
952  } data = {
953  .channels = {
954  msp_scale_rc(manualState.Roll),
955  msp_scale_rc(manualState.Pitch * -1), // MW pitch is backwards
956  msp_scale_rc(manualState.Yaw),
957  msp_scale_rc_thr(manualState.Throttle),
958  msp_scale_rc(manualState.Accessory[0]),
959  msp_scale_rc(manualState.Accessory[1]),
960  msp_scale_rc(manualState.Accessory[2]),
961  1000, // no aux4
962  }
963  };
964 
965  msp_send(m, MSP_RC, data.buf, sizeof(data));
966 }
967 
968 static void msp_send_boxids(struct msp_bridge *m) {
969  uint8_t boxes[MSP_BOX_LAST];
970  int len = 0;
971 
972  for (int i = 0; msp_boxes[i].mode != MSP_BOX_LAST; i++) {
973  boxes[len++] = msp_boxes[i].mwboxid;
974  }
975  msp_send(m, MSP_BOXIDS, boxes, len);
976 }
977 
978 #ifdef PIOS_INCLUDE_4WAY
979 uint8_t esc4wayInit(void);
980 #endif
981 
982 static void msp_handle_4wif(struct msp_bridge *m) {
983  struct msp_cmddata_escserial *escserial = &m->cmd_data.escserial;
984 
985  uint8_t num_esc = 0;
986 
987  msp_esc_protocol protocol = PROTOCOL_4WAY;
988 
989  if (m->cmd_size >= sizeof(*escserial)) {
990  protocol = escserial->protocol;
991  }
992 
993  switch (protocol) {
994  case PROTOCOL_4WAY:
995 #ifdef PIOS_INCLUDE_4WAY
997 
1000  }
1001 
1002  num_esc = esc4wayInit();
1003  m->handler = MSP_HANDLER_4WIF;
1004 #endif
1005  break;
1006 
1007  case PROTOCOL_SIMONK:
1008  case PROTOCOL_BLHELI:
1009  case PROTOCOL_KISS:
1010  case PROTOCOL_KISSALL:
1011  case PROTOCOL_CASTLE:
1012  default:
1013  /* Unsupported protocol */
1014  break;
1015  }
1016 
1017  msp_send(m, MSP_SET_4WAY_IF, &num_esc, 1);
1018 }
1019 
1020 #define ALARM_OK 0
1021 #define ALARM_WARN 1
1022 #define ALARM_ERROR 2
1023 #define ALARM_CRIT 3
1024 
1025 static void msp_send_alarms(struct msp_bridge *m) {
1026  union {
1027  uint8_t buf[0];
1028  struct {
1029  uint8_t state;
1030  char msg[MAX_ALARM_LEN];
1031  } __attribute__((packed)) alarm;
1032  } data;
1033 
1034  SystemAlarmsData alarm;
1035  SystemAlarmsGet(&alarm);
1036 
1037  // Special case early boot times -- just report boot reason
1039  data.alarm.state = ALARM_CRIT;
1040  const char *boot_reason = AlarmBootReason(alarm.RebootCause);
1041  strncpy((char*)data.alarm.msg, boot_reason, MAX_ALARM_LEN);
1042  data.alarm.msg[MAX_ALARM_LEN-1] = '\0';
1043  msp_send(m, MSP_ALARMS, data.buf, strlen((char*)data.alarm.msg)+1);
1044  return;
1045  }
1046 
1047  uint8_t state;
1048  data.alarm.state = ALARM_OK;
1049  int32_t len = AlarmString(&alarm, data.alarm.msg,
1050  sizeof(data.alarm.msg), false, &state);
1051  switch (state) {
1052  case SYSTEMALARMS_ALARM_WARNING:
1053  data.alarm.state = ALARM_WARN;
1054  break;
1055  case SYSTEMALARMS_ALARM_ERROR:
1056  break;
1057  case SYSTEMALARMS_ALARM_CRITICAL:
1058  data.alarm.state = ALARM_CRIT;;
1059  }
1060 
1061  msp_send(m, MSP_ALARMS, data.buf, len+1);
1062 }
1063 
1064 static msp_state msp_state_checksum(struct msp_bridge *m, uint8_t b)
1065 {
1066  if ((m->checksum ^ b) != 0) {
1067  return MSP_IDLE;
1068  }
1069 
1070  // Respond to interesting things.
1071  switch (m->cmd_id) {
1072  case MSP_API_VERSION:
1073  msp_send_api_version(m);
1074  break;
1075  case MSP_FC_VERSION:
1076  msp_send_fc_version(m);
1077  break;
1078  case MSP_FC_VARIANT:
1079  msp_send_fc_variant(m);
1080  break;
1081  case MSP_BOARD_INFO:
1082  msp_send_board_info(m);
1083  break;
1084  case MSP_BUILD_INFO2:
1085  msp_send_build_info_cf(m);
1086  break;
1087  case MSP_NAME:
1088  msp_send_name(m);
1089  break;
1090  case MSP_FEATURE:
1091  msp_send_feature(m);
1092  break;
1093  case MSP_CONFIG:
1094  msp_send_config(m);
1095  break;
1096  case MSP_BUILD_INFO:
1097  msp_send_build_info(m);
1098  break;
1099  case MSP_IDENT:
1100  msp_send_ident(m);
1101  break;
1102  case MSP_UID:
1103  msp_send_uid(m);
1104  break;
1105  case MSP_MOTOR:
1106  msp_send_motor(m);
1107  break;
1108  case MSP_RAW_GPS:
1109  msp_send_raw_gps(m);
1110  break;
1111  case MSP_COMP_GPS:
1112  msp_send_comp_gps(m);
1113  break;
1114  case MSP_ALTITUDE:
1115  msp_send_altitude(m);
1116  break;
1117  case MSP_ATTITUDE:
1118  msp_send_attitude(m);
1119  break;
1120  case MSP_STATUS:
1121  msp_send_status(m);
1122  break;
1123  case MSP_ANALOG:
1124  msp_send_analog(m);
1125  break;
1126  case MSP_RC:
1127  msp_send_channels(m);
1128  break;
1129  case MSP_RC_TUNING:
1130  msp_send_rc_tuning(m);
1131  break;
1132  case MSP_PID:
1133  msp_send_pid(m);
1134  break;
1135  case MSP_MISC:
1136  msp_send_misc(m);
1137  break;
1138  case MSP_BOXIDS:
1139  msp_send_boxids(m);
1140  break;
1141  case MSP_PIDNAMES:
1142  msp_send_pid_names(m);
1143  break;
1144  case MSP_SET_PID:
1145  msp_set_pid(m);
1146  break;
1147  case MSP_ALARMS:
1148  msp_send_alarms(m);
1149  break;
1150  case MSP_SET_4WAY_IF:
1151  msp_handle_4wif(m);
1152  break;
1153  default:
1154  msp_send_error(m, m->cmd_id);
1155  break;
1156  }
1157  return MSP_IDLE;
1158 }
1159 
1160 static msp_state msp_state_discard(struct msp_bridge *m, uint8_t b)
1161 {
1162  return m->cmd_i++ == m->cmd_size ? MSP_IDLE : MSP_DISCARD;
1163 }
1164 
1170 static void msp_receive_byte(struct msp_bridge *m, uint8_t b)
1171 {
1172  switch (m->state) {
1173  case MSP_IDLE:
1174  switch (b) {
1175  case '<': // uavtalk matching with 0x3c 0x2x 0xxx 0x0x
1176  m->state = MSP_MAYBE_UAVTALK2;
1177  break;
1178  case '$':
1179  m->state = MSP_HEADER_START;
1180  break;
1181  default:
1182  m->state = MSP_IDLE;
1183  }
1184  break;
1185  case MSP_HEADER_START:
1186  m->state = b == 'M' ? MSP_HEADER_M : MSP_IDLE;
1187  break;
1188  case MSP_HEADER_M:
1189  m->state = b == '<' ? MSP_HEADER_SIZE : MSP_IDLE;
1190  break;
1191  case MSP_HEADER_SIZE:
1192  m->state = msp_state_size(m, b);
1193  break;
1194  case MSP_HEADER_CMD:
1195  m->state = msp_state_cmd(m, b);
1196  break;
1197  case MSP_FILLBUF:
1198  m->state = msp_state_fill_buf(m, b);
1199  break;
1200  case MSP_CHECKSUM:
1201  m->state = msp_state_checksum(m, b);
1202  break;
1203  case MSP_DISCARD:
1204  m->state = msp_state_discard(m, b);
1205  break;
1206  case MSP_MAYBE_UAVTALK2:
1207  // e.g. 3c 20 1d 00
1208  // second possible uavtalk byte
1209  m->state = (b&0xf0) == 0x20 ? MSP_MAYBE_UAVTALK3 : MSP_IDLE;
1210  break;
1211  case MSP_MAYBE_UAVTALK3:
1212  // third possible uavtalk byte can be anything
1213  m->state = MSP_MAYBE_UAVTALK4;
1214  break;
1215  case MSP_MAYBE_UAVTALK4:
1216  m->state = MSP_IDLE;
1217  // If this looks like the fourth possible uavtalk byte, we're done
1218  if ((b & 0xf0) == 0) {
1219  PIOS_COM_TELEM_SER = m->com;
1220 
1221  m->handler = MSP_HANDLER_IDLE;
1222  }
1223  break;
1224  }
1225 }
1226 
1231 static int32_t uavoMSPBridgeStart(void)
1232 {
1233  if (!module_enabled) {
1234  // give port to telemetry if it doesn't have one
1235  // stops board getting stuck in condition where it can't be connected to gcs
1236  if(!PIOS_COM_TELEM_SER)
1238 
1239  return -1;
1240  }
1241 
1242  struct pios_thread *task = PIOS_Thread_Create(
1243  uavoMSPBridgeTask, "uavoMSPBridge",
1245  TaskMonitorAdd(TASKINFO_RUNNING_UAVOMSPBRIDGE,
1246  task);
1247 
1248  return 0;
1249 }
1250 
1251 static void setMSPSpeed(struct msp_bridge *m)
1252 {
1253  if (m->com) {
1254  uint8_t speed;
1255  ModuleSettingsMSPSpeedGet(&speed);
1256 
1258  }
1259 }
1260 
1265 static int32_t uavoMSPBridgeInitialize(void)
1266 {
1267  if (pios_com_msp_id && PIOS_Modules_IsEnabled(PIOS_MODULE_UAVOMSPBRIDGE)) {
1268  msp = PIOS_malloc(sizeof(*msp));
1269  if (msp != NULL) {
1270  memset(msp, 0x00, sizeof(*msp));
1271 
1272  msp->com = pios_com_msp_id;
1273 
1274  module_enabled = true;
1275  return 0;
1276  }
1277  }
1278 
1279  return -1;
1280 }
1281 MODULE_INITCALL(uavoMSPBridgeInitialize, uavoMSPBridgeStart)
1282 
1283 void esc4wayProcess(void *mspPort);
1284 
1289 static void uavoMSPBridgeTask(void *parameters)
1290 {
1291  setMSPSpeed(msp);
1292 
1293  while (1) {
1294  switch (msp->handler) {
1295  case MSP_HANDLER_MSP:
1296  (void) 0;
1297 
1298  uint8_t b = 0;
1299 
1300  uint16_t count =
1301  PIOS_COM_ReceiveBuffer(msp->com, &b, 1, 3000);
1302 
1303  if (count) {
1304  msp_receive_byte(msp, b);
1305  }
1306 
1307  break;
1308 
1309 #ifdef PIOS_INCLUDE_4WAY
1310  case MSP_HANDLER_4WIF:
1311  esc4wayProcess(&msp->com);
1312  msp->handler = MSP_HANDLER_MSP;
1313 
1314  PIOS_Thread_Sleep(3);
1316  break;
1317 #endif
1318 
1319  case MSP_HANDLER_IDLE:
1320  // Returning is considered risky here as
1321  // that's unusual and this is an edge case.
1322  while (1) {
1323  PIOS_Thread_Sleep(60*1000);
1324  }
1325  break;
1326 
1327  default:
1328  PIOS_Assert(0);
1329  }
1330  }
1331 }
1332 
1333 #endif //PIOS_INCLUDE_MSP_BRIDGE
1334 
int16_t vario
Definition: msp_messages.h:97
uint16_t speed
Definition: msp_messages.h:101
static bool msp_handler(enum msp_message_id msg_id, void *data, uint8_t len, void *context)
uint32_t PIOS_Thread_Systime(void)
Definition: pios_thread.c:212
uint16_t ground_course
Definition: msp_messages.h:102
uint8_t num_sat
Definition: msp_messages.h:97
uint16_t direction_to_home
Definition: msp_messages.h:97
#define MAX_ALARM_LEN
Definition: panel.c:468
const uint8_t count
Definition: panel.c:515
uint8_t esc4wayInit(void)
uint8_t throttle_expo
Definition: msp_messages.h:102
struct usb_configuration_desc config
static struct GPSGlobals * gps
Definition: gps_airspeed.c:56
uint16_t cycle_time
Definition: msp_messages.h:96
bool PIOS_Modules_IsEnabled(enum pios_modules module)
Definition: pios_modules.c:41
struct pios_com_dev * com
Definition: mspuavobridge.c:58
float p
Definition: pid.h:43
#define STACK_SIZE_BYTES
Definition: actuator.c:62
float P[NUMX][NUMX]
Definition: insgps14state.c:66
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
uint32_t lon
Definition: msp_messages.h:98
uint32_t lat
Definition: msp_messages.h:97
uint16_t rssi
Definition: msp_messages.h:98
#define PIOS_SYS_SERIAL_NUM_BINARY_LEN
Definition: pios_sys.h:36
bool module_enabled
uint16_t flags
Definition: uavtalk_priv.h:52
uint8_t yaw_rate
Definition: msp_messages.h:99
msp_state
Definition: msp.c:40
uint8_t fix
Definition: msp_messages.h:96
#define TASK_PRIORITY
Definition: actuator.c:65
static struct msp_bridge * msp
Definition: mspuavobridge.c:77
void PIOS_HAL_ConfigureSerialSpeed(uintptr_t com_id, HwSharedSpeedBpsOptions speed)
Definition: pios_hal.c:1115
uint8_t data[XFER_BYTES_PER_PACKET]
Definition: bl_messages.h:129
#define PIOS_COM_TELEM_SER
Definition: pios_hal.h:58
uint8_t rc_rate
Definition: msp_messages.h:96
int16_t status
Definition: main.c:61
struct _msp_pid_item alt
Definition: msp_messages.h:99
bool PIOS_SENSORS_IsRegistered(enum pios_sensor_type type)
Checks if a sensor type is registered with the PIOS_SENSORS interface.
Definition: pios_sensors.c:88
uint8_t roll_pitch_rate
Definition: msp_messages.h:98
#define MODULE_INITCALL(ifn, sfn)
Definition: pios_initcall.h:67
uint16_t PIOS_COM_ReceiveBuffer(uintptr_t com_id, uint8_t *buf, uint16_t buf_len, uint32_t timeout_ms)
#define BOOT_DISPLAY_TIME_MS
static struct PIOS_Sensor sensors[PIOS_SENSOR_NUM]
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
Definition: pios_thread.c:89
static TaskInfoRunningElem task
uint8_t vbat
Definition: msp_messages.h:96
int32_t TaskMonitorAdd(TaskInfoRunningElem task, struct pios_thread *threadp)
Definition: taskmonitor.c:67
uint8_t i
Definition: msp_messages.h:97
uint8_t throttle_mid
Definition: msp_messages.h:101
enum channel_mode mode
Definition: pios_servo.c:58
actuator_interlock
Definition: pios_modules.h:57
uint8_t msp_version
Definition: msp_messages.h:98
uint16_t min_command
Definition: msp_messages.h:99
const char * AlarmBootReason(uint8_t reason)
uint16_t distance_to_home
Definition: msp_messages.h:96
uint8_t d
Definition: msp_messages.h:98
uint16_t current
void PIOS_Thread_Sleep(uint32_t time_ms)
Definition: pios_thread.c:229
PIOS_COM_SendBuffer(shub_global->frsky_port, shub_global->serial_buf, msg_length)
uint8_t type
tuple f
Definition: px_mkfw.py:81
#define MIN(a, b)
Definition: misc_math.h:41
void esc4wayProcess(struct serialPort_s *mspPort)
#define DONT_BUILD_IF(COND, MSG)
Definition: morsel.c:206
Includes PiOS and core architecture components.
uintptr_t pios_com_msp_id
Generic interface for sensors.
int32_t AlarmString(SystemAlarmsData *alarm, char *buf, size_t buflen, bool blink, uint8_t *state)
if(BaroAltitudeHandle()!=NULL)
uint8_t p
Definition: msp_messages.h:96
static ManualControlCommandData cmd
Definition: pid.h:42
#define PIOS_Assert(test)
Definition: pios_debug.h:52
Definition: camerastab.c:69
typedef __attribute__
Definition: serial_4way.h:43
int32_t PIOS_SYS_SerialNumberGetBinary(uint8_t array[PIOS_SYS_SERIAL_NUM_BINARY_LEN])
enum arena_state state