public void TestConfigureLookUpTable()
        {
            LookUpTableConfiguration lutConfig = new LookUpTableConfiguration()
            {
                DutAverageInputPower_dBm = 10.0, // results in no scaling of iq data
                DutInputPower_dBm        = new float[] { 1.0f, 3.0f, 2.0f, 4.0f },
                SupplyVoltage_V          = new float[] { 5.0f, 7.0f, 6.0f, 8.0f }
            };

            Waveform referenceWaveform = new Waveform()
            {
                Data = ComplexWaveform <ComplexSingle> .FromArray1D(new ComplexSingle[] {
                    ComplexSingle.FromSingle(0.5f),
                    ComplexSingle.FromSingle(1.5f),
                    ComplexSingle.FromSingle(2.5f),
                    ComplexSingle.FromSingle(3.5f),
                    ComplexSingle.FromSingle(4.5f)
                })
            };

            // p = 10log(i^2) + 10
            // i = sqrt(10**(p - 10) / 10)
            var writableBuffer = referenceWaveform.Data.GetWritableBuffer();

            for (int i = 0; i < referenceWaveform.Data.SampleCount; i++)
            {
                writableBuffer[i] = ComplexSingle.FromSingle((float)Math.Sqrt(Math.Pow(10.0, (writableBuffer[i].Real - 10.0) / 10.0)));
            }

            Waveform envelopeWaveform = CreateLookUpTableEnvelopeWaveform(referenceWaveform, lutConfig);

            ComplexSingle.DecomposeArrayPolar(envelopeWaveform.Data.GetRawData(), out float[] yi, out _);

            float[] solution = new float[] { 4.5f, 5.5f, 6.5f, 7.5f, 8.5f };
            using (new AssertionScope())
            {
                for (int i = 0; i < yi.Length; i++)
                {
                    yi[i].Should().BeApproximately(solution[i], 0.1f);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>Creates an envelope waveform utilizing the lookup table method.</summary>
        /// <param name="referenceWaveform">Specifies the waveform used for RF signal generation.</param>
        /// <param name="lookUpTableConfig">Specifies common settings for creating the lookup table envelope waveform.</param>
        /// <returns>The lookup table envelope waveform.</returns>
        public static Waveform CreateLookUpTableEnvelopeWaveform(Waveform referenceWaveform, LookUpTableConfiguration lookUpTableConfig)
        {
            ComplexSingle[] iq = referenceWaveform.Data.GetRawData(); // get copy of iq samples

            /// power conversions needed to understand following scaling:
            /// power_dBW = 20log(V) - 10log(R) - since R is 100 we get power_dBW = 20log(V) - 20
            /// if we want to normalize to dbW 1ohm, we would have 20log(V) - 10log(1) = 20log(V)
            /// power_dBm = power_dBW + 30  therefore power_dBm = 20log(V) + 10
            /// therefore, to convert from dBm to dBW 1ohm we subtract 10 from dBm value

            // scale waveform to have average dBW 1ohm power equal to dut input power normalized to dBW 1ohm
            ComplexSingle scale = ComplexSingle.FromSingle((float)Math.Pow(10.0, (referenceWaveform.PAPR_dB + lookUpTableConfig.DutAverageInputPower_dBm - 10.0) / 20.0));

            for (int i = 0; i < iq.Length; i++)
            {
                iq[i] *= scale;
            }

            // get 1 ohm power trace in watts of scaled iq data
            float[] powerTrace_W = new float[iq.Length];
            for (int i = 0; i < iq.Length; i++)
            {
                powerTrace_W[i] = iq[i].Real * iq[i].Real + iq[i].Imaginary * iq[i].Imaginary;
            }

            // get lookup table input power trace in 1ohm watts
            float[] lutDutInputPowerWattOneOhm = new float[lookUpTableConfig.DutInputPower_dBm.Length];
            for (int i = 0; i < lookUpTableConfig.DutInputPower_dBm.Length; i++)
            {
                lutDutInputPowerWattOneOhm[i] = (float)Math.Pow(10.0, (lookUpTableConfig.DutInputPower_dBm[i] - 10.0) / 10.0); // V^2 = 10^((Pin - 10.0)/10)
            }
            // run the trace through 1D interpolation
            float[] rawEnvelope = LinearInterpolation1D(lutDutInputPowerWattOneOhm, lookUpTableConfig.SupplyVoltage_V, powerTrace_W);

            // create waveform to return to the user
            Waveform envelopeWaveform = CloneAndConditionReferenceWaveform(referenceWaveform);

            // copy raw envelope data into cloned envelope waveform
            WritableBuffer <ComplexSingle> envWfmWriteBuffer = envelopeWaveform.Data.GetWritableBuffer();

            for (int i = 0; i < rawEnvelope.Length; i++)
            {
                envWfmWriteBuffer[i] = ComplexSingle.FromSingle(rawEnvelope[i]);
            }

            return(envelopeWaveform);
        }
        /// <summary>
        /// This example illustrates how to use RFSG drivers and envelope tracking APIs to configure envelope tracking.
        /// </summary>
        static void Main(string[] args)
        {
            #region Example Settings
            // Select mode for use in the example
            EnvelopeMode mode         = EnvelopeMode.Detrough;
            string       waveformPath = @"C:\Users\Public\Documents\National Instruments\RFIC Test Software\Waveforms\LTE_FDD_DL_1x20MHz_TM11_OS4.tdms";
            #endregion

            #region Configure RF Generator
            // Initialize instrument sessions
            NIRfsg rfVsg = new NIRfsg("5840", true, false);

            // Load up waveform
            Waveform rfWfm = LoadWaveformFromTDMS(waveformPath);

            // Configure RF generator
            InstrumentConfiguration rfInstrConfig = InstrumentConfiguration.GetDefault();
            ConfigureInstrument(rfVsg, rfInstrConfig);
            DownloadWaveform(rfVsg, rfWfm);
            ConfigureContinuousGeneration(rfVsg, rfWfm);
            #endregion

            #region Configure Tracker Generator
            NIRfsg envVsg = new NIRfsg("5820", true, false);

            // Configure envelope generator
            EnvelopeGeneratorConfiguration envInstrConfig = EnvelopeGeneratorConfiguration.GetDefault();
            TrackerConfiguration           trackerConfig  = TrackerConfiguration.GetDefault();
            ConfigureEnvelopeGenerator(envVsg, envInstrConfig, trackerConfig);

            Waveform envWfm = new Waveform();
            switch (mode)
            {
            case EnvelopeMode.Detrough:
                // Create envelope waveform
                DetroughConfiguration detroughConfig = DetroughConfiguration.GetDefault();
                detroughConfig.MinimumVoltage_V = 1.5;
                detroughConfig.MaximumVoltage_V = 3.5;
                detroughConfig.Exponent         = 1.2;
                detroughConfig.Type             = DetroughType.Exponential;
                envWfm = CreateDetroughEnvelopeWaveform(rfWfm, detroughConfig);
                break;

            case EnvelopeMode.LUT:
                LookUpTableConfiguration lutConfig = new LookUpTableConfiguration
                {
                    DutAverageInputPower_dBm = rfInstrConfig.DutAverageInputPower_dBm
                };
                // Todo - initialize lookup table
                envWfm = CreateLookUpTableEnvelopeWaveform(rfWfm, lutConfig);
                break;
            }

            ScaleAndDownloadEnvelopeWaveform(envVsg, envWfm, trackerConfig);
            ConfigureContinuousGeneration(envVsg, envWfm, "PFI0");
            #endregion

            // Start envelope tracking
            SynchronizationConfiguration syncConfig = SynchronizationConfiguration.GetDefault();
            InitiateSynchronousGeneration(rfVsg, envVsg, syncConfig);

            // Wait until user presses a button to stop
            Console.WriteLine("Press any key to abort envelope tracking..");
            Console.ReadKey();

            AbortGeneration(envVsg);
            AbortGeneration(rfVsg);

            // Close instruments
            rfVsg.Close();
            envVsg.Close();
        }