Re-wrote socket implementations to be more compatible with embedded-nal
This commit is contained in:
parent
b1e83e3d05
commit
f546ff2011
17 changed files with 673 additions and 1603 deletions
|
|
@ -13,4 +13,6 @@ edition = "2018"
|
|||
[dependencies]
|
||||
byteorder = { version = "1.3.4", default-features = false }
|
||||
embedded-hal = "0.2.4"
|
||||
embedded-nal = { path = "../embedded-nal" }
|
||||
bit_field = "0.10.1"
|
||||
nb = "0.1.2"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
use core::fmt;
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
|
||||
|
|
@ -34,33 +34,39 @@ pub struct ActiveFourWire<Spi: FullDuplex<u8>, ChipSelect: OutputPin> {
|
|||
|
||||
impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin> ActiveBus for ActiveFourWire<Spi, ChipSelect> {
|
||||
type Error = FourWireError<Spi::Error, ChipSelect::Error>;
|
||||
fn transfer_frame<'a>(
|
||||
&mut self,
|
||||
block: u8,
|
||||
address: u16,
|
||||
is_write: bool,
|
||||
data: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Self::Error> {
|
||||
let mut control_phase = block << 3;
|
||||
if is_write {
|
||||
control_phase |= WRITE_MODE_MASK;
|
||||
}
|
||||
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error> {
|
||||
let address_phase = address.to_be_bytes();
|
||||
let control_phase = block << 3;
|
||||
let data_phase = data;
|
||||
let mut address_phase = [0u8; 2];
|
||||
BigEndian::write_u16(&mut address_phase, address);
|
||||
|
||||
self.cs
|
||||
.set_low()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
Self::transfer_bytes(&mut self.spi, &mut address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, &mut control_phase))
|
||||
.and_then(|_| Self::transfer_bytes(&mut self.spi, data_phase))
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| Self::read_bytes(&mut self.spi, data_phase))
|
||||
.map_err(|e| FourWireError::SpiError(e))?;
|
||||
self.cs
|
||||
.set_high()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
|
||||
Ok(data_phase)
|
||||
Ok(())
|
||||
}
|
||||
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> {
|
||||
let address_phase = address.to_be_bytes();
|
||||
let control_phase = block << 3 | WRITE_MODE_MASK;
|
||||
let data_phase = data;
|
||||
self.cs
|
||||
.set_low()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| Self::write_bytes(&mut self.spi, data_phase))
|
||||
.map_err(|e| FourWireError::SpiError(e))?;
|
||||
self.cs
|
||||
.set_high()
|
||||
.map_err(|e| FourWireError::ChipSelectError(e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl<Spi: FullDuplex<u8>, ChipSelect: OutputPin> ActiveFourWire<Spi, ChipSelect> {
|
||||
|
|
@ -74,3 +80,17 @@ pub enum FourWireError<SpiError, ChipSelectError> {
|
|||
SpiError(SpiError),
|
||||
ChipSelectError(ChipSelectError),
|
||||
}
|
||||
|
||||
impl<SpiError, ChipSelectError> fmt::Debug for FourWireError<SpiError, ChipSelectError> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"FourWireError::{}",
|
||||
match self {
|
||||
Self::SpiError(_) => "SpiError",
|
||||
Self::ChipSelectError(_) => "ChipSelectError",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO impl From and remove map_errs
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use core::fmt::Debug;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
|
||||
mod four_wire;
|
||||
|
|
@ -11,31 +12,27 @@ pub use self::three_wire::ThreeWire;
|
|||
pub trait Bus {}
|
||||
|
||||
pub trait ActiveBus {
|
||||
type Error;
|
||||
type Error: Debug;
|
||||
|
||||
fn transfer_frame<'a>(
|
||||
&mut self,
|
||||
block: u8,
|
||||
address: u16,
|
||||
is_write: bool,
|
||||
data: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Self::Error>;
|
||||
fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error>;
|
||||
|
||||
fn transfer_bytes<'a, Spi: FullDuplex<u8>>(
|
||||
spi: &mut Spi,
|
||||
bytes: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Spi::Error> {
|
||||
fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error>;
|
||||
|
||||
fn read_bytes<Spi: FullDuplex<u8>>(spi: &mut Spi, bytes: &mut [u8]) -> Result<(), Spi::Error> {
|
||||
for byte in bytes.iter_mut() {
|
||||
Self::transfer_byte(spi, byte)?;
|
||||
*byte = Self::transfer_byte(spi, *byte)?;
|
||||
}
|
||||
Ok(bytes)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn transfer_byte<'a, Spi: FullDuplex<u8>>(
|
||||
spi: &mut Spi,
|
||||
byte: &'a mut u8,
|
||||
) -> Result<&'a mut u8, Spi::Error> {
|
||||
*byte = block!(spi.send(*byte)).and_then(|_| block!(spi.read()))?;
|
||||
Ok(byte)
|
||||
fn write_bytes<Spi: FullDuplex<u8>>(spi: &mut Spi, bytes: &[u8]) -> Result<(), Spi::Error> {
|
||||
for byte in bytes.iter() {
|
||||
Self::transfer_byte(spi, *byte)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn transfer_byte<Spi: FullDuplex<u8>>(spi: &mut Spi, byte: u8) -> Result<u8, Spi::Error> {
|
||||
block!(spi.send(byte)).and_then(|_| block!(spi.read()))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
use core::fmt;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
|
||||
use crate::bus::{ActiveBus, Bus};
|
||||
|
|
@ -30,7 +30,7 @@ pub struct ActiveThreeWire<Spi: FullDuplex<u8>> {
|
|||
}
|
||||
|
||||
impl<Spi: FullDuplex<u8>> ActiveBus for ActiveThreeWire<Spi> {
|
||||
type Error = Spi::Error;
|
||||
type Error = ThreeWireError<Spi::Error>;
|
||||
|
||||
/// Transfers a frame with an arbitrary data length in FDM
|
||||
///
|
||||
|
|
@ -43,17 +43,13 @@ impl<Spi: FullDuplex<u8>> ActiveBus for ActiveThreeWire<Spi> {
|
|||
/// (address 23) 0xF0 0xAB 0x83 0xB2
|
||||
/// (address 27) 44 2C
|
||||
/// (address 29) AA
|
||||
fn transfer_frame<'a>(
|
||||
fn read_frame(
|
||||
&mut self,
|
||||
block: u8,
|
||||
mut address: u16,
|
||||
is_write: bool,
|
||||
data: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], Self::Error> {
|
||||
data: &mut [u8],
|
||||
) -> Result<(), Self::Error> {
|
||||
let mut control_phase = block << 3;
|
||||
if is_write {
|
||||
control_phase |= WRITE_MODE_MASK;
|
||||
}
|
||||
|
||||
let mut data_phase = &mut data[..];
|
||||
let mut last_length_written: u16;
|
||||
|
|
@ -69,19 +65,51 @@ impl<Spi: FullDuplex<u8>> ActiveBus for ActiveThreeWire<Spi> {
|
|||
last_length_written = 1;
|
||||
}
|
||||
|
||||
let mut address_phase = [0u8; 2];
|
||||
BigEndian::write_u16(&mut address_phase, address);
|
||||
Self::transfer_bytes(&mut self.spi, &mut address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, &mut control_phase))
|
||||
.and_then(|_| Self::transfer_bytes(
|
||||
let address_phase = address.to_be_bytes();
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| {
|
||||
Self::read_bytes(
|
||||
&mut self.spi,
|
||||
&mut data_phase[..last_length_written as usize]
|
||||
))?;
|
||||
&mut data_phase[..last_length_written as usize],
|
||||
)
|
||||
})
|
||||
.map_err(|e| ThreeWireError::SpiError(e))?;
|
||||
|
||||
address += last_length_written;
|
||||
data_phase = &mut data_phase[last_length_written as usize..];
|
||||
}
|
||||
Ok(data_phase)
|
||||
Ok(())
|
||||
}
|
||||
fn write_frame(&mut self, block: u8, mut address: u16, data: &[u8]) -> Result<(), Self::Error> {
|
||||
let mut control_phase = block << 3 | WRITE_MODE_MASK;
|
||||
|
||||
let mut data_phase = &data[..];
|
||||
let mut last_length_written: u16;
|
||||
while data_phase.len() > 0 {
|
||||
if data_phase.len() >= 4 {
|
||||
control_phase |= FIXED_DATA_LENGTH_MODE_4;
|
||||
last_length_written = 4;
|
||||
} else if data_phase.len() >= 2 {
|
||||
control_phase |= FIXED_DATA_LENGTH_MODE_2;
|
||||
last_length_written = 2;
|
||||
} else {
|
||||
control_phase |= FIXED_DATA_LENGTH_MODE_1;
|
||||
last_length_written = 1;
|
||||
}
|
||||
|
||||
let address_phase = address.to_be_bytes();
|
||||
Self::write_bytes(&mut self.spi, &address_phase)
|
||||
.and_then(|_| Self::transfer_byte(&mut self.spi, control_phase))
|
||||
.and_then(|_| {
|
||||
Self::write_bytes(&mut self.spi, &data_phase[..last_length_written as usize])
|
||||
})
|
||||
.map_err(|e| ThreeWireError::SpiError(e))?;
|
||||
|
||||
address += last_length_written;
|
||||
data_phase = &data_phase[last_length_written as usize..];
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,3 +118,19 @@ impl<Spi: FullDuplex<u8>> ActiveThreeWire<Spi> {
|
|||
(ThreeWire::new(), self.spi)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ThreeWireError<SpiError> {
|
||||
SpiError(SpiError),
|
||||
}
|
||||
impl<SpiError> fmt::Debug for ThreeWireError<SpiError> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"ThreeWireError::{}",
|
||||
match self {
|
||||
Self::SpiError(_) => "SpiError",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO impl From and remove map_errs
|
||||
|
|
|
|||
875
src/lib.rs
875
src/lib.rs
|
|
@ -2,52 +2,14 @@
|
|||
// #![allow(unused)]
|
||||
#![deny(broken_intra_doc_links)]
|
||||
|
||||
extern crate bit_field;
|
||||
extern crate byteorder;
|
||||
extern crate embedded_hal;
|
||||
extern crate embedded_nal;
|
||||
|
||||
#[macro_use(block)]
|
||||
extern crate nb;
|
||||
|
||||
// use hal::digital::v2::OutputPin;
|
||||
// use hal::spi::FullDuplex;
|
||||
|
||||
// use byteorder::BigEndian;
|
||||
// use byteorder::ByteOrder;
|
||||
|
||||
// const COMMAND_READ: u8 = 0x00 << 2;
|
||||
// const COMMAND_WRITE: u8 = 0x01 << 2;
|
||||
|
||||
// const VARIABLE_DATA_LENGTH: u8 = 0b_00;
|
||||
// const FIXED_DATA_LENGTH_1_BYTE: u8 = 0b_01;
|
||||
// const FIXED_DATA_LENGTH_2_BYTES: u8 = 0b_10;
|
||||
// const FIXED_DATA_LENGTH_4_BYTES: u8 = 0b_11;
|
||||
|
||||
/// IP Address struct. Represents an IP address as a u8 array of length 4. Can be instantiated with `IpAddress::new`
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq, Default, Debug)]
|
||||
pub struct IpAddress {
|
||||
pub address: [u8; 4],
|
||||
}
|
||||
|
||||
impl IpAddress {
|
||||
/// Instantiate a new IP address with u8s for each address fragment
|
||||
pub fn new(a0: u8, a1: u8, a2: u8, a3: u8) -> IpAddress {
|
||||
IpAddress {
|
||||
address: [a0, a1, a2, a3],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::core::fmt::Display for IpAddress {
|
||||
/// String formatter for IP addresses, useful for debugging output
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}.{}.{}.{}",
|
||||
self.address[0], self.address[1], self.address[2], self.address[3],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// MAC address struct. Represents a MAC address as a u8 array of length 6. Can be instantiated with `MacAddress::new`
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq, Default, Debug)]
|
||||
pub struct MacAddress {
|
||||
|
|
@ -55,54 +17,11 @@ pub struct MacAddress {
|
|||
}
|
||||
|
||||
impl MacAddress {
|
||||
/// Instantiate a new MAC address with u8s for each address fragment
|
||||
pub fn new(a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8) -> MacAddress {
|
||||
MacAddress {
|
||||
address: [a0, a1, a2, a3, a4, a5],
|
||||
}
|
||||
pub fn new(n0: u8, n1: u8, n2: u8, n3: u8, n4: u8, n5: u8) -> Self {
|
||||
MacAddress { address: [n0, n1, n2, n3, n4, n5] }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::core::fmt::Display for MacAddress {
|
||||
/// String formatter for MAC addresses, useful for debugging output
|
||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
|
||||
self.address[0],
|
||||
self.address[1],
|
||||
self.address[2],
|
||||
self.address[3],
|
||||
self.address[4],
|
||||
self.address[5],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// /// Error enum that represents the union between SPI hardware errors and digital IO pin errors. Returned as an Error
|
||||
// /// type by many W5500 that talk to the chip
|
||||
// #[derive(Copy, Clone, Debug)]
|
||||
// pub enum TransferError<SpiError, ChipSelectError> {
|
||||
// SpiError(SpiError),
|
||||
// ChipSelectError(ChipSelectError),
|
||||
// }
|
||||
|
||||
// if let OnWakeOnLan::InvokeInterrupt = settings.on_wake_on_lan {
|
||||
// value |= 1 << 5;
|
||||
// }
|
||||
|
||||
// if let OnPingRequest::Ignore = settings.on_ping_request {
|
||||
// value |= 1 << 4;
|
||||
// }
|
||||
|
||||
// if let ConnectionType::PPoE = settings.connection_type {
|
||||
// value |= 1 << 3;
|
||||
// }
|
||||
|
||||
// if let ArpResponses::DropAfterUse = settings.arp_responses {
|
||||
// value |= 1 << 1;
|
||||
// }
|
||||
|
||||
/// Settings for wake on LAN. Allows the W5500 to optionally emit an interrupt upon receiving a packet
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, PartialOrd, PartialEq)]
|
||||
|
|
@ -154,792 +73,6 @@ impl Default for Mode {
|
|||
}
|
||||
}
|
||||
|
||||
// /// Represents a socket that has not yet been initialized for a particular protocol
|
||||
// pub struct UninitializedSocket {
|
||||
// socket: Socket
|
||||
// }
|
||||
|
||||
// /// Represents a socket that has been initialized to use the UDP protocol
|
||||
// pub struct UdpSocket {
|
||||
// socket: Socket,
|
||||
// active_w5500: ActiveW5500,
|
||||
// }
|
||||
|
||||
// impl UdpSocket {
|
||||
// pub uninitialize() -> Result<(UninitializedSocket, ActiveW5500)
|
||||
// }
|
||||
|
||||
// /// The first level of instantiating communication with the W5500. It can not communicate by itself, but calling
|
||||
// /// `activate` will return an `ActiveW5500` which can.
|
||||
// pub struct W5500<'a, ChipSelect: OutputPin> {
|
||||
// chip_select: &'a mut ChipSelect,
|
||||
// sockets: u8, // each bit represents whether the corresponding socket is available for take
|
||||
// }
|
||||
|
||||
// impl<'b, 'a: 'b, ChipSelectError, ChipSelect: OutputPin<Error = ChipSelectError>>
|
||||
// W5500<'a, ChipSelect>
|
||||
// {
|
||||
// fn new(chip_select: &'a mut ChipSelect) -> Self {
|
||||
// W5500 {
|
||||
// chip_select,
|
||||
// sockets: 0xFF,
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Primary method for instantiating. Briefly activates the W5500, and sets it up with the specified configuration
|
||||
// pub fn with_initialisation<'c, Spi: FullDuplex<u8>>(
|
||||
// chip_select: &'a mut ChipSelect,
|
||||
// spi: &'c mut Spi,
|
||||
// wol: OnWakeOnLan,
|
||||
// ping: OnPingRequest,
|
||||
// mode: ConnectionType,
|
||||
// arp: ArpResponses,
|
||||
// ) -> Result<Self, TransferError<Spi::Error, ChipSelectError>> {
|
||||
// let mut w5500 = Self::new(chip_select);
|
||||
// {
|
||||
// let mut w5500_active = w5500.activate(spi)?;
|
||||
// unsafe {
|
||||
// w5500_active.reset()?;
|
||||
// }
|
||||
// w5500_active.update_operation_mode(wol, ping, mode, arp)?;
|
||||
// }
|
||||
// Ok(w5500)
|
||||
// }
|
||||
|
||||
// /// Returns the requested socket if it is not already used.
|
||||
// pub fn take_socket(&mut self, socket: Socket) -> Option<UninitializedSocket> {
|
||||
// let mask = (0x01 << socket.number());
|
||||
// if self.sockets & mask == mask {
|
||||
// self.sockets &= !mask;
|
||||
// Some(UninitializedSocket(socket))
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Creates a new `ActiveW5500` with the provided `FullDuplex` implementation
|
||||
// pub fn activate<'c, Spi: FullDuplex<u8>>(
|
||||
// &'b mut self,
|
||||
// spi: &'c mut Spi,
|
||||
// ) -> Result<ActiveW5500<'b, 'a, 'c, ChipSelect, Spi>, TransferError<Spi::Error, ChipSelectError>>
|
||||
// {
|
||||
// Ok(ActiveW5500(self, spi))
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Struct that can communicate with the W5500 chip, configuring it and reading/writing to the registers on a low level
|
||||
// pub struct ActiveW5500<'a, 'b: 'a, 'c, ChipSelect: OutputPin, Spi: FullDuplex<u8>>(
|
||||
// &'a mut W5500<'b, ChipSelect>,
|
||||
// &'c mut Spi,
|
||||
// );
|
||||
|
||||
// impl<
|
||||
// ChipSelectError,
|
||||
// ChipSelect: OutputPin<Error = ChipSelectError>,
|
||||
// SpiError,
|
||||
// Spi: FullDuplex<u8, Error = SpiError>,
|
||||
// > ActiveW5500<'_, '_, '_, ChipSelect, Spi>
|
||||
// {
|
||||
// /// Returns the requested socket if it is not already used
|
||||
// pub fn take_socket(&mut self, socket: Socket) -> Option<UninitializedSocket> {
|
||||
// self.0.take_socket(socket)
|
||||
// }
|
||||
|
||||
// /// Yields an uninitialized socket back to the pool
|
||||
// pub fn release_socket(&mut self, socket: UninitializedSocket) -> () {
|
||||
// self.0.reset_interrupt(socket.0, Interrupt::SendOk)?;
|
||||
// self.0.write_u16(socket.at(SocketRegister::LocalPort), 0)?;
|
||||
// self.0.write_to(
|
||||
// socket.at(SocketRegister::Mode),
|
||||
// &[
|
||||
// Protocol::UDP as u8, // Socket Mode Register
|
||||
// SocketCommand::Open as u8, // Socket Command Register
|
||||
// ],
|
||||
// )?;
|
||||
// let mask = (0x01 << socket.number());
|
||||
// this.sockets |= mask;
|
||||
// }
|
||||
|
||||
// /// Set up basic configuration of the W5500 chip
|
||||
// pub fn update_operation_mode(
|
||||
// &mut self,
|
||||
// wol: OnWakeOnLan,
|
||||
// ping: OnPingRequest,
|
||||
// mode: ConnectionType,
|
||||
// arp: ArpResponses,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// let mut value = 0x00;
|
||||
|
||||
// if let OnWakeOnLan::InvokeInterrupt = wol {
|
||||
// value |= (1 << 5);
|
||||
// }
|
||||
|
||||
// if let OnPingRequest::Ignore = ping {
|
||||
// value |= (1 << 4);
|
||||
// }
|
||||
|
||||
// if let ConnectionType::PPoE = mode {
|
||||
// value |= (1 << 3);
|
||||
// }
|
||||
|
||||
// if let ArpResponses::DropAfterUse = arp {
|
||||
// value |= (1 << 1);
|
||||
// }
|
||||
|
||||
// self.write_to(Register::CommonRegister(0x00_00_u16), &[value])
|
||||
// }
|
||||
|
||||
// /// Sets the IP address of the network gateway (router)
|
||||
// pub fn set_gateway(
|
||||
// &mut self,
|
||||
// gateway: IpAddress,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.write_to(Register::CommonRegister(0x00_01_u16), &gateway.address)
|
||||
// }
|
||||
|
||||
// /// Sets the subnet on the network
|
||||
// pub fn set_subnet(
|
||||
// &mut self,
|
||||
// subnet: IpAddress,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.write_to(Register::CommonRegister(0x00_05_u16), &subnet.address)
|
||||
// }
|
||||
|
||||
// /// Sets the MAC address of the W5500 device on the network
|
||||
// pub fn set_mac(
|
||||
// &mut self,
|
||||
// mac: MacAddress,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.write_to(Register::CommonRegister(0x00_09_u16), &mac.address)
|
||||
// }
|
||||
|
||||
// /// Sets the IP address of the W5500 device on network. Must be within the range permitted by the gateway
|
||||
// pub fn set_ip(
|
||||
// &mut self,
|
||||
// ip: IpAddress,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.write_to(Register::CommonRegister(0x00_0F_u16), &ip.address)
|
||||
// }
|
||||
|
||||
// /// Reads 4 bytesfrom any register location and returns the value as an IP address
|
||||
// pub fn read_ip(
|
||||
// &mut self,
|
||||
// register: Register,
|
||||
// ) -> Result<IpAddress, TransferError<SpiError, ChipSelectError>> {
|
||||
// let mut ip = IpAddress::default();
|
||||
// self.read_from(register, &mut ip.address)?;
|
||||
// Ok(ip)
|
||||
// }
|
||||
|
||||
// /// This is unsafe because it cannot set taken sockets back to be uninitialized
|
||||
// /// It assumes, none of the old sockets will used anymore. Otherwise that socket
|
||||
// /// will have undefined behavior.
|
||||
// pub unsafe fn reset(&mut self) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.write_to(
|
||||
// Register::CommonRegister(0x00_00_u16),
|
||||
// &[
|
||||
// 0b1000_0000, // Mode Register (force reset)
|
||||
// ],
|
||||
// )?;
|
||||
// self.0.sockets = 0xFF;
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// /// TODO document
|
||||
// fn is_interrupt_set(
|
||||
// &mut self,
|
||||
// socket: Socket,
|
||||
// interrupt: Interrupt,
|
||||
// ) -> Result<bool, TransferError<SpiError, ChipSelectError>> {
|
||||
// let mut state = [0u8; 1];
|
||||
// self.read_from(socket.at(SocketRegister::Interrupt), &mut state)?;
|
||||
// Ok(state[0] & interrupt as u8 != 0)
|
||||
// }
|
||||
|
||||
// /// TODO document
|
||||
// pub fn reset_interrupt(
|
||||
// &mut self,
|
||||
// socket: Socket,
|
||||
// interrupt: Interrupt,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.write_to(socket.at(SocketRegister::Interrupt), &[interrupt as u8])
|
||||
// }
|
||||
|
||||
// /// Reads one byte from any register address as a u8
|
||||
// fn read_u8(
|
||||
// &mut self,
|
||||
// register: Register,
|
||||
// ) -> Result<u8, TransferError<SpiError, ChipSelectError>> {
|
||||
// let mut buffer = [0u8; 1];
|
||||
// self.read_from(register, &mut buffer)?;
|
||||
// Ok(buffer[0])
|
||||
// }
|
||||
|
||||
// /// Reads two bytes from any register address and returns as a u16
|
||||
// fn read_u16(
|
||||
// &mut self,
|
||||
// register: Register,
|
||||
// ) -> Result<u16, TransferError<SpiError, ChipSelectError>> {
|
||||
// let mut buffer = [0u8; 2];
|
||||
// self.read_from(register, &mut buffer)?;
|
||||
// Ok(BigEndian::read_u16(&buffer))
|
||||
// }
|
||||
|
||||
// /// Reads enough bytes from any register address to fill the `target` u8 slice
|
||||
// fn read_from(
|
||||
// &mut self,
|
||||
// register: Register,
|
||||
// target: &mut [u8],
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.chip_select()
|
||||
// .map_err(|error| -> TransferError<SpiError, ChipSelectError> {
|
||||
// TransferError::ChipSelectError(error)
|
||||
// })?;
|
||||
// let mut request = [
|
||||
// 0_u8,
|
||||
// 0_u8,
|
||||
// register.control_byte() | COMMAND_READ | VARIABLE_DATA_LENGTH,
|
||||
// ];
|
||||
// BigEndian::write_u16(&mut request[..2], register.address());
|
||||
// let result = self
|
||||
// .write_bytes(&request)
|
||||
// .and_then(|_| self.read_bytes(target));
|
||||
// self.chip_deselect()
|
||||
// .map_err(|error| -> TransferError<SpiError, ChipSelectError> {
|
||||
// TransferError::ChipSelectError(error)
|
||||
// })?;
|
||||
// result.map_err(|error| TransferError::SpiError(error))
|
||||
// }
|
||||
|
||||
// /// Reads enough bytes over SPI to fill the `target` u8 slice
|
||||
// fn read_bytes(&mut self, bytes: &mut [u8]) -> Result<(), SpiError> {
|
||||
// for byte in bytes {
|
||||
// *byte = self.read()?;
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// /// Reads a single byte over SPI by writing a zero and reading the response
|
||||
// fn read(&mut self) -> Result<u8, SpiError> {
|
||||
// block!(self.1.send(0x00))?;
|
||||
// block!(self.1.read())
|
||||
// }
|
||||
|
||||
// /// Write a single u8 byte to any register address
|
||||
// fn write_u8(
|
||||
// &mut self,
|
||||
// register: Register,
|
||||
// value: u8,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.write_to(register, &[value])
|
||||
// }
|
||||
|
||||
// /// Write a u16 as two bytes o any register address
|
||||
// fn write_u16(
|
||||
// &mut self,
|
||||
// register: Register,
|
||||
// value: u16,
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// let mut data = [0u8; 2];
|
||||
// BigEndian::write_u16(&mut data, value);
|
||||
// self.write_to(register, &data)
|
||||
// }
|
||||
|
||||
// /// Write a slice of u8 bytes to any register address
|
||||
// fn write_to(
|
||||
// &mut self,
|
||||
// register: Register,
|
||||
// data: &[u8],
|
||||
// ) -> Result<(), TransferError<SpiError, ChipSelectError>> {
|
||||
// self.chip_select()
|
||||
// .map_err(|error| -> TransferError<SpiError, ChipSelectError> {
|
||||
// TransferError::ChipSelectError(error)
|
||||
// })?;
|
||||
// let mut request = [
|
||||
// 0_u8,
|
||||
// 0_u8,
|
||||
// register.control_byte() | COMMAND_WRITE | VARIABLE_DATA_LENGTH,
|
||||
// ];
|
||||
// BigEndian::write_u16(&mut request[..2], register.address());
|
||||
// let result = self
|
||||
// .write_bytes(&request)
|
||||
// .and_then(|_| self.write_bytes(data));
|
||||
// self.chip_deselect()
|
||||
// .map_err(|error| -> TransferError<SpiError, ChipSelectError> {
|
||||
// TransferError::ChipSelectError(error)
|
||||
// })?;
|
||||
// result.map_err(|error| TransferError::SpiError(error))
|
||||
// }
|
||||
|
||||
// /// Write a slice of u8 bytes over SPI
|
||||
// fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SpiError> {
|
||||
// for b in bytes {
|
||||
// self.write(*b)?;
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// /// Write a single byte over SPI
|
||||
// fn write(&mut self, byte: u8) -> Result<(), SpiError> {
|
||||
// block!(self.1.send(byte))?;
|
||||
// block!(self.1.read())?;
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// /// Begin a SPI frame by setting the CS signal to low
|
||||
// fn chip_select(&mut self) -> Result<(), ChipSelectError> {
|
||||
// self.0.chip_select.set_low()
|
||||
// }
|
||||
|
||||
// /// End a SPI frame by setting the CS signal to high
|
||||
// fn chip_deselect(&mut self) -> Result<(), ChipSelectError> {
|
||||
// self.0.chip_select.set_high()
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub trait IntoUdpSocket<SpiError> {
|
||||
// fn try_into_udp_server_socket(self, port: u16) -> Result<UdpSocket, SpiError>
|
||||
// where
|
||||
// Self: Sized;
|
||||
// }
|
||||
|
||||
// impl<ChipSelect: OutputPin, Spi: FullDuplex<u8>> IntoUdpSocket<UninitializedSocket>
|
||||
// for (
|
||||
// &mut ActiveW5500<'_, '_, '_, ChipSelect, Spi>,
|
||||
// UninitializedSocket,
|
||||
// )
|
||||
// {
|
||||
// /// Initialize a socket to operate in UDP mode
|
||||
// fn try_into_udp_server_socket(self, port: u16) -> Result<UdpSocket, UninitializedSocket> {
|
||||
// let socket = (self.1).0;
|
||||
// (|| {
|
||||
// self.0.reset_interrupt(socket, Interrupt::SendOk)?;
|
||||
|
||||
// self.0
|
||||
// .write_u16(socket.at(SocketRegister::LocalPort), port)?;
|
||||
// self.0.write_to(
|
||||
// socket.at(SocketRegister::Mode),
|
||||
// &[
|
||||
// Protocol::UDP as u8, // Socket Mode Register
|
||||
// SocketCommand::Open as u8, // Socket Command Register
|
||||
// ],
|
||||
// )?;
|
||||
// Ok(UdpSocket(socket))
|
||||
// })()
|
||||
// .map_err(|_: TransferError<Spi::Error, ChipSelect::Error>| UninitializedSocket(socket))
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// UDP trait that can send and receive UDP packets
|
||||
// pub trait Udp {
|
||||
// type Error;
|
||||
|
||||
// fn receive(
|
||||
// &mut self,
|
||||
// target_buffer: &mut [u8],
|
||||
// ) -> Result<Option<(IpAddress, u16, usize)>, Self::Error>;
|
||||
|
||||
// fn blocking_send(
|
||||
// &mut self,
|
||||
// host: &IpAddress,
|
||||
// host_port: u16,
|
||||
// data: &[u8],
|
||||
// ) -> Result<(), Self::Error>;
|
||||
// }
|
||||
|
||||
// impl<ChipSelect: OutputPin, Spi: FullDuplex<u8>> Udp
|
||||
// for (&mut ActiveW5500<'_, '_, '_, ChipSelect, Spi>, &UdpSocket)
|
||||
// {
|
||||
// type Error = TransferError<Spi::Error, ChipSelect::Error>;
|
||||
|
||||
// /// Returns a UDP packet if one is available. Will return `None` if no UDP packets are in the socket's buffer
|
||||
// fn receive(
|
||||
// &mut self,
|
||||
// destination: &mut [u8],
|
||||
// ) -> Result<Option<(IpAddress, u16, usize)>, Self::Error> {
|
||||
// let (w5500, UdpSocket(socket)) = self;
|
||||
|
||||
// if w5500.read_u8(socket.at(SocketRegister::InterruptMask))? & 0x04 == 0 {
|
||||
// return Ok(None);
|
||||
// }
|
||||
|
||||
// let receive_size = loop {
|
||||
// let s0 = w5500.read_u16(socket.at(SocketRegister::RxReceivedSize))?;
|
||||
// let s1 = w5500.read_u16(socket.at(SocketRegister::RxReceivedSize))?;
|
||||
// if s0 == s1 {
|
||||
// break s0 as usize;
|
||||
// }
|
||||
// };
|
||||
// if receive_size >= 8 {
|
||||
// let read_pointer = w5500.read_u16(socket.at(SocketRegister::RxReadPointer))?;
|
||||
|
||||
// // |<-- read_pointer read_pointer + received_size -->|
|
||||
// // |Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... |
|
||||
// // | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... |
|
||||
|
||||
// let ip = w5500.read_ip(socket.rx_register_at(read_pointer))?;
|
||||
// let port = w5500.read_u16(socket.rx_register_at(read_pointer + 4))?;
|
||||
// let data_length = destination
|
||||
// .len()
|
||||
// .min(w5500.read_u16(socket.rx_register_at(read_pointer + 6))? as usize);
|
||||
|
||||
// w5500.read_from(
|
||||
// socket.rx_register_at(read_pointer + 8),
|
||||
// &mut destination[..data_length],
|
||||
// )?;
|
||||
|
||||
// // reset
|
||||
// w5500.write_u16(
|
||||
// socket.at(SocketRegister::RxReadPointer),
|
||||
// read_pointer + receive_size as u16,
|
||||
// )?;
|
||||
// w5500.write_u8(
|
||||
// socket.at(SocketRegister::Command),
|
||||
// SocketCommand::Recv as u8,
|
||||
// )?;
|
||||
|
||||
// Ok(Some((ip, port, data_length)))
|
||||
// } else {
|
||||
// Ok(None)
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Sends a UDP packet to the specified IP and port, and blocks until it is sent
|
||||
// fn blocking_send(
|
||||
// &mut self,
|
||||
// host: &IpAddress,
|
||||
// host_port: u16,
|
||||
// data: &[u8],
|
||||
// ) -> Result<(), Self::Error> {
|
||||
// let (w5500, UdpSocket(socket)) = self;
|
||||
|
||||
// {
|
||||
// let local_port = w5500.read_u16(socket.at(SocketRegister::LocalPort))?;
|
||||
// let local_port = local_port.to_be_bytes();
|
||||
// let host_port = host_port.to_be_bytes();
|
||||
|
||||
// w5500.write_to(
|
||||
// socket.at(SocketRegister::LocalPort),
|
||||
// &[
|
||||
// local_port[0],
|
||||
// local_port[1], // local port u16
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00,
|
||||
// 0x00, // destination mac
|
||||
// host.address[0],
|
||||
// host.address[1],
|
||||
// host.address[2],
|
||||
// host.address[3], // target IP
|
||||
// host_port[0],
|
||||
// host_port[1], // destination port (5354)
|
||||
// ],
|
||||
// )?;
|
||||
// }
|
||||
|
||||
// let data_length = data.len() as u16;
|
||||
// {
|
||||
// let data_length = data_length.to_be_bytes();
|
||||
|
||||
// // TODO why write [0x00, 0x00] at TxReadPointer at all?
|
||||
// // TODO Is TxWritePointer not sufficient enough?
|
||||
// w5500.write_to(
|
||||
// socket.at(SocketRegister::TxReadPointer),
|
||||
// &[0x00, 0x00, data_length[0], data_length[1]],
|
||||
// );
|
||||
// }
|
||||
|
||||
// w5500.write_to(
|
||||
// socket.tx_register_at(0x00_00),
|
||||
// &data[..data_length as usize],
|
||||
// )?;
|
||||
|
||||
// w5500.write_to(
|
||||
// socket.at(SocketRegister::Command),
|
||||
// &[SocketCommand::Send as u8],
|
||||
// )?;
|
||||
|
||||
// for _ in 0..0xFFFF {
|
||||
// // wait until sent
|
||||
// if w5500.is_interrupt_set(*socket, Interrupt::SendOk)? {
|
||||
// w5500.reset_interrupt(*socket, Interrupt::SendOk)?;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// // restore listen state
|
||||
// w5500.write_to(
|
||||
// socket.at(SocketRegister::Mode),
|
||||
// &[
|
||||
// Protocol::UDP as u8, // Socket Mode Register
|
||||
// SocketCommand::Open as u8, // Socket Command Register
|
||||
// ],
|
||||
// )?;
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Offset addresses in each socket register
|
||||
// #[repr(u8)]
|
||||
// #[derive(Copy, Clone, PartialEq, Debug)]
|
||||
// pub enum SocketRegister {
|
||||
// Mode = 0x0000,
|
||||
// Command = 0x0001,
|
||||
// Interrupt = 0x0002,
|
||||
// Status = 0x0003,
|
||||
// LocalPort = 0x0004,
|
||||
// DestinationMac = 0x0006,
|
||||
// DestinationIp = 0x000C,
|
||||
// DestinationPort = 0x0010,
|
||||
// MaxSegmentSize = 0x0012,
|
||||
// // Reserved 0x0014
|
||||
// TypeOfService = 0x0015,
|
||||
// TimeToLive = 0x0016,
|
||||
// // Reserved 0x0017 - 0x001D
|
||||
// ReceiveBuffer = 0x001E,
|
||||
// TransmitBuffer = 0x001F,
|
||||
// TxFreeSize = 0x0020,
|
||||
// TxReadPointer = 0x0022,
|
||||
// TxWritePointer = 0x0024,
|
||||
// RxReceivedSize = 0x0026,
|
||||
// RxReadPointer = 0x0028,
|
||||
// RxWritePointer = 0x002A,
|
||||
// InterruptMask = 0x002C,
|
||||
// FragmentOffset = 0x002D,
|
||||
// KeepAliveTimer = 0x002F,
|
||||
// // Reserved 0x0030 - 0xFFFF
|
||||
// }
|
||||
|
||||
// /// Interrupt state bits
|
||||
// #[repr(u8)]
|
||||
// #[derive(Copy, Clone, PartialEq, Debug)]
|
||||
// pub enum Interrupt {
|
||||
// SendOk = 1 << 4,
|
||||
// Timeout = 1 << 3,
|
||||
// Received = 1 << 2,
|
||||
// Disconnected = 1 << 1,
|
||||
// Connected = 1, // 1 << 0
|
||||
// }
|
||||
|
||||
// /// Register protocol mode bits
|
||||
// #[repr(u8)]
|
||||
// #[derive(Copy, Clone, PartialEq, Debug)]
|
||||
// pub enum Protocol {
|
||||
// TCP = 0b0001,
|
||||
// UDP = 0b0010,
|
||||
// MACRAW = 0b0100,
|
||||
// }
|
||||
|
||||
// /// Bits for socket commands
|
||||
// #[repr(u8)]
|
||||
// #[derive(Copy, Clone, PartialEq, Debug)]
|
||||
// pub enum SocketCommand {
|
||||
// Open = 0x01,
|
||||
// Listen = 0x02,
|
||||
// Connect = 0x04,
|
||||
// Disconnect = 0x08,
|
||||
// Close = 0x10,
|
||||
// Send = 0x20,
|
||||
// SendMac = 0x21,
|
||||
// SendKeep = 0x22,
|
||||
// Recv = 0x40,
|
||||
// }
|
||||
|
||||
// /// Identifiers for each socket on the W5500
|
||||
// #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
|
||||
// pub enum Socket {
|
||||
// Socket0,
|
||||
// Socket1,
|
||||
// Socket2,
|
||||
// Socket3,
|
||||
// Socket4,
|
||||
// Socket5,
|
||||
// Socket6,
|
||||
// Socket7,
|
||||
// }
|
||||
|
||||
// impl Socket {
|
||||
// /// Gets the number of any given socket
|
||||
// pub fn number(self) -> usize {
|
||||
// match self {
|
||||
// Socket::Socket0 => 0,
|
||||
// Socket::Socket1 => 1,
|
||||
// Socket::Socket2 => 2,
|
||||
// Socket::Socket3 => 3,
|
||||
// Socket::Socket4 => 4,
|
||||
// Socket::Socket5 => 5,
|
||||
// Socket::Socket6 => 6,
|
||||
// Socket::Socket7 => 7,
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Returns the register address for a socket instance's TX
|
||||
// fn tx_register_at(self, address: u16) -> Register {
|
||||
// match self {
|
||||
// Socket::Socket0 => Register::Socket0TxBuffer(address),
|
||||
// Socket::Socket1 => Register::Socket1TxBuffer(address),
|
||||
// Socket::Socket2 => Register::Socket2TxBuffer(address),
|
||||
// Socket::Socket3 => Register::Socket3TxBuffer(address),
|
||||
// Socket::Socket4 => Register::Socket4TxBuffer(address),
|
||||
// Socket::Socket5 => Register::Socket5TxBuffer(address),
|
||||
// Socket::Socket6 => Register::Socket6TxBuffer(address),
|
||||
// Socket::Socket7 => Register::Socket7TxBuffer(address),
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Returns the register address for a socket instance's RX
|
||||
// fn rx_register_at(self, address: u16) -> Register {
|
||||
// match self {
|
||||
// Socket::Socket0 => Register::Socket0RxBuffer(address),
|
||||
// Socket::Socket1 => Register::Socket1RxBuffer(address),
|
||||
// Socket::Socket2 => Register::Socket2RxBuffer(address),
|
||||
// Socket::Socket3 => Register::Socket3RxBuffer(address),
|
||||
// Socket::Socket4 => Register::Socket4RxBuffer(address),
|
||||
// Socket::Socket5 => Register::Socket5RxBuffer(address),
|
||||
// Socket::Socket6 => Register::Socket6RxBuffer(address),
|
||||
// Socket::Socket7 => Register::Socket7RxBuffer(address),
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Returns the register address for a socket instance's register
|
||||
// fn register_at(self, address: u16) -> Register {
|
||||
// match self {
|
||||
// Socket::Socket0 => Register::Socket0Register(address),
|
||||
// Socket::Socket1 => Register::Socket1Register(address),
|
||||
// Socket::Socket2 => Register::Socket2Register(address),
|
||||
// Socket::Socket3 => Register::Socket3Register(address),
|
||||
// Socket::Socket4 => Register::Socket4Register(address),
|
||||
// Socket::Socket5 => Register::Socket5Register(address),
|
||||
// Socket::Socket6 => Register::Socket6Register(address),
|
||||
// Socket::Socket7 => Register::Socket7Register(address),
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn at(self, register: SocketRegister) -> Register {
|
||||
// self.register_at(register as u16)
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Chip register names
|
||||
// #[derive(Copy, Clone, PartialEq, Debug)]
|
||||
// pub enum Register {
|
||||
// CommonRegister(u16),
|
||||
|
||||
// Socket0Register(u16),
|
||||
// Socket0TxBuffer(u16),
|
||||
// Socket0RxBuffer(u16),
|
||||
|
||||
// Socket1Register(u16),
|
||||
// Socket1TxBuffer(u16),
|
||||
// Socket1RxBuffer(u16),
|
||||
|
||||
// Socket2Register(u16),
|
||||
// Socket2TxBuffer(u16),
|
||||
// Socket2RxBuffer(u16),
|
||||
|
||||
// Socket3Register(u16),
|
||||
// Socket3TxBuffer(u16),
|
||||
// Socket3RxBuffer(u16),
|
||||
|
||||
// Socket4Register(u16),
|
||||
// Socket4TxBuffer(u16),
|
||||
// Socket4RxBuffer(u16),
|
||||
|
||||
// Socket5Register(u16),
|
||||
// Socket5TxBuffer(u16),
|
||||
// Socket5RxBuffer(u16),
|
||||
|
||||
// Socket6Register(u16),
|
||||
// Socket6TxBuffer(u16),
|
||||
// Socket6RxBuffer(u16),
|
||||
|
||||
// Socket7Register(u16),
|
||||
// Socket7TxBuffer(u16),
|
||||
// Socket7RxBuffer(u16),
|
||||
// }
|
||||
|
||||
// impl Register {
|
||||
// /// Gets the control bits to identify any given register
|
||||
// fn control_byte(self) -> u8 {
|
||||
// #[allow(clippy::inconsistent_digit_grouping)]
|
||||
// match self {
|
||||
// Register::CommonRegister(_) => 0b00000_000,
|
||||
|
||||
// Register::Socket0Register(_) => 0b00001_000,
|
||||
// Register::Socket0TxBuffer(_) => 0b00010_000,
|
||||
// Register::Socket0RxBuffer(_) => 0b00011_000,
|
||||
|
||||
// Register::Socket1Register(_) => 0b00101_000,
|
||||
// Register::Socket1TxBuffer(_) => 0b00110_000,
|
||||
// Register::Socket1RxBuffer(_) => 0b00111_000,
|
||||
|
||||
// Register::Socket2Register(_) => 0b01001_000,
|
||||
// Register::Socket2TxBuffer(_) => 0b01010_000,
|
||||
// Register::Socket2RxBuffer(_) => 0b01011_000,
|
||||
|
||||
// Register::Socket3Register(_) => 0b01101_000,
|
||||
// Register::Socket3TxBuffer(_) => 0b01110_000,
|
||||
// Register::Socket3RxBuffer(_) => 0b01111_000,
|
||||
|
||||
// Register::Socket4Register(_) => 0b10001_000,
|
||||
// Register::Socket4TxBuffer(_) => 0b10010_000,
|
||||
// Register::Socket4RxBuffer(_) => 0b10011_000,
|
||||
|
||||
// Register::Socket5Register(_) => 0b10101_000,
|
||||
// Register::Socket5TxBuffer(_) => 0b10110_000,
|
||||
// Register::Socket5RxBuffer(_) => 0b10111_000,
|
||||
|
||||
// Register::Socket6Register(_) => 0b11001_000,
|
||||
// Register::Socket6TxBuffer(_) => 0b11010_000,
|
||||
// Register::Socket6RxBuffer(_) => 0b11011_000,
|
||||
|
||||
// Register::Socket7Register(_) => 0b11101_000,
|
||||
// Register::Socket7TxBuffer(_) => 0b11110_000,
|
||||
// Register::Socket7RxBuffer(_) => 0b11111_000,
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Returns the associated address as a u16
|
||||
// fn address(self) -> u16 {
|
||||
// match self {
|
||||
// Register::CommonRegister(address) => address,
|
||||
|
||||
// Register::Socket0Register(address) => address,
|
||||
// Register::Socket0TxBuffer(address) => address,
|
||||
// Register::Socket0RxBuffer(address) => address,
|
||||
|
||||
// Register::Socket1Register(address) => address,
|
||||
// Register::Socket1TxBuffer(address) => address,
|
||||
// Register::Socket1RxBuffer(address) => address,
|
||||
|
||||
// Register::Socket2Register(address) => address,
|
||||
// Register::Socket2TxBuffer(address) => address,
|
||||
// Register::Socket2RxBuffer(address) => address,
|
||||
|
||||
// Register::Socket3Register(address) => address,
|
||||
// Register::Socket3TxBuffer(address) => address,
|
||||
// Register::Socket3RxBuffer(address) => address,
|
||||
|
||||
// Register::Socket4Register(address) => address,
|
||||
// Register::Socket4TxBuffer(address) => address,
|
||||
// Register::Socket4RxBuffer(address) => address,
|
||||
|
||||
// Register::Socket5Register(address) => address,
|
||||
// Register::Socket5TxBuffer(address) => address,
|
||||
// Register::Socket5RxBuffer(address) => address,
|
||||
|
||||
// Register::Socket6Register(address) => address,
|
||||
// Register::Socket6TxBuffer(address) => address,
|
||||
// Register::Socket6RxBuffer(address) => address,
|
||||
|
||||
// Register::Socket7Register(address) => address,
|
||||
// Register::Socket7TxBuffer(address) => address,
|
||||
// Register::Socket7RxBuffer(address) => address,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
pub mod bus;
|
||||
mod inactive_w5500;
|
||||
mod network;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::network::NetworkSettings;
|
||||
use crate::{IpAddress, MacAddress};
|
||||
use crate::MacAddress;
|
||||
use embedded_nal::Ipv4Addr;
|
||||
|
||||
pub struct Manual {
|
||||
is_setup: bool,
|
||||
|
|
@ -10,7 +11,7 @@ pub struct Manual {
|
|||
}
|
||||
|
||||
impl Manual {
|
||||
pub fn new(mac: MacAddress, ip: IpAddress, gateway: IpAddress, subnet: IpAddress) -> Self {
|
||||
pub fn new(mac: MacAddress, ip: Ipv4Addr, gateway: Ipv4Addr, subnet: Ipv4Addr) -> Self {
|
||||
Self {
|
||||
is_setup: false,
|
||||
settings: NetworkSettings {
|
||||
|
|
|
|||
|
|
@ -5,14 +5,25 @@ pub use self::dhcp::Dhcp;
|
|||
pub use self::manual::Manual;
|
||||
use crate::bus::ActiveBus;
|
||||
use crate::register;
|
||||
use crate::{IpAddress, MacAddress};
|
||||
use crate::MacAddress;
|
||||
use embedded_nal::Ipv4Addr;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NetworkSettings {
|
||||
mac: MacAddress,
|
||||
ip: IpAddress,
|
||||
gateway: IpAddress,
|
||||
subnet: IpAddress,
|
||||
ip: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
subnet: Ipv4Addr,
|
||||
}
|
||||
|
||||
impl Default for NetworkSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mac: MacAddress::default(),
|
||||
ip: Ipv4Addr::unspecified(),
|
||||
gateway: Ipv4Addr::unspecified(),
|
||||
subnet: Ipv4Addr::unspecified(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Network {
|
||||
|
|
@ -29,38 +40,23 @@ pub trait Network {
|
|||
settings: &NetworkSettings,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
if settings.gateway != current.gateway {
|
||||
let mut address = settings.gateway.address;
|
||||
bus.transfer_frame(
|
||||
register::COMMON,
|
||||
register::common::GATEWAY,
|
||||
true,
|
||||
&mut address
|
||||
)?;
|
||||
let address = settings.gateway.octets();
|
||||
bus.write_frame(register::COMMON, register::common::GATEWAY, &address)?;
|
||||
current.gateway = settings.gateway;
|
||||
}
|
||||
if settings.subnet != current.subnet {
|
||||
let mut address = settings.subnet.address;
|
||||
bus.transfer_frame(
|
||||
register::COMMON,
|
||||
register::common::SUBNET_MASK,
|
||||
true,
|
||||
&mut address
|
||||
)?;
|
||||
let address = settings.subnet.octets();
|
||||
bus.write_frame(register::COMMON, register::common::SUBNET_MASK, &address)?;
|
||||
current.subnet = settings.subnet;
|
||||
}
|
||||
if settings.mac != current.mac {
|
||||
let mut address = settings.mac.address;
|
||||
bus.transfer_frame(
|
||||
register::COMMON,
|
||||
register::common::MAC,
|
||||
true,
|
||||
&mut address
|
||||
)?;
|
||||
bus.write_frame(register::COMMON, register::common::MAC, &mut address)?;
|
||||
current.mac = settings.mac;
|
||||
}
|
||||
if settings.ip != current.ip {
|
||||
let mut address = settings.ip.address;
|
||||
bus.transfer_frame(register::COMMON, register::common::IP, true, &mut address)?;
|
||||
let mut address = settings.ip.octets();
|
||||
bus.write_frame(register::COMMON, register::common::IP, &mut address)?;
|
||||
current.ip = settings.ip;
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ pub mod socketn {
|
|||
#[repr(u8)]
|
||||
pub enum Protocol {
|
||||
Udp = 0b10u8,
|
||||
Closed = 0u8,
|
||||
}
|
||||
pub const COMMAND: u16 = 0x01;
|
||||
#[repr(u8)]
|
||||
|
|
|
|||
201
src/socket.rs
Normal file
201
src/socket.rs
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::register::socketn;
|
||||
use embedded_nal::Ipv4Addr;
|
||||
|
||||
pub struct Socket {
|
||||
pub index: u8,
|
||||
register: u8,
|
||||
tx_buffer: u8,
|
||||
rx_buffer: u8,
|
||||
}
|
||||
|
||||
impl Socket {
|
||||
pub fn new(index: u8) -> Self {
|
||||
/*
|
||||
* Socket 0 is at address 0x01
|
||||
* Socket 0 TX is at address 0x02
|
||||
* Socket 0 RX is at address 0x03
|
||||
* skip 0x04
|
||||
* Socket 1 is at address 0x05
|
||||
* Socket 1 TX is at address 0x06
|
||||
* Socket 1 RX is at address 0x07
|
||||
* ...
|
||||
*/
|
||||
let block = index * 4;
|
||||
Socket {
|
||||
index,
|
||||
register: block + 1,
|
||||
tx_buffer: block + 2,
|
||||
rx_buffer: block + 3,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register(&self) -> u8 {
|
||||
self.register
|
||||
}
|
||||
pub fn tx_buffer(&self) -> u8 {
|
||||
self.tx_buffer
|
||||
}
|
||||
pub fn rx_buffer(&self) -> u8 {
|
||||
self.rx_buffer
|
||||
}
|
||||
|
||||
pub fn set_mode<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
mode: socketn::Protocol,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut mode = [mode as u8];
|
||||
bus.write_frame(self.register(), socketn::MODE, &mut mode)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn reset_interrupt<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
code: socketn::Interrupt,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [code as u8];
|
||||
bus.write_frame(self.register(), socketn::INTERRUPT, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn has_interrupt<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
code: socketn::Interrupt,
|
||||
) -> Result<bool, SpiBus::Error> {
|
||||
let mut data = [0u8];
|
||||
bus.read_frame(self.register(), socketn::INTERRUPT, &mut data)?;
|
||||
Ok(data[0] & code as u8 != 0)
|
||||
}
|
||||
|
||||
pub fn set_source_port<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
port: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = port.to_be_bytes();
|
||||
bus.write_frame(self.register(), socketn::SOURCE_PORT, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_destination_ip<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
ip: Ipv4Addr,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = ip.octets();
|
||||
bus.write_frame(self.register(), socketn::DESTINATION_IP, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_destination_port<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
port: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = port.to_be_bytes();
|
||||
bus.write_frame(self.register(), socketn::DESTINATION_PORT, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_tx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
bus.read_frame(self.register(), socketn::TX_DATA_READ_POINTER, &mut data)?;
|
||||
Ok(u16::from_be_bytes(data))
|
||||
}
|
||||
|
||||
pub fn set_tx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = pointer.to_be_bytes();
|
||||
bus.write_frame(self.register(), socketn::TX_DATA_READ_POINTER, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_tx_write_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
bus.read_frame(self.register(), socketn::TX_DATA_WRITE_POINTER, &mut data)?;
|
||||
Ok(u16::from_be_bytes(data))
|
||||
}
|
||||
|
||||
pub fn set_tx_write_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = pointer.to_be_bytes();
|
||||
bus.write_frame(self.register(), socketn::TX_DATA_WRITE_POINTER, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_rx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
bus.read_frame(self.register(), socketn::RX_DATA_READ_POINTER, &mut data)?;
|
||||
Ok(u16::from_be_bytes(data))
|
||||
}
|
||||
|
||||
pub fn set_rx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = pointer.to_be_bytes();
|
||||
bus.write_frame(self.register(), socketn::RX_DATA_READ_POINTER, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_interrupt_mask<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
mask: u8,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [mask];
|
||||
bus.write_frame(self.register(), socketn::INTERRUPT_MASK, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn command<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
command: socketn::Command,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [command as u8];
|
||||
bus.write_frame(self.register(), socketn::COMMAND, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_receive_size<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
loop {
|
||||
// Section 4.2 of datasheet, Sn_TX_FSR address docs indicate that read must be repeated until two sequential reads are stable
|
||||
let mut sample_0 = [0u8; 2];
|
||||
bus.read_frame(self.register(), socketn::RECEIVED_SIZE, &mut sample_0)?;
|
||||
let mut sample_1 = [0u8; 2];
|
||||
bus.read_frame(self.register(), socketn::RECEIVED_SIZE, &mut sample_1)?;
|
||||
if sample_0 == sample_1 && sample_0[0] >= 8 {
|
||||
break Ok(u16::from_be_bytes(sample_0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_register<SpiBus: ActiveBus>(&self, bus: &mut SpiBus) -> [u8; 0x30] {
|
||||
let mut register = [0u8; 0x30];
|
||||
bus.read_frame(self.register(), 0u16, &mut register);
|
||||
register
|
||||
}
|
||||
}
|
||||
|
|
@ -1,331 +0,0 @@
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
use crate::bus::ActiveBus;
|
||||
use crate::register;
|
||||
use crate::register::socketn;
|
||||
use crate::IpAddress;
|
||||
|
||||
pub trait Socket {
|
||||
fn register(&self) -> u8;
|
||||
fn tx_buffer(&self) -> u8;
|
||||
fn rx_buffer(&self) -> u8;
|
||||
|
||||
fn set_mode<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
mode: socketn::Protocol,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut mode = [mode as u8];
|
||||
bus.transfer_frame(self.register(), socketn::MODE, true, &mut mode)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_interrupt<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
code: socketn::Interrupt,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [code as u8];
|
||||
bus.transfer_frame(self.register(), socketn::INTERRUPT, true, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn has_interrupt<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
code: socketn::Interrupt,
|
||||
) -> Result<bool, SpiBus::Error> {
|
||||
let mut data = [0u8];
|
||||
bus.transfer_frame(self.register(), socketn::INTERRUPT, false, &mut data)?;
|
||||
Ok(data[0] & code as u8 != 0)
|
||||
}
|
||||
|
||||
fn set_source_port<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
port: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, port);
|
||||
bus.transfer_frame(self.register(), socketn::SOURCE_PORT, true, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_destination_ip<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
ip: IpAddress,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = ip.address;
|
||||
bus.transfer_frame(self.register(), socketn::DESTINATION_IP, true, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_destination_port<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
port: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, port);
|
||||
bus.transfer_frame(self.register(), socketn::DESTINATION_PORT, true, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_tx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::TX_DATA_READ_POINTER,
|
||||
false,
|
||||
&mut data
|
||||
)?;
|
||||
Ok(BigEndian::read_u16(&data))
|
||||
}
|
||||
|
||||
fn set_tx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, pointer);
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::TX_DATA_READ_POINTER,
|
||||
true,
|
||||
&mut data
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_tx_write_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::TX_DATA_WRITE_POINTER,
|
||||
false,
|
||||
&mut data
|
||||
)?;
|
||||
Ok(BigEndian::read_u16(&data))
|
||||
}
|
||||
|
||||
fn set_tx_write_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, pointer);
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::TX_DATA_WRITE_POINTER,
|
||||
true,
|
||||
&mut data
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_rx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<u16, SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RX_DATA_READ_POINTER,
|
||||
false,
|
||||
&mut data
|
||||
)?;
|
||||
Ok(BigEndian::read_u16(&data))
|
||||
}
|
||||
|
||||
fn set_rx_read_pointer<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
pointer: u16,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [0u8; 2];
|
||||
BigEndian::write_u16(&mut data, pointer);
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RX_DATA_READ_POINTER,
|
||||
true,
|
||||
&mut data
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_interrupt_mask<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
mask: u8,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [mask];
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::INTERRUPT_MASK,
|
||||
true,
|
||||
&mut data
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn command<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
command: socketn::Command,
|
||||
) -> Result<(), SpiBus::Error> {
|
||||
let mut data = [command as u8];
|
||||
bus.transfer_frame(self.register(), socketn::COMMAND, true, &mut data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_receive_size<SpiBus: ActiveBus>(&self, bus: &mut SpiBus) -> Result<u16, SpiBus::Error> {
|
||||
loop {
|
||||
// Section 4.2 of datasheet, Sn_TX_FSR address docs indicate that read must be repeated until two sequential reads are stable
|
||||
let mut sample_0 = [0u8; 2];
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RECEIVED_SIZE,
|
||||
false,
|
||||
&mut sample_0
|
||||
)?;
|
||||
let mut sample_1 = [0u8; 2];
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
socketn::RECEIVED_SIZE,
|
||||
false,
|
||||
&mut sample_1
|
||||
)?;
|
||||
if sample_0 == sample_1 && sample_0[0] >= 8 {
|
||||
break Ok(BigEndian::read_u16(&sample_0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_register<SpiBus: ActiveBus>(&self, bus: &mut SpiBus) -> [u8; 0x30] {
|
||||
let mut register = [0u8; 0x30];
|
||||
bus.transfer_frame(
|
||||
self.register(),
|
||||
0u16,
|
||||
false,
|
||||
&mut register
|
||||
);
|
||||
register
|
||||
}
|
||||
}
|
||||
|
||||
pub type OwnedSockets = (
|
||||
Socket0,
|
||||
Socket1,
|
||||
Socket2,
|
||||
Socket3,
|
||||
Socket4,
|
||||
Socket5,
|
||||
Socket6,
|
||||
Socket7,
|
||||
);
|
||||
|
||||
pub struct Socket0 {}
|
||||
impl Socket for Socket0 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET0
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET0_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET0_BUFFER_RX
|
||||
}
|
||||
}
|
||||
pub struct Socket1 {}
|
||||
impl Socket for Socket1 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET1
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET1_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET1_BUFFER_RX
|
||||
}
|
||||
}
|
||||
pub struct Socket2 {}
|
||||
impl Socket for Socket2 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET2
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET2_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET2_BUFFER_RX
|
||||
}
|
||||
}
|
||||
pub struct Socket3 {}
|
||||
impl Socket for Socket3 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET3
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET3_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET3_BUFFER_RX
|
||||
}
|
||||
}
|
||||
pub struct Socket4 {}
|
||||
impl Socket for Socket4 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET4
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET4_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET4_BUFFER_RX
|
||||
}
|
||||
}
|
||||
pub struct Socket5 {}
|
||||
impl Socket for Socket5 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET5
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET5_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET5_BUFFER_RX
|
||||
}
|
||||
}
|
||||
pub struct Socket6 {}
|
||||
impl Socket for Socket6 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET6
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET6_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET6_BUFFER_RX
|
||||
}
|
||||
}
|
||||
pub struct Socket7 {}
|
||||
impl Socket for Socket7 {
|
||||
fn register(&self) -> u8 {
|
||||
register::SOCKET7
|
||||
}
|
||||
fn tx_buffer(&self) -> u8 {
|
||||
register::SOCKET7_BUFFER_TX
|
||||
}
|
||||
fn rx_buffer(&self) -> u8 {
|
||||
register::SOCKET7_BUFFER_RX
|
||||
}
|
||||
}
|
||||
258
src/udp.rs
Normal file
258
src/udp.rs
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::register::socketn;
|
||||
use crate::socket::Socket;
|
||||
use crate::w5500::W5500;
|
||||
use core::fmt::Debug;
|
||||
use embedded_nal::{nb, IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, UdpServer, UdpClient};
|
||||
|
||||
pub struct UdpSocket {
|
||||
socket: Socket,
|
||||
}
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn new<SpiBus: ActiveBus>(
|
||||
bus: &mut SpiBus,
|
||||
socket: Socket,
|
||||
local_port: u16,
|
||||
) -> Result<Self, SpiBus::Error> {
|
||||
socket.command(bus, socketn::Command::Close)?;
|
||||
socket.reset_interrupt(bus, socketn::Interrupt::All)?;
|
||||
socket.set_source_port(bus, local_port)?;
|
||||
socket.set_mode(bus, socketn::Protocol::Udp)?;
|
||||
socket.set_interrupt_mask(
|
||||
bus,
|
||||
socketn::Interrupt::SendOk as u8 & socketn::Interrupt::Timeout as u8,
|
||||
)?;
|
||||
socket.command(bus, socketn::Command::Open)?;
|
||||
|
||||
Ok(UdpSocket { socket })
|
||||
}
|
||||
|
||||
fn set_destination<SpiBus: ActiveBus>(
|
||||
&mut self,
|
||||
bus: &mut SpiBus,
|
||||
remote: SocketAddrV4,
|
||||
) -> Result<(), UdpSocketError<SpiBus::Error>> {
|
||||
self.socket.set_destination_ip(bus, *remote.ip())?;
|
||||
self.socket.set_destination_port(bus, remote.port())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn send<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
send_buffer: &[u8],
|
||||
) -> NbResult<(), UdpSocketError<SpiBus::Error>> {
|
||||
// TODO increase longevity by cycling through buffer, instead of always writing to 0
|
||||
// TODO ensure write is currently possible
|
||||
self.socket
|
||||
.set_tx_read_pointer(bus, 0)
|
||||
.and_then(|_| bus.write_frame(self.socket.tx_buffer(), 0, &send_buffer))
|
||||
.and_then(|_| {
|
||||
self.socket
|
||||
.set_tx_write_pointer(bus, send_buffer.len() as u16)
|
||||
})
|
||||
.and_then(|_| self.socket.command(bus, socketn::Command::Send))?;
|
||||
|
||||
loop {
|
||||
if self
|
||||
.socket
|
||||
.get_tx_read_pointer(bus)?
|
||||
== self
|
||||
.socket
|
||||
.get_tx_write_pointer(bus)?
|
||||
{
|
||||
if self
|
||||
.socket
|
||||
.has_interrupt(bus, socketn::Interrupt::SendOk)?
|
||||
{
|
||||
self.socket
|
||||
.reset_interrupt(bus, socketn::Interrupt::All)?;
|
||||
return Ok(());
|
||||
} else if self
|
||||
.socket
|
||||
.has_interrupt(bus, socketn::Interrupt::Timeout)?
|
||||
{
|
||||
self.socket
|
||||
.reset_interrupt(bus, socketn::Interrupt::All)?;
|
||||
return Err(NbError::Other(UdpSocketError::WriteTimeout));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn send_to<SpiBus: ActiveBus>(
|
||||
&mut self,
|
||||
bus: &mut SpiBus,
|
||||
remote: SocketAddrV4,
|
||||
send_buffer: &[u8],
|
||||
) -> NbResult<(), UdpSocketError<SpiBus::Error>> {
|
||||
self.set_destination(bus, remote)?;
|
||||
self.send(bus, send_buffer)
|
||||
}
|
||||
|
||||
fn receive<SpiBus: ActiveBus>(
|
||||
&mut self,
|
||||
bus: &mut SpiBus,
|
||||
receive_buffer: &mut [u8],
|
||||
) -> NbResult<(usize, SocketAddr), UdpSocketError<SpiBus::Error>> {
|
||||
if !self
|
||||
.socket
|
||||
.has_interrupt(bus, socketn::Interrupt::Receive)?
|
||||
{
|
||||
return Err(NbError::WouldBlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Packet frame, as described in W5200 docs sectino 5.2.2.1
|
||||
* |<-- read_pointer read_pointer + received_size -->|
|
||||
* | Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... |
|
||||
* | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... |
|
||||
*/
|
||||
// TODO loop until RX received size stops changing, or it's larger than
|
||||
// receive_buffer.len()
|
||||
let read_pointer = self
|
||||
.socket
|
||||
.get_rx_read_pointer(bus)?;
|
||||
let mut header = [0u8; 8];
|
||||
bus.read_frame(self.socket.rx_buffer(), read_pointer, &mut header)?;
|
||||
let remote = SocketAddr::new(
|
||||
IpAddr::V4(Ipv4Addr::new(header[0], header[1], header[2], header[3])),
|
||||
u16::from_be_bytes([header[4], header[5]]),
|
||||
);
|
||||
let packet_size = u16::from_be_bytes([header[6], header[7]]).into();
|
||||
let data_read_pointer = read_pointer + 8;
|
||||
// TODO handle buffer overflow
|
||||
bus.read_frame(
|
||||
self.socket.rx_buffer(),
|
||||
data_read_pointer,
|
||||
&mut receive_buffer[0..packet_size],
|
||||
)?;
|
||||
|
||||
let tx_write_pointer = self
|
||||
.socket
|
||||
.get_tx_write_pointer(bus)?;
|
||||
self.socket
|
||||
.set_rx_read_pointer(bus, tx_write_pointer)
|
||||
.and_then(|_| self.socket.command(bus, socketn::Command::Receive))?;
|
||||
Ok((packet_size.into(), remote))
|
||||
}
|
||||
|
||||
fn close<SpiBus: ActiveBus>(
|
||||
&self,
|
||||
bus: &mut SpiBus,
|
||||
) -> Result<(), UdpSocketError<SpiBus::Error>> {
|
||||
self.socket.set_mode(bus, socketn::Protocol::Closed)?;
|
||||
self.socket.command(bus, socketn::Command::Close)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UdpSocketError<E: Debug> {
|
||||
NoMoreSockets,
|
||||
UnsupportedAddress,
|
||||
Other(E),
|
||||
WriteTimeout,
|
||||
}
|
||||
|
||||
impl<E: Debug> From<E> for UdpSocketError<E> {
|
||||
fn from(error: E) -> UdpSocketError<E> {
|
||||
UdpSocketError::Other(error)
|
||||
}
|
||||
}
|
||||
|
||||
type NbResult<T, E> = Result<T, NbError<E>>;
|
||||
enum NbError<E> {
|
||||
Other(E),
|
||||
WouldBlock,
|
||||
}
|
||||
|
||||
impl<E: Debug> From<UdpSocketError<E>> for NbError<UdpSocketError<E>> {
|
||||
fn from(error: UdpSocketError<E>) -> NbError<UdpSocketError<E>> {
|
||||
NbError::Other(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Debug> From<E> for NbError<UdpSocketError<E>> {
|
||||
fn from(error: E) -> NbError<UdpSocketError<E>> {
|
||||
NbError::Other(UdpSocketError::Other(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Debug> From<NbError<E>> for nb::Error<E> {
|
||||
fn from(error: NbError<E>) -> nb::Error<E> {
|
||||
match error {
|
||||
NbError::Other(e) => nb::Error::Other(e),
|
||||
NbError::WouldBlock => nb::Error::WouldBlock,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<SpiBus, NetworkImpl> UdpClient for W5500<SpiBus, NetworkImpl>
|
||||
where
|
||||
SpiBus: ActiveBus,
|
||||
NetworkImpl: Network,
|
||||
{
|
||||
type UdpSocket = UdpSocket;
|
||||
type Error = UdpSocketError<SpiBus::Error>;
|
||||
fn connect(&mut self, remote: SocketAddr) -> Result<Self::UdpSocket, Self::Error> {
|
||||
if let SocketAddr::V4(remote) = remote {
|
||||
if let Some(socket) = self.take_socket() {
|
||||
// TODO find a random port
|
||||
let mut udp_socket = UdpSocket::new(&mut self.bus, socket, 4000)?;
|
||||
udp_socket.set_destination(&mut self.bus, remote)?;
|
||||
Ok(udp_socket)
|
||||
} else {
|
||||
Err(Self::Error::NoMoreSockets)
|
||||
}
|
||||
} else {
|
||||
Err(Self::Error::UnsupportedAddress)
|
||||
}
|
||||
}
|
||||
fn send(&mut self, socket: &mut Self::UdpSocket, buffer: &[u8]) -> nb::Result<(), Self::Error> {
|
||||
socket.send(&mut self.bus, buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
fn receive(
|
||||
&mut self,
|
||||
socket: &mut Self::UdpSocket,
|
||||
buffer: &mut [u8],
|
||||
) -> nb::Result<(usize, SocketAddr), Self::Error> {
|
||||
Ok(socket.receive(&mut self.bus, buffer)?)
|
||||
}
|
||||
fn close(&mut self, socket: Self::UdpSocket) -> Result<(), Self::Error> {
|
||||
socket.close(&mut self.bus)?;
|
||||
self.release_socket(socket.socket);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<SpiBus, NetworkImpl> UdpServer for W5500<SpiBus, NetworkImpl>
|
||||
where
|
||||
SpiBus: ActiveBus,
|
||||
NetworkImpl: Network,
|
||||
{
|
||||
fn bind(&mut self, local_port: u16) -> Result<Self::UdpSocket, Self::Error> {
|
||||
if let Some(socket) = self.take_socket() {
|
||||
Ok(UdpSocket::new(&mut self.bus, socket, local_port)?)
|
||||
} else {
|
||||
Err(Self::Error::NoMoreSockets)
|
||||
}
|
||||
}
|
||||
fn send_to(
|
||||
&mut self,
|
||||
socket: &mut Self::UdpSocket,
|
||||
remote: SocketAddr,
|
||||
buffer: &[u8],
|
||||
) -> nb::Result<(), Self::Error> {
|
||||
if let SocketAddr::V4(remote) = remote {
|
||||
socket.send_to(&mut self.bus, remote, buffer)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(nb::Error::Other(Self::Error::UnsupportedAddress))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::socket::Socket;
|
||||
use crate::udp::UdpSocket;
|
||||
use crate::w5500::W5500;
|
||||
|
||||
pub struct InactiveUdpSocket<SocketImpl: Socket> {
|
||||
socket: SocketImpl,
|
||||
}
|
||||
|
||||
impl<SocketImpl: Socket> InactiveUdpSocket<SocketImpl> {
|
||||
pub fn new(socket: SocketImpl) -> Self {
|
||||
InactiveUdpSocket { socket }
|
||||
}
|
||||
|
||||
pub fn activate<SpiBus: ActiveBus, NetworkImpl: Network>(
|
||||
self,
|
||||
w5500: W5500<SpiBus, NetworkImpl>,
|
||||
) -> UdpSocket<SpiBus, NetworkImpl, SocketImpl> {
|
||||
UdpSocket {
|
||||
w5500,
|
||||
socket: self.socket,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::register::socketn;
|
||||
use crate::socket::Socket;
|
||||
use crate::udp::UdpSocket;
|
||||
use crate::IpAddress;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
pub struct IncomingPacket<UdpSocket> {
|
||||
udp_socket: UdpSocket,
|
||||
address: IpAddress,
|
||||
remote_port: u16,
|
||||
read_pointer: u16,
|
||||
write_pointer: u16,
|
||||
}
|
||||
|
||||
impl<SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
|
||||
IncomingPacket<UdpSocket<SpiBus, NetworkImpl, SocketImpl>>
|
||||
{
|
||||
pub fn new(
|
||||
mut udp_socket: UdpSocket<SpiBus, NetworkImpl, SocketImpl>,
|
||||
) -> Result<Self, SpiBus::Error> {
|
||||
let receive_size = udp_socket
|
||||
.socket
|
||||
.get_receive_size(&mut udp_socket.w5500.bus)?;
|
||||
|
||||
// Packet frame, as described in W5200 docs sectino 5.2.2.1
|
||||
// |<-- read_pointer read_pointer + received_size -->|
|
||||
// |Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... |
|
||||
// | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... |
|
||||
let read_pointer = udp_socket
|
||||
.socket
|
||||
.get_rx_read_pointer(&mut udp_socket.w5500.bus)?;
|
||||
let mut header = [0u8; 8];
|
||||
udp_socket.w5500.bus.transfer_frame(
|
||||
udp_socket.socket.rx_buffer(),
|
||||
read_pointer,
|
||||
false,
|
||||
&mut header
|
||||
)?;
|
||||
Ok(Self {
|
||||
udp_socket,
|
||||
address: IpAddress::new(header[0], header[1], header[2], header[3]),
|
||||
remote_port: BigEndian::read_u16(&header[4..5]),
|
||||
read_pointer: read_pointer + 8,
|
||||
write_pointer: read_pointer + receive_size,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_remote_port(&self) -> u16 {
|
||||
self.remote_port
|
||||
}
|
||||
|
||||
pub fn get_address(&self) -> IpAddress {
|
||||
self.address
|
||||
}
|
||||
|
||||
// TODO add read_all method
|
||||
|
||||
pub fn done(mut self) -> Result<UdpSocket<SpiBus, NetworkImpl, SocketImpl>, SpiBus::Error> {
|
||||
self.udp_socket
|
||||
.socket
|
||||
.set_rx_read_pointer(&mut self.udp_socket.w5500.bus, self.write_pointer)?;
|
||||
self.udp_socket
|
||||
.socket
|
||||
.command(&mut self.udp_socket.w5500.bus, socketn::Command::Receive)?;
|
||||
Ok(self.udp_socket)
|
||||
}
|
||||
}
|
||||
|
||||
impl<SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> Iterator
|
||||
for IncomingPacket<UdpSocket<SpiBus, NetworkImpl, SocketImpl>>
|
||||
{
|
||||
type Item = Result<u8, SpiBus::Error>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.read_pointer > self.write_pointer {
|
||||
return None;
|
||||
}
|
||||
let mut buffer = [0u8];
|
||||
let result = self.udp_socket.w5500.bus.transfer_frame(
|
||||
self.udp_socket.socket.rx_buffer(),
|
||||
self.read_pointer,
|
||||
false,
|
||||
&mut buffer
|
||||
);
|
||||
self.read_pointer += 1;
|
||||
// TODO handle looping back?
|
||||
match result {
|
||||
Ok(_) => Some(Ok(buffer[0])),
|
||||
Result::Err(error) => Some(Err(error)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
mod inactive_udp_socket;
|
||||
mod incoming_packet;
|
||||
mod outgoing_packet;
|
||||
|
||||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::register::socketn;
|
||||
use crate::socket::Socket;
|
||||
use crate::udp::inactive_udp_socket::InactiveUdpSocket;
|
||||
use crate::udp::incoming_packet::IncomingPacket;
|
||||
use crate::udp::outgoing_packet::OutgoingPacket;
|
||||
use crate::w5500::W5500;
|
||||
use crate::IpAddress;
|
||||
|
||||
pub struct UdpSocket<SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> {
|
||||
w5500: W5500<SpiBus, NetworkImpl>,
|
||||
|
||||
socket: SocketImpl,
|
||||
}
|
||||
|
||||
impl<SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
|
||||
UdpSocket<SpiBus, NetworkImpl, SocketImpl>
|
||||
{
|
||||
pub fn new(
|
||||
port: u16,
|
||||
mut w5500: W5500<SpiBus, NetworkImpl>,
|
||||
socket: SocketImpl,
|
||||
) -> Result<Self, SpiBus::Error> {
|
||||
socket.command(&mut w5500.bus, socketn::Command::Close)?;
|
||||
socket.reset_interrupt(&mut w5500.bus, socketn::Interrupt::All)?;
|
||||
socket.set_source_port(&mut w5500.bus, port)?;
|
||||
socket.set_mode(&mut w5500.bus, socketn::Protocol::Udp)?;
|
||||
socket.command(&mut w5500.bus, socketn::Command::Open)?;
|
||||
|
||||
Ok(UdpSocket { w5500, socket })
|
||||
}
|
||||
|
||||
pub fn dump_register(&mut self) -> [u8; 0x30] {
|
||||
self.socket.dump_register(&mut self.w5500.bus)
|
||||
}
|
||||
|
||||
/// Returns a UDP packet if one is available. Will return `None` if no UDP packets are in the socket's buffer
|
||||
pub fn receive(mut self) -> Result<Option<IncomingPacket<Self>>, SpiBus::Error> {
|
||||
if !self
|
||||
.socket
|
||||
.has_interrupt(&mut self.w5500.bus, socketn::Interrupt::Receive)?
|
||||
{
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(IncomingPacket::new(self)?))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends a UDP packet to the specified IP and port, and blocks until it is sent
|
||||
pub fn send(
|
||||
self,
|
||||
host: IpAddress,
|
||||
remote_port: u16,
|
||||
) -> Result<OutgoingPacket<Self>, SpiBus::Error> {
|
||||
Ok(OutgoingPacket::new(self, host, remote_port)?)
|
||||
}
|
||||
|
||||
pub fn deactivate(self) -> (InactiveUdpSocket<SocketImpl>, W5500<SpiBus, NetworkImpl>) {
|
||||
(InactiveUdpSocket::new(self.socket), self.w5500)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
use crate::bus::ActiveBus;
|
||||
use crate::network::Network;
|
||||
use crate::register::socketn;
|
||||
use crate::socket::Socket;
|
||||
use crate::udp::UdpSocket;
|
||||
use crate::IpAddress;
|
||||
|
||||
pub struct OutgoingPacket<UdpSocket> {
|
||||
pub udp_socket: UdpSocket,
|
||||
data_length: u16,
|
||||
}
|
||||
|
||||
impl<SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket>
|
||||
OutgoingPacket<UdpSocket<SpiBus, NetworkImpl, SocketImpl>>
|
||||
{
|
||||
pub fn new(
|
||||
mut udp_socket: UdpSocket<SpiBus, NetworkImpl, SocketImpl>,
|
||||
host: IpAddress,
|
||||
port: u16,
|
||||
) -> Result<Self, SpiBus::Error> {
|
||||
// TODO set interrupt mask to SendOk&Timeout
|
||||
udp_socket
|
||||
.socket
|
||||
.set_destination_ip(&mut udp_socket.w5500.bus, host)?;
|
||||
udp_socket
|
||||
.socket
|
||||
.set_destination_port(&mut udp_socket.w5500.bus, port)?;
|
||||
udp_socket
|
||||
.socket
|
||||
.set_tx_read_pointer(&mut udp_socket.w5500.bus, 0)?;
|
||||
Ok(Self {
|
||||
udp_socket,
|
||||
data_length: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write(&mut self, mut data: &mut [u8]) -> Result<(), SpiBus::Error> {
|
||||
self.udp_socket.w5500.bus.transfer_frame(
|
||||
self.udp_socket.socket.tx_buffer(),
|
||||
self.data_length,
|
||||
true,
|
||||
&mut data
|
||||
)?;
|
||||
self.data_length += data.len() as u16;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn send(mut self) -> Result<UdpSocket<SpiBus, NetworkImpl, SocketImpl>, SpiBus::Error> {
|
||||
self.udp_socket
|
||||
.socket
|
||||
.set_tx_write_pointer(&mut self.udp_socket.w5500.bus, self.data_length)?;
|
||||
self.udp_socket
|
||||
.socket
|
||||
.command(&mut self.udp_socket.w5500.bus, socketn::Command::Send)?;
|
||||
loop {
|
||||
// TODO wait until TX pointers match first
|
||||
// TODO check for Timeout interrupt
|
||||
// wait until send is complete
|
||||
if self
|
||||
.udp_socket
|
||||
.socket
|
||||
.has_interrupt(&mut self.udp_socket.w5500.bus, socketn::Interrupt::SendOk)?
|
||||
{
|
||||
self.udp_socket
|
||||
.socket
|
||||
.reset_interrupt(&mut self.udp_socket.w5500.bus, socketn::Interrupt::SendOk)?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.udp_socket
|
||||
.socket
|
||||
.command(&mut self.udp_socket.w5500.bus, socketn::Command::Open)?;
|
||||
Ok(self.udp_socket)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
use crate::network::{Dhcp, Manual, Network};
|
||||
use crate::{IpAddress, MacAddress, Mode};
|
||||
use crate::{MacAddress, Mode};
|
||||
use bus::{ActiveBus, ActiveFourWire, ActiveThreeWire};
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
use embedded_nal::Ipv4Addr;
|
||||
use register;
|
||||
use socket::OwnedSockets;
|
||||
use socket::{Socket0, Socket1, Socket2, Socket3, Socket4, Socket5, Socket6, Socket7};
|
||||
use w5500::W5500;
|
||||
|
||||
pub struct UninitializedW5500<SpiBus: ActiveBus> {
|
||||
|
|
@ -17,6 +16,7 @@ pub enum InitializeError<SpiError> {
|
|||
SpiError(SpiError),
|
||||
ChipNotConnected,
|
||||
}
|
||||
// TODO add From impl and remove map_errs
|
||||
|
||||
impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
|
||||
pub fn new(bus: SpiBus) -> UninitializedW5500<SpiBus> {
|
||||
|
|
@ -27,7 +27,7 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
|
|||
self,
|
||||
mac: MacAddress,
|
||||
mode_options: Mode,
|
||||
) -> Result<(W5500<SpiBus, Dhcp>, OwnedSockets), InitializeError<SpiBus::Error>> {
|
||||
) -> Result<W5500<SpiBus, Dhcp>, InitializeError<SpiBus::Error>> {
|
||||
let network = Dhcp::new(mac);
|
||||
self.initialize_with_network(network, mode_options)
|
||||
}
|
||||
|
|
@ -35,23 +35,24 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
|
|||
pub fn initialize_manual(
|
||||
self,
|
||||
mac: MacAddress,
|
||||
ip: IpAddress,
|
||||
ip: Ipv4Addr,
|
||||
mode_options: Mode,
|
||||
) -> Result<(W5500<SpiBus, Manual>, OwnedSockets), InitializeError<SpiBus::Error>> {
|
||||
let mut gateway = ip;
|
||||
gateway.address[3] = 1;
|
||||
let subnet = IpAddress::new(255, 255, 255, 0);
|
||||
) -> Result<W5500<SpiBus, Manual>, InitializeError<SpiBus::Error>> {
|
||||
let mut ip_bytes = ip.octets();
|
||||
ip_bytes[3] = 1;
|
||||
let gateway = Ipv4Addr::from(ip_bytes);
|
||||
let subnet = Ipv4Addr::new(255, 255, 255, 0);
|
||||
self.initialize_advanced(mac, ip, gateway, subnet, mode_options)
|
||||
}
|
||||
|
||||
pub fn initialize_advanced(
|
||||
self,
|
||||
mac: MacAddress,
|
||||
ip: IpAddress,
|
||||
gateway: IpAddress,
|
||||
subnet: IpAddress,
|
||||
ip: Ipv4Addr,
|
||||
gateway: Ipv4Addr,
|
||||
subnet: Ipv4Addr,
|
||||
mode_options: Mode,
|
||||
) -> Result<(W5500<SpiBus, Manual>, OwnedSockets), InitializeError<SpiBus::Error>> {
|
||||
) -> Result<W5500<SpiBus, Manual>, InitializeError<SpiBus::Error>> {
|
||||
let network = Manual::new(mac, ip, gateway, subnet);
|
||||
self.initialize_with_network(network, mode_options)
|
||||
}
|
||||
|
|
@ -60,35 +61,21 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
|
|||
mut self,
|
||||
mut network: NetworkImpl,
|
||||
mode_options: Mode,
|
||||
) -> Result<(W5500<SpiBus, NetworkImpl>, OwnedSockets), InitializeError<SpiBus::Error>> {
|
||||
) -> Result<W5500<SpiBus, NetworkImpl>, InitializeError<SpiBus::Error>> {
|
||||
self.assert_chip_version(0x4)?;
|
||||
|
||||
// RESET
|
||||
/*
|
||||
let mut mode = [0b10000000];
|
||||
self
|
||||
.bus
|
||||
.transfer_frame(register::COMMON, register::common::MODE, true, &mut mode)
|
||||
self.bus
|
||||
.write_frame(register::COMMON, register::common::MODE, &mut mode)
|
||||
.map_err(|e| InitializeError::SpiError(e))?;
|
||||
*/
|
||||
|
||||
|
||||
self.set_mode(mode_options)
|
||||
.map_err(|e| InitializeError::SpiError(e))?;
|
||||
network
|
||||
.refresh(&mut self.bus)
|
||||
.map_err(|e| InitializeError::SpiError(e))?;
|
||||
let sockets = (
|
||||
Socket0 {},
|
||||
Socket1 {},
|
||||
Socket2 {},
|
||||
Socket3 {},
|
||||
Socket4 {},
|
||||
Socket5 {},
|
||||
Socket6 {},
|
||||
Socket7 {},
|
||||
);
|
||||
Ok((W5500::new(self.bus, network), sockets))
|
||||
Ok(W5500::new(self.bus, network))
|
||||
}
|
||||
|
||||
fn assert_chip_version(
|
||||
|
|
@ -96,12 +83,8 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
|
|||
expected_version: u8,
|
||||
) -> Result<(), InitializeError<SpiBus::Error>> {
|
||||
let mut version = [0];
|
||||
self.bus.transfer_frame(
|
||||
register::COMMON,
|
||||
register::common::VERSION,
|
||||
false,
|
||||
&mut version
|
||||
)
|
||||
self.bus
|
||||
.read_frame(register::COMMON, register::common::VERSION, &mut version)
|
||||
.map_err(|e| InitializeError::SpiError(e))?;
|
||||
if version[0] != expected_version {
|
||||
Err(InitializeError::ChipNotConnected)
|
||||
|
|
@ -116,9 +99,8 @@ impl<SpiBus: ActiveBus> UninitializedW5500<SpiBus> {
|
|||
mode[0] |= mode_options.on_ping_request as u8;
|
||||
mode[0] |= mode_options.connection_type as u8;
|
||||
mode[0] |= mode_options.arp_responses as u8;
|
||||
self
|
||||
.bus
|
||||
.transfer_frame(register::COMMON, register::common::MODE, true, &mut mode)?;
|
||||
self.bus
|
||||
.write_frame(register::COMMON, register::common::MODE, &mut mode)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
49
src/w5500.rs
49
src/w5500.rs
|
|
@ -1,43 +1,68 @@
|
|||
use crate::inactive_w5500::InactiveW5500;
|
||||
use crate::uninitialized_w5500::UninitializedW5500;
|
||||
use bit_field::BitArray;
|
||||
use bus::{ActiveBus, ActiveFourWire, ActiveThreeWire, FourWire, ThreeWire};
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use embedded_hal::spi::FullDuplex;
|
||||
use network::Network;
|
||||
use register;
|
||||
use socket::Socket;
|
||||
use udp::UdpSocket;
|
||||
|
||||
pub struct W5500<SpiBus: ActiveBus, NetworkImpl: Network> {
|
||||
pub bus: SpiBus,
|
||||
network: NetworkImpl,
|
||||
sockets: [u8; 1],
|
||||
}
|
||||
|
||||
pub enum ResetError<E> {
|
||||
SocketsNotReleased,
|
||||
Other(E),
|
||||
}
|
||||
|
||||
impl<E> From<E> for ResetError<E> {
|
||||
fn from(error: E) -> ResetError<E> {
|
||||
ResetError::Other(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl<SpiBus: ActiveBus, NetworkImpl: Network> W5500<SpiBus, NetworkImpl> {
|
||||
pub fn new(bus: SpiBus, network: NetworkImpl) -> Self {
|
||||
W5500 { bus, network }
|
||||
W5500 {
|
||||
bus,
|
||||
network,
|
||||
sockets: [0b11111111],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(mut self) -> Result<UninitializedW5500<SpiBus>, SpiBus::Error> {
|
||||
pub fn reset(mut self) -> Result<UninitializedW5500<SpiBus>, ResetError<SpiBus::Error>> {
|
||||
if self.sockets != [0b11111111] {
|
||||
Err(ResetError::SocketsNotReleased)
|
||||
} else {
|
||||
self.clear_mode()?;
|
||||
Ok(UninitializedW5500::new(self.bus))
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_mode(&mut self) -> Result<(), SpiBus::Error> {
|
||||
// reset bit
|
||||
let mut mode = [0b10000000];
|
||||
self
|
||||
.bus
|
||||
.transfer_frame(register::COMMON, register::common::MODE, true, &mut mode)?;
|
||||
self.bus
|
||||
.write_frame(register::COMMON, register::common::MODE, &mut mode)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn open_udp_socket<SocketImpl: Socket>(
|
||||
self,
|
||||
port: u16,
|
||||
socket: SocketImpl,
|
||||
) -> Result<UdpSocket<SpiBus, NetworkImpl, SocketImpl>, SpiBus::Error> {
|
||||
UdpSocket::new(port, self, socket)
|
||||
pub fn take_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
|
||||
}
|
||||
|
||||
pub fn release_socket(&mut self, socket: Socket) -> () {
|
||||
self.sockets.set_bit(socket.index.into(), true);
|
||||
}
|
||||
|
||||
pub fn release(self) -> (SpiBus, NetworkImpl) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue