
.include "m8def.inc"	;AT8-16, кварц4МГц, угол 45


.org 0				;начало кода
	rjmp start
.org 1				;нога int0
	rjmp datchik1
.org 2				;нога int1
	rjmp datchik2
.org 6				;Output Compare1A Interrupt Vector Address
	rjmp timer1compare
.org 8				;переполнение timer1
	rjmp timer1
.org 14				;прер. АЦП
	rjmp adc_complete;подпрограмма АЦП (срабатывает редко)


start:
;=========Стек===========
ldi R16, low(RAMEND) ;низ стека
out SPL, R16 
ldi R16, high(RAMEND);верх стека
out SPH, R16
;====установка портов====
ldi R16, 0b00000011
out ddrC, R16		;PС
ldi R16, 0b11111100
out PortC, R16		;подтягивающие резисторы
ldi R16, 0b11010010
out ddrD, R16		;PD0-RXD;PD1-TXD;PD2,PD3-signal;PD4-Flyback
ldi R16, 0b00101101
out PortD, R16		;подтягивающие резиторы
ldi R16, 0b00000100
out ddrB, R16		;PB
ldi R16, 0b11111111
out PortB, R16		;подтягивающие резисторы
;========регистры========
clr R0				;для умножения
clr R1				;для умножения
clr R2				;"0",для умножения
ldi R16,15
mov R4,R16			;АЦП,на старте среднее
clr R5				;старший бит задержки x%
clr R6				;младший бит задержки x%
clr R7				;OCR1AH
clr R8				;OCR1AL,искра
clr R9				;TCNT1H
clr R10				;TCNT1L,счет1
clr R11				;TCNT1H
clr R12				;TCNT1L,счет2
clr R13				;H
clr R14				;L,корр.предсказания
clr R15				;рон sreg,счетч
clr R16
clr R17
clr R18
clr R19				;переход на второй импульс мат.
ldi R20,0b10000000	;РОН статуса
clr R21				;РОН рассчета задержки для ОЗУ
ldi R22,242			;гистерезис
ldi R23,50			;длинна метки,х0.7°,160=112°
clr R25				;множитель задержки из ОЗУ
clr R26				;РОН "lowX",адресация ОЗУ,LD
clr R27				;POH "highX",адресация ОЗУ,LD
clr R28				;задержка опускания искры
clr R29				;задержка "ослепления"
ldi R30,0b00000000	;РОН статуса
;===таблица в озу===
rcall FuozTable1
rcall FuozTable2
rcall FuozTable3	;таблицы задержек в ОЗУ
;чистим счетчик математики метки
ldi R27,1
ldi R26,53		;ОЗУ 01-53
st X+,R2		;53,clr
st X+,R2		;54,clr
st X,R2			;55,clr
;чтение длинны метки с ПЗУ
;R16-адрес[0..+2],R17-дата
ldi R16,0		;[ROM-000..002]
sbrc R30, 1		;if pinX,n='1' then do
rcall readflash	;если можно,читаем
sbrc R30, 1		;if pinX,n='1' then do
mov R23,R17		;в регистр
;========Timer=======
ldi R16, 0b00000010	;задержка 8,для счета при 4МГц
out TCCR1B, R16 	;пуск таймера 16-бит
ldi R16, 0b00010100
out TIMSK, R16 		;настройки 16-бит счетчика
;=========АЦП========
ldi R16, 0b01100010	;AD_Converter ADMUX byte
out ADMUX, R16
ldi R16, 0b10001101	;AD_Converter ADCSRA byte,125kHz
out ADCSRA, R16		;первый замер АЦП 800т,следующие 416т
;===прерывания ног===
ldi R16, 0b11000000
out GICR, R16		;вкл.прерывания по int0,int1
ldi R16, 0b00001010
out MCUCR, R16		;прерывание по падающему фронту
sei 				;вкл. прерывания в ЦП
;==конец инициализации устройств, далее основной код==
//////////////////////////////////////////////////////////
;таблица контрольных бит,РОН20
;R20/7-холостые обороты,переполнение 16-бит счетчика
;R20/6-запрет обработки импульса,"ослепление" входа
;R20/5-обработан импульс датчика1,счет математики разрешен
;R20/4-расчет искры завершен,вкл.сравнение счетчика
;R20/3-переход на "предсказание" оборота 0x1FF
;R20/2-обработан импульс датчика2,счет математики разрешен
;R20/1-АЦП,коректор,замер сделан
//////////////////////////////////////////////////////////
;таблица контрольных бит,РОН30
;R30/2-дата для ПЗУ,запись ПЗУ[1-разр,0-зап]
;R30/1-математика,длина метки[1-разр,0-зап]
;R30/0-МК свободен,математика[1-разр,0-зап]
//////////////////////////////////////////////////////////
main:
;блок задержки искры и flyback(6mks/1)
;не отнимая времени ЦП на выполнение кода
sbis PinD,7		;выполнить если бит порта "0"
inc R28			;+1
cpi R28, 83		;500mks,искра
brlo main2		;если меньше
;если больше опустим "искру"
cbi PortD,6		;лог"0"на выход "искра"
cpi R28, 117	;702mks,flyback
brlo main2		;если меньше
;если больше вкл."flyback"
sbi PortD,7		;лог"1"на выход "flyback"
clr R28			;обнуляем переменную
ori R30, 0b00000001;sbiR30/0,длина метки
main2:


