; кварц на 16 мгц
; внутренний делитель отключен
;






.include 	"tn2313adef.inc"	; используем tiny2313a


.def	Temp=R16
.def	Temp1=R17
.def	Temp2=R18
.def	Temp3=R19
.def	Temp4=R20			; регистр исользуемый для сохранения/чтения регистра SREG
.def	Temp5=R21			; 
.def	Temp6=R22			; 
.def	Temp7=R23			; 
.def	Temp8=R24
.def	Temp9=R25










;******************************************************************************
; оперативка
;******************************************************************************



.dseg					; оперативка



ch_count: .byte 1			; номер импульса // 0,1,2 каналы
					; если = 3, то это синхроимпульс
					; если = 4, то это рассинхронизация или старт МК 


THR_len: .byte 2			; зарезервируем 2 байта в ОЗУ = переменная для хранения данных "газ"


ruds_len: .byte 2			; зарезервируем 2 байта в ОЗУ = переменная для хранения данных "ruds"













;******************************************************************************
; константы
;******************************************************************************



.equ	MIDDLE_RUD_const = 0x200	; 512 = нейтраль руля  ( летим прямо )



.EQU	const_1000 = 0x3E8 		; 1000  



.EQU	Chastota_const=0x9C40 		; вершина ШИМ для серопривода ( частота 50 Гц )
					; 50Гц=0,02сек
					; 1 тик таймера = 0,0000005 сек
					; 0,02/0,0000005=40000 ( 0x9C40 )













;******************************************************************************
; программный сегмент 
;******************************************************************************

.cseg

			

.org 0

rjmp RESET				; External Pin, Power-on Reset, Brown-out Reset, and Watchdog Reset






.org ICP1addr				; = 0x0003 Timer/Counter1 Capture Event ( прерывание по захвату )

rjmp ICP1_interruption




.org INT_VECTORS_SIZE











;******************************************************************************
; старт ***********************************************************************
;******************************************************************************

reset:					; включение микроконтроллера



	cli				; глобальный запрет на прерывания


	ldi Temp,low(RamEnd)		; инициализации стека	
	out SPL,Temp			;



	
	ldi Temp,0b11111111		; настроили порт "В" (0-ввод, 1-вывод)
	out DDRB,Temp			; 
					 
		
	ldi Temp,0b00000000		; выводим лог_0
	out PortB,Temp			; 



		
												 
	ldi Temp,0b00111111		; настраиваем порт "D" (0-ввод, 1-вывод)
	out DDRD,Temp 			; 00xxxxxx - вывод информации на сервы
					; 0х000000 - вход с приемника (ICP)



	ldi Temp,0b00000000		; выводим лог_0
	out PortD,Temp			;



;	RCALL	LCD_INIT		; инициализация дисплея




;******************************************************************************
;  настраиваем таймер_1
;******************************************************************************



