laser-dac
Unified DAC backend abstraction for laser projectors.
This crate provides a complete solution for communicating with various laser DAC hardware:
- Discovery: Automatically find connected DAC devices (USB and network)
- Streaming: Blocking and callback modes with backpressure handling
- Backends: Unified interface for all DAC types
This crate does not apply any additional processing on points (like blanking), except to make it compatible with the target DAC.
⚠️ Warning: use at your own risk! Laser projectors can be dangerous.
Supported DACs
| DAC | Connection | Verified | Notes |
|---|---|---|---|
| Helios | USB | ✅ | |
| Ether Dream | Network | ✅ | |
| IDN (ILDA Digital Network) | Network | ✅ | IDN is a standardized protocol. We tested with HeliosPRO |
| LaserCube WiFi | Network | ✅ | Recommend to not use through WiFi mode; use LAN only |
| LaserCube USB / Laserdock | USB | ✅ |
All DACs have been manually verified to work.
Quick Start
Connect your laser DAC and run an example. For full API details, see the documentation.
# or:
# callback mode (DAC-driven timing):
# frame mode (using FrameAdapter):
# reconnecting session (auto-reconnect on disconnect):
# audio-reactive (requires microphone):
The examples run continuously until you press Ctrl+C.
Streaming Modes
There are two ways to stream points to a DAC:
Blocking Mode
You control timing by calling next_request() which blocks until the DAC needs more data:
use ;
let devices = list_devices?;
let device = open_device?;
let config = new; // 30k points per second
let = device.start_stream?;
stream.control.arm?; // Enable laser output
loop
Callback Mode
The DAC drives timing by invoking your callback whenever it's ready for more data:
use ;
let devices = list_devices?;
let device = open_device?;
let config = new;
let = device.start_stream?;
stream.control.arm?;
let exit = stream.run?;
Return Some(points) to continue streaming, or None to signal completion.
Reconnecting Session (optional)
If you want automatic reconnection by device ID, use ReconnectingSession:
use ;
use Duration;
let mut session = new
.with_max_retries
.with_backoff
.on_disconnect
.on_reconnect;
// Arm output as usual (this persists across reconnects)
session.control.arm?;
let exit = session.run?;
Note: ReconnectingSession uses open_device() internally, so it won't include
external discoverers registered on a custom DacDiscovery.
Coordinate System
All backends use normalized coordinates:
- X: -1.0 (left) to 1.0 (right)
- Y: -1.0 (bottom) to 1.0 (top)
- Colors: 0-65535 for R, G, B, and intensity
Each backend handles conversion to its native format internally.
Data Types
| Type | Description |
|---|---|
DacInfo |
DAC metadata (name, type, capabilities) |
Dac |
Opened DAC ready for streaming |
Stream |
Active streaming session |
ReconnectingSession |
Stream wrapper with automatic reconnect |
StreamConfig |
Stream settings (PPS, chunk size) |
ChunkRequest |
Request for points from the DAC |
LaserPoint |
Single point with position (f32) and color (u16) |
DacType |
Enum of supported DAC hardware |
Features
By default, all DAC protocols are enabled via the all-dacs feature.
DAC Features
| Feature | Description |
|---|---|
all-dacs |
Enable all DAC protocols (default) |
usb-dacs |
Enable USB DACs: helios, lasercube-usb |
network-dacs |
Enable network DACs: ether-dream, idn, lasercube-wifi |
helios |
Helios USB DAC |
lasercube-usb |
LaserCube USB (LaserDock) DAC |
ether-dream |
Ether Dream network DAC |
idn |
ILDA Digital Network DAC |
lasercube-wifi |
LaserCube WiFi DAC |
For example, to enable only network DACs:
[]
= { = "*", = false, = ["network-dacs"] }
Other Features
| Feature | Description |
|---|---|
serde |
Enable serde serialization for DacType and EnabledDacTypes |
USB DAC Requirements
USB DACs (helios, lasercube-usb) use rusb which requires CMake to build.
Development Tools
IDN Simulator
The repository includes a debug simulator (in tools/idn-simulator/) that acts as a virtual IDN laser DAC. This is useful for testing and development without physical hardware.
# Build and run the simulator
# With custom options
Features:
- Responds to IDN discovery (appears as a real DAC)
- Renders received laser frames as connected lines
- Handles blanking (intensity=0 creates gaps between shapes)
- Shows frame statistics (frame count, point count, client address)
Usage:
When the simulator is running, launch your work that scans for IDN devices. You can use this crate, or any other tool that supports IDN!
For a simple test, you can run one of our examples: cargo run --example stream -- circle
CLI Options:
| Option | Description | Default |
|---|---|---|
-n, --hostname |
Hostname in scan responses | IDN-Simulator |
-s, --service-name |
Service name in service map | Simulator Laser |
-p, --port |
UDP port to listen on | 7255 |
Acknowledgements
- Helios DAC: heavily inspired from helios-dac
- Ether Dream DAC: heavily inspired from ether-dream
- Lasercube USB / WIFI: inspired from ildagen (ported from C++ to Rust)
- IDN: inspired from helios_dac (ported from C++ to Rust)
License
MIT