/* A fast CRC16 algorithm using 16 word table in RAM */ #include // CRC_POLYNOM = 0xA001 CRC_INIT = 0xFFFF // register name assignment zero = 1 tmp = 18 next = 19 crc_l = 20 crc_h = 21 data_cnt = 22 ; 22-25, mixed order! crc_ptr = 26 ; X data_ptr = 30 ; Z .macro crc_nibble mov tmp, crc_l ; save crc_l, low nibble is crc table index ; shift in next nibble into CRC, right shift ror next ror crc_h ror crc_l ror next ror crc_h ror crc_l ror next ror crc_h ror crc_l ror next ror crc_h ror crc_l andi tmp, 0x0F lsl tmp ; 16 bit word table ldi crc_ptr, lo8(crc16RAM) ; CRC16 table pointer ; ldi crc_ptr+1, hi8(crc16RAM) ; RAM is aligned to 32 Bytes, only LSB must be reloaded add crc_ptr, tmp ; adc crc_ptr+1, zero ld tmp, x+ eor crc_l, tmp ld tmp, x eor crc_h, tmp .endm /* int16_t calculate_crc(uint32_t app_end); registers r23 r22 r25 r24 */ .text .global calculate_crc calculate_crc: ; copy CRC table into RAM for faster access via X-Pointer ldi tmp, 32 ldi crc_ptr, lo8(crc16RAM) ldi crc_ptr, hi8(crc16RAM) ldi data_ptr, lo8(crc16ROM) ldi data_ptr, hi8(crc16ROM) copy_loop: lpm next, Z+ st X+, next subi tmp, 1 brne copy_loop ldi crc_l, lo8(CRC_INIT) ldi crc_h, hi8(CRC_INIT) sts RAMPZ, zero ldi data_ptr, 0 ; data pointer ldi data_ptr+1, 0 ldi crc_ptr+1, hi8(crc16RAM) crc_loop: elpm next, Z+ ; 3 cycles crc_nibble ; 23 cycles crc_nibble ; 23 cycles subi r24, 1 ; -1, 32 bit sbc r25, zero sbc r22, zero sbc r23, zero brne crc_loop ; 55 cycles / Byte mov r24, crc_l ; return CRC mov r25, crc_h ret crc16ROM: .word 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF .word 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF .data .global crc16RAM .balign 32 crc16RAM: .space 32