(**********************************************************************) (* *) (* Function: TSM Table Stepper Motor. *) (* *) (* Creation Date: 6/Aug/92 From: NEW *) (* *) (* Author: Jeff Wright *) (* *) (* Description: *) (* ------------ *) (* The TSM function is designed to drive 2 phase stepper motors in *) (* full and half step modes. Once running, the CPU only has to supply *) (* a desired position, and TSM will accelerate, slew and deccelerate *) (* the motor, interrupting the CPU when done. TSM will handle changes*) (* in desired position during mid-move. *) (* The acceleration/decceleration profile is defined by the user in *) (* the form of a table of parameters that are multiplied by the TPU *) (* with a user defined start period to obtain the step period. The *) (* size of the table is programmable and multiple motors can share the*) (* same table. The actual max speed of the motor is also programmed by*) (* the user independant of the acceleration table. Max size of the *) (* table is dependant on location but can be as big as 56 8 bit values*) (* in 2 channel mode and 80 values in 4 channel mode. *) (* Combined with start period and slew period, this gives up to 58 and*) (* 82 step rates in 2 and 4 channel modes. *) (* *) (* Updates: By: Modification: *) (* -------- --- ------------- *) (* 3/Feb/93 JW Increased max table size in four channel mode by *) (* using PRAM of slaves 2&3. Max. table size in four *) (* chan mode now 80 bytes. Two chan mode still 56. *) (* Code size up from 95 to 105 long words. *) (* 22/Feb/93 JW Reversed PIN_SEQUENCE operation to match spec. *) (* 16/Jun/93 JW Changed revNo from AlphaV.3 to 1.0 - first release*) (* 12/Aug/93 JL Converted to new TPUMASM syntax. *) (* *) (*--------------------------------------------------------------------*) (* Standard Exits Used:- End_Of_Phase: N End_Of_Link: N *) (* *) (* External Files included: NONE *) (* *) (* CODE SIZE excluding standard exits = 105 LONG WORDS *) (*--------------------------------------------------------------------*) (* *) (* *) (********** This Revision: 1.1 *********) (* *) (********** LAST MODIFIED: 12/Aug/93 BY: Jeff Loeliger ********) (* *) (**********************************************************************) (***************************************************************************) (*Motorola reserves the right to make changes without further notice to any*) (*product herein. Motorola makes no warranty, representation or guarantee *) (*regarding the suitability of its products for any particular purpose, nor*) (*does Motorola assume any liability arising out of the application or use *) (*of any product or circuit, and specifically disclaims any and all *) (*liability, including without limitation consequential or incidental *) (*damages. "Typical" parameters can and do vary in different applications. *) (*All operating parameters, including "Typical",must be validated for each *) (*customer application by customer's technical experts. Motorola does not *) (*convey any license under its patent rights nor the rights of others. *) (*Motorola products are not designed, intended, or authorized for use as *) (*components in systems intended for surgical implant into the body, or *) (*other applications intended to support or sustain life, or for any other *) (*application in which the failure of the Motorola product could create a *) (*situation where injury or death may occur. Should Buyer purchase or use *) (*Motorola products for any such unintended or unauthorized application, *) (*Buyer, shall indemnify and hold Motorola and its officers, employees, *) (*subsidiaries, affiliates, and distributors harmless against all claims, *) (*costs, damages, and expenses, and reasonable attorney fees arising out *) (*of, directly or indirectly, any claim of personal injury or death *) (*associated with such unintended or unauthorized use, even if such claim *) (*alleges that Motorola was negligent regarding the design or manufacture *) (*of the part. *) (*Motorola and the Motorola logo are registered trademarks of Motorola Inc.*) (*Motorola is an Equal Opportunity/Affirmative Action Employer. *) (*Copyright Motorola Inc. 1993 *) (***************************************************************************) (*()()()()()()()()()()() DATA STRUCTURE ()()()()()()()()()()()()()()()*) (* *) (* name: Written By: Location Bits: *) (* ----- ----------- --------------- *) (* DESIRED_POS CPU Parameter0 0..15 *) (* Desired destination of motor. *) (* *) (* CURRENT_POS BOTH Parameter1 0..15 *) (* Current position of motor - initialised by CPU,*) (* updated by TPU. *) (* *) (* TAB_INDEX BOTH Parameter2 0..7 *) (* Index into acceleration parameter table updated*) (* by TPU, initialised by CPU. *) (* *) (* TAB_SIZE BOTH Parameter2 8..15 *) (* Contains the length of the acceleration param *) (* table - initialsied by CPU. TPU writes but does*) (* not change. *) (* *) (* S_FLAG BOTH Parameter3 0 *) (* This bit is used as a slewing flag by the TPU. *) (* CPU should init to 0 then never write again. *) (* CPU can read anytime, a 1 indicates slewing. *) (* *) (* SLEW_PERIOD CPU Parameter3 1..15 *) (* This step period defines the maximum [slew] *) (* speed of the motor - max value < START_PERIOD. *) (* *) (* BIT_A CPU Parameter4 0 *) (* This bit determines whether 2 or 4 TPU channels*) (* Will be driven by TSM i.e. full/half step mode.*) (* *) (* START_PERIOD CPU Parameter4 1..15 *) (* This step period defines the start/stop speed *) (* of the motor - max value is $7FFF. *) (* *) (* PIN_SEQUENCE BOTH Parameter5 0..15 *) (* This parameter defines the sequence of channel *) (* pin changes that occur as a result of a step - *) (* - initialised by CPU, updated by TPU. *) (* *) (* HSQ1 HSQ0 Action *) (* ---- ---- ------ *) (* x 0 Acceleration table starts in slave1 PRAM. *) (* x 1 Acceleration table starts in slave1 PRAM and *) (* continues in Channel 14 PRAM. *) (* 0 x One rotate of PIN_SEQUENCE between channels. *) (* 1 x Two rotates of PIN_SEQUENCE between channels. *) (* *) (* hsr1 hsr0 Action *) (* ---- ---- ------ *) (* 0 1 Init, pin low. *) (* 1 0 Init, pin high. *) (* 1 1 Step Request. *) (* *) (* Links Accepted: NO Links Generated: NO *) (* *) (* Interrupts Generated After: INIT & CURRENT_POS = DESIRED_POS *) (* *) (*()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()*) (*+++++++++++++++++++++ PARAMETER MACROS +++++++++++++++++++++++++++*) %macro DESIRED_POS_TSM 'prm0'. %macro CURRENT_POS_TSM 'prm1'. %macro TAB_SIZE_TSM 'prm2'. %macro TAB_INDEX_TSM 'prm2'. %macro S_FLAG_TSM 'prm3'. %macro SLEW_PERIOD_TSM 'prm3'. %macro START_PERIOD_TSM 'prm4'. %macro BIT_A_TSM 'prm4'. %macro PIN_SEQUENCE_TSM 'prm5'. (*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*) (*====================================================================*) (*||||||||||||||||||||| MICROCODE STARTS BELOW |||||||||||||||||||||*) (*VVVVVVVVVVVVVVVVVVVVV--------------------------VVVVVVVVVVVVVVVVVVVVV*) (**********************************************************************) (* *) (* ENTRY name: INIT_LO_TSM *) (* *) (* STATE(S) ENTERED: S1 *) (* *) (* PRELOAD PARAMETER : None *) (* *) (* ENTER WHEN : HSR = %01 *) (* *) (* ACTION: Initialise channel with pin low. *) (* *) (**********************************************************************) %entry name = init_lo_tsm; start_address *; disable_match; cond hsr1 = 0, hsr0 = 1,lsr = x,m/tsr = x,pin = x,flag0 = x. INIT_LO_TSM: If true then goto got_there_tsm,flush; chan tbs:= out_m1_c1, pac := no_change, pin := low, disable_mtsr. (**********************************************************************) (* *) (* ENTRY name: INIT_HI_TSM *) (* *) (* STATE(S) ENTERED: S2 *) (* *) (* PRELOAD PARAMETER : None *) (* *) (* ENTER WHEN : HSR = %10 *) (* *) (* ACTION: Initialise channel with pin high. *) (* *) (**********************************************************************) %entry name = init_hi_tsm; start_address *; disable_match; cond hsr1 = 1, hsr0 = 0,lsr = x,m/tsr = x,pin = x,flag0 = x. INIT_HI_TSM: If true then goto got_there_tsm,flush; chan tbs:= out_m1_c1, pac := no_change, pin := high, disable_mtsr. (**********************************************************************) (* *) (* ENTRY name: MOVE_REQ_TSM *) (* *) (* STATE(S) ENTERED: S3 *) (* *) (* PRELOAD PARAMETER : DESIRED_POS *) (* *) (* ENTER WHEN : HSR = %11 *) (* *) (* ACTION: Initiate a move. *) (* *) (**********************************************************************) %entry name = move_req_tsm; start_address *; disable_match; cond hsr1 = 1, hsr0 = 1,lsr = x,m/tsr = x,pin = x,flag0 = x; ram p <- @DESIRED_POS_TSM. MOVE_REQ_TSM: If flag0 = 1 then goto End_of_link,flush; (* already stepping? *) chan enable_mtsr; chan set flag0. (* remember we are now *) au ert := tcr1; (* reference for 1st step match*) ram diob <- @CURRENT_POS_TSM. SETUP_DIR_TSM: au nil := p - diob,ccl. (* which direction ? *) If N = 1 then goto left_tsm,flush; chan clear flag1. (* left/anticlockwise *) If Z = 0 then goto right_tsm,flush; chan set flag1. (* right/clockwise *) GOT_THERE_TSM: chan clear flag0; (* negate stepping flag *) chan neg_mrl, neg_tdl, neg_lsl; chan cir; (* signal to CPU that move is complete*) end. (**********************************************************************) (* *) (* ENTRY name: STEP_TSM *) (* *) (* STATE(S) ENTERED: S3 *) (* *) (* PRELOAD PARAMETER : CURRENT_POS *) (* *) (* ENTER WHEN : m/tsr = 1 *) (* *) (* ACTION: . *) (* *) (**********************************************************************) %entry name = step_tsm; start_address *; disable_match; cond hsr1 = 0, hsr0 = 0,lsr = x,m/tsr = 1,pin = x,flag0 = x; ram p <- @CURRENT_POS_TSM. STEP_TSM: If flag1 = 1 then goto test_index_tsm. au diob := p + 1; (* update position for step *) ram diob -> @CURRENT_POS_TSM. (* - just completed *) au diob := p - 1; ram diob -> @CURRENT_POS_TSM. TEST_INDEX_TSM: ram p <- @TAB_INDEX_TSM. au nil := p_low,ccl; ram p <- @DESIRED_POS_TSM. (*if just finished deccelerating then*) If Z = 1 then goto setup_dir_tsm,flush. (* - go setup dir. flag *) TEST_DIR_TSM: au nil := p - diob,ccl. (* which way SHOULD we be going? *) If N = 1 then goto left_tsm,flush. If Z = 0 then goto right_tsm,flush. (* If D_P = C_P but we are *) (* not at start/stop rate *) If flag1 = 0 then goto left_tsm,flush. (* - then keep going *) RIGHT_TSM: If flag1 = 0 then goto deccel_tsm. (* if currently going left then deccelerate before going right*) au a := p; (* a = DESIRED_POS*) ram p <- @TAB_INDEX_TSM. au sr := p_low + diob + 1. (* sr = CURRENT_POS + TAB_INDEX +1*) (*--------------------------------------------------------------------------*) COMMON_TSM: au nil := sr - a,ccl; ram diob <-@SLEW_PERIOD_TSM. If Z = 1 then goto no_chnge_tsm,flush. (* more acceleration?*) If N = 0 then goto deccel_tsm,flush. (* time to deccelerate?*) au diob := p_high. (* more acceleration steps available?*) au nil := p_low - diob,ccl. (* TAB_INDEX - TAB_SIZE *) If Low_Same = 1 then goto calc_step_tsm. au p_low := p_low + 1; (* - yes so inc index *) ram p -> @TAB_INDEX_TSM. goto tst_sf_tsm,flush; (* - no so run at slew rate *) ram diob <- @SLEW_PERIOD_TSM. NO_CHNGE_TSM: au a :=>> diob,ccl. If C = 0 then goto calc_step_tsm,flush. goto set_ert_tsm,flush. (* if in slew_mode then dont lookup table*) DECCEL_TSM: au p_low := p_low - 1; (* dec acceleration index *) ram p -> @TAB_INDEX_TSM. (*--------------------------------------------------------------------------*) CALC_STEP_TSM: au p_low := p_low - 1,ccl; (* test for I = 0 or 1*) ram diob <- @START_PERIOD_TSM. If low_same = 1 then goto tst_slew_tsm. (*if I = 0 or 1 then just*) (* - use START_PER*) au a :=>> diob,ccl; (* correct start period *) ram diob <- @SLEW_PERIOD_TSM. (* & latch 2/4 chan select bit *) (* The following piece of code forms the address for obtaining the accel. *) (* parameter. If local mode is selected then all parameters are obtained *) (* from contiguous ram starting in the first slave channel. In local and *) (* remote mode, the table is split between the slave channels PRAM and the *) (* PRAM of channels 14,15,0. In two channel mode the first 12 parameters are*) (* obtained from slave 1 and the rest from chans 14->0. In four chan mode, *) (* the first 12 are obtained from slave1, the next 12 from slave 2,the next *) (* 12 from slave 3 and the rest from chans 14->0. *) (* In local and remote mode if channel 13 is the master then the slave *) (* resident parameters are obtained from chan 2 [+3 & 4 in four chan mode] *) (* - this is to allow chans 14->0 to be used for remote table parameters *) (* Enter with p_low = index, flag0 chan set, exit with diob [7:0] = param address *) (* Note that index = 1 for 1st table entry, not zero *) LOOK_UP_TSM: au diob := p_low + #$1F. (* 'A' *) If hsq0 = 0 then goto add_idx_tsm. (*local or local&remote*) au sr := chan_reg + #$F0. (* 'B', A+B = local mode addr *) If C = 0 then goto test_N_tsm. (* branch if 2 chan mode *) au nil := p_low + #$F3,ccl. (* is parameter one of first 12? *) If N = 1 then goto tst_chan14_tsm; (* - branch if yes *) chan clear flag0. (* temporarily use flag0=0 to indicate 4 chan mode *) au nil := p_low + #$E7,ccl. (* is parameter one of first 24? *) If N = 1 then goto tst_chan14_tsm. (* - branch if yes *) au diob := p_low + #$23. au nil := p_low + #$DB,ccl. (* is parameter one of first 36? *) au diob := p_low + #$27. TEST_N_TSM: If N = 1 then goto tst_chan14_tsm,flush. (* is parameter local? *) If flag0 = 1 then goto get_word_tsm. (* parameter in chan14/15/0 *) au diob := p_low + #$D3. (* form remote address in 2 chan mode *) goto get_word_tsm. au diob := p_low + #$BB. (* form remote address in 4 chan mode *) TST_CHAN14_TSM: au nil := chan_reg + #$30,ccl. (* is master channel 13? - *) If Z = 1 then goto get_word_tsm,flush. (* -yes get from chan2etc *) ADD_IDX_TSM: au diob := diob + sr. (* - no so get relative to current chan *) (* End of parameter address forming *) GET_WORD_TSM: au nil :=>> diob,ccl; (* do we want upper or lower param? *) ram p <- by_diob. (* get TWO acceleration parameters *) If C = 1 then goto per_mul_tsm; (* lsb=1 means upper param *) chan set flag0. (* restore stepping flag state *) au sr := p_high. au sr := p_low. PER_MUL_TSM: au p := a. (* a = [START_PER * ACC_PARAM]/256 = step period*) au dec := #$07. au a := 0; ram diob <- @SLEW_PERIOD_TSM. repeat; au a :=>> a + p,shift. (* fractional multiply *) TST_SLEW_TSM: au p :=>> diob. (* correct slew period *) au nil := a - p,ccl. (* use slew period ? *) If C = 0 then goto CLR_SF_TSM,flush. TST_SF_TSM: au a :=>> diob,ccl; (* correct slew period & latch flag*) ram p <- @TAB_INDEX_TSM. If C = 0 then goto SET_ERT_TSM. (* slewing already? *) au diob := a + a + 1; (* chan set slew flag *) ram diob -> @SLEW_PERIOD_TSM. goto SET_ERT_TSM. au p_low := p_low - 1; (* correct index if slewing *) ram p -> @TAB_INDEX_TSM. (* - but not on first slew step *) CLR_SF_TSM: au p :=<< p; (* clear slew flag *) ram p -> @SLEW_PERIOD_TSM. SET_ERT_TSM: au a := ert + a; (* get new match time ready *) ram diob <- @START_PERIOD_TSM. au sr :=>> diob,ccl. (* START_PERIOD must be > 0 *) au dec :=<< 1; ram p <- @PIN_SEQUENCE_TSM. If C = 0 then goto chan_tsm,flush. (* 2 or 4 channels? *) au dec :=<< dec. CHAN_TSM: If flag1 = 1 then goto set_pac_tsm. au diob :=R> p,ccl; (* rotate & store new pins*) ram diob -> @PIN_SEQUENCE_TSM. LR_TSM: au diob :=<< p,ccl; ram diob -> @PIN_SEQUENCE_TSM. If C = 0 then goto set_pac_tsm,flush. au diob := diob + 1; ram diob -> @PIN_SEQUENCE_TSM. SET_PAC_TSM: If N = 0 then goto write_ert_tsm; (* setup response for *) chan PAC := low. (* - next step match *) au dec := dec - 1,ccl. chan PAC := high. WRITE_ERT_TSM: au ert := a; (* schedule next step *) chan write_mer, neg_mrl, neg_tdl, neg_lsl. au chan_reg := chan_reg + #$10. (* move to next slave chan *) If Z = 1 then goto End_of_link,flush. (* more chans to go ? *) If hsq1 = 0 then goto set_pac_tsm. (* 1 or 2 rotates?*) au diob :=R> diob,ccl. goto set_pac_tsm. au diob :=R> diob,ccl. (*--------------------------------------------------------------------------*) LEFT_TSM: If flag1 = 1 then goto deccel_tsm. (* if currently going right then deccelerate before going left*) au sr := p + 1; (* sr = DESIRED_POS + 1*) ram p <- @TAB_INDEX_TSM. au a := p_low. goto common_tsm. au a := diob - a. (* a = CURRENT_POS - TAB_INDEX *) (**********************************************************************) (* UNUSED ENTRIES - execute appropriate termination *) (**********************************************************************) %entry name = dud_siop; start_address End_of_link; disable_match; cond hsr1 = 0, hsr0 = 0,lsr = 1,m/tsr = 0,pin = x,flag0 = x.