w5500_ll/
lib.rs

1//! Platform agnostic rust driver for the [Wiznet W5500] SPI internet offload
2//! chip.
3//!
4//! This is a low-level (ll) crate. The scope of this crate is:
5//! 1) Register accessors.
6//! 2) Networking data types.
7//!
8//! Higher level functionality (such as socket operations) should be built
9//! on-top of what is provided here.
10//!
11//! # Example
12//!
13//! Reading the VERSIONR register (a constant value).
14//!
15//! ```
16//! # let spi = ehm::eh1::spi::Mock::new(&[
17//! #   ehm::eh1::spi::Transaction::transaction_start(),
18//! #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x39, 0x00]),
19//! #   ehm::eh1::spi::Transaction::read(0x04),
20//! #   ehm::eh1::spi::Transaction::transaction_end(),
21//! # ]);
22//! use w5500_ll::{eh1::vdm::W5500, Registers};
23//!
24//! let mut w5500 = W5500::new(spi);
25//! let version: u8 = w5500.version()?;
26//! assert_eq!(version, 0x04);
27//! # w5500.free().done();
28//! # Ok::<(), eh1::spi::ErrorKind>(())
29//! ```
30//!
31//! # Feature Flags
32//!
33//! All features are disabled by default.
34//!
35//! * `defmt`: Enable formatting most types with `defmt`.
36//! * `eh0`: Enables the [`eh0`] module which contains
37//!   implementations of the [`Registers`] trait
38//!   using the `embedded-hal` version 0.2 traits.
39//! * `eh1`: Enables the [`eh1`] module which contains
40//!   implementations of the [`Registers`] trait
41//!   using the `embedded-hal` version 1 traits.
42//! * `eha1`:
43//!   Implements the [`aio::Registers`] trait for types in the [`eh1`] module
44//!   using the `embedded-hal-async` traits.
45//!
46//! [Wiznet W5500]: https://www.wiznet.io/product-item/w5500/
47//! [`aio::Registers`]: https://docs.rs/w5500-ll/latest/w5500_ll/aio/trait.Registers.html
48//! [`aio`]: https://docs.rs/w5500-ll/latest/w5500_ll/aio/index.html
49//! [`eh0`]: https://docs.rs/w5500-ll/latest/w5500_ll/eh0/index.html
50//! [`eh1`]: https://docs.rs/w5500-ll/latest/w5500_ll/eh1/index.html
51//! [`Registers`]: https://docs.rs/w5500-ll/latest/w5500_ll/trait.Registers.html
52#![cfg_attr(docsrs, feature(doc_cfg), feature(doc_auto_cfg))]
53#![no_std]
54#![allow(async_fn_in_trait)] // https://github.com/rust-embedded/embedded-hal/pull/515#issuecomment-1763525962
55#![forbid(unsafe_code)]
56#![warn(missing_docs)]
57
58pub mod aio;
59
60#[cfg(feature = "eh0")]
61pub mod eh0;
62#[cfg(feature = "eh1")]
63pub mod eh1;
64
65pub mod net;
66pub mod spi;
67
68mod addr;
69mod registers;
70mod specifiers;
71use net::{Eui48Addr, Ipv4Addr, SocketAddrV4};
72
73pub use addr::{Reg, SnReg};
74pub use registers::{Interrupt, Mode, PhyCfg, SocketInterrupt, SocketInterruptMask, SocketMode};
75pub use specifiers::{
76    BufferSize, DuplexStatus, LinkStatus, OperationMode, Protocol, SocketCommand, SocketStatus,
77    SpeedStatus,
78};
79
80/// Common register block address offset.
81pub const COMMON_BLOCK_OFFSET: u8 = 0x00;
82/// Socket spacing between blocks.
83const SOCKET_SPACING: u8 = 0x04;
84/// Socket common block select bits offset.
85const SOCKET_BLOCK_OFFSET: u8 = 0x01;
86/// Socket TX block select bits offset
87const SOCKET_TX_OFFSET: u8 = 0x02;
88/// Socket RX block select bits offset
89const SOCKET_RX_OFFSET: u8 = 0x03;
90
91/// Value of the W5500 VERSIONR register.
92///
93/// This is very useful as a sanity check to ensure the W5500 is out of reset
94/// and responding correctly to register reads.
95///
96/// # Example
97///
98/// ```
99/// # use ehm::eh1 as hal;
100/// # let spi = ehm::eh1::spi::Mock::new(&[
101/// #   ehm::eh1::spi::Transaction::transaction_start(),
102/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x39, 0x00]),
103/// #   ehm::eh1::spi::Transaction::read(0x04),
104/// #   ehm::eh1::spi::Transaction::transaction_end(),
105/// # ]);
106/// use w5500_ll::{eh1::vdm::W5500, Registers, VERSION};
107///
108/// let mut w5500 = W5500::new(spi);
109/// let version: u8 = w5500.version()?;
110/// assert_eq!(version, VERSION);
111/// # w5500.free().done();
112/// # Ok::<(), eh1::spi::ErrorKind>(())
113/// ```
114pub const VERSION: u8 = 0x04;
115
116/// W5500 socket numbers.
117#[repr(u8)]
118#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug, Hash)]
119#[cfg_attr(feature = "defmt", derive(defmt::Format))]
120pub enum Sn {
121    /// Socket 0.
122    ///
123    /// This is the only socket that can be used in the [`Macraw`] mode.
124    ///
125    /// [`Macraw`]: crate::Protocol::Macraw
126    Sn0 = 0,
127    /// Socket 1.
128    Sn1 = 1,
129    /// Socket 2.
130    Sn2 = 2,
131    /// Socket 3.
132    Sn3 = 3,
133    /// Socket 4.
134    Sn4 = 4,
135    /// Socket 5.
136    Sn5 = 5,
137    /// Socket 6.
138    Sn6 = 6,
139    /// Socket 7.
140    Sn7 = 7,
141}
142
143impl Sn {
144    /// Get the socket register block select bits.
145    ///
146    /// # Example
147    ///
148    /// ```
149    /// use w5500_ll::Sn;
150    ///
151    /// assert_eq!(Sn::Sn0.block(), 0b00001);
152    /// assert_eq!(Sn::Sn1.block(), 0b00101);
153    /// assert_eq!(Sn::Sn2.block(), 0b01001);
154    /// assert_eq!(Sn::Sn3.block(), 0b01101);
155    /// assert_eq!(Sn::Sn4.block(), 0b10001);
156    /// assert_eq!(Sn::Sn5.block(), 0b10101);
157    /// assert_eq!(Sn::Sn6.block(), 0b11001);
158    /// assert_eq!(Sn::Sn7.block(), 0b11101);
159    /// ```
160    #[inline]
161    pub const fn block(self) -> u8 {
162        SOCKET_SPACING * (self as u8) + SOCKET_BLOCK_OFFSET
163    }
164
165    /// Get the socket TX buffer block select bits.
166    ///
167    /// # Example
168    ///
169    /// ```
170    /// use w5500_ll::Sn;
171    ///
172    /// assert_eq!(Sn::Sn0.tx_block(), 0b00010);
173    /// assert_eq!(Sn::Sn1.tx_block(), 0b00110);
174    /// assert_eq!(Sn::Sn2.tx_block(), 0b01010);
175    /// assert_eq!(Sn::Sn3.tx_block(), 0b01110);
176    /// assert_eq!(Sn::Sn4.tx_block(), 0b10010);
177    /// assert_eq!(Sn::Sn5.tx_block(), 0b10110);
178    /// assert_eq!(Sn::Sn6.tx_block(), 0b11010);
179    /// assert_eq!(Sn::Sn7.tx_block(), 0b11110);
180    /// ```
181    #[inline]
182    pub const fn tx_block(self) -> u8 {
183        SOCKET_SPACING * (self as u8) + SOCKET_TX_OFFSET
184    }
185
186    /// Get the socket RX buffer block select bits.
187    ///
188    /// # Example
189    ///
190    /// ```
191    /// use w5500_ll::Sn;
192    ///
193    /// assert_eq!(Sn::Sn0.rx_block(), 0b00011);
194    /// assert_eq!(Sn::Sn1.rx_block(), 0b00111);
195    /// assert_eq!(Sn::Sn2.rx_block(), 0b01011);
196    /// assert_eq!(Sn::Sn3.rx_block(), 0b01111);
197    /// assert_eq!(Sn::Sn4.rx_block(), 0b10011);
198    /// assert_eq!(Sn::Sn5.rx_block(), 0b10111);
199    /// assert_eq!(Sn::Sn6.rx_block(), 0b11011);
200    /// assert_eq!(Sn::Sn7.rx_block(), 0b11111);
201    /// ```
202    #[inline]
203    pub const fn rx_block(self) -> u8 {
204        SOCKET_SPACING * (self as u8) + SOCKET_RX_OFFSET
205    }
206
207    /// Socket bitmask.
208    ///
209    /// This is useful for masking socket interrupts with [`set_simr`].
210    ///
211    /// # Examples
212    ///
213    /// Demonstration:
214    ///
215    /// ```
216    /// use w5500_ll::Sn;
217    ///
218    /// assert_eq!(Sn::Sn0.bitmask(), 0x01);
219    /// assert_eq!(Sn::Sn1.bitmask(), 0x02);
220    /// assert_eq!(Sn::Sn2.bitmask(), 0x04);
221    /// assert_eq!(Sn::Sn3.bitmask(), 0x08);
222    /// assert_eq!(Sn::Sn4.bitmask(), 0x10);
223    /// assert_eq!(Sn::Sn5.bitmask(), 0x20);
224    /// assert_eq!(Sn::Sn6.bitmask(), 0x40);
225    /// assert_eq!(Sn::Sn7.bitmask(), 0x80);
226    /// ```
227    ///
228    /// As an argument of [`set_simr`]:
229    ///
230    /// ```
231    /// # let spi = ehm::eh1::spi::Mock::new(&[
232    /// #   ehm::eh1::spi::Transaction::transaction_start(),
233    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x18, 0x04]),
234    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x0A]),
235    /// #   ehm::eh1::spi::Transaction::transaction_end(),
236    /// # ]);
237    /// use w5500_ll::{
238    ///     eh1::vdm::W5500,
239    ///     Registers,
240    ///     Sn::{Sn1, Sn3},
241    /// };
242    ///
243    /// let mut w5500 = W5500::new(spi);
244    /// // enable socket 1 and socket 3 interrupts
245    /// const SOCKET_INTERRUPT_MASK: u8 = Sn1.bitmask() | Sn3.bitmask();
246    /// w5500.set_simr(SOCKET_INTERRUPT_MASK)?;
247    /// # w5500.free().done();
248    /// # Ok::<(), eh1::spi::ErrorKind>(())
249    /// ```
250    ///
251    /// [`set_simr`]: crate::Registers::set_simr
252    pub const fn bitmask(self) -> u8 {
253        1 << (self as u8)
254    }
255
256    /// Iterate over all sockets.
257    ///
258    /// # Example
259    ///
260    /// Check all sockets for a pending interrupt.
261    ///
262    /// ```
263    /// # let spi = ehm::eh1::spi::Mock::new(&[
264    /// #   ehm::eh1::spi::Transaction::transaction_start(),
265    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x17, 0x00]),
266    /// #   ehm::eh1::spi::Transaction::read(0),
267    /// #   ehm::eh1::spi::Transaction::transaction_end(),
268    /// # ]);
269    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
270    ///
271    /// let mut w5500 = W5500::new(spi);
272    ///
273    /// let sir: u8 = w5500.sir()?;
274    /// for sn in Sn::iter() {
275    ///     let mask: u8 = sn.bitmask();
276    ///     if sir & sn.bitmask() != 0 {
277    ///         // handle socket interrupt
278    ///     }
279    /// }
280    /// # w5500.free().done();
281    /// # Ok::<(), eh1::spi::ErrorKind>(())
282    /// ```
283    #[inline]
284    pub fn iter() -> core::slice::Iter<'static, Self> {
285        SOCKETS.iter()
286    }
287}
288
289macro_rules! sn_conversion_for {
290    ($ty:ident) => {
291        impl From<Sn> for $ty {
292            #[inline]
293            fn from(s: Sn) -> Self {
294                s as $ty
295            }
296        }
297
298        impl TryFrom<$ty> for Sn {
299            type Error = $ty;
300
301            #[inline]
302            fn try_from(val: $ty) -> Result<Sn, $ty> {
303                match val {
304                    0 => Ok(Sn::Sn0),
305                    1 => Ok(Sn::Sn1),
306                    2 => Ok(Sn::Sn2),
307                    3 => Ok(Sn::Sn3),
308                    4 => Ok(Sn::Sn4),
309                    5 => Ok(Sn::Sn5),
310                    6 => Ok(Sn::Sn6),
311                    7 => Ok(Sn::Sn7),
312                    x => Err(x),
313                }
314            }
315        }
316    };
317}
318
319sn_conversion_for!(u8);
320sn_conversion_for!(u16);
321sn_conversion_for!(u32);
322sn_conversion_for!(u64);
323sn_conversion_for!(u128);
324sn_conversion_for!(usize);
325sn_conversion_for!(i8);
326sn_conversion_for!(i16);
327sn_conversion_for!(i32);
328sn_conversion_for!(i64);
329sn_conversion_for!(i128);
330sn_conversion_for!(isize);
331
332/// Array of all sockets.
333///
334/// Useful for iterating over sockets.
335///
336/// # Example
337///
338/// Close all sockets.
339///
340/// ```
341/// # use w5500_ll::Sn::*;
342/// # use ehm::eh1 as hal;
343/// # let spi = ehm::eh1::spi::Mock::new(&[
344/// #   ehm::eh1::spi::Transaction::transaction_start(),
345/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn0.block() << 3) | 0x04]),
346/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
347/// #   ehm::eh1::spi::Transaction::transaction_end(),
348/// #   ehm::eh1::spi::Transaction::transaction_start(),
349/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn1.block() << 3) | 0x04]),
350/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
351/// #   ehm::eh1::spi::Transaction::transaction_end(),
352/// #   ehm::eh1::spi::Transaction::transaction_start(),
353/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn2.block() << 3) | 0x04]),
354/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
355/// #   ehm::eh1::spi::Transaction::transaction_end(),
356/// #   ehm::eh1::spi::Transaction::transaction_start(),
357/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn3.block() << 3) | 0x04]),
358/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
359/// #   ehm::eh1::spi::Transaction::transaction_end(),
360/// #   ehm::eh1::spi::Transaction::transaction_start(),
361/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn4.block() << 3) | 0x04]),
362/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
363/// #   ehm::eh1::spi::Transaction::transaction_end(),
364/// #   ehm::eh1::spi::Transaction::transaction_start(),
365/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn5.block() << 3) | 0x04]),
366/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
367/// #   ehm::eh1::spi::Transaction::transaction_end(),
368/// #   ehm::eh1::spi::Transaction::transaction_start(),
369/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn6.block() << 3) | 0x04]),
370/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
371/// #   ehm::eh1::spi::Transaction::transaction_end(),
372/// #   ehm::eh1::spi::Transaction::transaction_start(),
373/// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn7.block() << 3) | 0x04]),
374/// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
375/// #   ehm::eh1::spi::Transaction::transaction_end(),
376/// # ]);
377/// use w5500_ll::{eh1::vdm::W5500, Registers, SocketCommand, SOCKETS};
378///
379/// let mut w5500 = W5500::new(spi);
380/// for socket in SOCKETS.iter() {
381///     w5500.set_sn_cr(*socket, SocketCommand::Close)?;
382/// }
383/// # w5500.free().done();
384/// # Ok::<(), eh1::spi::ErrorKind>(())
385/// ```
386pub const SOCKETS: [Sn; 8] = [
387    Sn::Sn0,
388    Sn::Sn1,
389    Sn::Sn2,
390    Sn::Sn3,
391    Sn::Sn4,
392    Sn::Sn5,
393    Sn::Sn6,
394    Sn::Sn7,
395];
396
397/// TX socket buffer pointers.
398///
399/// Returned by [`Registers::sn_tx_ptrs`] and [`aio::Registers::sn_tx_ptrs`].
400#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug, Hash)]
401#[cfg_attr(feature = "defmt", derive(defmt::Format))]
402pub struct TxPtrs {
403    /// Free size.
404    pub fsr: u16,
405    /// Write pointer.
406    pub wr: u16,
407}
408
409/// RX socket buffer pointers.
410///
411/// Returned by [`Registers::sn_rx_ptrs`] and [`aio::Registers::sn_rx_ptrs`].
412#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug, Hash)]
413#[cfg_attr(feature = "defmt", derive(defmt::Format))]
414pub struct RxPtrs {
415    /// Received size.
416    pub rsr: u16,
417    /// Read pointer.
418    pub rd: u16,
419}
420
421/// W5500 register setters and getters.
422///
423/// * All register getters are simply the name of the register.
424/// * All register setters are the name of the register prefixed with `set_`.
425///
426/// Most of the register documentation is taken from the data sheet.
427pub trait Registers {
428    /// Register accessor error type.
429    type Error;
430
431    /// Read from the W5500.
432    ///
433    /// # Arguments
434    ///
435    /// * `addr` - Starting address of the memory being read.
436    /// * `block` - W5500 block select bits
437    /// * `data` - Buffer to read data into. The number of bytes read is equal
438    ///   to the length of this buffer.
439    fn read(&mut self, addr: u16, block: u8, data: &mut [u8]) -> Result<(), Self::Error>;
440
441    /// Write to the W5500.
442    ///
443    /// # Arguments
444    ///
445    /// * `addr` - Starting address of the memory being written.
446    /// * `block` - W5500 block select bits
447    /// * `data` - Buffer of data to write. The number of bytes written is equal
448    ///   to the length of this buffer.
449    fn write(&mut self, addr: u16, block: u8, data: &[u8]) -> Result<(), Self::Error>;
450
451    /// Get the mode register.
452    ///
453    /// # Example
454    ///
455    /// ```
456    /// # let spi = ehm::eh1::spi::Mock::new(&[
457    /// #   ehm::eh1::spi::Transaction::transaction_start(),
458    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x00]),
459    /// #   ehm::eh1::spi::Transaction::read(0),
460    /// #   ehm::eh1::spi::Transaction::transaction_end(),
461    /// # ]);
462    /// use w5500_ll::{eh1::vdm::W5500, Mode, Registers};
463    ///
464    /// let mut w5500 = W5500::new(spi);
465    /// let mode: Mode = w5500.mr()?;
466    /// assert_eq!(mode, Mode::default());
467    /// # w5500.free().done();
468    /// # Ok::<(), eh1::spi::ErrorKind>(())
469    /// ```
470    fn mr(&mut self) -> Result<Mode, Self::Error> {
471        let mut reg: [u8; 1] = [0];
472        self.read(Reg::MR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
473        Ok(Mode::from(reg[0]))
474    }
475
476    /// Set the mode register.
477    ///
478    /// # Example
479    ///
480    /// ```
481    /// # let spi = ehm::eh1::spi::Mock::new(&[
482    /// #   ehm::eh1::spi::Transaction::transaction_start(),
483    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x04]),
484    /// #   ehm::eh1::spi::Transaction::write(w5500_ll::Mode::WOL_MASK),
485    /// #   ehm::eh1::spi::Transaction::transaction_end(),
486    /// # ]);
487    /// use w5500_ll::{eh1::vdm::W5500, Mode, Registers};
488    ///
489    /// const MODE: Mode = Mode::DEFAULT.enable_wol();
490    /// let mut w5500 = W5500::new(spi);
491    /// w5500.set_mr(MODE)?;
492    /// # w5500.free().done();
493    /// # Ok::<(), eh1::spi::ErrorKind>(())
494    /// ```
495    fn set_mr(&mut self, mode: Mode) -> Result<(), Self::Error> {
496        self.write(Reg::MR.addr(), COMMON_BLOCK_OFFSET, &[mode.into()])
497    }
498
499    /// Get the gateway IP address.
500    ///
501    /// # Example
502    ///
503    /// ```
504    /// # let spi = ehm::eh1::spi::Mock::new(&[
505    /// #   ehm::eh1::spi::Transaction::transaction_start(),
506    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x00]),
507    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
508    /// #   ehm::eh1::spi::Transaction::transaction_end(),
509    /// # ]);
510    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
511    ///
512    /// let mut w5500 = W5500::new(spi);
513    /// let gar = w5500.gar()?;
514    /// assert_eq!(gar, Ipv4Addr::UNSPECIFIED);
515    /// # w5500.free().done();
516    /// # Ok::<(), eh1::spi::ErrorKind>(())
517    /// ```
518    fn gar(&mut self) -> Result<Ipv4Addr, Self::Error> {
519        let mut gar: [u8; 4] = [0; 4];
520        self.read(Reg::GAR0.addr(), COMMON_BLOCK_OFFSET, &mut gar)?;
521        Ok(gar.into())
522    }
523
524    /// Set the gateway IP address.
525    ///
526    /// # Example
527    ///
528    /// ```
529    /// # let spi = ehm::eh1::spi::Mock::new(&[
530    /// #   ehm::eh1::spi::Transaction::transaction_start(),
531    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x04]),
532    /// #   ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 1]),
533    /// #   ehm::eh1::spi::Transaction::transaction_end(),
534    /// # ]);
535    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
536    ///
537    /// let mut w5500 = W5500::new(spi);
538    /// w5500.set_gar(&Ipv4Addr::new(192, 168, 0, 1))?;
539    /// # w5500.free().done();
540    /// # Ok::<(), eh1::spi::ErrorKind>(())
541    /// ```
542    fn set_gar(&mut self, gar: &Ipv4Addr) -> Result<(), Self::Error> {
543        self.write(Reg::GAR0.addr(), COMMON_BLOCK_OFFSET, &gar.octets())
544    }
545
546    /// Get the subnet mask.
547    ///
548    /// # Example
549    ///
550    /// ```
551    /// # let spi = ehm::eh1::spi::Mock::new(&[
552    /// #   ehm::eh1::spi::Transaction::transaction_start(),
553    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x05, 0x00]),
554    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
555    /// #   ehm::eh1::spi::Transaction::transaction_end(),
556    /// # ]);
557    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
558    ///
559    /// let mut w5500 = W5500::new(spi);
560    /// let subr = w5500.subr()?;
561    /// assert_eq!(subr, Ipv4Addr::UNSPECIFIED);
562    /// # w5500.free().done();
563    /// # Ok::<(), eh1::spi::ErrorKind>(())
564    /// ```
565    fn subr(&mut self) -> Result<Ipv4Addr, Self::Error> {
566        let mut subr: [u8; 4] = [0; 4];
567        self.read(Reg::SUBR0.addr(), COMMON_BLOCK_OFFSET, &mut subr)?;
568        Ok(subr.into())
569    }
570
571    /// Set the subnet mask.
572    ///
573    /// # Example
574    ///
575    /// ```
576    /// # let spi = ehm::eh1::spi::Mock::new(&[
577    /// #   ehm::eh1::spi::Transaction::transaction_start(),
578    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x05, 0x04]),
579    /// #   ehm::eh1::spi::Transaction::write_vec(vec![255, 255, 255, 0]),
580    /// #   ehm::eh1::spi::Transaction::transaction_end(),
581    /// # ]);
582    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
583    ///
584    /// let mut w5500 = W5500::new(spi);
585    /// w5500.set_subr(&Ipv4Addr::new(255, 255, 255, 0))?;
586    /// # w5500.free().done();
587    /// # Ok::<(), eh1::spi::ErrorKind>(())
588    /// ```
589    fn set_subr(&mut self, subr: &Ipv4Addr) -> Result<(), Self::Error> {
590        self.write(Reg::SUBR0.addr(), COMMON_BLOCK_OFFSET, &subr.octets())
591    }
592
593    /// Get the source hardware address.
594    ///
595    /// # Example
596    ///
597    /// ```
598    /// # let spi = ehm::eh1::spi::Mock::new(&[
599    /// #   ehm::eh1::spi::Transaction::transaction_start(),
600    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x09, 0x00]),
601    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0, 0, 0]),
602    /// #   ehm::eh1::spi::Transaction::transaction_end(),
603    /// # ]);
604    /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
605    ///
606    /// let mut w5500 = W5500::new(spi);
607    /// let shar = w5500.shar()?;
608    /// assert_eq!(shar, Eui48Addr::UNSPECIFIED);
609    /// # w5500.free().done();
610    /// # Ok::<(), eh1::spi::ErrorKind>(())
611    /// ```
612    fn shar(&mut self) -> Result<Eui48Addr, Self::Error> {
613        let mut shar = Eui48Addr::UNSPECIFIED;
614        self.read(Reg::SHAR0.addr(), COMMON_BLOCK_OFFSET, &mut shar.octets)?;
615        Ok(shar)
616    }
617
618    /// Set the source hardware address.
619    ///
620    /// # Example
621    ///
622    /// ```
623    /// # let spi = ehm::eh1::spi::Mock::new(&[
624    /// #   ehm::eh1::spi::Transaction::transaction_start(),
625    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x09, 0x04]),
626    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0, 0, 0, 0]),
627    /// #   ehm::eh1::spi::Transaction::transaction_end(),
628    /// # ]);
629    /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
630    ///
631    /// let mut w5500 = W5500::new(spi);
632    /// w5500.set_shar(&Eui48Addr::new(0x12, 0x34, 0x00, 0x00, 0x00, 0x00))?;
633    /// # w5500.free().done();
634    /// # Ok::<(), eh1::spi::ErrorKind>(())
635    /// ```
636    fn set_shar(&mut self, shar: &Eui48Addr) -> Result<(), Self::Error> {
637        self.write(Reg::SHAR0.addr(), COMMON_BLOCK_OFFSET, &shar.octets)
638    }
639
640    /// Get the source (client) IP address.
641    ///
642    /// # Example
643    ///
644    /// ```
645    /// # let spi = ehm::eh1::spi::Mock::new(&[
646    /// #   ehm::eh1::spi::Transaction::transaction_start(),
647    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0F, 0x00]),
648    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
649    /// #   ehm::eh1::spi::Transaction::transaction_end(),
650    /// # ]);
651    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
652    ///
653    /// let mut w5500 = W5500::new(spi);
654    /// let sipr = w5500.sipr()?;
655    /// assert_eq!(sipr, Ipv4Addr::UNSPECIFIED);
656    /// # w5500.free().done();
657    /// # Ok::<(), eh1::spi::ErrorKind>(())
658    /// ```
659    fn sipr(&mut self) -> Result<Ipv4Addr, Self::Error> {
660        let mut sipr: [u8; 4] = [0; 4];
661        self.read(Reg::SIPR0.addr(), COMMON_BLOCK_OFFSET, &mut sipr)?;
662        Ok(sipr.into())
663    }
664
665    /// Set the source (client) IP address.
666    ///
667    /// # Example
668    ///
669    /// ```
670    /// # let spi = ehm::eh1::spi::Mock::new(&[
671    /// #   ehm::eh1::spi::Transaction::transaction_start(),
672    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0F, 0x04]),
673    /// #   ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 150]),
674    /// #   ehm::eh1::spi::Transaction::transaction_end(),
675    /// # ]);
676    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
677    ///
678    /// let mut w5500 = W5500::new(spi);
679    /// w5500.set_sipr(&Ipv4Addr::new(192, 168, 0, 150))?;
680    /// # w5500.free().done();
681    /// # Ok::<(), eh1::spi::ErrorKind>(())
682    /// ```
683    fn set_sipr(&mut self, sipr: &Ipv4Addr) -> Result<(), Self::Error> {
684        self.write(Reg::SIPR0.addr(), COMMON_BLOCK_OFFSET, &sipr.octets())
685    }
686
687    /// Get the interrupt low level time.
688    ///
689    /// INTLEVEL configures the assert wait time (I<sub>AWT</sub>).
690    ///
691    /// When the  next interrupt occurs, the interrupt in (INTn) will assert
692    /// to low after INTLEVEL time.
693    ///
694    /// The equation is:
695    ///
696    /// I<sub>AWT</sub> = (INTLEVEL + 1) * PLL<sub>CLK</sub> * 4
697    ///
698    /// When INTLEVEL > 0.
699    ///
700    /// You might want to take a look at the data sheet, there is a handy
701    /// timing diagram there.
702    ///
703    /// # Example
704    ///
705    /// ```
706    /// # let spi = ehm::eh1::spi::Mock::new(&[
707    /// #   ehm::eh1::spi::Transaction::transaction_start(),
708    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x13, 0x00]),
709    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
710    /// #   ehm::eh1::spi::Transaction::transaction_end(),
711    /// # ]);
712    /// use w5500_ll::{eh1::vdm::W5500, Registers};
713    ///
714    /// let mut w5500 = W5500::new(spi);
715    /// let intlevel: u16 = w5500.intlevel()?;
716    /// assert_eq!(intlevel, 0x00);
717    /// # w5500.free().done();
718    /// # Ok::<(), eh1::spi::ErrorKind>(())
719    /// ```
720    fn intlevel(&mut self) -> Result<u16, Self::Error> {
721        let mut buf: [u8; 2] = [0; 2];
722        self.read(Reg::INTLEVEL0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
723        Ok(u16::from_be_bytes(buf))
724    }
725
726    /// Set the interrupt low level time.
727    ///
728    /// See [`Registers::intlevel`] for more information.
729    ///
730    /// # Example
731    ///
732    /// ```
733    /// # let spi = ehm::eh1::spi::Mock::new(&[
734    /// #   ehm::eh1::spi::Transaction::transaction_start(),
735    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x13, 0x04]),
736    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
737    /// #   ehm::eh1::spi::Transaction::transaction_end(),
738    /// # ]);
739    /// use w5500_ll::{eh1::vdm::W5500, Registers};
740    ///
741    /// let mut w5500 = W5500::new(spi);
742    /// w5500.set_intlevel(0x1234)?;
743    /// # w5500.free().done();
744    /// # Ok::<(), eh1::spi::ErrorKind>(())
745    /// ```
746    fn set_intlevel(&mut self, intlevel: u16) -> Result<(), Self::Error> {
747        self.write(
748            Reg::INTLEVEL0.addr(),
749            COMMON_BLOCK_OFFSET,
750            &intlevel.to_be_bytes(),
751        )
752    }
753
754    /// Get the interrupt status.
755    ///
756    /// `1` indicates the interrupt is raised.
757    ///
758    /// # Example
759    ///
760    /// ```
761    /// # let spi = ehm::eh1::spi::Mock::new(&[
762    /// #   ehm::eh1::spi::Transaction::transaction_start(),
763    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x00]),
764    /// #   ehm::eh1::spi::Transaction::read(0),
765    /// #   ehm::eh1::spi::Transaction::transaction_end(),
766    /// # ]);
767    /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
768    ///
769    /// let mut w5500 = W5500::new(spi);
770    /// let ir: Interrupt = w5500.ir()?;
771    /// assert_eq!(ir, Interrupt::default());
772    /// # w5500.free().done();
773    /// # Ok::<(), eh1::spi::ErrorKind>(())
774    /// ```
775    fn ir(&mut self) -> Result<Interrupt, Self::Error> {
776        let mut reg: [u8; 1] = [0];
777        self.read(Reg::IR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
778        Ok(Interrupt::from(reg[0]))
779    }
780
781    /// Set the interrupt status.
782    ///
783    /// Setting an interrupt bit to `1` will clear the interrupt.
784    ///
785    /// # Example
786    ///
787    /// ```
788    /// # let spi = ehm::eh1::spi::Mock::new(&[
789    /// #   ehm::eh1::spi::Transaction::transaction_start(),
790    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x00]),
791    /// #   ehm::eh1::spi::Transaction::read(0),
792    /// #   ehm::eh1::spi::Transaction::transaction_end(),
793    /// #   ehm::eh1::spi::Transaction::transaction_start(),
794    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x04]),
795    /// #   ehm::eh1::spi::Transaction::write(0),
796    /// #   ehm::eh1::spi::Transaction::transaction_end(),
797    /// # ]);
798    /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
799    ///
800    /// let mut w5500 = W5500::new(spi);
801    /// let ir: Interrupt = w5500.ir()?;
802    /// w5500.set_ir(ir)?;
803    /// # w5500.free().done();
804    /// # Ok::<(), eh1::spi::ErrorKind>(())
805    /// ```
806    fn set_ir(&mut self, interrupt: Interrupt) -> Result<(), Self::Error> {
807        self.write(Reg::IR.addr(), COMMON_BLOCK_OFFSET, &[interrupt.into()])
808    }
809
810    /// Get the interrupt mask.
811    ///
812    /// `0` indicates the interrupt is masked.
813    ///
814    /// # Example
815    ///
816    /// ```
817    /// # let spi = ehm::eh1::spi::Mock::new(&[
818    /// #   ehm::eh1::spi::Transaction::transaction_start(),
819    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x00]),
820    /// #   ehm::eh1::spi::Transaction::read(0),
821    /// #   ehm::eh1::spi::Transaction::transaction_end(),
822    /// # ]);
823    /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
824    ///
825    /// let mut w5500 = W5500::new(spi);
826    /// let imr: Interrupt = w5500.imr()?;
827    /// assert_eq!(imr, Interrupt::default());
828    /// # w5500.free().done();
829    /// # Ok::<(), eh1::spi::ErrorKind>(())
830    /// ```
831    fn imr(&mut self) -> Result<Interrupt, Self::Error> {
832        let mut reg: [u8; 1] = [0];
833        self.read(Reg::IMR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
834        Ok(Interrupt::from(reg[0]))
835    }
836
837    /// Set the interrupt mask.
838    ///
839    /// Setting an interrupt bit to `1` will mask the interrupt.
840    /// When a bit of IMR is `1` and the corresponding interrupt is `1` an
841    /// interrupt will be issued.
842    /// If a bit of IMR is `0`, and interrupt will not be issued even if the
843    /// corresponding IR bit is `1`.
844    ///
845    /// # Example
846    ///
847    /// ```
848    /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
849    /// # let spi = ehm::eh1::spi::Mock::new(&[
850    /// #   ehm::eh1::spi::Transaction::transaction_start(),
851    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x04]),
852    /// #   ehm::eh1::spi::Transaction::write_vec(vec![Interrupt::MP_MASK]),
853    /// #   ehm::eh1::spi::Transaction::transaction_end(),
854    /// # ]);
855    ///
856    /// // enable the magic packet interrupt
857    /// const IMR: Interrupt = Interrupt::DEFAULT.set_mp();
858    ///
859    /// let mut w5500 = W5500::new(spi);
860    /// w5500.set_imr(IMR)?;
861    /// # w5500.free().done();
862    /// # Ok::<(), eh1::spi::ErrorKind>(())
863    /// ```
864    fn set_imr(&mut self, mask: Interrupt) -> Result<(), Self::Error> {
865        self.write(Reg::IMR.addr(), COMMON_BLOCK_OFFSET, &[mask.into()])
866    }
867
868    /// Get the socket interrupt status.
869    ///
870    /// SIMR indicates the interrupt status of all sockets.
871    /// Each bit of SIR will be `1` until [`sn_ir`] is cleared.
872    /// If [`sn_ir`] is not equal to `0x00` the n<sub>th</sub>
873    /// bit of `sir` is `1` and the INTn pin is asserted until SIR is `0x00`.
874    ///
875    /// # Example
876    ///
877    /// ```
878    /// # let spi = ehm::eh1::spi::Mock::new(&[
879    /// #   ehm::eh1::spi::Transaction::transaction_start(),
880    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x17, 0x00]),
881    /// #   ehm::eh1::spi::Transaction::read(0),
882    /// #   ehm::eh1::spi::Transaction::transaction_end(),
883    /// # ]);
884    /// use w5500_ll::{eh1::vdm::W5500, Registers, SOCKETS};
885    ///
886    /// let mut w5500 = W5500::new(spi);
887    /// let sir = w5500.sir()?;
888    /// // clear all socket interrupts
889    /// for socket in SOCKETS.iter() {
890    ///     if 1 << (*socket as u8) & sir != 0 {
891    ///         let sn_ir = w5500.sn_ir(*socket)?;
892    ///         w5500.set_sn_ir(*socket, sn_ir)?;
893    ///     }
894    /// }
895    /// # w5500.free().done();
896    /// # Ok::<(), eh1::spi::ErrorKind>(())
897    /// ```
898    ///
899    /// [`sn_ir`]: Registers::sn_ir
900    fn sir(&mut self) -> Result<u8, Self::Error> {
901        let mut reg: [u8; 1] = [0];
902        self.read(Reg::SIR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
903        Ok(reg[0])
904    }
905
906    /// Get the socket interrupt mask.
907    ///
908    /// Each bit of SIMR corresponds to each bit of [`Registers::sir`].
909    /// When a bit of SIMR is `1` and the corresponding bit of SIR is `1`
910    /// and interrupt will be issued.
911    /// If a bit of SIMR is `0` an interrupt will be not issued even if the
912    /// corresponding bit of SIR is `1`.
913    ///
914    /// # Example
915    ///
916    /// ```
917    /// # let spi = ehm::eh1::spi::Mock::new(&[
918    /// #   ehm::eh1::spi::Transaction::transaction_start(),
919    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x18, 0x00]),
920    /// #   ehm::eh1::spi::Transaction::read(0),
921    /// #   ehm::eh1::spi::Transaction::transaction_end(),
922    /// # ]);
923    /// use w5500_ll::{eh1::vdm::W5500, Registers};
924    ///
925    /// let mut w5500 = W5500::new(spi);
926    /// let simr: u8 = w5500.simr()?;
927    /// # w5500.free().done();
928    /// # Ok::<(), eh1::spi::ErrorKind>(())
929    /// ```
930    fn simr(&mut self) -> Result<u8, Self::Error> {
931        let mut reg: [u8; 1] = [0];
932        self.read(Reg::SIMR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
933        Ok(reg[0])
934    }
935
936    /// Set the socket interrupt mask.
937    ///
938    /// See [`Registers::simr`] for more information.
939    ///
940    /// # Example
941    ///
942    /// ```
943    /// # let spi = ehm::eh1::spi::Mock::new(&[
944    /// #   ehm::eh1::spi::Transaction::transaction_start(),
945    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x18, 0x04]),
946    /// #   ehm::eh1::spi::Transaction::write(0xFF),
947    /// #   ehm::eh1::spi::Transaction::transaction_end(),
948    /// # ]);
949    /// use w5500_ll::{eh1::vdm::W5500, Registers};
950    ///
951    /// let mut w5500 = W5500::new(spi);
952    /// // enable all socket interrupts
953    /// w5500.set_simr(0xFF)?;
954    /// # w5500.free().done();
955    /// # Ok::<(), eh1::spi::ErrorKind>(())
956    /// ```
957    fn set_simr(&mut self, simr: u8) -> Result<(), Self::Error> {
958        self.write(Reg::SIMR.addr(), COMMON_BLOCK_OFFSET, &[simr])
959    }
960
961    /// Get the retry time.
962    ///
963    /// RTR configures the re-transmission timeout period.
964    /// The unit of timeout period is 100 us and the default of RTR is `0x07D0`
965    /// or `2000`.
966    /// And so the default timeout period is 200 ms (100 us X 2000).
967    /// During the time configured by RTR, the W5500 waits for the peer response
968    /// to the packet that is transmitted by Sn_CR (CONNECT, DISCON, CLOSE,
969    /// SEND, SEND_MAC, SEND_KEEP command).
970    /// If the peer does not respond within the RTR time, the W5500 re-transmits
971    /// the packet or issues a timeout.
972    ///
973    /// # Example
974    ///
975    /// ```
976    /// # let spi = ehm::eh1::spi::Mock::new(&[
977    /// #   ehm::eh1::spi::Transaction::transaction_start(),
978    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x19, 0x00]),
979    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0x07, 0xD0]),
980    /// #   ehm::eh1::spi::Transaction::transaction_end(),
981    /// # ]);
982    /// use w5500_ll::{eh1::vdm::W5500, Registers};
983    ///
984    /// let mut w5500 = W5500::new(spi);
985    /// let rtr: u16 = w5500.rtr()?;
986    /// assert_eq!(rtr, 0x07D0);
987    /// # w5500.free().done();
988    /// # Ok::<(), eh1::spi::ErrorKind>(())
989    /// ```
990    fn rtr(&mut self) -> Result<u16, Self::Error> {
991        let mut buf: [u8; 2] = [0; 2];
992        self.read(Reg::RTR0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
993        Ok(u16::from_be_bytes(buf))
994    }
995
996    /// Set the retry time.
997    ///
998    /// See [`Registers::rtr`] for more information.
999    ///
1000    /// # Example
1001    ///
1002    /// ```
1003    /// # let spi = ehm::eh1::spi::Mock::new(&[
1004    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1005    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x19, 0x04]),
1006    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
1007    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1008    /// # ]);
1009    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1010    ///
1011    /// let mut w5500 = W5500::new(spi);
1012    /// w5500.set_rtr(0x1234)?;
1013    /// # w5500.free().done();
1014    /// # Ok::<(), eh1::spi::ErrorKind>(())
1015    /// ```
1016    fn set_rtr(&mut self, rtr: u16) -> Result<(), Self::Error> {
1017        self.write(Reg::RTR0.addr(), COMMON_BLOCK_OFFSET, &rtr.to_be_bytes())
1018    }
1019
1020    /// Get the retry count.
1021    ///
1022    /// RCR configured the number of re-transmission attempts.
1023    /// When the number of re-transmission equals RCR + 1 the socket timeout
1024    /// interrupt is raised.
1025    ///
1026    /// There is a LOT more information in the data sheet,
1027    /// including some equations that would be very annoying to input.
1028    ///
1029    /// # Example
1030    ///
1031    /// ```
1032    /// # let spi = ehm::eh1::spi::Mock::new(&[
1033    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1034    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1B, 0x00]),
1035    /// #   ehm::eh1::spi::Transaction::read(0x08),
1036    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1037    /// # ]);
1038    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1039    ///
1040    /// let mut w5500 = W5500::new(spi);
1041    /// let rcr: u8 = w5500.rcr()?;
1042    /// # w5500.free().done();
1043    /// # Ok::<(), eh1::spi::ErrorKind>(())
1044    /// ```
1045    fn rcr(&mut self) -> Result<u8, Self::Error> {
1046        let mut reg: [u8; 1] = [0];
1047        self.read(Reg::RCR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1048        Ok(reg[0])
1049    }
1050
1051    /// Set the retry count.
1052    ///
1053    /// See [`Registers::rcr`] for more information.
1054    ///
1055    /// # Example
1056    ///
1057    /// ```
1058    /// # let spi = ehm::eh1::spi::Mock::new(&[
1059    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1060    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1B, 0x04]),
1061    /// #   ehm::eh1::spi::Transaction::write(0x0A),
1062    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1063    /// # ]);
1064    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1065    ///
1066    /// let mut w5500 = W5500::new(spi);
1067    /// w5500.set_rcr(0x0A)?;
1068    /// # w5500.free().done();
1069    /// # Ok::<(), eh1::spi::ErrorKind>(())
1070    /// ```
1071    fn set_rcr(&mut self, rcr: u8) -> Result<(), Self::Error> {
1072        self.write(Reg::RCR.addr(), COMMON_BLOCK_OFFSET, &[rcr])
1073    }
1074
1075    /// Get the PPP link control protocol request timer.
1076    ///
1077    /// PTIMER configures the time for sending LCP echo request.
1078    ///
1079    /// The unit of time is 25 milliseconds, for a register value of 200 the
1080    /// timer is 5 seconds.
1081    ///
1082    /// # Example
1083    ///
1084    /// ```
1085    /// # let spi = ehm::eh1::spi::Mock::new(&[
1086    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1087    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1C, 0x00]),
1088    /// #   ehm::eh1::spi::Transaction::read(0x08),
1089    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1090    /// # ]);
1091    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1092    ///
1093    /// let mut w5500 = W5500::new(spi);
1094    /// let ptimer: u8 = w5500.ptimer()?;
1095    /// # w5500.free().done();
1096    /// # Ok::<(), eh1::spi::ErrorKind>(())
1097    /// ```
1098    fn ptimer(&mut self) -> Result<u8, Self::Error> {
1099        let mut reg: [u8; 1] = [0];
1100        self.read(Reg::PTIMER.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1101        Ok(reg[0])
1102    }
1103
1104    /// Set the PPP link control protocol request timer.
1105    ///
1106    /// See [`Registers::ptimer`] for more information.
1107    ///
1108    /// # Example
1109    ///
1110    /// ```
1111    /// # let spi = ehm::eh1::spi::Mock::new(&[
1112    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1113    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1C, 0x04]),
1114    /// #   ehm::eh1::spi::Transaction::write(0xC8),
1115    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1116    /// # ]);
1117    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1118    ///
1119    /// let mut w5500 = W5500::new(spi);
1120    /// w5500.set_ptimer(200)?;
1121    /// # w5500.free().done();
1122    /// # Ok::<(), eh1::spi::ErrorKind>(())
1123    /// ```
1124    fn set_ptimer(&mut self, ptimer: u8) -> Result<(), Self::Error> {
1125        self.write(Reg::PTIMER.addr(), COMMON_BLOCK_OFFSET, &[ptimer])
1126    }
1127
1128    /// Get the PPP link control protocol magic number.
1129    ///
1130    /// PMAGIC configures the 4 byte magic number used in the LCP echo request.
1131    /// For a register value of `0x01` the magic number is `0x01010101`.
1132    ///
1133    /// # Example
1134    ///
1135    /// ```
1136    /// # let spi = ehm::eh1::spi::Mock::new(&[
1137    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1138    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1D, 0x00]),
1139    /// #   ehm::eh1::spi::Transaction::read(0x08),
1140    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1141    /// # ]);
1142    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1143    ///
1144    /// let mut w5500 = W5500::new(spi);
1145    /// let pmagic: u8 = w5500.pmagic()?;
1146    /// # w5500.free().done();
1147    /// # Ok::<(), eh1::spi::ErrorKind>(())
1148    /// ```
1149    fn pmagic(&mut self) -> Result<u8, Self::Error> {
1150        let mut reg: [u8; 1] = [0];
1151        self.read(Reg::PMAGIC.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1152        Ok(reg[0])
1153    }
1154
1155    /// Set the PPP link control protocol magic number.
1156    ///
1157    /// See [`Registers::pmagic`] for more information.
1158    ///
1159    /// # Example
1160    ///
1161    /// ```
1162    /// # let spi = ehm::eh1::spi::Mock::new(&[
1163    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1164    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1D, 0x04]),
1165    /// #   ehm::eh1::spi::Transaction::write(0x01),
1166    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1167    /// # ]);
1168    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1169    ///
1170    /// let mut w5500 = W5500::new(spi);
1171    /// w5500.set_pmagic(0x01)?;
1172    /// # w5500.free().done();
1173    /// # Ok::<(), eh1::spi::ErrorKind>(())
1174    /// ```
1175    fn set_pmagic(&mut self, pmagic: u8) -> Result<(), Self::Error> {
1176        self.write(Reg::PMAGIC.addr(), COMMON_BLOCK_OFFSET, &[pmagic])
1177    }
1178
1179    /// Get the destination hardware address in PPPoE mode.
1180    ///
1181    /// # Example
1182    ///
1183    /// ```
1184    /// # let spi = ehm::eh1::spi::Mock::new(&[
1185    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1186    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x00]),
1187    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0, 0, 0]),
1188    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1189    /// # ]);
1190    /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
1191    ///
1192    /// let mut w5500 = W5500::new(spi);
1193    /// let phar = w5500.phar()?;
1194    /// assert_eq!(phar, Eui48Addr::UNSPECIFIED);
1195    /// # w5500.free().done();
1196    /// # Ok::<(), eh1::spi::ErrorKind>(())
1197    /// ```
1198    fn phar(&mut self) -> Result<Eui48Addr, Self::Error> {
1199        let mut phar = Eui48Addr::UNSPECIFIED;
1200        self.read(Reg::PHAR0.addr(), COMMON_BLOCK_OFFSET, &mut phar.octets)?;
1201        Ok(phar)
1202    }
1203
1204    /// Set the destination hardware address in PPPoE mode.
1205    ///
1206    /// # Example
1207    ///
1208    /// ```
1209    /// # let spi = ehm::eh1::spi::Mock::new(&[
1210    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1211    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x04]),
1212    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0, 0, 0, 0]),
1213    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1214    /// # ]);
1215    /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
1216    ///
1217    /// let mut w5500 = W5500::new(spi);
1218    /// w5500.set_phar(&Eui48Addr::new(0x12, 0x34, 0x00, 0x00, 0x00, 0x00))?;
1219    /// # w5500.free().done();
1220    /// # Ok::<(), eh1::spi::ErrorKind>(())
1221    /// ```
1222    fn set_phar(&mut self, phar: &Eui48Addr) -> Result<(), Self::Error> {
1223        self.write(Reg::PHAR0.addr(), COMMON_BLOCK_OFFSET, &phar.octets)
1224    }
1225
1226    /// Get the session ID in PPPoE mode.
1227    ///
1228    /// PSID should be written to the PPPoE server session ID acquired in the
1229    /// PPPoE connection process.
1230    ///
1231    /// # Example
1232    ///
1233    /// ```
1234    /// # let spi = ehm::eh1::spi::Mock::new(&[
1235    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1236    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x00]),
1237    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1238    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1239    /// # ]);
1240    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1241    ///
1242    /// let mut w5500 = W5500::new(spi);
1243    /// let psid: u16 = w5500.psid()?;
1244    /// assert_eq!(psid, 0x0000);
1245    /// # w5500.free().done();
1246    /// # Ok::<(), eh1::spi::ErrorKind>(())
1247    /// ```
1248    fn psid(&mut self) -> Result<u16, Self::Error> {
1249        let mut buf: [u8; 2] = [0; 2];
1250        self.read(Reg::PSID0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
1251        Ok(u16::from_be_bytes(buf))
1252    }
1253
1254    /// Set the session ID in PPPoE mode.
1255    ///
1256    /// See [`Registers::psid`] for more information.
1257    ///
1258    /// # Example
1259    ///
1260    /// ```
1261    /// # let spi = ehm::eh1::spi::Mock::new(&[
1262    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1263    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x04]),
1264    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
1265    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1266    /// # ]);
1267    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1268    ///
1269    /// let mut w5500 = W5500::new(spi);
1270    /// w5500.set_psid(0x1234)?;
1271    /// # w5500.free().done();
1272    /// # Ok::<(), eh1::spi::ErrorKind>(())
1273    /// ```
1274    fn set_psid(&mut self, psid: u16) -> Result<(), Self::Error> {
1275        self.write(Reg::PSID0.addr(), COMMON_BLOCK_OFFSET, &psid.to_be_bytes())
1276    }
1277
1278    /// Get the maximum receive unit in PPPoE mode.
1279    ///
1280    /// PMRU configures the maximum receive unit of PPPoE.
1281    ///
1282    /// # Example
1283    ///
1284    /// ```
1285    /// # let spi = ehm::eh1::spi::Mock::new(&[
1286    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1287    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x26, 0x00]),
1288    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1289    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1290    /// # ]);
1291    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1292    ///
1293    /// let mut w5500 = W5500::new(spi);
1294    /// let pmru: u16 = w5500.pmru()?;
1295    /// assert_eq!(pmru, 0x0000);
1296    /// # w5500.free().done();
1297    /// # Ok::<(), eh1::spi::ErrorKind>(())
1298    /// ```
1299    fn pmru(&mut self) -> Result<u16, Self::Error> {
1300        let mut buf: [u8; 2] = [0; 2];
1301        self.read(Reg::PMRU0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
1302        Ok(u16::from_be_bytes(buf))
1303    }
1304
1305    /// Set the maximum receive unit in PPPoE mode.
1306    ///
1307    /// See [`Registers::pmru`] for more information.
1308    ///
1309    /// # Example
1310    ///
1311    /// ```
1312    /// # let spi = ehm::eh1::spi::Mock::new(&[
1313    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1314    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x26, 0x04]),
1315    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
1316    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1317    /// # ]);
1318    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1319    ///
1320    /// let mut w5500 = W5500::new(spi);
1321    /// w5500.set_pmru(0x1234)?;
1322    /// # w5500.free().done();
1323    /// # Ok::<(), eh1::spi::ErrorKind>(())
1324    /// ```
1325    fn set_pmru(&mut self, pmru: u16) -> Result<(), Self::Error> {
1326        self.write(Reg::PMRU0.addr(), COMMON_BLOCK_OFFSET, &pmru.to_be_bytes())
1327    }
1328
1329    /// Get the unreachable IP address.
1330    ///
1331    /// This awkward wording is taken directly from the data-sheet:
1332    ///
1333    /// W5500 receives an ICMP packet (destination port unreachable)
1334    /// when data is sent to a port number which socket is not open and
1335    /// the UNREACH bit of [`Registers::ir`] becomes `1` and UIPR and UPORTR
1336    /// indicates the destination IP address and port number respectively.
1337    ///
1338    /// # Example
1339    ///
1340    /// ```
1341    /// # let spi = ehm::eh1::spi::Mock::new(&[
1342    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1343    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x28, 0x00]),
1344    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
1345    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1346    /// # ]);
1347    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
1348    ///
1349    /// let mut w5500 = W5500::new(spi);
1350    /// let uipr = w5500.uipr()?;
1351    /// assert_eq!(uipr, Ipv4Addr::UNSPECIFIED);
1352    /// # w5500.free().done();
1353    /// # Ok::<(), eh1::spi::ErrorKind>(())
1354    /// ```
1355    fn uipr(&mut self) -> Result<Ipv4Addr, Self::Error> {
1356        let mut uipr: [u8; 4] = [0; 4];
1357        self.read(Reg::UIPR0.addr(), COMMON_BLOCK_OFFSET, &mut uipr)?;
1358        Ok(uipr.into())
1359    }
1360
1361    /// Get the unreachable port.
1362    ///
1363    /// See [`Registers::uipr`] for more information.
1364    ///
1365    /// # Example
1366    ///
1367    /// ```
1368    /// # let spi = ehm::eh1::spi::Mock::new(&[
1369    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1370    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2C, 0x00]),
1371    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1372    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1373    /// # ]);
1374    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1375    ///
1376    /// let mut w5500 = W5500::new(spi);
1377    /// let uportr = w5500.uportr()?;
1378    /// # w5500.free().done();
1379    /// # Ok::<(), eh1::spi::ErrorKind>(())
1380    /// ```
1381    fn uportr(&mut self) -> Result<u16, Self::Error> {
1382        let mut buf: [u8; 2] = [0; 2];
1383        self.read(Reg::UPORTR0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
1384        Ok(u16::from_be_bytes(buf))
1385    }
1386
1387    /// Get the PHY configuration.
1388    ///
1389    /// # Example
1390    ///
1391    /// ```
1392    /// # let spi = ehm::eh1::spi::Mock::new(&[
1393    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1394    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2E, 0x00]),
1395    /// #   ehm::eh1::spi::Transaction::read(0b10111000),
1396    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1397    /// # ]);
1398    /// use w5500_ll::{eh1::vdm::W5500, PhyCfg, Registers};
1399    ///
1400    /// let mut w5500 = W5500::new(spi);
1401    /// let phy_cfg: PhyCfg = w5500.phycfgr()?;
1402    /// assert_eq!(phy_cfg, PhyCfg::default());
1403    /// # w5500.free().done();
1404    /// # Ok::<(), eh1::spi::ErrorKind>(())
1405    /// ```
1406    fn phycfgr(&mut self) -> Result<PhyCfg, Self::Error> {
1407        let mut reg: [u8; 1] = [0];
1408        self.read(Reg::PHYCFGR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1409        Ok(PhyCfg::from(reg[0]))
1410    }
1411
1412    /// Set the PHY configuration.
1413    ///
1414    /// # Example
1415    ///
1416    /// ```
1417    /// # let spi = ehm::eh1::spi::Mock::new(&[
1418    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1419    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2E, 0x04]),
1420    /// #   ehm::eh1::spi::Transaction::write(0b11111000),
1421    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1422    /// # ]);
1423    /// use w5500_ll::{eh1::vdm::W5500, OperationMode, PhyCfg, Registers};
1424    ///
1425    /// const PHY_CFG: PhyCfg = PhyCfg::DEFAULT.set_opmdc(OperationMode::Auto);
1426    /// let mut w5500 = W5500::new(spi);
1427    /// w5500.set_phycfgr(PHY_CFG)?;
1428    /// # w5500.free().done();
1429    /// # Ok::<(), eh1::spi::ErrorKind>(())
1430    /// ```
1431    fn set_phycfgr(&mut self, phycfg: PhyCfg) -> Result<(), Self::Error> {
1432        self.write(Reg::PHYCFGR.addr(), COMMON_BLOCK_OFFSET, &[phycfg.into()])
1433    }
1434
1435    /// Get the version.
1436    ///
1437    /// The value returned is always `0x04`.
1438    ///
1439    /// This register is extremely useful as a sanity check to ensure SPI
1440    /// communications are working with the W5500.
1441    ///
1442    /// # Example
1443    ///
1444    /// ```
1445    /// # let spi = ehm::eh1::spi::Mock::new(&[
1446    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1447    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x39, 0x00]),
1448    /// #   ehm::eh1::spi::Transaction::read(0x04),
1449    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1450    /// # ]);
1451    /// use w5500_ll::{eh1::vdm::W5500, Registers};
1452    ///
1453    /// let mut w5500 = W5500::new(spi);
1454    /// let version = w5500.version()?;
1455    /// assert_eq!(version, 0x04);
1456    /// # w5500.free().done();
1457    /// # Ok::<(), eh1::spi::ErrorKind>(())
1458    /// ```
1459    fn version(&mut self) -> Result<u8, Self::Error> {
1460        let mut reg: [u8; 1] = [0];
1461        self.read(Reg::VERSIONR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1462        Ok(reg[0])
1463    }
1464
1465    /// Get the socket mode.
1466    ///
1467    /// # Example
1468    ///
1469    /// ```
1470    /// # let spi = ehm::eh1::spi::Mock::new(&[
1471    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1472    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x08]),
1473    /// #   ehm::eh1::spi::Transaction::read(0),
1474    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1475    /// # ]);
1476    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
1477    ///
1478    /// let mut w5500 = W5500::new(spi);
1479    /// let socket_mode = w5500.sn_mr(Sn::Sn0)?;
1480    /// assert_eq!(socket_mode, SocketMode::default());
1481    /// # w5500.free().done();
1482    /// # Ok::<(), eh1::spi::ErrorKind>(())
1483    /// ```
1484    fn sn_mr(&mut self, sn: Sn) -> Result<SocketMode, Self::Error> {
1485        let mut reg: [u8; 1] = [0];
1486        self.read(SnReg::MR.addr(), sn.block(), &mut reg)?;
1487        Ok(SocketMode::from(reg[0]))
1488    }
1489
1490    /// Set the socket mode.
1491    ///
1492    /// # Example
1493    ///
1494    /// ```
1495    /// # let spi = ehm::eh1::spi::Mock::new(&[
1496    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1497    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x08 | 0x04]),
1498    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x01]),
1499    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1500    /// # ]);
1501    /// use w5500_ll::{eh1::vdm::W5500, Protocol, Registers, Sn, SocketMode};
1502    ///
1503    /// const SOCKET_MODE: SocketMode = SocketMode::DEFAULT.set_protocol(Protocol::Tcp);
1504    /// let mut w5500 = W5500::new(spi);
1505    /// w5500.set_sn_mr(Sn::Sn0, SOCKET_MODE)?;
1506    /// # w5500.free().done();
1507    /// # Ok::<(), eh1::spi::ErrorKind>(())
1508    /// ```
1509    fn set_sn_mr(&mut self, sn: Sn, mode: SocketMode) -> Result<(), Self::Error> {
1510        self.write(SnReg::MR.addr(), sn.block(), &[mode.into()])
1511    }
1512
1513    /// Get the socket command.
1514    ///
1515    /// The only use for reading this register is to check if a socket command
1516    /// has been accepted.
1517    ///
1518    /// # Example
1519    ///
1520    /// ```
1521    /// # let spi = ehm::eh1::spi::Mock::new(&[
1522    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1523    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08 | 0x04]),
1524    /// #   ehm::eh1::spi::Transaction::write(0x01),
1525    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1526    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1527    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08]),
1528    /// #   ehm::eh1::spi::Transaction::read(1),
1529    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1530    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1531    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08]),
1532    /// #   ehm::eh1::spi::Transaction::read(0),
1533    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1534    /// # ]);
1535    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
1536    ///
1537    /// let mut w5500 = W5500::new(spi);
1538    /// w5500.set_sn_cr(Sn::Sn0, SocketCommand::Open)?;
1539    /// while w5500.sn_cr(Sn::Sn0)? != SocketCommand::Accepted.into() {}
1540    /// # w5500.free().done();
1541    /// # Ok::<(), eh1::spi::ErrorKind>(())
1542    /// ```
1543    fn sn_cr(&mut self, sn: Sn) -> Result<u8, Self::Error> {
1544        let mut reg: [u8; 1] = [0];
1545        self.read(SnReg::CR.addr(), sn.block(), &mut reg)?;
1546        Ok(reg[0])
1547    }
1548
1549    /// Set the socket command.
1550    ///
1551    /// # Example
1552    ///
1553    /// ```
1554    /// # let spi = ehm::eh1::spi::Mock::new(&[
1555    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1556    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08 | 0x04]),
1557    /// #   ehm::eh1::spi::Transaction::write(0x01),
1558    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1559    /// # ]);
1560    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
1561    ///
1562    /// let mut w5500 = W5500::new(spi);
1563    /// w5500.set_sn_cr(Sn::Sn0, SocketCommand::Open)?;
1564    /// # w5500.free().done();
1565    /// # Ok::<(), eh1::spi::ErrorKind>(())
1566    /// ```
1567    fn set_sn_cr(&mut self, sn: Sn, cmd: SocketCommand) -> Result<(), Self::Error> {
1568        self.write(SnReg::CR.addr(), sn.block(), &[cmd.into()])
1569    }
1570
1571    /// Get the socket interrupt status.
1572    ///
1573    /// # Example
1574    ///
1575    /// ```
1576    /// # let spi = ehm::eh1::spi::Mock::new(&[
1577    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1578    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08]),
1579    /// #   ehm::eh1::spi::Transaction::read(0),
1580    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1581    /// # ]);
1582    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1583    ///
1584    /// let mut w5500 = W5500::new(spi);
1585    /// let socket_interrupts = w5500.sn_ir(Sn::Sn0)?;
1586    /// # w5500.free().done();
1587    /// # Ok::<(), eh1::spi::ErrorKind>(())
1588    /// ```
1589    fn sn_ir(&mut self, sn: Sn) -> Result<SocketInterrupt, Self::Error> {
1590        let mut reg: [u8; 1] = [0];
1591        self.read(SnReg::IR.addr(), sn.block(), &mut reg)?;
1592        Ok(SocketInterrupt::from(reg[0]))
1593    }
1594
1595    /// Set the socket interrupt status.
1596    ///
1597    /// This is a write 1 to clear register.
1598    ///
1599    /// # Examples
1600    ///
1601    /// Clearing all raised interrupts.
1602    ///
1603    /// ```
1604    /// # let spi = ehm::eh1::spi::Mock::new(&[
1605    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1606    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08]),
1607    /// #   ehm::eh1::spi::Transaction::read(0),
1608    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1609    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1610    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08 | 0x04]),
1611    /// #   ehm::eh1::spi::Transaction::write(0),
1612    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1613    /// # ]);
1614    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterrupt};
1615    ///
1616    /// let mut w5500 = W5500::new(spi);
1617    /// let socket_interrupts: SocketInterrupt = w5500.sn_ir(Sn::Sn0)?;
1618    /// w5500.set_sn_ir(Sn::Sn0, socket_interrupts)?;
1619    /// # w5500.free().done();
1620    /// # Ok::<(), eh1::spi::ErrorKind>(())
1621    /// ```
1622    ///
1623    /// Clearing only the SENDOK interrupt.
1624    ///
1625    /// ```
1626    /// # let spi = ehm::eh1::spi::Mock::new(&[
1627    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1628    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08 | 0x04]),
1629    /// #   ehm::eh1::spi::Transaction::write(SocketInterrupt::SENDOK_MASK),
1630    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1631    /// # ]);
1632    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterrupt};
1633    ///
1634    /// let mut w5500 = W5500::new(spi);
1635    /// w5500.set_sn_ir(Sn::Sn0, SocketInterrupt::SENDOK_MASK)?;
1636    /// # w5500.free().done();
1637    /// # Ok::<(), eh1::spi::ErrorKind>(())
1638    /// ```
1639    fn set_sn_ir<T: Into<u8>>(&mut self, sn: Sn, sn_ir: T) -> Result<(), Self::Error> {
1640        self.write(SnReg::IR.addr(), sn.block(), &[sn_ir.into()])
1641    }
1642
1643    /// Get the socket status.
1644    ///
1645    /// **Note:** This method returns a nested [`core::result::Result`].
1646    ///
1647    /// The outermost `Result` is for handling bus errors, similar to most of
1648    /// the other methods in this trait.
1649    ///
1650    /// The innermost `Result<SocketStatus, u8>` is the result of a `u8` to
1651    /// [`SocketStatus`] conversion because not every value of `u8` corresponds
1652    /// to a valid [`SocketStatus`].
1653    /// * `u8` values that have a corresponding [`SocketStatus`] will be
1654    ///   converted and returned in the [`Ok`] variant of the inner `Result`.
1655    /// * `u8` values that do not corresponding [`SocketStatus`] will have the
1656    ///   raw `u8` byte returned in the [`Err`] variant of the inner `Result`.
1657    ///
1658    /// # Example
1659    ///
1660    /// ```
1661    /// # let spi = ehm::eh1::spi::Mock::new(&[
1662    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1663    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x03, 0x08]),
1664    /// #   ehm::eh1::spi::Transaction::read(0),
1665    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1666    /// # ]);
1667    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketStatus};
1668    ///
1669    /// let mut w5500 = W5500::new(spi);
1670    /// let sn_sr = w5500.sn_sr(Sn::Sn0)?;
1671    /// assert_eq!(sn_sr, Ok(SocketStatus::Closed));
1672    /// # w5500.free().done();
1673    /// # Ok::<(), eh1::spi::ErrorKind>(())
1674    /// ```
1675    ///
1676    /// [`Ok`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok
1677    /// [`Err`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err
1678    fn sn_sr(&mut self, sn: Sn) -> Result<Result<SocketStatus, u8>, Self::Error> {
1679        let mut reg: [u8; 1] = [0];
1680        self.read(SnReg::SR.addr(), sn.block(), &mut reg)?;
1681        Ok(SocketStatus::try_from(reg[0]))
1682    }
1683
1684    /// Get the socket source port.
1685    ///
1686    /// This is only valid in TCP/UDP mode.
1687    /// This should be set before sending the OPEN command.
1688    ///
1689    /// # Example
1690    ///
1691    /// ```
1692    /// # let spi = ehm::eh1::spi::Mock::new(&[
1693    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1694    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x04, 0x08]),
1695    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1696    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1697    /// # ]);
1698    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
1699    ///
1700    /// let mut w5500 = W5500::new(spi);
1701    /// let socket_port: u16 = w5500.sn_port(Sn::Sn0)?;
1702    /// # w5500.free().done();
1703    /// # Ok::<(), eh1::spi::ErrorKind>(())
1704    /// ```
1705    fn sn_port(&mut self, sn: Sn) -> Result<u16, Self::Error> {
1706        let mut reg: [u8; 2] = [0; 2];
1707        self.read(SnReg::PORT0.addr(), sn.block(), &mut reg)?;
1708        Ok(u16::from_be_bytes(reg))
1709    }
1710
1711    /// Set the socket source port.
1712    ///
1713    /// See [`Registers::sn_port`] for more information.
1714    ///
1715    /// # Example
1716    ///
1717    /// ```
1718    /// # let spi = ehm::eh1::spi::Mock::new(&[
1719    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1720    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x04, 0x08 | 0x04]),
1721    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 68]),
1722    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1723    /// # ]);
1724    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1725    ///
1726    /// let mut w5500 = W5500::new(spi);
1727    /// w5500.set_sn_port(Sn::Sn0, 68)?;
1728    /// # w5500.free().done();
1729    /// # Ok::<(), eh1::spi::ErrorKind>(())
1730    /// ```
1731    fn set_sn_port(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error> {
1732        self.write(SnReg::PORT0.addr(), sn.block(), &u16::to_be_bytes(port))
1733    }
1734
1735    /// Get the socket destination hardware address.
1736    ///
1737    /// Sn_DHAR configures the destination hardware address of Socket n when
1738    /// using SEND_MAC command in UDP mode or it indicates that it is acquired
1739    /// in ARP-process by CONNECT/SEND command.
1740    ///
1741    /// # Example
1742    ///
1743    /// ```
1744    /// # let spi = ehm::eh1::spi::Mock::new(&[
1745    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1746    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x06, 0x08]),
1747    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]),
1748    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1749    /// # ]);
1750    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1751    ///
1752    /// let mut w5500 = W5500::new(spi);
1753    /// let dhar = w5500.sn_dhar(Sn::Sn0)?;
1754    /// # w5500.free().done();
1755    /// # Ok::<(), eh1::spi::ErrorKind>(())
1756    /// ```
1757    fn sn_dhar(&mut self, sn: Sn) -> Result<Eui48Addr, Self::Error> {
1758        let mut dhar: Eui48Addr = Eui48Addr::UNSPECIFIED;
1759        self.read(SnReg::DHAR0.addr(), sn.block(), &mut dhar.octets)?;
1760        Ok(dhar)
1761    }
1762
1763    /// Set the socket destination hardware address.
1764    ///
1765    /// See [`Registers::sn_dhar`] for more information.
1766    ///
1767    /// # Example
1768    ///
1769    /// ```
1770    /// # let spi = ehm::eh1::spi::Mock::new(&[
1771    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1772    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x06, 0x08 | 0x04]),
1773    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0x00, 0x00, 0x00, 0x00]),
1774    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1775    /// # ]);
1776    /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers, Sn};
1777    ///
1778    /// let dhar = Eui48Addr::new(0x12, 0x34, 0x00, 0x00, 0x00, 0x00);
1779    /// let mut w5500 = W5500::new(spi);
1780    /// w5500.set_sn_dhar(Sn::Sn0, &dhar)?;
1781    /// # w5500.free().done();
1782    /// # Ok::<(), eh1::spi::ErrorKind>(())
1783    /// ```
1784    fn set_sn_dhar(&mut self, sn: Sn, dhar: &Eui48Addr) -> Result<(), Self::Error> {
1785        self.write(SnReg::DHAR0.addr(), sn.block(), &dhar.octets)
1786    }
1787
1788    /// Get the socket destination IP address.
1789    ///
1790    /// This register configures or indicates the destination IP address.
1791    /// It it valid when the socket is in TCP/UDP mode.
1792    ///
1793    /// In TCP client mode it configures the TCP server address before the
1794    /// [`SocketCommand::Connect`] command.
1795    ///
1796    /// In TCP server mode it indicates the IP address of the TCP client after
1797    /// successfully establishing a connection.
1798    ///
1799    /// In UDP mode it configures an IP address of the peer to receive the UDP
1800    /// packet send by the [`SocketCommand::Send`] or [`SocketCommand::SendMac`]
1801    /// command.
1802    ///
1803    /// # Example
1804    ///
1805    /// ```
1806    /// # let spi = ehm::eh1::spi::Mock::new(&[
1807    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1808    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08]),
1809    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
1810    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1811    /// # ]);
1812    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers, Sn};
1813    ///
1814    /// let mut w5500 = W5500::new(spi);
1815    /// let dipr = w5500.sn_dipr(Sn::Sn0)?;
1816    /// assert_eq!(dipr, Ipv4Addr::UNSPECIFIED);
1817    /// # w5500.free().done();
1818    /// # Ok::<(), eh1::spi::ErrorKind>(())
1819    /// ```
1820    fn sn_dipr(&mut self, sn: Sn) -> Result<Ipv4Addr, Self::Error> {
1821        let mut dipr: [u8; 4] = [0; 4];
1822        self.read(SnReg::DIPR0.addr(), sn.block(), &mut dipr)?;
1823        Ok(dipr.into())
1824    }
1825
1826    /// Set the socket destination IP address.
1827    ///
1828    /// See [`Registers::sn_dipr`] for more information.
1829    ///
1830    /// # Example
1831    ///
1832    /// ```
1833    /// # let spi = ehm::eh1::spi::Mock::new(&[
1834    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1835    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08 | 0x04]),
1836    /// #   ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 11]),
1837    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1838    /// # ]);
1839    /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers, Sn};
1840    ///
1841    /// let mut w5500 = W5500::new(spi);
1842    /// w5500.set_sn_dipr(Sn::Sn0, &Ipv4Addr::new(192, 168, 0, 11))?;
1843    /// # w5500.free().done();
1844    /// # Ok::<(), eh1::spi::ErrorKind>(())
1845    /// ```
1846    fn set_sn_dipr(&mut self, sn: Sn, dipr: &Ipv4Addr) -> Result<(), Self::Error> {
1847        self.write(SnReg::DIPR0.addr(), sn.block(), &dipr.octets())
1848    }
1849
1850    /// Get the socket destination port.
1851    ///
1852    /// This register configures or indicates the destination port number of
1853    /// the socket.
1854    /// It is valid when the socket is used in TCP/UDP mode.
1855    ///
1856    /// In TCP client mode, it configures the listen port number of the TCP
1857    /// server before the [`SocketCommand::Send`] command.
1858    ///
1859    /// In TCP server mode, it indicates the port number of the TCP client
1860    /// after successfully establishing connection.
1861    ///
1862    /// In UDP mode, it configures the port number of the peer to be transmitted
1863    /// in the UDP packet by the [`SocketCommand::Send`] or
1864    /// [`SocketCommand::SendMac`] command.
1865    ///
1866    /// # Example
1867    ///
1868    /// ```
1869    /// # let spi = ehm::eh1::spi::Mock::new(&[
1870    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1871    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x10, 0x08]),
1872    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1873    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1874    /// # ]);
1875    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
1876    ///
1877    /// let mut w5500 = W5500::new(spi);
1878    /// let socket_destination_port: u16 = w5500.sn_dport(Sn::Sn0)?;
1879    /// # w5500.free().done();
1880    /// # Ok::<(), eh1::spi::ErrorKind>(())
1881    /// ```
1882    fn sn_dport(&mut self, sn: Sn) -> Result<u16, Self::Error> {
1883        let mut reg: [u8; 2] = [0; 2];
1884        self.read(SnReg::DPORT0.addr(), sn.block(), &mut reg)?;
1885        Ok(u16::from_be_bytes(reg))
1886    }
1887
1888    /// Set the socket destination port.
1889    ///
1890    /// See [`Registers::sn_dport`] for more information.
1891    ///
1892    /// # Example
1893    ///
1894    /// ```
1895    /// # let spi = ehm::eh1::spi::Mock::new(&[
1896    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1897    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x10, 0x08 | 0x04]),
1898    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 67]),
1899    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1900    /// # ]);
1901    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1902    ///
1903    /// let mut w5500 = W5500::new(spi);
1904    /// w5500.set_sn_dport(Sn::Sn0, 67)?;
1905    /// # w5500.free().done();
1906    /// # Ok::<(), eh1::spi::ErrorKind>(())
1907    /// ```
1908    fn set_sn_dport(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error> {
1909        self.write(SnReg::DPORT0.addr(), sn.block(), &u16::to_be_bytes(port))
1910    }
1911
1912    /// Get the socket destination IPv4 and port.
1913    ///
1914    /// This is equivalent to [`Registers::sn_dipr`] and [`Registers::sn_dport`]
1915    /// in a single read transaction.
1916    ///
1917    /// # Example
1918    ///
1919    /// ```
1920    /// # let spi = ehm::eh1::spi::Mock::new(&[
1921    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1922    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08]),
1923    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0, 0, 0]),
1924    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1925    /// # ]);
1926    /// use w5500_ll::{
1927    ///     eh1::vdm::W5500,
1928    ///     net::{Ipv4Addr, SocketAddrV4},
1929    ///     Registers, Sn,
1930    /// };
1931    ///
1932    /// let mut w5500 = W5500::new(spi);
1933    /// let addr = w5500.sn_dest(Sn::Sn0)?;
1934    /// assert_eq!(addr, SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0));
1935    /// # w5500.free().done();
1936    /// # Ok::<(), eh1::spi::ErrorKind>(())
1937    /// ```
1938    fn sn_dest(&mut self, sn: Sn) -> Result<SocketAddrV4, Self::Error> {
1939        let mut buf: [u8; 6] = [0; 6];
1940        self.read(SnReg::DIPR0.addr(), sn.block(), &mut buf)?;
1941        Ok(SocketAddrV4::new(
1942            Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]),
1943            u16::from_be_bytes([buf[4], buf[5]]),
1944        ))
1945    }
1946
1947    /// Set the socket destination IPv4 and port.
1948    ///
1949    /// This is equivalent to [`Registers::set_sn_dipr`] and
1950    /// [`Registers::set_sn_dport`] in a single writer transaction.
1951    ///
1952    /// # Example
1953    ///
1954    /// ```
1955    /// # let spi = ehm::eh1::spi::Mock::new(&[
1956    /// #   ehm::eh1::spi::Transaction::transaction_start(),
1957    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08 | 0x04]),
1958    /// #   ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 11, 0, 67]),
1959    /// #   ehm::eh1::spi::Transaction::transaction_end(),
1960    /// # ]);
1961    /// use w5500_ll::{
1962    ///     eh1::vdm::W5500,
1963    ///     net::{Ipv4Addr, SocketAddrV4},
1964    ///     Registers, Sn,
1965    /// };
1966    ///
1967    /// let addr: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 11), 67);
1968    /// let mut w5500 = W5500::new(spi);
1969    /// w5500.set_sn_dest(Sn::Sn0, &addr)?;
1970    /// # w5500.free().done();
1971    /// # Ok::<(), eh1::spi::ErrorKind>(())
1972    /// ```
1973    fn set_sn_dest(&mut self, sn: Sn, addr: &SocketAddrV4) -> Result<(), Self::Error> {
1974        let buf: [u8; 6] = [
1975            addr.ip().octets()[0],
1976            addr.ip().octets()[1],
1977            addr.ip().octets()[2],
1978            addr.ip().octets()[3],
1979            (addr.port() >> 8) as u8,
1980            addr.port() as u8,
1981        ];
1982        self.write(SnReg::DIPR0.addr(), sn.block(), &buf)
1983    }
1984
1985    /// Get the socket maximum segment size.
1986    ///
1987    /// This register configures or indicates the MTU (Maximum Transfer Unit)
1988    /// of the socket.
1989    ///
1990    /// The default MTU is valid when the socket is used in TCP / UDP mode.
1991    /// However, when used in PPPoE mode it is determined within the PPPoE MTU.
1992    ///
1993    /// | Mode   | Normal Default | Normal Range | PPPoE Default | PPPoE Range |
1994    /// |--------|----------------|--------------|---------------|-------------|
1995    /// | TCP    | 1460           | 1 - 1460     | 1452          | 1 - 1452    |
1996    /// | UDP    | 1472           | 1 - 1472     | 1464          | 1 - 1464    |
1997    /// | MACRAW | 1514           | 1514         | 1514          | 1514        |
1998    ///
1999    /// When socket n is used in MACRAW mode, the default MTU is applied
2000    /// because the MTU is not processed internally.
2001    /// Therefore, when transmitting the data bigger than default MTU, the host
2002    /// should manually divide the data into the unit of default MTU.
2003    /// When socket n is used in TCP/UDP mode, and transmitting data bigger than
2004    /// the MTU, the data is automatically divided into the unit of MTU.
2005    ///
2006    /// In UDP mode, the configured MTU is used.
2007    /// When transmitting data to a peer with the different MTU size,
2008    /// the ICMP (Fragment MTU) packet might be received.
2009    /// In this case, IR(FMTU) becomes `1` and the peer information such as the
2010    /// MTU size and IP address is indicated from FMTUR and UIPR respectively.
2011    /// If IR\[MTU\] = `1`, the user cannot transmit data to the peer.
2012    ///
2013    /// To resume the communication with peer, do as followed.
2014    /// 1. Close socket n with the [`SocketCommand::Close`] command.
2015    /// 2. Set Sn_MSS to the indicated MTU from FMTUR
2016    /// 3. Open socket n with the [`SocketCommand::Open`] command.
2017    /// 4. Resume the communication with the peer.
2018    ///
2019    /// # Example
2020    ///
2021    /// ```
2022    /// # let spi = ehm::eh1::spi::Mock::new(&[
2023    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2024    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x12, 0x08]),
2025    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0x00, 0x00]),
2026    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2027    /// # ]);
2028    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2029    ///
2030    /// let mut w5500 = W5500::new(spi);
2031    /// let sn__mssr: u16 = w5500.sn_mssr(Sn::Sn0)?;
2032    /// # w5500.free().done();
2033    /// # Ok::<(), eh1::spi::ErrorKind>(())
2034    /// ```
2035    fn sn_mssr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2036        let mut reg: [u8; 2] = [0; 2];
2037        self.read(SnReg::MSSR0.addr(), sn.block(), &mut reg)?;
2038        Ok(u16::from_be_bytes(reg))
2039    }
2040
2041    /// Set the socket maximum segment size.
2042    ///
2043    /// See [`Registers::sn_mssr`] for lots more information.
2044    ///
2045    /// # Example
2046    ///
2047    /// ```
2048    /// # let spi = ehm::eh1::spi::Mock::new(&[
2049    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2050    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x12, 0x08 | 0x04]),
2051    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x05, 0xB4]),
2052    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2053    /// # ]);
2054    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2055    ///
2056    /// let mut w5500 = W5500::new(spi);
2057    /// w5500.set_sn_mssr(Sn::Sn0, 1460)?;
2058    /// # w5500.free().done();
2059    /// # Ok::<(), eh1::spi::ErrorKind>(())
2060    /// ```
2061    fn set_sn_mssr(&mut self, sn: Sn, mssr: u16) -> Result<(), Self::Error> {
2062        self.write(SnReg::MSSR0.addr(), sn.block(), &u16::to_be_bytes(mssr))
2063    }
2064
2065    /// Get the IP type of service.
2066    ///
2067    /// This register configures the TOS (Type of service field in IP header)
2068    /// for socket n.
2069    /// Configure this field before sending the [`SocketCommand::Open`] command.
2070    ///
2071    /// For more details see [iana.org/assignments/ip-parameters].
2072    ///
2073    /// [iana.org/assignments/ip-parameters]: https://www.iana.org/assignments/ip-parameters
2074    ///
2075    /// # Example
2076    ///
2077    /// ```
2078    /// # let spi = ehm::eh1::spi::Mock::new(&[
2079    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2080    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x08]),
2081    /// #   ehm::eh1::spi::Transaction::read(0),
2082    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2083    /// # ]);
2084    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2085    ///
2086    /// let mut w5500 = W5500::new(spi);
2087    /// let tos: u8 = w5500.sn_tos(Sn::Sn0)?;
2088    /// # w5500.free().done();
2089    /// # Ok::<(), eh1::spi::ErrorKind>(())
2090    /// ```
2091    fn sn_tos(&mut self, sn: Sn) -> Result<u8, Self::Error> {
2092        let mut reg: [u8; 1] = [0];
2093        self.read(SnReg::TOS.addr(), sn.block(), &mut reg)?;
2094        Ok(reg[0])
2095    }
2096
2097    /// Set the IP type of service.
2098    ///
2099    /// For more information see [`Registers::sn_tos`].
2100    ///
2101    /// # Example
2102    ///
2103    /// ```
2104    /// # let spi = ehm::eh1::spi::Mock::new(&[
2105    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2106    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x08 | 0x04]),
2107    /// #   ehm::eh1::spi::Transaction::write(0x01),
2108    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2109    /// # ]);
2110    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2111    ///
2112    /// let mut w5500 = W5500::new(spi);
2113    /// w5500.set_sn_tos(Sn::Sn0, 1)?;
2114    /// # w5500.free().done();
2115    /// # Ok::<(), eh1::spi::ErrorKind>(())
2116    /// ```
2117    fn set_sn_tos(&mut self, sn: Sn, tos: u8) -> Result<(), Self::Error> {
2118        self.write(SnReg::TOS.addr(), sn.block(), &[tos])
2119    }
2120
2121    /// Get the time to live.
2122    ///
2123    /// This register configures the TTL (Time to Live field in the IP header)
2124    /// for socket n.
2125    ///
2126    /// For more details see <https://www.iana.org/assignments/ip-parameters>.
2127    ///
2128    /// # Example
2129    ///
2130    /// ```
2131    /// # let spi = ehm::eh1::spi::Mock::new(&[
2132    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2133    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x08]),
2134    /// #   ehm::eh1::spi::Transaction::read(0x80),
2135    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2136    /// # ]);
2137    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2138    ///
2139    /// let mut w5500 = W5500::new(spi);
2140    /// let ttl: u8 = w5500.sn_ttl(Sn::Sn0)?;
2141    /// # w5500.free().done();
2142    /// # Ok::<(), eh1::spi::ErrorKind>(())
2143    /// ```
2144    fn sn_ttl(&mut self, sn: Sn) -> Result<u8, Self::Error> {
2145        let mut reg: [u8; 1] = [0];
2146        self.read(SnReg::TTL.addr(), sn.block(), &mut reg)?;
2147        Ok(reg[0])
2148    }
2149
2150    /// Set the time to live.
2151    ///
2152    /// For more information see [`Registers::sn_ttl`].
2153    ///
2154    /// # Example
2155    ///
2156    /// ```
2157    /// # let spi = ehm::eh1::spi::Mock::new(&[
2158    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2159    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x08 | 0x04]),
2160    /// #   ehm::eh1::spi::Transaction::write(0x80),
2161    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2162    /// # ]);
2163    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2164    ///
2165    /// let mut w5500 = W5500::new(spi);
2166    /// w5500.set_sn_ttl(Sn::Sn0, 0x80)?;
2167    /// # w5500.free().done();
2168    /// # Ok::<(), eh1::spi::ErrorKind>(())
2169    /// ```
2170    fn set_sn_ttl(&mut self, sn: Sn, ttl: u8) -> Result<(), Self::Error> {
2171        self.write(SnReg::TTL.addr(), sn.block(), &[ttl])
2172    }
2173
2174    /// Get the socket RX buffer size.
2175    ///
2176    /// The buffer size can be configured to any of the sizes in [`BufferSize`].
2177    ///
2178    /// The sum of all the socket RX buffers cannot exceed 16 KiB.
2179    ///
2180    /// **Note:** This method returns a nested [`core::result::Result`].
2181    ///
2182    /// The outermost `Result` is for handling bus errors, similar to most of
2183    /// the other methods in this trait.
2184    ///
2185    /// The innermost `Result<BufferSize, u8>` is the result of a `u8` to
2186    /// [`BufferSize`] conversion because not every value of `u8` corresponds
2187    /// to a valid [`BufferSize`].
2188    /// * `u8` values that have a corresponding [`BufferSize`] will be
2189    ///   converted and returned in the [`Ok`] variant of the inner `Result`.
2190    /// * `u8` values that do not corresponding [`BufferSize`] will have the
2191    ///   raw `u8` byte returned in the [`Err`] variant of the inner `Result`.
2192    ///
2193    /// # Example
2194    ///
2195    /// ```
2196    /// # let spi = ehm::eh1::spi::Mock::new(&[
2197    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2198    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x08]),
2199    /// #   ehm::eh1::spi::Transaction::read(0x02),
2200    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2201    /// # ]);
2202    /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2203    ///
2204    /// let mut w5500 = W5500::new(spi);
2205    /// let sn_rxbuf_size = w5500.sn_rxbuf_size(Sn::Sn0)?;
2206    /// assert_eq!(sn_rxbuf_size, Ok(BufferSize::KB2));
2207    /// # w5500.free().done();
2208    /// # Ok::<(), eh1::spi::ErrorKind>(())
2209    /// ```
2210    ///
2211    /// [`Ok`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok
2212    /// [`Err`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err
2213    fn sn_rxbuf_size(&mut self, sn: Sn) -> Result<Result<BufferSize, u8>, Self::Error> {
2214        let mut reg: [u8; 1] = [0];
2215        self.read(SnReg::RXBUF_SIZE.addr(), sn.block(), &mut reg)?;
2216        Ok(BufferSize::try_from(reg[0]))
2217    }
2218
2219    /// Set the socket RX buffer size.
2220    ///
2221    /// See [`Registers::sn_rxbuf_size`] for more information.
2222    ///
2223    /// # Example
2224    ///
2225    /// ```
2226    /// # let spi = ehm::eh1::spi::Mock::new(&[
2227    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2228    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x08 | 0x04]),
2229    /// #   ehm::eh1::spi::Transaction::write(1),
2230    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2231    /// # ]);
2232    /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2233    ///
2234    /// let mut w5500 = W5500::new(spi);
2235    /// w5500.set_sn_rxbuf_size(Sn::Sn0, BufferSize::KB1)?;
2236    /// # w5500.free().done();
2237    /// # Ok::<(), eh1::spi::ErrorKind>(())
2238    /// ```
2239    fn set_sn_rxbuf_size(&mut self, sn: Sn, size: BufferSize) -> Result<(), Self::Error> {
2240        self.write(SnReg::RXBUF_SIZE.addr(), sn.block(), &[size.into()])
2241    }
2242
2243    /// Get the socket TX buffer size.
2244    ///
2245    /// The buffer size can be configured to any of the sizes in [`BufferSize`].
2246    ///
2247    /// The sum of all the socket TX buffers cannot exceed 16 KiB.
2248    ///
2249    /// **Note:** This method returns a nested [`core::result::Result`].
2250    ///
2251    /// The outermost `Result` is for handling bus errors, similar to most of
2252    /// the other methods in this trait.
2253    ///
2254    /// The innermost `Result<BufferSize, u8>` is the result of a `u8` to
2255    /// [`BufferSize`] conversion because not every value of `u8` corresponds
2256    /// to a valid [`BufferSize`].
2257    /// * `u8` values that have a corresponding [`BufferSize`] will be
2258    ///   converted and returned in the [`Ok`] variant of the inner `Result`.
2259    /// * `u8` values that do not corresponding [`BufferSize`] will have the
2260    ///   raw `u8` byte returned in the [`Err`] variant of the inner `Result`.
2261    ///
2262    /// # Example
2263    ///
2264    /// ```
2265    /// # let spi = ehm::eh1::spi::Mock::new(&[
2266    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2267    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1F, 0x08]),
2268    /// #   ehm::eh1::spi::Transaction::read(0x02),
2269    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2270    /// # ]);
2271    /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2272    ///
2273    /// let mut w5500 = W5500::new(spi);
2274    /// let sn_txbuf_size = w5500.sn_txbuf_size(Sn::Sn0)?;
2275    /// assert_eq!(sn_txbuf_size, Ok(BufferSize::KB2));
2276    /// # w5500.free().done();
2277    /// # Ok::<(), eh1::spi::ErrorKind>(())
2278    /// ```
2279    ///
2280    /// [`Ok`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok
2281    /// [`Err`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err
2282    fn sn_txbuf_size(&mut self, sn: Sn) -> Result<Result<BufferSize, u8>, Self::Error> {
2283        let mut reg: [u8; 1] = [0];
2284        self.read(SnReg::TXBUF_SIZE.addr(), sn.block(), &mut reg)?;
2285        Ok(BufferSize::try_from(reg[0]))
2286    }
2287
2288    /// Set the socket TX buffer size.
2289    ///
2290    /// See [`Registers::sn_rxbuf_size`] for more information.
2291    ///
2292    /// # Example
2293    ///
2294    /// ```
2295    /// # let spi = ehm::eh1::spi::Mock::new(&[
2296    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2297    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1F, 0x08 | 0x04]),
2298    /// #   ehm::eh1::spi::Transaction::write(1),
2299    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2300    /// # ]);
2301    /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2302    ///
2303    /// let mut w5500 = W5500::new(spi);
2304    /// w5500.set_sn_txbuf_size(Sn::Sn0, BufferSize::KB1)?;
2305    /// # w5500.free().done();
2306    /// # Ok::<(), eh1::spi::ErrorKind>(())
2307    /// ```
2308    fn set_sn_txbuf_size(&mut self, sn: Sn, size: BufferSize) -> Result<(), Self::Error> {
2309        self.write(SnReg::TXBUF_SIZE.addr(), sn.block(), &[size.into()])
2310    }
2311
2312    /// Get transmit buffer free size.
2313    ///
2314    /// This register indicates the free size of socket n TX buffer.
2315    /// It is initialized to the configured size by [`Registers::sn_txbuf_size`].
2316    /// Data bigger than Sn_TX_FSR should not be written to the TX buffer to
2317    /// prevent buffer overflow.
2318    ///
2319    /// Check this register before writing data to the socket TX buffer,
2320    /// and if data is equal or smaller than its checked size, transmit the data
2321    /// with the [`SocketCommand::Send`] or [`SocketCommand::SendMac`] command
2322    /// after saving the data in Socket n TX buffer.
2323    ///
2324    /// If data is bigger than its checked size, transmit the data after
2325    /// dividing into the checked size and saving in the socket TX buffer.
2326    ///
2327    /// If [`Registers::sn_mr`] is not in TCP mode, this register is
2328    /// automatically calculated as the difference between
2329    /// [`Registers::sn_tx_wr`] and [`Registers::sn_tx_rd`].
2330    ///
2331    /// If [`Registers::sn_mr`] is in TCP mode, this register is automatically
2332    /// calculated as the difference between the internal ACK pointer which
2333    /// indicates the point of data is received already by the connected
2334    /// peer.
2335    ///
2336    /// # Example
2337    ///
2338    /// ```
2339    /// # let spi = ehm::eh1::spi::Mock::new(&[
2340    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2341    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x20, 0x08]),
2342    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0x08, 0x00]),
2343    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2344    /// # ]);
2345    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
2346    ///
2347    /// let mut w5500 = W5500::new(spi);
2348    /// let sn_tx_fsr: u16 = w5500.sn_tx_fsr(Sn::Sn0)?;
2349    /// # w5500.free().done();
2350    /// # Ok::<(), eh1::spi::ErrorKind>(())
2351    /// ```
2352    fn sn_tx_fsr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2353        let mut reg: [u8; 2] = [0; 2];
2354        self.read(SnReg::TX_FSR0.addr(), sn.block(), &mut reg)?;
2355        Ok(u16::from_be_bytes(reg))
2356    }
2357
2358    /// Get the socket TX read pointer.
2359    ///
2360    /// This register is initialized by the [`SocketCommand::Open`] command.
2361    /// However, in TCP mode, this is re-initialized while connecting with TCP.
2362    ///
2363    /// After initialization, this is auto-increased by the
2364    /// [`SocketCommand::Send`] command.
2365    ///
2366    /// The [`SocketCommand::Send`] command transmits the saved data from the
2367    /// current [`Registers::sn_tx_rd`] to the [`Registers::sn_tx_wr`] in the
2368    /// socket n TX buffer.
2369    /// After transmitting the saved data, the [`SocketCommand::Send`] command
2370    /// increases [`Registers::sn_tx_rd`] the as same as
2371    /// [`Registers::sn_tx_wr`].
2372    ///
2373    /// If its increment value exceeds the maximum value `0xFFFF`,
2374    /// (greater than `0x10000` and the carry bit occurs), then the carry bit is
2375    /// ignored and will automatically update with the lower 16 bits value.
2376    ///
2377    /// # Example
2378    ///
2379    /// ```
2380    /// # let spi = ehm::eh1::spi::Mock::new(&[
2381    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2382    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x22, 0x08]),
2383    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2384    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2385    /// # ]);
2386    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
2387    ///
2388    /// let mut w5500 = W5500::new(spi);
2389    /// let sn_tx_rd: u16 = w5500.sn_tx_rd(Sn::Sn0)?;
2390    /// # w5500.free().done();
2391    /// # Ok::<(), eh1::spi::ErrorKind>(())
2392    /// ```
2393    fn sn_tx_rd(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2394        let mut reg: [u8; 2] = [0; 2];
2395        self.read(SnReg::TX_RD0.addr(), sn.block(), &mut reg)?;
2396        Ok(u16::from_be_bytes(reg))
2397    }
2398
2399    /// Get the socket TX write pointer.
2400    ///
2401    /// This register is initialized by the [`SocketCommand::Open`] command.
2402    /// However, in TCP mode, this is re-initialized while connecting with TCP.
2403    ///
2404    /// This should be updated as follows:
2405    /// 1. Read the starting address for transmitting data.
2406    /// 2. Write data to the socket TX buffer buffer.
2407    /// 3. Update this register by the number of bytes written to the TX buffer.
2408    ///    Allow wrapping to occur upon `u16` overflow.
2409    /// 4. Transmit the saved data in the socket TX buffer by using the
2410    ///    [`SocketCommand::Send`] command.
2411    ///
2412    /// See [`Registers::set_sn_tx_buf`] for an additional example.
2413    ///
2414    /// # Example
2415    ///
2416    /// ```
2417    /// # let spi = ehm::eh1::spi::Mock::new(&[
2418    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2419    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x08]),
2420    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2421    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2422    /// # ]);
2423    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2424    ///
2425    /// let mut w5500 = W5500::new(spi);
2426    /// let sn_tx_wr: u16 = w5500.sn_tx_wr(Sn::Sn0)?;
2427    /// # w5500.free().done();
2428    /// # Ok::<(), eh1::spi::ErrorKind>(())
2429    /// ```
2430    fn sn_tx_wr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2431        let mut reg: [u8; 2] = [0; 2];
2432        self.read(SnReg::TX_WR0.addr(), sn.block(), &mut reg)?;
2433        Ok(u16::from_be_bytes(reg))
2434    }
2435
2436    /// Set the socket TX write pointer.
2437    ///
2438    /// See [`Registers::sn_tx_wr`] for more information.
2439    ///
2440    /// See [`Registers::set_sn_tx_buf`] for an example.
2441    fn set_sn_tx_wr(&mut self, sn: Sn, ptr: u16) -> Result<(), Self::Error> {
2442        self.write(SnReg::TX_WR0.addr(), sn.block(), &ptr.to_be_bytes())
2443    }
2444
2445    /// Get the socket TX free size and write pointer
2446    ///
2447    /// This is equivalent to [`Registers::sn_tx_fsr`] and
2448    /// [`Registers::sn_tx_wr`] in a single read transaction.
2449    fn sn_tx_ptrs(&mut self, sn: Sn) -> Result<TxPtrs, Self::Error> {
2450        let mut buf: [u8; 6] = [0; 6];
2451        self.read(SnReg::TX_FSR0.addr(), sn.block(), &mut buf)?;
2452        Ok(TxPtrs {
2453            fsr: u16::from_be_bytes(buf[..2].try_into().unwrap()),
2454            wr: u16::from_be_bytes(buf[4..].try_into().unwrap()),
2455        })
2456    }
2457
2458    /// Get the socket received data size.
2459    ///
2460    /// This register indicates the data size received and saved in the socket
2461    /// RX buffer.
2462    /// This register does not exceed the configured size
2463    /// ([`Registers::set_sn_rxbuf_size`]) and is calculated as the difference
2464    /// between [`Registers::sn_rx_wr`] and [`Registers::sn_rx_rd`].
2465    ///
2466    /// # Example
2467    ///
2468    /// ```
2469    /// # let spi = ehm::eh1::spi::Mock::new(&[
2470    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2471    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x26, 0x08]),
2472    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2473    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2474    /// # ]);
2475    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2476    ///
2477    /// let mut w5500 = W5500::new(spi);
2478    /// let sn_rx_rsr: u16 = w5500.sn_rx_rsr(Sn::Sn0)?;
2479    /// # w5500.free().done();
2480    /// # Ok::<(), eh1::spi::ErrorKind>(())
2481    /// ```
2482    fn sn_rx_rsr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2483        let mut reg: [u8; 2] = [0; 2];
2484        self.read(SnReg::RX_RSR0.addr(), sn.block(), &mut reg)?;
2485        Ok(u16::from_be_bytes(reg))
2486    }
2487
2488    /// Get the socket read data pointer.
2489    ///
2490    /// This register is initialized by the [`SocketCommand::Open`] command.
2491    ///
2492    /// This should be updated as follows:
2493    /// 1. Read the starting address for reading data.
2494    /// 2. Read from the socket RX buffer.
2495    /// 3. Update this register by the number of bytes read from the RX buffer.
2496    ///    Allow wrapping to occur upon `u16` overflow.
2497    /// 4. Send a [`SocketCommand::Recv`] command to notify the W5500 of the
2498    ///    retrieved data.
2499    ///
2500    /// See [`Registers::sn_rx_buf`] for an additional example.
2501    ///
2502    /// # Example
2503    ///
2504    /// ```
2505    /// # let spi = ehm::eh1::spi::Mock::new(&[
2506    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2507    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x28, 0x08]),
2508    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2509    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2510    /// # ]);
2511    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2512    ///
2513    /// let mut w5500 = W5500::new(spi);
2514    /// let sn_rx_rd: u16 = w5500.sn_rx_rd(Sn::Sn0)?;
2515    /// # w5500.free().done();
2516    /// # Ok::<(), eh1::spi::ErrorKind>(())
2517    /// ```
2518    fn sn_rx_rd(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2519        let mut reg: [u8; 2] = [0; 2];
2520        self.read(SnReg::RX_RD0.addr(), sn.block(), &mut reg)?;
2521        Ok(u16::from_be_bytes(reg))
2522    }
2523
2524    /// Set the socket read data pointer.
2525    ///
2526    /// See [`Registers::sn_rx_rd`] for more information.
2527    /// See [`Registers::sn_rx_buf`] for an example.
2528    fn set_sn_rx_rd(&mut self, sn: Sn, ptr: u16) -> Result<(), Self::Error> {
2529        self.write(SnReg::RX_RD0.addr(), sn.block(), &ptr.to_be_bytes())
2530    }
2531
2532    /// Get the socket RX write pointer.
2533    ///
2534    /// This register is initialized by the [`SocketCommand::Open`] command, and
2535    /// it is auto-incremented by hardware.
2536    ///
2537    /// # Example
2538    ///
2539    /// ```
2540    /// # let spi = ehm::eh1::spi::Mock::new(&[
2541    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2542    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2A, 0x08]),
2543    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2544    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2545    /// # ]);
2546    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2547    ///
2548    /// let mut w5500 = W5500::new(spi);
2549    /// let sn_rx_wr: u16 = w5500.sn_rx_wr(Sn::Sn0)?;
2550    /// # w5500.free().done();
2551    /// # Ok::<(), eh1::spi::ErrorKind>(())
2552    /// ```
2553    fn sn_rx_wr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2554        let mut reg: [u8; 2] = [0; 2];
2555        self.read(SnReg::RX_WR0.addr(), sn.block(), &mut reg)?;
2556        Ok(u16::from_be_bytes(reg))
2557    }
2558
2559    /// Get the socket RX received size size and write pointer
2560    ///
2561    /// This is equivalent to [`Registers::sn_rx_rsr`] and
2562    /// [`Registers::sn_rx_rd`] in a single read transaction.
2563    fn sn_rx_ptrs(&mut self, sn: Sn) -> Result<RxPtrs, Self::Error> {
2564        let mut buf: [u8; 4] = [0; 4];
2565        self.read(SnReg::RX_RSR0.addr(), sn.block(), &mut buf)?;
2566        Ok(RxPtrs {
2567            rsr: u16::from_be_bytes(buf[..2].try_into().unwrap()),
2568            rd: u16::from_be_bytes(buf[2..].try_into().unwrap()),
2569        })
2570    }
2571
2572    /// Get the socket interrupt mask.
2573    ///
2574    /// # Example
2575    ///
2576    /// ```
2577    /// # let spi = ehm::eh1::spi::Mock::new(&[
2578    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2579    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2C, 0x08]),
2580    /// #   ehm::eh1::spi::Transaction::read(0xFF),
2581    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2582    /// # ]);
2583    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterruptMask};
2584    ///
2585    /// let mut w5500 = W5500::new(spi);
2586    /// let sn_imr: SocketInterruptMask = w5500.sn_imr(Sn::Sn0)?;
2587    /// assert_eq!(sn_imr, SocketInterruptMask::default());
2588    /// # w5500.free().done();
2589    /// # Ok::<(), eh1::spi::ErrorKind>(())
2590    /// ```
2591    fn sn_imr(&mut self, sn: Sn) -> Result<SocketInterruptMask, Self::Error> {
2592        let mut reg: [u8; 1] = [0];
2593        self.read(SnReg::IMR.addr(), sn.block(), &mut reg)?;
2594        Ok(SocketInterruptMask::from(reg[0]))
2595    }
2596
2597    /// Set the socket interrupt mask.
2598    ///
2599    /// # Example
2600    ///
2601    /// ```
2602    /// # let spi = ehm::eh1::spi::Mock::new(&[
2603    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2604    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2C, 0x08 | 0x04]),
2605    /// #   ehm::eh1::spi::Transaction::write(0xE0),
2606    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2607    /// # ]);
2608    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterruptMask};
2609    ///
2610    /// let mut w5500 = W5500::new(spi);
2611    /// w5500.set_sn_imr(Sn::Sn0, SocketInterruptMask::ALL_MASKED)?;
2612    /// # w5500.free().done();
2613    /// # Ok::<(), eh1::spi::ErrorKind>(())
2614    /// ```
2615    fn set_sn_imr(&mut self, sn: Sn, mask: SocketInterruptMask) -> Result<(), Self::Error> {
2616        self.write(SnReg::IMR.addr(), sn.block(), &[mask.into()])
2617    }
2618
2619    /// Get the socket fragment.
2620    ///
2621    /// This configures the fragment field in the IP header.
2622    ///
2623    /// # Example
2624    ///
2625    /// ```
2626    /// # let spi = ehm::eh1::spi::Mock::new(&[
2627    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2628    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2D, 0x08]),
2629    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0x40, 0x00]),
2630    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2631    /// # ]);
2632    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2633    ///
2634    /// let mut w5500 = W5500::new(spi);
2635    /// let frag: u16 = w5500.sn_frag(Sn::Sn0)?;
2636    /// assert_eq!(frag, 0x4000);
2637    /// # w5500.free().done();
2638    /// # Ok::<(), eh1::spi::ErrorKind>(())
2639    /// ```
2640    fn sn_frag(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2641        let mut buf: [u8; 2] = [0; 2];
2642        self.read(SnReg::FRAG0.addr(), sn.block(), &mut buf)?;
2643        Ok(u16::from_be_bytes(buf))
2644    }
2645
2646    /// Set the socket fragment.
2647    ///
2648    /// See [`Registers::sn_frag`] for more information.
2649    ///
2650    /// # Example
2651    ///
2652    /// ```
2653    /// # let spi = ehm::eh1::spi::Mock::new(&[
2654    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2655    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2D, 0x08 | 0x04]),
2656    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00]),
2657    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2658    /// # ]);
2659    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2660    ///
2661    /// let mut w5500 = W5500::new(spi);
2662    /// w5500.set_sn_frag(Sn::Sn0, 0)?;
2663    /// # w5500.free().done();
2664    /// # Ok::<(), eh1::spi::ErrorKind>(())
2665    /// ```
2666    fn set_sn_frag(&mut self, sn: Sn, frag: u16) -> Result<(), Self::Error> {
2667        self.write(SnReg::FRAG0.addr(), sn.block(), &u16::to_be_bytes(frag))
2668    }
2669
2670    /// Get the socket keep alive time.
2671    ///
2672    /// This register configures the transmitting timer of the keep alive (KA)
2673    /// packet for the socket.  This is valid only in TCP mode, and is ignored
2674    /// in all other modes.
2675    ///
2676    /// The time unit is 5 seconds.
2677    ///
2678    /// The KA packet is transmittable after [`Registers::sn_sr`] is changed to
2679    /// [`SocketStatus::Established`] and after the data is transmitted or
2680    /// received to/from a peer at least once.
2681    ///
2682    /// In the case of a non-zero keep alive value the W5500 automatically
2683    /// transmits a KA packet after time-period for checking the TCP connection
2684    /// (automatic-keepalive-process).
2685    ///
2686    /// In case of a zero keep alive value, the keep alive packet can be
2687    /// transmitted with [`SocketCommand::SendKeep`].  This command is ignored
2688    /// for non-zero keep alive values.
2689    ///
2690    /// # Example
2691    ///
2692    /// ```
2693    /// # let spi = ehm::eh1::spi::Mock::new(&[
2694    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2695    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2F, 0x08]),
2696    /// #   ehm::eh1::spi::Transaction::read(0),
2697    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2698    /// # ]);
2699    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2700    ///
2701    /// let mut w5500 = W5500::new(spi);
2702    /// let sn_kpalvtr: u8 = w5500.sn_kpalvtr(Sn::Sn0)?;
2703    /// # w5500.free().done();
2704    /// # Ok::<(), eh1::spi::ErrorKind>(())
2705    /// ```
2706    fn sn_kpalvtr(&mut self, sn: Sn) -> Result<u8, Self::Error> {
2707        let mut buf: [u8; 1] = [0];
2708        self.read(SnReg::KPALVTR.addr(), sn.block(), &mut buf)?;
2709        Ok(buf[0])
2710    }
2711
2712    /// Set the socket keep alive time.
2713    ///
2714    /// See [`Registers::sn_kpalvtr`] for more information.
2715    ///
2716    /// # Example
2717    ///
2718    /// ```
2719    /// # let spi = ehm::eh1::spi::Mock::new(&[
2720    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2721    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2F, 0x08 | 0x04]),
2722    /// #   ehm::eh1::spi::Transaction::write(0x0A),
2723    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2724    /// # ]);
2725    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2726    ///
2727    /// let mut w5500 = W5500::new(spi);
2728    /// // 50s keep alive timer
2729    /// w5500.set_sn_kpalvtr(Sn::Sn0, 10)?;
2730    /// # w5500.free().done();
2731    /// # Ok::<(), eh1::spi::ErrorKind>(())
2732    /// ```
2733    fn set_sn_kpalvtr(&mut self, sn: Sn, kpalvtr: u8) -> Result<(), Self::Error> {
2734        self.write(SnReg::KPALVTR.addr(), sn.block(), &[kpalvtr])
2735    }
2736
2737    /// Write the socket TX buffer.
2738    ///
2739    /// # Example
2740    ///
2741    /// ```
2742    /// use core::cmp::min;
2743    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2744    /// # let spi = ehm::eh1::spi::Mock::new(&[
2745    /// #   // sn_tx_fsr
2746    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2747    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::TX_FSR0.addr() as u8, 0x08]),
2748    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0x08, 0x00]),
2749    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2750    /// #   // sn_tx_write
2751    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2752    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::TX_WR0.addr() as u8, 0x08]),
2753    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2754    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2755    /// #   // set_sn_tx_buf
2756    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2757    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.tx_block() as u8) << 3 | 0x04]),
2758    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0x56, 0x78, 0x9A]),
2759    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2760    /// #   // set_sn_tx_wr
2761    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2762    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x08 | 0x04]),
2763    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 5]),
2764    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2765    /// #   // set_sn_cr
2766    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2767    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08 | 0x04]),
2768    /// #   ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Send.into()]),
2769    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2770    /// # ]);
2771    /// # let mut w5500 = W5500::new(spi);
2772    ///
2773    /// // the socket should already be opened at this point
2774    /// const THE_SOCKET: Sn = Sn::Sn0;
2775    ///
2776    /// let buf: [u8; 5] = [0x12, 0x34, 0x56, 0x78, 0x9A];
2777    ///
2778    /// // transmit as many bytes as possible
2779    /// // for large buffers this may not transmit all the available data
2780    /// let tx_bytes: u16 = {
2781    ///     min(w5500.sn_tx_fsr(THE_SOCKET)?, u16::try_from(buf.len()).unwrap_or(u16::MAX))
2782    /// };
2783    /// if tx_bytes == 0 {
2784    ///     return Ok(());
2785    /// }
2786    ///
2787    /// let ptr: u16 = w5500.sn_tx_wr(THE_SOCKET)?;
2788    /// w5500.set_sn_tx_buf(THE_SOCKET, ptr, &buf[..usize::from(tx_bytes)])?;
2789    /// w5500.set_sn_tx_wr(THE_SOCKET, ptr.wrapping_add(tx_bytes))?;
2790    /// w5500.set_sn_cr(THE_SOCKET, SocketCommand::Send)?;
2791    /// # w5500.free().done();
2792    /// # Ok::<(), eh1::spi::ErrorKind>(())
2793    /// ```
2794    fn set_sn_tx_buf(&mut self, sn: Sn, ptr: u16, buf: &[u8]) -> Result<(), Self::Error> {
2795        self.write(ptr, sn.tx_block(), buf)
2796    }
2797
2798    /// Read the socket TX buffer.
2799    ///
2800    /// This method is typically unused; there are very few use cases that
2801    /// require reading the TX buffer.
2802    ///
2803    /// # Example
2804    ///
2805    /// ```
2806    /// use core::cmp::min;
2807    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2808    /// # let spi = ehm::eh1::spi::Mock::new(&[
2809    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2810    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.tx_block() as u8) << 3]),
2811    /// #   ehm::eh1::spi::Transaction::read(0),
2812    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2813    /// # ]);
2814    /// # let mut w5500 = W5500::new(spi);
2815    /// let mut buf: [u8; 1] = [0];
2816    /// w5500.sn_tx_buf(Sn::Sn0, 0, &mut buf)?;
2817    /// # w5500.free().done();
2818    /// # Ok::<(), eh1::spi::ErrorKind>(())
2819    /// ```
2820    fn sn_tx_buf(&mut self, sn: Sn, ptr: u16, buf: &mut [u8]) -> Result<(), Self::Error> {
2821        self.read(ptr, sn.tx_block(), buf)
2822    }
2823
2824    /// Read the socket RX buffer.
2825    ///
2826    /// # Example
2827    ///
2828    /// ```
2829    /// use core::cmp::min;
2830    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2831    /// # let spi = ehm::eh1::spi::Mock::new(&[
2832    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2833    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::RX_RSR0.addr() as u8, 0x08]),
2834    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 4]),
2835    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2836    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2837    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::RX_RD0.addr() as u8, 0x08]),
2838    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2839    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2840    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2841    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.rx_block() as u8) << 3]),
2842    /// #   ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
2843    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2844    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2845    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::RX_RD0.addr() as u8, 0x08 | 0x04]),
2846    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0, 4]),
2847    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2848    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2849    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::CR.addr() as u8, 0x08 | 0x04]),
2850    /// #   ehm::eh1::spi::Transaction::write(SocketCommand::Recv.into()),
2851    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2852    /// # ]);
2853    /// # let mut w5500 = W5500::new(spi);
2854    ///
2855    /// // the socket should already be opened at this point
2856    /// // a socket interrupt will indicate there is data to be retrieved
2857    /// const THE_SOCKET: Sn = Sn::Sn0;
2858    ///
2859    /// // in reality you will need a larger buffer for most protocols
2860    /// const BUF_LEN: usize = 16;
2861    /// let mut buf: [u8; BUF_LEN] = [0; BUF_LEN];
2862    ///
2863    /// let rx_bytes: u16 = {
2864    ///     min(w5500.sn_rx_rsr(THE_SOCKET)?, u16::try_from(buf.len()).unwrap_or(u16::MAX))
2865    /// };
2866    /// if rx_bytes == 0 {
2867    ///     return Ok(());
2868    /// }
2869    ///
2870    /// let ptr: u16 = w5500.sn_rx_rd(THE_SOCKET)?;
2871    /// w5500.sn_rx_buf(THE_SOCKET, ptr, &mut buf[..usize::from(rx_bytes)])?;
2872    /// w5500.set_sn_rx_rd(THE_SOCKET, ptr.wrapping_add(rx_bytes))?;
2873    /// w5500.set_sn_cr(THE_SOCKET, SocketCommand::Recv)?;
2874    /// # w5500.free().done();
2875    /// # Ok::<(), eh1::spi::ErrorKind>(())
2876    /// ```
2877    fn sn_rx_buf(&mut self, sn: Sn, ptr: u16, buf: &mut [u8]) -> Result<(), Self::Error> {
2878        self.read(ptr, sn.rx_block(), buf)
2879    }
2880
2881    /// Write the socket RX buffer.
2882    ///
2883    /// This method is typically unused; there are very few use cases that
2884    /// require writing the RX buffer.
2885    ///
2886    /// # Example
2887    ///
2888    /// ```
2889    /// use core::cmp::min;
2890    /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2891    /// # let spi = ehm::eh1::spi::Mock::new(&[
2892    /// #   ehm::eh1::spi::Transaction::transaction_start(),
2893    /// #   ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.rx_block() as u8) << 3 | 0x04]),
2894    /// #   ehm::eh1::spi::Transaction::write(0),
2895    /// #   ehm::eh1::spi::Transaction::transaction_end(),
2896    /// # ]);
2897    /// # let mut w5500 = W5500::new(spi);
2898    /// let buf: [u8; 1] = [0];
2899    /// w5500.set_sn_rx_buf(Sn::Sn0, 0, &buf)?;
2900    /// # w5500.free().done();
2901    /// # Ok::<(), eh1::spi::ErrorKind>(())
2902    /// ```
2903    fn set_sn_rx_buf(&mut self, sn: Sn, ptr: u16, buf: &[u8]) -> Result<(), Self::Error> {
2904        self.write(ptr, sn.rx_block(), buf)
2905    }
2906}