.include "m8def.inc"	;AT8-16, кварц4МГц

.org 0				;начало кода
rjmp start
.org 1				;External Interrupt0 Vector Address
.org 2				;External Interrupt1 Vector Address
.org 3				;Output Compare2 Interrupt Vector Address
.org 4				;переполнение timer2
.org 5				;Input Capture1 Interrupt Vector Address
.org 6				;Output Compare1A Interrupt Vector Address
rjmp timer1compare
.org 7				;Output Compare1B Interrupt Vector Address
.org 8				;переполнение timer1
rjmp timer1
.org 9				;переполнение timer0
.org 10				;SPI Interrupt Vector Address
.org 11				;USART Receive Complete Interrupt Vector Address
.org 12				;USART Data Register Empty Interrupt Vector Address
.org 13				;USART Transmit Complete Interrupt Vector Address
.org 14				;вектор прер. АЦП
.org 15				;EEPROM Interrupt Vector Address
.org 16				;Analog Comparator Interrupt Vector Address
.org 17 			;Irq. vector address for Two-Wire Interface
.org 18				;SPM complete Interrupt Vector Address
.org 19				;SPM complete Interrupt Vector Address


start:
;=========Стек===========
ldi R16, low(RAMEND) ;низ стека
out SPL, R16 
ldi R16, high(RAMEND);верх стека
out SPH, R16
;====установка портов====
ldi R16, 0b00000001
out ddrC, R16		;установка порта С0 на выход сигнала
ldi R16, 0b00110000
out PortC, R16		;выход С0 в"0",+подтягивающие резисторы C5,C4
ldi R16, 0b00000000
out ddrD, R16		;установка порта D0 на вход сигнала
ldi R16, 0b00000001
out PortD, R16		;+подтягивающий резитор D0
clr R2				;"0", для умножения
clr R3				;множитель задержки из ОЗУ H
clr R4				;множитель задержки из ОЗУ L
clr R5				;старший бит задержки x%
clr R6				;младший бит задержки x%
clr R7				;OCR1AH
clr R8				;OCR1AL
clr R9				;TCNT1H
clr R10				;TCNT1L
clr R19				;задержка опускания искры
clr R20				;РОН статуса
clr R21				;РОН рассчета задержки для ОЗУ
clr R25				;множитель задержки из ОЗУ
clr R26				;РОН "lowX",адресация ОЗУ,LD
clr R27				;POH "highX",адресация ОЗУ,LD
;===таблица в озу===
rcall FuozTable1
rcall FuozTable2
rcall FuozTable3	;таблицы задержек в ОЗУ
;========Timer+ADC=======
ldi R16, 0b00000010	;задержка 8,для счета при 4МГц
out TCCR1B, R16 	;пуск таймера 16-бит
ldi R16, 0b00010100
out TIMSK, R16 		;вкл. переполнение 8и16-бит счетчиков
sei 				;вкл. прерывания в ЦП
;==конец инициализации устройств, далее основной код==

main:
;блок задержки искры, опускает искру
;не отнимая сремени ЦП на выполнение кода
sbic PinC,0		;выполнить если бит порта "1"
inc R19			;+1
cpi R19, 0x80	;задержка лог "1"на выходе"искра"
brlo main2		;перейти если меньше
;а если больше, опустим искру
cbi PortC,0		;лог"0"на выход "искра"
clr R19			;РОН задержки опускания искры
main2:

;ожидание импульса
sbic PinD,0		;выполнить если бит порта "1"
rcall noimpuls

;пришел ипмульс датчика
sbis PinD,0		;выполнить если бит порта "0"
rcall impuls

sbrs R20, 5		;if pinX,n='0' then do
rjmp main
sbrc R20, 7		;if pinX,n='1' then do
rcall holostie
sbrs R20, 7		;if pinX,n='0' then do
rcall norm

rjmp main
nop
nop
nop
;-------------------------------------------------------------
;----------------далее только подпрограммы--------------------
;-------------------------------------------------------------
;==переполнение 16-бит счетчика==
timer1:
;переполнение означает что частота оборотов ниже 480/мин
ori R20, 0b10000000	;sbiR20/7, контроль
reti

;=совпадение сравнения OCR1A, 16-бит счетчика=
timer1compare:
;совпадение угла опережения, рассчетная искра
sbrs R20, 4		;if pinX,n='0' then do
reti
sbi PortC,0		;лог"1"на выход "искра"
andi R20, 0b11101111;cbiR20/4, контроль
reti

;====импульс вмт датчика====
impuls:
sbrc R20, 6		;if pinX,n='1' then do
ret				;если уже был счет то выход
in R10, TCNT1L
in R9, TCNT1H	;считываем показания счетчика
clr R16
out TCNT1H, R16
out TCNT1L, R16	;обнуляем счетчик
ori R20, 0b01100000	;sbiR20/6,5, контроль
;показания счетчика записаны, счетчик обнулен
;контроль 2 бит, один обнуляеться при рабочем ходе
;второй при расчете гтовности искры
ret

