#define useVSA
//#undef useVSA
#define chassisSetup
#undef chassisSetup
#define autoChassisSetup

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using Ivi.Driver.Interop;
using Agilent.AgM938x.Interop;
using Agilent.AgM9300.Interop;
using Agilent.AgM9018.Interop;
using Agilent.Autobot.Lib;
using Agilent.Autobot.Lib.Validate;
using Agilent.Autobot.Lib.Prereq;
#if useVSA
using Agilent.SA.Vsa;
#endif
//using Ivi.Visa;
//using Ivi.Visa.Interop;
//using System.Runtime.InteropServices;


namespace MIMOTestPlan
{
    public partial class MIMODemoProgram : Form
    {
        private Stopwatch sw = new Stopwatch();
        private Stopwatch sw2 = new Stopwatch();

        # region Member Variables
        // Driver and Initialization Variables
        public IAgM938xEx[] M9381 = new IAgM938xEx[4];

        public IAgM9300Ex M9300;
#if chassisSetup
        public IAgM9018 M9018;
        public IAgM9018 M9018vsa;
#endif

#if useVSA
        Agilent.SA.Vsa.Application vsa = null;
        bool vsaIsCreated = false;
#endif

        public bool use89600VSA = false;
        public int numChannels = 0;

        public bool simulateHardware = false;
        // Default resource strings for VSG and VSA.   These will be used to populate the test boxes in the GUI
        // Reference should be included with the M9381A and the M9381A should be initialized first
 
        // when using M9000, need to use an IVI configuration store named configuration
        public string[] M9381resource = {"M9381Chan1", "M9381Chan2", "M9381Chan3", "M9381Chan4"};

        public string M9300resource = "M9300";
#if chassisSetup
        public string M9018resource = "M9018";
        public string M9018vsaResource = "M9018_VSA";
#endif

        public int[] sourceExtTrig = new int[4];
        public int []sourceALCTrig = new int[4];
        public int []referenceListenTrig = new int[4];
        public int triggerToSource;

        public string examplesDirectory = "C:\\Program Files (x86)\\Agilent\\M938x\\Example Waveforms\\";
        public string applicationDirectory = System.Windows.Forms.Application.StartupPath + "\\";

        // Waveform Information use with Get Arb Info command
        public double arbSampleRate = 0;
        public double arbRmsValue = 0;
        public double arbScale = 0.5;
        public AgM938xMarkerEnum rfMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
        public AgM938xMarkerEnum alcMarker = AgM938xMarkerEnum.AgM938xMarkerNone;

        public double mAmplitude = -2.0;

        public double rfLevelOffset = 0;
        public double scaleFactorOffset = 1;

        public Boolean mInitComplete = false;

#if chassisSetup
        public Boolean mVSAChassisEnabled = true;
#endif

        public string mWaveformHandle = "WF1";

        public double[] spectrumData = new double[53];

        private Stopwatch sw1 = new Stopwatch();
        # endregion

        # region Gui Event Handlers
        public MIMODemoProgram()
        {
            InitializeComponent();
            
            vsg1ResourceStringBox.Text = M9381resource[0];
            vsg2ResourceStringBox.Text = M9381resource[1];    
            vsg3ResourceStringBox.Text = M9381resource[2];
            vsg4ResourceStringBox.Text = M9381resource[3];

            referenceResourceStringBox.Text = M9300resource;
#if chassisSetup
            chassisResourceStringBox.Text = M9018resource;
            chassisVSAResourceStringBox.Text = M9018vsaResource;
#endif
            useVSACheckBox.Enabled = true;
            closeButton.Enabled = false;
            loadWaveformButton.Enabled = false;
           
            trackAmplitudeChangesCheckBox.Checked = true;

            continuousRadioButton.Checked = true;
            waveformListBox.Enabled = true;
            sequenceListBox.Enabled = false;

            setupForNumChannels();
           
        }

        private void setupForNumChannels()
        {
#if chassisSetup
            if (numChannels > 2)
            {
                vsaChassisEnableCheckBox.Enabled = true;

                vsaChassisEnableCheckBox.Checked = mVSAChassisEnabled;

            }
            else
            {
                vsaChassisEnableCheckBox.Enabled = false;
                vsaChassisEnableCheckBox.Checked = false;
            }


            if (mVSAChassisEnabled)
                chassisResourceStringBox.Enabled = true;
            else
                chassisResourceStringBox.Enabled = false;
#endif


            if (numChannels > 1)
            {
                vsg2ResourceStringBox.Enabled = true;
            }
            else
            {
                vsg2ResourceStringBox.Enabled = false;
            }
            if (numChannels > 2)
            {
                vsg3ResourceStringBox.Enabled = true;
            }
            else
            {
                vsg3ResourceStringBox.Enabled = false;
            }
            if (numChannels > 3)
            {
                vsg4ResourceStringBox.Enabled = true;
            }
            else
            {
                vsg4ResourceStringBox.Enabled = false;
            }

            if (trackAmplitudeChangesCheckBox.Checked == false)
            {
                // show as many amplitudes as we have channels
                if (numChannels > 1)
                    AmpCh2_dBmControl.Enabled = true;
                else
                    AmpCh2_dBmControl.Enabled = false;
                if (numChannels > 2)
                    AmpCh3_dBmControl.Enabled = true;
                else
                    AmpCh3_dBmControl.Enabled = false;
                if (numChannels > 3)
                    AmpCh4_dBmControl.Enabled = true;
                else
                    AmpCh4_dBmControl.Enabled = false;
            }
            else
            {
                // Only enable channel 1
                AmpCh2_dBmControl.Enabled = false;
                AmpCh3_dBmControl.Enabled = false;
                AmpCh4_dBmControl.Enabled = false;
            }
        }

        private void measureButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;
            testStatusLabel.Text = "Measuring";
 
            double [] range = new double[4];
            for (int i=0;i<4; i++)
                range[i] = -99;
           // double range2 = -99;


            // TODO: create a class variable to track whether setup has been loaded.  If waveform changes, then invalidate setup
            // and force reload

            //Start Test timer
            sw.Reset();
            sw.Start();

            measEVM(false, ref range);

            addResultsFooter("EVM speed: ", sw.ElapsedMilliseconds);

            //sw.Reset();
            //sw.Start();

            //measSEM(false, range);

            //addResultsFooter("SEM speed: ", sw.ElapsedMilliseconds);

            //// Increment test index and add blank line to the results
            //nextTest();


            testStatusLabel.Text = "Measurement Complete";
            resultsBox.Text = resultsString;

            Cursor.Current = Cursors.Default;
        }

