public static void OrxCaptureTest([Values(Mykonos.OBSRXCHANNEL.OBS_RX1_TXLO, Mykonos.OBSRXCHANNEL.OBS_RX2_TXLO)] Mykonos.OBSRXCHANNEL channel, [Values(-20)] int amp_dbm, [Values(10000)] int IQExptVal) { //Retrieve Profile Information, samplingFreq_Hz, ProfileBW, LO Frequency Information double[] profileInfo = new double[3]; profileInfo[0] = settings.rxProfileData.IqRate_kHz; profileInfo[1] = settings.rxPllLoFreq_Hz; profileInfo[2] = settings.rxProfileData.PrimarySigBw_Hz; double samplingFreq_Hz = profileInfo[0] * 1000; double profileBW_MHz = profileInfo[2] / 1000000; Console.WriteLine("Rx Sampling Freq (Hz): " + samplingFreq_Hz); Console.WriteLine("Rx Profile Bandwdith (MHz): " + profileBW_MHz); double freqLo_kHz = profileInfo[1] / 1000; Console.WriteLine("Rx LO Frequency (kHz): " + freqLo_kHz); //Define Receiver Test Signal to be 10MHz Offset from LO frequency double testSigFreq_MHz = (freqLo_kHz / 1000 + 10); int amplitude_dBm = amp_dbm; Console.WriteLine("Rx Test Signal Freq (MHz): " + testSigFreq_MHz); //Define DataCapture Parameters const int NUM_SAMPLES = 8192; short[] rxDataArray = new short[NUM_SAMPLES * 2]; double[,] timeDomainData = new double[NUM_SAMPLES / 2, 3]; //Generate Test Signal for Rx Capture with ESG SG_AgilentESG esg = new SG_AgilentESG(measEquipment.ESGAddress); Console.WriteLine("ESG Info:" + esg.Identify()); Console.WriteLine("ESG Address :" + measEquipment.ESGAddress); Console.WriteLine("ESG Generating Tone Freq:" + testSigFreq_MHz); Console.WriteLine("ESG Generating Tone Amp:" + amplitude_dBm); esg.SetFrequency(testSigFreq_MHz); esg.SetAmplitude(amp_dbm); esg.SetRfOutput(true); //Enable Mykonos Rx Datapath AdiCommandServerClient Link = AdiCommandServerClient.Instance; Link.hw.Connect(TestSetupConfig.ipAddr, TestSetupConfig.port); //Link.Mykonos.setEnsmState(Mykonos.ENSM_STATE.TX_RX); //Link.Mykonos.powerUpRxPath(channel); Link.Mykonos.radioOn(); Link.Mykonos.setObsRxPathSource(channel); Link.Disconnect(); System.Threading.Thread.Sleep(1000); //Retrieve Rx Data from FPGA rxDataArray = Helper.MykonosOrxCapture(channel, NUM_SAMPLES); //Frequency Domain Data Processing AdiMath.FftAnalysis analysisData = new AdiMath.FftAnalysis(); double samplingFreq_MHz = samplingFreq_Hz / 1000000; byte sampleBitWidth = 16; double[] data = AdiMath.complexfftAndScale(rxDataArray, samplingFreq_MHz, sampleBitWidth, true, out analysisData); //Define the 2D array to store frequency bins corresponding to fft data double[,] fftFreqAmp = new double[data.Length, 2]; double binSize = (samplingFreq_MHz / NUM_SAMPLES); double minFreq = samplingFreq_MHz / 2 * (-1); for (int i = 0; i < data.Length; i++) { fftFreqAmp[i, 0] = minFreq + (binSize * 2 * i); fftFreqAmp[i, 1] = data[i]; } //Time Domain Data Processing int numSamplesDiv2 = (int)NUM_SAMPLES / 2; for (int i = 0; i < numSamplesDiv2; i++) { timeDomainData[i, 0] = i; timeDomainData[i, 1] = rxDataArray[2 * i]; timeDomainData[i, 2] = rxDataArray[2 * i + 1]; } var IMin = System.Linq.Enumerable.Range(0, numSamplesDiv2).Select(i => timeDomainData[i, 1]).Min(); var IMax = System.Linq.Enumerable.Range(0, numSamplesDiv2).Select(i => timeDomainData[i, 1]).Max(); var QMin = System.Linq.Enumerable.Range(0, numSamplesDiv2).Select(i => timeDomainData[i, 2]).Min(); var QMax = System.Linq.Enumerable.Range(0, numSamplesDiv2).Select(i => timeDomainData[i, 2]).Max(); Console.WriteLine("I Max, Min:" + IMax.ToString() + "," + IMin.ToString()); Console.WriteLine("Q Max, Min:" + QMax.ToString() + "," + QMin.ToString()); #if WR_RES_TO_PDF string path = RxRfTests.ResPath + "Rx_FFT_TimeDomain_Plots"; if (channel == Mykonos.OBSRXCHANNEL.OBS_RX1_TXLO) { path = path + "ORX1"; } else { path = path + "ORX2"; } string[] timeLabels = new string[] { "Time Domain Response of " + channel.ToString(), "Sample Number", "ADC Codes", "I data", "Q data" }; string[] fftLabels = new string[] { "Frequency Domain Response of " + channel.ToString(), "Frequency (MHz)", "Amplitude (dBFS)", "FFT DATA" }; // Should be >=4 long. var doc1 = new Document(); iTextSharp.text.Image[] container = new iTextSharp.text.Image[2]; container[0] = Helper.MakeChartObject(timeDomainData, timeLabels, path); container[1] = Helper.MakeChartObject(fftFreqAmp, fftLabels, path); string[] pcbInfo; pcbInfo = Helper.PcbInfo((settings.txPllLoFreq_Hz / 1000000.0).ToString(), (settings.rxPllLoFreq_Hz / 1000000.0).ToString(), settings.mykSettings.txProfileName, settings.mykSettings.rxProfileName, "N/A", "N/A"); Helper.AddAllChartsToPdf(container, path + ".pdf", pcbInfo); // open result pdf System.Diagnostics.Process.Start(path + ".pdf"); #endif // open result pdf System.Diagnostics.Process.Start(path + ".pdf"); /* * NUnit.Framework.Assert.Greater(IMin, ((-1) * (IQExptVal + ((IQExptVal * 10) / 100)))); * NUnit.Framework.Assert.Less(IMin, (IQExptVal * (-1))); * NUnit.Framework.Assert.Less(IMax, ((IQExptVal + ((IQExptVal * 10) / 100)))); * NUnit.Framework.Assert.Greater(IMax, IQExptVal); * * NUnit.Framework.Assert.Greater(QMin, ((-1) * (IQExptVal + ((IQExptVal * 10) / 100)))); * NUnit.Framework.Assert.Less(QMin, (IQExptVal * (-1))); * NUnit.Framework.Assert.Less(QMax, ((IQExptVal + ((IQExptVal * 10) / 100)))); * NUnit.Framework.Assert.Greater(QMax, IQExptVal); */ NUnit.Framework.Assert.Greater(IMax, 5000); NUnit.Framework.Assert.Greater(QMax, 5000); }
public static void ORxGainSweep([Values(Mykonos.OBSRXCHANNEL.OBS_RX1_TXLO, Mykonos.OBSRXCHANNEL.OBS_RX2_TXLO)] Mykonos.OBSRXCHANNEL channel) { //Initialize param structure with Hardcoded Values double[] profileInfo = Helper.SetOrxProfileInfo(channel); double samplingFreq_MHz = profileInfo[0] / 1000; double freqLo_MHz = profileInfo[1] / 1000000; double profileBW_MHz = profileInfo[2] / 1000000; double testFreq = 2510; double amplitude_dBm = -20; string[] pcbInfo; //TODO: Hard coded, may want to read the gain tables instead if custom ones are loaded //Number of known indicies in the gain index table. //Should a customer provide a custom gain table, we should determine the number of valid gain indicies // and this array size should correspond to that number. int numIndices = 19; double[,] amplitudeData = new double[numIndices, 3]; double[,] amplitudeDiffData = new double[numIndices - 1, 2]; short[] rxDataArray = new short[16384]; Console.WriteLine("Detected LO Frequency: " + freqLo_MHz); Console.WriteLine("Profile BW: " + profileBW_MHz); switch (channel) { case Mykonos.OBSRXCHANNEL.OBS_RX1_TXLO: case Mykonos.OBSRXCHANNEL.OBS_RX2_TXLO: testFreq = freqLo_MHz + 10; break; case Mykonos.OBSRXCHANNEL.OBS_SNIFFER_A: case Mykonos.OBSRXCHANNEL.OBS_SNIFFER_B: case Mykonos.OBSRXCHANNEL.OBS_SNIFFER_C: testFreq = freqLo_MHz + 5; amplitude_dBm = -30; break; } //ESG Configuration SG_AgilentESG esg = new SG_AgilentESG(measEquipment.ESGAddress); Console.WriteLine(measEquipment.ESGAddress); Console.WriteLine(esg.Identify()); esg.SetFrequency(testFreq); esg.SetAmplitude(amplitude_dBm); esg.SetRfOutput(true); //Test Sequence byte gainIndex = 255; AdiCommandServerClient Link = AdiCommandServerClient.Instance; AdiMath.FftAnalysis analysisData = new AdiMath.FftAnalysis(); for (int i = 0; i < (numIndices + 1); i++) { try { Link.hw.Connect(TestSetupConfig.ipAddr, TestSetupConfig.port); Link.spiWrite(0x4F1, 0x80); gainIndex = (byte)(255 - i); Console.WriteLine("Initial gain index = " + Link.Mykonos.getObsRxGain()); Link.Mykonos.setObsRxManualGain(channel, gainIndex); //There is currently an error in the API. Console.WriteLine("Set gain index = " + gainIndex); System.Threading.Thread.Sleep(100); } catch (Exception e) { //Console.WriteLine("Invalid Gain index reached" + i); //Need to figure out a better way to exit the loop when invalid gain reached Console.WriteLine(e); break; } finally { Link.Disconnect(); } rxDataArray = Helper.MykonosOrxCapture(channel, 8192); //Grab data from the FPGA byte sampleBitWidth = 16; double[] data = AdiMath.complexfftAndScale(rxDataArray, samplingFreq_MHz, sampleBitWidth, true, out analysisData); amplitudeData[i, 0] = (double)gainIndex; amplitudeData[i, 1] = analysisData.FundamentalPower_dBFS; if (i == 0) { amplitudeData[i, 2] = analysisData.FundamentalPower_dBFS; } else { amplitudeData[i, 2] = amplitudeData[i - 1, 2] - 1; amplitudeDiffData[i - 1, 0] = (double)gainIndex; amplitudeDiffData[i - 1, 1] = amplitudeData[i - 1, 1] - amplitudeData[i, 1]; Console.WriteLine(" Gain index :" + amplitudeDiffData[i - 1, 0]); Console.WriteLine(" Differential Amplitude" + amplitudeDiffData[i - 1, 1]); } } #if WR_RES_TO_PDF string path = ObsRxRfTests.ResPath + "ORxGainSweep"; if (channel == Mykonos.OBSRXCHANNEL.OBS_RX1_TXLO) { path = path + "OBS_RX1_TXLO"; } else { path = path + "OBS_RX2_TXLO"; } var doc1 = new Document(); iTextSharp.text.Image[] container = new iTextSharp.text.Image[2]; string[] timeLabels = new string[] { "Rx Gain Sweep versus Amplitude for " + channel.ToString(), "Gain Index (byte)", "Amplitude (dBFS)", "Amplitude: " + amplitude_dBm + "dBm", "Perfect 1dB Gain Index Steps" }; string[] timeLabels2 = new string[] { "Difference between consecutive gain entries " + channel.ToString(), "Gain Index", "Amplitude delta (dB, comparing A(n + 1) - A(n))", "Amplitude: " + amplitude_dBm + "dBm" }; pcbInfo = Helper.PcbInfo(); container[0] = Helper.MakeChartObject(amplitudeData, timeLabels, path); container[1] = Helper.MakeChartObject(amplitudeDiffData, timeLabels2, path + "2"); Helper.AddAllChartsToPdf(container, path + ".pdf", pcbInfo); //Open Result PDF System.Diagnostics.Process.Start(path + ".pdf"); for (int i = 1; i < (numIndices); i++) { NUnit.Framework.Assert.IsTrue(((amplitudeDiffData[i - 1, 1] < 1) && (amplitudeDiffData[i - 1, 1] > 0))); } #endif }
public static void ORxPassbandSweep([Values(Mykonos.OBSRXCHANNEL.OBS_RX1_TXLO, Mykonos.OBSRXCHANNEL.OBS_RX2_TXLO)] Mykonos.OBSRXCHANNEL channel) { //Retrieve Profile Information, samplingFreq_Hz, ProfileBW, LO Frequency Information double[] profileInfo = new double[3]; profileInfo[0] = settings.rxProfileData.IqRate_kHz; profileInfo[1] = settings.rxPllLoFreq_Hz; profileInfo[2] = settings.rxProfileData.PrimarySigBw_Hz; double samplingFreq_MHz = profileInfo[0] / 1000; double profileBW_MHz = profileInfo[2] / 1000000; Console.WriteLine("Rx Sampling Freq (MHz): " + samplingFreq_MHz); Console.WriteLine("Rx Profile Bandwdith (MHz): " + profileBW_MHz); double freqLo_MHz = profileInfo[1] / 1000000; Console.WriteLine("Rx LO Frequency (MHz): " + freqLo_MHz); //Define Test Parameters Based on Profile Info & Lo Frequency //Allow for testing 50% over & under PassBand //Hard coded values for amplitude & Frequency Setups settings const int NUM_SAMPLES = 8192; double SwpSigAmp = -20; double SwpMinFreq = freqLo_MHz - (profileBW_MHz / 2) * 1.5; double SwpMaxFreq = freqLo_MHz + (profileBW_MHz / 2) * 1.5; int SwpNumSteps = 150; SwpParamStruct param = new SwpParamStruct(SwpMinFreq, SwpMaxFreq, SwpSigAmp, SwpNumSteps); Console.WriteLine("SwpMinFreq (MHz): " + SwpMinFreq); Console.WriteLine("SwpMaxMax (MHz): " + SwpMaxFreq); Console.WriteLine("SwpSigAmp (MHz): " + SwpSigAmp); //Define Data Array for storing Fundamental short[] rxDataArray = new short[16384]; double[,] outputData = new double[param.numSteps, 4]; string[] pcbInfo; AdiMath.FftAnalysis analysisData = new AdiMath.FftAnalysis(); //Configure Signal Generator SG_AgilentESG sigGen = new SG_AgilentESG(measEquipment.ESGAddress); Console.WriteLine(sigGen.Identify()); sigGen.SetFrequency(param.freqMin); sigGen.SetAmplitude(param.amplitude); sigGen.SetRfOutput(true); //Enable Mykonos Rx Datapath AdiCommandServerClient Link = AdiCommandServerClient.Instance; Link.hw.Connect(TestSetupConfig.ipAddr, TestSetupConfig.port); //Link.Mykonos.setEnsmState(Mykonos.ENSM_STATE.TX_RX); //Link.Mykonos.powerUpRxPath(channel); Link.Mykonos.radioOn(); Link.Disconnect(); //Test Sequence //Sweep Thru Rx Passband & Capture Data //Capture Received data from FPGA //Process Sampled Data to Determine //Fundemental Frequency Detected (MHz) //Fundamental Power of Signal (dBFS) //Image Power(dBFS) for (int i = 0; i < param.numSteps; i++) { double test_freq = param.freqMin + i * (param.freqMax - param.freqMin) / param.numSteps; sigGen.SetFrequency(test_freq); System.Threading.Thread.Sleep(100); rxDataArray = Helper.MykonosOrxCapture(channel, NUM_SAMPLES); byte sampleBitWidth = 16; double[] fftMagnitudeData = AdiMath.complexfftAndScale(rxDataArray, samplingFreq_MHz, sampleBitWidth, true, out analysisData); outputData[i, 0] = test_freq; //outputData[i, 0] = analysisData.FundamentalFrequency_MHz; outputData[i, 1] = analysisData.FundamentalPower_dBFS; outputData[i, 2] = analysisData.ImagePower_dBFS; outputData[i, 3] = analysisData.DcOffset_dBFS; } string path = RxRfTests.ResPath + "RxPassbandSweep"; if (channel == Mykonos.OBSRXCHANNEL.OBS_RX1_TXLO) { path = path + "RX1"; } else { path = path + "RX2"; } #if WR_RES_TO_PDF var doc1 = new Document(); iTextSharp.text.Image[] container = new iTextSharp.text.Image[1]; string[] timeLabels = new string[] { "FFT Statistics versus CW Input Frequency for " + channel.ToString(), "CW Input Frequency (MHz)", "Amplitude (dBFS)", "Fundamental Tone", "Image Amplitude", "DC Offset Amplitude" }; pcbInfo = Helper.PcbInfo((settings.txPllLoFreq_Hz / 1000000.0).ToString(), (settings.rxPllLoFreq_Hz / 1000000.0).ToString(), settings.mykSettings.txProfileName, settings.mykSettings.rxProfileName, "N/A", "N/A"); container[0] = Helper.MakeChartObject(outputData, timeLabels, path); Helper.AddAllChartsToPdf(container, path + ".pdf", pcbInfo); //Open Result PDF System.Diagnostics.Process.Start(path + ".pdf"); #endif #if WR_RES_TO_TXT // Write data to txt file using (System.IO.StreamWriter file = new System.IO.StreamWriter(path + ".txt")) { file.WriteLine("Sample, Frequency MHz, Fundamental Power(dBFS), Image Power(dBFS), DC Offset(dBFS)"); for (int i = 0; i < param.numSteps; i++) { file.WriteLine(i + "," + outputData[i, 0].ToString() + "," + outputData[i, 1].ToString() + "," + outputData[i, 2].ToString() + "," + outputData[i, 3].ToString()); } } #endif //Check Min Max Fund Amplitudes are within 0.5db of each other. //var MinFundPower_dBFS = System.Linq.Enumerable.Range(50, 100).Select(i => outputData[i, 1]).Min(); //var MaxFundPower_dBFS = System.Linq.Enumerable.Range(50, 100).Select(i => outputData[i, 1]).Max(); double MinFundPower_dBFS = outputData[50, 1]; double MaxFundPower_dBFS = outputData[50, 1]; for (int i = 50; i < 100; i++) { if (outputData[i, 1] < MinFundPower_dBFS) { MinFundPower_dBFS = outputData[i, 1]; } if (outputData[i, 1] > MaxFundPower_dBFS) { MaxFundPower_dBFS = outputData[i, 1]; } } Console.WriteLine("MinFundAmp: " + MinFundPower_dBFS); Console.WriteLine("MaxFundAmp: " + MaxFundPower_dBFS); Console.WriteLine("MaxDiffFundAmp: " + (MaxFundPower_dBFS - MinFundPower_dBFS)); NUnit.Framework.Assert.IsTrue((MaxFundPower_dBFS - MinFundPower_dBFS) <= 0.5); }