Arduino_VESC_Library
vesc_packet.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the arduino vesc library (https://github.com/arduino_vesc)
3  *
4  * Copyright (c) 2019 Gianmarco Vitelli
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 3.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <Arduino.h>
20 #include <HardwareSerial.h>
21 #include "vesc_packet.h"
22 
30 void VescPacket::send_packet(HardwareSerial *port, unsigned char *data, unsigned int len)
31 {
32  uint8_t tx_buffer[600];
33 
34  if (len == 0 || len > 255)
35  {
36  return;
37  }
38 
39  int b_ind = 0;
40 
41  if (len <= 512)
42  {
43  tx_buffer[b_ind++] = 2;
44  tx_buffer[b_ind++] = len;
45  }
46  else if (len <= 65535)
47  {
48  tx_buffer[b_ind++] = 3;
49  tx_buffer[b_ind++] = len >> 8;
50  tx_buffer[b_ind++] = len & 0xFF;
51  }
52  else
53  {
54  tx_buffer[b_ind++] = 4;
55  tx_buffer[b_ind++] = len >> 16;
56  tx_buffer[b_ind++] = (len >> 8) & 0x0F;
57  tx_buffer[b_ind++] = len & 0xFF;
58  }
59 
60  memcpy(tx_buffer + b_ind, data, len);
61  b_ind += len;
62 
63  unsigned short crc = crc16(data, len);
64  tx_buffer[b_ind++] = (uint8_t)(crc >> 8);
65  tx_buffer[b_ind++] = (uint8_t)(crc & 0xFF);
66  tx_buffer[b_ind++] = 3;
67 
68  port->write(tx_buffer, b_ind);
69  port->flush();
70 }
71 
80 bool VescPacket::receive_packet(HardwareSerial *port, unsigned char *data)
81 {
82 
83  for (; port->available() == 0;)
84  {
85  delay(100);
86  }
87 
88  unsigned char rx_buffer[600];
89  int b_ind = 0;
90  int type = rx_buffer[b_ind++] = port->read();
91 
92  uint8_t len;
93  switch (type)
94  {
95  case 2:
96  len = rx_buffer[b_ind++] = port->read();
97  break;
98  case 3:
99  len = (rx_buffer[b_ind++] = port->read()) << 8 |
100  (rx_buffer[b_ind++] = port->read());
101  break;
102  case 4:
103  len = (rx_buffer[b_ind++] = port->read()) << 16 |
104  (rx_buffer[b_ind++] = port->read()) << 8 |
105  (rx_buffer[b_ind++] = port->read());
106  break;
107  default:
108  return false;
109  }
110 
111  for (int i = 0; i < len; i++)
112  {
113  rx_buffer[b_ind++] = port->read();
114  }
115 
116  unsigned short crc_calc = crc16(rx_buffer + type, len);
117  unsigned short crc_rx = (unsigned short)(rx_buffer[len + 2] = port->read()) << 8 | (unsigned short) port->read();
118  unsigned short packet_end = (rx_buffer[len + 3] = port->read());
119  if (crc_calc == crc_rx && packet_end == 3)
120  {
121  memcpy(data, rx_buffer + type, len);
122  return true;
123  }
124 
125  return false;
126 }
127 
131 const unsigned short crc16_tab[] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084,
132  0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad,
133  0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7,
134  0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
135  0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a,
136  0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672,
137  0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719,
138  0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7,
139  0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948,
140  0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50,
141  0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b,
142  0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
143  0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97,
144  0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe,
145  0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca,
146  0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3,
147  0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d,
148  0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214,
149  0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c,
150  0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
151  0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3,
152  0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d,
153  0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806,
154  0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e,
155  0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1,
156  0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b,
157  0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0,
158  0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
159  0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
160 
168 unsigned short VescPacket::crc16(unsigned char *buf, unsigned int len)
169 {
170  unsigned int i;
171  unsigned short cksum = 0;
172  for (i = 0; i < len; i++)
173  {
174  cksum = crc16_tab[(((cksum >> 8) ^ *buf++) & 0xFF)] ^ (cksum << 8);
175  }
176  return cksum;
177 }
vesc_packet.h
crc16_tab
const unsigned short crc16_tab[]
table of crc16
Definition: vesc_packet.cpp:131
VescPacket::send_packet
static void send_packet(HardwareSerial *port, unsigned char *data, unsigned int len)
send packet to vesc
Definition: vesc_packet.cpp:30
VescPacket::crc16
static unsigned short crc16(unsigned char *buf, unsigned int len)
generate crc16
Definition: vesc_packet.cpp:168
VescPacket::receive_packet
static bool receive_packet(HardwareSerial *port, unsigned char *data)
receive packet from vesc
Definition: vesc_packet.cpp:80