;Simple Alarm System (Transmitter)
;Version 1.1 RC6
;(c)1997-2008
;Author: Kirill Yelizarov

; *** HOW TO MAKE ***
;1.Select desired processor in MPLAB
;2.Select IR receiver in _IR_REC
;3.Compile

;Possible processor selections:
;12C508, 12C508A, 12C509, 12C509A, 12CE518, 12CE519, 12F508, 12F509, 16F84, 16F84A
;PICs 16F84 and 16F84A are used for debug

;----------- S E L E C T --- Y O U R --- R E C E I V E R ----------- 
;Possible IR receiver selections:
_TBA_2800	EQU	.1	;_TBA_2800 - TBA 2800 (Micronas Intermetall GmbH http://www.intermetall.de)
_BRM_1020	EQU	.2	;_BRM_1020 - BRM-1020 (Bright LED Electronics Corp. http://www.brtled.com)
_TSOP_1738	EQU	.3	;_TSOP_1738 - TSOP-1738 (Vishay SemiconductorsGmbH http://www.vishay.com)
_TSOP_2156	EQU	.4	;_TSOP_2156 - TSOP-2156 (Vishay SemiconductorsGmbH http://www.vishay.com)
; 
_IR_REC		EQU		_TBA_2800		;IR receiver selection
;-------------------------------------------------------------------

;Debug
_DEBUG		EQU		.0	;no debug, normal operation
;Debug levels for 16F84 and 16F84A only
;Some pins are used another way in debug mode 
;Check code before using this option
;_DEBUG		EQU		.1	;output single pulse for receiver calibration 

;Processors
_12C508		EQU		.1
_12C508A	EQU		.2
_12C509		EQU		.3
_12C509A	EQU		.4
_12CE518	EQU		.5
_12CE519	EQU		.6
_16F84		EQU		.7
_16F84A		EQU		.8
_12F508		EQU		.9
_12F509		EQU		.10

	IFDEF	__12C508
	LIST		P=PIC12C508
	INCLUDE		p12c508.inc
_PIC_CPU	equ	_12C508
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__12C508A
	LIST		P=PIC12C508A
	INCLUDE		p12c508a.inc
_PIC_CPU	equ	_12C508A
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__12C509
	LIST		P=PIC12C509
	INCLUDE		p12c509.inc
_PIC_CPU	equ	_12C509
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__12C509A
	LIST		P=PIC12C509A
	INCLUDE		p12c509a.inc
_PIC_CPU	equ	_12C509A
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__12CE518
	LIST		P=PIC12CE518
	INCLUDE		p12ce518.inc
_PIC_CPU	equ	_12CE518
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__12CE519
	LIST		P=PIC12CE519
	INCLUDE		p12ce519.inc
_PIC_CPU	equ	_12CE519
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__12F508
	LIST		P=PIC12F508
	INCLUDE		p12f508.inc
_PIC_CPU	equ	_12F508
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__12F509
	LIST		P=PIC12F509
	INCLUDE		p12f509.inc
_PIC_CPU	equ	_12F509
_PIC_MEM	equ	0x0a
	ENDIF

	IFDEF	__16F84
	LIST		P=PIC16F84
	INCLUDE		p16f84.inc
_PIC_CPU	equ	_16F84
_PIC_MEM	equ	0x0c
	ENDIF

	IFDEF	__16F84A
	LIST		P=PIC16F84A
	INCLUDE		p16f84a.inc
_PIC_CPU	equ	_16F84A
_PIC_MEM	equ	0x0c
	ENDIF

	IFDEF _PIC_CPU
	IFDEF _IR_REC

	IF (_PIC_CPU==_12C508)||(_PIC_CPU==_12C508A)||(_PIC_CPU==_12C509)||(_PIC_CPU==_12C509A)||(_PIC_CPU==_12CE518)||(_PIC_CPU==_12CE519)||(_PIC_CPU==_12F508)||(_PIC_CPU==_12F509)
	__CONFIG _IntRC_OSC & _WDT_OFF & _CP_OFF & _MCLRE_OFF
	ENDIF
	IF (_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A)
	__CONFIG _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF
	ENDIF

	INCLUDE		"password.inc"

	IF (_PIC_CPU==_12C508)||(_PIC_CPU==_12C508A)||(_PIC_CPU==_12C509)||(_PIC_CPU==_12C509A)||(_PIC_CPU==_12CE518)||(_PIC_CPU==_12CE519)||(_PIC_CPU==_12F508)||(_PIC_CPU==_12F509)
#define	TESTBAT	GPIO,0
#define	IRLED	GPIO,2	;Infra Red LED pin
#define	BATCHK	GPIO,4
#define	LED		GPIO,5
#define	BUTTONS	GPIO
	ENDIF
	IF (_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A)
#define	IRLED	PORTA,0	;Infra Red LED pin
#define	BATCHK	PORTA,2
#define	TESTBAT	PORTA,3
#define	LED		PORTA,4
#define	BUTTONS	PORTB
	ENDIF

;----- SFRs -----
	CBLOCK	_PIC_MEM
Counter
DelayCountLow
DelayCountHi
Com						;Command
Dig1					;64 bit Password
Dig2
Dig3
Dig4
Dig5
Dig6
Dig7
Dig8
Dig9					;command and CRC
	ENDC

;----- CODE -----
	org	0x00
	goto	Start
	
	org	0x04
	goto	Start

	org	0x40
Start:
	clrf	STATUS
	IF (_PIC_CPU==_12C508)||(_PIC_CPU==_12C508A)||(_PIC_CPU==_12C509)||(_PIC_CPU==_12C509A)||(_PIC_CPU==_12CE518)||(_PIC_CPU==_12CE519)||(_PIC_CPU==_12F508)||(_PIC_CPU==_12F509)
	movlw	b'00000000'	;Enable weak pull-up on GP0, GP1 and GP3
	option				;and wake up on pin change
	movlw	b'00011010'	;Set GP0,GP2,GP5 as output and the rest are inputs
	tris	BUTTONS
	ENDIF
	IF (_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A)
	movlw	b'10000000'
	movwf	INTCON		;enable global interrupts
	movlw	b'00001000'	;Enable weak pull-up on PortB
	bsf		STATUS,RP0	;select bank1
	movwf	OPTION_REG
	movlw	b'11100110'
	movwf	TRISA
	movlw	b'11111111'
	movwf	TRISB
	bcf		STATUS,RP0	;select bank0
	ENDIF
	bsf		LED
	bcf		IRLED
	bcf		TESTBAT
	goto	Transmit

;Delay for timing intervals
;Delay = W*3-1+5 us with 4MHz oscillator
Delay
	movwf	DelayCountLow	
DelayStart:
	decfsz	DelayCountLow,F
	goto	DelayStart
	retlw	0x00

;Delay for key de bounce
;Delay = W ms with 4 MHz oscillator
LongDelay
	movwf	DelayCountHi
	clrf	DelayCountLow
DelayLoop:
	nop
	incfsz	DelayCountLow,F
	goto	DelayLoop
	decfsz	DelayCountHi,F
	goto	DelayLoop
	retlw	0x00

Transmit:
	IF	(_DEBUG==.1)&&((_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A))
	goto	_debug1_Next
	ENDIF
	comf	BUTTONS,W		;read and invert BUTTONS contents
	IF (_PIC_CPU==_12C508)||(_PIC_CPU==_12C508A)||(_PIC_CPU==_12C509)||(_PIC_CPU==_12C509A)||(_PIC_CPU==_12CE518)||(_PIC_CPU==_12CE519)||(_PIC_CPU==_12F508)||(_PIC_CPU==_12F509)
	andlw	b'00001010'
	ENDIF
	IF (_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A)
	andlw	b'11110000'
	ENDIF
	btfsc	STATUS,Z	;check if a button is pressed
	goto	_Sleep		;if not go to sleep
	movwf	Com			;assign command
	movlw	0x1e
	call	LongDelay	;wait for 30 ms
	comf	BUTTONS,W		;read and invert BUTTONS again
	IF (_PIC_CPU==_12C508)||(_PIC_CPU==_12C508A)||(_PIC_CPU==_12C509)||(_PIC_CPU==_12C509A)||(_PIC_CPU==_12CE518)||(_PIC_CPU==_12CE519)||(_PIC_CPU==_12F508)||(_PIC_CPU==_12F509)
	andlw	b'00001010'
	ENDIF
	IF (_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A)
	andlw	b'11110000'
	ENDIF
	btfsc	STATUS,Z	;check if a button is still pressed
	goto	_Sleep		;if not go to sleep
	xorwf	Com,W		;Is a button is still pressed and it is the same command
	btfss	STATUS,Z
	goto	_Sleep		;if not go to sleep
	IF (_PIC_CPU==_12C508)||(_PIC_CPU==_12C508A)||(_PIC_CPU==_12C509)||(_PIC_CPU==_12C509A)||(_PIC_CPU==_12CE518)||(_PIC_CPU==_12CE519)||(_PIC_CPU==_12F508)||(_PIC_CPU==_12F509)
	swapf	Com,F		;place command in higher nibble
	ENDIF

;Battery tester (low voltage flag set at 3,5V or less)
	bsf		TESTBAT			;activate battery tester
	movlw	.12
	call	Delay			;delay 12*3-1+5=40 us
	btfss	BATCHK			;check battery
	bsf		Com,4			;set battery weak bit
	bcf		TESTBAT			;turn off battery tester

	bcf		LED

;Calculate CRC
	movlw	PASS1
	movwf	Dig1
	movlw	PASS2
	movwf	Dig2
	movlw	PASS3
	movwf	Dig3
	movlw	PASS4
	movwf	Dig4
	movlw	PASS5
	movwf	Dig5
	movlw	PASS6
	movwf	Dig6
	movlw	PASS7
	movwf	Dig7
	movlw	PASS8
	movwf	Dig8
	movf	Com,W
	movwf	Dig9

	movlw	.72
	movwf	Counter
	movlw	b'00110000'		;set poly (4bit CRC poly=10011)
NextBit:
	bcf	STATUS,C
	rlf	Dig9,F
	rlf	Dig8,F
	rlf	Dig7,F
	rlf	Dig6,F
	rlf	Dig5,F
	rlf	Dig4,F
	rlf	Dig3,F
	rlf	Dig2,F
	rlf	Dig1,F
	btfsc	STATUS,C	
	xorwf	Dig1,F
	decfsz	Counter,F
	goto	NextBit

	swapf	Dig1,W
	iorwf	Com,W
	movwf	Dig9			;add command nibble to CRC nibble

	movlw	PASS1
	movwf	Dig1
	movlw	PASS2
	movwf	Dig2
	movlw	PASS3
	movwf	Dig3
	movlw	PASS4
	movwf	Dig4
	movlw	PASS5
	movwf	Dig5
	movlw	PASS6
	movwf	Dig6
	movlw	PASS7
	movwf	Dig7
	movlw	PASS8
	movwf	Dig8

	movlw	.72
	movwf	Counter			;72 bits transmission 

	IF	(_DEBUG==.1)&&((_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A))
_debug1_Next:
	ENDIF

;send start pulse ***************************
	IF	_IR_REC==_TBA_2800	;No carrier. TTY mode. Pulse 30us. 1 pulse in a bit.
	bsf	IRLED
	movlw	.7
	call	Delay			;delay 8*3-1+5=28 us
	bcf	IRLED
	nop
	movlw	.74
	call	Delay			;delay 74*3-1+5=226
	ENDIF

	IF	_IR_REC==_BRM_1020	;Carrier 38kHz (26us). NEC mode. Pulse 7us. 7 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .7
	bsf	IRLED
	nop
	nop
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	movlw	.4
	call	Delay			;delay 4*3-1+5=16 us
i = i+1
	ENDW
	movlw	.23
	call	Delay			;delay 23*3-1+5=73
	ENDIF

	IF	_IR_REC==_TSOP_1738	;Carrier 38kHz (26us). NEC mode. Pulse 7us. 8 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .8
	bsf	IRLED
	nop
	nop
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	movlw	.4
	call	Delay			;delay 4*3-1+5=16 us
i = i+.1
	ENDW
	nop
	movlw	.14
	call	Delay			;delay 14*3-1+5=46
	ENDIF

	IF	_IR_REC==_TSOP_2156	;Carrier 56kHz (18us). NEC mode. Pulse 5us. 7 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .7
	bsf	IRLED
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	nop
	movlw	.2
	call	Delay			;delay 2*3-1+5=10 us
i = i+.1
	ENDW
	nop
	movlw	.39
	call	Delay			;delay 39*3-1+5=113
	ENDIF

	nop
	movlw	.254
	call	Delay			;delay 82*3-1+5=766 us

	IF	(_DEBUG==.1)&&((_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A))
	movlw	0xff
	call	LongDelay	;wait for 255 ms
	goto	_debug1_Next
	ENDIF

NextDig:
;send next pulse *********************************************
	IF	_IR_REC==_TBA_2800	;No carrier. TTY mode. Pulse 30us. 1 pulse in a bit.
	bsf	IRLED
	movlw	.7
	call	Delay			;delay 8*3-1+5=28 us
	bcf	IRLED
	nop
	movlw	.74
	call	Delay			;delay 74*3-1+5=226
	ENDIF

	IF	_IR_REC==_BRM_1020	;Carrier 38kHz (26us). NEC mode. Pulse 7us. 7 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .7
	bsf	IRLED
	nop
	nop
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	movlw	.4
	call	Delay			;delay 4*3-1+5=16 us
i = i+1
	ENDW
	movlw	.23
	call	Delay			;delay 23*3-1+5=73
	ENDIF

	IF	_IR_REC==_TSOP_1738	;Carrier 38kHz (26us). NEC mode. Pulse 7us. 8 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .8
	bsf	IRLED
	nop
	nop
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	movlw	.4
	call	Delay			;delay 4*3-1+5=16 us
i = i+.1
	ENDW
	nop
	movlw	.14
	call	Delay			;delay 14*3-1+5=46
	ENDIF

	IF	_IR_REC==_TSOP_2156	;Carrier 56kHz (18us). NEC mode. Pulse 5us. 7 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .7
	bsf	IRLED
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	nop
	movlw	.2
	call	Delay			;delay 2*3-1+5=10 us
i = i+.1
	ENDW
	nop
	movlw	.39
	call	Delay			;delay 39*3-1+5=113
	ENDIF

	bcf	STATUS,C
	rlf	Dig9,F
	rlf	Dig8,F
	rlf	Dig7,F
	rlf	Dig6,F
	rlf	Dig5,F
	rlf	Dig4,F
	rlf	Dig3,F
	rlf	Dig2,F			;rotate 64 bits to get the next bit
	rlf	Dig1,F			;to transmit and place it into STATUS,C
        
	btfss	STATUS,C		;if STATUS,C is low
	goto	Send0			;then delay between bits is 256 us else delay is 512 us

	movlw	.84			
	call	Delay			;delay 84*3-1+5=256 us

Send0:
	nop
	movlw	.78
	call	Delay			;delay 78*3-1+5=238 us

	decfsz	Counter,F		;last bit is not reached
	goto	NextDig			;proceed to next bit

	nop

;send last pulse ***********************************************
	IF	_IR_REC==_TBA_2800	;No carrier. TTY mode. Pulse 30us. 1 pulse in a bit.
	bsf	IRLED
	movlw	.7
	call	Delay			;delay 8*3-1+5=28 us
	bcf	IRLED
	nop
	movlw	.74
	call	Delay			;delay 74*3-1+5=226
	ENDIF

	IF	_IR_REC==_BRM_1020	;Carrier 38kHz (26us). NEC mode. Pulse 7us. 7 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .7
	bsf	IRLED
	nop
	nop
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	movlw	.4
	call	Delay			;delay 4*3-1+5=16 us
i = i+1
	ENDW
	movlw	.23
	call	Delay			;delay 23*3-1+5=73
	ENDIF

	IF	_IR_REC==_TSOP_1738	;Carrier 38kHz (26us). NEC mode. Pulse 7us. 8 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .8
	bsf	IRLED
	nop
	nop
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	movlw	.4
	call	Delay			;delay 4*3-1+5=16 us
i = i+.1
	ENDW
	nop
	movlw	.14
	call	Delay			;delay 14*3-1+5=46
	ENDIF

	IF	_IR_REC==_TSOP_2156	;Carrier 56kHz (18us). NEC mode. Pulse 5us. 7 pulses in a bit.
	VARIABLE i
i=0
	WHILE i < .7
	bsf	IRLED
	nop
	nop
	nop
	nop
	bcf	IRLED
	nop
	nop
	movlw	.2
	call	Delay			;delay 2*3-1+5=10 us
i = i+.1
	ENDW
	nop
	movlw	.39
	call	Delay			;delay 39*3-1+5=113
	ENDIF

	bsf	LED

_Sleep:
	IF (_PIC_CPU==_16F84)||(_PIC_CPU==_16F84A)
	movf	BUTTONS,W	;read PORTB to clear interrupt condition
	movlw	b'10001000'
	movwf	INTCON		;enable global interrupts and RB port change and flags
	ENDIF
	sleep				;go to sleep
	goto	_Sleep

	IF (_PIC_CPU==_12C508)||(_PIC_CPU==_12C508A)||(_PIC_CPU==_12CE518)||(_PIC_CPU==_12F508)
	org	0x1ff
	movlw	b'01110000'		;set OSCCAL
	ENDIF

	IF (_PIC_CPU==_12C509)||(_PIC_CPU==_12C509A)||(_PIC_CPU==_12CE519)||(_PIC_CPU==_12F509)
	org	0x3ff
	movlw	b'01110000'		;set OSCCAL
	ENDIF

	ELSE
	Error	"IR Receiver not selected. Check code"
	ENDIF
	ELSE
	Error	"Wrong PIC selected. Select [Configure]->[Select Device...]"
	ENDIF

	end