GithubHelp home page GithubHelp logo

deviceinterface's Introduction

Documentation needs to get updated since major refactoring of low-level device interfacing

#DeviceInterface

For a very simple usage example, see our console-demo

##Overview DeviceInterface translates the SmartScope API to hardware I/O. It consists of several layers:

  • DeviceManager
    • Device
      • Memories
        • Registers
      • HardwareInterface
        • OS-specific hardware interfacing

DeviceManager

The device manager class is the starting point to work with the DeviceInterface library. Instantiate it with a DeviceConnectHandler callback, called whenever a device connects or disconnects.

When a device is disconnected, the DeviceConnectHandler is called with the DummyScope (the so-called fallback device). This way, you always have a device to work with. To get a fallback device at startup, call DeviceConnectHandler(DeviceManager.fallbackDevice, true) after DeviceManager instantiation and before DeviceManager.Start()

Devices

There are three interfaces used to implement the SmartScope

Interface Function
IDevice implements a general device, could be your fridge
IScope implements an oscillocope/logic analyser
IWaveGenerator implements an analog and/or digital wave generator

IDevice

A simple interface to the device's status (ready or not) and its serial number

IScope

You're going to use this interface the most when working with the SmartScope.

Implements IDevice, provides properties and methods to control the oscilloscope and get scope data.

Provides a DataSource, a class which fetches and records scope data in its own thread.

IWaveGenerator

Implements IDevice, provides properties and methods to control the wave generator and upload waveforms.

IWaveGenerator usage - Generate analog waves

When using the SmartScope for generating a custom analog waveform, follow this procedure:

  1. (optional) To be safe: first disable all outputs
scope.GeneratorToDigitalEnabled = false;
scope.GeneratorToAnalogEnabled = false;
  1. Define and upload custom wave (specified immediately in Voltages, between 0V and 3.3V)
double[] customWave = new double[] { 0, 1.5, 1.88, 2, 1.2, 1, 0.5 };
scope.GeneratorDataDouble = customWave;
  1. Set output frequency (in seconds)

scope.GeneratorSamplePeriod = 0.000005;

  1. CommitSettings must be called to make the samplePeriod setting effective

scope.CommitSettings();

  1. Enable analog output

scope.GeneratorToAnalogEnabled = true;

IWaveGenerator examples - Generate analog waves

IWaveGenerator usage - Generate digital waves

When using the SmartScope for generating up to 4 simultaneous customized digital signals, follow this procedure:

  1. (optional) To be safe: first disable all outputs
scope.GeneratorToDigitalEnabled = false;
scope.GeneratorToAnalogEnabled = false;
  1. Define and upload custom wave
byte[] customWave = new byte[] { 0, 1, 0, 2, 0, 4, 0, 8 };
scope.GeneratorDataByte = customWave;
  1. Set output frequency (in seconds)

scope.GeneratorSamplePeriod = 0.000005;

  1. Set output voltage to 3V or 5V

scope.SetDigitalOutputVoltage(DigitalOutputVoltage.V3_0);

  1. CommitSettings must be called to make the samplePeriod setting effective

scope.CommitSettings();

  1. Enable digital output

scope.GeneratorToDigitalEnabled = true;

IWaveGenerator examples - Generate digital waves

Memories and registers

To use DeviceInterface, you don't actually need to understand these internals, so this is just a rough sketch of the functionality.

All 'smart' chips (PIC, FPGA, ADC) inside the SmartScope have their registers, typically bytes. These are the 'parameters' of certain functionalities of these chips. Examples:

  • FGPA: the TRIGGER_LEVEL register defines the voltage of the analog trigger level (FPGA register 7, see the FPGA register list)
  • ADC: bits 5 and 4 of register 6 in the ADC defines wheth er its data is in two's complement or simply offset binary (see the MAX19506 datasheet p22)

Therefore, some logic is required to convert from physical values to register values (eg GUI trigger slider to TRIGGER_LEVEL bytevalue). These conversions are implemented in DeviceInterface (see the TriggerValue setter method in SmartScopeSettings.cs).

MemoryRegister represents a register inside of a device. For efficiency's sake, they are cached, meaning the change of a register is not immediately written through to the device. Instead, you can change a bunch of registers and finally call Commit() on the containing DeviceMemory object to effectuate the register changes. To circumvent this chaching mechanism, use MemoryRegister.WriteImmediate().

