;***************************************************************************
;* A P P L I C A T I O N   N O T E   F O R   T H E   A V R   F A M I L Y
;*
;* Number               : AVR test
;* File Name            :"T25time.asm"
;* Title                :Tiny25 timer
;* Date                 :24.12.2008
;* Version              :1.0
;* Support forum        :www.skif.biz/index.php?name=Forums&file=viewtopic&t=3078&pagenum=1
;* Support fax          :у деда Вани факса нет, но есть тыр-нет ;-)
;* Target MCU           :tiny25
;*
;* DESCRIPTION
;* пример использования таймера Т0 AtTiny25/45/85 для
;* генератора импульсов нанозажигания
;*
;* The timing is adapted for 8Mhz internal clok
;*
;*Fuses
;*Есть простое правило, которое нужно отработать до автоматизма -
;*перед тем как устанавливать фуз-биты в программаторе, сначала прочитайте их из МК.
;*По состоянию фуза SPIEN сразу станет ясно, прямая или инверсная кодировка
;*у вашей программы-программатора.
;*
;*  OSCCAL        = 90
;
;*  CKDIV         = 1   8MHZ     =0  1MHZ
; Определяет начальное состояние делителя системного
;тактового сигнала

;*  CKOUT         = 1            =0  PB3 out
; Определяет состояние выходного буфера системного  тактового сигнала
; (0 - подключен к выводу микроконтроллера, 1 - отключен)

;*  SUT           = 0
; Определяет длительность задержки сброса /ТОит

;*  CKSEL         = 2
; Определяет режим работы тактового генератора, а также
; длительность задержки сброса /ТОит

;*  RSTDISBL      = 1
; Определяет функционирование вывода  микроконтроллера,
; совмещенного с выводом аппаратного сброса
; (0 -  контакт порта ввода/вывода, 1 - вывод сброса)

;*  DWEN          = 1
; Разрешает/запрещает работу отладочного интерфейса
; debugWire (0 - разрешена, 1 - запрещена)

;*  WDTON         = 1
;Определяет режим работы сторожевого таймера
; (0 -всегда включен, 1 - может быть выключен программно)
;Сторожевой таймер (Watch Dog Timer) призван защитить микроконтроллер от зависания.
;Работает это следующим образом:
;запускается этот самый Сторожевой таймер (фьюз WDTON у ATtiny2313), начинается отсчет,
; при достижении заданного значения таймер сбрасывает микроконтроллер.
;По ходу программы нужно постоянно сбрасывать сторожевой таймер до того как он переполниться
; и сбросит микроконтроллер (это делается командой WDR).
;Если программа зациклилась или микроконтроллер завис и команда WDR больше не вызываться,
; произойдет переполнение сторожевого таймера и сброс микроконтроллера.
;После сброса программа начинает работать с начала.
;Применяется для ответственных приложений, там где важно не потерять контроль над объектом.
;
;*  EESAVE        = 1      Определяет влияние команды <Стирание кристалла> на
; EEPROM-память (0 - не стирает, 1 - стирает)

;*  BODLEVEL      = 7   Определяет порог срабатывания схемы BOR

;*  SELFPRGEN     = 1  Разрешение самопрограммироввния (0 - разрешено, 1 - запрещено)
;*
;*
;*
;***************************************************************************
;.device tiny25							;определяет тип микроконтроллера,для которого пишется программа.
										;По этой директиве в ассемблере выбирается файл,
										;в котором присвоены имена регистрам ввода-вывода
										;и их разрядам, указана емкость запоминающих устройств
										;и отмечены другие особенности микроконтроллера используемого типа.
										; "медитируем до полного прояснения- для чего каждая строчка написана"-
.include "tn25def.inc"					;директива ".include" указывает имя дополнительного файла,
										;который должен быть использован в процессе ассемблирования.
.def      tmp	= r16                   ; директива ".def" присваивает символИческое(то есть из символов)
                                        ; имя Регистру Общего Назначения (сокращенно - РОН).
                                        ; РОН R16 теперь называется просто tm,
                                        ; по этой кличке мы его будем дальше обзывать в программе

