NinjaFlight
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mavlink_helpers.h
Go to the documentation of this file.
1 #ifndef _MAVLINK_HELPERS_H_
2 #define _MAVLINK_HELPERS_H_
3 
4 #include "string.h"
5 #include "checksum.h"
6 #include "mavlink_types.h"
7 #include "mavlink_conversions.h"
8 
9 #ifndef MAVLINK_HELPER
10 #define MAVLINK_HELPER
11 #endif
12 
13 /*
14  * Internal function to give access to the channel status for each channel
15  */
16 #ifndef MAVLINK_GET_CHANNEL_STATUS
18 {
19 #ifdef MAVLINK_EXTERNAL_RX_STATUS
20  // No m_mavlink_status array defined in function,
21  // has to be defined externally
22 #else
23  static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NUM_BUFFERS];
24 #endif
25  return &m_mavlink_status[chan];
26 }
27 #endif
28 
29 /*
30  * Internal function to give access to the channel buffer for each channel
31  */
32 #ifndef MAVLINK_GET_CHANNEL_BUFFER
33 MAVLINK_HELPER mavlink_message_t* mavlink_get_channel_buffer(uint8_t chan)
34 {
35 
36 #ifdef MAVLINK_EXTERNAL_RX_BUFFER
37  // No m_mavlink_buffer array defined in function,
38  // has to be defined externally
39 #else
40  static mavlink_message_t m_mavlink_buffer[MAVLINK_COMM_NUM_BUFFERS];
41 #endif
42  return &m_mavlink_buffer[chan];
43 }
44 #endif
45 
50 {
53 }
54 
67 #if MAVLINK_CRC_EXTRA
68 MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id,
69  uint8_t chan, uint8_t length, uint8_t crc_extra)
70 #else
71 MAVLINK_HELPER uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id,
72  uint8_t chan, uint8_t length)
73 #endif
74 {
75  // This code part is the same for all messages;
76  msg->magic = MAVLINK_STX;
77  msg->len = length;
78  msg->sysid = system_id;
79  msg->compid = component_id;
80  // One sequence number per channel
83  msg->checksum = crc_calculate(((const uint8_t*)(msg)) + 3, MAVLINK_CORE_HEADER_LEN);
84  crc_accumulate_buffer(&msg->checksum, _MAV_PAYLOAD(msg), msg->len);
85 #if MAVLINK_CRC_EXTRA
86  crc_accumulate(crc_extra, &msg->checksum);
87 #endif
88  mavlink_ck_a(msg) = (uint8_t)(msg->checksum & 0xFF);
89  mavlink_ck_b(msg) = (uint8_t)(msg->checksum >> 8);
90 
91  return length + MAVLINK_NUM_NON_PAYLOAD_BYTES;
92 }
93 
94 
98 #if MAVLINK_CRC_EXTRA
99 MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id,
100  uint8_t length, uint8_t crc_extra)
101 {
102  return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length, crc_extra);
103 }
104 #else
105 MAVLINK_HELPER uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id,
106  uint8_t length)
107 {
108  return mavlink_finalize_message_chan(msg, system_id, component_id, MAVLINK_COMM_0, length);
109 }
110 #endif
111 
112 #ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS
113 MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len);
114 
118 #if MAVLINK_CRC_EXTRA
119 MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet,
120  uint8_t length, uint8_t crc_extra)
121 #else
122 MAVLINK_HELPER void _mav_finalize_message_chan_send(mavlink_channel_t chan, uint8_t msgid, const char *packet, uint8_t length)
123 #endif
124 {
125  uint16_t checksum;
126  uint8_t buf[MAVLINK_NUM_HEADER_BYTES];
127  uint8_t ck[2];
129  buf[0] = MAVLINK_STX;
130  buf[1] = length;
131  buf[2] = status->current_tx_seq;
132  buf[3] = mavlink_system.sysid;
133  buf[4] = mavlink_system.compid;
134  buf[5] = msgid;
135  status->current_tx_seq++;
136  checksum = crc_calculate((const uint8_t*)&buf[1], MAVLINK_CORE_HEADER_LEN);
137  crc_accumulate_buffer(&checksum, packet, length);
138 #if MAVLINK_CRC_EXTRA
139  crc_accumulate(crc_extra, &checksum);
140 #endif
141  ck[0] = (uint8_t)(checksum & 0xFF);
142  ck[1] = (uint8_t)(checksum >> 8);
143 
144  MAVLINK_START_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length);
145  _mavlink_send_uart(chan, (const char *)buf, MAVLINK_NUM_HEADER_BYTES);
146  _mavlink_send_uart(chan, packet, length);
147  _mavlink_send_uart(chan, (const char *)ck, 2);
148  MAVLINK_END_UART_SEND(chan, MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)length);
149 }
150 
155 MAVLINK_HELPER void _mavlink_resend_uart(mavlink_channel_t chan, const mavlink_message_t *msg)
156 {
157  uint8_t ck[2];
158 
159  ck[0] = (uint8_t)(msg->checksum & 0xFF);
160  ck[1] = (uint8_t)(msg->checksum >> 8);
161  // XXX use the right sequence here
162 
164  _mavlink_send_uart(chan, (const char *)&msg->magic, MAVLINK_NUM_HEADER_BYTES);
165  _mavlink_send_uart(chan, _MAV_PAYLOAD(msg), msg->len);
166  _mavlink_send_uart(chan, (const char *)ck, 2);
168 }
169 #endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS
170 
174 MAVLINK_HELPER uint16_t mavlink_msg_to_send_buffer(uint8_t *buffer, const mavlink_message_t *msg)
175 {
176  memcpy(buffer, (const uint8_t *)&msg->magic, MAVLINK_NUM_HEADER_BYTES + (uint16_t)msg->len);
177 
178  uint8_t *ck = buffer + (MAVLINK_NUM_HEADER_BYTES + (uint16_t)msg->len);
179 
180  ck[0] = (uint8_t)(msg->checksum & 0xFF);
181  ck[1] = (uint8_t)(msg->checksum >> 8);
182 
183  return MAVLINK_NUM_NON_PAYLOAD_BYTES + (uint16_t)msg->len;
184 }
185 
187  uint8_t uint8;
188  int8_t int8;
189  uint16_t uint16;
190  int16_t int16;
191  uint32_t uint32;
192  int32_t int32;
193 };
194 
195 
196 MAVLINK_HELPER void mavlink_start_checksum(mavlink_message_t* msg)
197 {
198  crc_init(&msg->checksum);
199 }
200 
201 MAVLINK_HELPER void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c)
202 {
203  crc_accumulate(c, &msg->checksum);
204 }
205 
247 MAVLINK_HELPER uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status)
248 {
249  /*
250  default message crc function. You can override this per-system to
251  put this data in a different memory segment
252  */
253 #if MAVLINK_CRC_EXTRA
254 #ifndef MAVLINK_MESSAGE_CRC
255  static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS;
256 #define MAVLINK_MESSAGE_CRC(msgid) mavlink_message_crcs[msgid]
257 #endif
258 #endif
259 
260 /* Enable this option to check the length of each message.
261  This allows invalid messages to be caught much sooner. Use if the transmission
262  medium is prone to missing (or extra) characters (e.g. a radio that fades in
263  and out). Only use if the channel will only contain messages types listed in
264  the headers.
265 */
266 #ifdef MAVLINK_CHECK_MESSAGE_LENGTH
267 #ifndef MAVLINK_MESSAGE_LENGTH
268  static const uint8_t mavlink_message_lengths[256] = MAVLINK_MESSAGE_LENGTHS;
269 #define MAVLINK_MESSAGE_LENGTH(msgid) mavlink_message_lengths[msgid]
270 #endif
271 #endif
272 
273  mavlink_message_t* rxmsg = mavlink_get_channel_buffer(chan);
275  int bufferIndex = 0;
276 
277  status->msg_received = 0;
278 
279  switch (status->parse_state)
280  {
283  if (c == MAVLINK_STX)
284  {
286  rxmsg->len = 0;
287  rxmsg->magic = c;
288  mavlink_start_checksum(rxmsg);
289  }
290  break;
291 
293  if (status->msg_received
294 /* Support shorter buffers than the
295  default maximum packet size */
296 #if (MAVLINK_MAX_PAYLOAD_LEN < 255)
298 #endif
299  )
300  {
301  status->buffer_overrun++;
302  status->parse_error++;
303  status->msg_received = 0;
305  }
306  else
307  {
308  // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2
309  rxmsg->len = c;
310  status->packet_idx = 0;
311  mavlink_update_checksum(rxmsg, c);
313  }
314  break;
315 
317  rxmsg->seq = c;
318  mavlink_update_checksum(rxmsg, c);
320  break;
321 
323  rxmsg->sysid = c;
324  mavlink_update_checksum(rxmsg, c);
326  break;
327 
329  rxmsg->compid = c;
330  mavlink_update_checksum(rxmsg, c);
332  break;
333 
335 #ifdef MAVLINK_CHECK_MESSAGE_LENGTH
336  if (rxmsg->len != MAVLINK_MESSAGE_LENGTH(c))
337  {
338  status->parse_error++;
340  break;
341  }
342 #endif
343  rxmsg->msgid = c;
344  mavlink_update_checksum(rxmsg, c);
345  if (rxmsg->len == 0)
346  {
348  }
349  else
350  {
352  }
353  break;
354 
356  _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx++] = (char)c;
357  mavlink_update_checksum(rxmsg, c);
358  if (status->packet_idx == rxmsg->len)
359  {
361  }
362  break;
363 
365 #if MAVLINK_CRC_EXTRA
366  mavlink_update_checksum(rxmsg, MAVLINK_MESSAGE_CRC(rxmsg->msgid));
367 #endif
368  if (c != (rxmsg->checksum & 0xFF)) {
369  // Check first checksum byte
370  status->parse_error++;
371  status->msg_received = 0;
373  if (c == MAVLINK_STX)
374  {
376  rxmsg->len = 0;
377  mavlink_start_checksum(rxmsg);
378  }
379  }
380  else
381  {
383  _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx] = (char)c;
384  }
385  break;
386 
388  if (c != (rxmsg->checksum >> 8)) {
389  // Check second checksum byte
390  status->parse_error++;
391  status->msg_received = 0;
393  if (c == MAVLINK_STX)
394  {
396  rxmsg->len = 0;
397  mavlink_start_checksum(rxmsg);
398  }
399  }
400  else
401  {
402  // Successfully got message
403  status->msg_received = 1;
405  _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx+1] = (char)c;
406  memcpy(r_message, rxmsg, sizeof(mavlink_message_t));
407  }
408  break;
409  }
410 
411  bufferIndex++;
412  // If a message has been sucessfully decoded, check index
413  if (status->msg_received == 1)
414  {
415  //while(status->current_seq != rxmsg->seq)
416  //{
417  // status->packet_rx_drop_count++;
418  // status->current_seq++;
419  //}
420  status->current_rx_seq = rxmsg->seq;
421  // Initial condition: If no packet has been received so far, drop count is undefined
422  if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0;
423  // Count this packet as received
424  status->packet_rx_success_count++;
425  }
426 
427  r_message->len = rxmsg->len; // Provide visibility on how far we are into current msg
428  r_mavlink_status->parse_state = status->parse_state;
429  r_mavlink_status->packet_idx = status->packet_idx;
430  r_mavlink_status->current_rx_seq = status->current_rx_seq+1;
431  r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count;
432  r_mavlink_status->packet_rx_drop_count = status->parse_error;
433  status->parse_error = 0;
434  return status->msg_received;
435 }
436 
447 MAVLINK_HELPER uint8_t put_bitfield_n_by_index(int32_t b, uint8_t bits, uint8_t packet_index, uint8_t bit_index, uint8_t* r_bit_index, uint8_t* buffer)
448 {
449  uint16_t bits_remain = bits;
450  // Transform number into network order
451  int32_t v;
452  uint8_t i_bit_index, i_byte_index, curr_bits_n;
453 #if MAVLINK_NEED_BYTE_SWAP
454  union {
455  int32_t i;
456  uint8_t b[4];
457  } bin, bout;
458  bin.i = b;
459  bout.b[0] = bin.b[3];
460  bout.b[1] = bin.b[2];
461  bout.b[2] = bin.b[1];
462  bout.b[3] = bin.b[0];
463  v = bout.i;
464 #else
465  v = b;
466 #endif
467 
468  // buffer in
469  // 01100000 01000000 00000000 11110001
470  // buffer out
471  // 11110001 00000000 01000000 01100000
472 
473  // Existing partly filled byte (four free slots)
474  // 0111xxxx
475 
476  // Mask n free bits
477  // 00001111 = 2^0 + 2^1 + 2^2 + 2^3 = 2^n - 1
478  // = ((uint32_t)(1 << n)) - 1; // = 2^n - 1
479 
480  // Shift n bits into the right position
481  // out = in >> n;
482 
483  // Mask and shift bytes
484  i_bit_index = bit_index;
485  i_byte_index = packet_index;
486  if (bit_index > 0)
487  {
488  // If bits were available at start, they were available
489  // in the byte before the current index
490  i_byte_index--;
491  }
492 
493  // While bits have not been packed yet
494  while (bits_remain > 0)
495  {
496  // Bits still have to be packed
497  // there can be more than 8 bits, so
498  // we might have to pack them into more than one byte
499 
500  // First pack everything we can into the current 'open' byte
501  //curr_bits_n = bits_remain << 3; // Equals bits_remain mod 8
502  //FIXME
503  if (bits_remain <= (uint8_t)(8 - i_bit_index))
504  {
505  // Enough space
506  curr_bits_n = (uint8_t)bits_remain;
507  }
508  else
509  {
510  curr_bits_n = (8 - i_bit_index);
511  }
512 
513  // Pack these n bits into the current byte
514  // Mask out whatever was at that position with ones (xxx11111)
515  buffer[i_byte_index] &= (0xFF >> (8 - curr_bits_n));
516  // Put content to this position, by masking out the non-used part
517  buffer[i_byte_index] |= ((0x00 << curr_bits_n) & v);
518 
519  // Increment the bit index
520  i_bit_index += curr_bits_n;
521 
522  // Now proceed to the next byte, if necessary
523  bits_remain -= curr_bits_n;
524  if (bits_remain > 0)
525  {
526  // Offer another 8 bits / one byte
527  i_byte_index++;
528  i_bit_index = 0;
529  }
530  }
531 
532  *r_bit_index = i_bit_index;
533  // If a partly filled byte is present, mark this as consumed
534  if (i_bit_index != 7) i_byte_index++;
535  return i_byte_index - packet_index;
536 }
537 
538 #ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS
539 
540 // To make MAVLink work on your MCU, define comm_send_ch() if you wish
541 // to send 1 byte at a time, or MAVLINK_SEND_UART_BYTES() to send a
542 // whole packet at a time
543 
544 /*
545 
546 #include "mavlink_types.h"
547 
548 void comm_send_ch(mavlink_channel_t chan, uint8_t ch)
549 {
550  if (chan == MAVLINK_COMM_0)
551  {
552  uart0_transmit(ch);
553  }
554  if (chan == MAVLINK_COMM_1)
555  {
556  uart1_transmit(ch);
557  }
558 }
559  */
560 
561 MAVLINK_HELPER void _mavlink_send_uart(mavlink_channel_t chan, const char *buf, uint16_t len)
562 {
563 #ifdef MAVLINK_SEND_UART_BYTES
564  /* this is the more efficient approach, if the platform
565  defines it */
566  MAVLINK_SEND_UART_BYTES(chan, (const uint8_t *)buf, len);
567 #else
568  /* fallback to one byte at a time */
569  uint16_t i;
570  for (i = 0; i < len; i++) {
571  comm_send_ch(chan, (uint8_t)buf[i]);
572  }
573 #endif
574 }
575 #endif // MAVLINK_USE_CONVENIENCE_FUNCTIONS
576 
577 #endif /* _MAVLINK_HELPERS_H_ */
ubx_nav_status status
Definition: gps.c:829
#define MAVLINK_START_UART_SEND(chan, length)
Definition: protocol.h:30
#define MAVLINK_END_UART_SEND(chan, length)
Definition: protocol.h:34
#define MAVLINK_MESSAGE_CRCS
Definition: ardupilotmega.h:23
#define MAVLINK_MESSAGE_LENGTHS
Definition: ardupilotmega.h:19