Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed PID ADXL345 Camera_LS_Y201 ITG3200 RangeFinder mbos xbee_lib Motor Servo
protocol.h
00001 #ifndef _MAVLINK_PROTOCOL_H_ 00002 #define _MAVLINK_PROTOCOL_H_ 00003 00004 #include "string.h" 00005 #include "checksum.h" 00006 00007 #include "mavlink_types.h" 00008 00009 extern Serial pc; 00010 00011 /** 00012 * @brief Initialize the communication stack 00013 * 00014 * This function has to be called before using commParseBuffer() to initialize the different status registers. 00015 * 00016 * @return Will initialize the different buffers and status registers. 00017 */ 00018 static void mavlink_parse_state_initialize(mavlink_status_t* initStatus) 00019 { 00020 if ((initStatus->parse_state <= MAVLINK_PARSE_STATE_UNINIT) || (initStatus->parse_state > MAVLINK_PARSE_STATE_GOT_CRC1)) 00021 { 00022 initStatus->ck_a = 0; 00023 initStatus->ck_b = 0; 00024 initStatus->msg_received = 0; 00025 initStatus->buffer_overrun = 0; 00026 initStatus->parse_error = 0; 00027 initStatus->parse_state = MAVLINK_PARSE_STATE_UNINIT; 00028 initStatus->packet_idx = 0; 00029 initStatus->packet_rx_drop_count = 0; 00030 initStatus->packet_rx_success_count = 0; 00031 initStatus->current_rx_seq = 0; 00032 initStatus->current_tx_seq = 0; 00033 } 00034 } 00035 00036 static inline mavlink_status_t* mavlink_get_channel_status(uint8_t chan) 00037 { 00038 static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NUM_BUFFERS]; 00039 return &m_mavlink_status[chan]; 00040 } 00041 00042 /** 00043 * @brief Finalize a MAVLink message with MAVLINK_COMM_0 as default channel 00044 * 00045 * This function calculates the checksum and sets length and aircraft id correctly. 00046 * It assumes that the message id and the payload are already correctly set. 00047 * 00048 * @warning This function implicitely assumes the message is sent over channel zero. 00049 * if the message is sent over a different channel it will reach the receiver 00050 * without error, BUT the sequence number might be wrong due to the wrong 00051 * channel sequence counter. This will result is wrongly reported excessive 00052 * packet loss. Please use @see mavlink_{pack|encode}_headerless and then 00053 * @see mavlink_finalize_message_chan before sending for a correct channel 00054 * assignment. Please note that the mavlink_msg_xxx_pack and encode functions 00055 * assign channel zero as default and thus induce possible loss counter errors.\ 00056 * They have been left to ensure code compatibility. 00057 * 00058 * @see mavlink_finalize_message_chan 00059 * @param msg Message to finalize 00060 * @param system_id Id of the sending (this) system, 1-127 00061 * @param length Message length, usually just the counter incremented while packing the message 00062 */ 00063 00064 00065 static inline uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, uint16_t length) 00066 { 00067 // This code part is the same for all messages; 00068 //for extra seed in mavlink 1.0 00069 static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; 00070 00071 uint16_t checksum; 00072 msg->len = length; 00073 msg->sysid = system_id; 00074 msg->compid = component_id; 00075 // One sequence number per component 00076 msg->seq = mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq; 00077 mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq = mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq+1; 00078 checksum = crc_calculate((uint8_t*)((void*)msg), length + MAVLINK_CORE_HEADER_LEN); 00079 //for extra seed in mavlink 1.0 00080 crc_accumulate(mavlink_message_crcs[msg->msgid], &checksum); 00081 00082 msg->ck_a = (uint8_t)(checksum & 0xFF); ///< High byte 00083 msg->ck_b = (uint8_t)(checksum >> 8); ///< Low byte 00084 00085 return length + MAVLINK_NUM_NON_STX_PAYLOAD_BYTES; 00086 } 00087 00088 /** 00089 * @brief Finalize a MAVLink message with channel assignment 00090 * 00091 * This function calculates the checksum and sets length and aircraft id correctly. 00092 * It assumes that the message id and the payload are already correctly set. This function 00093 * can also be used if the message header has already been written before (as in mavlink_msg_xxx_pack 00094 * instead of mavlink_msg_xxx_pack_headerless), it just introduces little extra overhead. 00095 * 00096 * @param msg Message to finalize 00097 * @param system_id Id of the sending (this) system, 1-127 00098 * @param length Message length, usually just the counter incremented while packing the message 00099 */ 00100 static inline uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, uint8_t chan, uint16_t length) 00101 { 00102 // This code part is the same for all messages; 00103 uint16_t checksum; 00104 msg->len = length; 00105 msg->sysid = system_id; 00106 msg->compid = component_id; 00107 // One sequence number per component 00108 msg->seq = mavlink_get_channel_status(chan)->current_tx_seq; 00109 mavlink_get_channel_status(chan)->current_tx_seq = mavlink_get_channel_status(chan)->current_tx_seq+1; 00110 checksum = crc_calculate((uint8_t*)((void*)msg), length + MAVLINK_CORE_HEADER_LEN); 00111 msg->ck_a = (uint8_t)(checksum & 0xFF); ///< High byte 00112 msg->ck_b = (uint8_t)(checksum >> 8); ///< Low byte 00113 00114 return length + MAVLINK_NUM_NON_STX_PAYLOAD_BYTES; 00115 } 00116 00117 /** 00118 * @brief Pack a message to send it over a serial byte stream 00119 */ 00120 static inline uint16_t mavlink_msg_to_send_buffer(uint8_t* buffer, const mavlink_message_t* msg) 00121 { 00122 *(buffer+0) = MAVLINK_STX; ///< Start transmit 00123 memcpy((buffer+1), msg, msg->len + MAVLINK_CORE_HEADER_LEN); ///< Core header plus payload 00124 *(buffer + msg->len + MAVLINK_CORE_HEADER_LEN + 1) = msg->ck_a; 00125 *(buffer + msg->len + MAVLINK_CORE_HEADER_LEN + 2) = msg->ck_b; 00126 return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES; 00127 //return 0; 00128 } 00129 00130 /** 00131 * @brief Get the required buffer size for this message 00132 */ 00133 static inline uint16_t mavlink_msg_get_send_buffer_length(const mavlink_message_t* msg) 00134 { 00135 return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES; 00136 } 00137 00138 union checksum_ { 00139 uint16_t s; 00140 uint8_t c[2]; 00141 }; 00142 00143 union __mavlink_bitfield { 00144 uint8_t uint8; 00145 int8_t int8; 00146 uint16_t uint16; 00147 int16_t int16; 00148 uint32_t uint32; 00149 int32_t int32; 00150 }; 00151 00152 00153 static inline void mavlink_start_checksum(mavlink_message_t* msg) 00154 { 00155 union checksum_ ck; 00156 crc_init(&(ck.s)); 00157 msg->ck_a = ck.c[0]; 00158 msg->ck_b = ck.c[1]; 00159 } 00160 00161 static inline void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c) 00162 { 00163 union checksum_ ck; 00164 ck.c[0] = msg->ck_a; 00165 ck.c[1] = msg->ck_b; 00166 crc_accumulate(c, &(ck.s)); 00167 msg->ck_a = ck.c[0]; 00168 msg->ck_b = ck.c[1]; 00169 } 00170 00171 /** 00172 * This is a convenience function which handles the complete MAVLink parsing. 00173 * the function will parse one byte at a time and return the complete packet once 00174 * it could be successfully decoded. Checksum and other failures will be silently 00175 * ignored. 00176 * 00177 * @param chan ID of the current channel. This allows to parse different channels with this function. 00178 * a channel is not a physical message channel like a serial port, but a logic partition of 00179 * the communication streams in this case. COMM_NB is the limit for the number of channels 00180 * on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows 00181 * @param c The char to barse 00182 * 00183 * @param returnMsg NULL if no message could be decoded, the message data else 00184 * @return 0 if no message could be decoded, 1 else 00185 * 00186 * A typical use scenario of this function call is: 00187 * 00188 * @code 00189 * #include <inttypes.h> // For fixed-width uint8_t type 00190 * 00191 * mavlink_message_t msg; 00192 * int chan = 0; 00193 * 00194 * 00195 * while(serial.bytesAvailable > 0) 00196 * { 00197 * uint8_t byte = serial.getNextByte(); 00198 * if (mavlink_parse_char(chan, byte, &msg)) 00199 * { 00200 * printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid); 00201 * } 00202 * } 00203 * 00204 * 00205 * @endcode 00206 */ 00207 static inline uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status) 00208 { 00209 static mavlink_message_t m_mavlink_message[MAVLINK_COMM_NUM_BUFFERS]; 00210 00211 // For crc calculation with extra seed in mavlink 1.0 00212 //static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS; 00213 00214 // Initializes only once, values keep unchanged after first initialization 00215 mavlink_parse_state_initialize(mavlink_get_channel_status(chan)); 00216 00217 mavlink_message_t* rxmsg = &m_mavlink_message[chan]; ///< The currently decoded message 00218 mavlink_status_t* status = mavlink_get_channel_status(chan); ///< The current decode status 00219 int bufferIndex = 0; 00220 00221 status->msg_received = 0; 00222 00223 switch (status->parse_state) 00224 { 00225 case MAVLINK_PARSE_STATE_UNINIT: 00226 case MAVLINK_PARSE_STATE_IDLE: 00227 if (c == MAVLINK_STX) 00228 { 00229 status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; 00230 mavlink_start_checksum(rxmsg); 00231 } 00232 break; 00233 00234 case MAVLINK_PARSE_STATE_GOT_STX: 00235 if (status->msg_received) 00236 { 00237 status->buffer_overrun++; 00238 status->parse_error++; 00239 status->msg_received = 0; 00240 status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00241 } 00242 else 00243 { 00244 // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2 00245 rxmsg->len = c; 00246 status->packet_idx = 0; 00247 mavlink_update_checksum(rxmsg, c); 00248 status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH; 00249 } 00250 break; 00251 00252 case MAVLINK_PARSE_STATE_GOT_LENGTH: 00253 rxmsg->seq = c; 00254 mavlink_update_checksum(rxmsg, c); 00255 status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ; 00256 break; 00257 00258 case MAVLINK_PARSE_STATE_GOT_SEQ: 00259 rxmsg->sysid = c; 00260 mavlink_update_checksum(rxmsg, c); 00261 status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID; 00262 break; 00263 00264 case MAVLINK_PARSE_STATE_GOT_SYSID: 00265 rxmsg->compid = c; 00266 mavlink_update_checksum(rxmsg, c); 00267 status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID; 00268 break; 00269 00270 case MAVLINK_PARSE_STATE_GOT_COMPID: 00271 rxmsg->msgid = c; 00272 mavlink_update_checksum(rxmsg, c); 00273 if (rxmsg->len == 0) 00274 { 00275 status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; 00276 } 00277 else 00278 { 00279 status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID; 00280 } 00281 break; 00282 00283 case MAVLINK_PARSE_STATE_GOT_MSGID: 00284 rxmsg->payload[status->packet_idx++] = c; 00285 mavlink_update_checksum(rxmsg, c); 00286 if (status->packet_idx == rxmsg->len) 00287 { 00288 status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; 00289 } 00290 break; 00291 00292 case MAVLINK_PARSE_STATE_GOT_PAYLOAD: 00293 /* Add seed to checksum depending on message id */ 00294 //mavlink_update_checksum(rxmsg, mavlink_message_crcs[rxmsg->msgid]); 00295 //pc.printf("Calculated Checksum : a %d b %d\n", rxmsg->ck_a, rxmsg->ck_b); 00296 00297 /*if (c != rxmsg->ck_a) 00298 { 00299 // Check first checksum byte 00300 status->parse_error++; 00301 status->msg_received = 0; 00302 status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00303 if (c == MAVLINK_STX) 00304 { 00305 status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; 00306 mavlink_start_checksum(rxmsg); 00307 } 00308 } 00309 else 00310 { 00311 status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1; 00312 }*/ 00313 status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1; 00314 break; 00315 00316 case MAVLINK_PARSE_STATE_GOT_CRC1: 00317 /*if (c != rxmsg->ck_b) 00318 {// Check second checksum byte 00319 status->parse_error++; 00320 status->msg_received = 0; 00321 status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00322 if (c == MAVLINK_STX) 00323 { 00324 status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; 00325 mavlink_start_checksum(rxmsg); 00326 } 00327 } 00328 else 00329 { 00330 // Successfully got message 00331 status->msg_received = 1; 00332 status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00333 memcpy(r_message, rxmsg, sizeof(mavlink_message_t)); 00334 }*/ 00335 status->msg_received = 1; 00336 status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00337 memcpy(r_message, rxmsg, sizeof(mavlink_message_t)); 00338 break; 00339 } 00340 00341 bufferIndex++; 00342 // If a message has been sucessfully decoded, check index 00343 if (status->msg_received == 1) 00344 { 00345 //while(status->current_seq != rxmsg->seq) 00346 //{ 00347 // status->packet_rx_drop_count++; 00348 // status->current_seq++; 00349 //} 00350 status->current_rx_seq = rxmsg->seq; 00351 // Initial condition: If no packet has been received so far, drop count is undefined 00352 if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0; 00353 // Count this packet as received 00354 status->packet_rx_success_count++; 00355 } 00356 00357 r_mavlink_status->current_rx_seq = status->current_rx_seq+1; 00358 r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count; 00359 r_mavlink_status->packet_rx_drop_count = status->parse_error; 00360 status->parse_error = 0; 00361 return status->msg_received; 00362 } 00363 00364 00365 /** 00366 * This is a convenience function which handles the complete MAVLink parsing. 00367 * the function will parse one byte at a time and return the complete packet once 00368 * it could be successfully decoded. Checksum and other failures will be silently 00369 * ignored. 00370 * 00371 * @param chan ID of the current channel. This allows to parse different channels with this function. 00372 * a channel is not a physical message channel like a serial port, but a logic partition of 00373 * the communication streams in this case. COMM_NB is the limit for the number of channels 00374 * on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows 00375 * @param c The char to barse 00376 * 00377 * @param returnMsg NULL if no message could be decoded, the message data else 00378 * @return 0 if no message could be decoded, 1 else 00379 * 00380 * A typical use scenario of this function call is: 00381 * 00382 * @code 00383 * #include <inttypes.h> // For fixed-width uint8_t type 00384 * 00385 * mavlink_message_t msg; 00386 * int chan = 0; 00387 * 00388 * 00389 * while(serial.bytesAvailable > 0) 00390 * { 00391 * uint8_t byte = serial.getNextByte(); 00392 * if (mavlink_parse_char(chan, byte, &msg)) 00393 * { 00394 * printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid); 00395 * } 00396 * } 00397 * 00398 * 00399 * @endcode 00400 */ 00401 00402 #define MAVLINK_PACKET_START_CANDIDATES 50 00403 /* 00404 static inline uint8_t mavlink_parse_char_new(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status) 00405 { 00406 static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NUM_BUFFERS]; 00407 static uint8_t m_msgbuf[MAVLINK_COMM_NUM_BUFFERS][MAVLINK_MAX_PACKET_LEN * 2]; 00408 static uint8_t m_msgbuf_index[MAVLINK_COMM_NUM_BUFFERS]; 00409 static mavlink_message_t m_mavlink_message[MAVLINK_COMM_NUM_BUFFERS]; 00410 static uint8_t m_packet_start[MAVLINK_COMM_NUM_BUFFERS][MAVLINK_PACKET_START_CANDIDATES]; 00411 static uint8_t m_packet_start_index_read[MAVLINK_COMM_NUM_BUFFERS]; 00412 static uint8_t m_packet_start_index_write[MAVLINK_COMM_NUM_BUFFERS]; 00413 00414 // Set a packet start candidate index if sign is start sign 00415 if (c == MAVLINK_STX) 00416 { 00417 m_packet_start[chan][++(m_packet_start_index_write[chan]) % MAVLINK_PACKET_START_CANDIDATES] = m_msgbuf_index[chan]; 00418 } 00419 00420 // Parse normally, if a CRC mismatch occurs retry with the next packet index 00421 } 00422 // static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NUM_BUFFERS]; 00423 // static mavlink_message_t m_mavlink_message[MAVLINK_COMM_NUM_BUFFERS]; 00424 //// Initializes only once, values keep unchanged after first initialization 00425 // mavlink_parse_state_initialize(&m_mavlink_status[chan]); 00426 // 00427 //mavlink_message_t* rxmsg = &m_mavlink_message[chan]; ///< The currently decoded message 00428 //mavlink_status_t* status = &m_mavlink_status[chan]; ///< The current decode status 00429 //int bufferIndex = 0; 00430 // 00431 //status->msg_received = 0; 00432 // 00433 //switch (status->parse_state) 00434 //{ 00435 //case MAVLINK_PARSE_STATE_UNINIT: 00436 //case MAVLINK_PARSE_STATE_IDLE: 00437 // if (c == MAVLINK_STX) 00438 // { 00439 // status->parse_state = MAVLINK_PARSE_STATE_GOT_STX; 00440 // mavlink_start_checksum(rxmsg); 00441 // } 00442 // break; 00443 // 00444 //case MAVLINK_PARSE_STATE_GOT_STX: 00445 // if (status->msg_received) 00446 // { 00447 // status->buffer_overrun++; 00448 // status->parse_error++; 00449 // status->msg_received = 0; 00450 // status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00451 // } 00452 // else 00453 // { 00454 // // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2 00455 // rxmsg->len = c; 00456 // status->packet_idx = 0; 00457 // mavlink_update_checksum(rxmsg, c); 00458 // status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH; 00459 // } 00460 // break; 00461 // 00462 //case MAVLINK_PARSE_STATE_GOT_LENGTH: 00463 // rxmsg->seq = c; 00464 // mavlink_update_checksum(rxmsg, c); 00465 // status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ; 00466 // break; 00467 // 00468 //case MAVLINK_PARSE_STATE_GOT_SEQ: 00469 // rxmsg->sysid = c; 00470 // mavlink_update_checksum(rxmsg, c); 00471 // status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID; 00472 // break; 00473 // 00474 //case MAVLINK_PARSE_STATE_GOT_SYSID: 00475 // rxmsg->compid = c; 00476 // mavlink_update_checksum(rxmsg, c); 00477 // status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID; 00478 // break; 00479 // 00480 //case MAVLINK_PARSE_STATE_GOT_COMPID: 00481 // rxmsg->msgid = c; 00482 // mavlink_update_checksum(rxmsg, c); 00483 // if (rxmsg->len == 0) 00484 // { 00485 // status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; 00486 // } 00487 // else 00488 // { 00489 // status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID; 00490 // } 00491 // break; 00492 // 00493 //case MAVLINK_PARSE_STATE_GOT_MSGID: 00494 // rxmsg->payload[status->packet_idx++] = c; 00495 // mavlink_update_checksum(rxmsg, c); 00496 // if (status->packet_idx == rxmsg->len) 00497 // { 00498 // status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD; 00499 // } 00500 // break; 00501 // 00502 //case MAVLINK_PARSE_STATE_GOT_PAYLOAD: 00503 // if (c != rxmsg->ck_a) 00504 // { 00505 // // Check first checksum byte 00506 // status->parse_error++; 00507 // status->msg_received = 0; 00508 // status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00509 // } 00510 // else 00511 // { 00512 // status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1; 00513 // } 00514 // break; 00515 // 00516 //case MAVLINK_PARSE_STATE_GOT_CRC1: 00517 // if (c != rxmsg->ck_b) 00518 // {// Check second checksum byte 00519 // status->parse_error++; 00520 // status->msg_received = 0; 00521 // status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00522 // } 00523 // else 00524 // { 00525 // // Successfully got message 00526 // status->msg_received = 1; 00527 // status->parse_state = MAVLINK_PARSE_STATE_IDLE; 00528 // memcpy(r_message, rxmsg, sizeof(mavlink_message_t)); 00529 // } 00530 // break; 00531 //} 00532 00533 bufferIndex++; 00534 // If a message has been sucessfully decoded, check index 00535 if (status->msg_received == 1) 00536 { 00537 //while(status->current_seq != rxmsg->seq) 00538 //{ 00539 // status->packet_rx_drop_count++; 00540 // status->current_seq++; 00541 //} 00542 status->current_seq = rxmsg->seq; 00543 // Initial condition: If no packet has been received so far, drop count is undefined 00544 if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0; 00545 // Count this packet as received 00546 status->packet_rx_success_count++; 00547 } 00548 00549 r_mavlink_status->current_seq = status->current_seq+1; 00550 r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count; 00551 r_mavlink_status->packet_rx_drop_count = status->parse_error; 00552 return status->msg_received; 00553 } 00554 */ 00555 00556 00557 typedef union __generic_16bit 00558 { 00559 uint8_t b[2]; 00560 int16_t s; 00561 } generic_16bit; 00562 00563 typedef union __generic_32bit 00564 { 00565 uint8_t b[4]; 00566 float f; 00567 int32_t i; 00568 int16_t s; 00569 } generic_32bit; 00570 00571 typedef union __generic_64bit 00572 { 00573 uint8_t b[8]; 00574 int64_t ll; ///< Long long (64 bit) 00575 double d; ///< IEEE-754 double precision floating point 00576 } generic_64bit; 00577 00578 /** 00579 * @brief Place an unsigned byte into the buffer 00580 * 00581 * @param b the byte to add 00582 * @param bindex the position in the packet 00583 * @param buffer the packet buffer 00584 * @return the new position of the last used byte in the buffer 00585 */ 00586 static inline uint8_t put_uint8_t_by_index(uint8_t b, uint8_t bindex, uint8_t* buffer) 00587 { 00588 *(buffer + bindex) = b; 00589 return sizeof(b); 00590 } 00591 00592 /** 00593 * @brief Place a signed byte into the buffer 00594 * 00595 * @param b the byte to add 00596 * @param bindex the position in the packet 00597 * @param buffer the packet buffer 00598 * @return the new position of the last used byte in the buffer 00599 */ 00600 static inline uint8_t put_int8_t_by_index(int8_t b, int8_t bindex, uint8_t* buffer) 00601 { 00602 *(buffer + bindex) = (uint8_t)b; 00603 return sizeof(b); 00604 } 00605 00606 /** 00607 * @brief Place two unsigned bytes into the buffer 00608 * 00609 * @param b the bytes to add 00610 * @param bindex the position in the packet 00611 * @param buffer the packet buffer 00612 * @return the new position of the last used byte in the buffer 00613 */ 00614 static inline uint8_t put_uint16_t_by_index(uint16_t b, const uint8_t bindex, uint8_t* buffer) 00615 { 00616 buffer[bindex] = (b>>8)&0xff; 00617 buffer[bindex+1] = (b & 0xff); 00618 return sizeof(b); 00619 } 00620 00621 /** 00622 * @brief Place two signed bytes into the buffer 00623 * 00624 * @param b the bytes to add 00625 * @param bindex the position in the packet 00626 * @param buffer the packet buffer 00627 * @return the new position of the last used byte in the buffer 00628 */ 00629 static inline uint8_t put_int16_t_by_index(int16_t b, uint8_t bindex, uint8_t* buffer) 00630 { 00631 return put_uint16_t_by_index(b, bindex, buffer); 00632 } 00633 00634 /** 00635 * @brief Place four unsigned bytes into the buffer 00636 * 00637 * @param b the bytes to add 00638 * @param bindex the position in the packet 00639 * @param buffer the packet buffer 00640 * @return the new position of the last used byte in the buffer 00641 */ 00642 static inline uint8_t put_uint32_t_by_index(uint32_t b, const uint8_t bindex, uint8_t* buffer) 00643 { 00644 buffer[bindex] = (b>>24)&0xff; 00645 buffer[bindex+1] = (b>>16)&0xff; 00646 buffer[bindex+2] = (b>>8)&0xff; 00647 buffer[bindex+3] = (b & 0xff); 00648 return sizeof(b); 00649 } 00650 00651 /** 00652 * @brief Place four signed bytes into the buffer 00653 * 00654 * @param b the bytes to add 00655 * @param bindex the position in the packet 00656 * @param buffer the packet buffer 00657 * @return the new position of the last used byte in the buffer 00658 */ 00659 static inline uint8_t put_int32_t_by_index(int32_t b, uint8_t bindex, uint8_t* buffer) 00660 { 00661 buffer[bindex] = (b>>24)&0xff; 00662 buffer[bindex+1] = (b>>16)&0xff; 00663 buffer[bindex+2] = (b>>8)&0xff; 00664 buffer[bindex+3] = (b & 0xff); 00665 return sizeof(b); 00666 } 00667 00668 /** 00669 * @brief Place four unsigned bytes into the buffer 00670 * 00671 * @param b the bytes to add 00672 * @param bindex the position in the packet 00673 * @param buffer the packet buffer 00674 * @return the new position of the last used byte in the buffer 00675 */ 00676 static inline uint8_t put_uint64_t_by_index(uint64_t b, const uint8_t bindex, uint8_t* buffer) 00677 { 00678 buffer[bindex] = (b>>56)&0xff; 00679 buffer[bindex+1] = (b>>48)&0xff; 00680 buffer[bindex+2] = (b>>40)&0xff; 00681 buffer[bindex+3] = (b>>32)&0xff; 00682 buffer[bindex+4] = (b>>24)&0xff; 00683 buffer[bindex+5] = (b>>16)&0xff; 00684 buffer[bindex+6] = (b>>8)&0xff; 00685 buffer[bindex+7] = (b & 0xff); 00686 return sizeof(b); 00687 } 00688 00689 /** 00690 * @brief Place four signed bytes into the buffer 00691 * 00692 * @param b the bytes to add 00693 * @param bindex the position in the packet 00694 * @param buffer the packet buffer 00695 * @return the new position of the last used byte in the buffer 00696 */ 00697 static inline uint8_t put_int64_t_by_index(int64_t b, uint8_t bindex, uint8_t* buffer) 00698 { 00699 return put_uint64_t_by_index(b, bindex, buffer); 00700 } 00701 00702 /** 00703 * @brief Place a float into the buffer 00704 * 00705 * @param b the float to add 00706 * @param bindex the position in the packet 00707 * @param buffer the packet buffer 00708 * @return the new position of the last used byte in the buffer 00709 */ 00710 static inline uint8_t put_float_by_index(float b, uint8_t bindex, uint8_t* buffer) 00711 { 00712 generic_32bit g; 00713 g.f = b; 00714 return put_int32_t_by_index(g.i, bindex, buffer); 00715 } 00716 00717 /** 00718 * @brief Place a double into the buffer 00719 * 00720 * @param b the double to add 00721 * @param bindex the position in the packet 00722 * @param buffer the packet buffer 00723 * @return the new position of the last used byte in the buffer 00724 */ 00725 static inline uint8_t put_double_by_index(double b, uint8_t bindex, uint8_t* buffer) 00726 { 00727 generic_64bit g; 00728 g.d = b; 00729 return put_int64_t_by_index(g.ll, bindex, buffer); 00730 } 00731 00732 /** 00733 * @brief Place an array into the buffer 00734 * 00735 * @param b the array to add 00736 * @param length size of the array (for strings: length WITH '\0' char) 00737 * @param bindex the position in the packet 00738 * @param buffer packet buffer 00739 * @return new position of the last used byte in the buffer 00740 */ 00741 static inline uint8_t put_array_by_index(const int8_t* b, uint8_t length, uint8_t bindex, uint8_t* buffer) 00742 { 00743 memcpy(buffer+bindex, b, length); 00744 return length; 00745 } 00746 00747 /** 00748 * @brief Place a string into the buffer 00749 * 00750 * @param b the string to add 00751 * @param maxlength size of the array (for strings: length WITHOUT '\0' char) 00752 * @param bindex the position in the packet 00753 * @param buffer packet buffer 00754 * @return new position of the last used byte in the buffer 00755 */ 00756 static inline uint8_t put_string_by_index(const char* b, uint8_t maxlength, uint8_t bindex, uint8_t* buffer) 00757 { 00758 uint16_t length = 0; 00759 // Copy string into buffer, ensuring not to exceed the buffer size 00760 int i; 00761 for (i = 1; i < maxlength; i++) 00762 { 00763 length++; 00764 // String characters 00765 if (i < (maxlength - 1)) 00766 { 00767 buffer[bindex+i] = b[i]; 00768 // Stop at null character 00769 if (b[i] == '\0') 00770 { 00771 break; 00772 } 00773 } 00774 // Enforce null termination at end of buffer 00775 else if (i == (maxlength - 1)) 00776 { 00777 buffer[i] = '\0'; 00778 } 00779 } 00780 // Write length into first field 00781 put_uint8_t_by_index(length, bindex, buffer); 00782 return length; 00783 } 00784 00785 /** 00786 * @brief Put a bitfield of length 1-32 bit into the buffer 00787 * 00788 * @param b the value to add, will be encoded in the bitfield 00789 * @param bits number of bits to use to encode b, e.g. 1 for boolean, 2, 3, etc. 00790 * @param packet_index the position in the packet (the index of the first byte to use) 00791 * @param bit_index the position in the byte (the index of the first bit to use) 00792 * @param buffer packet buffer to write into 00793 * @return new position of the last used byte in the buffer 00794 */ 00795 static inline 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) 00796 { 00797 uint16_t bits_remain = bits; 00798 // Transform number into network order 00799 generic_32bit bin; 00800 generic_32bit bout; 00801 uint8_t i_bit_index, i_byte_index, curr_bits_n; 00802 bin.i = b; 00803 bout.b[0] = bin.b[3]; 00804 bout.b[1] = bin.b[2]; 00805 bout.b[2] = bin.b[1]; 00806 bout.b[3] = bin.b[0]; 00807 00808 // buffer in 00809 // 01100000 01000000 00000000 11110001 00810 // buffer out 00811 // 11110001 00000000 01000000 01100000 00812 00813 // Existing partly filled byte (four free slots) 00814 // 0111xxxx 00815 00816 // Mask n free bits 00817 // 00001111 = 2^0 + 2^1 + 2^2 + 2^3 = 2^n - 1 00818 // = ((uint32_t)(1 << n)) - 1; // = 2^n - 1 00819 00820 // Shift n bits into the right position 00821 // out = in >> n; 00822 00823 // Mask and shift bytes 00824 i_bit_index = bit_index; 00825 i_byte_index = packet_index; 00826 if (bit_index > 0) 00827 { 00828 // If bits were available at start, they were available 00829 // in the byte before the current index 00830 i_byte_index--; 00831 } 00832 00833 // While bits have not been packed yet 00834 while (bits_remain > 0) 00835 { 00836 // Bits still have to be packed 00837 // there can be more than 8 bits, so 00838 // we might have to pack them into more than one byte 00839 00840 // First pack everything we can into the current 'open' byte 00841 //curr_bits_n = bits_remain << 3; // Equals bits_remain mod 8 00842 //FIXME 00843 if (bits_remain <= (8 - i_bit_index)) 00844 { 00845 // Enough space 00846 curr_bits_n = bits_remain; 00847 } 00848 else 00849 { 00850 curr_bits_n = (8 - i_bit_index); 00851 } 00852 00853 // Pack these n bits into the current byte 00854 // Mask out whatever was at that position with ones (xxx11111) 00855 buffer[i_byte_index] &= (0xFF >> (8 - curr_bits_n)); 00856 // Put content to this position, by masking out the non-used part 00857 buffer[i_byte_index] |= ((0x00 << curr_bits_n) & bout.i); 00858 00859 // Increment the bit index 00860 i_bit_index += curr_bits_n; 00861 00862 // Now proceed to the next byte, if necessary 00863 bits_remain -= curr_bits_n; 00864 if (bits_remain > 0) 00865 { 00866 // Offer another 8 bits / one byte 00867 i_byte_index++; 00868 i_bit_index = 0; 00869 } 00870 } 00871 00872 *r_bit_index = i_bit_index; 00873 // If a partly filled byte is present, mark this as consumed 00874 if (i_bit_index != 7) i_byte_index++; 00875 return i_byte_index - packet_index; 00876 } 00877 00878 #ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS 00879 00880 // To make MAVLink work on your MCU, define a similar function 00881 00882 /* 00883 00884 #include "mavlink_types.h" 00885 00886 void comm_send_ch(mavlink_channel_t chan, uint8_t ch) 00887 { 00888 if (chan == MAVLINK_COMM_0) 00889 { 00890 uart0_transmit(ch); 00891 } 00892 if (chan == MAVLINK_COMM_1) 00893 { 00894 uart1_transmit(ch); 00895 } 00896 } 00897 */ 00898 00899 static inline void mavlink_send_uart_uint8_t(mavlink_channel_t chan, uint8_t b, uint16_t* checksum) 00900 { 00901 crc_accumulate(b, checksum); 00902 comm_send_ch(chan, b); 00903 } 00904 00905 static inline void mavlink_send_uart_int8_t(mavlink_channel_t chan, int8_t b, uint16_t* checksum) 00906 { 00907 crc_accumulate(b, checksum); 00908 comm_send_ch(chan, b); 00909 } 00910 00911 static inline void mavlink_send_uart_uint16_t(mavlink_channel_t chan, uint16_t b, uint16_t* checksum) 00912 { 00913 char s; 00914 s = (b>>8)&0xff; 00915 comm_send_ch(chan, s); 00916 crc_accumulate(s, checksum); 00917 s = (b & 0xff); 00918 comm_send_ch(chan, s); 00919 crc_accumulate(s, checksum); 00920 } 00921 00922 static inline void mavlink_send_uart_int16_t(mavlink_channel_t chan, int16_t b, uint16_t* checksum) 00923 { 00924 mavlink_send_uart_uint16_t(chan, b, checksum); 00925 } 00926 00927 static inline void mavlink_send_uart_uint32_t(mavlink_channel_t chan, uint32_t b, uint16_t* checksum) 00928 { 00929 char s; 00930 s = (b>>24)&0xff; 00931 comm_send_ch(chan, s); 00932 crc_accumulate(s, checksum); 00933 s = (b>>16)&0xff; 00934 comm_send_ch(chan, s); 00935 crc_accumulate(s, checksum); 00936 s = (b>>8)&0xff; 00937 comm_send_ch(chan, s); 00938 crc_accumulate(s, checksum); 00939 s = (b & 0xff); 00940 comm_send_ch(chan, s); 00941 crc_accumulate(s, checksum); 00942 } 00943 00944 static inline void mavlink_send_uart_int32_t(mavlink_channel_t chan, int32_t b, uint16_t* checksum) 00945 { 00946 mavlink_send_uart_uint32_t(chan, b, checksum); 00947 } 00948 00949 static inline void mavlink_send_uart_uint64_t(mavlink_channel_t chan, uint64_t b, uint16_t* checksum) 00950 { 00951 char s; 00952 s = (b>>56)&0xff; 00953 comm_send_ch(chan, s); 00954 crc_accumulate(s, checksum); 00955 s = (b>>48)&0xff; 00956 comm_send_ch(chan, s); 00957 crc_accumulate(s, checksum); 00958 s = (b>>40)&0xff; 00959 comm_send_ch(chan, s); 00960 crc_accumulate(s, checksum); 00961 s = (b>>32)&0xff; 00962 comm_send_ch(chan, s); 00963 crc_accumulate(s, checksum); 00964 s = (b>>24)&0xff; 00965 comm_send_ch(chan, s); 00966 crc_accumulate(s, checksum); 00967 s = (b>>16)&0xff; 00968 comm_send_ch(chan, s); 00969 crc_accumulate(s, checksum); 00970 s = (b>>8)&0xff; 00971 comm_send_ch(chan, s); 00972 crc_accumulate(s, checksum); 00973 s = (b & 0xff); 00974 comm_send_ch(chan, s); 00975 crc_accumulate(s, checksum); 00976 } 00977 00978 static inline void mavlink_send_uart_int64_t(mavlink_channel_t chan, int64_t b, uint16_t* checksum) 00979 { 00980 mavlink_send_uart_uint64_t(chan, b, checksum); 00981 } 00982 00983 static inline void mavlink_send_uart_float(mavlink_channel_t chan, float b, uint16_t* checksum) 00984 { 00985 generic_32bit g; 00986 g.f = b; 00987 mavlink_send_uart_uint32_t(chan, g.i, checksum); 00988 } 00989 00990 static inline void mavlink_send_uart_double(mavlink_channel_t chan, double b, uint16_t* checksum) 00991 { 00992 generic_64bit g; 00993 g.d = b; 00994 mavlink_send_uart_uint32_t(chan, g.ll, checksum); 00995 } 00996 00997 static inline void mavlink_send_uart(mavlink_channel_t chan, mavlink_message_t* msg) 00998 { 00999 // ARM7 MCU board implementation 01000 // Create pointer on message struct 01001 // Send STX 01002 comm_send_ch(chan, MAVLINK_STX); 01003 comm_send_ch(chan, msg->len); 01004 comm_send_ch(chan, msg->seq); 01005 comm_send_ch(chan, msg->sysid); 01006 comm_send_ch(chan, msg->compid); 01007 comm_send_ch(chan, msg->msgid); 01008 for(uint16_t i = 0; i < msg->len; i++) 01009 { 01010 comm_send_ch(chan, msg->payload[i]); 01011 } 01012 comm_send_ch(chan, msg->ck_a); 01013 comm_send_ch(chan, msg->ck_b); 01014 } 01015 #endif 01016 01017 #endif /* _MAVLINK_PROTOCOL_H_ */
Generated on Wed Jul 13 2022 02:33:40 by
1.7.2