1use crate::adapters;
2use crate::configuration;
3use crate::device;
4use crate::flag;
5use crate::properties;
6use crate::usb;
7
8use device::Usb;
9
10#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
11pub struct Biases {
12 pub pr: u8,
13 pub fo: u8,
14 pub hpf: u8,
15 pub diff_on: u8,
16 pub diff: u8,
17 pub diff_off: u8,
18 pub inv: u8,
19 pub refr: u8,
20 pub reqpuy: u8,
21 pub reqpux: u8,
22 pub sendreqpdy: u8,
23 pub unknown_1: u8,
24 pub unknown_2: u8,
25}
26
27#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
28pub enum Clock {
29 Internal = 0,
30 InternalWithOutputEnabled = 1,
31 External = 2,
32}
33
34#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
35pub struct RateLimiter {
36 pub reference_period_us: u16,
37 pub maximum_events_per_period: u32,
38}
39
40#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
41pub struct Configuration {
42 pub biases: Biases,
43 pub x_mask: [u64; 20],
44 pub y_mask: [u64; 12],
45 pub pixel_mask: [u64; 21],
46 pub mask_intersection_only: bool,
47 pub enable_external_trigger: bool,
48 pub clock: Clock,
49 pub rate_limiter: Option<RateLimiter>,
50 pub enable_output: bool,
51}
52
53pub struct Device {
54 handle: std::sync::Arc<rusb::DeviceHandle<rusb::Context>>,
55 ring: usb::Ring,
56 configuration_updater: configuration::Updater<Configuration>,
57 vendor_and_product_id: (u16, u16),
58 serial: String,
59 chip_firmware_configuration: Configuration,
60 register_mutex: std::sync::Arc<std::sync::Mutex<()>>,
61}
62
63#[derive(thiserror::Error, Debug, Clone)]
64pub enum Error {
65 #[error(transparent)]
66 Usb(#[from] usb::Error),
67
68 #[error("short write ({requested} bytes requested, {written} bytes written)")]
69 ShortWrite { requested: usize, written: usize },
70
71 #[error("short response while reading register {0}")]
72 RegisterReadShortResponse(u32),
73
74 #[error("bytes mismatch while reading register {0}")]
75 RegisterReadMismatch(u32),
76
77 #[error("unsupported mask code ({code}) for pixel mask {offset}")]
78 PixelMask { code: u32, offset: u32 },
79
80 #[error("the temperature measurement failed")]
81 Temperature,
82
83 #[error("the illuminance measurement failed")]
84 Illuminance,
85}
86
87impl From<rusb::Error> for Error {
88 fn from(error: rusb::Error) -> Self {
89 usb::Error::from(error).into()
90 }
91}
92
93pub const PROPERTIES: properties::Camera<Configuration> = Device::PROPERTIES;
94pub const DEFAULT_CONFIGURATION: Configuration = Device::PROPERTIES.default_configuration;
95pub const DEFAULT_USB_CONFIGURATION: usb::Configuration = Device::DEFAULT_USB_CONFIGURATION;
96pub fn open<IntoError, IntoWarning>(
97 serial_or_bus_number_and_address: device::SerialOrBusNumberAndAddress,
98 configuration: Configuration,
99 usb_configuration: &usb::Configuration,
100 event_loop: std::sync::Arc<usb::EventLoop>,
101 flag: flag::Flag<IntoError, IntoWarning>,
102) -> Result<Device, Error>
103where
104 IntoError: From<Error> + Clone + Send + 'static,
105 IntoWarning: From<usb::Overflow> + Clone + Send + 'static,
106{
107 Device::open(
108 serial_or_bus_number_and_address,
109 configuration,
110 usb_configuration,
111 event_loop,
112 flag,
113 )
114}
115
116impl device::Usb for Device {
117 type Adapter = adapters::evt3::Adapter;
118
119 type Configuration = Configuration;
120
121 type Error = Error;
122
123 type Properties = properties::Camera<Self::Configuration>;
124
125 const VENDOR_AND_PRODUCT_IDS: &'static [(u16, u16)] = &[
126 (0x04B4, 0x00F4),
127 (0x04B4, 0x00F5),
128 (0x31F7, 0x0003),
129 (0x31F7, 0x0004),
130 (0x1409, 0x8E00),
131 ];
132
133 const PROPERTIES: Self::Properties = Self::Properties {
134 name: "Prophesee EVK4",
135 width: 1280,
136 height: 720,
137 default_configuration: Self::Configuration {
138 biases: Biases {
139 pr: 0x7C,
140 fo: 0x53,
141 hpf: 0x00,
142 diff_on: 0x66,
143 diff: 0x4D,
144 diff_off: 0x49,
145 inv: 0x5B,
146 refr: 0x14,
147 reqpuy: 0x8C,
148 reqpux: 0x7C,
149 sendreqpdy: 0x94,
150 unknown_1: 0x74,
151 unknown_2: 0x51,
152 },
153 x_mask: [0; 20],
154 y_mask: [0; 12],
155 pixel_mask: [0; 21],
156 mask_intersection_only: false,
157 enable_external_trigger: true,
158 clock: Clock::Internal,
159 rate_limiter: None,
160 enable_output: true,
161 },
162 };
163
164 const DEFAULT_USB_CONFIGURATION: usb::Configuration = usb::Configuration {
165 buffer_length: 1 << 17,
166 ring_length: 1 << 12,
167 transfer_queue_length: 1 << 5,
168 allow_dma: false,
169 };
170
171 fn read_serial(handle: &mut rusb::DeviceHandle<rusb::Context>) -> rusb::Result<Option<String>> {
172 handle.claim_interface(0)?;
173 let mut type_buffer = [0u8; 2];
174 if handle.read_control(
175 0xC0,
176 0x72,
177 0x00,
178 0x00,
179 &mut type_buffer,
180 std::time::Duration::from_secs(1),
181 )? != 2
182 {
183 return Ok(None);
184 }
185 if type_buffer[0] != EVK3_IMX636_TYPE && type_buffer[0] != EVK3_IMX646_TYPE {
186 return Ok(None);
187 }
188 handle.write_bulk(
189 0x02,
190 &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
191 std::time::Duration::from_secs(1),
192 )?;
193 let mut buffer = vec![0u8; 16];
194 handle.read_bulk(0x82, &mut buffer, std::time::Duration::from_secs(1))?;
195 Ok(Some(format!(
196 "{:02X}{:02X}{:02X}{:02X}",
197 buffer[11], buffer[10], buffer[9], buffer[8]
198 )))
199 }
200
201 fn default_configuration(&self) -> Self::Configuration {
202 PROPERTIES.default_configuration
203 }
204
205 fn current_configuration(&self) -> Self::Configuration {
206 self.configuration_updater.current_configuration()
207 }
208
209 fn update_configuration(&self, configuration: Self::Configuration) {
210 self.configuration_updater.update(configuration);
211 }
212
213 fn open<IntoError, IntoWarning>(
214 serial_or_bus_number_and_address: device::SerialOrBusNumberAndAddress,
215 configuration: Self::Configuration,
216 usb_configuration: &usb::Configuration,
217 event_loop: std::sync::Arc<usb::EventLoop>,
218 flag: flag::Flag<IntoError, IntoWarning>,
219 ) -> Result<Self, Self::Error>
220 where
221 IntoError: From<Self::Error> + Clone + Send + 'static,
222 IntoWarning: From<usb::Overflow> + Clone + Send + 'static,
223 {
224 let (handle, vendor_and_product_id, serial) = match serial_or_bus_number_and_address {
225 device::SerialOrBusNumberAndAddress::Serial(serial) => {
226 Self::open_serial(event_loop.context(), serial)?
227 }
228 device::SerialOrBusNumberAndAddress::BusNumberAndAddress((bus_number, address)) => {
229 Self::open_bus_number_and_address(event_loop.context(), bus_number, address)?
230 }
231 device::SerialOrBusNumberAndAddress::None => Self::open_any(event_loop.context())?,
232 };
233 usb::assert_control_transfer(
234 &handle,
235 0x80,
236 0x06,
237 0x0300,
238 0x0000,
239 &[0x04, 0x03, 0x09, 0x04],
240 TIMEOUT,
241 )?;
242 usb::assert_string_descriptor_any(
243 &handle,
244 0x80,
245 0x06,
246 0x0301,
247 0x0409,
248 &[
249 &[
251 b'P', 0x00, b'r', 0x00, b'o', 0x00, b'p', 0x00, b'h', 0x00, b'e', 0x00, b's',
252 0x00, b'e', 0x00, b'e', 0x00,
253 ],
254 &[
256 b'C', 0x00, b'e', 0x00, b'n', 0x00, b't', 0x00, b'u', 0x00, b'r', 0x00, b'y',
257 0x00, b'A', 0x00, b'r', 0x00, b'k', 0x00, b's', 0x00,
258 ],
259 &[
261 b'I', 0x00, b'D', 0x00, b'S', 0x00, b' ', 0x00, b'I', 0x00, b'm', 0x00, b'a',
262 0x00, b'g', 0x00, b'i', 0x00, b'n', 0x00, b'g', 0x00, b' ', 0x00, b'D', 0x00,
263 b'e', 0x00, b'v', 0x00, b'e', 0x00, b'l', 0x00, b'o', 0x00, b'p', 0x00, b'm',
264 0x00, b'e', 0x00, b'n', 0x00, b't', 0x00, b' ', 0x00, b'S', 0x00, b'y', 0x00,
265 b's', 0x00, b't', 0x00, b'e', 0x00, b'm', 0x00, b's', 0x00, b' ', 0x00, b'G',
266 0x00, b'm', 0x00, b'b', 0x00, b'H', 0x00,
267 ],
268 ],
269 TIMEOUT,
270 )?;
271 usb::assert_string_descriptor_any(
272 &handle,
273 0x80,
274 0x06,
275 0x0302,
276 0x0409,
277 &[
278 &[b'E', 0x00, b'V', 0x00, b'K', 0x00, b'4', 0x00],
280 &[
282 b'S', 0x00, b'i', 0x00, b'l', 0x00, b'k', 0x00, b'y', 0x00, b'E', 0x00, b'v',
283 0x00, b'C', 0x00, b'a', 0x00, b'm', 0x00, b' ', 0x00, b'H', 0x00, b'D', 0x00,
284 b' ', 0x00, b'v', 0x00, b'0', 0x00, b'3', 0x00, b'.', 0x00, b'0', 0x00, b'9',
285 0x00, b'.', 0x00, b'0', 0x00, b'0', 0x00, b'C', 0x00,
286 ],
287 &[
289 b'S', 0x00, b'i', 0x00, b'l', 0x00, b'k', 0x00, b'y', 0x00, b'E', 0x00, b'v',
290 0x00, b'C', 0x00, b'a', 0x00, b'm', 0x00, b' ', 0x00, b'H', 0x00, b'D', 0x00,
291 b' ', 0x00, b'L', 0x00, b'i', 0x00, b't', 0x00, b'e', 0x00, b' ', 0x00, b'v',
292 0x00, b'0', 0x00, b'3', 0x00, b'.', 0x00, b'0', 0x00, b'9', 0x00, b'.', 0x00,
293 b'0', 0x00, b'1', 0x00, b'C', 0x00,
294 ],
295 &[
297 b'U', 0x00, b'E', 0x00, b'-', 0x00, b'3', 0x00, b'9', 0x00, b'B', 0x00, b'0',
298 0x00, b'X', 0x00, b'C', 0x00, b'P',
299 ],
300 ],
301 TIMEOUT,
302 )?;
303 request(
304 &handle,
305 &[0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
306 TIMEOUT,
307 )?; request(
309 &handle,
310 &[0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
311 TIMEOUT,
312 )?; request(
314 &handle,
315 &[0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00],
316 TIMEOUT,
317 )?; request(
319 &handle,
320 &[
321 0x03, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 ],
323 TIMEOUT,
324 )?; request(
326 &handle,
327 &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
328 TIMEOUT,
329 )?; request(
331 &handle,
332 &[0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00],
333 TIMEOUT,
334 )?; request(
336 &handle,
337 &[
338 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 ],
340 TIMEOUT,
341 )?; request(
343 &handle,
344 &[
345 0x03, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 ],
347 TIMEOUT,
348 )?; let mut chip_firmware_configuration = Self::PROPERTIES.default_configuration.clone();
352 chip_firmware_configuration.biases = Biases {
353 pr: BiasPr::read(&handle)?.idac_ctl as u8,
354 fo: BiasFo::read(&handle)?.idac_ctl as u8,
355 hpf: BiasHpf::read(&handle)?.idac_ctl as u8,
356 diff_on: BiasDiffOn::read(&handle)?.idac_ctl as u8,
357 diff: BiasDiff::read(&handle)?.idac_ctl as u8,
358 diff_off: BiasDiffOff::read(&handle)?.idac_ctl as u8,
359 inv: BiasInv::read(&handle)?.idac_ctl as u8,
360 refr: BiasRefr::read(&handle)?.idac_ctl as u8,
361 reqpuy: BiasReqpuy::read(&handle)?.idac_ctl as u8,
362 reqpux: BiasReqpux::read(&handle)?.idac_ctl as u8,
363 sendreqpdy: BiasSendreqpdy::read(&handle)?.idac_ctl as u8,
364 unknown_1: BiasUnknown1::read(&handle)?.idac_ctl as u8,
365 unknown_2: BiasUnknown2::read(&handle)?.idac_ctl as u8,
366 };
367
368 RoiCtrl {
370 reserved_0_1: 0,
371 td_enable: 1,
372 reserved_2_5: 0,
373 td_shadow_trigger: 0,
374 td_roni_n_en: 1,
375 reserved_7_10: 0,
376 td_rstn: 0,
377 reserved_11_32: 0x1e000a,
378 }
379 .write(&handle)?;
380 Unknown002C { value: 0x0022c324 }.write(&handle)?;
381 RoCtrl {
382 area_count_enable: 0,
383 output_disable: 1,
384 keep_timer_high: 0,
385 }
386 .write(&handle)?;
387 std::thread::sleep(std::time::Duration::from_millis(1));
388 TimeBaseCtrl {
389 enable: 0,
390 external: 0,
391 primary: 1,
392 external_enable: 0,
393 reserved_4_32: 0x64,
394 }
395 .write(&handle)?;
396 MipiControl { value: 0x000002f8 }.write(&handle)?;
397 std::thread::sleep(std::time::Duration::from_micros(300));
398 Unknown0070 { value: 0x00400008 }.write(&handle)?;
402 Unknown006C { value: 0x0ee47114 }.write(&handle)?;
403 std::thread::sleep(std::time::Duration::from_micros(500));
404 UnknownA00C { value: 0x00020400 }.write(&handle)?;
405 std::thread::sleep(std::time::Duration::from_micros(500));
406 UnknownA010 { value: 0x00008068 }.write(&handle)?;
407 std::thread::sleep(std::time::Duration::from_micros(200));
408 Unknown1104 { value: 0x00000000 }.write(&handle)?;
409 std::thread::sleep(std::time::Duration::from_micros(200));
410 UnknownA020 { value: 0x00000050 }.write(&handle)?;
411 std::thread::sleep(std::time::Duration::from_micros(200));
412 UnknownA004 { value: 0x000b0500 }.write(&handle)?;
413 std::thread::sleep(std::time::Duration::from_micros(200));
414 UnknownA008 { value: 0x00002404 }.write(&handle)?;
415 std::thread::sleep(std::time::Duration::from_micros(200));
416 UnknownA000 { value: 0x000b0500 }.write(&handle)?;
417 UnknownB044 { value: 0x00000000 }.write(&handle)?;
418 UnknownB004 { value: 0x0000000a }.write(&handle)?;
419 UnknownB040 { value: 0x0000000e }.write(&handle)?;
420 UnknownB0C8 { value: 0x00000000 }.write(&handle)?;
421 UnknownB040 { value: 0x00000006 }.write(&handle)?;
422 UnknownB040 { value: 0x00000004 }.write(&handle)?;
423 Unknown0000 { value: 0x4f006442 }.write(&handle)?;
424 Unknown0000 { value: 0x0f006442 }.write(&handle)?;
425 Unknown00B8 { value: 0x00000401 }.write(&handle)?;
426 Unknown00B8 { value: 0x00000400 }.write(&handle)?;
427 UnknownB07C { value: 0x00000000 }.write(&handle)?;
428 Unknown001C { value: 0x00000001 }.write(&handle)?;
432 Reset { value: 0x00000001 }.write(&handle)?;
433 std::thread::sleep(std::time::Duration::from_secs(1));
434 Reset { value: 0x00000000 }.write(&handle)?;
435 std::thread::sleep(std::time::Duration::from_millis(500));
436 MipiControl { value: 0x00000158 }.write(&handle)?;
437 std::thread::sleep(std::time::Duration::from_secs(1));
438 UnknownB044 { value: 0x00000000 }.write(&handle)?;
439 std::thread::sleep(std::time::Duration::from_micros(300));
440 UnknownB004 { value: 0x0000000a }.write(&handle)?;
441 UnknownB040 { value: 0x00000000 }.write(&handle)?;
442 UnknownB0C8 { value: 0x00000000 }.write(&handle)?;
443 UnknownB040 { value: 0x00000000 }.write(&handle)?;
444 UnknownB040 { value: 0x00000000 }.write(&handle)?;
445 Unknown0000 { value: 0x4f006442 }.write(&handle)?;
446 Unknown0000 { value: 0x0f006442 }.write(&handle)?;
447 Unknown00B8 { value: 0x00000400 }.write(&handle)?;
448 Unknown00B8 { value: 0x00000400 }.write(&handle)?;
449 UnknownB07C { value: 0x00000000 }.write(&handle)?;
450 UnknownB074 { value: 0x00000002 }.write(&handle)?;
451 UnknownB078 { value: 0x000000a0 }.write(&handle)?;
452 Unknown00C0 { value: 0x00000110 }.write(&handle)?;
453 Unknown00C0 { value: 0x00000210 }.write(&handle)?;
454 UnknownB120 { value: 0x00000001 }.write(&handle)?;
455 UnknownE120 { value: 0x00000000 }.write(&handle)?;
456 UnknownB068 { value: 0x00000004 }.write(&handle)?;
457 UnknownB07C { value: 0x00000001 }.write(&handle)?;
458 std::thread::sleep(std::time::Duration::from_micros(10));
459 UnknownB07C { value: 0x00000003 }.write(&handle)?;
460 std::thread::sleep(std::time::Duration::from_millis(1));
461 Unknown00B8 { value: 0x00000401 }.write(&handle)?;
462 Unknown00B8 { value: 0x00000409 }.write(&handle)?;
463 Unknown0000 { value: 0x4f006442 }.write(&handle)?;
464 Unknown0000 { value: 0x4f00644a }.write(&handle)?;
465 UnknownB080 { value: 0x00000077 }.write(&handle)?;
466 UnknownB084 { value: 0x0000000f }.write(&handle)?;
467 UnknownB088 { value: 0x00000037 }.write(&handle)?;
468 UnknownB08C { value: 0x00000037 }.write(&handle)?;
469 UnknownB090 { value: 0x000000df }.write(&handle)?;
470 UnknownB094 { value: 0x00000057 }.write(&handle)?;
471 UnknownB098 { value: 0x00000037 }.write(&handle)?;
472 UnknownB09C { value: 0x00000067 }.write(&handle)?;
473 UnknownB0A0 { value: 0x00000037 }.write(&handle)?;
474 UnknownB0A4 { value: 0x0000002f }.write(&handle)?;
475 UnknownB0AC { value: 0x00000028 }.write(&handle)?;
476 UnknownB0CC { value: 0x00000001 }.write(&handle)?;
477 MipiControl { value: 0x000002f8 }.write(&handle)?;
478 UnknownB004 { value: 0x0000008a }.write(&handle)?;
479 UnknownB01C { value: 0x00000030 }.write(&handle)?;
480 MipiPacketSize { value: 0x00002000 }.write(&handle)?;
481 UnknownB02C { value: 0x000000ff }.write(&handle)?;
482 MipiFrameBlanking { value: 0x00003e80 }.write(&handle)?;
483 MipiFramePeriod { value: 0x00000fa0 }.write(&handle)?;
484 UnknownA000 { value: 0x000b0501 }.write(&handle)?;
485 std::thread::sleep(std::time::Duration::from_micros(200));
486 UnknownA008 { value: 0x00002405 }.write(&handle)?;
487 std::thread::sleep(std::time::Duration::from_micros(200));
488 UnknownA004 { value: 0x000b0501 }.write(&handle)?;
489 std::thread::sleep(std::time::Duration::from_micros(200));
490 UnknownA020 { value: 0x00000150 }.write(&handle)?;
491 std::thread::sleep(std::time::Duration::from_micros(200));
492 UnknownB040 { value: 0x00000007 }.write(&handle)?;
493 UnknownB064 { value: 0x00000006 }.write(&handle)?;
494 UnknownB040 { value: 0x0000000f }.write(&handle)?;
495 std::thread::sleep(std::time::Duration::from_micros(100));
496 UnknownB004 { value: 0x0000008a }.write(&handle)?;
497 std::thread::sleep(std::time::Duration::from_micros(200));
498 UnknownB0C8 { value: 0x00000003 }.write(&handle)?;
499 std::thread::sleep(std::time::Duration::from_micros(200));
500 UnknownB044 { value: 0x00000001 }.write(&handle)?;
501 MipiControl { value: 0x000002f9 }.write(&handle)?;
502 Unknown7008 { value: 0x00000001 }.write(&handle)?;
503 EdfPipelineControl { value: 0x00070001 }.write(&handle)?;
504 Unknown8000 { value: 0x0001e085 }.write(&handle)?;
505 TimeBaseCtrl {
506 enable: 0,
507 external: 0,
508 primary: 1,
509 external_enable: 0,
510 reserved_4_32: 0x64,
511 }
512 .write(&handle)?;
513 RoiCtrl {
514 reserved_0_1: 0,
515 td_enable: 1,
516 reserved_2_5: 0,
517 td_shadow_trigger: 0,
518 td_roni_n_en: 1,
519 reserved_7_10: 0,
520 td_rstn: 0,
521 reserved_11_32: 0x1e000a,
522 }
523 .write(&handle)?;
524 Spare0 { value: 0x00000200 }.write(&handle)?;
525 BiasDiff {
526 idac_ctl: 0x4d,
527 vdac_ctl: 0x50,
528 buf_stg: 1,
529 ibtype_sel: 0,
530 mux_sel: 0,
531 mux_en: 1,
532 vdac_en: 0,
533 buf_en: 1,
534 idac_en: 1,
535 reserved: 0,
536 single: 1,
537 }
538 .write(&handle)?;
539 RoFsmCtrl {
540 readout_wait: 0,
541 reserved_16_31: 0,
542 }
543 .write(&handle)?;
544 std::thread::sleep(std::time::Duration::from_millis(1));
545 ReadoutCtrl { value: 0x00000200 }.write(&handle)?;
546 AdcControl {
550 adc_en: 1,
551 adc_clk_en: 0,
552 adc_start: 0,
553 reserved_3_32: 0xEC8,
554 }
555 .write(&handle)?;
556 AdcControl {
557 adc_en: 1,
558 adc_clk_en: 1,
559 adc_start: 0,
560 reserved_3_32: 0xEC8,
561 }
562 .write(&handle)?;
563 AdcMiscCtrl {
564 reserved_0_1: 0,
565 adc_buf_cal_en: 1,
566 reserved_2_10: 0x210,
567 adc_rng: 0,
568 adc_temp: 0,
569 reserved_13_32: 0,
570 }
571 .write(&handle)?;
572 std::thread::sleep(std::time::Duration::from_micros(100));
573
574 TempCtrl {
576 temp_buf_cal_en: 0,
577 temp_buf_en: 1,
578 reserved_2_32: 0x80020,
579 }
580 .write(&handle)?;
581 TempCtrl {
582 temp_buf_cal_en: 1,
583 temp_buf_en: 1,
584 reserved_2_32: 0x80020,
585 }
586 .write(&handle)?;
587 std::thread::sleep(std::time::Duration::from_micros(100));
588 AdcControl {
589 adc_en: 1,
590 adc_clk_en: 0,
591 adc_start: 0,
592 reserved_3_32: 0xEC8,
593 }
594 .write(&handle)?;
595
596 AdcControl {
598 adc_en: 1,
599 adc_clk_en: 1,
600 adc_start: 0,
601 reserved_3_32: 0xEC8,
602 }
603 .write(&handle)?;
604 AdcMiscCtrl {
605 reserved_0_1: 0,
606 adc_buf_cal_en: 1,
607 reserved_2_10: 0x84,
608 adc_rng: 0,
609 adc_temp: 1,
610 reserved_13_32: 0,
611 }
612 .write(&handle)?;
613
614 IphMirrCtrl {
616 iph_mirr_en: 0,
617 iph_mirr_amp_en: 1,
618 reserved_2_32: 0,
619 }
620 .write(&handle)?;
621 std::thread::sleep(std::time::Duration::from_micros(10));
622 IphMirrCtrl {
623 iph_mirr_en: 1,
624 iph_mirr_amp_en: 1,
625 reserved_2_32: 0,
626 }
627 .write(&handle)?;
628 std::thread::sleep(std::time::Duration::from_micros(20));
629 LifoCtrl {
630 lifo_en: 1,
631 lifo_out_en: 0,
632 lifo_cnt_en: 0,
633 reserved_3_32: 0,
634 }
635 .write(&handle)?;
636 std::thread::sleep(std::time::Duration::from_micros(5));
637 LifoCtrl {
638 lifo_en: 1,
639 lifo_out_en: 1,
640 lifo_cnt_en: 0,
641 reserved_3_32: 0,
642 }
643 .write(&handle)?;
644 LifoCtrl {
645 lifo_en: 1,
646 lifo_out_en: 1,
647 lifo_cnt_en: 1,
648 reserved_3_32: 0,
649 }
650 .write(&handle)?;
651
652 AfkPeriod {
654 min_cutoff_period: 15,
655 max_cutoff_period: 156,
656 inverted_duty_cycle: 8,
657 }
658 .write(&handle)?;
659 AfkPipelineControl {
660 reserved_0_2: 1,
661 bypass: 1,
662 }
663 .write(&handle)?;
664
665 StcTimestamping {
669 prescaler: 13,
670 multiplier: 1,
671 reserved_9_16: 1,
672 reset_refractory_period_on_event: 0,
673 }
674 .write(&handle)?;
675 StcParam {
676 enable: 0,
677 threshold: 1480,
678 reserved_20_24: 0,
679 disable_cut_trail: 1,
680 }
681 .write(&handle)?;
682 TrailParam {
683 enable: 0,
684 threshold: 100000,
685 }
686 .write(&handle)?;
687 BurstPipelineInvalidation {
688 dt_fifo_wait_time: 4,
689 dt_fifo_timeout: 280,
690 reserved_24_29: 10,
691 }
692 .write(&handle)?;
693 BurstPipelineInitialization {
694 force_sram_initialization: 0,
695 reserved_1_2: 0,
696 clear_flag: 0,
697 }
698 .write(&handle)?;
699 BurstPipelineControl {
700 reserved_0_2: 1,
701 bypass: 1,
702 }
703 .write(&handle)?;
704
705 ErcReserved6000 { value: 0x00155400 }.write(&handle)?;
707 match &configuration.rate_limiter {
708 Some(rate_limiter) => {
709 ErcInDropRateControl {
710 enable: 1,
711 reserved_1_32: 0,
712 }
713 .write(&handle)?;
714 ErcReferencePeriod {
715 duration_us: rate_limiter.reference_period_us as u32,
716 reserved_10_32: 0,
717 }
718 .write(&handle)?;
719 ErcTdTargetEventRate {
720 maximum_per_period: rate_limiter.maximum_events_per_period,
721 reserved_22_32: 0,
722 }
723 .write(&handle)?;
724 ErcControl {
725 enable: 1,
726 reserved_1_32: 1,
727 }
728 .write(&handle)?;
729 }
730 None => {
731 ErcInDropRateControl {
732 enable: 0,
733 reserved_1_32: 0,
734 }
735 .write(&handle)?;
736 ErcControl {
737 enable: 0,
738 reserved_1_32: 1,
739 }
740 .write(&handle)?;
741 }
742 }
743 ErcReserved602C { value: 0x00000001 }.write(&handle)?;
744 for offset in 0..230 {
745 ErcReserved6800 { value: 0x08080808 }
746 .offset(offset)
747 .write(&handle)?;
748 }
749 ErcReserved602C { value: 0x00000002 }.write(&handle)?;
750 for offset in 0..256 {
751 TDropLut {
752 value: ((offset * 2 + 1) << 16) | (offset * 2),
753 }
754 .offset(offset)
755 .write(&handle)?;
756 }
757 ErcTDroppingControl {
758 enable: configuration.rate_limiter.is_some() as u32,
759 reserved_1_32: 0,
760 }
761 .write(&handle)?;
762 ErcHDroppingControl {
763 enable: 0,
764 reserved_1_32: 0,
765 }
766 .write(&handle)?;
767 ErcVDroppingControl {
768 enable: 0,
769 reserved_1_32: 0,
770 }
771 .write(&handle)?;
772 ErcReserved6000 { value: 0x00155401 }.write(&handle)?;
773 EdfReserved7004 {
774 reserved_0_10: 0b0111111111,
775 external_trigger: if configuration.enable_external_trigger {
776 1
777 } else {
778 0
779 },
780 reserved_11_32: 0b11000,
781 }
782 .write(&handle)?;
783 loop {
784 let mut buffer = vec![0u8; Self::DEFAULT_USB_CONFIGURATION.buffer_length];
785 match handle.read_bulk(0x81, &mut buffer, TIMEOUT) {
786 Ok(size) => {
787 if size == 0 {
788 break;
789 }
790 }
791 Err(error) => match error {
792 rusb::Error::Timeout => break,
793 error => return Err(error.into()),
794 },
795 }
796 }
797 request(
798 &handle,
799 &[0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
800 TIMEOUT,
801 )?;
802 update_configuration(&handle, None, &configuration)?;
803
804 MipiControl { value: 0x000002f9 }.write(&handle)?;
806 if configuration.enable_output {
807 RoCtrl {
808 area_count_enable: 0,
809 output_disable: 0,
810 keep_timer_high: 0,
811 }
812 .write(&handle)?;
813 }
814 match configuration.clock {
815 Clock::Internal => {
816 TimeBaseCtrl {
817 enable: 1,
818 external: 0,
819 primary: 1,
820 external_enable: 0,
821 reserved_4_32: 0x64,
822 }
823 .write(&handle)?;
824 }
825 Clock::InternalWithOutputEnabled => {
826 TimeBaseCtrl {
827 enable: 0,
828 external: 1,
829 primary: 1,
830 external_enable: 1,
831 reserved_4_32: 0x64,
832 }
833 .write(&handle)?;
834 DigPad2Ctrl {
835 reserved_0_16: 0xFCCF,
836 sync: 0b1100,
837 reserved_20_32: 0xCCF,
838 }
839 .write(&handle)?;
840 std::thread::sleep(std::time::Duration::from_millis(1));
841 TimeBaseCtrl {
842 enable: 1,
843 external: 1,
844 primary: 1,
845 external_enable: 1,
846 reserved_4_32: 0x64,
847 }
848 .write(&handle)?;
849 }
850 Clock::External => {
851 TimeBaseCtrl {
852 enable: 1,
853 external: 1,
854 primary: 0,
855 external_enable: 1,
856 reserved_4_32: 0x64,
857 }
858 .write(&handle)?;
859 DigPad2Ctrl {
860 reserved_0_16: 0xFCCF,
861 sync: 0b1111,
862 reserved_20_32: 0xCCF,
863 }
864 .write(&handle)?;
865 }
866 }
867 Unknown002C { value: 0x0022c724 }.write(&handle)?;
868 RoiCtrl {
869 reserved_0_1: 0,
870 td_enable: 1,
871 reserved_2_5: 0,
872 td_shadow_trigger: 0,
873 td_roni_n_en: (!configuration.mask_intersection_only) as u32,
874 reserved_7_10: 0,
875 td_rstn: 1,
876 reserved_11_32: 0x1e000a,
877 }
878 .write(&handle)?;
879 let handle = std::sync::Arc::new(handle);
882 let error_flag = flag.clone();
883 let warning_flag = flag.clone();
884 let register_mutex = std::sync::Arc::new(std::sync::Mutex::new(()));
885 Ok(Device {
886 handle: handle.clone(),
887 ring: usb::Ring::new(
888 handle.clone(),
889 usb_configuration,
890 move |usb_error| {
891 error_flag.store_error_if_not_set(Self::Error::from(usb_error));
892 },
893 move |overflow| {
894 warning_flag.store_warning_if_not_set(overflow);
895 },
896 event_loop,
897 usb::TransferType::Bulk {
898 endpoint: 1 | libusb1_sys::constants::LIBUSB_ENDPOINT_IN,
899 timeout: std::time::Duration::ZERO,
900 },
901 )?,
902 configuration_updater: configuration::Updater::new(
903 configuration,
904 ConfigurationUpdaterContext {
905 handle,
906 flag,
907 register_mutex: register_mutex.clone(),
908 },
909 |context, previous_configuration, configuration| {
910 let result = {
911 let _guard = context
912 .register_mutex
913 .lock()
914 .expect("register mutex is not poisoned");
915 update_configuration(
916 &context.handle,
917 Some(previous_configuration),
918 configuration,
919 )
920 };
921 if let Err(error) = result {
922 context.flag.store_error_if_not_set(error);
923 }
924 context
925 },
926 ),
927 vendor_and_product_id,
928 serial,
929 chip_firmware_configuration,
930 register_mutex,
931 })
932 }
933
934 fn next_with_timeout(&'_ self, timeout: &std::time::Duration) -> Option<usb::BufferView<'_>> {
935 self.ring.next_with_timeout(timeout)
936 }
937
938 fn backlog(&self) -> usize {
939 self.ring.backlog()
940 }
941
942 fn clutch(&self) -> usb::Clutch {
943 self.ring.clutch()
944 }
945
946 fn vendor_and_product_id(&self) -> (u16, u16) {
947 self.vendor_and_product_id
948 }
949
950 fn serial(&self) -> String {
951 self.serial.clone()
952 }
953
954 fn chip_firmware_configuration(&self) -> Self::Configuration {
955 self.chip_firmware_configuration.clone()
956 }
957
958 fn bus_number(&self) -> u8 {
959 self.handle.device().bus_number()
960 }
961
962 fn address(&self) -> u8 {
963 self.handle.device().address()
964 }
965
966 fn speed(&self) -> usb::Speed {
967 self.handle.device().speed().into()
968 }
969
970 fn create_adapter(&self) -> Self::Adapter {
971 Self::Adapter::from_dimensions(Self::PROPERTIES.width, Self::PROPERTIES.height)
972 }
973}
974
975impl Device {
976 pub fn illuminance(&self) -> Result<u32, Error> {
977 let lifo_status = LifoStatus::read(&self.handle)?;
978 if lifo_status.lifo_ton_valid == 1 {
979 Ok(lifo_status.lifo_ton)
980 } else {
981 Err(Error::Illuminance)
982 }
983 }
984
985 pub fn temperature_celsius(&self) -> Result<device::TemperatureCelsius, Error> {
986 let _guard = self
987 .register_mutex
988 .lock()
989 .expect("register mutex is not poisoned");
990 AdcControl {
991 adc_en: 1,
992 adc_clk_en: 1,
993 adc_start: 1,
994 reserved_3_32: 0xEC8,
995 }
996 .write(&self.handle)?;
997 let adc_status = AdcStatus::read(&self.handle)?;
998 if adc_status.adc_done_dyn == 1 {
999 Ok(device::TemperatureCelsius(
1000 adc_status.adc_dac_dyn as f32 * 0.19 - 56.0,
1001 ))
1002 } else {
1003 Err(Error::Temperature)
1004 }
1005 }
1006}
1007
1008impl Drop for Device {
1009 fn drop(&mut self) {
1010 let _ = LifoCtrl {
1011 lifo_en: 0,
1012 lifo_out_en: 0,
1013 lifo_cnt_en: 0,
1014 reserved_3_32: 0,
1015 }
1016 .write(&self.handle);
1017 let _ = IphMirrCtrl {
1018 iph_mirr_en: 0,
1019 iph_mirr_amp_en: 0,
1020 reserved_2_32: 0,
1021 }
1022 .write(&self.handle);
1023 let _ = TempCtrl {
1024 temp_buf_cal_en: 1,
1025 temp_buf_en: 1,
1026 reserved_2_32: 0x80020,
1027 }
1028 .write(&self.handle);
1029 let _ = AdcControl {
1030 adc_en: 0,
1031 adc_clk_en: 0,
1032 adc_start: 0,
1033 reserved_3_32: 0xEC8,
1034 }
1035 .write(&self.handle);
1036
1037 let _ = RoiCtrl {
1039 reserved_0_1: 0,
1040 td_enable: 1,
1041 reserved_2_5: 0,
1042 td_shadow_trigger: 0,
1043 td_roni_n_en: 1,
1044 reserved_7_10: 0,
1045 td_rstn: 0,
1046 reserved_11_32: 0x1e000a,
1047 }
1048 .write(&self.handle);
1049 let _ = Unknown002C { value: 0x0022c324 }.write(&self.handle);
1050 let _ = RoCtrl {
1051 area_count_enable: 0,
1052 output_disable: 1,
1053 keep_timer_high: 0,
1054 }
1055 .write(&self.handle);
1056 std::thread::sleep(std::time::Duration::from_millis(1));
1057 let _ = TimeBaseCtrl {
1058 enable: 0,
1059 external: 0,
1060 primary: 1,
1061 external_enable: 0,
1062 reserved_4_32: 0x64,
1063 }
1064 .write(&self.handle);
1065 let _ = MipiControl { value: 0x000002f8 }.write(&self.handle);
1066 std::thread::sleep(std::time::Duration::from_micros(300));
1067 let _ = Unknown0070 { value: 0x00400008 }.write(&self.handle);
1071 let _ = Unknown006C { value: 0x0ee47114 }.write(&self.handle);
1072 std::thread::sleep(std::time::Duration::from_micros(500));
1073 let _ = UnknownA00C { value: 0x00020400 }.write(&self.handle);
1074 std::thread::sleep(std::time::Duration::from_micros(500));
1075 let _ = UnknownA010 { value: 0x00008068 }.write(&self.handle);
1076 std::thread::sleep(std::time::Duration::from_micros(200));
1077 let _ = Unknown1104 { value: 0x00000000 }.write(&self.handle);
1078 std::thread::sleep(std::time::Duration::from_micros(200));
1079 let _ = UnknownA020 { value: 0x00000050 }.write(&self.handle);
1080 std::thread::sleep(std::time::Duration::from_micros(200));
1081 let _ = UnknownA004 { value: 0x000b0500 }.write(&self.handle);
1082 std::thread::sleep(std::time::Duration::from_micros(200));
1083 let _ = UnknownA008 { value: 0x00002404 }.write(&self.handle);
1084 std::thread::sleep(std::time::Duration::from_micros(200));
1085 let _ = UnknownA000 { value: 0x000b0500 }.write(&self.handle);
1086 let _ = UnknownB044 { value: 0x00000000 }.write(&self.handle);
1087 let _ = UnknownB004 { value: 0x0000000a }.write(&self.handle);
1088 let _ = UnknownB040 { value: 0x0000000e }.write(&self.handle);
1089 let _ = UnknownB0C8 { value: 0x00000000 }.write(&self.handle);
1090 let _ = UnknownB040 { value: 0x00000006 }.write(&self.handle);
1091 let _ = UnknownB040 { value: 0x00000004 }.write(&self.handle);
1092 let _ = Unknown0000 { value: 0x4f006442 }.write(&self.handle);
1093 let _ = Unknown0000 { value: 0x0f006442 }.write(&self.handle);
1094 let _ = Unknown00B8 { value: 0x00000401 }.write(&self.handle);
1095 let _ = Unknown00B8 { value: 0x00000400 }.write(&self.handle);
1096 let _ = UnknownB07C { value: 0x00000000 }.write(&self.handle);
1097 }
1099}
1100
1101const TIMEOUT: std::time::Duration = std::time::Duration::from_secs(1);
1102
1103fn request(
1104 handle: &rusb::DeviceHandle<rusb::Context>,
1105 buffer: &[u8],
1106 timeout: std::time::Duration,
1107) -> Result<Vec<u8>, Error> {
1108 let written = handle.write_bulk(0x02, buffer, timeout)?;
1109 if buffer.len() != written {
1110 return Err(Error::ShortWrite {
1111 requested: buffer.len(),
1112 written,
1113 });
1114 }
1115 let mut buffer = vec![0; 1024];
1116 let read = handle.read_bulk(0x82, &mut buffer, timeout)?;
1117 buffer.truncate(read);
1118 Ok(buffer)
1119}
1120
1121macro_rules! update_bias {
1122 ($name:ident, $register:ident, $handle:ident, $previous_biases:ident, $biases:expr) => {
1123 if match $previous_biases {
1124 Some(previous_biases) => previous_biases.$name != $biases.$name,
1125 None => true,
1126 } {
1127 $register {
1128 idac_ctl: $biases.$name as u32,
1129 vdac_ctl: 0,
1130 buf_stg: 1,
1131 ibtype_sel: 0,
1132 mux_sel: 0,
1133 mux_en: 1,
1134 vdac_en: 0,
1135 buf_en: 1,
1136 idac_en: 1,
1137 reserved: 0,
1138 single: 1,
1139 }
1140 .write($handle)?;
1141 }
1142 };
1143}
1144
1145fn update_configuration(
1146 handle: &rusb::DeviceHandle<rusb::Context>,
1147 previous_configuration: Option<&Configuration>,
1148 configuration: &Configuration,
1149) -> Result<(), Error> {
1150 if match previous_configuration {
1151 Some(previous_configuration) => {
1152 previous_configuration.enable_output != configuration.enable_output
1153 }
1154 None => false,
1155 } {
1156 RoCtrl {
1157 area_count_enable: 0,
1158 output_disable: if configuration.enable_output { 0 } else { 1 },
1159 keep_timer_high: 0,
1160 }
1161 .write(handle)?;
1162 }
1163 {
1164 let previous_biases = previous_configuration.map(|configuration| &configuration.biases);
1165 update_bias!(pr, BiasPr, handle, previous_biases, configuration.biases);
1166 update_bias!(fo, BiasFo, handle, previous_biases, configuration.biases);
1167 update_bias!(hpf, BiasHpf, handle, previous_biases, configuration.biases);
1168 update_bias!(
1169 diff_on,
1170 BiasDiffOn,
1171 handle,
1172 previous_biases,
1173 configuration.biases
1174 );
1175 update_bias!(
1176 diff,
1177 BiasDiff,
1178 handle,
1179 previous_biases,
1180 configuration.biases
1181 );
1182 update_bias!(
1183 diff_off,
1184 BiasDiffOff,
1185 handle,
1186 previous_biases,
1187 configuration.biases
1188 );
1189 update_bias!(inv, BiasInv, handle, previous_biases, configuration.biases);
1190 update_bias!(
1191 refr,
1192 BiasRefr,
1193 handle,
1194 previous_biases,
1195 configuration.biases
1196 );
1197 update_bias!(
1198 reqpuy,
1199 BiasReqpuy,
1200 handle,
1201 previous_biases,
1202 configuration.biases
1203 );
1204 update_bias!(
1205 reqpux,
1206 BiasReqpux,
1207 handle,
1208 previous_biases,
1209 configuration.biases
1210 );
1211 update_bias!(
1212 sendreqpdy,
1213 BiasSendreqpdy,
1214 handle,
1215 previous_biases,
1216 configuration.biases
1217 );
1218 update_bias!(
1219 unknown_1,
1220 BiasUnknown1,
1221 handle,
1222 previous_biases,
1223 configuration.biases
1224 );
1225 update_bias!(
1226 unknown_2,
1227 BiasUnknown2,
1228 handle,
1229 previous_biases,
1230 configuration.biases
1231 );
1232 }
1233 if match previous_configuration {
1234 Some(previous_configuration) => {
1235 previous_configuration.x_mask != configuration.x_mask
1236 || previous_configuration.y_mask != configuration.y_mask
1237 || previous_configuration.mask_intersection_only
1238 != configuration.mask_intersection_only
1239 }
1240 None => true,
1241 } {
1242 for offset in 0..((configuration.x_mask.len() as u32) * 2) {
1243 let register = TdRoiX {
1244 value: if (offset % 2) == 0 {
1245 (configuration.x_mask[(offset / 2) as usize] & 0xffffffffu64) as u32
1246 } else {
1247 ((configuration.x_mask[(offset / 2) as usize] & 0xffffffff00000000u64) >> 32)
1248 as u32
1249 },
1250 }
1251 .offset(offset);
1252 register.write(handle)?;
1253 }
1254 for offset in 0..((configuration.y_mask.len() as u32) * 2 - 1) {
1255 let register = TdRoiY {
1256 value: if (offset % 2) == 0 {
1257 let [byte2, byte3, _, _, _, _, _, _] = configuration.y_mask
1258 [configuration.y_mask.len() - 1 - (offset / 2) as usize]
1259 .to_le_bytes();
1260 if offset < (configuration.y_mask.len() as u32) * 2 - 2 {
1261 let [_, _, _, _, _, _, byte0, byte1] = configuration.y_mask
1262 [configuration.y_mask.len() - 2 - (offset / 2) as usize]
1263 .to_le_bytes();
1264 u32::from_le_bytes([
1265 byte3.reverse_bits(),
1266 byte2.reverse_bits(),
1267 byte1.reverse_bits(),
1268 byte0.reverse_bits(),
1269 ])
1270 } else {
1271 u32::from_le_bytes([byte3.reverse_bits(), byte2.reverse_bits(), 0xff, 0x00])
1272 }
1273 } else {
1274 let [_, _, byte0, byte1, byte2, byte3, _, _] = configuration.y_mask
1275 [configuration.y_mask.len() - 2 - (offset / 2) as usize]
1276 .to_le_bytes();
1277 u32::from_le_bytes([
1278 byte3.reverse_bits(),
1279 byte2.reverse_bits(),
1280 byte1.reverse_bits(),
1281 byte0.reverse_bits(),
1282 ])
1283 },
1284 }
1285 .offset(offset);
1286 register.write(handle)?;
1287 }
1288 RoiCtrl {
1289 reserved_0_1: 0,
1290 td_enable: 1,
1291 reserved_2_5: 0,
1292 td_shadow_trigger: 1,
1293 td_roni_n_en: (!configuration.mask_intersection_only) as u32,
1294 reserved_7_10: 0,
1295 td_rstn: previous_configuration.is_some() as u32,
1296 reserved_11_32: 0x1e000a,
1297 }
1298 .write(handle)?;
1299 }
1300 if match previous_configuration {
1301 Some(previous_configuration) => {
1302 previous_configuration.pixel_mask != configuration.pixel_mask
1303 }
1304 None => true,
1305 } {
1306 for offset in 0u32..64u32 {
1307 let code = if offset < 63 {
1308 (((configuration.pixel_mask[(offset / 3) as usize]) >> ((offset % 3) * 21))
1309 & 0x1fffff) as u32
1310 } else {
1311 let mut code: u32 = 0;
1312 for bit in 0..21 {
1313 code |= ((configuration.pixel_mask[bit] >> 63) << bit) as u32;
1314 }
1315 code
1316 };
1317 if code == 0 {
1318 DigitalMask {
1319 x: 0,
1320 reserved_11_16: 0,
1321 y: 0,
1322 reserved_26_31: 0,
1323 enable: 0,
1324 }
1325 .offset(offset)
1326 .write(handle)?;
1327 } else {
1328 let x = (code - 1) % 1280;
1329 let y = 720 - 1 - (code - 1) / 1280;
1330 if x >= 1280 || y >= 720 {
1331 return Err(Error::PixelMask { code, offset });
1332 }
1333 DigitalMask {
1334 x,
1335 reserved_11_16: 0,
1336 y,
1337 reserved_26_31: 0,
1338 enable: 1,
1339 }
1340 .offset(offset)
1341 .write(handle)?;
1342 }
1343 }
1344 }
1345 Ok(())
1346}
1347
1348struct ConfigurationUpdaterContext<IntoError, IntoWarning>
1349where
1350 IntoError: From<Error> + Clone + Send,
1351 IntoWarning: From<usb::Overflow> + Clone + Send,
1352{
1353 handle: std::sync::Arc<rusb::DeviceHandle<rusb::Context>>,
1354 flag: flag::Flag<IntoError, IntoWarning>,
1355 register_mutex: std::sync::Arc<std::sync::Mutex<()>>,
1356}
1357
1358const EVK3_IMX636_TYPE: u8 = 0x31;
1359const EVK3_IMX646_TYPE: u8 = 0x35;
1360
1361struct RuntimeRegister {
1362 address: u32,
1363 value: u32,
1364}
1365
1366trait Register {
1367 fn address(&self) -> u32;
1368
1369 fn value(&self) -> u32;
1370
1371 fn offset(&self, registers: u32) -> RuntimeRegister;
1372
1373 fn write(&self, handle: &rusb::DeviceHandle<rusb::Context>) -> Result<(), Error> {
1374 let address = self.address();
1375 let value = self.value();
1376 request(
1377 handle,
1378 &[
1379 0x02,
1380 0x01,
1381 0x01,
1382 0x40,
1383 0x0c,
1384 0x00,
1385 0x00,
1386 0x00,
1387 0x00,
1388 0x00,
1389 0x00,
1390 0x00,
1391 (address & 0xff) as u8,
1392 ((address >> 8) & 0xff) as u8,
1393 ((address >> 16) & 0xff) as u8,
1394 ((address >> 24) & 0xff) as u8,
1395 (value & 0xff) as u8,
1396 ((value >> 8) & 0xff) as u8,
1397 ((value >> 16) & 0xff) as u8,
1398 ((value >> 24) & 0xff) as u8,
1399 ],
1400 TIMEOUT,
1401 )?;
1402 Ok(())
1403 }
1404}
1405
1406impl Register for RuntimeRegister {
1407 fn address(&self) -> u32 {
1408 self.address
1409 }
1410 fn value(&self) -> u32 {
1411 self.value
1412 }
1413 fn offset(&self, registers: u32) -> RuntimeRegister {
1414 RuntimeRegister {
1415 address: self.address + registers * 4,
1416 value: self.value,
1417 }
1418 }
1419}
1420
1421macro_rules! register {
1422 ($name:ident, $address:literal, {$($subname:ident: $substart:literal..$subend:literal),+ $(,)?}) => {
1423 #[derive(Default)]
1424 struct $name {
1425 $(
1426 $subname: u32,
1427 )+
1428 }
1429 $(
1430 const _: () = assert!($substart < $subend);
1431 )+
1432 impl Register for $name {
1433 fn address(&self) -> u32 {
1434 $address
1435 }
1436 fn value(&self) -> u32 {
1437 0u32
1438 $(
1439 | ((self.$subname & (((1u64 << ($subend - $substart)) - 1) as u32)) << $substart)
1440 )+
1441 }
1442 fn offset(&self, registers: u32) -> RuntimeRegister {
1443 RuntimeRegister {
1444 address: $address + registers * 4,
1445 value: self.value(),
1446 }
1447 }
1448 }
1449 impl $name {
1450 #[allow(dead_code)]
1451 fn read(handle: &rusb::DeviceHandle<rusb::Context>) -> Result<Self, Error> {
1452 let buffer = [
1453 0x02,
1454 0x01,
1455 0x01,
1456 0x00,
1457 0x0c,
1458 0x00,
1459 0x00,
1460 0x00,
1461 0x00,
1462 0x00,
1463 0x00,
1464 0x00,
1465 ($address & 0xff) as u8,
1466 (($address >> 8) & 0xff) as u8,
1467 (($address >> 16) & 0xff) as u8,
1468 (($address >> 24) & 0xff) as u8,
1469 0x01,
1470 0x00,
1471 0x00,
1472 0x00,
1473 ];
1474 let result = request(handle, &buffer, TIMEOUT)?;
1475 if result.len() != buffer.len() {
1476 return Err(Error::RegisterReadShortResponse($address));
1477 }
1478 if result[0..16] != buffer[0..16] {
1479 return Err(Error::RegisterReadMismatch($address));
1480 }
1481 let value = u32::from_le_bytes(result[16..20].try_into().unwrap());
1483 Ok(Self {
1484 $(
1485 $subname: (value >> $substart) & (((1u64 << ($subend - $substart)) - 1) as u32),
1486 )+
1487 })
1488 }
1489 }
1490 };
1491}
1492
1493register! { Unknown0000, 0x0000, { value: 0..32 } }
1494register! { RoiCtrl, 0x0004, {
1495 reserved_0_1: 0..1,
1496 td_enable: 1..2,
1497 reserved_2_5: 2..5,
1498 td_shadow_trigger: 5..6,
1499 td_roni_n_en: 6..7,
1500 reserved_7_10: 7..10,
1501 td_rstn: 10..11,
1502 reserved_11_32: 11..32,
1503} }
1504register! { LifoCtrl, 0x000C, {
1505 lifo_en: 0..1,
1506 lifo_out_en: 1..2,
1507 lifo_cnt_en: 2..3,
1508 reserved_3_32: 3..32,
1509} }
1510register! { LifoStatus, 0x0010, {
1511 lifo_ton: 0..29,
1512 lifo_ton_valid: 29..30,
1513 reserved_30_32: 30..32,
1514} }
1515register! { Reserved0014, 0x0014, { value: 0..32 } }
1516register! { Spare0, 0x0018, { value: 0..32 } }
1517register! { Unknown001C, 0x001C, { value: 0..32 } }
1518register! { RefractoryCtrl, 0x0020, { value: 0..32 } }
1519register! { Unknown002C, 0x002C, { value: 0..32 } }
1520register! { RoiWinCtrl, 0x0034, { value: 0..32 } }
1521register! { RoiWinStartAddr, 0x0038, { value: 0..32 } }
1522register! { RoiWinEndAddr, 0x003C, { value: 0..32 } }
1523register! { DigPad2Ctrl, 0x0044, {
1524 reserved_0_16: 0..16,
1525 sync: 16..20,
1526 reserved_20_32: 20..32,
1527} }
1528register! { AdcControl, 0x004C, {
1529 adc_en: 0..1,
1530 adc_clk_en: 1..2,
1531 adc_start: 2..3,
1532 reserved_3_32: 3..32
1533} }
1534register! { AdcStatus, 0x0050, {
1535 adc_dac_dyn: 0..10,
1536 reserved_10_11: 10..11,
1537 adc_done_dyn: 11..12,
1538 reserved_12_32: 12..32,
1539} }
1540register! { AdcMiscCtrl, 0x0054, {
1541 reserved_0_1: 0..1,
1542 adc_buf_cal_en: 1..2,
1543 reserved_2_10: 2..10,
1544 adc_rng: 10..12,
1545 adc_temp: 12..13,
1546 reserved_13_32: 13..32,
1547} }
1548register! { TempCtrl, 0x005C, {
1549 temp_buf_cal_en: 0..1,
1550 temp_buf_en: 1..2,
1551 reserved_2_32: 2..32,
1552} }
1553register! { Unknown006C, 0x006C, { value: 0..32 } }
1554register! { Unknown0070, 0x0070, { value: 0..32 } }
1555register! { IphMirrCtrl, 0x0074, {
1556 iph_mirr_en: 0..1,
1557 iph_mirr_amp_en: 1..2,
1558 reserved_2_32: 2..32,
1559} }
1560register! { GcdCtrl1, 0x0078, { value: 0..32 } }
1561register! { GcdShadowCtrl, 0x0090, { value: 0..32 } }
1562register! { GcdShadowStatus, 0x0094, { value: 0..32 } }
1563register! { GcdShadowCounter, 0x0098, { value: 0..32 } }
1564register! { Unknown00B8, 0x00B8, { value: 0..32 } }
1565register! { Unknown00C0, 0x00C0, { value: 0..32 } }
1566register! { StopSequenceControl, 0x00C8, { value: 0..32 } }
1567register! { BiasPr, 0x1000, {
1568 idac_ctl: 0..8,
1569 vdac_ctl: 8..16,
1570 buf_stg: 16..19,
1571 ibtype_sel: 19..20,
1572 mux_sel: 20..21,
1573 mux_en: 21..22,
1574 vdac_en: 22..23,
1575 buf_en: 23..24,
1576 idac_en: 24..25,
1577 reserved: 25..28,
1578 single: 28..29,
1579} }
1580register! { BiasFo, 0x1004, {
1581 idac_ctl: 0..8,
1582 vdac_ctl: 8..16,
1583 buf_stg: 16..19,
1584 ibtype_sel: 19..20,
1585 mux_sel: 20..21,
1586 mux_en: 21..22,
1587 vdac_en: 22..23,
1588 buf_en: 23..24,
1589 idac_en: 24..25,
1590 reserved: 25..28,
1591 single: 28..29,
1592} }
1593register! { BiasHpf, 0x100C, {
1594 idac_ctl: 0..8,
1595 vdac_ctl: 8..16,
1596 buf_stg: 16..19,
1597 ibtype_sel: 19..20,
1598 mux_sel: 20..21,
1599 mux_en: 21..22,
1600 vdac_en: 22..23,
1601 buf_en: 23..24,
1602 idac_en: 24..25,
1603 reserved: 25..28,
1604 single: 28..29,
1605} }
1606register! { BiasDiffOn, 0x1010, {
1607 idac_ctl: 0..8,
1608 vdac_ctl: 8..16,
1609 buf_stg: 16..19,
1610 ibtype_sel: 19..20,
1611 mux_sel: 20..21,
1612 mux_en: 21..22,
1613 vdac_en: 22..23,
1614 buf_en: 23..24,
1615 idac_en: 24..25,
1616 reserved: 25..28,
1617 single: 28..29,
1618} }
1619register! { BiasDiff, 0x1014, {
1620 idac_ctl: 0..8,
1621 vdac_ctl: 8..16,
1622 buf_stg: 16..19,
1623 ibtype_sel: 19..20,
1624 mux_sel: 20..21,
1625 mux_en: 21..22,
1626 vdac_en: 22..23,
1627 buf_en: 23..24,
1628 idac_en: 24..25,
1629 reserved: 25..28,
1630 single: 28..29,
1631} }
1632register! { BiasDiffOff, 0x1018, {
1633 idac_ctl: 0..8,
1634 vdac_ctl: 8..16,
1635 buf_stg: 16..19,
1636 ibtype_sel: 19..20,
1637 mux_sel: 20..21,
1638 mux_en: 21..22,
1639 vdac_en: 22..23,
1640 buf_en: 23..24,
1641 idac_en: 24..25,
1642 reserved: 25..28,
1643 single: 28..29,
1644} }
1645register! { BiasInv, 0x101C, {
1646 idac_ctl: 0..8,
1647 vdac_ctl: 8..16,
1648 buf_stg: 16..19,
1649 ibtype_sel: 19..20,
1650 mux_sel: 20..21,
1651 mux_en: 21..22,
1652 vdac_en: 22..23,
1653 buf_en: 23..24,
1654 idac_en: 24..25,
1655 reserved: 25..28,
1656 single: 28..29,
1657} }
1658register! { BiasRefr, 0x1020, {
1659 idac_ctl: 0..8,
1660 vdac_ctl: 8..16,
1661 buf_stg: 16..19,
1662 ibtype_sel: 19..20,
1663 mux_sel: 20..21,
1664 mux_en: 21..22,
1665 vdac_en: 22..23,
1666 buf_en: 23..24,
1667 idac_en: 24..25,
1668 reserved: 25..28,
1669 single: 28..29,
1670} }
1671register! { BiasReqpuy, 0x1040, {
1672 idac_ctl: 0..8,
1673 vdac_ctl: 8..16,
1674 buf_stg: 16..19,
1675 ibtype_sel: 19..20,
1676 mux_sel: 20..21,
1677 mux_en: 21..22,
1678 vdac_en: 22..23,
1679 buf_en: 23..24,
1680 idac_en: 24..25,
1681 reserved: 25..28,
1682 single: 28..29,
1683} }
1684register! { BiasReqpux, 0x1044, {
1685 idac_ctl: 0..8,
1686 vdac_ctl: 8..16,
1687 buf_stg: 16..19,
1688 ibtype_sel: 19..20,
1689 mux_sel: 20..21,
1690 mux_en: 21..22,
1691 vdac_en: 22..23,
1692 buf_en: 23..24,
1693 idac_en: 24..25,
1694 reserved: 25..28,
1695 single: 28..29,
1696} }
1697register! { BiasSendreqpdy, 0x1048, {
1698 idac_ctl: 0..8,
1699 vdac_ctl: 8..16,
1700 buf_stg: 16..19,
1701 ibtype_sel: 19..20,
1702 mux_sel: 20..21,
1703 mux_en: 21..22,
1704 vdac_en: 22..23,
1705 buf_en: 23..24,
1706 idac_en: 24..25,
1707 reserved: 25..28,
1708 single: 28..29,
1709} }
1710register! { BiasUnknown1, 0x104C, {
1711 idac_ctl: 0..8,
1712 vdac_ctl: 8..16,
1713 buf_stg: 16..19,
1714 ibtype_sel: 19..20,
1715 mux_sel: 20..21,
1716 mux_en: 21..22,
1717 vdac_en: 22..23,
1718 buf_en: 23..24,
1719 idac_en: 24..25,
1720 reserved: 25..28,
1721 single: 28..29,
1722} }
1723register! { BiasUnknown2, 0x1050, {
1724 idac_ctl: 0..8,
1725 vdac_ctl: 8..16,
1726 buf_stg: 16..19,
1727 ibtype_sel: 19..20,
1728 mux_sel: 20..21,
1729 mux_en: 21..22,
1730 vdac_en: 22..23,
1731 buf_en: 23..24,
1732 idac_en: 24..25,
1733 reserved: 25..28,
1734 single: 28..29,
1735} }
1736register! { BgenCtrl, 0x1100, { value: 0..32 } }
1737register! { Unknown1104, 0x1104, { value: 0..32 } }
1738register! { TdRoiX, 0x2000, { value: 0..32 } }
1739register! { TdRoiY, 0x4000, { value: 0..32 } }
1740register! { ErcReserved6000, 0x6000, { value: 0..32 } }
1741register! { ErcInDropRateControl, 0x6004, {
1742 enable: 0..1,
1743 reserved_1_32: 1..32,
1744} }
1745register! { ErcReferencePeriod, 0x6008, {
1746 duration_us: 0..10,
1747 reserved_10_32: 10..32,
1748} }
1749register! { ErcTdTargetEventRate, 0x600C, {
1750 maximum_per_period: 0..22,
1751 reserved_22_32: 22..32,
1752} }
1753register! { ErcControl, 0x6028, {
1754 enable: 0..1,
1755 reserved_1_32: 1..32,
1756} }
1757register! { ErcReserved602C, 0x602C, { value: 0..32 } }
1758register! { ErcTDroppingControl, 0x6050, {
1759 enable: 0..1,
1760 reserved_1_32: 1..32,
1761} }
1762register! { ErcHDroppingControl, 0x6060, {
1763 enable: 0..1,
1764 reserved_1_32: 1..32,
1765} }
1766register! { ErcVDroppingControl, 0x6070, {
1767 enable: 0..1,
1768 reserved_1_32: 1..32,
1769} }
1770register! { TDropLut, 0x6400, { value: 0..32 } }
1771register! { ErcReserved6800, 0x6800, { value: 0..32 } }
1772register! { EdfPipelineControl, 0x7000, { value: 0..32 } }
1773register! { EdfReserved7004, 0x7004, {
1774 reserved_0_10: 0..10,
1775 external_trigger: 10..11,
1776 reserved_11_32: 11..32,
1777} }
1778register! { Unknown7008, 0x7008, { value: 0..32 } }
1779register! { Unknown8000, 0x8000, { value: 0..32 } }
1780register! { ReadoutCtrl, 0x9000, { value: 0..32 } }
1781register! { RoFsmCtrl, 0x9004, {
1782 readout_wait: 0..16,
1783 reserved_16_31: 16..32,
1784} }
1785register! { TimeBaseCtrl, 0x9008, {
1786 enable: 0..1,
1787 external: 1..2,
1788 primary: 2..3,
1789 external_enable: 3..4,
1790 reserved_4_32: 4..32,
1791} }
1792register! { DigCtrl, 0x900C, { value: 0..32 } }
1793register! { DigStartPos, 0x9010, { value: 0..32 } }
1794register! { DigEndPos, 0x9014, { value: 0..32 } }
1795register! { RoCtrl, 0x9028, {
1796 area_count_enable: 0..1,
1797 output_disable: 1..2,
1798 keep_timer_high: 2..3,
1799} }
1800register! { AreaX0Addr, 0x902C, { value: 0..32 } }
1801register! { AreaX1Addr, 0x9030, { value: 0..32 } }
1802register! { AreaX2Addr, 0x9034, { value: 0..32 } }
1803register! { AreaX3Addr, 0x9038, { value: 0..32 } }
1804register! { AreaX4Addr, 0x903C, { value: 0..32 } }
1805register! { AreaY0Addr, 0x9040, { value: 0..32 } }
1806register! { AreaY1Addr, 0x9044, { value: 0..32 } }
1807register! { AreaY2Addr, 0x9048, { value: 0..32 } }
1808register! { AreaY3Addr, 0x904C, { value: 0..32 } }
1809register! { AreaY4Addr, 0x9050, { value: 0..32 } }
1810register! { CounterCtrl, 0x9054, { value: 0..32 } }
1811register! { CounterTimerThreshold, 0x9058, { value: 0..32 } }
1812register! { DigitalMask, 0x9100, {
1813 x: 0..11,
1814 reserved_11_16: 11..16,
1815 y: 16..26,
1816 reserved_26_31: 26..31,
1817 enable: 31..32,
1818} }
1819register! { AreaCnt00, 0x9200, { value: 0..32 } }
1820register! { AreaCnt01, 0x9204, { value: 0..32 } }
1821register! { AreaCnt02, 0x9208, { value: 0..32 } }
1822register! { AreaCnt03, 0x920C, { value: 0..32 } }
1823register! { AreaCnt04, 0x9210, { value: 0..32 } }
1824register! { AreaCnt05, 0x9214, { value: 0..32 } }
1825register! { AreaCnt06, 0x9218, { value: 0..32 } }
1826register! { AreaCnt07, 0x921C, { value: 0..32 } }
1827register! { AreaCnt08, 0x9220, { value: 0..32 } }
1828register! { AreaCnt09, 0x9224, { value: 0..32 } }
1829register! { AreaCnt10, 0x9228, { value: 0..32 } }
1830register! { AreaCnt11, 0x922C, { value: 0..32 } }
1831register! { AreaCnt12, 0x9230, { value: 0..32 } }
1832register! { AreaCnt13, 0x9234, { value: 0..32 } }
1833register! { AreaCnt14, 0x9238, { value: 0..32 } }
1834register! { AreaCnt15, 0x923C, { value: 0..32 } }
1835register! { EvtVectorCntVal, 0x9244, { value: 0..32 } }
1836register! { UnknownA000, 0xA000, { value: 0..32 } }
1837register! { UnknownA004, 0xA004, { value: 0..32 } }
1838register! { UnknownA008, 0xA008, { value: 0..32 } }
1839register! { UnknownA00C, 0xA00C, { value: 0..32 } }
1840register! { UnknownA010, 0xA010, { value: 0..32 } }
1841register! { UnknownA020, 0xA020, { value: 0..32 } }
1842register! { MipiControl, 0xB000, { value: 0..32 } }
1843register! { UnknownB004, 0xB004, { value: 0..32 } }
1844register! { UnknownB01C, 0xB01C, { value: 0..32 } }
1845register! { MipiPacketSize, 0xB020, { value: 0..32 } }
1846register! { MipiPacketTimeout, 0xB024, { value: 0..32 } }
1847register! { MipiFramePeriod, 0xB028, { value: 0..32 } }
1848register! { UnknownB02C, 0xB02C, { value: 0..32 } }
1849register! { MipiFrameBlanking, 0xB030, { value: 0..32 } }
1850register! { UnknownB040, 0xB040, { value: 0..32 } }
1851register! { UnknownB044, 0xB044, { value: 0..32 } }
1852register! { UnknownB064, 0xB064, { value: 0..32 } }
1853register! { UnknownB068, 0xB068, { value: 0..32 } }
1854register! { UnknownB074, 0xB074, { value: 0..32 } }
1855register! { UnknownB078, 0xB078, { value: 0..32 } }
1856register! { UnknownB07C, 0xB07C, { value: 0..32 } }
1857register! { UnknownB080, 0xB080, { value: 0..32 } }
1858register! { UnknownB084, 0xB084, { value: 0..32 } }
1859register! { UnknownB088, 0xB088, { value: 0..32 } }
1860register! { UnknownB08C, 0xB08C, { value: 0..32 } }
1861register! { UnknownB090, 0xB090, { value: 0..32 } }
1862register! { UnknownB094, 0xB094, { value: 0..32 } }
1863register! { UnknownB098, 0xB098, { value: 0..32 } }
1864register! { UnknownB09C, 0xB09C, { value: 0..32 } }
1865register! { UnknownB0A0, 0xB0A0, { value: 0..32 } }
1866register! { UnknownB0A4, 0xB0A4, { value: 0..32 } }
1867register! { UnknownB0AC, 0xB0AC, { value: 0..32 } }
1868register! { UnknownB0C8, 0xB0C8, { value: 0..32 } }
1869register! { UnknownB0CC, 0xB0CC, { value: 0..32 } }
1870register! { UnknownB120, 0xB120, { value: 0..32 } }
1871register! { AfkPipelineControl, 0xC000, {
1872 reserved_0_2: 0..2,
1873 bypass: 2..3,
1874} }
1875register! { ReservedC004, 0xC004, { value: 0..32 } }
1876register! { AfkPeriod, 0xC008, {
1877 min_cutoff_period: 0..8,
1878 max_cutoff_period: 8..16,
1879 inverted_duty_cycle: 16..20,
1880} }
1881register! { Invalidation, 0xC0C0, { value: 0..32 } }
1882register! { AfkInitialization, 0xC0C4, { value: 0..32 } }
1883register! { BurstPipelineControl, 0xD000, {
1884 reserved_0_2: 0..2,
1885 bypass: 2..3,
1886} }
1887register! { StcParam, 0xD004, {
1888 enable: 0..1,
1889 threshold: 1..20,
1890 reserved_20_24: 20..24,
1891 disable_cut_trail: 24..25,
1892} }
1893register! { TrailParam, 0xD008, {
1894 enable: 0..1,
1895 threshold: 1..20,
1896} }
1897register! { StcTimestamping, 0xD00C, {
1898 prescaler: 0..5,
1899 multiplier: 5..9,
1900 reserved_9_16: 9..16,
1901 reset_refractory_period_on_event: 16..17,
1902} }
1903register! { BurstPipelineInvalidation, 0xD0C0, {
1904 dt_fifo_wait_time: 0..12,
1905 dt_fifo_timeout: 12..24,
1906 reserved_24_29: 24..29,
1907} }
1908register! { BurstPipelineInitialization, 0xD0C4, {
1909 force_sram_initialization: 0..1,
1910 reserved_1_2: 1..2,
1911 clear_flag: 2..3,
1912} }
1913register! { SlvsControl, 0xE000, { value: 0..32 } }
1914register! { SlvsPacketSize, 0xE020, { value: 0..32 } }
1915register! { SlvsPacketTimeout, 0xE024, { value: 0..32 } }
1916register! { SlvsFrameBlanking, 0xE030, { value: 0..32 } }
1917register! { UnknownE120, 0xE120, { value: 0..32 } }
1918register! { SlvsPhyLogicCtrl00, 0xE150, { value: 0..32 } }
1919register! { Reset, 0x400004, { value: 0..32 } }