diff --git a/src/register.rs b/src/register.rs index 114b870..23b2be6 100644 --- a/src/register.rs +++ b/src/register.rs @@ -49,23 +49,31 @@ pub mod socketn { pub const COMMAND: u16 = 0x01; #[repr(u8)] pub enum Command { + Open = 0x01, + Send = 0x20, Receive = 0x40, } pub const INTERRUPT: u16 = 0x02; #[repr(u8)] pub enum Interrupt { - SendOk = 0b10000u8, + SendOk = 0b010000u8, + Receive = 0b00100u8, } pub const SOURCE_PORT: u16 = 0x04; - pub const INTERRUPT_MASK: u16 = 0x2C; - pub mod interrupt_mask { - pub const RECEIVE: u8 = 0b100; - } + pub const DESTINATION_IP: u16 = 0x0C; + + pub const DESTINATION_PORT: u16 = 0x10; + + pub const TX_DATA_READ_POINTER: u16 = 0x22; + + pub const TX_DATA_WRITE_POINTER: u16 = 0x24; pub const RECEIVED_SIZE: u16 = 0x26; pub const RX_DATA_READ_POINTER: u16 = 0x28; + + pub const INTERRUPT_MASK: u16 = 0x2C; } diff --git a/src/socket/mod.rs b/src/socket/mod.rs index 86b48d2..dbe0183 100644 --- a/src/socket/mod.rs +++ b/src/socket/mod.rs @@ -3,6 +3,7 @@ use byteorder::{BigEndian, ByteOrder}; use crate::bus::ActiveBus; use crate::register; use crate::register::socketn; +use crate::IpAddress; pub trait Socket { fn is_owned_by(&self, sockets: &OwnedSockets) -> bool; @@ -30,24 +31,79 @@ pub trait Socket { Ok(()) } + fn has_interrupt( + &self, + bus: &mut SpiBus, + code: socketn::Interrupt, + ) -> Result { + let mut data = [0u8]; + BigEndian::write_u16(&mut data, code as u16); + block!(bus.transfer_frame(self.register(), socketn::INTERRUPT_MASK, true, &mut data))?; + Ok(data[0] & socketn::Interrupt::Receive 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); + BigEndian::write_u16(&mut data, port); block!(bus.transfer_frame(self.register(), socketn::SOURCE_PORT, true, &mut data))?; Ok(()) } - fn has_received( + fn set_destination_ip( &self, bus: &mut SpiBus, - ) -> Result { - let mut data = [0u8]; - block!(bus.transfer_frame(self.register(), socketn::INTERRUPT_MASK, true, &mut data))?; - Ok(data[0] & socketn::interrupt_mask::RECEIVE != 0) + ip: IpAddress, + ) -> Result<(), SpiBus::Error> { + let mut data = ip.address; + block!(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); + block!(bus.transfer_frame(self.register(), socketn::DESTINATION_PORT, true, &mut data))?; + Ok(()) + } + + 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); + block!(bus.transfer_frame( + self.register(), + socketn::TX_DATA_READ_POINTER, + true, + &mut data + ))?; + Ok(()) + } + + 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); + block!(bus.transfer_frame( + self.register(), + socketn::TX_DATA_WRITE_POINTER, + true, + &mut data + ))?; + Ok(()) } fn get_rx_read_pointer( @@ -55,18 +111,36 @@ pub trait Socket { bus: &mut SpiBus, ) -> Result { let mut data = [0u8; 2]; - block!(bus.transfer_frame(self.register(), socketn::RX_DATA_READ_POINTER, true, &mut data))?; + block!(bus.transfer_frame( + self.register(), + socketn::RX_DATA_READ_POINTER, + true, + &mut data + ))?; Ok(BigEndian::read_u16(&data)) } - fn set_rx_read_pointer(&self, bus: &mut SpiBus, pointer: u16) -> Result<(), SpiBus::Error> { + 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); - block!(bus.transfer_frame(self.register(), socketn::RX_DATA_READ_POINTER, true, &mut data))?; + block!(bus.transfer_frame( + self.register(), + socketn::RX_DATA_READ_POINTER, + true, + &mut data + ))?; Ok(()) } - fn command(&self, bus: &mut SpiBus, command: socketn::Command) -> Result<(), SpiBus::Error> { + fn command( + &self, + bus: &mut SpiBus, + command: socketn::Command, + ) -> Result<(), SpiBus::Error> { let mut data = [0u8; 2]; BigEndian::write_u16(&mut data, command as u16); block!(bus.transfer_frame(self.register(), socketn::COMMAND, true, &mut data))?; @@ -77,9 +151,19 @@ pub trait Socket { 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]; - block!(bus.transfer_frame(self.register(), socketn::RECEIVED_SIZE, false, &mut sample_0))?; + block!(bus.transfer_frame( + self.register(), + socketn::RECEIVED_SIZE, + false, + &mut sample_0 + ))?; let mut sample_1 = [0u8; 2]; - block!(bus.transfer_frame(self.register(), socketn::RECEIVED_SIZE, false, &mut sample_1))?; + block!(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)); } diff --git a/src/udp/incoming_packet.rs b/src/udp/incoming_packet.rs index 8375fd8..3e46750 100644 --- a/src/udp/incoming_packet.rs +++ b/src/udp/incoming_packet.rs @@ -1,10 +1,10 @@ -use byteorder::{BigEndian, ByteOrder}; -use crate::udp::UdpSocket; -use crate::network::Network; use crate::bus::ActiveBus; -use crate::socket::Socket; -use crate::IpAddress; +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, @@ -14,9 +14,12 @@ pub struct IncomingPacket { write_pointer: u16, } -impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> IncomingPacket> +impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> + IncomingPacket> { - pub fn new(mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>) -> Result { + pub fn new( + mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>, + ) -> Result { let receive_size = udp_socket.socket.get_receive_size(&mut udp_socket.bus)?; // Packet frame, as described in W5200 docs sectino 5.2.2.1 @@ -25,7 +28,12 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> IncomingPa // | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... | let read_pointer = udp_socket.socket.get_rx_read_pointer(&mut udp_socket.bus)?; let mut header = [0u8; 8]; - block!(udp_socket.bus.transfer_frame(udp_socket.socket.rx_buffer(), read_pointer, false, &mut header))?; + block!(udp_socket.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]), @@ -46,21 +54,31 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> IncomingPa // 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.bus, self.write_pointer)?; - self.udp_socket.socket.command(&mut self.udp_socket.bus, socketn::Command::Receive)?; + self.udp_socket + .socket + .set_rx_read_pointer(&mut self.udp_socket.bus, self.write_pointer)?; + self.udp_socket + .socket + .command(&mut self.udp_socket.bus, socketn::Command::Receive)?; Ok(self.udp_socket) } - } -impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> Iterator for IncomingPacket> { +impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> 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 = block!(self.udp_socket.bus.transfer_frame(self.udp_socket.socket.rx_buffer(), self.read_pointer, false, &mut buffer)); + let result = block!(self.udp_socket.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 { diff --git a/src/udp/mod.rs b/src/udp/mod.rs index 498d82d..5931e4b 100644 --- a/src/udp/mod.rs +++ b/src/udp/mod.rs @@ -4,12 +4,12 @@ mod outgoing_packet; use crate::bus::ActiveBus; use crate::network::Network; -use crate::socket::{Socket, OwnedSockets}; +use crate::register::socketn; +use crate::socket::{OwnedSockets, 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::register::socketn; use crate::IpAddress; pub struct UdpSocket<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> { @@ -33,6 +33,7 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> socket.reset_interrupt(&mut bus, socketn::Interrupt::SendOk)?; socket.set_source_port(&mut bus, port)?; socket.set_mode(&mut bus, socketn::Protocol::Udp)?; + socket.command(&mut bus, socketn::Command::Open)?; Ok(UdpSocket { bus, @@ -44,7 +45,10 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> /// 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_received(&mut self.bus)? { + if !self + .socket + .has_interrupt(&mut self.bus, socketn::Interrupt::Receive)? + { Ok(None) } else { Ok(Some(IncomingPacket::new(self)?)) @@ -52,11 +56,14 @@ impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> } /// 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> { + pub fn send( + self, + host: IpAddress, + remote_port: u16, + ) -> Result, SpiBus::Error> { Ok(OutgoingPacket::new(self, host, remote_port)?) } - pub fn deactivate( self, ) -> ( diff --git a/src/udp/outgoing_packet.rs b/src/udp/outgoing_packet.rs index 952ddc0..aebf660 100644 --- a/src/udp/outgoing_packet.rs +++ b/src/udp/outgoing_packet.rs @@ -1,88 +1,72 @@ use crate::bus::ActiveBus; use crate::network::Network; +use crate::register::socketn; use crate::socket::Socket; -use crate::IpAddress; use crate::udp::UdpSocket; +use crate::IpAddress; pub struct OutgoingPacket { - udp_socket: UdpSocket + udp_socket: UdpSocket, + data_length: u16, } -impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> OutgoingPacket> { +impl<'a, SpiBus: ActiveBus, NetworkImpl: Network, SocketImpl: Socket> + OutgoingPacket> +{ + pub fn new( + mut udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>, + host: IpAddress, + port: u16, + ) -> Result { + udp_socket + .socket + .set_destination_ip(&mut udp_socket.bus, host)?; + udp_socket + .socket + .set_destination_port(&mut udp_socket.bus, port)?; + udp_socket + .socket + .set_tx_read_pointer(&mut udp_socket.bus, 0)?; + Ok(Self { + udp_socket, + data_length: 0, + }) + } - pub fn new(udp_socket: UdpSocket<'a, SpiBus, NetworkImpl, SocketImpl>, host: IpAddress, port: u16) -> Result { - Ok(Self { udp_socket }) -// let (w5500, UdpSocket(socket)) = self; + pub fn write(&mut self, mut data: &mut [u8]) -> Result<(), SpiBus::Error> { + block!(self.udp_socket.bus.transfer_frame( + self.udp_socket.socket.tx_buffer(), + self.data_length, + true, + &mut data + ))?; + self.data_length += data.len() as u16; + Ok(()) + } -// { - -// // TODO set up packet destination -// 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) -// ], -// )?; -// } - -// // TODO set read/write pointers -// 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]], -// ); -// } - -// // TODO write body to buffer -// w5500.write_to( -// socket.tx_register_at(0x00_00), -// &data[..data_length as usize], -// )?; - -// // TODO execute send command -// w5500.write_to( -// socket.at(SocketRegister::Command), -// &[SocketCommand::Send as u8], -// )?; - -// // TODO wait until send is complete -// for _ in 0..0xFFFF { -// // wait until sent -// if w5500.is_interrupt_set(*socket, Interrupt::SendOk)? { -// w5500.reset_interrupt(*socket, Interrupt::SendOk)?; -// break; -// } -// } -// // TODO listen for incoming sockets -// w5500.write_to( -// socket.at(SocketRegister::Mode), -// &[ -// Protocol::UDP as u8, // Socket Mode Register -// SocketCommand::Open as u8, // Socket Command Register -// ], -// )?; -// Ok(()) + pub fn send(mut self) -> Result, SpiBus::Error> { + self.udp_socket + .socket + .set_tx_write_pointer(&mut self.udp_socket.bus, self.data_length)?; + self.udp_socket + .socket + .command(&mut self.udp_socket.bus, socketn::Command::Send)?; + loop { + // wait until send is complete + if self + .udp_socket + .socket + .has_interrupt(&mut self.udp_socket.bus, socketn::Interrupt::SendOk)? + { + self.udp_socket + .socket + .reset_interrupt(&mut self.udp_socket.bus, socketn::Interrupt::SendOk)?; + break; + } + } + self.udp_socket + .socket + .command(&mut self.udp_socket.bus, socketn::Command::Open)?; + Ok(self.udp_socket) } }