1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//! Fixed data length implementation of the [`Registers`] trait using the
//! [`embedded-hal`] blocking SPI trait.
//!
//! This uses the W5500 fixed data length mode (FDM).
//! In FSM mode the SPI chip select pin is always tied low, and it is not
//! possible to share the bus with other devices.
//!
//! If possible, you should use the [VDM] implementation instead.
//!
//! [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal
//! [`Registers`]: crate::Registers
//! [VDM]: crate::eh1::vdm
use crate::spi::{self, AccessMode};
/// W5500 blocking fixed data length implementation.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct W5500<SPI> {
/// SPI bus.
spi: SPI,
}
impl<SPI> W5500<SPI>
where
SPI: eh1::spi::SpiBus<u8>,
{
/// Creates a new `W5500` driver from a SPI bus.
///
/// # Example
///
/// ```
/// # use ehm::eh1 as hal;
/// # let spi = hal::spi::Mock::new(&[]);
/// use w5500_ll::eh1::fdm::W5500;
///
/// let mut w5500: W5500<_> = W5500::new(spi);
/// # w5500.free().done();
/// ```
#[inline]
pub fn new(spi: SPI) -> Self {
W5500 { spi }
}
/// Free the SPI bus from the W5500.
///
/// # Example
///
/// ```
/// # use ehm::eh1 as hal;
/// # let spi = hal::spi::Mock::new(&[]);
/// use w5500_ll::eh1::fdm::W5500;
///
/// let w5500: W5500<_> = W5500::new(spi);
/// let mut spi = w5500.free();
/// # spi.done();
/// ```
#[inline]
pub fn free(self) -> SPI {
self.spi
}
}
impl<SPI> crate::Registers for W5500<SPI>
where
SPI: eh1::spi::SpiBus<u8>,
{
/// SPI IO error type.
type Error = SPI::Error;
/// Read from the W5500.
#[allow(clippy::while_let_on_iterator)]
fn read(&mut self, mut address: u16, block: u8, data: &mut [u8]) -> Result<(), Self::Error> {
let mut chunks = data.chunks_exact_mut(4);
while let Some(chunk) = chunks.next() {
let header = spi::fdm_header_4b(address, block, AccessMode::Read);
self.spi.write(&header)?;
self.spi.read(chunk)?;
address = address.wrapping_add(4);
}
let mut chunks = chunks.into_remainder().chunks_exact_mut(2);
while let Some(chunk) = chunks.next() {
let header = spi::fdm_header_2b(address, block, AccessMode::Read);
self.spi.write(&header)?;
self.spi.read(chunk)?;
address = address.wrapping_add(2);
}
let mut chunks = chunks.into_remainder().chunks_exact_mut(1);
while let Some(chunk) = chunks.next() {
let header = spi::fdm_header_1b(address, block, AccessMode::Read);
self.spi.write(&header)?;
self.spi.read(chunk)?;
address = address.wrapping_add(1);
}
Ok(())
}
/// Write to the W5500.
#[allow(clippy::while_let_on_iterator)]
fn write(&mut self, mut address: u16, block: u8, data: &[u8]) -> Result<(), Self::Error> {
let mut chunks = data.chunks_exact(4);
while let Some(chunk) = chunks.next() {
let header = spi::fdm_header_4b(address, block, AccessMode::Write);
self.spi.write(&header)?;
self.spi.write(chunk)?;
address = address.wrapping_add(4);
}
let mut chunks = chunks.remainder().chunks_exact(2);
while let Some(chunk) = chunks.next() {
let header = spi::fdm_header_2b(address, block, AccessMode::Write);
self.spi.write(&header)?;
self.spi.write(chunk)?;
address = address.wrapping_add(2);
}
let mut chunks = chunks.remainder().chunks_exact(1);
while let Some(chunk) = chunks.next() {
let header = spi::fdm_header_1b(address, block, AccessMode::Write);
self.spi.write(&header)?;
self.spi.write(chunk)?;
address = address.wrapping_add(1);
}
Ok(())
}
}