.INCLUDE     "tn2313def.inc"
;==============================================================
;              Программа "ИК барьер"
;              Написана для AT90S2313.
;===============================================================
.org 000
	rjmp reset		;Вектор сброса
.org 001
	rjmp ext_int0	;Вектор прерываний от вывода INT0
.org 006
	rjmp tim_ovf0	;Вектор прерываний от таймера/счетчика0
;==============================================================
;Подпрограмма обработки прерываний от вывода INT0.
;==============================================================
ext_int0:
	ldi r31,25
	rcall pause	;Вызываем подпрограмму задержки
	reti		;Выход из подпрограммы обработки прерывания
;==============================================================
;Подпрограмма обработки прерываний от таймера/счетчика 0.
;==============================================================
tim_ovf0:
	out tcnt0,r18	;Загружаем таймер длительностью полу периода частоты модуляции
	inc r19		;Увеличиваем значение регистра на единицу
	sbrc r19,0		;Проверяем на четность младший бит r19
	cbi portd,4	;Устанавливаем на выводе PD4 логический 0
	sbrs r19,0		;Проверяем на четность младший бит r19
	sbi portd,4	;Устанавливаем на выводе PD4 логический 1
	reti		;Выход из подпрограммы обработки прерывания
;===============================================================
; С этого места собственно и начинается основная программа.
;===============================================================
reset:
	ldi r16,0b01010010
	out ddrd,r16	;Устанавливаем направление работы порта D
	ldi r16,0b01101100	
	out portd,r16	;Включаем подтягивающие резисторы
	ldi r16,0b00001000	
	out ddrb,r16	;Устанавливаем направление работы порта В
	ldi r16,0b11110111	
	out portb,r16	;Устанавливаем соответствующие уровни на выходах порта В
	ldi r16,$80	
	out spl,r16	;Инициализируем стек
	ldi r16,0b00011000
	out ucr,r16	;Разрешаем роботу приемника и передатчика UART
	ldi r16,$ff
	out ubrr,r16	;Задаем скорость роботы UART
	ldi r16,$1
	out tccr0,r16	;Синхронизируем работу таймера/счетчика 0 на прямую от тактового генератора
	ldi r16,$1
	out tccr1b,r16	;Синхронизируем работу таймера/счетчика 1
	ldi r16,$30
	out mcucr,r16	;Разрешаем энергосберегательный режим работы микроконтроллера
	ldi r18,$cb	;Задаем полу период частоты модуляции
	sei		;Разрешаем прерывания
	clr r1		;Очищаем регистр
start:	
	sbis pind,2	;Проверяем не нажата ли кнопка
	rjmp sleep	;Если нажата то переходим на метку sleep 
	clr r2		;Очищаем регистр
	inc r1		;Увеличиваем значение регистра на единицу
	rcall uart		;Вызываем подпрограмму модуляции сигнала
	sbis usr,rxc  	;Проверяем, принял ли приемник UART переданный байт
	rjmp signal	;Если нет, то включаем сигнализацию
	sbic usr,fe		;Проверяем, не было ли ошибки кадра
	rjmp signal	;Если была ошибка кадра то включаем сигнализацию
	in r2,udr		;Переписываем значение из приемника UART в регистр
	cpse r1,r2		;Сравниваем переданный и принятый байт
	rjmp signal_1	;Если не равно, то включаем сигнализацию
	ldi r31,1
	rcall pause	
	rjmp start		;Возвращаемся в начало цикла
signal:	
in r2,udr		;Переписываем значение из приемника UART
signal_1:ldi r25,3		;Задаем количество сигналов сигнализации
signal_2:ldi r16,0b11000001
	out tccr1a,r16	;Разрешаем работу ШИМа
	cbi portd,6	;Гасим светодиод
	ldi r16,170
	out ocr1al,r16	;Задаем частоту ШИМа
	ldi r31,10		;Задаем время задержки
	rcall pause	;Вызываем подпрограмму задержки
	clr r16
	out tccr1a,r16	;Запрещаем работу ШИМа
	sbi portd,6	;Включаем светодиод
	ldi r31,5		;Задаем время задержки
	rcall pause	;Вызываем подпрограмму задержки
	dec r25		;Отнимаем единицу от значения регистра
	breq start		;Если нулевое значение, то идем на метку start
	rjmp signal_2	;Если нет, то повторяем цикл
sleep:	
	cbi portd,6	;Гасим светодиод
	ldi r31,25
	rcall pause	;Вызываем подпрограмму задержки
	ldi r16,$40
	out gimsk,r16	;Разрешаем прерывания от вывода INT0
	sleep		;Переходим в енергосберегательный режим
	sbi portd,6	;Включаем светодиод
	ldi r16,$0
	out gimsk,r16	;Запрещаем прерывания от вывода INT0
	rjmp start		;Возвращаемся на start

;==============================================================
;  Подпрограмма модуляции и передачи байта UART.
;==============================================================	
uart:
	out udr,r1		;Загружаем байт в регистр передатчика  UART
up:
	out tcnt0,r18	;Загружаем таймер длительностью полу периода частоты модуляции
	ldi r16,$2		
	out timsk,r16	;Разрешаем прерывания по переполнению таймера/счетчика 0
up_1:
	sbis pind,1	;Проверяем логический уровень на выводе  PD1
	rjmp up_1
	ldi r16,$0
	out timsk,r16	;Запрещаем прерывания по переполнению таймера/счетчика 0
	cbi portd,4	;Устанавливаем логический 0 на выводе PD4 
down:
	sbis pind,1	;Проверяем логический уровень на выводе  PD1
	rjmp up		
	sbic usr,txc	;Проверяем, не установлен ли флаг окончания передачи
	rjmp exit
	rjmp down
exit:
	sbi usr,txc		;Сбрасываем флаг окончания передачи
	ret
;==============================================================
;              Подпрограмма задержки. 
;==============================================================
pause:
d_3:	clr r30
d_2:	clr r29
d_1:	dec r29
	brne d_1
	dec r30
	brne d_2
	dec r31
	brne d_3
	ret
.EXIT
