Renamed W5500 -> Device, added an Interface struct that should implement the embedded-nal traits, used it to internalize the mutability of the device

This commit is contained in:
Jonah Dahlquist 2020-11-19 19:28:12 -08:00
commit 3cad9cac57
7 changed files with 113 additions and 83 deletions

View file

@ -1,5 +1,5 @@
use crate::inactive_w5500::InactiveW5500; use crate::inactive_device::InactiveDevice;
use crate::uninitialized_w5500::UninitializedW5500; use crate::uninitialized_device::UninitializedDevice;
use bit_field::BitArray; use bit_field::BitArray;
use bus::{ActiveBus, ActiveFourWire, ActiveThreeWire, FourWire, ThreeWire}; use bus::{ActiveBus, ActiveFourWire, ActiveThreeWire, FourWire, ThreeWire};
use embedded_hal::digital::v2::OutputPin; use embedded_hal::digital::v2::OutputPin;
@ -7,8 +7,9 @@ use embedded_hal::spi::FullDuplex;
use network::Network; use network::Network;
use register; use register;
use socket::Socket; use socket::Socket;
use interface::Interface;
pub struct W5500<SpiBus: ActiveBus, NetworkImpl: Network> { pub struct Device<SpiBus: ActiveBus, NetworkImpl: Network> {
pub bus: SpiBus, pub bus: SpiBus,
network: NetworkImpl, network: NetworkImpl,
sockets: [u8; 1], sockets: [u8; 1],
@ -25,29 +26,28 @@ impl<E> From<E> for ResetError<E> {
} }
} }
impl<SpiBus: ActiveBus, NetworkImpl: Network> W5500<SpiBus, NetworkImpl> { impl<SpiBus: ActiveBus, NetworkImpl: Network> Device<SpiBus, NetworkImpl> {
pub fn new(bus: SpiBus, network: NetworkImpl) -> Self { pub fn new(bus: SpiBus, network: NetworkImpl) -> Self {
W5500 { Device {
bus, bus,
network, network,
sockets: [0b11111111], sockets: [0b11111111],
} }
} }
pub fn reset(mut self) -> Result<UninitializedW5500<SpiBus>, ResetError<SpiBus::Error>> { pub fn reset(mut self) -> Result<UninitializedDevice<SpiBus>, ResetError<SpiBus::Error>> {
if self.sockets != [0b11111111] { if self.sockets != [0b11111111] {
Err(ResetError::SocketsNotReleased) Err(ResetError::SocketsNotReleased)
} else { } else {
self.clear_mode()?; self.clear_mode()?;
Ok(UninitializedW5500::new(self.bus)) Ok(UninitializedDevice::new(self.bus))
} }
} }
fn clear_mode(&mut self) -> Result<(), SpiBus::Error> { fn clear_mode(&mut self) -> Result<(), SpiBus::Error> {
// reset bit // reset bit
let mut mode = [0b10000000]; let mut mode = [0b10000000];
self.bus self.bus.write_frame(register::COMMON, register::common::MODE, &mut mode)?;
.write_frame(register::COMMON, register::common::MODE, &mut mode)?;
Ok(()) Ok(())
} }
@ -61,6 +61,10 @@ impl<SpiBus: ActiveBus, NetworkImpl: Network> W5500<SpiBus, NetworkImpl> {
None None
} }
pub fn into_interface(self) -> Interface<SpiBus, NetworkImpl> {
self.into()
}
pub fn release_socket(&mut self, socket: Socket) -> () { pub fn release_socket(&mut self, socket: Socket) -> () {
self.sockets.set_bit(socket.index.into(), true); self.sockets.set_bit(socket.index.into(), true);
} }
@ -71,17 +75,17 @@ impl<SpiBus: ActiveBus, NetworkImpl: Network> W5500<SpiBus, NetworkImpl> {
} }
impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin, NetworkImpl: Network> impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin, NetworkImpl: Network>
W5500<ActiveFourWire<Spi, ChipSelect>, NetworkImpl> Device<ActiveFourWire<Spi, ChipSelect>, NetworkImpl>
{ {
pub fn deactivate(self) -> (InactiveW5500<FourWire<ChipSelect>, NetworkImpl>, Spi) { pub fn deactivate(self) -> (InactiveDevice<FourWire<ChipSelect>, NetworkImpl>, Spi) {
let (bus, spi) = self.bus.deactivate(); let (bus, spi) = self.bus.deactivate();
(InactiveW5500::new(bus, self.network), spi) (InactiveDevice::new(bus, self.network), spi)
} }
} }
impl<Spi: FullDuplex<u8>, NetworkImpl: Network> W5500<ActiveThreeWire<Spi>, NetworkImpl> { impl<Spi: FullDuplex<u8>, NetworkImpl: Network> Device<ActiveThreeWire<Spi>, NetworkImpl> {
pub fn deactivate(self) -> (InactiveW5500<ThreeWire, NetworkImpl>, Spi) { pub fn deactivate(self) -> (InactiveDevice<ThreeWire, NetworkImpl>, Spi) {
let (bus, spi) = self.bus.deactivate(); let (bus, spi) = self.bus.deactivate();
(InactiveW5500::new(bus, self.network), spi) (InactiveDevice::new(bus, self.network), spi)
} }
} }

34
src/inactive_device.rs Normal file
View file

@ -0,0 +1,34 @@
use bus::{ActiveFourWire, ActiveThreeWire, Bus, FourWire, ThreeWire};
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::FullDuplex;
use network::Network;
use device::Device;
pub struct InactiveDevice<SpiBus: Bus, NetworkImpl: Network> {
bus: SpiBus,
network: NetworkImpl,
}
impl<SpiBus: Bus, NetworkImpl: Network> InactiveDevice<SpiBus, NetworkImpl> {
pub fn new(bus: SpiBus, network: NetworkImpl) -> Self {
Self { bus, network }
}
}
impl<ChipSelect: OutputPin, NetworkImpl: Network> InactiveDevice<FourWire<ChipSelect>, NetworkImpl> {
pub fn activate<Spi: FullDuplex<u8>>(
self,
spi: Spi,
) -> Device<ActiveFourWire<Spi, ChipSelect>, NetworkImpl> {
Device::new(self.bus.activate(spi), self.network)
}
}
impl<NetworkImpl: Network> InactiveDevice<ThreeWire, NetworkImpl> {
pub fn activate<Spi: FullDuplex<u8>>(
self,
spi: Spi,
) -> Device<ActiveThreeWire<Spi>, NetworkImpl> {
Device::new(self.bus.activate(spi), self.network)
}
}

View file

@ -1,34 +0,0 @@
use bus::{ActiveFourWire, ActiveThreeWire, Bus, FourWire, ThreeWire};
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::FullDuplex;
use network::Network;
use w5500::W5500;
pub struct InactiveW5500<SpiBus: Bus, NetworkImpl: Network> {
bus: SpiBus,
network: NetworkImpl,
}
impl<SpiBus: Bus, NetworkImpl: Network> InactiveW5500<SpiBus, NetworkImpl> {
pub fn new(bus: SpiBus, network: NetworkImpl) -> Self {
Self { bus, network }
}
}
impl<ChipSelect: OutputPin, NetworkImpl: Network> InactiveW5500<FourWire<ChipSelect>, NetworkImpl> {
pub fn activate<Spi: FullDuplex<u8>>(
self,
spi: Spi,
) -> W5500<ActiveFourWire<Spi, ChipSelect>, NetworkImpl> {
W5500::new(self.bus.activate(spi), self.network)
}
}
impl<NetworkImpl: Network> InactiveW5500<ThreeWire, NetworkImpl> {
pub fn activate<Spi: FullDuplex<u8>>(
self,
spi: Spi,
) -> W5500<ActiveThreeWire<Spi>, NetworkImpl> {
W5500::new(self.bus.activate(spi), self.network)
}
}

21
src/interface.rs Normal file
View file

@ -0,0 +1,21 @@
use bus::{ActiveBus};
use device::Device;
use network::Network;
use core::cell::RefCell;
pub struct Interface<SpiBus: ActiveBus, NetworkImpl: Network> {
pub device: RefCell<Device<SpiBus, NetworkImpl>>,
}
impl<SpiBus: ActiveBus, NetworkImpl: Network> Interface<SpiBus, NetworkImpl> {
fn new(device: Device<SpiBus, NetworkImpl>) -> Self {
Self { device: RefCell::new(device) }
}
}
impl<SpiBus: ActiveBus, NetworkImpl: Network> From<Device<SpiBus, NetworkImpl>> for Interface<SpiBus, NetworkImpl> {
fn from(device: Device<SpiBus, NetworkImpl>) -> Interface<SpiBus, NetworkImpl> {
Interface::<SpiBus, NetworkImpl>::new(device)
}
}

View file

@ -74,12 +74,14 @@ impl Default for Mode {
} }
pub mod bus; pub mod bus;
mod inactive_w5500; mod inactive_device;
mod network; mod network;
pub mod register; pub mod register;
mod socket; mod socket;
mod udp; mod udp;
pub mod uninitialized_w5500; pub mod uninitialized_device;
mod w5500; mod device;
pub mod interface;
pub use bus::ActiveFourWire; pub use bus::ActiveFourWire;
pub use interface::Interface;

View file

