list	p=16f648a
#include	p16f648a.inc

#define Bank0	bcf STATUS,RP0
		bcf STATUS,RP1
#define Bank1	bsf STATUS,RP0
		bcf STATUS,RP1
#define Bank2	bcf STATUS,RP0
		bsf STATUS,RP1
#define Bank3	bsf STATUS,RP0
		bsf STATUS,RP1


   __CONFIG _CPD_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF

OPTION	equ	h81	; OPTION_REG
RBPU	EQU	h7	; Бит подтяжек глобально
IC1	equ	h5	; бобина 1Ц RB5
IC2	equ	h6	; бобина 2Ц RB6
TAH	equ	0	; тахометр RB0
TMRA	EQU	h1	; TMR0 отсчёт toff ton AA (УОЗ)
pTMRA	EQU		; prescaler TMR0 отсчёт toff ton AA (УОЗ)
TMRT	EQU	hE	; TMR1 измерение периода
TMRTL	EQU	hE
TMRTH	EQU	hF
D1	equ	h2	; RA2 sense in, active LOW ↓↑
D2	equ	h3	; RA3 sense in, active LOW ↓↑
ICflg	equ	0	; флаг вкл/выкл бобин Dflg 0бит, сигнализирует о вкл состоянии бобин
1RPM	equ		; в тиках TMR OSC/4
2RPM	equ		;
3RPM	equ		;
4RPM	equ		;
5RPM	equ		;
6RPM	equ		;
loop_drbzg equ	h5	; число проходов антидребезга
cnt_loop equ		; регистр проходов антидребезга
LmRPMn equ		; ниже УОЗ=0, в тиках TMR OSC/4
LmRPMx equ		; огр макс обороты, выше УОЗ=0, в тиках TMR OSC/4
TH	UDATA_SHR	; Время полуоборота в тиках TMR OSC/4
TL	UDATA_SHR	; Время полуоборота в тиках TMR OSC/4
AAH	UDATA_SHR	; УОЗ в тиках TMR OSC/4
AAL	UDATA_SHR	; УОЗ в тиках TMR OSC/4
tonH	UDATA_SHR	; время накопления в тиках TMR OSC/4
tonL	UDATA_SHR	; время накопления в тиках TMR OSC/4
toffH	UDATA_SHR	; время ожидания, выдержка, в тиках TMR OSC/4
toffL	UDATA_SHR	; время ожидания, выдержка, в тиках TMR OSC/4
Dact	UDATA_SHR	; RA2-3 D1 || D2 актив лог0, активный канал
Stsflg	UDATA_SHR	; флаги состояния: 0бит:ICflg
Dlvl	UDATA_SHR	; моментальный реальный уровень датчиков, для обнаружения инверсии
pTMRoff	UDATA_SHR	; предделитель вычисленный для загруза в pTMRA
TMRoff	UDATA_SHR	; выдержка вычисленная для загруза в TMRA
pTMRon	UDATA_SHR	; предделитель вычисленный для загруза в pTMRA
TMRon	UDATA_SHR	; время вкл бобин вычисленная для загруза в TMRA
Rtmp1	UDATA_SHR	; вспом регистр
Rtmp2	UDATA_SHR	; вспом регистр

w_sav	UDATA_SHR
stat_sav UDATA_SHR
pclath_sav UDATA_SHR

org 0
Start:	goto	Init

org 4
	movwf	w_sav		; save context
	swapf	STATUS,w
	movwf	stat_sav
	movf	PCLATH,w	; only required if using more than first page
	movwf	pclath_sav
	clrf	PCLATH
; << insert interrupt code >>
	movf	pclath_sav,w	; restore context
	movwf	PCLATH
	swapf	stat_sav,w
	movwf	STATUS
	swapf	w_sav,f
	swapf	w_sav,w
	retfie

