public DataPackageScope GetScopeData()
        {
            //Sleep to simulate USB delay
            System.Threading.Thread.Sleep(usbLatency);
            TimeSpan timeOffset = DateTime.Now - timeOrigin;

            if (acquisitionRunning)
            {
                lock (viewportUpdateLock)
                {
                    viewportUpdate = true;
                }
                int triggerHoldoffInSamples = 0;
                int triggerIndex            = 0;
                Dictionary <AnalogChannel, List <float> > waveAnalog = new Dictionary <AnalogChannel, List <float> >();
                foreach (AnalogChannel ch in AnalogChannel.List)
                {
                    waveAnalog.Add(ch, new List <float>((int)waveLength));
                }
                List <byte> waveDigital = new List <byte>();

                bool triggerDetected = false;

                while (true)
                {
                    AcquisitionMode AcquisitionModeCurrent;
                    lock (acquisitionSettingsLock)
                    {
                        acquisitionBufferAnalog     = new Dictionary <AnalogChannel, float[]>();
                        AcquisitionModeCurrent      = acquisitionMode;
                        acquisitionDepthCurrent     = AcquisitionDepth;
                        TriggerHoldoffCurrent       = triggerHoldoff;
                        SamplePeriodCurrent         = SamplePeriod;
                        waveLengthCurrent           = waveLength;
                        logicAnalyserChannelCurrent = logicAnalyserChannel;
                        logicAnalyserEnabledCurrent = LogicAnalyserEnabled;
                    }

                    acquistionId++;

                    //Stop trying to find a trigger at some point to avoid running out of memory
                    if (waveAnalog.Where(x => x.Value.Count > GENERATION_LENGTH_MAX).Count() > 0 || waveDigital.Count > GENERATION_LENGTH_MAX)
                    {
                        System.Threading.Thread.Sleep(10);
                        return(null);
                    }

                    foreach (AnalogChannel channel in AnalogChannel.List)
                    {
                        if (logicAnalyserEnabledCurrent && channel == logicAnalyserChannelCurrent)
                        {
                            continue;
                        }
                        float[] wave;
                        switch (waveSource)
                        {
                        case WaveSource.GENERATOR:
                            wave = DummyScope.GenerateWave(waveLengthCurrent,
                                                           SamplePeriodCurrent,
                                                           timeOffset.Ticks / 1e7,
                                                           ChannelConfig[channel]);
                            break;

                        case WaveSource.FILE:
                            wave = GetWaveFromFile(channel, waveLengthCurrent, SamplePeriodCurrent, timeOffset.Ticks / 1e7);
                            break;

                        default:
                            throw new Exception("Unsupported wavesource");
                        }
                        if (ChannelConfig[channel].coupling == Coupling.AC)
                        {
                            DummyScope.RemoveDcComponent(ref wave, ChannelConfig[channel].frequency, SamplePeriodCurrent);
                        }
                        else
                        {
                            DummyScope.AddDcComponent(ref wave, (float)ChannelConfig[channel].dcOffset);
                        }
                        DummyScope.AddNoise(wave, ChannelConfig[channel].noise);
                        waveAnalog[channel].AddRange(wave);
                    }
                    if (logicAnalyserEnabledCurrent)
                    {
                        waveDigital.AddRange(DummyScope.GenerateWaveDigital(waveLengthCurrent, SamplePeriodCurrent, timeOffset.TotalSeconds));
                    }

                    triggerHoldoffInSamples = (int)(TriggerHoldoffCurrent / SamplePeriodCurrent);
                    double triggerTimeout = 0.0;
                    if (AcquisitionModeCurrent == AcquisitionMode.AUTO)
                    {
                        triggerTimeout = GENERATION_LENGTH_MAX * SamplePeriodCurrent; //Give up after 10ms
                    }
                    if (logicAnalyserEnabledCurrent && this.triggerValue.mode == TriggerMode.Digital)
                    {
                        triggerDetected = DummyScope.DoTriggerDigital(waveDigital.ToArray(), triggerHoldoffInSamples, digitalTrigger, acquisitionDepthCurrent, out triggerIndex);
                    }
                    else
                    {
                        if (triggerValue.source != TriggerSource.Channel)
                        {
                            throw new Exception("Doing analog trigger but mode is not set to analog!");
                        }
                        triggerDetected = DummyScope.DoTriggerAnalog(waveAnalog[triggerValue.channel].ToArray(), triggerValue,
                                                                     triggerHoldoffInSamples, triggerThreshold, triggerWidth,
                                                                     acquisitionDepthCurrent, out triggerIndex);
                    }
                    awaitingTrigger = !triggerDetected;

                    if (triggerDetected)
                    {
                        forceTrigger    = false;
                        awaitingTrigger = false;
                        break;
                    }

                    if (
                        forceTrigger ||
                        (triggerTimeout > 0 && waveAnalog[AnalogChannel.ChA].Count * SamplePeriodCurrent >= triggerTimeout)
                        )
                    {
                        forceTrigger    = false;
                        triggerIndex    = triggerHoldoffInSamples;
                        awaitingTrigger = false;
                        break;
                    }

                    var timePassed = new TimeSpan((long)(waveLengthCurrent * SamplePeriodCurrent * 1e7));
                    timeOffset = timeOffset.Add(timePassed);
                }

                foreach (AnalogChannel channel in AnalogChannel.List)
                {
                    if (logicAnalyserEnabledCurrent && channel == logicAnalyserChannelCurrent)
                    {
                        continue;
                    }
                    acquisitionBufferAnalog[channel] = DummyScope.CropWave(acquisitionDepthCurrent, waveAnalog[channel].ToArray(), triggerIndex, triggerHoldoffInSamples);
                }
                acquisitionBufferDigital = DummyScope.CropWave(acquisitionDepthCurrent, waveDigital.ToArray(), triggerIndex, triggerHoldoffInSamples);
                if (StopPending)
                {
                    acquisitionRunning = false;
                }
            }
            lock (viewportUpdateLock)
            {
                if (!viewportUpdate)
                {
                    return(null);
                }
                viewportUpdate = false;
            }

            if (acquisitionBufferAnalog.Count == null)
            {
                return(null);
            }

            //Decrease the number of samples till viewport sample period is larger than
            //or equal to the full sample rate
            uint samples            = VIEWPORT_SAMPLES_MAX;
            int  viewportDecimation = 0;

            while (true)
            {
                viewportDecimation = (int)Math.Ceiling(Math.Log(ViewPortTimeSpan / (samples + 2) / SamplePeriodCurrent, 2));
                if (viewportDecimation >= 0)
                {
                    break;
                }
                samples /= 2;
            }

            if (viewportDecimation > VIEW_DECIMATION_MAX)
            {
                Logger.Warn("Clipping view decimation! better decrease the sample rate!");
                viewportDecimation = VIEW_DECIMATION_MAX;
            }
            int viewportSamples     = (int)(ViewPortTimeSpan / (SamplePeriodCurrent * Math.Pow(2, viewportDecimation))) + 2;
            int viewportOffsetLocal = (int)(ViewPortOffset / SamplePeriodCurrent);


            p = new DataPackageScope(this.GetType(),
                                     acquisitionDepthCurrent, SamplePeriodCurrent,
                                     viewportSamples, (Int64)(ViewPortOffset / SamplePeriodCurrent),
                                     TriggerHoldoffCurrent, (Int64)(TriggerHoldoffCurrent / SamplePeriodCurrent), false, acquistionId, TriggerValue);
            p.FullAcquisitionFetchProgress = 1f;
            p.samplePeriod[ChannelDataSourceScope.Viewport] = SamplePeriodCurrent * Math.Pow(2, viewportDecimation);
            p.offset[ChannelDataSourceScope.Viewport]       = ViewPortOffset;

            foreach (AnalogChannel ch in AnalogChannel.List)
            {
                if (logicAnalyserEnabledCurrent && ch == logicAnalyserChannelCurrent)
                {
                    continue;
                }
                if (SendOverviewBuffer)
                {
                    p.SetData(ChannelDataSourceScope.Overview, ch, GetViewport(acquisitionBufferAnalog[ch], 0, (int)(Math.Log(acquisitionDepthCurrent / OVERVIEW_LENGTH, 2)), OVERVIEW_LENGTH));
                }
                p.SetData(ChannelDataSourceScope.Viewport, ch, GetViewport(acquisitionBufferAnalog[ch], viewportOffsetLocal, viewportDecimation, viewportSamples));
                p.SetData(ChannelDataSourceScope.Acquisition, ch, acquisitionBufferAnalog[ch]);

                //set dummy minmax values
                p.SaturationLowValue[ch]  = float.MinValue;
                p.SaturationHighValue[ch] = float.MaxValue;
            }

            if (logicAnalyserEnabledCurrent)
            {
                if (SendOverviewBuffer)
                {
                    p.SetData(ChannelDataSourceScope.Overview, LogicAnalyserChannel.LA, GetViewport(acquisitionBufferDigital, 0, (int)(Math.Log(acquisitionDepthCurrent / OVERVIEW_LENGTH, 2)), OVERVIEW_LENGTH));
                }
                p.SetData(ChannelDataSourceScope.Viewport, LogicAnalyserChannel.LA, GetViewport(acquisitionBufferDigital, viewportOffsetLocal, viewportDecimation, viewportSamples));
                p.SetData(ChannelDataSourceScope.Acquisition, LogicAnalyserChannel.LA, acquisitionBufferDigital);
            }

            if (acquisitionMode == AcquisitionMode.SINGLE)
            {
                acquisitionRunning = false;
            }

            return(p);
        }
