;* Таймер
;* ATmega16	1 Мгц (внутренний генератор)
;*
;* Описание: При нажатии на кнопку "Пуск", включается нагрузка
;* (в данном случае светодиод) и таймар начинает отсчёт
;* вренени от начального значения (константа tm_MAX) до нуля.
;* Декремент осуществляет прерывание от таймера_1А по совпадению 
;* Во время отсчёта времени опрос кнопки "Пуск" блокируется
;* для этого используется флаг Т (0-опрашивать, 1-не опрашивать)
;* Текушее состояние таймара выводится на восемь светодиодов (PortC)
;* По окончании отсчёта ТАЙМЕР переходит в начальное состояние
;* ожидая нового нажатия кнопки
;*
;* Схема: 
;* PortC - выход, подключено 8 светодиодов (1-горит, 0-не горит)
;*	   выводится остаток времени (регистр tm двоичная система)
;* PortB.0 - вход, кнопка "Пуск" с подтягивающим резистором на"+"
;* 	     1-не нажата, 0-нажата
;* PortB.3 - выход, вкл./выкл нагрузки, в данном случае стоит
;*	     светодиод (1-включено горит, 0-не включено)
;*
;*************************************************************************

.include "C:\avr\avrasm\appnotes\m16def.inc"


;КОНСТАНТЫ

.equ timer_on = 0b00010000	;включение таймера_1А на совпадение
.equ timer_off = 0b00000000	;
.equ tm_MAX = 0x03		;МАХ количество циклов(прерываний) таймера_1А

;***** Регистровые переменные

.def temp0 = r16		;Временный рабочий регистр
.def temp1 = r17		;Временный рабочий регистр

.def key_s = r19		;Длительность (число циклов) удержания клавиши "Пуск"
.def tm = r20			;регистр счётчика (декремент по прерыванию таймера_1А)


;***** Настройка векторов прерываний

.cseg
.org 0			;Адрес перезапуска
jmp	Reset
.org	OC1Aaddr
jmp	OC1A		;Совпадение "А" таймера/счётчика Т1


;****************************************************
; ИНИЦИАЛИЗАЦИЯ
;****************************************************

Reset:

ldi temp0,low(RAMEND)
out SPL,temp0			;Инициализация указателя стека
ldi temp0,high(RAMEND)
out SPH,temp0

cli				;Общее запрещение прерываний

ldi temp0,0b11111111		;настройка портов
out DDRC,temp0			;порт С - 8 светодиодов индикации

ldi temp0,0b00001000		;PinB.0 - вход, клавиша "Пуск"(0-нажата)
out DDRB,temp0			;PinB.3 - выход светодиод-нагрузка (1-горит)
				
ldi temp0,0b00001100		;режим работа СТС (сброс при совпадении)
out TCCR1B,temp0		;тактовый сигнал = CK/256

ldi temp0,0x0F			;установка предела счёта для таймера_1A
out OCR1AH,temp0		; 1МГц/256=3906 = F42 (~ 1сек.)
ldi temp0,0x42
out OCR1AL,temp0

ldi temp0,0x00
mov key_s,temp0			;Обнуление клавиши "Пуск"

ldi tm,tm_MAX			;установка регистра счётчика

clt				;сброс флага Т (опрос кнопок включен)
sei				;Общее разрешение прерываний

;*********************************************************
; ОСНОВНАЯ ПРОГРАММА
;*********************************************************

Start:

out PortC,tm			;вывести на светодиоды состояние регистра счётчика

;***** проверка регистра счетчика на нулевое значение
;***** если ноль - остановить таймер и погасить светодиод (выключить нагрузку)
;***** сбросить флаг Т - включить опрос кнопок

	cpi tm,0		;сравнить регистр счетчика с нулевым значением
	brne metka_1		;перейти по "не равно"

	ldi Temp0,timer_off	;запретить прерывание таймера_1A
	out TIMSK,Temp0	

	cbi	PORTB,3		;Сбросить разряд 3 PinB (светодиод погасить)
	ldi tm,tm_MAX		;установка регистра счётчика
	clt			;сброс флага Т (опрос кнопок включить)
metka_1:

;***** проверка нажатия клавиши "Пуск" (240 раз)
;***** если нажата - запустить таймер_1А, включить светодиод (включить нагрузку)
;***** установить флаг Т - пропускать опрос кнопок пока ТАЙМЕР работает

	brts	end_key		;переход если флаг Т установлен(т.е. не опрашивать кнопку)
	sbic	PINB,0		;Пропуск след.команды если PinB.0 сброшен(кнопка нажата)
	clr	key_s		;Сбросить счетчик "удержания" кнопки
	inc	key_s		;Увеличить на один значение счетчика
	cpi	key_s,0xf0	;сравнить с "пределом" удержания ~ 240раз
	brne	end_key		;перейти по не равно
	clr	key_s		;Сбросить счетчик "удержания" кнопки
        set 			;установить флаг Т (для пропуска опроса кнопок)
	ldi	Temp0,0
	out	TCNT1L,Temp0		;обнуление таймера перед запуском
	out	TCNT1H,Temp0
	ldi	Temp0,timer_on		;разрешить прерывание таймера_1A по совпадению
	out	TIMSK,Temp0
	sbi	PORTB,3		;Установить разряд 3 PinB (светодиод зажечь)

end_key:

rjmp Start

;****************************************************
; ОБРАБОТЧИК ПРЕРЫВАНИЯ по совпадению таймера_1А
;****************************************************

OC1A:
	dec tm	;уменьшить регистр счетчика на 1
reti        		