The same goes for MemoryRegister.Get(): the cached value is returned. To first update the cache, use MemoryRegiter.Read().Get().

  • DeviceMemory, containing as set of MemoryRegister, is the abstract class used to implement all devices inside of the SmartScope.
  • ByteMemory inherits from DeviceMemory, providing an indexer [] returning ByteRegister.
  • Most memories are of the type ByteMemory

Hardware Interfaces

There's no need to understand this part to use the library, so here's just a concise explanation of the mechanisms.

InterfaceManager is a singleton instance instantiated by DeviceManager. Its function is to monitor the presence of a SmartScope USB interface ISmartScopeUsbInterface. It's implementation is OS-specific, hence 3 different implementations of both InterfaceManager and ISmartScopeUsbInterface.

When InterfaceManager detects a change in the presence of a ISmartScopeUsbInterface (a smartscope is (un)plugged into the USB port), it notifies DeviceManager which then decides to create or destroy a SmartScope instance and pass it further to your application.

SmartScope is instantiated with an ISmartScopeUsbInterface in its constructor, used for all hardware interfacing.

IScope Usage

  1. Create a DeviceConnectHandler(IDevice dev, bool connected) callback
  2. Instantiate a DeviceManager with a DeviceConnectHandler callback
  3. Start() the DeviceManager
  4. In your DeviceConnectHandler
  5. Check if the device got connected or disconnected
  6. Check if the IDevice is an IScope, if so, cast it
  7. Choose how to fetch data
    1. Using the aynchronous DataSource
    2. Using the synchronous IScope.GetScopeData
  8. Configure the IScope
    1. Set voltage and time range, sample period, viewport,...
    2. Set acquisition mode
    3. Set trigger
    4. Call IScope.CommitSettings()
    5. Set IScope.running = true
  9. If not using DataSource, start your loop which calls IScope.GetScopeData()

Whichever method you choose, you will end up with DataPackageScope objects coming out of the IScope or DataSource. Below is a detailed explanation of what it contains and how to use it.

DataSource

DataSource is a class beloning to an IScope which periodically calls IScope.GetScopeData() and calls all NewDataAvailableHandler callbacks registered to it, so you don't have to write your own data fetch loop.

Usage

  1. Add a NewDataAvailableHandler callback to IScope.DataSourceScope.OnNewDataAvailable
  2. Call IScope.DataSourceScope.Start()
  3. Configure your IScope and watch data coming in

DataPackageScope

This is the object returned by the IScope, containing all data you need to further process the scope measurement. Indeed, you can have changed IScope settings after an acquisition was started, therefore, when displaying or processing data, don't read back IScope properties but use the ones from the DataPackageScope.

There are a few global acquisition parameters (see source for inline documentation)

  • Acquisition ID
  • Timestamp
  • trigger holdoff
  • acquisition length
  • viewport settings
  • ...

Then there is also a set of per-channel data, contained in ChannelData objects, containing

  • The type of data: viewport, acquisition or overview (see table below)
  • The channel (i.e. AnalogChannel.ChB, DigitalChannel.Digi3,...)
  • The array of data
  • Whether it is partial
  • The sample period and time-offset to the beginning of the acquisition (for viewport data)

DataSourceType

DataSourceType Meaning
Viewport an up to 2kSa representation of the viewport data
Acquisition the full acquisition, up to 4MSa
Overview a 2kSa representation of the entire acquisition

Once a DataPackageScope object is obtained, you can retrieve the data by calling DataPackageScope.GetData(), providing the DataSourceType you're interested in and the channel. If the data is not present, NULL will be returned.

NOTE: As long as DataPackageScope.FullAcquisitionProgress is below 1, DataPackageScope.GetData will a ChannelData object with an incomplete array for DataSourceType.Acquisition.

NOTE: If you want to process and change the data array of a ChannelData object, be aware that IScope might still update (and append) to that array in the following cases:

DataSourceType Scenario
DataSourceType.Viewport IScope.Partial is true and the entire viewport was not entirely fetched
DataSourceType.Viewport or DataSourceType.Overview IScope.Rolling is true and the acquisition is updated as the acquisition buffer rolls by
DataSourceType.Acquisition The full acquisition buffer is still being read to the host, but a partial buffer is already returned by DeviceInterface. Monitor DataPackageScope.FullAcquisitionProgress to know if the ChannelData is complete

In general, it's safest to just copy the array contents instead of changing it.

deviceinterface's People

Contributors

karlp avatar louiecaulfield avatar madwizard-thomas avatar riemerg avatar tewarid avatar zeldin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deviceinterface's Issues

Can not stop the scope

