;05IR-Lv2.asm
;WWW.MWFTR.COM/book.html
;Charles Kim
;This program is to:
;1. Read IR command from SHARP Remote Controller
;2. Turn ON the LED for a given amount of seconds by
;   the number pressed by the button:
;    '1': 1 sec
;    '2': 2 sec  etc
;
;Sharp Command
; key "1" : 01
; key "2": 02
;key "0": 0A
;
; LED is connected to RD1 
;
;IR-RX pin(IRX) is dedicated to RB7 port

;
;
;

        list P = 16F877

STATUS	EQU	0x03
CARRY	EQU	0x00
ZERO	EQU	0x02
TRISB	EQU	0x86
PORTB	EQU	0x06
TRISD	EQU	0x88
PORTD	EQU	0x08
IRX	EQU	0x07		;RB7 for IR receiver
LED	EQU	0x01
MSB	EQU	0x07

;RAM arEA
       
	CBLOCK	0x20
		TIMEBLOCK
		Kount120us   ;Delay count (number of instr cycles for delay)
		Kount100us
		Kount1ms
		Kount10ms
		Kount200ms
		Kount1s
		Kount10s
		Kount1m
		first
		second
		third
		Bitcount	;data bit count
		Kount		;Delay count (number of instr cycles for delay)
		ADDRreg		;IR ADDRESS
		COMreg		;IR Command
		Pcount		;HIGH duration count
		ADcount
		CMcount
	ENDC
	

;The Next 5 lines must be here
;because of bootloader arrangement
;Bootloader first execute the first 4 addresses
;then jump to the address what the execution directs 
;=========================================================
        org 	0x0000      	;line 1
	GOTO	START		;line 2 ($0000)
	NOP			;line 3 ($0001)
	NOP			;line 4 ($0002)
	NOP			;line 5 ($0003)
;======================================================
;start of the program from $0004
START	
	
	banksel	TRISB
; Port setting (1 for input and 0 for output)
; 1000 0000
	clrf	STATUS
	movlw	0x80
	movwf	TRISB
;RB7 - IRX Pin (IN)

	banksel	TRISD
	movlw	H'00'
	movwf	TRISD
	
	banksel	PORTD		;All ports are outputs
	clrf	PORTD
AGAIN	
	bcf	PORTD, LED
	call	SharpIR
	movf	COMreg,0		;W has now the content of the command
	andlw	B'11111110'
	btfss	STATUS, ZERO		; W = 01?  then 1 
	goto	next
	goto 	oneLED					
next	movf	COMreg,0
	andlw	B'11111101'		;W= 2?  then 2 sec
	btfss	STATUS, ZERO
	goto	next2
	goto	twoLED
next2	movf	COMreg, 0
	andlw	B'11111100'		;W=3?  then 3 sec
	btfss	STATUS, ZERO
	goto	next3
	goto	threeLED
next3	movf	COMreg,0
	andlw	B'11111011'		;W=4? then 4 sec
	btfss	STATUS,ZERO
	goto	next4
	goto	fourLED
next4	movf	COMreg,0
	andlw	B'11111010'		;W=5? then 5 sec
	btfss	STATUS, ZERO
	goto	next5
	goto	fiveLED
next5	movf	COMreg,0
	andlw	B'11111001'		;W=6? then 6 sec
	btfss	STATUS,ZERO
	goto	next6
	goto	sixLED
next6	movf	COMreg,0
	andlw	B'11111000'		;W=7? then 7 sec
	btfss	STATUS, ZERO
	goto	next7
	goto	sevenLED
next7	movf	COMreg, W
	andlw	B'11110111'		;W=8? then 8 sec
	btfss	STATUS, ZERO
	goto	next8
	goto	eightLED
next8	movf	COMreg,0
	andlw	B'11110110'		;W=9? then nine sec
	btfss	STATUS, ZERO
	goto	next9
	goto	nineLED
next9	goto	AGAIN

; LED routine
nineLED	bsf	PORTD, LED
	call	delay1s	
eightLED
	bsf	PORTD, LED
	call	delay1s
sevenLED
	bsf	PORTD, LED
	call	delay1s
sixLED	bsf	PORTD, LED
	call	delay1s
fiveLED	bsf	PORTD,LED
	call	delay1s
fourLED	bsf	PORTD,LED
	call	delay1s
threeLED
	bsf	PORTD, LED
	call	delay1s
twoLED	bsf	PORTD,LED
	call	delay1s
oneLED	bsf	PORTD,LED
	call	delay1s
	goto	AGAIN



;==Sharp IR Subroutine =====

SharpIR	
	banksel	ADDRreg
	clrf	ADDRreg
	clrf	COMreg
	clrf	Pcount
; CHECK IF THE IRX is HIGH at least for 200 mS
;to make sure it does not read the second info (inverted)
; 200 mS delay is about 1700 of 120uS delay
	banksel	PORTB
	btfss	PORTB, IRX
	goto	SharpIR		;if IRX is LOW, start again
