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}