;==нет импульса, рабочий ход==
noimpuls:
andi R20, 0b10111111;cbiR20/6, контроль
ret

;====нормальные обороты=====
;=определяем задержку искры=
norm:
mov R21, R9		;скопируем значение счетчика 16-бит
com R21			;инвертируем число
;теперь имеем 255 значений счетчика оборотов,
;наименьшее значение - медленные обороты, большее - большые
;для усреднения точек таблицы выборка делаеться
;через некоторое число точек, для равномерности
///////////////////////////////////////////////////
;cpi R21, 249	;сравнение РОН с контстантой
;brsh rpm19k5	;если больше или равно
;cpi R21, 248	;сравнение РОН с контстантой
;brsh rpm16k7	;если больше или равно
;cpi R21, 247	;сравнение РОН с контстантой
;brsh rpm14k6	;если больше или равно
;cpi R21, 246	;сравнение РОН с контстантой
;brsh rpm13k		;если больше или равно
;cpi R21, 245	;сравнение РОН с контстантой
;brsh rpm11k7	;если больше или равно
;cpi R21, 244	;сравнение РОН с контстантой
;brsh rpm10k6	;если больше или равно
cpi R21, 243	;сравнение РОН с контстантой
brsh rpm9k7		;если больше или равно
cpi R21, 242	;сравнение РОН с контстантой
brsh rpm9k		;если больше или равно
cpi R21, 241	;сравнение РОН с контстантой
brsh rpm8k3		;если больше или равно
cpi R21, 240	;сравнение РОН с контстантой
brsh rpm7k8		;если больше или равно
cpi R21, 239	;сравнение РОН с контстантой
brsh rpm7k3		;если больше или равно
cpi R21, 238	;сравнение РОН с контстантой
brsh rpm6k9		;если больше или равно
cpi R21, 237	;сравнение РОН с контстантой
brsh rpm6k5		;если больше или равно
cpi R21, 236	;сравнение РОН с контстантой
brsh rpm6k1		;если больше или равно
cpi R21, 234	;сравнение РОН с контстантой
brsh rpm5k6		;если больше или равно
cpi R21, 232	;сравнение РОН с контстантой
brsh rpm5k1		;если больше или равно
cpi R21, 230	;сравнение РОН с контстантой
brsh rpm4k7		;если больше или равно
cpi R21, 227	;сравнение РОН с контстантой
brsh rpm4k2		;если больше или равно
cpi R21, 225	;сравнение РОН с контстантой
brsh rpm3k9		;если больше или равно
cpi R21, 222	;сравнение РОН с контстантой
brsh rpm3k5		;если больше или равно
cpi R21, 216	;сравнение РОН с контстантой
brsh rpm3k		;если больше или равно
cpi R21, 213	;сравнение РОН с контстантой
brsh rpm2k8		;если больше или равно
cpi R21, 208	;сравнение РОН с контстантой
brsh rpm2k5		;если больше или равно
cpi R21, 202	;сравнение РОН с контстантой
brsh rpm2k2		;если больше или равно
cpi R21, 197	;сравнение РОН с контстантой
brsh rpm2k		;если больше или равно
cpi R21, 190	;сравнение РОН с контстантой
brsh rpm1k8		;если больше или равно
cpi R21, 177	;сравнение РОН с контстантой
brsh rpm1k5		;если больше или равно
cpi R21, 158	;сравнение РОН с контстантой
brsh rpm1k2		;если больше или равно
cpi R21, 138	;сравнение РОН с контстантой
brsh rpm1k		;если больше или равно
cpi R21, 110	;сравнение РОН с контстантой
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
rjmp RpmEnd
;адрес ОЗУ "lowХ" определен
;задействованно ОЗУ 0х0100-0х011F,32строки
RpmEnd:

;выбор таблицы УОЗ тумблером на"0"
;приоритет у нижних таблиц
ldi R27, 0x01	;задаем "highX"таблица№1
sbis PinC,5		;выполнить если бит порта "0"
ldi R27, 0x02	;задаем "highX"таблица№2
sbis PinC,4		;выполнить если бит порта "0"
ldi R27, 0x03	;задаем "highX"таблица№3

;адрес ОЗУ "HighХ" определен, чтение ОЗУ
ld R25, X		;байт из ОЗУ-R27:26 загружается в РОН25
;проверим на нулевое значение, что
;соответствует оборотам более 4к
;при этом искра по датчику уоз,20°
cpi R25, 0x01	;"1"
brlo iskra		;если задержка "0",искра без задержки

;проверим на значение более DD,уоз=100°
;соответствует опережению больше угла датчика
;при этом искра до датчика уоз
clr R3			;РОН3=0, чистим старшый разряд множителя
cpi R25, 0xDD	;100°
brlo nizkie	;если меньше, то переходим на штатную
;проверим на первое срабатывание
sbrs R20, 3		;if pinX,n='0' then do
sbi PortC,0		;лог"1"на выход "искра"
ori R20, 0b00001000	;sbiR20/3, контроль
inc R3			;РОН3=1,вторые пол оборота,для выше датчика
rjmp raschet

