	list	b=4
;************************************************************************
; Philips RC5(X) Infrared protocol implemented with 6-8 pin Microchip 	*
; microcontrollers from 16F series.										*
;																		*
;	Last modified:	2012-05-28											*
#define	VersionMajor	0x12	;										*
#define	VersionMinor	0x01	;										*
;																		*
; 10F320, 10F322														*
;   many other,  6-8 pin 16Fxxx device may be used						*
;	   - 4 byte RAM from 0x20 - 0x23 used only							*
;	   - no more than 256 word of program memory needed					*
;	   - IOC on 3 pins													*
;	   - 8 level stack													* 
;																		*
;************************************************************************
;																		*
;	Pins:																*
;		GPIO:															*
;			0: Button 1													*
;			1: Button 2													*
;			2: IR Led output											*
;			3: Button 3													*
;			4: Button 4													*
;			5: Button 5													*
;																		*
;************************************************************************

	errorlevel	-302			; Register in operand not in bank 0.

	ifdef	__12F683
		list	p=12f683		; 12F683 can be used
		#include <p12f683.inc>	; processor specific variable definitions
		__CONFIG _CP_OFF & _WDTE_OFF & _MCLRE_OFF & _FOSC_INTOSCIO & _IESO_OFF & _FCMEN_OFF
    endif

	ifndef	PCL
		error	"Invalid processor type selected"
	endif

FOSC	EQU	.4000000			; 4.00 MHz clock frequency used

								; Default address to use afther power up
#define	DefaultAddress		0x1D	; Used when ADDRESS button up   during powerup
#define	MenuCode			0x0F
#define	BSW1Code			0x09
#define	BSW2Code			0x05
#define	BSW3Code			0x19
#define	BSW4Code			0x15


#define	UsePage4				; Uncomment this line to use 4 command page mode 
#define	Send2Times
;#define	Send5Times				; Comment this line to send a command only once

	__idlocs		0xC000 | (VersionMajor << 8) | (VersionMinor)

	cblock	0x20
		comcode					; Command code to send
		address					; Address to send  -  bit 5: toggle bit
		cntr					; Delay counter
		bitcnt					; Bit counter
	endc

	if bitcnt > 0x2F
		error "Too many variable used"
	endif

		org		0x0000
POWERON
		CLRWDT
		movlw	7

	ifdef	CMCON0				; If controller has comparator - disable it
		movwf	CMCON0
	endif

	ifdef	ADCON0				; If controller has A/D - disable it
		clrf	ADCON0
	endif

		bsf		STATUS,RP0		; Bank1

	ifdef	ANSEL				; If controller has A/D - disable it
		clrf	ANSEL
	endif

		movlw	0x60			; 4MHz internal oscillator
		movwf	OSCCON

		MOVLW	0x01 			; Pullups on	
		movwf	OPTION_REG
		MOVLW	0xFB
		movwf	TRISIO			; Bit 2 Ir Led output, 3: Menu button, 1: Button 2, 0: Button 1
		movwf	IOC
		movlw	0xFF
		movwf	WPUA

		bcf		STATUS,RP0		; Bank0

		MOVLW	DefaultAddress	; address = default address
		MOVWF	address			; Clear toggle bit

MainLoop
		movf	GPIO,w
		bsf		INTCON,GPIE		; Enable IOCN wake up
		
		SLEEP					; Goto sleep
		NOP  					; Port change will wake up
		MOVF	GPIO,W			; Get a copy of GPIO
		movwf	FSR

		bcf		INTCON,GPIE		; Disable IOCN wake up
		
								; Button pressed
		xorlw	0x3B
		andlw	0x3B
		btfsc	STATUS,Z
		goto	KeyUp
		
		btfss	FSR,5
		movlw	BSW4Code
		btfss	FSR,4
		movlw	BSW3Code
		btfss	FSR,3
		movlw	MenuCode
		btfss	FSR,1
		movlw	BSW2Code
		btfss	FSR,0
		movlw	BSW1Code

