Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WaveFormsSDK.jl

Julia bindings for Digilent's WaveForms SDK — Analog Discovery, Digital Discovery, ADP and DPS hardware.

using WaveFormsSDK, Unitful

Device() do dev
    scope = AnalogIn(dev)
    configure!(scope[1]; enabled = true, range = 5u"V")
    configure!(scope; frequency = 100u"kHz", samples = 4096)
    trigger!(scope; source = TriggerSource.DetectorAnalogIn, level = 0.5u"V", slope = Slope.Rise)

    data = acquire(start!(scope))       # 4096×2 Matrix of volts
end

Install

Install the WaveForms application (which bundles the SDK), then:

] add https://github.com/notthetup/waveformssdk.jl

The library is located at load time: ENV["WAVEFORMS_DWF_PATH"] if set, otherwise /Library/Frameworks/dwf.framework/dwf (macOS), libdwf.so (Linux) or dwf.dll (Windows). isavailable() tells you whether it was found without throwing.

No hardware? Use a demo device

The SDK ships virtual devices that simulate acquisition, generation and even a W1 → 1+ loopback. The entire test suite runs on them.

devices(demo = true)                    # 11 virtual devices
Device(demo = "Analog Discovery 3")     # open one

Conventions

  • Channels are 1-based. scope[1] is the first channel; the 0-based index the C API wants never surfaces.
  • Units in, units out. Any Unitful quantity of the right dimension is accepted, and a bare number is taken to already be in the natural unit — 1u"MHz", 1e6 and 1000u"kHz" are the same sample rate. Sample buffers come back as Vector{...V}; ustrip(data) aliases the same memory, so dropping the units is free.
  • Instruments are their channels. AnalogIn, AnalogOut and DigitalOut are AbstractVectors, so for ch in scope, length, map and friends work.
  • configure! batches. Each keyword is one SDK setter, but the whole call is a single device round trip rather than one per keyword.
  • Failures throw. Every SDK call is checked; DwfError carries the driver's message and the C function that produced it.

Instruments

AnalogIn oscilloscope — configure!, trigger!, start!, wait, acquire, record
AnalogOut waveform generator — standard and custom waveforms, AM/FM via node =
AnalogIO supplies, references and monitors — supplies(dev), aio["System Monitor"][:Temp]
DigitalIO static pins — dio[1], configure!(dio; outputenable, output)
DigitalIn logic analyzer — acquire(la, UInt16)
DigitalOut pattern generator — configure!(pg[1]; frequency = 1u"MHz", duty = 0.5)

Device configurations

Devices trade buffer depth between instruments, and the choice is fixed at open. On an Analog Discovery 3 the AnalogIn buffer ranges 4096…32768 across six configurations:

info = only(i for i in devices() if i.name == "Analog Discovery 3")
configurations(info)                     # the table
Device(info; config = 1)                 # 32768-sample scope buffer

Supplies are discovered

Supply channels are found by asking the device, not by index — an AD3 reports V+/V-, a DPS3340 reports Output 1…3, an ADP3450 reports only DVCC.

ps = supplies(dev)
configure!(ps["V+"]; voltage = 3.3u"V", enabled = true)
ps["V+"][:current]
reset!(ps)          # clears a latched overcurrent trip

Closing

close(dev) stops the instruments by default, rather than inheriting whatever the WaveForms GUI last set. Use onclose!(dev, :continue) to leave outputs live, or :shutdown to power the device down. closeall() runs at exit; the do-block form of Device closes on the way out either way.

Hardware notes

Measured on an Analog Discovery 3 (rev 3, SDK 3.23.4) — things the API cannot hide:

  • Supply rails ramp. Reading a supply back immediately after setting it returns a mid-ramp value. A 1.8 V → 3.3 V step reads 3.20 V at 250 ms and settles to 3.31 V by 500 ms. Sleep before you assert.
  • record loses samples if you outrun USB. Two channels stream cleanly at 100 kHz; at 20 MHz roughly a third are lost. Losses leave a gap — the returned rows are no longer evenly spaced — so record throws SampleLoss unless you pass onloss = :warn or :ignore.
  • One process at a time. The WaveForms GUI holds the device exclusively; Device() will tell you so rather than failing obscurely.
  • AnalogIn re-enables channels on start, so acquire returns every channel rather than trusting the enable flags. Use acquire(scope[1]) for just one.

Not covered yet

Protocol engines (UART/SPI/I²C/CAN/SWD), the impedance analyzer, FDwfSpectrum* (DSP.jl and FFTW.jl do it better), FIR/IIR channel filters, 16-bit raw status readers, compressed digital capture, and 64-bit DIO masks for Digital Discovery's 40+ pins.

Tests

] test WaveFormsSDK

Runs entirely on demo devices; skips with a warning if the SDK is not installed. examples/wavegen_loopback.jl is the hardware smoke test — wire W1 to 1+ and run it with WAVEFORMS_HW=1.

About

Julia wrapper around the Digilent Waveforms SDK

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages