laser_dac/backend.rs
1//! DAC backend trait and implementations for the streaming API.
2//!
3//! This module provides the [`StreamBackend`] trait that all DAC backends must
4//! implement, as well as implementations for all supported DAC types.
5
6use crate::types::{DacCapabilities, DacType, LaserPoint};
7
8// Re-export error types for backwards compatibility
9pub use crate::error::{Error, Result};
10
11// =============================================================================
12// StreamBackend Trait
13// =============================================================================
14
15/// Write result from a backend chunk submission.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum WriteOutcome {
18 /// The chunk was accepted and written.
19 Written,
20 /// The device cannot accept more data right now.
21 WouldBlock,
22}
23
24/// Backend trait for streaming DAC output.
25///
26/// All backends must implement this trait to support the streaming API.
27/// The key contract is uniform backpressure: `try_write_chunk` must return
28/// `WriteOutcome::WouldBlock` when the device cannot accept more data,
29/// enabling the stream scheduler to pace output correctly.
30pub trait StreamBackend: Send + 'static {
31 /// Returns the DAC type for this backend.
32 fn dac_type(&self) -> DacType;
33
34 /// Returns the device capabilities.
35 fn caps(&self) -> &DacCapabilities;
36
37 /// Connect to the device.
38 fn connect(&mut self) -> Result<()>;
39
40 /// Disconnect from the device.
41 fn disconnect(&mut self) -> Result<()>;
42
43 /// Returns whether the device is connected.
44 fn is_connected(&self) -> bool;
45
46 /// Attempt to write a chunk of points at the given PPS.
47 ///
48 /// # Contract
49 ///
50 /// This is the core backpressure mechanism. Implementations must:
51 ///
52 /// 1. Return `WriteOutcome::WouldBlock` when the device cannot accept more data
53 /// (buffer full, not ready, etc.).
54 /// 2. Return `WriteOutcome::Written` when the chunk was accepted.
55 /// 3. Return `Err(...)` only for actual errors (disconnection, protocol errors).
56 fn try_write_chunk(&mut self, pps: u32, points: &[LaserPoint]) -> Result<WriteOutcome>;
57
58 /// Stop output (if supported by the device).
59 fn stop(&mut self) -> Result<()>;
60
61 /// Open/close the shutter (if supported by the device).
62 fn set_shutter(&mut self, open: bool) -> Result<()>;
63
64 /// Best-effort estimate of points currently queued in the device.
65 ///
66 /// Not all devices can report this. Return `None` if unavailable.
67 fn queued_points(&self) -> Option<u64> {
68 None
69 }
70}
71
72// =============================================================================
73// Re-exports from protocol-specific backends
74// =============================================================================
75
76#[cfg(feature = "helios")]
77pub use crate::protocols::helios::HeliosBackend;
78
79#[cfg(feature = "ether-dream")]
80pub use crate::protocols::ether_dream::EtherDreamBackend;
81
82#[cfg(feature = "idn")]
83pub use crate::protocols::idn::IdnBackend;
84
85#[cfg(feature = "lasercube-wifi")]
86pub use crate::protocols::lasercube_wifi::LasercubeWifiBackend;
87
88#[cfg(feature = "lasercube-usb")]
89pub use crate::protocols::lasercube_usb::LasercubeUsbBackend;