;  Copyright (c) 2008   by  woodocat <woodocat@woodocat.ru>,   ver 1.1
;
;  Example of work IR of remote control   http://woodocat.ru/IR.html
;
;  This program is free software; you can redistribute it and/or modify
;  it under the terms of the GNU General Public License as published by
;  the Free Software Foundation; either version 2 of the License, or
;  (at your option) any later version.
;
;  This program is distributed in the hope that it will be useful,
;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;  GNU General Public License for more details.
;
;  You should have received a copy of the GNU General Public License
;  along with this program; if not, write to the Free Software
;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
;  ********************************************************************
;
;  MCU target		ATtiny12L
;  MCU freq		1.2 MHz
;  RC protocol		NEC



#include	"tn12def.inc"
; --- определение верхних регистов ---
.def	A		= R16			;переменная 1
.def	B		= R17			;переменная 2
.def	C		= R18			;счетчик
.def	D		= R19			;данные
.def	Delay		= R20			;регистр установки задержки

.def	Command_0	= R21			;регистры принятой с пульта команды
.def	Command_1	= R22
.def	Command_2	= R23
.def	Command_3	= R24

.def	one		= R25			;однократное выполнение процедуры


; --- список адресов ---
.equ	RESaddr		= $00			;вектор сброса

; --- основные константы ---
.equ    Delay_1125us	= -168			;f=1.2MHz:   8*168 = 1120 (Err = +0.0%)

; --- определение выводов ---
.equ	IRR		= 1			;PB1 - инфракрасный приемник
.equ	LED		= 3			;PB3 - LED (включается/выключается)





.cseg
; --- таблица векторов прерываний ---
.org	RESaddr
		rjmp	Reset				;вектор сброса
.org	OVF0addr
		rjmp	Timer0_Overflow			;обработчик таймера





; --- инициализация ---
Reset:		cli					;отключение прерываний

		ldi	A,	0b00011101		;вывод IRR (PB1) на ввод, остальные на вывод
		out	DDRB,	A
		ldi	A,	0b00000000		;вывод IRR (PB1) в Hi-Z, остальные в нулях
		out	PortB,	A

		rcall	Reset_TMR			;инициализация таймера
		clr	one				;сброс регистра однократного выполнения

		sei					;разрешаем все прерываения




; --- Faul ---						;при ошибке и при включении мигает CH1
Faul:

; --- Main ---
Main:		clr	Command_0			;очищаем регистры принятой команды
		clr	Command_1
		clr	Command_2
		clr	Command_3

  Main_0:	sbic	PinB,	IRR			;ожидаем 0 (с приемника приходит инвертированный сигнал)
		rjmp	Main_0

                ldi	Delay,	8			;устанавливаем 8 периодов ожидания (8 * 1,125 = 9 мсек)
                rcall	Resync_TMR			;синхронизируем таймер

  Main_1:	tst	Delay				;проверяем пройденное количество периодов
		breq	Faul				;если время вышло, значит ошибка
                sbis	PinB,	IRR			;если появился 1 - выходим
                rjmp	Main_1

                cpi	Delay,	2			;проверем пройденные периоды, если больше 1 - ошибка
                brge	Faul

                ldi	Delay,	4			;устанавливаем 4 периода ожидания (4 * 1,125 = 4,5 мсек)
                rcall	Resync_TMR			;синхронизируем таймер

  Main_2:	tst	Delay				;проверяем пройденное количество периодов
		breq	Faul				;если время вышло, значит ошибка
                sbic	PinB,	IRR			;если появился 0 - выходим
                rjmp	Main_2

                cpi	Delay,	2			;проверем пройденные периоды, если больше 1 - ошибка
                brge	Faul

		; *** Loop ***
		ldi	C,	32			;синхронизация прошла успешно - принимаем 32 бита

  Loop_1:	ldi	Delay,	1			;устанавливаем 1 период ожидания (1,125 мсек)
                rcall	Resync_TMR			;синхронизируем таймер

  Main_3:	tst	Delay				;ждем 1
                breq	Faul				;если уже прошел 1 период (вместо половины) - значит ошибка
                sbis	PinB,	IRR			;если появился 1 - выходим
                rjmp	Main_3

  Main_4:	tst	Delay				;ждем 0
		breq	Main_S1				;более 1 периода (1,125 мсек) -> "1"
                sbic	PinB,	IRR			;менее 1 периода (1,125 мсек) -> "0"
                rjmp	Main_4

     Main_S0:   clc					;записываем "0" в бит переноса
                rjmp	Main_SB
     Main_S1:   sec					;записываем "1" в бит переноса

     Main_SB:	rol	Command_0			;последовательным сдвигом заполняем регистры команды
       		rol	Command_1			;принятывми битами из переноса
       		rol	Command_2
       		rol	Command_3

		dec	C				;уменьшаем счетчик
                brne	Loop_1				;продолжаем цикл


                ; < ДЕЛАЕМ ТУПО, НО БЫСТРО >
		cpi	one,	0			;если это первое принятое нажатие
		brne	Skip
                mov	r0,	Command_0		;запоминаем эту команду
                mov	r1,	Command_1
                mov	r2,	Command_2
                mov	r3,	Command_3
                inc	one				;и  больше сюда не заходим
                Skip:


                ; < СРАВНЕНИЕ КОМАНДЫ >
  Case_0:	cp	r0,	Command_0		;проверяем принятую команду с константой
                brne	Case_End
                cp	r1,	Command_1
                brne	Case_End
                cp	r2,	Command_2
                brne	Case_End
                cp	r3,	Command_3
                brne	Case_End

                sbis	PortB,	LED			;если удачно, переключаем состояние LED
                rjmp	bs_0
           bc_0:cbi	PortB,	LED
                rjmp	sk_0
           bs_0:sbi	PortB,	LED
                sk_0:


  Case_End:     ldi	Delay,	255			;небольшая пауза после удачного приема
                rcall	Resync_TMR
  Wait:		tst	Delay
		brne	Wait

		rjmp	Main




; --- Reset_TMR ---
Reset_TMR:	ldi	A,	0b00000010		;установка коэффициента предделения 8
                out	TCCR0,	A			;8*140 = 1120 (Err = -0.444%)
                ldi	A,	Delay_1125us		;установка счетчика (1,125 мсек)
                out	TCNT0,	A
                ldi	A,	0b00000010		;включаем счетчик
                out	TIMSK,	A
		ret

; --- Resync_TMR ---
Resync_TMR:	ldi	A,	Delay_1125us		;переустановка счетчика (1,125 мсек)
                out	TCNT0,	A
                ret



; --- Timer0_Overflow ---
Timer0_Overflow:
TMR:		ldi	A,	Delay_1125us		;перезагрузка счетчика (1,125 мсек)
		out	TCNT0,	A

                tst	Delay
                breq	TMR_Exit
                dec	Delay

  TMR_Exit:	reti



;  *** NEC Protocol ***
;
;     _______         _   _   _   _         _   _   _   _
;   _|       |_______| |_| |_| |_| |_ ...  | |_| |_| |_| |_
;
;      9,0ms  4,5ms     С0 .. С11              D0 .. D7
;
;
;     "0"                            "1"
;    _   _                         _      _
;   | |_| |_                      | |____| |_
;
;   |___|______ 1,125ms           |______|______ 2,25ms
;

