Skip to main content

elata_eeg_hal/
device.rs

1//! Core device abstraction trait
2
3use crate::channel::ChannelConfig;
4use crate::error::Result;
5use crate::sample::SampleBuffer;
6
7/// State of an EEG device
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum DeviceState {
10    /// Device is not connected
11    Disconnected,
12    /// Device is connected but not streaming
13    Connected,
14    /// Device is actively streaming data
15    Streaming,
16}
17
18/// Information about an EEG device
19#[derive(Debug, Clone)]
20pub struct DeviceInfo {
21    /// Human-readable device name
22    pub name: String,
23    /// Device manufacturer
24    pub manufacturer: String,
25    /// Sample rate in Hz
26    pub sample_rate: u16,
27    /// Channel configuration
28    pub channels: ChannelConfig,
29}
30
31impl DeviceInfo {
32    pub fn new(
33        name: impl Into<String>,
34        manufacturer: impl Into<String>,
35        sample_rate: u16,
36        channels: ChannelConfig,
37    ) -> Self {
38        Self {
39            name: name.into(),
40            manufacturer: manufacturer.into(),
41            sample_rate,
42            channels,
43        }
44    }
45}
46
47/// Core trait for EEG devices
48///
49/// This trait provides a unified interface for all EEG devices, whether
50/// physical (Muse S, OpenBCI) or synthetic (for testing).
51///
52/// # Lifecycle
53///
54/// 1. Create device instance
55/// 2. Call `connect()` to establish connection
56/// 3. Call `start_stream()` to begin data acquisition
57/// 4. Call `read_samples()` to get data
58/// 5. Call `stop_stream()` when done
59/// 6. Call `disconnect()` to release resources
60pub trait EegDevice {
61    /// Get device information
62    fn info(&self) -> DeviceInfo;
63
64    /// Get current device state
65    fn state(&self) -> DeviceState;
66
67    /// Connect to the device
68    fn connect(&mut self) -> Result<()>;
69
70    /// Disconnect from the device
71    fn disconnect(&mut self) -> Result<()>;
72
73    /// Start streaming data
74    fn start_stream(&mut self) -> Result<()>;
75
76    /// Stop streaming data
77    fn stop_stream(&mut self) -> Result<()>;
78
79    /// Read available samples into the buffer
80    ///
81    /// Returns the number of samples read. This may be 0 if no data is available.
82    /// The buffer is NOT cleared before reading; new samples are appended.
83    fn read_samples(&mut self, buffer: &mut SampleBuffer) -> Result<usize>;
84
85    /// Check if the device is connected
86    fn is_connected(&self) -> bool {
87        matches!(
88            self.state(),
89            DeviceState::Connected | DeviceState::Streaming
90        )
91    }
92
93    /// Check if the device is streaming
94    fn is_streaming(&self) -> bool {
95        self.state() == DeviceState::Streaming
96    }
97}
98
99/// Extension trait for devices that support configuration
100pub trait ConfigurableDevice: EegDevice {
101    /// Set the sample rate (if supported by the device)
102    fn set_sample_rate(&mut self, rate: u16) -> Result<()>;
103
104    /// Enable or disable specific channels
105    fn set_channels_enabled(&mut self, enabled: &[bool]) -> Result<()>;
106}