; ШИМ для сервы ( аппаратный )
; ICP для измерения длительности импульса.


					

	ldi Temp,(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)|(1<<WGM10)
	out TCCR1A,Temp	
				
					; быстрый ШИМ с вершиной в OCR1A // очистить по совпадению, установить при сбросе
					; *1 ( ШИМ с регулируемой частотой )
					; генерации на OC1A в этом режиме нет! по идее можно отключить!


					; COM1A1  / поведение вывода OC1A // 
					; COM1A0  / поведение вывода OC1A // 
					; COM1B1  / поведение вывода OC1B // 
					; COM1B0  / поведение вывода OC1B //  
					; WGM11=1 / режим *
					; WGM10=0 / режим *





	ldi Temp,(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|(1<<cs11)	
	out TCCR1B,Temp					
					; захват с ноги ICP по падающему фронту							;*****
					; тактовый сигнал таймера 1/8 ( 1 тик таймера = 0,5 мкс )
					; *1



					; тактовый сигнал = CK 1:8 (16МГц/8=2Мгц) 1 тик таймера = 0,5 мкс
					; таймер начал считать!!!

					; ICNC1=0 / фильтр шума на контакте ICP // отключено
					; ICES1=0 / захват с ноги ICP по падающему фронту
					; WGM13=1 / режим *
					; WGM12=1 / режим * Быстрый ШИМ ( Fast PWM )
					; CS12=0  / тактовый сигнал
					; CS11=1  / тактовый сигнал 
					; CS10=0  / тактовый сигнал = CK 1:8 (16МГц/8=2Мгц) 1 тик таймера = 0,5 мкс




	LDI Temp,high(Chastota_const)	; зададим Частоту ШИМ ( установим вершину ШИМ )
	OUT OCR1AH,Temp			; и выведем ее в порт сравнения
	LDI Temp,low(Chastota_const)							
	OUT OCR1AL,Temp	



	ldi xh, 0xF			; 4000 = 0x0FA0 - крайнее положение сервопривода...
	ldi xl, 0xA0


	OUT OCR1BH,XH			; зададим длину импульса ( среднее положение )
	OUT OCR1BL,XL			; и выведем ее в порт сравнения





	ldi Temp,(1<<ICIE1)		;  прерывание по захвату включено
	out TIMSK,Temp

					; TOIE1=0  / прерывание по переполнению счетчика таймера_1 // отключено
					; OCIE1A=0 / прерывание компатора_A таймера_1 // отключено 
					; OCIE1B=0 / прерывание компатора_B таймера_1 // отключено
					; ICIE1=1  / прерывание по захвату // включено
					; OCIE0B=0 / прерывание компатора_B таймера_0 // отключено
					; TOIE=0   / прерывание по переполнению счетчика таймера_0 // отключено
					; OCIE0A=0 / прерывание компатора_A таймера_0 // отключено





;******************************************************************************
; настраиваем переменные
;******************************************************************************


	ldi Temp, 4			; устанавливаем флаг рассинхронизации/включения_мк
	sts ch_count, Temp







;******************************************************************************
; сброс таймеров
;******************************************************************************



	ldi Temp,0			; обнуление таймера_1
	out TCNT1H,Temp
	out TCNT1L,Temp

	sei				; глобальное разрешение прерываний




	

;*******************************************************************************
; главный цикл *****************************************************************
;*******************************************************************************


Main_cicle:


	
	rjmp Main_cicle			; циклимся






;*******************************************************************************
; обработка прерывания *********************************************************
;*******************************************************************************

ICP1_interruption:
	



	in temp4,SREG			; сохраняем "SREG"/////////////////////////////////////////////////////
	push temp4




;*******************************************************************************




	in XL,ICR1L 			; читаем младший байт счетчика
	in XH,ICR1H 			; читаем старший байт счетчика



	ldi Temp,0			; обнуление таймера !!!!!!!!!!!!!!!!!!!!! этого делать нельзя!!!!!!!!!! ломается генерация ШИМа
	out TCNT1H,Temp
	out TCNT1L,Temp



;**************************************************************************************************************
; проверка синхронизации ( а так-же нужно при включении мк )
;**************************************************************************************************************



	LDS Temp, ch_count		; читаем номер импульса


	cpi Temp, 4			; флаг рассинхронизации установлен ?
	brne work			; флаг снят, Все сихронизировано!!!!
	rjmp sinhro			; флаг установлен, требуется синхронизация





;*********************************************************************************
; сравниваем полученную длительность с 13 мс ( 0b110010110010000 ) ( 0x6590 )
;*********************************************************************************

sinhro:

	mov Temp,XH			; копируем  "Х"
	mov Temp1,XL



	ldi YH,0x65			; записываем в регистровую пару "Y" 13мс  0x6590
	ldi YL,0x90



	rcall compare_XY16		; сравниваем...

	breq bolshe			; переход на обработку когда X=Y 
	brcs menshe			; переход на обработку когда X<Y
	rjmp bolshe			; переход на обработку когда X>Y 






;*****************************************************************************************
; подпрограмма сравнения 
;*****************************************************************************************


compare_XY16:

	cp Temp,YH			; сравниваем старшие части регистров
	breq xh_eq_yh			; значения старших регистров равны, нужно сравнить младшие xl и yl
					; флаг С - установлен когда X<Y
					; флаг С - сброшен когда X>Y
	ret



xh_eq_yh:

	cp Temp1,YL			; сравниваем младшие части регистров
					; флаг Z=1 когда X=Y
					; флаг С - установлен когда X<Y
					; флаг С - сброшен когда X>Y

	ret                            






;*****************************************************************************************
; ...
;*****************************************************************************************




bolshe:					; это синхроимпульс! 


	ldi Temp, 0			; снимаем флаг включения_МК, устанавливаем флаг 0-го канала 
	sts ch_count, Temp

	rjmp out_1			; выход






menshe:					; это был не синхроимпульс!

	rjmp out_1			; выход







;*****************************************************************************************
; все синхронизировано, можно работать
;*****************************************************************************************


work:						;



channal_check_0:				; проверка канала_0


	LDS Temp, ch_count			; читаем номер импульса


	cpi Temp, 0				; это 0-ой канал ?
	brne channal_check_1			; нет
	rjmp channal_0				; да






channal_check_1:				; проверка канала_1


	LDS Temp, ch_count			; читаем номер импульса


	cpi Temp, 1				; это 1-ый канал ?
	brne channal_check_2			; нет
	rjmp channal_1				; да




channal_check_2:				; проверка канала_2


	LDS Temp, ch_count			; читаем номер импульса


	cpi Temp, 2				; это 2-ой канал ?
	brne channal_check_sinhro		; нет
	rjmp channal_2				; да





channal_check_sinhro:				; синхроимпульс ( если это не канал, значит - синхроимпульс )			



	ldi Temp, 4				; если рассинхронизировалось, то ждем синхронизацию
	sts ch_count, Temp


	rjmp out_1				; выход







;*****************************************************************************************
; РАБОТА С КАНАЛАМИ
;*****************************************************************************************




channal_0:					; канал_0 ( газ )

	
	ldi Temp, 1				; следующим будет канал_1
	sts ch_count, Temp




	rjmp out_1				; выход									



; здесь вырезан код отвечающий за управление двигателями






;**********************************************************************************************



channal_1:					; канал_1 ( курс )




	ldi Temp, 2				; следующим будет канал_2
	sts ch_count, Temp




	rjmp out_1				; выход



; здесь вырезан код отвечающий за управление двигателями





;**********************************************************************************************

channal_2:					; канал_2 ( сервопривод тангажа )





	ldi Temp, 4				; следующим будет СИНХРОИМПУЛЬС
	sts ch_count, Temp





						 
	OUT OCR1BH,XH				; зададим длину импульса
	OUT OCR1BL,XL				; и выведем ее в порт сравнения




	rjmp out_1				; выход





;**************************************************************************************************************
; Выход из прерывания
;**************************************************************************************************************

out_1:	

	

	pop temp4			; извлекаем "SREG" ////////////////////////////////////////////////////
	out SREG, temp4

	RETI				; точка выхода из прерывания



;**************************************************************************************************************
; подключаемые модули
;**************************************************************************************************************

; .include "lcd5110mini.asm"		; подключение драйвера дисплея	