@ -2,7 +2,7 @@ use crate::bus::ActiveBus;
use crate::network::Network; use crate::network::Network;
use crate::register::socketn; use crate::register::socketn;
use crate::socket::Socket; use crate::socket::Socket;
use crate::w5500::W5500; use crate::interface::Interface;
use core::fmt::Debug; use core::fmt::Debug;
use embedded_nal::{nb, IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, UdpServer, UdpClient}; use embedded_nal::{nb, IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, UdpServer, UdpClient};
@ -191,19 +191,20 @@ impl<E: Debug> From<NbError<E>> for nb::Error<E> {
} }
impl<SpiBus, NetworkImpl> UdpClient for W5500<SpiBus, NetworkImpl> impl<SpiBus, NetworkImpl> UdpClient for Interface<SpiBus, NetworkImpl>
where where
SpiBus: ActiveBus, SpiBus: ActiveBus,
NetworkImpl: Network, NetworkImpl: Network,
{ {
type UdpSocket = UdpSocket; type UdpSocket = UdpSocket;
type Error = UdpSocketError<SpiBus::Error>; type Error = UdpSocketError<SpiBus::Error>;
fn connect(&mut self, remote: SocketAddr) -> Result<Self::UdpSocket, Self::Error> { fn connect(&self, remote: SocketAddr) -> Result<Self::UdpSocket, Self::Error> {
let mut device = self.device.borrow_mut();
if let SocketAddr::V4(remote) = remote { if let SocketAddr::V4(remote) = remote {
if let Some(socket) = self.take_socket() { if let Some(socket) = device.take_socket() {
// TODO find a random port // TODO find a random port
let mut udp_socket = UdpSocket::new(&mut self.bus, socket, 4000)?; let mut udp_socket = UdpSocket::new(&mut device.bus, socket, 4000)?;
udp_socket.set_destination(&mut self.bus, remote)?; udp_socket.set_destination(&mut device.bus, remote)?;
Ok(udp_socket) Ok(udp_socket)
} else { } else {
Err(Self::Error::NoMoreSockets) Err(Self::Error::NoMoreSockets)
@ -212,44 +213,46 @@ where
Err(Self::Error::UnsupportedAddress) Err(Self::Error::UnsupportedAddress)
} }
} }
fn send(&mut self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error> { fn send(&self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error> {
socket.send(&mut self.bus, buffer)?; socket.send(&mut self.device.borrow_mut().bus, buffer)?;
Ok(()) Ok(())
} }
fn receive( fn receive(
&mut self, &self,
socket: &mut Self::UdpSocket, socket: &mut Self::UdpSocket,
buffer: &mut [u8], buffer: &mut [u8],
) -> nb::Result<(usize, SocketAddr), Self::Error> { ) -> nb::Result<(usize, SocketAddr), Self::Error> {
Ok(socket.receive(&mut self.bus, buffer)?) Ok(socket.receive(&mut self.device.borrow_mut().bus, buffer)?)
} }
fn close(&mut self, socket: Self::UdpSocket) -> Result<(), Self::Error> { fn close(&self, socket: Self::UdpSocket) -> Result<(), Self::Error> {
socket.close(&mut self.bus)?; let mut device = self.device.borrow_mut();
self.release_socket(socket.socket); socket.close(&mut device.bus)?;
device.release_socket(socket.socket);
Ok(()) Ok(())
} }
} }
impl<SpiBus, NetworkImpl> UdpServer for W5500<SpiBus, NetworkImpl> impl<SpiBus, NetworkImpl> UdpServer for Interface<SpiBus, NetworkImpl>
where where
SpiBus: ActiveBus, SpiBus: ActiveBus,
NetworkImpl: Network, NetworkImpl: Network,
{ {
fn bind(&mut self, local_port: u16) -> Result<Self::UdpSocket, Self::Error> { fn bind(&self, local_port: u16) -> Result<Self::UdpSocket, Self::Error> {
if let Some(socket) = self.take_socket() { let mut device = self.device.borrow_mut();
Ok(UdpSocket::new(&mut self.bus, socket, local_port)?) if let Some(socket) = device.take_socket() {
Ok(UdpSocket::new(&mut device.bus, socket, local_port)?)
} else { } else {
Err(Self::Error::NoMoreSockets) Err(Self::Error::NoMoreSockets)
} }
} }
fn send_to( fn send_to(
&mut self, &self,
socket: &mut Self::UdpSocket, socket: &mut Self::UdpSocket,
remote: SocketAddr, remote: SocketAddr,
buffer: &[u8], buffer: &[u8],
) -> nb::Result<(), Self::Error> { ) -> nb::Result<(), Self::Error> {
if let SocketAddr::V4(remote) = remote { if let SocketAddr::V4(remote) = remote {
socket.send_to(&mut self.bus, remote, buffer)?; socket.send_to(&mut self.device.borrow_mut().bus, remote, buffer)?;
Ok(()) Ok(())
} else { } else {
Err(nb::Error::Other(Self::Error::UnsupportedAddress)) Err(nb::Error::Other(Self::Error::UnsupportedAddress))

View file

@ -5,9 +5,9 @@ use embedded_hal::digital::v2::OutputPin;
use embedded_hal::spi::FullDuplex; use embedded_hal::spi::FullDuplex;
use embedded_nal::Ipv4Addr; use embedded_nal::Ipv4Addr;
use register; use register;
use w5500::W5500; use device::Device;
pub struct UninitializedW5500<SpiBus: ActiveBus> { pub struct UninitializedDevice<SpiBus: ActiveBus> {
bus: SpiBus, bus: SpiBus,
} }
@ -18,16 +18,16 @@ pub enum InitializeError<SpiError> {
} }
// TODO add From impl and remove map_errs // TODO add From impl and remove map_errs
impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> { impl<SpiBus: ActiveBus> UninitializedDevice<SpiBus> {
pub fn new(bus: SpiBus) -> UninitializedW5500<SpiBus> { pub fn new(bus: SpiBus) -> UninitializedDevice<SpiBus> {
UninitializedW5500 { bus: bus } UninitializedDevice { bus: bus }
} }
pub fn initialize( pub fn initialize(
self, self,
mac: MacAddress, mac: MacAddress,
mode_options: Mode, mode_options: Mode,
) -> Result<W5500<SpiBus, Dhcp>, InitializeError<SpiBus::Error>> { ) -> Result<Device<SpiBus, Dhcp>, InitializeError<SpiBus::Error>> {
let network = Dhcp::new(mac); let network = Dhcp::new(mac);
self.initialize_with_network(network, mode_options) self.initialize_with_network(network, mode_options)
} }
@ -37,7 +37,7 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
mac: MacAddress, mac: MacAddress,
ip: Ipv4Addr, ip: Ipv4Addr,
mode_options: Mode, mode_options: Mode,
) -> Result<W5500<SpiBus, Manual>, InitializeError<SpiBus::Error>> { ) -> Result<Device<SpiBus, Manual>, InitializeError<SpiBus::Error>> {
let mut ip_bytes = ip.octets(); let mut ip_bytes = ip.octets();
ip_bytes[3] = 1; ip_bytes[3] = 1;
let gateway = Ipv4Addr::from(ip_bytes); let gateway = Ipv4Addr::from(ip_bytes);
@ -52,7 +52,7 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
gateway: Ipv4Addr, gateway: Ipv4Addr,
subnet: Ipv4Addr, subnet: Ipv4Addr,
mode_options: Mode, mode_options: Mode,
) -> Result<W5500<SpiBus, Manual>, InitializeError<SpiBus::Error>> { ) -> Result<Device<SpiBus, Manual>, InitializeError<SpiBus::Error>> {
let network = Manual::new(mac, ip, gateway, subnet); let network = Manual::new(mac, ip, gateway, subnet);
self.initialize_with_network(network, mode_options) self.initialize_with_network(network, mode_options)
} }
@ -61,7 +61,7 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
mut self, mut self,
mut network: NetworkImpl, mut network: NetworkImpl,
mode_options: Mode, mode_options: Mode,
) -> Result<W5500<SpiBus, NetworkImpl>, InitializeError<SpiBus::Error>> { ) -> Result<Device<SpiBus, NetworkImpl>, InitializeError<SpiBus::Error>> {
self.assert_chip_version(0x4)?; self.assert_chip_version(0x4)?;
// RESET // RESET
@ -75,7 +75,7 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
network network
.refresh(&mut self.bus) .refresh(&mut self.bus)
.map_err(|e| InitializeError::SpiError(e))?; .map_err(|e| InitializeError::SpiError(e))?;
Ok(W5500::new(self.bus, network)) Ok(Device::new(self.bus, network))
} }
fn assert_chip_version( fn assert_chip_version(
@ -106,7 +106,7 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
} }
impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin> impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin>
UninitializedW5500<ActiveFourWire<Spi, ChipSelect>> UninitializedDevice<ActiveFourWire<Spi, ChipSelect>>
{ {
pub fn deactivate(self) -> (Spi, ChipSelect) { pub fn deactivate(self) -> (Spi, ChipSelect) {
let (bus, spi) = self.bus.deactivate(); let (bus, spi) = self.bus.deactivate();
@ -114,7 +114,7 @@ impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin>
} }
} }
impl<Spi: FullDuplex<u8>> UninitializedW5500<ActiveThreeWire<Spi>> { impl<Spi: FullDuplex<u8>> UninitializedDevice<ActiveThreeWire<Spi>> {
pub fn deactivate(self) -> Spi { pub fn deactivate(self) -> Spi {
self.bus.deactivate().1 self.bus.deactivate().1
} }