Esempio n. 1
0
 public RunLog(DateTime runTime, DateTime listStartTime, SequenceData sequence, SettingsData settings, string sequenceFileName, string settingsFileName)
 {
     this.runTime = runTime;
     this.listStartTime = listStartTime;
     this.runSequence = sequence;
     this.runSettings = settings;
     this.SequenceFileName = sequenceFileName;
     this.SettingsFileName = settingsFileName;
 }
        public void setSettings(SettingsData settings)
        {
            if (mainClientForm.instance != null)
                mainClientForm.instance.cursorWait();
            if (digitalOverrides == null)
            {
                digitalOverrides = new List<DigitalOverride>();
            }
            foreach (DigitalOverride dov in digitalOverrides)
            {
                digitalOverridePanel.Controls.Remove(dov);
                dov.unRegsiterHotkey();
                dov.Dispose();
            }
            digitalOverrides.Clear();

            List<int> digitalIDs = new List<int>(settings.logicalChannelManager.Digitals.Keys);
            digitalIDs.Sort();
            int counter = 0;
            foreach (int id in digitalIDs)
            {
                LogicalChannel chan = settings.logicalChannelManager.Digitals[id];
                DigitalOverride dov = new DigitalOverride(chan, id);
                dov.Location = new Point(digitalOverridePlaceholder.Location.X,
                                        digitalOverridePlaceholder.Location.Y + counter * (digitalOverridePlaceholder.Height - 4));
                digitalOverrides.Add(dov);
                dov.registerHotkey();
                dov.BackColor = Storage.settingsData.DigitalGridColors[counter % Storage.settingsData.DigitalGridColors.Count];
                counter++;
            }
            digitalOverridePanel.Controls.AddRange(digitalOverrides.ToArray());

            if (analogOverrides == null) {
                analogOverrides = new List<AnalogOverride>();
            }
            foreach (AnalogOverride ao in analogOverrides) {
                analogOverridePanel.Controls.Remove(ao);
                ao.Dispose();
            }
            analogOverrides.Clear();

            List<int> analogIDs = new List<int>(settings.logicalChannelManager.Analogs.Keys);
            analogIDs.Sort();
            counter = 0;
            foreach (int id in analogIDs)
            {
                LogicalChannel chan = settings.logicalChannelManager.Analogs[id];
                AnalogOverride ao = new AnalogOverride(chan, id);
                ao.Location = new Point(analogOverridePlaceholder.Location.X, analogOverridePlaceholder.Location.Y + counter * analogOverridePlaceholder.Height);
                analogOverrides.Add(ao);
                counter++;
            }
            analogOverridePanel.Controls.AddRange(analogOverrides.ToArray());

            if (mainClientForm.instance != null)
                mainClientForm.instance.cursorWaitRelease();
        }
 public Dictionary<int, bool[]> _testCalculateAllDigitalBuffersVariableFrequency(SettingsData settings, double masterTimestepSize)
 {
     Dictionary<int, bool[]> ans = new Dictionary<int, bool[]>();
     TimestepTimebaseSegmentCollection varbase = this.generateVariableTimebaseSegments(VariableTimebaseTypes.AnalogGroupControlledVariableFrequencyClock, masterTimestepSize);
     int nSamples = varbase.nSegmentSamples() +1;
     foreach (int digitalChannelId in settings.logicalChannelManager.Digitals.Keys)
     {
         bool[] chanBuff = new bool[nSamples];
         this.computeDigitalBuffer(digitalChannelId, masterTimestepSize, chanBuff, varbase);
         ans.Add(digitalChannelId, chanBuff);
     }
     return ans;
 }
 public Dictionary<int, double[]> _testCalculateAllAnalogBuffersFixedFrequenct(SettingsData settings, double masterTimestepSize)
 {
     Dictionary<int, double[]> ans = new Dictionary<int, double[]>();
     foreach (int analogId in settings.logicalChannelManager.Analogs.Keys)
     {
         ans.Add(analogId, this.computeAnalogBuffer(analogId, masterTimestepSize));
     }
     return ans;
 }
        public void populateWithChannels(SettingsData settings)
        {
            foreach (TimeStep step in TimeSteps)
            {
                // Add digital datapoints to each timestep.
                foreach (int digitalID in settings.logicalChannelManager.ChannelCollections[HardwareChannel.HardwareConstants.ChannelTypes.digital].getSortedChannelIDList())
                {
                    if (!step.DigitalData.ContainsKey(digitalID))
                    {
                        step.DigitalData.Add(digitalID, new DigitalDataPoint());
                    }
                }
            }

            foreach (AnalogGroup ag in AnalogGroups)
            {
                foreach (int analogID in settings.logicalChannelManager.ChannelCollections[HardwareChannel.HardwareConstants.ChannelTypes.analog].getSortedChannelIDList())
                {
                    if (!ag.containsChannelID(analogID))
                    {
                        ag.addChannel(analogID);
                    }
                }
            }
        }
 public ServerActionStatus setSettingsOnConnectedServers(SettingsData settings, EventHandler<MessageEvent> messageLog)
 {
     return runNamedMethodOnConnectedServers("setSettings", new object[] { settings }, 4000, messageLog);
 }
 public ServerActionStatus outputRS232GroupOnConnectedServers(RS232Group rs232Group, SettingsData settings, EventHandler<MessageEvent> messageLog)
 {
     return runNamedMethodOnConnectedServers("outputRS232Group", new object[] { rs232Group, settings }, 4000, messageLog);
 }
        /// <summary>
        /// This method is a sort of combination of createDaqMxVariableTimebaseSource and createDaqMxTask. It is intended 
        /// for use to create a digital output task that has both a variable timebase source on it, without having to discard
        /// all of the other channels on that port (and possibly on its neighboring port).
        /// 
        /// NOTE: No longer true. This function can not create the variable timebase outputs at the same time as
        /// normal outputs. If you attempt to use digital outputs on the same half of the card as your variable timebase output,
        /// this method will complain.
        /// </summary>
        /// <param name="channelName">
        /// Name of the channel that will output the variable timebase clock.
        /// </param>
        /// <param name="portsToUse">
        /// A list of integers specifying the digital ports that this task will use. The task will automatically
        /// make use of the full port that the variable timebase clock belongs to. If portsToUse is null, then 
        /// this function will automatically use both this port and its neighboring port (0 with 1, 2 with 3, etc).
        /// The rationale for this is that on some NI devices, these pairs of ports will share a sample clock and 
        /// cannot truly be used independently.
        /// </param>
        /// <param name="masterFrequency">
        /// The frequency, in hertz, of the master clock which will drive the variable timebase clock and the rest of the
        /// channels in this task.
        /// </param>
        /// <param name="sequenceData"></param>
        /// <param name="timebaseType"></param>
        /// <param name="deviceName"></param>
        /// <param name="deviceSettings"></param>
        /// <param name="sequence"></param>
        /// <param name="settings"></param>
        /// <param name="usedDigitalChannels"></param>
        /// <param name="usedAnalogChannels"></param>
        /// <param name="serverSettings"></param>
        /// <returns></returns>
        public static Task createDaqMxDigitalOutputAndVariableTimebaseSource(string channelName, List<int> portsToUse, int masterFrequency, 
            SequenceData sequenceData, SequenceData.VariableTimebaseTypes timebaseType,
            string deviceName, DeviceSettings deviceSettings, SettingsData settings, Dictionary<int, HardwareChannel> usedDigitalChannels,  ServerSettings serverSettings)
        {
            // First generate the variable timebase buffer. We will need stuff like its length for configuring the task, which is why we do this first.

            TimestepTimebaseSegmentCollection timebaseSegments = sequenceData.generateVariableTimebaseSegments(timebaseType, 1.0 / deviceSettings.SampleClockRate);
            bool[] variableTimebaseBuffer = sequenceData.getVariableTimebaseClock(timebaseSegments);

            if (deviceName.ToUpper() != HardwareChannel.parseDeviceNameStringFromPhysicalChannelString(channelName).ToUpper())
            {
                throw new Exception("The variable timebase device " + HardwareChannel.parseDeviceNameStringFromPhysicalChannelString(channelName) + " does not match device " + deviceName + ". These must match for their their task to be created together.");
            }

            int timebasePortNum;
            int timebaseLineNum;

            try
            {
                timebasePortNum = HardwareChannel.parsePortNumberFromChannelString(channelName);
                timebaseLineNum = HardwareChannel.parseLineNumberFromChannelString(channelName);
            }
            catch (Exception)
            {
                throw new Exception("Channel name " + channelName + " is not a valid digital channel name. Cannot create a variable timebase output on this channel.");
            }

            if (portsToUse == null)
            {
                portsToUse = new List<int>();
                portsToUse.Add(timebasePortNum);
                int spousePort; // this port is likely to have a shared sample clock with timebasePortNum,
                // at least in my experience so far.
                if (timebasePortNum % 2 == 0)
                    spousePort = timebasePortNum + 1;
                else
                    spousePort = timebasePortNum - 1;

                portsToUse.Add(spousePort);
            }

            if (!portsToUse.Contains(timebasePortNum))
            {
                portsToUse.Add(timebasePortNum);
            }

            bool otherChannelsUsedOnUsedPort = false;
            foreach (HardwareChannel hc in usedDigitalChannels.Values)
            {
                if (hc.DeviceName.ToUpper() == deviceName.ToUpper())
                {
                    if (portsToUse.Contains(hc.daqMxDigitalPortNumber()))
                        otherChannelsUsedOnUsedPort = true;
                }
            }

            if (otherChannelsUsedOnUsedPort)
            {
                throw new Exception("Variable timebase channel is on a port that shares a sample clock with a used output channel (on most devices, port 0 and 1 have a shared clock, and port 2 and 3 have a shared clock). This usage is not recommended, and not currently supported. Aborting buffer generation.");

                #region Deprecated code

                /*
                Task task = new Task("Variable timebase output task");

                // Create channels in the task
                foreach (int portNum in portsToUse)
                {
                    task.DOChannels.CreateChannel(deviceName + '/' + HardwareChannel.digitalPhysicalChannelName(portNum), "", ChannelLineGrouping.OneChannelForAllLines);
                }

                // Configure the task...

                task.Timing.ConfigureSampleClock("", masterFrequency, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, variableTimebaseBuffer.Length);

                if (serverSettings.VariableTimebaseTriggerInput != "")
                {
                    task.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger(serverSettings.VariableTimebaseTriggerInput, DigitalEdgeStartTriggerEdge.Rising);
                }

                // Figure out which ports we are going to use, and which digital ID each line on each of those ports
                // maps to.
                Dictionary<int, HardwareChannel> digitalChannelsToUse = getChannelsOnDevice(usedDigitalChannels, deviceName);
                List<int> temp = new List<int>(digitalChannelsToUse.Keys);
                foreach (int id in temp)
                {
                    HardwareChannel ch = digitalChannelsToUse[id];
                    if (!portsToUse.Contains(HardwareChannel.parsePortNumberFromChannelString(ch.ChannelName)))
                    {
                        digitalChannelsToUse.Remove(id);
                    }
                }

                // Remove all of the digital channels this buffer generation is consuming from the
                // usedDigitalChannels dictionary. Why? Because there may still be another task to
                // generate on this device, and this is a way of keeping track of which channels
                // have already had their buffers generated.
                // Since digitalChannelsToUse gets passed by reference from AtticusServerRuntime.generateBuffers(...),
                // these changes thus get communicated back to AtticusServerRuntime.
                foreach (HardwareChannel hc in digitalChannelsToUse.Values)
                {
                    foreach (int i in usedDigitalChannels.Keys)
                    {
                        if (usedDigitalChannels[i] == hc)
                        {
                            usedDigitalChannels.Remove(i);
                            break;
                        }
                    }
                }

                List<int> ids = new List<int>(digitalChannelsToUse.Keys);
                ids.Sort();
                List<HardwareChannel> hcs = new List<HardwareChannel>();
                foreach (int id in ids)
                {
                    hcs.Add(digitalChannelsToUse[id]);
                }

                Dictionary<int, int[]> port_digital_ids;
                List<int> usedPorts;

                groupDigitalChannels(ids, hcs, out port_digital_ids, out usedPorts);

                // now to generate the buffers.

                if (usedPorts.Count != 0)
                {
                    byte[,] digitalBuffer;

                    try
                    {
                        digitalBuffer = new byte[usedPorts.Count, variableTimebaseBuffer.Length];
                    }
                    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 < usedPorts.Count; i++)
                    {
                        int portNum = usedPorts[i];
                        byte digitalBitMask = 1;
                        for (int lineNum = 0; lineNum < 8; lineNum++)
                        {
                            bool[] singleChannelBuffer = null;

                            if (portNum == timebasePortNum && lineNum == timebaseLineNum)
                            { // this current line is the variable timebase...
                                singleChannelBuffer = variableTimebaseBuffer;
                            }
                            else
                            {
                                int digitalID = port_digital_ids[portNum][lineNum];
                                if (digitalID != -1)
                                {
                                    if (settings.logicalChannelManager.Digitals[digitalID].overridden)
                                    {
                                        singleChannelBuffer = new bool[variableTimebaseBuffer.Length];
                                        if (settings.logicalChannelManager.Digitals[digitalID].digitalOverrideValue)
                                        {
                                            for (int j = 0; j < singleChannelBuffer.Length; j++)
                                            {
                                                singleChannelBuffer[j] = true;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        singleChannelBuffer = sequenceData.getDigitalBufferClockSharedWithVariableTimebaseClock(timebaseSegments, digitalID, 1.0 / deviceSettings.SampleClockRate);
                                    }
                                }
                            }

                            if (singleChannelBuffer != null)
                            {
                                for (int j = 0; j < singleChannelBuffer.Length; j++)
                                {
                                    if (singleChannelBuffer[j])
                                    {
                                        digitalBuffer[i, j] |= digitalBitMask;
                                    }
                                }
                            }
                            digitalBitMask = (byte)(digitalBitMask << 1);

                        }
                    }
                    System.GC.Collect();
                    DigitalMultiChannelWriter writer = new DigitalMultiChannelWriter(task.Stream);
                    writer.WriteMultiSamplePort(false, digitalBuffer);

                }

                return task; */

                #endregion
            }
            else
            {
                return createDaqMxVariableTimebaseSource(
                    channelName, masterFrequency, sequenceData, timebaseType, serverSettings, deviceSettings);
            }
        }
 /// <summary>
 /// Outputs a single gpib group. (evaluated at the beginning of the group.)
 /// </summary>
 /// <param name="gpibGroup"></param>
 /// <param name="settings"></param>
 /// <returns></returns>
 public abstract bool outputGPIBGroup(GPIBGroup gpibGroup, SettingsData settings);
 /// <summary>
 /// Sets the settings object.
 /// </summary>
 public abstract bool setSettings(SettingsData settings);
 public override bool outputSingleTimestep(SettingsData settings, SingleOutputFrame output)
 {
     return true;
 }
 public override bool outputRS232Group(RS232Group rs232Group, SettingsData settings)
 {
     return true;
 }
 public override bool outputGPIBGroup(GPIBGroup gpibGroup, SettingsData settings)
 {
     return true;
 }
 public override bool setSettings(SettingsData settings)
 {
     return true;
 }
        public override bool outputRS232Group(RS232Group rs232Group, SettingsData settings)
        {
            lock (remoteLockObj)
            {

                try
                {
                    messageLog(this, new MessageEvent("Received an output rs232 group request."));

                    if (rs232Group == null)
                    {
                        messageLog(this, new MessageEvent("Received a null output object. Unable to comply."));
                        displayError();
                        return false;
                    }

                    if (!stopAndCleanupTasks())
                        return false;

                    if (!setSettings(settings))
                        return false;

                    foreach (int channelID in usedRS232Channels.Keys)
                    {
                        if (rs232Group.channelEnabled(channelID))
                        {
                            HardwareChannel hc = usedRS232Channels[channelID];
                            RS232GroupChannelData channelData = rs232Group.ChannelDatas[channelID];
                            if (channelData.DataType == RS232GroupChannelData.RS232DataType.Raw)
                            {
                                NationalInstruments.VisaNS.SerialSession ss = getSerialSession(hc);
                                ss.Write(RS232Task.AddNewlineCharacters(channelData.RawString));
                                messageLog(this, new MessageEvent("Wrote rs232 command " + channelData.RawString));
                            }
                            else if (channelData.DataType == RS232GroupChannelData.RS232DataType.Parameter)
                            {
                                if (channelData.StringParameterStrings != null)
                                {
                                    foreach (StringParameterString sps in channelData.StringParameterStrings)
                                    {
                                        NationalInstruments.VisaNS.SerialSession ss = getSerialSession(hc);
                                        string rawCommand = sps.ToString();
                                        string command = RS232Task.AddNewlineCharacters(rawCommand);
                                        ss.Write(command);
                                        messageLog(this, new MessageEvent("Wrote rs232 command " + rawCommand));
                                    }
                                }
                            }
                            else
                            {
                                messageLog(this, new MessageEvent("Skipping output on channel " + channelID + ", output now not enabled for data of type " + channelData.DataType.ToString()));
                            }
                        }
                    }

                    return true;
                }
                catch (Exception e)
                {
                    messageLog(this, new MessageEvent("Caught exception when attempting output of single rs232 group: " + e.Message + e.StackTrace));
                    displayError();
                    return false;
                }

                return true;
            }
        }
        public override bool setSettings(SettingsData settings)
        {
            lock (remoteLockObj)
            {
                try
                {
                    messageLog(this, new MessageEvent("Received settings."));
                    this.settings = settings;

                    findMyChannels();
                    return true;
                }
                catch (Exception e)
                {
                    messageLog(this, new MessageEvent("Caught exception while attempting to verify settings. " + e.Message + e.StackTrace));
                    displayError();
                    return false;
                }
            }
        }
 /// <summary>
 /// Outputs a single rs232 Group. (evaluated at the beginning of the group.)
 /// </summary>
 /// <param name="rs232Group"></param>
 /// <param name="settings"></param>
 /// <returns></returns>
 public abstract bool outputRS232Group(RS232Group rs232Group, SettingsData settings);
 /// <summary>
 /// Outputs a single timestep.
 /// </summary>
 /// <param name="settings"></param>
 /// <param name="output"></param>
 /// <returns></returns>
 public abstract bool outputSingleTimestep(SettingsData settings, SingleOutputFrame output);