;							pin	func
Init:	Bank0			;			1, 2 -	RA2 RA3 sense in
;;;	clrf	PORTA		;			4 -	MCLR
	clrf	PORTB		;			6 -	RB0 taho out
	movlw	b'111'		;			7, 8 -	RB1 RB2 +/- uoz in
	movwf	CMCON		;			9 -	RB3 switch in
	Bank1			;			11, 12	RB5 RB6 spark out
	movlw	b'11111111'	; also CMCON VRCON
	movwf	TRISA		; 0xFF ; Все ноги в Z как входы, ВКЛЮЧИТЬ ПОДТЯЖКИ!!!
	movlw	b'10011110'	; ноги в Z как входы, кроме 0 5 6
	movwf	TRISB
	movlw	b'11010111'	; see OPTION_REG
	movwf	OPTION
	movlw	b'00000000'	; see INTCON
	movwf	INTCON		; INTCON
	clrf	PIE1		; запрет прерываний от АЦП и ТАЙМЕРОВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВВ
;;; конфиг TMRT - TMR1
	CLRF T1CON		; Stop Timer1, Internal Clock Source, ; T1 oscillator disabled, prescaler = 1:1
	CLRF TMR1H		; Clear Timer1 High byte register
	CLRF TMR1L		; Clear Timer1 Low byte register
	CLRF INTCON		; Disable interrupts
	BSF STATUS,RP0		; Bank1
	CLRF PIE1		; Disable peripheral interrupts
	BCF STATUS,RP0		; Bank0
	CLRF PIR1		; Clear peripheral interrupts Flags
	MOVLW 0x30		; Internal Clock source with 1:8 prescaler
	MOVWF T1CON		; Timer1 is stopped and T1 osc is disabled
;;	BSF T1CON,TMR1ON	; Timer1 starts to increment
;;; конфиг TMRA - TMR0
	CLRF TMR0		; Clear Timer0 register
	CLRF INTCON		; Disable interrupts and clear T0IF
	BSF STATUS, RP0		; Bank1
	MOVLW 0xC3		; PortB pull-ups are disabled,
	MOVWF OPTION_REG	; Interrupt on rising edge of RB0, Timer0 increment from internal clock with a prescaler of 1:16
	BCF STATUS, RP0		; Bank0
;;	BSF INTCON, T0IE	; Enable TMR0 interrupt
;;	BSF INTCON, GIE		; Enable all interrupts

;;; Зарядка первозначений для начала
	clrf	TMRTL		; для первого полуоборота TMRT=FFFF, эмуляция периода ≈65мс
	clrf	TMRTH
	comf	TMRTL,f
	comf	TMRTH,f

; Первоначальный скан обоих датчиков, (↓ call ICon && call FwdFront) || (↑ nop)
ScanDs0: movlw	loop_drbzg	; установка числа проходов с повторяющимся рез-том, для стабильности
	movwf	cnt_loop
ScanDs1: movf	PORTA,w		; быстрый поиск активного входа
	andlw	0xC		; выделение RA2 RA3 по маске, актив лог0 ((1 << RA3) || (1 << RA2))
	movwf	Dlvl		; W=Dlvl=PORTA
	btfss	Dlvl,D1		; инверсная логика, активность лог0
	goto	ActDs
	btfsc	Dlvl,D2		; инверсная логика, активность лог0
	goto	ScanDs1		; ничего, все входы неактивны                                 ?????????????????????????????????????????
ActDs:	movf	PORTA,w		; сравнение с предыдущим
	andlw	0xC		; выделение RA2 RA3 по маске, актив лог0 ((1 << RA3) || (1 << RA2))
	subwf	Dlvl,w		; сравнение с предыдущим циклом антидребезга
	btfss	STATUS,Z
	goto	ScanDs0		; не совпадает, сброс счётчика проходов, в начало
	decfsz	cnt_loop,f	; один из Д сработал, совпад с пред, декремент счётчика проходов
	goto	ActDs		; на след проход scanDs1??                                     ?????????????????????????????????????????

	movf	Dlvl,w		; Dlvl=PORTA loop_drbzg раз повторяющийся, D1 || D2 (2 3 bit) активен лог0
	movwf	Dact		; W=Dlvl=Dact
	call	ICon		; первый имп, врубить бобину сразу
