; Author : Гринев Сергей (for_dgf@mail.ru)
.include "m328pdef.inc"
;****************************************************	Карта входов и выходов
; Порт B							
; PB0(icp)		in	!Mode переключатель - 2
; PB1(osc1)		in	!Mode переключатель - 1
; PB2(ss)		in	!Mode переключатель - 0
; PB3(mosi)		in	!Цифровой вход 
; PB4(miso)		in	!Цифровой вход 
; PB5(sck)		out	!Вспомогательный светодиод на Ардуино
;*******************************************************************************
; Порт D 
; PD0(rxd)			!UART обмен  
; PD1(txd)			!UART обмен  
; PD2(int0)		in	!Вход датчика DH1	
; PD3(int1)		in	!Вход датчика DH2 (отключен)						
; PD4(t0)		out	!Сигнал управления током симистора
; PD5(t1)		in	!Соединить с PD6 
; PD6(ain0)		out	!Соединить с PD5 
; PD7(ain1)		in	!Mode переключатель 3
;*******************************************************************************
; Порт C	
; PC0(adc0)		out	!Сигнал зажигания выход
; PC1(adc1)		in	!Свободен
; PC2(adc2)		in	!Свободен
; PC3(adc3)		in	!Свободен
; PC4(adc4/scl)		in	!
; PC5(adc5/sda)		in	!
;     adc6		in	!Канал АЦП выбора таблицы или Канал АЦП корректора
;     adc7		in	!Канал АЦП выбора таблицы или Канал АЦП корректора

#define	VersionName "1Ц.4T.ДИ - Один импульс"		;Одноцилиндровый двигатель cо штатным индуктивным датчиком
							;Эмуляция второго датчика
#define _Betta 		8.0				;Угловое расстояние от ВМТ до метки Delta. 
#define	_Delta		22.0				;Угловой размер метка Delta
#define	_UOZMax		30.0				;Максимальный угол опережения зажигания (=<LBetta+LDelta)
#define	_UOZMin		_Betta				;Минимальный угол опережения зажигания (>=LBetta)

#define	_Alfa		0.1				;Угловое расстояние отключения сигнала зажигания после метки Delta

#define	_StopTime	2.0				;Время (сек) детектирования режима СТОП
#define	_Manual		5.0				;Угловая апертура ручного корректора УОЗ на +/- (не более половины Delta)
							;Ручной корректор отключается при ADCCanCorSelectr = 0. 
							;Середина кода АЦП соотвествует сдвигу 0 градусов
#define	_Load		0.0                             ;Угловая апертура корректора нагрузки в "-" (не более Delta)

.equ	Base		= 360				;Угол-база в градусах 
.equ	Fn		= 14				;Частота тактовых импульсов, поступающих на таймер Т1

.equ	TblCount	= 8				;Количество таблиц УОЗ  2N (N=1, 2, 4, 8, 16, 32). Номер активной таблицы 
							;переключается напряжением на входе канала АЦП ADCCanTblSelectr. 
							;При ADCCanTblSelectr = 0 номер таблицы выбирается  максимальным из доступных.
.equ	ADCBufferSize	= 8 				;Длина кольцевых буферов каналов АЦП (2, 4, 8, 16, 32)
.equ	LoadBufferSize	= 32 				;Длина кольцевого буфера корректора нагрузки (32, 64, 128)

.equ	ADCCanTblSelectr= 0				;[4..7] - Номер канала мультиплексора датчика ДАД/ДПЗД (выбор активной таблицы)
.equ	ADCCanCorSelectr= 0				;[4..7] - Номер канала мультиплексора ручного корректора УОЗ

.equ	ADCCanA		= 0                             ;[4..7] - Номер канала A пользователя. ADCCanA =0 – канал отключен.
.equ	ADCCanB		= 0                             ;[4..7] - Номер канала Б пользователя. ADCCanB =0 – канал отключен.

.equ	ProtectClk	= 6				;Интервал дискретизации протокола защиты от пульсаций  в мкс
.equ	ProtectCount 	= 2				;Количество повторных чтений протоколом защиты с интервалом ProtectClk после первого 
							;изменения линии датчика. Значение может быть в пределах 1-7.
.equ	CmdLineBit	= 0				;Номер бита сигнала управления 
.equ	TriacLineBit	= 4                             ;Номер бита сигнала управления током симистора
.equ	StartDeltaCode	= 0b00001010			;Код начала метки Delta на цилиндре

.include "core.inc"					;Подключение Ядра (сегмент кода, сегмент данных)          

.dseg
.org EndCoreDseg

.equ	DeltaVitual	= int(_Delta/(Base-_Delta)*65536+0.5)		

.CSEG

.org EndCoreCSeg

