/// <summary> /// Creates a new RandomAccessScanner writing samples to the indicated channels /// </summary> /// <param name="lookupTable">The point-voltage conversion table to use</param> /// <param name="xChannel">The device and ao-channel for the x-mirror</param> /// <param name="yChannel">The device and ao-channel for the y-mirror</param> /// <param name="vMin">The minimum of the voltage range used on the Ao channels</param> /// <param name="vMax">The maximum of the voltage range used on the Ao channels</param> public RandomAccessScanner(PointVoltageConverter lookupTable, string xChannel, string yChannel, double vMin, double vMax) { if (!(vMin < vMax)) { throw new ArgumentException("Minimum voltage has to be smaller than maximum voltage"); } if (vMin < -10 || vMax > 10) { throw new ArgumentException("The minimum voltage can't be below -10 and the maximum voltage can't be above 10"); } _vMin = vMin; _vMax = vMax; //_xMirrorTask = new Task("AOXMirror"); //_xMirrorTask.AOChannels.CreateVoltageChannel(xChannel, "XOut", vMin, vMax, AOVoltageUnits.Volts); //_xWriter = new AnalogSingleChannelWriter(_xMirrorTask.Stream); //_yMirrorTask = new Task("AOYMirror"); //_yMirrorTask.AOChannels.CreateVoltageChannel(yChannel, "YOut", vMin, vMax, AOVoltageUnits.Volts); //_yWriter = new AnalogSingleChannelWriter(_yMirrorTask.Stream); _mirrorTask = new Task("AOMirror"); _mirrorTask.AOChannels.CreateVoltageChannel(xChannel, "XOut", vMin, vMax, AOVoltageUnits.Volts); _mirrorTask.AOChannels.CreateVoltageChannel(yChannel, "YOut", vMin, vMax, AOVoltageUnits.Volts); _multiWriter = new AnalogMultiChannelWriter(_mirrorTask.Stream); if (lookupTable != null && !lookupTable.Complete) { throw new ArgumentException("The provided lookup table has to be complete"); } CoordinateConverter = lookupTable; }
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; }
/// <summary> /// Perform AO task. /// </summary> /// <param name="volts">Voltage values to write.</param> public void AnalogWrite(params double[] volts) { if (analogOut != null) { try { AnalogMultiChannelWriter aw = new AnalogMultiChannelWriter(analogOut.Stream); double[] input = new double[analogOut.AOChannels.Count]; for (int i = 0; i < input.Length; i++) { try { input[i] = volts[i]; } catch { input[i] = 0; } } aw.WriteSingleSample(true, input); } catch (DaqException de) { log.Write(de.Message); } } }
/// <summary> /// Stops all acquisition and generation /// </summary> public void Stop() { if (!IsRunning) { return; } _writeThreadReady.Reset(); if (_writeThread != null) { _writeThread.Stop(); _writeThread.Dispose(); _writeThread = null; } if (_readThread != null) { _readThread.Stop(); _readThread.Dispose(); _readThread = null; } //Reset all writes to 0 Task resetTask = new Task("ChReset"); for (int i = 0; i < 3; i++) { resetTask.AOChannels.CreateVoltageChannel(HardwareSettings.DAQ.DeviceName + "/" + string.Format("AO{0}", i), "", -10, 10, AOVoltageUnits.Volts); } AnalogMultiChannelWriter resetWriter = new AnalogMultiChannelWriter(resetTask.Stream); resetWriter.WriteSingleSample(true, new double[3]); resetTask.Dispose(); pipeCanceller.Cancel(); IsRunning = false; }
public void OutputPatternAndWait(double[,] pattern) { AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(analogOutputTask.Stream); writer.WriteMultiSample(false, pattern); analogOutputTask.Start(); }
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; }
public void Setup_USB6008() { //Resets and configures the NI USB6008 Daq boards Device dev = DaqSystem.Local.LoadDevice(loc);//added to reset the DAQ boards if they fail to comunicate giving error code 50405 dev.Reset(); AIChannel StrainChannel, CurrentChannel; AOChannel LateralMotorChannel, TraverseMotorChannel; try { //Setting up NI DAQ for Axial Force Measurment via Strain Circuit and current Measurment of Spindle Motor for torque USB6008_AITask = new NationalInstruments.DAQmx.Task(); StrainChannel = USB6008_AITask.AIChannels.CreateVoltageChannel( loc + "/ai0", //Physical name of channel "strainChannel", //The name to associate with this channel AITerminalConfiguration.Differential, //Differential Wiring -0.1, //-0.1v minimum NIMaxVolt, //1v maximum AIVoltageUnits.Volts //Use volts ); CurrentChannel = USB6008_AITask.AIChannels.CreateVoltageChannel( loc + "/ai1", //Physical name of channel "CurrentChannel", //The name to associate with this channel AITerminalConfiguration.Differential, //Differential Wiring -0.1, //-0.1v minimum 10, //10v maximum AIVoltageUnits.Volts //Use volts ); USB6008_Reader = new AnalogMultiChannelReader(USB6008_AITask.Stream); //////////////////////////////////////////////////////////// USB6008_AOTask = new NationalInstruments.DAQmx.Task(); TraverseMotorChannel = USB6008_AOTask.AOChannels.CreateVoltageChannel( loc + "/ao0", //Physical name of channel) "TravverseMotorChannel", //The name to associate with this channel 0, //0v minimum 5, //5v maximum AOVoltageUnits.Volts ); LateralMotorChannel = USB6008_AOTask.AOChannels.CreateVoltageChannel( loc + "/ao1", //Physical name of channel) "LateralMotorChannel", //The name to associate with this channel 0, //0v minimum 5, //5v maximum AOVoltageUnits.Volts ); USB6008_Analog_Writter = new AnalogMultiChannelWriter(USB6008_AOTask.Stream); //////////////////////////////////////////////////////////// USB6008_DOTask = new NationalInstruments.DAQmx.Task(); USB6008_DOTask.DOChannels.CreateChannel(loc + "/port0", "port0", ChannelLineGrouping.OneChannelForAllLines); USB6008_Digital_Writter = new DigitalSingleChannelWriter(USB6008_DOTask.Stream); } catch (NationalInstruments.DAQmx.DaqException e) { Console.WriteLine("Error?\n\n" + e.ToString(), "NI USB 6008 1 Error"); } }
public void addAnalogOutputChannels(string[] channelNames, double[] minVol, double[] maxVol, double[,] wave) { outputWaveArray = wave; for (int ch = 0; ch < channelNames.Length; ch++) { string name = channelNames[ch]; string vname = "Voltage" + ch; task.AOChannels.CreateVoltageChannel(name, vname, minVol[ch], maxVol[ch], AOVoltageUnits.Volts); } aowriter = new AnalogMultiChannelWriter(task.Stream); }
internal void MakeWriters() { if (analogTask != null) { analogWriter = new AnalogMultiChannelWriter(analogTask.Stream); } if (digitalTask != null) { digitalWriter = new DigitalSingleChannelWriter(digitalTask.Stream); } }
//parts of setup that are specific to clearing and configuring tasks private void SetupTasks()//Task[] analogTasks, AnalogMultiChannelWriter[] analogWriters, Task[] digitalTasks, DigitalSingleChannelWriter[] digitalWriters) { //do outputbuffer-specific task configuration (which device/channels, ranges) SetupTasksSpecific(ref analogTasks, ref digitalTasks); //do general configuration stuff (clocks, starts, writemodes, buffer sizes) //analog analogWriters = new AnalogMultiChannelWriter[analogTasks.Length]; for (int i = 0; i < analogTasks.Length; i++) { //set timing off of the master task analogTasks[i].Timing.ReferenceClockSource = masterTask.Timing.ReferenceClockSource; analogTasks[i].Timing.ReferenceClockRate = masterTask.Timing.ReferenceClockRate; //set start triggers off of the buffer loading (counter) task analogTasks[i].Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( masterLoad, DigitalEdgeStartTriggerEdge.Rising); //configure the on board (hardware) buffer analogTasks[i].Stream.Buffer.OutputBufferSize = 2 * BUFFSIZE; //#soft! // analogTasks[i].Stream.WriteRegenerationMode = WriteRegenerationMode.DoNotAllowRegeneration; analogTasks[i].Stream.WriteRegenerationMode = WriteRegenerationMode.AllowRegeneration; //create a writer for this task analogWriters[i] = new AnalogMultiChannelWriter(analogTasks[i].Stream); //now that we've created a potential task configuration, check to make sure everything is kosher //actually set the hardware to these settings analogTasks[i].Control(TaskAction.Reserve); } digitalWriters = new DigitalSingleChannelWriter[digitalTasks.Length]; for (int i = 0; i < digitalTasks.Length; i++) { //configure the on board (hardware) buffer digitalTasks[i].Stream.Buffer.OutputBufferSize = 2 * BUFFSIZE; //digitalTasks[i].Stream.WriteRegenerationMode = WriteRegenerationMode.DoNotAllowRegeneration; digitalTasks[i].Stream.WriteRegenerationMode = WriteRegenerationMode.AllowRegeneration; //create a writer for this task digitalWriters[i] = new DigitalSingleChannelWriter(digitalTasks[i].Stream); //now that we've created a potential task configuration, check to make sure everything is kosher digitalTasks[i].Control(TaskAction.Verify); //actually set the hardware to these settings digitalTasks[i].Control(TaskAction.Reserve); } }
/// <summary> /// 配置Ao输出任务 /// </summary> /// <returns></returns> private API_RETURN_CODE ConfigAoTask() { API_RETURN_CODE code = API_RETURN_CODE.API_SUCCESS; try { m_aoTask = new Task(); m_aoTask.AOChannels.CreateVoltageChannel(GetAoPhysicalChannelName(), "", -10.0, 10.0, AOVoltageUnits.Volts); m_aoTask.Control(TaskAction.Verify); m_aoTask.Timing.SampleClockRate = m_params.AoSampleRate; m_aoTask.Timing.ConfigureSampleClock("", m_aoTask.Timing.SampleClockRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, m_params.AoSampleCountPerFrame); // 路由Ao Sample Clcok到PFI0 //if (m_config.Debugging) //{ // Logger.Info(string.Format("route ao sample clock to PFI0.")); // m_aoTask.ExportSignals.SampleClockOutputTerminal = string.Concat("/", NI_CARD_NAME_DEFAULT, "/", "PFI0"); //} //string source = m_sysConfig.GetStartSyncSignal(); //m_aoTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger(source, DigitalEdgeStartTriggerEdge.Rising); // 写入波形 AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(m_aoTask.Stream); AnalogWaveform <double>[] waves; if (m_config.GetScanMirrorNum() == SCAN_MIRROR_NUM.THREEE) { waves = new AnalogWaveform <double> [3]; waves[2] = AnalogWaveform <double> .FromArray1D(m_waver.Y2Wave); } else { waves = new AnalogWaveform <double> [2]; } waves[0] = AnalogWaveform <double> .FromArray1D(m_waver.XWave); waves[1] = AnalogWaveform <double> .FromArray1D(m_waver.Y1Wave); writer.WriteWaveform(false, waves); } catch (Exception e) { Logger.Error(string.Format("config ao task exception: [{0}].", e)); code = API_RETURN_CODE.API_FAILED_NI_CONFIG_AO_TASK_EXCEPTION; } return(code); }
public void setChannel(int line, double value) { Task task = new Task(); string devFullname = string.Format("{0}/ao{1}", name, line); AOChannel channel = task.AOChannels.CreateVoltageChannel(devFullname, "", 0.0, 10.0, AOVoltageUnits.Volts); task.Start(); AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(task.Stream); IAsyncResult result = writer.BeginWriteSingleSample(true, new double[] { value }, null, null); task.Stop(); }
public void Write() { try { string[] channelNameList = DaqSystem.Local.GetPhysicalChannels(PhysicalChannelTypes.AO, PhysicalChannelAccess.External); if (channelNameList.Length > 0) { Task task1 = new Task(); task1.AOChannels.CreateVoltageChannel(channelNameList[0], "Voltage1", 0, 10, AOVoltageUnits.Volts); task1.AOChannels.CreateVoltageChannel(channelNameList[1], "Voltage2", 0, 10, AOVoltageUnits.Volts); task1.AOChannels.CreateVoltageChannel(channelNameList[2], "Voltage3", 0, 10, AOVoltageUnits.Volts); task1.Timing.ConfigureSampleClock("", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); task1.Control(TaskAction.Verify); Task task2 = new Task(); task2.AOChannels.CreateVoltageChannel(channelNameList[0], "Voltage1", 0, 10, AOVoltageUnits.Volts); task2.AOChannels.CreateVoltageChannel(channelNameList[1], "Voltage2", 0, 10, AOVoltageUnits.Volts); task2.AOChannels.CreateVoltageChannel(channelNameList[2], "Voltage3", 0, 10, AOVoltageUnits.Volts); task2.Timing.ConfigureSampleClock("", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); task2.Control(TaskAction.Verify); AnalogMultiChannelWriter aowriter1 = new AnalogMultiChannelWriter(task1.Stream); AnalogMultiChannelWriter aowriter2 = new AnalogMultiChannelWriter(task2.Stream); double[,] wave = new double[3, 1000]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 1000; j++) { wave[i, j] = 0.001 * (1000 - j); } } Console.WriteLine("Task is ready"); aowriter1.WriteMultiSample(false, wave); task1.Control(TaskAction.Start); Console.ReadKey(); task1.Control(TaskAction.Stop); task1.Control(TaskAction.Unreserve); Console.WriteLine("Task1 is released"); aowriter2.WriteMultiSample(false, wave); task1.Control(TaskAction.Start); Console.ReadKey(); task1.Control(TaskAction.Stop); task1.Control(TaskAction.Unreserve); Console.ReadKey(); } } catch (DaqException e) { Console.Out.WriteLine(e.Message); } }
void ConfigureTask(int sampleCount, bool forceReset = false) { if (LastError != null || sampleCount == m_lastSampleCount && !forceReset) { return; } LastError = null; m_lastSampleCount = sampleCount; DestroyWriterTask(); WriterTask = new Task(); WriterTask.AOChannels.CreateVoltageChannel(XChanName, "XChannel", -10, 10, AOVoltageUnits.Volts); WriterTask.AOChannels.CreateVoltageChannel(YChanName, "YChannel", -10, 10, AOVoltageUnits.Volts); WriterTask.Stream.Timeout = Convert.ToInt32(sampleCount / SamplingFrequency) * 1000 + 1000; WriterTask.SynchronizeCallbacks = SynchronizeCallbacks; if (sampleCount == 0) { return; } WriterTask.Timing.ConfigureSampleClock(String.Empty, SamplingFrequency, SampleClockActiveEdge.Rising, sampleCount == 1 ? SampleQuantityMode.HardwareTimedSinglePoint : SampleQuantityMode.FiniteSamples, sampleCount); //long bufferSize = sampleCount > 500000 ? 500000 : sampleCount; // 10% of sample count; //bufferSize = bufferSize <= 1 ? 1 : bufferSize; //if (bufferSize > 1) //{ // //WriterTask.Stream.ConfigureOutputBuffer(bufferSize); //} WriterTask.Control(TaskAction.Verify); if (sampleCount > 1) { WriterTask.Done += WriterTask_Done; //WriterTask.SampleClock += WriterTask_SampleClock; } MCWriter = new AnalogMultiChannelWriter(WriterTask.Stream); MCWriter.SynchronizeCallbacks = SynchronizeCallbacks; }
void WriteThreadRun(AutoResetEvent stop, Func <long, int, double[, ]> sampleFunction) { Task writeTask = new Task("EphysWrite"); double[,] firstSamples = sampleFunction(0, HardwareSettings.DAQ.Rate); if (firstSamples.GetLength(1) != HardwareSettings.DAQ.Rate) { throw new ApplicationException("Did not receive the required number of samples"); } var nChannels = firstSamples.GetLength(0); for (int i = 0; i < nChannels; i++) { writeTask.AOChannels.CreateVoltageChannel(HardwareSettings.DAQ.DeviceName + "/" + string.Format("AO{0}", i), "", -10, 10, AOVoltageUnits.Volts); } //Note: Can't use ai clock, since we cannot guarantee that the read thread ai task finishes *after* the write task //otherwise Task.Stop will block indefinitely... writeTask.Timing.ConfigureSampleClock("", HardwareSettings.DAQ.Rate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples); writeTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("ai/StartTrigger ", DigitalEdgeStartTriggerEdge.Rising); writeTask.Stream.WriteRegenerationMode = WriteRegenerationMode.DoNotAllowRegeneration; AnalogMultiChannelWriter dataWriter = new AnalogMultiChannelWriter(writeTask.Stream); dataWriter.WriteMultiSample(false, firstSamples); writeTask.Start(); _writeThreadReady.Set(); long start_sample = HardwareSettings.DAQ.Rate; try { while (!stop.WaitOne(50)) { double[,] samples = sampleFunction(start_sample, HardwareSettings.DAQ.Rate / 5); if (samples == null) { break; } dataWriter.WriteMultiSample(false, samples); start_sample += HardwareSettings.DAQ.Rate / 5; } System.Diagnostics.Debug.WriteLine("Left write loop"); } finally { writeTask.Stop(); writeTask.Dispose(); } }
private void Start() { Cursor.Current = Cursors.WaitCursor; try { // 创建模拟输出任务 galvTask = new Task(); // 创建模拟电压输出通道 galvTask.AOChannels.CreateVoltageChannel("Dev1/ao0:2", "", -10.0, 10.0, AOVoltageUnits.Volts); // 验证任务 galvTask.Control(TaskAction.Verify); double desiredFrequency = aoSampleRate / sampleCountPerAO; double samplesPerBuffer = sampleCountPerAO; double cyclesPerBuffer = 1.0; WaveGenerator wave = new WaveGenerator( galvTask.Timing, desiredFrequency, samplesPerBuffer, cyclesPerBuffer, WaveformType.GalvWave, 2.0); // configure the sample clock with the calculated rate galvTask.Timing.ConfigureSampleClock("", wave.ResultingSampleClockRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, sampleCountPerAO); AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(galvTask.Stream); AnalogWaveform <double>[] waves = new AnalogWaveform <double> [3]; waves[0] = AnalogWaveform <double> .FromArray1D(xWaves); waves[1] = AnalogWaveform <double> .FromArray1D(y1Waves); waves[2] = AnalogWaveform <double> .FromArray1D(y2Waves); //write data to buffer writer.WriteWaveform(false, waves); //start writing out data galvTask.Start(); } catch (DaqException e) { Logger.Error(string.Format("daq exception [{0}].", e)); MessageBox.Show(e.Message); galvTask.Dispose(); } Cursor.Current = Cursors.Default; }
internal void ZeroAOChanOnDev(string dev, int[] channelsToZero) { lock (this) { try { // Create an analog out task for a given device for all 4 channels. // Write clearingBufferSize zeros to that port. Wait // until this is finished and destroy the clearning Task. Task analogClearingTask = new Task("AnalogClear"); foreach (int chan in channelsToZero) { analogClearingTask.AOChannels.CreateVoltageChannel( "/" + dev + "/ao" + chan, "", -10.0, 10.0, AOVoltageUnits.Volts); } //analogClearingTask.Timing.ConfigureSampleClock("/" + dev + "/PF", // clearingSampleRate, // SampleClockActiveEdge.Rising, // SampleQuantityMode.FiniteSamples, // clearingBufferSize); analogClearingTask.Timing.ReferenceClockSource = ("/" + dev + "/PFI2"); analogClearingTask.Timing.ReferenceClockRate = 10e6; AnalogMultiChannelWriter analogClearingWriter = new AnalogMultiChannelWriter(analogClearingTask.Stream); double[] zeroData = new double[channelsToZero.Length]; analogClearingWriter.BeginWriteSingleSample(false, zeroData, null, null); analogClearingTask.Control(TaskAction.Verify); analogClearingTask.Start(); //analogClearingWriter.WriteSingleSample(true, zeroData); //analogClearingWriter.WriteMultiSample(true, zeroData); analogClearingTask.WaitUntilDone(30); analogClearingTask.Stop(); analogClearingTask.Dispose(); analogClearingTask = null; } catch (Exception e) { Console.WriteLine("Could not zero analog outputs on device: " + dev); Console.WriteLine(e.Message); } } }
internal void ZeroAOChanOnDev(string dev, int[] channelsToZero) { lock (this) { try { // Create an analog out task for a given device for all 4 channels. // Write clearingBufferSize zeros to that port. Wait // until this is finished and destroy the clearning Task. Task analogClearingTask = new Task("AnalogClear"); foreach (int chan in channelsToZero) analogClearingTask.AOChannels.CreateVoltageChannel( "/" + dev + "/ao" + chan, "", -10.0, 10.0, AOVoltageUnits.Volts); //analogClearingTask.Timing.ConfigureSampleClock("/" + dev + "/PF", // clearingSampleRate, // SampleClockActiveEdge.Rising, // SampleQuantityMode.FiniteSamples, // clearingBufferSize); analogClearingTask.Timing.ReferenceClockSource = ("/" + dev + "/PFI2"); analogClearingTask.Timing.ReferenceClockRate = 10e6; AnalogMultiChannelWriter analogClearingWriter = new AnalogMultiChannelWriter(analogClearingTask.Stream); double[] zeroData = new double[channelsToZero.Length]; analogClearingWriter.BeginWriteSingleSample(false, zeroData, null, null); analogClearingTask.Control(TaskAction.Verify); analogClearingTask.Start(); //analogClearingWriter.WriteSingleSample(true, zeroData); //analogClearingWriter.WriteMultiSample(true, zeroData); analogClearingTask.WaitUntilDone(30); analogClearingTask.Stop(); analogClearingTask.Dispose(); analogClearingTask = null; } catch (Exception e) { Console.WriteLine("Could not zero analog outputs on device: " + dev); Console.WriteLine(e.Message); } } }
protected virtual void Dispose(bool Disposing) { /*if (_xMirrorTask != null) * _xMirrorTask.Dispose(); * if (_yMirrorTask != null) * _yMirrorTask.Dispose();*/ if (_mirrorTask != null) { _mirrorTask.Dispose(); _mirrorTask = null; } if (_multiWriter != null) { _multiWriter = null; } if (!Disposing)//stuff we don't want to do in a finalizer { } }
/// <summary> /// This method creates analog and digital output buffers for daqMx cards. Note that the daqmx library seems to only support /// either analog OR digital on a given card at one time. Despite the fact that this method will create both types of buffers, /// it will probably throw some daqMX level exceptions if asked to create both analog and digital buffers for the same device. /// </summary> /// <param name="deviceName"></param> /// <param name="deviceSettings"></param> /// <param name="sequence"></param> /// <param name="settings"></param> /// <param name="usedDigitalChannels">digital channels which reside on this server.</param> /// <param name="usedAnalogChannels">analog channels which reside on this server</param> /// <returns></returns> public static Task createDaqMxTask(string deviceName, DeviceSettings deviceSettings, SequenceData sequence, SettingsData settings, Dictionary<int, HardwareChannel> usedDigitalChannels, Dictionary<int, HardwareChannel> usedAnalogChannels, ServerSettings serverSettings, out long expectedSamplesGenerated) { expectedSamplesGenerated = 0; Task task = new Task(deviceName + " output task"); List<int> analogIDs; List<HardwareChannel> analogs; Dictionary<int, int[]> port_digital_IDs; List<int> usedPortNumbers; // Parse and create channels. parseAndCreateChannels(deviceName,deviceSettings, usedDigitalChannels, usedAnalogChannels, task, out analogIDs, out analogs, out port_digital_IDs, out usedPortNumbers); if (analogIDs.Count != 0) { if (deviceSettings.UseCustomAnalogTransferSettings) { task.AOChannels.All.DataTransferMechanism = deviceSettings.AnalogDataTransferMechanism; task.AOChannels.All.DataTransferRequestCondition = deviceSettings.AnalogDataTransferCondition; } } if (usedPortNumbers.Count != 0) { if (deviceSettings.UseCustomDigitalTransferSettings) { task.DOChannels.All.DataTransferMechanism = deviceSettings.DigitalDataTransferMechanism; task.DOChannels.All.DataTransferRequestCondition = deviceSettings.DigitalDataTransferCondition; } } // ok! now create the buffers #region NON variable timebase buffer if (deviceSettings.UsingVariableTimebase == false) { // non "variable timebase" buffer creation double timeStepSize = 1.0 / (double)deviceSettings.SampleClockRate; int nBaseSamples = sequence.nSamples(timeStepSize); // for reasons that are utterly stupid and frustrating, the DAQmx libraries seem to prefer sample // buffers with lengths that are a multiple of 4. (otherwise they, on occasion, depending on the parity of the // number of channels, throw exceptions complaining. // thus we add a few filler samples at the end of the sequence which parrot back the last sample. int nFillerSamples = 4 - nBaseSamples % 4; if (nFillerSamples == 4) nFillerSamples = 0; int nSamples = nBaseSamples + nFillerSamples; if (deviceSettings.MySampleClockSource == DeviceSettings.SampleClockSource.DerivedFromMaster) { task.Timing.ConfigureSampleClock("", deviceSettings.SampleClockRate, deviceSettings.ClockEdge, SampleQuantityMode.FiniteSamples, nSamples); } else { task.Timing.ConfigureSampleClock(deviceSettings.SampleClockExternalSource, deviceSettings.SampleClockRate, deviceSettings.ClockEdge, SampleQuantityMode.FiniteSamples, nSamples); } if (deviceSettings.MasterTimebaseSource != "" && deviceSettings.MasterTimebaseSource != null) { task.Timing.MasterTimebaseSource = deviceSettings.MasterTimebaseSource.ToString(); } // Analog first... if (analogIDs.Count != 0) { double[,] analogBuffer; double[] singleChannelBuffer; try { analogBuffer = new double[analogs.Count, nSamples]; singleChannelBuffer = new double[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate analog buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < analogIDs.Count; i++) { int analogID = analogIDs[i]; if (settings.logicalChannelManager.Analogs[analogID].TogglingChannel) { DaqMxTaskGenerator.getAnalogTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Analogs[analogID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Analogs[analogID].analogOverrideValue; } } else { sequence.computeAnalogBuffer(analogIDs[i], timeStepSize, singleChannelBuffer); } for (int j = 0; j < nBaseSamples; j++) { analogBuffer[i, j] = singleChannelBuffer[j]; } for (int j = nBaseSamples; j < nSamples; j++) { analogBuffer[i, j] = analogBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(task.Stream); writer.WriteMultiSample(false, analogBuffer); // analog cards report the exact number of generated samples. for non-variable timebase this is nSamples expectedSamplesGenerated = nSamples; } if (usedPortNumbers.Count != 0) { byte[,] digitalBuffer; bool[] singleChannelBuffer; try { digitalBuffer = new byte[usedPortNumbers.Count, nSamples]; singleChannelBuffer = new bool[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate digital buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < usedPortNumbers.Count; i++) { int portNum = usedPortNumbers[i]; byte digitalBitMask = 1; for (int lineNum = 0; lineNum < 8; lineNum++) { int digitalID = port_digital_IDs[portNum][lineNum]; if (digitalID != -1) { if (settings.logicalChannelManager.Digitals[digitalID].TogglingChannel) { getDigitalTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Digitals[digitalID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Digitals[digitalID].digitalOverrideValue; } } else { sequence.computeDigitalBuffer(digitalID, timeStepSize, singleChannelBuffer); } // byte digitalBitMask = (byte)(((byte) 2)^ ((byte)lineNum)); for (int j = 0; j < nBaseSamples; j++) { // copy the bit value into the digital buffer byte. if (singleChannelBuffer[j]) digitalBuffer[i, j] |= digitalBitMask; } } digitalBitMask = (byte)(digitalBitMask << 1); } for (int j = nBaseSamples; j < nSamples; j++) { digitalBuffer[i, j] = digitalBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); DigitalMultiChannelWriter writer = new DigitalMultiChannelWriter(task.Stream); writer.WriteMultiSamplePort(false, digitalBuffer); /// Digital cards report the number of generated samples as a multiple of 4 expectedSamplesGenerated = nSamples; } } #endregion #region Variable timebase buffer creation else // variable timebase buffer creation... { double timeStepSize = 1.0 / (double)deviceSettings.SampleClockRate; TimestepTimebaseSegmentCollection timebaseSegments = sequence.generateVariableTimebaseSegments(serverSettings.VariableTimebaseType, timeStepSize); int nBaseSamples = timebaseSegments.nSegmentSamples(); nBaseSamples++; // add one sample for the dwell sample at the end of the buffer // for reasons that are utterly stupid and frustrating, the DAQmx libraries seem to prefer sample // buffers with lengths that are a multiple of 4. (otherwise they, on occasion, depending on the parity of the // number of channels, throw exceptions complaining. // thus we add a few filler samples at the end of the sequence which parrot back the last sample. int nFillerSamples = 4 - nBaseSamples % 4; if (nFillerSamples == 4) nFillerSamples = 0; int nSamples = nBaseSamples + nFillerSamples; if (deviceSettings.MySampleClockSource == DeviceSettings.SampleClockSource.DerivedFromMaster) { throw new Exception("Attempt to use a uniform sample clock with a variable timebase enabled device. This will not work. To use a variable timebase for this device, you must specify an external sample clock source."); } else { task.Timing.ConfigureSampleClock(deviceSettings.SampleClockExternalSource, deviceSettings.SampleClockRate, deviceSettings.ClockEdge, SampleQuantityMode.FiniteSamples, nSamples); } // Analog first... if (analogIDs.Count != 0) { double[,] analogBuffer; double[] singleChannelBuffer; try { analogBuffer = new double[analogs.Count, nSamples]; singleChannelBuffer = new double[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate analog buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < analogIDs.Count; i++) { int analogID = analogIDs[i]; if (settings.logicalChannelManager.Analogs[analogID].TogglingChannel) { getAnalogTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Analogs[analogID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Analogs[analogID].analogOverrideValue; } } else { sequence.computeAnalogBuffer(analogIDs[i], timeStepSize, singleChannelBuffer, timebaseSegments); } for (int j = 0; j < nBaseSamples; j++) { analogBuffer[i, j] = singleChannelBuffer[j]; } for (int j = nBaseSamples; j < nSamples; j++) { analogBuffer[i, j] = analogBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(task.Stream); writer.WriteMultiSample(false, analogBuffer); // Analog cards report the exact number of samples generated. for variable timebase this is nBaseSamples expectedSamplesGenerated = nBaseSamples; } if (usedPortNumbers.Count != 0) { byte[,] digitalBuffer; bool[] singleChannelBuffer; try { digitalBuffer = new byte[usedPortNumbers.Count, nSamples]; singleChannelBuffer = new bool[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate digital buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < usedPortNumbers.Count; i++) { int portNum = usedPortNumbers[i]; byte digitalBitMask = 1; for (int lineNum = 0; lineNum < 8; lineNum++) { int digitalID = port_digital_IDs[portNum][lineNum]; if (digitalID != -1) { if (settings.logicalChannelManager.Digitals[digitalID].TogglingChannel) { getDigitalTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Digitals[digitalID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Digitals[digitalID].digitalOverrideValue; } } else { sequence.computeDigitalBuffer(digitalID, timeStepSize, singleChannelBuffer, timebaseSegments); } // byte digitalBitMask = (byte)(((byte) 2)^ ((byte)lineNum)); for (int j = 0; j < nBaseSamples; j++) { // copy the bit value into the digital buffer byte. if (singleChannelBuffer[j]) digitalBuffer[i, j] |= digitalBitMask; } } digitalBitMask = (byte)(digitalBitMask << 1); } for (int j = nBaseSamples; j < nSamples; j++) { digitalBuffer[i, j] = digitalBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); DigitalMultiChannelWriter writer = new DigitalMultiChannelWriter(task.Stream); writer.WriteMultiSamplePort(false, digitalBuffer); // digital cards report number of samples generated up to multiple of 4 expectedSamplesGenerated = nSamples; } } #endregion if (deviceSettings.StartTriggerType == DeviceSettings.TriggerType.TriggerIn) { task.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( deviceSettings.TriggerInPort, DigitalEdgeStartTriggerEdge.Rising); } task.Control(TaskAction.Verify); task.Control(TaskAction.Commit); task.Control(TaskAction.Reserve); return task; }
/* /// <summary> /// This class contains both the analog and the digital tasks returned from a specific device. /// The reason for its existence is that if a device is to have both its analog and its digital outputs used, /// then they must exist in separate tasks. /// </summary> /// public class TaskCollection { public Task analogTask; public Task digitalTask; } */ /* public static Task createVariableTimebaseTask(string digitalTimebaseOutLine, string analogTimebaseOutLine) { }*/ /// /// This method creates a daqMX task for an "output now" command, and starts the output. /// </summary> /// <param name="deviceName"></param> /// <param name="settings"></param> /// <param name="output"></param> /// <returns></returns> public static Task createDaqMxTaskAndOutputNow(string deviceName, DeviceSettings deviceSettings, SingleOutputFrame output, SettingsData settings, Dictionary<int, HardwareChannel> usedDigitalChannels, Dictionary<int, HardwareChannel> usedAnalogChannels) { Task task = new Task(deviceName + " output task"); List<int> analogIDs; List<HardwareChannel> analogs; Dictionary<int, int[]> port_digital_IDs; List<int> usedPortNumbers; // Parse and create channels. parseAndCreateChannels(deviceName,deviceSettings, usedDigitalChannels, usedAnalogChannels, task, out analogIDs, out analogs, out port_digital_IDs, out usedPortNumbers); // now create buffer. task.Timing.SampleTimingType = SampleTimingType.OnDemand; // analog output if (analogIDs.Count != 0) { // extract a list of analog values corresponding to the list analodIDs. This is // sorted in the same way as the channels were created in parseAndCreateChannels List<double> outputValues = new List<double>(); foreach (int analogID in analogIDs) { double val; if (output.analogValues.ContainsKey(analogID)) val = output.analogValues[analogID]; else val = 0; outputValues.Add(val); } AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(task.Stream); writer.WriteSingleSample(true, outputValues.ToArray()); } // digital output if (usedPortNumbers.Count != 0) { List<byte> outputValues = new List<byte>(); foreach (int portNumber in usedPortNumbers) { byte digitalMask = 1; byte value=0; for (int lineNum = 0; lineNum < 8; lineNum++) { int digitalID = port_digital_IDs[portNumber][lineNum]; if (digitalID != -1) { bool val = false; if (output.digitalValues.ContainsKey(digitalID)) val = output.digitalValues[digitalID]; if (val) value |= digitalMask; } digitalMask = (byte) (digitalMask << 1); } outputValues.Add(value); } DigitalMultiChannelWriter writer = new DigitalMultiChannelWriter(task.Stream); writer.WriteSingleSamplePort(true, outputValues.ToArray()); } return task; }
private void DaqInit() { try { daqTask = new NationalInstruments.DAQmx.Task(); daqTask2 = new NationalInstruments.DAQmx.Task(); daqTask3 = new NationalInstruments.DAQmx.Task(); daqTask.AIChannels.CreateVoltageChannel("Dev1/ai0", "", (AITerminalConfiguration)(-1), -10, 10, AIVoltageUnits.Volts); daqTask.AIChannels.CreateVoltageChannel("Dev1/ai1", "", (AITerminalConfiguration)(-1), -10, 10, AIVoltageUnits.Volts); daqTask2.AOChannels.CreateVoltageChannel("Dev1/ao0", "", -10, 10, AOVoltageUnits.Volts); daqTask2.AOChannels.CreateVoltageChannel("Dev1/ao1", "", -10, 10, AOVoltageUnits.Volts); daqTask.Timing.ConfigureSampleClock("", sampleRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, sampleRate); daqTask.AIChannels.All.DataTransferMechanism = AIDataTransferMechanism.Dma; daqTask2.Timing.ConfigureSampleClock("", sampleRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, sampleRate); daqTask2.AOChannels.All.DataTransferMechanism = AODataTransferMechanism.Dma; daqTask2.Stream.WriteRegenerationMode = WriteRegenerationMode.DoNotAllowRegeneration; reader = new AnalogMultiChannelReader(daqTask.Stream); int inBufSize1 = sampleRate, inBufSize2 = 2 * sampleRate; inDriveSignal = reader.ReadWaveform(inBufSize1); /*fftw_plan mplan; * double[] din = new double[inBufSize1]; * double[] freq = new double[inBufSize1*2]; * GCHandle hdin = GCHandle.Alloc(din, GCHandleType.Pinned); * GCHandle hdout = GCHandle.Alloc(freq, GCHandleType.Pinned); * fftw_complexarray min = new fftw_complexarray(din); * fftw_complexarray mout = new fftw_complexarray(freq); * IntPtr fplan5 = fftw.dft_r2c_1d(sampleRate, hdin.AddrOfPinnedObject(), hdout.AddrOfPinnedObject(), fftw_flags.Estimate); * Array.Copy(inDriveSignal[0].GetRawData(), din, inBufSize1); * fftw.execute(fplan5); * measuredFreq1 = (double)Util.AbsMaxIndex(freq) / 2;*/ /*int rem = (int)((double)(measuredFreq1 - (int)measuredFreq1) * 1000); * int mul; * if (rem > 0) * { * mul = 1000 / (int)Integers.GCD(rem, 1000); * measuredFreq1 *= mul; * * }*/ //Array.Copy(inDriveSignal[1].GetRawData(), din, inBufSize1); //fftw.execute(fplan5); //measuredFreq2 = (double)Util.AbsMaxIndex(freq) / 2; ZX1 = Util.GetZeroCrossings(inDriveSignal[0].GetRawData()); ZX2 = Util.GetZeroCrossings(inDriveSignal[1].GetRawData()); /*rem = (int)((double)(measuredFreq2 - (int)measuredFreq2) * 1000); * if (rem > 0) * { * mul = 1000 / (int)Integers.GCD(rem, 1000); * measuredFreq2 *= mul; * }*/ //samplePerChannel = (int)Math.Max(ch1, ch2); //sampleRate = 500*(int)Integers.LCM((long)measuredFreq1, (long)measuredFreq2); samplePerChannel = sampleRate / 25; daqTask2.EveryNSamplesWrittenEventInterval = samplePerChannel; daqTask2.EveryNSamplesWritten += daqTask2_EveryNSamplesWritten; writer = new AnalogMultiChannelWriter(daqTask2.Stream); bufsize = sampleRate; waveX = new double[180][]; waveY = new double[180][]; outWave = new double[2, samplePerChannel]; for (int i = 0; i < 180; i++) { waveX[i] = new double[bufsize]; waveY[i] = new double[bufsize]; } waveX[0] = inDriveSignal[0].GetRawData(0, bufsize); waveY[0] = inDriveSignal[1].GetRawData(0, bufsize); //Array.Copy(waveX[0], waveX[0].Length / 2, waveY[0], 0, waveY[0].Length / 2); //Array.Copy(waveX[0], 0, waveY[0], waveY[0].Length / 2, waveY[0].Length / 2); // initialize rotations for (int i = 1; i < 180; i++) { for (int j = 0; j < bufsize; j++) { double theta = ((i) / 180.0) * Math.PI; double x = waveX[0][j]; double y = waveY[0][j]; waveX[i][j] = x * Math.Cos(theta) - y * Math.Sin(theta); waveY[i][j] = x * Math.Sin(theta) + y * Math.Cos(theta); } } double[] X = new double[samplePerChannel]; double[] Y = new double[samplePerChannel]; Array.Copy(waveX[0], ZX1[1], X, 0, samplePerChannel); Array.Copy(waveY[0], ZX2[1], Y, 0, samplePerChannel); sampleIndex = samplePerChannel; sampleIndex2 = samplePerChannel; AnalogWaveform <double>[] waves = { AnalogWaveform <double> .FromArray1D(X), AnalogWaveform <double> .FromArray1D(Y) }; writer.WriteWaveform <double>(false, waves); daqTask.Timing.ConfigureSampleClock("", sampleRate, SampleClockActiveEdge.Rising, SampleQuantityMode.HardwareTimedSinglePoint, 0); double[] sample; bool negative = false; daqTask2.Start(); //daqTask2.AOChannels.All.DataTransferMechanism = AODataTransferMechanism.Dma; dcOffsetX = dcOffsetY = 0; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
private void button_electrolesioningStart_Click(object sender, EventArgs e) { //Change mouse cursor to waiting cursor this.Cursor = Cursors.WaitCursor; //Grab values from UI double voltage = Convert.ToDouble(numericUpDown_electrolesioningVoltage.Value); double duration = Convert.ToDouble(numericUpDown_electrolesioningDuration.Value); List<Int32> chList = new List<int>(listBox_electrolesioningChannels.SelectedIndices.Count); for (int i = 0; i < listBox_electrolesioningChannels.SelectedIndices.Count; ++i) chList.Add(listBox_electrolesioningChannels.SelectedIndices[i] + 1); //+1 since indices are 0-based but channels are 1-base //Disable buttons, so users don't try running two experiments at once button_electrolesioningStart.Enabled = false; button_electrolesioningSelectAll.Enabled = false; button_electrolesioningSelectNone.Enabled = false; button_electrolesioningStart.Refresh(); //Refresh stim task stimDigitalTask.Dispose(); stimDigitalTask = new Task("stimDigitalTask_Electrolesioning"); if (Properties.Settings.Default.StimPortBandwidth == 32) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes else if (Properties.Settings.Default.StimPortBandwidth == 8) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); //Refresh pulse task stimPulseTask.Dispose(); stimPulseTask = new Task("stimPulseTask"); if (Properties.Settings.Default.StimPortBandwidth == 32) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); } stimPulseWriter = new AnalogMultiChannelWriter(stimPulseTask.Stream); stimPulseTask.Timing.ConfigureSampleClock("", StimPulse.STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimPulseTask.Timing.SamplesPerChannel = 2; stimDigitalTask.Control(TaskAction.Verify); stimPulseTask.Control(TaskAction.Verify); //For each channel, deliver lesioning pulse for (int i = 0; i < chList.Count; ++i) { int channel = chList[i]; UInt32 data = StimPulse.channel2MUX((double)channel); //Setup digital waveform, open MUX channel stimDigitalWriter.WriteSingleSamplePort(true, data); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); //Write voltage to channel, wait duration, stop stimPulseWriter.WriteMultiSample(true, new double[,] { { 0, 0 }, { 0, 0 }, { voltage, voltage }, { 0, 0 } }); stimPulseTask.WaitUntilDone(); stimPulseTask.Stop(); Thread.Sleep((int)(Math.Round(duration * 1000))); //Convert to ms stimPulseWriter.WriteMultiSample(true, new double[,] { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }); stimPulseTask.WaitUntilDone(); stimPulseTask.Stop(); //Close MUX stimDigitalWriter.WriteSingleSamplePort(true, 0); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); } bool[] fData = new bool[Properties.Settings.Default.StimPortBandwidth]; stimDigitalWriter.WriteSingleSampleMultiLine(true, fData); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); button_electrolesioningSelectAll.Enabled = true; button_electrolesioningSelectNone.Enabled = true; button_electrolesioningStart.Enabled = true; //Now, destroy the objects we made updateSettings(); this.Cursor = Cursors.Default; }
private void TimedMove(double __dCycleTime, double[,] __dCoordinates, int[] __iLevels, bool master, bool continuous) { Stopwatch watch = new Stopwatch(); watch.Start(); _logger.Debug("Start:" + watch.ElapsedMilliseconds.ToString()); int _iSamplesPerChannel = __dCoordinates.Length / 3; // Prepare the stage control task for writing as many samples as necessary to complete Move. this.Configure(__dCycleTime, _iSamplesPerChannel, master, continuous); AnalogMultiChannelWriter writerA = new AnalogMultiChannelWriter(this.m_daqtskMoveStage.Stream); DigitalSingleChannelWriter writerD = new DigitalSingleChannelWriter(this.m_daqtskLineTrigger.Stream); try { // Perform the actual AO write. writerA.WriteMultiSample(false, __dCoordinates); writerD.WriteMultiSamplePort(false, __iLevels); _logger.Debug("End write:" + watch.ElapsedMilliseconds.ToString()); // Start all four tasks in the correct order. Global sync should be last. this.m_daqtskLineTrigger.Start(); this.m_daqtskMoveStage.Start(); if (this.m_bMaster && this.m_sampleClock != null) { this.m_sampleClock.Start(this.m_samplePeriod); } } catch (Exception ex) { _logger.Error("Something went wrong! : \r\n", ex); m_daqtskMoveStage.Stop(); } }
internal void getImpedance(double startFreq, double stopFreq, double numPeriods, bool isCurrentControlled, int startChannel, int numChannels, double RCurr, double RMeas, double RGain, double commandVoltage, bool useBandpassFilter, bool useMatchedFilter) { this.numPeriods = numPeriods; this.startChannel = startChannel; this.numChannels = numChannels; this.RCurr = RCurr; this.RGain = RGain; this.RMeas = RMeas; this.commandVoltage = commandVoltage; this.isCurrentControlled = isCurrentControlled; this.useBandpassFilter = useBandpassFilter; this.useMatchedFilter = useMatchedFilter; //StartChannel is 1-based if (startFreq == stopFreq) freqs = new double[1]; else if ((stopFreq/startFreq)%RESOLUTION == 0) //stopFreq is a RESOLUTION multiple of startFreq freqs = new double[Convert.ToInt32(Math.Floor(Math.Log(stopFreq / startFreq) / Math.Log(RESOLUTION))) + 1]; //This determines the number of frequencies counting by doublings else //not an exact multiple freqs = new double[Convert.ToInt32(Math.Floor(Math.Log(stopFreq / startFreq) / Math.Log(RESOLUTION))) + 2]; //This determines the number of frequencies counting by doublings //Populate freqs vector freqs[0] = startFreq; for (int i = 1; i < freqs.GetLength(0); ++i) freqs[i] = freqs[i - 1] * RESOLUTION; if (freqs[freqs.Length - 1] > stopFreq) freqs[freqs.Length - 1] = stopFreq; //Setup tasks impedanceRecord = new Task("Impedance Analog Input Task"); stimDigitalTask = new Task("stimDigitalTask_impedance"); stimAnalogTask = new Task("stimAnalogTask_impedance"); //Choose appropriate input for current/voltage-controlled stimulation String inputChannel = (isCurrentControlled ? "/ai2" : "/ai3"); //if (isCurrentControlled) inputChannel = "/ai2"; //else inputChannel = "/ai3"; impedanceRecord.AIChannels.CreateVoltageChannel(Properties.Settings.Default.ImpedanceDevice + inputChannel, "", AITerminalConfiguration.Rse, -5.0, 5.0, AIVoltageUnits.Volts); //try delaying sampling impedanceRecord.Timing.DelayFromSampleClock = 10; impedanceRecord.Timing.ConfigureSampleClock("", IMPEDANCE_SAMPLING_RATE, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); impedanceReader = new AnalogSingleChannelReader(impedanceRecord.Stream); impedanceRecord.Timing.ReferenceClockSource = "OnboardClock"; //Configure stim digital output task if (Properties.Settings.Default.StimPortBandwidth == 32) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes else if (Properties.Settings.Default.StimPortBandwidth == 8) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); //Configure stim analog output task if (Properties.Settings.Default.StimPortBandwidth == 32) { stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual pulse stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } stimAnalogTask.Timing.ConfigureSampleClock("/" + Properties.Settings.Default.ImpedanceDevice + "/ai/SampleClock", IMPEDANCE_SAMPLING_RATE, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimAnalogTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + Properties.Settings.Default.ImpedanceDevice + "/ai/StartTrigger", DigitalEdgeStartTriggerEdge.Rising); impedanceRecord.Control(TaskAction.Verify); stimAnalogTask.Timing.ReferenceClockSource = impedanceRecord.Timing.ReferenceClockSource; stimAnalogTask.Timing.ReferenceClockRate = impedanceRecord.Timing.ReferenceClockRate; stimAnalogWriter = new AnalogMultiChannelWriter(stimAnalogTask.Stream); //Verify tasks impedanceRecord.Control(TaskAction.Verify); stimDigitalTask.Control(TaskAction.Verify); stimAnalogTask.Control(TaskAction.Verify); //Setup storage variable impedance = new double[numChannels][]; for (int c = 0; c < numChannels; ++c) { impedance[c] = new double[freqs.GetLength(0)]; for (int f = 0; f < freqs.Length; ++f) impedance[c][f] = double.NaN; } //Setup background worker bgWorker = new BackgroundWorker(); bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged); bgWorker.WorkerSupportsCancellation = true; bgWorker.WorkerReportsProgress = true; //Run worker bgWorker.RunWorkerAsync(); }
public int Configure_Start_Single_Measurement(Parameters Parameters_Instance ) { StopTask(); // ensure clear tasks before measurement string ParametersFileName = Parameters_Instance.Output_File + ".json"; using (System.IO.StreamWriter file = new System.IO.StreamWriter(ParametersFileName)) { file.Write(JsonConvert.SerializeObject(Parameters_Instance, Formatting.Indented)); } _Parameters_Instance = Parameters_Instance; if (_Parameters_Instance.NumberOfSamples == "Infinite") { Number_Of_Samples_Reqired = -1; Is_Number_Of_Samples_Infinite = true; } else { Is_Number_Of_Samples_Infinite = false; try { Number_Of_Samples_Reqired = int.Parse(_Parameters_Instance.NumberOfSamples); } catch (Exception) { StopTask(); MessageBox.Show("Number of samples is not an integer number or 'Infinite'."); return(1); } } Number_Of_Samples_Measured = 0; // Find output data format in case of text output if (Parameters_Instance.Input_Channel_Value_Save_Format.Substring(0, 4).ToLower() == "text") { int Index2 = Parameters_Instance.Input_Channel_Value_Save_Format.LastIndexOf(")"); int Index1 = Parameters_Instance.Input_Channel_Value_Save_Format.IndexOf("("); Input_Channel_Value_Save_Format_Syntax = Parameters_Instance.Input_Channel_Value_Save_Format.Substring(Index1 + 1, Index2 - Index1 - 1); MainWindow.WindowInstance.Dispatcher.BeginInvoke(new MainWindow.Append_Log_Delegate(MainWindow.WindowInstance.Append_Log), "Output syntax:" + Input_Channel_Value_Save_Format_Syntax + "\n" ); } // Sync pulse double Sync_PulseVoltage = +4.9; // [V] double Sync_IdileVoltage = 0.0; int NumberOfSamples_During_Pulse = 10; double WritingRate_Pulse = NumberOfSamples_During_Pulse / Parameters_Instance.Pulse_Width; double[,] Output_Data = new double[2, NumberOfSamples_During_Pulse + 1]; for (int i = 0; i < NumberOfSamples_During_Pulse; i++) { Output_Data[0, i] = Sync_PulseVoltage; Output_Data[1, i] = Parameters_Instance.Pulse_Voltage; } Output_Data[0, NumberOfSamples_During_Pulse] = Sync_IdileVoltage; Output_Data[1, NumberOfSamples_During_Pulse] = Parameters_Instance.Reverse_Voltage; try { // Create the master and slave tasks inputTask = new Task("InputTask"); outputTask = new Task("OutputTask"); // Configure both tasks with the values selected on the UI. #SyncTask inputTask.AIChannels.CreateVoltageChannel(Parameters_Instance.Input_Channel, "InputChannel", AITerminalConfiguration.Differential, Parameters_Instance.Input_Channel_MinVoltage, Parameters_Instance.Input_Channel_MaxVoltage, AIVoltageUnits.Volts); outputTask.AOChannels.CreateVoltageChannel(Parameters_Instance.Sync_Channel, "", Convert.ToDouble(0.0), Convert.ToDouble(5.0), AOVoltageUnits.Volts); outputTask.AOChannels.CreateVoltageChannel(Parameters_Instance.Output_Channel, "", Parameters_Instance.Output_Channel_MinVoltage, Parameters_Instance.Output_Channel_MaxVoltage, AOVoltageUnits.Volts); // Output pulse inputTask.Timing.ConfigureSampleClock("", Parameters_Instance.Sampling_Rate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, Parameters_Instance.BufferSize); outputTask.Timing.ConfigureSampleClock("", WritingRate_Pulse, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, NumberOfSamples_During_Pulse + 1); // Set up the start trigger DigitalEdgeStartTriggerEdge Input_triggerEdge = DigitalEdgeStartTriggerEdge.Falling; inputTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger(Parameters_Instance.Trigger_Channel, Input_triggerEdge); // Verify the tasks inputTask.Control(TaskAction.Verify); outputTask.Control(TaskAction.Verify); // Write data to each output channel Output_Writer = new AnalogMultiChannelWriter(outputTask.Stream); Output_Writer.WriteMultiSample(false, Output_Data); inputTask.Start(); inputCallback = new AsyncCallback(InputRead); Input_Reader = new AnalogSingleChannelReader(inputTask.Stream); //// Use SynchronizeCallbacks to specify that the object //// marshals callbacks across threads appropriately. Input_Reader.SynchronizeCallbacks = true; Input_Reader.BeginReadMultiSample(Parameters_Instance.BufferSize, inputCallback, inputTask); // Generate Sync pulse //syncTask.Start(); outputTask.Start(); MainWindow.WindowInstance.Dispatcher.BeginInvoke(new MainWindow.Append_Log_Delegate(MainWindow.WindowInstance.Append_Log), "Done: Configure_Start " + Number_Of_measurements_Measured_string + "\n" ); //inputTask.WaitUntilDone(); } catch (Exception ex) { StopTask(); MessageBox.Show(ex.Message); return(1); } return(0); }
// Look at the stimulation hardware settings and create NI Tasks that reflect the user's choices private void UpdateStimulationSettings() { try { if (stimPulseTask != null) { stimPulseTask.Dispose(); stimPulseTask = null; } if (stimDigitalTask != null) { stimDigitalTask.Dispose(); stimDigitalTask = null; } if (Properties.Settings.Default.UseStimulator) { if (stimDigitalTask == null) { stimDigitalTask = new Task("stimDigitalTask"); stimPulseTask = new Task("stimPulseTask"); if (Properties.Settings.Default.StimPortBandwidth == 32) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes else if (Properties.Settings.Default.StimPortBandwidth == 8) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes if (Properties.Settings.Default.StimPortBandwidth == 32) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); } if (Properties.Settings.Default.UseCineplex) { stimPulseTask.Timing.ReferenceClockSource = videoTask.Timing.ReferenceClockSource; stimPulseTask.Timing.ReferenceClockRate = videoTask.Timing.ReferenceClockRate; } else { string tmp1 = Properties.Settings.Default.StimulatorDevice.ToString(); string tmp2 = Properties.Settings.Default.AnalogInDevice[0].ToString(); if (tmp1.Equals(tmp2)) { stimPulseTask.Timing.ReferenceClockSource = "OnboardClock"; } else { stimPulseTask.Timing.ReferenceClockSource = "/" + Properties.Settings.Default.StimulatorDevice.ToString() + "/PFI0"; stimPulseTask.Timing.ReferenceClockRate = 10000000.0; //10 MHz timebase } } stimDigitalTask.Timing.ConfigureSampleClock("100KHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimPulseTask.Timing.ConfigureSampleClock("100KHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimDigitalTask.SynchronizeCallbacks = false; stimPulseTask.SynchronizeCallbacks = false; stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); stimPulseWriter = new AnalogMultiChannelWriter(stimPulseTask.Stream); stimPulseTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( "/" + Properties.Settings.Default.StimulatorDevice + "/PFI6", DigitalEdgeStartTriggerEdge.Rising); stimDigitalTask.Control(TaskAction.Verify); stimPulseTask.Control(TaskAction.Verify); //Check to ensure one of the I/V buttons is checked if (!radioButton_impCurrent.Checked && !radioButton_impVoltage.Checked) { radioButton_impCurrent.Checked = true; radioButton_impVoltage.Checked = false; radioButton_stimCurrentControlled.Checked = true; radioButton_stimVoltageControlled.Checked = false; } if (Properties.Settings.Default.UseStimulator) { stimIvsVTask = new Task("stimIvsV"); stimIvsVTask.DOChannels.CreateChannel(Properties.Settings.Default.StimIvsVDevice + "/Port1/line0", "", ChannelLineGrouping.OneChannelForAllLines); stimIvsVWriter = new DigitalSingleChannelWriter(stimIvsVTask.Stream); stimIvsVTask.Control(TaskAction.Verify); if (radioButton_impCurrent.Checked) stimIvsVWriter.WriteSingleSampleSingleLine(true, true); else stimIvsVWriter.WriteSingleSampleSingleLine(true, false); stimIvsVTask.WaitUntilDone(); //stimIvsVTask.Stop(); stimIvsVTask.Dispose(); } } button_stim.Enabled = true; button_stimExpt.Enabled = true; openLoopStart.Enabled = true; radioButton_impCurrent.Enabled = true; radioButton_impVoltage.Enabled = true; radioButton_stimCurrentControlled.Enabled = true; radioButton_stimVoltageControlled.Enabled = true; button_impedanceTest.Enabled = true; } else { button_stim.Enabled = false; button_stimExpt.Enabled = false; openLoopStart.Enabled = false; radioButton_impCurrent.Enabled = false; radioButton_impVoltage.Enabled = false; radioButton_stimCurrentControlled.Enabled = false; radioButton_stimVoltageControlled.Enabled = false; button_impedanceTest.Enabled = false; } Console.WriteLine("UpdateStimulationSettings completed"); } catch (DaqException exception) { MessageBox.Show(exception.Message); //Display Errors reset(); } }
/// <summary> /// This method creates analog and digital output buffers for daqMx cards. Note that the daqmx library seems to only support /// either analog OR digital on a given card at one time. Despite the fact that this method will create both types of buffers, /// it will probably throw some daqMX level exceptions if asked to create both analog and digital buffers for the same device. /// </summary> /// <param name="deviceName"></param> /// <param name="deviceSettings"></param> /// <param name="sequence"></param> /// <param name="settings"></param> /// <param name="usedDigitalChannels">digital channels which reside on this server.</param> /// <param name="usedAnalogChannels">analog channels which reside on this server</param> /// <returns></returns> public static Task createDaqMxTask(string deviceName, DeviceSettings deviceSettings, SequenceData sequence, SettingsData settings, Dictionary <int, HardwareChannel> usedDigitalChannels, Dictionary <int, HardwareChannel> usedAnalogChannels, ServerSettings serverSettings, out long expectedSamplesGenerated) { expectedSamplesGenerated = 0; Task task = new Task(deviceName + " output task"); List <int> analogIDs; List <HardwareChannel> analogs; Dictionary <int, int[]> port_digital_IDs; List <int> usedPortNumbers; // Parse and create channels. parseAndCreateChannels(deviceName, deviceSettings, usedDigitalChannels, usedAnalogChannels, task, out analogIDs, out analogs, out port_digital_IDs, out usedPortNumbers); if (analogIDs.Count != 0) { if (deviceSettings.UseCustomAnalogTransferSettings) { task.AOChannels.All.DataTransferMechanism = deviceSettings.AnalogDataTransferMechanism; task.AOChannels.All.DataTransferRequestCondition = deviceSettings.AnalogDataTransferCondition; } } if (usedPortNumbers.Count != 0) { if (deviceSettings.UseCustomDigitalTransferSettings) { task.DOChannels.All.DataTransferMechanism = deviceSettings.DigitalDataTransferMechanism; task.DOChannels.All.DataTransferRequestCondition = deviceSettings.DigitalDataTransferCondition; } } // ok! now create the buffers #region NON variable timebase buffer if (deviceSettings.UsingVariableTimebase == false) { // non "variable timebase" buffer creation double timeStepSize = Common.getPeriodFromFrequency(deviceSettings.SampleClockRate); int nBaseSamples = sequence.nSamples(timeStepSize); // for reasons that are utterly stupid and frustrating, the DAQmx libraries seem to prefer sample // buffers with lengths that are a multiple of 4. (otherwise they, on occasion, depending on the parity of the // number of channels, throw exceptions complaining. // thus we add a few filler samples at the end of the sequence which parrot back the last sample. int nFillerSamples = 4 - nBaseSamples % 4; if (nFillerSamples == 4) { nFillerSamples = 0; } int nSamples = nBaseSamples + nFillerSamples; if (deviceSettings.MySampleClockSource == DeviceSettings.SampleClockSource.DerivedFromMaster) { task.Timing.ConfigureSampleClock("", deviceSettings.SampleClockRate, deviceSettings.ClockEdge, SampleQuantityMode.FiniteSamples, nSamples); } else { task.Timing.ConfigureSampleClock(deviceSettings.SampleClockExternalSource, deviceSettings.SampleClockRate, deviceSettings.ClockEdge, SampleQuantityMode.FiniteSamples, nSamples); } if (deviceSettings.MasterTimebaseSource != "" && deviceSettings.MasterTimebaseSource != null) { task.Timing.MasterTimebaseSource = deviceSettings.MasterTimebaseSource.ToString(); } // Analog first... if (analogIDs.Count != 0) { double[,] analogBuffer; double[] singleChannelBuffer; try { analogBuffer = new double[analogs.Count, nSamples]; singleChannelBuffer = new double[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate analog buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < analogIDs.Count; i++) { int analogID = analogIDs[i]; if (settings.logicalChannelManager.Analogs[analogID].TogglingChannel) { DaqMxTaskGenerator.getAnalogTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Analogs[analogID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Analogs[analogID].analogOverrideValue; } } else { sequence.computeAnalogBuffer(analogIDs[i], timeStepSize, singleChannelBuffer); } for (int j = 0; j < nBaseSamples; j++) { analogBuffer[i, j] = singleChannelBuffer[j]; } for (int j = nBaseSamples; j < nSamples; j++) { analogBuffer[i, j] = analogBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(task.Stream); writer.WriteMultiSample(false, analogBuffer); // analog cards report the exact number of generated samples. for non-variable timebase this is nSamples expectedSamplesGenerated = nSamples; } if (usedPortNumbers.Count != 0) { byte[,] digitalBuffer; bool[] singleChannelBuffer; try { digitalBuffer = new byte[usedPortNumbers.Count, nSamples]; singleChannelBuffer = new bool[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate digital buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < usedPortNumbers.Count; i++) { int portNum = usedPortNumbers[i]; byte digitalBitMask = 1; for (int lineNum = 0; lineNum < 8; lineNum++) { int digitalID = port_digital_IDs[portNum][lineNum]; if (digitalID != -1) { if (settings.logicalChannelManager.Digitals[digitalID].TogglingChannel) { getDigitalTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Digitals[digitalID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Digitals[digitalID].digitalOverrideValue; } } else { sequence.computeDigitalBuffer(digitalID, timeStepSize, singleChannelBuffer); } // byte digitalBitMask = (byte)(((byte) 2)^ ((byte)lineNum)); for (int j = 0; j < nBaseSamples; j++) { // copy the bit value into the digital buffer byte. if (singleChannelBuffer[j]) { digitalBuffer[i, j] |= digitalBitMask; } } } digitalBitMask = (byte)(digitalBitMask << 1); } for (int j = nBaseSamples; j < nSamples; j++) { digitalBuffer[i, j] = digitalBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); DigitalMultiChannelWriter writer = new DigitalMultiChannelWriter(task.Stream); writer.WriteMultiSamplePort(false, digitalBuffer); /// Digital cards report the number of generated samples as a multiple of 4 expectedSamplesGenerated = nSamples; } } #endregion #region Variable timebase buffer creation else // variable timebase buffer creation... { double timeStepSize = Common.getPeriodFromFrequency(deviceSettings.SampleClockRate); TimestepTimebaseSegmentCollection timebaseSegments = sequence.generateVariableTimebaseSegments(serverSettings.VariableTimebaseType, timeStepSize); int nBaseSamples = timebaseSegments.nSegmentSamples(); nBaseSamples++; // add one sample for the dwell sample at the end of the buffer // for reasons that are utterly stupid and frustrating, the DAQmx libraries seem to prefer sample // buffers with lengths that are a multiple of 4. (otherwise they, on occasion, depending on the parity of the // number of channels, throw exceptions complaining. // thus we add a few filler samples at the end of the sequence which parrot back the last sample. int nFillerSamples = 4 - nBaseSamples % 4; if (nFillerSamples == 4) { nFillerSamples = 0; } int nSamples = nBaseSamples + nFillerSamples; if (deviceSettings.MySampleClockSource == DeviceSettings.SampleClockSource.DerivedFromMaster) { throw new Exception("Attempt to use a uniform sample clock with a variable timebase enabled device. This will not work. To use a variable timebase for this device, you must specify an external sample clock source."); } else { task.Timing.ConfigureSampleClock(deviceSettings.SampleClockExternalSource, deviceSettings.SampleClockRate, deviceSettings.ClockEdge, SampleQuantityMode.FiniteSamples, nSamples); } // Analog first... if (analogIDs.Count != 0) { double[,] analogBuffer; double[] singleChannelBuffer; try { analogBuffer = new double[analogs.Count, nSamples]; singleChannelBuffer = new double[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate analog buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < analogIDs.Count; i++) { int analogID = analogIDs[i]; if (settings.logicalChannelManager.Analogs[analogID].TogglingChannel) { getAnalogTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Analogs[analogID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Analogs[analogID].analogOverrideValue; } } else { sequence.computeAnalogBuffer(analogIDs[i], timeStepSize, singleChannelBuffer, timebaseSegments); } for (int j = 0; j < nBaseSamples; j++) { analogBuffer[i, j] = singleChannelBuffer[j]; } for (int j = nBaseSamples; j < nSamples; j++) { analogBuffer[i, j] = analogBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(task.Stream); writer.WriteMultiSample(false, analogBuffer); // Analog cards report the exact number of samples generated. for variable timebase this is nBaseSamples expectedSamplesGenerated = nBaseSamples; } if (usedPortNumbers.Count != 0) { byte[,] digitalBuffer; bool[] singleChannelBuffer; try { digitalBuffer = new byte[usedPortNumbers.Count, nSamples]; singleChannelBuffer = new bool[nSamples]; } catch (Exception e) { throw new Exception("Unable to allocate digital buffer for device " + deviceName + ". Reason: " + e.Message + "\n" + e.StackTrace); } for (int i = 0; i < usedPortNumbers.Count; i++) { int portNum = usedPortNumbers[i]; byte digitalBitMask = 1; for (int lineNum = 0; lineNum < 8; lineNum++) { int digitalID = port_digital_IDs[portNum][lineNum]; if (digitalID != -1) { if (settings.logicalChannelManager.Digitals[digitalID].TogglingChannel) { getDigitalTogglingBuffer(singleChannelBuffer); } else if (settings.logicalChannelManager.Digitals[digitalID].overridden) { for (int j = 0; j < singleChannelBuffer.Length; j++) { singleChannelBuffer[j] = settings.logicalChannelManager.Digitals[digitalID].digitalOverrideValue; } } else { sequence.computeDigitalBuffer(digitalID, timeStepSize, singleChannelBuffer, timebaseSegments); } // byte digitalBitMask = (byte)(((byte) 2)^ ((byte)lineNum)); for (int j = 0; j < nBaseSamples; j++) { // copy the bit value into the digital buffer byte. if (singleChannelBuffer[j]) { digitalBuffer[i, j] |= digitalBitMask; } } } digitalBitMask = (byte)(digitalBitMask << 1); } for (int j = nBaseSamples; j < nSamples; j++) { digitalBuffer[i, j] = digitalBuffer[i, j - 1]; } } singleChannelBuffer = null; System.GC.Collect(); DigitalMultiChannelWriter writer = new DigitalMultiChannelWriter(task.Stream); writer.WriteMultiSamplePort(false, digitalBuffer); // digital cards report number of samples generated up to multiple of 4 expectedSamplesGenerated = nSamples; } } #endregion if (deviceSettings.StartTriggerType == DeviceSettings.TriggerType.TriggerIn) { task.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( deviceSettings.TriggerInPort, DigitalEdgeStartTriggerEdge.Rising); } task.Control(TaskAction.Verify); task.Control(TaskAction.Commit); task.Control(TaskAction.Reserve); return(task); }
private void WriteAnalog(IDictionary<Channel, double[]> output, int nsamples) { var data = new double[output.Count, nsamples]; var chans = DAQTasks.AOChannels.Cast<AOChannel>().ToList(); foreach (var o in output) { int chanIndex = chans.FindIndex(c => c.PhysicalName == o.Key.PhysicalName); for (int i = 0; i < o.Value.Count(); i++) { data[chanIndex, i] = o.Value[i]; } } var writer = new AnalogMultiChannelWriter(DAQTasks.AOStream); writer.WriteMultiSample(false, data); }
/* * /// <summary> * /// This class contains both the analog and the digital tasks returned from a specific device. * /// The reason for its existence is that if a device is to have both its analog and its digital outputs used, * /// then they must exist in separate tasks. * /// </summary> * /// * public class TaskCollection * { * public Task analogTask; * public Task digitalTask; * } */ /* * public static Task createVariableTimebaseTask(string digitalTimebaseOutLine, string analogTimebaseOutLine) * { * * }*/ /// /// This method creates a daqMX task for an "output now" command, and starts the output. /// </summary> /// <param name="deviceName"></param> /// <param name="settings"></param> /// <param name="output"></param> /// <returns></returns> public static Task createDaqMxTaskAndOutputNow(string deviceName, DeviceSettings deviceSettings, SingleOutputFrame output, SettingsData settings, Dictionary <int, HardwareChannel> usedDigitalChannels, Dictionary <int, HardwareChannel> usedAnalogChannels) { Task task = new Task(deviceName + " output task"); List <int> analogIDs; List <HardwareChannel> analogs; Dictionary <int, int[]> port_digital_IDs; List <int> usedPortNumbers; // Parse and create channels. parseAndCreateChannels(deviceName, deviceSettings, usedDigitalChannels, usedAnalogChannels, task, out analogIDs, out analogs, out port_digital_IDs, out usedPortNumbers); // now create buffer. task.Timing.SampleTimingType = SampleTimingType.OnDemand; // analog output if (analogIDs.Count != 0) { // extract a list of analog values corresponding to the list analodIDs. This is // sorted in the same way as the channels were created in parseAndCreateChannels List <double> outputValues = new List <double>(); foreach (int analogID in analogIDs) { double val; if (output.analogValues.ContainsKey(analogID)) { val = output.analogValues[analogID]; } else { val = 0; } outputValues.Add(val); } AnalogMultiChannelWriter writer = new AnalogMultiChannelWriter(task.Stream); writer.WriteSingleSample(true, outputValues.ToArray()); } // digital output if (usedPortNumbers.Count != 0) { List <byte> outputValues = new List <byte>(); foreach (int portNumber in usedPortNumbers) { byte digitalMask = 1; byte value = 0; for (int lineNum = 0; lineNum < 8; lineNum++) { int digitalID = port_digital_IDs[portNumber][lineNum]; if (digitalID != -1) { bool val = false; if (output.digitalValues.ContainsKey(digitalID)) { val = output.digitalValues[digitalID]; } if (val) { value |= digitalMask; } } digitalMask = (byte)(digitalMask << 1); } outputValues.Add(value); } DigitalMultiChannelWriter writer = new DigitalMultiChannelWriter(task.Stream); writer.WriteSingleSamplePort(true, outputValues.ToArray()); } return(task); }
//call this method after changing stimulation settings, or finishing a stimulation experiment //includes code to set dc offsets back to zero private void updateStim() { lock (this) { bool placedzeros = false; if (stimPulseTask != null || stimDigitalTask != null) { try { // If we were ruuning a closed loop or open-loop protocol, this will zero the outputs double[,] AnalogBuffer = new double[stimPulseTask.AOChannels.Count, STIMBUFFSIZE]; // buffer for analog channels UInt32[] DigitalBuffer = new UInt32[STIMBUFFSIZE]; stimPulseTask.Stop(); stimDigitalTask.Stop(); stimPulseWriter.WriteMultiSample(true, AnalogBuffer); stimDigitalWriter.WriteMultiSamplePort(true, DigitalBuffer); stimPulseTask.WaitUntilDone(20); stimDigitalTask.WaitUntilDone(20); stimPulseTask.Stop(); stimDigitalTask.Stop(); placedzeros = true; } catch (Exception ex) { placedzeros = false; } } if (stimDigitalTask != null) { stimDigitalTask.Dispose(); stimDigitalTask = null; } if (stimPulseTask != null) { stimPulseTask.Dispose(); stimPulseTask = null; } if (Properties.Settings.Default.UseStimulator) { stimPulseTask = new Task("stimPulseTask"); stimDigitalTask = new Task("stimDigitalTask"); if (Properties.Settings.Default.StimPortBandwidth == 32) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes else if (Properties.Settings.Default.StimPortBandwidth == 8) stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes if (Properties.Settings.Default.StimPortBandwidth == 32) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); } if (Properties.Settings.Default.UseCineplex) { stimPulseTask.Timing.ReferenceClockSource = videoTask.Timing.ReferenceClockSource; stimPulseTask.Timing.ReferenceClockRate = videoTask.Timing.ReferenceClockRate; } else { stimPulseTask.Timing.ReferenceClockSource = "OnboardClock"; //stimPulseTask.Timing.ReferenceClockRate = 10000000.0; //10 MHz timebase } stimDigitalTask.Timing.ConfigureSampleClock("100kHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimPulseTask.Timing.ConfigureSampleClock("100kHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimDigitalTask.SynchronizeCallbacks = false; stimPulseTask.SynchronizeCallbacks = false; stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); stimPulseWriter = new AnalogMultiChannelWriter(stimPulseTask.Stream); stimPulseTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( "/" + Properties.Settings.Default.StimulatorDevice + "/PFI6", DigitalEdgeStartTriggerEdge.Rising); stimDigitalTask.Control(TaskAction.Verify); stimPulseTask.Control(TaskAction.Verify); //Check to ensure one of the I/V buttons is checked if (!radioButton_impCurrent.Checked && !radioButton_impVoltage.Checked) { radioButton_impCurrent.Checked = true; radioButton_impVoltage.Checked = false; radioButton_stimCurrentControlled.Checked = true; radioButton_stimVoltageControlled.Checked = false; } if (Properties.Settings.Default.UseStimulator) { stimIvsVTask = new Task("stimIvsV"); stimIvsVTask.DOChannels.CreateChannel(Properties.Settings.Default.StimIvsVDevice + "/Port1/line0", "", ChannelLineGrouping.OneChannelForAllLines); stimIvsVWriter = new DigitalSingleChannelWriter(stimIvsVTask.Stream); //stimIvsVTask.Timing.ConfigureSampleClock("100kHztimebase", 100000, // SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimIvsVTask.Control(TaskAction.Verify); //byte[] b_array; //if (radioButton_impCurrent.Checked) // b_array = new byte[5] { 255, 255, 255, 255, 255 }; //else // b_array = new byte[5] { 0, 0, 0, 0, 0 }; //DigitalWaveform wfm = new DigitalWaveform(5, 8, DigitalState.ForceDown); //wfm = NationalInstruments.DigitalWaveform.FromPort(b_array); //stimIvsVWriter.WriteWaveform(true, wfm); if (radioButton_impCurrent.Checked) stimIvsVWriter.WriteSingleSampleSingleLine(true, true); else stimIvsVWriter.WriteSingleSampleSingleLine(true, false); stimIvsVTask.WaitUntilDone(); stimIvsVTask.Stop(); stimIvsVTask.Dispose(); if (!placedzeros)//try again { double[,] AnalogBuffer = new double[stimPulseTask.AOChannels.Count, STIMBUFFSIZE]; // buffer for analog channels UInt32[] DigitalBuffer = new UInt32[STIMBUFFSIZE]; stimPulseTask.Stop(); stimDigitalTask.Stop(); stimPulseWriter.WriteMultiSample(true, AnalogBuffer); stimDigitalWriter.WriteMultiSamplePort(true, DigitalBuffer); //stimPulseTask.Start(); //stimDigitalTask.Start(); //stimPulseTask.WaitUntilDone(); stimPulseTask.Stop(); stimDigitalTask.Stop(); } } button_stim.Enabled = true; button_stimExpt.Enabled = true; openLoopStart.Enabled = true; radioButton_impCurrent.Enabled = true; radioButton_impVoltage.Enabled = true; radioButton_stimCurrentControlled.Enabled = true; radioButton_stimVoltageControlled.Enabled = true; button_impedanceTest.Enabled = true; } else { button_stim.Enabled = false; button_stimExpt.Enabled = false; openLoopStart.Enabled = false; radioButton_impCurrent.Enabled = false; radioButton_impVoltage.Enabled = false; radioButton_stimCurrentControlled.Enabled = false; radioButton_stimVoltageControlled.Enabled = false; button_impedanceTest.Enabled = false; } } Console.WriteLine("updateStim"); }
// Look at the stimulation hardware settings and create NI Tasks that reflect the user's choices private void UpdateStimulationSettings() { try { if (stimPulseTask != null) { stimPulseTask.Dispose(); stimPulseTask = null; } if (stimDigitalTask != null) { stimDigitalTask.Dispose(); stimDigitalTask = null; } if (Properties.Settings.Default.UseStimulator) { if (stimDigitalTask == null) { stimDigitalTask = new Task("stimDigitalTask"); stimPulseTask = new Task("stimPulseTask"); if (Properties.Settings.Default.StimPortBandwidth == 32) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } if (Properties.Settings.Default.StimPortBandwidth == 32) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); } if (Properties.Settings.Default.UseCineplex) { stimPulseTask.Timing.ReferenceClockSource = videoTask.Timing.ReferenceClockSource; stimPulseTask.Timing.ReferenceClockRate = videoTask.Timing.ReferenceClockRate; } else { string tmp1 = Properties.Settings.Default.StimulatorDevice.ToString(); string tmp2 = Properties.Settings.Default.AnalogInDevice[0].ToString(); if (tmp1.Equals(tmp2)) { stimPulseTask.Timing.ReferenceClockSource = "OnboardClock"; } else { stimPulseTask.Timing.ReferenceClockSource = "/" + Properties.Settings.Default.StimulatorDevice.ToString() + "/PFI0"; stimPulseTask.Timing.ReferenceClockRate = 10000000.0; //10 MHz timebase } } stimDigitalTask.Timing.ConfigureSampleClock("100KHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimPulseTask.Timing.ConfigureSampleClock("100KHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimDigitalTask.SynchronizeCallbacks = false; stimPulseTask.SynchronizeCallbacks = false; stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); stimPulseWriter = new AnalogMultiChannelWriter(stimPulseTask.Stream); stimPulseTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( "/" + Properties.Settings.Default.StimulatorDevice + "/PFI6", DigitalEdgeStartTriggerEdge.Rising); stimDigitalTask.Control(TaskAction.Verify); stimPulseTask.Control(TaskAction.Verify); //Check to ensure one of the I/V buttons is checked if (!radioButton_impCurrent.Checked && !radioButton_impVoltage.Checked) { radioButton_impCurrent.Checked = true; radioButton_impVoltage.Checked = false; radioButton_stimCurrentControlled.Checked = true; radioButton_stimVoltageControlled.Checked = false; } if (Properties.Settings.Default.UseStimulator) { stimIvsVTask = new Task("stimIvsV"); stimIvsVTask.DOChannels.CreateChannel(Properties.Settings.Default.StimIvsVDevice + "/Port1/line0", "", ChannelLineGrouping.OneChannelForAllLines); stimIvsVWriter = new DigitalSingleChannelWriter(stimIvsVTask.Stream); stimIvsVTask.Control(TaskAction.Verify); if (radioButton_impCurrent.Checked) { stimIvsVWriter.WriteSingleSampleSingleLine(true, true); } else { stimIvsVWriter.WriteSingleSampleSingleLine(true, false); } stimIvsVTask.WaitUntilDone(); //stimIvsVTask.Stop(); stimIvsVTask.Dispose(); } } button_stim.Enabled = true; button_stimExpt.Enabled = true; openLoopStart.Enabled = true; radioButton_impCurrent.Enabled = true; radioButton_impVoltage.Enabled = true; radioButton_stimCurrentControlled.Enabled = true; radioButton_stimVoltageControlled.Enabled = true; button_impedanceTest.Enabled = true; } else { button_stim.Enabled = false; button_stimExpt.Enabled = false; openLoopStart.Enabled = false; radioButton_impCurrent.Enabled = false; radioButton_impVoltage.Enabled = false; radioButton_stimCurrentControlled.Enabled = false; radioButton_stimVoltageControlled.Enabled = false; button_impedanceTest.Enabled = false; } Console.WriteLine("UpdateStimulationSettings completed"); } catch (DaqException exception) { MessageBox.Show(exception.Message); //Display Errors reset(); } }
//call this method after changing stimulation settings, or finishing a stimulation experiment //includes code to set dc offsets back to zero private void updateStim() { lock (this) { bool placedzeros = false; if (stimPulseTask != null || stimDigitalTask != null) { try { // If we were ruuning a closed loop or open-loop protocol, this will zero the outputs double[,] AnalogBuffer = new double[stimPulseTask.AOChannels.Count, STIMBUFFSIZE]; // buffer for analog channels UInt32[] DigitalBuffer = new UInt32[STIMBUFFSIZE]; stimPulseTask.Stop(); stimDigitalTask.Stop(); stimPulseWriter.WriteMultiSample(true, AnalogBuffer); stimDigitalWriter.WriteMultiSamplePort(true, DigitalBuffer); stimPulseTask.WaitUntilDone(20); stimDigitalTask.WaitUntilDone(20); stimPulseTask.Stop(); stimDigitalTask.Stop(); placedzeros = true; } catch (Exception ex) { placedzeros = false; } } if (stimDigitalTask != null) { stimDigitalTask.Dispose(); stimDigitalTask = null; } if (stimPulseTask != null) { stimPulseTask.Dispose(); stimPulseTask = null; } if (Properties.Settings.Default.UseStimulator) { stimPulseTask = new Task("stimPulseTask"); stimDigitalTask = new Task("stimDigitalTask"); if (Properties.Settings.Default.StimPortBandwidth == 32) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } if (Properties.Settings.Default.StimPortBandwidth == 32) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); } if (Properties.Settings.Default.UseCineplex) { stimPulseTask.Timing.ReferenceClockSource = videoTask.Timing.ReferenceClockSource; stimPulseTask.Timing.ReferenceClockRate = videoTask.Timing.ReferenceClockRate; } else { stimPulseTask.Timing.ReferenceClockSource = "OnboardClock"; //stimPulseTask.Timing.ReferenceClockRate = 10000000.0; //10 MHz timebase } stimDigitalTask.Timing.ConfigureSampleClock("100kHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimPulseTask.Timing.ConfigureSampleClock("100kHzTimebase", STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimDigitalTask.SynchronizeCallbacks = false; stimPulseTask.SynchronizeCallbacks = false; stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); stimPulseWriter = new AnalogMultiChannelWriter(stimPulseTask.Stream); stimPulseTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger( "/" + Properties.Settings.Default.StimulatorDevice + "/PFI6", DigitalEdgeStartTriggerEdge.Rising); stimDigitalTask.Control(TaskAction.Verify); stimPulseTask.Control(TaskAction.Verify); //Check to ensure one of the I/V buttons is checked if (!radioButton_impCurrent.Checked && !radioButton_impVoltage.Checked) { radioButton_impCurrent.Checked = true; radioButton_impVoltage.Checked = false; radioButton_stimCurrentControlled.Checked = true; radioButton_stimVoltageControlled.Checked = false; } if (Properties.Settings.Default.UseStimulator) { stimIvsVTask = new Task("stimIvsV"); stimIvsVTask.DOChannels.CreateChannel(Properties.Settings.Default.StimIvsVDevice + "/Port1/line0", "", ChannelLineGrouping.OneChannelForAllLines); stimIvsVWriter = new DigitalSingleChannelWriter(stimIvsVTask.Stream); //stimIvsVTask.Timing.ConfigureSampleClock("100kHztimebase", 100000, // SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimIvsVTask.Control(TaskAction.Verify); //byte[] b_array; //if (radioButton_impCurrent.Checked) // b_array = new byte[5] { 255, 255, 255, 255, 255 }; //else // b_array = new byte[5] { 0, 0, 0, 0, 0 }; //DigitalWaveform wfm = new DigitalWaveform(5, 8, DigitalState.ForceDown); //wfm = NationalInstruments.DigitalWaveform.FromPort(b_array); //stimIvsVWriter.WriteWaveform(true, wfm); if (radioButton_impCurrent.Checked) { stimIvsVWriter.WriteSingleSampleSingleLine(true, true); } else { stimIvsVWriter.WriteSingleSampleSingleLine(true, false); } stimIvsVTask.WaitUntilDone(); stimIvsVTask.Stop(); stimIvsVTask.Dispose(); if (!placedzeros) //try again { double[,] AnalogBuffer = new double[stimPulseTask.AOChannels.Count, STIMBUFFSIZE]; // buffer for analog channels UInt32[] DigitalBuffer = new UInt32[STIMBUFFSIZE]; stimPulseTask.Stop(); stimDigitalTask.Stop(); stimPulseWriter.WriteMultiSample(true, AnalogBuffer); stimDigitalWriter.WriteMultiSamplePort(true, DigitalBuffer); //stimPulseTask.Start(); //stimDigitalTask.Start(); //stimPulseTask.WaitUntilDone(); stimPulseTask.Stop(); stimDigitalTask.Stop(); } } button_stim.Enabled = true; button_stimExpt.Enabled = true; openLoopStart.Enabled = true; radioButton_impCurrent.Enabled = true; radioButton_impVoltage.Enabled = true; radioButton_stimCurrentControlled.Enabled = true; radioButton_stimVoltageControlled.Enabled = true; button_impedanceTest.Enabled = true; } else { button_stim.Enabled = false; button_stimExpt.Enabled = false; openLoopStart.Enabled = false; radioButton_impCurrent.Enabled = false; radioButton_impVoltage.Enabled = false; radioButton_stimCurrentControlled.Enabled = false; radioButton_stimVoltageControlled.Enabled = false; button_impedanceTest.Enabled = false; } } Console.WriteLine("updateStim"); }
public void Write() { try { string[] channelNameList = DaqSystem.Local.GetPhysicalChannels(PhysicalChannelTypes.AO, PhysicalChannelAccess.External); if (channelNameList.Length > 0) { Task task1 = new Task(); task1.AOChannels.CreateVoltageChannel(channelNameList[0], "Voltage1", 0, 10, AOVoltageUnits.Volts); task1.AOChannels.CreateVoltageChannel(channelNameList[1], "Voltage2", 0, 10, AOVoltageUnits.Volts); task1.AOChannels.CreateVoltageChannel(channelNameList[2], "Voltage3", 0, 10, AOVoltageUnits.Volts); task1.Timing.ConfigureSampleClock("", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); task1.Control(TaskAction.Verify); Task task2 = new Task(); task2.AOChannels.CreateVoltageChannel(channelNameList[0], "Voltage1", 0, 10, AOVoltageUnits.Volts); task2.AOChannels.CreateVoltageChannel(channelNameList[1], "Voltage2", 0, 10, AOVoltageUnits.Volts); task2.AOChannels.CreateVoltageChannel(channelNameList[2], "Voltage3", 0, 10, AOVoltageUnits.Volts); task2.Timing.ConfigureSampleClock("", 100, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); task2.Control(TaskAction.Verify); AnalogMultiChannelWriter aowriter1 = new AnalogMultiChannelWriter(task1.Stream); AnalogMultiChannelWriter aowriter2 = new AnalogMultiChannelWriter(task2.Stream); double[,] wave = new double[3, 1000]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 1000; j++) { wave[i,j] = 0.001*(1000-j); } } Console.WriteLine("Task is ready"); aowriter1.WriteMultiSample(false, wave); task1.Control(TaskAction.Start); Console.ReadKey(); task1.Control(TaskAction.Stop); task1.Control(TaskAction.Unreserve); Console.WriteLine("Task1 is released"); aowriter2.WriteMultiSample(false, wave); task1.Control(TaskAction.Start); Console.ReadKey(); task1.Control(TaskAction.Stop); task1.Control(TaskAction.Unreserve); Console.ReadKey(); } } catch (DaqException e) { Console.Out.WriteLine(e.Message); } }
private void button_electrolesioningStart_Click(object sender, EventArgs e) { //Change mouse cursor to waiting cursor this.Cursor = Cursors.WaitCursor; //Grab values from UI double voltage = Convert.ToDouble(numericUpDown_electrolesioningVoltage.Value); double duration = Convert.ToDouble(numericUpDown_electrolesioningDuration.Value); List <Int32> chList = new List <int>(listBox_electrolesioningChannels.SelectedIndices.Count); for (int i = 0; i < listBox_electrolesioningChannels.SelectedIndices.Count; ++i) { chList.Add(listBox_electrolesioningChannels.SelectedIndices[i] + 1); //+1 since indices are 0-based but channels are 1-base } //Disable buttons, so users don't try running two experiments at once button_electrolesioningStart.Enabled = false; button_electrolesioningSelectAll.Enabled = false; button_electrolesioningSelectNone.Enabled = false; button_electrolesioningStart.Refresh(); //Refresh stim task stimDigitalTask.Dispose(); stimDigitalTask = new Task("stimDigitalTask_Electrolesioning"); if (Properties.Settings.Default.StimPortBandwidth == 32) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); //Refresh pulse task stimPulseTask.Dispose(); stimPulseTask = new Task("stimPulseTask"); if (Properties.Settings.Default.StimPortBandwidth == 32) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); stimPulseTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); } stimPulseWriter = new AnalogMultiChannelWriter(stimPulseTask.Stream); stimPulseTask.Timing.ConfigureSampleClock("", StimPulse.STIM_SAMPLING_FREQ, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimPulseTask.Timing.SamplesPerChannel = 2; stimDigitalTask.Control(TaskAction.Verify); stimPulseTask.Control(TaskAction.Verify); //For each channel, deliver lesioning pulse for (int i = 0; i < chList.Count; ++i) { int channel = chList[i]; UInt32 data = StimPulse.channel2MUX((double)channel); //Setup digital waveform, open MUX channel stimDigitalWriter.WriteSingleSamplePort(true, data); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); //Write voltage to channel, wait duration, stop stimPulseWriter.WriteMultiSample(true, new double[, ] { { 0, 0 }, { 0, 0 }, { voltage, voltage }, { 0, 0 } }); stimPulseTask.WaitUntilDone(); stimPulseTask.Stop(); Thread.Sleep((int)(Math.Round(duration * 1000))); //Convert to ms stimPulseWriter.WriteMultiSample(true, new double[, ] { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }); stimPulseTask.WaitUntilDone(); stimPulseTask.Stop(); //Close MUX stimDigitalWriter.WriteSingleSamplePort(true, 0); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); } bool[] fData = new bool[Properties.Settings.Default.StimPortBandwidth]; stimDigitalWriter.WriteSingleSampleMultiLine(true, fData); stimDigitalTask.WaitUntilDone(); stimDigitalTask.Stop(); button_electrolesioningSelectAll.Enabled = true; button_electrolesioningSelectNone.Enabled = true; button_electrolesioningStart.Enabled = true; //Now, destroy the objects we made updateSettings(); this.Cursor = Cursors.Default; }
internal void getImpedance(double startFreq, double stopFreq, double numPeriods, bool isCurrentControlled, int startChannel, int numChannels, double RCurr, double RMeas, double RGain, double commandVoltage, bool useBandpassFilter, bool useMatchedFilter) { this.numPeriods = numPeriods; this.startChannel = startChannel; this.numChannels = numChannels; this.RCurr = RCurr; this.RGain = RGain; this.RMeas = RMeas; this.commandVoltage = commandVoltage; this.isCurrentControlled = isCurrentControlled; this.useBandpassFilter = useBandpassFilter; this.useMatchedFilter = useMatchedFilter; //StartChannel is 1-based if (startFreq == stopFreq) { freqs = new double[1]; } else if ((stopFreq / startFreq) % RESOLUTION == 0) //stopFreq is a RESOLUTION multiple of startFreq { freqs = new double[Convert.ToInt32(Math.Floor(Math.Log(stopFreq / startFreq) / Math.Log(RESOLUTION))) + 1]; //This determines the number of frequencies counting by doublings } else //not an exact multiple { freqs = new double[Convert.ToInt32(Math.Floor(Math.Log(stopFreq / startFreq) / Math.Log(RESOLUTION))) + 2]; //This determines the number of frequencies counting by doublings } //Populate freqs vector freqs[0] = startFreq; for (int i = 1; i < freqs.GetLength(0); ++i) { freqs[i] = freqs[i - 1] * RESOLUTION; } if (freqs[freqs.Length - 1] > stopFreq) { freqs[freqs.Length - 1] = stopFreq; } //Setup tasks impedanceRecord = new Task("Impedance Analog Input Task"); stimDigitalTask = new Task("stimDigitalTask_impedance"); stimAnalogTask = new Task("stimAnalogTask_impedance"); //Choose appropriate input for current/voltage-controlled stimulation String inputChannel = (isCurrentControlled ? "/ai2" : "/ai3"); //if (isCurrentControlled) inputChannel = "/ai2"; //else inputChannel = "/ai3"; impedanceRecord.AIChannels.CreateVoltageChannel(Properties.Settings.Default.ImpedanceDevice + inputChannel, "", AITerminalConfiguration.Rse, -5.0, 5.0, AIVoltageUnits.Volts); //try delaying sampling impedanceRecord.Timing.DelayFromSampleClock = 10; impedanceRecord.Timing.ConfigureSampleClock("", IMPEDANCE_SAMPLING_RATE, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); impedanceReader = new AnalogSingleChannelReader(impedanceRecord.Stream); impedanceRecord.Timing.ReferenceClockSource = "OnboardClock"; //Configure stim digital output task if (Properties.Settings.Default.StimPortBandwidth == 32) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:31", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimDigitalTask.DOChannels.CreateChannel(Properties.Settings.Default.StimulatorDevice + "/Port0/line0:7", "", ChannelLineGrouping.OneChannelForAllLines); //To control MUXes } stimDigitalWriter = new DigitalSingleChannelWriter(stimDigitalTask.Stream); //Configure stim analog output task if (Properties.Settings.Default.StimPortBandwidth == 32) { stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Triggers stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao2", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual Pulse stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao3", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } else if (Properties.Settings.Default.StimPortBandwidth == 8) { stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao0", "", -10.0, 10.0, AOVoltageUnits.Volts); //Actual pulse stimAnalogTask.AOChannels.CreateVoltageChannel(Properties.Settings.Default.StimulatorDevice + "/ao1", "", -10.0, 10.0, AOVoltageUnits.Volts); //Timing } stimAnalogTask.Timing.ConfigureSampleClock("/" + Properties.Settings.Default.ImpedanceDevice + "/ai/SampleClock", IMPEDANCE_SAMPLING_RATE, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples); stimAnalogTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + Properties.Settings.Default.ImpedanceDevice + "/ai/StartTrigger", DigitalEdgeStartTriggerEdge.Rising); impedanceRecord.Control(TaskAction.Verify); stimAnalogTask.Timing.ReferenceClockSource = impedanceRecord.Timing.ReferenceClockSource; stimAnalogTask.Timing.ReferenceClockRate = impedanceRecord.Timing.ReferenceClockRate; stimAnalogWriter = new AnalogMultiChannelWriter(stimAnalogTask.Stream); //Verify tasks impedanceRecord.Control(TaskAction.Verify); stimDigitalTask.Control(TaskAction.Verify); stimAnalogTask.Control(TaskAction.Verify); //Setup storage variable impedance = new double[numChannels][]; for (int c = 0; c < numChannels; ++c) { impedance[c] = new double[freqs.GetLength(0)]; for (int f = 0; f < freqs.Length; ++f) { impedance[c][f] = double.NaN; } } //Setup background worker bgWorker = new BackgroundWorker(); bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged); bgWorker.WorkerSupportsCancellation = true; bgWorker.WorkerReportsProgress = true; //Run worker bgWorker.RunWorkerAsync(); }