;;;;;;	goto	FwdFront

;;; ПП отр фронта ↓, Ds 1->0, Dlvl D1 || D2 -> 0 , надо уложиться в ширину шторки
;;; Чтение таймера периода TMRTH:TMRTL в регистр периода TH:TL и его старт
;;; The prescaler counter is cleared on writes to the TMR1H or TMR1L registers
;;; Запрет прерываний????????????????????????????????????????????????????????????????????
FwdFront: bcf	T1CON,TMR1ON	; STOP
	movf	TMRTH,W
	movwf	TH
	movf	TMRTL,W
	movwf	TL
	clrf	TMRTH
	clrf	TMRTL
	bsf	T1CON,TMR1ON	; Start TMRT
;;;;;	goto	ScanD

;; Скан D1 || D2 = f(Dact) на инверсию поочерёдно по пред уровню Dlvl
;; (↓ call FwdFront) || (↑ call RearFront)
;; Dact D1 || D2 актив лог0 == Dlvl пред цикл
;; опр активный D1 || D2 in Dact
ScanD:	btfsc	Dact,D1		; activD1?
	goto	LoopD2		; нет, D2
LoopD1:	movlw	loop_drbzg	; activD1: установка числа проходов с повторяющимся рез-том, для стабильности
	movwf	cnt_loop,f
ScanD1:	movf	PORTA,w		
	andlw	0x4		; выделение D1 RA2 по маске
	xorwf	Dlvl,w		; сравнение с предыд состоянием, инверсия входа?
	btfsc	STATUS,Z	; если Z=1, уровень не изменился
	goto	LoopD1		; уровень не изменился
	decfsz	cnt_loop,f	; уровень изменился, декремент счётчика проходов
	goto	ScanD1		; на след проход
; RA2 изменил уровень, как? Спад или подъём? Факт смены уровня подразумавает инверсию D1 in Dlvl
; Просто инвертируем его, если был 0 -> 1 && call RearFront, 1 -> 0 && call FwdFront
	movlw	0x4		; вес D1
	xorwf	Dlvl,f		; инверсия D1 по факту соответствия PORTA
	btfss	Dlvl,D1
	goto	FwdFront
	goto	RearFront

LoopD2:	movlw	loop_drbzg	; activD2: установка числа проходов с повторяющимся рез-том, для стабильности
	movwf	cnt_loop,f
ScanD2: movf	PORTA,w		; activD2:
	andlw	0x8		; выделение D2 RA3 по маске
	xorwf	Dlvl,w		; сравнение с предыд состоянием
	btfsc	STATUS,Z	; если Z=1, уровень не изменился
	goto	LoopD2
	decfsz	cnt_loop,f	; уровень изменился, декремент счётчика проходов
	goto	ScanD2		; на след проход
; RA3 изменил уровень, как? Спад или подъём? Факт смены уровня подразумавает инверсию D2 in Dlvl
; Просто инвертируем его, если был 0 -> 1 && call RearFront, 1 -> 0 && call FwdFront
	movlw	0x8		; вес D2
	xorwf	Dlvl,f		; инверсия D2 по факту соответствия PORTA
	btfss	Dlvl,D1
	call	FwdFront
	btfss	Dlvl,D2
	goto	FwdFront
;;;;;	goto	RearFront

;; ПП положит фронта ↑, Ds 0->1, Dlvl D1 || D2 -> 1
;; загруз таймера выдержки pTMRA:TMRA из pTMRoff:TMRoff и его старт
;; The prescaler counter is cleared on writes to the TMRA registers
;; Запрет прерываний????????????????????????????????????????????????????????????????????
;; if ICflag=1 ; call ICoff ; (stop TMRA) ;; ??1st   start TMRA (toff);; swap D1-D2 Dflag
;; pTMRoff TMRoff swap activ D1-D2
RearFront: btfsc Stsflg,ICflg	; если бобины включены, выкл, на всяк случай
	call ICoff

	movlw	C		; веса D1 D2 in Dact
	xorwf	Dact,f		; swap D1 <-> D2



