pokeys_lib/protocols/uspibridge.rs
1//! uSPIBridge protocol implementation
2//!
3//! This module provides uSPIBridge-specific functionality for PoKeys devices,
4//! including custom segment mapping and display configuration for MAX7219 devices.
5
6use crate::device::PoKeysDevice;
7use crate::error::Result;
8use crate::types::I2cStatus;
9
10/// uSPIBridge-specific I2C commands for display control and virtual devices
11///
12/// All commands are now available via I2C interface after firmware implementation.
13#[derive(Debug, Clone, Copy, PartialEq)]
14#[repr(u8)]
15pub enum USPIBridgeCommand {
16 // Device Commands (0x10-0x2F) - All implemented in I2C
17 SetBrightness = 0x11, // Set device brightness ✅
18 DisplayText = 0x20, // Display text on device ✅
19 DisplayNumber = 0x21, // Display number on device ✅
20 SetCharacter = 0x22, // Set character at position ✅
21 SetPattern = 0x23, // Set raw segment pattern ✅
22 SetDecimal = 0x24, // Set decimal point ✅
23 ClearDevice = 0x25, // Clear device ✅
24
25 // Segment Mapping Commands (0x26-0x2F) - Now implemented in I2C
26 SetSegmentMapping = 0x26, // Set custom segment mapping array ✅
27 SetSegmentMappingType = 0x27, // Set predefined segment mapping type ✅
28 GetSegmentMapping = 0x28, // Get current segment mapping ✅
29 TestSegmentMapping = 0x29, // Test segment mapping with pattern ✅
30
31 // Virtual Display Commands (0x40-0x4F) - All implemented in I2C
32 CreateVirtualDevice = 0x40, // Create virtual device ✅
33 DeleteVirtualDevice = 0x41, // Delete virtual device ✅
34 ListVirtualDevices = 0x42, // List virtual devices ✅
35 VirtualText = 0x43, // Virtual display text ✅
36 VirtualBrightness = 0x44, // Virtual device brightness ✅
37 VirtualClear = 0x45, // Clear virtual display ✅
38 VirtualScrollLeft = 0x46, // Virtual scroll left ✅
39 VirtualScrollRight = 0x47, // Virtual scroll right ✅
40 VirtualFlash = 0x48, // Virtual flash ✅
41 VirtualStop = 0x49, // Stop virtual effect ✅
42
43 // System Commands (0x50-0x5F) - Implemented in I2C
44 SystemReset = 0x50, // Reset system/devices ✅
45 SystemStatus = 0x51, // Get system status ✅
46 SystemConfig = 0x52, // System configuration (Serial only)
47}
48
49/// Predefined segment mapping types for different display manufacturers
50///
51/// Values match the uSPIBridge firmware SegmentMappingType enum:
52/// - C++ enum class values are implicitly 0, 1, 2, 3, 4, 5
53/// - I2C interface currently only accepts 0-4 for setSegmentMappingType
54/// - Value 5 (Custom) is used internally when custom arrays are provided
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56#[repr(u8)]
57pub enum SegmentMappingType {
58 /// Standard MAX7219 mapping (A=6, B=5, C=4, D=3, E=2, F=1, G=0, DP=7)
59 Standard = 0,
60 /// Completely reversed bit order mapping
61 Reversed = 1,
62 /// Common cathode display variant mapping
63 CommonCathode = 2,
64 /// SparkFun Serial 7-Segment Display mapping
65 SparkfunSerial = 3,
66 /// Adafruit LED Backpack mapping
67 AdafruitBackpack = 4,
68 /// User-defined custom mapping (used internally)
69 Custom = 5,
70}
71
72impl Default for SegmentMappingType {
73 fn default() -> Self {
74 Self::Standard
75 }
76}
77
78/// Segment mapping configuration for custom 7-segment display wiring
79#[derive(Debug, Clone, PartialEq)]
80pub struct SegmentMapping {
81 /// The type of segment mapping being used
82 pub mapping_type: SegmentMappingType,
83 /// Custom bit mapping array (only used when mapping_type is Custom)
84 pub custom_mapping: Option<[u8; 8]>,
85}
86
87impl Default for SegmentMapping {
88 fn default() -> Self {
89 Self {
90 mapping_type: SegmentMappingType::Standard,
91 custom_mapping: None,
92 }
93 }
94}
95
96impl SegmentMapping {
97 /// Create a new segment mapping with a predefined type
98 pub fn new(mapping_type: SegmentMappingType) -> Self {
99 Self {
100 mapping_type,
101 custom_mapping: None,
102 }
103 }
104
105 /// Create a new segment mapping with a custom mapping array
106 pub fn custom(mapping: [u8; 8]) -> Self {
107 Self {
108 mapping_type: SegmentMappingType::Custom,
109 custom_mapping: Some(mapping),
110 }
111 }
112
113 /// Check if this mapping uses a custom array
114 pub fn is_custom(&self) -> bool {
115 self.mapping_type == SegmentMappingType::Custom
116 }
117
118 /// Get the mapping array if it's custom
119 pub fn get_custom_mapping(&self) -> Option<&[u8; 8]> {
120 self.custom_mapping.as_ref()
121 }
122}
123
124/// uSPIBridge configuration for multiple MAX7219 devices
125#[derive(Debug, Clone)]
126pub struct USPIBridgeConfig {
127 /// Number of MAX7219 devices in the daisy chain
128 pub device_count: u8,
129 /// Segment mappings for each device
130 pub segment_mappings: Vec<SegmentMapping>,
131 /// Default brightness level (0-15)
132 pub default_brightness: u8,
133 /// Maximum number of virtual devices supported
134 pub max_virtual_devices: u8,
135}
136
137impl Default for USPIBridgeConfig {
138 fn default() -> Self {
139 Self::new()
140 }
141}
142
143impl USPIBridgeConfig {
144 /// Create a new uSPIBridge configuration with default settings
145 pub fn new() -> Self {
146 Self {
147 device_count: 8,
148 segment_mappings: vec![SegmentMapping::default(); 8],
149 default_brightness: 8,
150 max_virtual_devices: 16,
151 }
152 }
153
154 /// Set the number of devices in the daisy chain
155 pub fn with_device_count(mut self, count: u8) -> Self {
156 self.device_count = count;
157 // Ensure we have enough segment mappings
158 self.segment_mappings
159 .resize(count as usize, SegmentMapping::default());
160 self
161 }
162
163 /// Set the segment mapping for a specific device
164 pub fn with_segment_mapping(mut self, device_id: usize, mapping: SegmentMapping) -> Self {
165 if device_id < self.segment_mappings.len() {
166 self.segment_mappings[device_id] = mapping;
167 }
168 self
169 }
170
171 /// Set the same segment mapping for all devices
172 pub fn with_all_devices_segment_mapping(mut self, mapping: SegmentMapping) -> Self {
173 for device_mapping in &mut self.segment_mappings {
174 *device_mapping = mapping.clone();
175 }
176 self
177 }
178
179 /// Set the default brightness level
180 pub fn with_default_brightness(mut self, brightness: u8) -> Self {
181 self.default_brightness = brightness.min(15);
182 self
183 }
184
185 /// Set the maximum number of virtual devices
186 pub fn with_max_virtual_devices(mut self, max_devices: u8) -> Self {
187 self.max_virtual_devices = max_devices;
188 self
189 }
190}
191
192/// uSPIBridge protocol implementation
193impl PoKeysDevice {
194 /// Write I2C command with proper uSPIBridge packet structure
195 ///
196 /// # Arguments
197 /// * `slave_address` - I2C slave address of the uSPIBridge device
198 /// * `command` - uSPIBridge command type
199 /// * `device_id` - Target device ID (for device-specific commands)
200 /// * `data` - Command payload data
201 ///
202 /// # Returns
203 /// I2C operation status
204 pub fn uspibridge_write_command(
205 &mut self,
206 slave_address: u8,
207 command: USPIBridgeCommand,
208 device_id: u8,
209 data: &[u8],
210 ) -> Result<I2cStatus> {
211 let mut packet = Vec::new();
212 packet.push(command as u8); // Command type
213 packet.push(device_id); // Device ID
214 packet.push(data.len() as u8); // Data length
215 packet.extend_from_slice(data); // Data payload
216
217 // Calculate XOR checksum
218 let mut checksum = 0u8;
219 for &byte in &packet {
220 checksum ^= byte;
221 }
222 packet.push(checksum);
223
224 self.i2c_write(slave_address, &packet)
225 }
226
227 /// Set custom segment mapping for a specific device
228 ///
229 /// # Arguments
230 /// * `slave_address` - I2C slave address of the uSPIBridge device
231 /// * `device_id` - Target MAX7219 device ID (0-based)
232 /// * `mapping` - Array of 8 values mapping standard bits to custom bits
233 ///
234 /// # Returns
235 /// I2C operation status
236 pub fn uspibridge_set_segment_mapping(
237 &mut self,
238 slave_address: u8,
239 device_id: u8,
240 mapping: &[u8; 8],
241 ) -> Result<I2cStatus> {
242 self.uspibridge_write_command(
243 slave_address,
244 USPIBridgeCommand::SetSegmentMapping,
245 device_id,
246 mapping,
247 )
248 }
249
250 /// Set predefined segment mapping type for a specific device
251 ///
252 /// # Arguments
253 /// * `slave_address` - I2C slave address of the uSPIBridge device
254 /// * `device_id` - Target MAX7219 device ID (0-based)
255 /// * `mapping_type` - Predefined mapping type to use (0-4 supported)
256 ///
257 /// # Returns
258 /// I2C operation status
259 pub fn uspibridge_set_segment_mapping_type(
260 &mut self,
261 slave_address: u8,
262 device_id: u8,
263 mapping_type: SegmentMappingType,
264 ) -> Result<I2cStatus> {
265 let data = vec![mapping_type as u8];
266 self.uspibridge_write_command(
267 slave_address,
268 USPIBridgeCommand::SetSegmentMappingType,
269 device_id,
270 &data,
271 )
272 }
273
274 /// Get current segment mapping for a specific device
275 ///
276 /// # Arguments
277 /// * `slave_address` - I2C slave address of the uSPIBridge device
278 /// * `device_id` - Target MAX7219 device ID (0-based)
279 ///
280 /// # Returns
281 /// Tuple of (I2C status, optional segment mapping array)
282 pub fn uspibridge_get_segment_mapping(
283 &mut self,
284 slave_address: u8,
285 device_id: u8,
286 ) -> Result<(I2cStatus, Option<[u8; 8]>)> {
287 // Send get mapping command
288 let status = self.uspibridge_write_command(
289 slave_address,
290 USPIBridgeCommand::GetSegmentMapping,
291 device_id,
292 &[],
293 )?;
294
295 if status != I2cStatus::Ok {
296 return Ok((status, None));
297 }
298
299 // Wait for response processing
300 std::thread::sleep(std::time::Duration::from_millis(10));
301
302 // Read response (expecting 8 bytes of mapping data)
303 let (read_status, response_data) = self.i2c_read(slave_address, 10)?;
304
305 if read_status == I2cStatus::Ok && response_data.len() >= 8 {
306 let mut mapping = [0u8; 8];
307 mapping.copy_from_slice(&response_data[0..8]);
308 Ok((read_status, Some(mapping)))
309 } else {
310 Ok((read_status, None))
311 }
312 }
313
314 /// Test segment mapping with a specific pattern
315 ///
316 /// This command displays a test pattern on the specified device to verify
317 /// that the segment mapping is working correctly.
318 ///
319 /// # Arguments
320 /// * `slave_address` - I2C slave address of the uSPIBridge device
321 /// * `device_id` - Target MAX7219 device ID (0-based)
322 /// * `test_pattern` - 8-bit pattern to display for testing
323 ///
324 /// # Returns
325 /// I2C operation status
326 pub fn uspibridge_test_segment_mapping(
327 &mut self,
328 slave_address: u8,
329 device_id: u8,
330 test_pattern: u8,
331 ) -> Result<I2cStatus> {
332 let data = vec![test_pattern];
333 self.uspibridge_write_command(
334 slave_address,
335 USPIBridgeCommand::TestSegmentMapping,
336 device_id,
337 &data,
338 )
339 }
340
341 /// Display text on a specific MAX7219 device
342 ///
343 /// # Arguments
344 /// * `slave_address` - I2C slave address of the uSPIBridge device
345 /// * `device_id` - Target MAX7219 device ID (0-based)
346 /// * `text` - Text to display on the device
347 ///
348 /// # Returns
349 /// I2C operation status
350 pub fn uspibridge_display_text(
351 &mut self,
352 slave_address: u8,
353 device_id: u8,
354 text: &str,
355 ) -> Result<I2cStatus> {
356 self.uspibridge_write_command(
357 slave_address,
358 USPIBridgeCommand::DisplayText,
359 device_id,
360 text.as_bytes(),
361 )
362 }
363
364 /// Display a number on a specific MAX7219 device
365 ///
366 /// # Arguments
367 /// * `slave_address` - I2C slave address of the uSPIBridge device
368 /// * `device_id` - Target MAX7219 device ID (0-based)
369 /// * `number` - 32-bit number to display
370 ///
371 /// # Returns
372 /// I2C operation status
373 pub fn uspibridge_display_number(
374 &mut self,
375 slave_address: u8,
376 device_id: u8,
377 number: u32,
378 ) -> Result<I2cStatus> {
379 let data = number.to_le_bytes();
380 self.uspibridge_write_command(
381 slave_address,
382 USPIBridgeCommand::DisplayNumber,
383 device_id,
384 &data,
385 )
386 }
387
388 /// Set a character at a specific position on a MAX7219 device
389 ///
390 /// # Arguments
391 /// * `slave_address` - I2C slave address of the uSPIBridge device
392 /// * `device_id` - Target MAX7219 device ID (0-based)
393 /// * `position` - Position on the display (0-7)
394 /// * `character` - Character to display
395 ///
396 /// # Returns
397 /// I2C operation status
398 pub fn uspibridge_set_character(
399 &mut self,
400 slave_address: u8,
401 device_id: u8,
402 position: u8,
403 character: u8,
404 ) -> Result<I2cStatus> {
405 let data = vec![position, character];
406 self.uspibridge_write_command(
407 slave_address,
408 USPIBridgeCommand::SetCharacter,
409 device_id,
410 &data,
411 )
412 }
413
414 /// Set a raw segment pattern at a specific position on a MAX7219 device
415 ///
416 /// # Arguments
417 /// * `slave_address` - I2C slave address of the uSPIBridge device
418 /// * `device_id` - Target MAX7219 device ID (0-based)
419 /// * `position` - Position on the display (0-7)
420 /// * `pattern` - 8-bit segment pattern
421 ///
422 /// # Returns
423 /// I2C operation status
424 pub fn uspibridge_set_pattern(
425 &mut self,
426 slave_address: u8,
427 device_id: u8,
428 position: u8,
429 pattern: u8,
430 ) -> Result<I2cStatus> {
431 let data = vec![position, pattern];
432 self.uspibridge_write_command(
433 slave_address,
434 USPIBridgeCommand::SetPattern,
435 device_id,
436 &data,
437 )
438 }
439
440 /// Set decimal point at a specific position on a MAX7219 device
441 ///
442 /// # Arguments
443 /// * `slave_address` - I2C slave address of the uSPIBridge device
444 /// * `device_id` - Target MAX7219 device ID (0-based)
445 /// * `position` - Position on the display (0-7)
446 /// * `state` - Decimal point state (0=off, 1=on)
447 ///
448 /// # Returns
449 /// I2C operation status
450 pub fn uspibridge_set_decimal(
451 &mut self,
452 slave_address: u8,
453 device_id: u8,
454 position: u8,
455 state: bool,
456 ) -> Result<I2cStatus> {
457 let data = vec![position, if state { 1 } else { 0 }];
458 self.uspibridge_write_command(
459 slave_address,
460 USPIBridgeCommand::SetDecimal,
461 device_id,
462 &data,
463 )
464 }
465
466 /// Set brightness for a specific MAX7219 device
467 ///
468 /// # Arguments
469 /// * `slave_address` - I2C slave address of the uSPIBridge device
470 /// * `device_id` - Target MAX7219 device ID (0-based)
471 /// * `brightness` - Brightness level (0-15)
472 ///
473 /// # Returns
474 /// I2C operation status
475 pub fn uspibridge_set_brightness(
476 &mut self,
477 slave_address: u8,
478 device_id: u8,
479 brightness: u8,
480 ) -> Result<I2cStatus> {
481 let data = vec![brightness.min(15)];
482 self.uspibridge_write_command(
483 slave_address,
484 USPIBridgeCommand::SetBrightness,
485 device_id,
486 &data,
487 )
488 }
489
490 /// Clear a specific MAX7219 device
491 ///
492 /// # Arguments
493 /// * `slave_address` - I2C slave address of the uSPIBridge device
494 /// * `device_id` - Target MAX7219 device ID (0-based)
495 ///
496 /// # Returns
497 /// I2C operation status
498 pub fn uspibridge_clear_device(
499 &mut self,
500 slave_address: u8,
501 device_id: u8,
502 ) -> Result<I2cStatus> {
503 self.uspibridge_write_command(
504 slave_address,
505 USPIBridgeCommand::ClearDevice,
506 device_id,
507 &[],
508 )
509 }
510
511 /// Set text on a virtual display
512 ///
513 /// # Arguments
514 /// * `slave_address` - I2C slave address of the uSPIBridge device
515 /// * `virtual_id` - Virtual display ID (0-based)
516 /// * `text` - Text to display
517 ///
518 /// # Returns
519 /// I2C operation status
520 pub fn uspibridge_virtual_text(
521 &mut self,
522 slave_address: u8,
523 virtual_id: u8,
524 text: &str,
525 ) -> Result<I2cStatus> {
526 self.uspibridge_write_command(
527 slave_address,
528 USPIBridgeCommand::VirtualText,
529 virtual_id,
530 text.as_bytes(),
531 )
532 }
533
534 /// Create a new virtual device
535 ///
536 /// # Arguments
537 /// * `slave_address` - I2C slave address of the uSPIBridge device
538 /// * `virtual_id` - Virtual device ID to create (0-based)
539 /// * `physical_devices` - Array of physical device IDs to map to this virtual device
540 ///
541 /// # Returns
542 /// I2C operation status
543 pub fn uspibridge_create_virtual_device(
544 &mut self,
545 slave_address: u8,
546 virtual_id: u8,
547 physical_devices: &[u8],
548 ) -> Result<I2cStatus> {
549 self.uspibridge_write_command(
550 slave_address,
551 USPIBridgeCommand::CreateVirtualDevice,
552 virtual_id,
553 physical_devices,
554 )
555 }
556
557 /// Delete a virtual device
558 ///
559 /// # Arguments
560 /// * `slave_address` - I2C slave address of the uSPIBridge device
561 /// * `virtual_id` - Virtual device ID to delete (0-based)
562 ///
563 /// # Returns
564 /// I2C operation status
565 pub fn uspibridge_delete_virtual_device(
566 &mut self,
567 slave_address: u8,
568 virtual_id: u8,
569 ) -> Result<I2cStatus> {
570 self.uspibridge_write_command(
571 slave_address,
572 USPIBridgeCommand::DeleteVirtualDevice,
573 virtual_id,
574 &[],
575 )
576 }
577
578 /// List all virtual devices
579 ///
580 /// # Arguments
581 /// * `slave_address` - I2C slave address of the uSPIBridge device
582 ///
583 /// # Returns
584 /// Tuple of (I2C status, optional virtual device list data)
585 pub fn uspibridge_list_virtual_devices(
586 &mut self,
587 slave_address: u8,
588 ) -> Result<(I2cStatus, Option<Vec<u8>>)> {
589 let status = self.uspibridge_write_command(
590 slave_address,
591 USPIBridgeCommand::ListVirtualDevices,
592 0, // Device ID not used for this command
593 &[],
594 )?;
595
596 if status != I2cStatus::Ok {
597 return Ok((status, None));
598 }
599
600 // Wait for response processing
601 std::thread::sleep(std::time::Duration::from_millis(10));
602
603 // Read response
604 let (read_status, response_data) = self.i2c_read(slave_address, 32)?;
605 Ok((read_status, Some(response_data)))
606 }
607
608 /// Set brightness for a virtual device
609 ///
610 /// # Arguments
611 /// * `slave_address` - I2C slave address of the uSPIBridge device
612 /// * `virtual_id` - Virtual device ID (0-based)
613 /// * `brightness` - Brightness level (0-15)
614 ///
615 /// # Returns
616 /// I2C operation status
617 pub fn uspibridge_virtual_brightness(
618 &mut self,
619 slave_address: u8,
620 virtual_id: u8,
621 brightness: u8,
622 ) -> Result<I2cStatus> {
623 let data = vec![brightness.min(15)];
624 self.uspibridge_write_command(
625 slave_address,
626 USPIBridgeCommand::VirtualBrightness,
627 virtual_id,
628 &data,
629 )
630 }
631
632 /// Start scrolling effect on a virtual display
633 ///
634 /// # Arguments
635 /// * `slave_address` - I2C slave address of the uSPIBridge device
636 /// * `virtual_id` - Virtual display ID (0-based)
637 /// * `text` - Text to scroll
638 /// * `speed_ms` - Scroll speed in milliseconds
639 /// * `direction_left` - True for left scroll, false for right scroll
640 ///
641 /// # Returns
642 /// I2C operation status
643 pub fn uspibridge_virtual_scroll(
644 &mut self,
645 slave_address: u8,
646 virtual_id: u8,
647 text: &str,
648 speed_ms: u16,
649 direction_left: bool,
650 ) -> Result<I2cStatus> {
651 let mut data = text.as_bytes().to_vec();
652 data.extend_from_slice(&speed_ms.to_le_bytes());
653
654 let command = if direction_left {
655 USPIBridgeCommand::VirtualScrollLeft
656 } else {
657 USPIBridgeCommand::VirtualScrollRight
658 };
659
660 self.uspibridge_write_command(slave_address, command, virtual_id, &data)
661 }
662
663 /// Start flashing effect on a virtual display
664 ///
665 /// # Arguments
666 /// * `slave_address` - I2C slave address of the uSPIBridge device
667 /// * `virtual_id` - Virtual display ID (0-based)
668 /// * `text` - Text to flash
669 /// * `interval_ms` - Flash interval in milliseconds
670 ///
671 /// # Returns
672 /// I2C operation status
673 pub fn uspibridge_virtual_flash(
674 &mut self,
675 slave_address: u8,
676 virtual_id: u8,
677 text: &str,
678 interval_ms: u16,
679 ) -> Result<I2cStatus> {
680 let mut data = text.as_bytes().to_vec();
681 data.extend_from_slice(&interval_ms.to_le_bytes());
682
683 self.uspibridge_write_command(
684 slave_address,
685 USPIBridgeCommand::VirtualFlash,
686 virtual_id,
687 &data,
688 )
689 }
690
691 /// Stop effects on a virtual display
692 ///
693 /// # Arguments
694 /// * `slave_address` - I2C slave address of the uSPIBridge device
695 /// * `virtual_id` - Virtual display ID (0-based)
696 ///
697 /// # Returns
698 /// I2C operation status
699 pub fn uspibridge_virtual_stop(
700 &mut self,
701 slave_address: u8,
702 virtual_id: u8,
703 ) -> Result<I2cStatus> {
704 self.uspibridge_write_command(
705 slave_address,
706 USPIBridgeCommand::VirtualStop,
707 virtual_id,
708 &[],
709 )
710 }
711
712 /// Clear a virtual display
713 ///
714 /// # Arguments
715 /// * `slave_address` - I2C slave address of the uSPIBridge device
716 /// * `virtual_id` - Virtual display ID (0-based)
717 ///
718 /// # Returns
719 /// I2C operation status
720 pub fn uspibridge_virtual_clear(
721 &mut self,
722 slave_address: u8,
723 virtual_id: u8,
724 ) -> Result<I2cStatus> {
725 self.uspibridge_write_command(
726 slave_address,
727 USPIBridgeCommand::VirtualClear,
728 virtual_id,
729 &[],
730 )
731 }
732
733 /// Reset the uSPIBridge system
734 ///
735 /// # Arguments
736 /// * `slave_address` - I2C slave address of the uSPIBridge device
737 ///
738 /// # Returns
739 /// I2C operation status
740 pub fn uspibridge_system_reset(&mut self, slave_address: u8) -> Result<I2cStatus> {
741 self.uspibridge_write_command(slave_address, USPIBridgeCommand::SystemReset, 0, &[])
742 }
743
744 /// Get uSPIBridge system status
745 ///
746 /// # Arguments
747 /// * `slave_address` - I2C slave address of the uSPIBridge device
748 ///
749 /// # Returns
750 /// Tuple of (I2C status, optional status data)
751 pub fn uspibridge_system_status(
752 &mut self,
753 slave_address: u8,
754 ) -> Result<(I2cStatus, Option<Vec<u8>>)> {
755 let status =
756 self.uspibridge_write_command(slave_address, USPIBridgeCommand::SystemStatus, 0, &[])?;
757
758 if status != I2cStatus::Ok {
759 return Ok((status, None));
760 }
761
762 // Wait for response processing
763 std::thread::sleep(std::time::Duration::from_millis(10));
764
765 // Read response
766 let (read_status, response_data) = self.i2c_read(slave_address, 16)?;
767 Ok((read_status, Some(response_data)))
768 }
769}