;блок "ослепления" входа датчика
sbrc R20, 6		;if pinX,n='1' then do
inc R29			;+1
cpi R29, 166	;1ms,ослепление
brlo main3
andi R20, 0b10111111;cbiR20/6, контроль
clr R29			;обнуляем переменную
main3:


;блок определения длины метки
;в свободное от расчета время
;определенный диапазон оборотов
sbrs R30, 0		;if pinX,n='0' then do
rjmp main4		;если запрет,вых.
sbrc R30, 2		;if pinX,n='1' then do
rcall eeprom_metki;запись в ПЗУ
sbrc R30, 1		;if pinX,n='1' then do
rcall dlina_metki;математика длина метки
main4:


sbrs R20, 5		;if pinX,n='0' then do
rjmp main
sbrc R20, 7		;if pinX,n='1' then do
rcall holostie	;сюда,если обороты ниже 460/мин
rcall norm		;счет математики,импульс1
rjmp main
nop
nop
nop
;-------------------------------------------------------------
;----------------далее только подпрограммы--------------------
;-------------------------------------------------------------
;==переполнение 16-бит счетчика==
;переполнение означает что частота оборотов ниже 480/мин
timer1:
in R15,SREG		;сохраним SREG
ori R20, 0b10000000	;sbiR20/7, контроль
clr R19			;переход математики счета
sbi PortB,2		;test led indicator
out SREG,R15	;восстановим SREG
reti


;=совпадение сравнения OCR1A, 16-бит счетчика=
;нормальная,расчетная искра по счетчику
timer1compare:
in R15,SREG		;сохраним SREG
sbrs R20, 4		;if pinX,n='0' then do
reti
ori R20, 0b01000000	;sbiR20/6,ослепление
cbi PortD,7		;лог"0"на выход "flyback"
sbi PortD,6		;лог"1"на выход "искра"
andi R20, 0b11101111;cbiR20/4,искра
out SREG,R15	;восстановим SREG
reti


;===первый сигнал датчика===
datchik1:
in R15,SREG		;сохраним SREG
sbrc R20, 6		;if pinX,n='1' then do
rjmp d1propusk	;ошибка,вых.
in R10, TCNT1L
in R9, TCNT1H	;считываем показания счетчика
out TCNT1H, R2	;R2=0
out TCNT1L, R2	;обнуляем счетчик
ori R20, 0b00100000	;sbiR20/5, контроль
;показания счетчика записаны, счетчик обнулен
;контрольный бит расчета по первому сигналу
sbrs R20, 4		;if pinX,n='0' then do
rjmp d1propusk	;все норм.,вых.
;если пропустили искру по динамике
ori R20, 0b01000000	;sbiR20/6,ослепление
cbi PortD,7		;лог"0"на выход "flyback"
sbi PortD,6		;лог"1"на выход "искра"
andi R20, 0b11101111;cbiR20/4,контроль
d1propusk:
out SREG,R15	;восстановим SREG
reti

;===второй сигнал датчика===
datchik2:
in R15,SREG		;сохраним SREG
sbrc R20, 6		;if pinX,n='1' then do
rjmp d2propusk	;ошибка,вых.
in R12, TCNT1L
in R11, TCNT1H	;считываем показания счетчика
ori R20, 0b00000100	;sbiR20/2,контроль
;показания счетчика записаны,контрольный бит
;готовности расчета по второму сигналу
d2propusk:
ldi R27,1
ldi R26,53		;ОЗУ 01-53
st X,R2			;счетчик присутстивия
out SREG,R15	;восстановим SREG
reti


;====АЦП замер сделан====
adc_complete:
in R4, ADCL	
in R4, ADCH
lsr R4			;1/2=128
lsr R4			;1/2=64
lsr R4			;1/2=32
ori R20, 0b00000010;sbiR20/1,АЦП,контроль
reti


