diff --git a/Cargo.toml b/Cargo.toml index b5b441e..7be3ea2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/bus/four_wire.rs b/src/bus/four_wire.rs index 082bf32..ffdf7d1 100644 --- a/src/bus/four_wire.rs +++ b/src/bus/four_wire.rs @@ -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, ChipSelect: OutputPin> { impl, ChipSelect: OutputPin> ActiveBus for ActiveFourWire { type Error = FourWireError; - 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)) - .map_err(|e| FourWireError::SpiError(e))?; + 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, ChipSelect: OutputPin> ActiveFourWire { @@ -74,3 +80,17 @@ pub enum FourWireError { SpiError(SpiError), ChipSelectError(ChipSelectError), } + +impl fmt::Debug for FourWireError { + 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 diff --git a/src/bus/mod.rs b/src/bus/mod.rs index c80e13b..e9bd338 100644 --- a/src/bus/mod.rs +++ b/src/bus/mod.rs @@ -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>( - 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: &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>( - 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: &mut Spi, bytes: &[u8]) -> Result<(), Spi::Error> { + for byte in bytes.iter() { + Self::transfer_byte(spi, *byte)?; + } + Ok(()) + } + + fn transfer_byte>(spi: &mut Spi, byte: u8) -> Result { + block!(spi.send(byte)).and_then(|_| block!(spi.read())) } } diff --git a/src/bus/three_wire.rs b/src/bus/three_wire.rs index 8891797..e6cf71a 100644 --- a/src/bus/three_wire.rs +++ b/src/bus/three_wire.rs @@ -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> { } impl> ActiveBus for ActiveThreeWire { - type Error = Spi::Error; + type Error = ThreeWireError; /// Transfers a frame with an arbitrary data length in FDM /// @@ -43,17 +43,13 @@ impl> ActiveBus for ActiveThreeWire { /// (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> ActiveBus for ActiveThreeWire { 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( - &mut self.spi, - &mut data_phase[..last_length_written as usize] - ))?; + 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], + ) + }) + .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> ActiveThreeWire { (ThreeWire::new(), self.spi) } } + +pub enum ThreeWireError { + SpiError(SpiError), +} +impl fmt::Debug for ThreeWireError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "ThreeWireError::{}", + match self { + Self::SpiError(_) => "SpiError", + } + ) + } +} +// TODO impl From and remove map_errs diff --git a/src/lib.rs b/src/lib.rs index 1f6fbab..ebe57db 100644 --- a/src/lib.rs +++ b/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(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> -// 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>( -// chip_select: &'a mut ChipSelect, -// spi: &'c mut Spi, -// wol: OnWakeOnLan, -// ping: OnPingRequest, -// mode: ConnectionType, -// arp: ArpResponses, -// ) -> Result> { -// 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 { -// 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>( -// &'b mut self, -// spi: &'c mut Spi, -// ) -> Result, TransferError> -// { -// 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>( -// &'a mut W5500<'b, ChipSelect>, -// &'c mut Spi, -// ); - -// impl< -// ChipSelectError, -// ChipSelect: OutputPin, -// SpiError, -// Spi: FullDuplex, -// > ActiveW5500<'_, '_, '_, ChipSelect, Spi> -// { -// /// Returns the requested socket if it is not already used -// pub fn take_socket(&mut self, socket: Socket) -> Option { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// 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> { -// self.chip_select() -// .map_err(|error| -> TransferError { -// 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 { -// 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 { -// 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> { -// 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> { -// 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> { -// self.chip_select() -// .map_err(|error| -> TransferError { -// 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 { -// 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 { -// fn try_into_udp_server_socket(self, port: u16) -> Result -// where -// Self: Sized; -// } - -// impl> IntoUdpSocket -// for ( -// &mut ActiveW5500<'_, '_, '_, ChipSelect, Spi>, -// UninitializedSocket, -// ) -// { -// /// Initialize a socket to operate in UDP mode -// fn try_into_udp_server_socket(self, port: u16) -> Result { -// 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| 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, Self::Error>; - -// fn blocking_send( -// &mut self, -// host: &IpAddress, -// host_port: u16, -// data: &[u8], -// ) -> Result<(), Self::Error>; -// } - -// impl> Udp -// for (&mut ActiveW5500<'_, '_, '_, ChipSelect, Spi>, &UdpSocket) -// { -// type Error = TransferError; - -// /// 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, 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; diff --git a/src/network/manual.rs b/src/network/manual.rs index 0a38725..00c9099 100644 --- a/src/network/manual.rs +++ b/src/network/manual.rs @@ -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 { diff --git a/src/network/mod.rs b/src/network/mod.rs index 19ed9b5..9899b9b 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -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(()) diff --git a/src/register.rs b/src/register.rs index d41b09c..adfd64d 100644 --- a/src/register.rs +++ b/src/register.rs @@ -45,6 +45,7 @@ pub mod socketn { #[repr(u8)] pub enum Protocol { Udp = 0b10u8, + Closed = 0u8, } pub const COMMAND: u16 = 0x01; #[repr(u8)] diff --git a/src/socket.rs b/src/socket.rs new file mode 100644 index 0000000..03a5152 --- /dev/null +++ b/src/socket.rs @@ -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( + &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( + &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( + &self, + bus: &mut SpiBus, + code: socketn::Interrupt, + ) -> Result { + 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( + &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( + &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( + &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( + &self, + bus: &mut SpiBus, + ) -> Result { + 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( + &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( + &self, + bus: &mut SpiBus, + ) -> Result { + 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( + &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( + &self, + bus: &mut SpiBus, + ) -> Result { + 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( + &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( + &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( + &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( + &self, + bus: &mut SpiBus, + ) -> Result { + 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(&self, bus: &mut SpiBus) -> [u8; 0x30] { + let mut register = [0u8; 0x30]; + bus.read_frame(self.register(), 0u16, &mut register); + register + } +} diff --git a/src/socket/mod.rs b/src/socket/mod.rs deleted file mode 100644 index 91d1b88..0000000 --- a/src/socket/mod.rs +++ /dev/null @@ -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( - &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( - &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( - &self, - bus: &mut SpiBus, - code: socketn::Interrupt, - ) -> Result { - 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( - &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( - &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( - &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( - &self, - bus: &mut SpiBus, - ) -> Result { - 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( - &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( - &self, - bus: &mut SpiBus, - ) -> Result { - 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( - &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( - &self, - bus: &mut SpiBus, - ) -> Result { - 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( - &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( - &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( - &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(&self, bus: &mut SpiBus) -> Result { - 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(&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 - } -} diff --git a/src/udp.rs b/src/udp.rs new file mode 100644 index 0000000..62b5983 --- /dev/null +++ b/src/udp.rs @@ -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( + bus: &mut SpiBus, + socket: Socket, + local_port: u16, + ) -> Result { + 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( + &mut self, + bus: &mut SpiBus, + remote: SocketAddrV4, + ) -> Result<(), UdpSocketError> { + self.socket.set_destination_ip(bus, *remote.ip())?; + self.socket.set_destination_port(bus, remote.port())?; + Ok(()) + } + + fn send( + &self, + bus: &mut SpiBus, + send_buffer: &[u8], + ) -> NbResult<(), UdpSocketError> { + // 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( + &mut self, + bus: &mut SpiBus, + remote: SocketAddrV4, + send_buffer: &[u8], + ) -> NbResult<(), UdpSocketError> { + self.set_destination(bus, remote)?; + self.send(bus, send_buffer) + } + + fn receive( + &mut self, + bus: &mut SpiBus, + receive_buffer: &mut [u8], + ) -> NbResult<(usize, SocketAddr), UdpSocketError> { + 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( + &self, + bus: &mut SpiBus, + ) -> Result<(), UdpSocketError> { + self.socket.set_mode(bus, socketn::Protocol::Closed)?; + self.socket.command(bus, socketn::Command::Close)?; + Ok(()) + } +} + +#[derive(Debug)] +pub enum UdpSocketError { + NoMoreSockets, + UnsupportedAddress, + Other(E), + WriteTimeout, +} + +impl From for UdpSocketError { + fn from(error: E) -> UdpSocketError { + UdpSocketError::Other(error) + } +} + +type NbResult = Result>; +enum NbError { + Other(E), + WouldBlock, +} + +impl From> for NbError> { + fn from(error: UdpSocketError) -> NbError> { + NbError::Other(error) + } +} + +impl From for NbError> { + fn from(error: E) -> NbError> { + NbError::Other(UdpSocketError::Other(error)) + } +} + +impl From> for nb::Error { + fn from(error: NbError) -> nb::Error { + match error { + NbError::Other(e) => nb::Error::Other(e), + NbError::WouldBlock => nb::Error::WouldBlock, + } + } +} + + +impl UdpClient for W5500 +where + SpiBus: ActiveBus, + NetworkImpl: Network, +{ + type UdpSocket = UdpSocket; + type Error = UdpSocketError; + fn connect(&mut self, remote: SocketAddr) -> Result { + 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 UdpServer for W5500 +where + SpiBus: ActiveBus, + NetworkImpl: Network, +{ + fn bind(&mut self, local_port: u16) -> Result { + 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)) + } + } +} diff --git a/src/udp/inactive_udp_socket.rs b/src/udp/inactive_udp_socket.rs deleted file mode 100644 index 64c8cf9..0000000 --- a/src/udp/inactive_udp_socket.rs +++ /dev/null @@ -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 { - socket: SocketImpl, -} - -impl InactiveUdpSocket { - pub fn new(socket: SocketImpl) -> Self { - InactiveUdpSocket { socket } - } - - pub fn activate( - self, - w5500: W5500, - ) -> UdpSocket { - UdpSocket { - w5500, - socket: self.socket, - } - } -} diff --git a/src/udp/incoming_packet.rs b/src/udp/incoming_packet.rs deleted file mode 100644 index ccf8866..0000000 --- a/src/udp/incoming_packet.rs +++ /dev/null @@ -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 { - udp_socket: UdpSocket, - address: IpAddress, - remote_port: u16, - read_pointer: u16, - write_pointer: u16, -} - -impl - IncomingPacket> -{ - pub fn new( - mut udp_socket: UdpSocket, - ) -> Result { - 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, 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 Iterator - for IncomingPacket> -{ - type Item = Result; - fn next(&mut self) -> Option { - 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)), - } - } -} diff --git a/src/udp/mod.rs b/src/udp/mod.rs deleted file mode 100644 index 098e5bf..0000000 --- a/src/udp/mod.rs +++ /dev/null @@ -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 { - w5500: W5500, - - socket: SocketImpl, -} - -impl - UdpSocket -{ - pub fn new( - port: u16, - mut w5500: W5500, - socket: SocketImpl, - ) -> Result { - 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>, 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, SpiBus::Error> { - Ok(OutgoingPacket::new(self, host, remote_port)?) - } - - pub fn deactivate(self) -> (InactiveUdpSocket, W5500) { - (InactiveUdpSocket::new(self.socket), self.w5500) - } -} diff --git a/src/udp/outgoing_packet.rs b/src/udp/outgoing_packet.rs deleted file mode 100644 index 673d770..0000000 --- a/src/udp/outgoing_packet.rs +++ /dev/null @@ -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 { - pub udp_socket: UdpSocket, - data_length: u16, -} - -impl - OutgoingPacket> -{ - pub fn new( - mut udp_socket: UdpSocket, - host: IpAddress, - port: u16, - ) -> Result { - // 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, 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) - } -} diff --git a/src/uninitialized_w5500.rs b/src/uninitialized_w5500.rs index 5374251..f076650 100644 --- a/src/uninitialized_w5500.rs +++ b/src/uninitialized_w5500.rs @@ -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 { @@ -17,6 +16,7 @@ pub enum InitializeError { SpiError(SpiError), ChipNotConnected, } +// TODO add From impl and remove map_errs impl UninitializedW5500 { pub fn new(bus: SpiBus) -> UninitializedW5500 { @@ -27,7 +27,7 @@ impl UninitializedW5500 { self, mac: MacAddress, mode_options: Mode, - ) -> Result<(W5500, OwnedSockets), InitializeError> { + ) -> Result, InitializeError> { let network = Dhcp::new(mac); self.initialize_with_network(network, mode_options) } @@ -35,23 +35,24 @@ impl UninitializedW5500 { pub fn initialize_manual( self, mac: MacAddress, - ip: IpAddress, + ip: Ipv4Addr, mode_options: Mode, - ) -> Result<(W5500, OwnedSockets), InitializeError> { - let mut gateway = ip; - gateway.address[3] = 1; - let subnet = IpAddress::new(255, 255, 255, 0); + ) -> Result, InitializeError> { + 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, OwnedSockets), InitializeError> { + ) -> Result, InitializeError> { let network = Manual::new(mac, ip, gateway, subnet); self.initialize_with_network(network, mode_options) } @@ -60,35 +61,21 @@ impl UninitializedW5500 { mut self, mut network: NetworkImpl, mode_options: Mode, - ) -> Result<(W5500, OwnedSockets), InitializeError> { + ) -> Result, InitializeError> { 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,13 +83,9 @@ impl UninitializedW5500 { expected_version: u8, ) -> Result<(), InitializeError> { let mut version = [0]; - self.bus.transfer_frame( - register::COMMON, - register::common::VERSION, - false, - &mut version - ) - .map_err(|e| InitializeError::SpiError(e))?; + 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) } else { @@ -116,9 +99,8 @@ impl UninitializedW5500 { 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(()) } } diff --git a/src/w5500.rs b/src/w5500.rs index 7bce02a..92603d0 100644 --- a/src/w5500.rs +++ b/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 { pub bus: SpiBus, network: NetworkImpl, + sockets: [u8; 1], +} + +pub enum ResetError { + SocketsNotReleased, + Other(E), +} + +impl From for ResetError { + fn from(error: E) -> ResetError { + ResetError::Other(error) + } } impl W5500 { pub fn new(bus: SpiBus, network: NetworkImpl) -> Self { - W5500 { bus, network } + W5500 { + bus, + network, + sockets: [0b11111111], + } } - pub fn reset(mut self) -> Result, SpiBus::Error> { - self.clear_mode()?; - Ok(UninitializedW5500::new(self.bus)) + pub fn reset(mut self) -> Result, ResetError> { + 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( - self, - port: u16, - socket: SocketImpl, - ) -> Result, SpiBus::Error> { - UdpSocket::new(port, self, socket) + pub fn take_socket(&mut self) -> Option { + 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) {