diff --git a/Examples/LTE_NanosemiDPD_EVM_ACP_UL/App.config b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.cs b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.cs
new file mode 100644
index 0000000..dcc0c8e
--- /dev/null
+++ b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.cs
@@ -0,0 +1,198 @@
+using NationalInstruments.ModularInstruments.NIRfsg;
+using NationalInstruments.RFmx.InstrMX;
+using NationalInstruments.RFmx.LteMX;
+using NationalInstruments.RFmx.SpecAnMX;
+using System;
+using static NationalInstruments.ReferenceDesignLibraries.SA.RFmxLTE;
+using static NationalInstruments.ReferenceDesignLibraries.SG;
+
+namespace NationalInstruments.ReferenceDesignLibraries.Examples
+{
+ public class LTE_NanosemiDPD_EVM_ACP_UL
+ {
+ #region Declaring Parameters
+ //shared Parameters
+ public string resourceName;
+ public double centerFrequency;
+ public string signalStringSpecan, signalStringLte;
+ public string resultStringSpecan, resultStringLte;
+
+ //Generator Configuration
+ public SG.InstrumentConfiguration SgInstrConfig;
+
+ public string filePath;
+
+ //Analyzer Configuration
+ public SA.RFmxInstr.InstrumentConfiguration saInstrConfig;
+ public SA.CommonConfiguration saCommonConfig;
+ public SA.AutoLevelConfiguration saAutolevelConfig;
+
+ public SA.RFmxLTE.StandardConfiguration StandardConfigLte = new SA.RFmxLTE.StandardConfiguration();
+
+
+ //Measurements Configuration
+ public SA.RFmxLTE.AcpConfiguration AcpConfigLte;
+ public SA.RFmxLTE.AcpResults AcpResultsLte = new SA.RFmxLTE.AcpResults();
+
+ public SA.RFmxLTE.ModAccConfiguration ModaccConfigLte;
+ public SA.RFmxLTE.ModAccResults ModaccResultsLte = new SA.RFmxLTE.ModAccResults();
+
+ //Methods Configuration
+ public Methods.NanosemiDPD.NanosemiDPDConfiguration nsDPDConfig;
+ public Methods.NanosemiDPD.PreDpdCrestFactorReductionConfiguration preDpdCrestFactorReductionConfig;
+ public bool EnableDpd;
+ #endregion
+
+ public LTE_NanosemiDPD_EVM_ACP_UL()
+ {
+ InitializeParameters();
+ }
+
+ public void InitializeParameters()
+ {
+ //shared Parameters
+ centerFrequency = 1.95e9; //Hz
+ resourceName = "5840";
+ filePath = @"C:\Users\Public\Documents\National Instruments\RFIC Test Software\Waveforms\LTE_FDD_UL_1x20MHz_256QAM_OS4.tdms";
+ signalStringSpecan = "specanSig0";
+ signalStringLte = "lteSig0";
+ resultStringSpecan = "specanResult0";
+ resultStringLte = "lteResult0";
+
+ //Generator Configuiration
+ SgInstrConfig = SG.InstrumentConfiguration.GetDefault();
+ SgInstrConfig.CarrierFrequency_Hz = centerFrequency;
+ SgInstrConfig.DutAverageInputPower_dBm = -10.0;
+ SgInstrConfig.ExternalAttenuation_dB = 0;
+
+ //Analyzer Configuration
+ saInstrConfig = SA.RFmxInstr.InstrumentConfiguration.GetDefault();
+ saCommonConfig = SA.CommonConfiguration.GetDefault();
+ saCommonConfig.ExternalAttenuation_dB = 0;
+ saCommonConfig.CenterFrequency_Hz = centerFrequency;
+ saCommonConfig.ReferenceLevel_dBm = 0;
+
+ saAutolevelConfig = SA.AutoLevelConfiguration.GetDefault();
+ saAutolevelConfig.Enabled = true;
+
+
+ StandardConfigLte = SA.RFmxLTE.StandardConfiguration.GetDefault();
+ StandardConfigLte.ComponentCarrierConfigurations[0].Bandwidth_Hz = 20.0e6;
+ StandardConfigLte.ComponentCarrierConfigurations[0].PuschModulationType = RFmxLteMXPuschModulationType.ModulationType256Qam;
+
+ AcpConfigLte = SA.RFmxLTE.AcpConfiguration.GetDefault();
+
+ ModaccConfigLte = SA.RFmxLTE.ModAccConfiguration.GetDefault();
+
+ //Methods Configuration
+ nsDPDConfig = Methods.NanosemiDPD.NanosemiDPDConfiguration.GetDefault();
+ nsDPDConfig.DpdConfiguration = NanoSemiLinearizer.Interop.nstdpd.DpdGetDefaultConfig();
+ nsDPDConfig.NumberOfIterations = 3;
+ nsDPDConfig.DpdConfiguration.lvl = NanoSemiLinearizer.Interop.nstdpd.DpdLevel.NST_DPD_LEVEL0;
+ nsDPDConfig.DpdConfiguration.rho = 0.1f;
+ nsDPDConfig.DpdConfiguration.training_samples = 25000;
+ EnableDpd = true;
+
+ }
+
+ public void Run()
+ {
+ #region Create Sessions
+ NIRfsg nIRfsg = new NIRfsg(resourceName, false, false);
+ RFmxInstrMX instr = new RFmxInstrMX(resourceName, "");
+ RFmxSpecAnMX specAn = instr.GetSpecAnSignalConfiguration(signalStringSpecan);
+ RFmxLteMX lte = instr.GetLteSignalConfiguration(signalStringLte);
+ #endregion
+
+ #region Configure Generation
+ ConfigureInstrument(nIRfsg, SgInstrConfig);
+ Waveform waveform = LoadWaveformFromTDMS(filePath);
+
+ DownloadWaveform(nIRfsg, waveform);
+ ConfigureContinuousGeneration(nIRfsg, waveform);
+ nIRfsg.Initiate();
+ #endregion
+
+ #region Configure Analyzer
+ saAutolevelConfig.MeasurementInterval_s = waveform.BurstLength_s;
+ SA.RFmxInstr.ConfigureInstrument(instr, saInstrConfig);
+
+ SA.RFmxSpecAn.ConfigureCommon(specAn, saCommonConfig);
+
+
+ SA.RFmxLTE.ConfigureCommon(lte, saCommonConfig);
+ SA.RFmxLTE.ConfigureStandard(lte, StandardConfigLte);
+ #endregion
+
+ #region Configure and Measure DPD
+ if (EnableDpd)
+ {
+ Methods.NanosemiDPD.ConfigureNanosemi(specAn, nsDPDConfig, waveform, "");
+ Console.WriteLine("\n--------------- Measurement Results with DPD --------------\n");
+ Methods.NanosemiDPD.PerformNanosemiDPD(specAn, nIRfsg, waveform, nsDPDConfig, "");
+ }
+ else
+ {
+ Console.WriteLine("\n------------- Measurement Results without DPD -------------\n");
+ }
+ #endregion
+
+ #region Measure
+
+ ConfigureAcp(lte, AcpConfigLte);
+ RFmxLteMXMeasurementTypes[] lteMeasurements = new RFmxLteMXMeasurementTypes[1] { RFmxLteMXMeasurementTypes.Acp };
+ SA.RFmxLTE.SelectAndInitiateMeasurements(lte, lteMeasurements, saAutolevelConfig, false, "", resultStringLte);
+ AcpResultsLte = FetchAcp(lte, RFmxLteMX.BuildResultString(resultStringLte));
+ PrintACPResults();
+
+ ConfigureModAcc(lte, ModaccConfigLte);
+ lteMeasurements[0] = RFmxLteMXMeasurementTypes.ModAcc;
+ SA.RFmxLTE.SelectAndInitiateMeasurements(lte, lteMeasurements, saAutolevelConfig, false, "", resultStringLte);
+ ModaccResultsLte = FetchModAcc(lte, RFmxLteMX.BuildResultString(resultStringLte));
+ PrintModAccResults();
+ #endregion
+
+ specAn.Dispose();
+ specAn = null;
+ lte.Dispose();
+ instr.Close();
+
+ AbortGeneration(nIRfsg);
+ CloseInstrument(nIRfsg);
+ }
+
+ #region Utilities
+ private void PrintACPResults()
+ {
+ Console.WriteLine("\n----------------------- ACP Results -----------------------\n");
+ Console.WriteLine("Carrier Absolute Power (dBm): {0:0.00}\n", AcpResultsLte.ComponentCarrierResults[0].AbsolutePower_dBm);
+ Console.WriteLine("\n-----------Offset Channel Measurements----------- \n");
+
+ for (int i = 0; i < AcpResultsLte.OffsetResults.Length; i++)
+ {
+ Console.WriteLine("Offset {0}", i);
+ Console.WriteLine("Lower Absolute Power (dBm) : {0:0.000}", AcpResultsLte.OffsetResults[i].LowerAbsolutePower_dBm);
+ Console.WriteLine("Upper Absolute Power (dBm) : {0:0.000}", AcpResultsLte.OffsetResults[i].UpperAbsolutePower_dBm);
+ Console.WriteLine("Lower Relative Power (dB) : {0:0.000}", AcpResultsLte.OffsetResults[i].LowerRelativePower_dB);
+ Console.WriteLine("Upper Relative Power (dB) : {0:0.000}", AcpResultsLte.OffsetResults[i].UpperRelativePower_dB);
+ Console.WriteLine("Offset Frequency (Hz) : {0:0.000}", AcpResultsLte.OffsetResults[i].Frequency_Hz);
+ Console.WriteLine("Offset Integration Bandwidth (Hz) : {0:0.000}", AcpResultsLte.OffsetResults[i].IntegrationBandwidth_Hz);
+ Console.WriteLine("-------------------------------------------------\n");
+ }
+ }
+ private void PrintModAccResults()
+ {
+ for (int i = 0; i < ModaccResultsLte.ComponentCarrierResults.Length; i++)
+ {
+ Console.WriteLine("\n----------------------- EVM Results CC {0} -----------------------\n", i);
+ Console.WriteLine("Composite RMS EVM Mean (% or dB) : {0:0.000}", ModaccResultsLte.ComponentCarrierResults[i].MeanRmsCompositeEvm);
+ Console.WriteLine("Composite Peak EVM Maximum (% or dB) : {0:0.000}", ModaccResultsLte.ComponentCarrierResults[i].MaxPeakCompositeEvm);
+ Console.WriteLine("Composite Peak EVM Slot Index : {0}", ModaccResultsLte.ComponentCarrierResults[i].PeakCompositeEvmSlotIndex);
+ Console.WriteLine("Composite Peak EVM Symbol Index : {0}", ModaccResultsLte.ComponentCarrierResults[i].PeakCompositeEvmSymbolIndex);
+ Console.WriteLine("Composite Peak EVM Subcarrier Index : {0}", ModaccResultsLte.ComponentCarrierResults[i].PeakCompositeEvmSubcarrierIndex);
+ Console.WriteLine("Component Carrier Frequency Error Mean (Hz) : {0:0.000}", ModaccResultsLte.ComponentCarrierResults[i].MeanFrequencyError_Hz);
+ }
+ }
+ #endregion
+ }
+}
diff --git a/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.csproj b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.csproj
new file mode 100644
index 0000000..01b9d01
--- /dev/null
+++ b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.csproj
@@ -0,0 +1,87 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}
+ Exe
+ LTE_NanosemiDPD_EVM_ACP_UL
+ LTE_NanosemiDPD_EVM_ACP_UL
+ v4.5
+ 512
+ true
+
+
+ x64
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {8e7d5092-b685-4ad3-9da3-7c53e56f0f32}
+ Common
+
+
+ {7fdb7cdb-4281-4b0d-a407-a6d4c63fcd36}
+ NanosemiDPD
+
+
+ {ab49d5a9-9585-445a-ae8a-e4dd2b8956aa}
+ RFmxInstr
+
+
+ {1eb6f1ae-2eea-4dc8-8cdb-09b5fadf2236}
+ RFmxLTE
+
+
+ {3d1bc0f6-273c-4a44-82f6-3bb933862ffb}
+ RFmxSpecAn
+
+
+ {89abcac5-cedb-4535-bd58-e205a97834d9}
+ SG
+
+
+
+
\ No newline at end of file
diff --git a/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.sln b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.sln
new file mode 100644
index 0000000..31d8efb
--- /dev/null
+++ b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/LTE_NanosemiDPD_EVM_ACP_UL.sln
@@ -0,0 +1,101 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29324.140
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LTE_NanosemiDPD_EVM_ACP_UL", "LTE_NanosemiDPD_EVM_ACP_UL.csproj", "{C95B388B-A9DD-4019-B4A1-64BC0188083D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{09F0830E-B2C7-45C5-BDDF-2E355662B9EA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RFmxInstr", "..\..\Source\SA\RFmx Instr\RFmxInstr.csproj", "{AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RFmxLTE", "..\..\Source\SA\RFmx LTE\RFmxLTE.csproj", "{1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RFmxSpecAn", "..\..\Source\SA\RFmx SpecAn\RFmxSpecAn.csproj", "{3D1BC0F6-273C-4A44-82F6-3BB933862FFB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NanosemiDPD", "..\..\Source\Methods\NanosemiDPD\NanosemiDPD.csproj", "{7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SG", "..\..\Source\SG\SG.csproj", "{89ABCAC5-CEDB-4535-BD58-E205A97834D9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "..\..\Source\Common\Common.csproj", "{8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Debug|x64.Build.0 = Debug|Any CPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Release|x64.ActiveCfg = Release|Any CPU
+ {C95B388B-A9DD-4019-B4A1-64BC0188083D}.Release|x64.Build.0 = Release|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|x64.Build.0 = Debug|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|x64.ActiveCfg = Release|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|x64.Build.0 = Release|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|x64.Build.0 = Debug|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|x64.ActiveCfg = Release|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|x64.Build.0 = Release|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|x64.Build.0 = Debug|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|x64.ActiveCfg = Release|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|x64.Build.0 = Release|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|x64.ActiveCfg = Debug|x64
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|x64.Build.0 = Debug|x64
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|x64.ActiveCfg = Release|x64
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|x64.Build.0 = Release|x64
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|x64.Build.0 = Debug|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|x64.ActiveCfg = Release|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|x64.Build.0 = Release|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|x64.Build.0 = Debug|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|x64.ActiveCfg = Release|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|x64.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA} = {09F0830E-B2C7-45C5-BDDF-2E355662B9EA}
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236} = {09F0830E-B2C7-45C5-BDDF-2E355662B9EA}
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB} = {09F0830E-B2C7-45C5-BDDF-2E355662B9EA}
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36} = {09F0830E-B2C7-45C5-BDDF-2E355662B9EA}
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9} = {09F0830E-B2C7-45C5-BDDF-2E355662B9EA}
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32} = {09F0830E-B2C7-45C5-BDDF-2E355662B9EA}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {2A8146D3-319B-49A6-AA8C-8D0A662DF6F3}
+ EndGlobalSection
+EndGlobal
diff --git a/Examples/LTE_NanosemiDPD_EVM_ACP_UL/Program.cs b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/Program.cs
new file mode 100644
index 0000000..a0d79cc
--- /dev/null
+++ b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/Program.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace NationalInstruments.ReferenceDesignLibraries.Examples
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Example Application LTE_NanosemiDPD_EVM_ACP_UL\n");
+ LTE_NanosemiDPD_EVM_ACP_UL lteNanosemiDpdAmPmEvmAcpUl = new LTE_NanosemiDPD_EVM_ACP_UL();
+ try
+ {
+ lteNanosemiDpdAmPmEvmAcpUl.Run();
+
+ }
+ catch (Exception e)
+ {
+
+ DisplayError(e);
+ }
+ Console.WriteLine("Press any key to finish.");
+ Console.ReadKey();
+ }
+ static void DisplayError(Exception e)
+ {
+ Console.WriteLine("ERROR:\n" + e.GetType() + ": " + e.Message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Examples/LTE_NanosemiDPD_EVM_ACP_UL/Properties/AssemblyInfo.cs b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b37b7d8
--- /dev/null
+++ b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("LTE_NanosemiDPD_EVM_ACP_UL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("National Instruments")]
+[assembly: AssemblyProduct("LTE_NanosemiDPD_EVM_ACP_UL")]
+[assembly: AssemblyCopyright("Copyright © National Instruments 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c95b388b-a9dd-4019-b4a1-64bc0188083d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Examples/LTE_NanosemiDPD_EVM_ACP_UL/RFmxInstr.cs b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/RFmxInstr.cs
new file mode 100644
index 0000000..03b3850
--- /dev/null
+++ b/Examples/LTE_NanosemiDPD_EVM_ACP_UL/RFmxInstr.cs
@@ -0,0 +1,55 @@
+using NationalInstruments.RFmx.InstrMX;
+using System.Text.RegularExpressions;
+
+namespace NationalInstruments.ReferenceDesignLibraries.SA
+{
+ /// Defines common types and methods for configuring instruments with NI-RFmx.
+ public static class RFmxInstr
+ {
+ #region Type Definitions
+ /// Defines common instrument configurations to apply to the analyzer.
+ public struct InstrumentConfiguration
+ {
+ /// Defines the local oscillator sharing behavior for VST devices.
+ public LocalOscillatorSharingMode LOSharingMode;
+ /// Specifies the frequency reference source.
+ public string FrequencyReferenceSource;
+
+ /// Returns the struct with default values set.
+ /// The struct with default values set.
+ public static InstrumentConfiguration GetDefault()
+ {
+ return new InstrumentConfiguration
+ {
+ LOSharingMode = LocalOscillatorSharingMode.Automatic,
+ FrequencyReferenceSource = RFmxInstrMXConstants.PxiClock
+ };
+ }
+ }
+ #endregion
+
+ #region Instrument Configurations
+ /// Applies common instrument settings to the analyzer.
+ /// The open RFmx Instr session to configure.
+ /// The instrument configuration properties to apply.
+ public static void ConfigureInstrument(RFmxInstrMX instrHandle, InstrumentConfiguration instrConfig)
+ {
+ instrHandle.SetFrequencyReferenceSource("", instrConfig.FrequencyReferenceSource);
+ instrHandle.GetInstrumentModel("", out string model);
+ // Only configure LO settings on supported VSTs
+ if (Regex.IsMatch(model, "NI PXIe-58[34].")) // Matches 583x and 584x VST families
+ {
+ if (instrConfig.LOSharingMode == LocalOscillatorSharingMode.None)
+ instrHandle.ConfigureAutomaticSGSASharedLO("", RFmxInstrMXAutomaticSGSASharedLO.Disabled);
+ else
+ {
+ instrHandle.ConfigureAutomaticSGSASharedLO("", RFmxInstrMXAutomaticSGSASharedLO.Enabled);
+ // Configure automatic LO offsetting
+ instrHandle.SetLOLeakageAvoidanceEnabled("", RFmxInstrMXLOLeakageAvoidanceEnabled.True);
+ instrHandle.ResetAttribute("", RFmxInstrMXPropertyId.DownconverterFrequencyOffset);
+ }
+ }
+ }
+ #endregion
+ }
+}
diff --git a/Source/Methods/NanosemiDPD/AssemblyInfo.cs b/Source/Methods/NanosemiDPD/AssemblyInfo.cs
new file mode 100644
index 0000000..002de7a
--- /dev/null
+++ b/Source/Methods/NanosemiDPD/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("NanosemiDPD")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("National Instruments")]
+[assembly: AssemblyProduct("NanosemiDPD")]
+[assembly: AssemblyCopyright("Copyright © National Instruments 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7fdb7cdb-4281-4b0d-a407-a6d4c63fcd36")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Methods/NanosemiDPD/NanosemiDPD.cs b/Source/Methods/NanosemiDPD/NanosemiDPD.cs
new file mode 100644
index 0000000..ccf0cb7
--- /dev/null
+++ b/Source/Methods/NanosemiDPD/NanosemiDPD.cs
@@ -0,0 +1,127 @@
+using System;
+using NationalInstruments.RFmx.SpecAnMX;
+using NationalInstruments.ModularInstruments.NIRfsg;
+using NationalInstruments.ModularInstruments.NIRfsgPlayback;
+using static NationalInstruments.ReferenceDesignLibraries.SG;
+using NanoSemiLinearizer.Interop;
+
+namespace NationalInstruments.ReferenceDesignLibraries.Methods
+{
+ public static class NanosemiDPD
+ {
+ #region Type Definitions
+
+ /// Defines commmon settings for the application of crest factor reduction on the reference waveform prior to applying DPD for a single carrier channel.
+ public struct PreDpdCrestFactorReductionConfiguration
+ {
+
+ public nstdpd.CfrConfig CfrConfiguration;
+
+ /// Returns the struct with default values set.
+ /// The struct with default values set.
+ public static PreDpdCrestFactorReductionConfiguration GetDefault()
+ {
+ return new PreDpdCrestFactorReductionConfiguration
+ {
+ CfrConfiguration = nstdpd.CfrGetDefaultConfig()
+ };
+
+ }
+ }
+
+ public struct NanosemiDPDConfiguration
+ {
+ public nstdpd.DpdConfig DpdConfiguration;
+ /// Specifies the number of iterations over which Nanosemi DPD is computed using indirect-learning architecture.
+ public int NumberOfIterations;
+ /// Specifies the duration of the reference waveform considered for the DPD measurement.
+ public double IQAcquisitionLength_s;
+
+ public static NanosemiDPDConfiguration GetDefault()
+ {
+ return new NanosemiDPDConfiguration
+ {
+
+ DpdConfiguration = nstdpd.DpdGetDefaultConfig(),
+ NumberOfIterations = 3,
+ IQAcquisitionLength_s = 1e-3
+
+ };
+ }
+ }
+
+
+ public struct NanosemiDPDResults
+ {
+ /// Returns the whose data represents the complex baseband equivalent of the RF signal
+ /// after applying digital pre-distortion.
+ public Waveform PredistortedWaveform;
+ }
+ #endregion
+
+ #region ConfigureNanosemiDPD
+
+ /// Specifies the SpecAn signal to configure.
+ /// Specifies the whose data defines the complex baseband equivalent of the RF signal on which the
+ /// pre-DPD signal conditioning is applied.
+ /// Pass an empty string. The signal name that is passed when creating the signal configuration is used.
+ public static void ConfigureNanosemi(RFmxSpecAnMX specAn, NanosemiDPDConfiguration nsDPDConfig, Waveform referenceWaveform, string selectorString = "")
+ {
+ specAn.SelectMeasurements("", RFmxSpecAnMXMeasurementTypes.IQ, true);
+ specAn.IQ.Configuration.ConfigureAcquisition(selectorString, referenceWaveform.SampleRate, 1, nsDPDConfig.IQAcquisitionLength_s, 0);
+ nsDPDConfig.DpdConfiguration.f_sample = (float)(referenceWaveform.SampleRate * 1e-6);
+ nstdpd.DpdResetTraining(nsDPDConfig.DpdConfiguration);
+
+ }
+ #endregion
+
+ #region PerformDPD
+
+ /// Acquires the incoming signal, trains the DPD model, applies the DPD model to the reference waveform, and downloads the predistorted waveform to the generator.
+ /// If generation is in progress when this function is called, generation will resume with the predistorted waveform.
+ /// Specifies the SpecAn signal to configure.
+ /// Specifies the open RFSG session to configure.
+ /// Specifies the whose data defines the complex baseband equivalent of the RF signal applied at the input
+ /// port of the device under test when performing the measurement.
+ /// Pass an empty string. The signal name that is passed when creating the signal configuration is used.
+ /// Common results after the application of lookup table based DPD.
+ public static NanosemiDPDResults PerformNanosemiDPD(RFmxSpecAnMX specAn, NIRfsg rfsgSession, Waveform referenceWaveform, NanosemiDPDConfiguration nsDPDConfig, string selectorString = "")
+ {
+ IntPtr rfGeneratorHandle;
+ rfGeneratorHandle = rfsgSession.GetInstrumentHandle().DangerousGetHandle();
+ NanosemiDPDResults nanosemiDPDResults = new NanosemiDPDResults()
+ {
+ PredistortedWaveform = referenceWaveform
+ };
+ nanosemiDPDResults.PredistortedWaveform.Data = referenceWaveform.Data.Clone(); // clone waveform so RFmx can't act on reference waveform
+ nanosemiDPDResults.PredistortedWaveform.UpdateNameAndScript(referenceWaveform.Name + "postNsDpd");
+ ComplexWaveform acquiredIQData = new ComplexWaveform(0);
+
+
+ for (int dpdIter = 0; dpdIter < nsDPDConfig.NumberOfIterations; dpdIter++)
+ {
+ specAn.Initiate(selectorString, "");
+ specAn.IQ.Results.FetchData(selectorString, 3, 0, -1, ref acquiredIQData);
+
+ nstdpd.DpdTrain(referenceWaveform.Data, acquiredIQData, nsDPDConfig.DpdConfiguration);
+ nanosemiDPDResults.PredistortedWaveform.Data = nstdpd.DpdApply(referenceWaveform.Data, nsDPDConfig.DpdConfiguration);
+
+ //Modify RFSG waveform to DPD waveform and Initiate generation again.
+ RfsgGenerationStatus preDpdGenerationStatus = rfsgSession.CheckGenerationStatus();
+ rfsgSession.Abort();
+ NIRfsgPlayback.ClearAllWaveforms(rfGeneratorHandle);
+
+ //Download DPD waveform to the RF Generator and update scripts
+ NIRfsgPlayback.DownloadUserWaveform(rfGeneratorHandle, nanosemiDPDResults.PredistortedWaveform.Name, nanosemiDPDResults.PredistortedWaveform.Data, true);
+ NIRfsgPlayback.RetrieveWaveformPapr(rfGeneratorHandle, nanosemiDPDResults.PredistortedWaveform.Name, out nanosemiDPDResults.PredistortedWaveform.PAPR_dB);
+ NIRfsgPlayback.RetrieveWaveformSampleRate(rfGeneratorHandle, nanosemiDPDResults.PredistortedWaveform.Name, out nanosemiDPDResults.PredistortedWaveform.SampleRate);
+ ApplyWaveformAttributes(rfsgSession, nanosemiDPDResults.PredistortedWaveform);
+
+ //Initiate generation of post DPD waveform
+ rfsgSession.Initiate();
+ }
+ return nanosemiDPDResults;
+ }
+ #endregion
+ }
+}
diff --git a/Source/Methods/NanosemiDPD/NanosemiDPD.csproj b/Source/Methods/NanosemiDPD/NanosemiDPD.csproj
new file mode 100644
index 0000000..d2d7beb
--- /dev/null
+++ b/Source/Methods/NanosemiDPD/NanosemiDPD.csproj
@@ -0,0 +1,89 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}
+ Library
+ Properties
+ NanosemiDPD
+ NanosemiDPD
+ v4.5
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ 7.3
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ 7.3
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+ Properties\SolutionInfo.cs
+
+
+
+
+
+
+
+ {8e7d5092-b685-4ad3-9da3-7c53e56f0f32}
+ Common
+ False
+
+
+ {89abcac5-cedb-4535-bd58-e205a97834d9}
+ SG
+ False
+
+
+
+
\ No newline at end of file
diff --git a/Source/Methods/NanosemiDPD/Properties/AssemblyInfo.cs b/Source/Methods/NanosemiDPD/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8c1cc96
--- /dev/null
+++ b/Source/Methods/NanosemiDPD/Properties/AssemblyInfo.cs
@@ -0,0 +1,32 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("NanosemiDPD")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("NanosemiDPD")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7fdb7cdb-4281-4b0d-a407-a6d4c63fcd36")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Methods/NanosemiDPD/nstdpd.cs b/Source/Methods/NanosemiDPD/nstdpd.cs
new file mode 100644
index 0000000..fc347e7
--- /dev/null
+++ b/Source/Methods/NanosemiDPD/nstdpd.cs
@@ -0,0 +1,398 @@
+using System;
+using System.Runtime.InteropServices;
+using NationalInstruments;
+
+namespace NanoSemiLinearizer.Interop
+{
+ public static class nstdpd
+ {
+ #region Public Structs and Enums
+ ///
+ ///CFR configuration structure.
+ ///Dictates the behavior the NSTDPD CFR algorithm.
+ ///All fields must have non-Infinity, non-NaN values.
+ ///
+ ///The num_bands, fc_list, and bw_list fields describe the spectral mask of the input waveform as a list of carrier bands with a certain bandwidths and center frequencies.
+ ///If the offset field is nonzero, the mask described by num_bands/fc_list/bw_list will be frequency-shifted by that value.
+ ///The overal spectrum mask described by the first four fields of this struct must be fully contained within the range[-f_sample / 2, f_sample / 2].
+ ///
+ ///struct NST_CFR_CONFIG_STRUCT
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct CfrConfig
+ {
+ ///
+ /// The number of frequency bands to apply CFR to. Must be a non-negative value.
+ ///
+ public int num_bands;
+ ///
+ /// The center frequency (MHz) of each band.
+ ///
+ public float[] fc_list;
+ ///
+ /// The width of each frequency band (MHz).
+ ///
+ public float[] bw_list;
+ ///
+ /// The frequency-domain baseband offset of the input waveform (MHz).
+ ///
+ public float offset;
+ ///
+ /// The sampling rate (MHz) of the input waveform. Must be a positive value.
+ ///
+ public float f_sample;
+ ///
+ /// The desired PAPR (dB) of the CFR output. Must be a non-negative value.
+ ///
+ public float targetPAPR;
+ ///
+ /// For FDD waveforms set this to 1.0f. For a TDD DL waveform, set this to (number of downlink subframes/total subframes). For a TDD UL waveform, set this to (number of uplink subframes/total subframes). Valid values are [1,0).
+ ///
+ public float TDD_duty_cycle;
+ }
+
+ ///
+ /// DPD Performance Levels.
+ /// Adaptive DPD offers four tiers of DPD performance, which are enumerated here.
+ /// Linearizer performance & execution time increase for higher performance levels.
+ ///
+ public enum DpdLevel
+ {
+ /// NST_DPD_LEVEL3 -> 3
+ NST_DPD_LEVEL3 = 3,
+ /// NST_DPD_LEVEL2 -> 2
+ NST_DPD_LEVEL2 = 2,
+ /// NST_DPD_LEVEL1 -> 1
+ NST_DPD_LEVEL1 = 1,
+ /// NST_DPD_LEVEL0 -> 0
+ NST_DPD_LEVEL0 = 0,
+ }
+
+ ///
+ /// DPD configuration Structure.
+ /// Dictates the behavior of the DPD Training algorithms.
+ /// struct NST_DPD_CONFIG_STRUCT
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DpdConfig
+ {
+ ///
+ /// Configures the performance level of the DPD algorithm
+ ///
+ public DpdLevel lvl;
+ ///
+ /// The robustness coefficient for DPD training. Must be a positive value.
+ ///
+ public float rho;
+ ///
+ /// The absolute value of the endpoints of the VSG full-scale range, [-abs_vsg_max,abs_vsg_max]. Must be a positive value.
+ ///
+ public float abs_vsg_max;
+ ///
+ /// The number of samples to use when training the DPD. Must be a positive value less than the number of samples in the waveform.
+ ///
+ public int training_samples;
+ ///
+ /// The sampling rate (MHz) of the input waveform. Must be a positive value.
+ ///
+ public float f_sample;
+ ///
+ /// The DPD training algorithm will operate on input samples in the range [TDD_training_start_point , TDD_training_start_point + training_samples). For FDD, this can safely be set to 0. For TDD DL, choose this value so that the training algorithm is operating on a DL subframe. For TDD UL, choose this value so that the training algorithm is operating on a UL subframe. It is recommended that the subframe immediately after a UL-to-DL or DL-to-UL transition not be used for training.
+ ///
+ public int TDD_training_start_point;
+ }
+
+ #endregion
+
+ #region Private Data Structures
+ ///
+ /// Separate version of CFR Configuration Struct to allow for easier DLL calling (where Fc and BW arrays are separate inputs to the CFR methods
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ private struct CfrConfigLV
+ {
+ public int num_bands;
+ public float offset;
+ public float f_sample;
+ public float targetPAPR;
+ public float TDD_duty_cycle;
+ }
+
+ ///
+ /// DPD trained or untrained.
+ ///
+ private enum dpdTrainedStatus
+ {
+ /// The DPD state has been modified by the training algorithm.
+ NST_DPD_TRAINED = 1,
+ /// The DPD state has been reset to its default value. In this state the DPD output matches its input.
+ NST_DPD_UNTRAINED = 0,
+ }
+ #endregion
+
+ #region NanoSemi CFR
+ ///
+ /// Populates the CFR configuration structure with default settings.
+ ///
+ /// Default settings structure
+ public static CfrConfig CfrGetDefaultConfig()
+ {
+ PInvoke.nst_dpd_cfr_get_default_config(out CfrConfig config);
+ config.num_bands = 1;
+ config.bw_list = new float[1] { 0.0f };
+ config.fc_list = new float[1] { 0.0f };
+ return config;
+ }
+
+ ///
+ /// The CFR algorithm clip-and-filters the input waveform to satisfy config.targetPAPR.
+ /// The input waveform must not contain Infinity or NaN samples.
+ /// All fields of the CFR configuration struct must have valid settings.
+ ///
+ /// The I channel of the input waveform to apply CFR to.
+ /// The Q channel of the input waveform to apply CFR to.
+ /// Returns the I channel of the waveform with CFR applied, with the same number of samples as wfm_in.
+ /// Returns the Q channel of the waveform with CFR applied, with the same number of samples as wfm_in.
+ /// Configures the behavior of the CFR algorithm.
+ public static void CfrApply(float[] wfm_in_i, float[] wfm_in_q, out float[] wfm_out_i, out float[] wfm_out_q, CfrConfig CfrConfiguration)
+ {
+ CfrConfigLV lvconf = new CfrConfigLV()
+ {
+ num_bands = CfrConfiguration.num_bands,
+ offset = CfrConfiguration.offset,
+ f_sample = CfrConfiguration.f_sample,
+ targetPAPR = CfrConfiguration.targetPAPR,
+ TDD_duty_cycle = CfrConfiguration.TDD_duty_cycle
+ };
+
+ int waveformLength = wfm_in_i.Length;
+ float[] wfm_out_i_pinv = new float[waveformLength];
+ float[] wfm_out_q_pinv = new float[waveformLength];
+
+ int pInvokeResult = PInvoke.nst_dpd_cfr_apply_labview(wfm_in_i, wfm_in_q, waveformLength, wfm_out_i_pinv, wfm_out_q_pinv, lvconf, CfrConfiguration.fc_list, CfrConfiguration.bw_list);
+ TestForError(pInvokeResult);
+
+ wfm_out_i = wfm_out_i_pinv;
+ wfm_out_q = wfm_out_q_pinv;
+ }
+
+ ///
+ /// The CFR algorithm clip-and-filters the input waveform to satisfy config.targetPAPR.
+ /// The input waveform must not contain Infinity or NaN samples.
+ /// All fields of the CFR configuration struct must have valid settings.
+ ///
+ /// The Input waveform to apply CFR to.
+ /// Configures the behavior of the CFR algorithm.
+ /// Waveform with CFR applied
+ public static ComplexWaveform CfrApply(ComplexWaveform WaveformIn, CfrConfig CfrConfiguration)
+ {
+ ComplexSingle.DecomposeArray(WaveformIn.GetRawData(), out float[] IArray, out float[] QArray);
+ CfrApply(IArray, QArray, out float[] WfmOutI, out float[] WfmOutQ, CfrConfiguration);
+
+ //Handle the necessary Conversion from I/Q arrays to NI ComplexWaveform Datatype
+ ComplexSingle[] PostCFRWaveformData = ComplexSingle.ComposeArray(WfmOutI, WfmOutQ);
+ ComplexWaveform CfrWaveformOut = new ComplexWaveform(0);
+ CfrWaveformOut.Append(PostCFRWaveformData);
+ CfrWaveformOut.PrecisionTiming = WaveformIn.PrecisionTiming;
+
+ return CfrWaveformOut;
+ }
+ #endregion
+
+ #region NanoSemi DPD
+ ///
+ /// Populates the DPD configuration structure with default settings.
+ ///
+ /// Return the default settings structure.
+ public static DpdConfig DpdGetDefaultConfig()
+ {
+ PInvoke.nst_dpd_get_default_config(out DpdConfig config);
+ config.abs_vsg_max = 1.01f;
+ return config;
+ }
+
+ ///
+ /// Reset DPD to untrained state.
+ /// This call(1) resets the DPD state to its default (untrained) value, and (2) sets the DPD performance level to the value of config.lvl.
+ /// The DPD performance level must be valid.
+ ///
+ ///
+ public static void DpdResetTraining(DpdConfig DpdConfiguration)
+ {
+ int pInvokeResult = PInvoke.nst_dpd_reset_training(DpdConfiguration);
+ TestForError(pInvokeResult);
+ }
+
+ ///
+ /// Query DPD training state.
+ /// Indicates whether the DPD algorithm has been trained, or is in an untrained state.
+ ///
+ /// Returns the training state of the DPD algorithm (True = Trained)
+ public static bool DpdQueryTrained()
+ {
+ int pInvokeResult = PInvoke.nst_dpd_query_trained(out dpdTrainedStatus trainedSt);
+ TestForError(pInvokeResult);
+ return (trainedSt == dpdTrainedStatus.NST_DPD_TRAINED);
+ }
+ ///
+ /// Train the Adaptive DPD.
+ /// Improve DPD linearization by comparing a predistorted waveform to the baseband DUT output waveform that results from applying that predistorted waveform to the DUT.
+ ///
+ /// This function updates the DPD state in memory; it has no return values.
+ /// The input waveforms must not contain Infinity or NaN samples.
+ /// For the wfm_dpd argument, the magnitudes of the complex waveform samples must not exceed config.abs_vsg_max.
+ /// For the wfm_Rx argument, the magnitudes of the complex waveform samples must not exceed config.abs_vsa_max.
+ /// All fields of the DPD configuration struct must have valid settings.
+ /// config.training_samples must be at least 5000.
+ ///
+ ///
+ /// The I channel of the predistorted waveform.
+ /// The Q channel of the predistorted waveform.
+ /// The I channel of the baseband DUT output waveform, with the same number of samples as wfm_in.
+ /// The Q channel of the baseband DUT output waveform, with the same number of samples as wfm_in.
+ /// Configures the behavior of the training algorithm.
+ public static void DpdTrain(float[] wfm_dpd_i, float[] wfm_dpd_q, float[] wfm_Rx_i, float[] wfm_Rx_q, DpdConfig DpdConfiguration)
+ {
+ int waveformLength = wfm_Rx_i.Length;
+
+ int pInvokeResult = PInvoke.nst_dpd_train(wfm_dpd_i, wfm_dpd_q, waveformLength, wfm_Rx_i, wfm_Rx_q, DpdConfiguration);
+ TestForError(pInvokeResult);
+ }
+
+ ///
+ /// Train the Adaptive DPD.
+ /// Improve DPD linearization by comparing a predistorted waveform to the baseband DUT output waveform that results from applying that predistorted waveform to the DUT.
+ ///
+ /// This function updates the DPD state in memory; it has no return values.
+ /// The input waveforms must not contain Infinity or NaN samples.
+ /// For the wfm_dpd argument, the magnitudes of the complex waveform samples must not exceed config.abs_vsg_max.
+ /// All fields of the DPD configuration struct must have valid settings.
+ /// config.training_samples must be at least 5000.
+ ///
+ ///
+ /// Waveform being generated to the DUT input
+ /// Acquired waveform from the DUT output
+ /// Configures the behavior of the training algorithm.
+ public static void DpdTrain(ComplexWaveform GeneratedWaveform, ComplexWaveform AcquiredWaveform, DpdConfig DpdConfiguration)
+ {
+ ComplexSingle.DecomposeArray(GeneratedWaveform.GetRawData(), out float[] wfm_dpd_i, out float[] wfm_dpd_q);
+ ComplexSingle.DecomposeArray(AcquiredWaveform.GetRawData(), out float[] wfm_Rx_i, out float[] wfm_Rx_q);
+ DpdTrain(wfm_dpd_i, wfm_dpd_q, wfm_Rx_i, wfm_Rx_q, DpdConfiguration);
+ }
+
+ ///
+ /// Predistort a waveform.
+ ///
+ /// The input waveform must not contain Infinity or NaN samples.
+ /// The magnitudes of the complex waveform samples must not exceed config.abs_vsg_max.
+ /// All fields of the DPD configuration struct must have valid settings.
+ ///
+ ///
+ /// The I channel of the input waveform to apply DPD to.
+ /// The Q channel of the input waveform to apply DPD to.
+ /// Returns the I channel of the waveform with DPD applied, with the same number of samples as wfm_in.
+ /// Returns the Q channel of the waveform with DPD applied, with the same number of samples as wfm_in.
+ /// Configures the behavior of the training algorithm.
+ public static void DpdApply(float[] wfm_in_i, float[] wfm_in_q, out float[] wfm_out_i, out float[] wfm_out_q, DpdConfig DpdConfiguration)
+ {
+ int waveformLength = wfm_in_i.Length;
+ float[] wfm_out_i_pinv = new float[waveformLength];
+ float[] wfm_out_q_pinv = new float[waveformLength];
+
+ int pInvokeResult = PInvoke.nst_dpd_apply(wfm_in_i, wfm_in_q, waveformLength, wfm_out_i_pinv, wfm_out_q_pinv, DpdConfiguration);
+ TestForError(pInvokeResult);
+
+ wfm_out_i = wfm_out_i_pinv;
+ wfm_out_q = wfm_out_q_pinv;
+ }
+
+ ///
+ /// Predistort a waveform.
+ ///
+ /// The input waveform must not contain Infinity or NaN samples.
+ /// The magnitudes of the complex waveform samples must not exceed config.abs_vsg_max.
+ /// All fields of the DPD configuration struct must have valid settings.
+ /// The Input waveform to apply DPD to.
+ /// Configures the behavior of the training algorithm.
+ /// Waveform with DPD applied
+ public static ComplexWaveform DpdApply(ComplexWaveform WaveformIn, DpdConfig DpdConfiguration)
+ {
+ ComplexSingle.DecomposeArray(WaveformIn.GetRawData(), out float[] IArray, out float[] QArray);
+ DpdApply(IArray, QArray, out float[] WfmOutI, out float[] WfmOutQ, DpdConfiguration);
+
+ //Handle the necessary Conversion from I/Q arrays to NI ComplexWaveform Datatype
+ ComplexSingle[] PostDPDWaveformData = ComplexSingle.ComposeArray(WfmOutI, WfmOutQ);
+ ComplexWaveform DpdWaveformOut = new ComplexWaveform(0);
+ DpdWaveformOut.Append(PostDPDWaveformData);
+ DpdWaveformOut.PrecisionTiming = WaveformIn.PrecisionTiming;
+
+ return DpdWaveformOut;
+ }
+ #endregion
+
+ #region Utilities
+ ///
+ /// NSTDPD software module version. Get the version number of this release of NSTDPD.
+ ///
+ /// NSTDPD Version Number
+ public static float GetVersion()
+ {
+ int pInvokeResult = PInvoke.nst_dpd_version(out float version);
+ TestForError(pInvokeResult);
+ return version;
+ }
+ #endregion
+
+ #region PInvoke
+ private class PInvoke
+ {
+ private const string nstdpddll = @"C:\NanoSemi\bin\nstdpd.dll";
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_error_description", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_error_description(int code, out IntPtr description);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_version", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_version(out float version);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_cfr_get_default_config", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_cfr_get_default_config(out CfrConfig config);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_cfr_apply_labview", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_cfr_apply_labview([In] float[] wfm_in_i, [In] float[] wfm_in_q, int count, [In, Out] float[] wfm_out_i, [In, Out] float[] wfm_out_q, CfrConfigLV config, [In] float[] fc_list, [In] float[] bw_list);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_reset_training", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_reset_training(DpdConfig DpdConfiguration);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_train", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_train(float[] wfm_dpd_i, float[] wfm_dpd_q, int count, float[] wfm_Rx_i, float[] wfm_Rx_q, DpdConfig DpdConfiguration);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_train_without_align", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int nst_dpd_train_without_align(float[] wfm_dpd_i, float[] wfm_dpd_q, int count, float[] wfm_Rx_i, float[] wfm_Rx_q, DpdConfig DpdConfiguration);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_apply", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_apply([In] float[] wfm_in_i, [In] float[] wfm_in_q, int count, [In, Out] float[] wfm_out_i, [In, Out] float[] wfm_out_q, DpdConfig DpdConfiguration);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_query_trained", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_query_trained(out dpdTrainedStatus status);
+
+ [DllImport(nstdpddll, EntryPoint = "nst_dpd_get_default_config", CallingConvention = CallingConvention.StdCall)]
+ public static extern int nst_dpd_get_default_config(out DpdConfig config);
+ }
+ private static int TestForError(int status)
+ {
+ if (status < 0)
+ {
+ string errorString = GetError(status);
+ throw new ExternalException(errorString, status);
+ }
+ return status;
+ }
+ private static string GetError(int code)
+ {
+ PInvoke.nst_dpd_error_description(code, out IntPtr errorPtr);
+ string errorString = Marshal.PtrToStringAnsi(errorPtr);
+ return errorString;
+ }
+ #endregion
+ }
+}
diff --git a/Source/Reference Design Libraries.sln b/Source/Reference Design Libraries.sln
index 2e2e57a..64b0837 100644
--- a/Source/Reference Design Libraries.sln
+++ b/Source/Reference Design Libraries.sln
@@ -38,60 +38,120 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RFmxInstr", "SA\RFmx Instr\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Envelope Tracking", "Methods\Envelope Tracking\Envelope Tracking.csproj", "{724A8D0C-EE49-405C-AA33-884FDA656088}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NanosemiDPD", "Methods\NanosemiDPD\NanosemiDPD.csproj", "{7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Debug|x64.Build.0 = Debug|Any CPU
{9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Release|x64.ActiveCfg = Release|Any CPU
+ {9E8F4D28-AC1D-4A06-8C62-FC96097890B9}.Release|x64.Build.0 = Release|Any CPU
{89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Debug|x64.Build.0 = Debug|Any CPU
{89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|x64.ActiveCfg = Release|Any CPU
+ {89ABCAC5-CEDB-4535-BD58-E205A97834D9}.Release|x64.Build.0 = Release|Any CPU
{6E38C48B-DD17-4438-9366-E336528E62AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E38C48B-DD17-4438-9366-E336528E62AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6E38C48B-DD17-4438-9366-E336528E62AE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6E38C48B-DD17-4438-9366-E336528E62AE}.Debug|x64.Build.0 = Debug|Any CPU
{6E38C48B-DD17-4438-9366-E336528E62AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E38C48B-DD17-4438-9366-E336528E62AE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6E38C48B-DD17-4438-9366-E336528E62AE}.Release|x64.ActiveCfg = Release|Any CPU
+ {6E38C48B-DD17-4438-9366-E336528E62AE}.Release|x64.Build.0 = Release|Any CPU
{3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Debug|x64.Build.0 = Debug|Any CPU
{3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|x64.ActiveCfg = Release|Any CPU
+ {3D1BC0F6-273C-4A44-82F6-3BB933862FFB}.Release|x64.Build.0 = Release|Any CPU
{7659CA3A-45D7-4A1C-8253-98615F119CF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7659CA3A-45D7-4A1C-8253-98615F119CF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7659CA3A-45D7-4A1C-8253-98615F119CF3}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7659CA3A-45D7-4A1C-8253-98615F119CF3}.Debug|x64.Build.0 = Debug|Any CPU
{7659CA3A-45D7-4A1C-8253-98615F119CF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7659CA3A-45D7-4A1C-8253-98615F119CF3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7659CA3A-45D7-4A1C-8253-98615F119CF3}.Release|x64.ActiveCfg = Release|Any CPU
+ {7659CA3A-45D7-4A1C-8253-98615F119CF3}.Release|x64.Build.0 = Release|Any CPU
{A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Debug|x64.Build.0 = Debug|Any CPU
{A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Release|x64.ActiveCfg = Release|Any CPU
+ {A12F87E8-772D-4DD9-9AE1-E6A72E83F4FE}.Release|x64.Build.0 = Release|Any CPU
{B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Debug|x64.Build.0 = Debug|Any CPU
{B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Release|x64.ActiveCfg = Release|Any CPU
+ {B12280C1-69D7-4E52-8A41-95B1D568DD6B}.Release|x64.Build.0 = Release|Any CPU
{1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Debug|x64.Build.0 = Debug|Any CPU
{1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|x64.ActiveCfg = Release|Any CPU
+ {1EB6F1AE-2EEA-4DC8-8CDB-09B5FADF2236}.Release|x64.Build.0 = Release|Any CPU
{C725B272-463E-421D-8648-4E3F87868711}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C725B272-463E-421D-8648-4E3F87868711}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C725B272-463E-421D-8648-4E3F87868711}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C725B272-463E-421D-8648-4E3F87868711}.Debug|x64.Build.0 = Debug|Any CPU
{C725B272-463E-421D-8648-4E3F87868711}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C725B272-463E-421D-8648-4E3F87868711}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C725B272-463E-421D-8648-4E3F87868711}.Release|x64.ActiveCfg = Release|Any CPU
+ {C725B272-463E-421D-8648-4E3F87868711}.Release|x64.Build.0 = Release|Any CPU
{8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Debug|x64.Build.0 = Debug|Any CPU
{8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|x64.ActiveCfg = Release|Any CPU
+ {8E7D5092-B685-4AD3-9DA3-7C53E56F0F32}.Release|x64.Build.0 = Release|Any CPU
{AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Debug|x64.Build.0 = Debug|Any CPU
{AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|x64.ActiveCfg = Release|Any CPU
+ {AB49D5A9-9585-445A-AE8A-E4DD2B8956AA}.Release|x64.Build.0 = Release|Any CPU
{724A8D0C-EE49-405C-AA33-884FDA656088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{724A8D0C-EE49-405C-AA33-884FDA656088}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {724A8D0C-EE49-405C-AA33-884FDA656088}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {724A8D0C-EE49-405C-AA33-884FDA656088}.Debug|x64.Build.0 = Debug|Any CPU
{724A8D0C-EE49-405C-AA33-884FDA656088}.Release|Any CPU.ActiveCfg = Release|Any CPU
{724A8D0C-EE49-405C-AA33-884FDA656088}.Release|Any CPU.Build.0 = Release|Any CPU
+ {724A8D0C-EE49-405C-AA33-884FDA656088}.Release|x64.ActiveCfg = Release|Any CPU
+ {724A8D0C-EE49-405C-AA33-884FDA656088}.Release|x64.Build.0 = Release|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|x64.ActiveCfg = Debug|x64
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Debug|x64.Build.0 = Debug|x64
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|x64.ActiveCfg = Release|x64
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -111,6 +171,7 @@ Global
{8E7D5092-B685-4AD3-9DA3-7C53E56F0F32} = {9DF8AA31-0EBB-4E3D-ACAE-96F2350DA9F8}
{AB49D5A9-9585-445A-AE8A-E4DD2B8956AA} = {2B079B61-B71B-440E-BFF7-0DF80927B5C5}
{724A8D0C-EE49-405C-AA33-884FDA656088} = {3779EC48-73B9-4620-8E17-57340A70611A}
+ {7FDB7CDB-4281-4B0D-A407-A6D4C63FCD36} = {3779EC48-73B9-4620-8E17-57340A70611A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D020C05D-4EF8-45D5-8E12-D76DE5E66039}