w5500_ll/lib.rs
1//! Platform agnostic rust driver for the [Wiznet W5500] SPI internet offload
2//! chip.
3//!
4//! This is a low-level (ll) crate. The scope of this crate is:
5//! 1) Register accessors.
6//! 2) Networking data types.
7//!
8//! Higher level functionality (such as socket operations) should be built
9//! on-top of what is provided here.
10//!
11//! # Example
12//!
13//! Reading the VERSIONR register (a constant value).
14//!
15//! ```
16//! # let spi = ehm::eh1::spi::Mock::new(&[
17//! # ehm::eh1::spi::Transaction::transaction_start(),
18//! # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x39, 0x00]),
19//! # ehm::eh1::spi::Transaction::read(0x04),
20//! # ehm::eh1::spi::Transaction::transaction_end(),
21//! # ]);
22//! use w5500_ll::{eh1::vdm::W5500, Registers};
23//!
24//! let mut w5500 = W5500::new(spi);
25//! let version: u8 = w5500.version()?;
26//! assert_eq!(version, 0x04);
27//! # w5500.free().done();
28//! # Ok::<(), eh1::spi::ErrorKind>(())
29//! ```
30//!
31//! # Feature Flags
32//!
33//! All features are disabled by default.
34//!
35//! * `defmt`: Enable formatting most types with `defmt`.
36//! * `eh0`: Enables the [`eh0`] module which contains
37//! implementations of the [`Registers`] trait
38//! using the `embedded-hal` version 0.2 traits.
39//! * `eh1`: Enables the [`eh1`] module which contains
40//! implementations of the [`Registers`] trait
41//! using the `embedded-hal` version 1 traits.
42//! * `eha1`:
43//! Implements the [`aio::Registers`] trait for types in the [`eh1`] module
44//! using the `embedded-hal-async` traits.
45//!
46//! [Wiznet W5500]: https://www.wiznet.io/product-item/w5500/
47//! [`aio::Registers`]: https://docs.rs/w5500-ll/latest/w5500_ll/aio/trait.Registers.html
48//! [`aio`]: https://docs.rs/w5500-ll/latest/w5500_ll/aio/index.html
49//! [`eh0`]: https://docs.rs/w5500-ll/latest/w5500_ll/eh0/index.html
50//! [`eh1`]: https://docs.rs/w5500-ll/latest/w5500_ll/eh1/index.html
51//! [`Registers`]: https://docs.rs/w5500-ll/latest/w5500_ll/trait.Registers.html
52#![cfg_attr(docsrs, feature(doc_cfg), feature(doc_auto_cfg))]
53#![no_std]
54#![allow(async_fn_in_trait)] // https://github.com/rust-embedded/embedded-hal/pull/515#issuecomment-1763525962
55#![forbid(unsafe_code)]
56#![warn(missing_docs)]
57
58pub mod aio;
59
60#[cfg(feature = "eh0")]
61pub mod eh0;
62#[cfg(feature = "eh1")]
63pub mod eh1;
64
65pub mod net;
66pub mod spi;
67
68mod addr;
69mod registers;
70mod specifiers;
71use net::{Eui48Addr, Ipv4Addr, SocketAddrV4};
72
73pub use addr::{Reg, SnReg};
74pub use registers::{Interrupt, Mode, PhyCfg, SocketInterrupt, SocketInterruptMask, SocketMode};
75pub use specifiers::{
76 BufferSize, DuplexStatus, LinkStatus, OperationMode, Protocol, SocketCommand, SocketStatus,
77 SpeedStatus,
78};
79
80/// Common register block address offset.
81pub const COMMON_BLOCK_OFFSET: u8 = 0x00;
82/// Socket spacing between blocks.
83const SOCKET_SPACING: u8 = 0x04;
84/// Socket common block select bits offset.
85const SOCKET_BLOCK_OFFSET: u8 = 0x01;
86/// Socket TX block select bits offset
87const SOCKET_TX_OFFSET: u8 = 0x02;
88/// Socket RX block select bits offset
89const SOCKET_RX_OFFSET: u8 = 0x03;
90
91/// Value of the W5500 VERSIONR register.
92///
93/// This is very useful as a sanity check to ensure the W5500 is out of reset
94/// and responding correctly to register reads.
95///
96/// # Example
97///
98/// ```
99/// # use ehm::eh1 as hal;
100/// # let spi = ehm::eh1::spi::Mock::new(&[
101/// # ehm::eh1::spi::Transaction::transaction_start(),
102/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x39, 0x00]),
103/// # ehm::eh1::spi::Transaction::read(0x04),
104/// # ehm::eh1::spi::Transaction::transaction_end(),
105/// # ]);
106/// use w5500_ll::{eh1::vdm::W5500, Registers, VERSION};
107///
108/// let mut w5500 = W5500::new(spi);
109/// let version: u8 = w5500.version()?;
110/// assert_eq!(version, VERSION);
111/// # w5500.free().done();
112/// # Ok::<(), eh1::spi::ErrorKind>(())
113/// ```
114pub const VERSION: u8 = 0x04;
115
116/// W5500 socket numbers.
117#[repr(u8)]
118#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug, Hash)]
119#[cfg_attr(feature = "defmt", derive(defmt::Format))]
120pub enum Sn {
121 /// Socket 0.
122 ///
123 /// This is the only socket that can be used in the [`Macraw`] mode.
124 ///
125 /// [`Macraw`]: crate::Protocol::Macraw
126 Sn0 = 0,
127 /// Socket 1.
128 Sn1 = 1,
129 /// Socket 2.
130 Sn2 = 2,
131 /// Socket 3.
132 Sn3 = 3,
133 /// Socket 4.
134 Sn4 = 4,
135 /// Socket 5.
136 Sn5 = 5,
137 /// Socket 6.
138 Sn6 = 6,
139 /// Socket 7.
140 Sn7 = 7,
141}
142
143impl Sn {
144 /// Get the socket register block select bits.
145 ///
146 /// # Example
147 ///
148 /// ```
149 /// use w5500_ll::Sn;
150 ///
151 /// assert_eq!(Sn::Sn0.block(), 0b00001);
152 /// assert_eq!(Sn::Sn1.block(), 0b00101);
153 /// assert_eq!(Sn::Sn2.block(), 0b01001);
154 /// assert_eq!(Sn::Sn3.block(), 0b01101);
155 /// assert_eq!(Sn::Sn4.block(), 0b10001);
156 /// assert_eq!(Sn::Sn5.block(), 0b10101);
157 /// assert_eq!(Sn::Sn6.block(), 0b11001);
158 /// assert_eq!(Sn::Sn7.block(), 0b11101);
159 /// ```
160 #[inline]
161 pub const fn block(self) -> u8 {
162 SOCKET_SPACING * (self as u8) + SOCKET_BLOCK_OFFSET
163 }
164
165 /// Get the socket TX buffer block select bits.
166 ///
167 /// # Example
168 ///
169 /// ```
170 /// use w5500_ll::Sn;
171 ///
172 /// assert_eq!(Sn::Sn0.tx_block(), 0b00010);
173 /// assert_eq!(Sn::Sn1.tx_block(), 0b00110);
174 /// assert_eq!(Sn::Sn2.tx_block(), 0b01010);
175 /// assert_eq!(Sn::Sn3.tx_block(), 0b01110);
176 /// assert_eq!(Sn::Sn4.tx_block(), 0b10010);
177 /// assert_eq!(Sn::Sn5.tx_block(), 0b10110);
178 /// assert_eq!(Sn::Sn6.tx_block(), 0b11010);
179 /// assert_eq!(Sn::Sn7.tx_block(), 0b11110);
180 /// ```
181 #[inline]
182 pub const fn tx_block(self) -> u8 {
183 SOCKET_SPACING * (self as u8) + SOCKET_TX_OFFSET
184 }
185
186 /// Get the socket RX buffer block select bits.
187 ///
188 /// # Example
189 ///
190 /// ```
191 /// use w5500_ll::Sn;
192 ///
193 /// assert_eq!(Sn::Sn0.rx_block(), 0b00011);
194 /// assert_eq!(Sn::Sn1.rx_block(), 0b00111);
195 /// assert_eq!(Sn::Sn2.rx_block(), 0b01011);
196 /// assert_eq!(Sn::Sn3.rx_block(), 0b01111);
197 /// assert_eq!(Sn::Sn4.rx_block(), 0b10011);
198 /// assert_eq!(Sn::Sn5.rx_block(), 0b10111);
199 /// assert_eq!(Sn::Sn6.rx_block(), 0b11011);
200 /// assert_eq!(Sn::Sn7.rx_block(), 0b11111);
201 /// ```
202 #[inline]
203 pub const fn rx_block(self) -> u8 {
204 SOCKET_SPACING * (self as u8) + SOCKET_RX_OFFSET
205 }
206
207 /// Socket bitmask.
208 ///
209 /// This is useful for masking socket interrupts with [`set_simr`].
210 ///
211 /// # Examples
212 ///
213 /// Demonstration:
214 ///
215 /// ```
216 /// use w5500_ll::Sn;
217 ///
218 /// assert_eq!(Sn::Sn0.bitmask(), 0x01);
219 /// assert_eq!(Sn::Sn1.bitmask(), 0x02);
220 /// assert_eq!(Sn::Sn2.bitmask(), 0x04);
221 /// assert_eq!(Sn::Sn3.bitmask(), 0x08);
222 /// assert_eq!(Sn::Sn4.bitmask(), 0x10);
223 /// assert_eq!(Sn::Sn5.bitmask(), 0x20);
224 /// assert_eq!(Sn::Sn6.bitmask(), 0x40);
225 /// assert_eq!(Sn::Sn7.bitmask(), 0x80);
226 /// ```
227 ///
228 /// As an argument of [`set_simr`]:
229 ///
230 /// ```
231 /// # let spi = ehm::eh1::spi::Mock::new(&[
232 /// # ehm::eh1::spi::Transaction::transaction_start(),
233 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x18, 0x04]),
234 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x0A]),
235 /// # ehm::eh1::spi::Transaction::transaction_end(),
236 /// # ]);
237 /// use w5500_ll::{
238 /// eh1::vdm::W5500,
239 /// Registers,
240 /// Sn::{Sn1, Sn3},
241 /// };
242 ///
243 /// let mut w5500 = W5500::new(spi);
244 /// // enable socket 1 and socket 3 interrupts
245 /// const SOCKET_INTERRUPT_MASK: u8 = Sn1.bitmask() | Sn3.bitmask();
246 /// w5500.set_simr(SOCKET_INTERRUPT_MASK)?;
247 /// # w5500.free().done();
248 /// # Ok::<(), eh1::spi::ErrorKind>(())
249 /// ```
250 ///
251 /// [`set_simr`]: crate::Registers::set_simr
252 pub const fn bitmask(self) -> u8 {
253 1 << (self as u8)
254 }
255
256 /// Iterate over all sockets.
257 ///
258 /// # Example
259 ///
260 /// Check all sockets for a pending interrupt.
261 ///
262 /// ```
263 /// # let spi = ehm::eh1::spi::Mock::new(&[
264 /// # ehm::eh1::spi::Transaction::transaction_start(),
265 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x17, 0x00]),
266 /// # ehm::eh1::spi::Transaction::read(0),
267 /// # ehm::eh1::spi::Transaction::transaction_end(),
268 /// # ]);
269 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
270 ///
271 /// let mut w5500 = W5500::new(spi);
272 ///
273 /// let sir: u8 = w5500.sir()?;
274 /// for sn in Sn::iter() {
275 /// let mask: u8 = sn.bitmask();
276 /// if sir & sn.bitmask() != 0 {
277 /// // handle socket interrupt
278 /// }
279 /// }
280 /// # w5500.free().done();
281 /// # Ok::<(), eh1::spi::ErrorKind>(())
282 /// ```
283 #[inline]
284 pub fn iter() -> core::slice::Iter<'static, Self> {
285 SOCKETS.iter()
286 }
287}
288
289macro_rules! sn_conversion_for {
290 ($ty:ident) => {
291 impl From<Sn> for $ty {
292 #[inline]
293 fn from(s: Sn) -> Self {
294 s as $ty
295 }
296 }
297
298 impl TryFrom<$ty> for Sn {
299 type Error = $ty;
300
301 #[inline]
302 fn try_from(val: $ty) -> Result<Sn, $ty> {
303 match val {
304 0 => Ok(Sn::Sn0),
305 1 => Ok(Sn::Sn1),
306 2 => Ok(Sn::Sn2),
307 3 => Ok(Sn::Sn3),
308 4 => Ok(Sn::Sn4),
309 5 => Ok(Sn::Sn5),
310 6 => Ok(Sn::Sn6),
311 7 => Ok(Sn::Sn7),
312 x => Err(x),
313 }
314 }
315 }
316 };
317}
318
319sn_conversion_for!(u8);
320sn_conversion_for!(u16);
321sn_conversion_for!(u32);
322sn_conversion_for!(u64);
323sn_conversion_for!(u128);
324sn_conversion_for!(usize);
325sn_conversion_for!(i8);
326sn_conversion_for!(i16);
327sn_conversion_for!(i32);
328sn_conversion_for!(i64);
329sn_conversion_for!(i128);
330sn_conversion_for!(isize);
331
332/// Array of all sockets.
333///
334/// Useful for iterating over sockets.
335///
336/// # Example
337///
338/// Close all sockets.
339///
340/// ```
341/// # use w5500_ll::Sn::*;
342/// # use ehm::eh1 as hal;
343/// # let spi = ehm::eh1::spi::Mock::new(&[
344/// # ehm::eh1::spi::Transaction::transaction_start(),
345/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn0.block() << 3) | 0x04]),
346/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
347/// # ehm::eh1::spi::Transaction::transaction_end(),
348/// # ehm::eh1::spi::Transaction::transaction_start(),
349/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn1.block() << 3) | 0x04]),
350/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
351/// # ehm::eh1::spi::Transaction::transaction_end(),
352/// # ehm::eh1::spi::Transaction::transaction_start(),
353/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn2.block() << 3) | 0x04]),
354/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
355/// # ehm::eh1::spi::Transaction::transaction_end(),
356/// # ehm::eh1::spi::Transaction::transaction_start(),
357/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn3.block() << 3) | 0x04]),
358/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
359/// # ehm::eh1::spi::Transaction::transaction_end(),
360/// # ehm::eh1::spi::Transaction::transaction_start(),
361/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn4.block() << 3) | 0x04]),
362/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
363/// # ehm::eh1::spi::Transaction::transaction_end(),
364/// # ehm::eh1::spi::Transaction::transaction_start(),
365/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn5.block() << 3) | 0x04]),
366/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
367/// # ehm::eh1::spi::Transaction::transaction_end(),
368/// # ehm::eh1::spi::Transaction::transaction_start(),
369/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn6.block() << 3) | 0x04]),
370/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
371/// # ehm::eh1::spi::Transaction::transaction_end(),
372/// # ehm::eh1::spi::Transaction::transaction_start(),
373/// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, (Sn7.block() << 3) | 0x04]),
374/// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Close.into()]),
375/// # ehm::eh1::spi::Transaction::transaction_end(),
376/// # ]);
377/// use w5500_ll::{eh1::vdm::W5500, Registers, SocketCommand, SOCKETS};
378///
379/// let mut w5500 = W5500::new(spi);
380/// for socket in SOCKETS.iter() {
381/// w5500.set_sn_cr(*socket, SocketCommand::Close)?;
382/// }
383/// # w5500.free().done();
384/// # Ok::<(), eh1::spi::ErrorKind>(())
385/// ```
386pub const SOCKETS: [Sn; 8] = [
387 Sn::Sn0,
388 Sn::Sn1,
389 Sn::Sn2,
390 Sn::Sn3,
391 Sn::Sn4,
392 Sn::Sn5,
393 Sn::Sn6,
394 Sn::Sn7,
395];
396
397/// TX socket buffer pointers.
398///
399/// Returned by [`Registers::sn_tx_ptrs`] and [`aio::Registers::sn_tx_ptrs`].
400#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug, Hash)]
401#[cfg_attr(feature = "defmt", derive(defmt::Format))]
402pub struct TxPtrs {
403 /// Free size.
404 pub fsr: u16,
405 /// Write pointer.
406 pub wr: u16,
407}
408
409/// RX socket buffer pointers.
410///
411/// Returned by [`Registers::sn_rx_ptrs`] and [`aio::Registers::sn_rx_ptrs`].
412#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug, Hash)]
413#[cfg_attr(feature = "defmt", derive(defmt::Format))]
414pub struct RxPtrs {
415 /// Received size.
416 pub rsr: u16,
417 /// Read pointer.
418 pub rd: u16,
419}
420
421/// W5500 register setters and getters.
422///
423/// * All register getters are simply the name of the register.
424/// * All register setters are the name of the register prefixed with `set_`.
425///
426/// Most of the register documentation is taken from the data sheet.
427pub trait Registers {
428 /// Register accessor error type.
429 type Error;
430
431 /// Read from the W5500.
432 ///
433 /// # Arguments
434 ///
435 /// * `addr` - Starting address of the memory being read.
436 /// * `block` - W5500 block select bits
437 /// * `data` - Buffer to read data into. The number of bytes read is equal
438 /// to the length of this buffer.
439 fn read(&mut self, addr: u16, block: u8, data: &mut [u8]) -> Result<(), Self::Error>;
440
441 /// Write to the W5500.
442 ///
443 /// # Arguments
444 ///
445 /// * `addr` - Starting address of the memory being written.
446 /// * `block` - W5500 block select bits
447 /// * `data` - Buffer of data to write. The number of bytes written is equal
448 /// to the length of this buffer.
449 fn write(&mut self, addr: u16, block: u8, data: &[u8]) -> Result<(), Self::Error>;
450
451 /// Get the mode register.
452 ///
453 /// # Example
454 ///
455 /// ```
456 /// # let spi = ehm::eh1::spi::Mock::new(&[
457 /// # ehm::eh1::spi::Transaction::transaction_start(),
458 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x00]),
459 /// # ehm::eh1::spi::Transaction::read(0),
460 /// # ehm::eh1::spi::Transaction::transaction_end(),
461 /// # ]);
462 /// use w5500_ll::{eh1::vdm::W5500, Mode, Registers};
463 ///
464 /// let mut w5500 = W5500::new(spi);
465 /// let mode: Mode = w5500.mr()?;
466 /// assert_eq!(mode, Mode::default());
467 /// # w5500.free().done();
468 /// # Ok::<(), eh1::spi::ErrorKind>(())
469 /// ```
470 fn mr(&mut self) -> Result<Mode, Self::Error> {
471 let mut reg: [u8; 1] = [0];
472 self.read(Reg::MR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
473 Ok(Mode::from(reg[0]))
474 }
475
476 /// Set the mode register.
477 ///
478 /// # Example
479 ///
480 /// ```
481 /// # let spi = ehm::eh1::spi::Mock::new(&[
482 /// # ehm::eh1::spi::Transaction::transaction_start(),
483 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x04]),
484 /// # ehm::eh1::spi::Transaction::write(w5500_ll::Mode::WOL_MASK),
485 /// # ehm::eh1::spi::Transaction::transaction_end(),
486 /// # ]);
487 /// use w5500_ll::{eh1::vdm::W5500, Mode, Registers};
488 ///
489 /// const MODE: Mode = Mode::DEFAULT.enable_wol();
490 /// let mut w5500 = W5500::new(spi);
491 /// w5500.set_mr(MODE)?;
492 /// # w5500.free().done();
493 /// # Ok::<(), eh1::spi::ErrorKind>(())
494 /// ```
495 fn set_mr(&mut self, mode: Mode) -> Result<(), Self::Error> {
496 self.write(Reg::MR.addr(), COMMON_BLOCK_OFFSET, &[mode.into()])
497 }
498
499 /// Get the gateway IP address.
500 ///
501 /// # Example
502 ///
503 /// ```
504 /// # let spi = ehm::eh1::spi::Mock::new(&[
505 /// # ehm::eh1::spi::Transaction::transaction_start(),
506 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x00]),
507 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
508 /// # ehm::eh1::spi::Transaction::transaction_end(),
509 /// # ]);
510 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
511 ///
512 /// let mut w5500 = W5500::new(spi);
513 /// let gar = w5500.gar()?;
514 /// assert_eq!(gar, Ipv4Addr::UNSPECIFIED);
515 /// # w5500.free().done();
516 /// # Ok::<(), eh1::spi::ErrorKind>(())
517 /// ```
518 fn gar(&mut self) -> Result<Ipv4Addr, Self::Error> {
519 let mut gar: [u8; 4] = [0; 4];
520 self.read(Reg::GAR0.addr(), COMMON_BLOCK_OFFSET, &mut gar)?;
521 Ok(gar.into())
522 }
523
524 /// Set the gateway IP address.
525 ///
526 /// # Example
527 ///
528 /// ```
529 /// # let spi = ehm::eh1::spi::Mock::new(&[
530 /// # ehm::eh1::spi::Transaction::transaction_start(),
531 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x04]),
532 /// # ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 1]),
533 /// # ehm::eh1::spi::Transaction::transaction_end(),
534 /// # ]);
535 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
536 ///
537 /// let mut w5500 = W5500::new(spi);
538 /// w5500.set_gar(&Ipv4Addr::new(192, 168, 0, 1))?;
539 /// # w5500.free().done();
540 /// # Ok::<(), eh1::spi::ErrorKind>(())
541 /// ```
542 fn set_gar(&mut self, gar: &Ipv4Addr) -> Result<(), Self::Error> {
543 self.write(Reg::GAR0.addr(), COMMON_BLOCK_OFFSET, &gar.octets())
544 }
545
546 /// Get the subnet mask.
547 ///
548 /// # Example
549 ///
550 /// ```
551 /// # let spi = ehm::eh1::spi::Mock::new(&[
552 /// # ehm::eh1::spi::Transaction::transaction_start(),
553 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x05, 0x00]),
554 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
555 /// # ehm::eh1::spi::Transaction::transaction_end(),
556 /// # ]);
557 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
558 ///
559 /// let mut w5500 = W5500::new(spi);
560 /// let subr = w5500.subr()?;
561 /// assert_eq!(subr, Ipv4Addr::UNSPECIFIED);
562 /// # w5500.free().done();
563 /// # Ok::<(), eh1::spi::ErrorKind>(())
564 /// ```
565 fn subr(&mut self) -> Result<Ipv4Addr, Self::Error> {
566 let mut subr: [u8; 4] = [0; 4];
567 self.read(Reg::SUBR0.addr(), COMMON_BLOCK_OFFSET, &mut subr)?;
568 Ok(subr.into())
569 }
570
571 /// Set the subnet mask.
572 ///
573 /// # Example
574 ///
575 /// ```
576 /// # let spi = ehm::eh1::spi::Mock::new(&[
577 /// # ehm::eh1::spi::Transaction::transaction_start(),
578 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x05, 0x04]),
579 /// # ehm::eh1::spi::Transaction::write_vec(vec![255, 255, 255, 0]),
580 /// # ehm::eh1::spi::Transaction::transaction_end(),
581 /// # ]);
582 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
583 ///
584 /// let mut w5500 = W5500::new(spi);
585 /// w5500.set_subr(&Ipv4Addr::new(255, 255, 255, 0))?;
586 /// # w5500.free().done();
587 /// # Ok::<(), eh1::spi::ErrorKind>(())
588 /// ```
589 fn set_subr(&mut self, subr: &Ipv4Addr) -> Result<(), Self::Error> {
590 self.write(Reg::SUBR0.addr(), COMMON_BLOCK_OFFSET, &subr.octets())
591 }
592
593 /// Get the source hardware address.
594 ///
595 /// # Example
596 ///
597 /// ```
598 /// # let spi = ehm::eh1::spi::Mock::new(&[
599 /// # ehm::eh1::spi::Transaction::transaction_start(),
600 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x09, 0x00]),
601 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0, 0, 0]),
602 /// # ehm::eh1::spi::Transaction::transaction_end(),
603 /// # ]);
604 /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
605 ///
606 /// let mut w5500 = W5500::new(spi);
607 /// let shar = w5500.shar()?;
608 /// assert_eq!(shar, Eui48Addr::UNSPECIFIED);
609 /// # w5500.free().done();
610 /// # Ok::<(), eh1::spi::ErrorKind>(())
611 /// ```
612 fn shar(&mut self) -> Result<Eui48Addr, Self::Error> {
613 let mut shar = Eui48Addr::UNSPECIFIED;
614 self.read(Reg::SHAR0.addr(), COMMON_BLOCK_OFFSET, &mut shar.octets)?;
615 Ok(shar)
616 }
617
618 /// Set the source hardware address.
619 ///
620 /// # Example
621 ///
622 /// ```
623 /// # let spi = ehm::eh1::spi::Mock::new(&[
624 /// # ehm::eh1::spi::Transaction::transaction_start(),
625 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x09, 0x04]),
626 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0, 0, 0, 0]),
627 /// # ehm::eh1::spi::Transaction::transaction_end(),
628 /// # ]);
629 /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
630 ///
631 /// let mut w5500 = W5500::new(spi);
632 /// w5500.set_shar(&Eui48Addr::new(0x12, 0x34, 0x00, 0x00, 0x00, 0x00))?;
633 /// # w5500.free().done();
634 /// # Ok::<(), eh1::spi::ErrorKind>(())
635 /// ```
636 fn set_shar(&mut self, shar: &Eui48Addr) -> Result<(), Self::Error> {
637 self.write(Reg::SHAR0.addr(), COMMON_BLOCK_OFFSET, &shar.octets)
638 }
639
640 /// Get the source (client) IP address.
641 ///
642 /// # Example
643 ///
644 /// ```
645 /// # let spi = ehm::eh1::spi::Mock::new(&[
646 /// # ehm::eh1::spi::Transaction::transaction_start(),
647 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0F, 0x00]),
648 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
649 /// # ehm::eh1::spi::Transaction::transaction_end(),
650 /// # ]);
651 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
652 ///
653 /// let mut w5500 = W5500::new(spi);
654 /// let sipr = w5500.sipr()?;
655 /// assert_eq!(sipr, Ipv4Addr::UNSPECIFIED);
656 /// # w5500.free().done();
657 /// # Ok::<(), eh1::spi::ErrorKind>(())
658 /// ```
659 fn sipr(&mut self) -> Result<Ipv4Addr, Self::Error> {
660 let mut sipr: [u8; 4] = [0; 4];
661 self.read(Reg::SIPR0.addr(), COMMON_BLOCK_OFFSET, &mut sipr)?;
662 Ok(sipr.into())
663 }
664
665 /// Set the source (client) IP address.
666 ///
667 /// # Example
668 ///
669 /// ```
670 /// # let spi = ehm::eh1::spi::Mock::new(&[
671 /// # ehm::eh1::spi::Transaction::transaction_start(),
672 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0F, 0x04]),
673 /// # ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 150]),
674 /// # ehm::eh1::spi::Transaction::transaction_end(),
675 /// # ]);
676 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
677 ///
678 /// let mut w5500 = W5500::new(spi);
679 /// w5500.set_sipr(&Ipv4Addr::new(192, 168, 0, 150))?;
680 /// # w5500.free().done();
681 /// # Ok::<(), eh1::spi::ErrorKind>(())
682 /// ```
683 fn set_sipr(&mut self, sipr: &Ipv4Addr) -> Result<(), Self::Error> {
684 self.write(Reg::SIPR0.addr(), COMMON_BLOCK_OFFSET, &sipr.octets())
685 }
686
687 /// Get the interrupt low level time.
688 ///
689 /// INTLEVEL configures the assert wait time (I<sub>AWT</sub>).
690 ///
691 /// When the next interrupt occurs, the interrupt in (INTn) will assert
692 /// to low after INTLEVEL time.
693 ///
694 /// The equation is:
695 ///
696 /// I<sub>AWT</sub> = (INTLEVEL + 1) * PLL<sub>CLK</sub> * 4
697 ///
698 /// When INTLEVEL > 0.
699 ///
700 /// You might want to take a look at the data sheet, there is a handy
701 /// timing diagram there.
702 ///
703 /// # Example
704 ///
705 /// ```
706 /// # let spi = ehm::eh1::spi::Mock::new(&[
707 /// # ehm::eh1::spi::Transaction::transaction_start(),
708 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x13, 0x00]),
709 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
710 /// # ehm::eh1::spi::Transaction::transaction_end(),
711 /// # ]);
712 /// use w5500_ll::{eh1::vdm::W5500, Registers};
713 ///
714 /// let mut w5500 = W5500::new(spi);
715 /// let intlevel: u16 = w5500.intlevel()?;
716 /// assert_eq!(intlevel, 0x00);
717 /// # w5500.free().done();
718 /// # Ok::<(), eh1::spi::ErrorKind>(())
719 /// ```
720 fn intlevel(&mut self) -> Result<u16, Self::Error> {
721 let mut buf: [u8; 2] = [0; 2];
722 self.read(Reg::INTLEVEL0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
723 Ok(u16::from_be_bytes(buf))
724 }
725
726 /// Set the interrupt low level time.
727 ///
728 /// See [`Registers::intlevel`] for more information.
729 ///
730 /// # Example
731 ///
732 /// ```
733 /// # let spi = ehm::eh1::spi::Mock::new(&[
734 /// # ehm::eh1::spi::Transaction::transaction_start(),
735 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x13, 0x04]),
736 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
737 /// # ehm::eh1::spi::Transaction::transaction_end(),
738 /// # ]);
739 /// use w5500_ll::{eh1::vdm::W5500, Registers};
740 ///
741 /// let mut w5500 = W5500::new(spi);
742 /// w5500.set_intlevel(0x1234)?;
743 /// # w5500.free().done();
744 /// # Ok::<(), eh1::spi::ErrorKind>(())
745 /// ```
746 fn set_intlevel(&mut self, intlevel: u16) -> Result<(), Self::Error> {
747 self.write(
748 Reg::INTLEVEL0.addr(),
749 COMMON_BLOCK_OFFSET,
750 &intlevel.to_be_bytes(),
751 )
752 }
753
754 /// Get the interrupt status.
755 ///
756 /// `1` indicates the interrupt is raised.
757 ///
758 /// # Example
759 ///
760 /// ```
761 /// # let spi = ehm::eh1::spi::Mock::new(&[
762 /// # ehm::eh1::spi::Transaction::transaction_start(),
763 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x00]),
764 /// # ehm::eh1::spi::Transaction::read(0),
765 /// # ehm::eh1::spi::Transaction::transaction_end(),
766 /// # ]);
767 /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
768 ///
769 /// let mut w5500 = W5500::new(spi);
770 /// let ir: Interrupt = w5500.ir()?;
771 /// assert_eq!(ir, Interrupt::default());
772 /// # w5500.free().done();
773 /// # Ok::<(), eh1::spi::ErrorKind>(())
774 /// ```
775 fn ir(&mut self) -> Result<Interrupt, Self::Error> {
776 let mut reg: [u8; 1] = [0];
777 self.read(Reg::IR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
778 Ok(Interrupt::from(reg[0]))
779 }
780
781 /// Set the interrupt status.
782 ///
783 /// Setting an interrupt bit to `1` will clear the interrupt.
784 ///
785 /// # Example
786 ///
787 /// ```
788 /// # let spi = ehm::eh1::spi::Mock::new(&[
789 /// # ehm::eh1::spi::Transaction::transaction_start(),
790 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x00]),
791 /// # ehm::eh1::spi::Transaction::read(0),
792 /// # ehm::eh1::spi::Transaction::transaction_end(),
793 /// # ehm::eh1::spi::Transaction::transaction_start(),
794 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x04]),
795 /// # ehm::eh1::spi::Transaction::write(0),
796 /// # ehm::eh1::spi::Transaction::transaction_end(),
797 /// # ]);
798 /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
799 ///
800 /// let mut w5500 = W5500::new(spi);
801 /// let ir: Interrupt = w5500.ir()?;
802 /// w5500.set_ir(ir)?;
803 /// # w5500.free().done();
804 /// # Ok::<(), eh1::spi::ErrorKind>(())
805 /// ```
806 fn set_ir(&mut self, interrupt: Interrupt) -> Result<(), Self::Error> {
807 self.write(Reg::IR.addr(), COMMON_BLOCK_OFFSET, &[interrupt.into()])
808 }
809
810 /// Get the interrupt mask.
811 ///
812 /// `0` indicates the interrupt is masked.
813 ///
814 /// # Example
815 ///
816 /// ```
817 /// # let spi = ehm::eh1::spi::Mock::new(&[
818 /// # ehm::eh1::spi::Transaction::transaction_start(),
819 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x00]),
820 /// # ehm::eh1::spi::Transaction::read(0),
821 /// # ehm::eh1::spi::Transaction::transaction_end(),
822 /// # ]);
823 /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
824 ///
825 /// let mut w5500 = W5500::new(spi);
826 /// let imr: Interrupt = w5500.imr()?;
827 /// assert_eq!(imr, Interrupt::default());
828 /// # w5500.free().done();
829 /// # Ok::<(), eh1::spi::ErrorKind>(())
830 /// ```
831 fn imr(&mut self) -> Result<Interrupt, Self::Error> {
832 let mut reg: [u8; 1] = [0];
833 self.read(Reg::IMR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
834 Ok(Interrupt::from(reg[0]))
835 }
836
837 /// Set the interrupt mask.
838 ///
839 /// Setting an interrupt bit to `1` will mask the interrupt.
840 /// When a bit of IMR is `1` and the corresponding interrupt is `1` an
841 /// interrupt will be issued.
842 /// If a bit of IMR is `0`, and interrupt will not be issued even if the
843 /// corresponding IR bit is `1`.
844 ///
845 /// # Example
846 ///
847 /// ```
848 /// use w5500_ll::{eh1::vdm::W5500, Interrupt, Registers};
849 /// # let spi = ehm::eh1::spi::Mock::new(&[
850 /// # ehm::eh1::spi::Transaction::transaction_start(),
851 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x04]),
852 /// # ehm::eh1::spi::Transaction::write_vec(vec![Interrupt::MP_MASK]),
853 /// # ehm::eh1::spi::Transaction::transaction_end(),
854 /// # ]);
855 ///
856 /// // enable the magic packet interrupt
857 /// const IMR: Interrupt = Interrupt::DEFAULT.set_mp();
858 ///
859 /// let mut w5500 = W5500::new(spi);
860 /// w5500.set_imr(IMR)?;
861 /// # w5500.free().done();
862 /// # Ok::<(), eh1::spi::ErrorKind>(())
863 /// ```
864 fn set_imr(&mut self, mask: Interrupt) -> Result<(), Self::Error> {
865 self.write(Reg::IMR.addr(), COMMON_BLOCK_OFFSET, &[mask.into()])
866 }
867
868 /// Get the socket interrupt status.
869 ///
870 /// SIMR indicates the interrupt status of all sockets.
871 /// Each bit of SIR will be `1` until [`sn_ir`] is cleared.
872 /// If [`sn_ir`] is not equal to `0x00` the n<sub>th</sub>
873 /// bit of `sir` is `1` and the INTn pin is asserted until SIR is `0x00`.
874 ///
875 /// # Example
876 ///
877 /// ```
878 /// # let spi = ehm::eh1::spi::Mock::new(&[
879 /// # ehm::eh1::spi::Transaction::transaction_start(),
880 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x17, 0x00]),
881 /// # ehm::eh1::spi::Transaction::read(0),
882 /// # ehm::eh1::spi::Transaction::transaction_end(),
883 /// # ]);
884 /// use w5500_ll::{eh1::vdm::W5500, Registers, SOCKETS};
885 ///
886 /// let mut w5500 = W5500::new(spi);
887 /// let sir = w5500.sir()?;
888 /// // clear all socket interrupts
889 /// for socket in SOCKETS.iter() {
890 /// if 1 << (*socket as u8) & sir != 0 {
891 /// let sn_ir = w5500.sn_ir(*socket)?;
892 /// w5500.set_sn_ir(*socket, sn_ir)?;
893 /// }
894 /// }
895 /// # w5500.free().done();
896 /// # Ok::<(), eh1::spi::ErrorKind>(())
897 /// ```
898 ///
899 /// [`sn_ir`]: Registers::sn_ir
900 fn sir(&mut self) -> Result<u8, Self::Error> {
901 let mut reg: [u8; 1] = [0];
902 self.read(Reg::SIR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
903 Ok(reg[0])
904 }
905
906 /// Get the socket interrupt mask.
907 ///
908 /// Each bit of SIMR corresponds to each bit of [`Registers::sir`].
909 /// When a bit of SIMR is `1` and the corresponding bit of SIR is `1`
910 /// and interrupt will be issued.
911 /// If a bit of SIMR is `0` an interrupt will be not issued even if the
912 /// corresponding bit of SIR is `1`.
913 ///
914 /// # Example
915 ///
916 /// ```
917 /// # let spi = ehm::eh1::spi::Mock::new(&[
918 /// # ehm::eh1::spi::Transaction::transaction_start(),
919 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x18, 0x00]),
920 /// # ehm::eh1::spi::Transaction::read(0),
921 /// # ehm::eh1::spi::Transaction::transaction_end(),
922 /// # ]);
923 /// use w5500_ll::{eh1::vdm::W5500, Registers};
924 ///
925 /// let mut w5500 = W5500::new(spi);
926 /// let simr: u8 = w5500.simr()?;
927 /// # w5500.free().done();
928 /// # Ok::<(), eh1::spi::ErrorKind>(())
929 /// ```
930 fn simr(&mut self) -> Result<u8, Self::Error> {
931 let mut reg: [u8; 1] = [0];
932 self.read(Reg::SIMR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
933 Ok(reg[0])
934 }
935
936 /// Set the socket interrupt mask.
937 ///
938 /// See [`Registers::simr`] for more information.
939 ///
940 /// # Example
941 ///
942 /// ```
943 /// # let spi = ehm::eh1::spi::Mock::new(&[
944 /// # ehm::eh1::spi::Transaction::transaction_start(),
945 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x18, 0x04]),
946 /// # ehm::eh1::spi::Transaction::write(0xFF),
947 /// # ehm::eh1::spi::Transaction::transaction_end(),
948 /// # ]);
949 /// use w5500_ll::{eh1::vdm::W5500, Registers};
950 ///
951 /// let mut w5500 = W5500::new(spi);
952 /// // enable all socket interrupts
953 /// w5500.set_simr(0xFF)?;
954 /// # w5500.free().done();
955 /// # Ok::<(), eh1::spi::ErrorKind>(())
956 /// ```
957 fn set_simr(&mut self, simr: u8) -> Result<(), Self::Error> {
958 self.write(Reg::SIMR.addr(), COMMON_BLOCK_OFFSET, &[simr])
959 }
960
961 /// Get the retry time.
962 ///
963 /// RTR configures the re-transmission timeout period.
964 /// The unit of timeout period is 100 us and the default of RTR is `0x07D0`
965 /// or `2000`.
966 /// And so the default timeout period is 200 ms (100 us X 2000).
967 /// During the time configured by RTR, the W5500 waits for the peer response
968 /// to the packet that is transmitted by Sn_CR (CONNECT, DISCON, CLOSE,
969 /// SEND, SEND_MAC, SEND_KEEP command).
970 /// If the peer does not respond within the RTR time, the W5500 re-transmits
971 /// the packet or issues a timeout.
972 ///
973 /// # Example
974 ///
975 /// ```
976 /// # let spi = ehm::eh1::spi::Mock::new(&[
977 /// # ehm::eh1::spi::Transaction::transaction_start(),
978 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x19, 0x00]),
979 /// # ehm::eh1::spi::Transaction::read_vec(vec![0x07, 0xD0]),
980 /// # ehm::eh1::spi::Transaction::transaction_end(),
981 /// # ]);
982 /// use w5500_ll::{eh1::vdm::W5500, Registers};
983 ///
984 /// let mut w5500 = W5500::new(spi);
985 /// let rtr: u16 = w5500.rtr()?;
986 /// assert_eq!(rtr, 0x07D0);
987 /// # w5500.free().done();
988 /// # Ok::<(), eh1::spi::ErrorKind>(())
989 /// ```
990 fn rtr(&mut self) -> Result<u16, Self::Error> {
991 let mut buf: [u8; 2] = [0; 2];
992 self.read(Reg::RTR0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
993 Ok(u16::from_be_bytes(buf))
994 }
995
996 /// Set the retry time.
997 ///
998 /// See [`Registers::rtr`] for more information.
999 ///
1000 /// # Example
1001 ///
1002 /// ```
1003 /// # let spi = ehm::eh1::spi::Mock::new(&[
1004 /// # ehm::eh1::spi::Transaction::transaction_start(),
1005 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x19, 0x04]),
1006 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
1007 /// # ehm::eh1::spi::Transaction::transaction_end(),
1008 /// # ]);
1009 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1010 ///
1011 /// let mut w5500 = W5500::new(spi);
1012 /// w5500.set_rtr(0x1234)?;
1013 /// # w5500.free().done();
1014 /// # Ok::<(), eh1::spi::ErrorKind>(())
1015 /// ```
1016 fn set_rtr(&mut self, rtr: u16) -> Result<(), Self::Error> {
1017 self.write(Reg::RTR0.addr(), COMMON_BLOCK_OFFSET, &rtr.to_be_bytes())
1018 }
1019
1020 /// Get the retry count.
1021 ///
1022 /// RCR configured the number of re-transmission attempts.
1023 /// When the number of re-transmission equals RCR + 1 the socket timeout
1024 /// interrupt is raised.
1025 ///
1026 /// There is a LOT more information in the data sheet,
1027 /// including some equations that would be very annoying to input.
1028 ///
1029 /// # Example
1030 ///
1031 /// ```
1032 /// # let spi = ehm::eh1::spi::Mock::new(&[
1033 /// # ehm::eh1::spi::Transaction::transaction_start(),
1034 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1B, 0x00]),
1035 /// # ehm::eh1::spi::Transaction::read(0x08),
1036 /// # ehm::eh1::spi::Transaction::transaction_end(),
1037 /// # ]);
1038 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1039 ///
1040 /// let mut w5500 = W5500::new(spi);
1041 /// let rcr: u8 = w5500.rcr()?;
1042 /// # w5500.free().done();
1043 /// # Ok::<(), eh1::spi::ErrorKind>(())
1044 /// ```
1045 fn rcr(&mut self) -> Result<u8, Self::Error> {
1046 let mut reg: [u8; 1] = [0];
1047 self.read(Reg::RCR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1048 Ok(reg[0])
1049 }
1050
1051 /// Set the retry count.
1052 ///
1053 /// See [`Registers::rcr`] for more information.
1054 ///
1055 /// # Example
1056 ///
1057 /// ```
1058 /// # let spi = ehm::eh1::spi::Mock::new(&[
1059 /// # ehm::eh1::spi::Transaction::transaction_start(),
1060 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1B, 0x04]),
1061 /// # ehm::eh1::spi::Transaction::write(0x0A),
1062 /// # ehm::eh1::spi::Transaction::transaction_end(),
1063 /// # ]);
1064 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1065 ///
1066 /// let mut w5500 = W5500::new(spi);
1067 /// w5500.set_rcr(0x0A)?;
1068 /// # w5500.free().done();
1069 /// # Ok::<(), eh1::spi::ErrorKind>(())
1070 /// ```
1071 fn set_rcr(&mut self, rcr: u8) -> Result<(), Self::Error> {
1072 self.write(Reg::RCR.addr(), COMMON_BLOCK_OFFSET, &[rcr])
1073 }
1074
1075 /// Get the PPP link control protocol request timer.
1076 ///
1077 /// PTIMER configures the time for sending LCP echo request.
1078 ///
1079 /// The unit of time is 25 milliseconds, for a register value of 200 the
1080 /// timer is 5 seconds.
1081 ///
1082 /// # Example
1083 ///
1084 /// ```
1085 /// # let spi = ehm::eh1::spi::Mock::new(&[
1086 /// # ehm::eh1::spi::Transaction::transaction_start(),
1087 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1C, 0x00]),
1088 /// # ehm::eh1::spi::Transaction::read(0x08),
1089 /// # ehm::eh1::spi::Transaction::transaction_end(),
1090 /// # ]);
1091 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1092 ///
1093 /// let mut w5500 = W5500::new(spi);
1094 /// let ptimer: u8 = w5500.ptimer()?;
1095 /// # w5500.free().done();
1096 /// # Ok::<(), eh1::spi::ErrorKind>(())
1097 /// ```
1098 fn ptimer(&mut self) -> Result<u8, Self::Error> {
1099 let mut reg: [u8; 1] = [0];
1100 self.read(Reg::PTIMER.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1101 Ok(reg[0])
1102 }
1103
1104 /// Set the PPP link control protocol request timer.
1105 ///
1106 /// See [`Registers::ptimer`] for more information.
1107 ///
1108 /// # Example
1109 ///
1110 /// ```
1111 /// # let spi = ehm::eh1::spi::Mock::new(&[
1112 /// # ehm::eh1::spi::Transaction::transaction_start(),
1113 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1C, 0x04]),
1114 /// # ehm::eh1::spi::Transaction::write(0xC8),
1115 /// # ehm::eh1::spi::Transaction::transaction_end(),
1116 /// # ]);
1117 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1118 ///
1119 /// let mut w5500 = W5500::new(spi);
1120 /// w5500.set_ptimer(200)?;
1121 /// # w5500.free().done();
1122 /// # Ok::<(), eh1::spi::ErrorKind>(())
1123 /// ```
1124 fn set_ptimer(&mut self, ptimer: u8) -> Result<(), Self::Error> {
1125 self.write(Reg::PTIMER.addr(), COMMON_BLOCK_OFFSET, &[ptimer])
1126 }
1127
1128 /// Get the PPP link control protocol magic number.
1129 ///
1130 /// PMAGIC configures the 4 byte magic number used in the LCP echo request.
1131 /// For a register value of `0x01` the magic number is `0x01010101`.
1132 ///
1133 /// # Example
1134 ///
1135 /// ```
1136 /// # let spi = ehm::eh1::spi::Mock::new(&[
1137 /// # ehm::eh1::spi::Transaction::transaction_start(),
1138 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1D, 0x00]),
1139 /// # ehm::eh1::spi::Transaction::read(0x08),
1140 /// # ehm::eh1::spi::Transaction::transaction_end(),
1141 /// # ]);
1142 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1143 ///
1144 /// let mut w5500 = W5500::new(spi);
1145 /// let pmagic: u8 = w5500.pmagic()?;
1146 /// # w5500.free().done();
1147 /// # Ok::<(), eh1::spi::ErrorKind>(())
1148 /// ```
1149 fn pmagic(&mut self) -> Result<u8, Self::Error> {
1150 let mut reg: [u8; 1] = [0];
1151 self.read(Reg::PMAGIC.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1152 Ok(reg[0])
1153 }
1154
1155 /// Set the PPP link control protocol magic number.
1156 ///
1157 /// See [`Registers::pmagic`] for more information.
1158 ///
1159 /// # Example
1160 ///
1161 /// ```
1162 /// # let spi = ehm::eh1::spi::Mock::new(&[
1163 /// # ehm::eh1::spi::Transaction::transaction_start(),
1164 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1D, 0x04]),
1165 /// # ehm::eh1::spi::Transaction::write(0x01),
1166 /// # ehm::eh1::spi::Transaction::transaction_end(),
1167 /// # ]);
1168 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1169 ///
1170 /// let mut w5500 = W5500::new(spi);
1171 /// w5500.set_pmagic(0x01)?;
1172 /// # w5500.free().done();
1173 /// # Ok::<(), eh1::spi::ErrorKind>(())
1174 /// ```
1175 fn set_pmagic(&mut self, pmagic: u8) -> Result<(), Self::Error> {
1176 self.write(Reg::PMAGIC.addr(), COMMON_BLOCK_OFFSET, &[pmagic])
1177 }
1178
1179 /// Get the destination hardware address in PPPoE mode.
1180 ///
1181 /// # Example
1182 ///
1183 /// ```
1184 /// # let spi = ehm::eh1::spi::Mock::new(&[
1185 /// # ehm::eh1::spi::Transaction::transaction_start(),
1186 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x00]),
1187 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0, 0, 0]),
1188 /// # ehm::eh1::spi::Transaction::transaction_end(),
1189 /// # ]);
1190 /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
1191 ///
1192 /// let mut w5500 = W5500::new(spi);
1193 /// let phar = w5500.phar()?;
1194 /// assert_eq!(phar, Eui48Addr::UNSPECIFIED);
1195 /// # w5500.free().done();
1196 /// # Ok::<(), eh1::spi::ErrorKind>(())
1197 /// ```
1198 fn phar(&mut self) -> Result<Eui48Addr, Self::Error> {
1199 let mut phar = Eui48Addr::UNSPECIFIED;
1200 self.read(Reg::PHAR0.addr(), COMMON_BLOCK_OFFSET, &mut phar.octets)?;
1201 Ok(phar)
1202 }
1203
1204 /// Set the destination hardware address in PPPoE mode.
1205 ///
1206 /// # Example
1207 ///
1208 /// ```
1209 /// # let spi = ehm::eh1::spi::Mock::new(&[
1210 /// # ehm::eh1::spi::Transaction::transaction_start(),
1211 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x04]),
1212 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0, 0, 0, 0]),
1213 /// # ehm::eh1::spi::Transaction::transaction_end(),
1214 /// # ]);
1215 /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers};
1216 ///
1217 /// let mut w5500 = W5500::new(spi);
1218 /// w5500.set_phar(&Eui48Addr::new(0x12, 0x34, 0x00, 0x00, 0x00, 0x00))?;
1219 /// # w5500.free().done();
1220 /// # Ok::<(), eh1::spi::ErrorKind>(())
1221 /// ```
1222 fn set_phar(&mut self, phar: &Eui48Addr) -> Result<(), Self::Error> {
1223 self.write(Reg::PHAR0.addr(), COMMON_BLOCK_OFFSET, &phar.octets)
1224 }
1225
1226 /// Get the session ID in PPPoE mode.
1227 ///
1228 /// PSID should be written to the PPPoE server session ID acquired in the
1229 /// PPPoE connection process.
1230 ///
1231 /// # Example
1232 ///
1233 /// ```
1234 /// # let spi = ehm::eh1::spi::Mock::new(&[
1235 /// # ehm::eh1::spi::Transaction::transaction_start(),
1236 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x00]),
1237 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1238 /// # ehm::eh1::spi::Transaction::transaction_end(),
1239 /// # ]);
1240 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1241 ///
1242 /// let mut w5500 = W5500::new(spi);
1243 /// let psid: u16 = w5500.psid()?;
1244 /// assert_eq!(psid, 0x0000);
1245 /// # w5500.free().done();
1246 /// # Ok::<(), eh1::spi::ErrorKind>(())
1247 /// ```
1248 fn psid(&mut self) -> Result<u16, Self::Error> {
1249 let mut buf: [u8; 2] = [0; 2];
1250 self.read(Reg::PSID0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
1251 Ok(u16::from_be_bytes(buf))
1252 }
1253
1254 /// Set the session ID in PPPoE mode.
1255 ///
1256 /// See [`Registers::psid`] for more information.
1257 ///
1258 /// # Example
1259 ///
1260 /// ```
1261 /// # let spi = ehm::eh1::spi::Mock::new(&[
1262 /// # ehm::eh1::spi::Transaction::transaction_start(),
1263 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x04]),
1264 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
1265 /// # ehm::eh1::spi::Transaction::transaction_end(),
1266 /// # ]);
1267 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1268 ///
1269 /// let mut w5500 = W5500::new(spi);
1270 /// w5500.set_psid(0x1234)?;
1271 /// # w5500.free().done();
1272 /// # Ok::<(), eh1::spi::ErrorKind>(())
1273 /// ```
1274 fn set_psid(&mut self, psid: u16) -> Result<(), Self::Error> {
1275 self.write(Reg::PSID0.addr(), COMMON_BLOCK_OFFSET, &psid.to_be_bytes())
1276 }
1277
1278 /// Get the maximum receive unit in PPPoE mode.
1279 ///
1280 /// PMRU configures the maximum receive unit of PPPoE.
1281 ///
1282 /// # Example
1283 ///
1284 /// ```
1285 /// # let spi = ehm::eh1::spi::Mock::new(&[
1286 /// # ehm::eh1::spi::Transaction::transaction_start(),
1287 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x26, 0x00]),
1288 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1289 /// # ehm::eh1::spi::Transaction::transaction_end(),
1290 /// # ]);
1291 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1292 ///
1293 /// let mut w5500 = W5500::new(spi);
1294 /// let pmru: u16 = w5500.pmru()?;
1295 /// assert_eq!(pmru, 0x0000);
1296 /// # w5500.free().done();
1297 /// # Ok::<(), eh1::spi::ErrorKind>(())
1298 /// ```
1299 fn pmru(&mut self) -> Result<u16, Self::Error> {
1300 let mut buf: [u8; 2] = [0; 2];
1301 self.read(Reg::PMRU0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
1302 Ok(u16::from_be_bytes(buf))
1303 }
1304
1305 /// Set the maximum receive unit in PPPoE mode.
1306 ///
1307 /// See [`Registers::pmru`] for more information.
1308 ///
1309 /// # Example
1310 ///
1311 /// ```
1312 /// # let spi = ehm::eh1::spi::Mock::new(&[
1313 /// # ehm::eh1::spi::Transaction::transaction_start(),
1314 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x26, 0x04]),
1315 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34]),
1316 /// # ehm::eh1::spi::Transaction::transaction_end(),
1317 /// # ]);
1318 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1319 ///
1320 /// let mut w5500 = W5500::new(spi);
1321 /// w5500.set_pmru(0x1234)?;
1322 /// # w5500.free().done();
1323 /// # Ok::<(), eh1::spi::ErrorKind>(())
1324 /// ```
1325 fn set_pmru(&mut self, pmru: u16) -> Result<(), Self::Error> {
1326 self.write(Reg::PMRU0.addr(), COMMON_BLOCK_OFFSET, &pmru.to_be_bytes())
1327 }
1328
1329 /// Get the unreachable IP address.
1330 ///
1331 /// This awkward wording is taken directly from the data-sheet:
1332 ///
1333 /// W5500 receives an ICMP packet (destination port unreachable)
1334 /// when data is sent to a port number which socket is not open and
1335 /// the UNREACH bit of [`Registers::ir`] becomes `1` and UIPR and UPORTR
1336 /// indicates the destination IP address and port number respectively.
1337 ///
1338 /// # Example
1339 ///
1340 /// ```
1341 /// # let spi = ehm::eh1::spi::Mock::new(&[
1342 /// # ehm::eh1::spi::Transaction::transaction_start(),
1343 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x28, 0x00]),
1344 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
1345 /// # ehm::eh1::spi::Transaction::transaction_end(),
1346 /// # ]);
1347 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers};
1348 ///
1349 /// let mut w5500 = W5500::new(spi);
1350 /// let uipr = w5500.uipr()?;
1351 /// assert_eq!(uipr, Ipv4Addr::UNSPECIFIED);
1352 /// # w5500.free().done();
1353 /// # Ok::<(), eh1::spi::ErrorKind>(())
1354 /// ```
1355 fn uipr(&mut self) -> Result<Ipv4Addr, Self::Error> {
1356 let mut uipr: [u8; 4] = [0; 4];
1357 self.read(Reg::UIPR0.addr(), COMMON_BLOCK_OFFSET, &mut uipr)?;
1358 Ok(uipr.into())
1359 }
1360
1361 /// Get the unreachable port.
1362 ///
1363 /// See [`Registers::uipr`] for more information.
1364 ///
1365 /// # Example
1366 ///
1367 /// ```
1368 /// # let spi = ehm::eh1::spi::Mock::new(&[
1369 /// # ehm::eh1::spi::Transaction::transaction_start(),
1370 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2C, 0x00]),
1371 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1372 /// # ehm::eh1::spi::Transaction::transaction_end(),
1373 /// # ]);
1374 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1375 ///
1376 /// let mut w5500 = W5500::new(spi);
1377 /// let uportr = w5500.uportr()?;
1378 /// # w5500.free().done();
1379 /// # Ok::<(), eh1::spi::ErrorKind>(())
1380 /// ```
1381 fn uportr(&mut self) -> Result<u16, Self::Error> {
1382 let mut buf: [u8; 2] = [0; 2];
1383 self.read(Reg::UPORTR0.addr(), COMMON_BLOCK_OFFSET, &mut buf)?;
1384 Ok(u16::from_be_bytes(buf))
1385 }
1386
1387 /// Get the PHY configuration.
1388 ///
1389 /// # Example
1390 ///
1391 /// ```
1392 /// # let spi = ehm::eh1::spi::Mock::new(&[
1393 /// # ehm::eh1::spi::Transaction::transaction_start(),
1394 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2E, 0x00]),
1395 /// # ehm::eh1::spi::Transaction::read(0b10111000),
1396 /// # ehm::eh1::spi::Transaction::transaction_end(),
1397 /// # ]);
1398 /// use w5500_ll::{eh1::vdm::W5500, PhyCfg, Registers};
1399 ///
1400 /// let mut w5500 = W5500::new(spi);
1401 /// let phy_cfg: PhyCfg = w5500.phycfgr()?;
1402 /// assert_eq!(phy_cfg, PhyCfg::default());
1403 /// # w5500.free().done();
1404 /// # Ok::<(), eh1::spi::ErrorKind>(())
1405 /// ```
1406 fn phycfgr(&mut self) -> Result<PhyCfg, Self::Error> {
1407 let mut reg: [u8; 1] = [0];
1408 self.read(Reg::PHYCFGR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1409 Ok(PhyCfg::from(reg[0]))
1410 }
1411
1412 /// Set the PHY configuration.
1413 ///
1414 /// # Example
1415 ///
1416 /// ```
1417 /// # let spi = ehm::eh1::spi::Mock::new(&[
1418 /// # ehm::eh1::spi::Transaction::transaction_start(),
1419 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2E, 0x04]),
1420 /// # ehm::eh1::spi::Transaction::write(0b11111000),
1421 /// # ehm::eh1::spi::Transaction::transaction_end(),
1422 /// # ]);
1423 /// use w5500_ll::{eh1::vdm::W5500, OperationMode, PhyCfg, Registers};
1424 ///
1425 /// const PHY_CFG: PhyCfg = PhyCfg::DEFAULT.set_opmdc(OperationMode::Auto);
1426 /// let mut w5500 = W5500::new(spi);
1427 /// w5500.set_phycfgr(PHY_CFG)?;
1428 /// # w5500.free().done();
1429 /// # Ok::<(), eh1::spi::ErrorKind>(())
1430 /// ```
1431 fn set_phycfgr(&mut self, phycfg: PhyCfg) -> Result<(), Self::Error> {
1432 self.write(Reg::PHYCFGR.addr(), COMMON_BLOCK_OFFSET, &[phycfg.into()])
1433 }
1434
1435 /// Get the version.
1436 ///
1437 /// The value returned is always `0x04`.
1438 ///
1439 /// This register is extremely useful as a sanity check to ensure SPI
1440 /// communications are working with the W5500.
1441 ///
1442 /// # Example
1443 ///
1444 /// ```
1445 /// # let spi = ehm::eh1::spi::Mock::new(&[
1446 /// # ehm::eh1::spi::Transaction::transaction_start(),
1447 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x39, 0x00]),
1448 /// # ehm::eh1::spi::Transaction::read(0x04),
1449 /// # ehm::eh1::spi::Transaction::transaction_end(),
1450 /// # ]);
1451 /// use w5500_ll::{eh1::vdm::W5500, Registers};
1452 ///
1453 /// let mut w5500 = W5500::new(spi);
1454 /// let version = w5500.version()?;
1455 /// assert_eq!(version, 0x04);
1456 /// # w5500.free().done();
1457 /// # Ok::<(), eh1::spi::ErrorKind>(())
1458 /// ```
1459 fn version(&mut self) -> Result<u8, Self::Error> {
1460 let mut reg: [u8; 1] = [0];
1461 self.read(Reg::VERSIONR.addr(), COMMON_BLOCK_OFFSET, &mut reg)?;
1462 Ok(reg[0])
1463 }
1464
1465 /// Get the socket mode.
1466 ///
1467 /// # Example
1468 ///
1469 /// ```
1470 /// # let spi = ehm::eh1::spi::Mock::new(&[
1471 /// # ehm::eh1::spi::Transaction::transaction_start(),
1472 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x08]),
1473 /// # ehm::eh1::spi::Transaction::read(0),
1474 /// # ehm::eh1::spi::Transaction::transaction_end(),
1475 /// # ]);
1476 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
1477 ///
1478 /// let mut w5500 = W5500::new(spi);
1479 /// let socket_mode = w5500.sn_mr(Sn::Sn0)?;
1480 /// assert_eq!(socket_mode, SocketMode::default());
1481 /// # w5500.free().done();
1482 /// # Ok::<(), eh1::spi::ErrorKind>(())
1483 /// ```
1484 fn sn_mr(&mut self, sn: Sn) -> Result<SocketMode, Self::Error> {
1485 let mut reg: [u8; 1] = [0];
1486 self.read(SnReg::MR.addr(), sn.block(), &mut reg)?;
1487 Ok(SocketMode::from(reg[0]))
1488 }
1489
1490 /// Set the socket mode.
1491 ///
1492 /// # Example
1493 ///
1494 /// ```
1495 /// # let spi = ehm::eh1::spi::Mock::new(&[
1496 /// # ehm::eh1::spi::Transaction::transaction_start(),
1497 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, 0x08 | 0x04]),
1498 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x01]),
1499 /// # ehm::eh1::spi::Transaction::transaction_end(),
1500 /// # ]);
1501 /// use w5500_ll::{eh1::vdm::W5500, Protocol, Registers, Sn, SocketMode};
1502 ///
1503 /// const SOCKET_MODE: SocketMode = SocketMode::DEFAULT.set_protocol(Protocol::Tcp);
1504 /// let mut w5500 = W5500::new(spi);
1505 /// w5500.set_sn_mr(Sn::Sn0, SOCKET_MODE)?;
1506 /// # w5500.free().done();
1507 /// # Ok::<(), eh1::spi::ErrorKind>(())
1508 /// ```
1509 fn set_sn_mr(&mut self, sn: Sn, mode: SocketMode) -> Result<(), Self::Error> {
1510 self.write(SnReg::MR.addr(), sn.block(), &[mode.into()])
1511 }
1512
1513 /// Get the socket command.
1514 ///
1515 /// The only use for reading this register is to check if a socket command
1516 /// has been accepted.
1517 ///
1518 /// # Example
1519 ///
1520 /// ```
1521 /// # let spi = ehm::eh1::spi::Mock::new(&[
1522 /// # ehm::eh1::spi::Transaction::transaction_start(),
1523 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08 | 0x04]),
1524 /// # ehm::eh1::spi::Transaction::write(0x01),
1525 /// # ehm::eh1::spi::Transaction::transaction_end(),
1526 /// # ehm::eh1::spi::Transaction::transaction_start(),
1527 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08]),
1528 /// # ehm::eh1::spi::Transaction::read(1),
1529 /// # ehm::eh1::spi::Transaction::transaction_end(),
1530 /// # ehm::eh1::spi::Transaction::transaction_start(),
1531 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08]),
1532 /// # ehm::eh1::spi::Transaction::read(0),
1533 /// # ehm::eh1::spi::Transaction::transaction_end(),
1534 /// # ]);
1535 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
1536 ///
1537 /// let mut w5500 = W5500::new(spi);
1538 /// w5500.set_sn_cr(Sn::Sn0, SocketCommand::Open)?;
1539 /// while w5500.sn_cr(Sn::Sn0)? != SocketCommand::Accepted.into() {}
1540 /// # w5500.free().done();
1541 /// # Ok::<(), eh1::spi::ErrorKind>(())
1542 /// ```
1543 fn sn_cr(&mut self, sn: Sn) -> Result<u8, Self::Error> {
1544 let mut reg: [u8; 1] = [0];
1545 self.read(SnReg::CR.addr(), sn.block(), &mut reg)?;
1546 Ok(reg[0])
1547 }
1548
1549 /// Set the socket command.
1550 ///
1551 /// # Example
1552 ///
1553 /// ```
1554 /// # let spi = ehm::eh1::spi::Mock::new(&[
1555 /// # ehm::eh1::spi::Transaction::transaction_start(),
1556 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08 | 0x04]),
1557 /// # ehm::eh1::spi::Transaction::write(0x01),
1558 /// # ehm::eh1::spi::Transaction::transaction_end(),
1559 /// # ]);
1560 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
1561 ///
1562 /// let mut w5500 = W5500::new(spi);
1563 /// w5500.set_sn_cr(Sn::Sn0, SocketCommand::Open)?;
1564 /// # w5500.free().done();
1565 /// # Ok::<(), eh1::spi::ErrorKind>(())
1566 /// ```
1567 fn set_sn_cr(&mut self, sn: Sn, cmd: SocketCommand) -> Result<(), Self::Error> {
1568 self.write(SnReg::CR.addr(), sn.block(), &[cmd.into()])
1569 }
1570
1571 /// Get the socket interrupt status.
1572 ///
1573 /// # Example
1574 ///
1575 /// ```
1576 /// # let spi = ehm::eh1::spi::Mock::new(&[
1577 /// # ehm::eh1::spi::Transaction::transaction_start(),
1578 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08]),
1579 /// # ehm::eh1::spi::Transaction::read(0),
1580 /// # ehm::eh1::spi::Transaction::transaction_end(),
1581 /// # ]);
1582 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1583 ///
1584 /// let mut w5500 = W5500::new(spi);
1585 /// let socket_interrupts = w5500.sn_ir(Sn::Sn0)?;
1586 /// # w5500.free().done();
1587 /// # Ok::<(), eh1::spi::ErrorKind>(())
1588 /// ```
1589 fn sn_ir(&mut self, sn: Sn) -> Result<SocketInterrupt, Self::Error> {
1590 let mut reg: [u8; 1] = [0];
1591 self.read(SnReg::IR.addr(), sn.block(), &mut reg)?;
1592 Ok(SocketInterrupt::from(reg[0]))
1593 }
1594
1595 /// Set the socket interrupt status.
1596 ///
1597 /// This is a write 1 to clear register.
1598 ///
1599 /// # Examples
1600 ///
1601 /// Clearing all raised interrupts.
1602 ///
1603 /// ```
1604 /// # let spi = ehm::eh1::spi::Mock::new(&[
1605 /// # ehm::eh1::spi::Transaction::transaction_start(),
1606 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08]),
1607 /// # ehm::eh1::spi::Transaction::read(0),
1608 /// # ehm::eh1::spi::Transaction::transaction_end(),
1609 /// # ehm::eh1::spi::Transaction::transaction_start(),
1610 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08 | 0x04]),
1611 /// # ehm::eh1::spi::Transaction::write(0),
1612 /// # ehm::eh1::spi::Transaction::transaction_end(),
1613 /// # ]);
1614 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterrupt};
1615 ///
1616 /// let mut w5500 = W5500::new(spi);
1617 /// let socket_interrupts: SocketInterrupt = w5500.sn_ir(Sn::Sn0)?;
1618 /// w5500.set_sn_ir(Sn::Sn0, socket_interrupts)?;
1619 /// # w5500.free().done();
1620 /// # Ok::<(), eh1::spi::ErrorKind>(())
1621 /// ```
1622 ///
1623 /// Clearing only the SENDOK interrupt.
1624 ///
1625 /// ```
1626 /// # let spi = ehm::eh1::spi::Mock::new(&[
1627 /// # ehm::eh1::spi::Transaction::transaction_start(),
1628 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x02, 0x08 | 0x04]),
1629 /// # ehm::eh1::spi::Transaction::write(SocketInterrupt::SENDOK_MASK),
1630 /// # ehm::eh1::spi::Transaction::transaction_end(),
1631 /// # ]);
1632 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterrupt};
1633 ///
1634 /// let mut w5500 = W5500::new(spi);
1635 /// w5500.set_sn_ir(Sn::Sn0, SocketInterrupt::SENDOK_MASK)?;
1636 /// # w5500.free().done();
1637 /// # Ok::<(), eh1::spi::ErrorKind>(())
1638 /// ```
1639 fn set_sn_ir<T: Into<u8>>(&mut self, sn: Sn, sn_ir: T) -> Result<(), Self::Error> {
1640 self.write(SnReg::IR.addr(), sn.block(), &[sn_ir.into()])
1641 }
1642
1643 /// Get the socket status.
1644 ///
1645 /// **Note:** This method returns a nested [`core::result::Result`].
1646 ///
1647 /// The outermost `Result` is for handling bus errors, similar to most of
1648 /// the other methods in this trait.
1649 ///
1650 /// The innermost `Result<SocketStatus, u8>` is the result of a `u8` to
1651 /// [`SocketStatus`] conversion because not every value of `u8` corresponds
1652 /// to a valid [`SocketStatus`].
1653 /// * `u8` values that have a corresponding [`SocketStatus`] will be
1654 /// converted and returned in the [`Ok`] variant of the inner `Result`.
1655 /// * `u8` values that do not corresponding [`SocketStatus`] will have the
1656 /// raw `u8` byte returned in the [`Err`] variant of the inner `Result`.
1657 ///
1658 /// # Example
1659 ///
1660 /// ```
1661 /// # let spi = ehm::eh1::spi::Mock::new(&[
1662 /// # ehm::eh1::spi::Transaction::transaction_start(),
1663 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x03, 0x08]),
1664 /// # ehm::eh1::spi::Transaction::read(0),
1665 /// # ehm::eh1::spi::Transaction::transaction_end(),
1666 /// # ]);
1667 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketStatus};
1668 ///
1669 /// let mut w5500 = W5500::new(spi);
1670 /// let sn_sr = w5500.sn_sr(Sn::Sn0)?;
1671 /// assert_eq!(sn_sr, Ok(SocketStatus::Closed));
1672 /// # w5500.free().done();
1673 /// # Ok::<(), eh1::spi::ErrorKind>(())
1674 /// ```
1675 ///
1676 /// [`Ok`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok
1677 /// [`Err`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err
1678 fn sn_sr(&mut self, sn: Sn) -> Result<Result<SocketStatus, u8>, Self::Error> {
1679 let mut reg: [u8; 1] = [0];
1680 self.read(SnReg::SR.addr(), sn.block(), &mut reg)?;
1681 Ok(SocketStatus::try_from(reg[0]))
1682 }
1683
1684 /// Get the socket source port.
1685 ///
1686 /// This is only valid in TCP/UDP mode.
1687 /// This should be set before sending the OPEN command.
1688 ///
1689 /// # Example
1690 ///
1691 /// ```
1692 /// # let spi = ehm::eh1::spi::Mock::new(&[
1693 /// # ehm::eh1::spi::Transaction::transaction_start(),
1694 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x04, 0x08]),
1695 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1696 /// # ehm::eh1::spi::Transaction::transaction_end(),
1697 /// # ]);
1698 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
1699 ///
1700 /// let mut w5500 = W5500::new(spi);
1701 /// let socket_port: u16 = w5500.sn_port(Sn::Sn0)?;
1702 /// # w5500.free().done();
1703 /// # Ok::<(), eh1::spi::ErrorKind>(())
1704 /// ```
1705 fn sn_port(&mut self, sn: Sn) -> Result<u16, Self::Error> {
1706 let mut reg: [u8; 2] = [0; 2];
1707 self.read(SnReg::PORT0.addr(), sn.block(), &mut reg)?;
1708 Ok(u16::from_be_bytes(reg))
1709 }
1710
1711 /// Set the socket source port.
1712 ///
1713 /// See [`Registers::sn_port`] for more information.
1714 ///
1715 /// # Example
1716 ///
1717 /// ```
1718 /// # let spi = ehm::eh1::spi::Mock::new(&[
1719 /// # ehm::eh1::spi::Transaction::transaction_start(),
1720 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x04, 0x08 | 0x04]),
1721 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 68]),
1722 /// # ehm::eh1::spi::Transaction::transaction_end(),
1723 /// # ]);
1724 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1725 ///
1726 /// let mut w5500 = W5500::new(spi);
1727 /// w5500.set_sn_port(Sn::Sn0, 68)?;
1728 /// # w5500.free().done();
1729 /// # Ok::<(), eh1::spi::ErrorKind>(())
1730 /// ```
1731 fn set_sn_port(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error> {
1732 self.write(SnReg::PORT0.addr(), sn.block(), &u16::to_be_bytes(port))
1733 }
1734
1735 /// Get the socket destination hardware address.
1736 ///
1737 /// Sn_DHAR configures the destination hardware address of Socket n when
1738 /// using SEND_MAC command in UDP mode or it indicates that it is acquired
1739 /// in ARP-process by CONNECT/SEND command.
1740 ///
1741 /// # Example
1742 ///
1743 /// ```
1744 /// # let spi = ehm::eh1::spi::Mock::new(&[
1745 /// # ehm::eh1::spi::Transaction::transaction_start(),
1746 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x06, 0x08]),
1747 /// # ehm::eh1::spi::Transaction::read_vec(vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]),
1748 /// # ehm::eh1::spi::Transaction::transaction_end(),
1749 /// # ]);
1750 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1751 ///
1752 /// let mut w5500 = W5500::new(spi);
1753 /// let dhar = w5500.sn_dhar(Sn::Sn0)?;
1754 /// # w5500.free().done();
1755 /// # Ok::<(), eh1::spi::ErrorKind>(())
1756 /// ```
1757 fn sn_dhar(&mut self, sn: Sn) -> Result<Eui48Addr, Self::Error> {
1758 let mut dhar: Eui48Addr = Eui48Addr::UNSPECIFIED;
1759 self.read(SnReg::DHAR0.addr(), sn.block(), &mut dhar.octets)?;
1760 Ok(dhar)
1761 }
1762
1763 /// Set the socket destination hardware address.
1764 ///
1765 /// See [`Registers::sn_dhar`] for more information.
1766 ///
1767 /// # Example
1768 ///
1769 /// ```
1770 /// # let spi = ehm::eh1::spi::Mock::new(&[
1771 /// # ehm::eh1::spi::Transaction::transaction_start(),
1772 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x06, 0x08 | 0x04]),
1773 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0x00, 0x00, 0x00, 0x00]),
1774 /// # ehm::eh1::spi::Transaction::transaction_end(),
1775 /// # ]);
1776 /// use w5500_ll::{eh1::vdm::W5500, net::Eui48Addr, Registers, Sn};
1777 ///
1778 /// let dhar = Eui48Addr::new(0x12, 0x34, 0x00, 0x00, 0x00, 0x00);
1779 /// let mut w5500 = W5500::new(spi);
1780 /// w5500.set_sn_dhar(Sn::Sn0, &dhar)?;
1781 /// # w5500.free().done();
1782 /// # Ok::<(), eh1::spi::ErrorKind>(())
1783 /// ```
1784 fn set_sn_dhar(&mut self, sn: Sn, dhar: &Eui48Addr) -> Result<(), Self::Error> {
1785 self.write(SnReg::DHAR0.addr(), sn.block(), &dhar.octets)
1786 }
1787
1788 /// Get the socket destination IP address.
1789 ///
1790 /// This register configures or indicates the destination IP address.
1791 /// It it valid when the socket is in TCP/UDP mode.
1792 ///
1793 /// In TCP client mode it configures the TCP server address before the
1794 /// [`SocketCommand::Connect`] command.
1795 ///
1796 /// In TCP server mode it indicates the IP address of the TCP client after
1797 /// successfully establishing a connection.
1798 ///
1799 /// In UDP mode it configures an IP address of the peer to receive the UDP
1800 /// packet send by the [`SocketCommand::Send`] or [`SocketCommand::SendMac`]
1801 /// command.
1802 ///
1803 /// # Example
1804 ///
1805 /// ```
1806 /// # let spi = ehm::eh1::spi::Mock::new(&[
1807 /// # ehm::eh1::spi::Transaction::transaction_start(),
1808 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08]),
1809 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
1810 /// # ehm::eh1::spi::Transaction::transaction_end(),
1811 /// # ]);
1812 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers, Sn};
1813 ///
1814 /// let mut w5500 = W5500::new(spi);
1815 /// let dipr = w5500.sn_dipr(Sn::Sn0)?;
1816 /// assert_eq!(dipr, Ipv4Addr::UNSPECIFIED);
1817 /// # w5500.free().done();
1818 /// # Ok::<(), eh1::spi::ErrorKind>(())
1819 /// ```
1820 fn sn_dipr(&mut self, sn: Sn) -> Result<Ipv4Addr, Self::Error> {
1821 let mut dipr: [u8; 4] = [0; 4];
1822 self.read(SnReg::DIPR0.addr(), sn.block(), &mut dipr)?;
1823 Ok(dipr.into())
1824 }
1825
1826 /// Set the socket destination IP address.
1827 ///
1828 /// See [`Registers::sn_dipr`] for more information.
1829 ///
1830 /// # Example
1831 ///
1832 /// ```
1833 /// # let spi = ehm::eh1::spi::Mock::new(&[
1834 /// # ehm::eh1::spi::Transaction::transaction_start(),
1835 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08 | 0x04]),
1836 /// # ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 11]),
1837 /// # ehm::eh1::spi::Transaction::transaction_end(),
1838 /// # ]);
1839 /// use w5500_ll::{eh1::vdm::W5500, net::Ipv4Addr, Registers, Sn};
1840 ///
1841 /// let mut w5500 = W5500::new(spi);
1842 /// w5500.set_sn_dipr(Sn::Sn0, &Ipv4Addr::new(192, 168, 0, 11))?;
1843 /// # w5500.free().done();
1844 /// # Ok::<(), eh1::spi::ErrorKind>(())
1845 /// ```
1846 fn set_sn_dipr(&mut self, sn: Sn, dipr: &Ipv4Addr) -> Result<(), Self::Error> {
1847 self.write(SnReg::DIPR0.addr(), sn.block(), &dipr.octets())
1848 }
1849
1850 /// Get the socket destination port.
1851 ///
1852 /// This register configures or indicates the destination port number of
1853 /// the socket.
1854 /// It is valid when the socket is used in TCP/UDP mode.
1855 ///
1856 /// In TCP client mode, it configures the listen port number of the TCP
1857 /// server before the [`SocketCommand::Send`] command.
1858 ///
1859 /// In TCP server mode, it indicates the port number of the TCP client
1860 /// after successfully establishing connection.
1861 ///
1862 /// In UDP mode, it configures the port number of the peer to be transmitted
1863 /// in the UDP packet by the [`SocketCommand::Send`] or
1864 /// [`SocketCommand::SendMac`] command.
1865 ///
1866 /// # Example
1867 ///
1868 /// ```
1869 /// # let spi = ehm::eh1::spi::Mock::new(&[
1870 /// # ehm::eh1::spi::Transaction::transaction_start(),
1871 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x10, 0x08]),
1872 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
1873 /// # ehm::eh1::spi::Transaction::transaction_end(),
1874 /// # ]);
1875 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
1876 ///
1877 /// let mut w5500 = W5500::new(spi);
1878 /// let socket_destination_port: u16 = w5500.sn_dport(Sn::Sn0)?;
1879 /// # w5500.free().done();
1880 /// # Ok::<(), eh1::spi::ErrorKind>(())
1881 /// ```
1882 fn sn_dport(&mut self, sn: Sn) -> Result<u16, Self::Error> {
1883 let mut reg: [u8; 2] = [0; 2];
1884 self.read(SnReg::DPORT0.addr(), sn.block(), &mut reg)?;
1885 Ok(u16::from_be_bytes(reg))
1886 }
1887
1888 /// Set the socket destination port.
1889 ///
1890 /// See [`Registers::sn_dport`] for more information.
1891 ///
1892 /// # Example
1893 ///
1894 /// ```
1895 /// # let spi = ehm::eh1::spi::Mock::new(&[
1896 /// # ehm::eh1::spi::Transaction::transaction_start(),
1897 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x10, 0x08 | 0x04]),
1898 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 67]),
1899 /// # ehm::eh1::spi::Transaction::transaction_end(),
1900 /// # ]);
1901 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
1902 ///
1903 /// let mut w5500 = W5500::new(spi);
1904 /// w5500.set_sn_dport(Sn::Sn0, 67)?;
1905 /// # w5500.free().done();
1906 /// # Ok::<(), eh1::spi::ErrorKind>(())
1907 /// ```
1908 fn set_sn_dport(&mut self, sn: Sn, port: u16) -> Result<(), Self::Error> {
1909 self.write(SnReg::DPORT0.addr(), sn.block(), &u16::to_be_bytes(port))
1910 }
1911
1912 /// Get the socket destination IPv4 and port.
1913 ///
1914 /// This is equivalent to [`Registers::sn_dipr`] and [`Registers::sn_dport`]
1915 /// in a single read transaction.
1916 ///
1917 /// # Example
1918 ///
1919 /// ```
1920 /// # let spi = ehm::eh1::spi::Mock::new(&[
1921 /// # ehm::eh1::spi::Transaction::transaction_start(),
1922 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08]),
1923 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0, 0, 0]),
1924 /// # ehm::eh1::spi::Transaction::transaction_end(),
1925 /// # ]);
1926 /// use w5500_ll::{
1927 /// eh1::vdm::W5500,
1928 /// net::{Ipv4Addr, SocketAddrV4},
1929 /// Registers, Sn,
1930 /// };
1931 ///
1932 /// let mut w5500 = W5500::new(spi);
1933 /// let addr = w5500.sn_dest(Sn::Sn0)?;
1934 /// assert_eq!(addr, SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0));
1935 /// # w5500.free().done();
1936 /// # Ok::<(), eh1::spi::ErrorKind>(())
1937 /// ```
1938 fn sn_dest(&mut self, sn: Sn) -> Result<SocketAddrV4, Self::Error> {
1939 let mut buf: [u8; 6] = [0; 6];
1940 self.read(SnReg::DIPR0.addr(), sn.block(), &mut buf)?;
1941 Ok(SocketAddrV4::new(
1942 Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]),
1943 u16::from_be_bytes([buf[4], buf[5]]),
1944 ))
1945 }
1946
1947 /// Set the socket destination IPv4 and port.
1948 ///
1949 /// This is equivalent to [`Registers::set_sn_dipr`] and
1950 /// [`Registers::set_sn_dport`] in a single writer transaction.
1951 ///
1952 /// # Example
1953 ///
1954 /// ```
1955 /// # let spi = ehm::eh1::spi::Mock::new(&[
1956 /// # ehm::eh1::spi::Transaction::transaction_start(),
1957 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x0C, 0x08 | 0x04]),
1958 /// # ehm::eh1::spi::Transaction::write_vec(vec![192, 168, 0, 11, 0, 67]),
1959 /// # ehm::eh1::spi::Transaction::transaction_end(),
1960 /// # ]);
1961 /// use w5500_ll::{
1962 /// eh1::vdm::W5500,
1963 /// net::{Ipv4Addr, SocketAddrV4},
1964 /// Registers, Sn,
1965 /// };
1966 ///
1967 /// let addr: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 11), 67);
1968 /// let mut w5500 = W5500::new(spi);
1969 /// w5500.set_sn_dest(Sn::Sn0, &addr)?;
1970 /// # w5500.free().done();
1971 /// # Ok::<(), eh1::spi::ErrorKind>(())
1972 /// ```
1973 fn set_sn_dest(&mut self, sn: Sn, addr: &SocketAddrV4) -> Result<(), Self::Error> {
1974 let buf: [u8; 6] = [
1975 addr.ip().octets()[0],
1976 addr.ip().octets()[1],
1977 addr.ip().octets()[2],
1978 addr.ip().octets()[3],
1979 (addr.port() >> 8) as u8,
1980 addr.port() as u8,
1981 ];
1982 self.write(SnReg::DIPR0.addr(), sn.block(), &buf)
1983 }
1984
1985 /// Get the socket maximum segment size.
1986 ///
1987 /// This register configures or indicates the MTU (Maximum Transfer Unit)
1988 /// of the socket.
1989 ///
1990 /// The default MTU is valid when the socket is used in TCP / UDP mode.
1991 /// However, when used in PPPoE mode it is determined within the PPPoE MTU.
1992 ///
1993 /// | Mode | Normal Default | Normal Range | PPPoE Default | PPPoE Range |
1994 /// |--------|----------------|--------------|---------------|-------------|
1995 /// | TCP | 1460 | 1 - 1460 | 1452 | 1 - 1452 |
1996 /// | UDP | 1472 | 1 - 1472 | 1464 | 1 - 1464 |
1997 /// | MACRAW | 1514 | 1514 | 1514 | 1514 |
1998 ///
1999 /// When socket n is used in MACRAW mode, the default MTU is applied
2000 /// because the MTU is not processed internally.
2001 /// Therefore, when transmitting the data bigger than default MTU, the host
2002 /// should manually divide the data into the unit of default MTU.
2003 /// When socket n is used in TCP/UDP mode, and transmitting data bigger than
2004 /// the MTU, the data is automatically divided into the unit of MTU.
2005 ///
2006 /// In UDP mode, the configured MTU is used.
2007 /// When transmitting data to a peer with the different MTU size,
2008 /// the ICMP (Fragment MTU) packet might be received.
2009 /// In this case, IR(FMTU) becomes `1` and the peer information such as the
2010 /// MTU size and IP address is indicated from FMTUR and UIPR respectively.
2011 /// If IR\[MTU\] = `1`, the user cannot transmit data to the peer.
2012 ///
2013 /// To resume the communication with peer, do as followed.
2014 /// 1. Close socket n with the [`SocketCommand::Close`] command.
2015 /// 2. Set Sn_MSS to the indicated MTU from FMTUR
2016 /// 3. Open socket n with the [`SocketCommand::Open`] command.
2017 /// 4. Resume the communication with the peer.
2018 ///
2019 /// # Example
2020 ///
2021 /// ```
2022 /// # let spi = ehm::eh1::spi::Mock::new(&[
2023 /// # ehm::eh1::spi::Transaction::transaction_start(),
2024 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x12, 0x08]),
2025 /// # ehm::eh1::spi::Transaction::read_vec(vec![0x00, 0x00]),
2026 /// # ehm::eh1::spi::Transaction::transaction_end(),
2027 /// # ]);
2028 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2029 ///
2030 /// let mut w5500 = W5500::new(spi);
2031 /// let sn__mssr: u16 = w5500.sn_mssr(Sn::Sn0)?;
2032 /// # w5500.free().done();
2033 /// # Ok::<(), eh1::spi::ErrorKind>(())
2034 /// ```
2035 fn sn_mssr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2036 let mut reg: [u8; 2] = [0; 2];
2037 self.read(SnReg::MSSR0.addr(), sn.block(), &mut reg)?;
2038 Ok(u16::from_be_bytes(reg))
2039 }
2040
2041 /// Set the socket maximum segment size.
2042 ///
2043 /// See [`Registers::sn_mssr`] for lots more information.
2044 ///
2045 /// # Example
2046 ///
2047 /// ```
2048 /// # let spi = ehm::eh1::spi::Mock::new(&[
2049 /// # ehm::eh1::spi::Transaction::transaction_start(),
2050 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x12, 0x08 | 0x04]),
2051 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x05, 0xB4]),
2052 /// # ehm::eh1::spi::Transaction::transaction_end(),
2053 /// # ]);
2054 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2055 ///
2056 /// let mut w5500 = W5500::new(spi);
2057 /// w5500.set_sn_mssr(Sn::Sn0, 1460)?;
2058 /// # w5500.free().done();
2059 /// # Ok::<(), eh1::spi::ErrorKind>(())
2060 /// ```
2061 fn set_sn_mssr(&mut self, sn: Sn, mssr: u16) -> Result<(), Self::Error> {
2062 self.write(SnReg::MSSR0.addr(), sn.block(), &u16::to_be_bytes(mssr))
2063 }
2064
2065 /// Get the IP type of service.
2066 ///
2067 /// This register configures the TOS (Type of service field in IP header)
2068 /// for socket n.
2069 /// Configure this field before sending the [`SocketCommand::Open`] command.
2070 ///
2071 /// For more details see [iana.org/assignments/ip-parameters].
2072 ///
2073 /// [iana.org/assignments/ip-parameters]: https://www.iana.org/assignments/ip-parameters
2074 ///
2075 /// # Example
2076 ///
2077 /// ```
2078 /// # let spi = ehm::eh1::spi::Mock::new(&[
2079 /// # ehm::eh1::spi::Transaction::transaction_start(),
2080 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x08]),
2081 /// # ehm::eh1::spi::Transaction::read(0),
2082 /// # ehm::eh1::spi::Transaction::transaction_end(),
2083 /// # ]);
2084 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2085 ///
2086 /// let mut w5500 = W5500::new(spi);
2087 /// let tos: u8 = w5500.sn_tos(Sn::Sn0)?;
2088 /// # w5500.free().done();
2089 /// # Ok::<(), eh1::spi::ErrorKind>(())
2090 /// ```
2091 fn sn_tos(&mut self, sn: Sn) -> Result<u8, Self::Error> {
2092 let mut reg: [u8; 1] = [0];
2093 self.read(SnReg::TOS.addr(), sn.block(), &mut reg)?;
2094 Ok(reg[0])
2095 }
2096
2097 /// Set the IP type of service.
2098 ///
2099 /// For more information see [`Registers::sn_tos`].
2100 ///
2101 /// # Example
2102 ///
2103 /// ```
2104 /// # let spi = ehm::eh1::spi::Mock::new(&[
2105 /// # ehm::eh1::spi::Transaction::transaction_start(),
2106 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x15, 0x08 | 0x04]),
2107 /// # ehm::eh1::spi::Transaction::write(0x01),
2108 /// # ehm::eh1::spi::Transaction::transaction_end(),
2109 /// # ]);
2110 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2111 ///
2112 /// let mut w5500 = W5500::new(spi);
2113 /// w5500.set_sn_tos(Sn::Sn0, 1)?;
2114 /// # w5500.free().done();
2115 /// # Ok::<(), eh1::spi::ErrorKind>(())
2116 /// ```
2117 fn set_sn_tos(&mut self, sn: Sn, tos: u8) -> Result<(), Self::Error> {
2118 self.write(SnReg::TOS.addr(), sn.block(), &[tos])
2119 }
2120
2121 /// Get the time to live.
2122 ///
2123 /// This register configures the TTL (Time to Live field in the IP header)
2124 /// for socket n.
2125 ///
2126 /// For more details see <https://www.iana.org/assignments/ip-parameters>.
2127 ///
2128 /// # Example
2129 ///
2130 /// ```
2131 /// # let spi = ehm::eh1::spi::Mock::new(&[
2132 /// # ehm::eh1::spi::Transaction::transaction_start(),
2133 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x08]),
2134 /// # ehm::eh1::spi::Transaction::read(0x80),
2135 /// # ehm::eh1::spi::Transaction::transaction_end(),
2136 /// # ]);
2137 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2138 ///
2139 /// let mut w5500 = W5500::new(spi);
2140 /// let ttl: u8 = w5500.sn_ttl(Sn::Sn0)?;
2141 /// # w5500.free().done();
2142 /// # Ok::<(), eh1::spi::ErrorKind>(())
2143 /// ```
2144 fn sn_ttl(&mut self, sn: Sn) -> Result<u8, Self::Error> {
2145 let mut reg: [u8; 1] = [0];
2146 self.read(SnReg::TTL.addr(), sn.block(), &mut reg)?;
2147 Ok(reg[0])
2148 }
2149
2150 /// Set the time to live.
2151 ///
2152 /// For more information see [`Registers::sn_ttl`].
2153 ///
2154 /// # Example
2155 ///
2156 /// ```
2157 /// # let spi = ehm::eh1::spi::Mock::new(&[
2158 /// # ehm::eh1::spi::Transaction::transaction_start(),
2159 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x16, 0x08 | 0x04]),
2160 /// # ehm::eh1::spi::Transaction::write(0x80),
2161 /// # ehm::eh1::spi::Transaction::transaction_end(),
2162 /// # ]);
2163 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2164 ///
2165 /// let mut w5500 = W5500::new(spi);
2166 /// w5500.set_sn_ttl(Sn::Sn0, 0x80)?;
2167 /// # w5500.free().done();
2168 /// # Ok::<(), eh1::spi::ErrorKind>(())
2169 /// ```
2170 fn set_sn_ttl(&mut self, sn: Sn, ttl: u8) -> Result<(), Self::Error> {
2171 self.write(SnReg::TTL.addr(), sn.block(), &[ttl])
2172 }
2173
2174 /// Get the socket RX buffer size.
2175 ///
2176 /// The buffer size can be configured to any of the sizes in [`BufferSize`].
2177 ///
2178 /// The sum of all the socket RX buffers cannot exceed 16 KiB.
2179 ///
2180 /// **Note:** This method returns a nested [`core::result::Result`].
2181 ///
2182 /// The outermost `Result` is for handling bus errors, similar to most of
2183 /// the other methods in this trait.
2184 ///
2185 /// The innermost `Result<BufferSize, u8>` is the result of a `u8` to
2186 /// [`BufferSize`] conversion because not every value of `u8` corresponds
2187 /// to a valid [`BufferSize`].
2188 /// * `u8` values that have a corresponding [`BufferSize`] will be
2189 /// converted and returned in the [`Ok`] variant of the inner `Result`.
2190 /// * `u8` values that do not corresponding [`BufferSize`] will have the
2191 /// raw `u8` byte returned in the [`Err`] variant of the inner `Result`.
2192 ///
2193 /// # Example
2194 ///
2195 /// ```
2196 /// # let spi = ehm::eh1::spi::Mock::new(&[
2197 /// # ehm::eh1::spi::Transaction::transaction_start(),
2198 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x08]),
2199 /// # ehm::eh1::spi::Transaction::read(0x02),
2200 /// # ehm::eh1::spi::Transaction::transaction_end(),
2201 /// # ]);
2202 /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2203 ///
2204 /// let mut w5500 = W5500::new(spi);
2205 /// let sn_rxbuf_size = w5500.sn_rxbuf_size(Sn::Sn0)?;
2206 /// assert_eq!(sn_rxbuf_size, Ok(BufferSize::KB2));
2207 /// # w5500.free().done();
2208 /// # Ok::<(), eh1::spi::ErrorKind>(())
2209 /// ```
2210 ///
2211 /// [`Ok`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok
2212 /// [`Err`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err
2213 fn sn_rxbuf_size(&mut self, sn: Sn) -> Result<Result<BufferSize, u8>, Self::Error> {
2214 let mut reg: [u8; 1] = [0];
2215 self.read(SnReg::RXBUF_SIZE.addr(), sn.block(), &mut reg)?;
2216 Ok(BufferSize::try_from(reg[0]))
2217 }
2218
2219 /// Set the socket RX buffer size.
2220 ///
2221 /// See [`Registers::sn_rxbuf_size`] for more information.
2222 ///
2223 /// # Example
2224 ///
2225 /// ```
2226 /// # let spi = ehm::eh1::spi::Mock::new(&[
2227 /// # ehm::eh1::spi::Transaction::transaction_start(),
2228 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1E, 0x08 | 0x04]),
2229 /// # ehm::eh1::spi::Transaction::write(1),
2230 /// # ehm::eh1::spi::Transaction::transaction_end(),
2231 /// # ]);
2232 /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2233 ///
2234 /// let mut w5500 = W5500::new(spi);
2235 /// w5500.set_sn_rxbuf_size(Sn::Sn0, BufferSize::KB1)?;
2236 /// # w5500.free().done();
2237 /// # Ok::<(), eh1::spi::ErrorKind>(())
2238 /// ```
2239 fn set_sn_rxbuf_size(&mut self, sn: Sn, size: BufferSize) -> Result<(), Self::Error> {
2240 self.write(SnReg::RXBUF_SIZE.addr(), sn.block(), &[size.into()])
2241 }
2242
2243 /// Get the socket TX buffer size.
2244 ///
2245 /// The buffer size can be configured to any of the sizes in [`BufferSize`].
2246 ///
2247 /// The sum of all the socket TX buffers cannot exceed 16 KiB.
2248 ///
2249 /// **Note:** This method returns a nested [`core::result::Result`].
2250 ///
2251 /// The outermost `Result` is for handling bus errors, similar to most of
2252 /// the other methods in this trait.
2253 ///
2254 /// The innermost `Result<BufferSize, u8>` is the result of a `u8` to
2255 /// [`BufferSize`] conversion because not every value of `u8` corresponds
2256 /// to a valid [`BufferSize`].
2257 /// * `u8` values that have a corresponding [`BufferSize`] will be
2258 /// converted and returned in the [`Ok`] variant of the inner `Result`.
2259 /// * `u8` values that do not corresponding [`BufferSize`] will have the
2260 /// raw `u8` byte returned in the [`Err`] variant of the inner `Result`.
2261 ///
2262 /// # Example
2263 ///
2264 /// ```
2265 /// # let spi = ehm::eh1::spi::Mock::new(&[
2266 /// # ehm::eh1::spi::Transaction::transaction_start(),
2267 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1F, 0x08]),
2268 /// # ehm::eh1::spi::Transaction::read(0x02),
2269 /// # ehm::eh1::spi::Transaction::transaction_end(),
2270 /// # ]);
2271 /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2272 ///
2273 /// let mut w5500 = W5500::new(spi);
2274 /// let sn_txbuf_size = w5500.sn_txbuf_size(Sn::Sn0)?;
2275 /// assert_eq!(sn_txbuf_size, Ok(BufferSize::KB2));
2276 /// # w5500.free().done();
2277 /// # Ok::<(), eh1::spi::ErrorKind>(())
2278 /// ```
2279 ///
2280 /// [`Ok`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok
2281 /// [`Err`]: https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err
2282 fn sn_txbuf_size(&mut self, sn: Sn) -> Result<Result<BufferSize, u8>, Self::Error> {
2283 let mut reg: [u8; 1] = [0];
2284 self.read(SnReg::TXBUF_SIZE.addr(), sn.block(), &mut reg)?;
2285 Ok(BufferSize::try_from(reg[0]))
2286 }
2287
2288 /// Set the socket TX buffer size.
2289 ///
2290 /// See [`Registers::sn_rxbuf_size`] for more information.
2291 ///
2292 /// # Example
2293 ///
2294 /// ```
2295 /// # let spi = ehm::eh1::spi::Mock::new(&[
2296 /// # ehm::eh1::spi::Transaction::transaction_start(),
2297 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x1F, 0x08 | 0x04]),
2298 /// # ehm::eh1::spi::Transaction::write(1),
2299 /// # ehm::eh1::spi::Transaction::transaction_end(),
2300 /// # ]);
2301 /// use w5500_ll::{eh1::vdm::W5500, BufferSize, Registers, Sn};
2302 ///
2303 /// let mut w5500 = W5500::new(spi);
2304 /// w5500.set_sn_txbuf_size(Sn::Sn0, BufferSize::KB1)?;
2305 /// # w5500.free().done();
2306 /// # Ok::<(), eh1::spi::ErrorKind>(())
2307 /// ```
2308 fn set_sn_txbuf_size(&mut self, sn: Sn, size: BufferSize) -> Result<(), Self::Error> {
2309 self.write(SnReg::TXBUF_SIZE.addr(), sn.block(), &[size.into()])
2310 }
2311
2312 /// Get transmit buffer free size.
2313 ///
2314 /// This register indicates the free size of socket n TX buffer.
2315 /// It is initialized to the configured size by [`Registers::sn_txbuf_size`].
2316 /// Data bigger than Sn_TX_FSR should not be written to the TX buffer to
2317 /// prevent buffer overflow.
2318 ///
2319 /// Check this register before writing data to the socket TX buffer,
2320 /// and if data is equal or smaller than its checked size, transmit the data
2321 /// with the [`SocketCommand::Send`] or [`SocketCommand::SendMac`] command
2322 /// after saving the data in Socket n TX buffer.
2323 ///
2324 /// If data is bigger than its checked size, transmit the data after
2325 /// dividing into the checked size and saving in the socket TX buffer.
2326 ///
2327 /// If [`Registers::sn_mr`] is not in TCP mode, this register is
2328 /// automatically calculated as the difference between
2329 /// [`Registers::sn_tx_wr`] and [`Registers::sn_tx_rd`].
2330 ///
2331 /// If [`Registers::sn_mr`] is in TCP mode, this register is automatically
2332 /// calculated as the difference between the internal ACK pointer which
2333 /// indicates the point of data is received already by the connected
2334 /// peer.
2335 ///
2336 /// # Example
2337 ///
2338 /// ```
2339 /// # let spi = ehm::eh1::spi::Mock::new(&[
2340 /// # ehm::eh1::spi::Transaction::transaction_start(),
2341 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x20, 0x08]),
2342 /// # ehm::eh1::spi::Transaction::read_vec(vec![0x08, 0x00]),
2343 /// # ehm::eh1::spi::Transaction::transaction_end(),
2344 /// # ]);
2345 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
2346 ///
2347 /// let mut w5500 = W5500::new(spi);
2348 /// let sn_tx_fsr: u16 = w5500.sn_tx_fsr(Sn::Sn0)?;
2349 /// # w5500.free().done();
2350 /// # Ok::<(), eh1::spi::ErrorKind>(())
2351 /// ```
2352 fn sn_tx_fsr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2353 let mut reg: [u8; 2] = [0; 2];
2354 self.read(SnReg::TX_FSR0.addr(), sn.block(), &mut reg)?;
2355 Ok(u16::from_be_bytes(reg))
2356 }
2357
2358 /// Get the socket TX read pointer.
2359 ///
2360 /// This register is initialized by the [`SocketCommand::Open`] command.
2361 /// However, in TCP mode, this is re-initialized while connecting with TCP.
2362 ///
2363 /// After initialization, this is auto-increased by the
2364 /// [`SocketCommand::Send`] command.
2365 ///
2366 /// The [`SocketCommand::Send`] command transmits the saved data from the
2367 /// current [`Registers::sn_tx_rd`] to the [`Registers::sn_tx_wr`] in the
2368 /// socket n TX buffer.
2369 /// After transmitting the saved data, the [`SocketCommand::Send`] command
2370 /// increases [`Registers::sn_tx_rd`] the as same as
2371 /// [`Registers::sn_tx_wr`].
2372 ///
2373 /// If its increment value exceeds the maximum value `0xFFFF`,
2374 /// (greater than `0x10000` and the carry bit occurs), then the carry bit is
2375 /// ignored and will automatically update with the lower 16 bits value.
2376 ///
2377 /// # Example
2378 ///
2379 /// ```
2380 /// # let spi = ehm::eh1::spi::Mock::new(&[
2381 /// # ehm::eh1::spi::Transaction::transaction_start(),
2382 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x22, 0x08]),
2383 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2384 /// # ehm::eh1::spi::Transaction::transaction_end(),
2385 /// # ]);
2386 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketMode};
2387 ///
2388 /// let mut w5500 = W5500::new(spi);
2389 /// let sn_tx_rd: u16 = w5500.sn_tx_rd(Sn::Sn0)?;
2390 /// # w5500.free().done();
2391 /// # Ok::<(), eh1::spi::ErrorKind>(())
2392 /// ```
2393 fn sn_tx_rd(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2394 let mut reg: [u8; 2] = [0; 2];
2395 self.read(SnReg::TX_RD0.addr(), sn.block(), &mut reg)?;
2396 Ok(u16::from_be_bytes(reg))
2397 }
2398
2399 /// Get the socket TX write pointer.
2400 ///
2401 /// This register is initialized by the [`SocketCommand::Open`] command.
2402 /// However, in TCP mode, this is re-initialized while connecting with TCP.
2403 ///
2404 /// This should be updated as follows:
2405 /// 1. Read the starting address for transmitting data.
2406 /// 2. Write data to the socket TX buffer buffer.
2407 /// 3. Update this register by the number of bytes written to the TX buffer.
2408 /// Allow wrapping to occur upon `u16` overflow.
2409 /// 4. Transmit the saved data in the socket TX buffer by using the
2410 /// [`SocketCommand::Send`] command.
2411 ///
2412 /// See [`Registers::set_sn_tx_buf`] for an additional example.
2413 ///
2414 /// # Example
2415 ///
2416 /// ```
2417 /// # let spi = ehm::eh1::spi::Mock::new(&[
2418 /// # ehm::eh1::spi::Transaction::transaction_start(),
2419 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x08]),
2420 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2421 /// # ehm::eh1::spi::Transaction::transaction_end(),
2422 /// # ]);
2423 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2424 ///
2425 /// let mut w5500 = W5500::new(spi);
2426 /// let sn_tx_wr: u16 = w5500.sn_tx_wr(Sn::Sn0)?;
2427 /// # w5500.free().done();
2428 /// # Ok::<(), eh1::spi::ErrorKind>(())
2429 /// ```
2430 fn sn_tx_wr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2431 let mut reg: [u8; 2] = [0; 2];
2432 self.read(SnReg::TX_WR0.addr(), sn.block(), &mut reg)?;
2433 Ok(u16::from_be_bytes(reg))
2434 }
2435
2436 /// Set the socket TX write pointer.
2437 ///
2438 /// See [`Registers::sn_tx_wr`] for more information.
2439 ///
2440 /// See [`Registers::set_sn_tx_buf`] for an example.
2441 fn set_sn_tx_wr(&mut self, sn: Sn, ptr: u16) -> Result<(), Self::Error> {
2442 self.write(SnReg::TX_WR0.addr(), sn.block(), &ptr.to_be_bytes())
2443 }
2444
2445 /// Get the socket TX free size and write pointer
2446 ///
2447 /// This is equivalent to [`Registers::sn_tx_fsr`] and
2448 /// [`Registers::sn_tx_wr`] in a single read transaction.
2449 fn sn_tx_ptrs(&mut self, sn: Sn) -> Result<TxPtrs, Self::Error> {
2450 let mut buf: [u8; 6] = [0; 6];
2451 self.read(SnReg::TX_FSR0.addr(), sn.block(), &mut buf)?;
2452 Ok(TxPtrs {
2453 fsr: u16::from_be_bytes(buf[..2].try_into().unwrap()),
2454 wr: u16::from_be_bytes(buf[4..].try_into().unwrap()),
2455 })
2456 }
2457
2458 /// Get the socket received data size.
2459 ///
2460 /// This register indicates the data size received and saved in the socket
2461 /// RX buffer.
2462 /// This register does not exceed the configured size
2463 /// ([`Registers::set_sn_rxbuf_size`]) and is calculated as the difference
2464 /// between [`Registers::sn_rx_wr`] and [`Registers::sn_rx_rd`].
2465 ///
2466 /// # Example
2467 ///
2468 /// ```
2469 /// # let spi = ehm::eh1::spi::Mock::new(&[
2470 /// # ehm::eh1::spi::Transaction::transaction_start(),
2471 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x26, 0x08]),
2472 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2473 /// # ehm::eh1::spi::Transaction::transaction_end(),
2474 /// # ]);
2475 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2476 ///
2477 /// let mut w5500 = W5500::new(spi);
2478 /// let sn_rx_rsr: u16 = w5500.sn_rx_rsr(Sn::Sn0)?;
2479 /// # w5500.free().done();
2480 /// # Ok::<(), eh1::spi::ErrorKind>(())
2481 /// ```
2482 fn sn_rx_rsr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2483 let mut reg: [u8; 2] = [0; 2];
2484 self.read(SnReg::RX_RSR0.addr(), sn.block(), &mut reg)?;
2485 Ok(u16::from_be_bytes(reg))
2486 }
2487
2488 /// Get the socket read data pointer.
2489 ///
2490 /// This register is initialized by the [`SocketCommand::Open`] command.
2491 ///
2492 /// This should be updated as follows:
2493 /// 1. Read the starting address for reading data.
2494 /// 2. Read from the socket RX buffer.
2495 /// 3. Update this register by the number of bytes read from the RX buffer.
2496 /// Allow wrapping to occur upon `u16` overflow.
2497 /// 4. Send a [`SocketCommand::Recv`] command to notify the W5500 of the
2498 /// retrieved data.
2499 ///
2500 /// See [`Registers::sn_rx_buf`] for an additional example.
2501 ///
2502 /// # Example
2503 ///
2504 /// ```
2505 /// # let spi = ehm::eh1::spi::Mock::new(&[
2506 /// # ehm::eh1::spi::Transaction::transaction_start(),
2507 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x28, 0x08]),
2508 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2509 /// # ehm::eh1::spi::Transaction::transaction_end(),
2510 /// # ]);
2511 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2512 ///
2513 /// let mut w5500 = W5500::new(spi);
2514 /// let sn_rx_rd: u16 = w5500.sn_rx_rd(Sn::Sn0)?;
2515 /// # w5500.free().done();
2516 /// # Ok::<(), eh1::spi::ErrorKind>(())
2517 /// ```
2518 fn sn_rx_rd(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2519 let mut reg: [u8; 2] = [0; 2];
2520 self.read(SnReg::RX_RD0.addr(), sn.block(), &mut reg)?;
2521 Ok(u16::from_be_bytes(reg))
2522 }
2523
2524 /// Set the socket read data pointer.
2525 ///
2526 /// See [`Registers::sn_rx_rd`] for more information.
2527 /// See [`Registers::sn_rx_buf`] for an example.
2528 fn set_sn_rx_rd(&mut self, sn: Sn, ptr: u16) -> Result<(), Self::Error> {
2529 self.write(SnReg::RX_RD0.addr(), sn.block(), &ptr.to_be_bytes())
2530 }
2531
2532 /// Get the socket RX write pointer.
2533 ///
2534 /// This register is initialized by the [`SocketCommand::Open`] command, and
2535 /// it is auto-incremented by hardware.
2536 ///
2537 /// # Example
2538 ///
2539 /// ```
2540 /// # let spi = ehm::eh1::spi::Mock::new(&[
2541 /// # ehm::eh1::spi::Transaction::transaction_start(),
2542 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2A, 0x08]),
2543 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2544 /// # ehm::eh1::spi::Transaction::transaction_end(),
2545 /// # ]);
2546 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2547 ///
2548 /// let mut w5500 = W5500::new(spi);
2549 /// let sn_rx_wr: u16 = w5500.sn_rx_wr(Sn::Sn0)?;
2550 /// # w5500.free().done();
2551 /// # Ok::<(), eh1::spi::ErrorKind>(())
2552 /// ```
2553 fn sn_rx_wr(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2554 let mut reg: [u8; 2] = [0; 2];
2555 self.read(SnReg::RX_WR0.addr(), sn.block(), &mut reg)?;
2556 Ok(u16::from_be_bytes(reg))
2557 }
2558
2559 /// Get the socket RX received size size and write pointer
2560 ///
2561 /// This is equivalent to [`Registers::sn_rx_rsr`] and
2562 /// [`Registers::sn_rx_rd`] in a single read transaction.
2563 fn sn_rx_ptrs(&mut self, sn: Sn) -> Result<RxPtrs, Self::Error> {
2564 let mut buf: [u8; 4] = [0; 4];
2565 self.read(SnReg::RX_RSR0.addr(), sn.block(), &mut buf)?;
2566 Ok(RxPtrs {
2567 rsr: u16::from_be_bytes(buf[..2].try_into().unwrap()),
2568 rd: u16::from_be_bytes(buf[2..].try_into().unwrap()),
2569 })
2570 }
2571
2572 /// Get the socket interrupt mask.
2573 ///
2574 /// # Example
2575 ///
2576 /// ```
2577 /// # let spi = ehm::eh1::spi::Mock::new(&[
2578 /// # ehm::eh1::spi::Transaction::transaction_start(),
2579 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2C, 0x08]),
2580 /// # ehm::eh1::spi::Transaction::read(0xFF),
2581 /// # ehm::eh1::spi::Transaction::transaction_end(),
2582 /// # ]);
2583 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterruptMask};
2584 ///
2585 /// let mut w5500 = W5500::new(spi);
2586 /// let sn_imr: SocketInterruptMask = w5500.sn_imr(Sn::Sn0)?;
2587 /// assert_eq!(sn_imr, SocketInterruptMask::default());
2588 /// # w5500.free().done();
2589 /// # Ok::<(), eh1::spi::ErrorKind>(())
2590 /// ```
2591 fn sn_imr(&mut self, sn: Sn) -> Result<SocketInterruptMask, Self::Error> {
2592 let mut reg: [u8; 1] = [0];
2593 self.read(SnReg::IMR.addr(), sn.block(), &mut reg)?;
2594 Ok(SocketInterruptMask::from(reg[0]))
2595 }
2596
2597 /// Set the socket interrupt mask.
2598 ///
2599 /// # Example
2600 ///
2601 /// ```
2602 /// # let spi = ehm::eh1::spi::Mock::new(&[
2603 /// # ehm::eh1::spi::Transaction::transaction_start(),
2604 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2C, 0x08 | 0x04]),
2605 /// # ehm::eh1::spi::Transaction::write(0xE0),
2606 /// # ehm::eh1::spi::Transaction::transaction_end(),
2607 /// # ]);
2608 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketInterruptMask};
2609 ///
2610 /// let mut w5500 = W5500::new(spi);
2611 /// w5500.set_sn_imr(Sn::Sn0, SocketInterruptMask::ALL_MASKED)?;
2612 /// # w5500.free().done();
2613 /// # Ok::<(), eh1::spi::ErrorKind>(())
2614 /// ```
2615 fn set_sn_imr(&mut self, sn: Sn, mask: SocketInterruptMask) -> Result<(), Self::Error> {
2616 self.write(SnReg::IMR.addr(), sn.block(), &[mask.into()])
2617 }
2618
2619 /// Get the socket fragment.
2620 ///
2621 /// This configures the fragment field in the IP header.
2622 ///
2623 /// # Example
2624 ///
2625 /// ```
2626 /// # let spi = ehm::eh1::spi::Mock::new(&[
2627 /// # ehm::eh1::spi::Transaction::transaction_start(),
2628 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2D, 0x08]),
2629 /// # ehm::eh1::spi::Transaction::read_vec(vec![0x40, 0x00]),
2630 /// # ehm::eh1::spi::Transaction::transaction_end(),
2631 /// # ]);
2632 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2633 ///
2634 /// let mut w5500 = W5500::new(spi);
2635 /// let frag: u16 = w5500.sn_frag(Sn::Sn0)?;
2636 /// assert_eq!(frag, 0x4000);
2637 /// # w5500.free().done();
2638 /// # Ok::<(), eh1::spi::ErrorKind>(())
2639 /// ```
2640 fn sn_frag(&mut self, sn: Sn) -> Result<u16, Self::Error> {
2641 let mut buf: [u8; 2] = [0; 2];
2642 self.read(SnReg::FRAG0.addr(), sn.block(), &mut buf)?;
2643 Ok(u16::from_be_bytes(buf))
2644 }
2645
2646 /// Set the socket fragment.
2647 ///
2648 /// See [`Registers::sn_frag`] for more information.
2649 ///
2650 /// # Example
2651 ///
2652 /// ```
2653 /// # let spi = ehm::eh1::spi::Mock::new(&[
2654 /// # ehm::eh1::spi::Transaction::transaction_start(),
2655 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2D, 0x08 | 0x04]),
2656 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00]),
2657 /// # ehm::eh1::spi::Transaction::transaction_end(),
2658 /// # ]);
2659 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2660 ///
2661 /// let mut w5500 = W5500::new(spi);
2662 /// w5500.set_sn_frag(Sn::Sn0, 0)?;
2663 /// # w5500.free().done();
2664 /// # Ok::<(), eh1::spi::ErrorKind>(())
2665 /// ```
2666 fn set_sn_frag(&mut self, sn: Sn, frag: u16) -> Result<(), Self::Error> {
2667 self.write(SnReg::FRAG0.addr(), sn.block(), &u16::to_be_bytes(frag))
2668 }
2669
2670 /// Get the socket keep alive time.
2671 ///
2672 /// This register configures the transmitting timer of the keep alive (KA)
2673 /// packet for the socket. This is valid only in TCP mode, and is ignored
2674 /// in all other modes.
2675 ///
2676 /// The time unit is 5 seconds.
2677 ///
2678 /// The KA packet is transmittable after [`Registers::sn_sr`] is changed to
2679 /// [`SocketStatus::Established`] and after the data is transmitted or
2680 /// received to/from a peer at least once.
2681 ///
2682 /// In the case of a non-zero keep alive value the W5500 automatically
2683 /// transmits a KA packet after time-period for checking the TCP connection
2684 /// (automatic-keepalive-process).
2685 ///
2686 /// In case of a zero keep alive value, the keep alive packet can be
2687 /// transmitted with [`SocketCommand::SendKeep`]. This command is ignored
2688 /// for non-zero keep alive values.
2689 ///
2690 /// # Example
2691 ///
2692 /// ```
2693 /// # let spi = ehm::eh1::spi::Mock::new(&[
2694 /// # ehm::eh1::spi::Transaction::transaction_start(),
2695 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2F, 0x08]),
2696 /// # ehm::eh1::spi::Transaction::read(0),
2697 /// # ehm::eh1::spi::Transaction::transaction_end(),
2698 /// # ]);
2699 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2700 ///
2701 /// let mut w5500 = W5500::new(spi);
2702 /// let sn_kpalvtr: u8 = w5500.sn_kpalvtr(Sn::Sn0)?;
2703 /// # w5500.free().done();
2704 /// # Ok::<(), eh1::spi::ErrorKind>(())
2705 /// ```
2706 fn sn_kpalvtr(&mut self, sn: Sn) -> Result<u8, Self::Error> {
2707 let mut buf: [u8; 1] = [0];
2708 self.read(SnReg::KPALVTR.addr(), sn.block(), &mut buf)?;
2709 Ok(buf[0])
2710 }
2711
2712 /// Set the socket keep alive time.
2713 ///
2714 /// See [`Registers::sn_kpalvtr`] for more information.
2715 ///
2716 /// # Example
2717 ///
2718 /// ```
2719 /// # let spi = ehm::eh1::spi::Mock::new(&[
2720 /// # ehm::eh1::spi::Transaction::transaction_start(),
2721 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x2F, 0x08 | 0x04]),
2722 /// # ehm::eh1::spi::Transaction::write(0x0A),
2723 /// # ehm::eh1::spi::Transaction::transaction_end(),
2724 /// # ]);
2725 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn};
2726 ///
2727 /// let mut w5500 = W5500::new(spi);
2728 /// // 50s keep alive timer
2729 /// w5500.set_sn_kpalvtr(Sn::Sn0, 10)?;
2730 /// # w5500.free().done();
2731 /// # Ok::<(), eh1::spi::ErrorKind>(())
2732 /// ```
2733 fn set_sn_kpalvtr(&mut self, sn: Sn, kpalvtr: u8) -> Result<(), Self::Error> {
2734 self.write(SnReg::KPALVTR.addr(), sn.block(), &[kpalvtr])
2735 }
2736
2737 /// Write the socket TX buffer.
2738 ///
2739 /// # Example
2740 ///
2741 /// ```
2742 /// use core::cmp::min;
2743 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2744 /// # let spi = ehm::eh1::spi::Mock::new(&[
2745 /// # // sn_tx_fsr
2746 /// # ehm::eh1::spi::Transaction::transaction_start(),
2747 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::TX_FSR0.addr() as u8, 0x08]),
2748 /// # ehm::eh1::spi::Transaction::read_vec(vec![0x08, 0x00]),
2749 /// # ehm::eh1::spi::Transaction::transaction_end(),
2750 /// # // sn_tx_write
2751 /// # ehm::eh1::spi::Transaction::transaction_start(),
2752 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::TX_WR0.addr() as u8, 0x08]),
2753 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2754 /// # ehm::eh1::spi::Transaction::transaction_end(),
2755 /// # // set_sn_tx_buf
2756 /// # ehm::eh1::spi::Transaction::transaction_start(),
2757 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.tx_block() as u8) << 3 | 0x04]),
2758 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x12, 0x34, 0x56, 0x78, 0x9A]),
2759 /// # ehm::eh1::spi::Transaction::transaction_end(),
2760 /// # // set_sn_tx_wr
2761 /// # ehm::eh1::spi::Transaction::transaction_start(),
2762 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x24, 0x08 | 0x04]),
2763 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 5]),
2764 /// # ehm::eh1::spi::Transaction::transaction_end(),
2765 /// # // set_sn_cr
2766 /// # ehm::eh1::spi::Transaction::transaction_start(),
2767 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x01, 0x08 | 0x04]),
2768 /// # ehm::eh1::spi::Transaction::write_vec(vec![SocketCommand::Send.into()]),
2769 /// # ehm::eh1::spi::Transaction::transaction_end(),
2770 /// # ]);
2771 /// # let mut w5500 = W5500::new(spi);
2772 ///
2773 /// // the socket should already be opened at this point
2774 /// const THE_SOCKET: Sn = Sn::Sn0;
2775 ///
2776 /// let buf: [u8; 5] = [0x12, 0x34, 0x56, 0x78, 0x9A];
2777 ///
2778 /// // transmit as many bytes as possible
2779 /// // for large buffers this may not transmit all the available data
2780 /// let tx_bytes: u16 = {
2781 /// min(w5500.sn_tx_fsr(THE_SOCKET)?, u16::try_from(buf.len()).unwrap_or(u16::MAX))
2782 /// };
2783 /// if tx_bytes == 0 {
2784 /// return Ok(());
2785 /// }
2786 ///
2787 /// let ptr: u16 = w5500.sn_tx_wr(THE_SOCKET)?;
2788 /// w5500.set_sn_tx_buf(THE_SOCKET, ptr, &buf[..usize::from(tx_bytes)])?;
2789 /// w5500.set_sn_tx_wr(THE_SOCKET, ptr.wrapping_add(tx_bytes))?;
2790 /// w5500.set_sn_cr(THE_SOCKET, SocketCommand::Send)?;
2791 /// # w5500.free().done();
2792 /// # Ok::<(), eh1::spi::ErrorKind>(())
2793 /// ```
2794 fn set_sn_tx_buf(&mut self, sn: Sn, ptr: u16, buf: &[u8]) -> Result<(), Self::Error> {
2795 self.write(ptr, sn.tx_block(), buf)
2796 }
2797
2798 /// Read the socket TX buffer.
2799 ///
2800 /// This method is typically unused; there are very few use cases that
2801 /// require reading the TX buffer.
2802 ///
2803 /// # Example
2804 ///
2805 /// ```
2806 /// use core::cmp::min;
2807 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2808 /// # let spi = ehm::eh1::spi::Mock::new(&[
2809 /// # ehm::eh1::spi::Transaction::transaction_start(),
2810 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.tx_block() as u8) << 3]),
2811 /// # ehm::eh1::spi::Transaction::read(0),
2812 /// # ehm::eh1::spi::Transaction::transaction_end(),
2813 /// # ]);
2814 /// # let mut w5500 = W5500::new(spi);
2815 /// let mut buf: [u8; 1] = [0];
2816 /// w5500.sn_tx_buf(Sn::Sn0, 0, &mut buf)?;
2817 /// # w5500.free().done();
2818 /// # Ok::<(), eh1::spi::ErrorKind>(())
2819 /// ```
2820 fn sn_tx_buf(&mut self, sn: Sn, ptr: u16, buf: &mut [u8]) -> Result<(), Self::Error> {
2821 self.read(ptr, sn.tx_block(), buf)
2822 }
2823
2824 /// Read the socket RX buffer.
2825 ///
2826 /// # Example
2827 ///
2828 /// ```
2829 /// use core::cmp::min;
2830 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2831 /// # let spi = ehm::eh1::spi::Mock::new(&[
2832 /// # ehm::eh1::spi::Transaction::transaction_start(),
2833 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::RX_RSR0.addr() as u8, 0x08]),
2834 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 4]),
2835 /// # ehm::eh1::spi::Transaction::transaction_end(),
2836 /// # ehm::eh1::spi::Transaction::transaction_start(),
2837 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::RX_RD0.addr() as u8, 0x08]),
2838 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0]),
2839 /// # ehm::eh1::spi::Transaction::transaction_end(),
2840 /// # ehm::eh1::spi::Transaction::transaction_start(),
2841 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.rx_block() as u8) << 3]),
2842 /// # ehm::eh1::spi::Transaction::read_vec(vec![0, 0, 0, 0]),
2843 /// # ehm::eh1::spi::Transaction::transaction_end(),
2844 /// # ehm::eh1::spi::Transaction::transaction_start(),
2845 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::RX_RD0.addr() as u8, 0x08 | 0x04]),
2846 /// # ehm::eh1::spi::Transaction::write_vec(vec![0, 4]),
2847 /// # ehm::eh1::spi::Transaction::transaction_end(),
2848 /// # ehm::eh1::spi::Transaction::transaction_start(),
2849 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, w5500_ll::SnReg::CR.addr() as u8, 0x08 | 0x04]),
2850 /// # ehm::eh1::spi::Transaction::write(SocketCommand::Recv.into()),
2851 /// # ehm::eh1::spi::Transaction::transaction_end(),
2852 /// # ]);
2853 /// # let mut w5500 = W5500::new(spi);
2854 ///
2855 /// // the socket should already be opened at this point
2856 /// // a socket interrupt will indicate there is data to be retrieved
2857 /// const THE_SOCKET: Sn = Sn::Sn0;
2858 ///
2859 /// // in reality you will need a larger buffer for most protocols
2860 /// const BUF_LEN: usize = 16;
2861 /// let mut buf: [u8; BUF_LEN] = [0; BUF_LEN];
2862 ///
2863 /// let rx_bytes: u16 = {
2864 /// min(w5500.sn_rx_rsr(THE_SOCKET)?, u16::try_from(buf.len()).unwrap_or(u16::MAX))
2865 /// };
2866 /// if rx_bytes == 0 {
2867 /// return Ok(());
2868 /// }
2869 ///
2870 /// let ptr: u16 = w5500.sn_rx_rd(THE_SOCKET)?;
2871 /// w5500.sn_rx_buf(THE_SOCKET, ptr, &mut buf[..usize::from(rx_bytes)])?;
2872 /// w5500.set_sn_rx_rd(THE_SOCKET, ptr.wrapping_add(rx_bytes))?;
2873 /// w5500.set_sn_cr(THE_SOCKET, SocketCommand::Recv)?;
2874 /// # w5500.free().done();
2875 /// # Ok::<(), eh1::spi::ErrorKind>(())
2876 /// ```
2877 fn sn_rx_buf(&mut self, sn: Sn, ptr: u16, buf: &mut [u8]) -> Result<(), Self::Error> {
2878 self.read(ptr, sn.rx_block(), buf)
2879 }
2880
2881 /// Write the socket RX buffer.
2882 ///
2883 /// This method is typically unused; there are very few use cases that
2884 /// require writing the RX buffer.
2885 ///
2886 /// # Example
2887 ///
2888 /// ```
2889 /// use core::cmp::min;
2890 /// use w5500_ll::{eh1::vdm::W5500, Registers, Sn, SocketCommand};
2891 /// # let spi = ehm::eh1::spi::Mock::new(&[
2892 /// # ehm::eh1::spi::Transaction::transaction_start(),
2893 /// # ehm::eh1::spi::Transaction::write_vec(vec![0x00, 0x00, (Sn::Sn0.rx_block() as u8) << 3 | 0x04]),
2894 /// # ehm::eh1::spi::Transaction::write(0),
2895 /// # ehm::eh1::spi::Transaction::transaction_end(),
2896 /// # ]);
2897 /// # let mut w5500 = W5500::new(spi);
2898 /// let buf: [u8; 1] = [0];
2899 /// w5500.set_sn_rx_buf(Sn::Sn0, 0, &buf)?;
2900 /// # w5500.free().done();
2901 /// # Ok::<(), eh1::spi::ErrorKind>(())
2902 /// ```
2903 fn set_sn_rx_buf(&mut self, sn: Sn, ptr: u16, buf: &[u8]) -> Result<(), Self::Error> {
2904 self.write(ptr, sn.rx_block(), buf)
2905 }
2906}