w5500_ll/
specifiers.rs

1//! Register specifiers (enumerations).
2
3/// Socket status.
4///
5/// This is used with the [`sn_sr`] method.
6///
7/// [`sn_sr`]: crate::Registers::sn_sr
8#[derive(Copy, Clone, Eq, PartialEq, Debug, PartialOrd, Ord, Hash, Default)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10#[repr(u8)]
11pub enum SocketStatus {
12    /// Socket closed, this is the reset state of all sockets.
13    ///
14    /// This state can be set by a [`Disconnect`] or [`Close`] command.
15    ///
16    /// This state will also be set automatically if a timeout occurs.
17    ///
18    /// [`Disconnect`]: SocketCommand::Disconnect
19    /// [`Close`]: SocketCommand::Close
20    #[default]
21    Closed = 0x00,
22    /// The socket is opened in TCP mode.
23    ///
24    /// This state is set when the socket protocol is [`Tcp`], and a [`Open`]
25    /// command is sent.
26    ///
27    /// In this state you can use the [`Listen`] and [`Connect`] commands.
28    ///
29    /// [`Tcp`]: Protocol::Tcp
30    /// [`Open`]: SocketCommand::Open
31    /// [`Listen`]: SocketCommand::Listen
32    /// [`Connect`]: SocketCommand::Connect
33    Init = 0x13,
34    /// The socket is listening, operating as a TCP server.
35    ///
36    /// The socket will wait for a connextion-request (SYN packet) from a
37    /// peer (TCP client).
38    ///
39    /// The state will change to [`Established`] when the connection-request is
40    /// successfully accepted.
41    /// Otherwise the state will change to [`Closed`] after the
42    /// TCP timeout duration set by [`rcr`] and [`rtr`].
43    ///
44    /// [`Established`]: SocketStatus::Established
45    /// [`Closed`]: SocketStatus::Closed
46    /// [`rcr`]: crate::Registers::rcr
47    /// [`rtr`]: crate::Registers::rtr
48    Listen = 0x14,
49    /// Connection request (SYN packet) has been sent to a peer.
50    ///
51    /// This is temporarily displayed between the [`Init`] and [`Established`]
52    /// states, after a [`Connect`] command has been sent.
53    ///
54    /// If the SYN/ACK is received from the peer the state changes to
55    /// [`Established`], otherwise the state changes to [`Closed`] after the TCP
56    /// timeout duration set by [`rcr`] and [`rtr`].
57    ///
58    /// [`Init`]: SocketStatus::Init
59    /// [`Connect`]: SocketCommand::Connect
60    /// [`Established`]: SocketStatus::Established
61    /// [`Closed`]: SocketStatus::Closed
62    /// [`rcr`]: crate::Registers::rcr
63    /// [`rtr`]: crate::Registers::rtr
64    SynSent = 0x15,
65    /// Connection request (SYN packet) has been received from a peer.
66    ///
67    /// If the socket sends the response (SYN/ACK packet) to the peer
68    /// successfully the state changes to [`Established`], otherwise the state
69    /// changes to [`Closed`] after the TCP timeout duration set by [`rcr`] and
70    /// [`rtr`].
71    ///
72    /// [`Established`]: SocketStatus::Established
73    /// [`Closed`]: SocketStatus::Closed
74    /// [`rcr`]: crate::Registers::rcr
75    /// [`rtr`]: crate::Registers::rtr
76    SynRecv = 0x16,
77    /// TCP connection is established.
78    ///
79    /// When operating as a TCP client this state is set after the TCP server
80    /// accepts the SYN packet, which is sent by the client after issuing a
81    /// [`Connect`].
82    ///
83    /// When operating as a TCP server this state is set after a client
84    /// connects when in the [`Listen`] state.
85    ///
86    /// While in this state data can be transferred with the [`Send`] and
87    /// [`Recv`] commands.
88    ///
89    /// [`Connect`]: SocketCommand::Connect
90    /// [`Listen`]: SocketStatus::Listen
91    /// [`Send`]: SocketCommand::Send
92    /// [`Recv`]: SocketCommand::Recv
93    Established = 0x17,
94    /// Temporary status between status transitions.
95    ///
96    /// This indicates the socket is closing.
97    FinWait = 0x18,
98    /// Temporary status between status transitions.
99    ///
100    /// This indicates the socket is closing.
101    Closing = 0x1A,
102    /// Temporary status between status transitions.
103    ///
104    /// This indicates the socket is closing.
105    TimeWait = 0x1B,
106    /// The socket has received the disconnect-request (FIN packet) from the
107    /// connected peer.
108    ///
109    /// This is half-closing status, and data can be transferred.
110    ///
111    /// For full-closing the [`Disconnect`] command is used.
112    ///
113    /// For just-closing the [`Close`] command is used.
114    ///
115    /// [`Disconnect`]: SocketCommand::Disconnect
116    /// [`Close`]: SocketCommand::Close
117    CloseWait = 0x1C,
118    /// Temporary status between status transitions.
119    LastAck = 0x1D,
120    /// Socket is opened in UDP mode.
121    ///
122    /// This state is set when the socket protocol is [`Udp`], and a [`Open`]
123    /// command is sent.
124    ///
125    /// [`Udp`]: Protocol::Udp
126    /// [`Open`]: SocketCommand::Open
127    Udp = 0x22,
128    /// Socket is opened in MACRAW mode.
129    ///
130    /// This is valid only for [socket 0].
131    ///
132    /// This state is set when the socket protocol is [`Macraw`], and a [`Open`]
133    /// command is sent.
134    ///
135    /// [socket 0]: crate::Sn::Sn0
136    /// [`Macraw`]: Protocol::Macraw
137    /// [`Open`]: SocketCommand::Open
138    Macraw = 0x42,
139}
140impl From<SocketStatus> for u8 {
141    fn from(val: SocketStatus) -> u8 {
142        val as u8
143    }
144}
145impl TryFrom<u8> for SocketStatus {
146    type Error = u8;
147    fn try_from(val: u8) -> Result<SocketStatus, u8> {
148        match val {
149            x if x == SocketStatus::Closed as u8 => Ok(SocketStatus::Closed),
150            x if x == SocketStatus::Init as u8 => Ok(SocketStatus::Init),
151            x if x == SocketStatus::Listen as u8 => Ok(SocketStatus::Listen),
152            x if x == SocketStatus::SynSent as u8 => Ok(SocketStatus::SynSent),
153            x if x == SocketStatus::SynRecv as u8 => Ok(SocketStatus::SynRecv),
154            x if x == SocketStatus::Established as u8 => Ok(SocketStatus::Established),
155            x if x == SocketStatus::FinWait as u8 => Ok(SocketStatus::FinWait),
156            x if x == SocketStatus::Closing as u8 => Ok(SocketStatus::Closing),
157            x if x == SocketStatus::TimeWait as u8 => Ok(SocketStatus::TimeWait),
158            x if x == SocketStatus::CloseWait as u8 => Ok(SocketStatus::CloseWait),
159            x if x == SocketStatus::LastAck as u8 => Ok(SocketStatus::LastAck),
160            x if x == SocketStatus::Udp as u8 => Ok(SocketStatus::Udp),
161            x if x == SocketStatus::Macraw as u8 => Ok(SocketStatus::Macraw),
162            _ => Err(val),
163        }
164    }
165}
166
167/// Socket commands.
168///
169/// This is used to set the command for socket n.
170///
171/// After W5500 accepts the command, the [`sn_cr`] register is automatically
172/// cleared to `0x00`.
173/// Even though [`sn_cr`] is cleared to `0x00`, the command
174/// is still being processed.
175/// To check whether the command is completed or not, check
176/// [`sn_ir`] or [`sn_sr`].
177///
178/// [`sn_cr`]: crate::Registers::set_sn_cr
179/// [`sn_ir`]: crate::Registers::sn_ir
180/// [`sn_sr`]: crate::Registers::sn_sr
181#[derive(Copy, Clone, Eq, PartialEq, Debug, PartialOrd, Ord, Hash)]
182#[cfg_attr(feature = "defmt", derive(defmt::Format))]
183#[repr(u8)]
184pub enum SocketCommand {
185    /// The command register clears to this state once a command has been
186    /// accepted.
187    Accepted = 0x00,
188    /// The socket is initialized and opened according to the protocol
189    /// selected in [`sn_mr`].
190    ///
191    /// | [`sn_mr`]            | [`sn_sr`]                   |
192    /// |----------------------|-----------------------------|
193    /// | [`Protocol::Closed`] | -                           |
194    /// | [`Protocol::Tcp`]    | [`SocketStatus::Init`]      |
195    /// | [`Protocol::Udp`]    | [`SocketStatus::Udp`]       |
196    /// | [`Protocol::Macraw`] | [`SocketStatus::Macraw`]    |
197    ///
198    /// [`sn_mr`]: crate::Registers::sn_mr
199    /// [`sn_sr`]: crate::Registers::sn_sr
200    Open = 0x01,
201    /// Operate the socket as a TCP server.
202    ///
203    /// This will change the socket state from [`Init`] to [`Listen`],
204    /// and the socket will listen for a
205    /// connection-request (SYN packet) from any TCP client.
206    ///
207    /// When a TCP client connection request is successfully established,
208    /// the socket state changes from [`Listen`] to
209    /// [`Established`] and the [`CON`] socket interrupt is raised.
210    ///
211    /// When a TCP client connection request fails the [`TIMEOUT`] socket
212    /// interrupt is set and the
213    /// socket status changes to [`Closed`].
214    ///
215    /// Only valid in [`Tcp`] mode.
216    ///
217    /// [`Closed`]: SocketStatus::Closed
218    /// [`CON`]: crate::SocketInterrupt::con_raised
219    /// [`Established`]: SocketStatus::Established
220    /// [`Init`]: SocketStatus::Init
221    /// [`Listen`]: SocketStatus::Listen
222    /// [`Tcp`]: Protocol::Tcp
223    /// [`TIMEOUT`]: crate::SocketInterrupt::timeout_raised
224    Listen = 0x02,
225    /// Connect to a TCP server.
226    ///
227    /// A connect-request (SYN packet) is sent to the TCP server configured by
228    /// the IPv4 address and port set with [`set_sn_dest`].
229    ///
230    /// If the connect-request is successful, the socket state changes to
231    /// [`Established`] and the [`CON`] socket interrupt is raised.
232    ///
233    /// The connect-request fails in the following three cases:
234    /// 1. When a ARP<sub>TO</sub> occurs ([`timeout_raised`]) because the
235    ///    destination hardware address is not acquired through the
236    ///    ARP-process.
237    /// 2. When a SYN/ACK packet is not received within the TCP timeout duration
238    ///    set by [`rcr`] and [`rtr`] ([`timeout_raised`]).
239    /// 3. When a RST packet is received instead of a SYN/ACK packet.
240    ///
241    /// In these cases the socket state changes to [`Closed`].
242    ///
243    /// Only valid in [`Tcp`] mode when acting as a TCP client.
244    ///
245    /// [`Closed`]: SocketStatus::Closed
246    /// [`CON`]: crate::SocketInterrupt::con_raised
247    /// [`Established`]: SocketStatus::Established
248    /// [`rcr`]: crate::Registers::rcr
249    /// [`rtr`]: crate::Registers::rtr
250    /// [`set_sn_dest`]: crate::Registers::set_sn_dest
251    /// [`Tcp`]: Protocol::Tcp
252    /// [`timeout_raised`]: crate::SocketInterrupt::timeout_raised
253    Connect = 0x04,
254    /// Start the disconnect process.
255    ///
256    /// * **Active close** it transmits disconnect-request(FIN packet)
257    ///   to the connected peer.
258    /// * **Passive close** when FIN packet is received from peer,
259    ///   a FIN packet is replied back to the peer.
260    ///
261    /// When the disconnect-process is successful
262    /// (that is, FIN/ACK packet is received successfully),
263    /// the socket state changes to [`Closed`].
264    /// Otherwise, TCP timeout occurs
265    /// ([`timeout_raised`]) and then
266    /// the socket state changes to [`Closed`].
267    ///
268    /// If the [`Close`] command is used instead of
269    /// [`Disconnect`], the socket state is changes to
270    /// [`Closed`] without the disconnect process.
271    ///
272    /// If a RST packet is received from a peer during communication the socket
273    /// status is unconditionally changed to [`Closed`].
274    ///
275    /// Only valid in [`Tcp`] mode.
276    ///
277    /// [`Disconnect`]: SocketCommand::Disconnect
278    /// [`Close`]: SocketCommand::Close
279    /// [`Closed`]: SocketStatus::Closed
280    /// [`Tcp`]: Protocol::Tcp
281    /// [`timeout_raised`]: crate::SocketInterrupt::timeout_raised
282    Disconnect = 0x08,
283    /// Close the socket.
284    ///
285    /// The socket status is changed to [`Closed`].
286    ///
287    /// [`Closed`]: SocketStatus::Closed
288    Close = 0x10,
289    /// Transmits all the data in the socket TX buffer.
290    Send = 0x20,
291    /// The basic operation is same as [`Send`].
292    ///
293    /// Normally [`Send`] transmits data after destination
294    /// hardware address is acquired by the automatic ARP-process
295    /// (Address Resolution Protocol).
296    /// [`SendMac`] transmits data without the automatic
297    /// ARP-process.
298    /// In this case, the destination hardware address is acquired from
299    /// [`sn_dhar`] configured by the host, instead of the ARP
300    /// process.
301    ///
302    /// Only valid in [`Udp`] mode.
303    ///
304    /// [`Send`]: SocketCommand::Send
305    /// [`SendMac`]: SocketCommand::SendMac
306    /// [`Udp`]: Protocol::Udp
307    /// [`sn_dhar`]: crate::Registers::sn_dhar
308    SendMac = 0x21,
309    /// Sends a 1 byte keep-alive packet.
310    ///
311    /// If the peer cannot respond to the keep-alive packet during timeout
312    /// time, the connection is terminated and the timeout interrupt will
313    /// occur ([`timeout_raised`]).
314    ///
315    /// Only valid in [`Tcp`] mode.
316    ///
317    /// [`Tcp`]: Protocol::Tcp
318    /// [`timeout_raised`]: crate::SocketInterrupt::timeout_raised
319    SendKeep = 0x22,
320    /// Completes the processing of the received data in socket RX buffer.
321    ///
322    /// See [`sn_rx_buf`] for an example.
323    ///
324    /// [`sn_rx_buf`]: crate::Registers::sn_rx_buf
325    Recv = 0x40,
326}
327impl From<SocketCommand> for u8 {
328    fn from(val: SocketCommand) -> u8 {
329        val as u8
330    }
331}
332impl TryFrom<u8> for SocketCommand {
333    type Error = u8;
334    fn try_from(val: u8) -> Result<Self, u8> {
335        match val {
336            x if x == Self::Accepted as u8 => Ok(Self::Accepted),
337            x if x == Self::Open as u8 => Ok(Self::Open),
338            x if x == Self::Listen as u8 => Ok(Self::Listen),
339            x if x == Self::Connect as u8 => Ok(Self::Connect),
340            x if x == Self::Disconnect as u8 => Ok(Self::Disconnect),
341            x if x == Self::Close as u8 => Ok(Self::Close),
342            x if x == Self::Send as u8 => Ok(Self::Send),
343            x if x == Self::SendMac as u8 => Ok(Self::SendMac),
344            x if x == Self::SendKeep as u8 => Ok(Self::SendKeep),
345            x if x == Self::Recv as u8 => Ok(Self::Recv),
346            _ => Err(val),
347        }
348    }
349}
350
351/// Socket protocol.
352///
353/// This is used by [`SocketMode::protocol`] method for the [`sn_mr`] register.
354///
355/// [`SocketMode::protocol`]: crate::SocketMode::protocol
356/// [`sn_mr`]: crate::Registers::sn_mr
357#[derive(Copy, Clone, Eq, PartialEq, Debug, PartialOrd, Ord, Hash)]
358#[cfg_attr(feature = "defmt", derive(defmt::Format))]
359#[repr(u8)]
360pub enum Protocol {
361    /// Closed.
362    Closed = 0b0000,
363    /// TCP.
364    Tcp = 0b0001,
365    /// UDP.
366    Udp = 0b0010,
367    /// MACRAW.
368    ///
369    /// MACRAW mode can only be used with [socket 0].
370    ///
371    /// [socket 0]: crate::Sn::Sn0
372    Macraw = 0b0100,
373}
374impl Protocol {
375    /// Convert a raw `u8` to an `Protocol`.
376    ///
377    /// Bit values that do not correspond to a protocol will be returned in the
378    /// `Err` variant of the result.
379    ///
380    /// # Example
381    ///
382    /// ```
383    /// use w5500_ll::Protocol;
384    ///
385    /// assert_eq!(Protocol::from_raw(0b0000), Ok(Protocol::Closed));
386    /// assert_eq!(Protocol::from_raw(0b0001), Ok(Protocol::Tcp));
387    /// assert_eq!(Protocol::from_raw(0b0010), Ok(Protocol::Udp));
388    /// assert_eq!(Protocol::from_raw(0b0100), Ok(Protocol::Macraw));
389    /// assert_eq!(Protocol::from_raw(0b0101), Err(0b0101));
390    /// ```
391    pub const fn from_raw(val: u8) -> Result<Self, u8> {
392        match val {
393            x if x == Protocol::Closed as u8 => Ok(Protocol::Closed),
394            x if x == Protocol::Tcp as u8 => Ok(Protocol::Tcp),
395            x if x == Protocol::Udp as u8 => Ok(Protocol::Udp),
396            x if x == Protocol::Macraw as u8 => Ok(Protocol::Macraw),
397            _ => Err(val),
398        }
399    }
400}
401impl From<Protocol> for u8 {
402    fn from(val: Protocol) -> u8 {
403        val as u8
404    }
405}
406impl Default for Protocol {
407    fn default() -> Self {
408        Self::Closed
409    }
410}
411impl TryFrom<u8> for Protocol {
412    type Error = u8;
413    fn try_from(val: u8) -> Result<Self, u8> {
414        Self::from_raw(val)
415    }
416}
417
418/// PHY operation mode.
419///
420/// This is used by [`PhyCfg::opmdc`] method for the [`phycfgr`] register.
421///
422/// [`PhyCfg::opmdc`]: crate::PhyCfg::opmdc
423/// [`phycfgr`]: crate::Registers::phycfgr
424#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
425#[cfg_attr(feature = "defmt", derive(defmt::Format))]
426#[repr(u8)]
427pub enum OperationMode {
428    /// 10BT half-duplex. Auto-negotiation disabled.
429    HalfDuplex10bt = 0b000,
430    /// 10BT full-duplex. Auto-negotiation disabled.
431    FullDuplex10bt = 0b001,
432    /// 100BT half-duplex. Auto-negotiation disabled.
433    HalfDuplex100bt = 0b010,
434    /// 100BT full-duplex. Auto-negotiation disabled.
435    FullDuplex100bt = 0b011,
436    /// 100BT half-duplex. Auto-negotiation enabled.
437    HalfDuplex100btAuto = 0b100,
438    /// Power down mode.
439    PowerDown = 0b110,
440    /// All capable. Auto-negotiation enabled.
441    Auto = 0b111,
442}
443impl OperationMode {
444    /// Convert a raw `u8` to an `OperationMode`.
445    ///
446    /// Only the first 3 bits of the `u8` value are used.
447    ///
448    /// # Example
449    ///
450    /// ```
451    /// use w5500_ll::OperationMode;
452    ///
453    /// assert_eq!(
454    ///     OperationMode::from_raw(0b000),
455    ///     OperationMode::HalfDuplex10bt
456    /// );
457    /// assert_eq!(
458    ///     OperationMode::from_raw(0b001),
459    ///     OperationMode::FullDuplex10bt
460    /// );
461    /// assert_eq!(
462    ///     OperationMode::from_raw(0b010),
463    ///     OperationMode::HalfDuplex100bt
464    /// );
465    /// assert_eq!(
466    ///     OperationMode::from_raw(0b011),
467    ///     OperationMode::FullDuplex100bt
468    /// );
469    /// assert_eq!(
470    ///     OperationMode::from_raw(0b100),
471    ///     OperationMode::HalfDuplex100btAuto
472    /// );
473    /// assert_eq!(OperationMode::from_raw(0b110), OperationMode::PowerDown);
474    /// assert_eq!(OperationMode::from_raw(0b111), OperationMode::Auto);
475    /// ```
476    pub const fn from_raw(val: u8) -> Self {
477        match val & 0b111 {
478            x if x == Self::HalfDuplex10bt as u8 => Self::HalfDuplex10bt,
479            x if x == Self::FullDuplex10bt as u8 => Self::FullDuplex10bt,
480            x if x == Self::HalfDuplex100bt as u8 => Self::HalfDuplex100bt,
481            x if x == Self::FullDuplex100bt as u8 => Self::FullDuplex100bt,
482            x if x == Self::HalfDuplex100btAuto as u8 => Self::HalfDuplex100btAuto,
483            x if x == Self::PowerDown as u8 => Self::PowerDown,
484            // x if x == Self::Auto as u8
485            _ => Self::Auto,
486        }
487    }
488}
489impl From<OperationMode> for u8 {
490    fn from(val: OperationMode) -> u8 {
491        val as u8
492    }
493}
494impl Default for OperationMode {
495    fn default() -> Self {
496        Self::Auto
497    }
498}
499
500/// PHY link status.
501///
502/// This is used by [`PhyCfg::lnk`] method for the [`phycfgr`] register.
503///
504/// [`PhyCfg::lnk`]: crate::PhyCfg::lnk
505/// [`phycfgr`]: crate::Registers::phycfgr
506#[derive(Copy, Clone, Eq, PartialEq, Debug, PartialOrd, Ord, Hash, Default)]
507#[cfg_attr(feature = "defmt", derive(defmt::Format))]
508#[repr(u8)]
509pub enum LinkStatus {
510    /// PHY link down.
511    #[default]
512    Down = 0,
513    /// PHY link up.
514    Up = 1,
515}
516impl From<bool> for LinkStatus {
517    fn from(val: bool) -> LinkStatus {
518        if val {
519            LinkStatus::Up
520        } else {
521            LinkStatus::Down
522        }
523    }
524}
525impl From<LinkStatus> for u8 {
526    fn from(val: LinkStatus) -> u8 {
527        val as u8
528    }
529}
530
531/// PHY speed status.
532///
533/// This is used by [`PhyCfg::spd`] method for the [`phycfgr`] register.
534///
535/// [`PhyCfg::spd`]: crate::PhyCfg::spd
536/// [`phycfgr`]: crate::Registers::phycfgr
537#[derive(Copy, Clone, Eq, PartialEq, Debug, PartialOrd, Ord, Hash, Default)]
538#[cfg_attr(feature = "defmt", derive(defmt::Format))]
539#[repr(u8)]
540pub enum SpeedStatus {
541    /// 10 Mbps.
542    #[default]
543    Mbps10 = 0,
544    /// 100 Mbps.
545    Mbps100 = 1,
546}
547impl From<bool> for SpeedStatus {
548    fn from(val: bool) -> SpeedStatus {
549        if val {
550            SpeedStatus::Mbps100
551        } else {
552            SpeedStatus::Mbps10
553        }
554    }
555}
556impl From<SpeedStatus> for u8 {
557    fn from(val: SpeedStatus) -> u8 {
558        val as u8
559    }
560}
561
562/// PHY duplex status.
563///
564/// This is used by [`PhyCfg::dpx`] method for the [`phycfgr`] register.
565///
566/// [`PhyCfg::dpx`]: crate::PhyCfg::dpx
567/// [`phycfgr`]: crate::Registers::phycfgr
568#[derive(Copy, Clone, Eq, PartialEq, Debug, PartialOrd, Ord, Hash, Default)]
569#[cfg_attr(feature = "defmt", derive(defmt::Format))]
570#[repr(u8)]
571pub enum DuplexStatus {
572    /// Half duplex.
573    #[default]
574    Half = 0,
575    /// Full duplex.
576    Full = 1,
577}
578impl From<bool> for DuplexStatus {
579    fn from(val: bool) -> DuplexStatus {
580        if val {
581            DuplexStatus::Full
582        } else {
583            DuplexStatus::Half
584        }
585    }
586}
587impl From<DuplexStatus> for u8 {
588    fn from(val: DuplexStatus) -> u8 {
589        val as u8
590    }
591}
592
593/// RX and TX buffer sizes.
594///
595/// This is an argument of [`Registers::set_sn_rxbuf_size`] and
596/// [`Registers::set_sn_txbuf_size`].
597///
598/// [`Registers::set_sn_txbuf_size`]: crate::Registers::set_sn_txbuf_size
599/// [`Registers::set_sn_rxbuf_size`]: crate::Registers::set_sn_rxbuf_size
600#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
601#[cfg_attr(feature = "defmt", derive(defmt::Format))]
602#[repr(u8)]
603#[allow(clippy::upper_case_acronyms)]
604pub enum BufferSize {
605    /// 0 KiB
606    KB0 = 0,
607    /// 1 KiB
608    KB1 = 1,
609    /// 2 KiB
610    KB2 = 2,
611    /// 4 KiB
612    KB4 = 4,
613    /// 8 KiB
614    KB8 = 8,
615    /// 16 KiB
616    KB16 = 16,
617}
618impl From<BufferSize> for u8 {
619    /// Get the register value from a buffer size.
620    ///
621    /// # Example
622    ///
623    /// ```
624    /// use w5500_ll::BufferSize;
625    ///
626    /// assert_eq!(u8::from(BufferSize::KB0), 0);
627    /// assert_eq!(u8::from(BufferSize::KB1), 1);
628    /// assert_eq!(u8::from(BufferSize::KB2), 2);
629    /// assert_eq!(u8::from(BufferSize::KB4), 4);
630    /// assert_eq!(u8::from(BufferSize::KB8), 8);
631    /// assert_eq!(u8::from(BufferSize::KB16), 16);
632    /// ```
633    fn from(val: BufferSize) -> u8 {
634        val as u8
635    }
636}
637
638impl TryFrom<u8> for BufferSize {
639    type Error = u8;
640
641    /// Get the buffer size given the register value.
642    ///
643    /// # Example
644    ///
645    /// ```
646    /// use w5500_ll::BufferSize;
647    ///
648    /// assert_eq!(BufferSize::try_from(0), Ok(BufferSize::KB0));
649    /// assert_eq!(BufferSize::try_from(1), Ok(BufferSize::KB1));
650    /// assert_eq!(BufferSize::try_from(2), Ok(BufferSize::KB2));
651    /// assert_eq!(BufferSize::try_from(4), Ok(BufferSize::KB4));
652    /// assert_eq!(BufferSize::try_from(8), Ok(BufferSize::KB8));
653    /// assert_eq!(BufferSize::try_from(16), Ok(BufferSize::KB16));
654    /// assert_eq!(BufferSize::try_from(17), Err(17));
655    /// ```
656    fn try_from(val: u8) -> Result<BufferSize, u8> {
657        match val {
658            x if x == BufferSize::KB0 as u8 => Ok(BufferSize::KB0),
659            x if x == BufferSize::KB1 as u8 => Ok(BufferSize::KB1),
660            x if x == BufferSize::KB2 as u8 => Ok(BufferSize::KB2),
661            x if x == BufferSize::KB4 as u8 => Ok(BufferSize::KB4),
662            x if x == BufferSize::KB8 as u8 => Ok(BufferSize::KB8),
663            x if x == BufferSize::KB16 as u8 => Ok(BufferSize::KB16),
664            _ => Err(val),
665        }
666    }
667}
668
669impl Default for BufferSize {
670    /// Default buffer size.
671    ///
672    /// # Example
673    ///
674    /// ```
675    /// use w5500_ll::BufferSize;
676    ///
677    /// assert_eq!(BufferSize::default(), BufferSize::KB2);
678    /// ```
679    fn default() -> Self {
680        BufferSize::KB2
681    }
682}
683
684impl BufferSize {
685    /// Get the buffer size in bytes.
686    ///
687    /// # Example
688    ///
689    /// ```
690    /// use w5500_ll::BufferSize;
691    ///
692    /// assert_eq!(BufferSize::KB0.size_in_bytes(), 0);
693    /// assert_eq!(BufferSize::KB1.size_in_bytes(), 1 * 1024);
694    /// assert_eq!(BufferSize::KB2.size_in_bytes(), 2 * 1024);
695    /// assert_eq!(BufferSize::KB4.size_in_bytes(), 4 * 1024);
696    /// assert_eq!(BufferSize::KB8.size_in_bytes(), 8 * 1024);
697    /// assert_eq!(BufferSize::KB16.size_in_bytes(), 16 * 1024);
698    /// ```
699    pub const fn size_in_bytes(&self) -> usize {
700        match self {
701            BufferSize::KB0 => 0,
702            BufferSize::KB1 => 1024,
703            BufferSize::KB2 => 2048,
704            BufferSize::KB4 => 4096,
705            BufferSize::KB8 => 8192,
706            BufferSize::KB16 => 16384,
707        }
708    }
709}