forked from Darwinnpos/tmc5160
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtmc5160_api_header.c
More file actions
222 lines (194 loc) · 8.12 KB
/
Copy pathtmc5160_api_header.c
File metadata and controls
222 lines (194 loc) · 8.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-11-27 Fpi_lc the first version
*/
//part 1
/*
* CRC.c
*
* Created on: 04.12.2017
* Author: LH
*
* This is a generic implementation for a CRC8 generator supporting
* both compile-time (1) and run-time initialized Lookup tables for efficient CRC8 calculation.
* You can store multiple tables for different polynomials and (non-)reflected CRCs.
* The different tables are referenced by an index, with an upper limit set at compile time (CRC_TABLE_COUNT).
*
* To generate CRCs you must first generate the Lookup-table by calling fillCRCTable()
* with any index. CRCs can then be generated from any data buffer by calling CRC()
* with the same index previously given to fillCRCTable().
*
* The table generation has been optimized for speed so that the runtime
* table generation can even be done during normal operation if required.
* However, as long as the required polynomials are known on initialization,
* the table generation should be done at that time.
* On the Landungsbruecke the initialization of a CRC table takes ~250µs. (2)
* Should your application still have problems with the table calculation time,
* this algorithm could probably be speed up by preparing a 2- or 4-bit lookup table
* to speed up the actual table generation.
*
* (1): For compile-time CRC tables, just fill the table(s) by initializing CRCTables[] to the proper values.
* (2): Tested by toggling a GPIO pin, generating a table in-between and measuring the GPIO pulse width.
*/
#include "packages/tmc5160/include/tmc5160_api_header.h"
typedef struct {
uint8_t table[256];
uint8_t polynomial;
bool isReflected;
} CRCTypeDef;
CRCTypeDef CRCTables[CRC_TABLE_COUNT] = { 0 };
static uint8_t flipByte(uint8_t value);
static uint32_t flipBitsInBytes(uint32_t value);
/* This function generates the Lookup table used for CRC calculations.
*
* Arguments:
* uint8_t polynomial: The CRC polynomial for which the table will be generated.
* bool isReflected: Indicator whether the CRC table will be reflected or not.
* uint8_t index: The index of the table to be filled.
*
* How it works:
* A CRC calculation of a byte can be done by taking the byte to be CRC'd,
* shifting it left by one (appending a 0) and - if a 1 has been shifted out -
* XOR-ing in the CRC polynomial. After 8 iterations the result will be the
* CRC of the Byte.
*
* The function below does this in a compact way, by using all 4 bytes of a
* uint32_t to do 4 separate CRC bytes at once.
* For this to work without the Byte shifting interfering with adjacent bytes,
* the polynomial has the 8th bit (0x100) set. That way, if the shifted-out bit
* is 1, the following XOR-ing with the CRC polynomial will set that 1 to a 0,
* resulting in the shifted-in 0 for the adjacent byte.
* This process will go from the the lowest to the highest byte, resulting in
* fully independent byte-wise CRC calculations. For the highest byte, the value
* of the shifted-out byte needs to be stored before shifting the bytes (isMSBSet).
*
* The for-loop that iterates over all uint8_t values starts out with the
* uint8_t values 3 to 0 stored in one uint32_t: 0x03020100
* for each iteration each uint8_t value will increase by 4..
* 0 -> 4 -> 8 -> C -> ...
* 1 -> 5 -> 9 -> D -> ...
* 2 -> 6 -> A -> E -> ...
* 3 -> 7 -> B -> F -> ...
* ..resulting in an increase of the uint32_t by 0x04040404:
* 0x03020100 -> 0x07060504 -> 0x0B0A0908 -> 0x0F0E0D0C -> ...
* The loop ends as soon as we have iterated over all uint8_t values.
* We detect that by looking for the byte-wise overflow into the next byte:
* 0xFFFEFDFC <- last uint32_t value to be calculated
* 0xFF, 0xFE, 0xFD, 0xFC <- the corresponding uint8_t values
* 0x103, 0x102, 0x101, 0x100 <- incremented uint8_t values (overflow into the next byte!)
* 0x04030200 <- uint32_t value with the overflowed bytes
*
* We have the lower uint8_t values at the lower bytes of the uint32_t.
* This allows us to simply store the lowest byte of the uint32_t,
* right-shift the uint32_t by 8 and increment the table pointer.
* After 4 iterations of that all 4 bytes of the uint32_t are stored in the table.
*/
uint8_t tmc_fillCRC8Table(uint8_t polynomial, bool isReflected, uint8_t index)
{
uint32_t CRCdata;
// Helper pointer for traversing the result table
uint8_t *table;
if(index >= CRC_TABLE_COUNT)
return 0;
CRCTables[index].polynomial = polynomial;
CRCTables[index].isReflected = isReflected;
table = &CRCTables[index].table[0];
// Extend the polynomial to correct byte MSBs shifting into next bytes
uint32_t poly = (uint32_t) polynomial | 0x0100;
// Iterate over all 256 possible uint8_t values, compressed into a uint32_t (see detailed explanation above)
uint32_t i;
for(i = 0x03020100; i != 0x04030200; i+=0x04040404)
{
// For reflected table: Flip the bits of each input byte
CRCdata = (isReflected)? flipBitsInBytes(i) : i;
// Iterate over 8 Bits
int j;
for(j = 0; j < 8; j++)
{
// Store value of soon-to-be shifted out byte
uint8_t isMSBSet = (CRCdata & 0x80000000)? 1:0;
// CRC Shift
CRCdata <<= 1;
// XOR the bytes when required, lowest to highest
CRCdata ^= (CRCdata & 0x00000100)? (poly ) : 0;
CRCdata ^= (CRCdata & 0x00010000)? (poly << 8 ) : 0;
CRCdata ^= (CRCdata & 0x01000000)? (poly << 16) : 0;
CRCdata ^= (isMSBSet)? (poly << 24) : 0;
}
// For reflected table: Flip the bits of each output byte
CRCdata = (isReflected)? flipBitsInBytes(CRCdata) : CRCdata;
// Store the CRC result bytes in the table array
*table++ = (uint8_t) CRCdata;
CRCdata >>= 8;
*table++ = (uint8_t) CRCdata;
CRCdata >>= 8;
*table++ = (uint8_t) CRCdata;
CRCdata >>= 8;
*table++ = (uint8_t) CRCdata;
}
return 1;
}
/* This function calculates the CRC from a data buffer
*
* Arguments:
* uint8_t *data: A pointer to the data that will be CRC'd.
* uint32_t bytes: The length of the data buffer.
* uint8_t index: The index of the CRC table to be used.
*/
uint8_t tmc_CRC8(uint8_t *data, uint32_t bytes, uint8_t index)
{
uint8_t result = 0;
uint8_t *table;
if(index >= CRC_TABLE_COUNT)
return 0;
table = &CRCTables[index].table[0];
while(bytes--)
result = table[result ^ *data++];
return (CRCTables[index].isReflected)? flipByte(result) : result;
}
uint8_t tmc_tableGetPolynomial(uint8_t index)
{
if(index >= CRC_TABLE_COUNT)
return 0;
return CRCTables[index].polynomial;
}
bool tmc_tableIsReflected(uint8_t index)
{
if(index >= CRC_TABLE_COUNT)
return false;
return CRCTables[index].isReflected;
}
// Helper functions
static uint8_t flipByte(uint8_t value)
{
// swap odd and even bits
value = ((value >> 1) & 0x55) | ((value & 0x55) << 1);
// swap consecutive pairs
value = ((value >> 2) & 0x33) | ((value & 0x33) << 2);
// swap nibbles ...
value = ((value >> 4) & 0x0F) | ((value & 0x0F) << 4);
return value;
}
/* This helper function switches all bits within each byte.
* The byte order remains the same:
* [b31 b30 b29 b28 b27 b26 b25 b24 .. b7 b6 b5 b4 b3 b2 b1 b0]
* ||
* \||/
* \/
* [b24 b25 b26 b27 b28 b29 b30 b31 .. b0 b1 b2 b3 b4 b5 b6 b7]
*/
static uint32_t flipBitsInBytes(uint32_t value)
{
// swap odd and even bits
value = ((value >> 1) & 0x55555555) | ((value & 0x55555555) << 1);
// swap consecutive pairs
value = ((value >> 2) & 0x33333333) | ((value & 0x33333333) << 2);
// swap nibbles ...
value = ((value >> 4) & 0x0F0F0F0F) | ((value & 0x0F0F0F0F) << 4);
return value;
}