//////////////////////// // Here is the C version of the algorithm: unsigned short g_crc; /////// void crc_ccitt_init(void) { g_crc = 0xffff; // 0xFFFF initialization standard CCITT // g_crc = 0; // xmodem standard (maybe, can't verify this?) } // see http://www.lammertbies.nl/comm/info/crc-calculation.html // and http://zorc.breitbandkatze.de/crc.html // to verify the accuracy of this algorithm. void crc_ccitt_update(unsigned char x) { // this must be an unsigned short to match the 65816 algorithm I wrote unsigned short crc_new = (unsigned char)(g_crc >> 8) | (g_crc << 8); crc_new ^= x; crc_new ^= (unsigned char)(crc_new & 0xff) >> 4; crc_new ^= crc_new << 12; crc_new ^= (crc_new & 0xff) << 5; g_crc = crc_new; } ///////////////////////////////////////////////// // HERE IS THE 65816 ASSEMBLY VERSION ///////////////////////////////////////// ******************************** * CRC-CCITT Calculation * ******************************** * By Matt Ownby, Feb 2011 * ******************************** ; This is the CRC-16 0xFFFF flavor (for want of a better way to describe it) ; Stipulations for use: ; crc_init must be called to setup the initial crc value ; ptr points to the block to be calculated... ; strlen holds the length of the block ; crc returns the 16 bit word... ; crc_update called in 8 bit mode... strlen ds 2 crc ds 2 crc_new ds 2 crc_tmp ds 2 ; temporary storage ******************************** crc_init lda #$ff ; this algorithm starts off initializing the CRC to FFFF sta crc sta crc+1 rts crc_update ; calculate crc pha phy ; go into 16-bit mode, it makes it much easier clc xce rep #$30 ldy #0 :nxtbyte lda (ptr),y ; see what value we've got... ; NOTE, it is one byte and #$00ff ; knock off high schlop because we do one byte at a time :inner_update pha ; store incoming char (x) temporarily lda crc ; crc >> 8 lsr lsr lsr lsr lsr lsr lsr lsr sta crc_new ; crc_new = (crc >> 8) lda crc ; crc << 8 asl asl asl asl asl asl asl asl ora crc_new sta crc_new ; crc_new = crc_new | (crc << 8) pla ; A = incoming byte eor crc_new ; crc_new ^= x sta crc_new and #$00ff lsr lsr lsr lsr ; A = (crc_new & 0xFF) >> 4 eor crc_new sta crc_new ; crc_new ^= A asl asl asl asl asl asl asl asl asl asl asl asl ; A = crc_new << 12 eor crc_new sta crc_new ; crc_new ^= A and #$00ff asl asl asl asl asl ; A = crc_new << 5 eor crc_new sta crc ; final result! *phew* iny ; move to the next byte dec strlen lda strlen ; have we gone through the whole string? bne :nxtbyte sec xce ply pla rts ********************************