Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Retry time and count #54

Merged
merged 12 commits into from
Jul 25, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Add `defmt` features for enabling `defmt::Format` to most structs and errors by [@elpiel](https://github.com/elpiel) ([#39](https://github.com/kellerkindt/w5500/issues/39))
- Fixed an issue where internal function names were conflicting with trait names by [@ryan-summers](https://github.com/ryan-summers) ([#36](https://github.com/kellerkindt/w5500/issues/36))
- Add `RetryTime` value and `RetryCount` registers methods and common register methods to `Bus` by [@elpiel](https://github.com/elpiel) ([#54][PR54])

### Fixed

Expand Down
108 changes: 108 additions & 0 deletions src/bus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ mod four_wire;
mod four_wire_ref;
mod three_wire;

use crate::register::{
self,
common::{PhyConfig, RetryCount, RetryTime, MODE, VERSION},
};

pub use self::four_wire::FourWire;
pub use self::four_wire::FourWireError;
pub use self::four_wire_ref::FourWireRef;
Expand All @@ -18,6 +23,109 @@ pub trait Bus {
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error>;

fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error>;

/// Reset the device
#[inline]
fn reset(&mut self) -> Result<(), Self::Error> {
self.write_frame(
register::COMMON,
register::common::MODE,
&register::common::Mode::Reset.to_register(),
)?;

Ok(())
}

#[inline]
fn set_mode(&mut self, mode_options: register::common::Mode) -> Result<(), Self::Error> {
self.write_frame(
register::COMMON,
register::common::MODE,
&mode_options.to_register(),
)?;
Ok(())
}

#[inline]
fn version(&mut self) -> Result<u8, Self::Error> {
let mut version_register = [0_u8];
self.read_frame(
register::COMMON,
register::common::VERSION,
&mut version_register,
)?;

Ok(version_register[0])
}

/// RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0]
///
/// # Example
/// ```
/// use w5500::register::common::RetryTime;
///
/// let default = RetryTime::from_millis(200);
/// assert_eq!(RetryTime::default(), default);
///
/// // E.g. 4000 (register) = 400ms
/// let four_hundred_ms = RetryTime::from_millis(400);
/// assert_eq!(four_hundred_ms.to_u16(), 4000);
/// ```
#[inline]
fn set_retry_timeout(&mut self, retry_time_value: RetryTime) -> Result<(), Self::Error> {
self.write_frame(
register::COMMON,
register::common::RETRY_TIME,
&retry_time_value.to_register(),
)?;

Ok(())
}

/// RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0]
///
/// E.g. 4000 = 400ms
#[inline]
fn current_retry_timeout(&mut self) -> Result<RetryTime, Self::Error> {
let mut retry_time_register: [u8; 2] = [0, 0];
self.read_frame(
register::COMMON,
register::common::RETRY_TIME,
&mut retry_time_register,
)?;

Ok(RetryTime::from_register(retry_time_register))
}

/// Set a new value for the Retry Count register.
///
/// RCR (Retry Count Register) [R/W] [0x001B] [0x08]
fn set_retry_count(&mut self, retry_count: RetryCount) -> Result<(), Self::Error> {
self.write_frame(
register::COMMON,
register::common::RETRY_COUNT,
&retry_count.to_register(),
)?;

Ok(())
}

/// Get the current Retry Count value
/// RCR (Retry Count Register) [R/W] [0x001B] [0x08]
///
/// E.g. In case of errors it will retry for 7 times:
/// `RCR = 0x0007`
#[inline]
fn current_retry_count(&mut self) -> Result<RetryCount, Self::Error> {
let mut retry_count_register: [u8; 1] = [0];
self.read_frame(
register::COMMON,
register::common::RETRY_COUNT,
&mut retry_count_register,
)?;

Ok(RetryCount::from_register(retry_count_register))
}
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved
}

pub struct BusRef<'a, B: Bus>(pub &'a mut B);
Expand Down
108 changes: 102 additions & 6 deletions src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use crate::host::Host;
use crate::net::Ipv4Addr;
use crate::socket::Socket;
use crate::uninitialized_device::UninitializedDevice;
use crate::{register, MacAddress};
use crate::{
common::{RetryCount, RetryTime},
register, MacAddress,
};

pub enum ResetError<E> {
SocketsNotReleased,
Expand Down Expand Up @@ -52,11 +55,8 @@ impl<SpiBus: Bus, HostImpl: Host> Device<SpiBus, HostImpl> {
}

fn clear_mode(&mut self) -> Result<(), SpiBus::Error> {
// reset bit
let mode = [0b10000000];
self.bus
.write_frame(register::COMMON, register::common::MODE, &mode)?;
Ok(())
// Set RST common register of the w5500
self.bus.reset()
}

#[inline]
Expand Down Expand Up @@ -89,6 +89,53 @@ impl<SpiBus: Bus, HostImpl: Host> Device<SpiBus, HostImpl> {
self.as_mut().version()
}

/// Get the currently set Retry Time-value Register.
///
/// RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0]
#[inline]
pub fn current_retry_timeout(&mut self) -> Result<RetryTime, SpiBus::Error> {
self.as_mut().current_retry_timeout()
}

/// Set a new value for the Retry Time-value Register.
///
/// RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0]
///
/// # Example
/// ```
/// use w5500::register::common::RetryTime;
///
/// let default = RetryTime::from_millis(200);
/// assert_eq!(RetryTime::default(), default);
///
/// // E.g. 4000 (register) = 400ms
/// let four_hundred_ms = RetryTime::from_millis(400);
/// assert_eq!(four_hundred_ms.to_u16(), 4000);
/// ```
#[inline]
pub fn set_retry_timeout(&mut self, retry_time_value: RetryTime) -> Result<(), SpiBus::Error> {
self.as_mut().set_retry_timeout(retry_time_value)
}

/// Get the current Retry Count Register value.
///
/// RCR (Retry Count Register) [R/W] [0x001B] [0x08]
///
/// E.g. In case of errors it will retry for 7 times:
/// `RCR = 0x0007`
#[inline]
pub fn current_retry_count(&mut self) -> Result<RetryCount, SpiBus::Error> {
self.as_mut().current_retry_count()
}

/// Set a new value for the Retry Count register.
///
/// RCR (Retry Count Register) [R/W] [0x001B] [0x08]
#[inline]
pub fn set_retry_count(&mut self, retry_count: RetryCount) -> Result<(), SpiBus::Error> {
self.as_mut().set_retry_count(retry_count)
}

#[inline]
pub(crate) fn as_mut(&mut self) -> DeviceRefMut<'_, BusRef<'_, SpiBus>, HostImpl> {
DeviceRefMut {
Expand Down Expand Up @@ -187,4 +234,53 @@ impl<SpiBus: Bus, HostImpl: Host> DeviceRefMut<'_, SpiBus, HostImpl> {
.read_frame(register::COMMON, register::common::VERSION, &mut version)?;
Ok(version[0])
}

/// Get the currently set Retry Time-value Register.
///
/// RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0]
///
/// E.g. 4000 = 400ms
#[inline]
pub fn current_retry_timeout(&mut self) -> Result<RetryTime, SpiBus::Error> {
self.bus.current_retry_timeout()
}

/// Set a new value for the Retry Time-value Register.
///
/// RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0]
///
/// # Example
/// ```
/// use w5500::register::common::RetryTime;
///
/// let default = RetryTime::from_millis(200);
/// assert_eq!(RetryTime::default(), default);
///
/// // E.g. 4000 (register) = 400ms
/// let four_hundred_ms = RetryTime::from_millis(400);
/// assert_eq!(four_hundred_ms.to_u16(), 4000);
/// ```
#[inline]
pub fn set_retry_timeout(&mut self, retry_time_value: RetryTime) -> Result<(), SpiBus::Error> {
self.bus.set_retry_timeout(retry_time_value)
}

/// Get the current Retry Count Register value.
///
/// RCR (Retry Count Register) [R/W] [0x001B] [0x08]
///
/// E.g. In case of errors it will retry for 7 times:
/// `RCR = 0x0007`
#[inline]
pub fn current_retry_count(&mut self) -> Result<RetryCount, SpiBus::Error> {
self.bus.current_retry_count()
}

/// Set a new value for the Retry Count register.
///
/// RCR (Retry Count Register) [R/W] [0x001B] [0x08]
#[inline]
pub fn set_retry_count(&mut self, retry_count: RetryCount) -> Result<(), SpiBus::Error> {
self.bus.set_retry_count(retry_count)
}
}
60 changes: 50 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![no_std]
#![cfg_attr(not(test), no_std)]
#![allow(unused)]
#![deny(rustdoc::broken_intra_doc_links)]
#![doc = include_str!("../README.md")]
Expand All @@ -15,50 +15,68 @@ pub mod tcp;
pub mod udp;
mod uninitialized_device;

pub use device::{Device, DeviceRefMut, InactiveDevice};
pub use host::{Dhcp, Host, HostConfig, Manual};
pub use net::MacAddress;
pub use uninitialized_device::{InitializeError, UninitializedDevice};
#[doc(inline)]
pub use self::{
device::{Device, DeviceRefMut, InactiveDevice},
host::{Dhcp, Host, HostConfig, Manual},
net::MacAddress,
uninitialized_device::{InitializeError, UninitializedDevice},
};

use register::common;

// TODO add better docs to all public items, add unit tests.

/// Settings for wake on LAN. Allows the W5500 to optionally emit an interrupt upon receiving a packet
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OnWakeOnLan {
InvokeInterrupt = 0b00100000,
Ignore = 0b00000000,
}

/// Ping Block Mode
///
/// Settings for ping. Allows the W5500 to respond to or ignore network ping requests
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum OnPingRequest {
/// 0: Disable Ping block
Respond = 0b00000000,
/// 1 : Enable Ping block
///
/// If the bit is ‘1’, it blocks the response to a ping request.
Ignore = 0b00010000,
}

/// Use [ConnectionType::PPoE] when talking
/// to an ADSL modem. Otherwise use [ConnectionType::Ethernet]
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ConnectionType {
PPoE = 0b00001000,
Ethernet = 0b00000000,
}

#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
/// Force ARP
///
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum ArpResponses {
/// 0 : Disable Force ARP mode
Cache = 0b00000000,
/// 1 : Enable Force ARP mode
///
/// In Force ARP mode, It forces on sending ARP Request whenever data is
/// sent.
DropAfterUse = 0b00000010,
}

#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Mode {
pub on_wake_on_lan: OnWakeOnLan,
Expand All @@ -67,6 +85,28 @@ pub struct Mode {
pub arp_responses: ArpResponses,
}

impl Mode {
pub fn to_register(self) -> [u8; 1] {
[self.to_u8()]
}

pub fn to_u8(self) -> u8 {
let mut register = 0;
register |= self.on_wake_on_lan as u8;
register |= self.on_ping_request as u8;
register |= self.connection_type as u8;
register |= self.arp_responses as u8;

register
}
}

impl From<Mode> for common::Mode {
fn from(value: Mode) -> Self {
Self::Mode(value)
}
}
ryan-summers marked this conversation as resolved.
Show resolved Hide resolved

impl Default for Mode {
fn default() -> Self {
Self {
Expand Down
Loading