laser_dac/protocols/lasercube_usb/
protocol.rs1use crate::point::LaserPoint;
4use std::time::Duration;
5
6pub const CONTROL_TIMEOUT: Duration = Duration::from_millis(1000);
8
9pub const LASERDOCK_VID: u16 = 0x1fc9;
11
12pub const LASERDOCK_PID: u16 = 0x04d8;
14
15pub const CONTROL_INTERFACE: u8 = 0;
17
18pub const DATA_INTERFACE: u8 = 1;
20
21pub const DATA_ALT_SETTING: u8 = 1;
23
24pub const ENDPOINT_CONTROL_OUT: u8 = 0x01;
26
27pub const ENDPOINT_CONTROL_IN: u8 = 0x81;
29
30pub const ENDPOINT_DATA_OUT: u8 = 0x03;
32
33pub const CONTROL_PACKET_SIZE: usize = 64;
35
36pub const CMD_SET_OUTPUT: u8 = 0x80;
39pub const CMD_GET_OUTPUT: u8 = 0x81;
41pub const CMD_SET_DAC_RATE: u8 = 0x82;
43pub const CMD_GET_DAC_RATE: u8 = 0x83;
45pub const CMD_GET_MAX_DAC_RATE: u8 = 0x84;
47pub const CMD_GET_SAMPLE_ELEMENT_COUNT: u8 = 0x85;
49pub const CMD_GET_ISO_PACKET_SAMPLE_COUNT: u8 = 0x86;
51pub const CMD_GET_MIN_DAC_VALUE: u8 = 0x87;
53pub const CMD_GET_MAX_DAC_VALUE: u8 = 0x88;
55pub const CMD_GET_RINGBUFFER_SAMPLE_COUNT: u8 = 0x89;
57pub const CMD_GET_RINGBUFFER_EMPTY_SAMPLE_COUNT: u8 = 0x8A;
59pub const CMD_GET_VERSION_MAJOR: u8 = 0x8B;
61pub const CMD_GET_VERSION_MINOR: u8 = 0x8C;
63pub const CMD_CLEAR_RINGBUFFER: u8 = 0x8D;
65pub const CMD_GET_BULK_PACKET_SAMPLE_COUNT: u8 = 0x8E;
67
68pub const CMD_RUNNER_MODE: u8 = 0xC0;
70pub const RUNNER_MODE_SUB_ENABLE: u8 = 0x01;
72pub const RUNNER_MODE_SUB_RUN: u8 = 0x09;
74
75pub const MAX_COORDINATE_VALUE: u16 = 4095;
77
78pub const SAMPLE_SIZE_BYTES: usize = 8;
80
81#[repr(C)]
89#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
90pub struct Sample {
91 pub rg: u16,
93 pub b: u16,
95 pub x: u16,
97 pub y: u16,
99}
100
101impl Sample {
102 pub fn new(x: u16, y: u16, r: u8, g: u8, b: u8) -> Self {
111 Self {
112 rg: (r as u16) | ((g as u16) << 8),
113 b: b as u16,
114 x: x.min(MAX_COORDINATE_VALUE),
115 y: y.min(MAX_COORDINATE_VALUE),
116 }
117 }
118
119 pub fn blank() -> Self {
121 Self::new(2048, 2048, 0, 0, 0)
122 }
123
124 pub fn red(&self) -> u8 {
126 (self.rg & 0xFF) as u8
127 }
128
129 pub fn green(&self) -> u8 {
131 ((self.rg >> 8) & 0xFF) as u8
132 }
133
134 pub fn blue(&self) -> u8 {
136 (self.b & 0xFF) as u8
137 }
138
139 pub fn flip_x(&mut self) {
141 self.x = MAX_COORDINATE_VALUE - self.x;
142 }
143
144 pub fn flip_y(&mut self) {
146 self.y = MAX_COORDINATE_VALUE - self.y;
147 }
148
149 pub fn to_bytes(&self) -> [u8; SAMPLE_SIZE_BYTES] {
151 let mut bytes = [0u8; SAMPLE_SIZE_BYTES];
152 bytes[0..2].copy_from_slice(&self.rg.to_le_bytes());
153 bytes[2..4].copy_from_slice(&self.b.to_le_bytes());
154 bytes[4..6].copy_from_slice(&self.x.to_le_bytes());
155 bytes[6..8].copy_from_slice(&self.y.to_le_bytes());
156 bytes
157 }
158}
159
160impl From<&LaserPoint> for Sample {
161 fn from(p: &LaserPoint) -> Self {
166 Sample::new(
167 LaserPoint::coord_to_u12(p.x),
168 LaserPoint::coord_to_u12(p.y),
169 LaserPoint::color_to_u8(p.r),
170 LaserPoint::color_to_u8(p.g),
171 LaserPoint::color_to_u8(p.b),
172 )
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_sample_new() {
182 let sample = Sample::new(2048, 2048, 255, 128, 64);
183 assert_eq!(sample.x, 2048);
184 assert_eq!(sample.y, 2048);
185 assert_eq!(sample.red(), 255);
186 assert_eq!(sample.green(), 128);
187 assert_eq!(sample.blue(), 64);
188 }
189
190 #[test]
191 fn test_sample_blank() {
192 let blank = Sample::blank();
193 assert_eq!(blank.x, 2048);
194 assert_eq!(blank.y, 2048);
195 assert_eq!(blank.red(), 0);
196 assert_eq!(blank.green(), 0);
197 assert_eq!(blank.blue(), 0);
198 }
199
200 #[test]
201 fn test_sample_clamps_coordinates() {
202 let sample = Sample::new(5000, 6000, 0, 0, 0);
203 assert_eq!(sample.x, MAX_COORDINATE_VALUE);
204 assert_eq!(sample.y, MAX_COORDINATE_VALUE);
205 }
206
207 #[test]
208 fn test_sample_flip() {
209 let mut sample = Sample::new(1000, 3000, 0, 0, 0);
210 sample.flip_x();
211 sample.flip_y();
212 assert_eq!(sample.x, 4095 - 1000);
213 assert_eq!(sample.y, 4095 - 3000);
214 }
215
216 #[test]
217 fn test_sample_size() {
218 assert_eq!(std::mem::size_of::<Sample>(), SAMPLE_SIZE_BYTES);
219 }
220}