;этот карман нужен для не пропуска при переходе
nizkie:
andi R20, 0b11110111;cbiR20/3, контроль

;далее основной расчет, для всех режимов один блок
raschet:
;mov R4, R25		;РОН25 неизменен, множитель УОЗ
;рассчет УОЗ
mov R5, R9		;копируем счет 16-бит,H
mov R6, R10		;копируем счет 16-бит,L
lsr R5			;1/2,шаг смены
ror R6			;угла 720°/512=1.4°
;========умножение:R6*R3R4=R7R8======================
mul R5,R3		;умножаем старшие
mov R7,R0
mul R6,R3		;младший и старший
mov R8,R0
mul R5,R25		;старший и младший
add R8, R0
adc R7, R1
mul R6,R25		;младший и младший
add R8,R1
adc R7,R2		;R2=0
;теперь имеем R7R8 значение задержки
;запишем в регистр сравнения 16-бит счетчика
out OCR1AH, R7	;записываем задержку HighByte
out OCR1AL, R8	;записываем задержку LowByte
ori R20, 0b00010000	;sbiR20/4, контроль
andi R20, 0b11011111;cbiR20/5, контроль
ret

;==искра без задержки==
;====== УОЗ 20° =======
iskra:
sbi PortC,0		;лог"1"на выход "искра"
andi R20, 0b11011111;cbiR20/5, контроль
ret

;==холостые(низкие) обороты==
;режим активен при переполнении счетчика
;когда обороты ниже чем 460/мин
;при этом рассчет задержки невозможен
;и имеет смысл делать ее константой для
;познего зажигания 4°,без пропусков искры
holostie:
ser R16			;РОН=0xFF
mov R9, R16		;сработает как 500/мин
mov R10, R16	;и мл.
andi R20, 0b01111111;cbiR20/7, контроль
ret

///////////////////////////////////////////////////////////
;таблица контрольных бит, РОН20
;R20/7-холостые обороты, переполнение 16-бит счетчика
;R20/6-пришел импульс с датчика, бит-1, контроль вала
;R20/5-пришел импульс с датчика, бит-2, контроль рассчета
;R20/4-окончен рассчет опережения, вкл. сравнение 16-бит
;R20/3-переход на опережение оборота 0x1FF
///////////////////////////////////////////////////////////

;==таблица №1,углов опережения в ОЗУ==
;=======для метки 22°, шаг 0.1°=======
FuozTable1:
ldi R27, 0x01	;задаем "highX"=01
ldi R26, 0x00	;задаем "lowX"=00
;опережение при оборотах
;400 и ниже, об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 4,4°
;600 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 6,5°
;800 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 8.7°
;1000 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 10.8°
;1200 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 13°
;1500 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 16.2°
;1800 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 19.5°
;2000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 21,7°
;3000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 21,9°
;4000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 22°
;5000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 22.3°
;6000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,5°
;7000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,7°
;8000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,9°
;9000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 23,1°
;10000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 23.3°
;11000 об/мин
ldi R16, 252	;множитель
st X+, R16	;в ОЗУ, 23,5°
ret		;возврат в программу

;==таблица №2,углов опережения в ОЗУ==
;=======для метки 22°, шаг 0.1°=======
FuozTable2:
ldi R27, 0x02	;задаем "highX"=02
ldi R26, 0x00	;задаем "lowX"=00
;опережение при оборотах
;400 и ниже, об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 4,4°
;600 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 6,5°
;800 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 8.7°
;1000 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 10.8°
;1200 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 13°
;1500 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 16.2°
;1800 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 19.5°
;2000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 21,7°
;3000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 21,9°
;4000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 22°
;5000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 22.3°
;6000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,5°
;7000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,7°
;8000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,9°
;9000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 23,1°
;10000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 23.3°
;11000 об/мин
ldi R16, 252	;множитель
st X+, R16	;в ОЗУ, 23,5°
ret		;возврат в программу

;==таблица №3,углов опережения в ОЗУ==
;=======для метки 22°, шаг 0.1°=======
FuozTable3:
ldi R27, 0x03	;задаем "highX"=03
ldi R26, 0x00	;задаем "lowX"=00
;опережение при оборотах
;400 и ниже, об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 4,4°
;600 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 6,5°
;800 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 8.7°
;1000 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 10.8°
;1200 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 13°
;1500 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 16.2°
;1800 об/мин
ldi R16, 11	;множитель
st X+, R16	;в ОЗУ, 19.5°
;2000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 21,7°
;3000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 21,9°
;4000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 22°
;5000 об/мин
ldi R16, 254	;множитель
st X+, R16	;в ОЗУ, 22.3°
;6000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,5°
;7000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,7°
;8000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 22,9°
;9000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 23,1°
;10000 об/мин
ldi R16, 253	;множитель
st X+, R16	;в ОЗУ, 23.3°
;11000 об/мин
ldi R16, 252	;множитель
st X+, R16	;в ОЗУ, 23,5°
ret		;возврат в программу


