w5500_ll/eh1/
vdm.rs

1//! Variable data length implementation of the [`Registers`] trait using the
2//! [`embedded-hal`] blocking SPI trait, and a fallible GPIO pin.
3//!
4//! This uses the W5500 variable data length mode (VDM).
5//! In VDM mode the SPI frame data length is determined by the chip select pin.
6//! This is the preferred blocking implementation if your W5500 has a fallible
7//! chip select pin.
8//!
9//! [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal
10//! [`Registers`]: crate::Registers
11
12use crate::spi::{vdm_header, AccessMode};
13use eh1::spi::ErrorType;
14
15/// W5500 blocking variable data length implementation.
16#[derive(Debug)]
17#[cfg_attr(feature = "defmt", derive(defmt::Format))]
18pub struct W5500<SPI> {
19    /// SPI bus + chip select pin.
20    spi: SPI,
21}
22
23impl<SPI, E> W5500<SPI>
24where
25    SPI: eh1::spi::SpiDevice<Error = E>,
26{
27    /// Creates a new `W5500` driver from a SPI device.
28    ///
29    /// # Example
30    ///
31    /// ```
32    /// # use ehm::eh1 as hal;
33    /// # let spi = hal::spi::Mock::new(&[]);
34    /// use w5500_ll::eh1::vdm::W5500;
35    ///
36    /// let mut w5500: W5500<_> = W5500::new(spi);
37    /// # w5500.free().done();
38    /// ```
39    #[inline]
40    pub fn new(spi: SPI) -> Self {
41        W5500 { spi }
42    }
43
44    /// Free the SPI device.
45    ///
46    /// # Example
47    ///
48    /// ```
49    /// # use ehm::eh1 as hal;
50    /// # let spi = hal::spi::Mock::new(&[]);
51    /// use w5500_ll::eh1::vdm::W5500;
52    ///
53    /// let mut w5500 = W5500::new(spi);
54    /// let mut spi = w5500.free();
55    /// # spi.done();
56    /// ```
57    #[inline]
58    pub fn free(self) -> SPI {
59        self.spi
60    }
61}
62
63impl<SPI> crate::Registers for W5500<SPI>
64where
65    SPI: eh1::spi::SpiDevice,
66{
67    /// SPI IO error type.
68    type Error = SPI::Error;
69
70    /// Read from the W5500.
71    #[inline]
72    fn read(
73        &mut self,
74        address: u16,
75        block: u8,
76        data: &mut [u8],
77    ) -> Result<(), <SPI as ErrorType>::Error> {
78        let header = vdm_header(address, block, AccessMode::Read);
79        let mut ops = [
80            eh1::spi::Operation::Write(&header),
81            eh1::spi::Operation::Read(data),
82        ];
83        self.spi.transaction(&mut ops)
84    }
85
86    /// Write to the W5500.
87    #[inline]
88    fn write(
89        &mut self,
90        address: u16,
91        block: u8,
92        data: &[u8],
93    ) -> Result<(), <SPI as ErrorType>::Error> {
94        let header = vdm_header(address, block, AccessMode::Write);
95        let mut ops = [
96            eh1::spi::Operation::Write(&header),
97            eh1::spi::Operation::Write(data),
98        ];
99        self.spi.transaction(&mut ops)
100    }
101}
102
103#[cfg(feature = "eha1")]
104impl<SPI> crate::aio::Registers for W5500<SPI>
105where
106    SPI: eha1::spi::SpiDevice,
107{
108    /// SPI IO error type.
109    type Error = SPI::Error;
110
111    /// Read from the W5500 asynchronously.
112    async fn read(
113        &mut self,
114        address: u16,
115        block: u8,
116        data: &mut [u8],
117    ) -> Result<(), <SPI as ErrorType>::Error> {
118        let header = vdm_header(address, block, AccessMode::Read);
119        let mut ops = [
120            eh1::spi::Operation::Write(&header),
121            eh1::spi::Operation::Read(data),
122        ];
123        self.spi.transaction(&mut ops).await
124    }
125
126    /// Write to the W5500 asynchronously.
127    async fn write(
128        &mut self,
129        address: u16,
130        block: u8,
131        data: &[u8],
132    ) -> Result<(), <SPI as ErrorType>::Error> {
133        let header = vdm_header(address, block, AccessMode::Write);
134        let mut ops = [
135            eh1::spi::Operation::Write(&header),
136            eh1::spi::Operation::Write(data),
137        ];
138        self.spi.transaction(&mut ops).await
139    }
140}