; ; asm program to manage IR Proximity Detector ; version 2 - for 12C509 ; ;40 kiloherz = 25 us per cycle or 12.5 us per 1/2 cycle ; ; There is an issue with being right on frequency. It makes the ; detector very sensitive and causes spurious readings. The ; code in this program detunes from the 40khz center freq. The actual ; frequency is determined by testing. I have noticed differences ; between detectors and detector types - so it is best to check ; each one with a reprogrammable chip before committing to an OTP ; ; Psuedo Code And Definitions Follow ; ;GPIO 0 and 1 are IR LED controllers. ;GPIO 3 is the IR detector input ; 3 can only be an input! ; so I couldn't drive anything with it. ;GPIO 2 is the left detect port ;GPIO 4 is the right detect port ;GPIO 5 is the 'equal hits' port ; ;Start the psuedo-code: ; ;1. Pause 1 ms ;2. zeroize counters ;3. Getting received signal? ; yes - goto 1 ;4. turn on left LED (GPIO0) at 40KHZ for 600 us ; after 600 us, ; check for return signal (GPIO3), ; if return was positive, increment left hit counter ; ;5. turn on right LED (GPIO1) at 40KHZ for 600 us ; after 600 us, ; check for return signal (GPIO3), ; if return was positive, increment right hit counter ; ;6. if left hit counter = 1 then ; goto 8 ; ;7. if right hit counter = 1 then ; set right indicator (GPIO4) because only right side is active ; goto 1 ; ;8. if right hit counter = 1 then ; goto 9 because both are getting hits ; else ; turn on left indicator (GPIO2) because only left side is active ; goto 1 ; ;9. turn on 'both getting hits' indicator (GPIO5) ; ;10. goto 1 ; ; ;At burn time, select Internal Oscillator RC, No WDT, No Power Up Timer ;and Master Clear Internal ; ;Code follows: list p=12C509 radix hex ; oscal equ 0x05 GPIO equ 0x06 count equ 0x07 count1 equ 0x08 ;counts are all delay values count2 equ 0x09 bitpatt equ 0x0a ;results of input port tests ; org 0x00 movwf oscal ;store oscillator cal value ; movlw b'11011111' ;clear tocs bit so we can use gp2 option movlw b'00001000' ;port 3 input from rcv, rest outputs tris GPIO ;teach clrf GPIO start call paws1ms ;wait 1 ms btfss GPIO,3 ;input = 1 (no received sig)? goto start ;getting rx, wait - eliminate falsies movlw 0x18 ;cycles to call subroutines movwf count ;put value in count variable clrf bitpatt ;clear out the bit pattern arnd1 call leftOn ;call left LED 24 times (0x18) decfsz count,f goto arnd1 btfsc GPIO,3 ;test input bit goto clr1 ;not receiving bsf bitpatt,0 ;rx, so set bitpatt clr1 movlw 0x18 ;18 hex is 24 decimal movwf count arnd2 call rightOn ;call right LED 24 times (0x18) decfsz count,f goto arnd2 btfsc GPIO,3 ;test input bit goto eval ;not receiving bsf bitpatt,1 ;rx, so set bitpatt ; ; if to here, then we have set (or not set) the bit patterns in ; the bit pattern variable. We now need to test them ; eval clrf GPIO ;clear indicator ports btfsc bitpatt,0 ;test first bit goto leftset ;yes, check second one btfss bitpatt,1 ;no, then just test second bit goto start ;no, neither were set bsf GPIO,4 ;just right one was set goto start ; ; if to here, then the left bit is getting hits, we need to check the ; right bit. If it is getting hits also, then we need to turn on ; the 'equal hit' port ; leftset btfsc bitpatt,1 ;test second bit goto setboth ;good also, light 'equal hit' port bsf GPIO,2 ;just left one was getting hits goto start setboth bsf GPIO,5 ;set 'equal hit' port goto start ;and so on, forever ;SUBROUTINES ;leftOn will turn on the LED for 12.5 us (approx) and then turn it off ;for 12.5 us (approximately) for 24 total cycles to make approximately ;600 us worth of cycles at 40 khz (40 khz=25us per cycle - 1/40000) ; ;problem with being exactly on freq - so this isn't ; ;rightOn will do the same thing only with the right LED ; ;paws1ms will pause about one millisecond ; leftOn: bsf GPIO,0 ; turn on left LED nop nop nop nop nop nop nop nop nop nop nop nop nop nop bcf GPIO,0 ; turn off left LED nop nop nop nop nop nop nop nop nop nop nop return rightOn: bsf GPIO,1 ; turn on right LED nop nop nop nop nop nop nop nop nop nop nop nop nop nop bcf GPIO,1 ; turn off right LED nop nop nop nop nop nop nop nop nop nop nop return ; Pause subroutine is right out of Easy Pic'n ; Desired delay code to put in nested loop is Y ; Let's do 12 milliseconds (as in book) ; ; M=outer loop, N=inner loop ; Y=M=N ; 3Y^2=12000/3=4000 : Y=SQR(4000)=63.3=0x3F ; so for one millisecond it is 14.14 - or 14 to be even ; paws1ms movlw 0x0e ;set up outer loop movwf count1 loadn movlw 0x0e ;inner loop movwf count2 decn decfsz count2,f ;decrement inner loop goto decn ;not zero so decrement again decfsz count1,f ;decrement outer loop goto loadn ;not zero - set up inner ;loop again return ;zero - go home end ; ;At burn time, select Internal Oscillator RC, No WDT, No Power Up Timer ;and Master Clear Internal ;