an_packet_protocol.c
Go to the documentation of this file.
1 /****************************************************************/
2 /* */
3 /* Advanced Navigation Packet Protocol Library */
4 /* C Language Dynamic Spatial SDK, Version 4.0 */
5 /* Copyright 2014, Xavier Orr, Advanced Navigation Pty Ltd */
6 /* */
7 /****************************************************************/
8 /*
9  * Copyright (C) 2014 Advanced Navigation Pty Ltd
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining
12  * a copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  */
29 
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <string.h>
33 #include "an_packet_protocol.h"
34 
35 /*
36  * Function to calculate the CRC16 of data
37  * CRC16-CCITT
38  * Initial value = 0xFFFF
39  * Polynomial = x^16 + x^12 + x^5 + x^0
40  */
41 uint16_t calculate_crc16(const void *data, uint16_t length)
42 {
43  uint8_t *bytes = (uint8_t *) data;
44  uint16_t crc = 0xFFFF, i;
45  for (i = 0; i < length; i++)
46  {
47  crc = (uint16_t)((crc << 8) ^ crc16_table[(crc >> 8) ^ bytes[i]]);
48  }
49  return crc;
50 }
51 
52 /*
53  * Function to calculate a 4 byte LRC
54  */
55 uint8_t calculate_header_lrc(uint8_t *data)
56 {
57  return ((data[0] + data[1] + data[2] + data[3]) ^ 0xFF) + 1;
58 }
59 
60 /*
61  * Function to dynamically allocate an an_packet
62  */
63 an_packet_t *an_packet_allocate(uint8_t length, uint8_t id)
64 {
65  an_packet_t *an_packet = malloc(sizeof(an_packet_t) + length * sizeof(uint8_t));
66  if (an_packet != NULL)
67  {
68  an_packet->id = id;
69  an_packet->length = length;
70  }
71  return an_packet;
72 }
73 
74 /*
75  * Function to free an an_packet
76  */
77 void an_packet_free(an_packet_t **an_packet)
78 {
79  free(*an_packet);
80  *an_packet = NULL;
81 }
82 
83 /*
84  * Initialise the decoder
85  */
87 {
88  an_decoder->buffer_length = 0;
89  an_decoder->crc_errors = 0;
90 }
91 
92 /*
93  * Function to decode an_packets from raw data
94  * Returns a pointer to the packet decoded or NULL if no packet was decoded
95  */
97 {
98  uint16_t decode_iterator = 0;
99  an_packet_t *an_packet = NULL;
100  uint8_t header_lrc, id, length;
101  uint16_t crc;
102 
103  while (decode_iterator + AN_PACKET_HEADER_SIZE <= an_decoder->buffer_length)
104  {
105  header_lrc = an_decoder->buffer[decode_iterator++];
106  if (header_lrc == calculate_header_lrc(&an_decoder->buffer[decode_iterator]))
107  {
108  id = an_decoder->buffer[decode_iterator++];
109  length = an_decoder->buffer[decode_iterator++];
110  crc = an_decoder->buffer[decode_iterator++];
111  crc |= an_decoder->buffer[decode_iterator++] << 8;
112 
113  if (decode_iterator + length > an_decoder->buffer_length)
114  {
115  decode_iterator -= AN_PACKET_HEADER_SIZE;
116  break;
117  }
118 
119  if (crc == calculate_crc16(&an_decoder->buffer[decode_iterator], length))
120  {
121  an_packet = an_packet_allocate(length, id);
122  if (an_packet != NULL)
123  {
124  memcpy(an_packet->header, &an_decoder->buffer[decode_iterator - AN_PACKET_HEADER_SIZE], AN_PACKET_HEADER_SIZE * sizeof(uint8_t));
125  memcpy(an_packet->data, &an_decoder->buffer[decode_iterator], length * sizeof(uint8_t));
126  }
127  decode_iterator += length;
128  break;
129  }
130  else
131  {
132  decode_iterator -= (AN_PACKET_HEADER_SIZE - 1);
133  an_decoder->crc_errors++;
134  }
135  }
136  }
137  if (decode_iterator < an_decoder->buffer_length)
138  {
139  if (decode_iterator > 0)
140  {
141  memmove(&an_decoder->buffer[0], &an_decoder->buffer[decode_iterator], (an_decoder->buffer_length - decode_iterator) * sizeof(uint8_t));
142  an_decoder->buffer_length -= decode_iterator;
143  }
144  }
145  else an_decoder->buffer_length = 0;
146 
147  return an_packet;
148 }
149 
150 /*
151  * Function to encode an an_packet
152  */
154 {
155  uint16_t crc;
156  an_packet->header[1] = an_packet->id;
157  an_packet->header[2] = an_packet->length;
158  crc = calculate_crc16(an_packet->data, an_packet->length);
159  memcpy(&an_packet->header[3], &crc, sizeof(uint16_t));
160  an_packet->header[0] = calculate_header_lrc(&an_packet->header[1]);
161 }
162 
static const uint16_t crc16_table[256]
uint8_t data[1]
an_packet_t * an_packet_decode(an_decoder_t *an_decoder)
void an_packet_encode(an_packet_t *an_packet)
uint16_t calculate_crc16(const void *data, uint16_t length)
an_packet_t * an_packet_allocate(uint8_t length, uint8_t id)
void an_decoder_initialise(an_decoder_t *an_decoder)
uint8_t buffer[AN_DECODE_BUFFER_SIZE]
void an_packet_free(an_packet_t **an_packet)
uint8_t calculate_header_lrc(uint8_t *data)
uint16_t buffer_length
#define AN_PACKET_HEADER_SIZE
uint8_t header[AN_PACKET_HEADER_SIZE]


advanced_navigation_driver
Author(s):
autogenerated on Thu Jun 6 2019 19:13:08