void StartGeneration() { string rfsgName = resourceNameComboBox.Text; double freq = (double)frequencyNumeric.Value; double power = (double)powerLevelNumeric.Value; try { rfsgSession = new NIRfsg(rfsgName, true, false); rfsgHandle = rfsgSession.GetInstrumentHandle().DangerousGetHandle(); int i = 0; foreach (string tdmsPath in tdmsFilePaths) { NIRfsgPlayback.ReadAndDownloadWaveformFromFile(rfsgHandle, tdmsPath, tdmsWaveformNames[i]); i++; } //Q: Is it acceptable to utilize mostly private class data and keep prototype empty? I suppose if I don't aniticpate any reuse I can leave it empty... string autoScript = ScriptGen(); NIRfsgPlayback.SetScriptToGenerateSingleRfsg(rfsgHandle, autoScript); rfsgSession.RF.Configure(freq, power); rfsgSession.Initiate(); } catch (Exception uhOh) { ShowError("Start Generation", uhOh); } }
/// <summary>Calls <see cref="NIRfsgPlayback.SetScriptToGenerateSingleRfsg(IntPtr, string)"/>, which will download the script contained in <paramref name="waveform"/> and apply /// all associated parameters.</summary> /// <param name="rfsgHandle">The open RFSG session to configure.</param> /// <param name="waveform">Specifies the waveform and its associated script that is to be used for generation.</param> public static void ApplyWaveformAttributes(NIRfsg rfsgHandle, Waveform waveform) { if (string.IsNullOrEmpty(waveform.Script)) // default to continuous if no script in waveform { ConfigureContinuousGeneration(rfsgHandle, waveform); } else { IntPtr rfsgPtr = rfsgHandle.GetInstrumentHandle().DangerousGetHandle(); NIRfsgPlayback.SetScriptToGenerateSingleRfsg(rfsgPtr, waveform.Script); } }
public static void ConfigureContinuousGeneration(NIRfsg rfsgHandle, Waveform waveform, string waveformStartTriggerExport = "PXI_Trig0") { //Configure the trigger to be generated on the first sample of each waveform generation, //denoted in the script below as "marker0" rfsgHandle.DeviceEvents.MarkerEvents[0].ExportedOutputTerminal = RfsgMarkerEventExportedOutputTerminal.FromString(waveformStartTriggerExport); //A software trigger is configured that is used in the script below to control generation of //the script. This ensures that a complete packet is always generated before aborting, and //allows all generation functions to share a single abort function. rfsgHandle.Triggers.ScriptTriggers[0].ConfigureSoftwareTrigger(); string script = $@"script REPEAT{waveform.WaveformName} repeat until ScriptTrigger0 generate {waveform.WaveformName} marker0(0) end repeat end script"; //Get the instrument handle to utilize with the RFSGPlayback library IntPtr rfsgPtr = rfsgHandle.GetInstrumentHandle().DangerousGetHandle(); //Download the newly created script for generation when "Initiate" is called NIRfsgPlayback.SetScriptToGenerateSingleRfsg(rfsgPtr, script); }
public static void ConfigureBurstedGeneration(NIRfsg rfsgHandle, Waveform waveform, WaveformTimingConfiguration waveTiming, PAENConfiguration paenConfig, out double period, out double idleTime) { IntPtr rfsgPtr = rfsgHandle.GetInstrumentHandle().DangerousGetHandle(); rfsgHandle.Arb.GenerationMode = RfsgWaveformGenerationMode.Script; string scriptName = String.Format("{0}{1}", waveform.WaveformName, waveTiming.DutyCycle_Percent); if (waveTiming.DutyCycle_Percent <= 0) { throw new System.ArgumentOutOfRangeException("DutyCycle_Percent", waveTiming.DutyCycle_Percent, "Duty cycle must be greater than 0 %"); } //Calculate various timining information double dutyCycle = waveTiming.DutyCycle_Percent / 100; double totalBurstTime = waveTiming.PreBurstTime_s + waveform.BurstLength_s + waveTiming.PostBurstTime_s; idleTime = (totalBurstTime / dutyCycle) - totalBurstTime; period = totalBurstTime + idleTime; //Convert all time based values to sample based values long preBurstSamp, postBurstSamp, idleSamp, enableSamples, disableSamples; preBurstSamp = TimeToSamples(waveTiming.PreBurstTime_s, waveform.SampleRate); postBurstSamp = TimeToSamples(waveTiming.PostBurstTime_s, waveform.SampleRate); idleSamp = TimeToSamples(idleTime, waveform.SampleRate); enableSamples = TimeToSamples(paenConfig.CommandEnableTime_s, waveform.SampleRate); disableSamples = TimeToSamples(paenConfig.CommandDisableTime_s, waveform.SampleRate); //RFSG enforces a minimum wait time of 8 samples, so ensure that the minimum pre/post burst time // and idle time are at least 8 samples long if (preBurstSamp < 8) { preBurstSamp = 8; } if (postBurstSamp < 8) { postBurstSamp = 8; } if (idleSamp < 8) { idleSamp = 8; } //Initialize the script StringBuilder with the first line of the script (name) StringBuilder sb = new StringBuilder($"script {scriptName}"); sb.AppendLine(); #region Script Building //If we have a static PA Enable mode, ensure that we trigger at the beginning of the script prior to looping. if (paenConfig.PAEnableMode == PAENMode.Static) { sb.AppendLine("wait 8 marker1(7)"); } //Configure for endless repeating sb.AppendLine("Repeat until scriptTrigger0"); //Configure the idle time prior to each packet generation sb.Append($"wait {idleSamp}"); //If PAEN Mode is dynamic we need to trigger the PA to enable if (paenConfig.PAEnableMode == PAENMode.Dynamic) { //PA Enable is triggered at or before the last sample of the wait period long PAEnableTriggerLoc = idleSamp - enableSamples - 1; sb.Append($" marker1({PAEnableTriggerLoc})"); } sb.AppendLine(); //Configure waiting for the pre-burst time sb.AppendLine($"wait {preBurstSamp}"); //Configure generation of the selected waveform but only for the burst length; send a trigger at the beginning of each burst sb.Append($"generate {waveform.WaveformName} subset({waveform.BurstStartLocations[0]},{waveform.BurstStopLocations[0]}) marker0(0)"); //Check to see if the command time is longer than the post-burst time, which determines when the PA disable command needs sent bool LongCommand = waveTiming.PostBurstTime_s <= paenConfig.CommandDisableTime_s; if (paenConfig.PAEnableMode == PAENMode.Dynamic && LongCommand) { //Trigger is placed a number of samples from the end of the burst corresponding with //how much longer than the post burst time it is long PADisableTriggerLoc = waveform.BurstStopLocations[0] - (disableSamples - postBurstSamp) - 1; sb.Append($" marker1({PADisableTriggerLoc})"); } sb.AppendLine(); //Configure waiting for the post-burst time sb.Append($"wait {postBurstSamp}"); //If the ommand time is shorter than the post-burst time, the disable trigger must be sent //during the post-burst time if (paenConfig.PAEnableMode == PAENMode.Dynamic && !LongCommand) { long PADisableTriggerLoc = postBurstSamp - disableSamples - 1; sb.Append($" marker1({PADisableTriggerLoc})"); } sb.AppendLine(); //Close out the script sb.AppendLine("end repeat"); //If we have a static PA Enable mode, ensure that we trigger at the end of the script prior to concluding. if (paenConfig.PAEnableMode == PAENMode.Static) { sb.AppendLine("wait 10 marker1(0)"); } sb.AppendLine("end script"); #endregion //Download the generation script to the generator for later initiation NIRfsgPlayback.SetScriptToGenerateSingleRfsg(rfsgPtr, sb.ToString()); //Configure the triggering for PA enable if selected if (paenConfig.PAEnableMode != PAENMode.Disabled) { rfsgHandle.DeviceEvents.MarkerEvents[1].ExportedOutputTerminal = RfsgMarkerEventExportedOutputTerminal.FromString( paenConfig.PAEnableTriggerExportTerminal); rfsgHandle.DeviceEvents.MarkerEvents[1].OutputBehaviour = paenConfig.PAEnableTriggerMode; //Configure scriptTrigger0 for software triggering. This way, when it is time to abort we can stop //the loop and trigger the appropriate off command if PAEN mode is Static rfsgHandle.Triggers.ScriptTriggers[0].ConfigureSoftwareTrigger(); } //Configure the trigger to be generated on the first sample of each waveform generation, //denoted in the script below as "marker0" rfsgHandle.DeviceEvents.MarkerEvents[0].ExportedOutputTerminal = RfsgMarkerEventExportedOutputTerminal.FromString(waveTiming.BurstStartTriggerExport); }