Hello,
I have every thing running and can copy the data to a new array. However I can not make the scope run again, without shutting down.
These are buttons on a Windows form some work and some do not.
I have the scope set to Running False during configuration , and it takes all my config, after a commit
The data returned from the first click of the button2 is great, however read my comments ( Comments )for the next click.

I could really use some help
Thanks
George Zamiar
502-494-6792

     public void button4_Click_1(object sender, EventArgs e)
    {
        // STOP Button **This button never works**
        scope.CommitSettings();
        scope.Running = false;
            Application.DoEvents();
            scope.CommitSettings();
    }

    public void btnFireScope_Click(object sender, EventArgs e)
    {
       // Trigger **This button Never works**
        scope.ForceTrigger();
    }



    // Set scope to run
    public void button2_Click(object sender, EventArgs e)
    {
        // RUN BUTTON  **This button set the scope running, gets the first set of data and updates the Scope.Running.  However you do not hear it click and status never up dates to to "Armed"  **
        scope.Running = true;
        scope.CommitSettings();
    }

    // Increment trigger Up
    public void button1_Click(object sender, EventArgs e)
    {
        // INCREMENT plus  **This button works just fine**
        float InTrig = scope.TriggerValue.level + .20F;
        var tv = scope.TriggerValue;
        tv.level = InTrig;
        scope.TriggerValue = tv;
        scope.CommitSettings();
    }

    // Increment trigger Down
    public void button3_Click(object sender, EventArgs e)
    {
        
        // DECREMENT **This button works just fine**
        float InTrig = scope.TriggerValue.level - .020F;
        var tv = scope.TriggerValue;
        tv.level = InTrig;
        scope.TriggerValue = tv;
        scope.CommitSettings();
        Application.DoEvents();
    }
    private void tmrMain_Tick(object sender, EventArgs e)
    {
        if (scope != null)  **All these fields up Date**
        {
            label4.Text = DateTime.Now.ToString();
            label1.Text = "Scope is Runing: " +
                scope.Running.ToString();
            label2.Text = "Current Trigger Value: " +
                scope.TriggerValue.level.ToString();
            label3.Text = "Scope is Armed: " +
                scope.Armed.ToString();
            label5.Text = "Mode: " +
                scope.AcquisitionMode.ToString();
            label6.Text = "Awaiting Trig: " +
               scope.AwaitingTrigger.ToString();
            label7.Text="Scope Ready "+
               scope.Ready.ToString();
            textBox1.Text = scope.ToString();
            label8.Text = "Dat Source is Running: "+
                scope.DataSourceScope.IsRunning.ToString();
        }
        else if (scope==null)
        {
            label7.Text = "Scope Ready " +
               "Scope IS NULL"; **Never get Here**

        }
    }

    private void button5_Click(object sender, EventArgs e) **This button works just fine**
    {
        scope.AcquisitionMode = AcquisitionMode.SINGLE;

    }

    private void button6_Click(object sender, EventArgs e) **This button works just fine**
    {
        scope.AcquisitionMode = AcquisitionMode.NORMAL;

    }

how to get digital trigger working?

Hi,

I want to modify the SmartScopeConsole example in order to save LogicAnalyser data to a csv file.
Using

ChannelData d = p.GetData(ChannelDataSourceScope.Viewport, LogicAnalyserChannel.LA);

I get some data but it is either incomplete or not detailed enough.

Now I'd like to use DigitalTriggerValue.L but it never seems to be 'fired'.

I use:

	TriggerValue dtv = new TriggerValue();
	dtv.mode = TriggerMode.Digital;
	dtv.channel = null;
	scope.TriggerValue = dtv;

and modified the default trigger to Digital[ch] = DigitalTriggerValue.L;.

But as I said nothing happens. When using the UI (SmartScope.exe) the trigger works.

licensing clarification

Please add LICENSE or COPYING file to clarify under which license the source code in this repo is available.

how to get correct samples

Hi,

I want to modify the SmartScopeConsole example in order to save LogicAnalyser data to a csv file.
I managed to get some data but it is either incomplete or not detailed enough.
(using ChannelData d = p.GetData(ChannelDataSourceScope.Viewport, LogicAnalyserChannel.LA);)

I want to capture a UART async signal at 115200 baud that lasts 0.2s and be able to decode it (using sigrok).
I guess I should change AcquisitionLength and AcquisitionDepth but their effect on the results are a mystery to me.
Any help on this would be really appreciated.

Using the UI (SmartScope.exe) it works so the scope is able to do it.

setting and reading trigger level not working

