***************************************************************************** * 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. * * 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 Miniboard; spi_com.asm * should be assembled and loaded onto the Handyboard. initSpi.c can be loaded * and then INIT_SPI() can be called to get the Handyboard ready to * communicate. ***************************************************************************** EEPROM EQU $F800 ; start of eeprom * 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 * Masks for serial port PORTD_WOM EQU $20 BAUD1200 EQU $B3 BAUD9600 EQU $B0 TRENA EQU $0C ; Transmit, Receive ENAble RDRF EQU $20 ; Receive Data Register Full TDRE EQU $80 ; Transmit Data Register Empty ************************************************************************* *** zero page RAM definitions ORG $00 sonar_0 RMB 1 ;full left sonar_1 RMB 1 ;half left sonar_2 RMB 1 ;front sonar_3 RMB 1 ;half right sonar_4 RMB 1 ;full right sonar_5 RMB 1 ;back sonar_6 RMB 1 ;half back ***analog storage adc_0 RMB 1 ; Register 7 adc_1 RMB 1 adc_2 RMB 1 adc_3 RMB 1 adc_4 RMB 1 adc_5 RMB 1 adc_6 RMB 1 adc_7 RMB 1 ***Pulse accumulator stuff storeDist RMB 2 *** motor control byte *** high bits control enable low bits control direction motctrl RMB 1 *** motor speed stuff plsCnt RMB 1 speed1 RMB 1 desrdClicks RMB 1 speedTmr RMB 2 stuckCnt RMB 2 clicksGone RMB 1 imStuck RMB 1 totalDiff RMB 2 minSpeed RMB 1 ***steering stuff maxRight RMB 2 maxLeft RMB 2 ***sonar variables sonarMask RMB 1 Smask2 RMB 1 sonarCount RMB 1 pingedSonar RMB 1 Psonar2 RMB 1 oldPingedSon RMB 1 sonarNum RMB 1 maxWait RMB 1 numCount RMB 1 sonChgdFlag RMB 1 startTime RMB 2 tempDist RMB 1 tempCount RMB 1 ***other temps temp RMB 1 doubleTemp RMB 2 dTemp2 RMB 2 ********************************************************************** * * * MAIN CODE * * * ********************************************************************** ORG $F800 Start: LDS #$00ff LDX #$1000 ; point to register base BSET OPTION,X %10000000 ; turn on analog subsystem BCLR SCCR2,X %00001100 *servo control stuff LDAA #$60 ;01100000 STAA OC1M,X ;plug the servos into port A pin 6 and pin 5 STAA OC1D,X CLR TOC1 ;TOC1 is going to turn the pulses on BSET TCTL1,X %10100000 ;OC2 turns off PA6, OC3 turns off PA5 LDD #3280 ;Center the servos. 0deg=4840 180deg=1630 STD TOC2 STD TOC3 *steering stuff LDD #3718 ; Maximum turns for our robots are +-24 degs STD maxLeft LDD #2902 STD maxRight * it's a rev 1 board: turn off the motor LDAA #$CC ;BUT turn on the servo motors (2 and 3) STAA PORTB,X STAA motctrl * clear speed stuff CLR plsCnt CLR speed1 CLR imStuck CLR clicksGone CLR desrdClicks LDD #0 STD speedTmr STD stuckCnt STD totalDiff * Set up SPI port LDAA #%00000110 STAA DDRD,X LDAA #%11000100 STAA SPCR,X BSET PORTD,X %00000010 LDAA SPSR,X LDAA SPDR,X * Set up for sonars LDAA #$FD STAA DDRC,X BCLR PORTCL,X #$FD BSET PORTCL,X #1 BSET TCTL2,X %00010000 CLR sonarMask ;all 7 sonars off initiallly CLR sonarCount CLR sonarNum CLR pingedSonar CLR sonChgdFlag LDAA #100 STAA maxWait LDAA #4 STAA TFLG1,X LDAA #$FF STAA sonar_0 STAA sonar_1 STAA sonar_2 STAA sonar_3 STAA sonar_4 STAA sonar_5 STAA sonar_6 *Get pulse accumulator ready LDAA #$50 STAA PACTL,X LDD #0 STD storeDist *Clear the status register CLRA TAP * Insert YOUR code here MAIN LDAB #$10 ; Here the mpu is just performing a to d STAB ADCTL ; conversion on the analog inputs, and BRCLR ADCTL,X %10000000 * ; waiting for 1 ms to pass. (RIGHT HERE tho, LDAB ADR1 ; it is waiting for the first half of the STAB adc_0 ; a/d conversion to finish.) LDAB ADR2 STAB adc_1 LDAB ADR3 STAB adc_2 LDAB ADR4 STAB adc_3 LDAB #$14 STAB ADCTL BRCLR ADCTL,X %10000000 * ; Now it is waiting for the 2nd half to LDAB ADR1 ; finish. STAB adc_4 LDAB ADR2 STAB adc_5 LDAB ADR3 STAB adc_6 LDAB ADR4 STAB adc_7 BRCLR TFLG1,X %00010000 MAIN ; If 1 ms has NOT passed, continue this loop. JSR SYSTEMINT ; Otherwise, do housekeeping stuff and then BRA MAIN ; come back to this loop. ********************************************************************** * * SYSTEMINT 1 kHz system interrupt routine * * TIMER: uses TOC4 for control * * * System interrupt performs the following tasks: * * 1) Set up for next time * 2) check the sonars * 3) check pulse accumulator * 4) check if stuck * 5) check speed * 6) do PWM ********************************************************************* SYSTEMINT: ************************************************************************ * setup for next (polled) interrupt ************************************************************************ LDD #2000 ; 2000 cycles = 1 millisec. ADDD TOC4,X ; add TOC4 to D STD TOC4,X ; store back BCLR TFLG1,X %11101111 ; clear OC4 for next compare ************************************************************************* *Check if there were new changes to the sonars chosen since the last echo *was received. ************************************************************************* LDAA sonChgdFlag ;Only change when we got changes to make BEQ GOODNAME CLR sonChgdFlag ;wait until the echo returns. If the echo LDAA Psonar2 ;never returns, the changes won't occur until STAA pingedSonar ;the next sonar gets its' echo back. LDAA Smask2 ; Check out CASE_4 below to follow all the logic STAA sonarMask LDAA maxWait STAA sonarCount GOODNAME *********************************************************************** *Update sonarCount and check for time to ping next sonar. MaxWait will *be reached no matter what else happens. *********************************************************************** LDAA pingedSonar ; If no sonar was pinged, skip the rest BEQ NOECHO ; INC sonarCount LDAA sonarCount CMPA maxWait BLO WAITING BCLR PORTC,X #$FD ;Turn off the init pulse BRSET TFLG1,X %00000100 NONAME JSR FINDSONAR ;Flag was never set. Sonar number is returne in LDAA #128 ;sonarNum. LDAB sonarNum ;Sonar data is stored starting at "0" LDY #0 ABY STAA 0,Y ;Store value in position indexed by Y NONAME JSR NEXTSONAR ;it was set, but not cleared by an CLR sonarCount ;echo. The value has been JMP NOECHO ;stored already. WAITING ************************************************************************* *Check if tic1 has captured an echo. If so, store the time in the proper *memory and prepare for next ping. Does NOT ping next sonar until the *max wait time has passed; see above routine. ************************************************************************* BRCLR TFLG1,X %00000100 NOECHO BCLR PORTC,X #$FE ;Turn off the init pulse JSR FINDSONAR ;sonarNum will have the number of the sonar LDD TIC1,X ;that was fired SUBD startTime CMPA #20 ; Distances < 20 are invalid BLO NOECHO ; HERE'S WHERE YOU CHANGE THE CMPA #128 ; MAXIMUM DISTANCE RETURNED BY THE SONAR BLO OKTOSTORE LDAA #128 OKTOSTORE LDAB sonarNum ;Sonar data (INSTNEOUS) starts at 0 LDY #0 ABY STAA 0,Y ;Store value in position indexed by Y NOECHO **************************************************************************** *Update the shaft encoder *if the motor is running backwards, and the PACNT has registered a pulse, *we should subtract one from the stored PACNT **************************************************************************** BRCLR TFLG2,X %00010000 DONE_SE ;Check if there has been a pulse BCLR TFLG2,X %11101111 ;if not -> done. Else clear the flag LDAA desrdClicks ;and check if movement is desired. BEQ DONE_SE ;If no movement desired -> done, else LDX storeDist ;increment the total (2 byte) distance. INX STX storeDist ;Next, increment clicksGone which LDX #BASE ;keeps track of distance travelled since INC clicksGone ;we last looked at the speed. DONE_SE ***************************************************************************** * Watch for being Stuck ***************************************************************************** LDAA imStuck ; No sense checking if we are already stuck BNE STUCK LDAA desrdClicks ; We aren't expected to be moving -> not stuck BEQ NOT_STUCK LDAA clicksGone ; We have moved -> not stuck BNE NOT_STUCK LDD stuckCnt ;The motor has been on and we haven't moved ADDD #1 ;for 5000 ms --> we're stuck STD stuckCnt CPD #5000 BNE MAYBE_STUCK ; If it has not been 5 sec. yet, keep looking INC imStuck ; Else we are stuck. BCLR PORTB,X %00010001 ; Turn off the motor. CLR desrdClicks STUCK JMP NOCLEAR NOT_STUCK LDD #0 ; Clear the timer-for-being-stuck STD stuckCnt MAYBE_STUCK ***************************************************************************** * SPEED regulation * Here an attempt is made to modulate the PWM according to the actual * distance the shaft encoder says we have moved, so as to keep a constant * speed. Also takes battery level into account. ***************************************************************************** LDD speedTmr ADDD #1 STD speedTmr CPD #250 ; Check the speed after .25 sec. BLO NO_CHANGE LDD #0 ; Get ready for next time. STD speedTmr LDAB desrdClicks ; First, check if we want to move, if so then BNE CHECK_BATTERY ; check the battery level. CLR speed1 ; Else, clear speed variable and skip the rest. BRA NO_CHANGE CHECK_BATTERY LDAB #3 ; Set the minimum PWM according to the battery STAB minSpeed ; level. When battery is strong, minimum PWM LDAB adc_0 ; is 3 out of 16 ms. CMPB #170 BHI CHECK_SPEED INC minSpeed ; Slightly weak -> PWMmin == 4 out of 16 ms. CMPB #150 BHI CHECK_SPEED INC minSpeed ; Really weak -> PWMmin == 5 out of 16 ms. CHECK_SPEED LDAB clicksGone ;now check the speed CMPB desrdClicks BLO GOING_SLOWER GOING_FASTER CLR clicksGone ; Reset for next time. SUBB desrdClicks ; If the robot went too far this time, there is CLRA ; still the possibility that the overall speed ADDD totalDiff ; is too slow; if so, there will be no change STD totalDiff ; in the PWM. If the totalDiff is <= 0 then BHI SLOW_DOWN ; don't do anything. BRA NO_CHANGE SLOW_DOWN LDAB speed1 DECB CMPB minSpeed ; Can't go below the minimum PWM, I call. BCC SPEED_DONE ; (I think BCC == BLE...) LDAB minSpeed BRA SPEED_DONE GOING_SLOWER LDAB desrdClicks ; Capture the difference, then reset for next time. SUBB clicksGone CLR clicksGone CLRA COMA ; Twos complement addition == subtraction COMB ADDD #1 ADDD totalDiff STD totalDiff ; ... There is still the possibility the overall BLO SPEED_UP ; speed is too fast ... If the totalDiff >= 0 BRA NO_CHANGE ; don't do anything this time. SPEED_UP LDAB speed1 ADDB #1 CMPB #16 ; Can't go above 16 out of 16 ms pulse widths. BLS SPEED_DONE LDAB #16 SPEED_DONE STAB speed1 NO_CHANGE *********************************************************************** * Do pulse width modulation, using speed1 as the amount of time the * pulse is high. ************************************************************************ LDAA #$10 ;1/16 is the smallest pulse width ratio SUBA plsCnt ;have we reached the time to set motor on? CMPA speed1 ;Depends on how long (/16) we want it on. BLE KEEPITUP ;if it is within desired pulse width time ->go faster LDAA #$CC ;otherwise, make it turn the motor (1) off and STAA PORTB,X ;keep servos on JMP ENDPWM KEEPITUP LDAA motctrl ;make it turn the motor on STAA PORTB,X ENDPWM INC plsCnt LDAA plsCnt CMPA #$10 BNE NOCLEAR CLR plsCnt NOCLEAR RTS **************************************************************************** * All done with the house keeping; the following subroutines are called from * above. **************************************************************************** ****************************************************************************** * NEXTSONAR - Ping next sonar in mask, store the start time and clear the * timer flag. ***************************************************************************** NEXTSONAR LSL pingedSonar ;Now shift pinged sonar until we find the BNE NORELOAD ;next bit needed in sonarMask LDAA #2 STAA pingedSonar NORELOAD LDAA sonarMask ANDA pingedSonar BEQ NEXTSONAR LDAA #$04 ;clear timer flag STAA TFLG1,X LDD TCNT,X STD startTime LDAA pingedSonar ;ping that sonar STAA PORTC,X NSDONE RTS ***************************************************************************** * FINDSONAR - Find which sonar was fired last ***************************************************************************** FINDSONAR CLR sonarNum LDAA pingedSonar ;find out which sonar was pinged last time STAA oldPingedSon CMPA #$80 BEQ FOUNDBIT ;It is found when MSBit is a 1 REPEATSHIFT INC sonarNum ;keep track of number of shifts LSL pingedSonar LDAA pingedSonar CMPA #$80 BNE REPEATSHIFT ;keep shifting until 1 in MSB FOUNDBIT LDAA oldPingedSon ;Recover original bit placement STAA pingedSonar RTS ********************************************************************** * This is the SPI port interupt menu code. This is the only interupt * that has been enabled. ******************************************************************** PRESPI JMP SPIDONE SPI_COM LDX #BASE ; There is a wire from TxD to digital input BRCLR SPSR,X %10000000 PRESPI ; pin 15 on the handyboard, used as busy flag. LDAB SPSR,X ;clear the flag LDAB SPDR,X BCLR SPCR,X %10000000 ;disable the interupt CASE_0 CMPB #$30 ; (Turn a motor on, any motor.) Note: this BNE CASE_1 ; general purpose functionality has been LDAA imStuck ; subverted by the particulars of the design BNE IM_STUCK ; that we were working on. Our speciallized JSR GET_C ; (Get the motor mask byte.) design used only TBA ; one motor, so the PWM and speed control are LSRA ; are dedicated to that one motor. LSRA LSRA LSRA COMA ANDA motctrl STAA motctrl ORAB motctrl STAB motctrl ; Load the mask into motctrl. JSR GET_C ; Get the speed in cm/sec. LSRB ; cm/sec == 2 * clicks/.25 sec STAB desrdClicks ; (wheel size dependant). LDD #0 STD totalDiff STD speedTmr JMP SPIDONE IM_STUCK JSR GET_C ;Don't do nothing till the stuck flag is cleared JSR GET_C JMP SPIDONE CASE_1 CMPB #$31 ; Turn a selected motor off. BNE CASE_2 JSR GET_C ; Receive the motor to turn off. COMB ANDB motctrl STAB motctrl CLRB STAB desrdClicks JMP SPIDONE CASE_2 CMPB #$32 ; Get a selected analog reading. BNE CASE_3 JSR GET_C ADDB #7 ; Analogs stored starting at register 7. LDY #$0000 ABY ; Data is stored at reg 7 + # of analog desired. LDAB 0,Y JSR PUT_C ; Return the data. JMP SPIDONE CASE_3 CMPB #$33 ; Change the angle of a servo BNE CASE_4 ; (control pins PA5 and PA6). JSR GET_C ; Get which servo to change, CMPB #1 ; 1 (Port A5) or "the other" (Port A6). BNE SRV_OTHR JSR GET_C ; Get high byte of the angle TBA JSR GET_C ; Get low byte of the angle JSR CALCANGLE ; Calculate the value to be given the TOC2 CPD maxLeft ; Don't turn beyond the laws of physics! BHI CANNOT CPD maxRight BLO CANNOT STD TOC2 CANNOT JMP SPIDONE SRV_OTHR JSR GET_C ; Get high byte of the angle TBA JSR GET_C ; Get low byte of the angle JSR CALCANGLE ; Calculate the value to be given the TOC3 STD TOC3 ; no limits JMP SPIDONE CASE_4 CMPB #$34 ; Choose which sonars to fire. BNE CASE_5 INC sonChgdFlag ; To know (during housekeeping) if sonars have changed. CLR Psonar2 ; Clear Psonar2 here in case we are turning them off. JSR GET_C ; Get the mask of bits that say which sonars to fire; ANDB #$FD ; 11111110 will fire all 7 sonars, 10000000 will only STAB Smask2 ; fire sonar_0, 00000010 will fire only sonar_6 etc. BEQ OUTAHERE ; 00000000 will turn them all off LDAA #1 ; Starting with sonar closest to sonar_6, find the STAA Psonar2 ; first sonar to be fired after this change. AGAINSHIFTING LSL Psonar2 ; Now shift pinged sonar until we find the LDAA Smask2 ; closest bit to bit 1 (00000010). ANDA Psonar2 BEQ AGAINSHIFTING CLR numCount ; Now to set the maxWait time; LDAA #2 ; first count the number of bits in the mask. STAA temp BACK ANDA Smask2 BEQ SKIPPED INC numCount SKIPPED LSL temp LDAA temp BEQ SETMAXWAIT BRA BACK SETMAXWAIT LDAA numCount ; Now that we have the number of sonars firing we can LDAB #5 ; set maxWait, which depends on that number. Maximum MUL ; wait time varies linearly, starting at STAB numCount LDAA #115 ; 110ms for 1 sonar -> 80ms for 7 sonars SUBA numCount STAA maxWait OUTAHERE JMP SPIDONE CASE_5 CMPB #$35 ; Read from a register. BNE CASE_6 JSR GET_C ; Get the high byte. TBA JSR GET_C ; Get the low byte. XGDY ; Put it in Y. LDAB 0,Y ; Retrieve and JSR PUT_C ; return the data. JMP SPIDONE CASE_6 CMPB #$36 ; Write to a register BNE CASE_7 JSR GET_C ; Get high byte TBA ; move it to high byte. JSR GET_C ; Get low byte. XGDY JSR GET_C ; Get data byte. STAB 0,Y ; Store it. JMP SPIDONE CASE_7 CMPB #$37 ;read the distance traveled, in cm BNE CASE_8 LDD storeDist ; Retrieve the number of clicks. LSRD ; This is how we converted the number of shaft encoder STD doubleTemp ; counts into centimeters. Weird math. LSRD LSRD LSRD LSRD STD dTemp2 ;D = .4609375 * storeDist == distance travelled in cm LDD doubleTemp ; == (.5 - 1/32 - 1/128) * count SUBD dTemp2 ;since circumference of the wheel is ~ 14.75 cm and STD doubleTemp ;there are 32 counts per rotation. LDD dTemp2 LSRD LSRD STD dTemp2 LDD doubleTemp SUBD dTemp2 STD doubleTemp TAB JSR PUT_C ; Calculation over, send the high byte. LDD doubleTemp JSR PUT_C ; And send the low byte. JMP SPIDONE CASE_8 CMPB #$38 ;Reset the shaft encoder BNE CASE_10 LDD #0 STD storeDist JMP SPIDONE CASE_10 CMPB #$40 ;return a sonar reading BNE CASE_11 CLR temp JSR GET_C CMPB #$80 ;find which sonar is wanted BEQ FNDBIT2 ;It is found when MSBit is a 1 RPTSHFT2 INC temp ;keep track of number of shifts LSLB CMPB #$80 BNE RPTSHFT2 ;keep shifting until 1 in MSB FNDBIT2 LDAB temp LDY #$0000 ABY ; Data is stored at reg 0 + number of sonar desired. LDAB 0,Y JSR PUT_C ; Return the data. JMP SPIDONE CASE_11 CMPB #$41 ;return the stuck flag BNE CASE_12 LDAB imStuck JSR PUT_C JMP SPIDONE CASE_12 CMPB #$42 ;clear the stuck flag BNE DEFAULT CLR imStuck JMP SPIDONE DEFAULT INCB JSR PUT_C SPIDONE JSR PUT_C ; Once more to say bye bye. BSET SPCR,X %10000000 ; Get the flag set. RTI **************************************************************************** * This part contains the comunication routine for the miniboard. * This routine sets the NOT BUSY bit and then waits for the master to * send a byte. Bytes are sent and received in accum. B. ***************************************************************************** GET_C PUT_C LDX #BASE STAB SPDR,X BCLR PORTD,X %00000010 BRCLR SPSR,X %10000000 * LDAB SPDR,X BSET PORTD,X %00000010 RTS ***************************************************************************** * Another utility function used when changing the servo angle ***************************************************************************** CALCANGLE STD doubleTemp LDX #10 IDIV ;X has quotiant, D has remainder (<=9) LSRD STD dTemp2 ;remainder/2 PSHX ;get x into b PULB ;(should be 0) PULB ;B = m/10 LDAA #7 ;multiply times 7 MUL ; D = 7*m/10 ADDD dTemp2 ;D = 7*m/10 +r/2 ADDD doubleTemp ;D = m + 7*m/10 + r/2 COMA COMB ADDD #4841 ;D = 4840 - (m + 7*m/10 +r/2) LDX #BASE RTS ***************************************************************************** * Interrupt vectors. ***************************************************************************** * bad interrupt? return! BadInt RTI Org $FFC0 FDB BadInt ; $FFC0: Reserved FDB BadInt ; $FFC2: Reserved FDB BadInt ; $FFC4: Reserved FDB BadInt ; $FFC6: Reserved FDB BadInt ; $FFC8: Reserved FDB BadInt ; $FFCA: Reserved FDB BadInt ; $FFCC: Reserved FDB BadInt ; $FFCE: Reserved FDB BadInt ; $FFD0: Reserved FDB BadInt ; $FFD2: Reserved FDB BadInt ; $FFD4: Reserved FDB BadInt ; $FFD6: SCI Serial System FDB SPI_COM ; $FFD8: SPI Serial Transfer Complete FDB BadInt ; $FFDA: Pulse Accumulator Input Edge FDB BadInt ; $FFDC: Pulse Accumulator Overflow FDB BadInt ; $FFDE: Timer Overflow FDB BadInt ; $FFE0: Timer Input Capture 4/Output Compare 5 (TI4O5) FDB BadInt ; $FFE2: Timer Output Compare 4 (TOC4) FDB BadInt ; $FFE4: Timer Output Compare 3 (TOC3) ;BEEP; FDB BadInt ; $FFE6: Timer Output Compare 2 (TOC2) FDB BadInt ; $FFE8: Timer Output Compare 1 (TOC1) FDB BadInt ; $FFEA: Timer Input Capture 3 (TIC3) FDB BadInt ; $FFEC: Timer Input Capture 2 (TIC2) FDB BadInt ; $FFEE: Timer Input Capture 1 (TIC1) FDB BadInt ; $FFF0: Real Time Interrupt (RTI) FDB BadInt ; $FFF2: /IRQ (External Pin or Parallel I/O) (IRQ) FDB BadInt ; $FFF4: /XIRQ (Pseudo Non-Maskable Interrupt) (XIRQ) FDB BadInt ; $FFF6: Software Interrupt (SWI) FDB BadInt ; $FFF8: Illegal Opcode Trap () FDB BadInt ; $FFFA: COP Failure (Reset) () FDB BadInt ; $FFFC: COP Clock Monitor Fail (Reset) () FDB Start ; $FFFE: /RESET END ***************************************************************************