;====нормальные обороты=====
;=определяем задержку искры=
norm:
mov R21, R9		;скопируем значение счетчика 16-бит,Hbyte
com R21			;инвертируем число
;теперь имеем 255 значений счетчика оборотов,
;наименьшее значение - медленные обороты, большее - большые
;для усреднения точек таблицы выборка делаеться
;через некоторое число точек, для равномерности
///////////////////////////////////////////////////
cpi R21, 242	;сравнение РОН с контстантой
brsh rpm19k5	;если больше или равно
cpi R21, 241	;сравнение РОН с контстантой
brsh rpm16k7	;если больше или равно
cpi R21, 240	;сравнение РОН с контстантой
brsh rpm14k6	;если больше или равно
cpi R21, 239	;сравнение РОН с контстантой
brsh rpm13k		;если больше или равно
cpi R21, 238	;сравнение РОН с контстантой
brsh rpm11k7	;если больше или равно
cpi R21, 237	;сравнение РОН с контстантой
brsh rpm10k6	;если больше или равно
cpi R21, 236	;сравнение РОН с контстантой
brsh rpm9k7		;если больше или равно
cpi R21, 234	;сравнение РОН с контстантой
brsh rpm9k		;если больше или равно
cpi R21, 232	;сравнение РОН с контстантой
brsh rpm8k3		;если больше или равно
cpi R21, 230	;сравнение РОН с контстантой
brsh rpm7k8		;если больше или равно
cpi R21, 227	;сравнение РОН с контстантой
brsh rpm7k3		;если больше или равно
cpi R21, 225	;сравнение РОН с контстантой
brsh rpm6k9		;если больше или равно
cpi R21, 222	;сравнение РОН с контстантой
brsh rpm6k5		;если больше или равно
cpi R21, 219	;сравнение РОН с контстантой
brsh rpm6k1		;если больше или равно
cpi R21, 216	;сравнение РОН с контстантой
brsh rpm5k6		;если больше или равно
cpi R21, 213	;сравнение РОН с контстантой
brsh rpm5k1		;если больше или равно
cpi R21, 208	;сравнение РОН с контстантой
brsh rpm4k7		;если больше или равно
cpi R21, 202	;сравнение РОН с контстантой
brsh rpm4k2		;если больше или равно
cpi R21, 197	;сравнение РОН с контстантой
brsh rpm3k9		;если больше или равно
cpi R21, 190	;сравнение РОН с контстантой
brsh rpm3k5		;если больше или равно
cpi R21, 182	;сравнение РОН с контстантой
brsh rpm3k		;если больше или равно
cpi R21, 177	;сравнение РОН с контстантой
brsh rpm2k8		;если больше или равно
cpi R21, 171	;сравнение РОН с контстантой
brsh rpm2k5		;если больше или равно
cpi R21, 165	;сравнение РОН с контстантой
brsh rpm2k2		;если больше или равно
cpi R21, 157	;сравнение РОН с контстантой
brsh rpm2k		;если больше или равно
cpi R21, 148	;сравнение РОН с контстантой
brsh rpm1k8		;если больше или равно
cpi R21, 138	;сравнение РОН с контстантой
brsh rpm1k5		;если больше или равно
cpi R21, 125	;сравнение РОН с контстантой
brsh rpm1k2		;если больше или равно
cpi R21, 109	;сравнение РОН с контстантой
brsh rpm1k		;если больше или равно
cpi R21, 88	;сравнение РОН с контстантой
brsh rpm0k8		;если больше или равно
cpi R21, 60	;сравнение РОН с контстантой
brsh rpm0k6		;если больше или равно
clr R26			;если 500 и меньше об/мин
rjmp RpmEnd		;всего 32строки
////////////////////////////////////////////////////////
rpm19k5:		;обороты
ldi R26, 0x1F	;задаем адрес ОЗУ "lowХ"
rjmp RpmEnd		;метка "дальше"
rpm16k7:
ldi R26, 0x1E
rjmp RpmEnd
rpm14k6:
ldi R26, 0x1D
rjmp RpmEnd
rpm13k:
ldi R26, 0x1C
rjmp RpmEnd
rpm11k7:
ldi R26, 0x1B
rjmp RpmEnd
rpm10k6:
ldi R26, 0x1A
rjmp RpmEnd
rpm9k7:
ldi R26, 0x19
rjmp RpmEnd
rpm9k:
ldi R26, 0x18
rjmp RpmEnd
rpm8k3:
ldi R26, 0x17
rjmp RpmEnd
rpm7k8:
ldi R26, 0x16
rjmp RpmEnd
rpm7k3:
ldi R26, 0x15
rjmp RpmEnd
rpm6k9:
ldi R26, 0x14
rjmp RpmEnd
rpm6k5:
ldi R26, 0x13
rjmp RpmEnd
rpm6k1:
ldi R26, 0x12
rjmp RpmEnd
rpm5k6:
ldi R26, 0x11
rjmp RpmEnd
rpm5k1:
ldi R26, 0x10
rjmp RpmEnd
rpm4k7:
ldi R26, 0x0F
rjmp RpmEnd
rpm4k2:
ldi R26, 0x0E
rjmp RpmEnd
rpm3k9:
ldi R26, 0x0D
rjmp RpmEnd
rpm3k5:
ldi R26, 0x0C
rjmp RpmEnd
rpm3k:
ldi R26, 0x0B
rjmp RpmEnd
rpm2k8:
ldi R26, 0x0A
rjmp RpmEnd
rpm2k5:
ldi R26, 0x09
rjmp RpmEnd
rpm2k2:
ldi R26, 0x08
rjmp RpmEnd
rpm2k:
ldi R26, 0x07
rjmp RpmEnd
rpm1k8:
ldi R26, 0x06
rjmp RpmEnd
rpm1k5:
ldi R26, 0x05
rjmp RpmEnd
rpm1k2:
ldi R26, 0x04
rjmp RpmEnd
rpm1k:
ldi R26, 0x03
rjmp RpmEnd
rpm0k8:
ldi R26, 0x02
rjmp RpmEnd
rpm0k6:
ldi R26, 0x01
;адрес ОЗУ "lowХ" определен
;задействованно ОЗУ 0х0100-0х011F,32строки
RpmEnd:

;выбор таблицы УОЗ тумблером на"0"
;приоритет у нижних таблиц
ldi R27, 1		;задаем "highX"таблица№1
sbis PinC,5		;выполнить если бит порта "0"
ldi R27, 2		;задаем "highX"таблица№2
sbis PinC,4		;выполнить если бит порта "0"
ldi R27, 3		;задаем "highX"таблица№3
;адрес ОЗУ "HighХ" определен, чтение ОЗУ
ld R25, X		;байт из ОЗУ-R27:26 загружается в РОН25


;АЦП корректор:
;sbi ADCSRA,6	;старт замер АЦП
;sbrs R20, 1		;if pinX,n='0' then do
;rjmp ADC_negotov
;mov R17,R4		;новый сдвиг
;andi R20, 0b11111101;cbiR20/1,контроль
;ADC_negotov:
;АЦП корректор
;cpi R17,16		;средина резистора
;brlo adc_plus	;если меньше
;;adc_minus:
;mov R16,R17
;subi R16,16		;0...15
;sub R25,R16		;"задержка" минус АЦП
;rjmp adc_exit	;вых
;adc_plus:
;ldi R16,15
;sub R16,R17		;инверсия,0...15
;add R25,R16		;"задержка" плюс АЦП
;adc_exit:


;второй импульс датчика
;cp R25,R23		;табл.с длинной метки
;brlo pervii		;если табл.меньше,мат1
;cpi R25, 180	;если задержка >=180
;brsh pervii		;на "предсказание"
cpi R21, 117	;если больше 850об/мин
brsh pervii		;расчет по первому
cpi R19, 50		;прошло 3с. запуска
brsh pervii		;расчет по первому
andi R20, 0b11111011;cbiR20/2,контроль
sbi PortB,2		;test led indicator
vtoroi:			;расчет по второму сигналу
sbrc R20, 7		;if pinX,n='1' then do
rjmp err2		;ошибка,вых.
sbrs R20, 2		;if pinX,n='0' then do
rjmp vtoroi		;ждем импульс
;дальше начало счета по второму:
;cp R25,R23		;если равны
;brne noiskr
;rjmp iskra		;искра без задержки
;noiskr:			;иначе счет
;sub R25,R23		;"табл."-"метка"
;далее расчет на "запаздывание",второй имп.дат.
;mov R16,R9		;сохраним регистры
;mov R17,R10		;счетчика
mov R8,R12
mov R7,R11
lsr R7
ror R8			;1/2=20°
add R8,R12
adc R7,R11
;rcall matematika;R16R17*R25=R7R8
;add R8,R12
;adc R7,R11		;+счт.длина метки
;теперь имеем R7R8 значение задержки
;запишем в регистр сравнения счетчика
out OCR1AH, R7	;HighByte
out OCR1AL, R8	;LowByte
ori R20, 0b00010000	;sbiR20/4,контроль
andi R20, 0b11010011;cbiR20/532,контроль
ret
err2:			;заглох между датчиками
ldi R27,1
ldi R26,53		;ОЗУ 01-53
ld R16,X		;53
inc R16
cpi R16,3
brlo err3		;если нет втрой метки
ldi R23,160		;длинна метки,х0.7°,160=112°
st X,R2			;53,счетчик
ori R30, 0b00000100;sbiR30/2,ПЗУ
andi R20, 0b11010011;cbiR20/532,контроль
ret
err3:
st X,R16		;53,счетчик
andi R20, 0b11010011;cbiR20/532,контроль
ret


