dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mspuavobridge.c
Go to the documentation of this file.
1 
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, see <http://www.gnu.org/licenses/>
24  *
25  * Additional note on redistribution: The copyright and license notices above
26  * must be maintained in each individual source file that is a derivative work
27  * of this source file; otherwise redistribution is prohibited.
28  */
29 
30 #include "openpilot.h"
31 #include "pios_hal.h"
32 #include "pios_thread.h"
33 #include "coordinate_conversions.h"
34 #include "msp.h"
35 
36 #include "modulesettings.h"
37 #include "attitudeactual.h"
38 #include "accels.h"
39 #include "gyros.h"
40 #include "flightbatterystate.h"
41 #include "manualcontrolcommand.h"
42 
43 #if defined(PIOS_MSP_STACK_SIZE)
44 #define STACK_SIZE_BYTES PIOS_MSP_STACK_SIZE
45 #else
46 #define STACK_SIZE_BYTES 800
47 #endif
48 #define THREAD_PRIORITY PIOS_THREAD_PRIO_LOW
49 
50 /* time to wait for a reply */
51 #define MSP_TIMEOUT 10 // ms
52 #define MSP_BRIDGE_MAGIC 0x97a4dc58
53 
54 
55 struct msp_bridge {
56  uint32_t magic;
57 
58  struct pios_com_dev *com;
59  struct msp_parser *parser;
60 
62  bool done;
63 };
64 
65 static struct msp_message_list_item {
66  uint32_t last_fetched;
67  uint16_t period; /* ms */
69 } message_list[] = {
70  /* these are the messages that will be fetched and their intervals */
71  { .msg_id = MSP_MSG_ATTITUDE, .period = 20 },
72  { .msg_id = MSP_MSG_ANALOG, .period = 100 },
73  { .msg_id = MSP_MSG_RAW_IMU, .period = 50 },
74 };
75 
76 static bool module_enabled = false;
77 static struct msp_bridge *msp;
78 
79 // TODO: ick, use a real pointer
80 extern uintptr_t pios_com_msp_id;
81 
82 
83 static bool msp_bridge_validate(struct msp_bridge *m)
84 {
85  return m != NULL && m->magic == MSP_BRIDGE_MAGIC;
86 }
87 
88 static bool msp_unpack_attitude(void *data, uint8_t len)
89 {
90  struct msp_attitude *att = data;
91  if (len < sizeof(*att))
92  return false;
93 
94  AttitudeActualData attActual;
95  AttitudeActualGet(&attActual);
96 
97  const float rpy[3] = {
98  (float)att->angx / 10.0f, /* [-1800:1800] 1/10 deg */
99  (float)att->angy / -10.0f, /* [-900:900] 1/10 deg */
100  att->heading /* [-180:180] deg */
101  };
102  attActual.Roll = rpy[0];
103  attActual.Pitch = rpy[1];
104  attActual.Yaw = rpy[2];
105 
106  float q[4];
107  RPY2Quaternion(rpy, q);
108  attActual.q1 = q[0];
109  attActual.q2 = q[1];
110  attActual.q3 = q[2];
111  attActual.q4 = q[3];
112 
113  AttitudeActualSet(&attActual);
114 
115  return true;
116 }
117 
118 static bool msp_unpack_raw_imu(void *data, uint8_t len)
119 {
120  struct msp_raw_imu *imu = data;
121  if (len < sizeof(*imu))
122  return false;
123 
124  AccelsData accels;
125  AccelsGet(&accels);
126  /* based on MPU 6050 numbers given in protocol spec */
127  accels.x = (float)imu->accx * 9.8f / 512;
128  accels.y = (float)imu->accy * 9.8f / 512;
129  accels.z = (float)imu->accz * 9.8f / 512;
130  AccelsSet(&accels);
131 
132  GyrosData gyros;
133  GyrosGet(&gyros);
134  /* based on MPU 6050 numbers given in protocol spec */
135  gyros.x = (float)imu->gyrx / 4.096f;
136  gyros.y = (float)imu->gyry / 4.096f;
137  gyros.z = (float)imu->gyrz / 4.096f;
138  GyrosSet(&gyros);
139 
140  return true;
141 }
142 
143 static bool msp_unpack_analog(void *data, uint8_t len)
144 {
145  struct msp_analog *analog = data;
146  if (len < sizeof(*analog))
147  return false;
148 
149  FlightBatteryStateData batt;
150  FlightBatteryStateGet(&batt);
151  batt.Voltage = (float)analog->vbat / 10.0f;
152  /* TODO: check scaling */
153  batt.Current = (float)analog->amperage;
154  batt.ConsumedEnergy = (float)analog->power_meter_sum;
155  FlightBatteryStateSet(&batt);
156 
157  ManualControlCommandData cntrl;
158  ManualControlCommandGet(&cntrl);
159  cntrl.RawRssi = analog->rssi;
160  cntrl.Rssi = analog->rssi * 100 / 1024; /* [0:1023] */
161  ManualControlCommandSet(&cntrl);
162 
163  return true;
164 }
165 
166 static void set_baudrate(struct msp_bridge *m)
167 {
169  if (!m->com)
170  return;
171 
172  uint8_t baud;
173  ModuleSettingsMSPSpeedGet(&baud);
174  /* TODO: teach pios_com to take a real pointer */
175  PIOS_HAL_ConfigureSerialSpeed((uintptr_t)m->com, baud);
176 }
177 
178 static bool msp_handler(enum msp_message_id msg_id, void *data, uint8_t len, void *context)
179 {
180  struct msp_bridge *m = context;
181  if (!msp_bridge_validate(m))
182  return false;
183 
184  bool retval = false;
185  switch (msg_id) {
186  case MSP_MSG_ATTITUDE:
187  retval &= msp_unpack_attitude(data, len);
188  break;
189  case MSP_MSG_RAW_IMU:
190  retval &= msp_unpack_raw_imu(data, len);
191  break;
192  case MSP_MSG_ANALOG:
193  retval &= msp_unpack_analog(data, len);
194  break;
195  default:
196  break;
197  }
198 
199  if (msg_id == m->expected)
200  m->done = true;
201 
202  return retval;
203 }
204 
206 {
207  for (int i = 0; i < NELEMENTS(message_list); i++) {
208  struct msp_message_list_item *item = &message_list[i];
209  if (PIOS_Thread_Period_Elapsed(item->last_fetched, item->period)) {
211  return item->msg_id;
212  }
213  }
214  return 0;
215 }
216 
221 static void mspUavoBridge_Task(void *parameters)
222 {
223  set_baudrate(msp);
225 
226  while(true) {
228  msp->done = false;
229 
230  while (!(msp->expected = get_next_message()))
232 
233  msp_send_com(msp->parser, msp->com, msp->expected, NULL, 0);
234 
235  int time = 0;
236  while (!msp->done && time < MSP_TIMEOUT) {
237  msp_process_com(msp->parser, msp->com);
238  if (!msp->done) {
239  time++;
241  }
242  }
243  }
244 }
245 
253 static int32_t mspUavoBridge_Start(void)
254 {
255  if (!module_enabled)
256  return -1;
257 
258  if (!msp_bridge_validate(msp))
259  return -2;
260 
261  struct pios_thread *task = PIOS_Thread_Create(mspUavoBridge_Task,
262  "MspUavoBridge", STACK_SIZE_BYTES, NULL, THREAD_PRIORITY);
263 
264  if (!task)
265  return -3;
266 
267  TaskMonitorAdd(TASKINFO_RUNNING_MSPUAVOBRIDGE, task);
268 
269  return 0;
270 }
271 
279 static int32_t mspUavoBridge_Init(void)
280 {
281  // TODO: PIOS_MODULE_MSPUAVOBRIDGE
283  module_enabled = true;
284 
285  msp = PIOS_malloc(sizeof(*msp));
286  if (!msp) {
287  module_enabled = false;
288  return -1;
289  }
290 
291  memset(msp, 0, sizeof(*msp));
292 
294  if (!msp->parser) {
295  PIOS_free(msp);
296  return -2;
297  }
298 
299  /* TODO: make pios_com use real pointer */
300  msp->com = (struct pios_com_dev *)pios_com_msp_id;
301 
302  /* Init these in case they aren't already (we don't want to die) */
303  bool check = true;
304  /* WARNING: this macro has side-effects! */
305  #define INIT_CHECK_UAVO(name) name##Initialize(); check &= (name##Handle() != NULL)
306  INIT_CHECK_UAVO(Accels);
307  INIT_CHECK_UAVO(AttitudeActual);
308  INIT_CHECK_UAVO(Gyros);
309  INIT_CHECK_UAVO(FlightBatteryState);
310  INIT_CHECK_UAVO(ManualControlCommand);
311  if (!check)
312  return -3;
313 
314  msp->magic = MSP_BRIDGE_MAGIC;
315 
316  return 0;
317 }
318 
320 
321 
#define INIT_CHECK_UAVO(name)
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
int32_t msp_send_com(struct msp_parser *parser, struct pios_com_dev *com, enum msp_message_id msg_id, void *payload, uint8_t len)
Construct and send an MSP message via PIOS_COM.
Definition: msp.c:235
uint16_t power_meter_sum
Definition: msp_messages.h:194
int16_t gyrz
Definition: msp_messages.h:128
void RPY2Quaternion(const float rpy[3], float q[4])
int16_t accx
Definition: msp_messages.h:123
uint16_t rssi
Definition: msp_messages.h:195
#define NELEMENTS(x)
Definition: pios.h:192
#define MSP_TIMEOUT
Definition: mspuavobridge.c:51
static void set_baudrate(struct msp_bridge *m)
bool PIOS_Modules_IsEnabled(enum pios_modules module)
Definition: pios_modules.c:41
int16_t gyrx
Definition: msp_messages.h:126
struct pios_com_dev * com
Definition: mspuavobridge.c:58
enum msp_message_id msg_id
Definition: mspuavobridge.c:68
static bool msp_unpack_raw_imu(void *data, uint8_t len)
int16_t gyry
Definition: msp_messages.h:127
int32_t msp_register_handler(struct msp_parser *parser, msp_handler_t handler, void *context)
Register a handler for valid received messages.
Definition: msp.c:255
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
int16_t angx
Definition: msp_messages.h:182
int16_t angy
Definition: msp_messages.h:183
uint32_t magic
Definition: mspuavobridge.c:56
struct msp_parser * parser
Definition: mspuavobridge.c:59
uint8_t vbat
Definition: msp_messages.h:193
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
static int32_t mspUavoBridge_Init(void)
Initialize the MSP to UAVO bridge module.
#define MODULE_INITCALL(ifn, sfn)
Definition: pios_initcall.h:67
int16_t accz
Definition: msp_messages.h:125
static int32_t mspUavoBridge_Start(void)
Start the MSP to UAVO bridge module.
msp_message_id
Definition: msp_messages.h:41
static bool msp_unpack_analog(void *data, uint8_t len)
enum msp_message_id expected
Definition: mspuavobridge.c:61
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
int32_t TaskMonitorAdd(TaskInfoRunningElem task, struct pios_thread *threadp)
Definition: taskmonitor.c:67
uint8_t i
Definition: msp_messages.h:97
static bool msp_unpack_attitude(void *data, uint8_t len)
Definition: mspuavobridge.c:88
bool PIOS_Thread_Period_Elapsed(const uint32_t prev_systime, const uint32_t increment_ms)
Determine if a period has elapsed since a datum.
Definition: pios_thread.c:281
void PIOS_free(void *buf)
Definition: pios_heap.c:174
void PIOS_Thread_Sleep(uint32_t time_ms)
Definition: pios_thread.c:229
Header for Coordinate conversions library in coordinate_conversions.c.
static bool msp_bridge_validate(struct msp_bridge *m)
Definition: mspuavobridge.c:83
Includes PiOS and core architecture components.
int16_t accy
Definition: msp_messages.h:124
static void mspUavoBridge_Task(void *parameters)
MSP to UAVO bridge main task.
#define MSP_BRIDGE_MAGIC
Definition: mspuavobridge.c:52
uintptr_t pios_com_msp_id
int32_t msp_process_com(struct msp_parser *parser, struct pios_com_dev *com)
Process MSP stream from PIOS_COM.
Definition: msp.c:219
int16_t heading
Definition: msp_messages.h:184
#define THREAD_PRIORITY
Definition: mspuavobridge.c:48
uint16_t amperage
Definition: msp_messages.h:196
Definition: msp.c:51
static struct msp_message_list_item message_list[]
struct msp_parser * msp_parser_init(enum msp_parser_type type)
Initialize a new parser instance.
Definition: msp.c:193
static enum msp_message_id get_next_message(void)
static bool module_enabled
Definition: mspuavobridge.c:76
#define PIOS_Assert(test)
Definition: pios_debug.h:52
#define STACK_SIZE_BYTES
Definition: mspuavobridge.c:46