; irsens.asm 5 channel active IR sensor for vacuum robot. ; Also has IR beacon function. ;; Written by Dale A. Heatherington Jan 2000 ;;---------------------------------------------------------------------- ;;This program is free software; you can redistribute it and/or modify ;;it under the terms of the GNU General Public License as published by ;;the Free Software Foundation; either version 2 of the License, or ;;(at your option) any later version. ;; ;;This program is distributed in the hope that it will be useful, ;;but WITHOUT ANY WARRANTY; without even the implied warranty of ;;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;GNU General Public License for more details. ;;You should have received a copy of the GNU General Public License ;;along with this program; if not, write to the Free Software ;;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA ;;------------------------------------------------------------------------ RADIX dec processor 16c73 __CONFIG h'3ff2' ;Internal HS 4 mhz osc, no watchdog ;Note: this is overridden in the makefile. include "p16c73.inc" #define p16c73 ;------------------------------------------------------------ ;Port A input bits IR_Right equ 0 ;Right IR sensor input (low true) on port A IR_Left equ 1 ;Left IR sensor input IR_Center equ 2 ;Center IR sensor input ;Port B output bits to IR LEDs BILED_R equ 7 ;Right beam interruption IR led (low true) BILED_L equ 6 ;Left beam interruption IR led RFLED_R equ 5 ;Right reflection IR LED RFLED_C equ 4 ;Center reflection IR LED RFLED_L equ 3 ;Left reflection IR LED BEACON equ 2 ;High power beacon LEDS (** High True **) ;Port C output bits to control processor OBJ_L equ 0 ;Left object detected (low true) OBJ_C equ 1 ;Center object detected OBJ_R equ 2 ;Right object detected BI_L equ 3 ;Left beam interruption BI_R equ 4 ;Right beam interruption BEACON_R equ 5 ;Beacon RIGHT BEACON_L equ 6 ;Beacon LEFT ;---------------------- N_cycles equ 15 ;variables i_main equ 20h integ_L equ 21h integ_C equ 22h integ_R equ 23h integ_BI_L equ 24h integ_BI_R equ 25h integ_beacon_L equ 26h integ_beacon_R equ 27h j_main equ 28h ;-------------------------------------------------- ; MACROS BANK0 macro bcf STATUS,RP0 endm BANK1 macro bsf STATUS,RP0 endm ;;Cycle the sensor LEDs ;;One cycle of 40 KHZ (less 10uS for overhead in other code) ;This takes 15uS to execute. A complete cycle is 25 uS long. ;These LEDs need logic low to turn them on. cycle_leds MACRO LED bcf PORTB,LED nop nop nop nop nop nop nop nop nop nop nop bsf PORTB,LED nop nop endm ;Cycle the beacon LEDs at 33 khz ;The high power beacon LEDs need a logic high to turn them on ;This takes 20 uS plus 10uS in other code ; cycle_beacon_leds MACRO LED bsf PORTB,LED nop nop nop nop nop nop nop nop nop nop nop nop nop bcf PORTB,LED nop nop nop nop nop endm delay_7us MACRO nop nop nop nop nop nop nop endm delay_16us MACRO local _loop movlw 4 movwf j_main _loop decfsz j_main goto _loop nop nop endm ;;Drive the integrator up 1 count if return pulse is present ;; but count down by 1 if the pulse is not present. integrate_pulse MACRO N,inbit local _ip_seen, _ip_done btfss PORTA,inbit ; //sample IR sensor (low = pulse seen) goto _ip_seen; movf N,w ; btfss STATUS,Z ; //Don't wrap below zero decf N,f; //Decrement integrator if pulse not there goto _ip_done; _ip_seen incf N,f; //increment if pulse is there btfsc STATUS,Z; //Don't wrap from 255 to 0 decf N,f; _ip_done ENDM ;;Drive the integrator up 1 count if pulse is NOT present ;; but decrement it if a pulse IS present. (pulse is not supposed to be here) integrate_space MACRO N,inbit local _is_seen, _is_done btfsc PORTA,inbit ; //sample IR sensor (high = pulse not seen) goto _is_seen; movf N,w; btfss STATUS,Z; //If it's zero don't decrement it decf N,f; goto _is_done; _is_seen incf N,f; btfsc STATUS,Z ; //Don't wrap around decf N,f; _is_done ENDM ;;Make the output go LOW (true) if the integrator ;;value is greater than 127. output MACRO N,outbit local _one_out, _output_done btfss N,7 goto _one_out bcf PORTC,outbit goto _output_done _one_out bsf PORTC,outbit _output_done endm ;Subtract "K" from integrator, don't underflow below zero leak_down MACRO N,K local _leak_exit movf N,f ;test for zero btfsc STATUS,Z goto _leak_exit movlw ~K + 1 ;twos complement for subtraction addwf N,f btfss STATUS,C clrf N ;force N to zero if it overflowed below zero _leak_exit endm ;--------------------------------------------------------------------- ORG 0 goto main_code ORG 4 nop ; No interrupts main_code clrf STATUS clrf INTCON clrf ADCON0 movlw 0f8h movwf PORTB movlw 0ffh movwf PORTC clrf TMR0 clrf integ_L clrf integ_R clrf integ_C clrf integ_BI_L clrf integ_BI_R clrf integ_beacon_L clrf integ_beacon_R BANK1 movlw 7 ;Bits 0,1 and 2 are the IR sensor inputs movwf TRISA movlw 0 movwf TRISB ;port C bits all outputs movwf TRISC ;port B bits all outputs movlw 081h movwf OPTION_REG movlw 7 movwf ADCON1 ;Set for all digital inputs on port A BANK0 MainLoop: ;Start of frame: 0 uS ; Emit IR pulses on left LED and register response in integ_L. movlw 5 movwf i_main pre_L cycle_leds RFLED_L ;5 cycles of 40 khz delay_7us decfsz i_main goto pre_L pulse_L movlw N_cycles ; movwf i_main ; Loop N_cycles times for N_cycles cycles of 40 khz ; This makes a 500uS IR pulse pulse_loop_L cycle_leds RFLED_L integrate_pulse integ_L,IR_Left ;Check for presense of pulse for N_cycles decfsz i_main goto pulse_loop_L ;Offset from start: 500uS ;Emit IR pulses on right LED and register response with integ_R. movlw 5 movwf i_main pre_R cycle_leds RFLED_R ;5 cycles of 40 khz delay_7us decfsz i_main goto pre_R pulse_R movlw N_cycles movwf i_main ; Loop N_cycles times for N_cycles cycles of 40 khz pulse_loop_R cycle_leds RFLED_R integrate_pulse integ_R,IR_Right ;Check for presense of pulse decfsz i_main goto pulse_loop_R ;offset from start: 1000 uS ;Emit IR pulses on center LED and register response with integ_C. movlw 5 movwf i_main pre_C cycle_leds RFLED_C ;5 cycles of 40 khz delay_7us decfsz i_main goto pre_C movlw N_cycles movwf i_main ; Loop N_cycles times for N_cycles cycles of 40 khz pulse_loop_C cycle_leds RFLED_C integrate_pulse integ_C,IR_Center ;Check for presense of pulse decfsz i_main goto pulse_loop_C ;offset from start 1500 uS ;Emit IR pulses on right beam interruption LED ; and register response with integ_BI_R. movlw 5 movwf i_main pre_BI_R cycle_leds BILED_R ;5 cycles of 40 khz delay_7us decfsz i_main goto pre_BI_R pulse_BI_R movlw N_cycles movwf i_main ; Loop N_cycles times for N_cycles cycles of 40 khz pulse_loop_BI_R cycle_leds BILED_R integrate_pulse integ_BI_R,IR_Right ;Check for presense of pulse decfsz i_main goto pulse_loop_BI_R ;offset from start 2000 uS ;Emit IR pulses on left beam interruption LED ;and register response with integ_BI_L. movlw 5 movwf i_main pre_BI_L cycle_leds BILED_L ;5 cycles of 40 khz delay_7us decfsz i_main goto pre_BI_L pulse_BI_L movlw N_cycles movwf i_main ; Loop N_cycles times for N_cycles cycles of 40 khz pulse_loop_BI_L cycle_leds BILED_L integrate_pulse integ_BI_L,IR_Left ;Check for presense of pulse decfsz i_main goto pulse_loop_BI_L ;offset from start: 2500 uS ;Now produce a High power 500 uS beacon pulse. ;We expect the transponder to reply with a 500 uS pulse ; 4000 uS later. movlw 20 movwf i_main Pulse_loop_Beacon cycle_beacon_leds BEACON delay_7us decfsz i_main goto Pulse_Loop_Beacon ;All LEDs are now off ;offset from start: 3000 uS movlw 12 movwf i_main pre_space delay_16us ;delay 197uS, wait for pulse to drop decfsz i_main goto pre_space movlw N_cycles movwf i_main ;loop N_cycles with all LEDs OFF space_loop integrate_space integ_C,IR_Center ;Now all integrators look for space (no pulse) integrate_space integ_R,IR_Right integrate_space integ_L,IR_Left integrate_space integ_BI_L, IR_Left integrate_space integ_BI_R, IR_right integrate_space integ_BEACON_R, IR_right integrate_space integ_BEACON_L, IR_Left decfsz i_main goto space_loop ;;Now we check the integrators and set the output bits accordingly. ;Low true unless otherwise noted. ck_integ output integ_L,OBJ_L ;Left object detected output integ_R,OBJ_R ;right object detected output integ_C,OBJ_C ;center object detected output integ_BI_L,BI_L ;Left beam interrupted (high true) output integ_BI_R,BI_R ;Right beam interrupted (high true) output integ_BEACON_L, BEACON_L ;Left Beacon detected output integ_BEACON_R, BEACON_R ;Right Beacon detected ;4600 uS from start ;Wait for transponder beacon pulse movlw 150 ;2400uS delay movwf i_main wt_bcn: delay_16us decfsz i_main goto wt_bcn ; Now capture the long delayed returning ; beacon pulse from the transponder ;7000 uS from start and 4000 uS from BEACON pulse movlw N_cycles movwf i_main ; Loop N_cycles times bsf PORTB,0 ;Debug timing pulse on port B:0 getBeacon integrate_pulse integ_BEACON_L,IR_Left ;Check for presense of pulse integrate_pulse integ_BEACON_R,IR_Right delay_7us decfsz i_main goto getBeacon bcf PORTB,0 ;Drop debug pulse on port B:0 ; leak leak_down integ_L,8 ;Bias the integrators to the down side... leak_down integ_R,8 ;...for random or no inputs. leak_down integ_C,8 leak_down integ_BI_L,8 leak_down integ_BI_R,8 leak_down integ_BEACON_R,8 leak_down integ_BEACON_L,8 movlw 18 ;Delay about 300 uS before restarting the loop movwf i_main wt_final: delay_16us decfsz i_main goto wt_final goto MainLoop ;Infinite main loop ;------------------------------------------------------------ END