private const double refractory = 1; // in seconds internal IISZapper(int phaseWidth, double amplitude, int channel, int numPulses, double rate, Task stimDigitalTask, Task stimAnalogTask, DigitalSingleChannelWriter stimDigitalWriter, AnalogMultiChannelWriter stimAnalogWriter, double deviceRefreshRate, NeuroRighter sender) { const int prePadding = 100; const int postPadding = 100; const double offsetVoltage = 0.0; const int interPhaseLength = 0; this.stimDigitalTask = stimDigitalTask; this.stimDigitalWriter = stimDigitalWriter; this.stimAnalogTask = stimAnalogTask; this.stimAnalogWriter = stimAnalogWriter; this.channel = channel - 1; sp = new StimPulse(phaseWidth, phaseWidth, amplitude, -amplitude, channel, numPulses, rate, offsetVoltage, interPhaseLength, prePadding, postPadding, true); stimAnalogTask.Timing.SamplesPerChannel = numPulses * sp.analogPulse.GetLength(1); stimDigitalTask.Timing.SamplesPerChannel = numPulses * sp.digitalData.GetLength(0); totalNumReadsTraining = (int)(numSecondsTraining / deviceRefreshRate); totalNumReadsRefractory = (int)(refractory / deviceRefreshRate); numReadsRefractory = totalNumReadsRefractory; }
internal IISZapper(int phaseWidth, double amplitude, int channel, int numPulses, double rate, Task stimDigitalTask, Task stimAnalogTask, DigitalSingleChannelWriter stimDigitalWriter, AnalogMultiChannelWriter stimAnalogWriter, double deviceRefreshRate, NeuroRighter sender) { const int prePadding = 100; const int postPadding = 100; const double offsetVoltage = 0.0; const int interPhaseLength = 0; this.stimDigitalTask = stimDigitalTask; this.stimDigitalWriter = stimDigitalWriter; this.stimAnalogTask = stimAnalogTask; this.stimAnalogWriter = stimAnalogWriter; this.channel = channel - 1; sp = new StimPulse(phaseWidth, phaseWidth, amplitude, -amplitude, channel, numPulses, rate, offsetVoltage, interPhaseLength, prePadding, postPadding, true); stimAnalogTask.Timing.SamplesPerChannel = numPulses * sp.analogPulse.GetLength(1); stimDigitalTask.Timing.SamplesPerChannel = numPulses * sp.digitalData.GetLength(0); totalNumReadsTraining = (int)(numSecondsTraining / deviceRefreshRate); totalNumReadsRefractory = (int)(refractory / deviceRefreshRate); numReadsRefractory = totalNumReadsRefractory; }
internal void populate(Boolean addTrigger) { //Compute total length of pulse, in samples int totalLength = 0; for (int c = 0; c < interpulseIntervals.Count; ++c) { totalLength += interpulseIntervals[c]; //All interpulse intervals } totalLength += prePadding[0]; //The 'off' time of first pulse totalLength += postPadding[channel.Count - 1]; //'off' time of last pulse totalLength += width1[channel.Count - 1] + width2[channel.Count - 1] + interphaseLength[channel.Count - 1]; //and length of last pulse if (addTrigger) //If trigger is being added to end, add that length too { totalLength += 1 + StimPulse.STIM_SAMPLING_FREQ * WATCH_TIME / 1000; } //This experiment REQUIRES triggers, therefore MUST use 32-bit ports!!! int numRows = 4; if (Properties.Settings.Default.StimPortBandwidth != 32) { System.Windows.Forms.MessageBox.Show("Must use 32-bit port for this experiment, since triggers must be used.", "Port-size error"); return; } //Set aside space for analog pulse analogPulse = new double[numRows, totalLength]; //Only make one pulse of train, the padding zeros will ensure proper rate when sampling is regenerative digitalData = new UInt32[totalLength + 2 * (StimPulse.NUM_SAMPLES_BLANKING + 2)]; //Bookkeeping variable for constructing pulse int offset = 0; for (int c = 0; c < channel.Count; ++c) //for each pulse { //Setup voltage waveform, pos. then neg. int size = Convert.ToInt32((((double)width1[c] + (double)width2[c]) / 1000000.0) * StimPulse.STIM_SAMPLING_FREQ + prePadding[c] + postPadding[c] + interphaseLength[c]); //Num. pts. in pulse //What was that doing? Convert width to seconds, divide by sample duration, mult. by //two since the pulse is biphasic, add padding to both sides #region AnalogPulseCreation //v1 and v2 encode channel number double v1 = Math.Ceiling((double)channel[c] / 8.0); double v2 = (double)((channel[c] - 1) % 8) + 1.0; for (int j = 0; j < prePadding[c]; ++j) { analogPulse[2, j + offset] = offsetVoltage[c]; } for (int j = prePadding[c]; j < prePadding[c] + Convert.ToInt32(((double)width1[c] / 1000000.0) * StimPulse.STIM_SAMPLING_FREQ); ++j) { analogPulse[2, j + offset] = amp1[c] + offsetVoltage[c]; } for (int j = prePadding[c] + Convert.ToInt32(((double)width1[c] / 1000000.0) * StimPulse.STIM_SAMPLING_FREQ); j < prePadding[c] + Convert.ToInt32(((double)width1[c] / 1000000.0) * StimPulse.STIM_SAMPLING_FREQ) + interphaseLength[c]; ++j) { analogPulse[2, j + offset] = offsetVoltage[c]; } for (int j = prePadding[c] + Convert.ToInt32(((double)width1[c] / 1000000.0) * StimPulse.STIM_SAMPLING_FREQ) + interphaseLength[c]; j < size - postPadding[c]; ++j) { analogPulse[2, j + offset] = amp2[c] + offsetVoltage[c]; } for (int j = size - postPadding[c]; j < size; ++j) { analogPulse[2, j + offset] = offsetVoltage[c]; } for (int j = prePadding[c]; j < 20 + prePadding[c]; ++j) { analogPulse[3, j + offset] = v1; } for (int j = 20 + prePadding[c]; j < 40 + prePadding[c]; ++j) { analogPulse[3, j + offset] = v2; } for (int j = 40 + prePadding[c]; j < 60 + prePadding[c]; ++j) { analogPulse[3, j + offset] = amp1[c]; } for (int j = 60 + prePadding[c]; j < 80 + prePadding[c]; ++j) { analogPulse[3, j + offset] = (double)(width1[c]) / 100.0; } //Add trigger, if applicable if (addTrigger && c == channel.Count - 1) { for (int j = size; j < StimPulse.STIM_SAMPLING_FREQ * WATCH_TIME / 1000; ++j) { analogPulse[0, j + offset] = 4.0; //4 Volts, TTL-compatible } analogPulse[0, analogPulse.GetLength(1) - 1] = 0.0; } #endregion #region DigitalPulseCreation //Get data bits lined up to control MUXes UInt32 temp; if (c == 0) { temp = StimPulse.channel2MUX((double)channel[c]); } else { temp = StimPulse.channel2MUX((double)channel[c], true, false); //select channel without start trigger for AO } UInt32 temp_noEn = StimPulse.channel2MUX_noEN((double)channel[c]); UInt32 temp_blankOnly = Convert.ToUInt32(Math.Pow(2, (Properties.Settings.Default.StimPortBandwidth == 32 ? BLANKING_BIT_32bitPort : BLANKING_BIT_8bitPort))); for (int j = 1; j <= StimPulse.NUM_SAMPLES_BLANKING; ++j) { digitalData[j + offset] = temp_blankOnly; } digitalData[StimPulse.NUM_SAMPLES_BLANKING + 1 + offset] = temp_noEn; for (int j = StimPulse.NUM_SAMPLES_BLANKING + 2; j < size + StimPulse.NUM_SAMPLES_BLANKING + 2; ++j) { digitalData[j + offset] = temp; } digitalData[size + StimPulse.NUM_SAMPLES_BLANKING + 2 + offset] = temp_noEn; for (int j = size + StimPulse.NUM_SAMPLES_BLANKING + 3; j < size + 2 * StimPulse.NUM_SAMPLES_BLANKING + 3; ++j) { digitalData[j + offset] = temp_blankOnly; } #endregion //Update offset to account for interphase length if (c < interpulseIntervals.Count) { offset += interpulseIntervals[c]; //this has one less member than all the stimpulses } //NB: this form of offset changing assumes homogeneous prepaddings } }
private void bw_stim_DoWork(object sender, DoWorkEventArgs e) { //Get pulse arguments double[] stim_params = (double[])e.Argument; //Select between uni- and biphasic pulses int phase2Width = (int)stim_params[0]; if (radioButton_OnDemandUniphasic.Checked) phase2Width = 0; if (stim_params[3] * 1000 / stim_params[4] < 500) { //Create pulse StimPulse sp = new StimPulse((int)stim_params[0], phase2Width, stim_params[1], -stim_params[1], (int)stim_params[2], (int)stim_params[3], (int)stim_params[4], (double)stim_params[5], (int)stim_params[6], 10, 10, true); if (stim_params[3] == 1) { stimPulseTask.Timing.SamplesPerChannel = sp.analogPulse.GetLength(1); stimDigitalTask.Timing.SamplesPerChannel = sp.digitalData.Length; } //Write stimPulseWriter.WriteMultiSample(true, sp.analogPulse); if (Properties.Settings.Default.StimPortBandwidth == 32) stimDigitalWriter.WriteMultiSamplePort(true, sp.digitalData); else if (Properties.Settings.Default.StimPortBandwidth == 8) stimDigitalWriter.WriteMultiSamplePort(true, StimPulse.convertTo8Bit(sp.digitalData)); DateTime stimStartTime = DateTime.Now; stimStopTime = stimStartTime.AddMilliseconds(((double)stim_params[3] * 1000.0) / (double)stim_params[4]); //timer.Enabled = true; stimPulseTask.WaitUntilDone(); stimDigitalTask.WaitUntilDone(); stimPulseTask.Stop(); stimDigitalTask.Stop(); } else { //Make a single stim pulse, but with the correct number of zeros to insure proper rate //when task is regenerative StimPulse sp = new StimPulse((int)stim_params[0], phase2Width, stim_params[1], -stim_params[1], (int)stim_params[2], 1, (int)stim_params[4], (double)stim_params[5], (int)stim_params[6], 10, 10, true); if (stim_params[3] == 1) { stimPulseTask.Timing.SamplesPerChannel = sp.analogPulse.GetLength(1); stimDigitalTask.Timing.SamplesPerChannel = sp.digitalData.Length; } stimPulseWriter.WriteMultiSample(true, sp.analogPulse); //stimDigitalWriter.WriteWaveform(true, sp.digitalPulse); if (Properties.Settings.Default.StimPortBandwidth == 32) stimDigitalWriter.WriteMultiSamplePort(true, sp.digitalData); else if (Properties.Settings.Default.StimPortBandwidth == 8) stimDigitalWriter.WriteMultiSamplePort(true, StimPulse.convertTo8Bit(sp.digitalData)); DateTime stimStartTime = DateTime.Now; stimStopTime = stimStartTime.AddMilliseconds(((double)stim_params[3] * 1000.0) / (double)stim_params[4]); stimTimer = new System.Threading.Timer(stim_timer_tick, null, 100, 100); } }
private void bw_openLoop_DoWork(object sender, DoWorkEventArgs e) { //DEBUGGING stimPulseTask.Control(TaskAction.Verify); stimDigitalTask.Control(TaskAction.Verify); stim_params sp = (stim_params)e.Argument; //Create randomized list of channels int numStimChannels = sp.stimChannelList.GetLength(0); ArrayList chListSorted = new ArrayList(numStimChannels); int[] chListRand = new int[numStimChannels]; for (int i = 0; i < numStimChannels; ++i) chListSorted.Add(sp.stimChannelList[i]); Random r = new Random(); for (int i = 0; i < numStimChannels; ++i) { int j = r.Next(chListSorted.Count); chListRand[i] = (int)chListSorted[j]; chListSorted.RemoveAt(j); } StimPulse spulse = new StimPulse(sp.width1, sp.width2, sp.v1, sp.v2, chListRand, sp.rate, sp.offsetVoltage, sp.interphaseLength, sp.prephaseLength, sp.postphaseLength); stimPulseWriter.WriteMultiSample(true, spulse.analogPulse); if (Properties.Settings.Default.StimPortBandwidth == 32) stimDigitalWriter.WriteMultiSamplePort(true, spulse.digitalData); else if (Properties.Settings.Default.StimPortBandwidth == 8) stimDigitalWriter.WriteMultiSamplePort(true, StimPulse.convertTo8Bit(spulse.digitalData)); }
private void bw_genExpt_DoWork(object sender, DoWorkEventArgs e) { //NB: Within new threads, you shouldn't reference any of the main forms controls //expt_Params ep = (expt_Params)e.Argument; List<Object> exptParams = (List<Object>)e.Argument; //exptParams.Add(channels, numTrials, voltages, pulsesPerTrain, pulseWidths, trainRate); int[] channels = (int[])exptParams[0]; int numTrials = (int)exptParams[1]; double[] voltages = (double[])exptParams[2]; int[] pulsesPerTrain = (int[])exptParams[3]; int[] pulseWidths = (int[])exptParams[4]; int trainRate = (int)exptParams[5]; stimList = new ArrayList(channels.Length * voltages.Length * numTrials * pulseWidths.Length * pulsesPerTrain.Length); for (int i = 0; i < channels.Length; ++i) { for (int v = 0; v < voltages.Length; ++v) { for (int ppt = 0; ppt < pulsesPerTrain.Length; ++ppt) { for (int pw = 0; pw < pulseWidths.Length; ++pw) { for (int j = 0; j < numTrials; ++j) //Repeat each test 5x { StimPulse sp = new StimPulse(pulseWidths[pw], pulseWidths[pw], voltages[v], -voltages[v], channels[i], pulsesPerTrain[ppt], trainRate, 0.0, 0, 100, 100, false); stimList.Add(sp); } } } } } }