reset:  sbi	DDRC,CmdLineBit				;Назначение линии PC0(adc0) контролера для работы на выход
	cbi	PORTC,CmdLineBit			;Деактивировать выходную линию
	sbi	DDRD,TriacLineBit                       ;Назначение линии PD4(t0) контролера для работы на выход
	sbi	PORTD,TriacLineBit			;Включить ток симистора

	SetLEDCtrl  2       				;Светодиод на Arduino отражает состояние основного входного датчика
;0 - Выключен
;1 - Delta
;2 - CPU D2(PD2)
;3 - CPU D3(PD3)
;4 - CPU A3(PC3)
;5 - CPU A2(PC2)
;6 - CPU A1(PC1)
;7 - CPU A0(PC0)
;8 - Остановка
;9 - Низкие обороты
;10- УОЗ макс.
;11- УОЗ мин.
;12- Флаг  Ign1
;13- Флаг  Ign2
;14- UARTCtrl
;15- Включен
	load	A,CoreSetup				;Начальное значение 0b000000X0 (Все включено),
							;где X=ADCDisableBit устанавливает Сore при анализе параметров 
;___________________76543210				;ADCCanTblSelectr, ADCCanCorSelectr, ADCCanA, ADCCanB
	ori	A,0b10101100				;Настройка параметров Ядра
 	store	CoreSetup,A
;Инверсная логика: 0 - включен, 1 - отключен
;7 - Отключен датчик DH2 
;6 - Отключено усреднение по двум отсчетам Т1
;5 - Отключен вызов события ServiceA 			
;4 - Отключен вызов события ServiceB 			
;3 - Отключен корректор для коммутатора ХХ.37.34
;2 - Отключен корректор нагрузки
;1 - Отключен АЦП
;0 - Отключен UART 
        ret
;Если есть DIP переключатели, то следующий блок может отключать включенные ранее функции- 
	sbis	PinD,7					;Если DIP переключатель замкнут на землю, то UART отключен
	sbi	CoreSetup,UARTDisableBit	
	load	A,ECoreSetup
	sbis	PinB,0					;Если DIP переключатель замкнут на землю, то ручной корректор отключен
	cbr	A,(1<<ADCCanCorSelectr)
	sbis	PinB,1					;Если DIP переключатель замкнут на землю, то переключатель таблиц отключен
	cbr	A,(1<<ADCCanTblSelectr)
	store	ECoreSetup,A
	andi	A,0xF0		
        brne	reset1                                  ;Автоматическое отключение АЦП в случае отключения всех каналов	
	sbi	CoreSetup,ADCDisableBit
reset1:	ret						;Возврат в вызывающую программу



;Общее функционирование:

;"Глухой" цикл: 
;		Усреднение буферов АЦП.
;		Расчет добавки к УОЗ от ручного корректора (данные АЦП).
;		Расчет добавки к УОЗ от корректора нагрузки (рассчетные данные).
;		Переключение таблиц УОЗ (данные АЦП).		
;		Обслуживание UART в части выполнения команд от программы UOZ.exe 
;		Вызов события loop.
;		Обслуживание АЦП в режиме останова двигателя 
;"Глухой" цикл временно прерывается событиями в системе:

;- Завершение приема в буфер очередной команды по UART от программы UOZ.exe.

;- Прерывания от механизма контрольного чтения входных линий датчика. 
;  Начинаются после физического изменения уровня входных датчиков и повторяются заданное количество ProtectCount раз 
;  или вплоть до подтвреждение изменений c периодом ProtectClk (мкс). 

;1. Actions - Любое подтвержденное изменение сигнала датчика. В случае совпадения кодовой последовательности
;   значений уровня датчика в данный и 3 предыдущих моментах времени с цепочкой StartDeltaCode - запуск события 2.

;2. Начало DELTA (_Betta+_Delta {28 грд.}): Вычисления, АЦП (чтение), программирование событий 3 и 4,  

;3. Зажигание в цилиндре по событиям Ignition или UOZMinError (_Betta+_Delta..._Betta {28...10 грд.}).
;!![cобытие Ignition происходит при равенстве таймера OCR1А внутри виртуального импульса Delta]
;!![cобытие UOZMinError происходит в случае не возможности установки заданного угла]

;4. ServiceB - Завершение DELTA (_Betta {~ 10грд.}): АЦП (запуск), вычисление события 5, контрольная активации линии зажигания.
;!![cобытие ServiceB происходит при равенстве таймера OCR1B внутри виртуального импульса Delta]

;5. Service - (_Betta-_Alfa {~5 грд.}): Выключение сигнала зажигания, досрочное выполнение события 6 или его программирование.
;!![cобытие Service происходит при равенстве таймера OCR1B вне виртуального импульса Delta - измерительный интервал]

;Основная программа (вызывается Ядром постоянно)
loop:	ret                                             ;Возврат в вызывающую программу