.equ	TCYKLE0	= 240					; set 30mks 
.equ	TPULSE0	= 40					; set 5mks
.equ	CYKLES0	= 30					; Cчётчик циклов (для куражу можно 33 ;-)

.equ	PRESCL0	= 0x09					; prescaller & clock sourse таймера 68 c. ДШ


.equ	TCYKLE1	= 200					; set 200 mks
.equ	TPULSE1	= 100					; set  OCR1B
.equ	CYKLES1	= 10					; Cчётчик MAX циклов пачки = 2 ms

.equ	PRESCL1	= 0x44					; prescaller & = / 8   c4 ???

.equ	GMSK	= 0x40					; Global Int Mask
.equ	TMSK	= 0x06					; Timers Int Mask



.cseg                                   ; определяет тип сегмента CSEG (всего три типа сегментов:
                                        ; 1. CSEG - программный сегмент(Кодовый сегмент);
                                        ; 2. ESEG - сегмент EEPROM;
                                        ; 3. DSEG - сегмент данных(Сегмент ОЗУ,(RAM))
; ***************************************
; Таблица прерываний МК АТини25 из ДШ
; ***************************************
.org 0		rjmp    reset               ; прерывание по сбросу или при сбое питания и прыгаем на метку "reset:"
.org 1		rjmp	ext_int0			; IRQ0 Handler
.org 2		reti	;rjmp	pc_int0				; PCINT0 Handler
.org 3		reti	;rjmp	tim1_compa			; Timer1 CompareA Handler
.org 4		rjmp	tim1_ovf			; Timer1 Overflow Handler
.org 5		rjmp    tim0_ovf			; Timer0 Overflow Handler
.org 6		reti	;rjmp    ee_rdy				; EEPROM Ready Handler
.org 7		reti	;rjmp	ana_comp			; Analog Comparator Handler
.org 8		reti	;rjmp	adc_conv			; ADC Conversion Handler
.org 9		reti	;rjmp	tim1_compb			; Timer1 Compare b Handler
.org 10		reti	;rjmp	tim0_compa			; Timer0 Compare a Handler
.org 11		rjmp	tim0_compb			; Timer0 Compare b Handler
.org 12		reti	;rjmp	wdt
.org 13		reti	;rjmp	usi_start
.org 14		reti	;rjmp	usi_ovf

;.org 20

; ***************************************
; Старт главной программы после сброса
; ***************************************

reset:		ldi     r16, low(ramend)	; Загрузка указателя стэка - stack
			out     spl, r16            ; set low reg stack

			ldi     r16, 0x90           ; подстройка тактового генератора
			out     osccal, r16         ; set generator запись tm в osccal
			clr		r5					; Program ZERO
										
			; Настройка портов

            ldi		r16, 0x0b			; PB0 = A0  PB1 = OC0B  PB3 = A1  Выходы 09 | 0B
            out     ddrb, r16			; PB2 = DX  PB4 = Входы 
			clr		r17					; r17 - N channel
            out     portb, r17			; CH = 0

			ldi		r16, TMSK			; OCIE0B - Timer/Counter0 Compare Match Interrupt Enable
			out     timsk, r16			; прерывания tim0_compb и timovf 8 | 2 0x0a  OCIE1B

			; Настройка ext_int0

			ldi		r16, 0x23			; set sleep enable + ext_int0 enable rising
			out		mcucr, r16			; разрешаем режим сна

			ldi		r16, GMSK			; 
			out     gimsk, r16			; Разрешаем прерывание ext_int0

			cli							; Запрет прерываний By Wait 1 CYL На всякий случай ...

			; Настройка таймеров

timer0:		ldi		r16, TCYKLE0		; set 30mks  записываем в r16 значение "0xf0" f0=240тактов=30mks, 1 такт 0,125мкс
			out		ocr0a, r16			; пишем в таймер ocr0a значение tm="0xf0"(завели его на повтор через 30mks) и запускаем

			ldi		r16, TPULSE0		; set 5mks, через 5mks(28=40тактов=5mks) сбросит выход в ноль.
			out		ocr0b, r16			; пишем в таймер ocr0b значение 0x28

;*			ldi		r16, 0x63			; Регистр контроля - set fast PWM wgm02 in tccr0b это 08 !
			ldi		r16, 0x33			; Регистр контроля - set fast PWM wgm02 in tccr0b это 08 !
			out		tccr0a, r16			; OCRb- output = 0b01100011

timer1:		ldi		r16, TCYKLE1		; метка "timer1:" ЗАПУСК RTC 200 mks
			out		ocr1a, r16			; 
			out		ocr1c, r16			; 
			
			ldi		r16, TPULSE1		; 
			out		ocr1b, r16			; 

			out		gtccr, r5			; Timer/Counter1 control. На всякий случай ...

			; Ожидание 1-го цил. т.е. DX2

            ldi		r17, 0x09			; CH = 3
            out     portb, r17			; DX2 - By Wait 1 CYL

wcyl1:		in		r16, PINB			; цикл ожидания DX2 1 CYL
			andi	r16, 0x10			; PB4
			breq	wcyl1				; Нет 1 - уходим

			; пуск таймеров будет после прерывания INT0 !

dispetcher:	sei							; разрешаем прерывания
			nop
			sleep						; уходим спать
			nop
			rjmp	dispetcher			; уходим спать ещё раз, недоспали ... ;-)

