.def	_PvEnc	= r14 	; предыдущие данные с энкодера
.def	_PvDir		= r13 	; предыдущее направление с энкодера

.def	_PosH		= r12 	; 24-bit счетчик текущего положения 
.def	_PosM		= r11 	;
.def	_PosL		= r10 	;

=================================================== 
; ********* Таблица перехода от прерываний **********
	RJMP 	INT_Encoder		; External Interrupt Request 0

;---------------------------------------------------------------------------------------------------------------------------------
; ************** Настройка прерывания от INT0 *************
	ldi		r16,0b00000001		; INT0 по любому изменению  (Encoder)
	sts		EICRA, r16			; 
	
	ldi		r16,0b00000001		; разрешить прерывания от INT0 (B_Int Encoder)
	out		EIMSK, r16			; 
;-------------------------------------------------------------------------------------------------------------------------------



;===========================================================
; Обработчик прерывания от INT0 - Опрос энкодера
;===========================================================
INT_Encoder:
	cli
	push	r0
	push	r16
	push	zl
	push	zh
	in		r0, SREG

	mov		zl, _PvEnc			; старое состояние zl[1:0]

	clr		r16					; Проверить состояние
	sbic	PINC,3				; входов энкодера (РС3=А, PD2=B_Int)
	sbr		r16,(1<<1)			; и установить соответсвующие
	sbic	PIND,2				; биты (А=1, B_Int=0) в 
	sbr		r16,(1<<0)			; регистре _PvEnc
	mov		_PvEnc,r16			;	

	sub		zl, _PvEnc			; Decode motion (zl = zl - _PvEnc)
	andi	zl, 3				; zl = zl and b11
	breq	enc_ext				; 00 - нет движения
	cpi		zl, 1
	breq	enc_inc				; 01 - движение вправо
	cpi		zl, 3
	breq	enc_dec				; 11 - движение влево
								; 10 - неопределено
	mov		zl, _PvDir
	mov		zh, _PvDir			; Count by 2 for previous direction
	lsl		zl					; zl=zl shl 1, bit0 cleared
	asr		zh					; zh=zh shr 1, bit7=const, bit0 -> carry flag	
	rjmp	enc_add

enc_dec:
	ldi		zl, low(-1)
	ldi		zh, high(-1)
	rjmp	enc_setpvdir

enc_inc:
	ldi		zl, low(1)
	ldi		zh, high(1)
enc_setpvdir:
	mov		_PvDir, zl
enc_add:
	add		_PosL, zl			; новая позиция
	adc		_PosM, zh
	adc		_PosH, zh

enc_ext:
	out		SREG, r0
	pop		zh
	pop		zl
	pop		r16
	pop		r0
	sei
	reti