;
; ctrlir.asm
;
TITLE "IR Remote Receiver"
;
include "reg84.h"
;
; To Do
; Reject notches by accumulating very small counts
;
;
; Equates
;
DbgIr equ 01H
;
; Port B bits(Bits 6 & 7 are used by serial comms.)
InpBit equ 00H
;
if DbgIr != 0
DbgBit equ 01H
DbgByte equ 02H
DbgMain equ 03H
DbgIsr equ 04H
endif
;
; Flag bits in StatByte
PrevBit equ 00H ; State of previous bit sample
RcvBusy equ 01H ; In the process of receiving
RcvReady equ 02H ; Code completely received
BitReady equ 03h ; Bit ready for assembly
XmitCod1 equ 04h ; LSB of code ready for xmit
XmitCod2 equ 05h ; MSB of code ready for xmit
CodeOrun equ 06h ; Code overrun
;
; Rate of interrupt. Set at 9600/sec. Rest of this arrived at by
; trial and error(mostly error). The calculation is as follows.
; Required rate = 1/9600 = 104us
; No. of instruction cycles = 104*3.58/4
; = 93(with a crystal of 3.58 MHz)
; RtccCount = 0 - 93 = A3h
; With an overhead(12d?) it is afh
;
RtccCount equ 0afh
;
; Timing constants
HdrTic equ 19h ; 2500us-2700us
MarkTic equ 0bh ; 1100us-1300us
SpacTic equ 05h ; 500us-700us
EndCode equ 14h ; Gap indicating end of code(2ms)
;
; Data
ORG 0CH ; Data Origin
;
SaveWReg RES 1 ; Save W during ISR
SaveStat RES 1 ; Save Status during ISR
IntDiv RES 1 ; Divider for periodic interrupt
;
CurrTime RES 1 ; The current ticks
MarkTime RES 1 ; Ticks the mark lasted
SpacTime RES 1 ; Ticks the space lasted
StatByte RES 1 ; A whole bunch of flags
CodeByt1 RES 1 ; LSB of the received byte
CodeByt2 RES 1 ; MSB of the received byte
CodeCnt RES 1 ; Bits received so far
SendCod1 RES 1 ; Hold before transmit
SendCod2 RES 1
;
include "ctrlcomm.h"
;
; Macros
;
;
; ChkRng : If value in register ChkReg is not between ChkVal
; and ChkVal + 2 go to ErrLbl
ChkRng MACRO ChkReg,ErrLbl,ChkVal
movf ChkReg,0
sublw ChkVal+2
JMPC ErrLbl ; Value more than ChkVal + 2
sublw 3
JMPC ErrLbl ; Value less than ChkVal
ENDM
;
; Program
;
ORG 0 ; Reset vector
;
goto main
;
;
ORG 4 ; Interrupt vector
;
goto isr
;
;
ORG 8 ; Program starts here
;
main call InitIr
call InitPort
if DbgIr != 0
bcf RegPortb,DbgBit
bcf RegPortb,DbgByte
endif
loop1 btfss StatByte,BitReady
goto DoneIr ; Nothing on IR port
if DbgIr != 0
bcf RegPortb,DbgBit
endif
bcf StatByte,BitReady
movf CodeCnt,0
JMPNZ NotHdr ; Not expecting header
; Header has m=21-23, space=5-7
ChkRng MarkTime,IrErr,15h
ChkRng SpacTime,IrErr,5 ; Expecting header & this ain't it
incf CodeCnt,1
clrf CodeByt1
clrf CodeByt2
goto DoneIr
NotHdr bcf RegStatus,BitCarry ; It's not the header
rlf CodeByt1,1
rlf CodeByt2,1
ChkRng MarkTime,NotOne,0bh ; Is it a 1?
goto Maybe1
NotOne ChkRng MarkTime,IrErr,5 ; Is it a 0?
goto ChkSpac
Maybe1 bsf CodeByt1,0
ChkSpac ChkRng SpacTime,IsItEnd,5
incf CodeCnt,1
goto DoneIr
IsItEnd movf SpacTime,0
sublw EndCode
JMPNZ IrErr
clrf CodeCnt
movf StatByte
andlw (1<<XmitCod1)|(1<<XmitCod2)
JMPZ NoOrun
bsf StatByte,CodeOrun
goto DoneIr
NoOrun movf CodeByt1,0
movwf SendCod1
movf CodeByt2,0
movwf SendCod2
bsf StatByte,XmitCod1
bsf StatByte,XmitCod2
goto DoneIr
IrErr clrf CodeCnt
bcf StatByte,RcvBusy
if DbgIr != 0
bcf RegPortb,DbgByte
endif
goto DoneIr
DoneIr btfss StatByte,XmitCod1
goto TryCod2
btfss P1Stat,TxRdy
goto SkipXmt
movf SendCod1,0
bsf RegPortb,DbgMain
call P1PutC
bcf RegPortb,DbgMain
bcf StatByte,XmitCod1
goto SkipXmt
TryCod2 btfss StatByte,XmitCod2
goto SkipXmt
btfss P1Stat,TxRdy
goto SkipXmt
movf SendCod2,0
bsf RegPortb,DbgMain
call P1PutC
bcf RegPortb,DbgMain
bcf StatByte,XmitCod2
goto SkipXmt
SkipXmt goto loop1 ; Play it again, Sam.
;
InitIr bsf RegStatus,BitRp0
movlw 0
movwf RegTrisa ; Set Port A to all outputs
movlw 1
movwf RegTrisb ; Set Port B Bit 0 to input
bcf RegOption,BitRts ; Enable RTCC timer
bcf RegStatus,BitRp0
movlw 0
movwf RegRtcc
movlw 0
movwf IntDiv
movwf CurrTime
movwf CodeByt1
movwf CodeByt2
movwf CodeCnt
movwf StatByte
return
;
isr btfss RegIntcon,BitRtif
retfie
movwf SaveWReg
swapf RegStatus,w
movwf SaveStat
movlw RtccCount
movwf RegRtcc
bcf RegStatus,BitRp0
bsf RegPorta,0
; The real work starts here
; The IR detector output is inverted. Thus, all tests of
; InpBit are inverted.
btfsc RegPortb,InpBit
goto IsSpace
btfsc StatByte,RcvBusy
goto Rcving ; In the middle of receiving
bsf StatByte,RcvBusy ; Now I'm busy
if DbgIr != 0
bsf RegPortb,DbgByte
endif
clrf CurrTime ; Start count
goto OneDone
;
Rcving btfss StatByte,PrevBit
goto WasZero
incf CurrTime
goto OneDone
;
WasZero movf CurrTime,0
movwf SpacTime
clrf CurrTime
bsf StatByte, BitReady
if DbgIr != 0
bsf RegPortb,DbgBit
endif
goto OneDone
;
IsSpace btfss StatByte,RcvBusy
goto Done ; All quiet
btfsc StatByte,PrevBit ; Current input is space
goto WasOne
incf CurrTime
movlw EndCode
subwf CurrTime,0
JMPNZ Done
movf CurrTime,0 ; Received end of code
movwf SpacTime
bcf StatByte,RcvBusy
if DbgIr != 0
bcf RegPortb,DbgByte
endif
bsf StatByte,BitReady
if DbgIr != 0
bsf RegPortb,DbgBit
endif
goto Done
;
WasOne movf CurrTime,0 ; Just changed from 1 to 0
movwf MarkTime ; Store MarkTime
clrf CurrTime
bcf StatByte,PrevBit
goto Done
;
OneDone bsf StatByte,PrevBit
Done incf IntDiv,1
movf IntDiv,0
sublw 2
JMPNZ SkipSer ; Call the serial ISR every two tics
clrf IntDiv
call SerIsr
SkipSer bcf RegPorta,0
swapf SaveStat,w
movwf RegStatus
swapf SaveWReg
swapf SaveWReg,w
bcf RegIntcon,BitRtif
retfie
;
include "ctrlcomm.asm"
;
end
External Labels :
InitPort in ctrlcomm.asm
ChkSpac
P1PutC in ctrlcomm.asm
SerIsr in ctrlcomm.asm