; ; asm program to manage IR Proximity Detector ; version 3 - for 12C509 - this version meant to ; have more robost falsie elimination ; ; Jan 9, 2000 ; ; Chips burnt with this version will have a red dot ; ;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! ;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. zeroize counters ; Do items 2 through 5 four times ; ;2. pause 1 ms ; ;3. Getting received signal? ; yes - goto 2 ; ;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 = 4 then ; goto 8 ; ;7. if right hit counter = 4 then ; set right indicator (GPIO4) because only right side is active ; goto 1 ; ;8. if right hit counter = 4 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 count3 equ 0x0a bitpatl equ 0x0b ;results of input port tests bitpatr equ 0x0c ; 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 main movlw 0x04 ;number of times to sample (if you change this, then ;be sure to change the pattern tests (below) movwf count3 clrf bitpatl ;clear out the bit pattern vars clrf bitpatr 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 arnd1 call leftOn ;call left LED 24 times (0x18) decfsz count,f goto arnd1 btfsc GPIO,3 ;test input bit goto clr1 ;not receiving incf bitpatl,f ;rx, so increment 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 incf bitpatr,f ;rx, so set bitpatt eval decfsz count3,f ;decrement main loop goto start ; ; if to here, then we have set (or not set) the bit patterns in ; the bit pattern variable. We now need to test them. This version ; requires 4 transmissions and all 4 must have valid hits before ; a target is verified. This stops false signals. I needed to do this ; because of an exceptionally unfriendly robot setup that I made. This ; seems to work fine. ; ; CHANGE PATTERN TESTS HERE IF YOU CHANGE THE LOOP COUNTER! (count3) ; clrf GPIO ;clear indicator ports btfsc bitpatl,2 ;test first pattern - bit 3 should be set ; ; if you changed the loop counter to 8, then you would use ; btfsc bitpatl,3 ; goto leftset ;yes, check second one btfss bitpatr,2 ;no, then just test second bit ; ; if you changed the loop counter to 8, then you would use ; btfsc bitpatr,3 ; goto main ;no, neither were set bsf GPIO,4 ;just right one was set goto main ; ; if to here, then the left bit is getting consistent hits, check the ; right bit. If it is getting consistent hits also, then turn on ; the 'equal hit' port ; leftset btfsc bitpatr,2 ;test right bitpatt ; ; if you changed the loop counter to 8, then you would use ; btfsc bitpatr,3 ; goto setboth ;good also, light 'equal hit' port bsf GPIO,2 ;just left one was getting hits goto main setboth bsf GPIO,5 ;set 'equal hit' port goto main ;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 ;