Example #2
0
        public DataPackageScope GetScopeData()
        {
            //Sleep to simulate USB delay
            System.Threading.Thread.Sleep(usbLatency);
            TimeSpan timeOffset = DateTime.Now - timeOrigin;

            List <AnalogChannel> channelsToAcquireDataFor = new List <AnalogChannel> ();

            if (isAudio)
            {
                channelsToAcquireDataFor.Add(AnalogChannel.ChA);
            }
            else
            {
                channelsToAcquireDataFor.AddRange(AnalogChannel.List);
            }

            if (acquisitionRunning)
            {
                lock (viewportUpdateLock)
                {
                    viewportUpdate = true;
                }
                int triggerHoldoffInSamples = 0;
                int triggerIndex            = 0;
                Dictionary <AnalogChannel, List <float> > waveAnalog = new Dictionary <AnalogChannel, List <float> >();
                foreach (AnalogChannel ch in AnalogChannel.List)
                {
                    waveAnalog.Add(ch, new List <float>((int)waveLength));
                }
                List <byte> waveDigital = new List <byte>();

                bool triggerDetected = false;

                //loop until trigger condition is met
                while (true)
                {
                    //in case the stop button has been pressed, this section makes sure the last-shown acquisition is kept on the display (otherwise it is replaced by a new acquisition)
                    if ((StopPending || !acquisitionRunning) && (lastCommittedDataPackage != null))
                    {
                        acquisitionRunning = false;
                        return(lastCommittedDataPackage);
                    }

                    AcquisitionMode AcquisitionModeCurrent;
                    lock (acquisitionSettingsLock)
                    {
                        acquisitionBufferAnalog     = new Dictionary <AnalogChannel, float[]>();
                        AcquisitionModeCurrent      = acquisitionMode;
                        acquisitionDepthCurrent     = AcquisitionDepth;
                        TriggerHoldoffCurrent       = triggerHoldoff;
                        SamplePeriodCurrent         = SamplePeriod;
                        waveLengthCurrent           = waveLength;
                        logicAnalyserChannelCurrent = logicAnalyserChannel;
                        logicAnalyserEnabledCurrent = LogicAnalyserEnabled;
                    }

                    acquistionId++;

                    //Stop trying to find a trigger at some point to avoid running out of memory
                    if (waveAnalog.Where(x => x.Value.Count > GENERATION_LENGTH_MAX).Count() > 0 || waveDigital.Count > GENERATION_LENGTH_MAX)
                    {
                        System.Threading.Thread.Sleep(10);
                        return(null);
                    }

                    foreach (AnalogChannel channel in channelsToAcquireDataFor)
                    {
                        if (logicAnalyserEnabledCurrent && channel == logicAnalyserChannelCurrent)
                        {
                            continue;
                        }
                        float[] wave;
                        if (HardwareInterface == DummyInterface.Generator)
                        {
                            wave = DummyScope.GenerateWave(waveLengthCurrent,
                                                           SamplePeriodCurrent,
                                                           timeOffset.Ticks / 1e7,
                                                           ChannelConfig[channel]);
                        }
                        else if (HardwareInterface == DummyInterface.File)
                        {
                            wave = GetWaveFromFile(channel, waveLengthCurrent, SamplePeriodCurrent, timeOffset.Ticks / 1e7);
                        }
#if ANDROID
                        else if (hardwareInterface == DummyInterface.Audio)
                        {
                            //fetch audio data
                            if (audioJack == null)
                            {
                                return(null);
                            }
                            byte[] audioData = new byte[audioBufferLengthInBytes];
                            int    bytesRead = audioJack.Read(audioData, 0, audioBufferLengthInBytes);                           //2 bytes per sample
                            int    watchdog  = 0;
                            while (bytesRead <= 0 && watchdog++ < 1000)
                            {
                                System.Threading.Thread.Sleep(1);
                                bytesRead = audioJack.Read(audioData, 0, audioBufferLengthInBytes);                                  //2 bytes per sample
                            }

                            //convert bytes to shorts
                            short[] sampleData = new short[audioData.Length / 2];
                            Buffer.BlockCopy(audioData, 0, sampleData, 0, sampleData.Length * 2);

                            //and then into floats
                            wave = new float[sampleData.Length];
                            for (int i = 0; i < wave.Length; i++)
                            {
                                wave [i] = (float)sampleData [i] / (float)short.MaxValue;
                            }

                            //in case of large zoomouts, decimation will be > 0
                            //FIXME: this is not the best location to do this. time-errors will accumulate. better to do this on eventual wave. but then trigger index etc needs to be adjusted
                            int skip = 1 << (int)decimation;
                            wave = wave.Where((x, i) => i % skip == 0).ToArray();
                        }
#endif
                        else
                        {
                            throw new Exception("Unsupported dummy interface");
                        }

                        //coupling, noise injection in SW
                        if (!isAudio)
                        {
                            if (ChannelConfig [channel].coupling == Coupling.AC)
                            {
                                DummyScope.RemoveDcComponent(ref wave, ChannelConfig [channel].frequency, SamplePeriodCurrent);
                            }
                            else
                            {
                                DummyScope.AddDcComponent(ref wave, (float)ChannelConfig [channel].dcOffset);
                            }
                            DummyScope.AddNoise(wave, ChannelConfig [channel].noise);
                        }
                        waveAnalog[channel].AddRange(wave);
                    }
                    if (!isAudio && logicAnalyserEnabledCurrent)
                    {
                        waveDigital.AddRange(DummyScope.GenerateWaveDigital(waveLengthCurrent, SamplePeriodCurrent, timeOffset.TotalSeconds));
                    }

                    triggerHoldoffInSamples = (int)(TriggerHoldoffCurrent / SamplePeriodCurrent);
                    double triggerTimeout = 0.0;
                    if (AcquisitionModeCurrent == AcquisitionMode.AUTO)
                    {
                        triggerTimeout = SamplePeriodCurrent * acquisitionDepthCurrent * 1.0;                         //Give up after twice the acqbuffer timespan
                    }
                    //detect digital trigger
                    if (logicAnalyserEnabledCurrent && this.triggerValue.mode == TriggerMode.Digital)
                    {
                        triggerDetected = DummyScope.DoTriggerDigital(waveDigital.ToArray(), triggerHoldoffInSamples, digitalTrigger, acquisitionDepthCurrent, out triggerIndex);
                        if (isAudio)
                        {
                            triggerDetected = false;
                        }
                    }
                    else
                    //detect analog trigger
                    {
                        if (triggerValue.source == TriggerSource.External)
                        {
                            triggerDetected = false;
                        }
                        triggerDetected = DummyScope.DoTriggerAnalog(waveAnalog[triggerValue.channel].ToArray(), triggerValue,
                                                                     triggerHoldoffInSamples, triggerThreshold, triggerWidth,
                                                                     acquisitionDepthCurrent, out triggerIndex);
                    }
                    awaitingTrigger = !triggerDetected;

                    //break out of while loop if trigger was detected
                    if (triggerDetected)
                    {
                        forceTrigger    = false;
                        awaitingTrigger = false;
                        break;
                    }

                    //break out of while loop if triggerWasForced or synthetical 10ms limit was reached
                    if (
                        forceTrigger ||
                        (triggerTimeout > 0 && waveAnalog[AnalogChannel.ChA].Count * SamplePeriodCurrent >= triggerTimeout)
                        )
                    {
                        forceTrigger    = false;
                        triggerIndex    = triggerHoldoffInSamples;
                        awaitingTrigger = false;
                        break;
                    }

                    //keep track of time of first samplemoment
                    var timePassed = new TimeSpan((long)(waveLengthCurrent * SamplePeriodCurrent * 1e7));
                    timeOffset = timeOffset.Add(timePassed);
                }

                //crop wave to only displayable part and store in buffer
                foreach (AnalogChannel channel in channelsToAcquireDataFor)
                {
                    if (logicAnalyserEnabledCurrent && channel == logicAnalyserChannelCurrent)
                    {
                        continue;
                    }
                    acquisitionBufferAnalog[channel] = DummyScope.CropWave(acquisitionDepthCurrent, waveAnalog[channel].ToArray(), triggerIndex, triggerHoldoffInSamples);
                }
                acquisitionBufferDigital = DummyScope.CropWave(acquisitionDepthCurrent, waveDigital.ToArray(), triggerIndex, triggerHoldoffInSamples);
                if (StopPending)
                {
                    acquisitionRunning = false;
                }
            }
            lock (viewportUpdateLock)
            {
                if (!viewportUpdate)
                {
                    return(null);
                }
                viewportUpdate = false;
            }

            if (acquisitionBufferAnalog.Count == 0)
            {
                return(null);
            }

            //Decrease the number of samples till viewport sample period is larger than
            //or equal to the full sample rate
            uint samples            = VIEWPORT_SAMPLES_MAX;
            int  viewportDecimation = 0;
            while (true)
            {
                viewportDecimation = (int)Math.Ceiling(Math.Log(ViewPortTimeSpan / (samples + 2) / SamplePeriodCurrent, 2));
                if (viewportDecimation >= 0)
                {
                    break;
                }
                samples /= 2;
            }

            if (viewportDecimation > VIEW_DECIMATION_MAX)
            {
                Logger.Warn("Clipping view decimation! better decrease the sample rate!");
                viewportDecimation = VIEW_DECIMATION_MAX;
            }
            int viewportSamples     = (int)(ViewPortTimeSpan / (SamplePeriodCurrent * Math.Pow(2, viewportDecimation))) + 2;
            int viewportOffsetLocal = (int)(ViewPortOffset / SamplePeriodCurrent);


            p = new DataPackageScope(this.GetType(),
                                     acquisitionDepthCurrent, SamplePeriodCurrent,
                                     viewportSamples, (Int64)(ViewPortOffset / SamplePeriodCurrent),
                                     TriggerHoldoffCurrent, (Int64)(TriggerHoldoffCurrent / SamplePeriodCurrent), false, acquistionId, TriggerValue);
            p.FullAcquisitionFetchProgress = 1f;
            p.samplePeriod[ChannelDataSourceScope.Viewport] = SamplePeriodCurrent * Math.Pow(2, viewportDecimation);
            p.offset[ChannelDataSourceScope.Viewport]       = ViewPortOffset;

            //set values, needed for ETS to work properly
            if (acquisitionBufferAnalog != null && acquisitionBufferAnalog.ContainsKey(AnalogChannel.ChA))
            {
                p.samplePeriod[ChannelDataSourceScope.Overview] = SamplePeriodCurrent * (float)acquisitionBufferAnalog[AnalogChannel.ChA].Length / (float)OVERVIEW_LENGTH;
                p.offset[ChannelDataSourceScope.Overview]       = 0;
            }

            if (acquisitionBufferAnalog.Count == 0)
            {
                return(lastCommittedDataPackage);
            }

            foreach (AnalogChannel ch in channelsToAcquireDataFor)
            {
                if (logicAnalyserEnabledCurrent && ch == logicAnalyserChannelCurrent)
                {
                    continue;
                }
                if (SendOverviewBuffer)
                {
                    Array arr = GetViewport(acquisitionBufferAnalog[ch], 0, (int)(Math.Log(acquisitionDepthCurrent / OVERVIEW_LENGTH, 2)), OVERVIEW_LENGTH);
                    p.SetData(ChannelDataSourceScope.Overview, ch, arr);
                }
                p.SetData(ChannelDataSourceScope.Viewport, ch, GetViewport(acquisitionBufferAnalog[ch], viewportOffsetLocal, viewportDecimation, viewportSamples));
                p.SetData(ChannelDataSourceScope.Acquisition, ch, acquisitionBufferAnalog[ch]);

                //set dummy minmax values
                p.SaturationLowValue[ch]  = float.MinValue;
                p.SaturationHighValue[ch] = float.MaxValue;

                //set 20mV as resolution, which is needed for some processors (like freqdetection). Don't go too low, as ETS uses this in its difference detector
                p.Resolution[ch] = 0.020f;
            }


            if (logicAnalyserEnabledCurrent)
            {
                if (SendOverviewBuffer)
                {
                    p.SetData(ChannelDataSourceScope.Overview, LogicAnalyserChannel.LA, GetViewport(acquisitionBufferDigital, 0, (int)(Math.Log(acquisitionDepthCurrent / OVERVIEW_LENGTH, 2)), OVERVIEW_LENGTH));
                }
                p.SetData(ChannelDataSourceScope.Viewport, LogicAnalyserChannel.LA, GetViewport(acquisitionBufferDigital, viewportOffsetLocal, viewportDecimation, viewportSamples));
                p.SetData(ChannelDataSourceScope.Acquisition, LogicAnalyserChannel.LA, acquisitionBufferDigital);
            }

            if (acquisitionMode == AcquisitionMode.SINGLE)
            {
                acquisitionRunning = false;
            }

            lastCommittedDataPackage = p;
            return(p);
        }