Reputation: 1159
I have to do a simple CRC check for the following: Take an 8-bit input from a port, get it's CRC checksum value and output it. So far, I can take the input and I read the algorithm, so I append n - 1 zeros to my input, effectively making it big enough to be 16 bit. I got that working as well and I know I'll need a XOR here as we do a modulo 2 while dividing. But, I can't go any further with the algorithm, don't know where to even start.
.MACRO INITSTACK
LDI R16, HIGH(RAMEND)
OUT SPH, R16
LDI R16, LOW(RAMEND)
OUT SPL, R16
.ENDMACRO
.MACRO LOADIO
LDI R20, @1
OUT @0, R20
.ENDMACRO
.include "m128def.inc"
.EQU ones = 0xFF ; output
.EQU zeros = 0x00 ; input
.EQU CRC_CODE = 0x13 ; our CRC polynomial in binary (10011)
.DEF INPUTREG = R16 ; input register
.DEF CRC_RES = R17 ; Holds the CRC result (4 bits)
.DEF OPREG1 = R18 ; temp operation register 1
.DEF OPREG2 = R19 ; temp operation register 2
.DEF OPREG3 = R20 ; temp operation register 3
.DEF OPREG4 = R21 ; temp operation register 4
.DEF OPREG5 = R22 ; temp operation register 5
.ORG 0x0000
main:
INITSTACK
; Modifies the INPUTREG
RCALL TakeInput
RCALL CreateCRC
LOADIO DDRA, ones
LOADIO DDRB, ones
OUT PORTA, CRC_RES
Stop:
NOP
JMP Stop
TakeInput:
LOADIO DDRA, zeros
IN INPUTREG, PORTA
CLR XH
MOV XL, INPUTREG
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
RET
CreateCRC:
LDI OPREG1, 0x08 ; do shift 8 times
LDI OPREG2, CRC_CODE ; load the polynom
LSL OPREG2 ; no need for 5th bit, we only do operation with lower 4 bits (CLC does XOR for the high bit we skipped)
SWAP OPREG2 ; Swap nibbles, so the number has the bits we want at higher 4 bits
CLZ
crc_loop:
CLC
ROL INPUTREG
DEC OPREG1
BREQ crc_end ; if we did this 8 times, stop
BRCC crc_loop ; no carry, then keep shifting, if its set we go to XOR
crc_do_xor:
EOR INPUTREG, OPREG2
JMP crc_loop
crc_end:
SWAP INPUTREG ; Swap the higher 4 bits to lower 4 bits
MOV CRC_RES, INPUTREG
RET
EDIT: Now I get an incorrect result for the message 1100 1111 with code 10011. Output should be 1100 but I get 1101. Where could it be wrong?
Upvotes: 1
Views: 1159
Reputation: 8449
Your code doesn't seem to have anything useful yet. You need to think about how the algorithm works, and decide on a good way to use the bytes you need.
Since your input is only a single byte instead of a stream, I suggest you work with that byte and perform the shift 8 times. I suggest you use ROL, rotate left through carry, and CLC, clear carry bit, as well as an XOR instruction.
The idea is to clear the carry flag, then rotate left one position. If the carry bit is set, then you need to do an XOR instruction with 00110000. This is the polynomial without the first 1, shifted to the left.
1) 11001111 CLC and ROL
2) 10011110 with C=1, so do an XOR
10101110 CLC and ROL
3) 01011100 with C=1, so do an XOR
01101100 CLC and ROL
4) 11011000 with C=0, so don't XOR.
CLC and ROL
5) 10110000 with C=1, so do an XOR
01000000 CLC and ROL
6) 10000000 with C=0, so don't XOR.
CLC and ROL
7) 00000000 with C=1, so do an XOR
00110000 CLC and ROL
8) 01100000 with C=0, so don't XOR.
CLC and ROL
9) 11000000 The first four bits are the result. SWAP to get it to the right.
Write a loop that does this algorithm, testing the C bit for branching. Notice that the high bit of the polynomial doesn't need to be used directly. It is implied, in that you only XOR the lower bits if the carry bit is set. CLC does the "XOR" for the carry bit itself.
Upvotes: 2