https://github.com/RaymondLab/Code
Tip revision: f562b26a59ee1fe18ddbdd35eb072e822e4e0f63 authored by Katie Li on 14 November 2022, 22:02:35 UTC
Matlab files on D241B setup
Matlab files on D241B setup
Tip revision: f562b26
Parameters_Universal_temp_SumofSines.s2s
' UNIVERSAL PARAMETERS
'--------------------------------------------------------------------------------
' SINE PARAMETERS
'--------------------------------------------------------------------------------
var sinHzChair := 1;
var sinPhChair := -90;
var actualChairPh;
var sinHzDrum := 1;
var sinPhDrum := 90;
var actualDrumPh;
var sineOn% := 0;
var sinAmpChair := 10;
var sinAmpDrum := 10;
var halfPhaseDelay := (sinHzDrum * 1000) / 2;
var sinPhDrum_Original := sinPhDrum;
var sinAmpDrum_Original := sinAmpDrum;
const CustomWaveformKey$ := "W";
PlayWaveAdd(CustomWaveformKey$,"wave",0,0,24.975,2,0,"C:\\Users\\Public\\RaymondLabCode\\Waveforms\\test_25.smrx");
PlayWaveCycles("0",0);
'--------------------------------------------------------------------------------
' STEP PARAMETERS
'--------------------------------------------------------------------------------
var stepPeriod := 1000;
var stepLength := 250;
var stepStim := 0;
var step_AmpChair := 10;
var step_AmpDrum := 10;
var sRest2;
var sStart;
var sLength;
var sLength1;
var sRest1;
var sAmpChair;
var sAmpDrum;
var sAmpChairN;
var sAmpDrumN;
var stepLen1 := 0;
var stepLen2 := 0;
var stepLen3 := 0;
'For video alignment pulse - duration
var pulseDurationV := 33;
'For video alignment pulse - time between pulses
var pulseWaitV := 1000 - pulseDurationV - 5;
var pulsePeriod := 1000;
var checkConfig := 1;
var QueTime := 0;
'--------------------------------------------------------------------------------
' PULSE PARAMETERS
'--------------------------------------------------------------------------------
var pWait := 0;
var pNumber := 1;
var pDuration;
var pInterval;
var pStart;
var pulseDuration := 500;
var pulseInterval := 0;
var pWait2 := 0;
var pulsePhase := 0 ;
var stepLight := 0;
var lightDur := 500;
var lightStart := 0;
var everyNCycles := 1;
'--------------------------------------------------------------------------------
' EXPERIMENT PARAMETERS
'--------------------------------------------------------------------------------
var nBlocks% := 6; 'Number of run-test blocks in exmpt
var nTestreps% := 1; 'Number of times to repeat 40 sec test
var runLength := 300; 'Seconds to run protocol in each block(300 for 5 min)
var testLength := 45; 'Seconds to test
var expmtLoc% := 1;
var prePostNum := 1;
var trainLoc% := 1;
var trainAmount := 0;
var expmtMode := 2; 'expmtMode: 0=off, 1=0x, 2=2x, 3=ipsi stim, 4=contra stim
var testString$;
var runExpmt% := 0; ' Random note: % denotes integer types
var rep% := 0; 'Rep (5min run, 40 sec test)
var test% := 1; 'test: 0=run testLength, 1=test testLength, 2=init&wait 20 sec, 3=init&wait 10 sec, 4=init&wait runLength
var testrep% := 0;
var goalTime := 1000000000; 'maximum time the motor is allowed to run for
var flashon% := 1;
var waitLength := 300;
var prevTime := 0;
var W := 1;
var X := 1.02;
var Y := .9;
var Z := 1;
'--------------------------------------------------------------------------------
' MISC PARAMETERS
'--------------------------------------------------------------------------------
var SampleWindow%;
var comment$;
var vidOn := 0;
var stepOn% := 0;
var fullPulse := 0;
'Voltage Range: check in Edit -> Edit Parameters
var MaxVoltage := 10;
var driftFix := 1;
var centerLineChair := 0;
var centerLineDrum := 0;
var testStim := 0;
var rotationVelocity := 0.02;
var radianConversion := 57.295779513; 'divide a value in degrees by this number to convert to radians - from Spike2 manual'
var measuredZeroChair := 0;
var measuredZeroDrum := 0;
var layoutChoice := 0;
'--------------------------------------------------------------------------------
' TOOLBAR PARAMETERS
'--------------------------------------------------------------------------------
const NewFilePos := 2;
const InitPos := NewFilePos+1;
const CommentPos := InitPos+1;
const LightPos := CommentPos+1;
const LaserPos := LightPos+1;
const SinePos := LaserPos+1;
const CustomWaveformPos := SinePos+1;
const SineConfigPos := CustomWaveformPos+1;
const PulsePos := SineConfigPos+1;
const PulseConfigPos := PulsePos+1;
const VidPos := PulseConfigPos+1;
const StepPos := VidPos+1;
const StepConfigPos := StepPos+1;
const ExpmtPos := StepConfigPos+1;
const ExpmtConfigPos := ExpmtPos+1;
const devPos := ExpmtConfigPos+1;
'--------------------------------------------------------------------------------
' DEFAULT CHAN PARAMETERS
'--------------------------------------------------------------------------------
var HTVELChCom% := 1;
var HHVELChCom% := 2;
var htposCh% := 3;
var hhposCh% := 4;
var heposCh1% := 5;
var heposCh2% := 6;
var ephysch% := 7;
var hhvelCh% := 8;
var htvelCh% := 13;
var TTL1ch% := 9;
var TTL2ch% := 10;
var TTL3ch% := 11;
var TTL4ch% := 12;
'--------------------------------------------------------------------------------
' SINE FUNCTIONS
'--------------------------------------------------------------------------------
Func ToolbarCustomWaveformStart%()
prevTime := MaxTime();
measuredZeroChair := ChanMeasure(hhposCh%, 2, prevTime-2, prevTime-.5);
measuredZeroDrum := ChanMeasure(htposCh%, 2, prevTime-2, prevTime-.5);
SampleKey(CustomWaveformKey$);
sineOn% := 1;
Yield();
ToolbarSet(CustomWaveformPos, "Custom Waveform Off",ToolbarCustomWaveformStop%);
Return( 1 );
End
Func ToolbarCustomWaveformStop%()
SampleKey( "s" );
sineOn% := 0;
ToolbarSet(CustomWaveformPos, "Custom Waveform On",ToolbarCustomWaveformStart%);
Return( 1 );
End
Func ToolbarSineStart%()
prevTime := MaxTime();
measuredZeroChair := ChanMeasure(hhposCh%, 2, prevTime-2, prevTime-.5);
measuredZeroDrum := ChanMeasure(htposCh%, 2, prevTime-2, prevTime-.5);
SampleKey( "S" );
sineOn% := 1;
Yield();
ToolbarSet(SinePos, "Sine Off",ToolbarSineStop%);
Return( 1 );
End
Func ToolbarSineStop%()
SampleKey( "s" );
sineOn% := 0;
ToolbarSet(SinePos, "Sine On",ToolbarSineStart%);
Return( 1 );
End
Func ToolbarSineConfig%()
DlgCreate("Sine settings"); 'Start new dialog
DlgReal(1,"Chair Freq (Hz)",0,50);
DlgReal(2,"Chair Peak Velocity (deg/sec)",0,100); 'set to 0 if not using Chair
DlgReal(3,"Chair Phase (degree)",-180,180);
DlgReal(4,"Drum Freq (Hz)",0,50);
DlgReal(5,"Drum Peak Velocity (deg/sec)",0,100); 'set to 0 if not using Drum
DlgReal(6,"Drum Phase (degree)",-180,180);
DlgShow(sinHzChair,sinAmpChair, sinPhChair, sinHzDrum, sinAmpDrum_Original, sinPhDrum_Original);
halfPhaseDelay := (sinHzDrum * 1000) / 2;
' Convert Velocity Command Amplitude to Position Amplitude
sinPhDrum := sinPhDrum_Original - 90;
sinAmpDrum := sinAmpDrum_Original / (2 * 2.14159 * sinHzDrum);
SetPulseSettings%();
SetSequencerValues();
Return(1);
End
'--------------------------------------------------------------------------------
' LIGHT FUNCTIONS
'--------------------------------------------------------------------------------
Func ToolbarLightOn%()
SampleKey( "L" );
Toolbarset(LightPos,"Light Off", ToolbarLightOff%);
Return( 1 );
End
Func ToolbarLightOff%()
SampleKey( "l" );
Toolbarset(LightPos,"Light On", ToolbarLightOn%);
Return( 1 );
End
Proc runFlash()
if flashon% = 1 then
ToolbarLightOn%();
endif;
Yield(.2);
ToolbarLightOff%();
End
'--------------------------------------------------------------------------------
'Turn both lasers on/off
'--------------------------------------------------------------------------------
Func ToolbarLasersOn%()
SampleKey( "Z" );
Toolbarset(LaserPos,"Lasers Off", ToolbarLasersOff%);
Return( 1 );
End
Func ToolbarLasersOff%()
SampleKey( "z" );
Toolbarset(LaserPos,"Lasers On", ToolbarLasersOn%);
Return( 1 );
End
'--------------------------------------------------------------------------------
'Start sine wave/pulses for video
'--------------------------------------------------------------------------------
Func ToolbarVidOn%()
vidOn := 1;
Yield();
pulseDurationV := 33; 'For video alignment pulse
pulseWaitV := 1000*1/sinHzChair - pulseDurationV - 5; 'For video alignment
SetSequencerValues();
SampleKey( "V" );
Toolbarset(VidPos,"Video Off", ToolbarVidOff%);
Return( 1 );
End
Func ToolbarVidOff%()
vidOn := 0;
Yield();
SampleKey( "v" );
Toolbarset(VidPos,"Video On", ToolbarVidOn%);
Return( 1 );
End
'--------------------------------------------------------------------------------
' PULSE FUNCTIONS
'--------------------------------------------------------------------------------
Func ToolbarPulseConfig%()
DlgCreate("Pulse settings"); 'Start new dialog
'DlgReal(1,"Period (ms)",0,300000);
DlgReal(1,"Number of Pulses",0,1000);
DlgReal(2,"Pulse duration (ms)",0,5000);
DlgReal(3,"Interpulse interval (ms)",0,5000);
DlgReal(4,"Pulse phase (deg)",0,360);
DlgReal(5, "Pulses Occur Every X Cycles?", 1, 10000);
DlgShow(pNumber, pulseDuration, pulseInterval,pulsePhase, everyNCycles);
SetPulseSettings%();
Return( 1 );
End
Func SetPulseSettings%()
pulsePeriod := 1/sinHzChair * 1000;
fullPulse := 0;
pWait := (pulsePeriod/2) - 4 - (pNumber *(pulseDuration + pulseInterval+1));
if pWait < 0 then
pWait := 0 ;
fullPulse := 1; 'Immediate switching between states
endif;
pDuration := pulseDuration -2;
pWait2 := pWait-2;
pInterval := pulseInterval;
if pInterval > 1 then
pInterval := pulseInterval -3;
endif;
SetSequencerValues();
Return(1);
End
'--------------------------------------------------------------------------------
' STEP FUNCTIONS
'--------------------------------------------------------------------------------
Func ToolbarStepOn%()
stepOn% := 1;
if (stepStim = 0) and (stepLight = 0) then
if (stepPeriod - (2*stepLength)) = 0 then
SampleKey ( "T" );
ToolbarSet(StepPos, "Step Stop", ToolbarStepOff%);
else
if QueTime > 0 then
SampleKey("K");
ToolbarSet(stepPos, "Step Stop", ToolbarStepOff%);
else
SampleKey("k");
ToolbarSet(stepPos, "Step Stop", ToolbarStepOff%);
endif
endif
else
if stepLight = 1 and stepStim = 0 then
stepOn% := 1; Yield();
prevTime := MaxTime();
measuredZeroChair := ChanMeasure(hhposCh%, 2, prevTime-2, prevTime);
measuredZeroDrum := ChanMeasure(htposCh%, 2, prevTime-2, prevTime);
docase
case lightDur = stepLength and lightStart = 0 then
SampleKey ("t"); ' Entire step
case stepLen1 = 0 then
' Aligned to beginning of step
SampleKey("b");
case stepLen3 = 0 then
'Aligned to end of step
SampleKey("e");
else
' Somewhere in the middle of step
SampleKey ("d"); ' Delayed/partial
endcase;
ToolbarSet(StepPos, "Step Stop", ToolbarStepOff%);
endif;
if stepStim = 1 and stepLight = 1 then
SampleKey ( "u"); '***Currently non functional 8/2/12?
ToolbarSet(StepPos, "Step Stop", ToolbarStepOff%);
endif;
endif;
Return (1);
End
Func ToolbarStepOff%()
SampleKey( "I" );
stepOn% := 0;
ToolbarSet(StepPos, "Step Start", ToolbarStepOn%);
Return( 1 );
End
Func ToolbarStepConfig%()
' User dialog
'StepConfigWindow();
' Convert to exact numbers, accounting for software delays
'Max 11-2019: If you input a 1000ms stepPeriod it will not end up being 1000ms. idk why, sorry. Spike2 issue
sRest1 := (stepPeriod - stepLength - stepLength)/2 - 3;
if sRest1 < 0 then
sRest1 := 0;
endif
sLength := stepLength - 3;
if sLength < 0 then
sLength := 0;
endif
sRest2 := sRest1 - 1;
if sRest2 < 0 then
sRest2 := 0;
endif
' Chair and drum velocity
sAmpChair := ChairVel2Int32%( step_AmpChair ); ' Amp chair
sAmpChairN := 0-sAmpChair; ' Amp chair (opposite direction)
sAmpDrum := DrumVel2Int32%( step_AmpChair ); ' Amp drum
sAmpDrumN := 0-sAmpDrum; ' Amp drum (opposite direction)
'if chairDegreesPerSecondOffset > 0 then
'''SampleKey("1");
'sAmpChair := ChairVel2Int32%( step_AmpChair + chairDegreesPerSecondOffset/50); ' Amp chair
'''SampleKey("2");
'var chairDegreesPerSecondOffsetNEG := chairDegreesPerSecondOffset * -1;
'sAmpChair := ChairVel2Int32%( step_AmpChair + chairDegreesPerSecondOffsetNEG); ' Amp chair
'sAmpChairN := 0-ChairVel2Int32%( step_AmpChair + chairDegreesPerSecondOffsetNEG + chairDegreesPerSecondOffsetNEG/50);
'endif
'if DrumDegreesPerSecondOffset > 0 then
'SampleKey("1");
'sAmpDrum := DrumVel2Int32%( step_AmpChair + DrumDegreesPerSecondOffset); ' Amp chair
'sAmpDrumN := 0-DrumVel2Int32%( step_AmpChair - DrumDegreesPerSecondOffset*1.02);
'else
'SampleKey("2");
'var DrumDegreesPerSecondOffsetNEG := DrumDegreesPerSecondOffset * -1;
'sAmpDrum := DrumVel2Int32%( step_AmpChair + DrumDegreesPerSecondOffsetNEG*.02); ' Amp chair
'sAmpDrumN := 0-DrumVel2Int32%( step_AmpChair + DrumDegreesPerSecondOffsetNEG);
'endif
' Light pulse
if stepLight = 1 then
' If light pulse is not exactly the same as step pulse, break into 3 segments
if lightDur <> stepLength or lightStart <> 0 then
stepLen1 := max(lightStart - 3, 0); ' Chair alone
stepLen2 := lightDur - 2; ' Chair+light
stepLen3 := max(stepLength - lightDur - max(lightStart,2) - 2,0); ' Chair alone
if stepLen3 = 0 then 'Small adjustment to account for delay if light aligned to end of step
stepLen2 := stepLen2-1;
endif;
endif;
endif;
if stepStim = 1 then
pNumber := trunc((stepLength-4)/(pulseDuration + pulseInterval));
pDuration := pulseDuration -2;
pInterval := pulseInterval -3;
sLength1 := stepLength - ((pulseDuration + pulseInterval)*pNumber)-4;
endif;
'testing
SetPulseSettings%();
Yield();
SetSequencerValues();
Return (1);
End
Func StepConfigWindow%()
DlgCreate("Step settings"); 'Start new dialog for entering step commands
DlgReal(1,"Total Period (ms)", 0, 21000);
DlgReal(2,"Step length (ms)", 0, 15000);
DlgReal(3,"Chair Velocity (deg/sec)", -100, 100);
DlgReal(4,"Drum Velocity (deg/sec)", -100, 100);
DlgCheck(5,"Stimulate");
DlgReal(6, "Pulse duration (ms)", 0, 5000);
DlgReal(7, "Interpulse interval (ms)", 0, 5000);
DlgCheck(8, "Light");
DlgReal(9, "Light duration (ms)", 0, 5000);
DlgReal(10, "Start time rel. step", 0, 5000);
DlgShow(stepPeriod, stepLength, step_AmpChair, step_AmpChair, stepStim, pulseDuration, pulseInterval, stepLight, lightDur, lightStart);
ToolbarStepConfig%();
Return (1);
End
'--------------------------------------------------------------------------------
' STIM/PULSE FUNCTIONS
'--------------------------------------------------------------------------------
Func ToolbarStimOn%()
if fullPulse = 1 then
SampleKey( "Q" );
else
SampleKey("P");
endif;
sineOn% := 0;
Yield();
Toolbarset(PulsePos,"Pulse Off", ToolbarStimOff%);
Return( 1 );
End
Func ToolbarStimOff%()
SampleKey( "p" );
Yield();
SampleKey( "I" );
Yield();
sineOn% := 0;
Toolbarset(PulsePos,"Pulse On", ToolbarStimOn%);
Return( 1 );
End
'--------------------------------------------------------------------------------
' OTHER FUNCTIONS
'--------------------------------------------------------------------------------
Proc ToolbarConfig()
ToolbarClear(); 'Remove any old buttons
ToolbarSet(0, "Idle",ToolbarIdle%);
ToolbarSet(1, "Quit", ToolbarQuit%);
ToolbarSet(InitPos, "Init", ToolbarInit%);
ToolbarSet(LightPos, "Light On", ToolbarLightOn%);
ToolbarSet(LaserPos, "Lasers On", ToolbarLasersOn%);
ToolbarSet(SinePos, "Sine On", ToolbarSineStart%);
ToolbarSet(CustomWaveformPos, "Custom Waveform On", ToolbarCustomWaveformStart%);
ToolbarSet(SineConfigPos, "Sine Config", ToolbarSineConfig%);
ToolbarSet(PulseConfigPos, "Pulse Config", ToolbarPulseConfig%);
ToolbarSet(PulsePos, "Pulse On", ToolbarStimOn%);
ToolbarSet(VidPos, "Video On", ToolbarVidOn%);
ToolbarSet(StepPos, "Step On", ToolbarStepOn%);
ToolbarSet(StepConfigPos, "Step Config", StepConfigWindow%);
ToolbarSet(ExpmtPos, "Run Expmt", ToolbarRunExpmt%);
ToolbarSet(ExpmtConfigPos, "Expmt Config", ToolbarConfigExpmt%);
ToolbarSet(CommentPos, "Comment", ToolbarComment%);
ToolbarSet(NewFilePos, "New File", ToolbarNew%);
ToolbarSet(devPos, "Dev", DevParams%);
Toolbar("", 231);
End
Func chanLayout%()
DlgCreate("Channel Layout"); 'Start new dialog for entering step commands
DlgList(1,"Layout: ","default|Trace 2020|Alex 2020");
DlgShow(layoutChoice);
docase
case layoutChoice = 0 then
chanLayout_default%();
case layoutChoice = 1 then
chanLayout_Trace2020%();
case layoutChoice = 2 then
chanLayout_Alex2020%();
endcase
Return (1);
End
Func chanLayout_default%()
HTVELChCom% := 1;
HHVELChCom% := 2;
htposCh% := 3;
hhposCh% := 4;
heposCh1% := 5;
heposCh2% := 6;
ephysch% := 7;
hhvelCh% := 8;
htvelCh% := 13;
TTL1ch% := 9;
TTL2ch% := 10;
TTL3ch% := 11;
TTL4ch% := 12;
setChannels%();
'Create a spike2 data file and make the new window visible immediately
SampleWindow% := FileNew(0,1);
' Channel Order
ChanHide(-1);
ChanShow(1,2,3,4,5,6,7,8,9,10,11,12,13,14,30,31);
ChanOrder(0, -1, "5, 4, 8, 13, 3, 2, 1, 12, 11, 10, 9, 30, 31");
' Initial Channel y-range
YRange( HTVELChCom%, -10, 10 );
YRange( HHVELChCom%, -10, 10 );
YRange( htposCh%, -10, 10 );
YRange( hhposCh%, -10, 10 );
YRange( heposCh1%, -10, 10 );
YRange( heposCh2%, -10, 10 );
YRange( ephysch%, -10, 10 );
YRange( hhvelCh% , -10, 10 );
' Initial Channel x-range
XRange( 0, 20);
' Make Command Channels Smaller'
ChanWeight(HTVELChCom%,.5);
ChanWeight(HHVELChCom%,.5);
' Background Colour'
ViewColour(0,5);
' Font
FontSet("Verdana", 8, 0);
' Channel colors
chanColour(HTVELChCom%, 1, 28);
chanColour(htposCh%, 1, 28);
chanColour(htvelCh%, 1, 28);
chanColour(HHVELChCom%, 1, 30);
chanColour(hhposCh%, 1, 30);
chanColour(hhvelCh%, 1, 30);
chanColour(heposCh1%, 1, 1);
chanColour(heposCh2%, 1, 1);
' Useful Zero line indicators
HCursorNew(1);
HCursor(1, 0, HTVELChCom%);
HCursorNew(2);
HCursor(2, 0, HHVELChCom%);
HCursorNew(3);
HCursor(3, 0, htposCh%);
HCursorNew(4);
HCursor(4, 0, hhposCh%);
HCursorNew(5);
HCursor(5, 0, hhvelCh%);
HCursorNew(6);
HCursor(6, 0, htvelCh%);
'Create a spike2 data file and make the new window visible immediately
SampleWindow% := FileNew(0,1);
return(1)
End
Func chanLayout_trace2020%()
HHVELChCom% := 1;
hhposCh% := 2;
hhvelCh% := 3;
HTVELChCom% := 4;
htposCh% := 5;
htvelCh% := 6;
heposCh1% := 7;
heposCh2% := 8;
ephysch% := 9;
TTL1ch% := 10;
TTL2ch% := 11;
TTL3ch% := 12;
TTL4ch% := 13;
var HTPOSChCom% := 14;
setChannels%();
' Clear channels going to be replaced'
SampleClear(HTVELChCom%);
SampleClear(htvelCh%);
SampleClear(htposCh%);
SampleWaveform(HTPOSChCom%,0,1000);
SampleCalibrate(HTPOSChCom%,"deg", DrumVoltage2Velocity, DrumVoltage2VelocityC);
SampleTitle$(HTPOSChCom%,"HTPOS");
SampleComment$(HTPOSChCom%, "Position Signal sent to drum");
' Horizontal Target Position - Talker
SampleTalker(htposCh%,"LS7366",0);
SampleCalibrate(htposCh%, "deg", 1111.111, 0);
SampleTitle$(htposCh%, "DrumPos");
SampleComment$(htposCh%,"Drum Position");
'Create a spike2 data file and make the new window visible immediately
SampleWindow% := FileNew(0,1);
' Horizontal Target Velocity - virtual Channel
var htvelCh% := VirtualChan(0,"");
VirtualChan(htvelCh%, "rm(5)", 0, 0.001);
'VirtualChan(htvelCh%, "rm(5)");
ChanProcessAdd(htvelCh%, 3);
ChanProcessArg(htvelCh%, 1, 1, 0.006);
ChanTitle$(htvelCh%, "htvel");
' Horizontal Target Velocity Command - virtual Channel
var HTVELChCom% := VirtualChan(0,"");
VirtualChan(HTVELChCom%, "ch(14)", 0, 0.001);
'VirtualChan(HTVELChCom%, "ch(14)");
ChanProcessAdd(HTVELChCom%, 3);
ChanProcessArg(HTVELChCom%, 1, 1, 0.006);
ChanTitle$(HTVELChCom%, "HTVEL");
' Channel Order
ChanHide(-1);
ChanShow(1,2,3,4,5,6,7,8,9,10,11,12,13,14,30,31, "v1", "v2");
ChanOrder(0, -1, "2, 3, 14, v2, 4, 5, v1, 7, 8, 9, 10, 11, 12, 13, 30, 31");
' Initial Channel y-range
YRange( HTVELChCom%, -10, 10 );
YRange( HHVELChCom%, -10, 10 );
YRange( htposCh%, -10, 10 );
YRange( hhposCh%, -10, 10 );
YRange( heposCh1%, -10, 10 );
YRange( heposCh2%, -10, 10 );
YRange( ephysch%, -10, 10 );
YRange( hhvelCh% , -10, 10 );
' Initial Channel x-range
XRange( 0, 20);
' Make Command Channels Smaller'
'ChanWeight(HTVELChCom%,.5);
ChanWeight(HHVELChCom%,.5);
' Background Colour'
ViewColour(0,5);
' Font
FontSet("Verdana", 8, 0);
' channel colors
chanColour(heposCh1%, 1, 1);
chanColour(heposCh2%, 1, 1);
ChanColourSet(htvelCh%, 1, 0.501961, 0, 1);
ChanColourSet(htposCh%, 1, 0.501961, 0, 0.752941);
ChanColourSet(HTVELChCom%, 1, 0.501961, 0, 0.501961);
ChanColourSet(HTPOSChCom%, 1, 0.501961, 0, 0.501961);
ChanColourSet(hhvelCh%, 1, 0, 1, 0);
ChanColourSet(hhposCh%, 1, 0, 0.752941, 0);
ChanColourSet(HHVELChCom%, 1, 0, 0.501961, 0);
' Useful Zero line indicators
HCursorNew(1);
HCursor(1, 0, HTVELChCom%);
HCursorNew(2);
HCursor(2, 0, HHVELChCom%);
HCursorNew(3);
HCursor(3, 0, htposCh%);
HCursorNew(4);
HCursor(4, 0, hhposCh%);
HCursorNew(5);
HCursor(5, 0, hhvelCh%);
HCursorNew(6);
HCursor(6, 0, htvelCh%);
Return(1)
End
Func chanLayout_alex2020%()
HTVELChCom% := 1;
HHVELChCom% := 2;
htposCh% := 3;
hhposCh% := 4;
heposCh1% := 5;
heposCh2% := 6;
ephysch% := 7;
hhvelCh% := 8;
htvelCh% := 13;
TTL1ch% := 9;
TTL2ch% := 10;
TTL3ch% := 11;
TTL4ch% := 12;
const TTL5ch% := 15;
setChannels%();
' New Channel(s)
' Channel 15
SampleEvent(TTL5ch%,4,2,1000);
SampleTitle$(TTL5ch%,"TTL5");
SampleComment$(TTL5ch%, "TTL5: FP Pulse");
'Create a spike2 data file and make the new window visible immediately
SampleWindow% := FileNew(0,1);
' Channel Order
ChanHide(-1);
ChanShow(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,30,31);
ChanOrder(0, -1, "5, 4, 8, 13, 3, 2, 1, 12, 11, 10, 9, 30, 31, 15");
' Initial Channel y-range
YRange( HTVELChCom%, -10, 10 );
YRange( HHVELChCom%, -10, 10 );
YRange( htposCh%, -10, 10 );
YRange( hhposCh%, -10, 10 );
YRange( heposCh1%, -10, 10 );
YRange( heposCh2%, -10, 10 );
YRange( ephysch%, -10, 10 );
YRange( hhvelCh% , -10, 10 );
' Initial Channel x-range
XRange( 0, 20);
' Make Command Channels Smaller'
ChanWeight(HTVELChCom%,.5);
ChanWeight(HHVELChCom%,.5);
' Background Colour'
ViewColour(0,5);
' Font
FontSet("Verdana", 8, 0);
' Channel colors
chanColour(HTVELChCom%, 1, 28);
chanColour(htposCh%, 1, 28);
chanColour(htvelCh%, 1, 28);
chanColour(HHVELChCom%, 1, 30);
chanColour(hhposCh%, 1, 30);
chanColour(hhvelCh%, 1, 30);
chanColour(heposCh1%, 1, 1);
chanColour(heposCh2%, 1, 1);
' Useful Zero line indicators
HCursorNew(1);
HCursor(1, 0, HTVELChCom%);
HCursorNew(2);
HCursor(2, 0, HHVELChCom%);
HCursorNew(3);
HCursor(3, 0, htposCh%);
HCursorNew(4);
HCursor(4, 0, hhposCh%);
HCursorNew(5);
HCursor(5, 0, hhvelCh%);
HCursorNew(6);
HCursor(6, 0, htvelCh%);
Return(1)
End
Func setChannels%();
SampleClear(); 'Set the sampling configuration to a standard state
'sequencer setup - returns zero if OK
var err%; err% := SampleSequencer( SequencerFile$ );
if err%<0 then
Message(Print$("I can't find your Sequencer File:%s",Error$(err%)));
halt
endif
' Horizontal Target Velocity COMMAND
SampleWaveform(HTVELChCom%,0,1000);
SampleCalibrate(HTVELChCom%,"deg/s", DrumVoltage2Velocity, DrumVoltage2VelocityC);
SampleTitle$(HTVELChCom%,"HTVEL");
SampleComment$(HTVELChCom%, "Velocity Signal sent to drum");
' Horizontal Head Velocity COMMAND
SampleWaveform(HHVELChCom%,1,1000);
SampleCalibrate( HHVELChCom%, "deg/s", ChairVoltage2Velocity, ChairVoltage2VelocityC);
SampleTitle$(HHVELChCom%,"HHVEL");
SampleComment$(HHVELChCom%, "Velocity Signal sent to chair");
' Horizontal Target Position
SampleWaveform(htposCh%,2,1000);
SampleCalibrate(htposCh%, "deg", DrumPosReadoutScale, DrumPosReadoutOffset);
SampleTitle$(htposCh%,"htpos");
SampleComment$(htposCh%, "Drum position");
' Horizontal Head Position
SampleWaveform(hhposCh%,3,1000);
SampleCalibrate(hhposCh%,"deg", ChairPosReadoutScale, ChairPosReadoutOffset);
SampleTitle$(hhposCh%,"hhpos");
SampleComment$(hhposCh%, "Chair Position");
' Horizontal Target Velocity
SampleWaveform(htvelCh%,8,1000);
SampleCalibrate(htvelCh%,"deg/s",DrumVelReadoutScale,DrumVelReadoutOffset);
SampleTitle$(htvelCh%,"htvel");
SampleComment$(htvelCh%, "Drum Velocity");
' Horizontal Head Velocity
SampleWaveform(hhvelCh%,7,1000);
SampleCalibrate(hhvelCh%,"deg/s",ChairVelReadoutScale,ChairVelReadoutOffset);
SampleTitle$(hhvelCh%,"hhvel");
SampleComment$(hhvelCh%, "Chair velocity");
' Horizontal Eye Position 1
SampleWaveform(heposCh1%,4,1000);
SampleCalibrate(heposCh1%,"V",EyeVoltage2Position,EyeVoltage2PositionC);
SampleTitle$(heposCh1%,"hepos1");
SampleComment$(heposCh1%, "Eye Position 1");
' Horizontal Eye Position 2
SampleWaveform(heposCh2%,5,1000);
SampleCalibrate(heposCh2%,"V", EyeVoltage2Position,EyeVoltage2PositionC);
SampleTitle$(heposCh2%,"hepos2");
SampleComment$(heposCh2%, "Eye Position 2");
'Channel 7 UCOMMENT THIS FOR EPHYS
'SampleWaveform(ephysch,6,1000);
'SampleCalibrate(ephysch,"V",1,0);
'SampleTitle$(ephysch,"ephys");
'SampleComment$(ephysch, "ephys");
'Channel 7 UNCOMMENT THIS FOR HD MOTOR
'SampleTalker(3,"LS7366",1000);
'SampleCalibrate(3,"deg",1111.111,0);
'SampleTitle$(3,"DrumPos");
'SampleComment$(3,"Drum Position");
' TTL1: Shutter/LED/Light
SampleEvent(TTL1ch%,0,2,1000);
SampleTitle$(TTL1ch%,"TTL1");
SampleComment$(TTL1ch%, "TTL1: Shutter");
' TTL2: IR LED (used to be used for calibration, not used as of Feb 2020)
SampleEvent(TTL2ch%,1,2,1000);
SampleTitle$(TTL2ch%,"TTL2");
SampleComment$(TTL2ch%, "TTL2: IR LED");
' TLL3: Left Laser
SampleEvent(TTL3ch%,2,2,1000);
SampleTitle$(TTL3ch%,"TTL3");
SampleComment$(TTL3ch%, "TTL3: L laser");
' TTL4: Right Laser
SampleEvent(TTL4ch%,3,2,1000);
SampleTitle$(TTL4ch%,"TTL4");
SampleComment$(TTL4ch%, "TTL4: R laser");
'Channel 30
SampleTextMark(200);
'Set optimise mode (do this last)
SampleOptimise(1,1,0,2,50);
'Continuous sampling
SampleMode(1);
SetSequencerValues();
return(1);
End
Func ToolbarNew%()
' Ask User what layout they want'
chanLayout%();
' Make window full screen
WindowVisible(3);
Return (1);
End
Func ToolbarComment%()
DlgCreate("Comment"); 'Start new dialog for entering comments
DlgString(1,"Comment",200);
DlgShow(comment$);
SampleText(comment$);
Return(1);
End
Func ToolbarRunExpmt%()
runExpmt% := 1;
rep% := 0; 'Rep (5min run, 40 sec test)
test% := 0; 'test: 0=run testLength, 1=test testLength, 2=init&wait 20 sec, 3=init&wait 10 sec, 4=init&wait runLength
testrep% := 0; ' Changed from 0 to 1 5/2/14 so that VORD is only tested once at the beginning
goalTime := MaxTime();
SampleKey("H");
ToolbarSet(ExpmtPos, "Quit Expmt",ToolbarQuitExpmt%);
Return(1);
End
Func ToolbarQuitExpmt%()
runExpmt% := 0;
ToolbarInit%();
SampleKey("h");
ToolbarSet(ExpmtPos, "Run Expmt",ToolbarRunExpmt%);
Return(1)
End
Func ToolbarInit%()
ToolbarLightOff%(); Yield();
ToolbarStepOff%(); Yield();
ToolbarSineStop%(); Yield(.01);
ToolbarStimoff%(); Yield();
ToolbarLasersOff%(); Yield();
prevTime := 0; ' Reset prev time so sine offset code continues running in a new file
SampleKey( "I" );
Return( 1 );
End
Func ToolbarQuit%()
SampleKey( "O" );
Return( 0 );
End
Func DevParams%()
DlgCreate("Dev Params"); 'Start new dialog
DlgReal(1,"W",-2,2);
DlgReal(2,"X",-2,2);
DlgReal(3,"Y",-2,2);
DlgReal(4,"Z",-2,2);
DlgShow(W, X, Y, Z);
Return(1);
end
' Send values to the sequencer
Proc SetSequencerValues()
actualChairPh := ((sinPhChair + pulsePhase + 180) mod 360) - 180;
actualDrumPh := ((sinPhDrum + pulsePhase + 180) mod 360) - 180;
'Chair parameters
SampleSeqVar( 23, ChairAmp2Int32%( ChairDegreesPerSecondOffset ) );
SampleSeqVar( 27, ChairAmp2Int16%( sinAmpChair ) );
SampleSeqVar( 28, Angle2Int32%( actualChairPh ) );
SampleSeqVar( 29, Hz2Int32%( sinHzChair ) );
SampleSeqVar( 55, ChairResetDirection); 'default chair direction
'Drum parameters
SampleSeqVar( 22, DrumAmp2Int32%( DrumDegreesPerSecondOffset ) );
SampleSeqVar( 24, DrumAmp2Int16%( sinAmpDrum ) );
SampleSeqVar( 25, Angle2Int32%( actualDrumPh ) );
SampleSeqVar( 26, Hz2Int32%( sinHzDrum ) );
SampleSeqVar( 65, DrumResetDirection); 'default drum direction
'Pulse parameters
SampleSeqVar( 33, pWait );
SampleSeqVar( 34, pNumber );
SampleSeqVar( 35, pDuration);
SampleSeqVar( 36, pInterval);
SampleSeqVar( 37, pStart);
'Step parameters
SampleSeqVar( 38, sRest2);
SampleSeqVar( 39, sStart);
SampleSeqVar( 40, sLength);
SampleSeqVar( 41, sLength1);
SampleSeqVar( 42, sRest1);
SampleSeqVar( 43, sAmpChair);
SampleSeqVar( 44, sAmpDrum);
SampleSeqVar( 45, sAmpChairN);
SampleSeqVar( 46, sAmpDrumN);
SampleSeqVar( 47, stepLen1); ' For delayed light pulse with step
SampleSeqVar( 48, stepLen2);
SampleSeqVar( 49, stepLen3);
SampleSeqVar( 50, pulseDurationV);
SampleSeqVar( 51, pulseWaitV);
SampleSeqVar( 52, pulsePeriod);
SampleSeqVar( 54, everyNCycles);
SampleSeqVar( 55, QueTime );
SampleSeqVar( 56, DrumAmp2Int32%( DrumDegreesPerSecondOffsetDefault ) );
SampleSeqVar( 57, ChairAmp2Int32%( ChairDegreesPerSecondOffsetDefault ) );
SampleSeqVar( 58, halfPhaseDelay);
'Rotation Parameters
SampleSeqVar( 66, rotationVelocity); 'This is a relative value
End
Func driftFix%()
'drift back to 0 if sine wave isn't running
docase
case stepOn% = 1 then
'SampleKey("7");
if step_AmpChair > 0 then
'SampleKey("8");
centerLineChair := (stepLength/1000) * step_AmpChair * W;
endif
if step_AmpChair < 0 then
'SampleKey("9");
centerLineChair := (stepLength/1000) * step_AmpChair * X;
endif
if step_AmpChair = 0 then
'SampleKey("0");
centerLineChair := 0;
endif
if step_AmpChair > 0 then
'SampleKey("7");
centerLineDrum := (stepLength/1000) * step_AmpChair * Y;
endif
if step_AmpChair < 0 then
'SampleKey("6");
centerLineDrum := (stepLength/1000) * step_AmpChair * Z;
endif
if step_AmpChair = 0 then
centerLineDrum := 0;
endif
case sineOn% = 1 or vidOn = 1 then
var chairSign := 1; 'set default to 1 if phase = 0'
var drumSign := 1;
'figure out whether we want velocity to be positive or negative'
if sinPhChair <> 0 then
chairSign := sinPhChair / Abs(sinPhChair);
endif
if sinPhDrum <> 0 then
drumSign := sinPhDrum / Abs(sinPhDrum);
endif
'convert from the sine amplitude signal to the actual position amplitude'
var trueAmpChair := sinAmpChair / (2 * 3.14159 * sinHzChair);
var trueAmpDrum := sinAmpDrum / (2 * 3.14159 * sinHzDrum);
'calculates the center y value according to the phase given'
var centerForPhaseChair := trueAmpChair * (1 - cos((-1 * sinPhChair)/radianConversion));
var centerForPhaseDrum := trueAmpDrum * (1 - cos((-1 * sinPhDrum)/radianConversion));
'takes into account that chair/drum may not start at 0'
var theoreticalCenterChair := (centerForPhaseChair + measuredZeroChair) * chairSign;
var theoreticalCenterDrum := (centerForPhaseDrum + measuredZeroDrum) * drumSign;
'NOTE: there is something funky with the motors where there is an error that follows a sine wave from phase'
'WE DON'T KNOW WHY, ONLY THAT IT HAPPENS'
'the drift coefficients need to be calculated manually by testing the error for different phase offsets'
var errorOffsetChair := ChairDriftFactor * sinAmpChair * sin(2 * sinPhChair / radianConversion);
var errorOffsetDrum := DrumDriftFactor * sinAmpDrum * sin(2 * sinPhDrum / radianConversion);
centerLineChair := (theoreticalCenterChair + errorOffsetChair) * ChairResetDirection;
centerLineDrum := (theoreticalCenterDrum + errorOffsetDrum) * DrumResetDirection;
else
centerLineChair := 0;
centerLineDrum := 0;
endcase
prevTime := MaxTime();
' Measure slope from last 1 cycle of chair/drum position feedback
var hhposSlope := ChanValue(hhposCh%, prevTime) - ChanValue(hhposCh%, prevTime-(1/sinHzChair));
var htposSlope := ChanValue(htposCh%, prevTime) - ChanValue(htposCh%, prevTime-(1/sinHzDrum));
var hhposPos := ChanMeasure(hhposCh%, 2, prevTime-(1/sinHzChair), prevTime) + (centerLineChair);
var htposPos := ChanMeasure(htposCh%, 2, prevTime-(1/sinHzDrum), prevTime) + (centerLineDrum);
' Scales *1 for D253, *-1 for D019
ChairDegreesPerSecondOffset := (ChairDegreesPerSecondOffsetDefault - hhposSlope/4 - hhposPos/4) * ChairResetDirection;
DrumDegreesPerSecondOffset := (DrumDegreesPerSecondOffsetDefault - htposSlope/4 - htposPos/4) * DrumResetDirection;
'ToolbarStepConfig%();
SetSequencerValues();
End
'--------------------------------------------------------------------------------
' CONVERSION FUNCTIONS
'--------------------------------------------------------------------------------
' Angles in the range [-180,180] should span [-2147483648.0,2147483647.0]
Func Angle2Int32%( angle )
Return( angle * 2147483647.0 / 180 );
End
' Rates are calculated in degrees per sequencer step, with one degree being 11930465.
Func Hz2Int32%( hz )
'This assumes a sequencer rate of 1 kHz.
Return( hz * 11930465 * 360 / 1000 );
End
' Amplitudes must be converted such that [ 0, 32768 ] spans the positive range of the dac, e.g. [0, 5 ]
' We have to include the dac maximum and the degrees-per-second-to-voltage conversion factor. Does not include offset.
Func ChairAmp2Int16%( amp )
Return( amp * ChairDegreesPerSecond2Voltage * 32768 / MaxVoltage ) ;
End
Func DrumAmp2Int16%( amp )
Return( amp * DrumDegreesPerSecond2Voltage * 32768 / MaxVoltage ) ;
End
Func ChairAmp2Int32%( amp )
Return( amp * ChairDegreesPerSecond2Voltage * 2147483647 / MaxVoltage ) ;
End
Func DrumAmp2Int32%( amp )
Return( amp * DrumDegreesPerSecond2Voltage * 2147483647 / MaxVoltage ) ;
End
' steps
' Command velocities must be converted such that [ 0, 2147483647 ] spans the positive range of the dac, e.g. [0, 5 ]
' We have to include the dac maximum and the degrees-per-second-to-voltage conversion factor.
Func ChairVel2Int32%( amp )
Return( (amp + ChairDegreesPerSecondOffset) * ChairDegreesPerSecond2Voltage* 2147483647 / MaxVoltage );
End
Func DrumVel2Int32%( amp )
Return( (amp + DrumDegreesPerSecondOffset) * DrumDegreesPerSecond2Voltage * 2147483647 / MaxVoltage );
End