;-------------------------------------------------------- ; A D A P 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 (RED) VAR V34,LEDADD1 ;indicate which LED light (RED) VAR V35,LEDBRD2 ;indicate which LED board (GRN) VAR V36,LEDADD2 ;indicate which LED light (GRN) VAR V37,TRACKING ;is he 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,HT2 ;target-2 horizontal position VAR V47,VT2 ;target-2 vertical position VAR V48,HT1 ;target-1 horizontal position VAR V49,VT1 ;target-1 vertical position VAR V50,DURFORG ;how long he has been forgiven VAR V51,DURFEED=0 ;duration he has been on-target before getting fed 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, 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 ;-------------------------------------------------------- ; M A I N ;Directs program control to the mode of choice. ;10/11/04 ;-------------------------------------------------------- MAIN: MOVI ELAPSED,0 MOVI DURCONT,0 ;reset accumulators MOVI DURON,0 MOVI DURFORG,0 ;reset forgiveness timer ;-------------------------------------------------------- ; A D A P T ;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 = color (grn=0 red=1) ; ; ZERO+215 = stim_1 duration ; ZERO+216 = stim_2 duration ; ;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 = Type of stepping: 0=RTZ, 1=Random ; A+2 = Gap duration ; A+3 = Onset Velocity Threshold ; A+4 = Offset Velocity Threshold ; A+5 = Blanking Duration ; A+6 = Follow Duration ; 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 ;-------------------------------------------------------- ADAPT: BEQ PARAMCHG,0,ADAPT ;wait for parameters to arrive BEQ PARAMCHG,2,ADAPT1 ;skip if not the first time through ;first time only ;--------------- MARK 19 MOVI SHUT1,1 MOVI SHUT2,0 CALL SHUTTER MOVI PARAMCHG,2 ;new parameters grabbed CALL ZEROVAR ;clear all the re-usable VAR 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 MOVI V1,1000 ;data pointer TABLD V3,[V1+1] ;get the RTZ field TABLD V4,[V1+13] ;get the H starting point TABLD V2,[V1+10] ;get the H offset ADD V4,V2 DAC 0,V4 ;move to the starting point TABLD V5,[V1+14] ;get the V starting point ;MOVI V5,0 ;load the middle position TABLD V2,[V1+11] ;use the V offset for the zero location ADD V5,V2 ;add the offset to zero (this is done very explicitly!) DAC 1,V5 ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; CALL LEDS ;display the LED CALL REDGRN JUMP IDLE ;display this new position for awhile ;every time, is he on-target? ;--------------------------- ADAPT1: ADDI HITTYPE2,1 ;default inc non-adapt counter, undone later if adapt step ; CALL GETPOS ;get current eye position; HE,VE ; MOV V14,HE ;place it in V4 for TXPOS routine ; MOV V15,VE ;place it in V5 for TXPOS routine CALL OTTEST ;read target and eye values then compare (takes < 0.24 ms) BLT TRACKING,2,ADAPT2 ;confirm both H & V are on target MOVI FORGIVE,1 ;target moving, forgive for being off targ starting in IDLE ;move target to zero (RTZ) ;------------------------- ADAPT2: BEQ V3,-1,ADAPT5 ;branch if RTZ is not selected BEQ V3,0,ADAPT5 ;branch if last position was 0,0 MOVI V3,0 ;last position was 0,0 MARK 1 ;SAVE - an initial target step has occured MOVI V4,0 ;last X TABLD V2,[V1+10] ;get the H offset ADD V2,V4 DAC 0,V2 ;move to the middle MOVI V5,0 ;last Y TABLD V2,[V1+11] ;use the V offset for the zero location ADD V2,V5 ;add the offset to zero (this is done very explicitly!) DAC 1,V2 ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; CALL LEDS ;display the LED CALL REDGRN JUMP ADAPT99 ;target moved to center, all done ;select new vector ;----------------- ADAPT5: BEQ PARAMCHG,0,ADAPT ;wait for parameters to arrive MARK 20 ;? ; CALL GETPOS ;get current eye position; HE,VE ;; CALL TXPOS ;transpose the eye on the target vector ;; MOV V14,V4 ;store a pre-target step HE position ;; MOV V15,V5 ;store a pre-target step VE position ; MOV V14,HE ;store a pre-target step HE position ; MOV V15,VE ;store a pre-target step VE position MOVRND V17,3 ;get a random vector between 0-7 (hard-coded) ;get the stimulation durations ;-------------------------- MOV V10,V17 ;make a copy of the random number ADDI V10,450 ;add stimulation duration array offset ADD V10,V1 ;add 1000, the TABLE offset TABLD V2,[V10] ;get the stimulation duration TABST V2,[ZERO+215] ;store the stim_1 value MOV V10,V17 ;make a copy of the random number ADDI V10,460 ;add stimulation duration array offset ADD V10,V1 ;add 1000, the TABLE offset TABLD V2,[V10] ;get the stimulation duration TABST V2,[ZERO+216] ;store the stim_2 value ;get the axis slope ;----------------------------- MOV V10,V17 ;make a copy of the random number ADDI V10,350 ;add axis slope array offset ADD V10,V1 ;add 1000, the TABLE offset TABLD V2,[V10] ;get the slope TABST V2,[V1+504] ;store the slope for later use ADDI V10,10 ;360-offset to the perpendicular slope TABLD V2,[V10] ;get the perpendicular slope TABST V2,[V1+505] ;store the perpendicular slope for later use ;get the axis limits for X & Y ;----------------------------- MOV V10,V17 ;make a copy of the random number ADDI V10,370 ;add X excursion limit array offset ADD V10,V1 ;add 1000, the TABLE offset TABLD V2,[V10] ;get the X limit TABST V2,[V1+506] ;store the X limit for later use ADDI V10,10 ;380-get the Y limit TABLD V2,[V10] ;get the X limit TABST V2,[V1+507] ;store the Y limit for later use ;get the DAC value for 1 degree for X & Y ;----------------------------- MOV V10,V17 ;make a copy of the random number ADDI V10,390 ;add X DAC value offset ADD V10,V1 ;add 1000, the TABLE offset TABLD V2,[V10] ;get the X DAC value TABST V2,[ZERO+200] ;store the X DAC value ADDI V10,10 ;400-add offset to get the Y DAC value TABLD V2,[V10] ;get the Y DAC value TABST V2,[ZERO+201] ;store the Y DAC value ;get the initial X step ;---------------------- MOV V10,V17 ;make a copy of the random number MULI V10,10 ;convert rand to step of 10 ADDI V10,20 ;offset to table which starts at 20 ADD V10,V1 ;add 1000, the TABLE offset MOVRND V16,3 ;get a random step between 0-7 (hard-coded) ADD V10,V16 ;add to vector index BEQ NAN,[V10],ADAPT5 ;test if vector and intial step X size are valid TABLD V6,[V10] ;get initial step X value TABST V6,[V1+500] ;hold initial step X (500 loaded but not used) ;X new location rollover test ;---------------------- MOV V22,V6 ;copy the initial step X ADD V22,V4 ;add Xold BGE V4,ZERO,ADAPT6 ;branch if (+oldloc) ;negative old location BGE V6,ZERO,ADAPT9 ;branch if (-oldloc & +step) BLE V22,ZERO,ADAPT9 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ;positive old location ADAPT6: BLE V6,ZERO,ADAPT9 ;branch if (+oldloc & -step) BGE V22,ZERO,ADAPT9 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ADAPT9: MOV V6,V22 ;did not rollover, new location OK ;get the initial Y step ;---------------------- ADDI V10,80 ;offset to initial step Y size BEQ NAN,[V10],ADAPT5 ;test if vector and intial step Y size are valid TABLD V7,[V10] ;store initial step Y value TABST V7,[V1+501] ;hold initial step Y (501 loaded but not used) ;Y new location rollover test ;---------------------- MOV V22,V7 ;copy the initial step Y ADD V22,V5 ;add Yold BGE V5,ZERO,ADAPT12 ;branch if (+oldloc) ;negative old location BGE V7,ZERO,ADAPT13 ;branch if (-oldloc & +step) BLE V22,ZERO,ADAPT13 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ;positive old location ADAPT12: BLE V7,ZERO,ADAPT13 ;branch if (+oldloc & -step) BGE V22,ZERO,ADAPT13 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ADAPT13: MOV V7,V22 ;did not rollover, new location OK ;test if initial X is within limit ;--------------------------------- BLE ZERO,[V1+506],ADAPT3 ;is limit negative or positive? BLT V6,[V1+506],ADAPT5 ;neg limit, test if position is smaller JUMP ADAPT4 ADAPT3: BGT V6,[V1+506],ADAPT5 ;pos limit, test if position is larger ;test if initial Y is within limit ;--------------------------------- ADAPT4: BLE ZERO,[V1+507],ADAPT7 ;is limit negative or positive? BLT V7,[V1+507],ADAPT5 ;neg limit, test if position is smaller JUMP ADAPT98 ADAPT7: BGT V7,[V1+507],ADAPT5 ;pos limit, test if position is larger ;get the X adapt step (even if it is ZERO) ;------------------- ADAPT98: ADDI V10,80 ;offset to adapt step X size TABLD V8,[V10] ;180, get adapt step X value TABST V8,[V1+502] ;hold adapt step X size OR percent ;X new location rollover test ;---------------------- MOV V22,V8 ;copy the adapt step X ADD V22,V6 ;add Xold BGE V6,ZERO,ADAPT15 ;branch if (+oldloc) ;negative old location BGE V8,ZERO,ADAPT16 ;branch if (-oldloc & +step) BLE V22,ZERO,ADAPT16 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ;positive old location ADAPT15: BLE V8,ZERO,ADAPT16 ;branch if (+oldloc & -step) BGE V22,ZERO,ADAPT16 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ADAPT16: MOV V8,V22 ;did not rollover, new location OK ;get the Y adapt step (even if it is ZERO) ;------------------- ADDI V10,80 ;offset to adapt step Y size TABLD V9,[V10] ;190, get adapt step Y value TABST V9,[V1+503] ;hold adapt step Y size OR percent ;Y new location rollover test ;---------------------- MOV V22,V9 ;copy the adapt step Y ADD V22,V7 ;add Yold BGE V7,ZERO,ADAPT17 ;branch if (+oldloc) ;negative old location BGE V9,ZERO,ADAPT18 ;branch if (-oldloc & +step) BLE V22,ZERO,ADAPT18 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ;positive old location ADAPT17: BLE V9,ZERO,ADAPT18 ;branch if (+oldloc & -step) BGE V22,ZERO,ADAPT18 ;branch if (-oldloc & -step & -newloc) JUMP ADAPT5 ;ROLLOVER detected, get a different step ADAPT18: MOV V9,V22 ;did not rollover, new location OK ;test if adapt X is within limit ;--------------------------------- TABLD V2,[V1+10] ;get the H offset ADD V2,V8 ;prepare to test offset with limit BLE ZERO,[V1+506],ADAPT93 ;is limit negative or positive? BLT V8,[V1+506],ADAPT5 ;neg limit, test if position is smaller JUMP ADAPT94 ADAPT93: BGT V8,[V1+506],ADAPT5 ;pos limit, test if position is larger ;test if adapt Y is within limit ;---------------------- ADAPT94: TABLD V2,[V1+11] ;get the V offset ADD V2,V9 ;prepare to test offset with limit BLE ZERO,[V1+507],ADAPT97 ;is limit negative or positive? BLT V9,[V1+507],ADAPT5 ;neg limit, test if position is smaller JUMP ADAPT10 ADAPT97: BGT V9,[V1+507],ADAPT5 ;pos limit, test if position is larger ;trial approved ;================================================================= ADAPT10: NOP CALL GETPOS ;get current eye position; HE,VE CALL TXPOS ;transpose the eye on the target vector MOV V14,V4 ;store a pre-target step HE position MOV V15,V5 ;store a pre-target step VE position ; MOV V14,HE ;store a pre-target step HE position ; MOV V15,VE ;store a pre-target step VE position MOV V4,V6 ;transfer next initial X into current X MOV V5,V7 ;transfer next initial Y into current Y BEQ V3,-1,ADAPT11 ;if not RTZ skip MOVI V3,1 ;indicate that the last position was NOT 0,0 ADAPT11: NOP ;SAVE ;+gap+ ;----- BEQ ZERO,[V1+2],ADAPT23 ;bypass if no GAP is specified TABLD TEMPTIME,[V1+2] ;gap delay MOVI SHUT1,0 ;RED off CALL SHUTTER CALL LEDS ;RED LED off CALL STIMONE ;stimulate when the target goes off ADAPT8: DELAY 98 ;1- this is the GAP loop DBNZ TEMPTIME,ADAPT8 ;2- TABLD V2,[V1+10] ;get the H offset ADD V2,V4 DAC 0,V2 ;move to the next target location TABLD V2,[V1+11] ;get the H offset ADD V2,V5 DAC 1,V2 ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; ; MOVI SHUT1,1 ;RED on ; CALL SHUTTER ; CALL LEDS ;RED LED on CALL REDGRN MARK 1 ;SAVE - an initial target step has occured JUMP ADAPT24 ;-gap- ;+no gap+ ;-------- ADAPT23: TABLD V2,[V1+10] ;get the H offset ADD V2,V4 DAC 0,V2 ;move to the next target location TABLD V2,[V1+11] ;get the H offset ADD V2,V5 DAC 1,V2 MARK 1 ;SAVE - an initial target step has occured CALL STIMONE ;stimulate after target step ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; CALL LEDS ;display the LED CALL REDGRN ;-no gap- ;+blanking+ (adaptation OR blanking, not both) ;---------- ;BEQ ZERO,[V1+5],ADAPT24 ;bypass if no BLANKING is specified BGE ZERO,[V1+5],ADAPT24 ;bypass if no BLANKING is specified TICKS TEMP2 ;get the time to see if he moves in time for adaptation CALL ACCEL BEQ SUCCESS,0,ADAPT99 ;leave routine if he did not move (+1 & -1 are rt and lt) TICKS TEMPTIME ;get the current time SUB TEMPTIME,TEMP2 ;compute how long it took to respond to target step MOVI TEMP1,msTick(1) DIV TEMPTIME,TEMP1 ;convert to milliseconds ;MOV V11,TEMPTIME ;MOV V13,TEMPTIME TABLD TEMP1,[V1+7] ;get the min saccade latency TABLD TEMP2,[V1+8] ;get the max saccade latency BGT TEMP1,TEMPTIME,ADAPT99 ;branch out if he stepped too soon BLT TEMP2,TEMPTIME,ADAPT99 ;branch out if he stepped too late MOVI SHUT1,0 ;to close shutter CALL SHUTTER ;express shutter choices CALL LEDS ;RED LED off TABLD TEMPTIME,[V1+5] ;get blanking duration ADAPT25: DELAY 96 ;1-consume remaining millisecond BEQ PARAMCHG,0,ADAPT ;2-respond if the parameters have changed BLT TEMPTIME,ZERO,ADAPT ;3-8.30.06 occassion reqd when changing blanking to 0 DBNZ TEMPTIME,ADAPT25 ;4-test until period is over MOVI SHUT1,1 ;to open shutter CALL SHUTTER ;express shutter choices CALL LEDS ;RED LED on JUMP ADAPT14 ;jump to follow ;-blanking- ;+begin adaptation for all modes+ ;-------------------------------- ADAPT24: TICKS TEMP2 ;get the time to see if he moves in time for adaptation CALL ACCEL ;we're adapting, detect acceleration BNE ZERO,[V1+15],ADAPT34 ;adapt step everytime? BEQ SUCCESS,0,ADAPT99 ;leave routine if he did not move (+1 & -1 are rt and lt) TICKS TEMPTIME ;get the current time SUB TEMPTIME,TEMP2 ;compute how long it took to respond to target step MOVI TEMP1,msTick(1) DIV TEMPTIME,TEMP1 ;convert to milliseconds ;MOV V11,TEMPTIME ;MOV V13,TEMPTIME TABLD TEMP1,[V1+7] ;get the min saccade latency TABLD TEMP2,[V1+8] ;get the max saccade latency BGT TEMP1,TEMPTIME,ADAPT99 ;branch out if he stepped too soon BLT TEMP2,TEMPTIME,ADAPT99 ;branch out if he stepped too late ADAPT34: BEQ NAN,[V1+502],ADAPT14 ;7190-BR out if no adapt X step specified BNE ZERO,[V1+502],ADAPT59 ;7180-BR in if adapt X step specified BEQ NAN,[V1+503],ADAPT14 ;7190-BR out if no adapt Y step specified BNE ZERO,[V1+503],ADAPT59 ;7180-BR in if adapt Y step specified ADAPT59: TABLD TEMP1,[V1] ;get the type of adaptation BEQ TEMP1,0,ADAPT30 ;calling for Fixed Step Relative to Target BEQ TEMP1,1,ADAPT30 ;calling for Proportional Step Relative to Target BEQ TEMP1,2,ADAPT31 ;calling for Fixed Step Relative to Eye BEQ TEMP1,3,ADAPT31 ;calling for Proportional Step Relative to Eye JUMP ADAPT99 ;unknown code, don't adapt, blank or stimulate ;+fixed & proportional step relative to target+ ;------------------------------- ADAPT30: MOV V4,V8 ;transfer next X into current X MOV V5,V9 ;transfer next Y into current Y MARK 2 ;SAVE - an adapt target step has occured MARK 7 TABLD V2,[V1+10] ;get the H offset ADD V2,V4 DAC 0,V2 ;move to the next target location TABLD V2,[V1+11] ;get the H offset ADD V2,V5 DAC 1,V2 ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; CALL LEDS ;display the LED CALL REDGRN ADDI HITTYPE2,-1 ;undo default non-adapt increment ADDI HITTYPE1,1 ;inc adapt step counter JUMP ADAPT14 ;-fixed step relative to target- ;+transpose off-target eye to target vector+ ;---------------------------- ADAPT31: CALL DECEL ;detect deceleration BEQ SUCCESS,0,ADAPT99 ;leave routine if he did not move (+1 & -1 are rt and lt) CALL GETPOS ;get current eye position; HE,VE CALL TXPOS ;HE,VE; transpose current eye pos onto the vector; V4,V5 TABLD TEMP1,[V1] ;get the type of adaptation BEQ TEMP1,2,ADAPT33 ;this is Fixed Step Relative to Eye BEQ TEMP1,3,ADAPT32 ;this is Proportional Step Relative to Eye ;-transpose off-target eye to target vector- ;+fixed step relative to eye+ ;---------------------------- ;the eye has been "re-positioned" on the main vector ADAPT33: TABLD TEMP1,[ZERO+32] MUL V4,TEMP1 ;scale 16-bit A/D sig to the 32-bit D/A sig MUL V5,TEMP1 ;scale 16-bit A/D sig to the 32-bit D/A sig TABLD V6,[V1+502] ;get adapt step X value TABLD V7,[V1+503] ;get adapt step Y value ADD V6,V4 ;adapt Xpos = Xadapt + Xold ADD V7,V5 ;adapt Ypos = Yadapt + Yold MOV V4,V6 ;transfer next X into current X MOV V5,V7 ;transfer next Y into current Y MARK 2 ;SAVE - an adapt target step has occured MARK 8 TABLD V2,[V1+10] ;get the H offset ADD V2,V4 DAC 0,V2 ;move to the next target location TABLD V2,[V1+11] ;get the H offset ADD V2,V5 DAC 1,V2 ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; CALL LEDS ;display the LED CALL REDGRN ADDI HITTYPE2,-1 ;undo default non-adapt increment ADDI HITTYPE1,1 ;inc adapt step counter JUMP ADAPT14 ;all done ;-fixed step relative to eye- ;+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 TABLD V6,[V1+502] ;get adapt step X %-value TABLD V7,[V1+503] ;get adapt step Y %-value 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 TABLD TEMP1,[ZERO+32] MUL V4,TEMP1 ;scale 16-bit A/D sig to the 32-bit D/A sig MUL V5,TEMP1 ;scale 16-bit A/D sig to the 32-bit D/A sig ADD V6,V4 ;adapt Xpos = Xadapt + Xold ADD V7,V5 ;adapt Ypos = Yadapt + Yold MOV V4,V6 ;transfer next X into current X MOV V5,V7 ;transfer next Y into current Y MARK 2 ;SAVE - an adapt target step has occured MARK 9 TABLD V2,[V1+10] ;get the H offset ADD V2,V4 DAC 0,V2 ;move to the next target location TABLD V2,[V1+11] ;get the H offset ADD V2,V5 DAC 1,V2 ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; CALL LEDS ;display the LED CALL REDGRN ADDI HITTYPE2,-1 ;undo default non-adapt increment ADDI HITTYPE1,1 ;inc adapt step counter JUMP ADAPT14 ;-proportional step relative to eye- ;-adapt- ;+stimulate follow+ ;-------- ADAPT14: CALL STIMTWO ;stim AFTER vel detect, don't mess up 2nd saccade with stim BEQ ZERO,[V1+6],ADAPT99 ;only run if FOLLOW has a non-zero value ;TABLD PASSVAR,[V1+6] CALL FOLLOW ;target follows eye ;-stimulate follow- ;user select deadzone? ;----------------------- ADAPT99: TABLD V22,[V1+1] ;get the RTZ setting MOVI V2,1 ;the code = RTZ to compare with BEQ V2,V22,ADAPT999 ;can't do deadzone if RTZ ;Test all non-RTZ trials for the deadzone. If user has start point ;set to 0 (default), all new target positions will be >= zero. ; CALL GETPOS ;get current target positions ; TABLD V23,[V1+10] ;get the H target offset ; MOV V2,HT1 ;get current H target position with no offset ; SUB V2,V23 ;eliminate any H target offset ; MOV V4,V2 ;V4 has current non-offset H DAC pos ; ; TABLD V24,[V1+11] ;get the V target offset ; MOV V2,VT1 ;get current V target position with no offset ; SUB V2,V24 ;eliminate any V target offset ; MOV V5,V2 ;V5 has current non-offset V DAC pos MOV V23,ZERO ;initialize deadzone boundry MOV V24,ZERO ;initialize deadzone boundry MOV V25,ZERO ;initialize "in deadzone" flag ;horizontal ;---------- ;V4 = H target without offset ;V22 = temp H deadzone boundry ;V23 = H deadzone boundry ;V25 = target in deadzone flag ;V10 = deadzone address MOV V10,V17 ;make a copy of the random step number ADDI V10,410 ;add X-deadzone array offset ADD V10,V1 ;add 1000, the TABLE offset TABLD V22,[V10] ;get the X-deadzone value TABST V4,[ZERO+600] ;current HT1 BGT ZERO,V4,ADAPT81 ;br if target is negative ;HT1 is positive ;--------------- BGE V4,V22,HOK ;br if out of DZ MOV V23,V22 ;remember positive DZ boundry ADDI V25,1 ;target needs to be re-positioned MARK 65 ;"A" JUMP HOK ;HT1 is negative ;--------------- ADAPT81: MULI V22,-1 ;HT1 is negative, test it that way BLE V4,V22,HOK ;br if out of dz MOV V23,V22 ;remember negative DZ boundry ADDI V25,1 ;target needs to be re-positioned MARK 97 ;"a" JUMP HOK HOK: TABST V23,[ZERO+601] ;H boundry used MARK 123 ;"{" ;vertical ;-------- ;V5 = V target without offset ;V22 = temp V deadzone boundry ;V24 = V deadzone boundry ;V25 = target in deadzone flag ;V10= deadzone address ADDI V10,10 ;increment to 420 where the Y-deadzone array offsets are TABLD V22,[V10] ;get the X-deadzone value TABST V5,[ZERO+602] ;for testing, save VT1 BGT ZERO,V5,ADAPT86 ;br if target is negative ;VT1 is positive ;--------------- BGE V5,V22,VOK ;br if out of DZ MOV V24,V22 ;remember positive DZ boundry ADDI V25,1 ;record at least one axis is in DZ MARK 66 ;"B" JUMP VOK ;VT1 is negative ;--------------- ADAPT86: MULI V22,-1 ;VT1 is negative, test it that way BLE V5,V22,VOK ;br if out of dz MOV V24,V22 ;remember negative DZ boundry ADDI V25,1 ;record at least one axis is in DZ MARK 98 ;"b" JUMP VOK VOK: TABST V24,[ZERO+603] ;V boundry used MARK 125 ;"}" BEQ ZERO,V25,ADAPT999 ;V25=0 means H and V are out of deadzone MARK 126 ;"~" ;get new deadzone boundries and add offsets to them MOV V10,V17 ;make a copy of the random step number ADDI V10,410 ;add X-deadzone array offset ADD V10,V1 ;add 1000, the TABLE offset TABLD V23,[V10] ;get the X-deadzone value ADDI V10,10 ;increment to 420 where the Y-deadzone array offsets are TABLD V24,[V10] ;get the X-deadzone value MOVRND V2,1 BEQ V2,ZERO,ADAPT87 MULI V23,-1 MULI V24,-1 ADAPT87: NOP ;TABLD V2,[V1+10] ;get the H target offset ;ADD V23,V2 ;TABLD V2,[V1+11] ;get the V target offset ;ADD V24,V2 ;TABST V23,[ZERO+601] ;H boundry used ;TABST V23,[ZERO+603] ;V boundry used ;re-position the target outside of the deadzone MOV V4,V23 ;save H target with no offset MOV HT1,V23 ;move H target outside of deadzone TABLD V2,[V1+10] ;get the H offset ADD HT1,V2 ;add the H user offset MOV V5,V24 ;save V target with no offset MOV VT1,V24 ;move V target outside of deadzone TABLD V2,[V1+11] ;get the V target offset ADD VT1,V2 ;add the V user offset DAC 0,HT1 ;new HT position DAC 1,VT1 ;new VT position ;convert DAC positions to LED array information ; TABST V4,[ZERO+204] ;load X ; TABST V5,[ZERO+205] ;load Y ; CALL DAC2LED ;convert DAC to LED ; CALL LEDS ;display the LED CALL REDGRN ;signal to Spike2 "all done" ;--------------------------- ADAPT999: MOVI V2,1 ;signal that it is time to show the user some numbers TABST V2,[ZERO+31] JUMP IDLE ;wait for a new event ;v2 v3 v4 v5 v6 ;-------------------------------------------------------- ; R E D G R N ;Pass all the right values in preparation to draw the ;RED and GRN LEDs. ;convert DAC positions to LED array information ;3/22/05 ;-------------------------------------------------------- REDGRN: TABST V4,[ZERO+204] ;load RED X-to-204 TABST V5,[ZERO+205] ;load RED Y-to-205 MOVI V24,1 ;RED TABST V24,[ZERO+210] ;set RED color bit-to-210 CALL DAC2LED ;convert DAC to RED LED ; 3/22/07 So far there are no green LEDs in adapt, but there ; is in Memory where this routine came from. ; TABST V6,[ZERO+204] ;load GRN X ; TABST V7,[ZERO+205] ;load GRN Y ; MOVI V24,0 ;GRN ; TABST V24,[ZERO+210] ;set GRN color bit ; CALL DAC2LED ;convert DAC to GRN LED CALL LEDS ;display the RED & GRN LEDs RETURN ;-------------------------------------------------------- ; 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: 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 ;-------------------------------------------------------- ; I D L E ;Control spends most of the time here. It leaves when new ;choices have been made or when it is time to move. ;9/28/04 ;Table Data Map: ; ;On Target parameter stored in TABLE, ZERO=0000 ; ZERO+10 = pRealMinTime*1000; ASSOONAS ; ZERO+11 = pRealMaxTime*1000; NOLATER ; ZERO+12 = pRealContiguousTime*1000; CONTTON ; ZERO+13 = pRealTimeOn*1000; TOTALTON ; ZERO+14 = pOnFirst*1000; DURFIRST ; ZERO+15 = pOnSubsequent*1000; DURSUB ; ZERO+16 = pForgiveness*1000; FORGTIME ;-------------------------------------------------------- IDLE: BEQ PARAMCHG,1,MAIN ;the user choices have changed TICKS TIMECURR ;get the current time ;time to check again? BLT TIMECURR,TIMECHEK,IDLE ADDI TIMECHEK,msTick(1) ;1ms, 0.001s later (much more accurate! no time drift) ADDI ELAPSED,1 CALL OTTEST ;read target and eye values then compare (takes < 0.24 ms) ;is he being forgiven? BEQ FORGIVE,0,IDLE5 ADDI DURFORG,1 ;keep track of the forgiveness period BLT DURFORG,[ZERO+16],IDLE6 ;FORGTIME, still forgiving? MOVI FORGIVE,0 ;turn off forgiveness MOVI DURFORG,0 ;reset forgiveness timer ;is he on-target? IDLE5: BLT TRACKING,2,IDLE7 ;confirm both H & V are on target DIGOUT [....0...] ;high activates the SONALERT IDLE6: NOP ;comes directly here if in a FORGIVE period ADDI DURON,1 ;increase time on accumulator ADDI DURCONT,1 ;increase contiguous time on accumulator ADDI DURFEED,1 ;increase feed accumulator ;has he been OT long enough to be fed? BLT DURFEED,TIMEFEED,IDLE3 ;test if it is time to feed ;MARK 70 ;F CALL FEED ;0.103ms, feed him MOVI DURFEED,0 ;reset the accumulator TABLD TIMEFEED,[ZERO+15] ;DURSUB, use shorter subsequent time on-target dur ;has he been on long enough to move the target? IDLE3: BLE ELAPSED,[ZERO+10],IDLE ;ASSOONAS, satisfied the AS SOON AS requirement? BLE DURCONT,[ZERO+12],IDLE ;CONTTON, satisfied the contiguous requirement? BLE DURON,[ZERO+13],IDLE ;TOTALTON, satisfied the total time on requirement? JUMP MAIN ;move now! ;he is off target reset everything but the total time on move accumulator IDLE7: NOP ;MARK 66 DIGOUT [....1...] ;low de-activates the SONALERT BGE ELAPSED,[ZERO+11],MAIN ;NOLATER, long enough - move the target anyway? MOVI DURCONT,0 ;reset the contiguous time on MOVI DURFEED,0 ;reset the feed time on TABLD TIMEFEED,[ZERO+14] ;DURFIRST, subsequent time on-target duration JUMP IDLE ;-------------------------------------------------------- ; 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- ;-------------------------------------------------------- ; 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 he 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 CALL GETPOS ;8-find out where targ & eye are 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 he 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 he 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 the animal 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 the animal 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 ;he'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 he moved RETURN ;-------------------------------------------------------- ; F O L L O W ;This moves the target to the detected eye position. ;Updating the position every millisecond. ;11/26/03 ;-------------------------------------------------------- ;FOLLOW: CALL GETPOS ;1+7-get eye and target positions ; ; MOVI TEMP1,65536 ;8- ; MUL TEMP1,HE ;9-scale 16-bit A/D sig to the 32-bit D/A sig ; DAC 0,TEMP1 ;10-move the target to the eye position ; ; MOVI TEMP1,65536 ;11- ; MUL TEMP1,VE ;12-scale 16-bit A/D sig to the 32-bit D/A sig ; DAC 1,TEMP1 ;13-move the target to the eye position ; ; DELAY 85 ;14-consume remaining millisecond ; ;DBNZ PASSVAR,FOLLOW ;15-test until period is over ; DBNZ [V1+6],FOLLOW ;15-test until period is over ; RETURN ;-------------------------------------------------------- ; F O L L O W ;This moves the target to the detected eye position. ;Updating the position every millisecond. ;11/26/03 ;-------------------------------------------------------- FOLLOW: TICKS TIMECHEK ;get the current time TABLD V2,[V1+6] ;get the follow duration ADD TIMECHEK,V2 ;add the MEMORIZE duration (temporarily 1 second) FOLLOW1: CALL GETPOS ;get eye and target positions TABLD TEMP1,[ZERO+32] ;MOVI TEMP1,65536 MUL TEMP1,HE ;scale 16-bit A/D sig to the 32-bit D/A sig DAC 0,TEMP1 ;move the target to the eye position TABLD TEMP1,[ZERO+32] ;MOVI TEMP1,65536 MUL TEMP1,VE ;scale 16-bit A/D sig to the 32-bit D/A sig DAC 1,TEMP1 ;move the target to the eye position BLT TIMECURR,TIMECHEK,FOLLOW1 ;keep checking 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- ;-------------------------------------------------------- ; S T I M ;Sends a stimulation pulse. ;12/1/05 ;-------------------------------------------------------- STIMONE: MOVRND V2,7 ;get a random vector between 0-127 (hard-coded) BGT V2,[V1+12],STIM2 ;low stimulates, high does not stimulate TABLD V2,[ZERO+215] ;first stim period called JUMP STIM1 STIMTWO: MOVRND V2,7 ;get a random vector between 0-127 (hard-coded) BGT V2,[V1+12],STIM2 ;low stimulates, high does not stimulate TABLD V2,[ZERO+216] ;second stim period called STIM1: BLE V2,ZERO,STIM2 ;skip if dur = 0 DIGOUT [...1....] ;trigger stimulation MARK 47 ;/character DELAY V2 DIGOUT [...0....] ;stop stimulation MARK 92 ;\character STIM2: RETURN ;-------------------------------------------------------- ; 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 = 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 = color (grn=0 red=1) ;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" DAC2LEDC: BEQ ZERO,[ZERO+210],DAC2LEDH ;branch if green ;RED--prepare the LED address to be sent to the LED ARRAY ;--------------------------------------------------- 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 ;GRN--prepare the LED address to be sent to the LED ARRAY ;--------------------------------------------------- DAC2LEDH: TABLD LEDADD2,[ZERO+209] MARK [ZERO+209] ;leave a mark with the LED number MULI LEDADD2,2 ADDI LEDADD2,0 ;color bit for GRN (add zero for completeness) MULI LEDADD2,256 ;GRN--prepare the BOARD address to be sent to the LED ARRAY ;----------------------------------------------------- TABLD LEDBRD2,[ZERO+208] ADDI LEDBRD2,192 MULI LEDBRD2,256 RETURN ;-------------------------------------------------------- ; L E D S ;Activate a red or a green LED. Seems that the parallel- ;to-serial interface requires 120 microsec between ;characters. The buffering is not as fast as Frank Miles ;had hoped. The time it takes to complete this command ;varies: ; RED only = 0.44 ms ; GRN only = 0.45 ms ; RED & GRN = 0.71 ms ;3/19/03 ;-------------------------------------------------------- LEDS: DIGLOW [10101111] ;1-AF clear all boards DELAY 12 ;13-120 microsecond delay BEQ SHUT1,0,LEDS2 ;14-present a red LED? DIGLOW LEDBRD1 ;15-C0 add address + deg theta DELAY 12 ;27-120 microsecond delay DIGLOW LEDADD1 ;28-radius in lower nibble DELAY 12 ;40-120 microsecond delay ;MARK 18 ;12x LEDS2: BEQ SHUT2,0,LEDS3 ;41-present a green LED? DIGLOW LEDBRD2 ;42-C0 add address + deg theta DELAY 12 ;54-120 microsecond delay DIGLOW LEDADD2 ;55-radius in lower nibble DELAY 12 ;67-120 microsecond delay ;MARK 19 ;13x LEDS3: BNE SBUFFER,1,LEDS1 ;68- DIGLOW [10001111] ;69-8F send to all boards, #1 buffer MOVI SBUFFER,2 ;70-prepare to use the other buffer next time RETURN ;71- LEDS1: DIGLOW [10011111] ;69-9F send to all boards, #2 buffer loads first by default MOVI SBUFFER,1 ;70-prepare to use the other buffer next time RETURN ;71- ;-------------------------------------------------------- ; 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