diff --git a/Cargo.toml b/Cargo.toml index 4772295..4e0c484 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "w5500" -version = "0.1.2" +version = "0.1.3" authors = ["Michael Watzko "] repository = "https://github.com/kellerkindt/w5500.git" description = "W5500 IoT Controller implementation. Currently UDP sending and receiving is working. WIP" diff --git a/src/lib.rs b/src/lib.rs index c2db444..5481f7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,7 +93,7 @@ impl<'a> W5500<'a> { Ok(self) } - pub fn reset>(&mut self, spi: &mut S) -> Result<(), E> { + pub fn reset(&mut self, spi: &mut FullDuplex) -> Result<(), E> { self.write_to( spi, Register::CommonRegister(0x00_00_u16), @@ -103,7 +103,7 @@ impl<'a> W5500<'a> { ) } - pub fn set_mode>(&mut self, spi: &mut S, wol: bool, ping_block: bool, ppoe: bool, force_arp: bool) -> Result<(), E> { + pub fn set_mode(&mut self, spi: &mut FullDuplex, wol: bool, ping_block: bool, ppoe: bool, force_arp: bool) -> Result<(), E> { let mut mode = 0x00; @@ -130,7 +130,40 @@ impl<'a> W5500<'a> { ) } - pub fn set_gateway>(&mut self, spi: &mut S, gateway: &IpAddress) -> Result<(), E> { + pub fn set_interrupt_mask(&mut self, spi: &mut FullDuplex, sockets: &[Socket]) -> Result<(), E> { + let mut mask = 0u8; + for socket in sockets.iter() { + mask |= match *socket { + Socket::Socket0 => 1 << 0, + Socket::Socket1 => 1 << 1, + Socket::Socket2 => 1 << 2, + Socket::Socket3 => 1 << 3, + Socket::Socket4 => 1 << 4, + Socket::Socket5 => 1 << 5, + Socket::Socket6 => 1 << 6, + Socket::Socket7 => 1 << 7, + }; + } + self.write_to( + spi, + Register::CommonRegister(0x00_17_u16), + &[mask] + ) + } + + pub fn set_socket_interrupt_mask(&mut self, spi: &mut FullDuplex, socket: Socket, interrupts: &[Interrupt]) -> Result<(), E> { + let mut mask = 0u8; + for interrupt in interrupts.iter() { + mask |= *interrupt as u8; + } + self.write_to( + spi, + socket.at(SocketRegister::InterruptMask), + &[mask] + ) + } + + pub fn set_gateway(&mut self, spi: &mut FullDuplex, gateway: &IpAddress) -> Result<(), E> { self.write_to( spi, Register::CommonRegister(0x00_01_u16), @@ -138,7 +171,7 @@ impl<'a> W5500<'a> { ) } - pub fn set_subnet>(&mut self, spi: &mut S, subnet: &IpAddress) -> Result<(), E> { + pub fn set_subnet(&mut self, spi: &mut FullDuplex, subnet: &IpAddress) -> Result<(), E> { self.write_to( spi, Register::CommonRegister(0x00_05_u16), @@ -146,7 +179,7 @@ impl<'a> W5500<'a> { ) } - pub fn set_mac>(&mut self, spi: &mut S, mac: &MacAddress) -> Result<(), E> { + pub fn set_mac(&mut self, spi: &mut FullDuplex, mac: &MacAddress) -> Result<(), E> { self.write_to( spi, Register::CommonRegister(0x00_09_u16), @@ -154,7 +187,7 @@ impl<'a> W5500<'a> { ) } - pub fn get_mac>(&mut self, spi: &mut S) -> Result { + pub fn get_mac(&mut self, spi: &mut FullDuplex) -> Result { let mut mac = MacAddress::default(); self.read_from( spi, @@ -164,7 +197,7 @@ impl<'a> W5500<'a> { Ok(mac) } - pub fn set_ip>(&mut self, spi: &mut S, ip: &IpAddress) -> Result<(), E> { + pub fn set_ip(&mut self, spi: &mut FullDuplex, ip: &IpAddress) -> Result<(), E> { self.write_to( spi, Register::CommonRegister(0x00_0F_u16), @@ -172,14 +205,32 @@ impl<'a> W5500<'a> { ) } - pub fn send_udp>(&mut self, spi: &mut S, socket: Socket, local_port: u16, host: &IpAddress, host_port: u16, data: &[u8]) -> Result<(), E> { + pub fn is_interrupt_set(&mut self, spi: &mut FullDuplex, socket: Socket, interrupt: Interrupt) -> Result { + let mut state = [0u8; 1]; + self.read_from( + spi, + socket.at(SocketRegister::Interrupt), + &mut state + )?; + Ok(state[0] & interrupt as u8 != 0) + } + + pub fn reset_interrupt(&mut self, spi: &mut FullDuplex, socket: Socket, interrupt: Interrupt) -> Result<(), E> { + self.write_to( + spi, + socket.at(SocketRegister::Interrupt), + &[interrupt as u8] + ) + } + + pub fn send_udp(&mut self, spi: &mut FullDuplex, socket: Socket, local_port: u16, host: &IpAddress, host_port: u16, data: &[u8]) -> Result<(), E> { // TODO not always socket 0 // TODO check if in use self.write_to( spi, - socket.register_at(0x00_00), + socket.at(SocketRegister::Mode), &[ Protocol::UDP as u8, // Socket Mode Register SocketCommand::Open as u8 // Socket Command Regsiter @@ -192,7 +243,7 @@ impl<'a> W5500<'a> { self.write_to( spi, - socket.register_at(0x00_04), + socket.at(SocketRegister::LocalPort), &[ local_port[0], local_port[1], // local port u16 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // destination mac @@ -209,7 +260,7 @@ impl<'a> W5500<'a> { self.write_to( spi, - socket.register_at(0x00_22), + socket.at(SocketRegister::TxReadPointer), &[ 0x00, 0x00, data_length[0], data_length[1], @@ -226,22 +277,20 @@ impl<'a> W5500<'a> { self.write_to( spi, - socket.register_at(0x00_01), - &[ - 0x20 // SEND - ] + socket.at(SocketRegister::Command), + &[SocketCommand::Send as u8] ) } - pub fn listen_udp>(&mut self, spi: &mut S, socket: Socket, port: u16) -> Result<(), E> { + pub fn listen_udp(&mut self, spi: &mut FullDuplex, socket: Socket, port: u16) -> Result<(), E> { self.write_u16( spi, - socket.register_at(0x00_04), + socket.at(SocketRegister::LocalPort), port )?; self.write_to( spi, - socket.register_at(0x00_00), + socket.at(SocketRegister::Mode), &[ Protocol::UDP as u8, // Socket Mode Register SocketCommand::Open as u8 // Socket Command Regsiter @@ -250,19 +299,19 @@ impl<'a> W5500<'a> { } /// TODO destination buffer has to be as large as the receive buffer or complete read is not guaranteed - pub fn try_receive_udp>(&mut self, spi: &mut S, socket: Socket, destination: &mut [u8]) -> Result, E> { - if self.read_u8(spi, socket.register_at(0x00_2c))? & 0x04 == 0 { + pub fn try_receive_udp(&mut self, spi: &mut FullDuplex, socket: Socket, destination: &mut [u8]) -> Result, E> { + if self.read_u8(spi, socket.at(SocketRegister::InterruptMask))? & 0x04 == 0 { return Ok(None); } let receive_size = loop { - let s0 = self.read_u16(spi, socket.register_at(0x00_26))?; - let s1 = self.read_u16(spi, socket.register_at(0x00_26))?; + let s0 = self.read_u16(spi, socket.at(SocketRegister::RxReceivedSize))?; + let s1 = self.read_u16(spi, socket.at(SocketRegister::RxReceivedSize))?; if s0 == s1 { break s0 as usize; } }; if receive_size >= 8 { - let read_pointer = self.read_u16(spi, socket.register_at(0x00_28))?; + let read_pointer = self.read_u16(spi, socket.at(SocketRegister::RxReadPointer))?; // |<-- read_pointer read_pointer + received_size -->| // |Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... | @@ -282,8 +331,8 @@ impl<'a> W5500<'a> { // self.read_u16(socket.register_at(0x00_10))?; // reset - self.write_u16(spi, socket.register_at(0x00_28), read_pointer + receive_size as u16)?; - self.write_u8(spi, socket.register_at(0x00_01), SocketCommand::Recv as u8)?; + self.write_u16(spi, socket.at(SocketRegister::RxReadPointer), read_pointer + receive_size as u16)?; + self.write_u8 (spi, socket.at(SocketRegister::Command), SocketCommand::Recv as u8)?; Ok(Some((ip, port, data_length))) @@ -292,25 +341,25 @@ impl<'a> W5500<'a> { } } - pub fn read_u8>(&mut self, spi: &mut S, register: Register) -> Result { + pub fn read_u8(&mut self, spi: &mut FullDuplex, register: Register) -> Result { let mut buffer = [0u8; 1]; self.read_from(spi, register, &mut buffer)?; Ok(buffer[0]) } - pub fn read_u16>(&mut self, spi: &mut S, register: Register) -> Result { + pub fn read_u16(&mut self, spi: &mut FullDuplex, register: Register) -> Result { let mut buffer = [0u8; 2]; self.read_from(spi, register, &mut buffer)?; Ok(BigEndian::read_u16(&buffer)) } - pub fn read_ip>(&mut self, spi: &mut S, register: Register) -> Result { + pub fn read_ip(&mut self, spi: &mut FullDuplex, register: Register) -> Result { let mut ip = IpAddress::default(); self.read_from(spi, register, &mut ip.address)?; Ok(ip) } - pub fn read_from>(&mut self, spi: &mut S, register: Register, target: &mut [u8]) -> Result<(), E> { + pub fn read_from(&mut self, spi: &mut FullDuplex, register: Register, target: &mut [u8]) -> Result<(), E> { self.chip_select(); let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_READ | VARIABLE_DATA_LENGTH]; BigEndian::write_u16(&mut request[..2], register.address()); @@ -321,17 +370,17 @@ impl<'a> W5500<'a> { result } - pub fn write_u8>(&mut self, spi: &mut S, register: Register, value: u8) -> Result<(), E> { + pub fn write_u8(&mut self, spi: &mut FullDuplex, register: Register, value: u8) -> Result<(), E> { self.write_to(spi, register, &[value]) } - pub fn write_u16>(&mut self, spi: &mut S, register: Register, value: u16) -> Result<(), E> { + pub fn write_u16(&mut self, spi: &mut FullDuplex, register: Register, value: u16) -> Result<(), E> { let mut data = [0u8; 2]; BigEndian::write_u16(&mut data, value); self.write_to(spi, register, &data) } - pub fn write_to>(&mut self, spi: &mut S, register: Register, data: &[u8]) -> Result<(), E> { + pub fn write_to(&mut self, spi: &mut FullDuplex, register: Register, data: &[u8]) -> Result<(), E> { self.chip_select(); let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_WRITE | VARIABLE_DATA_LENGTH]; BigEndian::write_u16(&mut request[..2], register.address()); @@ -342,27 +391,27 @@ impl<'a> W5500<'a> { result } - fn read_bytes>(&mut self, spi: &mut S, bytes: &mut [u8]) -> Result<(), E> { + fn read_bytes(&mut self, spi: &mut FullDuplex, bytes: &mut [u8]) -> Result<(), E> { for i in 0..bytes.len() { bytes[i] = self.read(spi)?; } Ok(()) } - fn read>(&mut self, spi: &mut S) -> Result { + fn read(&mut self, spi: &mut FullDuplex) -> Result { block!(spi.send(0x00))?; let result = block!(spi.read()); result } - fn write_bytes>(&mut self, spi: &mut S, bytes: &[u8]) -> Result<(), E> { + fn write_bytes(&mut self, spi: &mut FullDuplex, bytes: &[u8]) -> Result<(), E> { for b in bytes { self.write(spi, *b)?; } Ok(()) } - fn write>(&mut self, spi: &mut S, byte: u8) -> Result<(), E> { + fn write(&mut self, spi: &mut FullDuplex, byte: u8) -> Result<(), E> { block!(spi.send(byte))?; block!(spi.read())?; Ok(()) @@ -384,6 +433,48 @@ fn u16_to_be_bytes(u16: u16) -> [u8; 2] { bytes } + +#[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 +} + + +#[repr(u8)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Interrupt { + SendOk = 1 << 4, + Timeout = 1 << 3, + Received = 1 << 2, + Disconnected = 1 << 1, + Connected = 1 << 0, +} + #[repr(u8)] #[derive(Copy, Clone, PartialEq, Debug)] pub enum Protocol { @@ -419,6 +510,19 @@ pub enum Socket { } impl 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, + } + } + fn tx_register_at(&self, address: u16) -> Register { match *self { Socket::Socket0 => Register::Socket0TxBuffer(address), @@ -457,6 +561,10 @@ impl Socket { Socket::Socket7 => Register::Socket7Register(address), } } + + fn at(&self, register: SocketRegister) -> Register { + self.register_at(register as u16) + } } #[derive(Copy, Clone, PartialEq, Debug)]