; ********************************************
; Обслуживание прерывания при переполнении T0
; ********************************************

tim0_ovf:	dec		r18					; Декркмент счётчика циклов - Все искры дали ?
			brne	ovf0				; Счётчик циклов не обнулился - возврат

			sbi		PORTB, 3			; Начало накачки - отправляем в /dev/null ;-)

			out		tccr1,  r5			; Oстанов таймера 1. Вроде как уже не нужен...

			ldi		r16, 0x0e			; Разрешим OCIE0B
			out     timsk, r16			; Там штатно выключим Т0. Почему, см. ниже...

ovf0:		reti						; разрешаем прерывания и возврат

; ********************************************
; Обслуживание прерывания при переполнении T1
; ********************************************

tim1_ovf:	dec		r19					; Декркмент счётчика циклов
			brne	ovf1				; Счётчик циклов не обнулился - возврат

			; А тут - пока Х Е З  ;-(
			
ovf1:		reti						; разрешаем прерывания и возврат

; ********************************************
; Обслуживание прерывания при переключении T0
; ********************************************

tim0_compb:	out     tccr0b, r5			; Oстанов таймера 0. Здесь выход всегда в нуле !!!

			cbi		PORTB, 3			; Восстанавливаем канал
										;
			ldi		r16, TMSK			; Восстанавливаем Interrupt Mask - OCIE0B
			out     timsk, r16			; прерывания

			reti						; разрешаем прерывания и возврат

; ******************************************
; Прицепленный ДХ Запуск пачки импульсов
; ******************************************

ext_int0:	ldi     r18, CYKLES0		; Загружаем счётчик циклов T0
			ldi     r19, CYKLES1		; Загружаем счётчик циклов T1

			ldi		r16, TCYKLE0-1		; set 30mks - 1 такт
			out		tcnt0, r16			; пишем в таймер стартовое значение

			in		r17, PINB			; Какой цилиндр был ?
			andi	r17, 0x01			; 
			breq	cyl0				; Переключаем цилиндр !
			clr		r17					; CH = 0
			rjmp	cout
cyl0:		ldi		r17, 0x01			; CH = 1
cout:		out     portb, r17			; Включаем нужный цилиндр !

			ldi		r16, PRESCL0		; set prescaller & clock sourse таймера 68 c. ДШ
			out		tccr0b, r16			; пуск таймера 0

			ldi		r16, PRESCL1		; set prescaller  0xc4
			out		tccr1, r16			; пуск таймера 1

			reti						; разрешаем прерывания и возврат


.db "Nano Ignition DI - V2.20 from JohnZ", 0	; Версия прошивки. Чё зря мозгам пропадать ? ;-)

; ************************************************************************
