tmc2209_uart/
datagram.rs

1//! UART datagram types for TMC2209 communication.
2//!
3//! The TMC2209 uses a simple UART protocol with three datagram types:
4//! - Read request (4 bytes): Request to read a register
5//! - Write request (8 bytes): Request to write a register
6//! - Read response (8 bytes): Response containing register data
7
8use crate::crc;
9use crate::error::Error;
10use crate::registers::Address;
11
12/// Sync byte used in all TMC2209 datagrams.
13pub const SYNC: u8 = 0x05;
14
15/// Master address used in read responses (always 0xFF).
16pub const MASTER_ADDR: u8 = 0xFF;
17
18/// Write bit OR'd with register address for write requests.
19pub const WRITE_BIT: u8 = 0x80;
20
21/// Address mask (7 bits).
22pub const ADDRESS_MASK: u8 = 0x7F;
23
24/// Read request datagram (4 bytes).
25///
26/// Format: `[SYNC, slave_addr, reg_addr, CRC]`
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29pub struct ReadRequest {
30    bytes: [u8; Self::LEN],
31}
32
33impl ReadRequest {
34    /// Length of a read request in bytes.
35    pub const LEN: usize = 4;
36
37    /// Create a new read request for the given slave and register address.
38    ///
39    /// # Arguments
40    ///
41    /// * `slave_addr` - Slave address (0-3)
42    /// * `reg_addr` - Register address to read
43    pub fn new(slave_addr: u8, reg_addr: Address) -> Self {
44        let mut bytes = [SYNC, slave_addr, reg_addr as u8, 0];
45        bytes[3] = crc::compute(&bytes[..3]);
46        Self { bytes }
47    }
48
49    /// Create a read request from a raw register address.
50    ///
51    /// Use this when you need to read a register by its raw address value.
52    pub fn from_raw_addr(slave_addr: u8, reg_addr: u8) -> Self {
53        let mut bytes = [SYNC, slave_addr, reg_addr & ADDRESS_MASK, 0];
54        bytes[3] = crc::compute(&bytes[..3]);
55        Self { bytes }
56    }
57
58    /// Get the request as a byte slice.
59    #[inline]
60    pub fn as_bytes(&self) -> &[u8] {
61        &self.bytes
62    }
63
64    /// Get the slave address.
65    #[inline]
66    pub fn slave_addr(&self) -> u8 {
67        self.bytes[1]
68    }
69
70    /// Get the register address.
71    #[inline]
72    pub fn reg_addr(&self) -> u8 {
73        self.bytes[2]
74    }
75}
76
77impl AsRef<[u8]> for ReadRequest {
78    fn as_ref(&self) -> &[u8] {
79        &self.bytes
80    }
81}
82
83/// Write request datagram (8 bytes).
84///
85/// Format: `[SYNC, slave_addr, reg_addr | 0x80, data[3], data[2], data[1], data[0], CRC]`
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88pub struct WriteRequest {
89    bytes: [u8; Self::LEN],
90}
91
92impl WriteRequest {
93    /// Length of a write request in bytes.
94    pub const LEN: usize = 8;
95
96    /// Create a new write request for the given slave, register address, and data.
97    ///
98    /// # Arguments
99    ///
100    /// * `slave_addr` - Slave address (0-3)
101    /// * `reg_addr` - Register address to write
102    /// * `data` - 32-bit data value to write
103    pub fn new(slave_addr: u8, reg_addr: Address, data: u32) -> Self {
104        Self::from_raw(slave_addr, reg_addr as u8, data)
105    }
106
107    /// Create a write request from raw address and data.
108    pub fn from_raw(slave_addr: u8, reg_addr: u8, data: u32) -> Self {
109        let data_bytes = data.to_be_bytes();
110        let mut bytes = [
111            SYNC,
112            slave_addr,
113            (reg_addr & ADDRESS_MASK) | WRITE_BIT,
114            data_bytes[0],
115            data_bytes[1],
116            data_bytes[2],
117            data_bytes[3],
118            0,
119        ];
120        bytes[7] = crc::compute(&bytes[..7]);
121        Self { bytes }
122    }
123
124    /// Get the request as a byte slice.
125    #[inline]
126    pub fn as_bytes(&self) -> &[u8] {
127        &self.bytes
128    }
129
130    /// Get the slave address.
131    #[inline]
132    pub fn slave_addr(&self) -> u8 {
133        self.bytes[1]
134    }
135
136    /// Get the register address (without write bit).
137    #[inline]
138    pub fn reg_addr(&self) -> u8 {
139        self.bytes[2] & ADDRESS_MASK
140    }
141
142    /// Get the data value.
143    #[inline]
144    pub fn data(&self) -> u32 {
145        u32::from_be_bytes([self.bytes[3], self.bytes[4], self.bytes[5], self.bytes[6]])
146    }
147}
148
149impl AsRef<[u8]> for WriteRequest {
150    fn as_ref(&self) -> &[u8] {
151        &self.bytes
152    }
153}
154
155/// Read response datagram (8 bytes).
156///
157/// Format: `[SYNC, master_addr (0xFF), reg_addr, data[3], data[2], data[1], data[0], CRC]`
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159#[cfg_attr(feature = "defmt", derive(defmt::Format))]
160pub struct ReadResponse {
161    bytes: [u8; Self::LEN],
162}
163
164impl ReadResponse {
165    /// Length of a read response in bytes.
166    pub const LEN: usize = 8;
167
168    /// Index of the sync byte.
169    pub const SYNC_IDX: usize = 0;
170    /// Index of the master address byte.
171    pub const MASTER_ADDR_IDX: usize = 1;
172    /// Index of the register address byte.
173    pub const REG_ADDR_IDX: usize = 2;
174    /// Start index of data bytes.
175    pub const DATA_START_IDX: usize = 3;
176    /// End index of data bytes (exclusive).
177    pub const DATA_END_IDX: usize = 7;
178    /// Index of the CRC byte.
179    pub const CRC_IDX: usize = 7;
180
181    /// Parse a read response from a byte buffer.
182    ///
183    /// # Arguments
184    ///
185    /// * `bytes` - 8-byte buffer containing the response
186    ///
187    /// # Returns
188    ///
189    /// The parsed response, or an error if validation fails.
190    pub fn from_bytes<E>(bytes: [u8; Self::LEN]) -> Result<Self, Error<E>> {
191        let response = Self { bytes };
192        response.validate()?;
193        Ok(response)
194    }
195
196    /// Parse a response from a slice, copying the data.
197    ///
198    /// # Errors
199    ///
200    /// Returns `Error::BufferTooSmall` if the slice is less than 8 bytes.
201    pub fn from_slice<E>(slice: &[u8]) -> Result<Self, Error<E>> {
202        if slice.len() < Self::LEN {
203            return Err(Error::BufferTooSmall);
204        }
205        let mut bytes = [0u8; Self::LEN];
206        bytes.copy_from_slice(&slice[..Self::LEN]);
207        Self::from_bytes(bytes)
208    }
209
210    /// Validate the response structure.
211    fn validate<E>(&self) -> Result<(), Error<E>> {
212        // Check sync byte
213        if self.bytes[Self::SYNC_IDX] != SYNC {
214            return Err(Error::InvalidSync);
215        }
216
217        // Check master address
218        if self.bytes[Self::MASTER_ADDR_IDX] != MASTER_ADDR {
219            return Err(Error::InvalidMasterAddress);
220        }
221
222        // Check CRC
223        if !crc::verify(&self.bytes) {
224            return Err(Error::CrcMismatch);
225        }
226
227        Ok(())
228    }
229
230    /// Get the register address from the response.
231    #[inline]
232    pub fn reg_addr(&self) -> u8 {
233        self.bytes[Self::REG_ADDR_IDX]
234    }
235
236    /// Get the typed register address if known.
237    pub fn address(&self) -> Option<Address> {
238        Address::from_u8(self.reg_addr())
239    }
240
241    /// Get the 32-bit data value.
242    #[inline]
243    pub fn data(&self) -> u32 {
244        u32::from_be_bytes([self.bytes[3], self.bytes[4], self.bytes[5], self.bytes[6]])
245    }
246
247    /// Get the raw bytes of the response.
248    #[inline]
249    pub fn as_bytes(&self) -> &[u8; Self::LEN] {
250        &self.bytes
251    }
252
253    /// Check if the CRC is valid.
254    #[inline]
255    pub fn crc_valid(&self) -> bool {
256        crc::verify(&self.bytes)
257    }
258}
259
260impl AsRef<[u8]> for ReadResponse {
261    fn as_ref(&self) -> &[u8] {
262        &self.bytes
263    }
264}
265
266/// Response reader for non-blocking/streaming response parsing.
267///
268/// This reader maintains state between read calls, allowing you to
269/// parse responses byte-by-byte or in chunks.
270#[derive(Debug, Default)]
271pub struct ResponseReader {
272    /// Current index into the response buffer.
273    index: usize,
274    /// Buffer for accumulating response bytes.
275    buffer: [u8; ReadResponse::LEN],
276}
277
278impl ResponseReader {
279    /// Create a new response reader.
280    pub fn new() -> Self {
281        Self::default()
282    }
283
284    /// Reset the reader state.
285    pub fn reset(&mut self) {
286        self.index = 0;
287    }
288
289    /// Feed bytes to the reader and attempt to parse a response.
290    ///
291    /// # Returns
292    ///
293    /// A tuple of (bytes_consumed, optional_response).
294    /// The response is `Some` when a complete valid response is parsed.
295    pub fn feed<E>(&mut self, bytes: &[u8]) -> (usize, Option<Result<ReadResponse, Error<E>>>) {
296        let mut consumed = 0;
297        let mut remaining = bytes;
298
299        loop {
300            // Looking for sync byte
301            while self.index == 0 {
302                match remaining.first() {
303                    Some(&SYNC) => {
304                        self.buffer[0] = SYNC;
305                        self.index = 1;
306                        remaining = &remaining[1..];
307                        consumed += 1;
308                    }
309                    Some(_) => {
310                        // Skip non-sync bytes
311                        remaining = &remaining[1..];
312                        consumed += 1;
313                    }
314                    None => {
315                        return (consumed, None);
316                    }
317                }
318            }
319
320            // Looking for master address
321            if self.index == 1 {
322                match remaining.first() {
323                    Some(&MASTER_ADDR) => {
324                        self.buffer[1] = MASTER_ADDR;
325                        self.index = 2;
326                        remaining = &remaining[1..];
327                        consumed += 1;
328                    }
329                    Some(_) => {
330                        // Not a valid response, reset
331                        self.index = 0;
332                        continue;
333                    }
334                    None => {
335                        return (consumed, None);
336                    }
337                }
338            }
339
340            // Read remaining bytes
341            let needed = ReadResponse::LEN - self.index;
342            let available = remaining.len().min(needed);
343
344            self.buffer[self.index..self.index + available]
345                .copy_from_slice(&remaining[..available]);
346            self.index += available;
347            consumed += available;
348
349            // Check if we have a complete response
350            if self.index == ReadResponse::LEN {
351                self.index = 0;
352                let result = ReadResponse::from_bytes(self.buffer);
353                return (consumed, Some(result));
354            }
355
356            return (consumed, None);
357        }
358    }
359
360    /// Get the current number of bytes buffered.
361    pub fn buffered(&self) -> usize {
362        self.index
363    }
364}
365
366#[cfg(test)]
367mod tests {
368    use super::*;
369
370    #[test]
371    fn test_read_request() {
372        let req = ReadRequest::new(0, Address::Gconf);
373        assert_eq!(req.slave_addr(), 0);
374        assert_eq!(req.reg_addr(), 0x00);
375        assert_eq!(req.as_bytes().len(), 4);
376    }
377
378    #[test]
379    fn test_write_request() {
380        let req = WriteRequest::new(0, Address::Gconf, 0x00000040);
381        assert_eq!(req.slave_addr(), 0);
382        assert_eq!(req.reg_addr(), 0x00);
383        assert_eq!(req.data(), 0x00000040);
384        assert_eq!(req.as_bytes().len(), 8);
385    }
386
387    #[test]
388    fn test_response_reader() {
389        // Create a mock response
390        let mut response_bytes = [SYNC, MASTER_ADDR, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00];
391        response_bytes[7] = crc::compute(&response_bytes[..7]);
392
393        let mut reader = ResponseReader::new();
394        let (consumed, result) = reader.feed::<()>(&response_bytes);
395
396        assert_eq!(consumed, 8);
397        assert!(result.is_some());
398        let response = result.unwrap().unwrap();
399        assert_eq!(response.data(), 0x00000040);
400    }
401}