***************************************************************************** * These files contain routines that allow the Handyboard to use the Miniboard * as a slave to run a number of sensors and effectors. If your only interest * is having the Handyboard communicate to the Miniboard, see the (BareBones) * spi_comBB.asm and bspiBB.asm files. These routines were written by Dirk * Edmonds, John Fischer, Paul Rybski and Brian Schmalz (in the order of the * alphabet). * * On the Miniboard, * up to 7 sonars can be plugged into Port C, with the echo going into TFLG1 * (port A pin 2) (We ORed the echos together). Eight analog inputs are * available in port E, but analog 0 is expected to be measuring the battery * level (as explained in the Miniboard technical reference). Only one drive * motor (0) is PW modulated; two others (2 and 3) are left on continuously, * for 2 servo motors (which are controlled by TOC2 and TOC3 (port A pins 5 * and 6)). An attempt has been made to regulate the speed of our robots; it * depends on the shaft encoders output and the size of the wheels. An IR * shaft encoder (using DIGIKEY part number OR516 with 330 and 1M ohm * resistors) is connected to port A pin 7. * * To connect the Handyboard to the Miniboard you must solder an eight pin * connector to one end of a regulation telephone cable. Assuming the * telephone cable is wired (looking into the connector with the tab on top) * left to right: * (b)lue - (y)ellow - (g)reen - (r)ed - bl(a)ck - white (not connected) * * Then the connector to the spi port on the Handyboard is wired: * _____ * | |by| * |r | | * |g |a | * | | | * ----- * * An extra wire from the Handyboard digital input pin 15 to the Miniboard TxD * is required as a busy flag. * * This file should be assembled and loaded onto the Handyboard; bspi.asm * should be assembled and loaded onto the Miniboard. initSpi.c can be loaded * and then INIT_SPI() can be called to get the Handyboard ready to * communicate. ***************************************************************************** * These are the functions available: * clearStuck(int nuthin) clears the stuck bit and sets speed to 0 * stuckStatus(int nuthin) returns the value of the stuck bit * readSonar(int sonarName) where sonarName is given below (Ex. FRONT) * resetDist(int nuthin) * readDist(int nuthin) * ICBwriteXReg(int arg) (ICBwrite0Reg(int arg)) (See writeReg in comm.c.) * readReg(int address). * chooseSonars(int mask) * servo1Dir(int degrees) (servo2Dir(int degrees)) * readAnalog(int num) (readIR(int num) where 0 <= num <= 7) * motorOff(int nuthin) * motForward(int cm/sec) (motBackward(int cm/sec)) ***************************************************************************** * file of standard 6811 register declarations ******************************************************************** * Control Registers BASE EQU $1000 PORTA EQU $1000 ; Port A data register RESV1 EQU $1001 ; Reserved PIOC EQU $1002 ; Parallel I/O Control register PORTC EQU $1003 ; Port C latched data register PORTB EQU $1004 ; Port B data register PORTCL EQU $1005 ; DDRC EQU $1007 ; Data Direction register for port C PORTD EQU $1008 ; Port D data register DDRD EQU $1009 ; Data Direction register for port D PORTE EQU $100A ; Port E data register CFORC EQU $100B ; Timer Compare Force Register OC1M EQU $100C ; Output Compare 1 Mask register OC1D EQU $100D ; Output Compare 1 Data register * Two-Byte Registers (High,Low -- Use Load & Store Double to access) TCNT EQU $100E ; Timer Count Register TIC1 EQU $1010 ; Timer Input Capture register 1 TIC2 EQU $1012 ; Timer Input Capture register 2 TIC3 EQU $1014 ; Timer Input Capture register 3 TOC1 EQU $1016 ; Timer Output Compare register 1 TOC2 EQU $1018 ; Timer Output Compare register 2 TOC3 EQU $101A ; Timer Output Compare register 3 TOC4 EQU $101C ; Timer Output Compare register 4 TI4O5 EQU $101E ; Timer Input compare 4 or Output compare 5 register TCTL1 EQU $1020 ; Timer Control register 1 TCTL2 EQU $1021 ; Timer Control register 2 TMSK1 EQU $1022 ; main Timer interrupt Mask register 1 TFLG1 EQU $1023 ; main Timer interrupt Flag register 1 TMSK2 EQU $1024 ; misc Timer interrupt Mask register 2 TFLG2 EQU $1025 ; misc Timer interrupt Flag register 2 PACTL EQU $1026 ; Pulse Accumulator Control register PACNT EQU $1027 ; Pulse Accumulator Count register SPCR EQU $1028 ; SPI Control Register SPSR EQU $1029 ; SPI Status Register SPDR EQU $102A ; SPI Data Register BAUD EQU $102B ; SCI Baud Rate Control Register SCCR1 EQU $102C ; SCI Control Register 1 SCCR2 EQU $102D ; SCI Control Register 2 SCSR EQU $102E ; SCI Status Register SCDR EQU $102F ; SCI Data Register ADCTL EQU $1030 ; A/D Control/status Register ADR1 EQU $1031 ; A/D Result Register 1 ADR2 EQU $1032 ; A/D Result Register 2 ADR3 EQU $1033 ; A/D Result Register 3 ADR4 EQU $1034 ; A/D Result Register 4 BPROT EQU $1035 ; Block Protect register RESV2 EQU $1036 ; Reserved RESV3 EQU $1037 ; Reserved RESV4 EQU $1038 ; Reserved OPTION EQU $1039 ; system configuration Options COPRST EQU $103A ; Arm/Reset COP timer circuitry PPROG EQU $103B ; EEPROM Programming register HPRIO EQU $103C ; Highest Priority Interrupt and misc. INIT EQU $103D ; RAM and I/O Mapping Register TEST1 EQU $103E ; factory Test register CONFIG EQU $103F ; Configuration Control Register * Interrupt Vector locations SCIINT EQU $D6 ; SCI serial system SPIINT EQU $D8 ; SPI serial system PAIINT EQU $DA ; Pulse Accumulator Input Edge PAOVINT EQU $DC ; Pulse Accumulator Overflow TOINT EQU $DE ; Timer Overflow TOC5INT EQU $E0 ; Timer Output Compare 5 TOC4INT EQU $E2 ; Timer Output Compare 4 TOC3INT EQU $E4 ; Timer Output Compare 3 TOC2INT EQU $E6 ; Timer Output Compare 2 TOC1INT EQU $E8 ; Timer Output Compare 1 TIC3INT EQU $EA ; Timer Input Capture 3 TIC2INT EQU $EC ; Timer Input Capture 2 TIC1INT EQU $EE ; Timer Input Capture 1 RTIINT EQU $F0 ; Real Time Interrupt IRQINT EQU $F2 ; IRQ External Interrupt XIRQINT EQU $F4 ; XIRQ External Interrupt SWIINT EQU $F6 ; Software Interrupt BADOPINT EQU $F8 ; Illegal Opcode Trap Interrupt NOCOPINT EQU $FA ; COP Failure (Reset) CMEINT EQU $FC ; COP Clock Monitor Fail (Reset) RESETINT EQU $FE ; RESET Interrupt ***************************************************************************** ORG MAIN_START variable_tempIcb: FDB 0 ;declare some variables first variable_LEFT: FDB 0x80 variable_H_LEFT: FDB 0x40 variable_FRONT: FDB 0x20 variable_H_RIGHT: FDB 0x10 variable_RIGHT: FDB 0x8 variable_BACK: FDB 0x4 variable_H_BACK: FDB 0x2 ***************************************************************************** *command_char must be treated special because it seizes control of the *interupts on the miniboard. ***************************************************************************** subroutine_command_char: LDX #BASE STAB SPDR,X BRCLR SPSR,X %10000000 * LDAB SPDR,X RTS ***************************************************************************** *These routines send and get characters; they're all the same. ***************************************************************************** subroutine_get_char: subroutine_put_char: subroutine_charXchg: LDX #$7FFF BRSET 0,X %00100000 * LDX #BASE STAB SPDR,X BRCLR SPSR,X %10000000 * LDAB SPDR,X LDX #$7FFF BRCLR 0,X %00100000 * LDX #BASE RTS ***************************************************************************** *Turn THE motor on (motor 0). Used by the functions "motForward" and *"motBackward" which loads accumulator A with the percent (speed) and *accumulator B with the direction. Form: ICBmotorOn(256*Percent +Dir(0,1)) *(if being called in C) ***************************************************************************** subroutine_ICBmotorOn: SEI PSHB ;save direction LDAB #$30 JSR subroutine_command_char PULB CMPB #0 ;compare to 0 BEQ goForward ;0 == go forward LDAB #$10 ;else go back JSR subroutine_charXchg BRA setSpeed2 goForward LDAB #$11 JSR subroutine_charXchg setSpeed2 TAB ;get the percentage out of the high byte JSR subroutine_charXchg ;and send it JSR subroutine_charXchg ;once more to say bye bye CLI RTS ***************************************************************************** *These routines cause the motor to go forward or backwards. *Form: motForward(int speed) (motBackward(int speed)) *where speed is in cm/sec ***************************************************************************** subroutine_motForward: SEI TBA LDAB #0 JSR subroutine_ICBmotorOn RTS subroutine_motBackward: SEI TBA LDAB #1 JSR subroutine_ICBmotorOn RTS ***************************************************************************** *Turn THE motor off. Form: motorOff(int nuthin) ***************************************************************************** subroutine_motorOff: SEI LDAB #$31 JSR subroutine_command_char LDAB #$11 JSR subroutine_charXchg JSR subroutine_charXchg CLI RTS ***************************************************************************** *Reads whatever data is stored in miniboard memory, starting at register 7 *Form: readAnalog(int num) OR readIR(int num) 0 <= num <= 7 ***************************************************************************** subroutine_readIR: subroutine_readAnalog: SEI PSHB ;save the num LDAB #$32 JSR subroutine_command_char PULB ;retrieve num and JSR subroutine_charXchg ;send it over then JSR subroutine_charXchg ;recieve the data back CLRA PSHB JSR subroutine_charXchg PULB CLI RTS ***************************************************************************** *Form: servo1Dir(int degrees*10) (servo2Dir(int degrees*10)) Sets the *angle of the servo with control pin PA6 (PA5) to "degrees". This routine *expects degrees to be given in tenths of degrees; for example 78.3 degrees *requires an argument of 783 ***************************************************************************** subroutine_servo1Dir: SEI STD variable_tempIcb ;store the angle LDAB #$33 JSR subroutine_command_char LDAB #1 ;set the servo number JSR subroutine_charXchg ;send over the servo number LDD variable_tempIcb TAB ;send over the high byte JSR subroutine_charXchg ;(of the angle) LDD variable_tempIcb ;retrieve the low byte JSR subroutine_charXchg ;send over the low byte JSR subroutine_charXchg CLI RTS subroutine_servo2Dir: SEI STD variable_tempIcb ;store the angle LDAB #$33 JSR subroutine_command_char LDAB #2 ;set the servo number JSR subroutine_charXchg ;send over the servo number LDD variable_tempIcb TAB ;send over the high byte JSR subroutine_charXchg ;(of the angle) LDD variable_tempIcb ;retrieve the low byte JSR subroutine_charXchg ;send over the low byte JSR subroutine_charXchg CLI RTS ***************************************************************************** *Choose sonars to be fired. Form: chooseSonars(int mask) where the mask *will be given as the concatenation of the sonar names; for example *chooseSonars(H_LEFT + H_RIGHT + FRONT) ***************************************************************************** subroutine_chooseSonars: SEI ; Each bit that is high indicates that PSHB ; that sonar is desired. Setting bit 0 LDAB #$34 ; will have no effect. Sending all zeros JSR subroutine_command_char ; will turn off all sonars. PULB JSR subroutine_charXchg ; Send the mask. JSR subroutine_charXchg CLI RTS ***************************************************************************** *Read any register. Form: readReg(int address). (Easiest to give address *in hexadecimal.) ***************************************************************************** subroutine_readReg: SEI PSHB ;save the low half of the address LDAB #$35 JSR subroutine_command_char TAB JSR subroutine_charXchg ;send over the high byte PULB ;retrieve the low byte JSR subroutine_charXchg ;send the low byte over CLRA JSR subroutine_charXchg ;receive the data back. CLRA PSHB JSR subroutine_charXchg PULB CLI RTS ***************************************************************************** *Lame way to write to those registers starting in the X segment of memory *No way around using a C function to "prepare" the argument; the Form is: * ICBwriteXReg(int arg) (ICBwrite0Reg(int arg)) where arg = 256 * low byte of *address + the byte to be written. C function should have 2 arguments, the *address and the data; check for x segment or 0 segment and call correct ICB *routine. ***************************************************************************** subroutine_ICBwriteXReg: SEI PSHB LDAB #$36 JSR subroutine_command_char LDAB #$10 JSR subroutine_charXchg ;high byte TAB JSR subroutine_charXchg ;low byte PULB JSR subroutine_charXchg ;data JSR subroutine_charXchg CLI RTS subroutine_ICBwrite0Reg: SEI PSHB LDAB #$36 JSR subroutine_command_char CLRB ;regs starting at 0 JSR subroutine_charXchg ;high byte TAB JSR subroutine_charXchg ;low byte PULB JSR subroutine_charXchg ;data JSR subroutine_charXchg CLI RTS ***************************************************************************** *Get the distance the pulse accumulator has accumulated so far. *Form: readDist(int nuthin) ***************************************************************************** subroutine_readDist: SEI LDAB #$37 JSR subroutine_command_char JSR subroutine_charXchg TBA JSR subroutine_charXchg PSHB JSR subroutine_charXchg PULB CLI RTS ***************************************************************************** *reset the shaft encoder memory. Form: resetDist(int nuthin) ***************************************************************************** subroutine_resetDist: SEI LDAB #$38 JSR subroutine_command_char JSR subroutine_charXchg CLI RTS ***************************************************************************** *This returns the latest readings of a particular sonar ***************************************************************************** subroutine_readSonar: SEI PSHB ;save which sonar is desired LDAB #$40 ;(Eg. FRONT) JSR subroutine_command_char PULB ;retrieve sonar and JSR subroutine_charXchg ;send it over then JSR subroutine_charXchg ;recieve the data back CLRA PSHB JSR subroutine_charXchg PULB CLI RTS ***************************************************************************** * Stuck routines ***************************************************************************** subroutine_stuckStatus: SEI LDAB #$41 ;retrieve the stuck flag JSR subroutine_command_char JSR subroutine_charXchg ;recieve the data back CLRA PSHB JSR subroutine_charXchg PULB CLI RTS subroutine_clearStuck: SEI LDAB #$42 ;clear the stuck flag JSR subroutine_command_char JSR subroutine_charXchg CLI RTS