;------------------------------------------------------------------------------ ; Source code Test Driver for driving a Motorola R/C Servo Driver. ; Rev 1.0, 11-22-00, 3:10pm ; Kevin Nichols, CSE 466 ; ; Note: Any timing loops are based on using a 32.0 MHz crystal. ; ; ; Port Usage ; P0.5 = YGM (output) "You've Got Mail" ; P0.4 = DAT (output) Dat line ; P0.3 = ACK (input) The Motorola chips' acknowledge line ;------------------------------------------------------------------------------ $NOMOD51 ; disable predefined 8051 registers $INCLUDE (At89c55.INC) ; include CPU definition file for Atmel 89C55 ;------------------------------------------------------------------------------ ; Module name ;------------------------------------------------------------------------------ NAME Test_Servo_Driver ;------------------------------------------------------------------------------ ; Segment and variable declarations ;------------------------------------------------------------------------------ ; ;------------------------------------------------------------------------------ ; Put the STACK segment in the main module. ;------------------------------------------------------------------------------ STACK1 SEGMENT IDATA ; STACK1 goes into IDATA RAM. RSEG STACK1 ; switch to STACK1 segment. DS 16 ; reserve 16 bytes stack space ;------------------------------------------------------------------------------ ; DATA SEGMENT--Reserves space in DATA RAM-- ;------------------------------------------------------------------------------ VARS SEGMENT DATA ; segment for DATA RAM. RSEG VARS ; switch to this data segment command_byte: DS 1 ; Holds the command byte [CCCCCAAA] servo_data: DS 1 ; Holds data for this command bit_count: DS 1 ; Counter for number of bits being sent buffer_h: DS 1 ; Buffer high byte (initially contains servo data) buffer_l: DS 1 ; Buffer low byte (initially contains command & address) ;------------------------------------------------------------------------------ ; CONSTANTS (typeless) ;------------------------------------------------------------------------------ YGM EQU P0_5 ; YGM (output) "You've Got Mail" line going to Motorola chip DAT EQU P0_4 ; DAT (output) Data bit going to the Motorola chip ACK EQU P0_3 ; ACK (input) from the Motorola chip ;------------------------------------------------------------------------------ ; LJMP to "start" ;------------------------------------------------------------------------------ CSEG AT 0 ; absolute Segment at Address 0 LJMP start ; reset location (jump to start) ;------------------------------------------------------------------------------ ; CODE SEGMENT--Reserves space in CODE ROM for assembler instructions. ;------------------------------------------------------------------------------ code_seg_name SEGMENT CODE RSEG code_seg_name ; switch to this code segment USING 0 ; Use register bank 0 start: MOV SP,#STACK1-1 ; assign stack at beginning CALL init ; Go init stuff (& start the frame timer) again: ; This is the servo test routine. ; MOV command_byte,#0x00 ; Command to turn servo 0 on MOV servo_data,#0xFE ; CALL send_package ; Send the package to the controller MOV command_byte,#0x02 ; Command to turn servo 2 on MOV servo_data,#0xFE ; CALL send_package ; Send the package to the controller MOV R1,#0xFF ; Wait for about 4 seconds CALL long_delay MOV command_byte,#0x02 ; Command to turn servo 2 on MOV servo_data,#0x80 ; CALL send_package ; Send the package to the controller MOV R1,#0xFF ; Wait for about 4 seconds CALL long_delay MOV command_byte,#0x00 ; Command to turn servo 0 on MOV servo_data,#0xA4 ; CALL send_package ; Send the package to the controller MOV R1,#0xFF ; Wait for about 4 seconds CALL long_delay SJMP again ;------------------------------------------------------------------------------ ; SUBROUTINES ;------------------------------------------------------------------------------ sub_segment SEGMENT CODE ; segment for interrupt function RSEG sub_segment ; switch to this code segment USING 1 ; register bank for subroutines; ;init subroutine ;-------------------------------------------------- ; Used to initialize all stuff on chip after reset init: CLR YGM ; Clear the output lines CLR DAT MOV command_byte,#0x00 MOV servo_data,#0x00 MOV bit_count,#0x11 ; Must be 1 more than the number of bits to send (ie decimal 17) MOV R1,#0x80 ; Wait about 2 seconds for Motorola chip to stabilize CALL long_delay RET ;send_package subroutine ;------------------------------------------------- ; Used to send a 16 bit package to the Motorola 68HC705 servo controller ; Assumes the data to be sent is already in command_byte and servo_data ; ; Sends 16 bits, high bit of buffer_h first (data) through low bit of buffer_l last (command / address). ; send_package: MOV bit_count,#0x11 ; Make sure bit counter starts with 17 (ie 16 bits to transfer.) MOV buffer_h,servo_data ; Copy the stuff that's going out (so that the last servo data, MOV buffer_l,command_byte ; address & command sent are always available if needed) send_loop: MOV C,ACK ; Get the ACK bit JNC ckYGM_1 ; If ACK is clear, go check YGM (we'll either wait, or send a new bit) ; To get here, ACK must be set. ; If YGM is clear, we need to wait for servo controller chip to clear its ACK. ; If YGM is set, then ball's in our court. We need to clear YGM. ; Either way, we can clear YGM and go back to top. CLR YGM ; Clear YGM. SJMP send_loop ; So, ACK set & YGM clear. Now we're just waiting for the ACK line to go low. ckYGM_1: MOV C,YGM ; So, ACK is clear. Get YGM bit JNC send_bit ; If YGM clear (& ACK is clear), then OK to send next bit. ; ACK clear & YGM is set. Means we're waiting for servo controller to ACK our data. SJMP send_loop ; Don't need to do anything. Just wait for servo controller to ACK our last bit. send_bit: DJNZ bit_count,send_bit_1 ; Check the number of bits still to send. Is it zero? RET ; If so, we're done!! send_bit_1: MOV A,buffer_l ; Still more bits to send. ACK clear, YGM clear. We're OK to send next bit. CLR C ; Clear out the carry flag RLC A ; Move 0 into lsb of buffer_l, and msb of buffer_l into carry MOV buffer_l,A ; Save new buffer_l value MOV A,buffer_h ; Get buffer_h RLC A ; Move msb of buffer_l (was in carry) into lsb of buffer_h, and msb of buffer_h into carry MOV DAT,C ; Put our bit on the DAT line. MOV buffer_h,A ; Save modified copy of buffer_h SETB YGM ; Set the "You've got mail" line. SJMP send_loop ;long_delay routine. ;-------------------------- ; To use: Load variable R1 with some number (FF = approx 4 seconds) ; then call this subroutine. Routine will return after specified amount of time. ; Number of cycles for each instruction shown in comments long_delay: MOV R0,#0xFF ;1 = 375ns outer_lp: MOV R2,#80 ;1 = 375ns inner_lp: DJNZ R2,inner_lp ;2 = 750ns (do this 80 times, total of 60us) DJNZ R0,outer_lp ;2 = 750ns (do this 256 times, total of 15.648ms) DJNZ R1,long_delay ;2 = 750ns (do this R1 times) RET ;2 = 750ns ;------------------------------------------------------------------------------ ; The END directive is ALWAYS required. ;------------------------------------------------------------------------------ END ; End Of File