Actions:
	cpi	Events,StartDeltaCode			;Сравнение регистра Событий с признаком начала метки на DH1
	brne	C_exit					;Если не равны, то проверка следующего кода

	sbrc	Selectr,7 				;Если обороты выше табличных то сразу зажигание
	sbi	PORTC,CmdLineBit	
	StartDelta                                      ;Макрос отметки времени (начало виртуального импульса Delta)
							;!!Программирование времени события Ignition							
	sbrc	Selectr,7				;Если обороты выше табличных то угол максимален
	sts	UOZCurrent,zerro
	sbrc	Selectr,7                               ;Если обороты выше табличных то угол максимален
	sts	UOZCurrent+1,zerro
	push	r0					;!!Вычисление времени завершения виртуального импульса LDELTA
	push	r1                                      ;По факту этого произойдет событие ServiceB
	ldi	temp,High(DeltaVitual)			
	mul	temp,NH	
	movw	ZH:ZL,r1:r0
	mul	temp,NL
	add	ZL,r1
	adc	ZH,zerro
	ldi	temp,Low(DeltaVitual)
	mul	temp,NH
	add	ZL,r1
	adc	ZH,zerro
	store	OCR1BH,ZH				;!!Программирование времени события ServiceB
	store	OCR1BL,ZL
	pop	r1
	pop	r0
C_exit:	ret        					;Возврат в вызывающую программу

ServiceA:
	ret						;Возврат в вызывающую программу
					
UOZMinError:
Ignition:	
	sbi	PORTC,CmdLineBit			;Включить сигнал зажигания принудительно на конце метки DELTA
	ret						;Возврат в вызывающую программу

Service:cbi	PORTC,CmdLineBit     		        ;Отключение сигнала зажигания 
	ret						;Возврат в вызывающую программу

ServiceB: 						;!!Конец виртуального импульса LDELTA
	sbi	PORTC,CmdLineBit			;!!!Включить сигнал зажигания принудительно на конце метки DELTA на 25 мкс.
	StopDelta                                       ;Макрос отметки времени (окончание виртуального импульса Delta) ~ 25 мкс
	ret						;Возврат в вызывающую программу

;****************************************************** Заполнение базовых таблиц из разметочной таблицы
FillIndex: 
	FTW	0xFFFF					;458  1/мин
	FTW	0xA7A9					;700  1/мин
	FTW	0x92B4					;800  1/мин
	FTW	0x8267					;900  1/мин
	FTW	0x755C					;1000  1/мин
	FTW	0x6AB1					;1100  1/мин
	FTW	0x6375					;1180  1/мин
	FTW	0x5C69					;1270  1/мин
	FTW	0x53D4					;1400  1/мин
	FTW	0x4E3E					;1500  1/мин
	FTW	0x4572					;1690  1/мин
	FTW	0x3D20					;1920  1/мин
	FTW	0x3559					;2200  1/мин
	FTW	0x2E63					;2530  1/мин
	FTW	0x2B78					;2700  1/мин
	FTW	0x27EB					;2940  1/мин
	FTW	0x24AD					;3200  1/мин
	FTW	0x2285					;3400  1/мин
	FTW	0x209A					;3600  1/мин
	FTW	0x1EE2					;3800  1/мин
	FTW	0x1D57					;4000  1/мин
	FTW	0x1BF1					;4200  1/мин
	FTW	0x1AAC					;4400  1/мин
	FTW	0x1983					;4600  1/мин
	FTW	0x1873					;4800  1/мин
	FTW	0x1779					;5000  1/мин
	FTW	0x1692					;5200  1/мин
	FTW	0x15BC					;5400  1/мин
	FTW	0x143C					;5800  1/мин
	FTW	0x12EE					;6200  1/мин
	FTW	0x11C8					;6600  1/мин
	FTW	0x10C4					;7000  1/мин
	ret

FillTable: 
	FTB	0xFA					;8  град.
	FTB	0xFA					;8  град.
	FTB	0xFA					;8  град.
	FTB	0xFA					;8  град.
	FTB	0xFA					;8  град.
	FTB	0xF4					;8,5  град.
	FTB	0xEF					;9  град.
	FTB	0xE3					;10  град.
	FTB	0xE5					;9,83  град.
	FTB	0xD9					;10,9  град.
	FTB	0xCD					;11,97  град.
	FTB	0xBC					;13,41  град.
	FTB	0xAC					;14,87  град.
	FTB	0x8A					;17,82  град.
	FTB	0x53					;22,73  град.
	FTB	0x44					;24  град.
	FTB	0x33					;25,52  град.
	FTB	0x2D					;26  град.
	FTB	0x26					;26,68  град.
	FTB	0x25					;26,75  град.
	FTB	0x20					;27,2  град.
	FTB	0x1A					;27,68  град.
	FTB	0x15					;28,16  град.
	FTB	0x14					;28,24  град.
	FTB	0x14					;28,25  град.
	FTB	0x0B					;29  град.
	FTB	0x00					;30  град.
	FTB	0x00					;30  град.
	FTB	0x00					;30  град.
	FTB	0x00					;30  град.
	FTB	0x00					;30  град.
	FTB	0x00					;30  град.
	ret
	