;* ;* SHARPIR.asc - Sharp GP2D02 IR range example assembly code driver ;* writen for the 68hc12b32 microcontroller. ;* ;* Ted Griebling 2-8-99 ;* opt nol #include equates.asm opt l ;**** Constants ;**** Ram Equates, variables org $0900 ;*************************************************************** ;**** Initialize INIT: lds #$0bff ;Initialize the stack pointer clr COPCTL ;kill the COP ;*************************************************************** ;**** Initialize Timer Functions bset TSCR $80 ;enable timer ;*************************************************************** ;**** Initialize PWM channels ldaa #$01 staa PWPOL ;PWM Channel 0: clock=A, polarity=1 clr PWSCAL0 ;PWM prescale register0 is zero clr PWSCNT0 ;PWM prescale counter0 is zero clr PWCNT0 ;PWM Channel 0 counter is zero ldaa #230 ;Approximate max sensor value... staa PWPER0 ; is stored as PWM Channel 0 period ldaa #50-1 ;Aprox min valid sensor value... staa PWDTY0 ; is stored as initial Duty cycle ;*************************************************************** ;**** Initialize I-O movb #$ff DDRA ;all of PortA is output clr DDRB ;all of PortB is input bset PUCR $02 ;enable PortB pull up resistors bset PWEN $01 ;PortP, bit0 is PWMchannel0 output ;**** Initialize IR subroutine bsr IR_INIT ;*************************************************************** ;**** MAIN program, A loop that repeatedly calls READ_IR and ;**** stores the result as the Duty cycle for PWM Channel 0 ;*************************************************************** MAIN: bsr READ_IR ;get the byte from IR Sensor subd #1 ;because desired duty = PWDTYx + 1 (for left) stab PWDTY0 ;store value as PWM channel 0 Duty Cyle bra MAIN ;do it all again ;*************************************************************** ;**** Initialize IR Sensor, ;**** Set the IR Sensor control line high ;**** It is important to wait the ~2000usec after this ;**** bit is initially set high. IROUTB equ $01 IROUTP equ PORTA IRINB equ $01 IRINP equ PORTB IR_INIT bset IROUTP IROUTB ;set IROUTPort,IROUTBbit high ldx #4000 ;is supposed to be 4000 (2000usec) bsr WAIT ;had as low as 1600 (800usec) rts ;*************************************************************** ;**** READ_IR subroutine, ;**** Set the control bit low ;**** Wait for input to go low ;**** Wait for input to go high ~45000usec ;**** Call GET_IR_BIT eight times ;**** Set control bit high ;**** Evaluate and output "good values" ;**** Wait, so sensor will be happy ;*************************************************************** READ_IR: bclr IROUTP IROUTB ;set IROUTPort,IROUTBbit low IR_REACT: ldx #2 ;load X for loop bsr WAIT ;wait at least 1usec for sensor to react ;AGAIN brset IRINP IRINB AGAIN ;wasts the time just the same WAIT_DIST: brclr IRINP IRINB WAIT_DIST ;Wait for IRINPort,IRDATBit high sei ;disable interrupts clrb ;clear ACCB bsr GET_IR_BIT ;get bits bsr GET_IR_BIT bsr GET_IR_BIT bsr GET_IR_BIT bsr GET_IR_BIT bsr GET_IR_BIT bsr GET_IR_BIT bsr GET_IR_BIT bset IROUTP IROUTB ;set IROUTPort,IROUTBbit high cmpb #50 ;compare with lowest possible good value bpl GOOD ;if good, then skip next line ldab #50 ;if bad, value is no less than 50 GOOD: ldx #4000 ;is supposed to be 4000 (2000usec) bsr WAIT ;had as low as 1600 (800usec) cli ;enable interrupts rts ;done, sensor value is in B ;*************************************************************** ;**** GET_IR_BIT subroutine, ;**** Toggl the control bit high. ;**** Wait. ;**** Toggle the control bit low. ;**** Wait. ;**** Shift the byte into B ;*************************************************************** GET_IR_BIT: bset IROUTP IROUTB ;set IROUTPort,IROUTBbit high ldx #200 ;is supposed to be 200 (100usec)(max?) bsr WAIT ;had as low as 15 (~9usec) (min?) bclr IROUTP IROUTB ;set IROUTPort,IROUTBbit low ldx #200 ;is supposed to be 200 (100usec)(max?) bsr WAIT ;had as low as 22 (~14usec) (min?) brclr IRINP IRINB IR_BIT_LOW ;test IRINPort,IRINBit IR_BIT_HI: sec ;if IRINBit is high, set the carry bit bra ROLLB ;skip the other case IR_BIT_LOW: clc ;If IRINBit is low, clear the carry bit ROLLB: rolb ;rotat the bit into B rts ;Done ;*************************************************************** ;**** WAIT subroutine, loops every 4 Eclock cycles (average). ;**** The Eclock is .125usec (16Mhz crystal = 8Mhz Eclock). ;**** Every wait loop is then .5usec (on average). ;**** (For small numbers the time to enter and exit the loop ;**** throws the timing off) ;*************************************************************** WAIT: dex bne WAIT rts