Esempio n. 19
0
 public ServerActionStatus setSettingsOnConnectedServers(SettingsData settings, EventHandler <MessageEvent> messageLog)
 {
     return(runNamedMethodOnConnectedServers("setSettings", new object[] { settings }, 4000, messageLog));
 }
 public ServerActionStatus outputGPIBGroupOnConnectedServers(GPIBGroup gpibGroup, SettingsData settings, EventHandler messageLog)
 {
     return runNamedMethodOnConnectedServers("outputGPIBGroup", new object[] { gpibGroup, settings }, 4000, messageLog);
 }
Esempio n. 21
0
 public ServerActionStatus outputSingleTimestepOnConnectedServers(SettingsData settings, SingleOutputFrame output, EventHandler <MessageEvent> messageLog)
 {
     return(runNamedMethodOnConnectedServers("outputSingleTimestep", new object[] { settings, output }, 5000, messageLog));
 }
 public ServerActionStatus outputSingleTimestepOnConnectedServers(SettingsData settings, SingleOutputFrame output, EventHandler<MessageEvent> messageLog)
 {
     return runNamedMethodOnConnectedServers("outputSingleTimestep", new object[] { settings, output }, 5000, messageLog);
 }
Esempio n. 23
0
 public ServerActionStatus outputRS232GroupOnConnectedServers(RS232Group rs232Group, SettingsData settings, EventHandler <MessageEvent> messageLog)
 {
     return(runNamedMethodOnConnectedServers("outputRS232Group", new object[] { rs232Group, settings }, 4000, messageLog));
 }
        public SingleOutputFrame getSingleOutputFrameAtEndOfTimestep(TimeStep step, SettingsData settings, bool outputAnalogDwellValues)
        {
            int analogStepID;
            if (outputAnalogDwellValues)
            {
                analogStepID = TimeSteps.IndexOf(dwellWord());
            }
            else
            {
                analogStepID = TimeSteps.IndexOf(step);
            }

            TimeStep analogStep = TimeSteps[analogStepID];

            int timeStepID = TimeSteps.IndexOf(step);

            SingleOutputFrame ans = new SingleOutputFrame();

            foreach (int analogID in settings.logicalChannelManager.Analogs.Keys)
            {
                if (settings.logicalChannelManager.Analogs[analogID].TogglingChannel)
                {
                    ans.analogValues.Add(analogID, 0);
                }
                else if (settings.logicalChannelManager.Analogs[analogID].overridden)
                {
                    ans.analogValues.Add(analogID, settings.logicalChannelManager.Analogs[analogID].analogOverrideValue);
                }
                else
                {
                    if (settings.logicalChannelManager.Analogs[analogID].AnalogChannelOutputNowUsesDwellWord)
                    {
                        ans.analogValues.Add(analogID, getAnalogValueAtEndOfTimestep(TimeSteps.IndexOf(dwellWord()), analogID, Variables));
                    }
                    else
                    {
                        ans.analogValues.Add(analogID, getAnalogValueAtEndOfTimestep(analogStepID, analogID, Variables));
                    }
                }
            }

            foreach (int digitalID in settings.logicalChannelManager.Digitals.Keys)
            {
                bool val = false;
                if (settings.logicalChannelManager.Digitals[digitalID].TogglingChannel) {
                    val = false;
                }
                else if (settings.logicalChannelManager.Digitals[digitalID].overridden)
                {
                    val = settings.logicalChannelManager.Digitals[digitalID].digitalOverrideValue;
                }
                else
                {
                    if (step.DigitalData.ContainsKey(digitalID))
                    {
                        DigitalDataPoint dp = step.DigitalData[digitalID];
                        if (!dp.DigitalContinue)
                        {
                            val = step.DigitalData[digitalID].getValue();
                        }
                        else  // this digital value is a "continue" value, so, we have to go backwards in time until we find
                        // what value to continue from
                        {
                            int checkStep = timeStepID - 1;
                            val = false; // if we hunt all the way to the first timestep with no answer, the default answer is false
                            while (checkStep >= 0)
                            {
                                if (TimeSteps[checkStep].StepEnabled)
                                {
                                    if (TimeSteps[checkStep].DigitalData.ContainsKey(digitalID))
                                    {
                                        if (TimeSteps[checkStep].DigitalData[digitalID].DigitalContinue)
                                        {
                                            checkStep--; // timestep had another continue keep hunting backwards...
                                        }
                                        else
                                        {
                                            val = TimeSteps[checkStep].DigitalData[digitalID].getValue();
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    checkStep--; // timestep was disabled, keep looking
                                }
                            }
                        }

                    }
                }
                ans.digitalValues.Add(digitalID, val);
            }

            return ans;
        }
        public void RefreshSettingsDataToUI(SettingsData settingsData)
        {
            WordGenerator.mainClientForm.instance.cursorWait();

            this.analogGroupEditor1.setChannelCollection(settingsData.logicalChannelManager.ChannelCollections[HardwareChannel.HardwareConstants.ChannelTypes.analog]);
            this.gpibGroupEditor1.setChannelCollection(settingsData.logicalChannelManager.ChannelCollections[HardwareChannel.HardwareConstants.ChannelTypes.gpib]);
            this.rS232GroupEditor1.setChannelCollection(settingsData.logicalChannelManager.ChannelCollections[HardwareChannel.HardwareConstants.ChannelTypes.rs232]);
            this.overridePage1.setSettings(Storage.settingsData);
            this.sequencePage1.layoutSettingsData();
            this.sequencePage1.updateOverrideCount();

            setTimestepEditorBackgrounds();

            WordGenerator.mainClientForm.instance.cursorWaitRelease();
        }
        /// <summary>
        /// Used for automated testing purposes only. Creates a buffer snapshot object which can be archived, or 
        /// compared to archived versions, to verify that buffer generation code doesn't change behavior with
        /// new releases.
        /// </summary>
        /// <param name="settings"></param>
        /// <param name="masterSamp"></param>
        /// <returns></returns>
        public BufferTestSnapshot _createBufferSnapshot(SettingsData settings, double masterSamp)
        {
            BufferTestSnapshot snap = new BufferTestSnapshot();
            snap.MasterTimebaseSampleDuration = masterSamp;
            snap.Sequence = this;
            snap.Settings = settings;

            this.createLoopCopies();
            snap.AnalogFixed = _testCalculateAllAnalogBuffersFixedFrequenct(snap.Settings, masterSamp);
            snap.AnalogVar = _testCalculateAllAnalogBuffersVariableFrequency(snap.Settings, masterSamp);
            snap.DigitalFixed = _testCalculateAllDigitalBuffersFixedFrequency(snap.Settings, masterSamp);
            snap.DigitalVar = _testCalculateAllDigitalBuffersVariableFrequency(snap.Settings, masterSamp);
            this.cleanupLoopCopies();

            return snap;
        }
Esempio n. 27
0
 public RunLog(DateTime runTime, DateTime listStartTime, SequenceData sequence, SettingsData settings, string sequenceFileName, string settingsFileName)
 {
     this.runTime          = runTime;
     this.listStartTime    = listStartTime;
     this.runSequence      = sequence;
     this.runSettings      = settings;
     this.SequenceFileName = sequenceFileName;
     this.SettingsFileName = settingsFileName;
 }
 public Dictionary<int, bool[]> _testCalculateAllDigitalBuffersFixedFrequency(SettingsData settings, double masterTimestepSize)
 {
     Dictionary<int, bool[]> ans = new Dictionary<int, bool[]>();
     foreach (int digitalChannelId in settings.logicalChannelManager.Digitals.Keys) {
         ans.Add(digitalChannelId, this.computeDigitalBuffer(digitalChannelId, masterTimestepSize));
     }
     return ans;
 }
 /// <summary>
 /// Outputs a single timestep.
 /// </summary>
 /// <param name="settings"></param>
 /// <param name="output"></param>
 /// <returns></returns>
 public abstract bool outputSingleTimestep(SettingsData settings, SingleOutputFrame output);
        public override bool outputGPIBGroup(GPIBGroup gpibGroup, SettingsData settings)
        {
            lock (remoteLockObj)
            {
                try
                {
                    messageLog(this, new MessageEvent("Received an output gpib group request."));

                    if (gpibGroup == null)
                    {
                        messageLog(this, new MessageEvent("Received a null object, unable to comply."));
                        displayError();
                        return false;
                    }

                    if (!stopAndCleanupTasks())
                        return false;

                    if (!setSettings(settings))
                        return false;

                    foreach (int channelID in usedGpibChannels.Keys)
                    {
                        if (gpibGroup.channelEnabled(channelID))
                        {
                            HardwareChannel hc = usedGpibChannels[channelID];
                            GPIBGroupChannelData channelData = gpibGroup.ChannelDatas[channelID];
                            if (channelData.DataType == GPIBGroupChannelData.GpibChannelDataType.raw_string)
                            {
                                NationalInstruments.NI4882.Device gpibDevice = new NationalInstruments.NI4882.Device(hc.gpibBoardNumber(), niAddress(hc.GpibAddress));
                                gpibDevice.Write(
                                    GpibTask.AddNewlineCharacters(channelData.RawString));
                                messageLog(this, new MessageEvent("Wrote GPIB data : " + channelData.RawString));
                            }
                            else if (channelData.DataType == GPIBGroupChannelData.GpibChannelDataType.string_param_string)
                            {
                                NationalInstruments.NI4882.Device gpibDevice = new NationalInstruments.NI4882.Device(hc.gpibBoardNumber(), niAddress(hc.GpibAddress));
                                if (channelData.StringParameterStrings != null)
                                {
                                    foreach (StringParameterString sps in channelData.StringParameterStrings)
                                    {
                                        gpibDevice.Write(
                                            GpibTask.AddNewlineCharacters(sps.ToString()));
                                        messageLog(this, new MessageEvent("Wrote GPIB data : " + sps.ToString()));
                                    }
                                }
                            }
                            else
                            {
                                messageLog(this, new MessageEvent("Skipping channel " + channelID + ", unsupported data type for an Output Now request: " + channelData.DataType.ToString()));
                                displayError();
                            }
                        }
                    }
                    return true;
                }
                catch (Exception e)
                {
                    messageLog(this, new MessageEvent("Caught exception when attempting to output gpib group: " + e.Message + e.StackTrace));
                    displayError();
                    return false;
                }
            }
        }
 /// <summary>
 /// Outputs a single gpib group. (evaluated at the beginning of the group.)
 /// </summary>
 /// <param name="gpibGroup"></param>
 /// <param name="settings"></param>
 /// <returns></returns>
 public abstract bool outputGPIBGroup(GPIBGroup gpibGroup, SettingsData settings);
        /// <summary>
        /// Outputs a single output frame to analog and digital cards. All other cards / outputs are unaffected.
        /// </summary>
        /// <param name="settings"></param>
        /// <param name="output"></param>
        /// <returns></returns>
        public override bool outputSingleTimestep(SettingsData settings, SingleOutputFrame output)
        {
            lock (remoteLockObj)
            {
                try
                {
                    messageLog(this, new MessageEvent("Received an output single timestep request."));

                    if (output == null)
                    {
                        messageLog(this, new MessageEvent("Received a null output object. Unable to comply."));
                        return false;
                    }

                    if (!stopAndCleanupTasks())
                        return false;

                    if (!setSettings(settings))
                        return false;

                    foreach (string dev in usedDaqMxDevices)
                    {

                        DeviceSettings deviceSettings = myServerSettings.myDevicesSettings[dev];
                        if (deviceSettings.DeviceEnabled)
                        {
                            messageLog(this, new MessageEvent("Generating single output for " + dev));
                            Task task = DaqMxTaskGenerator.createDaqMxTaskAndOutputNow(dev,
                                deviceSettings,
                                output,
                                settings,
                                usedDigitalChannels,
                                usedAnalogChannels);

                            daqMxTasks.Add(dev, task);
                            messageLog(this, new MessageEvent("Success."));
                        }
                        else
                        {
                            messageLog(this, new MessageEvent("Skipped buffer generation for disabled device " + dev));
                        }
                    }

                    return true;
                }
                catch (Exception e)
                {
                    messageLog(this, new MessageEvent("Caught exception when attempting output of single timestep: " + e.Message + e.StackTrace));
                    displayError();
                    return false;
                }
            }
        }
 /// <summary>
 /// Outputs a single rs232 Group. (evaluated at the beginning of the group.)
 /// </summary>
 /// <param name="rs232Group"></param>
 /// <param name="settings"></param>
 /// <returns></returns>
 public abstract bool outputRS232Group(RS232Group rs232Group, SettingsData settings);
        /// <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>
 /// Sets the settings object.
 /// </summary>
 public abstract bool setSettings(SettingsData settings);
        /*
        /// <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;
        }
Esempio n. 37
0
        public RfsgTask(SequenceData sequence, SettingsData settings, int channelID, string rfsgDeviceName, DeviceSettings deviceSettings)
        {
            if (!settings.logicalChannelManager.GPIBs.ContainsKey(channelID))
            {
                throw new InvalidDataException("Attempted to create an rfsg task with channel id " + channelID + ", which does not exist in the settings as a gpib channel.");
            }

            this.channelID = channelID;

            int currentStepIndex = -1;

            //measured in ticks. 1 tick = 100 ns.
            long currentTime = 0;

            commandBuffer = new List<RFSGCommand>();

            if (deviceSettings.AutoInitate)
            {
                RFSGCommand com = new RFSGCommand();
                com.commandTime = 0;
                com.commandType = RFSGCommand.CommandType.Initiate;
                commandBuffer.Add(com);
            }

            if (deviceSettings.AutoEnable)
            {
                RFSGCommand com = new RFSGCommand();
                com.commandTime = 0;
                com.commandType = RFSGCommand.CommandType.EnableOutput;
                commandBuffer.Add(com);
            }

            long postRetriggerTime = 100; // corresponds to 10us.
            // A workaround to issue when using software timed groups in
            // fpga-retriggered words

            // the workaround: delay the software timed group by an immesurable amount
            // if it is started in a retriggered word

            // This functionality is sort of somewhat duplicated in sequencedata.generatebuffers. It would be good
            // to come up with a more coherent framework to do these sorts of operations.
            while (true)
            {
                currentStepIndex++;

                if (currentStepIndex >= sequence.TimeSteps.Count)
                    break;

                TimeStep currentStep = sequence.TimeSteps[currentStepIndex];

                if (!currentStep.StepEnabled)
                    continue;

                if (currentStep.GpibGroup == null || !currentStep.GpibGroup.channelEnabled(channelID))
                {
                    currentTime += seconds_to_ticks(currentStep.StepDuration.getBaseValue());
                    continue;
                }

                long postTime = 0;
                if (currentStep.RetriggerOptions.WaitForRetrigger)
                    postTime = postRetriggerTime;

                // determine the index of the next step in which this channel has an action
                int nextEnabledStepIndex = sequence.findNextGpibChannelEnabledTimestep(currentStepIndex, channelID);

                long groupDuration = seconds_to_ticks(sequence.timeBetweenSteps(currentStepIndex, nextEnabledStepIndex));

                // now take action:

                GPIBGroupChannelData channelData = currentStep.GpibGroup.getChannelData(channelID);

                if (channelData.DataType == GPIBGroupChannelData.GpibChannelDataType.raw_string)
                {

                    throw new Exception("Not yet implemented.");
                    /*

                    // Raw string commands just get added
                    string stringWithCorrectNewlines = AddNewlineCharacters(channelData.RawString);

                    commandBuffer.Add(new GpibCommand(stringWithCorrectNewlines, currentTime));*/
                }
                else if (channelData.DataType == GPIBGroupChannelData.GpibChannelDataType.voltage_frequency_waveform)
                {

                    double[] amplitudeArray;
                    double[] frequencyArray;

                    // get amplitude and frequency value arrays
                    int nSamples = (int)(ticks_to_seconds(groupDuration) * (double)deviceSettings.SampleClockRate);
                    double secondsPerSample = ticks_to_seconds(groupDuration) / (double)nSamples;

                    amplitudeArray = channelData.volts.getInterpolation(nSamples, 0, ticks_to_seconds(groupDuration), sequence.Variables, sequence.CommonWaveforms);
                    frequencyArray = channelData.frequency.getInterpolation(nSamples, 0, ticks_to_seconds(groupDuration), sequence.Variables, sequence.CommonWaveforms);

                    double lastFreq = Double.MinValue;
                    double lastAmp = Double.MinValue;

                    for (int i = 0; i < nSamples; i++)
                    {
                        double currentFreq = frequencyArray[i];
                        double currentAmp = amplitudeArray[i];
                        if (currentFreq != lastFreq || currentAmp != lastAmp)
                        {
                            RFSGCommand command = new RFSGCommand();
                            command.commandType = RFSGCommand.CommandType.AmplitudeFrequency;
                            command.frequency = currentFreq;
                            command.amplitude = Vpp_to_dBm(currentAmp);
                            command.commandTime = (long)(currentTime + i * secondsPerSample * 10000000) + postTime;

                            commandBuffer.Add(command);
                        }
                        lastAmp = currentAmp;
                        lastFreq = currentFreq;

                    }
                }

                else if (channelData.DataType == GPIBGroupChannelData.GpibChannelDataType.string_param_string)
                {
                    foreach (StringParameterString sps in channelData.StringParameterStrings)
                    {
                        string clean = sps.Prefix.Trim().ToUpper();
                        if (clean == "ENABLE")
                        {
                            RFSGCommand com = new RFSGCommand();
                            com.commandType = RFSGCommand.CommandType.EnableOutput;
                            com.commandTime = currentTime + postTime;
                            commandBuffer.Add(com);
                        }

                        if (clean == "DISABLE")
                        {
                            RFSGCommand com = new RFSGCommand();
                            com.commandType = RFSGCommand.CommandType.DisableOutput;
                            com.commandTime = currentTime + postTime;
                            commandBuffer.Add(com);
                        }

                        if (clean == "ABORT")
                        {
                            RFSGCommand com = new RFSGCommand();
                            com.commandType = RFSGCommand.CommandType.Abort;
                            com.commandTime = currentTime + postTime;
                            commandBuffer.Add(com);
                        }

                        if (clean == "INITIATE")
                        {
                            RFSGCommand com = new RFSGCommand();
                            com.commandType = RFSGCommand.CommandType.Initiate;
                            com.commandTime = currentTime + postTime;
                            commandBuffer.Add(com);
                        }
                    }
                }

                currentTime += seconds_to_ticks(currentStep.StepDuration.getBaseValue());
            }

            if (rfsgDevices == null)
            {
                rfsgDevices = new Dictionary<string, niRFSG>();
                rfsgDeviceInitiated = new Dictionary<niRFSG, bool>();
            }

            if (rfsgDevices.ContainsKey(rfsgDeviceName))
            {
                rfsgDevice = rfsgDevices[rfsgDeviceName];
            }
            else
            {

                try
                {
                    rfsgDevice = new niRFSG(rfsgDeviceName, true, false);
                }
                catch (Exception e)
                {
                    throw new InvalidDataException("Caught exception when attempting to instantiate an rfsg device named " + rfsgDeviceName + ". Maybe a device by this name does not exist? Exception message: " + e.Message);
                }
                rfsgDevices.Add(rfsgDeviceName, rfsgDevice);
                rfsgDeviceInitiated.Add(rfsgDevice, false);
            }

            if (deviceSettings.MasterTimebaseSource != null && deviceSettings.MasterTimebaseSource != "")
            {
                rfsgDevice.ConfigureRefClock(deviceSettings.MasterTimebaseSource, 10000000);
            }
        }