SendPackets
	ifdef	Send5Times
								; Send command for 5 times or 7 times if 4 pages used
		call	SendTwoPackets0
		MOVLW	.16
		call	SendTwoPackets
		MOVLW	.32
	  ifdef	UsePage4
		call	SendTwoPackets
		MOVLW	.48
	  endif
		call	SendOnePacket
	else
								; Send command only 1 time
		call	SendOnePacket0
	endif

		movlw	0x20
		xorwf	address,f		; Invert toggle bit

KeyUp							; Wait for all keys up
		movf	GPIO,W
		XORLW	0x3B
		andlw	0x3B
		BTFSS 	STATUS,Z
		goto	KeyUp

NoKeyDown
		MOVLW	.50
		CALL	Delayms

		GOTO	MainLoop


Delay226ms
		call	Delay113ms

Delay113ms
		movlw	.113
Delayms
		MOVWF	cntr
lDel1
		clrf	FSR
lDel2
		NOP  
		DECFSZ	FSR,1
		GOTO	lDel2
		DECFSZ	cntr,1
		GOTO	lDel1
		return

SendBits
		movwf	FSR				; Save data to send
		movlw	.6
		movwf	bitcnt			; Save bit count
SendBits_loop
		btfsc	FSR,5			; Test bit
		CALL	SendBit1		; if bit==1 send a one
		btfss	FSR,5
		CALL	SendBit0		; if bit==0 send a zero
		RLF		FSR,f			; All bits to send are in the FSR, C is don't care
		decfsz	bitcnt,f		; Loop for all bits
		GOTO	SendBits_loop
		return

SendBit1
		call	SendPause

SendBit
		movlw	.32
		movwf	cntr
SendBit_loop
		BSF		GPIO,2			;1
		call	RET				;4
		call	RET				;4
		call	RET				;4
		BCF		GPIO,2			;1
		call	RET				;4
		call	RET				;4
		goto	$+1				;2
		decfsz	cntr,f			;1
		GOTO	SendBit_loop	;2
RET
		return

SendBit0
								;  890us with 36kHz modulation
								; 27.7us Periodtime - 32 Impulses
		call	SendBit

SendPause
		MOVLW	.32
		movwf	cntr
SendPause_loop
		call	RET				;4
		call	RET				;4
		call	RET				;4
		call	RET				;4
		call	RET				;4
		call	RET				;4
		decfsz	cntr,f			;1
		GOTO	SendPause_loop	;2
		return


; RC5 InfraRed Command Packet
;
;		Packet length: 24.899 ms, repeation time: 113.792 ms 		
;
;		Bit 1: 889uS - no pulses, 889us - 32 pulses 
;		Bit 0: 889uS - 32 pulses, 889us - no pulses 
;
;		 S  s   T   A4  A3  A2  A1  A0  C5  C4  C3  C2  C1  C0
;		|1 |s  |tg |a4 |a3 |a2 |a1 |a0 |c5 |c4 |c3 |c2 |c1 |c0 |
;
;		RC5  version s: second start bit : 1
;		RC5X version s: inverted bit 6 of command : !c6
;
;		a4..a0:	address
;		d6..d0: command
;		tg: toggle bit: send the same bit for repeated packet sending
;						send opposite bit for a new command

	ifdef	Send5Times
SendOnePacket
		SUBWF	comcode,W
		BTFSC	STATUS,C
	endif

SendOnePacket0
		CALL	SendIrPacket
	ifdef	Send2Times
		CALL	SendIrPacket
	endif
		return

	ifdef	Send5Times
SendTwoPackets
		SUBWF	comcode,W
		BTFSC	STATUS,C
SendTwoPackets0
		CALL	SendIrPacket
	endif

SendIrPacket
		CALL	SendBit1		; First  Startbit = 1
		btfss	comcode,6
		CALL	SendBit1		; Second Startbit = inv of bit 6 of command code 
		btfsc	comcode,6
		CALL	SendBit0

		movf	address,w		; toggle bit and 5 Bit address
		call	SendBits

		movf	comcode,w		; 6 Bit command code
		call	SendBits
		BCF   	GPIO,2			; Turn off IR LED

		GOTO  	Delay113ms		; Delay 64 Bits @ 1,78ms = 113ms

	END


