No longer consume SPI

This commit is contained in:
Michael Watzko 2018-03-31 00:26:11 +02:00
commit 6effe5c0a9
2 changed files with 69 additions and 56 deletions

2
Cargo.lock generated
View file

@ -18,7 +18,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "w5500" name = "w5500"
version = "0.1.0" version = "0.1.2"
dependencies = [ dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"embedded-hal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -75,28 +75,27 @@ impl ::core::fmt::Display for MacAddress {
} }
pub struct W5500<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> { pub struct W5500<'a> {
spi: S, cs: &'a mut OutputPin,
cs: O,
} }
impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> { impl<'a> W5500<'a> {
pub fn new(spi: S, cs: O) -> Result<W5500<E, S, O>, E> { pub fn new<E, S: FullDuplex<u8, Error=E>>(spi: &mut S, cs: &'a mut OutputPin) -> Result<W5500<'a>, E> {
W5500 { W5500 {
spi,
cs, cs,
}.init() }.init(spi)
} }
fn init(mut self) -> Result<Self, E> { fn init<E, S: FullDuplex<u8, Error=E>>(mut self, spi: &mut S) -> Result<Self, E> {
self.reset()?; self.reset(spi)?;
self.set_mode(false, false, false, false)?; self.set_mode(spi,false, false, false, false)?;
Ok(self) Ok(self)
} }
pub fn reset(&mut self) -> Result<(), E> { pub fn reset<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S) -> Result<(), E> {
self.write_to( self.write_to(
spi,
Register::CommonRegister(0x00_00_u16), Register::CommonRegister(0x00_00_u16),
&[ &[
0b1000_0000, // Mode Register (force reset) 0b1000_0000, // Mode Register (force reset)
@ -104,7 +103,7 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
) )
} }
pub fn set_mode(&mut self, wol: bool, ping_block: bool, ppoe: bool, force_arp: bool) -> Result<(), E> { pub fn set_mode<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, wol: bool, ping_block: bool, ppoe: bool, force_arp: bool) -> Result<(), E> {
let mut mode = 0x00; let mut mode = 0x00;
@ -125,54 +124,61 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
} }
self.write_to( self.write_to(
spi,
Register::CommonRegister(0x00_00_u16), Register::CommonRegister(0x00_00_u16),
&[mode] &[mode]
) )
} }
pub fn set_gateway(&mut self, gateway: &IpAddress) -> Result<(), E> { pub fn set_gateway<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, gateway: &IpAddress) -> Result<(), E> {
self.write_to( self.write_to(
spi,
Register::CommonRegister(0x00_01_u16), Register::CommonRegister(0x00_01_u16),
&gateway.address &gateway.address
) )
} }
pub fn set_subnet(&mut self, subnet: &IpAddress) -> Result<(), E> { pub fn set_subnet<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, subnet: &IpAddress) -> Result<(), E> {
self.write_to( self.write_to(
spi,
Register::CommonRegister(0x00_05_u16), Register::CommonRegister(0x00_05_u16),
&subnet.address &subnet.address
) )
} }
pub fn set_mac(&mut self, mac: &MacAddress) -> Result<(), E> { pub fn set_mac<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, mac: &MacAddress) -> Result<(), E> {
self.write_to( self.write_to(
spi,
Register::CommonRegister(0x00_09_u16), Register::CommonRegister(0x00_09_u16),
&mac.address &mac.address
) )
} }
pub fn get_mac(&mut self) -> Result<MacAddress, E> { pub fn get_mac<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S) -> Result<MacAddress, E> {
let mut mac = MacAddress::default(); let mut mac = MacAddress::default();
self.read_from( self.read_from(
spi,
Register::CommonRegister(0x00_09_u16), Register::CommonRegister(0x00_09_u16),
&mut mac.address &mut mac.address
)?; )?;
Ok(mac) Ok(mac)
} }
pub fn set_ip(&mut self, ip: &IpAddress) -> Result<(), E> { pub fn set_ip<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, ip: &IpAddress) -> Result<(), E> {
self.write_to( self.write_to(
spi,
Register::CommonRegister(0x00_0F_u16), Register::CommonRegister(0x00_0F_u16),
&ip.address &ip.address
) )
} }
pub fn send_udp(&mut self, socket: Socket, local_port: u16, host: &IpAddress, host_port: u16, data: &[u8]) -> Result<(), E> { pub fn send_udp<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, socket: Socket, local_port: u16, host: &IpAddress, host_port: u16, data: &[u8]) -> Result<(), E> {
// TODO not always socket 0 // TODO not always socket 0
// TODO check if in use // TODO check if in use
self.write_to( self.write_to(
spi,
socket.register_at(0x00_00), socket.register_at(0x00_00),
&[ &[
Protocol::UDP as u8, // Socket Mode Register Protocol::UDP as u8, // Socket Mode Register
@ -185,6 +191,7 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
let host_port = u16_to_be_bytes(host_port); let host_port = u16_to_be_bytes(host_port);
self.write_to( self.write_to(
spi,
socket.register_at(0x00_04), socket.register_at(0x00_04),
&[ &[
local_port[0], local_port[1], // local port u16 local_port[0], local_port[1], // local port u16
@ -201,6 +208,7 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
let data_length = u16_to_be_bytes(data_length); let data_length = u16_to_be_bytes(data_length);
self.write_to( self.write_to(
spi,
socket.register_at(0x00_22), socket.register_at(0x00_22),
&[ &[
0x00, 0x00, 0x00, 0x00,
@ -211,11 +219,13 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
self.write_to( self.write_to(
spi,
socket.tx_register_at(0x00_00), socket.tx_register_at(0x00_00),
&data[..data_length as usize] &data[..data_length as usize]
); );
self.write_to( self.write_to(
spi,
socket.register_at(0x00_01), socket.register_at(0x00_01),
&[ &[
0x20 // SEND 0x20 // SEND
@ -223,12 +233,14 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
) )
} }
pub fn listen_udp(&mut self, socket: Socket, port: u16) -> Result<(), E> { pub fn listen_udp<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, socket: Socket, port: u16) -> Result<(), E> {
self.write_u16( self.write_u16(
spi,
socket.register_at(0x00_04), socket.register_at(0x00_04),
port port
)?; )?;
self.write_to( self.write_to(
spi,
socket.register_at(0x00_00), socket.register_at(0x00_00),
&[ &[
Protocol::UDP as u8, // Socket Mode Register Protocol::UDP as u8, // Socket Mode Register
@ -238,29 +250,30 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
} }
/// TODO destination buffer has to be as large as the receive buffer or complete read is not guaranteed /// 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, socket: Socket, destination: &mut [u8]) -> Result<Option<(IpAddress, u16, usize)>, E> { pub fn try_receive_udp<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, socket: Socket, destination: &mut [u8]) -> Result<Option<(IpAddress, u16, usize)>, E> {
if self.read_u8(socket.register_at(0x00_2c))? & 0x04 == 0 { if self.read_u8(spi, socket.register_at(0x00_2c))? & 0x04 == 0 {
return Ok(None); return Ok(None);
} }
let receive_size = loop { let receive_size = loop {
let s0 = self.read_u16(socket.register_at(0x00_26))?; let s0 = self.read_u16(spi, socket.register_at(0x00_26))?;
let s1 = self.read_u16(socket.register_at(0x00_26))?; let s1 = self.read_u16(spi, socket.register_at(0x00_26))?;
if s0 == s1 { if s0 == s1 {
break s0 as usize; break s0 as usize;
} }
}; };
if receive_size >= 8 { if receive_size >= 8 {
let read_pointer = self.read_u16(socket.register_at(0x00_28))?; let read_pointer = self.read_u16(spi, socket.register_at(0x00_28))?;
// |<-- read_pointer read_pointer + received_size -->| // |<-- read_pointer read_pointer + received_size -->|
// |Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... | // |Destination IP Address | Destination Port | Byte Size of DATA | Actual DATA ... |
// | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... | // | --- 4 Bytes --- | --- 2 Bytes --- | --- 2 Bytes --- | .... |
let ip = self.read_ip(socket.rx_register_at(read_pointer))?; let ip = self.read_ip(spi, socket.rx_register_at(read_pointer))?;
let port = self.read_u16(socket.rx_register_at(read_pointer+4))?; let port = self.read_u16(spi, socket.rx_register_at(read_pointer+4))?;
let data_length = destination.len().min(self.read_u16(socket.rx_register_at(read_pointer+6))? as usize); let data_length = destination.len().min(self.read_u16(spi, socket.rx_register_at(read_pointer+6))? as usize);
self.read_from( self.read_from(
spi,
socket.rx_register_at(read_pointer+8), socket.rx_register_at(read_pointer+8),
&mut destination[..data_length] &mut destination[..data_length]
)?; )?;
@ -269,8 +282,8 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
// self.read_u16(socket.register_at(0x00_10))?; // self.read_u16(socket.register_at(0x00_10))?;
// reset // reset
self.write_u16(socket.register_at(0x00_28), read_pointer + receive_size as u16)?; self.write_u16(spi, socket.register_at(0x00_28), read_pointer + receive_size as u16)?;
self.write_u8(socket.register_at(0x00_01), SocketCommand::Recv as u8)?; self.write_u8(spi, socket.register_at(0x00_01), SocketCommand::Recv as u8)?;
Ok(Some((ip, port, data_length))) Ok(Some((ip, port, data_length)))
@ -279,79 +292,79 @@ impl<E, S: FullDuplex<u8, Error=E> + Sized, O: OutputPin> W5500<E, S, O> {
} }
} }
pub fn read_u8(&mut self, register: Register) -> Result<u8, E> { pub fn read_u8<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, register: Register) -> Result<u8, E> {
let mut buffer = [0u8; 1]; let mut buffer = [0u8; 1];
self.read_from(register, &mut buffer)?; self.read_from(spi, register, &mut buffer)?;
Ok(buffer[0]) Ok(buffer[0])
} }
pub fn read_u16(&mut self, register: Register) -> Result<u16, E> { pub fn read_u16<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, register: Register) -> Result<u16, E> {
let mut buffer = [0u8; 2]; let mut buffer = [0u8; 2];
self.read_from(register, &mut buffer)?; self.read_from(spi, register, &mut buffer)?;
Ok(BigEndian::read_u16(&buffer)) Ok(BigEndian::read_u16(&buffer))
} }
pub fn read_ip(&mut self, register: Register) -> Result<IpAddress, E> { pub fn read_ip<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, register: Register) -> Result<IpAddress, E> {
let mut ip = IpAddress::default(); let mut ip = IpAddress::default();
self.read_from(register, &mut ip.address)?; self.read_from(spi, register, &mut ip.address)?;
Ok(ip) Ok(ip)
} }
pub fn read_from(&mut self, register: Register, target: &mut [u8]) -> Result<(), E> { pub fn read_from<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, register: Register, target: &mut [u8]) -> Result<(), E> {
self.chip_select(); self.chip_select();
let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_READ | VARIABLE_DATA_LENGTH]; let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_READ | VARIABLE_DATA_LENGTH];
BigEndian::write_u16(&mut request[..2], register.address()); BigEndian::write_u16(&mut request[..2], register.address());
let result = self let result = self
.write_bytes(&request) .write_bytes(spi, &request)
.and_then(|_| self.read_bytes(target)); .and_then(|_| self.read_bytes(spi, target));
self.chip_deselect(); self.chip_deselect();
result result
} }
pub fn write_u8(&mut self, register: Register, value: u8) -> Result<(), E> { pub fn write_u8<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, register: Register, value: u8) -> Result<(), E> {
self.write_to(register, &[value]) self.write_to(spi, register, &[value])
} }
pub fn write_u16(&mut self, register: Register, value: u16) -> Result<(), E> { pub fn write_u16<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, register: Register, value: u16) -> Result<(), E> {
let mut data = [0u8; 2]; let mut data = [0u8; 2];
BigEndian::write_u16(&mut data, value); BigEndian::write_u16(&mut data, value);
self.write_to(register, &data) self.write_to(spi, register, &data)
} }
pub fn write_to(&mut self, register: Register, data: &[u8]) -> Result<(), E> { pub fn write_to<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, register: Register, data: &[u8]) -> Result<(), E> {
self.chip_select(); self.chip_select();
let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_WRITE | VARIABLE_DATA_LENGTH]; let mut request = [0_u8, 0_u8, register.control_byte() | COMMAND_WRITE | VARIABLE_DATA_LENGTH];
BigEndian::write_u16(&mut request[..2], register.address()); BigEndian::write_u16(&mut request[..2], register.address());
let result = self let result = self
.write_bytes(&request) .write_bytes(spi, &request)
.and_then(|_| self.write_bytes(data)); .and_then(|_| self.write_bytes(spi, data));
self.chip_deselect(); self.chip_deselect();
result result
} }
fn read_bytes(&mut self, bytes: &mut [u8]) -> Result<(), E> { fn read_bytes<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, bytes: &mut [u8]) -> Result<(), E> {
for i in 0..bytes.len() { for i in 0..bytes.len() {
bytes[i] = self.read()?; bytes[i] = self.read(spi)?;
} }
Ok(()) Ok(())
} }
fn read(&mut self) -> Result<u8, E> { fn read<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S) -> Result<u8, E> {
block!(self.spi.send(0x00))?; block!(spi.send(0x00))?;
let result = block!(self.spi.read()); let result = block!(spi.read());
result result
} }
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), E> { fn write_bytes<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, bytes: &[u8]) -> Result<(), E> {
for b in bytes { for b in bytes {
self.write(*b)?; self.write(spi, *b)?;
} }
Ok(()) Ok(())
} }
fn write(&mut self, byte: u8) -> Result<(), E> { fn write<E, S: FullDuplex<u8, Error=E>>(&mut self, spi: &mut S, byte: u8) -> Result<(), E> {
block!(self.spi.send(byte))?; block!(spi.send(byte))?;
block!(self.spi.read())?; block!(spi.read())?;
Ok(()) Ok(())
} }