pervii:			;расчет по первому сигналу
cbi PortB,2		;test led indicator
;автоотключение второго импульса
;обнуляется при переполении счетчика
cpi R19, 50		;задержка 3с. запуска
brsh max_r19	;чтобы не использовать второй
inc R19			;+1
max_r19:		;max=40

;коррекция предсказания оборота
;используется только в реж.предсказания
mov R6,R10		;копируем оборот
mov R5,R9		;и ст.
cp R10,R14		;сравнимваем с предыдущим
cpc R9,R13		;и ст.
breq rovno		;если равны,нет рассчета
brlo razgon
;замедление
sub R6,R14
sbc R5,R13
lsr R5
ror R6			;1/2 оборота расч.
add R6,R10
adc R5,R9
brvc rovno		;нет переполнения
ser R16			;РОН=0xFF
mov R6,R16		;если переполнение
mov R5,R16		;реж.холостые
rjmp rovno
razgon:			;рост оборотов
sub R14,R6
sbc R13,R5
lsr R13
ror R14			;1/2 оборота расч.
sub R6,R14
sbc R5,R13
rovno:
mov R14,R10
mov R13,R9
;R5:R6-расчетный 180°
;R9:R10-текущий
;R13:R14-предыдущий

;проверим на нулевое значение, что
;соответствует оборотам более 4к
;при этом искра по датчику уоз,20°
cpi R25, 2		;"min"
brlo iskra		;если задержка "0..1",искра без задержки
cp R25, R22		;"max"
brsh iskra		;если задержка "255",искра без задержки


ldi R22,242		;гистерезис,запаздывание
;проверим на значение более 180,уоз=126°
;соответствует опережению больше угла датчика
;при этом искра до датчика уоз
cpi R25, 180	;180*0.7=126°
brlo raschet	;если меньше, то переходим на штатную
breq propusk	;если равно, искра запрещена
;проверим на первое срабатывание
sbrs R20, 3		;if pinX,n='0' then do
rcall iskra		;если да,искра
ldi R22,243		;гистерезис,предсказание
;расчет на "предсказание",первый имп.дат.
mov R16,R5		;сохраним регистры
mov R17,R6		;счетчика
com R25			;инверсия регистра
rcall matematika;R16R17*R25=R7R8
sub R6,R8		;"расчетный оборот"-R7R8
sbc R5,R7
;теперь имеем R5R6 значение задержки
;запишем в регистр сравнения счетчика цилиндра
out OCR1AH, R5	;HighByte
out OCR1AL, R6	;LowByte
ori R20, 0b00011000	;sbiR20/43,контроль
andi R20, 0b11011111;cbiR20/5,контроль
ret

raschet:
;расчет на "запаздывание",первый имп.дат.
mov R16,R9		;сохраним регистры
mov R17,R10		;счетчика
rcall matematika;R16R17*R25=R7R8
;теперь имеем R7R8 значение задержки
;запишем в регистр сравнения счетчика цилиндра один
out OCR1AH, R7	;HighByte
out OCR1AL, R8	;LowByte
ori R20, 0b00010000	;sbiR20/4,контроль
andi R20, 0b11010111;cbiR20/53,контроль
ret


;подпрограмма умножения задержки
;R16R17*R25=R7R8
matematika:
lsr R16			;1/2,шаг смены
ror R17			;угла 360°/512=0.7°
mul R16,R25		;старший и младший
mov R8,R0
mov R7,R1
mul R17,R25		;младший и младший
add R8,R1
adc R7,R2		;R2=0
ret


;пропуск искры,режим "отсечка" оборотов
propusk:
andi R20, 0b11010111;cbiR20/53,контроль
ret


;======искра без задержки, сразу по датчику=======
;при первом переходе с запаздывания на опережение
;этот блок нужен для устранения провала при переходе
iskra:
ori R20, 0b01000000	;sbiR20/6,ослепление
sbrs R20, 3		;if pinX,n='0' then do
cbi PortD,7		;лог"0"на выход "flyback"
sbrs R20, 3		;if pinX,n='0' then do
sbi PortD,6		;лог"1"на выход "искра"
ldi R22,242		;гистерезис,ступенька,1 шаг
andi R20, 0b11010111;cbiR20/53,контроль
ret


;==холостые(низкие) обороты==
;режим активен при переполнении счетчика
;когда обороты ниже чем 460/мин
;при этом расчет задержки невозможен
;и имеет смысл делать ее константой для
;познего зажигания,без пропусков искры
holostie:
ser R16			;РОН=0xFF
mov R9, R16		;сработает как 480/мин
mov R10, R16	;и мл.1
mov R13, R16	;ст.2
mov R14, R16	;мл.2
andi R20, 0b01111111;cbiR20/7, контроль
ret



