forked from parallaxinc/spin-standard-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmath.crc.spin
295 lines (231 loc) · 8.9 KB
/
math.crc.spin
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
{
----------------------------------------------------------------------------------------------------
Filename: math.crc.spin
Description: A collection of CRC and checksum routines
Author: Jesse Burt
Started: Nov 19, 2017
Updated: Feb 23, 2025
Copyright (c) 2025 - See end of file for terms of use.
----------------------------------------------------------------------------------------------------
}
CON
' predefined polynomials usable with CRC routines
POLY8_ASAIR = $131
POLY8_DSMAX = $8C
POLY8_MEAS = $31
POLY8_MELEXIS = $107
POLY8_SD = $09
POLY8_SENSIRION = $31
POLY8_SILABS = $131
POLY16_DSMAX = $A001
POLY16_XYZMODEM = $1021
POLY32_ZMODEM = $EDB88320
PUB asaircrc8(ptr_data, len): crc
' CRC8 for ASAIR temp/RH sensors
return crc8(ptr_data, len, $ff, 0, POLY8_ASAIR, false, false)
PUB checksum8_twos_comp(p_buff, len): c
' 8-bit checksum, two's-complement
' p_buff: pointer to buffer of data to checksum
' len: length of data in bytes
' Returns: 8-bit checksum
repeat while len ' continue as long as there's still data left
c := (c + byte[p_buff++]) & $ff ' sum each byte of data (discard bits >7)
len--
return ( ( $ff - c ) + 1 ) ' return two's complement of the sum
PUB inet_chksum(p_buff, len, iv=0): ck | i
' Checksum used in various internet datagrams
' p_buff: pointer to buffer of data to calculate checksum
' len: length of data
' iv: optional initial value to add to this checksum, e.g., the checksum of a
' UDP or TCP pseudo-header.
' handle edge cases; these shouldn't generally happen, but should offer basic protection
if ( len == 0 )
return 0
if ( len == 1 )
return !( (byte[p_buff][0] << 8) & $ffff)
'
ck := 0
' Process two bytes at a time
repeat i from 0 to (len-2) step 2
ck += (byte[p_buff][i] << 8) | byte[p_buff][i+1]
' Handle an odd-length buffer by padding with zero
if ( len & 1 )
ck += byte[p_buff][len-1] << 8
' Add the optional pseudo-header check
ck += iv
' Fold carry into lower 16 bits (repeated if needed)
repeat while (ck > $ffff)
ck := (ck & $ffff) + (ck >> 16)
' Return one's complement of the result
return !ck & $ffff
PUB meas_crc8(data, len): crc | currbyte, i, j
' Measurement specialties CRC8
crc := $00
repeat i from 0 to len-1
currbyte := byte[data][(len-1)-i]
crc := crc ^ currbyte
repeat j from 0 to 7
if (crc & $80)
crc := (crc << 1) ^ POLY8_MEAS
else
crc := (crc << 1)
crc ^= $00
return crc & $FF
PUB sd_crc7(ptr_data, len): crc | byte_nr, bit_nr, curr_byte
' MMC/SD CRC7
crc := $00
repeat byte_nr from 0 to len-1
curr_byte := byte[ptr_data][byte_nr]
repeat bit_nr from 0 to 7
crc <<= 1
if ((curr_byte & $80) ^ (crc & $80))
crc ^= POLY8_SD
curr_byte <<= 1
return ((crc << 1) | 1) & $FF
PUB sensirion_crc8(data, len): crc | currbyte, i, j
crc := $FF
repeat i from 0 to len-1
currbyte := byte[data][(len-1)-i]
crc := crc ^ currbyte
repeat j from 0 to 7
if (crc & $80)
crc := (crc << 1) ^ POLY8_SENSIRION
else
crc := (crc << 1)
crc ^= $00
return crc & $FF
PUB silabs_crc8(data, len): crc | currbyte, i, j
crc := $00
repeat i from 0 to len-1
currbyte := byte[data][(len-1)-i]
crc := crc ^ currbyte
repeat j from 0 to 7
if (crc & $80)
crc := (crc << 1) ^ POLY8_SILABS
else
crc := (crc << 1)
crc ^= $00
return crc & $FF
PUB dallas_maxim_crc8(data, len): crc | currbyte, i, j, mix
crc := $00
repeat i from 0 to len-1
currbyte := byte[data][i]
repeat j from 0 to 7
mix := (crc ^ currbyte) & $01
crc >>= 1
if mix
crc ^= POLY8_DSMAX
currbyte >>= 1
return
PUB dallas_maxim_crc16(data, len): crc | currbyte, i, j, mix
crc := $00
repeat i from 0 to len-1
currbyte := byte[data][i]
repeat j from 0 to 7
mix := (crc ^ currbyte) & $01
crc >>= 1
if mix
crc ^= POLY16_DSMAX
currbyte >>= 1
return
PUB xor_checksum(p_data, len, init=0): c
' XOR checksum
' p_data: pointer to data to checksum
' len: length of data to checksum
' init: value to initialize checksum to (default is 0 if unspecified)
' Returns:
' checksum
c := init
repeat len
c := (c ^ byte[p_data++])
PUB xyzm_crc16(ptr_data, len): crc
' X/Y/ZModem 16bit CRC
' ptr_data: pointer to data
' data_len: length of data, in bytes
return crc16(ptr_data, len, $0000, 0, POLY16_XYZMODEM, false, false)
PUB zm_crc32(ptr_data, len): crc
' ZModem 32bit CRC
' ptr_data: pointer to data
' data_len: length of data, in bytes
return crc32(ptr_data, len, $FFFFFFFF, true, POLY32_ZMODEM, false, false)
PUB crc8(ptr_data, data_len, init, xorout, poly, ireflect, oreflect): crc | curr_byte, bit
' Calculate CRC8
' ptr_data: pointer to data
' data_len: length of data, in bytes (u31)
' init: value to initialize CRC with (u32)
' xorout: value to XOR final CRC with (u32)
' poly: polynomial to use in CRC calculation (u32)
' ireflect: bitwise reverse initial value? (bool)
' oreflect: bitwise reverse final value? (bool)
crc := init
if (ireflect) ' reflect initial value?
crc ><= 8
repeat curr_byte from 0 to (data_len-1)
crc ^= byte[ptr_data][curr_byte]
repeat bit from 0 to 7
if (crc & $80)
crc := (crc << 1) ^ poly
else
crc := (crc << 1)
if (oreflect) ' reflect final value?
crc ><= 8
return (crc ^ xorout) & $ff
PUB crc16(ptr_data, data_len, init, xorout, poly, ireflect, oreflect): crc | curr_byte, bit
' Calculate CRC16
' ptr_data: pointer to data
' data_len: length of data, in bytes
' init: value to initialize CRC with
' poly: polynomial to use in CRC calculation
' reflect: whether to bitwise-reverse data bytes read
crc := init ' initialize CRC
if (ireflect) ' reflect initial value?
crc ><= 16
repeat curr_byte from 0 to data_len-1
crc ^= (byte[ptr_data][curr_byte] << 8)
repeat bit from 7 to 0
if (crc & $8000)
crc := (crc << 1) ^ poly
else
crc := (crc << 1)
if (oreflect) ' reflect final value?
crc ><= 16
return ((crc ^ xorout) & $ffff)
PUB crc32(ptr_data, data_len, init, xorout, poly, ireflect, oreflect): crc | curr_byte, bit
' Calculate CRC32
' ptr_data: pointer to data
' data_len: length of data, in bytes (u31)
' init: value to initialize CRC with (u32)
' xorout: value to XOR final CRC with (u32)
' poly: polynomial to use in CRC calculation (u32)
' ireflect: bitwise reverse initial value? (bool)
' oreflect: bitwise reverse final value? (bool)
crc := init ' initialize CRC
if (ireflect) ' reflect initial value?
crc ><= 32
data_len-- ' pre-calc for loop
repeat curr_byte from 0 to data_len
crc ^= byte[ptr_data][curr_byte]
repeat bit from 7 to 0
if (crc & $01)
crc := (crc >> 1) ^ poly
else
crc := (crc >> 1)
if (oreflect) ' reflect final value?
crc ><= 32
return crc ^ xorout
DAT
{
Copyright 2025 Jesse Burt
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}