//Trigger level never seems to be set or read, this code compiles and does do throw exceptions
private void button3_Click(object sender, EventArgs e)
{
//I have tried it both way running true and false
//scope.Running = false;
//scope.CommitSettings();
if (NewTrigLev == "1V")
{
TriggerValue trigger = new TriggerValue() // tried this method and the method in the else
{
channel = AnalogChannel.ChA,
edge = TriggerEdge.RISING,
level = 1.0f,
};
}
else if (NewTrigLev == "5V")
{
{
scope.TriggerValue.level = 5.0f;

            }
        }
        scope.Running = true;
        scope.CommitSettings();
        label7.Text = "Trigger level:   " + scope.TriggerValue.level.ToString();
        label6.Text = DateTime.Now.ToString(); 

}

bootstrap doesn't work on linux?

Last step fails...

$ mono .nuget/NuGet.exe restore DeviceInterface.Linux.sln
Could not load file or assembly or one of its dependencies.
  Could not load file or assembly or one of its dependencies.
  Could not load file or assembly or one of its dependencies.

Mono version

$ mono --version
Mono JIT compiler version 4.4.2 (Stable 4.4.2.11/f72fe45 Tue Aug  2 08:14:37 UTC 2016)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug 
	LLVM:          supported, not enabled.
	GC:            sgen

Seems to be nuget bustage?

$ mono  .nuget/NuGet.exe --help
Could not load file or assembly or one of its dependencies.
  Could not load file or assembly or one of its dependencies.
  Could not load file or assembly or one of its dependencies.

Any ideas?

which blob for which hw?

How do we detect what sort of hardware we have, to know what blob to load? How recent are these blobs? Is there version history somewhere? How do they correspond to the blob that the app loads?

Crash when Bonjour not installed on Windows

From forum: The SmartScopeServerUI.exe program crashes when I click the start button. This is on a fairly clean Windows 10 (x64) without bonjour installed. The Smartscope.exe itself does not have this problem. I found a thread in this forum that suggests to add a test on the availability of bonjour in SmartScope. Probably the SmartScopeServerUI does not test (properly) on the availability of bonjour/ZeroConf. I tested with version 0.11.0, 2017-225-21-0 and 0.12.0. if I install the bonjour print services then the problem is solved.

get aquisition without a trigger

Hi,

Using a trigger (acquisition mode SINGLE) I can get a full acquisition. Now I would like to have one without a trigger.

Waiting for FullAcquisitionFetchProgress >= 1 does not seem to work. It waits forever.

Combining multiple Viewport sets (p.GetData(ChannelDataSourceScope.Viewport,...)) results in weird data, as if the Viewport data are only triggered small chunks.

What is the best way to get an X number of samples starting from 'now'?

Cannot start smartscope application on Ubuntu 16.04

when I try to start it, it crashes...

Any thoughts?

$ smartscope
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentOutOfRangeException: Value has to be >= 0.
Parameter name: sourceIndex
  at System.Array.Copy (System.Array sourceArray, Int32 sourceIndex, System.Array destinationArray, Int32 destinationIndex, Int32 length) <0x7fef5e655a00 + 0x00323> in <filename unknown>:0 
  at System.Array.Copy (System.Array sourceArray, Int64 sourceIndex, System.Array destinationArray, Int64 destinationIndex, Int64 length) <0x7fef5e655f10 + 0x000b0> in <filename unknown>:0 
  at LabNation.DeviceInterface.Devices.DummyScope.CropWave[T] (UInt32 outputLength, LabNation.DeviceInterface.Devices.T[] sourceWave, Int32 triggerIndex, Int32 holdoff) <0x415203a0 + 0x00099> in <filename unknown>:0 
  at LabNation.DeviceInterface.Devices.DummyScope.GetScopeData () <0x41515860 + 0x00e3f> in <filename unknown>:0 
  at LabNation.DeviceInterface.DataSources.DataSource.DataFetchThreadStart () <0x41513d20 + 0x00062> in <filename unknown>:0 
  at System.Threading.ThreadHelper.ThreadStart_Context (System.Object state) <0x7fef5e4b1010 + 0x00099> in <filename unknown>:0 
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, Boolean preserveSyncCtx) <0x7fef5e4af850 + 0x0016e> in <filename unknown>:0 
  at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, Boolean preserveSyncCtx) <0x7fef5e4af820 + 0x00020> in <filename unknown>:0 
  at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state) <0x7fef5e4af770 + 0x00059> in <filename unknown>:0 
  at System.Threading.ThreadHelper.ThreadStart () <0x7fef5e4b11d0 + 0x0002e> in <filename unknown>:0 
AL lib: (EE) alc_cleanup: 2 devices not closed
$

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.