; =======================================================================================
; compAA Вычисление УОЗ и сопутствующих ton toff
; comp tonH:tonL = TH:TL/4 (>>2)
	BCF	STATUS,C	; Clear carry
	RRF	TH,W		; Rotate high byte right
	movwf	tonH
	RRF	TL,W		; Rotate low byte right
	movwf	tonL		; ton = T/2
	BCF	STATUS,C	; Clear carry
	RRF	tonH,F
	RRF	tonL,F		; ton = T/4
; pTMRon = tonH:tonL/FF (>>8) >^2
; divxff:
	BCF	STATUS,C
	RRF	tonH,W
	movwf	Rtmp1
	RRF	tonL,W
	movwf	Rtmp2
	BCF	STATUS,C
	RRF	Rtmp1,F
	RRF	Rtmp2,F
	BCF	STATUS,C
	RRF	Rtmp1,F
	RRF	Rtmp2,F
	BCF	STATUS,C
	RRF	Rtmp1,F		; Rtmp1=0
	RRF	Rtmp2,F
	BCF	STATUS,C
	RRF	Rtmp2,F
	BCF	STATUS,C
	RRF	Rtmp2,F
	BCF	STATUS,C
	RRF	Rtmp2,F
	BCF	STATUS,C
	RRF	Rtmp2,F		; Rtmp2 = tonH:tonL/FF
; Вычисление Rtmp2 лог1>^2
; ®одэрик
ip1:	movlw	07h		; заготовка 0111 для OPTION:0:PS[2:0]
	movwf	Rtmp1
ip1.it1: btfsc	Rtmp2,7		; проверка старшего бита
	goto	ip1.rez	
	rlf	Rtmp2,f		; выдвижение следующего бита
	decfsz	Rtmp1,f
	goto	ip1.it1
ip1.rez: movf	Rtmp1,w
	movwf	pTMRon		; pTMRon = OPTION:00000:PS[2:0] готовый предделитель
	
; TMRon = tonH:tonL/[pTMRon]





; AAH:AAL




; if TH:TL > 6.3RPM || TH:TL < 1RPM ; then AA=0 ; else AA=f(TH:TL)

; find xDPZ
; let loAA hiAA loRPM hiRPM               sub 2b - 2b
; loDPZ=loRPM-T                           mul 2b * 2b
; hiDPZ=xDPZ-loDPZ                        add 4b + 4b
; AA=(hiAA*loDPZ+loAA*hiDPZ)/xDPZ         div 4b : 2b

; comp toffH:toffL = TH:TL - AAH:AAL - tonH:tonL
; pTMRoff = toffH:toffL/FF (>>8) >^2
; TMRoff = toffH:toffL/pTMRoff
goto ScanD




;; Вкл бобины для накопления энергии в зависимости от активного цилиндра Dact D1=0 || D2=0
;; Установка ICflg
;; Запрет прерываний????????????????????????????????????????????????????????????????????
ICon:	btfsc	Dact,D2
	goto	IC1on
	movlw	0x41		; веса IC2 + TAH, 01000001 (1 << IC2) + 1
	movwf	PORTB		; IC2on:
	goto	setICflg
IC1on:	movlw	0x20		; вес IC1 00100000 (1 << IC1)
	movwf	PORTB
setICflg: bsf	Stsflg,ICflg
return

;; Выкл бобин всех скопом, РАЗРЯД!, сброс ICflag
;; Запрет прерываний????????????????????????????????????????????????????????????????????
ICoff:	clrf	PORTB
	bcf	Stsflg,ICflg
return

sboj:	fill (goto Start),__CODE_END-$
	end