        private void measSEM(bool performAutoRange, double [] range)
        {
            int numIQPoints = 0;
            bool specMeasFail = false;
            float[][] spec2Result = new float[numChannels][];
            const int SPECTRUM_TRACE_BASE = 22;
            const int SEM_TRACE_BASE = 18;
            String[] SEM_REGISTER = { "D1", "D2", "D3", "D4" };
#if useVSA
            if (use89600VSA)
            {
                try
                {
                    // Now let's select the spectrum measurement 
                    sw2.Reset();
                    sw2.Start();
                    vsa.Measurements.SelectedItem = vsa.Measurements["spectrum"];
                    addResultsFooter("Switch to spectrum: ", sw2.ElapsedMilliseconds);

                    sw2.Reset();
                    sw2.Start();
                    vsa.Measurements.SelectedItem.IsContinuous = false;
                    vsa.Measurements.SelectedItem.Input.DataFrom = DataSource.Hardware;
                    addResultsFooter("single sweep and select hardware(not recording): ", sw2.ElapsedMilliseconds);

                    sw2.Reset();
                    sw2.Start();
                    vsa.Measurements.SelectedItem.Frequency.Channels[0].Center = (double)FreqMHzControl.Value * 1000000 - 80e6;
                    if (numChannels > 1)
                        vsa.Measurements.SelectedItem.Frequency.Channels[1].Center = (double)Freq2MHzControl.Value * 1e6 - 80e6;
                    if (numChannels > 2)
                        vsa.Measurements.SelectedItem.Frequency.Channels[2].Center = (double)Freq3MHzControl.Value * 1e6 - 80e6;
                    if (numChannels > 3)
                        vsa.Measurements.SelectedItem.Frequency.Channels[3].Center = (double)Freq4MHzControl.Value * 1e6 - 80e6;
                    addResultsFooter("Set frequencies: ", sw2.ElapsedMilliseconds);

                    for (int channelNumber = 0; channelNumber < numChannels; channelNumber++)
                        vsa.Display.Traces[SEM_TRACE_BASE + channelNumber].DataName = "No Data";

                    if (performAutoRange)
                    {
                        vsa.Measurements.SelectedItem.Input.Trigger.Style = TriggerStyle.Auto;
                        vsa.Measurements.SelectedItem.Input.Analog.AutoRange();
                        vsa.Measurements.SelectedItem.Input.Trigger.Style = TriggerStyle.MagnitudeLevel;
                    }
                    else
                    {
                        sw2.Reset();
                        sw2.Start();
                        for (int channelNumber = 0; channelNumber < numChannels; channelNumber++)
                            vsa.Measurements.SelectedItem.Input.Analog.Channels[channelNumber].Range = range[channelNumber];
                        // vsa.Measurements.SelectedItem.Input.Analog.Channels[1].Range = range2;
                        addResultsFooter("Setting range: ", sw2.ElapsedMilliseconds);
                        // Do extra meas here, avoids bug 
                        sw2.Reset();
                        sw2.Start();
                        vsa.Measurements.SelectedItem.Record();
                        try
                        {
                            vsa.Measurements.SelectedItem.WaitForRecordingDone(10000);
                        }
                        catch (System.TimeoutException ex)
                        {
                            MessageBox.Show("Timeout measuring Spectrum");
                            specMeasFail = true;
                        }
                        addResultsFooter("First recording: ", sw2.ElapsedMilliseconds);
                    }



                    // This will perform the measurement on the recording
                    sw2.Reset();
                    sw2.Start();
                    vsa.Measurements.SelectedItem.Resume();
                    try
                    {
                        vsa.Measurements.SelectedItem.WaitForMeasurementDone(3000);
                    }
                    catch (System.TimeoutException ex)
                    {
                        MessageBox.Show("Timeout measuring Spectrum");
                        specMeasFail = true;
                    }
                    addResultsFooter("first measurement on recording: ", sw2.ElapsedMilliseconds);
                    if (specMeasFail != true)
                    {
                        sw2.Reset();
                        sw2.Start();
                        bool isComplex = vsa.Display.Traces[SPECTRUM_TRACE_BASE].MeasurementData.IsComplex;
                        int pointsMultiplier = 1;
                        if (isComplex)
                            pointsMultiplier = 2;
                        for (int channelNumber = 0; channelNumber < numChannels; channelNumber++)
                        {
                            numIQPoints = vsa.Display.Traces[SPECTRUM_TRACE_BASE + channelNumber].MeasurementData.Points * 2;
                            spec2Result[channelNumber] = new float[numIQPoints * pointsMultiplier]; // numIQPoints for each trace
                            vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.Allocate(vsa.Display.Traces[SPECTRUM_TRACE_BASE + channelNumber].MeasurementData.DataType,
                                numIQPoints, isComplex);
                            // Some garbage for first half of filtered-off piece
                            Array.Copy(vsa.Display.Traces[SPECTRUM_TRACE_BASE + channelNumber].MeasurementData.FloatData, 0, spec2Result[channelNumber],
                                0, (int)((0.109375 / 2) * pointsMultiplier * numIQPoints));
                            // Now, same garbage plus first half of our good data
                            Array.Copy(vsa.Display.Traces[SPECTRUM_TRACE_BASE + channelNumber].MeasurementData.FloatData, 0, spec2Result[channelNumber],
                                (int)((0.109375 / 2) * pointsMultiplier * numIQPoints), (int)((0.890625 / 2) * pointsMultiplier * numIQPoints));

                            vsa.Display.Traces[SPECTRUM_TRACE_BASE + channelNumber].MeasurementData.State.CopyTo(vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.State);
                        }
                        addResultsFooter("First half of data copied to register: ", sw2.ElapsedMilliseconds);
                        sw2.Reset();
                        sw2.Start();
                        vsa.Measurements.SelectedItem.Input.DataFrom = DataSource.Hardware;
                        addResultsFooter("Set back to hardware mode: ", sw2.ElapsedMilliseconds);

                        double freq2 = 0;
                        double freq3 = 0;
                        double freq4 = 0;
                        double freq1 = (double)FreqMHzControl.Value * 1e6 + 80e6;
                        if (numChannels > 1)
                            freq2 = (double)Freq2MHzControl.Value * 1e6 + 80e6;
                        if (numChannels > 2)
                            freq3 = (double)Freq3MHzControl.Value * 1e6 + 80e6;
                        if (numChannels > 3)
                            freq4 = (double)Freq4MHzControl.Value * 1e6 + 80e6;

                        sw2.Reset();
                        sw2.Start();
                        vsa.Measurements.SelectedItem.Frequency.Channels[0].Center = freq1;
                        if (numChannels > 1)
                            vsa.Measurements.SelectedItem.Frequency.Channels[1].Center = freq2;
                        if (numChannels > 2)
                            vsa.Measurements.SelectedItem.Frequency.Channels[2].Center = freq3;
                        if (numChannels > 3)
                            vsa.Measurements.SelectedItem.Frequency.Channels[3].Center = freq4;
                        addResultsFooter("Setting frequency again: ", sw2.ElapsedMilliseconds);
                        sw2.Reset();
                        sw2.Start();
                        vsa.Measurements.SelectedItem.Record();
                        try
                        {
                            vsa.Measurements.SelectedItem.WaitForRecordingDone(10000);
                        }
                        catch (System.TimeoutException ex)
                        {
                            MessageBox.Show("Timeout measuring Spectrum");
                            specMeasFail = true;
                        }
                        addResultsFooter("Second recording: ", sw2.ElapsedMilliseconds);

                        sw2.Reset();
                        sw2.Start();
                        // This will perform the measurement on the recording
                        vsa.Measurements.SelectedItem.Resume();
                        try
                        {
                            vsa.Measurements.SelectedItem.WaitForMeasurementDone(3000);
                        }
                        catch (System.TimeoutException ex)
                        {
                            MessageBox.Show("Timeout measuring Spectrum");
                            specMeasFail = true;
                        }
                        addResultsFooter("Second measurement from recording: ", sw2.ElapsedMilliseconds);

                        if (specMeasFail != true)
                        {
                            if (spec2Result != null)
                            {
                                sw2.Reset();
                                sw2.Start();
                                for (int channelNumber = 0; channelNumber < numChannels; channelNumber++)
                                {
                                    // Next, second half of our good data plus garbage at end
                                    Array.Copy(vsa.Display.Traces[SPECTRUM_TRACE_BASE + channelNumber].MeasurementData.FloatData, (int)((0.109375 / 2) * pointsMultiplier * numIQPoints),
                                        spec2Result[channelNumber], (numIQPoints / 2) * pointsMultiplier, (int)((0.890625 / 2) * pointsMultiplier * numIQPoints));
                                    // Last, another copy of garbage at the end
                                    Array.Copy(vsa.Display.Traces[SPECTRUM_TRACE_BASE + channelNumber].MeasurementData.FloatData, (int)((0.890625 / 2) * pointsMultiplier * numIQPoints),
                                        spec2Result[channelNumber], (int)((1.890625 / 2) * pointsMultiplier * numIQPoints),
                                        (int)((0.109375 / 2) * pointsMultiplier * numIQPoints));
                                    vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.FloatData = spec2Result[channelNumber];
                                    vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.XDelta = (vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.XDelta) / pointsMultiplier;
                                    vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.XStart = (double)FreqMHzControl.Value * 1e6 - 160e6 -
                                        (vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.XDelta * (0.109375) * pointsMultiplier * numIQPoints);
                                    float[] peakSearchData = PeakSearch.ToDBm(spec2Result[channelNumber], numIQPoints, isComplex);
                                    int point = PeakSearch.FindPeak(peakSearchData);
                                    double magValue = -double.MaxValue;
                                    if (point >= 0)
                                        magValue = PeakSearch.DbmToVpk(peakSearchData[point] + 0.01);

                                    vsa.DataRegisters[SEM_REGISTER[channelNumber]].MeasurementData.State["Jake"] = magValue;

                                    //vsa.Measurements.SelectedItem.Restart();
                                    //try
                                    //{
                                    //    vsa.Measurements.SelectedItem.WaitForMeasurementDone(3000);
                                    //}
                                    //catch (System.TimeoutException ex)
                                    //{
                                    //    MessageBox.Show("Timeout measuring Spectrum");

                                    //}
                                    vsa.Display.Traces[SEM_TRACE_BASE + channelNumber].DataName = SEM_REGISTER[channelNumber];
                                    //vsa.Measurements.SelectedItem.Restart();
                                    //try
                                    //{
                                    //    vsa.Measurements.SelectedItem.WaitForMeasurementDone(3000);
                                    //}
                                    //catch (System.TimeoutException ex)
                                    //{
                                    //    MessageBox.Show("Timeout measuring Spectrum");

                                    //}
                                    // Query the SEM limit result
                                    LimitResultData semLimRes = vsa.Display.Traces[SEM_TRACE_BASE + channelNumber].Markers.LimitResult(0);
                                    double semNumResult = 999;
                                    string semStringResult = semLimRes.Result.ToString();
                                    if (semStringResult.Equals("Pass"))
                                        semNumResult = 1;
                                    else if (semStringResult.Equals("Fail"))
                                        semNumResult = 0;
                                    logDataItem("SEM", "Pass/Fail", "0", semNumResult);
                                    semLimRes.Result.ToString();
                                }
                                addResultsFooter("Shoving second half of result into register, displaying trace and querying data", sw2.ElapsedMilliseconds);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

#endif
        }

        private void measEVM(bool performAutoRange, ref double[] range)
        {
            const int ERROR_TRACE = 4;

#if useVSA

            if (use89600VSA)
            {
                try
                {


                    tstName = "802.11ac 2SS 80 MHz BW";

                    // TODO:  need to figure out which tests to run based on what the user has selected
                    addResultsHeader(tstName);
                    addResultsHeader("Frequency = " + FreqMHzControl.Value.ToString("0.0") + " MHz");

                    // choose setup file based on selected waveform
                    //vsa.RecallSetup(applicationDirectory + "\\Dual Channel\\" + "80211ac_MCS9_2SS_80MHzBW.setx");              

                    vsa.Measurements.SelectedItem = vsa.Measurements["demod"];

                    vsa.Measurements.SelectedItem.IsContinuous = false;

                    vsa.Measurements.SelectedItem.Frequency.Channels[0].Center = (double)FreqMHzControl.Value * 1000000;
                    if (numChannels > 1)
                        vsa.Measurements.SelectedItem.Frequency.Channels[1].Center = (double)Freq2MHzControl.Value * 1000000;
                    if (numChannels > 2)
                        vsa.Measurements.SelectedItem.Frequency.Channels[2].Center = (double)Freq3MHzControl.Value * 1e6;
                    if (numChannels > 3)
                        vsa.Measurements.SelectedItem.Frequency.Channels[3].Center = (double)Freq4MHzControl.Value * 1e6;

                    if (performAutoRange)
                    {
                        //:     autorange now on all channels.  But we might not want to do this in general
                        vsa.Measurements.SelectedItem.Input.Analog.AutoRange();
                    }

                    for (int channelNumber = 0; channelNumber < numChannels; channelNumber++)
                        range[channelNumber] = vsa.Measurements.SelectedItem.Input.Analog.Channels[channelNumber].Range;
                    //range2 = vsa.Measurements.SelectedItem.Input.Analog.Channels[1].Range;

                    // TODO: Set average count if desired

                    // Make a measurement, return EVM
                    vsa.Measurements.SelectedItem.Resume();

                    try
                    {
                        vsa.Measurements.SelectedItem.WaitForMeasurementDone(3000);
                    }
                    catch (System.TimeoutException ex)
                    {
                        MessageBox.Show("Timeout measuring EVM");
                    }

                    // RMS EVM index = numChannels
                    string evmData = vsa.Display.Traces[ERROR_TRACE].MeasurementData.Summary(2).ToString();


                    //string[] summaryNames = vsa.Display.Traces[ERROR_TRACE].MeasurementData.SummaryNames;

                    //addResultsHeader(summaryNames.ToString());


                    double evmResult = Double.Parse(evmData);

                    //vsaInst.WriteString("TRACe4:DATA:TABLe:VALue? \"EVM\"");
                    //double evmResult = (double) vsaInst.ReadNumber();
                    evmResult = 20 * Math.Log10(evmResult / 100);

                    logDataItem("RMS EVM", "dB", "0.00", evmResult);

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }

#endif

        }

        private void initButton_Click(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            numChannelsControl.Enabled = false;

            resultsBox.Text = "";
            resultsString = "";
            
            // Send GUI settings down to test library
            M9381resource[0] = vsg1ResourceStringBox.Text;
            M9381resource[1] = vsg2ResourceStringBox.Text;
            M9381resource[2] = vsg3ResourceStringBox.Text;
            M9381resource[3] = vsg4ResourceStringBox.Text;

            M9300resource = referenceResourceStringBox.Text;
#if chassisSetup
            M9018resource = chassisResourceStringBox.Text;
            M9018vsaResource = chassisVSAResourceStringBox.Text;
#endif
            simulateHardware = simulateBox.Checked;

            examplesDirectory = "C:\\Program Files (x86)\\Agilent\\M938x\\Example Waveforms\\";
            applicationDirectory = System.Windows.Forms.Application.StartupPath + "\\";

            // Initiailize the Instruments
            testStatusLabel.Text = "Initializing Hardware";
            try
            {

                initHardware();
                setupForNumChannels();
                readGuiControls();
                loadWaveforms();
                // Don't start playback right away.  Let the user press the "Play Waveforms" button.
                //if (ModEnableControl.Checked)
                //   playWaveform();
                mInitComplete = true;
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            // Setup the GUI to run tests
            testStatusLabel.Text = "Initialized";
            closeButton.Enabled = true;
            initButton.Enabled = false;
            simulateBox.Enabled = false;
            vsaChassisEnableCheckBox.Enabled = false;
           
            loadWaveformButton.Enabled = true;
            FreqMHzControl.Enabled = true;
            if ((mWaveformHandle == "user" || mWaveformHandle == "WF9") && (numChannels > 1))
                Freq2MHzControl.Enabled = true;
            if ((mWaveformHandle == "user" || mWaveformHandle == "WF9") && (numChannels > 2))
                Freq3MHzControl.Enabled = true;
            if ((mWaveformHandle == "user" || mWaveformHandle == "WF9") && (numChannels > 3))
                Freq4MHzControl.Enabled = true;

            Amp_dBmControl.Enabled = true;


            testStatusLabel.Text = "Initialization Complete";
            Cursor.Current = Cursors.Default;
        }

        private void closeButton_Click(object sender, EventArgs e)
        {
            testStatusLabel.Text = "Closing Hardware";
            closePxiHardware();

            // Put GUI back to Init state
            testStatusLabel.Text = "Press Init to Start";
            closeButton.Enabled = false;
            initButton.Enabled = true;
            simulateBox.Enabled = true;
            loadWaveformButton.Enabled = false;
            FreqMHzControl.Enabled = false;
            Freq2MHzControl.Enabled = false;
            Freq3MHzControl.Enabled = false;
            Freq4MHzControl.Enabled = false;
            Amp_dBmControl.Enabled = false;
            AmpCh2_dBmControl.Enabled = false;
            AmpCh3_dBmControl.Enabled = false;
            AmpCh4_dBmControl.Enabled = false;
            numChannelsControl.Enabled = true;
            vsaChassisEnableCheckBox.Enabled = true;
            useVSACheckBox.Enabled = true;
        }

        private void Form1_Close(object sender, FormClosingEventArgs e)
        {
            closePxiHardware();
        }

        private void M9381_ValueChanged(object sender, EventArgs e)
        {
            setupForNumChannels();
            readGuiControls();
        }

        private void readGuiControls()
        {
            stopPlayback();

            if (mWaveformHandle != "user" && mWaveformHandle != "WF9")
            {
                if (numChannels > 1)
                    Freq2MHzControl.Value = FreqMHzControl.Value;
                if (numChannels > 2)
                    Freq3MHzControl.Value = FreqMHzControl.Value;
                if (numChannels > 3)
                    Freq4MHzControl.Value = FreqMHzControl.Value;
            }

            // if we are tracking, propagate the changes from amp control to others
            double ampDelta = (double)Amp_dBmControl.Value - mAmplitude;
            mAmplitude = (double)Amp_dBmControl.Value;
            
            if (trackAmplitudeChangesCheckBox.Checked == true)
            {
                if (numChannels > 1)
                    AmpCh2_dBmControl.Value = AmpCh2_dBmControl.Value + (decimal)ampDelta;
                if (numChannels > 2)
                    AmpCh3_dBmControl.Value = AmpCh3_dBmControl.Value + (decimal)ampDelta;
                if (numChannels > 3)
                    AmpCh4_dBmControl.Value = AmpCh4_dBmControl.Value + (decimal)ampDelta;
            }
           
            AgM938xOutputPulseModeEnum pulseMode = AgM938xOutputPulseModeEnum.AgM938xOutputPulseModeNotPulsed;

            // Turn RF On, pulse blanking on
            if (pulseBlankingEnableCheckBox.Checked)
            {
                pulseMode = AgM938xOutputPulseModeEnum.AgM938xOutputPulseModePulseOnWithTrigger;
            }

            for (int i=0; i<numChannels; i++)
                M9381[i].RF.OutputPulseMode = pulseMode;

            for (int i = 0; i < numChannels; i++)
            {
                double freq = 1e9;
                switch (i)
                {
                    case 0:
                       freq = (double) FreqMHzControl.Value*1e6;
                       break;
                    case 1:
                        freq = (double) Freq2MHzControl.Value*1e6;
                        break;
                    case 2:
                        freq = (double) Freq3MHzControl.Value*1e6;
                        break;
                    case 3:
                        freq = (double) Freq4MHzControl.Value*1e6;
                        break;
                }
                M9381[i].RF.Frequency = freq;
                double tempLevel = -99.0;
                switch (i)
                {
                    case 0:
                        tempLevel = (double)Amp_dBmControl.Value;
                        break;
                    case 1:
                        tempLevel = (double)AmpCh2_dBmControl.Value;
                        break;
                    case 2:
                        tempLevel = (double)AmpCh3_dBmControl.Value;
                        break;
                    case 3:
                        tempLevel = (double)AmpCh4_dBmControl.Value;
                        break;
                }
                
                M9381[i].RF.Level = tempLevel;
                M9381[i].RF.OutputEnabled = RfEnableControl.Checked;
                M9381[i].Modulation.Enabled = ModEnableControl.Checked;
                M9381[i].Apply();
            }

            if (mInitComplete && ModEnableControl.Checked && RfEnableControl.Checked)
            {
                // Don't play waveform now.  Wait for user to press Play button
                //playWaveform();
            }
        }

        private void loadWaveforms()
        {

            waveformListBox.Items.Clear();
            sequenceListBox.Items.Clear();
            stopPlayback();

            for (int i = 0; i < numChannels; i++)
            {
                M9381[i].Modulation.Sequence.Remove("WF1");
                M9381[i].Modulation.IQ.RemoveArb("WF1");
                loadVsgWaveform(ref M9381[i], examplesDirectory, "WLAN_11ac_256QAM_80MHz.wfm", "WF1");
                createSequence(ref M9381[i], "WF1", "WF1", (int)repetitionsControl.Value);

                M9381[i].Modulation.Sequence.Remove("WF2");
                M9381[i].Modulation.IQ.RemoveArb("WF2");
                loadVsgWaveform(ref M9381[i], examplesDirectory, "WLAN_11ac_64QAM_160MHz.wfm", "WF2");
                createSequence(ref M9381[i], "WF2", "WF2", (int)repetitionsControl.Value);

                M9381[i].Modulation.Sequence.Remove("WF3");
                M9381[i].Modulation.IQ.RemoveArb("WF3");
                loadVsgWaveform(ref M9381[i], applicationDirectory + "Single Channel\\", "80211acMCS9_40MHz.wfm", "WF3");
                createSequence(ref M9381[i], "WF3", "WF3", (int)repetitionsControl.Value);

                M9381[i].Modulation.Sequence.Remove("WF4");
                M9381[i].Modulation.IQ.RemoveArb("WF4");
                loadVsgWaveform(ref M9381[i], applicationDirectory + "Single Channel\\", "80211nMCS7_20MHz.wfm", "WF4");
                createSequence(ref M9381[i], "WF4", "WF4", (int)repetitionsControl.Value);
            }

            waveformListBox.Items.Add("802.11ac 1SS 80MHz MCS8");
            sequenceListBox.Items.Add("802.11ac 1SS 80MHz MCS8");
            waveformListBox.Items.Add("802.11ac 1SS 160MHz MCS7");
            sequenceListBox.Items.Add("802.11ac 1SS 160MHz MCS7");
            waveformListBox.Items.Add("802.11ac 1SS 40MHz MCS9");
            sequenceListBox.Items.Add("802.11ac 1SS 40MHz MCS9");
            waveformListBox.Items.Add("802.11n 1SS 20MHz MCS7");
            sequenceListBox.Items.Add("802.11n 1SS 20MHz MCS7");

            switch (numChannels)
            {
                case 4:
                {
                    for (int i = 0; i < 4; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF5");
                        M9381[i].Modulation.IQ.RemoveArb("WF5");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_80MHzBW0.wfm", "WF5");
                    createSequence(ref M9381[0], "WF5", "WF5", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_80MHzBW1.wfm", "WF5");
                    createSequence(ref M9381[1], "WF5", "WF5", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_80MHzBW2.wfm", "WF5");
                    createSequence(ref M9381[2], "WF5", "WF5", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[3], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_80MHzBW3.wfm", "WF5");
                    createSequence(ref M9381[3], "WF5", "WF5", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11ac 4SS 80MHz MCS9");
                    sequenceListBox.Items.Add("802.11ac 4SS 80MHz MCS9");

                    for (int i = 0; i < 4; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF6");
                        M9381[i].Modulation.IQ.RemoveArb("WF6");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_160MHzBW0.wfm", "WF6");
                    createSequence(ref M9381[0], "WF6", "WF6", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_160MHzBW1.wfm", "WF6");
                    createSequence(ref M9381[1], "WF6", "WF6", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_160MHzBW2.wfm", "WF6");
                    createSequence(ref M9381[2], "WF6", "WF6", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[3], applicationDirectory + "Four Channel\\", "80211ac_MCS9_4SS_160MHzBW3.wfm", "WF6");
                    createSequence(ref M9381[3], "WF6", "WF6", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11ac 4SS 160MHz MCS9");
                    sequenceListBox.Items.Add("802.11ac 4SS 160MHz MCS9");

                    for (int i = 0; i < 4; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF7");
                        M9381[i].Modulation.IQ.RemoveArb("WF7");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Four Channel\\", "80211n_MCS31_40MHzBW0.wfm", "WF7");
                    createSequence(ref M9381[0], "WF7", "WF7", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Four Channel\\", "80211n_MCS31_40MHzBW1.wfm", "WF7");
                    createSequence(ref M9381[1], "WF7", "WF7", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Four Channel\\", "80211n_MCS31_40MHzBW2.wfm", "WF7");
                    createSequence(ref M9381[2], "WF7", "WF7", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[3], applicationDirectory + "Four Channel\\", "80211n_MCS31_40MHzBW3.wfm", "WF7");
                    createSequence(ref M9381[3], "WF7", "WF7", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11n 4SS 40MHz MCS31");
                    sequenceListBox.Items.Add("802.11n 4SS 40MHz MCS31");

                    for (int i = 0; i < 4; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF8");
                        M9381[i].Modulation.IQ.RemoveArb("WF8");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Four Channel\\", "80211n_MCS31_20MHzBW0.wfm", "WF8");
                    createSequence(ref M9381[0], "WF8", "WF8", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Four Channel\\", "80211n_MCS31_20MHzBW1.wfm", "WF8");
                    createSequence(ref M9381[1], "WF8", "WF8", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Four Channel\\", "80211n_MCS31_20MHzBW2.wfm", "WF8");
                    createSequence(ref M9381[2], "WF8", "WF8", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[3], applicationDirectory + "Four Channel\\", "80211n_MCS31_20MHzBW3.wfm", "WF8");
                    createSequence(ref M9381[3], "WF8", "WF8", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11n 4SS 20MHz MCS31");
                    sequenceListBox.Items.Add("802.11n 4SS 20MHz MCS31");


                    break;
                }
                case 3:
                {
                    for (int i = 0; i < 3; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF5");
                        M9381[i].Modulation.IQ.RemoveArb("WF5");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Three Channel\\", "80211ac_MCS9_3SS_80MHzBW0.wfm", "WF5");
                    createSequence(ref M9381[0], "WF5", "WF5", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Three Channel\\", "80211ac_MCS9_3SS_80MHzBW1.wfm", "WF5");
                    createSequence(ref M9381[1], "WF5", "WF5", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Three Channel\\", "80211ac_MCS9_3SS_80MHzBW2.wfm", "WF5");
                    createSequence(ref M9381[2], "WF5", "WF5", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11ac 3SS 80MHz MCS9");
                    sequenceListBox.Items.Add("802.11ac 3SS 80MHz MCS9");

                    for (int i = 0; i < 3; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF6");
                        M9381[i].Modulation.IQ.RemoveArb("WF6");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Three Channel\\", "80211ac_MCS8_3SS_160MHzBW0.wfm", "WF6");
                    createSequence(ref M9381[0], "WF6", "WF6", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Three Channel\\", "80211ac_MCS8_3SS_160MHzBW1.wfm", "WF6");
                    createSequence(ref M9381[1], "WF6", "WF6", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Three Channel\\", "80211ac_MCS8_3SS_160MHzBW2.wfm", "WF6");
                    createSequence(ref M9381[2], "WF6", "WF6", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11ac 3SS 160MHz MCS8");
                    sequenceListBox.Items.Add("802.11ac 3SS 160MHz MCS8");

                    for (int i = 0; i < 3; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF7");
                        M9381[i].Modulation.IQ.RemoveArb("WF7");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Three Channel\\", "80211n_MCS23_40MHzBW0.wfm", "WF7");
                    createSequence(ref M9381[0], "WF7", "WF7", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Three Channel\\", "80211n_MCS23_40MHzBW1.wfm", "WF7");
                    createSequence(ref M9381[1], "WF7", "WF7", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Three Channel\\", "80211n_MCS23_40MHzBW2.wfm", "WF7");
                    createSequence(ref M9381[2], "WF7", "WF7", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11n 3SS 40MHz MCS23");
                    sequenceListBox.Items.Add("802.11n 3SS 40MHz MCS23");

                    for (int i = 0; i < 3; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF8");
                        M9381[i].Modulation.IQ.RemoveArb("WF8");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Three Channel\\", "80211n_MCS23_20MHzBW0.wfm", "WF8");
                    createSequence(ref M9381[0], "WF8", "WF8", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Three Channel\\", "80211n_MCS23_20MHzBW1.wfm", "WF8");
                    createSequence(ref M9381[1], "WF8", "WF8", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[2], applicationDirectory + "Three Channel\\", "80211n_MCS23_20MHzBW2.wfm", "WF8");
                    createSequence(ref M9381[2], "WF8", "WF8", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11n 3SS 20MHz MCS23");
                    sequenceListBox.Items.Add("802.11n 3SS 20MHz MCS23");
 
                    break;
                }
                case 2:
                {
                    for (int i = 0; i < 2; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF5");
                        M9381[i].Modulation.IQ.RemoveArb("WF5");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_2SS_80MHzBW0.wfm", "WF5");
                    createSequence(ref M9381[0], "WF5", "WF5", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_2SS_80MHzBW1.wfm", "WF5");
                    createSequence(ref M9381[1], "WF5", "WF5", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11ac 2SS 80MHz MCS9");
                    sequenceListBox.Items.Add("802.11ac 2SS 80MHz MCS9");

                    for (int i = 0; i < 2; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF6");
                        M9381[i].Modulation.IQ.RemoveArb("WF6");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_2SS_160MHzBW0.wfm", "WF6");
                    createSequence(ref M9381[0], "WF6", "WF6", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_2SS_160MHzBW1.wfm", "WF6");
                    createSequence(ref M9381[1], "WF6", "WF6", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11ac 2SS 160MHz MCS9");
                    sequenceListBox.Items.Add("802.11ac 2SS 160MHz MCS9");

                    for (int i = 0; i < 2; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF7");
                        M9381[i].Modulation.IQ.RemoveArb("WF7");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Dual Channel\\", "80211n_MCS15_40MHzBW0.wfm", "WF7");
                    createSequence(ref M9381[0], "WF7", "WF7", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Dual Channel\\", "80211n_MCS15_40MHzBW1.wfm", "WF7");
                    createSequence(ref M9381[1], "WF7", "WF7", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11n 2SS 40MHz MCS15");
                    sequenceListBox.Items.Add("802.11n 2SS 40MHz MCS15");

                    for (int i = 0; i < 2; i++)
                    {
                        M9381[i].Modulation.Sequence.Remove("WF8");
                        M9381[i].Modulation.IQ.RemoveArb("WF8");
                    }
                    loadVsgWaveform(ref M9381[0], applicationDirectory + "Dual Channel\\", "80211n_MCS15_20MHzBW0.wfm", "WF8");
                    createSequence(ref M9381[0], "WF8", "WF8", (int)repetitionsControl.Value);
                    loadVsgWaveform(ref M9381[1], applicationDirectory + "Dual Channel\\", "80211n_MCS15_20MHzBW1.wfm", "WF8");
                    createSequence(ref M9381[1], "WF8", "WF8", (int)repetitionsControl.Value);
                    waveformListBox.Items.Add("802.11n 2SS 20MHz MCS15");
                    sequenceListBox.Items.Add("802.11n 2SS 20MHz MCS15");


                    break;
                }
            }

            if (numChannels > 1)
            {
                for (int i = 0; i < 2; i++)
                {
                    M9381[i].Modulation.Sequence.Remove("WF9");
                    M9381[i].Modulation.IQ.RemoveArb("WF9");
                }
                loadVsgWaveform(ref M9381[0], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_80plus800_0.wfm", "WF9");
                createSequence(ref M9381[0], "WF9", "WF9", (int)repetitionsControl.Value);
                loadVsgWaveform(ref M9381[1], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_80plus801_0.wfm", "WF9");
                createSequence(ref M9381[1], "WF9", "WF9", (int)repetitionsControl.Value);
                waveformListBox.Items.Add("802.11ac 80+80 80MHz MCS9");
                sequenceListBox.Items.Add("802.11ac 80+80 80MHz MCS9");
               
            }
            if (numChannels > 2)
            {
                M9381[2].Modulation.Sequence.Remove("WF9");
                M9381[2].Modulation.IQ.RemoveArb("WF9");
                loadVsgWaveform(ref M9381[2], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_80plus801_0.wfm", "WF9");
                createSequence(ref M9381[2], "WF9", "WF9", (int)repetitionsControl.Value);
            }
            if (numChannels > 3)
            {
                M9381[3].Modulation.Sequence.Remove("WF9");
                M9381[3].Modulation.IQ.RemoveArb("WF9");
                loadVsgWaveform(ref M9381[3], applicationDirectory + "Dual Channel\\", "80211ac_MCS9_80plus801_0.wfm", "WF9");
                createSequence(ref M9381[3], "WF9", "WF9", (int)repetitionsControl.Value);
            }

            waveformListBox.SelectedIndex = 0;
        }

        // extract code to play waveform.  Make a member variable that is the current ARB name
        // stop playback and delete the user-defined waveform before loading
        // Eventually, have this simply load the user-defined waveform into memory (replacing if necessary), but do not initiate playback.  
        // initiate playback instead based on the radio button selection.
        private void loadWaveformButton_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "Signal Studio files (*.wfm)|*.wfm|WAVEFORM files (*.WAVEFORM)|*.WAVEFORM|All files (*.*)|*.*";
            openFileDialog1.FileName = "";

            openFileDialog1.Title = "Select waveform for Channel 1";
            openFileDialog1.ShowDialog();
            wfFileChan1Box.Text = openFileDialog1.FileName;

            int wfNumber = waveformListBox.Items.Count + 1;

            if (numChannels > 1)
            {
                openFileDialog1.Title = "Select waveform for Channel 2";
                openFileDialog1.ShowDialog();
                wfFileChan2Box.Text = openFileDialog1.FileName;
            }

            if (numChannels > 2)
            {
                openFileDialog1.Title = "Select waveform for Channel 3";
                openFileDialog1.ShowDialog();
                wfFileChan3Box.Text = openFileDialog1.FileName;
            }
            if (numChannels > 3)
            {
                openFileDialog1.Title = "Select waveform for Channel 4";
                openFileDialog1.ShowDialog();
                wfFileChan4Box.Text = openFileDialog1.FileName;
            }
            try
            {
                FileInfo fi1 = new FileInfo(wfFileChan1Box.Text);
                FileInfo fi2 = null;
                if (numChannels > 1)
                    fi2 = new FileInfo(wfFileChan2Box.Text);
                FileInfo fi3 = null;
                if (numChannels > 2)
                    fi3 = new FileInfo(wfFileChan3Box.Text);
                FileInfo fi4 = null;
                if (numChannels > 3)
                    fi4 = new FileInfo(wfFileChan4Box.Text);

                for (int i = 0; i < numChannels; i++)
                    M9381[i].Modulation.Stop();

                for (int i = 0; i < numChannels; i++)
                {
                    string tempDirName = "";
                    string tempFileName = "";
                    switch (i)
                    {
                        case 0:
                            tempDirName = fi1.DirectoryName;
                            tempFileName = fi1.Name;
                            break;
                        case 1:
                            tempDirName = fi2.DirectoryName;
                            tempFileName = fi2.Name;
                            break;
                        case 2:
                            tempDirName = fi3.DirectoryName;
                            tempFileName = fi3.Name;
                            break;
                        case 3:
                            tempDirName = fi4.DirectoryName;
                            tempFileName = fi4.Name;
                            break;
                    }
                    M9381[i].Modulation.Sequence.Remove("WF" + wfNumber);
                    M9381[i].Modulation.IQ.RemoveArb("WF" + wfNumber);
                    
                    loadVsgWaveform(ref M9381[i], tempDirName + "\\", tempFileName, "WF" + wfNumber);
                }

                if (ModEnableControl.Checked)
                   playWaveform();

                testStatusLabel.Text = "Waveform " + newWaveformNameTextBox.Text.ToString() + " Loaded chan 1: " + fi1.Name;
                if (numChannels > 1)
                    testStatusLabel.Text += " chan 2: " + fi2.Name;
                if (numChannels > 2)
                    testStatusLabel.Text += " chan 3: " + fi3.Name;
                if (numChannels > 3)
                    testStatusLabel.Text += " chan 4: " + fi4.Name;

                waveformListBox.Items.Add(newWaveformNameTextBox.Text.ToString());
                for (int i = 0; i < numChannels; i++)
                    createSequence(ref M9381[i], "WF" + wfNumber, "WF" + wfNumber, (int)repetitionsControl.Value);
                sequenceListBox.Items.Add(newWaveformNameTextBox.Text.ToString());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void stopPlayback()
        {
            try
            {
                for (int i = 0; i < numChannels; i++)
                    M9381[i].Modulation.Stop();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            testStatusLabel.Text = "Waveform playback stopped";
        }
        
        private void playWaveform()
        {
            try
            {
                
                stopPlayback();
                int selectedWfIdx = 0;
                // Which waveform is selected?
                if (continuousRadioButton.Checked)
                    selectedWfIdx = waveformListBox.SelectedIndex + 1;
                else
                    selectedWfIdx = sequenceListBox.SelectedIndex + 1;

                mWaveformHandle = "WF" + selectedWfIdx;
                String sequenceHandle = mWaveformHandle;
                System.Threading.Thread.Sleep(100);

                double rmsValue = 0.0;
                double scaleFactor = 0.0;
                double sampleRate = 0.0;
                AgM938xMarkerEnum alcMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                AgM938xMarkerEnum blankingMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                

                for (int i = 0; i < numChannels; i++)
                {
                    // Recover the sample rate and RMS Value from the waveform to reuse for the zeros waveform
                    M9381[i].Modulation.IQ.ArbInformation(mWaveformHandle, ref sampleRate, ref rmsValue,
                            ref scaleFactor, ref blankingMarker, ref alcMarker);

                    createZerosWaveform(ref M9381[i], "zeros", sampleRate, rmsValue, scaleFactor);
                }



                // Play immediate first, do power search, and optionally do IQ DC alignment
                for (int i = 0; i < numChannels; i++)
                    M9381[i].Modulation.PlayArb("zeros", AgM938xStartEventEnum.AgM938xStartEventImmediate);

                System.Threading.Thread.Sleep(100);

                //Play the zeros waveform, perform power search, then play sequence
                for (int i = 0; i < numChannels; i++)
                    M9381[i].Calibration.PowerSearch.BlankRFDuringSearch = true;

                double[] powOffset = new double[numChannels];
                double[] scaleOffset = new double[numChannels];
                for (int i = 0; i < numChannels; i++)
                    M9381[i].Calibration.PowerSearch.DoPowerSearch(ref powOffset[i], ref scaleOffset[i]);

                for (int i = 0; i < numChannels; i++) 
                    M9381[i].Calibration.IQAlignment.AlignIQAtDC();

                //Stop playback, and let's start again, this time external triggered
                stopPlayback();

                System.Threading.Thread.Sleep(100);

                // Must apply the result we measured in power search previously when we replay
                for (int i = 0; i < numChannels; i++)
                    M9381[i].Calibration.PowerSearch.UsePowerSearchResult(powOffset[i], scaleOffset[i]);


                // Setup external trigger on M9300A
                // Generate a sync pulse on the M9300 reference module, on backplane trigger
                M9300.ReferenceBase2.ProgrammableOutputTrigger2.Destination = (AgM9300TriggerEnum)(triggerToSource + 2);
                M9300.Apply();

                if (continuousRadioButton.Checked)
                {
                    for (int i = 0; i < numChannels; i++)
                        M9381[i].Modulation.PlayArb(mWaveformHandle,
                            AgM938xStartEventEnum.AgM938xStartEventExternalTrigger);

                    System.Threading.Thread.Sleep(100);
                }
                else
                {
                    // Set scale factor.  This is important to avoid modulation quality issues
                    for (int i = 0; i < numChannels; i++)
                    { 
                        M9381[i].Modulation.Scale = scaleFactor;
                    }

                    // Arm the sequence playback
                    for (int i = 0; i < numChannels; i++) 
                        M9381[i].Modulation.Sequence.Play(sequenceHandle, AgM938xStartEventEnum.AgM938xStartEventExternalTrigger);

                    System.Threading.Thread.Sleep(100);
                }

                // Generate a sync pulse on the M9300 reference module, on PXI trigger 5
                M9300.ReferenceBase2.ProgrammableOutputTrigger2.GenerateTrigger();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            testStatusLabel.Text = "Waveform playback initiated";
        }

        private void createZerosWaveform(ref IAgM938xEx vsg, string wfName, double sampleRate, double rmsValue, double scaleFactor)
        {
            // Make a waveform with zeros to end our sequence with
            //Create a file with zeros at the same sample rate as the GSM and EDGE data files
            double[] ArbData = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };


            // Remove the zeros waveform if it already exist
            vsg.Modulation.IQ.RemoveArb(wfName);


            vsg.Modulation.IQ.UploadArbDoubles(wfName, ref ArbData, sampleRate, rmsValue, 1);
        }

        # endregion

        #region Init and Close Instruments
        // Instrument control Methods

        public void initHardware()
        {
            int errorcode = -1; string message = string.Empty;
            bool idquery = true;
            bool reset = false;
            string M9381options = string.Format(
                "QueryInstrStatus=true, Simulate={0}, M9381Setup= Model=M9381A, Trace=false", (simulateHardware ? "true" : "false"));
            string M9300options = string.Format(
                 "QueryInstrStatus=true, Simulate={0}, M9300Setup= Model=, Trace=false", (simulateHardware ? "true" : "false"));

            use89600VSA = useVSACheckBox.Checked;
            useVSACheckBox.Enabled = false;

#if chassisSetup
            string M9018options = string.Format(
                 "QueryInstrStatus=true, Simulate={0}, M9018Setup= Model=, Trace=false", (simulateHardware ? "true" : "false"));
            mVSAChassisEnabled = vsaChassisEnableCheckBox.Checked;
#endif
            try
            {
 

#if chassisSetup
                M9018 = new AgM9018();
                if (mVSAChassisEnabled)
                    M9018vsa = new AgM9018();
#endif

#if autoChassisSetup
                ResponseLogger results = new ResponseLogger();
                PrereqChecker.SystemSupportsMinimumSoftware(results);
                if (!results.Passed)
                    MessageBox.Show("Recommended software versions not met: " + results.ToString());
                //Use VISA to read PXI devices and group into chassis and modules
                VirtualChassis[] chassisArray = VirtualChassisBuilder.VirtualizePxiDevices();

                int chassisIndex = 0;
                foreach (VirtualChassis chassis in chassisArray)
                {
                    hardwareDetailsTextBox.Text += "Chassis " + chassisIndex + Environment.NewLine;
                    //groups modules together to form devices
                    chassis.IdentifyDevices();

                    if (chassis.Sources.Count > 0)
                    {
                        hardwareDetailsTextBox.Text += "Number of M9381A VSGs: " + chassis.Sources.Count + Environment.NewLine;
                        numChannels = chassis.Sources.Count;
                    }
                    if (chassis.Receivers.Count > 0)
                        hardwareDetailsTextBox.Text += "Number of M9391A VSAs: " + chassis.Receivers.Count + Environment.NewLine;

                    //determine trigger routing for devices
                    chassis.ConfigureChassis();

                    //connect to chassis and apply trigger routing
                    chassis.SetupDevice(new ResponseLogger());
                    if (!results.Passed)
                        MessageBox.Show("Failure routing triggers on chassis: " + results.ToString());

                    //disconnect from chassis
                    chassis.CloseDevice();

                    int sourceIdx = 0;
                    foreach (VirtualSource source in chassis.Sources)
                    {
                       
                        sourceExtTrig[sourceIdx] = source.ExtTrigInput;//Get the External Trigger
                        sourceALCTrig[sourceIdx] = source.AlcHoldTrig;//Get the ALC Hold Trigger
                        if (source.UseReferenceListenTrig)//Check to see if this source is triggered by a reference
                        {
                            referenceListenTrig[sourceIdx] = source.ReferenceListenTrig;//Get the trigger the reference will use to trigger source
                        }

                        //Get the Visa Address
                        M9381resource[sourceIdx] = source.GetVisaAddress();
                        sourceIdx++;

                    }
                   
                    VirtualReference ref10 = chassis.GetSlot10Ref();
                    if (ref10 != null)
                    {
                        if (ref10.UseBackplaneExtTrig)//true if it triggers sources
                        {
                            triggerToSource = ref10.BackplaneExtTrig;//Get the trigger number
                        }

                        //Get the Visa Address
                        M9300resource = ref10.GetVisaAddress();
                    }
                    chassisIndex++;
                }
                for (int i = 0; i < numChannels; i++)
                    M9381[i] = new AgM938x();
                M9300 = new AgM9300();
#endif

                // Initialize M9300A Frequency reference
                M9300.Initialize(M9300resource, idquery, reset, M9300options);

                // Clear startup messages & warnings if any.
                do
                {
                    M9300.Utility.ErrorQuery(ref errorcode, ref message);
                    if (errorcode != 0)
                        Console.WriteLine(message);
                } while (errorcode != 0);

#if chassisSetup
                // Initialize M9018A Chassis
                M9018.Initialize(M9018resource, idquery, false, M9018options);
                if (mVSAChassisEnabled)
                    M9018vsa.Initialize(M9018vsaResource, idquery, false, M9018options);
#endif
                //Initialize M9381 Channels
                for (int i = 0; i < numChannels; i++)
                {
                    M9381[i].Initialize(M9381resource[i], idquery, reset, M9381options);
                    hardwareDetailsTextBox.Text += "VSG address = " + M9381resource[i] + " initialized" + Environment.NewLine;
                    // Clear startup messages & warnings if any.
                    do
                    {
                        M9381[i].Utility.ErrorQuery(ref errorcode, ref message);
                        if (errorcode != 0)
                            Console.WriteLine(message);
                    } while (errorcode != 0);
                }


#if chassisSetup
                // Route triggers on chassis backplane
                if (numChannels == 3)
                {
                    M9018.TriggerBus.Connect(5, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus2To1And3); // Backplane ext trig
                    M9018.TriggerBus.Connect(0, AgM9018TrigBusEnum.AgM9018TrigBus2To1); // Ext Trig from M9301A
                    M9018.TriggerBus.Connect(4, AgM9018TrigBusEnum.AgM9018TrigBus1To2); // ALC Hold to M9310A

                    // redefine triggers for VSG 2
                    M9381[1].System.PXIResources.AddHint("M9311A", "M9310A", "ALC TRIGGER",
                        Agilent.AgM938x.Interop.AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER,
                        Agilent.AgM938x.Interop.AgM938xPXIResourcesEnum.AgM938xPXIResourcesTTL_TRIGGER_4);
                    M9381[1].System.PXIResources.AddHint("M9301A", "M9311A", "EXTERNAL TRIGGER",
                        Agilent.AgM938x.Interop.AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER,
                        Agilent.AgM938x.Interop.AgM938xPXIResourcesEnum.AgM938xPXIResourcesTTL_TRIGGER_0);

                    // If we have control of the VSA chassis, set up its triggers as well
                    if (mVSAChassisEnabled)
                    {
                        M9018vsa.TriggerBus.Connect(1, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus1To2To3);
                        M9018vsa.TriggerBus.Connect(2, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus2To1);
                        M9018vsa.TriggerBus.Connect(3, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus3To2To1);
                    }
                }
                else if (numChannels == 2)
                {
                    M9018.TriggerBus.Connect(5, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus2To1And3);
                    // Backplane ext trig
                    M9018.TriggerBus.Connect(1, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus2To3);
                    // Sync trig for VSA master to slave
                    M9018.TriggerBus.Connect(2, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus3To2);
                    // Sync trig for VSA slave to master
                }
                else if (numChannels == 1)
                {
                    M9018.TriggerBus.Connect(5, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus2To1);
                    // Backplane ext trig.  This will work if M9300 is in slot 10 or slot 6.  
                }
                else if (numChannels == 4)
                {
                    // Assume VSGs in slots 2-5,6-9,11-14 and 15-18
                    // M9300A in slot 10
                    // We need to make sure the ALC Hold and front panel External Trigger routings within each VSG do not conflict with adjacent VSG's
                    // We need to assign a trigger to use for the user-generated backplane trigger from M9300A to M9311A's that does not conflict with any other trigger, and 
                    // route it appropriately on the chassis backplane
                    // The easiest way to do this, with fewest 

                    // VSG 1 and 3 use default triggers 6 and 7 for ALC Hold and front panel external trigger
                    // VSG 2 and VSG 4 use triggers 0 and 1 
                    // Use trigger 5 for the external trigger on backplane
                    M9018.TriggerBus.Connect(0, AgM9018TrigBusEnum.AgM9018TrigBus2To1);
                    M9018.TriggerBus.Connect(1, AgM9018TrigBusEnum.AgM9018TrigBus1To2);
                    M9018.TriggerBus.Connect(6, AgM9018TrigBusEnum.AgM9018TrigBus3To2);
                    M9018.TriggerBus.Connect(7, AgM9018TrigBusEnum.AgM9018TrigBus2To3);
                    M9018.TriggerBus.Connect(5, AgM9018TrigBusEnum.AgM9018TrigBus2To1And3);

                    // Redefine tiggers for VSG 2 and 4
                    M9381[1].System.PXIResources.AddHint("M9311A", "M9310A", "ALC TRIGGER",
                        AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER,
                        AgM938xPXIResourcesEnum.AgM938xPXIResourcesTTL_TRIGGER_1);
                    M9381[1].System.PXIResources.AddHint("M9301A", "M9311A", "EXTERNAL TRIGGER",
                         AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER,
                         AgM938xPXIResourcesEnum.AgM938xPXIResourcesTTL_TRIGGER_0);
                    M9381[3].System.PXIResources.AddHint("M9311A", "M9310A", "ALC TRIGGER",
                        AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER,
                        AgM938xPXIResourcesEnum.AgM938xPXIResourcesTTL_TRIGGER_1);
                    M9381[3].System.PXIResources.AddHint("M9301A", "M9311A", "EXTERNAL TRIGGER",
                         AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER,
                         AgM938xPXIResourcesEnum.AgM938xPXIResourcesTTL_TRIGGER_0);
                    if (mVSAChassisEnabled)
                    {
                        // Assume VSAs in slots 2-4, 6-8, 12-14, 16-18
                        // We need to route trigger 1 from the master M9214A to the last slave M9214A.  
                        // Trigger 2 from slave #1 to master 
                        // Trigger 3 from slave #2 to master
                        // Trigger 4 from slave #3 to master
                        M9018vsa.TriggerBus.Connect(1, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus1To2To3);
                        M9018vsa.TriggerBus.Connect(2, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus2To1);
                        M9018vsa.TriggerBus.Connect(3, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus3To2To1);
                        M9018vsa.TriggerBus.Connect(4, Agilent.AgM9018.Interop.AgM9018TrigBusEnum.AgM9018TrigBus3To2To1);
                    }
                }
#endif
#if autoChassisSetup

                for (int channel = 0; channel < numChannels; channel++)
                {
                    M9381[channel].System.PXIResources.AddHint("M9311A", "M9310A", "ALC TRIGGER",
                        Agilent.AgM938x.Interop.AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER, (AgM938xPXIResourcesEnum) sourceALCTrig[channel]);
                    M9381[channel].System.PXIResources.AddHint("M9301A", "M9311A", "EXTERNAL TRIGGER",
                        Agilent.AgM938x.Interop.AgM938xPXIResourceTypeEnum.AgM938xPXIResourceTypeTTL_TRIGGER, (AgM938xPXIResourcesEnum) sourceExtTrig[channel]);
                    
                }


#endif
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error initializing hardware: " + ex.Message);
            }
#if useVSA
            if (use89600VSA)
            {
                try
                {
                    vsa = ApplicationFactory.Create();
                    vsaIsCreated = false;
                    if (vsa == null)
                    {
                        // There is no running 89600 VSA, try to create a new one
                        vsa = ApplicationFactory.Create(true, null, null, -1);
                        vsaIsCreated = true;
                    }

                    vsa.IsVisible = true;				// Make it visible
                    vsa.Title = "MIMO PXI VSA Demo";		// Label the VSA main window



                    // Turn auto-call off (recommended for programmatic control) so that it doesn't run 
                    // when it is not expected (which could result in timeouts when using SCPI without
                    // long enough timeout values).

                    /// TODO: Do I need to loop over all of these?
                    Calibration cal = vsa.Hardware.Configurations[0].Calibration;
                    cal.IsAutoCalibrateEnabled = false;

                    // Potentially run a calibration here
                    //cal.QuickCalibrate();

                    // Set to defaults 
                    vsa.Display.Preset();
                    // TODO:  Getting no object ref here on measurements.preset()
                    //vsa.Measurements.Preset();
                    vsa.Measurements.Reset();

                    //Stop any active measurements\      
                    vsa.Measurements.SelectedItem.Pause();

                    //vsa.Measurements.SelectedItem.SelectedAnalyzer = vsa.Hardware.Configurations["2ChanMIMOM9391"];

                    //vsa.Measurements.SelectedItem.SelectedAnalyzer = vsa.Hardware.Configurations["2ChanSimM9391"];

                    // Set for single measurement
                    vsa.Measurements.SelectedItem.IsContinuous = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error initializing 89600 VSA software: " + ex.Message);
                }
            }
#endif
            try 
            {


                // Set frequency and power level (don't.  Wait until the next step, in ReadGUIControls)

                // ALC always off for best WLAN EVM
                for (int i=0; i<numChannels; i++)
                    M9381[i].ALC.Enabled = false;

                bool rfEnabled = RfEnableControl.Checked;
                for (int i = 0; i < numChannels; i++) 
                    M9381[i].RF.OutputEnabled = rfEnabled;

                // Default to not pulse blanked
                AgM938xOutputPulseModeEnum pulseMode = AgM938xOutputPulseModeEnum.AgM938xOutputPulseModeNotPulsed;
                // Turn RF On, pulse blanking on
                if (pulseBlankingEnableCheckBox.Checked)
                    pulseMode = AgM938xOutputPulseModeEnum.AgM938xOutputPulseModePulseOnWithTrigger;

                for (int i = 0; i < numChannels; i++) 
                    M9381[i].RF.OutputPulseMode = pulseMode;

                // Configure External Triggers, using backplane trigger
                for (int i = 0; i < numChannels; i++)
                    M9381[i].Triggers.ExternalTrigger.Configure(true, 0.01, 0.5, AgM938xTriggerSlopeEnum.AgM938xTriggerSlopePositive,
                        (AgM938xTriggerEnum)(referenceListenTrig[i] + 2), AgM938xTriggerTerminationEnum.AgM938xTriggerTermination50Ohm, 10000,
                        AgM938xTimeoutModeEnum.AgM938xTimeoutModeTimeoutAbort);
               
                // Enable modulation
                bool modEnabled = ModEnableControl.Checked;
                for (int i = 0; i < numChannels; i++) 
                    M9381[i].Modulation.Enabled = modEnabled;

                // PLL MODE to best wide offset
                for (int i = 0; i < numChannels; i++) 
                    M9381[i].Modules.Synthesizer.PLLMode = AgM938xSynthesizerPLLModeEnum.AgM938xSynthesizerPLLModeBestWideOffset;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public void closePxiHardware()
        {
            try
            {
                for (int i = 0; i < numChannels; i++)
                {
                    if (M9381[i] != null)
                        if (M9381[i].Initialized)
                        {
                            M9381[i].Close();
                            M9381[i] = null;
                        }
                }

                if (M9300 != null)
                    if (M9300.Initialized)
                    {
                        M9300.Close();
                        M9300 = null;
                    }
#if chassisSetup
                if (M9018 != null)
                    if (M9018.Initialized)
                    {
                        M9018.Close();
                        M9018 = null;
                    }

                if (M9018vsa != null)
                    if (M9018vsa.Initialized)
                    {
                        M9018vsa.Close();
                        M9018vsa = null;
                    }
#endif

                // TODO:  Do I want to close 89600 here if I started it?
#if useVSA
                if (use89600VSA)
                {
                    vsa.Title = "";		// Revert to the old title

                    if (vsaIsCreated)
                        vsa.Quit();		// Exit 89600 VSA if I started it
                }
#endif
                mInitComplete = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region Load Waveforms

        public void createSequence(ref IAgM938xEx vsg, string sequenceName, string waveformName, int numReps)
        {

            vsg.Modulation.Sequence.Remove(sequenceName);
            string zerosName = sequenceName + "zeros";

            double rmsValue = 0.0;
            double scaleFactor = 0.0;
            double sampleRate = 0.0;
            AgM938xMarkerEnum alcMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
            AgM938xMarkerEnum blankingMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
            // Recover the sample rate and RMS Value from the waveform to reuse for the zeros waveform
            vsg.Modulation.IQ.ArbInformation(waveformName, ref sampleRate, ref rmsValue,
                    ref scaleFactor, ref blankingMarker, ref alcMarker);

            createZerosWaveform(ref vsg, zerosName, sampleRate, rmsValue, scaleFactor);

            vsg.Modulation.Sequence.Create(sequenceName);

            // RMS power must be set in the sequence definition.  
            vsg.Modulation.RmsPower = rmsValue;

            vsg.Modulation.Sequence.AddStep("Step1");

            // Add a segment with the waveform we want to play
            vsg.Modulation.Sequence.AddSegment(waveformName);

            // Specify how many times to play this waveform
            vsg.Modulation.Sequence.StepRepetitions = numReps;

            vsg.Modulation.Sequence.AddStep("Step2");

            // After our desired waveform(s), play a waveform that is all 0's to turn off RF output
            vsg.Modulation.Sequence.AddSegment(zerosName);

            vsg.Modulation.Sequence.StepRepetitions = 1;

            // Play Step 2, with the zeros, forever, until the "Stop" command is issued
            vsg.Modulation.Sequence.NextStep("Step2");

            vsg.Modulation.Sequence.End();

        }

        public void loadVsgWaveform(ref IAgM938xEx vsg, string filePath, string fileName, string arbReference)
        {
            try
            {
                if (fileName.Contains(".wfm") || fileName.Contains(".SECUREWAVE"))
                {
                    // Use the driver method to load normal encrypted signal studio files
                    vsg.Modulation.IQ.UploadArbAgilentFile(arbReference, filePath + fileName);
                }
                else if (fileName.Contains(".WAVEFORM"))
                {
                    // Read Header, marker and waveform files, and format for load from array driver method
                    FileInfo fi = new FileInfo(filePath + fileName);
                    long waveformSize = fi.Length / 2;
                    // Read the waveform file (.WAVEFORM)
                    var ws = new FileStream(filePath + fileName, FileMode.Open);
                    BinaryReader wd = new BinaryReader(ws);
                    double[] waveformData = new double[waveformSize];
                    byte[] a16 = new byte[2];
                    for (int i = 0; i < waveformSize; i++)
                    {
                        // Byte swap Int16, then divide by 32768 to scale from -1 to 1
                        a16 = wd.ReadBytes(2);
                        Array.Reverse(a16);
                        waveformData[i] = (double)(BitConverter.ToInt16(a16, 0)) / 32768;
                    }
                    wd.Close();
                    ws.Close();
                    // Read the marker data from the .MARKERS file
                    string markerFileName = fileName.Replace(".WAVEFORM", ".MARKERS");
                    var ms = new FileStream(filePath + markerFileName, FileMode.Open);
                    BinaryReader md = new BinaryReader(ms);
                    byte[] markerData = new byte[waveformSize / 2];
                    for (int i = 0; i < waveformSize / 2; i++) markerData[i] = md.ReadByte();
                    md.Close();
                    ms.Close();
                    // Read the required data from the .HEADER file
                    string headerFileName = fileName.Replace(".WAVEFORM", ".HEADER");
                    var hs = new FileStream(filePath + headerFileName, FileMode.Open);
                    BinaryReader hd = new BinaryReader(hs);
                    // Header Structure:
                    // skip 50 bytes
                    // Read double for Sample rate
                    // skip 4 bytes
                    // read u8 for ALC Routing
                    // skip 1 byte
                    // read u8 for pulse routing
                    // skip 8 bytes
                    // read double for RMS value
                    // read float for scale factor
                    for (int i = 0; i < 50; i++) hd.ReadByte(); // throw these away
                    byte[] a64 = new byte[8];
                    a64 = hd.ReadBytes(8);
                    Array.Reverse(a64);
                    arbSampleRate = BitConverter.ToDouble(a64, 0);

                    for (int i = 0; i < 4; i++) hd.ReadByte(); // throw these away
                    byte markerNum = hd.ReadByte();
                    AgM938xMarkerEnum pulseMarker;
                    switch (markerNum)
                    {
                        case 1:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }

                    hd.ReadByte(); // skip 1
                    markerNum = hd.ReadByte();
                    AgM938xMarkerEnum alcMarker;
                    switch (markerNum)
                    {
                        case 1:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }

                    for (int i = 0; i < 8; i++) hd.ReadByte(); // throw these away
                    a64 = hd.ReadBytes(8);
                    Array.Reverse(a64);
                    arbRmsValue = -20 * Math.Log10(BitConverter.ToDouble(a64, 0));  // -20*Log10 of value in file
                    byte[] a32 = new byte[4];
                    a32 = hd.ReadBytes(4);
                    Array.Reverse(a32);
                    arbScale = BitConverter.ToSingle(a32, 0) / 100; // Percent in file, divide by 100
                    hd.Close();
                    hs.Close();

                    // Finally, load the waveform data to the M9381A
                    vsg.Modulation.IQ.UploadArbDoublesWithMarkers(arbReference, ref waveformData, ref markerData,
                        arbSampleRate, arbRmsValue, arbScale, pulseMarker, alcMarker);
                }
                else if (fileName.Contains(".bin"))
                {
                    // Use the files output from the signal studio waveform utility
                    // Get the number of samples
                    FileInfo fi = new FileInfo(filePath + fileName);
                    long waveformSize = fi.Length / 8;
                    // Read the waveform file (.bin)
                    var ws = new FileStream(filePath + fileName, FileMode.Open);
                    BinaryReader wd = new BinaryReader(ws);
                    double[] waveformData = new double[waveformSize];
                    for (int i = 0; i < waveformSize; i++) waveformData[i] = wd.ReadDouble();
                    wd.Close();
                    ws.Close();
                    // Read the marker data from the .MARKERS file
                    string markerFileName = fileName.Replace(".bin", ".MARKERS");
                    var ms = new FileStream(filePath + markerFileName, FileMode.Open);
                    BinaryReader md = new BinaryReader(ms);
                    byte[] markerData = new byte[waveformSize / 2];
                    for (int i = 0; i < waveformSize / 2; i++) markerData[i] = md.ReadByte();
                    md.Close();
                    ms.Close();
                    // Read the sample rate, PAR and marker routing from the .ReadMe file
                    string readMeFileName = fileName.Replace(".bin", ".ReadMe");
                    var rs = new FileStream(filePath + readMeFileName, FileMode.Open);
                    TextReader rd = new StreamReader(rs);
                    string fileString = rd.ReadLine();
                    arbSampleRate = Convert.ToDouble(fileString.Replace("Sample Rate (Hz):", "").TrimStart(" ".ToCharArray()));
                    fileString = rd.ReadLine();
                    arbRmsValue = Convert.ToDouble(fileString.Replace("RMS (dB):", "").TrimStart(" ".ToCharArray()));
                    fileString = rd.ReadLine();
                    int markerNum = Convert.ToInt32(fileString.Replace("Pulse Marker:", "").TrimStart(" ".ToCharArray()));
                    AgM938xMarkerEnum pulseMarker;
                    switch (markerNum)
                    {
                        case 1:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }

                    fileString = rd.ReadLine();
                    markerNum = Convert.ToInt32(fileString.Replace("ALC Hold Marker: ", ""));
                    AgM938xMarkerEnum alcMarker;
                    switch (markerNum)
                    {
                        case 1:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }
                    rd.Close();
                    rs.Close();

                    // Finally, load the waveform data to the M9381A
                    vsg.Modulation.IQ.UploadArbDoublesWithMarkers(arbReference, ref waveformData, ref markerData,
                        arbSampleRate, arbRmsValue, arbScale, pulseMarker, alcMarker);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public void loadShortVsgWaveform(ref IAgM938xEx vsg, string filePath, string fileName, double startTime, double timeToLoad, string arbReference)
        {
            //testStatusLabel.Text = "Loading Waveform " + fileName;
            try
            {
                if (fileName.Contains(".wfm") || fileName.Contains(".SECUREWAVE"))
                {
                    Exception ex = new Exception("Can not load short version of Signal Studio Waveform");
                    throw (ex);
                }
                else if (fileName.Contains(".WAVEFORM"))
                {
                    // Read Header, marker and waveform files, and format for load from array driver method
                    // Read the required data from the .HEADER file
                    string headerFileName = fileName.Replace(".WAVEFORM", ".HEADER");
                    var hs = new FileStream(filePath + headerFileName, FileMode.Open);
                    BinaryReader hd = new BinaryReader(hs);
                    // Header Structure:
                    // skip 50 bytes
                    // Read double for Sample rate
                    // skip 4 bytes
                    // read u8 for ALC Routing
                    // skip 1 byte
                    // read u8 for pulse routing
                    // skip 8 bytes
                    // read double for RMS value
                    // read float for scale factor
                    for (int i = 0; i < 50; i++) hd.ReadByte(); // throw these away
                    byte[] a64 = new byte[8];
                    a64 = hd.ReadBytes(8);
                    Array.Reverse(a64);
                    arbSampleRate = BitConverter.ToDouble(a64, 0);

                    for (int i = 0; i < 4; i++) hd.ReadByte(); // throw these away
                    byte markerNum = hd.ReadByte();
                    AgM938xMarkerEnum pulseMarker;
                    switch (markerNum)
                    {
                        case 1:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }

                    hd.ReadByte(); // skip 1
                    markerNum = hd.ReadByte();
                    AgM938xMarkerEnum alcMarker;
                    switch (markerNum)
                    {
                        case 1:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }

                    for (int i = 0; i < 8; i++) hd.ReadByte(); // throw these away
                    a64 = hd.ReadBytes(8);
                    Array.Reverse(a64);
                    arbRmsValue = -20 * Math.Log10(BitConverter.ToDouble(a64, 0));  // -20*Log10 of value in file
                    byte[] a32 = new byte[4];
                    a32 = hd.ReadBytes(4);
                    Array.Reverse(a32);
                    arbScale = BitConverter.ToSingle(a32, 0) / 100; // Percent in file, divide by 100
                    hd.Close();
                    hs.Close();

                    FileInfo fi = new FileInfo(filePath + fileName);
                    long waveformSize = fi.Length / 2;
                    double waveformTime = waveformSize / arbSampleRate;
                    //double waveformStartTime = startTime / arbSampleRate;
                    if (waveformTime < timeToLoad + startTime)
                    {
                        Exception ex = new Exception("Waveform shorter than requested time");
                        throw (ex);
                    }
                    waveformSize = (int)(timeToLoad * arbSampleRate * 2);
                    int samplesToSkip = (int)(startTime * arbSampleRate * 2);
                    // Make sure to skip multiple of 2 samples
                    //if (samplesToSkip % 2 == 1) samplesToSkip++;

                    // Read the waveform file (.bin)
                    var ws = new FileStream(filePath + fileName, FileMode.Open);
                    BinaryReader wd = new BinaryReader(ws);
                    double[] waveformData = new double[waveformSize];
                    // Skip the beginning
                    for (int i = 0; i < samplesToSkip; i++) wd.ReadDouble(); // throw these away
                    byte[] a16 = new byte[2];
                    for (int i = 0; i < waveformSize; i++)
                    {
                        // Byte swap Int16, then divide by 32768 to scale from -1 to 1
                        a16 = wd.ReadBytes(2);
                        Array.Reverse(a16);
                        waveformData[i] = (double)(BitConverter.ToInt16(a16, 0)) / 32768;
                    }
                    wd.Close();
                    ws.Close();
                    // Read the marker data from the .MARKERS file
                    string markerFileName = fileName.Replace(".WAVEFORM", ".MARKERS");
                    var ms = new FileStream(filePath + markerFileName, FileMode.Open);
                    BinaryReader md = new BinaryReader(ms);
                    byte[] markerData = new byte[waveformSize / 2];
                    for (int i = 0; i < waveformSize / 2; i++) markerData[i] = md.ReadByte();
                    md.Close();
                    ms.Close();
                    // Finally, load the waveform data to the M9381A
                    vsg.Modulation.IQ.UploadArbDoublesWithMarkers(arbReference + "Short", ref waveformData, ref markerData,
                        arbSampleRate, arbRmsValue, arbScale, pulseMarker, alcMarker);
                }
                else if (fileName.Contains(".bin"))
                {
                    // Read the sample rate, PAR and marker routing from the .ReadMe file
                    string readMeFileName = fileName.Replace(".bin", ".ReadMe");
                    var rs = new FileStream(filePath + readMeFileName, FileMode.Open);
                    TextReader rd = new StreamReader(rs);
                    string fileString = rd.ReadLine();
                    arbSampleRate = Convert.ToDouble(fileString.Replace("Sample Rate (Hz):", "").TrimStart(" ".ToCharArray()));
                    fileString = rd.ReadLine();
                    arbRmsValue = Convert.ToDouble(fileString.Replace("RMS (dB):", "").TrimStart(" ".ToCharArray()));
                    fileString = rd.ReadLine();
                    int markerNum = Convert.ToInt32(fileString.Replace("Pulse Marker:", "").TrimStart(" ".ToCharArray()));
                    AgM938xMarkerEnum pulseMarker;
                    switch (markerNum)
                    {
                        case 1:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            pulseMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }

                    fileString = rd.ReadLine();
                    markerNum = Convert.ToInt32(fileString.Replace("ALC Hold Marker: ", ""));
                    AgM938xMarkerEnum alcMarker;
                    switch (markerNum)
                    {
                        case 1:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker1;
                            break;
                        case 2:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker2;
                            break;
                        case 3:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker3;
                            break;
                        case 4:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarker4;
                            break;
                        default:
                            alcMarker = AgM938xMarkerEnum.AgM938xMarkerNone;
                            break;
                    }
                    rd.Close();
                    rs.Close();

                    // Use the files output from the signal studio waveform utility
                    // Get the number of samples
                    FileInfo fi = new FileInfo(filePath + fileName);
                    long waveformSize = fi.Length / 8;
                    double waveformTime = waveformSize / arbSampleRate;
                    //double waveformStartTime = startTime / arbSampleRate;
                    if (waveformTime < timeToLoad + startTime)
                    {
                        Exception ex = new Exception("Waveform shorter than requested time");
                        throw (ex);
                    }
                    waveformSize = (int)(timeToLoad * arbSampleRate * 2);
                    int samplesToSkip = (int)(startTime * arbSampleRate * 2);
                    // Make sure to skip multiple of 2 samples
                    //if (samplesToSkip % 2 == 1) samplesToSkip++;

                    // Read the waveform file (.bin)
                    var ws = new FileStream(filePath + fileName, FileMode.Open);
                    BinaryReader wd = new BinaryReader(ws);
                    double[] waveformData = new double[waveformSize];
                    // Skip the beginning
                    for (int i = 0; i < samplesToSkip; i++) wd.ReadDouble(); // throw these away
                    for (int i = 0; i < waveformSize; i++) waveformData[i] = wd.ReadDouble();
                    wd.Close();
                    ws.Close();
                    // Read the marker data from the .MARKERS file
                    string markerFileName = fileName.Replace(".bin", ".MARKERS");
                    var ms = new FileStream(filePath + markerFileName, FileMode.Open);
                    BinaryReader md = new BinaryReader(ms);
                    byte[] markerData = new byte[waveformSize / 2];
                    for (int i = 0; i < waveformSize / 2; i++) markerData[i] = md.ReadByte();
                    md.Close();
                    ms.Close();
                    // Finally, load the waveform data to the M9381A
                    vsg.Modulation.IQ.UploadArbDoublesWithMarkers(arbReference + "Short", ref waveformData, ref markerData,
                        arbSampleRate, arbRmsValue, arbScale, pulseMarker, alcMarker);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        private void monitorButton_Click(object sender, EventArgs e)
        {
            //vsgMonitor myMonitor = new vsgMonitor(M9381);

        }

        private void scaleOffsetBox_TextChanged(object sender, EventArgs e)
        {

        }

        private void M9300ResourceStringBox_TextChanged(object sender, EventArgs e)
        {

        }

        private void radioButton4_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void groupBox1_Enter(object sender, EventArgs e)
        {
            //stopPlayback();
            //Freq2MHzControl.Enabled = false;
            //Freq3MHzControl.Enabled = false;
            //Freq4MHzControl.Enabled = false;
            //if (wf1RadioButton.Checked)
            //    mWaveformHandle = "WF1";
            //else if (wf2RadioButton.Checked)
            //    mWaveformHandle = "WF2";
            //else if (wf3RadioButton.Checked)
            //    mWaveformHandle = "WF3";
            //else if (wf4RadioButton.Checked)
            //    mWaveformHandle = "WF4";
            //else if (wf5RadioButton.Checked)
            //    mWaveformHandle = "WF5";
            //else if (wf6RadioButton.Checked)
            //    mWaveformHandle = "WF6";
            //else if (wf7RadioButton.Checked)
            //    mWaveformHandle = "WF7";
            //else if (wf8RadioButton.Checked)
            //    mWaveformHandle = "WF8";
            //else if (wf9RadioButton.Checked)
            //{
            //    if (numChannels > 1)
            //        Freq2MHzControl.Enabled = true;
            //    if (numChannels > 2)
            //        Freq3MHzControl.Enabled = true;
            //    if (numChannels > 3)
            //        Freq4MHzControl.Enabled = true;
            //    mWaveformHandle = "WF9";
                
            //}
            //else if (wf10RadioButton.Checked)
            //{
            //    if (numChannels > 1)
            //        Freq2MHzControl.Enabled = true;
            //    if (numChannels > 2)
            //        Freq3MHzControl.Enabled = true;
            //    if (numChannels > 3)
            //        Freq4MHzControl.Enabled = true;
            //    mWaveformHandle = "user";           
            //}
            //if (mWaveformHandle != "user" && mWaveformHandle != "WF9")
            //{
            //    if (numChannels > 1)
            //        Freq2MHzControl.Value = FreqMHzControl.Value;
            //    if (numChannels > 2)
            //        Freq3MHzControl.Value = FreqMHzControl.Value;
            //    if (numChannels > 3)
            //        Freq4MHzControl.Value = FreqMHzControl.Value;
            //    readGuiControls();
            //}
            //if (mWaveformHandle == "WF9")
            //{
            //    if (numChannels > 1)
            //        Freq2MHzControl.Value = FreqMHzControl.Value + 300;
            //    readGuiControls();
            //}
            //// User must press "Play Waveform" button to start playback
            ////if (ModEnableControl.Checked)
            ////    playWaveform();
        }

        private void wfFileChan1Box_TextChanged(object sender, EventArgs e)
        {

        }

        private void AnalogBox_Enter(object sender, EventArgs e)
        {

        }

        private void label20_Click(object sender, EventArgs e)
        {

        }

        private void playWaveformButtonClicked(object sender, EventArgs e)
        {
            if (mInitComplete && ModEnableControl.Checked && RfEnableControl.Checked)
            {
                playWaveform();
            }
        }

        private void numChannelsChanged(object sender, EventArgs e)
        {
            //numChannels = (int) numChannelsControl.Value;
            setupForNumChannels();
        }

        private void vsaEnableChanged(object sender, EventArgs e)
        {
#if chassisSetup
            mVSAChassisEnabled = vsaChassisEnableCheckBox.Checked;
#endif
            setupForNumChannels();
        }

        private void Label2_Click(object sender, EventArgs e)
        {

        }

        private void enableDisplay(bool enableDisplay)
        {
#if useVSA
            if (use89600VSA)
            {
                if (vsa != null)
                    vsa.IsVisible = enableDisplay;
            }
#endif
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            enableDisplay(vsaDisplayEnableCheckBox.Checked);
        }

        private void playbackModeChanged(object sender, EventArgs e)
        {
            if (continuousRadioButton.Checked)
            {
                waveformListBox.Enabled = true;
                sequenceListBox.Enabled = false;
            }
            else
            {
                sequenceListBox.Enabled = true;
                waveformListBox.Enabled = false;
            }
        }

        private void repsChanged(object sender, EventArgs e)
        {
            loadWaveforms();
        }

    }
}
