Skip to content

About

0364: This repository contains the hardware, firmware, and software related to the Harp quad DAC

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

69 Commits

Folders and files

Repository files navigation

harp.device.quac

hardware, firmware, and software source files for a Harp-compatible 4-channel Digital-to-Analog Converter.

Specs

  • Analog Output Channels: 4
  • Bit depth: 16-bit
  • Update Rate: 2.288 [KHz] to 500 [KHz] (selectable per-channel)
    • this is the rate at which a new output value is selected.
  • Voltage Swing: ±10 [V]
  • RMS noise at the zero voltage setting: ~±2.5 [mV]
  • absolute deviation from 0 [V]: ±2.5 [mV]
  • Power Input: 12-24 [V]
  • Power Input Plug: 2.1 x 5.5mm barrel jack (positive center)
  • Reverse Polarity protected.
  • Additional M4 ground lug provided for de-noising.
  • Open source hardware, firmware, and software.
  • Cost-effective at < $300 USD to manufacture a single unit.
  • Preview the hardware design online with KiCanvas.
  • Enclosure CAD Model

Trigger Specs

  • Trigger options
    • external trigger
    • software trigger
  • User-selectable external trigger mapping, i.e: any input trigger can be setup to trigger any number of analog output channels.
  • True simultaneous triggering in cases where multiple waveforms are triggered at the same time.

Waveform Player Specs

The device features 3 ways to play waveforms: either through the two built-in primitive waveform generators or by playing waveforms pre-uploaded to an SD card.

File Player Specs

  • Max Data Storage: limited by size of SD card
  • Max file length for a single file: 4GB
  • File names: user-specifiable with a 32-character limit.
  • Format: 16-bit Pulse Code Modulation (PCM)
    • -10 Volts corresponds to 0
    • 0 Volts corresponds to ~32768
    • 10 Volts corresponds to 65535

Harp Specs

The Quac board is a fully Harp-protocol-compliant device built on top of the Harp Pico Core.

  • Harp Device ID: 1411
  • Harp Events
    • Waveform Start (per-channel)
    • Waveform Finished (per-channel)

Alternates

The harp.device.quac board follows a legacy of many other devices that came before it. For similar devices, have a look at:

Ordering ➡ 💸

Order fully-assembled boards directly from PCBWay.

These printed circuit boards are made on-demand.

Generating Waveforms ﮩ٨ـﮩﮩ٨ـ

There are two ways to generate waveforms: either with one of two primitive waveform generators or by playing files from the SD card. These options are referred to as waveform Players.

Setting up and playing a waveform is a simple process for each Analog Output (AO) channel.

  1. Specify any external input trigger conditions for the output channel.
  2. Specify the waveform Player.
  3. Specify the Player's settings.
  4. Wait until the Player is ready (< 50[ms] of wait time for the player to apply the settings and arm the waveform).
  5. Trigger the Player either via software command or by applying external input to the corresponding external input pins.

For fully worked examples of the above steps, see the examples in the software folder.

Note

While waveforms on the SD card will remain on the card until they are deleted, Player settings for any Player do not persist across device power-cycles or resets.

Player Settings are detailed below for each Player.

Common Settings

The following settings are common to each Player.

  • cycles: number of iterations of the current settings (will probably be 1 in most cases).
  • duration_us: duration in microseconds to play the waveform or 0 to either play-forever (if the source is infinite ie: periodic functions) or play-to-completion (if the source is finite i.e: files on the SD card).
  • update_frequency_hz: rate at which samples are produced (max 500 [KHz]).

SinePlayer Waveforms

Settings

  • frequency_hz: sine wave frequency in hertz
  • amplitude_volts: "center-to-peak" amplitude in volts
  • vertical_shift_volts: vertical shift in volts
  • normalized_phase_shift: period shift normalized to -1.0 (max right shift) to 1.0 (max left shift)

Example Settings: play a 10Hz sine wave for 3 seconds

Setting Value Note
cycles 1 play the following settings once
duration_us 3000000 play for 3 seconds
update_frequency_hz 10000 rate at which to produce new samples
frequency_hz 10 sine wave frequency
amplitude_volts 0.5 result will be 1 [V] peak-to-peak
vertical_shift_volts 0.5 result will span 0 [V] to 1 [V]
normalized_phase_shift 0 no phase shift

Example Settings: play a 10Hz sine wave forever

Setting Value Note
cycles 1
duration_us 0 play forever (until aborted)
update_frequency_hz 10000
frequency_hz 10
amplitude_volts 0.5
vertical_shift_volts 0
normalized_phase_shift 0

TrapezoidPlayer Waveforms

Settings