;блок определения длины метки
;в свободное от расчета время
;определенный диапазон оборотов
dlina_metki:
;обороты двигателя
cpi R21,177		;если обороты
brsh metka_end2 ;выше 1.5к,или
cpi R21,157		;ниже 1.2к,то
brlo metka_end2	;нельзя,выход
;задержка между замерами
ldi R27,1
ldi R26,54		;ОЗУ 01-54
ld R16,X		;54
inc R16			;счетчик+1
cpi R16,2		;пропуск n оборотов
brsh metka2		;больше или равно
st X,R16		;54
rjmp metka_end2	;рано,вых
metka2:			;считаем дальше
st X,R2			;54,clr счетчик
;R9:R10-сч.оборота
;R11:R12-сч.метки
;R11R12/R9=R18,длина метки
mov R16,R11
mov R17,R12
lsl R16			;*2,шаг смены
rol R17			;угла для 0.7°
clr R18			;результат
cp R16,R2
cpc R17,R2		;проверка на ноль
breq metka_end2	;на ноль делить нельзя
minus:			;цикл вычитания делителя из делимого
cp R17,R9		;сравниваем младшие
cpc R16,R2		;и старшие байты
brlo exit		;если делимое меньше,выход из цикла
sub R17,R9		;иначе вычитаем из делимого делитель
sbc R16,R2		;младшие и старшие байты
inc R18			;+1 к результату
rjmp minus		;возвращаемся к началу цикла
exit:			;метка выхода из цикла
cpi R18,6		;метка не может быть меньше 4°
brlo metka_end2	;игнор текущего замера
cpi R18,172		;метка не может быть больше 120°
brsh metka_end2	;выход по ошибке
ldi R27,1
ldi R26,50		;ОЗУ 01-50
ld R17,X+		;байт из ОЗУ,50
ld R16,X+		;51
st X,R16		;52
st -X,R17		;51
st -X,R18		;50
cp R18,R17
cpc R18,R16
brne metka_end2	;не равны,вых.
;равны,значение истинно
cp R23,R18
breq metka_end	;старое верно
brsh metka_max	;старое больше
;старое значение меньше
dec R18			;если
cp R23,R18		;разница на 1
breq metka_end	;выход
dec R18			;если
cp R23,R18		;разница на 2
breq metka_end	;выход
rjmp metka_write;иначе сохраним
metka_max:		;старое значение больше
inc R18			;если
cp R23,R18		;разница на 1
breq metka_end	;выход
inc R18			;если
cp R23,R18		;разница на 2
breq metka_end	;выход
metka_write:	;запись в ПЗУ
mov R23,R17		;копируем рабочее значение
ori R30, 0b00000100;sbiR30/2,ПЗУ
metka_end:		;запрет повторного расчета
andi R30, 0b11111101;cbiR30/1,математика
metka_end2:
andi R30, 0b11111110;cbiR30/0,контроль
ret



;запись длинны метки в ПЗУ
;медленная память 8.5мс/байт
;R16-адрес[ОЗУ01-55],R17-дата
eeprom_metki:
;обороты двигателя
cpi R21,177		;если обороты
brsh metka_end	;выше 1.5к,вых
;иначе пишем байт ПЗУ
ldi R27,1
ldi R26,55		;ОЗУ 01-55
ld R16,X		;адрес-счетчик
cpi R16,9
brsh eeprom_end
cpi R16,6
brsh ROM_06
cpi R16,4
brsh ROM_04
cpi R16,3
brsh ROM_03
;ROM_0:
mov R17,R23		;копируем
rcall saveflash;[ROM-00..02]
inc R16			;адрес ROM+1
st X,R16		;55
rjmp metka_end	;вых.

ROM_03:
;чтение счетчика перезаписи ПЗУ
;R16-адрес[0..+2],R17-дата
;счетчик+1[ОЗУ01-56..57]
ldi R16,3		;[ROM-003..005]
rcall readflash	;HighByte
ldi R27,1
ldi R26,56		;ОЗУ 01-56
st X,R17		;56
ldi R16,6		;[ROM-006..008]
rcall readflash	;LowByte
ld R18,X		;56
ldi R16,1		;для математики
add R17,R16		;счетчик +1
adc R18,R2		;R2=0
st X+,R18		;56,HByte
st X,R17		;57,LByte
ldi R16,3		;адрес,HByte
ROM_04:
ldi R27,1
ldi R26,56		;ОЗУ 01-56
ld R17,X		;56
rcall saveflash;[ROM-03..05]
inc R16			;адрес ROM+1
ldi R26,55		;ОЗУ 01-55
st X,R16		;55
rjmp metka_end	;вых.

ROM_06:
ldi R27,1
ldi R26,57		;ОЗУ 01-56
ld R17,X		;56
rcall saveflash;[ROM-06..08]
inc R16			;адрес ROM+1
ldi R26,55		;ОЗУ 01-55
st X,R16		;55
rjmp metka_end	;вых.

eeprom_end:
;запись завершена,запретим использовать ПЗУ
andi R30, 0b11111000;cbiR30/210,ПЗУ
ldi R26,55		;ОЗУ 01-55
st X,R2			;clr55,ПЗУ счетчик
ret



;====запись ПЗУ====
;R16-адрес,R17-дата
saveflash:
sbic eecr,1		;выполнить если бит порта "1"
rjmp saveflash	;ждем гтовности ПЗУ
out eearh,R2	;адрес верх,R2=0
out eearl,R16	;и низ
out eedr,R17	;данные(L)
sbi eecr,2		;eemwe,предохранитель
sbi eecr,1		;eewe,старт записи
ret
;========чтение ПЗУ===========
;R16-адрес[0..+2],R17,R18-дата
readflash:
sbic eecr,1		;выполнить если бит порта "1"
rjmp readflash	;ждем гтовности ПЗУ
out eearh,R2	;адрес верх,R2=0
out eearl,R16	;и низ
sbi eecr,0		;eere,читаем
in R17,eedr		;данные(L)
inc R16			;+1адрес
readflash2:
sbic eecr,1		;выполнить если бит порта "1"
rjmp readflash2	;ждем гтовности ПЗУ
out eearl,R16	;и низ
sbi eecr,0		;eere,читаем
in R18,eedr		;данные(L)
cp R17,R18		;тест прочитаного
breq readcurrect
inc R16			;если не совпало
readflash3:		;читаем дальше
sbic eecr,1		;выполнить если бит порта "1"
rjmp readflash3	;ждем гтовности ПЗУ
out eearl,R16	;и низ
sbi eecr,0		;eere,читаем
in R16,eedr		;данные(L)
cp R17,R16		;тест прочитаного
breq readcurrect
mov R17,R18		;последняя надежда
readcurrect:
ret

//////////////////////////////////////////////////
//////////////////////////////////////////////////

;==таблица №1,углов опережения в ОЗУ==
;=======для метки 20°, шаг 0.7°=======
FuozTable1:
ldi R27, 0x01	;задаем "highX"=01
ldi R26, 0x00	;задаем "lowX"=00
;опережение при оборотах
;500 и ниже, об/мин
ldi R16, 67	;множитель
st X+, R16	;в ОЗУ, -1.9°
;600 об/мин
ldi R16, 66	;множитель
st X+, R16	;в ОЗУ, -1.2°
;800 об/мин
ldi R16, 64	;множитель
st X+, R16	;в ОЗУ, 0.2°
;1000 об/мин
ldi R16, 63	;множитель
st X+, R16	;в ОЗУ, 0.9°
;1200 об/мин
ldi R16, 61	;множитель
st X+, R16	;в ОЗУ, 2.3°
;1500 об/мин
ldi R16, 59	;множитель
st X+, R16	;в ОЗУ, 3.7°
;1800 об/мин
ldi R16, 56	;множитель
st X+, R16	;в ОЗУ, 5.8°
;2000 об/мин
ldi R16, 54	;множитель
st X+, R16	;в ОЗУ, 7.2°
;2200 об/мин
ldi R16, 54	;множитель
st X+, R16	;в ОЗУ, 7.2°
;2500 об/мин
ldi R16, 53	;множитель
st X+, R16	;в ОЗУ, 7.9°
;2800 об/мин
ldi R16, 52	;множитель
st X+, R16	;в ОЗУ, 8.6°
;3000 об/мин
ldi R16, 51	;множитель
st X+, R16	;в ОЗУ, 9.3°
;3500 об/мин
ldi R16, 49	;множитель
st X+, R16	;в ОЗУ, 10.7°
;3900 об/мин
ldi R16, 47	;множитель
st X+, R16	;в ОЗУ, 12.1°
;4200 об/мин
ldi R16, 46	;множитель
st X+, R16	;в ОЗУ, 12.8°
;4700 об/мин
ldi R16, 44	;множитель
st X+, R16	;в ОЗУ, 14.2°
;5100 об/мин
ldi R16, 43	;множитель
st X+, R16	;в ОЗУ, 14.9°
;5600 об/мин
ldi R16, 42	;множитель
st X+, R16	;в ОЗУ, 15.6°
;6100 об/мин
ldi R16, 41	;множитель
st X+, R16	;в ОЗУ, 16.3°
;6500 об/мин
ldi R16, 39	;множитель
st X+, R16	;в ОЗУ, 17.7°
;6900 об/мин
ldi R16, 38	;множитель
st X+, R16	;в ОЗУ, 18.4°
;7300 об/мин
ldi R16, 37	;множитель
st X+, R16	;в ОЗУ, 19.1°
;7800 об/мин
ldi R16, 36	;множитель
st X+, R16	;в ОЗУ, 19.8°
;8300 об/мин
ldi R16, 35	;множитель
st X+, R16	;в ОЗУ, 20.5°
;9000 об/мин
ldi R16, 34	;множитель
st X+, R16	;в ОЗУ, 21.2°
;9700 об/мин
ldi R16, 33	;множитель
st X+, R16	;в ОЗУ, 21.9°
;10600 об/мин
ldi R16, 32	;множитель
st X+, R16	;в ОЗУ, 22.6°
;11700 об/мин
ldi R16, 31	;множитель
st X+, R16	;в ОЗУ, 23.3°
;13000 об/мин
ldi R16, 31	;множитель
st X+, R16	;в ОЗУ, 23.3°
;14600 об/мин
ldi R16, 30	;множитель
st X+, R16	;в ОЗУ, 24°
;16700 об/мин
ldi R16, 30	;множитель
st X+, R16	;в ОЗУ, 24°
;19500 об/мин
ldi R16, 180	;множитель
st X+, R16	;в ОЗУ, 24°
ret		;возврат в программу

