w5500_ll/
aio.rs

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