Skip to content

feat: (WIP) Add support to nannou_laser for lasercube devices #1024

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: bevy-refactor
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ hrtf = "0.8"
ilda-idtf = "0.1"
image = { version = "0.25", default-features = false }
isf = "0.1.0"
lasercube = { path = "../lasercube/crates/lasercube" }
lasy = "0.4"
lyon = "1.0"
noise = "0.7"
Expand Down
1 change: 1 addition & 0 deletions nannou_laser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ crate-type = ["rlib", "staticlib", "cdylib"]
[dependencies]
ether-dream.workspace = true
ilda-idtf = { workspace = true, optional = true }
lasercube.workspace = true
lasy.workspace = true
thiserror.workspace = true

Expand Down
37 changes: 21 additions & 16 deletions nannou_laser/src/dac.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Items related to DACs and DAC detection.

use crate::protocol;
use std::io;
use std::sync::atomic::{self, AtomicBool};
use std::sync::mpsc;
Expand All @@ -15,17 +16,16 @@ impl<F> DetectedDacCallback for F where F: FnMut(io::Result<DetectedDac>) {}
/// It should be possible to use this to uniquely identify the same DAC on different occasions.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Id {
EtherDream { mac_address: [u8; 6] },
EtherDream(protocol::etherdream::Id),
LaserCube(protocol::lasercube::Id),
}

/// An available DAC detected on the system.
#[derive(Clone, Debug)]
pub enum DetectedDac {
/// An ether dream laser DAC discovered via the ether dream protocol broadcast message.
EtherDream {
broadcast: ether_dream::protocol::DacBroadcast,
source_addr: std::net::SocketAddr,
},
EtherDream(protocol::etherdream::DetectedDac),
LaserCube(protocol::lasercube::DetectedDac),
}

/// An iterator yielding laser DACs available on the system as they are discovered.
Expand All @@ -51,25 +51,28 @@ impl DetectedDac {
/// The maximum point rate allowed by the DAC.
pub fn max_point_hz(&self) -> u32 {
match self {
DetectedDac::EtherDream { ref broadcast, .. } => broadcast.max_point_rate as _,
DetectedDac::EtherDream(dac) => dac.max_point_hz(),
DetectedDac::LaserCube(dac) => dac.max_point_hz(),
}
}

/// The number of points that can be stored within the buffer.
pub fn buffer_capacity(&self) -> u32 {
match self {
DetectedDac::EtherDream { ref broadcast, .. } => broadcast.buffer_capacity as _,
DetectedDac::EtherDream(dac) => dac.buffer_capacity(),
DetectedDac::LaserCube(dac) => dac.buffer_capacity(),
}
}

/// A persistent, unique identifier associated with the DAC (like a MAC address).
/// A persistent, unique identifier associated with the DAC (like a MAC
/// address).
///
/// It should be possible to use this to uniquely identify the same DAC on different occasions.
/// It should be possible to use this to uniquely identify the same DAC on
/// different occasions.
pub fn id(&self) -> Id {
match self {
DetectedDac::EtherDream { ref broadcast, .. } => Id::EtherDream {
mac_address: broadcast.mac_address,
},
DetectedDac::EtherDream(dac) => Id::EtherDream(dac.id()),
DetectedDac::LaserCube(dac) => Id::LaserCube(dac.id()),
}
}
}
Expand Down Expand Up @@ -108,10 +111,12 @@ impl Iterator for DetectDacs {
let res = self.dac_broadcasts.next()?;
match res {
Err(err) => Some(Err(err)),
Ok((broadcast, source_addr)) => Some(Ok(DetectedDac::EtherDream {
broadcast,
source_addr,
})),
Ok((broadcast, source_addr)) => Some(Ok(DetectedDac::EtherDream(
protocol::etherdream::DetectedDac {
broadcast,
source_addr,
},
))),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions nannou_laser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod ffi;
#[cfg(feature = "ilda-idtf")]
pub mod ilda_idtf;
pub mod point;
pub mod protocol;
pub mod stream;
pub mod util;

Expand Down
4 changes: 4 additions & 0 deletions nannou_laser/src/protocol.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Implementations for each supported protocol (etherdream, lasercube).

pub mod etherdream;
pub mod lasercube;
29 changes: 29 additions & 0 deletions nannou_laser/src/protocol/etherdream.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Represent etherdream device IDs by their MAC address.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Id {
pub mac_address: [u8; 6],
}

/// An ether dream laser DAC discovered via the ether dream protocol broadcast
/// message.
#[derive(Clone, Debug)]
pub struct DetectedDac {
pub broadcast: ether_dream::protocol::DacBroadcast,
pub source_addr: std::net::SocketAddr,
}

impl DetectedDac {
pub fn max_point_hz(&self) -> u32 {
self.broadcast.max_point_rate as u32
}

pub fn buffer_capacity(&self) -> u32 {
self.broadcast.buffer_capacity as u32
}

pub fn id(&self) -> Id {
Id {
mac_address: self.broadcast.mac_address,
}
}
}
28 changes: 28 additions & 0 deletions nannou_laser/src/protocol/lasercube.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Represent lasercube device IDs by their serial number.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Id {
pub serial_number: [u8; 6],
}

/// A lasercube discovered via a `GET_FULL_INFO` response.
#[derive(Clone, Debug)]
pub struct DetectedDac {
info: lasercube::core::LaserInfo,
source_addr: std::net::SocketAddr,
}

impl DetectedDac {
pub fn max_point_hz(&self) -> u32 {
self.info.header.max_dac_rate
}

pub fn buffer_capacity(&self) -> u32 {
self.info.header.rx_buffer_size as u32
}

pub fn id(&self) -> Id {
Id {
serial_number: self.info.header.serial_number,
}
}
}
9 changes: 6 additions & 3 deletions nannou_laser/src/stream/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::time::Duration;
use thiserror::Error;

use crate::util::{clamp, map_range};
use crate::Inner as ApiInner;
use crate::{protocol, Inner as ApiInner};
use crate::{DetectedDac, RawPoint};

/// The function that will be called when a `Buffer` of points is requested.
Expand Down Expand Up @@ -649,11 +649,14 @@ where
F: RenderFn<M>,
{
// Currently only ether dream is supported, so retrieve the broadcast and addr.
// TODO: Refactor this into the protocol/etherdream.rs submodule, add
// similar implementation for `lasercube` inspired by `circle.rs` example.
let (broadcast, src_addr) = match dac {
DetectedDac::EtherDream {
DetectedDac::EtherDream(protocol::etherdream::DetectedDac {
broadcast,
source_addr,
} => (broadcast, source_addr),
}) => (broadcast, source_addr),
_ => todo!("Implement lasercube handling"),
};

// A buffer for collecting model updates.
Expand Down
Loading