Esempio n. 1
0
        private bool DetectSpan(FFTParams fftParams, SweepParams measParams,
                                List <double> powerList, List <double> frequencies,
                                List <double> attenList)
        {
            // detect over span
            for (int i = 0; i < fftParams.NumSegments; i++)
            {
                double cf = fftParams.CenterFrequencies[i];

                uint numFftsToCopy;
                if (i == fftParams.NumFullSegments)
                {
                    numFftsToCopy = fftParams.NumBinsLastSegment;
                }
                else
                {
                    numFftsToCopy = fftParams.NumValidFftBins;
                }

                bool overload = false;
                bool err      = DetectSegment(measParams, fftParams, powerList,
                                              null, cf, numFftsToCopy, ref overload);
                if (err)
                {
                    return(true);
                }
            }
            return(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Perfrom Y-factor calibration
        /// </summary>
        /// <param name="calParams"></param>
        /// <param name="sysMessage"></param>
        /// <param name="yFactorCal"></param>
        public void PerformCal(SweepParams calParams,
                               SysMessage sysMessage, out YfactorCal yFactorCal)
        {
            List <double> powerListNdOn  = new List <double>();
            List <double> powerListNdOff = new List <double>();

            calParams.MinAtten = calParams.Attenuation;
            calParams.MaxAtten = calParams.Attenuation;

            // set filter
            bool err = SetFilter(calParams.sys2Detect);

            if (err)
            {
                yFactorCal = null;
                return;
            }

            sysMessage.calibration.temp = preselector.GetTemp();

            // perfrom cal for number of attenuations
            // IS THIS necessary???
            //int iterations = 1 +
            //    (measParams.MaxAtten - measParams.Attenuation)
            //    / measParams.StepAtten;
            //for (int i = 0; i < iterations; i++)
            //{
            FFTParams fftParams =
                new FFTParams(sensorCapabilities, calParams,
                              possibleSampleRates, possibleSpans);

            if (fftParams.Error)
            {
                Utilites.LogMessage("error calculating FFT Params");
                yFactorCal = null;
                return;
            }

            // load sysMessage with fftParams and perfrom sweep for cal
            fftParams.LoadMessage(sysMessage);

            // Perform sweep with calibrated noise source on
            preselector.SetNdIn();
            preselector.PowerOnNd();
            err = DetectSpan(fftParams, calParams, powerListNdOn,
                             null, null);
            if (err)
            {
                yFactorCal = null;
                return;
            }

            // perfrom sweep with calibrated noise source off
            preselector.PowerOffNd();
            err = DetectSpan(fftParams, calParams, powerListNdOff,
                             null, null);
            if (err)
            {
                yFactorCal = null;
                return;
            }

            // Y-Factor Calibration
            if (powerListNdOff.Count != powerListNdOn.Count) // sanity check
            {
                Utilites.LogMessage("Error getting sweep data.  " +
                                    "Noise diode on and off power list are different sizes");
                yFactorCal = null;
                return;
            }

            yFactorCal = new YfactorCal(powerListNdOn, powerListNdOff,
                                        (double)sysMessage.calibration.measurementParameters.resolutionBw,
                                        (double)sysMessage.calibration.measurementParameters.equivalentNoiseBw,
                                        calParams.DwellTime,
                                        sysMessage.preselector.excessNoiseRatio,
                                        sysMessage.antenna.cableLoss,
                                        sysMessage.antenna.gain);

            sysMessage.calibration.processed = true;
            sysMessage.gain        = yFactorCal.GainDbw;
            sysMessage.noiseFigure = yFactorCal.NoseFigureDbw;
        }
Esempio n. 3
0
        private bool DetectSegment(SweepParams measParams,
                                   FFTParams fftParams, List <double> powerList,
                                   List <double> frequencies, double cf, uint numFftsToCopy,
                                   ref bool overloadFlag)
        {
            AgSalLib.SalError err;

            AgSalLib.SweepParms         sweepParams = new AgSalLib.SweepParms();
            AgSalLib.FrequencySegment[] fs
                = new AgSalLib.FrequencySegment[1];

            switch (measParams.Window.ToLower())
            {
            case "hanning": sweepParams.window =
                sweepParams.window             = AgSalLib.WindowType.Window_hann;
                break;

            case "gauss-top": sweepParams.window =
                sweepParams.window = AgSalLib.WindowType.Window_gaussTop;
                break;

            case "flattop": sweepParams.window =
                sweepParams.window             = AgSalLib.WindowType.Window_flatTop;
                break;

            case "rectangular": sweepParams.window =
                sweepParams.window = AgSalLib.WindowType.Window_uniform;
                break;

            default:
                Utilites.LogMessage("Invalid window type in " +
                                    "calibration json file");
                return(true);
            }

            switch (measParams.TimeOverlap)
            {
            case 50:
                fs[0].overlapType =
                    AgSalLib.OverlapType.OverlapType_on;
                break;

            default:
                fs[0].overlapType =
                    AgSalLib.OverlapType.OverlapType_off;
                break;
            }

            switch (measParams.Detector.ToLower())
            {
            case "rms": fs[0].averageType =
                fs[0].averageType         = AgSalLib.AverageType.Average_rms;
                break;

            case "sample": fs[0].averageType =
                fs[0].averageType            = AgSalLib.AverageType.Average_off;
                break;

            case "positive": fs[0].averageType =
                fs[0].averageType = AgSalLib.AverageType.Average_peak;
                break;

            default:
                Utilites.LogMessage("Invalid Detector type in " +
                                    "calibration json file");
                return(true);
            }

            switch (measParams.Antenna)
            {
            case 0:
                fs[0].antenna =
                    AgSalLib.AntennaType.Antenna_Terminated2;
                break;

            case 1:
                fs[0].antenna =
                    AgSalLib.AntennaType.Antenna_1;
                break;

            case 2:
                fs[0].antenna =
                    AgSalLib.AntennaType.Antenna_2;
                break;

            default:
                Utilites.LogMessage("Invalid antenna value " +
                                    "in cal json file");
                return(true);
            }

            sweepParams.numSweeps       = 1;
            sweepParams.numSegments     = 1;
            sweepParams.sweepInterval   = 0.0;
            sweepParams.monitorMode     = AgSalLib.MonitorMode.MonitorMode_off;
            sweepParams.monitorInterval = 0.0;
            // data return type for sweepParams is always real float32 dbm

            fs[0].numFftPoints    = fftParams.NumFftBins;
            fs[0].numAverages     = fftParams.NumFftsToAvg;
            fs[0].firstPoint      = 0;
            fs[0].numPoints       = fs[0].numFftPoints;
            fs[0].centerFrequency = cf;
            fs[0].sampleRate      = fftParams.SampleRate;
            fs[0].preamp          = measParams.PreAmp;
            fs[0].attenuation     = measParams.Attenuation;
            fs[0].dataType        = AgSalLib.FftDataType.FftData_db;

            // Setup pacing
            AgSalLib.salFlowControl flowControl = new AgSalLib.salFlowControl();
            flowControl.pacingPolicy       = 1; // wait when full
            flowControl.maxBacklogMessages = 50;

            err = AgSalLib.salStartSweep2(out measHandle, sensorHandle,
                                          ref sweepParams, ref fs, ref flowControl, null);
            if (SensorError(err, "salStartSweep"))
            {
                if (err == AgSalLib.SalError.SAL_ERR_SENSOR_NOT_CONNECTED)
                {
                    // lost connection to sensor, kill the process
                    // service will start it again
                    Environment.Exit(1);
                }
                return(true);
            }

            AgSalLib.SweepStatus status;
            double elapsed;

            AgSalLib.salGetSweepStatus2(measHandle, 0, out status, out elapsed);
            // wait until sweep is finished
            while (status == AgSalLib.SweepStatus.SweepStatus_running)
            {
                AgSalLib.salGetSweepStatus2(measHandle, 0, out status, out elapsed);
            }

            // get data from sweep
            AgSalLib.SegmentData dataHeader = new AgSalLib.SegmentData();
            // Agilent DLL requires float array even though it uses double
            // everywhere else ..... annoying
            float[] frequencyData = new float[fftParams.NumFftBins];

            // how long to read before exiting
            int      maxDataReadMilliSeconds = 1000;
            DateTime t0            = DateTime.Now;
            bool     dataRetrieved = false;
            int      startIndex    = 0;

            while (!dataRetrieved)
            {
                TimeSpan elapsedTime = DateTime.Now.Subtract(t0);
                if (elapsedTime.Milliseconds > maxDataReadMilliSeconds)
                {
                    Utilites.LogMessage("Getting segment data timed out, " +
                                        "restarting cal");
                }

                err = AgSalLib.salGetSegmentData(measHandle,
                                                 out dataHeader, frequencyData,
                                                 (uint)frequencyData.Length * 4);

                switch (err)
                {
                case AgSalLib.SalError.SAL_ERR_NONE:
                    if (dataHeader.errorNum != AgSalLib.SalError.SAL_ERR_NONE)
                    {
                        string message = "Segment data header returned an error: \n\n";
                        message += "errorNumber: " + dataHeader.errorNum.ToString() + "\n";
                        message += "errorInfo:   " + dataHeader.errorInfo;
                        Utilites.LogMessage(message);
                        return(true);
                    }
                    // get the data
                    // check if need to remove anti aliasing
                    // need startIndex after the while loop so declared outside
                    if (measParams.RemoveAntiAliasing)
                    {
                        startIndex = GetStartIndex(fftParams.SampleRate,
                                                   (int)fftParams.NumFftBins);
                    }

                    FloatArrayToListOfDoubles(frequencyData,
                                              powerList, numFftsToCopy, startIndex);
                    // check if overload occured
                    if (dataHeader.overload != 0)
                    {
                        overloadFlag = true;
                    }
                    else
                    {
                        overloadFlag = false;
                    }
                    dataRetrieved = true;
                    break;

                case AgSalLib.SalError.SAL_ERR_NO_DATA_AVAILABLE:
                    // data is not available yet ...
                    break;

                case AgSalLib.SalError.SAL_ERR_SENSOR_NOT_CONNECTED:
                    // lost connection to sensor, kill the process
                    // service will start it again
                    Environment.Exit(1);
                    break;

                default:
                    SensorError(err, "salGetSegmentData");
                    break;
                }
            }

            if (frequencies != null)
            {
                // calculate frquencies
                for (int i = 0; i < numFftsToCopy; i++)
                {
                    frequencies.Add(dataHeader.startFrequency +
                                    (startIndex - 1) * dataHeader.frequencyStep +
                                    i * dataHeader.frequencyStep);
                }
            }

            return(false);
        }
Esempio n. 4
0
        //}

        /// <summary>
        /// Performs a multi-segment detection with a Keysight N6841A sensor
        /// and applies variable attenuation when overload occurs.
        /// </summary>
        /// <param name="sweepParams"></param>
        /// <param name="dataMessage"></param>
        public bool PerformMeasurement(SweepParams sweepParams,
                                       DataMessage dataMessage, YfactorCal yFactorCal)
        {
            SetFilter(sweepParams.sys2Detect);
            preselector.SetRfIn();
            preselector.PowerOffNd();

            FFTParams fftParams = new FFTParams(sensorCapabilities,
                                                sweepParams, possibleSampleRates, possibleSpans);

            if (fftParams.Error)
            {
                Utilites.LogMessage("error calculating FFT Params");
                return(true);
            }

            fftParams.LoadMessage(dataMessage);

            // set filter
            bool err = SetFilter(sweepParams.sys2Detect);

            List <double> powerList     = new List <double>();
            List <double> frequencyList = new List <double>();
            List <int>    attenList     = Enumerable.Repeat(sweepParams.Attenuation,
                                                            (int)fftParams.NumSegments).ToList();

            // detect over span
            for (int i = 0; i < fftParams.NumSegments; i++)
            {
                double cf = fftParams.CenterFrequencies[i];

                uint numFftsToCopy;
                if (i == fftParams.NumFullSegments)
                {
                    numFftsToCopy = fftParams.NumBinsLastSegment;
                }
                else
                {
                    numFftsToCopy = fftParams.NumValidFftBins;
                }

                sweepParams.Attenuation = 0; // set attenuation back to its initial value. Hardcodded to 0 for testing purpose
                if (sweepParams.DynamicAttenuation)
                {
                    bool overload = true;
                    while (overload && attenList[i] <= MAX_ATTEN)
                    {
                        err = DetectSegment(sweepParams, fftParams, powerList,
                                            frequencyList, cf, numFftsToCopy, ref overload);
                        if (err)
                        {
                            return(true);
                        }
                        if (overload)
                        {
                            dataMessage.overloadFlag = true;
                            sweepParams.Attenuation += sweepParams.StepAtten;
                            attenList[i]             = sweepParams.Attenuation;
                        }

                        // remove previous duplicated segment
                        int indexDuplicate = 0;
                        foreach (double number in frequencyList)
                        {
                            if (number == frequencyList[frequencyList.Count - 1])
                            {
                                indexDuplicate = frequencyList.IndexOf(number);
                                if (indexDuplicate == frequencyList.Count - 1)
                                {
                                    indexDuplicate = 0;
                                }
                                break;
                            }
                        }

                        if (indexDuplicate != 0)
                        {
                            frequencyList.RemoveRange(indexDuplicate -
                                                      Convert.ToInt32(numFftsToCopy) + 1, Convert.ToInt32(numFftsToCopy));
                            powerList.RemoveRange(indexDuplicate -
                                                  Convert.ToInt32(numFftsToCopy) + 1, Convert.ToInt32(numFftsToCopy));
                        }
                        // end removing
                    }
                }
                else
                {
                    bool overload = false;
                    err = DetectSegment(sweepParams, fftParams, powerList,
                                        frequencyList, cf, numFftsToCopy, ref overload);
                    if (err)
                    {
                        return(true);
                    }
                    if (overload)
                    {
                        dataMessage.overloadFlag = true;
                    }
                }
            }

            List <double> measuredPowers = new List <double>();
            // Init antenna class to access cable loss and antenna gain
            string antennaString =
                File.ReadAllText(Constants.AntennaFile);

            SysMessage.Antenna antenna =
                new JavaScriptSerializer().Deserialize <SysMessage.Antenna>(
                    antennaString);

            // reference power levels to input of isotropic antenna
            for (int i = 0; i < powerList.Count; i++)
            {
                measuredPowers.Add(
                    powerList[i] + antenna.cableLoss - antenna.gain -
                    yFactorCal.GainDbw[i]);
            }
            dataMessage.processed      = true;
            dataMessage.measuredPowers = measuredPowers;
            return(false);
        }