\ *****************************************************************************
\ CRC-8.4th V0.1.0 2020 Sep 04 ANS Forth
\ CRC-8 calculation using a table loaded at run time
\ *****************************************************************************
0 [IF]
From : https://en.wikipedia.org/wiki/Cyclic_redundancy_check
"A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data."
Note : the Polynomial is often specified in reverse bit order, e.g. $F1 is shown as $07 .
The CRC calculation can either be in normal order, following the Big Endian description of the polynomial,
or in "reverse" order where the bits are reversed (which can be calculated more efficiently on Little Endian processors).
There is some confusion online about which of these is "reverse".
Usage
=====
Define your CRC8 parameters and create a definition line like :
\ Name Poly Init Xor Rev 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Name
create CRC-8/_ lineC, 07 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " CRC-8/_"
Run
0 v_Silent ! \ do not show test details
CRC-8/_ CRC8table_Init Show_CRC8_test
To show the results of the test, which will mostly fail :
\ Name Poly Init Xor Rev 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Name
create CRC-8/_ lineC, 07 00 00 FF 00 F4 6C 34 90 6E 68 42 ED 83 B1 CA A0 BD D7 00 30 " CRC-8/_"
Copy the results of the test back into the CRC-8/_ definition line and repeat the test.
The test results should be checked using an external reference :
e.g. https://crccalc.com/ or http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
To display all test results :
empty include crc8 Show_CRC8tests_all
the output is the CRC8 definitions lines used to create the tests.
CRC tables can be generated for use in systems with limited RAM, for Forth :
CRC-8/_ CRC8table_Init Show_CRC8table
or for C code :
CRC-8/_ CRC8table_Init Show_CRC8table_C
The word lineC, is defined to parse the text following it and add hex numbers, strings
and counted strings to the table. This makes the source code easier to read.
[THEN]
\ *****************************************************************************
\ Create CRC8 parameter definitions
\ *****************************************************************************
[UNDEFINED] 2.hex [IF]
: 2.hex ( c -- ) base @ >r hex 0 <# # # #> type r> base ! ;
[THEN]
[UNDEFINED] 4.hex [IF]
: 4.hex ( c -- ) base @ >r hex 0 <# # # # # #> type r> base ! ;
[THEN]
[UNDEFINED] ToColumn [IF]
: ToColumn ( u -- ) get-xy drop - 1 max 200 min spaces ; \ move to the given column number
[THEN]
[UNDEFINED] dumpL [IF]
\ dump on the same line
: dumpL ( a n -- ) 0 max $100 min space dup 2.hex ." | " over + swap ?do i c@ 2.hex space loop ;
[THEN]
[UNDEFINED] lineC, [IF]
\ Add up to 128 bytes to a structure, using the 128 hex ASCII words following, then ignore the rest of the line.
: lineC, ( -- )
base @ >r hex \ save the current number base on the return stack and change to hexadecimal
$80 0 do \ loop up to 128 times, or until something makes us "leave"
bl word count
dup 0= if 2drop leave then \ there are no more words on the line, so leave the loop
2dup s" \" compare 0= if 2drop leave then \ we have found a "comment until end of line" character, so leave the loop
2dup NUMBER? case \ NUMBER? returns 0, 1 or 2 plus 0, 1 or 2 cells on the stack
0 of
dup 1 = if
over c@ [char] " = if [CHAR] " STRING then \ " AAAA" will be added as a counted string AAAA with null terminator
over c@ [char] % = if [CHAR] % STRING then \ % BBBB% will be added as a counted string BBBB with null terminator
2drop
else
\ "AAAA" will be added as the string AAAA , %BBBB% will be added as the string BBBB
over c@ [CHAR] " = if 1 /string over + swap ?do i c@ dup [CHAR] " = if drop leave else c, then loop then
over c@ [CHAR] % = if 1 /string over + swap ?do i c@ dup [CHAR] % = if drop leave else c, then loop then
then
endof
1 of c, 2drop endof
2 of , 2drop endof
endcase
loop
r> base ! \ restore the number base from the return stack
postpone \ \ perform the action of "\", ignore everything until the end of the line
\ "postpone" means don't do this now, but when lineC, is called
;
[THEN]
\ | ... Test results ... |
\ Name Poly Init Xor Rev 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Name
create CRC-8/_ lineC, 07 00 00 FF 00 F4 6C 34 90 6E 68 42 ED 83 B1 CA A0 BD D7 00 30 " CRC-8/_"
create CRC-8/CDMA2000 lineC, 9B FF 00 FF FF DA B7 BC 2D EA 58 06 7D D9 99 77 C9 39 87 AC F6 " CRC-8/CDMA2000"
create CRC-8/DARC lineC, 39 00 00 00 00 15 A3 6F A8 BA 5C 4A F3 81 73 84 AE F9 D3 00 8F " CRC-8/DARC"
create CRC-8/DVB-S2 lineC, D5 00 00 FF 00 BC B8 EF F6 26 BA 06 AF E6 E4 F0 D2 06 24 00 2E " CRC-8/DVB-S2"
create CRC-8/EBU lineC, 1D FF 00 00 FF 97 04 34 1A 31 C5 A7 7D FB 16 1E FE D7 37 A1 94 " CRC-8/EBU"
create CRC-8/I-CODE lineC, 1D FD 00 FF FD 7E 87 E7 B4 4F 5B E8 B3 9C 5E 63 4A 8F A6 27 BC " CRC-8/I-CODE"
create CRC-8/ITU lineC, 07 00 55 FF 55 A1 39 61 C5 3B 3D 17 B8 D6 E4 9F F5 E8 82 55 65 " CRC-8/ITU"
create CRC-8/MAXIM lineC, 31 00 00 00 00 A1 E8 85 BE CD 9E 55 2B 83 12 90 41 18 C9 00 06 " CRC-8/MAXIM"
create CRC-8/ROHC lineC, 07 FF 00 00 FF D0 50 80 EB 61 73 C9 3C 0E E8 4D B1 39 C5 5A BB " CRC-8/ROHC"
create CRC-8/WCDMA lineC, 9B 00 00 00 00 25 BD F1 1B DC 02 56 88 13 E8 22 CC D4 3A 00 BE " CRC-8/WCDMA"
$04 constant o_OFFSET_TESTS \ fixed offset in bytes to the Test Results
$15 constant o_OFFSET_NAME \ fixed offset in bytes to the counted name string at the end
\ *****************************************************************************
\ Calculate the CRC8 using a table
\ *****************************************************************************
$100 constant |CRC8table|
|CRC8table| Buffer: CRC8table[] ( -- a )
variable p_CRC8: \ pointer to the current CRC8:x definition
\ The CRC8table[] must be initialised using CRC8table_Init . C-code \ crc = table[crc ^ data[i]];
: CRC8 ( a n -- c ) \ calculates the CRC8 of the given string using the parameters in the CRC8: definition string stored in p_CRC8:
( Init ) p_CRC8: @ 1 + c@ -rot \ v_CRC8 c! \ initialises the output CRC value in the required way
over + swap ?do
i c@
xor CRC8table[] + c@
loop
( Xor ) p_CRC8: @ 2 + c@ xor
;
\ 12 PAD ! PAD 1 CRC8 PAD 1+ c! PAD 2 CRC8 constant CRC_VALID
\ *****************************************************************************
\ Create the CRC8table
\ *****************************************************************************
variable BRin
variable BRout
: BitReverse8 ( c -- c ) \ slow version, used to constuct the table
BRin !
0 BRout !
#08 0 do
BRout @ 2* BRout !
BRin @ 1 and if BRout @ 1 or BRout ! then
BRin @ U2/ BRin !
loop
BRout @
;
variable v_polynomial
: CRC8calculateRev ( c -- c ) \ calculates the CRC value for table element n , slow method, Reversed
p_CRC8: @ c@ BitReverse8 v_polynomial !
8 0 do
dup $01 and if
1 rshift
v_polynomial @ xor
else
1 rshift
then
$FF and
loop
;
: CRC8calculateForward ( c -- c ) \ calculates the CRC value for table element n , slow method
p_CRC8: @ c@ v_polynomial !
8 0 do
dup $80 and if
1 lshift
v_polynomial @ xor
else
1 lshift
then
$FF and
loop
;
: CRC8calculate ( c -- c ) \ calculates the CRC value for table element n , slow method
p_CRC8: @ 3 + c@ if \ check to see if the bit order should be reversed
CRC8calculateForward \ "Normal" bit order
else
CRC8calculateRev \ Reversed bit order - is more efficient on Little Endian processors
then
;
: CRC8table_Init ( CRC8: -- ) \ Initialises the CRC8 table using the given CRC8 definition
p_CRC8: ! \ save the CRC8: definition line's address
|CRC8table| 0 do
i CRC8calculate CRC8table[] i + c!
loop
;
\ *****************************************************************************
\ Export a CRC8 table as compilable source code
\ *****************************************************************************
$20 constant c_LINE_LENGTH \ how many bytes to display on each line
: Show_CRC8table ( -- ) \ show the current table as Forth source code
cr ." create CRC8table_" p_CRC8: @ o_OFFSET_NAME + count type ." ( -- a ) "
." \ Poly = $" p_CRC8: @ c@ 2.hex ." (rev $" p_CRC8: @ c@ BitReverse8 2.hex ." )"
." Init = $" p_CRC8: @ 1 + c@ 2.hex ." Xor = $" p_CRC8: @ 2 + c@ 2.hex ." Rev = $" p_CRC8: @ 3 + c@ 2.hex
|CRC8table| 0 do
i c_LINE_LENGTH 1- and 0= if cr ." lineC, " then \ the text at the start of each line
i CRC8table[] + c@ 2.hex space
i c_LINE_LENGTH 1- and c_LINE_LENGTH 1- = if ." \ " i c_LINE_LENGTH 1- - 2.hex then \ the text at the end of each line
loop
cr
;
: Show_CRCtables_all ( -- )
CRC-8/_ CRC8table_Init Show_CRC8table
CRC-8/CDMA2000 CRC8table_Init Show_CRC8table
CRC-8/DARC CRC8table_Init Show_CRC8table
CRC-8/DVB-S2 CRC8table_Init Show_CRC8table
CRC-8/EBU CRC8table_Init Show_CRC8table
CRC-8/I-CODE CRC8table_Init Show_CRC8table
CRC-8/ITU CRC8table_Init Show_CRC8table
CRC-8/MAXIM CRC8table_Init Show_CRC8table
CRC-8/ROHC CRC8table_Init Show_CRC8table
CRC-8/WCDMA CRC8table_Init Show_CRC8table
cr
;
: Show_CRC8table_C ( CRC8:x -- ) \ show the current table as C source code
cr ." create CRC8table_" p_CRC8: @ o_OFFSET_NAME + count type ." ( -- a ) "
." // Poly = 0x" p_CRC8: @ c@ 2.hex
." (rev 0x" p_CRC8: @ c@ BitReverse8 2.hex ." )"
." Init = 0x" p_CRC8: @ 1 + c@ 2.hex ." Xor = 0x" p_CRC8: @ 2 + c@ 2.hex ." Rev = 0x" p_CRC8: @ 3 + c@ 2.hex
." Please remove the final ',' before the '}' .
cr ." { "
|CRC8table| 0 do
i c_LINE_LENGTH 1- and 0= if cr ." " then \ the text at the start of each line
i CRC8table[] + c@ 0 <# [char] , hold # # [char] x hold [char] 0 hold bl hold #> type \ C format - please remove the final ,
i c_LINE_LENGTH 1- and c_LINE_LENGTH 1- = if ." // " i c_LINE_LENGTH 1- - 2.hex then \ the text at the end of each line
loop
cr ." } "
cr
;
: Show_CRCtables_all_C ( -- )
CRC-8/_ CRC8table_Init Show_CRC8table_C
CRC-8/CDMA2000 CRC8table_Init Show_CRC8table_C
CRC-8/DARC CRC8table_Init Show_CRC8table_C
CRC-8/DVB-S2 CRC8table_Init Show_CRC8table_C
CRC-8/EBU CRC8table_Init Show_CRC8table_C
CRC-8/I-CODE CRC8table_Init Show_CRC8table_C
CRC-8/ITU CRC8table_Init Show_CRC8table_C
CRC-8/MAXIM CRC8table_Init Show_CRC8table_C
CRC-8/ROHC CRC8table_Init Show_CRC8table_C
CRC-8/WCDMA CRC8table_Init Show_CRC8table_C
cr
;
0 [IF]
Show_CRCtables_all
create CRC8table_CRC-8/_ ( -- a ) \ Poly = $07 (rev $E0) Init = $00 Xor = $00 Rev = $FF
lineC, 00 07 0E 09 1C 1B 12 15 38 3F 36 31 24 23 2A 2D 70 77 7E 79 6C 6B 62 65 48 4F 46 41 54 53 5A 5D \ 00
lineC, E0 E7 EE E9 FC FB F2 F5 D8 DF D6 D1 C4 C3 CA CD 90 97 9E 99 8C 8B 82 85 A8 AF A6 A1 B4 B3 BA BD \ 20
lineC, C7 C0 C9 CE DB DC D5 D2 FF F8 F1 F6 E3 E4 ED EA B7 B0 B9 BE AB AC A5 A2 8F 88 81 86 93 94 9D 9A \ 40
lineC, 27 20 29 2E 3B 3C 35 32 1F 18 11 16 03 04 0D 0A 57 50 59 5E 4B 4C 45 42 6F 68 61 66 73 74 7D 7A \ 60
lineC, 89 8E 87 80 95 92 9B 9C B1 B6 BF B8 AD AA A3 A4 F9 FE F7 F0 E5 E2 EB EC C1 C6 CF C8 DD DA D3 D4 \ 80
lineC, 69 6E 67 60 75 72 7B 7C 51 56 5F 58 4D 4A 43 44 19 1E 17 10 05 02 0B 0C 21 26 2F 28 3D 3A 33 34 \ A0
lineC, 4E 49 40 47 52 55 5C 5B 76 71 78 7F 6A 6D 64 63 3E 39 30 37 22 25 2C 2B 06 01 08 0F 1A 1D 14 13 \ C0
lineC, AE A9 A0 A7 B2 B5 BC BB 96 91 98 9F 8A 8D 84 83 DE D9 D0 D7 C2 C5 CC CB E6 E1 E8 EF FA FD F4 F3 \ E0
create CRC8table_CRC-8/CDMA2000 ( -- a ) \ Poly = $9B (rev $D9) Init = $FF Xor = $00 Rev = $FF
lineC, 00 9B AD 36 C1 5A 6C F7 19 82 B4 2F D8 43 75 EE 32 A9 9F 04 F3 68 5E C5 2B B0 86 1D EA 71 47 DC \ 00
lineC, 64 FF C9 52 A5 3E 08 93 7D E6 D0 4B BC 27 11 8A 56 CD FB 60 97 0C 3A A1 4F D4 E2 79 8E 15 23 B8 \ 20
lineC, C8 53 65 FE 09 92 A4 3F D1 4A 7C E7 10 8B BD 26 FA 61 57 CC 3B A0 96 0D E3 78 4E D5 22 B9 8F 14 \ 40
lineC, AC 37 01 9A 6D F6 C0 5B B5 2E 18 83 74 EF D9 42 9E 05 33 A8 5F C4 F2 69 87 1C 2A B1 46 DD EB 70 \ 60
lineC, 0B 90 A6 3D CA 51 67 FC 12 89 BF 24 D3 48 7E E5 39 A2 94 0F F8 63 55 CE 20 BB 8D 16 E1 7A 4C D7 \ 80
lineC, 6F F4 C2 59 AE 35 03 98 76 ED DB 40 B7 2C 1A 81 5D C6 F0 6B 9C 07 31 AA 44 DF E9 72 85 1E 28 B3 \ A0
lineC, C3 58 6E F5 02 99 AF 34 DA 41 77 EC 1B 80 B6 2D F1 6A 5C C7 30 AB 9D 06 E8 73 45 DE 29 B2 84 1F \ C0
lineC, A7 3C 0A 91 66 FD CB 50 BE 25 13 88 7F E4 D2 49 95 0E 38 A3 54 CF F9 62 8C 17 21 BA 4D D6 E0 7B \ E0
create CRC8table_CRC-8/DARC ( -- a ) \ Poly = $39 (rev $9C) Init = $00 Xor = $00 Rev = $00
lineC, 00 72 E4 96 F1 83 15 67 DB A9 3F 4D 2A 58 CE BC 8F FD 6B 19 7E 0C 9A E8 54 26 B0 C2 A5 D7 41 33 \ 00
lineC, 27 55 C3 B1 D6 A4 32 40 FC 8E 18 6A 0D 7F E9 9B A8 DA 4C 3E 59 2B BD CF 73 01 97 E5 82 F0 66 14 \ 20
lineC, 4E 3C AA D8 BF CD 5B 29 95 E7 71 03 64 16 80 F2 C1 B3 25 57 30 42 D4 A6 1A 68 FE 8C EB 99 0F 7D \ 40
lineC, 69 1B 8D FF 98 EA 7C 0E B2 C0 56 24 43 31 A7 D5 E6 94 02 70 17 65 F3 81 3D 4F D9 AB CC BE 28 5A \ 60
lineC, 9C EE 78 0A 6D 1F 89 FB 47 35 A3 D1 B6 C4 52 20 13 61 F7 85 E2 90 06 74 C8 BA 2C 5E 39 4B DD AF \ 80
lineC, BB C9 5F 2D 4A 38 AE DC 60 12 84 F6 91 E3 75 07 34 46 D0 A2 C5 B7 21 53 EF 9D 0B 79 1E 6C FA 88 \ A0
lineC, D2 A0 36 44 23 51 C7 B5 09 7B ED 9F F8 8A 1C 6E 5D 2F B9 CB AC DE 48 3A 86 F4 62 10 77 05 93 E1 \ C0
lineC, F5 87 11 63 04 76 E0 92 2E 5C CA B8 DF AD 3B 49 7A 08 9E EC 8B F9 6F 1D A1 D3 45 37 50 22 B4 C6 \ E0
create CRC8table_CRC-8/DVB-S2 ( -- a ) \ Poly = $D5 (rev $AB) Init = $00 Xor = $00 Rev = $FF
lineC, 00 D5 7F AA FE 2B 81 54 29 FC 56 83 D7 02 A8 7D 52 87 2D F8 AC 79 D3 06 7B AE 04 D1 85 50 FA 2F \ 00
lineC, A4 71 DB 0E 5A 8F 25 F0 8D 58 F2 27 73 A6 0C D9 F6 23 89 5C 08 DD 77 A2 DF 0A A0 75 21 F4 5E 8B \ 20
lineC, 9D 48 E2 37 63 B6 1C C9 B4 61 CB 1E 4A 9F 35 E0 CF 1A B0 65 31 E4 4E 9B E6 33 99 4C 18 CD 67 B2 \ 40
lineC, 39 EC 46 93 C7 12 B8 6D 10 C5 6F BA EE 3B 91 44 6B BE 14 C1 95 40 EA 3F 42 97 3D E8 BC 69 C3 16 \ 60
lineC, EF 3A 90 45 11 C4 6E BB C6 13 B9 6C 38 ED 47 92 BD 68 C2 17 43 96 3C E9 94 41 EB 3E 6A BF 15 C0 \ 80
lineC, 4B 9E 34 E1 B5 60 CA 1F 62 B7 1D C8 9C 49 E3 36 19 CC 66 B3 E7 32 98 4D 30 E5 4F 9A CE 1B B1 64 \ A0
lineC, 72 A7 0D D8 8C 59 F3 26 5B 8E 24 F1 A5 70 DA 0F 20 F5 5F 8A DE 0B A1 74 09 DC 76 A3 F7 22 88 5D \ C0
lineC, D6 03 A9 7C 28 FD 57 82 FF 2A 80 55 01 D4 7E AB 84 51 FB 2E 7A AF 05 D0 AD 78 D2 07 53 86 2C F9 \ E0
create CRC8table_CRC-8/EBU ( -- a ) \ Poly = $1D (rev $B8) Init = $FF Xor = $00 Rev = $00
lineC, 00 64 C8 AC E1 85 29 4D B3 D7 7B 1F 52 36 9A FE 17 73 DF BB F6 92 3E 5A A4 C0 6C 08 45 21 8D E9 \ 00
lineC, 2E 4A E6 82 CF AB 07 63 9D F9 55 31 7C 18 B4 D0 39 5D F1 95 D8 BC 10 74 8A EE 42 26 6B 0F A3 C7 \ 20
lineC, 5C 38 94 F0 BD D9 75 11 EF 8B 27 43 0E 6A C6 A2 4B 2F 83 E7 AA CE 62 06 F8 9C 30 54 19 7D D1 B5 \ 40
lineC, 72 16 BA DE 93 F7 5B 3F C1 A5 09 6D 20 44 E8 8C 65 01 AD C9 84 E0 4C 28 D6 B2 1E 7A 37 53 FF 9B \ 60
lineC, B8 DC 70 14 59 3D 91 F5 0B 6F C3 A7 EA 8E 22 46 AF CB 67 03 4E 2A 86 E2 1C 78 D4 B0 FD 99 35 51 \ 80
lineC, 96 F2 5E 3A 77 13 BF DB 25 41 ED 89 C4 A0 0C 68 81 E5 49 2D 60 04 A8 CC 32 56 FA 9E D3 B7 1B 7F \ A0
lineC, E4 80 2C 48 05 61 CD A9 57 33 9F FB B6 D2 7E 1A F3 97 3B 5F 12 76 DA BE 40 24 88 EC A1 C5 69 0D \ C0
lineC, CA AE 02 66 2B 4F E3 87 79 1D B1 D5 98 FC 50 34 DD B9 15 71 3C 58 F4 90 6E 0A A6 C2 8F EB 47 23 \ E0
create CRC8table_CRC-8/I-CODE ( -- a ) \ Poly = $1D (rev $B8) Init = $FD Xor = $00 Rev = $FF
lineC, 00 1D 3A 27 74 69 4E 53 E8 F5 D2 CF 9C 81 A6 BB CD D0 F7 EA B9 A4 83 9E 25 38 1F 02 51 4C 6B 76 \ 00
lineC, 87 9A BD A0 F3 EE C9 D4 6F 72 55 48 1B 06 21 3C 4A 57 70 6D 3E 23 04 19 A2 BF 98 85 D6 CB EC F1 \ 20
lineC, 13 0E 29 34 67 7A 5D 40 FB E6 C1 DC 8F 92 B5 A8 DE C3 E4 F9 AA B7 90 8D 36 2B 0C 11 42 5F 78 65 \ 40
lineC, 94 89 AE B3 E0 FD DA C7 7C 61 46 5B 08 15 32 2F 59 44 63 7E 2D 30 17 0A B1 AC 8B 96 C5 D8 FF E2 \ 60
lineC, 26 3B 1C 01 52 4F 68 75 CE D3 F4 E9 BA A7 80 9D EB F6 D1 CC 9F 82 A5 B8 03 1E 39 24 77 6A 4D 50 \ 80
lineC, A1 BC 9B 86 D5 C8 EF F2 49 54 73 6E 3D 20 07 1A 6C 71 56 4B 18 05 22 3F 84 99 BE A3 F0 ED CA D7 \ A0
lineC, 35 28 0F 12 41 5C 7B 66 DD C0 E7 FA A9 B4 93 8E F8 E5 C2 DF 8C 91 B6 AB 10 0D 2A 37 64 79 5E 43 \ C0
lineC, B2 AF 88 95 C6 DB FC E1 5A 47 60 7D 2E 33 14 09 7F 62 45 58 0B 16 31 2C 97 8A AD B0 E3 FE D9 C4 \ E0
create CRC8table_CRC-8/ITU ( -- a ) \ Poly = $07 (rev $E0) Init = $00 Xor = $55 Rev = $FF
lineC, 00 07 0E 09 1C 1B 12 15 38 3F 36 31 24 23 2A 2D 70 77 7E 79 6C 6B 62 65 48 4F 46 41 54 53 5A 5D \ 00
lineC, E0 E7 EE E9 FC FB F2 F5 D8 DF D6 D1 C4 C3 CA CD 90 97 9E 99 8C 8B 82 85 A8 AF A6 A1 B4 B3 BA BD \ 20
lineC, C7 C0 C9 CE DB DC D5 D2 FF F8 F1 F6 E3 E4 ED EA B7 B0 B9 BE AB AC A5 A2 8F 88 81 86 93 94 9D 9A \ 40
lineC, 27 20 29 2E 3B 3C 35 32 1F 18 11 16 03 04 0D 0A 57 50 59 5E 4B 4C 45 42 6F 68 61 66 73 74 7D 7A \ 60
lineC, 89 8E 87 80 95 92 9B 9C B1 B6 BF B8 AD AA A3 A4 F9 FE F7 F0 E5 E2 EB EC C1 C6 CF C8 DD DA D3 D4 \ 80
lineC, 69 6E 67 60 75 72 7B 7C 51 56 5F 58 4D 4A 43 44 19 1E 17 10 05 02 0B 0C 21 26 2F 28 3D 3A 33 34 \ A0
lineC, 4E 49 40 47 52 55 5C 5B 76 71 78 7F 6A 6D 64 63 3E 39 30 37 22 25 2C 2B 06 01 08 0F 1A 1D 14 13 \ C0
lineC, AE A9 A0 A7 B2 B5 BC BB 96 91 98 9F 8A 8D 84 83 DE D9 D0 D7 C2 C5 CC CB E6 E1 E8 EF FA FD F4 F3 \ E0
create CRC8table_CRC-8/MAXIM ( -- a ) \ Poly = $31 (rev $8C) Init = $00 Xor = $00 Rev = $00
lineC, 00 5E BC E2 61 3F DD 83 C2 9C 7E 20 A3 FD 1F 41 9D C3 21 7F FC A2 40 1E 5F 01 E3 BD 3E 60 82 DC \ 00
lineC, 23 7D 9F C1 42 1C FE A0 E1 BF 5D 03 80 DE 3C 62 BE E0 02 5C DF 81 63 3D 7C 22 C0 9E 1D 43 A1 FF \ 20
lineC, 46 18 FA A4 27 79 9B C5 84 DA 38 66 E5 BB 59 07 DB 85 67 39 BA E4 06 58 19 47 A5 FB 78 26 C4 9A \ 40
lineC, 65 3B D9 87 04 5A B8 E6 A7 F9 1B 45 C6 98 7A 24 F8 A6 44 1A 99 C7 25 7B 3A 64 86 D8 5B 05 E7 B9 \ 60
lineC, 8C D2 30 6E ED B3 51 0F 4E 10 F2 AC 2F 71 93 CD 11 4F AD F3 70 2E CC 92 D3 8D 6F 31 B2 EC 0E 50 \ 80
lineC, AF F1 13 4D CE 90 72 2C 6D 33 D1 8F 0C 52 B0 EE 32 6C 8E D0 53 0D EF B1 F0 AE 4C 12 91 CF 2D 73 \ A0
lineC, CA 94 76 28 AB F5 17 49 08 56 B4 EA 69 37 D5 8B 57 09 EB B5 36 68 8A D4 95 CB 29 77 F4 AA 48 16 \ C0
lineC, E9 B7 55 0B 88 D6 34 6A 2B 75 97 C9 4A 14 F6 A8 74 2A C8 96 15 4B A9 F7 B6 E8 0A 54 D7 89 6B 35 \ E0
create CRC8table_CRC-8/ROHC ( -- a ) \ Poly = $07 (rev $E0) Init = $FF Xor = $00 Rev = $00
lineC, 00 91 E3 72 07 96 E4 75 0E 9F ED 7C 09 98 EA 7B 1C 8D FF 6E 1B 8A F8 69 12 83 F1 60 15 84 F6 67 \ 00
lineC, 38 A9 DB 4A 3F AE DC 4D 36 A7 D5 44 31 A0 D2 43 24 B5 C7 56 23 B2 C0 51 2A BB C9 58 2D BC CE 5F \ 20
lineC, 70 E1 93 02 77 E6 94 05 7E EF 9D 0C 79 E8 9A 0B 6C FD 8F 1E 6B FA 88 19 62 F3 81 10 65 F4 86 17 \ 40
lineC, 48 D9 AB 3A 4F DE AC 3D 46 D7 A5 34 41 D0 A2 33 54 C5 B7 26 53 C2 B0 21 5A CB B9 28 5D CC BE 2F \ 60
lineC, E0 71 03 92 E7 76 04 95 EE 7F 0D 9C E9 78 0A 9B FC 6D 1F 8E FB 6A 18 89 F2 63 11 80 F5 64 16 87 \ 80
lineC, D8 49 3B AA DF 4E 3C AD D6 47 35 A4 D1 40 32 A3 C4 55 27 B6 C3 52 20 B1 CA 5B 29 B8 CD 5C 2E BF \ A0
lineC, 90 01 73 E2 97 06 74 E5 9E 0F 7D EC 99 08 7A EB 8C 1D 6F FE 8B 1A 68 F9 82 13 61 F0 85 14 66 F7 \ C0
lineC, A8 39 4B DA AF 3E 4C DD A6 37 45 D4 A1 30 42 D3 B4 25 57 C6 B3 22 50 C1 BA 2B 59 C8 BD 2C 5E CF \ E0
create CRC8table_CRC-8/WCDMA ( -- a ) \ Poly = $9B (rev $D9) Init = $00 Xor = $00 Rev = $00
lineC, 00 D0 13 C3 26 F6 35 E5 4C 9C 5F 8F 6A BA 79 A9 98 48 8B 5B BE 6E AD 7D D4 04 C7 17 F2 22 E1 31 \ 00
lineC, 83 53 90 40 A5 75 B6 66 CF 1F DC 0C E9 39 FA 2A 1B CB 08 D8 3D ED 2E FE 57 87 44 94 71 A1 62 B2 \ 20
lineC, B5 65 A6 76 93 43 80 50 F9 29 EA 3A DF 0F CC 1C 2D FD 3E EE 0B DB 18 C8 61 B1 72 A2 47 97 54 84 \ 40
lineC, 36 E6 25 F5 10 C0 03 D3 7A AA 69 B9 5C 8C 4F 9F AE 7E BD 6D 88 58 9B 4B E2 32 F1 21 C4 14 D7 07 \ 60
lineC, D9 09 CA 1A FF 2F EC 3C 95 45 86 56 B3 63 A0 70 41 91 52 82 67 B7 74 A4 0D DD 1E CE 2B FB 38 E8 \ 80
lineC, 5A 8A 49 99 7C AC 6F BF 16 C6 05 D5 30 E0 23 F3 C2 12 D1 01 E4 34 F7 27 8E 5E 9D 4D A8 78 BB 6B \ A0
lineC, 6C BC 7F AF 4A 9A 59 89 20 F0 33 E3 06 D6 15 C5 F4 24 E7 37 D2 02 C1 11 B8 68 AB 7B 9E 4E 8D 5D \ C0
lineC, EF 3F FC 2C C9 19 DA 0A A3 73 B0 60 85 55 96 46 77 A7 64 B4 51 81 42 92 3B EB 28 F8 1D CD 0E DE \ E0
[THEN]
\ ***************************************************************************
\ Known Answer Tests ( KAT )
\ ***************************************************************************
variable v_NextKAT_ptr
variable #failed
variable #failed_total
variable #tested
variable #tested_total
: GetNextKAT ( -- c )
p_CRC8: @ o_OFFSET_TESTS + v_NextKAT_ptr @ + c@
1 v_NextKAT_ptr +!
;
$40 constant |TestResults|
|TestResults| Buffer: TestResults[]
variable v_TestResultPtr
: TestResultsC! ( c -- )
TestResults[] v_TestResultPtr @ |TestResults| 1- and + c!
1 v_TestResultPtr +!
;
variable v_Silent
\ CRCtest tests the CRC8 of a string given its correct result u.
: CRCtest_Verbose ( a n -- )
cr 2 spaces 2dup type $30 over - 0 max spaces
CRC8 dup TestResultsC!
dup 2.hex
GetNextKAT 2dup = if
2drop ." ok"
else
." <-- should be " 2.hex ." failed!" drop 1 #failed +!
then
1 #tested +!
;
: CRCtest_Silent ( a n -- )
CRC8 dup TestResultsC!
GetNextKAT = not if
1 #failed +!
then
1 #tested +!
;
: CRCtest ( a n -- )
v_Silent @ if
CRCtest_Silent
else
CRCtest_Verbose
then
;
: Show_TestSetup ( -- )
cr ." create " p_CRC8: @ o_OFFSET_NAME + count type
$17 ToColumn
." lineC, "
p_CRC8: @ c@ 2.hex 3 spaces
p_CRC8: @ 1 + c@ 2.hex 3 spaces
p_CRC8: @ 2 + c@ 2.hex 2 spaces
p_CRC8: @ 3 + c@ 2.hex 2 spaces
TestResults[] v_TestResultPtr @ over + swap ?do i c@ 2.hex space loop
[char] " emit space p_CRC8: @ o_OFFSET_NAME + count type [char] " emit
;
\ some scratchpad contents from the DS18B20 \ CRC8
create KAT0[] $08 c, $38 c, $01 c, $1F c, $1F c, $1F c, $FF c, $1F c, $10 c, \ $9E c,
create KAT1[] $08 c, $50 c, $01 c, $1F c, $1F c, $1F c, $FF c, $1F c, $10 c, \ $55 c,
create KAT2[] $08 c, $48 c, $01 c, $1F c, $1F c, $1F c, $FF c, $1F c, $10 c, \ $2B c,
create KAT3[] $08 c, $68 c, $01 c, $1F c, $1F c, $1F c, $FF c, $1F c, $10 c, \ $83 c,
\ ttcrc tests a selection of strings against the known answers listed in the current CRC8: definition line.
: Show_CRC8_test ( n -- )
>r
0 v_NextKAT_ptr !
0 v_TestResultPtr !
0 #failed !
0 #tested !
v_Silent @ not if cr ." CRC8 tests : " then
0 0 CRCtest v_Silent @ not if ." ( 0 length string )" then
s" 123456789" CRCtest
s" the quick brown fox jumps over the lazy dog" CRCtest
s" THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG" CRCtest
s" 0" CRCtest
s" 01" CRCtest
KAT0[] count CRCtest
KAT1[] count CRCtest
KAT2[] count CRCtest
KAT3[] count CRCtest
s" An Arbitrary String 012345" CRCtest
s" ABCDEFGHIJKLMNOPQRSTUVWXYZ" CRCtest
s" ZYXWVUTSRQPONMLKJIHGFEDBCA" CRCtest
s" abcdefghijklmnopqrstuvwxyz" CRCtest
s" zyxwvutsrqponmlkjihgfedbca" CRCtest
pad #26 $00 fill pad #26 CRCtest v_Silent @ not if ." ( 26 bytes of 0 )" then
pad #26 $11 fill pad #26 CRCtest v_Silent @ not if ." ( 26 bytes of hex 11 )" then
v_Silent @ not if
cr #failed @ if
." !!!! Tested " #tested @ . ." strings, of which " #failed @ . ." failed !!!!"
else
." All " #tested @ . ." tests passed"
then
then
r> Show_TestSetup
#failed @ #failed_total +!
#tested @ #tested_total +!
;
: Show_Title ( -- )
cr ." \ | ... Test results ... |"
cr ." \ Name Poly Init Xor Rev 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Name"
;
: Show_CRC8tests_all ( -- )
-1 v_Silent ! \ change to 0 to see more detailed results
decimal
0 #failed_total !
0 #tested_total !
Show_Title
CRC-8/_ CRC8table_Init Show_CRC8_test
CRC-8/CDMA2000 CRC8table_Init Show_CRC8_test
CRC-8/DARC CRC8table_Init Show_CRC8_test
CRC-8/DVB-S2 CRC8table_Init Show_CRC8_test
CRC-8/EBU CRC8table_Init Show_CRC8_test
CRC-8/I-CODE CRC8table_Init Show_CRC8_test
CRC-8/ITU CRC8table_Init Show_CRC8_test
CRC-8/MAXIM CRC8table_Init Show_CRC8_test
CRC-8/ROHC CRC8table_Init Show_CRC8_test
CRC-8/WCDMA CRC8table_Init Show_CRC8_test
cr #failed_total @ if
." !!!! Tested " #tested_total @ . ." strings, of which " #failed_total @ . ." failed !!!!"
else
." All " #tested_total @ . ." tests passed"
then
cr ."
;
: ttCRC8 ( -- ) \ test to view one CRC-8 calculation in "silent" mode
page Show_Title
-1 v_Silent !
CRC-8/_ CRC8table_Init
Show_CRC8_test
cr
Show_CRC8table
\ Show_CRC8table_C
;
: ttCRC8V ( -- ) \ test to view one CRC-8 calculation in verbose mode
cr Show_Title
0 v_Silent !
CRC-8/_ CRC8table_Init
Show_CRC8_test
cr
Show_CRC8table
\ Show_CRC8table_C
;
\ *****************************************************************************
\ CRC-8 calculation using a pre-defined table
\ *****************************************************************************
create CRC8table_CRC-8/_ ( -- a ) \ Poly = $07 (rev $E0) Init = $00 Xor = $00 Rev = $FF
lineC, 00 07 0E 09 1C 1B 12 15 38 3F 36 31 24 23 2A 2D 70 77 7E 79 6C 6B 62 65 48 4F 46 41 54 53 5A 5D \ 00
lineC, E0 E7 EE E9 FC FB F2 F5 D8 DF D6 D1 C4 C3 CA CD 90 97 9E 99 8C 8B 82 85 A8 AF A6 A1 B4 B3 BA BD \ 20
lineC, C7 C0 C9 CE DB DC D5 D2 FF F8 F1 F6 E3 E4 ED EA B7 B0 B9 BE AB AC A5 A2 8F 88 81 86 93 94 9D 9A \ 40
lineC, 27 20 29 2E 3B 3C 35 32 1F 18 11 16 03 04 0D 0A 57 50 59 5E 4B 4C 45 42 6F 68 61 66 73 74 7D 7A \ 60
lineC, 89 8E 87 80 95 92 9B 9C B1 B6 BF B8 AD AA A3 A4 F9 FE F7 F0 E5 E2 EB EC C1 C6 CF C8 DD DA D3 D4 \ 80
lineC, 69 6E 67 60 75 72 7B 7C 51 56 5F 58 4D 4A 43 44 19 1E 17 10 05 02 0B 0C 21 26 2F 28 3D 3A 33 34 \ A0
lineC, 4E 49 40 47 52 55 5C 5B 76 71 78 7F 6A 6D 64 63 3E 39 30 37 22 25 2C 2B 06 01 08 0F 1A 1D 14 13 \ C0
lineC, AE A9 A0 A7 B2 B5 BC BB 96 91 98 9F 8A 8D 84 83 DE D9 D0 D7 C2 C5 CC CB E6 E1 E8 EF FA FD F4 F3 \ E0
\ CRC-8 calculation using a pre-defined table
: CRC8_const ( a n -- c ) \ calculates the CRC8 of the given string using the parameters in the CRC8: definition string stored in p_CRC8:
( Init ) $00 -rot \ v_CRC8 c! \ initialises the output CRC value in the required way
over + swap ?do
i c@
xor CRC8table_CRC-8/_ + c@
loop
\ ( Xor ) $00 xor \ no need to do this if the value is 0
;
: tt_CRC8_const ( -- )
cr ." tt_CRC8_const : "
s" 123456789" CRC8_const $F4 = if ." Passed " else ." Failed!!!" then
;
\ *****************************************************************************
\ *****************************************************************************
cr .( Show_CRCtables_all , Show_CRCtables_all_C or Show_CRC8tests_all )
cr .( Also tt_CRC8_const, ttCRC8 or ttCRC8V )
cr