;==таблица №2,углов опережения в ОЗУ==
;=======для метки 20°, шаг 0.7°=======
FuozTable2:
ldi R27, 0x02	;задаем "highX"=02
ldi R26, 0x00	;задаем "lowX"=00
;опережение при оборотах
;500 и ниже, об/мин
ldi R16, 30	;множитель
st X+, R16	;в ОЗУ, 24°
;600 об/мин
ldi R16, 28	;множитель
st X+, R16	;в ОЗУ, 25.4°
;800 об/мин
ldi R16, 27	;множитель
st X+, R16	;в ОЗУ, 26.1°
;1000 об/мин
ldi R16, 26	;множитель
st X+, R16	;в ОЗУ, 26.8°
;1200 об/мин
ldi R16, 24	;множитель
st X+, R16	;в ОЗУ, 28.2°
;1500 об/мин
ldi R16, 21	;множитель
st X+, R16	;в ОЗУ, 30.3°
;1800 об/мин
ldi R16, 20	;множитель
st X+, R16	;в ОЗУ, 31°
;2000 об/мин
ldi R16, 18	;множитель
st X+, R16	;в ОЗУ, 32.4°
;2200 об/мин
ldi R16, 18	;множитель
st X+, R16	;в ОЗУ, 32.4°
;2500 об/мин
ldi R16, 17	;множитель
st X+, R16	;в ОЗУ, 33.1°
;2800 об/мин
ldi R16, 16	;множитель
st X+, R16	;в ОЗУ, 33.8°
;3000 об/мин
ldi R16, 15	;множитель
st X+, R16	;в ОЗУ, 34.5°
;3500 об/мин
ldi R16, 14	;множитель
st X+, R16	;в ОЗУ, 35.2°
;3900 об/мин
ldi R16, 12	;множитель
st X+, R16	;в ОЗУ, 36.6°
;4200 об/мин
ldi R16, 10	;множитель
st X+, R16	;в ОЗУ, 38°
;4700 об/мин
ldi R16, 8	;множитель
st X+, R16	;в ОЗУ, 39.4°
;5100 об/мин
ldi R16, 7	;множитель
st X+, R16	;в ОЗУ, 40.1°
;5600 об/мин
ldi R16, 6	;множитель
st X+, R16	;в ОЗУ, 40.8°
;6100 об/мин
ldi R16, 5	;множитель
st X+, R16	;в ОЗУ, 41.5°
;6500 об/мин
ldi R16, 3	;множитель
st X+, R16	;в ОЗУ, 42.9°
;6900 об/мин
ldi R16, 2	;множитель
st X+, R16	;в ОЗУ, 43.6°
;7300 об/мин
ldi R16, 1	;множитель
st X+, R16	;в ОЗУ, 44.3°
;7800 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;8300 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;9000 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;9700 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;10600 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;11700 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;13000 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;14600 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;16700 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;19500 об/мин
ldi R16, 180	;множитель
st X+, R16	;в ОЗУ, 45°
ret		;возврат в программу

;==таблица №3,углов опережения в ОЗУ==
;=======для метки 20°, шаг 0.7°=======
FuozTable3:
ldi R27, 0x03	;задаем "highX"=03
ldi R26, 0x00	;задаем "lowX"=00
;опережение при оборотах
;500 и ниже, об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;600 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;800 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;1000 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;1200 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;1500 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;1800 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;2000 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;2200 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;2500 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;2800 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;3000 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;3500 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;3900 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;4200 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;4700 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;5100 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;5600 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;6100 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;6500 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;6900 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;7300 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;7800 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;8300 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;9000 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;9700 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;10600 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;11700 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;13000 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;14600 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;16700 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
;19500 об/мин
ldi R16, 0	;множитель
st X+, R16	;в ОЗУ, 45°
ret		;возврат в программу
