;-------------------------------------------------------- ; T H R E E S P O T ; ; S A C T R A C K S E Q U E N C E ;-------------------------------------------------------- ;Cannot exceed 1023 lines of instructions. ; SET 0.010 2 0 ;0.01 milliseconds per tick ;+/-10 volts ;0 degree offset; TABSZ 150000 ;set maximum table space ;DELAY command is based on the 100 microsecond clock ticks specified above ;TICKS command is based on the ADC sampling clock rate subject to num channels ;VAR V1 ;RE-USABLE variables for use only within mode subroutines ;VAR V2 ;these variables should not pass parameters between ;VAR V3 ;modes or subroutines ;VAR V4 ;VAR V5 ;VAR V6 ;VAR V7 ;VAR V8 ;VAR V9 ;VAR V10 ;VAR V11 ;VAR V12, ;VAR V13, ;VAR V14, ;VAR V15, ;VAR V16, ;VAR V17, VAR V18,TEMP2 ;Adapt routine VAR V19,TEMP1 ;MODE SUBROUTINE variable VAR V20,TEMP3 ;Accel Decel Adapt routines VAR V21,TEMP4 ;Accel Decel routines ;VAR V22, ;VAR V23, ;VAR V24, ;VAR V25, ;VAR V26, ;----------------------------------------------------------- ;above variables are zeroed every time a new mode is entered ;----------------------------------------------------------- ;VAR V27,ELAPSED=0 ;when OT testing began VAR V28,TIMECURR ;current SPIKE2 time VAR V29,TIMECHEK ;when to check if it is time to move ;VAR V30,TIMEFEED VAR V31,TEMPTRAK ;OT testing (convert to TABLE field?) VAR V32,TEMPWIND VAR V33,LEDBRD1 ;indicate which LED board (LEFT red) VAR V34,LEDADD1 ;indicate which LED light (LEFT red) VAR V35,LEDBRD2 ;indicate which LED board (CENTER red) VAR V36,LEDADD2 ;indicate which LED light (CENTER red) VAR V37,TRACKING ;is monkey tracking VAR V38,HITTYPE1 ;times all loc shown or step, non-adapt, etc shown VAR V39,HITTYPE2 ;times step-ramp, adapt shown VAR V40,ZERO=0 ;for many branching comparisons VAR V41,NAN=999999999 ;represents "not a number" VAR V42,SHUT1=1 ;primary shutter (normally open) VAR V43,SHUT2=0 ;secondary shutter (normally close) VAR V44,HE ;eye vertical position VAR V45,VE ;eye horizontal position VAR V46,LEDBRD3 ;indicate which LED board (RIGHT red) VAR V47,LEDADD3 ;indicate which LED light (RIGHT red) VAR V48,HT1 ;target-1 horizontal position VAR V49,VT1 ;target-1 vertical position VAR V50,HZERO ;H center pos with offset VAR V51,VZERO ;V center pos with offset VAR V52,DURCONT=0 ;contiguously on-target ;VAR V53,DURON=0 ;total time on-target VAR V54,PARAMCHG=0 ;signals parameters changed -- VAR V55,SUCCESS ;comlete the task? ;we test the Digitial Input so the following VAR is reserved ;VAR V56 ;Collision and Mayhem ;we have DAC 0,1,2,3 so the following VAR are reserved ;V57, last DAC 0 value ;won't work ;V58, last DAC 1 value ;with galvo ;V59, last DAC 2 value ;V60, last DAC 3 value ;we don't have DAC 4,5,6,7 so ok to use the following VAR VAR V61,TEMPTIME ;time counter variable VAR V62,ACTIVEOT=1 ;center spot VAR V63,SBUFFER=1 ;which serial buffer to use 1 or 2 (must start with 1) ;VAR V64,FORGIVE=0 ;forgiveness ;the data table transfered to the sequencer ;0000 - 0999 Common parameters ;[0] := gWindowHvgDAC%; HWIND ;[1] := gWindowVvgDAC%; VWIND ;[10] := pRealMinTime*1000; ASSOONAS ;[11] := pRealMaxTime*1000; NOLATER ;[12] := pRealContiguousTime*1000; CONTTON ;[13] := pRealTimeOn*1000; TOTALTON ;[14] := pOnFirst*1000; DURFIRST ;[15] := pOnSubsequent*1000; DURSUB ;[16] := pForgiveness*1000; FORGTIME ;[30] := gWhichBooth ;[31] := update report window info ;[32] := needed to convert a A/D signal to a D/A signal ;1000 - and above = for passing Table parmeters related to this behavioral mode ;-------------------------------------------------------- ; I N I T I A L I Z E L E D A R R A Y ;Initialize the LED array so buffer #1 will be active first. ;3/19/03 ;-------------------------------------------------------- DIGLOW [10101111] ;1-AF CLEAR all boards DELAY 12 ;13-120 microsecond delay DIGLOW [10111111] ;14-BF INTENSITY all boards DELAY 12 ;27-120 microsecond delay CALL BRITE TICKS TIMECURR ;set this up just so the IDLE routine will get started TICKS TIMECHEK,msTick(1) ;1ms, 0.001s later CRATE HZ(0) ;stop the ch 0 sinewave if it is running DRATE HZ(0) ;stop the ch 1 sinewave if it is running DIGOUT [....1...] ;low de-activates the SONALERT MOVI SHUT1,1 ;open the primary shutter MOVI SHUT2,0 ;close the secondary shutter CALL SHUTTER ;-------------------------------------------------------- ; T H R E E ;Moves the target on up to 8 vectors defined by the user. ; ;Implemented: ; Fixed Step Relative to Target - backstep specified in deg or % ; Fixed Step Relative to Eye - backstep specified in deg or % ; ;Re-usable Variables: ; V1 = table data address pointer ; V2 = table data holder ; V3 = RTZ status (-1=random, 0=last position was zero, 1=last position was not zero) ; V4 = current X DAC value ; V5 = current Y DAC value ; V6 = next initial X DAC value ; V7 = next initial Y DAC value ; V8 = next adapt X DAC value ; V9 = next adapt Y DAC value ; V10 = copy of V17 ; V11 = unused ; V12 = computation ; V13 = unused ; V14 = unused ; V15 = unused ; V16 = random initial step pointer ; V17 = random vector pointer ; ; TEMPTIME = countdown timer variable ; HITTYPE1 = how many times the adapt step has been presented ; HITTYPE2 = how many times the non-adapt step has been presented ; ;On Target parameter stored in TABLE, ZERO=0000 ; ZERO+200 = one degree on X axis ; ZERO+201 = one degree on Y axis ; ZERO+202 = largest of one degree on X & Y ; ZERO+203 = half degree of largest ; ZERO+204 = X ; ZERO+205 = Y ; ZERO+206 = negative largest of one degree on X & Y ; ZERO+207 = negative half largest of one degree on X & Y ; ZERO+208 = BRD ; ZERO+209 = ADD ; ZERO+210 = spot (left=0 center=1 right=2) ; ZERO+211 = ; ZERO+212 = ; ZERO+213 = ; ZERO+214 = ; ZERO+215 = stim_1 duration ; ZERO+216 = stim_2 duration ; ZERO+217 = ; ZERO+218 = ; ZERO+219 = ; ZERO+220 = X 16-bit left current spot value ; ZERO+221 = X 16-bit center current spot value ; ZERO+222 = X 16-bit right current spot value ; ZERO+223 = ; ZERO+224 = ; ZERO+225 = Y 16-bit left current spot value ; ZERO+226 = Y 16-bit center current spot value ; ZERO+227 = Y 16-bit right current spot value ; ZERO+228 = ; ZERO+229 = ; ZERO+230 = X 32-bit left current spot value ; ZERO+231 = X 32-bit center current spot value ; ZERO+232 = X 32-bit right current spot value ; ZERO+233 = ; ZERO+234 = ; ZERO+235 = Y 32-bit left current spot value ; ZERO+236 = Y 32-bit center current spot value ; ZERO+237 = Y 32-bit right current spot value ; ZERO+238 = ; ZERO+239 = ; ZERO+240 = X 32-bit separation value ; ZERO+241 = Y 32-bit separation value ; ZERO+242 = ; ZERO+242 = ; ZERO+243 = ; ZERO+244 = ; ZERO+245 = X 16- ; ZERO+246 = ; ZERO+247 = ; ZERO+248 = ; ZERO+249 = ; ;Table Data Map: ; 1000 = Adapt paradigm ; ;Adapt paradigm info stored in TABLE, A=1000 ; A+0 = Type of adapt: 0=RelTarg, 1=RelEye, 2=ProEye ; A+1 = ; A+2 = Gap duration ; A+3 = Onset Velocity Threshold ; A+4 = Offset Velocity Threshold ; A+5 = Blanking Duration ; A+6 = ; A+7 = Beginning of adapt time window ; A+8 = End of adapt time window ; A+9 = ; A+10= Horizontal offset ; A+11= Vertical offset ; A+12= Stimulation/NoStimulation ratio ; A+13= Horz DAC start at point ; A+14= Vert DAC start at point ; A+15= ; A+16= ; A+17= ; A+18= ; A+19= ; A+20-29 INITIAL STEPS on vector 0 in X DAC units ; A+30-39 INITIAL STEPS on vector 1 in X DAC units ; A+40-49 INITIAL STEPS on vector 2 in X DAC units ; A+50-59 INITIAL STEPS on vector 3 in X DAC units ; A+60-69 INITIAL STEPS on vector 4 in X DAC units ; A+70-79 INITIAL STEPS on vector 5 in X DAC units ; A+80-89 INITIAL STEPS on vector 6 in X DAC units ; A+90-99 INITIAL STEPS on vector 7 in X DAC units ; A+100-109 INITIAL STEPS on vector 0 in Y DAC units ; A+110-119 INITIAL STEPS on vector 1 in Y DAC units ; A+120-129 INITIAL STEPS on vector 2 in Y DAC units ; A+130-139 INITIAL STEPS on vector 3 in Y DAC units ; A+140-149 INITIAL STEPS on vector 4 in Y DAC units ; A+150-159 INITIAL STEPS on vector 5 in Y DAC units ; A+160-169 INITIAL STEPS on vector 6 in Y DAC units ; A+170-179 INITIAL STEPS on vector 7 in Y DAC units ; ; A+180-189 ADAPT STEPS on vector 0 in X DAC units ; A+190-199 ADAPT STEPS on vector 1 in X DAC units ; A+200-209 ADAPT STEPS on vector 2 in X DAC units ; A+210-219 ADAPT STEPS on vector 3 in X DAC units ; A+220-229 ADAPT STEPS on vector 4 in X DAC units ; A+230-239 ADAPT STEPS on vector 5 in X DAC units ; A+240-249 ADAPT STEPS on vector 6 in X DAC units ; A+250-259 ADAPT STEPS on vector 7 in X DAC units ; A+260-269 ADAPT STEPS on vector 0 in Y DAC units ; A+270-279 ADAPT STEPS on vector 1 in Y DAC units ; A+280-289 ADAPT STEPS on vector 2 in Y DAC units ; A+290-299 ADAPT STEPS on vector 3 in Y DAC units ; A+300-309 ADAPT STEPS on vector 4 in Y DAC units ; A+310-319 ADAPT STEPS on vector 5 in Y DAC units ; A+320-329 ADAPT STEPS on vector 6 in Y DAC units ; A+330-339 ADAPT STEPS on vector 7 in Y DAC units ; ; This has very little use since it has the address ; for the axes and not the axis the target is on. Because ; the sequencer moves the target in an XY fashion it ; doesn't know which axis the target is on. ; A+340-349 LED board addresses ; ; A+350-359 Axis Slopes ; A+360-369 PERPENDICULAR Axis Slopes ; A+370-379 EXCURSION LIMIT in X DAC units ; A+380-389 EXCURSION LIMIT in Y DAC units ; A+390-399 X value for 1 deg step (for LED computation) ; A+400-409 Y value for 1 deg step (for LED computation) ; A+410-419 DEADZONE LIMIT in X DAC units ; A+420-429 DEADZONE LIMIT in Y DAC units ; ; A+450-459 step stimulation durations ; A+460-469 velocity stimulation durations ; ;Randomly chosen steps: ; A+500 Initial Step Size X ; A+501 Initial Step Size Y ; A+502 Adapt Step Size X ; A+503 Adapt Step Size Y ; A+504 Axis slope ; A+505 Axis perpendicular slope ; A+506 Axis Limit X ; A+507 Axis Limit Y ; ;1/1/03 ;-------------------------------------------------------- THREE: MARK 40 ;"{" BEQ PARAMCHG,0,THREE ;wait for parameters to arrive BEQ PARAMCHG,2,THREE1 ;skip if not the first time through ;first time only ;--------------- MARK 63 ;"?" CALL ZEROVAR ;clear all the re-usable VAR MOVI V1,1000 ;data pointer MOVI PARAMCHG,2 ;new parameters grabbed MOVI DURCONT,0 ;reset accumulators MOVI V2,1 ;so it will update report first time through TABST V2,[ZERO+31] MOVI HITTYPE1,0 ;reset the non-adapt counter MOVI HITTYPE2,0 ;reset the adapt counter ;values necessary for DAC2LED conversion TABLD V2,[V1+390] ;get the one degree X DAC value TABST V2,[ZERO+200] ;store the one degree X DAC value TABLD V2,[V1+400] ;get the one degree Y DAC value TABST V2,[ZERO+201] ;store the one degree Y DAC value ;user offset is the basis for all future calculations TABLD HZERO,[V1+10] ;get X offset TABLD VZERO,[V1+11] ;get Y offset ADDI HZERO,0 ;add offset + center spot X location ADDI VZERO,0 ;add offset + center spot Y location CALL CALCSHW ;calc all target values based derived on the center position MOVI ACTIVEOT,1 ;center is the LED of interest MARK ACTIVEOT ;main part of routine ;-------------------- THREE1: MARK 4 BEQ PARAMCHG,1,THREE ;check if the user choices have changed ;;;JUMP THREE1 CALL GETPOS ;get current eye position; HE,VE CALL TXPOS ;transpose the eye on the target vector MOV V14,V4 ;store a pre-saccade HE position MOV V15,V5 ;store a pre-saccade VE position THREE2: CALL ACCEL BEQ SUCCESS,0,THREE2 ;stay here until monkey moves MARK 62 ;"" rt arrow (can't type the char, sequencer uses it) THREE3: NOP CALL DECEL ;detect deceleration BEQ SUCCESS,0,THREE3 ;stay here until monkey stops MARK 60 ;"<" lf arrow ;is he on a target? ;------------------ TABLD HT1,[ZERO+220] ;left X 16-bit TABLD VT1,[ZERO+225] ;left Y 16-bit CALL OTTEST BLT TRACKING,2,THREEA ;on left target MOVI ACTIVEOT,0 ;LED of interest MARK 0 JUMP THREE22 THREEA: TABLD HT1,[ZERO+221] ;center X 16-bit TABLD VT1,[ZERO+226] ;center Y 16-bit CALL OTTEST BLT TRACKING,2,THREEB ;on center target MOVI ACTIVEOT,1 ;LED of interest MARK 1 JUMP THREE22 THREEB: TABLD HT1,[ZERO+222] ;right X 16-bit TABLD VT1,[ZERO+227] ;right Y 16-bit CALL OTTEST BLT TRACKING,2,THREE1 ;continue until he is OT on any LED MOVI ACTIVEOT,2 ;LED of interest MARK 2 JUMP THREE22 ;is saccade too big or too small? ;-------------------------------- THREE22: CALL GETPOS ;get current eye position; HE,VE CALL TXPOS ;transpose the eye on the target vector MOV V16,V4 ;store a post-saccade HE position MOV V17,V5 ;store a post-saccade VE position ;get abs(delta X) MOV TEMP2,V14 ;pre-saccade X SUB TEMP2,V16 ;post-saccade X BGE TEMP2,ZERO,THREE24 ;br if positive MULI TEMP2,-1 ;abs ;get abs(delta Y) THREE24: MOV TEMP3,V15 ;pre-saccade Y SUB TEMP3,V17 ;post-saccade Y BGE TEMP3,ZERO,THREE25 ;br if positive MULI TEMP3,-1 ;abs ;which bigger, delta X or delta Y? THREE25: BLT TEMP2,TEMP3,THREE26 ;br if X LT Y MOV TEMP4,TEMP2 ;X is bigger JUMP THREE27 THREE26: MOV TEMP4,TEMP3 ;Y is bigger THREE27: TABLD TEMP1,[ZERO+32] ;32-to-16 bit conversion factor MUL TEMP4,TEMP1 ;16-to-32 bit conversion MARK 5 ;saccade an acceptable size? BLT TEMP4,[V1+16],THREE1 ;continue until saccade is big enough MARK 6 BGT TEMP4,[V1+17],THREE1 ;continue until saccade is small enough MARK 7 ;he made a good saccade so reward him ;------------------------------------ CALL FEED ;;;JUMP THREE1 ;;;TEMPORARY ;+proportional step relative to eye+ ;----------------------------------- ADAPT32: MULI V14,-1 ;invert pre-step eye position MULI V15,-1 CALL GETPOS ;get current eye position ADD V14,HE ;add it to current eye position for saccade size ADD V15,VE ;test if saccade is neg or pos dir MOVI TEMP4,1 ;1=use X 0=use Y to judge for + or - dir movement BNE TEMP4,[V1+18],ADAPT40 BGT TEMP2,ZERO,ADAPT33 ;deltaX is positive JUMP ADAPT34 ;deltaX is negative ADAPT40: BGT TEMP3,ZERO,ADAPT33 ;deltaY is positive JUMP ADAPT34 ;deltaY is negative ;pos saccade ADAPT33: TABLD V6,[V1+180] ;get adapt step X %-value TABLD V7,[V1+260] ;get adapt step Y %-value JUMP ADAPT35 ;neg saccade ADAPT34: TABLD V6,[V1+220] ;get adapt step X %-value TABLD V7,[V1+300] ;get adapt step Y %-value JUMP ADAPT35 ADAPT35: MUL V14,V6 MUL V15,V7 MOVI TEMP1,100 ;load constant to div by DIV V14,TEMP1 DIV V15,TEMP1 TABLD TEMP1,[ZERO+32] MUL V14,TEMP1 ;scale 16-bit A/D sig to the 32-bit D/A sig MUL V15,TEMP1 ;scale 16-bit A/D sig to the 32-bit D/A sig MOV V6,V14 ;copy adapt step computed with percent MOV V7,V15 ;prepare to move the targets ADD HZERO,V6 ;offset center X pos by adaptive amount ADD VZERO,V7 ;offset center Y pos by adaptive amount CALL CALCSHW ;comes back with spots at adaptive location or zero if it moved out of bounds ADDI HITTYPE2,-1 ;undo default non-adapt increment ADDI HITTYPE1,1 ;inc adapt step counter JUMP THREE1 ;display this new position for awhile ;-------------------------------------------------------- ; C A L C S H W ;Calculate all the values needed for each trial. To do ;this, CALCSHW needs to know: ;current 32-bit XY DAC position of the center spot ; HZERO center + offset ; VZERO center + offset ;current 32-bit XY DAC user offset in HOFF and VOFF ; ; ZERO+220 = X 16-bit left current spot value ; ZERO+221 = X 16-bit center current spot value ; ZERO+222 = X 16-bit right current spot value ; ZERO+223 = ; ZERO+224 = ; ZERO+225 = Y 16-bit left current spot value ; ZERO+226 = Y 16-bit center current spot value ; ZERO+227 = Y 16-bit right current spot value ; ZERO+228 = ; ZERO+229 = ; ZERO+230 = X 32-bit left current spot value ; ZERO+231 = X 32-bit center current spot value ; ZERO+232 = X 32-bit right current spot value ; ZERO+233 = ; ZERO+234 = ; ZERO+235 = Y 32-bit left current spot value ; ZERO+236 = Y 32-bit center current spot value ; ZERO+237 = Y 32-bit right current spot value ; ZERO+238 = ; ZERO+239 = ; ZERO+240 = X 32-bit separation value ; ZERO+241 = Y 32-bit separation value ; ZERO+242 = ; ;5/22/076 ;-------------------------------------------------------- CALCSHW: NOP TABLD TEMP1,[ZERO+32] ;32-to-16 bit conversion factor ;address the LEFT spot TABLD V4,[V1+60] ;LH spot X TABLD V5,[V1+140] ;LH spot Y ADD V4,HZERO ;add the H center offset ADD V5,VZERO ;add the V center offset TABST V4,[ZERO+230] ;load 32-bit X TABST V5,[ZERO+235] ;load 32-bit Y TABST V4,[ZERO+204] ;load X for LED presentation TABST V5,[ZERO+205] ;load Y for LED presentation DIV V4,TEMP1 ;convert from 32-to-16 bit value DIV V5,TEMP1 ;convert from 32-to-16 bit value TABST V4,[ZERO+220] ;load 16-bit X TABST V5,[ZERO+225] ;load 16-bit Y MOVI V2,0 ;0=left TABST V2,[ZERO+210] ;load left CALL DAC2LED ;convert DAC to LED (LEDADD1 LEDBRD1) ;test if initial X is within limit ;--------------------------------- BLE ZERO,[V1+370],TEST1 ;is limit negative or positive? BLT V4,[V1+370],TEST4 ;neg limit, test if position is smaller JUMP TEST2 TEST1: BGT V4,[V1+370],TEST4 ;pos limit, test if position is larger ;test if initial Y is within limit ;--------------------------------- TEST2: BLE ZERO,[V1+380],TEST3 ;is limit negative or positive? BLT V5,[V1+380],TEST4 ;neg limit, test if position is smaller JUMP CALCSHW1 TEST3: BGT V5,[V1+380],TEST4 ;pos limit, test if position is larger JUMP CALCSHW1 ;left spot within limits ;user offset is the basis for all future calculations TEST4: TABLD HZERO,[V1+10] ;get X offset TABLD VZERO,[V1+11] ;get Y offset ADDI HZERO,0 ;add offset + center spot X location ADDI VZERO,0 ;add offset + center spot Y location JUMP CALCSHW ;try again ;address the CENTER spot CALCSHW1: ADD V4,HZERO ;add the H center offset ADD V5,VZERO ;add the V center offset TABST V4,[ZERO+231] ;load 32-bit X TABST V5,[ZERO+236] ;load 32-bit Y TABST V4,[ZERO+204] ;load X for LED presentation TABST V5,[ZERO+205] ;load Y for LED presentation DIV V4,TEMP1 ;convert from 32-to-16 bit value DIV V5,TEMP1 ;convert from 32-to-16 bit value TABST V4,[ZERO+221] ;load 32-bit X TABST V5,[ZERO+226] ;load 32-bit Y MOVI V2,1 ;1=center TABST V2,[ZERO+210] ;load center CALL DAC2LED ;convert DAC to LED (LEDADD2 LEDBRD2) ;address the RIGHT spot TABLD V4,[V1+20] ;RH spot X TABLD V5,[V1+100] ;RH spot Y ADD V4,HZERO ;add the H center offset ADD V5,VZERO ;add the V center offset TABST V4,[ZERO+232] ;load 32-bit X TABST V5,[ZERO+237] ;load 32-bit Y TABST V4,[ZERO+204] ;load X for LED presentation TABST V5,[ZERO+205] ;load Y for LED presentation DIV V4,TEMP1 ;convert from 32-to-16 bit value DIV V5,TEMP1 ;convert from 32-to-16 bit value TABST V4,[ZERO+222] ;load 16-bit X TABST V5,[ZERO+227] ;load 16-bit Y MOVI V2,2 ;2=right TABST V2,[ZERO+210] ;load right CALL DAC2LED ;convert DAC to LED (LEDADD3 LEDBRD3) ;test if initial X is within limit ;--------------------------------- BLE ZERO,[V1+370],TEST6 ;is limit negative or positive? BLT V4,[V1+370],TEST9 ;neg limit, test if position is smaller JUMP TEST7 TEST6: BGT V4,[V1+370],TEST9 ;pos limit, test if position is larger ;test if initial Y is within limit ;--------------------------------- TEST7: BLE ZERO,[V1+380],TEST8 ;is limit negative or positive? BLT V5,[V1+380],TEST9 ;neg limit, test if position is smaller JUMP CALCSHW1 TEST8: BGT V5,[V1+380],TEST9 ;pos limit, test if position is larger JUMP CALCSHW2 ;right spot within limits ;user offset is the basis for all future calculations TEST9: TABLD HZERO,[V1+10] ;get X offset TABLD VZERO,[V1+11] ;get Y offset ADDI HZERO,0 ;add offset + center spot X location ADDI VZERO,0 ;add offset + center spot Y location JUMP CALCSHW ;try again ;activate the RED LEDs CALCSHW2: MOVI SHUT1,1 MOVI SHUT2,0 CALL SHUTTER CALL LEDS ;display the 3 LEDs DAC 2,[ZERO+231] ;show where the center location is DAC 3,[ZERO+236] ;show where the center location is BNE ACTIVEOT,0,CALCSHW5 ;left DAC 0,[ZERO+230] ;make center be the last location DAC 1,[ZERO+235] ;make center be the last location JUMP CALCSHW9 CALCSHW5: BNE ACTIVEOT,1,CALCSHW6 ;center DAC 0,[ZERO+231] ;make center be the last location DAC 1,[ZERO+236] ;make center be the last location JUMP CALCSHW9 CALCSHW6: BNE ACTIVEOT,2,CALCSHW9 ;right DAC 0,[ZERO+232] ;make center be the last location DAC 1,[ZERO+237] ;make center be the last location JUMP CALCSHW9 CALCSHW9: RETURN ;-------------------------------------------------------- ; G E T P O S ;Load the eye and target positions for processing by ;script routine TimeToMoveOrFeed. ;10/1/03 ;-------------------------------------------------------- GETPOS: CHAN HE,2 ;1-read the current H eye CHAN VE,3 ;2-read the current V eye ;CHAN HT1,4 ;3-read the current H primary target ;CHAN VT1,5 ;4-read the current V primary target ;CHAN HT2,8 ;5-read the current H secondary target ;CHAN VT2,9 ;6-read the current V secondary target RETURN ;7- ;-------------------------------------------------------- ; T X P O S ; Transpose the current eye position to the current vector. ; Horz & vert get treated directly, all others are computed. ;7/11/06 ;-------------------------------------------------------- TXPOS: NOP ;get m2, slope of the line perpendicular to the target vector TABLD TEMP1,[V1+505] ;get m2 ;TABLD V62,[V1+505] ;TESTING, report value to Spike2 BNE TEMP1,NAN,TXPOS1 ;BR if target not 0 or 180 vector MOV V4,HE MOVI V5,0 ;V is zero for theta = 0 or 180 ;MARK 4 JUMP TXPOS2 ;get m1, the vector line slope TXPOS1: NOP TABLD TEMP2,[V1+504] ;get m1 BNE TEMP2,NAN,TXPOS3 ;BR if target not 90 or 270 vector MOVI V4,0 ;H is zero for theta = 90 or 270 MOV V5,VE ;MARK 5 JUMP TXPOS2 ;DISPOSABLE ; temp1 ;RESULTS ; m2 = temp4 ; b2 = temp3 ; b2 = V16 ;compute b2, y-intercept of the perpendicular line (b=y-mx y=mx+b) TXPOS3: NOP ;MARK 6 ;slope still in form of 1xx where xx/100=slope ; 7/12/06 0.1 slope resolution is currently disabled by dividing slopes right away ; 10/12/06 0.1 slope activated again ; 10/18/06 0.01 slope resolution now used MOVI V2,100 ;load the constant value of 100 ; 10/18/06 The *100 slope resolution divides itself away, see notes in folder MOV TEMP4,TEMP1 ;make a copy of m2 MUL TEMP1,HE ;temp1 = m2 * X MOV TEMP3,VE ;temp3 <- VE MUL TEMP3,V2 ;temp3 = temp3 * 10 to match slope which is *10 SUB TEMP3,TEMP1 ;b2 = y-mx ;DISPOSABLE ; temp2 ;RESULTS ; m1 = V12 ; x3 = temp3 ; y3 = V16 ;compute X point on vector adjusted for eye position MOV V16,TEMP3 ;make a copy of b2 MOV V12,TEMP2 ;make a copy of m1 SUB TEMP2,TEMP4 ;= m1-m2 DIV TEMP3,TEMP2 ;x3 = b2/(m1-m2) MOV V4,TEMP3 ;adjusted HE <- x3 ;compute Y point on vector adjusted for eye position DIV V16,V2 ;b2/10 MULI V16,-1 ;negate b2 MUL V16,V12 ;multi by m1 SUB TEMP4,V12 ;m2-m1 DIV V16,TEMP4 ;y3 = /m2 MOV V5,V16 ;adjusted VE <- y3 TXPOS2: RETURN ;-------------------------------------------------------- ; O T T E S T ;Tests if the animal is on-target horizontally and ;vertically and reports the result. Requires 0.26ms or less. ; ;Sequence Variable Map: ; TEMPWIND = window size ; TEMPTRAK = target position ; TRACKING = 0, 1 or 2 depending if monkey is OT or not ; V2 = holds data from table ; ;On Target parameter stored in TABLE, ZERO=0000 ; ZERO+0 = gWindowHvgDAC%; HWIND ; ZERO+1 = gWindowVvgDAC%; VWIND ; ZERO+17= pForceOT%; 'override, make him OT at all times ; ;10/7/04 ;-------------------------------------------------------- OTTEST: MOVI TRACKING,0 ;1-initialize ;CHAN HE,2 ;1-read the current H eye ;CHAN VE,3 ;2-read the current V eye CALL GETPOS TABLD TEMPWIND,[ZERO] ;9-HWIND MOV TEMPTRAK,HT1 ;10-load horizontal target SUB TEMPTRAK,HE ;11-subtract horizonal eye BGT TEMPTRAK,0,OTTEST1 ;12-test if result is negative MULI TEMPTRAK,-1 ;13-abs() OTTEST1: BGT TEMPTRAK,TEMPWIND,OTTEST2 ;14-test if monkey is H-OT ADDI TRACKING,1 ;15-horizontally on-target OTTEST2: TABLD TEMPWIND,[ZERO+1] ;16-VWIND MOV TEMPTRAK,VT1 ;17-load vertical target SUB TEMPTRAK,VE ;18-subtract vertical eye BGT TEMPTRAK,0,OTTEST3 ;19-test if result is negative MULI TEMPTRAK,-1 ;20-abs() OTTEST3: BGT TEMPTRAK,TEMPWIND,OTTEST4 ;21-test if monkey is V-OT ADDI TRACKING,1 ;22-vertically on-target OTTEST4: TABLD V2,[ZERO+17] ;23-test if using OT override BEQ V2,0,OTTEST5 ;24-do it the old fashioned way, earn it! MOVI TRACKING,2 ;25-force him to be on-target, cheater! OTTEST5: RETURN ;26- ;-------------------------------------------------------- ; A C C E L ; ;Test when exceeds a specified eye velocity. ; ;I n p u t V a r ; THRESH2 = threshold velocity to come down to (in DAC bits) ;C o m p u t a t i o n V a r ; TEMPTIME = count down to zero ; TEMP3 = process H velocity (ch6) ; TEMP4 = process V velocity (ch7) ;O u t p u t V a r ; SUCCESS = -1:negative thresh 0:failed +1:positive thresh ; ;1/22/04 ;-------------------------------------------------------- ACCEL: MOVI TEMPTIME,1000 ;millisecond ticks ACCEL1: CHAN TEMP3,6 ;1-read the current analog velocity signal CHAN TEMP4,7 ;2-read the curennt analog velocity signal BGT TEMP3,[V1+3],ACCEL2 ;3-positive horizontal movement BGT TEMP4,[V1+3],ACCEL2 ;4-positive vertical movement MULI TEMP3,-1 ;5-invert to test negative direction MULI TEMP4,-1 ;6-invert to test negative direction BGT TEMP3,[V1+3],ACCEL3 ;7-negative direction movement BGT TEMP4,[V1+3],ACCEL3 ;8-negative direction movement DELAY 90 ;9-consume remaining millisecond DBNZ TEMPTIME,ACCEL1 ;10-test until period is over MOVI SUCCESS,0 ;unsuccessful trial RETURN ACCEL2: MOVI SUCCESS,1 ;successful positive direction trial JUMP ACCEL4 ;detect the end of the movement ACCEL3: MOVI SUCCESS,-1 ;successful negative direction trial JUMP ACCEL4 ;detect the end of the movement ACCEL4: RETURN ;-------------------------------------------------------- ; D E C E L ; ;Test when monkey slows to a specified eye velocity. ; ;I n p u t V a r ; THRESH2 = threshold velocity to come down to (in DAC bits) ;C o m p u t a t i o n V a r ; TEMPTIME = count down to zero ; TEMP3 = process H velocity (ch6) ; TEMP4 = process V velocity (ch7) ;O u t p u t V a r ; SUCCESS = 0:didn't stop in time +1:came to a stop ; ;1/22/04 ;---------------------------------------------- DECEL: MOVI TEMPTIME,1000 ;monkey's moved, now find the end of the movement DECEL1: CHAN TEMP3,6 ;1-read the current analog velocity signal CHAN TEMP4,7 ;2-read the curennt analog velocity signal BGT TEMP3,[V1+4],DECEL2 ;3-positive horizontal movement BGT TEMP4,[V1+4],DECEL2 ;4-positive vertical movement MULI TEMP3,-1 ;5-invert to test negative direction MULI TEMP4,-1 ;6-invert to test negative direction BGT TEMP3,[V1+4],DECEL2 ;7-negative direction movement BGT TEMP4,[V1+4],DECEL2 ;8-negative direction movement JUMP DECEL3 ;9-all channels are below threshold ;Since there are four velocity tests and any one of them can branch ;the program this timing scheme can be off by 0.0003 seconds DECEL2: DELAY 89 ;10-consume remaining millisecond DBNZ TEMPTIME,DECEL1 ;11-test until period is over MOVI SUCCESS,0 ;UNsuccessful trial, eyes never came to a stop RETURN DECEL3: MOVI SUCCESS,1 ;successful trial, report which direction monkey moved RETURN ;-------------------------------------------------------- ; S H U T T E R ;Sets the shutters open or closed. ;12/17/02 ;-------------------------------------------------------- SHUTTER: CALL SHUTTER1 ;set the primary shutter CALL SHUTTER2 ;set the secondary shutter RETURN ;-------------------------------------------------------- ; S H U T T E R 1 ;Sets primary shutter open or closed. ; 0 = HIGH OUTPUT ; 1 = LOW OUTPUT ;9/4/03 ;-------------------------------------------------------- SHUTTER1: TABLD V2,[ZERO+30] BEQ V2,0,SHUT1ROB ;Robinson convention is opposite of the Fuchs convention ;BEQ V2,3,SHUT1ROB ;Visual convention is opposite of the Fuchs convention ;0=ROB,1=OKN,2=LED,3=VIS ;Fuchs shutters BEQ SHUT1,1,OPENF DIGOUT [.......1] ;close the primary shutter MARK 70 ;"F" for "OFF" RETURN OPENF: DIGOUT [.......0] ;open the primary shutter MARK 78 ;"N" for "ON" RETURN ;Robinson shutters SHUT1ROB: BEQ SHUT1,1,OPENR DIGOUT [.......0] ;close the primary shutter MARK 70 ;"F" for "OFF" RETURN OPENR: DIGOUT [.......1] ;open the primary shutter MARK 78 ;"N" for "ON" RETURN ;-------------------------------------------------------- ; S H U T T E R 2 ;Sets secondary shutter open or closed. ; 0 = HIGH OUTPUT ; 1 = LOW OUTPUT ;9/4/03 ;-------------------------------------------------------- SHUTTER2: BEQ SHUT2,1,S2OPEN DIGOUT [......0.] ;close the secondary shutter MARK 102 ;"f" for "off" RETURN S2OPEN: DIGOUT [......1.] ;open the secondary shutter MARK 110 ;"n" for "on" RETURN ;-------------------------------------------------------- ; F E E D ;Sends a feeder pulse. ;10/12/04 ;-------------------------------------------------------- FEED: DIGOUT [.....1..] ;1-high triggers the feeder DELAY 100 ;101-1 ms pulse width DIGOUT [.....0..] ;102-low is the feeder off state MARK 64 ;@ RETURN ;103- ;-------------------------------------------------------- ; DAC2LED ;this algorithm determines what LED board and address ;correspond to a pair of DAC X & Y coordinates. ;There are more sophisticated approaches, but it would ;be challenging to use them with adaptation which can ;change axes and confuse the LED board assignment. ;looks like it will take about half a millisecond ;to do the conversion for red and again for green ;Re-usable Variables: ; V1 = table data address pointer ; V2 = table data holder ; V24 = computations ; V25 = X ; V26 = Y ; V23 = computations ;On Target parameter stored in TABLE, ZERO=0000 ; ZERO+200 = (IN ) one degree on X axis ; ZERO+201 = (IN ) one degree on Y axis ; ZERO+202 = (computed) largest of one degree on X & Y ; ZERO+203 = (computed) half degree of largest ; ZERO+204 = (IN ) X target DAC values ; ZERO+205 = (IN ) Y target DAC values ; ZERO+206 = (computed) negative largest of one degree on X & Y ; ZERO+207 = (computed) negative half largest of one degree on X & Y ; ZERO+208 = (computed) BRD ; ZERO+209 = (computed) ADD ; ZERO+210 = (IN ) which spot (left=0 center=1 right=2) ;Non-reuseable Variables: ; LEDBRD1 = (OUT ) indicate which LED board (RED) ; LEDADD1 = (OUT ) indicate which LED light (RED) ; LEDBRD2 = (OUT ) indicate which LED board (GRN) ; LEDADD2 = (OUT ) indicate which LED light (GRN) ;calling program must provide the DAC value for 1 degree on ;the current axes. This scheme only works because with 8 ;directions separated by 45 degrees the largest value always ;works (horz, vert and diagonals). ;1/25/05 ;-------------------------------------------------------- DAC2LED: TABLD V2,[ZERO+200] ;get X DAC degree BGT V2,ZERO,DAC2LEDD ;branch if positive MULI V2,-1 ;make positive DAC2LEDD: TABST V2,[ZERO+202] ;assume it is the largest TABLD V2,[ZERO+201] ;get Y DAC degree BGT V2,ZERO,DAC2LEDE ;branch if positive MULI V2,-1 ;make positive DAC2LEDE: BLE V2,[ZERO+202],DAC2LED1 ;test if it is larger TABST V2,[ZERO+202] ;store this as the largest ;MARK 86 ;"V" DAC2LED1: TABLD V2,[ZERO+202] ;get largest one DAC degree MULI V2,-1 TABST V2,[ZERO+206] ;store negative form of MOVI V23,2 DIV V2,V23 ;compute the size of a half degree TABST V2,[ZERO+207] ;store negative half degree MULI V2,-1 TABST V2,[ZERO+203] ;store positive of a half degree TABLD V25,[ZERO+204] ;load the target X value TABLD V26,[ZERO+205] ;load the target Y value ;test if center, special case since 0,0 is on theta 0 only ;--------------------------------------------------------- BLT V25,[ZERO+206],DAC2LED2 ;x lt -half ? BGT V25,[ZERO+203],DAC2LED2 ;x gt half ? BLT V26,[ZERO+206],DAC2LED2 ;y lt -half ? BGT V26,[ZERO+203],DAC2LED2 ;y lt half ? TABST ZERO,[ZERO+208] ;BRD=0 TABST ZERO,[ZERO+209] ;ADD=0 ;MARK 90 ;"Z" JUMP DAC2LEDC ;test if theta is on the vertical axis ;---------------- DAC2LED2: BGT V25,[ZERO+203],DAC2LED4 ;x gt half ? BLT V25,[ZERO+206],DAC2LED4 ;x lt -half ? ;theta = 90/270 ;-------------------------- MOV V23,V26 TABLD V24,[ZERO+202] DIV V23,V24 BGE V23,ZERO,DAC2LEDG ;is the ADD zero or higher, must be positive MULI V23,-1 ;make positive DAC2LEDG: TABST V23,[ZERO+209] ;divide by largest degree ;assign LED board ;---------------- BLT V26,0,DAC2LED3 MOVI V24,3 ;MARK 51 ;"3" TABST V24,[ZERO+208] ;BRD=3=theta 90 JUMP DAC2LEDC ;mult by 2, add 0 for grn or add 1 for red DAC2LED3: MOVI V24,8 TABST V24,[ZERO+208] ;BRD=8=theta=270 ;MARK 56 ;"8" JUMP DAC2LEDC ;mult by 2, add 0 for grn or add 1 for red ;compute LED address with X, 0/180 45/225 135/315 ;-------------------------- DAC2LED4: MOV V23,V25 TABLD V24,[ZERO+202] DIV V23,V24 ;divide by largest degree BGE V23,ZERO,DAC2LEDF ;is the ADD zero or higher, must be positive MULI V23,-1 ;make positive DAC2LEDF: TABST V23,[ZERO+209] ;ADD ;theta = horizontal ;------------------ BGT V26,[ZERO+203],DAC2LED8 ;y gt half ? BLT V26,[ZERO+206],DAC2LED8 ;y lt -half ? BLT V25,0,DAC2LED5 ;x lt 0 ? MOVI V24,0 TABST V24,[ZERO+208] ;BRD=0=theta 0 ;MARK 48 ;"0" JUMP DAC2LED6 DAC2LED5: MOVI V24,5 TABST V24,[ZERO+208] ;BRD=5=theta=180 ;MARK 53 ;"5" ;check if active LED is on an outer circuit board ;horizontal is +/-80 degrees spanning 4 boards DAC2LED6: BLE V23,47,DAC2LED7 ;LED on next board? ;MARK 49 ;"1" ;TABLD V24,[ZERO+208] ;BRD=BRD+1 board 0 to 1 or board 5 to 6 ADDI V24,1 TABST V24,[ZERO+208] ;TABLD V24,[ZERO+209] ADDI V23,-48 ;adjust address so it is between 0-47 on outer board TABST V23,[ZERO+209] DAC2LED7: JUMP DAC2LEDC ;mult by 2, add 0 for grn or add 1 for red ;theta = 45 or 135 ;----------------- DAC2LED8: BLT V26,0,DAC2LEDA ;y lt 0 ? BLT V25,0,DAC2LED9 ;x lt 0 ? MOVI V24,2 TABST V24,[ZERO+208] ;BRD=2=theta=45 ;MARK 50 ;"2" JUMP DAC2LEDC ;mult by 2, add 0 for grn or add 1 for red DAC2LED9: MOVI V24,4 TABST V24,[ZERO+208] ;BRD=4=theta=135 ;MARK 52 ;"4" JUMP DAC2LEDC ;mult by 2, add 0 for grn or add 1 for red ;theta = 225 or 315 ;------------------ DAC2LEDA: BGT V25,0,DAC2LEDB ;x gt 0 ? MOVI V24,7 ;MARK 55 ;"7" TABST V24,[ZERO+208] ;BRD=7=theta=225 JUMP DAC2LEDC ;mult by 2, add 0 for grn or add 1 for red DAC2LEDB: MOVI V24,9 TABST V24,[ZERO+208] ;BRD=9=theta=315 ;MARK 57 ;"9" ;RED--prepare the LED address to be sent to the LED ARRAY ;--------------------------------------------------- ;DAC2LEDC: jump DAC2LEDH DAC2LEDC: MOVI V2,0 BNE V2,[ZERO+210],DAC2LEDH ;branch if other spot TABLD LEDADD1,[ZERO+209] ;MARK [ZERO+209] ;leave a mark with the LED number MULI LEDADD1,2 ADDI LEDADD1,1 ;color bit for RED MULI LEDADD1,256 ;RED--prepare the BOARD address to be sent to the LED ARRAY ;----------------------------------------------------- TABLD LEDBRD1,[ZERO+208] ADDI LEDBRD1,192 MULI LEDBRD1,256 RETURN ;RED--prepare the LED address to be sent to the LED ARRAY ;--------------------------------------------------- DAC2LEDH: MOVI V2,1 BNE V2,[ZERO+210],DAC2LEDJ ;branch if other spot TABLD LEDADD2,[ZERO+209] ;MARK [ZERO+209] ;leave a mark with the LED number MULI LEDADD2,2 ADDI LEDADD2,1 ;color bit for RED MULI LEDADD2,256 ;RED--prepare the BOARD address to be sent to the LED ARRAY ;----------------------------------------------------- TABLD LEDBRD2,[ZERO+208] ADDI LEDBRD2,192 MULI LEDBRD2,256 RETURN ; ;RED--prepare the LED address to be sent to the LED ARRAY ;--------------------------------------------------- DAC2LEDJ: MOVI V2,2 BNE V2,[ZERO+210],DAC2LEDK ;branch if other spot TABLD LEDADD3,[ZERO+209] ;MARK [ZERO+209] ;leave a mark with the LED number MULI LEDADD3,2 ADDI LEDADD3,1 ;color bit for RED MULI LEDADD3,256 ;RED--prepare the BOARD address to be sent to the LED ARRAY ;----------------------------------------------------- TABLD LEDBRD3,[ZERO+208] ADDI LEDBRD3,192 MULI LEDBRD3,256 DAC2LEDK: RETURN ;-------------------------------------------------------- ; L E D S ;Activate three red LEDs. Seems that the parallel-to- ;serial interface requires 120 microsec between ;characters. The buffering is not as fast as Frank Miles ;had hoped. Twelve microseconds would not reliabily ;activate 3 spots. Thirteen microseconds seemed to ;reliabily activate 3 spots. Fifteen microseconds was ;chosen for an extra margin of reliability. ; ; Activating 3 RED spots requires 1.17 ms ; ;5/9/07 ;-------------------------------------------------------- LEDS: DIGLOW [10101111] ;1-AF clear all boards DELAY 15 ;16-15 microsecond delay BEQ SHUT1,0,LEDS9 ;17-br RED LED off DIGLOW LEDBRD3 ;18-add address + deg theta DELAY 15 ;33-15 microsecond delay DIGLOW LEDADD3 ;34-radius in lower nibble DELAY 15 ;49-15 microsecond delay ;MARK 20 ;14x DIGLOW LEDBRD1 ;50-add address + deg theta DELAY 15 ;65-15 microsecond delay DIGLOW LEDADD1 ;66-radius in lower nibble DELAY 15 ;81-15 microsecond delay ;MARK 18 ;12x DIGLOW LEDBRD2 ;82-C0 add address + deg theta DELAY 15 ;97-15 microsecond delay DIGLOW LEDADD2 ;98-radius in lower nibble DELAY 15 ;113-15 microsecond delay ;MARK 19 ;13x LEDS9: BNE SBUFFER,1,LEDS1 ;114- DIGLOW [10001111] ;115-8F send to all boards, #1 buffer MOVI SBUFFER,2 ;116-prepare to use the other buffer next time RETURN ;117- LEDS1: DIGLOW [10011111] ;115-9F send to all boards, #2 buffer loads first by default MOVI SBUFFER,1 ;116-prepare to use the other buffer next time RETURN ;117- ;-------------------------------------------------------- ; B R I T E ;Set the LED intensity. ;5/5/06 ;-------------------------------------------------------- BRITE: MARK 38 ;'&' DIGLOW [ZERO+29] ;1- (06...0C) (1...12) LED intensity DELAY 12 ;2-14 microsecond delay BNE SBUFFER,1,BRITE1 ;15- DIGLOW [10001111] ;16-8F send to all boards, #1 buffer MOVI SBUFFER,2 ;17-prepare to use the other buffer next time RETURN ;18- BRITE1: DIGLOW [10011111] ;19-9F send to all boards, #2 buffer loads first by default MOVI SBUFFER,1 ;20-prepare to use the other buffer next time RETURN ;21- ;-------------------------------------------------------- ; Z E R O V A R ; ;Zeros all the re-usable VAR so that they are empty before ;using. ; ;11/8/04 ;-------------------------------------------------------- ZEROVAR: MOVI V1,0 MOVI V2,0 MOVI V3,0 MOVI V4,0 MOVI V5,0 MOVI V6,0 MOVI V7,0 MOVI V8,0 MOVI V9,0 MOVI V10,0 MOVI V11,0 MOVI V12,0 MOVI V13,0 MOVI V14,0 MOVI V15,0 MOVI V16,0 MOVI V17,0 MOVI TEMP2,0 MOVI TEMP1,0 MOVI TEMP3,0 MOVI TEMP4,0 MOVI V22,0 MOVI V23,0 MOVI V24,0 MOVI V25,0 MOVI V26,0 RETURN