(Inherits all Common Settings and Sine Player Settings)

  • ramp_on_us: time in microseconds to rise from lowest to peak value.
  • pulse_width_us: the total pulse width (including ramp-on and ramp-off duration of the waveform in microseconds.
  • ramp_off_us: time in microseconds to fall from peak to lowest value.

FilePlayer Waveforms from the SD Card 💾

Settings

  • path: filepath on the SD card (32-character limit max)

Example Settings: play a file once

Setting Value Note
cycles 1 play the following settings once
duration_us 0 play the file to completion
update_frequency_hz 500000 max update rate (might be different depending on file).
path channel_0.bin assumes this file exists at the top level folder in the SD card

Example Settings: play a file multiple times

Setting Value Note
cycles 3 loop back and play the entire file 3 times
duration_us 0
update_frequency_hz 500000
path channel_0.bin

The quac board reads files in 16-bit little-endian Pulse-Code Modulation (PCM) format. There are a few options for generating waveforms in this format.

Upscaling Existing Files 💽

It's possible to convert existing audio files to a format compatible with the quac board using ffmpeg. To upscale an existing *.wav file to a 500KHz update rate, use:

ffmpeg -i example.wav -f u16le -ar 500000 output.raw

With numpy 💻

For more complicated waveforms that do not derive from an existing audio file, we recommend using numpy.

Here's an example that generates the North American Ringing Tone, which is the sum of a 440Hz and 480Hz sine wave.

import numpy as np

NUM_SAMPLES = int(5e6) # 5 million samples @ 500KSs -> 10 seconds of data.
SAMPLES_PER_SECOND = 500000.
FULL_SCALE_RANGE = (1 << 16) - 1 # 16 bit resolution
SECONDS = NUM_SAMPLES/SAMPLES_PER_SECOND
FILENAME = f"channel_0.bin"

t = np.linspace(0, SECONDS, NUM_SAMPLES)
x = np.zeros(NUM_SAMPLES)

# make sine wave. offset it to uint16 range: 0-65535
for freq in [440, 480]:
    x += (np.sin(2 * np.pi * freq * t)+1)/2 * FULL_SCALE_RANGE/2

# Write result to file in 16-bit little-endian format.
with open(FILENAME, "wb") as file:
    x.astype("<u2").tofile(file)

Uploading Waveforms ♒︎➝💾

Currently waveforms must be uploaded to the SD card manually.

Warning

Power down the device before removing or inserting the SD card.

Playing Waveforms 🎶

There are two ways to trigger a configured waveform to play: via software command or through the device's external triggers labeled DI0, DI1, DI2, and DI3.

Before triggering a waveform, you must

Software Triggering

For fully worked examples in both Bonsai and Python, see the software examples folder.

External Triggering

By default the device's power-on-reset behavior is setup to: setup external triggers such that pins DIO - DI3 correspond to playing output pins A0 - A3 respectively.

Trigger mapping is configurable! Any input trigger can be configured to trigger any number of outputs. To alter the trigger mapping, you must use software commands through either Bonsai or Python.

Compatible SD Cards 💾

During normal operation, up-to-four waveforms stored on the SD card are read (interleaved) at 4MB per second. With the extra overhead of switching between files, the SD card must be able to support read speeds ≥8MB per second. In theory, any Class 10 SD Card formatted in FAT32 format should be compatible.

But since card performance can vary, here's a list of tested cards:

Vendor Model
Samsung Pro Plus 8GB Smart Card
GIGASTONE Industrial 8GB MLC

Working Principle

The following section details how the underlying firmware generates waveforms.

Selectable Player Architecture

Each channel features a modular approach to dividing up the work of playing waveforms.

The level closest to the hardware is a driver that wraps a custom PIO program to communicate over SPI to each LTC2641 DAC chip.

The next stage up is a shared double buffer and two DMA channels responsible for ensuring that the driver receives an uninterrupted, steady stream of bytes paced by a DMA Timer setup to match the user-requested playback rate. Inspecting the state of the double buffer is implemented by reading single registers native to the Pico's DMA peripherals to eliminate the need to implement mutex locks to check multiple locations in memory concurrently.

The layer above features one of multiple ways of generating data. These Players are responsible for producing a sequence of bytes up to the limits specified by the user's waveform settings. Each Player is derived from a base class that manages sending data to the corresponding available buffer from the downstream double buffer and manages sequence arming and termination.

In the full architecture, four copies of the above pipeline exist like so:

The MultiTransferManager connects to each double buffer and driver and handles triggering an armed transfer, and it guarantees that multiple simultaneous requests to start a transfer occur simultaneously.

FilePlayer Streaming Pipeline

Waveforms are read interleaved from their sources in "chunks" of 16384 samples at a time and then pushed into double buffers such that the resulting output plays waveforms concurrently without interruption.

Buffer size was selected to be large enough such that data from the SD card is can be read faster than it needs to sent to the downstream DAC drivers. This setup was tested in the worst-case scenario where 4 files are being read at once.

A single CPU core is dedicated to this task of reading waveform sources and topping off buffers while the other core handles Harp communication, settings configuration, and waveform start/stop inputs.

Updating the Firmware

New firmware is available on the Releases Page. To upload new firmware to the device, do the following:

  1. Ensure that the board is connected to a PC with the USB cable.
  2. Power down the board. (Note that power comes from the barrel jack, not the USB cable.)
  3. Power on the board with the BOOTSEL button held down. Then release the BOOTSEL button once the board has been powered up. The device will now appear on the connected PC as a flash drive. See the figure below to identify the BOOTSEL button. You may need to use a hex key to access this button with the case lid attached.

  1. Drag and drop the *.uf2 firmware file into the flash drive's top level directory. The flash drive should disappear indicating that the firmware upload worked. The device now has new firmware.

Known Limitations

Currently the device has some known limits, most of which are planned to be eclipsed by future firmware releases. This non-comprehensive list includes:

For a full list of issues, head over to the project's issues page.

About

0364: This repository contains the hardware, firmware, and software related to the Harp quad DAC

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages