use bit_field::BitField;
use crate::bus::{Bus, FourWire, ThreeWire};
use crate::host::Host;
use crate::net::Ipv4Addr;
use crate::socket::Socket;
use crate::uninitialized_device::UninitializedDevice;
use crate::{
register::{self, common::RetryTime},
MacAddress, Mode,
};
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ResetError<E> {
SocketsNotReleased,
Other(E),
}
impl<E> From<E> for ResetError<E> {
fn from(error: E) -> ResetError<E> {
ResetError::Other(error)
}
}
mod private {
pub trait Sealed {}
impl<T: Sealed> Sealed for &'_ mut T {}
}
pub trait State: private::Sealed {
fn socket(&mut self) -> Option<Socket>;
fn release_socket(&mut self, socket: Socket);
fn any_allocated(&self) -> bool;
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DeviceState<HostImpl: Host> {
host: HostImpl,
sockets: u8,
}
impl<HostImpl: Host> DeviceState<HostImpl> {
pub fn new(host: HostImpl) -> Self {
Self {
sockets: 0xFF,
host,
}
}
}
impl<HostImpl: Host> private::Sealed for DeviceState<HostImpl> {}
impl<HostImpl: Host> State for DeviceState<HostImpl> {
fn socket(&mut self) -> Option<Socket> {
for index in 0..8 {
if self.sockets.get_bit(index) {
self.sockets.set_bit(index, false);
return Some(Socket::new(index as u8));
}
}
None
}
fn release_socket(&mut self, socket: Socket) {
self.sockets.set_bit(socket.index.into(), true);
}
fn any_allocated(&self) -> bool {
self.sockets != 0xFF
}
}
impl<T: State> State for &'_ mut T {
fn socket(&mut self) -> Option<Socket> {
T::socket(self)
}
fn release_socket(&mut self, socket: Socket) {
T::release_socket(self, socket)
}
fn any_allocated(&self) -> bool {
T::any_allocated(self)
}
}
pub struct Device<SpiBus: Bus, StateImpl: State> {
pub(crate) bus: SpiBus,
state: StateImpl,
}
impl<SpiBus: Bus, StateImpl: State> Device<SpiBus, StateImpl> {
pub(crate) fn new(bus: SpiBus, state: StateImpl) -> Self {
Device { bus, state }
}
pub fn get_state(&self) -> &StateImpl {
&self.state
}
pub fn reset(mut self) -> Result<UninitializedDevice<SpiBus>, ResetError<SpiBus::Error>> {
if self.state.any_allocated() {
Err(ResetError::SocketsNotReleased)
} else {
self.reset_device()?;
Ok(UninitializedDevice::new(self.bus))
}
}
pub fn release(self) -> (SpiBus, StateImpl) {
(self.bus, self.state)
}
pub fn take_socket(&mut self) -> Option<Socket> {
self.state.socket()
}
pub fn release_socket(&mut self, socket: Socket) {
self.state.release_socket(socket)
}
pub fn gateway(&mut self) -> Result<Ipv4Addr, SpiBus::Error> {
let mut octets = [0u8; 4];
self.bus
.read_frame(register::COMMON, register::common::GATEWAY, &mut octets)?;
Ok(Ipv4Addr::from(octets))
}
pub fn subnet_mask(&mut self) -> Result<Ipv4Addr, SpiBus::Error> {
let mut octets = [0u8; 4];
self.bus
.read_frame(register::COMMON, register::common::SUBNET_MASK, &mut octets)?;
Ok(Ipv4Addr::from(octets))
}
pub fn mac(&mut self) -> Result<MacAddress, SpiBus::Error> {
let mut mac = MacAddress::default();
self.bus
.read_frame(register::COMMON, register::common::MAC, &mut mac.octets)?;
Ok(mac)
}
pub fn ip(&mut self) -> Result<Ipv4Addr, SpiBus::Error> {
let mut octets = [0u8; 4];
self.bus
.read_frame(register::COMMON, register::common::IP, &mut octets)?;
Ok(Ipv4Addr::from(octets))
}
pub fn phy_config(&mut self) -> Result<register::common::PhyConfig, SpiBus::Error> {
let mut phy = [0u8];
self.bus
.read_frame(register::COMMON, register::common::PHY_CONFIG, &mut phy)?;
Ok(phy[0].into())
}
#[inline]
pub fn reset_device(&mut self) -> Result<(), SpiBus::Error> {
let mode = [0b10000000];
self.bus
.write_frame(register::COMMON, register::common::MODE, &mode)
}
#[inline]
pub fn set_mode(&mut self, mode_options: Mode) -> Result<(), SpiBus::Error> {
self.bus.write_frame(
register::COMMON,
register::common::MODE,
&mode_options.to_register(),
)
}
#[inline]
pub fn version(&mut self) -> Result<u8, SpiBus::Error> {
let mut version_register = [0_u8];
self.bus.read_frame(
register::COMMON,
register::common::VERSION,
&mut version_register,
)?;
Ok(version_register[0])
}
#[inline]
pub fn set_retry_timeout(&mut self, retry_time_value: RetryTime) -> Result<(), SpiBus::Error> {
self.bus.write_frame(
register::COMMON,
register::common::RETRY_TIME,
&retry_time_value.to_register(),
)?;
Ok(())
}
#[inline]
pub fn current_retry_timeout(&mut self) -> Result<RetryTime, SpiBus::Error> {
let mut retry_time_register: [u8; 2] = [0, 0];
self.bus.read_frame(
register::COMMON,
register::common::RETRY_TIME,
&mut retry_time_register,
)?;
Ok(RetryTime::from_register(retry_time_register))
}
pub fn set_retry_count(&mut self, retry_count: u8) -> Result<(), SpiBus::Error> {
self.bus.write_frame(
register::COMMON,
register::common::RETRY_COUNT,
&[retry_count],
)?;
Ok(())
}
#[inline]
pub fn current_retry_count(&mut self) -> Result<u8, SpiBus::Error> {
let mut retry_count_register: [u8; 1] = [0];
self.bus.read_frame(
register::COMMON,
register::common::RETRY_COUNT,
&mut retry_count_register,
)?;
Ok(retry_count_register[0])
}
pub fn deactivate(self) -> (SpiBus, InactiveDevice<StateImpl>) {
(self.bus, InactiveDevice(self.state))
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct InactiveDevice<StateImpl: State>(StateImpl);
impl<StateImpl: State> InactiveDevice<StateImpl> {
pub fn activate<SpiBus: Bus>(self, bus: SpiBus) -> Device<SpiBus, StateImpl> {
Device { bus, state: self.0 }
}
pub fn activate_ref<SpiBus: Bus>(&mut self, bus: SpiBus) -> Device<SpiBus, &mut StateImpl> {
Device {
bus,
state: &mut self.0,
}
}
}