Skip to main content

rw007/
protocol.rs

1//! RW007 SPI Protocol definitions
2//!
3//! Based on RT-Thread rw007 driver protocol.
4
5/// Master magic word 1
6pub const MASTER_MAGIC1: u32 = 0x67452301;
7/// Master magic word 2
8pub const MASTER_MAGIC2: u32 = 0xEFCDAB89;
9/// Slave magic word 1
10pub const SLAVE_MAGIC1: u32 = 0x98BADCFE;
11/// Slave magic word 2
12pub const SLAVE_MAGIC2: u32 = 0x10325476;
13
14/// Maximum data length in a single packet
15pub const SPI_MAX_DATA_LEN: usize = 1520;
16/// TX buffer pool size
17pub const SPI_TX_POOL_SIZE: usize = 4;
18/// RX buffer pool size
19pub const SPI_RX_POOL_SIZE: usize = 4;
20/// Slave interrupt timeout in milliseconds
21pub const SLAVE_INT_TIMEOUT_MS: u32 = 100;
22
23/// Master ready flag
24pub const MASTER_FLAG_MRDY: u8 = 0x01;
25/// Slave ready flag
26pub const SLAVE_FLAG_SRDY: u8 = 0x01;
27
28/// Phase type constants for SPI transfer
29/// Master phase types
30pub const MASTER_CMD_PHASE: u8 = 0x01;
31pub const MASTER_DATA_PHASE: u8 = 0x02;
32/// Slave phase types
33pub const SLAVE_CMD_PHASE: u8 = 0x03;
34pub const SLAVE_DATA_PHASE: u8 = 0x04;
35
36/// Application data type
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
39#[repr(u32)]
40pub enum DataType {
41    StaEthData = 1,
42    ApEthData = 2,
43    PromiscEthData = 3,
44    Cmd = 4,
45    Resp = 5,
46    Callback = 6,
47    Ble = 7,
48}
49
50impl TryFrom<u32> for DataType {
51    type Error = u32;
52
53    fn try_from(value: u32) -> Result<Self, Self::Error> {
54        match value {
55            1 => Ok(DataType::StaEthData),
56            2 => Ok(DataType::ApEthData),
57            3 => Ok(DataType::PromiscEthData),
58            4 => Ok(DataType::Cmd),
59            5 => Ok(DataType::Resp),
60            6 => Ok(DataType::Callback),
61            7 => Ok(DataType::Ble),
62            v => Err(v),
63        }
64    }
65}
66
67/// SPI Master Request (16 bytes, little-endian)
68#[derive(Debug, Clone, Copy, Default)]
69#[repr(C, packed)]
70pub struct MasterRequest {
71    pub reserve1: u8,
72    /// flag (4 bits) | type (4 bits)
73    pub flag_type: u8,
74    pub reserve2: u16,
75    pub seq: u16,
76    /// Master to slave data length
77    pub m2s_len: u16,
78    pub magic1: u32,
79    pub magic2: u32,
80}
81
82impl MasterRequest {
83    pub const SIZE: usize = 16;
84
85    /// Create a new CMD phase request
86    /// Bit layout of flag_type byte: [type:4][flag:4] (type in high nibble, flag in low nibble)
87    pub fn new_cmd(seq: u16, m2s_len: u16, master_ready: bool) -> Self {
88        // type goes to high 4 bits, flag goes to low 4 bits
89        let mut flag_type = MASTER_CMD_PHASE << 4;
90        if master_ready {
91            flag_type |= MASTER_FLAG_MRDY;
92        }
93        Self {
94            reserve1: 0,
95            flag_type,
96            reserve2: 0,
97            seq,
98            m2s_len,
99            magic1: MASTER_MAGIC1,
100            magic2: MASTER_MAGIC2,
101        }
102    }
103
104    /// Create a new DATA phase request
105    pub fn new_data(seq: u16, m2s_len: u16, master_ready: bool) -> Self {
106        // type goes to high 4 bits, flag goes to low 4 bits
107        let mut flag_type = MASTER_DATA_PHASE << 4;
108        if master_ready {
109            flag_type |= MASTER_FLAG_MRDY;
110        }
111        Self {
112            reserve1: 0,
113            flag_type,
114            reserve2: 0,
115            seq,
116            m2s_len,
117            magic1: MASTER_MAGIC1,
118            magic2: MASTER_MAGIC2,
119        }
120    }
121
122    /// Get flag (low 4 bits)
123    pub fn flag(&self) -> u8 {
124        self.flag_type & 0x0F
125    }
126
127    /// Get phase type (high 4 bits)
128    pub fn phase_type(&self) -> u8 {
129        (self.flag_type >> 4) & 0x0F
130    }
131
132    pub fn as_bytes(&self) -> &[u8] {
133        unsafe { core::slice::from_raw_parts(self as *const Self as *const u8, Self::SIZE) }
134    }
135
136    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
137        unsafe { core::slice::from_raw_parts_mut(self as *mut Self as *mut u8, Self::SIZE) }
138    }
139}
140
141/// SPI Slave Response (16 bytes, little-endian)
142#[derive(Debug, Clone, Copy, Default)]
143#[repr(C, packed)]
144pub struct SlaveResponse {
145    pub reserve1: u8,
146    /// flag (4 bits) | type (4 bits)
147    pub flag_type: u8,
148    /// slave_rx_buf (4 bits) | slave_tx_buf (4 bits)
149    pub slave_buf: u8,
150    pub reserve2: u8,
151    pub seq: u16,
152    /// Slave to master data length
153    pub s2m_len: u16,
154    pub magic1: u32,
155    pub magic2: u32,
156}
157
158impl SlaveResponse {
159    pub const SIZE: usize = 16;
160
161    /// Get magic1 safely (handles unaligned access)
162    pub fn get_magic1(&self) -> u32 {
163        let bytes = self.as_bytes();
164        u32::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11]])
165    }
166
167    /// Get magic2 safely (handles unaligned access)
168    pub fn get_magic2(&self) -> u32 {
169        let bytes = self.as_bytes();
170        u32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]])
171    }
172
173    /// Get seq safely (handles unaligned access)
174    pub fn get_seq(&self) -> u16 {
175        let bytes = self.as_bytes();
176        u16::from_le_bytes([bytes[4], bytes[5]])
177    }
178
179    /// Get s2m_len safely (handles unaligned access)
180    pub fn get_s2m_len(&self) -> u16 {
181        let bytes = self.as_bytes();
182        u16::from_le_bytes([bytes[6], bytes[7]])
183    }
184
185    /// Get flag (low 4 bits)
186    pub fn flag(&self) -> u8 {
187        self.flag_type & 0x0F
188    }
189
190    /// Get phase type (high 4 bits)
191    pub fn phase_type(&self) -> u8 {
192        (self.flag_type >> 4) & 0x0F
193    }
194
195    /// Get slave_rx_buf (low 4 bits)
196    pub fn slave_rx_buf(&self) -> u8 {
197        self.slave_buf & 0x0F
198    }
199
200    /// Get slave_tx_buf (high 4 bits)
201    pub fn slave_tx_buf(&self) -> u8 {
202        (self.slave_buf >> 4) & 0x0F
203    }
204
205    pub fn is_valid(&self) -> bool {
206        self.get_magic1() == SLAVE_MAGIC1 && self.get_magic2() == SLAVE_MAGIC2
207    }
208
209    /// Check if this is a CMD phase response (slave_cmd_phase = 0x03)
210    pub fn is_cmd_phase(&self) -> bool {
211        self.phase_type() == SLAVE_CMD_PHASE
212    }
213
214    /// Check if this is a DATA phase response (slave_data_phase = 0x04)
215    pub fn is_data_phase(&self) -> bool {
216        self.phase_type() == SLAVE_DATA_PHASE
217    }
218
219    pub fn is_slave_ready(&self) -> bool {
220        (self.flag() & SLAVE_FLAG_SRDY) != 0
221    }
222
223    pub fn as_bytes(&self) -> &[u8] {
224        unsafe { core::slice::from_raw_parts(self as *const Self as *const u8, Self::SIZE) }
225    }
226
227    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
228        unsafe { core::slice::from_raw_parts_mut(self as *mut Self as *mut u8, Self::SIZE) }
229    }
230}
231
232/// Data packet header
233#[derive(Debug, Clone, Copy, Default)]
234#[repr(C)]
235pub struct DataPacketHeader {
236    /// Length of data in buffer
237    pub data_len: u32,
238    /// Application data type (DataType)
239    pub data_type: u32,
240}
241
242impl DataPacketHeader {
243    pub const SIZE: usize = 8;
244
245    pub fn new(data_type: DataType, data_len: usize) -> Self {
246        Self {
247            data_len: data_len as u32,
248            data_type: data_type as u32,
249        }
250    }
251
252    pub fn as_bytes(&self) -> &[u8] {
253        unsafe { core::slice::from_raw_parts(self as *const Self as *const u8, Self::SIZE) }
254    }
255
256    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
257        unsafe { core::slice::from_raw_parts_mut(self as *mut Self as *mut u8, Self::SIZE) }
258    }
259}
260
261/// Maximum packet size (header + data)
262pub const MAX_SPI_PACKET_SIZE: usize = DataPacketHeader::SIZE + SPI_MAX_DATA_LEN;