;call delay10ms 20 times
	banksel	first
	movlw	0x14		;20
	movwf	first
redo	call	Delay10ms	;200mS delays
;check again for IRX
	btfss	PORTB, IRX
	goto	SharpIR
	decfsz	first
	goto	redo
;NOW ready to fresh read IR data
;
	movlw	0x05
	movwf	ADcount
; Check for START bit
ADNEXT  clrf	Pcount
	bcf	STATUS, CARRY	;Clear the Carry Bit
	rrf	ADDRreg		;rotate to the right
WAIT	btfsc	PORTB, IRX	;IRX=LOW?
	goto	WAIT		;NO
wait2	btfss	PORTB, IRX	;YES. Then check it AGain
	goto	wait2
DST	call	Delay120us	;IRX is HIGH NOW.  Delay 120 uS
;count (or measure) the HIGH duration
wait3	btfss	PORTB, IRX
	goto	onezero
	incf	Pcount		;if IRX still HIGH
	goto	DST

;
;"1" or "0" check
;	
onezero	btfsc	Pcount,0x03
	bsf	ADDRreg, MSB	;if bit 3 of the pulse count is 1 (i.e.,8 or bigger)
	decfsz	ADcount
	goto	ADNEXT

	bcf	STATUS, CARRY
	rrf	ADDRreg
	rrf	ADDRreg	
	rrf	ADDRreg

;Now COMMAND READING
	movlw	0x08
	movwf	CMcount
; Check for START bit
CMNEXT  clrf	Pcount
	bcf	STATUS, CARRY	;Clear the Carry Bit
	rrf	COMREG		;rotate to the right
;cWAIT	btfsc	PORTB, IRX	;IRX=LOW?
;	goto	cWAIT		;NO
cwait2	btfss	PORTB, IRX	;YES. Then check it AGain
	goto	cwait2
cDST	call	Delay120us	;IRX is HIGH NOW.  Delay 100 uS
;count (or measure) the HIGH duration
cwait3	btfss	PORTB, IRX
	goto	conezero
	incf	Pcount		;if IRX still HIGH
	goto	cDST
;"1" or "0" check
;	
conezero	
	btfsc	Pcount,0x03
	bsf	COMreg, MSB	;if bit 3 of the pulse count is 1 (i.e.,8 or bigger)
	decfsz	CMcount
	goto	CMNEXT


;read next two more data for EXP and CHK

ewait2	btfss	PORTB, IRX	;YES. Then check it AGain
	goto	ewait2
ewait3	btfsc	PORTB, IRX
	goto 	ewait3
ewait4	btfss	PORTB, IRX
	goto	ewait4

	return

;
;
;==========================================================
;DELAY SUBROUTINES 


; 1 instruction cycle for 20MHz clock is 0.2 us
; Therefore 120 uS delay needs 600 instuction cycles
;  600 =199*3 +3 ---->Kount=199=0xC7
;  or  =198*3 +6 ---->Kount=198=0xC6
;  or  =197*3 +9 ---->Kount=197=0xC5

Delay120us
	banksel	Kount120us
	movlw	H'C5'		;D'197'
	movwf	Kount120us
R120us	decfsz	Kount120us
	goto	R120us
	return
;
;100us delay needs 500 instruction cycles
;  500 =166*3 +2 ---->Kount=166=0xA6
;  or  =165*3 +5 ---->Kount=165=0xA5
;  or  =164*3 +8 ---->Kount=164=0xA4
Delay100us
	banksel	Kount100us
	movlw	H'A4'
	movwf	Kount100us
R100us	decfsz	Kount100us
	goto	R100us
	return

;
;10ms delay
; call 100 times of 100 us delay  (with some time discrepancy)
Delay10ms 
	banksel	Kount10ms
	movlw	H'64'	;100
	movwf	Kount10ms
R10ms	call	delay100us
	decfsz	Kount10ms
	goto	R10ms
	return
;
Delay200ms
	banksel	Kount200ms
	movlw	H'14'
	movwf	Kount200ms
R200ms	call	delay10ms
	decfsz	Kount200ms
	goto	R200ms
	return
;
;
	
;1 sec delay
;call 100 times of 10ms delay
Delay1s
	banksel	Kount1s
	movlw	H'64'
	movwf	Kount1s
R1s	call	Delay10ms
	decfsz	Kount1s
	goto	R1s
	return
;
;
;10 s delay
;call 10 tiems of 1 s delay
Delay10s
	banksel	Kount10s
	movlw	H'0A'		;10
	movwf	Kount10s
R10s	call	Delay1s
	decfsz	Kount10s
	goto	R10s
	return
;
;1 min delay
;call	60 times of 1 sec delay
Delay1m
	banksel	Kount1m
	movlw	H'3C'	;60
	movwf	Kount1m
R1m	call	Delay1s
	decfsz	Kount1m
	goto	R1m
	return
;======================================================
;
;END OF CODE
        END

