	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	0x02	;										*
;																		*
; 12F683																*
;   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	__12F629
		list	p=12f629		; 12F626 can be used
		#include <p12f629.inc>	; processor specific variable definitions
		__CONFIG _CP_OFF & _CP_OFF & _WDTE_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT
    endif
	ifdef	__12F675
		list	p=12f675		; 12F675 can be used
		#include <p12f675.inc>	; processor specific variable definitions
		__CONFIG _CP_OFF & _CP_OFF & _WDTE_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT
    endif
	ifdef	__12F683
		list	p=12f683		; 12F683 can be used
		#include <p12f683.inc>	; processor specific variable definitions
		__CONFIG _CP_OFF & _CP_OFF & _WDTE_OFF & _MCLRE_OFF & _FOSC_INTOSCIO & _IESO_OFF & _FCMEN_OFF
    endif

	ifndef	PCL
		error	"Invalid processor type selected"
	endif

F_OSC	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

	datareg
	txreg
	rcreg
	count
	delay
	endc

	if bitcnt > 0x2F
		error "Too many variable used"
	endif

; GPIO bits

bSw4	EQU		5
bSw3	EQU		4
bSwMenu	EQU		3
bIrLed	EQU		2
bSw2	EQU		1
bSw1	EQU		0

		org		0x0000
POWERON
		CLRWDT
		movlw	7
	ifdef	CMCON				; If controller has comparator - disable it
		movwf	CMCON
	endif

	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

	ifdef	OSCCON
		movlw	0x60			; 4MHz internal oscillator
		movwf	OSCCON
	endif

		MOVLW	0x01 			; Pullups on	
		movwf	OPTION_REG
		MOVLW	~ ( (1 << bIrLed) )
		movwf	TRISIO			; Bit 5: Button 4, 4: Button 3, 2 Ir Led output, 3: Menu button, 1: Button 2, 0: Button 1
		movwf	IOC
		movlw	0xFF
	ifdef	WPUA
		movwf	WPUA
	endif
	ifdef	WPU
		movwf	WPU
	endif


		MOVLW	DefaultAddress	; address = default address
		MOVWF	address			; Clear toggle bit

MainLoop
		bsf		INTCON,GPIE		; Enable IOCN wake up
		movf	GPIO,w
		bcf		INTCON,GPIF		

		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
		bcf		INTCON,GPIF		
		
								; Button pressed
		xorlw	0x3B
		andlw	0x3B
		btfsc	STATUS,Z
		goto	KeyUp
		
		btfss	FSR,bSw4		; Get key pressed
		movlw	BSW4Code
		btfss	FSR,bSw3
		movlw	BSW3Code
		btfss	FSR,bSwMenu
		movlw	MenuCode
		btfss	FSR,bSw2
		movlw	BSW2Code
		btfss	FSR,bSw1
		movlw	BSW1Code
		movwf	comcode

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


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

Delay113ms
		movlw	.113
Delayms
		MOVWF	cntr
lDel1
		clrf	FSR
lDel2
		NOP  
		DECFSZ	FSR,1
		GOTO	lDel2
		DECFSZ	cntr,1
		GOTO	lDel1
		return


	END


