;******************************************************************
;*******************   Модуль расчёта CRC16  **********************
;******************************************************************

                .DSEG
crc16H:		.byte	0x01	;Старший байт CRC16
crc16L:		.byte	0x01	;Младший байт CRC16




				.CSEG
table_crc16H:
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41 
		.db	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

table_crc16L:
		.db	0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2 
		.db	0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04 
		.db	0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E 
		.db	0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8 
		.db	0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A 
		.db	0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC 
		.db	0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6 
		.db	0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10 
		.db	0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32 
		.db	0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4 
		.db	0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE 
		.db	0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38 
		.db	0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA 
		.db	0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C 
		.db	0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26 
		.db	0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0 
		.db	0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62 
		.db	0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4 
		.db	0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE
		.db	0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68 
		.db	0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA 
		.db	0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C 
		.db	0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76 
		.db	0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0 
		.db	0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92 
		.db	0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54 
		.db	0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E 
		.db	0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98 
		.db	0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A 
		.db	0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C 
		.db	0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86 
		.db	0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40	


; Процедура инициализации CRC (0xFFFF)
Init_CRC16:
		push	temp0
		ldi		temp0,	0xFF
		sts		crc16H,	temp0
		sts		crc16L,	temp0
		pop		temp0
		ret

; Чтение байта номер (temp0) из таблицы table_crc16H
; вход		temp0 = номер байта(0..0хFF)
; выход		temp0 = считанный байт
GetTableHigh:
		push	ZL
		push	ZH
		ldi		ZL,		low (table_crc16H*2)
		ldi		ZH,		high(table_crc16H*2)
		add		ZL,		temp0
		brcc	gth1
		inc		ZH
gth1:	lpm
		mov		temp0,	r0	
		pop		ZH
		pop		ZL
		ret

; Чтение байта номер (temp0) из таблицы table_crc16L
; вход		temp0 = номер байта(0..0хFF)
; выход		r0 = считанный байт
GetTableLow:
		push	ZL
		push	ZH
		ldi		ZL,		low (table_crc16L*2)
		ldi		ZH,		high(table_crc16L*2)
		add		ZL,		temp0
		brcc	gtl1
		inc		ZH
gtl1:	lpm
		pop		ZH
		pop		ZL
		ret
		
;Обновление CRC после расчёта 1 байта
;X - адрес байта. После расчёта инкрементируется

CalcCRC16_OneByte:
		push 	rezL
		push	temp0
		push	ZL
		push	ZH
		ld		temp0,	X+		;загрузили в temp0 очередной байт данных
		lds		ZH,		crc16H
		lds		ZL,		crc16L
		eor		temp0,	ZH		;temp0 = (crc_high) XOR (data^)
		;
		push	temp0
		rcall	GetTableHigh
		;
		eor		r0,		ZL	
		mov		ZH,		r0	;crc_high = crc_low XOR crc16H[temp0]	
		;
		pop		temp0
		rcall	GetTableLow
		;
		mov		ZL,		r0	;crc_low = crc16L[temp0]
		sts		crc16H, ZH
		sts		crc16L,	ZL	
		pop		ZH
		pop		ZL
		pop		temp0
		pop		rezL
		ret
		
;******** Расчёт CRC всего буфера		*******
;******** вход	X - адрес начала буфера	*******
;********		temp1 - количество байт	*******
;******** выход	X - адрес следующего за последним байта	*******
CalcCRC16_Buffer:
		rcall	Init_CRC16
		; Побайтно вычисляем CRC
ccb1:	rcall	CalcCRC16_OneByte
		dec		temp1
		brne	ccb1
		;
		ret
