w5500_ll/
registers.rs

1//! Register structures.
2
3use crate::specifiers::{DuplexStatus, LinkStatus, OperationMode, Protocol, SpeedStatus};
4
5macro_rules! impl_boilerplate_for {
6    ($REG:ident) => {
7        impl From<u8> for $REG {
8            fn from(val: u8) -> Self {
9                Self(val)
10            }
11        }
12
13        impl From<$REG> for u8 {
14            fn from(val: $REG) -> u8 {
15                val.0
16            }
17        }
18
19        impl Default for $REG {
20            fn default() -> Self {
21                Self::DEFAULT
22            }
23        }
24    };
25}
26
27/// Mode register (MR).
28///
29/// Used for software reset, and controlling modes of operation.
30///
31/// This is used by the [`Registers::mr`] and [`Registers::set_mr`] methods.
32///
33/// [`Registers::mr`]: crate::Registers::mr
34/// [`Registers::set_mr`]: crate::Registers::set_mr
35#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
36pub struct Mode(u8);
37impl_boilerplate_for!(Mode);
38
39impl Mode {
40    /// Mode register reset value.
41    pub const RESET: u8 = 0x00;
42
43    /// Default value.
44    ///
45    /// This is the same as `default`, but as a `const` value.
46    ///
47    /// # Example
48    ///
49    /// ```
50    /// use w5500_ll::Mode;
51    ///
52    /// assert_eq!(Mode::DEFAULT, Mode::default());
53    /// ```
54    pub const DEFAULT: Self = Self(Self::RESET);
55
56    /// Bit offset for the `RST` field.
57    pub const RST_OFFSET: u8 = 7;
58    /// Bit offset for the `WOL` field.
59    pub const WOL_OFFSET: u8 = 5;
60    /// Bit offset for the `PB` field.
61    pub const PB_OFFSET: u8 = 4;
62    /// Bit offset for the `PPPoE` field.
63    pub const PPPOE_OFFSET: u8 = 3;
64    /// Bit offset for the `FARP` field.
65    pub const FARP_OFFSET: u8 = 1;
66
67    /// Bit mask for the `RST` field.
68    pub const RST_MASK: u8 = 1 << Self::RST_OFFSET;
69    /// Bit mask for the `WOL` field.
70    pub const WOL_MASK: u8 = 1 << Self::WOL_OFFSET;
71    /// Bit mask for the `PB` field.
72    pub const PB_MASK: u8 = 1 << Self::PB_OFFSET;
73    /// Bit mask for the `PPPoE` field.
74    pub const PPPOE_MASK: u8 = 1 << Self::PPPOE_OFFSET;
75    /// Bit mask for the `FARP` field.
76    pub const FARP_MASK: u8 = 1 << Self::FARP_OFFSET;
77
78    /// Set the software reset bit to `1`.
79    ///
80    /// When reset all internal registers will be initialized.
81    #[must_use = "rst returns a modified Mode"]
82    pub const fn rst(mut self) -> Self {
83        self.0 |= Self::RST_MASK;
84        self
85    }
86
87    /// Wake on LAN.
88    ///
89    /// If WOL mode is enabled and the received magic packet over
90    /// UDP has been normally processed, the interrupt pin (INTn) asserts to low.
91    ///
92    /// # Example
93    ///
94    /// ```
95    /// use w5500_ll::Mode;
96    ///
97    /// let mr: Mode = Mode::DEFAULT;
98    /// assert!(!mr.wol_enabled());
99    /// let mr: Mode = mr.enable_wol();
100    /// assert!(mr.wol_enabled());
101    /// let mr: Mode = mr.disable_wol();
102    /// assert!(!mr.wol_enabled());
103    /// ```
104    pub const fn wol_enabled(&self) -> bool {
105        self.0 & Self::WOL_MASK != 0
106    }
107
108    /// Enable wake on LAN.
109    #[must_use = "enable_wol returns a modified Mode"]
110    pub const fn enable_wol(mut self) -> Self {
111        self.0 |= Self::WOL_MASK;
112        self
113    }
114
115    /// Disable wake on LAN.
116    #[must_use = "disable_wol returns a modified Mode"]
117    pub const fn disable_wol(mut self) -> Self {
118        self.0 &= !Self::WOL_MASK;
119        self
120    }
121
122    /// Ping block mode.
123    ///
124    /// If enabled it blocks responses to ping requests.
125    ///
126    /// # Example
127    ///
128    /// ```
129    /// use w5500_ll::Mode;
130    ///
131    /// let mr: Mode = Mode::DEFAULT;
132    /// assert!(!mr.pb_enabled());
133    /// let mr: Mode = mr.enable_pb();
134    /// assert!(mr.pb_enabled());
135    /// let mr: Mode = mr.disable_pb();
136    /// assert!(!mr.pb_enabled());
137    /// ```
138    pub const fn pb_enabled(&self) -> bool {
139        self.0 & Self::PB_MASK != 0
140    }
141
142    /// Enable ping block.
143    #[must_use = "enable_pb returns a modified Mode"]
144    pub const fn enable_pb(mut self) -> Self {
145        self.0 |= Self::PB_MASK;
146        self
147    }
148
149    /// Disable ping block.
150    #[must_use = "disable_pb returns a modified Mode"]
151    pub const fn disable_pb(mut self) -> Self {
152        self.0 &= !Self::PB_MASK;
153        self
154    }
155
156    /// PPPoE mode.
157    ///
158    /// If you use ADSL this should be enabled.
159    ///
160    /// # Example
161    ///
162    /// ```
163    /// use w5500_ll::Mode;
164    ///
165    /// let mr: Mode = Mode::DEFAULT;
166    /// assert!(!mr.pppoe_enabled());
167    /// let mr: Mode = mr.enable_pppoe();
168    /// assert!(mr.pppoe_enabled());
169    /// let mr: Mode = mr.disable_pppoe();
170    /// assert!(!mr.pppoe_enabled());
171    /// ```
172    pub const fn pppoe_enabled(&self) -> bool {
173        self.0 & Self::PPPOE_MASK != 0
174    }
175
176    /// Enable PPPoE mode.
177    #[must_use = "enable_pppoe returns a modified Mode"]
178    pub const fn enable_pppoe(mut self) -> Self {
179        self.0 |= Self::PPPOE_MASK;
180        self
181    }
182
183    /// Disable PPPoE mode.
184    #[must_use = "disable_pppoe returns a modified Mode"]
185    pub const fn disable_pppoe(mut self) -> Self {
186        self.0 &= !Self::PPPOE_MASK;
187        self
188    }
189
190    /// Force ARP.
191    ///
192    /// When enabled it forces sending ARP request whenever data is sent.
193    ///
194    /// # Example
195    ///
196    /// ```
197    /// use w5500_ll::Mode;
198    ///
199    /// let mr: Mode = Mode::DEFAULT;
200    /// assert!(!mr.farp_enabled());
201    /// let mr: Mode = mr.enable_farp();
202    /// assert!(mr.farp_enabled());
203    /// let mr: Mode = mr.disable_farp();
204    /// assert!(!mr.farp_enabled());
205    /// ```
206    pub const fn farp_enabled(&self) -> bool {
207        self.0 & Self::FARP_MASK != 0
208    }
209
210    /// Enable force ARP.
211    #[must_use = "enable_farp returns a modified Mode"]
212    pub const fn enable_farp(mut self) -> Self {
213        self.0 |= Self::FARP_MASK;
214        self
215    }
216
217    /// Disable force ARP.
218    #[must_use = "disable_farp returns a modified Mode"]
219    pub const fn disable_farp(mut self) -> Self {
220        self.0 &= !Self::FARP_MASK;
221        self
222    }
223}
224
225impl ::core::fmt::Display for Mode {
226    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
227        f.debug_struct("Mode")
228            .field("wol_enabled", &self.wol_enabled())
229            .field("pb_enabled", &self.pb_enabled())
230            .field("pppoe_enabled", &self.pppoe_enabled())
231            .field("farp_enabled", &self.farp_enabled())
232            .finish()
233    }
234}
235
236#[cfg(feature = "defmt")]
237impl defmt::Format for Mode {
238    fn format(&self, fmt: defmt::Formatter) {
239        defmt::write!(
240            fmt,
241            "Mode {{ wol_enabled: {}, pb_enabled: {}, pppoe_enabled: {}, farp_enabled: {} }}",
242            self.wol_enabled(),
243            self.pb_enabled(),
244            self.pppoe_enabled(),
245            self.farp_enabled(),
246        );
247    }
248}
249
250/// Interrupt and interrupt mask register (IR and IMR).
251///
252/// When used for interrupt masking:
253/// * `false`: Interrupt is disabled.
254/// * `true`: Interrupt is enabled.
255///
256/// When used for reading interrupt status:
257/// * `false`: Interrupt is not raised.
258/// * `true`: Interrupt is raised.
259///
260/// This is used by these methods:
261/// * [`Registers::ir`]
262/// * [`Registers::set_ir`]
263/// * [`Registers::imr`]
264/// * [`Registers::set_imr`]
265///
266/// [`Registers::ir`]: crate::Registers::ir
267/// [`Registers::set_ir`]: crate::Registers::set_ir
268/// [`Registers::imr`]: crate::Registers::imr
269/// [`Registers::set_imr`]: crate::Registers::set_imr
270#[derive(Debug, Copy, Clone, Eq, PartialEq)]
271pub struct Interrupt(u8);
272impl_boilerplate_for!(Interrupt);
273
274impl Interrupt {
275    /// Interrupt and interrupt mask reset value.
276    pub const RESET: u8 = 0x00;
277
278    /// Default value.
279    ///
280    /// This is the same as `default`, but as a `const` value.
281    ///
282    /// # Example
283    ///
284    /// ```
285    /// use w5500_ll::Interrupt;
286    ///
287    /// assert_eq!(Interrupt::DEFAULT, Interrupt::default());
288    /// ```
289    pub const DEFAULT: Self = Self(Self::RESET);
290
291    /// Bit offset for the `CONFLICT` field.
292    pub const CONFLICT_OFFSET: u8 = 7;
293    /// Bit offset for the `UNREACH` field.
294    pub const UNREACH_OFFSET: u8 = 6;
295    /// Bit offset for the `PPPoE` field.
296    pub const PPPOE_OFFSET: u8 = 5;
297    /// Bit offset for the `MP` field.
298    pub const MP_OFFSET: u8 = 4;
299
300    /// Bit mask for the `CONFLICT` field.
301    pub const CONFLICT_MASK: u8 = 1 << Self::CONFLICT_OFFSET;
302    /// Bit mask for the `UNREACH` field.
303    pub const UNREACH_MASK: u8 = 1 << Self::UNREACH_OFFSET;
304    /// Bit mask for the `PPPoE` field.
305    pub const PPPOE_MASK: u8 = 1 << Self::PPPOE_OFFSET;
306    /// Bit mask for the `MP` field.
307    pub const MP_MASK: u8 = 1 << Self::MP_OFFSET;
308
309    /// Get the value of the IP conflict interrupt.
310    ///
311    /// This interrupt is set when our source IP is the same as the sender IP
312    /// in the received ARP request.
313    ///
314    /// # Example
315    ///
316    /// ```
317    /// use w5500_ll::Interrupt;
318    ///
319    /// let ir: Interrupt = Interrupt::DEFAULT;
320    /// assert!(!ir.conflict());
321    /// let ir: Interrupt = ir.set_conflict();
322    /// assert!(ir.conflict());
323    /// let ir: Interrupt = ir.clear_conflict();
324    /// assert!(!ir.conflict());
325    /// ```
326    pub const fn conflict(&self) -> bool {
327        self.0 & Self::CONFLICT_MASK != 0
328    }
329
330    /// Set the IP conflict bit.
331    #[must_use = "set_conflict returns a modified Interrupt"]
332    pub const fn set_conflict(mut self) -> Self {
333        self.0 |= Self::CONFLICT_MASK;
334        self
335    }
336
337    /// Clear the IP conflict bit.
338    #[must_use = "clear_conflict returns a modified Interrupt"]
339    pub const fn clear_conflict(mut self) -> Self {
340        self.0 &= !Self::CONFLICT_MASK;
341        self
342    }
343
344    /// Get the destination unreachable interrupt.
345    ///
346    /// This interrupt is set when receiving the ICMP
347    /// (destination port unreachable) packet.
348    ///
349    /// When this interrupt is set destination information such as the IP
350    /// address and port number may be checked with the corresponding [UIPR] and
351    /// [UPORTR] registers.
352    ///
353    /// # Example
354    ///
355    /// ```
356    /// use w5500_ll::Interrupt;
357    ///
358    /// let ir: Interrupt = Interrupt::DEFAULT;
359    /// assert!(!ir.unreach());
360    /// let ir: Interrupt = ir.set_unreach();
361    /// assert!(ir.unreach());
362    /// let ir: Interrupt = ir.clear_unreach();
363    /// assert!(!ir.unreach());
364    /// ```
365    ///
366    /// [UIPR]: crate::Registers::uipr
367    /// [UPORTR]: crate::Registers::uportr
368    pub const fn unreach(&self) -> bool {
369        self.0 & Self::UNREACH_MASK != 0
370    }
371
372    /// Set the destination unreachable bit.
373    #[must_use = "set_unreach returns a modified Interrupt"]
374    pub const fn set_unreach(mut self) -> Self {
375        self.0 |= Self::UNREACH_MASK;
376        self
377    }
378
379    /// Clear the destination unreachable bit.
380    #[must_use = "clear_unreach returns a modified Interrupt"]
381    pub const fn clear_unreach(mut self) -> Self {
382        self.0 &= !Self::UNREACH_MASK;
383        self
384    }
385
386    /// Get the PPPoE connection close interrupt.
387    ///
388    /// This interrupt is set when PPPoE is disconnected during PPPoE.
389    ///
390    /// # Example
391    ///
392    /// ```
393    /// use w5500_ll::Interrupt;
394    ///
395    /// let ir: Interrupt = Interrupt::DEFAULT;
396    /// assert!(!ir.pppoe());
397    /// let ir: Interrupt = ir.set_pppoe();
398    /// assert!(ir.pppoe());
399    /// let ir: Interrupt = ir.clear_pppoe();
400    /// assert!(!ir.pppoe());
401    /// ```
402    pub const fn pppoe(&self) -> bool {
403        self.0 & Self::PPPOE_MASK != 0
404    }
405
406    /// Set the PPPoE connection close bit.
407    #[must_use = "set_pppoe returns a modified Interrupt"]
408    pub const fn set_pppoe(mut self) -> Self {
409        self.0 |= Self::PPPOE_MASK;
410        self
411    }
412
413    /// Clear the PPPoE connection close bit.
414    #[must_use = "clear_pppoe returns a modified Interrupt"]
415    pub const fn clear_pppoe(mut self) -> Self {
416        self.0 &= !Self::PPPOE_MASK;
417        self
418    }
419
420    /// Get the magic packet interrupt.
421    ///
422    /// This interrupt is set when wake on LAN is enabled, and the magic packet
423    /// is received.
424    ///
425    /// # Example
426    ///
427    /// ```
428    /// use w5500_ll::Interrupt;
429    ///
430    /// let ir: Interrupt = Interrupt::DEFAULT;
431    /// assert!(!ir.mp());
432    /// let ir: Interrupt = ir.set_mp();
433    /// assert!(ir.mp());
434    /// let ir: Interrupt = ir.clear_mp();
435    /// assert!(!ir.mp());
436    /// ```
437    pub const fn mp(&self) -> bool {
438        self.0 & Self::MP_MASK != 0
439    }
440
441    /// Set the magic packet bit.
442    #[must_use = "set_mp returns a modified Interrupt"]
443    pub const fn set_mp(mut self) -> Self {
444        self.0 |= Self::MP_MASK;
445        self
446    }
447
448    /// Clear the magic packet bit.
449    #[must_use = "clear_mp returns a modified Interrupt"]
450    pub const fn clear_mp(mut self) -> Self {
451        self.0 &= !Self::MP_MASK;
452        self
453    }
454}
455
456impl ::core::fmt::Display for Interrupt {
457    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
458        f.debug_struct("Interrupt")
459            .field("conflict", &self.conflict())
460            .field("unreach", &self.unreach())
461            .field("pppoe", &self.pppoe())
462            .field("mp", &self.mp())
463            .finish()
464    }
465}
466
467#[cfg(feature = "defmt")]
468impl defmt::Format for Interrupt {
469    fn format(&self, fmt: defmt::Formatter) {
470        defmt::write!(
471            fmt,
472            "Interrupt {{ conflict: {}, unreach: {}, pppoe: {}, mp: {} }}",
473            self.conflict(),
474            self.unreach(),
475            self.pppoe(),
476            self.mp(),
477        );
478    }
479}
480
481/// PHY configuration register (PHYCFGR).
482///
483/// Used for:
484/// * PHY reset.
485/// * PHY operation modes.
486/// * PHY status.
487///
488/// This is used by the [`Registers::phycfgr`] and
489/// [`Registers::set_phycfgr`] methods.
490///
491/// [`Registers::phycfgr`]: crate::Registers::phycfgr
492/// [`Registers::set_phycfgr`]: crate::Registers::set_phycfgr
493#[derive(Debug, Copy, Clone, Eq, PartialEq)]
494pub struct PhyCfg(u8);
495impl_boilerplate_for!(PhyCfg);
496
497impl PhyCfg {
498    /// PHY configuration register reset value.
499    pub const RESET: u8 = 0b10111000;
500
501    /// Default value.
502    ///
503    /// This is the same as `default`, but as a `const` value.
504    ///
505    /// # Example
506    ///
507    /// ```
508    /// use w5500_ll::PhyCfg;
509    ///
510    /// assert_eq!(PhyCfg::DEFAULT, PhyCfg::default());
511    /// ```
512    pub const DEFAULT: Self = Self(Self::RESET);
513
514    /// Bit offset for the `RST` field.
515    pub const RST_OFFSET: u8 = 7;
516    /// Bit offset for the `OPMD` field.
517    pub const OPMD_OFFSET: u8 = 6;
518    /// Bit offset for the `OPMDC` field.
519    pub const OPMDC_OFFSET: u8 = 3;
520    /// Bit offset for the `DPX` field.
521    pub const DPX_OFFSET: u8 = 2;
522    /// Bit offset for the `SPD` field.
523    pub const SPD_OFFSET: u8 = 1;
524    /// Bit offset for the `LNK` field.
525    pub const LNK_OFFSET: u8 = 0;
526
527    /// Bit mask for the `RST` field.
528    pub const RST_MASK: u8 = 1 << Self::RST_OFFSET;
529    /// Bit mask for the `OPMD` field.
530    pub const OPMD_MASK: u8 = 1 << Self::OPMD_OFFSET;
531    /// Bit mask for the `OPMDC` field.
532    pub const OPMDC_MASK: u8 = 0b111 << Self::OPMDC_OFFSET;
533    /// Bit mask for the `DPX` field.
534    pub const DPX_MASK: u8 = 1 << Self::DPX_OFFSET;
535    /// Bit mask for the `SPD` field.
536    pub const SPD_MASK: u8 = 1 << Self::SPD_OFFSET;
537    /// Bit mask for the `LNK` field.
538    pub const LNK_MASK: u8 = 1 << Self::LNK_OFFSET;
539
540    /// Set the PHY reset bit to `0`, resetting the PHY.
541    #[must_use = "rst returns a modified PhyCfg"]
542    pub const fn rst(mut self) -> Self {
543        self.0 &= !Self::RST_MASK;
544        self
545    }
546
547    /// Get the PHY operation mode.
548    ///
549    /// * `true` configure PHY with software.
550    /// * `false` (reset value) configure PHY with hardware.
551    pub const fn opmd(&self) -> bool {
552        self.0 & Self::OPMD_MASK != 0
553    }
554
555    /// Enable hardware configuration of the PHY operation mode.
556    ///
557    /// This uses the PMODE pins to select the PHY operation mode.
558    ///
559    /// | PMODE\[2\] | PMODE\[1\] | PMODE\[0\] | Description                                  |
560    /// |------------|------------|------------|----------------------------------------------|
561    /// | 0          | 0          | 0          | 10BT Half-duplex, Auto-negotiation disabled  |
562    /// | 0          | 0          | 1          | 10BT Full-duplex, Auto-negotiation disabled  |
563    /// | 0          | 1          | 0          | 100BT Half-duplex, Auto-negotiation disabled |
564    /// | 0          | 1          | 1          | 100BT Full-duplex, Auto-negotiation disabled |
565    /// | 1          | 0          | 0          | 100BT Half-duplex, Auto-negotiation enabled  |
566    /// | 1          | 0          | 1          | Not used                                     |
567    /// | 1          | 1          | 0          | Not used                                     |
568    /// | 1          | 1          | 1          | All capable, Auto-negotiation enabled        |
569    ///
570    /// # Example
571    ///
572    /// ```
573    /// use w5500_ll::PhyCfg;
574    ///
575    /// let phy_cfg: PhyCfg = PhyCfg::DEFAULT;
576    /// assert!(!phy_cfg.opmd());
577    /// let phy_cfg: PhyCfg = phy_cfg.software_op();
578    /// assert!(phy_cfg.opmd());
579    /// let phy_cfg: PhyCfg = phy_cfg.hardware_op();
580    /// assert!(!phy_cfg.opmd());
581    /// ```
582    #[must_use = "hardware_op returns a modified PhyCfg"]
583    pub const fn hardware_op(mut self) -> Self {
584        self.0 &= !Self::OPMD_MASK;
585        self
586    }
587
588    /// Enable software configuration of the PHY operation mode.
589    ///
590    /// # Example
591    ///
592    /// ```
593    /// use w5500_ll::PhyCfg;
594    ///
595    /// let phy_cfg: PhyCfg = PhyCfg::DEFAULT;
596    /// assert!(!phy_cfg.opmd());
597    /// let phy_cfg: PhyCfg = phy_cfg.software_op();
598    /// assert!(phy_cfg.opmd());
599    /// ```
600    #[must_use = "software_op returns a modified PhyCfg"]
601    pub const fn software_op(mut self) -> Self {
602        self.0 |= Self::OPMD_MASK;
603        self
604    }
605
606    /// Get the operation mode.
607    ///
608    /// This returns an `Err(u8)` with the opmdc bits if the opmdc bits do not
609    /// match a valid operation mode.
610    ///
611    /// # Example
612    ///
613    /// ```
614    /// use w5500_ll::{OperationMode, PhyCfg};
615    ///
616    /// assert_eq!(PhyCfg::DEFAULT.opmdc(), OperationMode::Auto);
617    /// ```
618    pub const fn opmdc(&self) -> OperationMode {
619        // from_raw masks the value
620        OperationMode::from_raw(self.0 >> Self::OPMDC_OFFSET)
621    }
622
623    /// Set the PHY operation mode.
624    ///
625    /// Setting this will also call [`PhyCfg::software_op`] to enable the PHY
626    /// configuration with the value stored in this register.
627    ///
628    /// # Example
629    ///
630    /// ```
631    /// use w5500_ll::{OperationMode, PhyCfg};
632    ///
633    /// let phy_cfg: PhyCfg = PhyCfg::DEFAULT;
634    /// assert!(!phy_cfg.opmd());
635    /// let phy_cfg: PhyCfg = phy_cfg.set_opmdc(OperationMode::PowerDown);
636    /// assert!(phy_cfg.opmd());
637    /// assert_eq!(phy_cfg.opmdc(), OperationMode::PowerDown);
638    /// let phy_cfg: PhyCfg = phy_cfg.set_opmdc(OperationMode::Auto);
639    /// assert_eq!(phy_cfg.opmdc(), OperationMode::Auto);
640    /// ```
641    #[must_use = "set_opmdc returns a modified PhyCfg"]
642    pub const fn set_opmdc(mut self, mode: OperationMode) -> Self {
643        self = self.software_op();
644        self.0 &= !Self::OPMDC_MASK;
645        self.0 |= (mode as u8) << Self::OPMDC_OFFSET;
646        self
647    }
648
649    /// Get the duplex status.
650    ///
651    /// # Example
652    ///
653    /// ```
654    /// use w5500_ll::{DuplexStatus, PhyCfg};
655    ///
656    /// let phy_cfg: PhyCfg = PhyCfg::DEFAULT;
657    /// assert_eq!(phy_cfg.dpx(), DuplexStatus::Half);
658    /// ```
659    pub const fn dpx(&self) -> DuplexStatus {
660        match self.0 & Self::DPX_MASK == Self::DPX_MASK {
661            true => DuplexStatus::Full,
662            false => DuplexStatus::Half,
663        }
664    }
665
666    /// Get the speed status.
667    ///
668    /// # Example
669    ///
670    /// ```
671    /// use w5500_ll::{PhyCfg, SpeedStatus};
672    ///
673    /// let phy_cfg: PhyCfg = PhyCfg::DEFAULT;
674    /// assert_eq!(phy_cfg.spd(), SpeedStatus::Mbps10);
675    /// ```
676    pub const fn spd(&self) -> SpeedStatus {
677        match self.0 & Self::SPD_MASK == Self::SPD_MASK {
678            true => SpeedStatus::Mbps100,
679            false => SpeedStatus::Mbps10,
680        }
681    }
682
683    /// Get the link status.
684    ///
685    /// # Example
686    ///
687    /// ```
688    /// use w5500_ll::{LinkStatus, PhyCfg};
689    ///
690    /// let phy_cfg: PhyCfg = PhyCfg::DEFAULT;
691    /// assert_eq!(phy_cfg.lnk(), LinkStatus::Down);
692    /// ```
693    pub const fn lnk(&self) -> LinkStatus {
694        match self.0 & Self::LNK_MASK == Self::LNK_MASK {
695            true => LinkStatus::Up,
696            false => LinkStatus::Down,
697        }
698    }
699}
700
701impl ::core::fmt::Display for PhyCfg {
702    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
703        f.debug_struct("PhyCfg")
704            .field("opmd", &self.opmd())
705            .field("opmdc", &self.opmdc())
706            .field("dpx", &self.dpx())
707            .field("spd", &self.spd())
708            .field("lnk", &self.lnk())
709            .finish()
710    }
711}
712
713#[cfg(feature = "defmt")]
714impl defmt::Format for PhyCfg {
715    fn format(&self, fmt: defmt::Formatter) {
716        defmt::write!(
717            fmt,
718            "PhyCfg {{ opmd: {}, opmdc: {}, dpx: {}, spd: {}, lnk: {} }}",
719            self.opmd(),
720            self.opmdc(),
721            self.dpx(),
722            self.spd(),
723            self.lnk(),
724        );
725    }
726}
727
728/// Socket Mode Register (Sn_MR).
729///
730/// This is used by the [`Registers::sn_mr`] and
731/// [`Registers::set_sn_mr`] methods.
732///
733/// [`Registers::set_sn_mr`]: crate::Registers::set_sn_mr
734/// [`Registers::sn_mr`]: crate::Registers::sn_mr
735#[derive(Debug, Copy, Clone, Eq, PartialEq)]
736pub struct SocketMode(u8);
737impl_boilerplate_for!(SocketMode);
738
739impl SocketMode {
740    /// Reset value of the socket mode register.
741    pub const RESET: u8 = 0x00;
742
743    /// Default value.
744    ///
745    /// This is the same as `default`, but as a `const` value.
746    ///
747    /// # Example
748    ///
749    /// ```
750    /// use w5500_ll::SocketMode;
751    ///
752    /// assert_eq!(SocketMode::DEFAULT, SocketMode::default());
753    /// ```
754    pub const DEFAULT: Self = Self(Self::RESET);
755
756    /// Bit offset for the `MULTI` field.
757    pub const MULTI_OFFSET: u8 = 7;
758    /// Bit offset for the `MFEN` field.
759    pub const MFEN_OFFSET: u8 = 7;
760    /// Bit offset for the `BCASTB` field.
761    pub const BCASTB_OFFSET: u8 = 6;
762    /// Bit offset for the `ND` field.
763    pub const ND_OFFSET: u8 = 5;
764    /// Bit offset for the `MC` field.
765    pub const MC_OFFSET: u8 = 5;
766    /// Bit offset for the `MMB` field.
767    pub const MMB_OFFSET: u8 = 5;
768    /// Bit offset for the `UCASTB` field.
769    pub const UCASTB_OFFSET: u8 = 4;
770    /// Bit offset for the `MIP6B` field.
771    pub const MIP6B_OFFSET: u8 = 4;
772
773    /// Bit mask for the `MULTI` field.
774    pub const MULTI_MASK: u8 = 1 << Self::MULTI_OFFSET;
775    /// Bit mask for the `MFEN` field.
776    pub const MFEN_MASK: u8 = 1 << Self::MFEN_OFFSET;
777    /// Bit mask for the `BCASTB` field.
778    pub const BCASTB_MASK: u8 = 1 << Self::BCASTB_OFFSET;
779    /// Bit mask for the `ND` field.
780    pub const ND_MASK: u8 = 1 << Self::ND_OFFSET;
781    /// Bit mask for the `MC` field.
782    pub const MC_MASK: u8 = 1 << Self::MC_OFFSET;
783    /// Bit mask for the `MMB` field.
784    pub const MMB_MASK: u8 = 1 << Self::MMB_OFFSET;
785    /// Bit mask for the `UCASTB` field.
786    pub const UCASTB_MASK: u8 = 1 << Self::UCASTB_OFFSET;
787    /// Bit mask for the `MIP6B` field.
788    pub const MIP6B_MASK: u8 = 1 << Self::MIP6B_OFFSET;
789    /// Bit mask for the `PROTOCOL` field.
790    pub const PROTOCOL_MASK: u8 = 0xF;
791
792    /// Get the protocol.
793    ///
794    /// This returns an `Err(u8)` with the protocol bits if the protocol bits
795    /// do not match a valid protocol.
796    ///
797    /// # Example
798    ///
799    /// ```
800    /// use w5500_ll::{Protocol, SocketMode};
801    ///
802    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
803    /// assert_eq!(sn_mr.protocol(), Ok(Protocol::Closed));
804    /// ```
805    pub const fn protocol(&self) -> Result<Protocol, u8> {
806        Protocol::from_raw(self.0 & Self::PROTOCOL_MASK)
807    }
808
809    /// Set the protocol.
810    ///
811    /// # Example
812    ///
813    /// ```
814    /// use w5500_ll::{Protocol, SocketMode};
815    ///
816    /// const SN_MR: SocketMode = SocketMode::DEFAULT.set_protocol(Protocol::Tcp);
817    /// assert_eq!(SN_MR.protocol(), Ok(Protocol::Tcp));
818    /// ```
819    pub const fn set_protocol(mut self, protocol: Protocol) -> Self {
820        self.0 = (self.0 & 0xF0) | ((protocol as u8) & 0xF);
821        self
822    }
823
824    /// Multicasting.
825    ///
826    /// This applies only for a socket with the UDP protocol.
827    ///
828    /// To use multicasting [`Registers::sn_dipr`] and [`Registers::sn_dport`]
829    /// should be configured with the multicast group IP and port number
830    /// before the socket is opened.
831    ///
832    /// # Example
833    ///
834    /// ```
835    /// use w5500_ll::SocketMode;
836    ///
837    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
838    /// assert!(!sn_mr.multi_enabled());
839    /// let sn_mr: SocketMode = sn_mr.enable_multi();
840    /// assert!(sn_mr.multi_enabled());
841    /// let sn_mr: SocketMode = sn_mr.disable_multi();
842    /// assert!(!sn_mr.multi_enabled());
843    /// ```
844    ///
845    /// [`Registers::sn_dipr`]: crate::Registers::sn_dipr
846    /// [`Registers::sn_dport`]: crate::Registers::sn_dport
847    pub const fn multi_enabled(&self) -> bool {
848        self.0 & Self::MULTI_MASK != 0
849    }
850
851    /// Enable multicasting.
852    #[must_use = "enable_multi returns a modified SocketMode"]
853    pub const fn enable_multi(mut self) -> Self {
854        self.0 |= Self::MULTI_MASK;
855        self
856    }
857
858    /// Disable multicasting.
859    #[must_use = "disable_multi returns a modified SocketMode"]
860    pub const fn disable_multi(mut self) -> Self {
861        self.0 &= !Self::MULTI_MASK;
862        self
863    }
864
865    /// MAC filter.
866    ///
867    /// This applies only for a socket with the MACRAW protocol.
868    ///
869    /// When enabled the W5500 can only receive broadcasting packets sent to
870    /// itself.
871    /// When disabled the W5500 can receive all packets.
872    /// If you want to implement a hybrid TCP/IP stack it is recommended that
873    /// this is enabled for reducing host overhead to process all the received
874    /// packets.
875    ///
876    /// # Example
877    ///
878    /// ```
879    /// use w5500_ll::SocketMode;
880    ///
881    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
882    /// assert!(!sn_mr.mfen_enabled());
883    /// let sn_mr: SocketMode = sn_mr.enable_mfen();
884    /// assert!(sn_mr.mfen_enabled());
885    /// let sn_mr: SocketMode = sn_mr.disable_mfen();
886    /// assert!(!sn_mr.mfen_enabled());
887    /// ```
888    pub const fn mfen_enabled(&self) -> bool {
889        self.0 & Self::MFEN_MASK != 0
890    }
891
892    /// Enable MAC filter.
893    #[must_use = "enable_mfen returns a modified SocketMode"]
894    pub const fn enable_mfen(mut self) -> Self {
895        self.0 |= Self::MFEN_MASK;
896        self
897    }
898
899    /// Disable MAC filter.
900    #[must_use = "disable_mfen returns a modified SocketMode"]
901    pub const fn disable_mfen(mut self) -> Self {
902        self.0 &= !Self::MFEN_MASK;
903        self
904    }
905
906    /// Broadcast blocking.
907    ///
908    /// This applies only for a socket with the MACRAW or UDP protocol.
909    ///
910    /// # Example
911    ///
912    /// ```
913    /// use w5500_ll::SocketMode;
914    ///
915    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
916    /// assert!(!sn_mr.bcastb_enabled());
917    /// let sn_mr: SocketMode = sn_mr.enable_bcastb();
918    /// assert!(sn_mr.bcastb_enabled());
919    /// let sn_mr: SocketMode = sn_mr.disable_bcastb();
920    /// assert!(!sn_mr.bcastb_enabled());
921    /// ```
922    pub const fn bcastb_enabled(&self) -> bool {
923        self.0 & Self::BCASTB_MASK != 0
924    }
925
926    /// Enable broadcast blocking.
927    #[must_use = "enable_bcastb returns a modified SocketMode"]
928    pub const fn enable_bcastb(mut self) -> Self {
929        self.0 |= Self::BCASTB_MASK;
930        self
931    }
932
933    /// Disable broadcast blocking.
934    #[must_use = "disable_bcastb returns a modified SocketMode"]
935    pub const fn disable_bcastb(mut self) -> Self {
936        self.0 &= !Self::BCASTB_MASK;
937        self
938    }
939
940    /// Use no delayed ACK.
941    ///
942    /// This applies only for a socket with the TCP protocol.
943    ///
944    /// When enabled the ACK packet is sent without delay as soon as a data
945    /// packet is received from a peer.
946    /// When disabled the ACK packet is sent after waiting for the time
947    /// configured by [`rtr`].
948    ///
949    /// # Example
950    ///
951    /// ```
952    /// use w5500_ll::SocketMode;
953    ///
954    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
955    /// assert!(!sn_mr.nd_enabled());
956    /// let sn_mr: SocketMode = sn_mr.enable_nd();
957    /// assert!(sn_mr.nd_enabled());
958    /// let sn_mr: SocketMode = sn_mr.disable_nd();
959    /// assert!(!sn_mr.nd_enabled());
960    /// ```
961    ///
962    /// [`rtr`]: crate::Registers::rtr
963    pub const fn nd_enabled(&self) -> bool {
964        self.0 & Self::ND_MASK != 0
965    }
966
967    /// Disable no delayed ACK.
968    #[must_use = "disable_nd returns a modified SocketMode"]
969    pub const fn disable_nd(mut self) -> Self {
970        self.0 &= !Self::ND_MASK;
971        self
972    }
973
974    /// Enable no delayed ACK.
975    #[must_use = "enable_nd returns a modified SocketMode"]
976    pub const fn enable_nd(mut self) -> Self {
977        self.0 |= Self::ND_MASK;
978        self
979    }
980
981    /// Multicast IGMP version.
982    ///
983    /// This applies only for a socket with the UDP protocol.
984    ///
985    /// This field configures the version for IGMP messages (join/leave/report).
986    ///
987    /// * `false` IGMP version 2
988    /// * `true` IGMP version 1
989    ///
990    /// # Example
991    ///
992    /// ```
993    /// use w5500_ll::SocketMode;
994    ///
995    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
996    /// assert!(!sn_mr.mc());
997    /// let sn_mr: SocketMode = sn_mr.set_igmp_v1();
998    /// assert!(sn_mr.mc());
999    /// let sn_mr: SocketMode = sn_mr.set_igmp_v2();
1000    /// assert!(!sn_mr.mc());
1001    /// ```
1002    pub const fn mc(&self) -> bool {
1003        self.0 & Self::MC_MASK != 0
1004    }
1005
1006    /// Set IGMP version 1.
1007    #[must_use = "set_igmp_v1 returns a modified SocketMode"]
1008    pub const fn set_igmp_v1(mut self) -> Self {
1009        self.0 |= Self::MC_MASK;
1010        self
1011    }
1012
1013    /// Set IGMP version 2.
1014    #[must_use = "set_igmp_v2 returns a modified SocketMode"]
1015    pub const fn set_igmp_v2(mut self) -> Self {
1016        self.0 &= !Self::MC_MASK;
1017        self
1018    }
1019
1020    /// Multicast blocking.
1021    ///
1022    /// This applies only for a socket with the [MACRAW] protocol.
1023    ///
1024    /// # Example
1025    ///
1026    /// ```
1027    /// use w5500_ll::SocketMode;
1028    ///
1029    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
1030    /// assert!(!sn_mr.mmb_enabled());
1031    /// let sn_mr: SocketMode = sn_mr.enable_mmb();
1032    /// assert!(sn_mr.mmb_enabled());
1033    /// let sn_mr: SocketMode = sn_mr.disable_mmb();
1034    /// assert!(!sn_mr.mmb_enabled());
1035    /// ```
1036    ///
1037    /// [MACRAW]: crate::Protocol::Macraw
1038    pub const fn mmb_enabled(&self) -> bool {
1039        self.0 & Self::MMB_MASK != 0
1040    }
1041
1042    /// Enable multicast blocking.
1043    #[must_use = "enable_mmb returns a modified SocketMode"]
1044    pub const fn enable_mmb(mut self) -> Self {
1045        self.0 |= Self::MMB_MASK;
1046        self
1047    }
1048
1049    /// Disable multicast blocking.
1050    #[must_use = "disable_mmb returns a modified SocketMode"]
1051    pub const fn disable_mmb(mut self) -> Self {
1052        self.0 &= !Self::MMB_MASK;
1053        self
1054    }
1055
1056    /// Unicast blocking enabled.
1057    ///
1058    /// This applies only for a socket with the UDP protocol.
1059    ///
1060    /// # Example
1061    ///
1062    /// ```
1063    /// use w5500_ll::SocketMode;
1064    ///
1065    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
1066    /// assert!(!sn_mr.ucastb_enabled());
1067    /// let sn_mr: SocketMode = sn_mr.enable_ucastb();
1068    /// assert!(sn_mr.ucastb_enabled());
1069    /// let sn_mr: SocketMode = sn_mr.disable_ucastb();
1070    /// assert!(!sn_mr.ucastb_enabled());
1071    /// ```
1072    pub const fn ucastb_enabled(&self) -> bool {
1073        self.0 & Self::UCASTB_MASK != 0
1074    }
1075
1076    /// Enable unicast blocking.
1077    #[must_use = "enable_ucastb returns a modified SocketMode"]
1078    pub const fn enable_ucastb(mut self) -> Self {
1079        self.0 |= Self::UCASTB_MASK;
1080        self
1081    }
1082
1083    /// Disable unicast blocking.
1084    #[must_use = "disable_ucastb returns a modified SocketMode"]
1085    pub const fn disable_ucastb(mut self) -> Self {
1086        self.0 &= !Self::UCASTB_MASK;
1087        self
1088    }
1089
1090    /// IPV6 packet blocking.
1091    ///
1092    /// This applies only for a socket with the [MACRAW] protocol.
1093    ///
1094    /// # Example
1095    ///
1096    /// ```
1097    /// use w5500_ll::SocketMode;
1098    ///
1099    /// let sn_mr: SocketMode = SocketMode::DEFAULT;
1100    /// assert!(!sn_mr.mip6b_enabled());
1101    /// let sn_mr: SocketMode = sn_mr.enable_mip6b();
1102    /// assert!(sn_mr.mip6b_enabled());
1103    /// let sn_mr: SocketMode = sn_mr.disable_mip6b();
1104    /// assert!(!sn_mr.mip6b_enabled());
1105    /// ```
1106    ///
1107    /// [MACRAW]: crate::Protocol::Macraw
1108    pub const fn mip6b_enabled(&self) -> bool {
1109        self.0 & Self::MIP6B_MASK != 0
1110    }
1111
1112    /// Enable IPV6 packet blocking.
1113    #[must_use = "enable_mip6b returns a modified SocketMode"]
1114    pub const fn enable_mip6b(mut self) -> Self {
1115        self.0 |= Self::MIP6B_MASK;
1116        self
1117    }
1118
1119    /// Disable IPV6 packet blocking.
1120    #[must_use = "disable_mip6b returns a modified SocketMode"]
1121    pub const fn disable_mip6b(mut self) -> Self {
1122        self.0 &= !Self::MIP6B_MASK;
1123        self
1124    }
1125}
1126
1127impl ::core::fmt::Display for SocketMode {
1128    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1129        f.debug_struct("SocketMode")
1130            .field("protocol", &self.protocol())
1131            .field("multi_enabled", &self.multi_enabled())
1132            .field("mfen_enabled", &self.mfen_enabled())
1133            .field("bcastb_enabled", &self.bcastb_enabled())
1134            .field("nd_enabled", &self.nd_enabled())
1135            .field("mc", &self.mc())
1136            .field("mmb_enabled", &self.mmb_enabled())
1137            .field("ucastb_enabled", &self.ucastb_enabled())
1138            .field("mip6b_enabled", &self.mip6b_enabled())
1139            .finish()
1140    }
1141}
1142
1143#[cfg(feature = "defmt")]
1144impl defmt::Format for SocketMode {
1145    fn format(&self, fmt: defmt::Formatter) {
1146        defmt::write!(
1147            fmt,
1148            "SocketMode {{ protocol: {}, multi_enabled: {}, mfen_enabled: {}, bcastb_enabled: {}, nd_enabled: {}, mc: {}, mmb_enabled: {}, ucastb_enabled: {}, mip6b_enabled: {} }}",
1149            self.protocol(),
1150            self.multi_enabled(),
1151            self.mfen_enabled(),
1152            self.bcastb_enabled(),
1153            self.nd_enabled(),
1154            self.mc(),
1155            self.mmb_enabled(),
1156            self.ucastb_enabled(),
1157            self.mip6b_enabled(),
1158        );
1159    }
1160}
1161
1162/// Socket Interrupt Register (Sn_IR).
1163///
1164/// Indicated the socket status, such as connection, termination,
1165/// receiving data, and timeout.
1166///
1167/// This is used by the [`Registers::sn_ir`] and
1168/// [`Registers::set_sn_ir`] methods.
1169///
1170/// [`Registers::sn_ir`]: crate::Registers::sn_ir
1171/// [`Registers::set_sn_ir`]: crate::Registers::set_sn_ir
1172#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1173pub struct SocketInterrupt(u8);
1174impl_boilerplate_for!(SocketInterrupt);
1175
1176impl SocketInterrupt {
1177    /// Socket interrupt status register (Sn_IR) reset value.
1178    pub const RESET: u8 = 0x00;
1179
1180    /// Default value.
1181    ///
1182    /// This is the same as `default`, but as a `const` value.
1183    ///
1184    /// # Example
1185    ///
1186    /// ```
1187    /// use w5500_ll::SocketInterrupt;
1188    ///
1189    /// assert_eq!(SocketInterrupt::DEFAULT, SocketInterrupt::default());
1190    /// ```
1191    pub const DEFAULT: Self = Self(Self::RESET);
1192
1193    /// Bit offset for the `CON` field.
1194    pub const CON_OFFSET: u8 = 0;
1195    /// Bit offset for the `DISCON` field.
1196    pub const DISCON_OFFSET: u8 = 1;
1197    /// Bit offset for the `RECV` field.
1198    pub const RECV_OFFSET: u8 = 2;
1199    /// Bit offset for the `TIMEOUT` field.
1200    pub const TIMEOUT_OFFSET: u8 = 3;
1201    /// Bit offset for the `SENDOK` field.
1202    pub const SENDOK_OFFSET: u8 = 4;
1203
1204    /// Bit mask for the `CON` field.
1205    pub const CON_MASK: u8 = 1 << Self::CON_OFFSET;
1206    /// Bit mask for the `DISCON` field.
1207    pub const DISCON_MASK: u8 = 1 << Self::DISCON_OFFSET;
1208    /// Bit mask for the `RECV` field.
1209    pub const RECV_MASK: u8 = 1 << Self::RECV_OFFSET;
1210    /// Bit mask for the `TIMEOUT` field.
1211    pub const TIMEOUT_MASK: u8 = 1 << Self::TIMEOUT_OFFSET;
1212    /// Bit mask for the `SENDOK` field.
1213    pub const SENDOK_MASK: u8 = 1 << Self::SENDOK_OFFSET;
1214
1215    const ALL_MASK: u8 = Self::CON_MASK
1216        | Self::DISCON_MASK
1217        | Self::RECV_MASK
1218        | Self::TIMEOUT_MASK
1219        | Self::SENDOK_MASK;
1220
1221    /// Get the value of the `CON` interrupt.
1222    ///
1223    /// This is issued once when the connection with the peer is successful.
1224    ///
1225    /// # Example
1226    ///
1227    /// ```
1228    /// use w5500_ll::SocketInterrupt;
1229    ///
1230    /// let sir: SocketInterrupt = SocketInterrupt::DEFAULT;
1231    /// assert!(!sir.con_raised());
1232    /// # assert!(sir.clear_con().con_raised());
1233    /// ```
1234    pub const fn con_raised(&self) -> bool {
1235        self.0 & Self::CON_MASK != 0
1236    }
1237
1238    /// Clear the `CON` interrupt by writing `1`.
1239    #[must_use = "clear_con returns a modified SocketInterrupt"]
1240    pub const fn clear_con(mut self) -> Self {
1241        self.0 |= Self::CON_MASK;
1242        self
1243    }
1244
1245    /// Get the value of the `DISCON` interrupt.
1246    ///
1247    /// This is issued when FIN or FIN/ACK packet is received from a peer.
1248    ///
1249    /// # Example
1250    ///
1251    /// ```
1252    /// use w5500_ll::SocketInterrupt;
1253    ///
1254    /// let sir: SocketInterrupt = SocketInterrupt::DEFAULT;
1255    /// assert!(!sir.discon_raised());
1256    /// # assert!(sir.clear_discon().discon_raised());
1257    /// ```
1258    pub const fn discon_raised(&self) -> bool {
1259        self.0 & Self::DISCON_MASK != 0
1260    }
1261
1262    /// Clear the `DISCON` interrupt by writing `1`.
1263    #[must_use = "clear_discon returns a modified SocketInterrupt"]
1264    pub const fn clear_discon(mut self) -> Self {
1265        self.0 |= Self::DISCON_MASK;
1266        self
1267    }
1268
1269    /// Get the value of the `RECV` interrupt.
1270    ///
1271    /// This is issued whenever data is received from a peer.
1272    ///
1273    /// # Example
1274    ///
1275    /// ```
1276    /// use w5500_ll::SocketInterrupt;
1277    ///
1278    /// let sir: SocketInterrupt = SocketInterrupt::DEFAULT;
1279    /// assert!(!sir.recv_raised());
1280    /// # assert!(sir.clear_recv().recv_raised());
1281    /// ```
1282    pub const fn recv_raised(&self) -> bool {
1283        self.0 & Self::RECV_MASK != 0
1284    }
1285
1286    /// Clear the `RECV` interrupt by writing `1`.
1287    #[must_use = "clear_recv returns a modified SocketInterrupt"]
1288    pub const fn clear_recv(mut self) -> Self {
1289        self.0 |= Self::RECV_MASK;
1290        self
1291    }
1292
1293    /// Get the value of the `TIMEOUT` interrupt.
1294    ///
1295    /// This is issued when ARP<sub>TO</sub> or TCP<sub>TO</sub> occurs.
1296    ///
1297    /// # Example
1298    ///
1299    /// ```
1300    /// use w5500_ll::SocketInterrupt;
1301    ///
1302    /// let sir: SocketInterrupt = SocketInterrupt::DEFAULT;
1303    /// assert!(!sir.timeout_raised());
1304    /// # assert!(sir.clear_timeout().timeout_raised());
1305    /// ```
1306    pub const fn timeout_raised(&self) -> bool {
1307        self.0 & Self::TIMEOUT_MASK != 0
1308    }
1309
1310    /// Clear the `TIMEOUT` interrupt by writing `1`.
1311    #[must_use = "clear_timeout returns a modified SocketInterrupt"]
1312    pub const fn clear_timeout(mut self) -> Self {
1313        self.0 |= Self::TIMEOUT_MASK;
1314        self
1315    }
1316
1317    /// Get the value of the `SENDOK` interrupt.
1318    ///
1319    /// This is issued when [SEND] command is completed.
1320    ///
1321    /// # Example
1322    ///
1323    /// ```
1324    /// use w5500_ll::SocketInterrupt;
1325    ///
1326    /// let sir: SocketInterrupt = SocketInterrupt::DEFAULT;
1327    /// assert!(!sir.sendok_raised());
1328    /// # assert!(sir.clear_sendok().sendok_raised());
1329    /// ```
1330    ///
1331    /// [SEND]: crate::SocketCommand::Send
1332    pub const fn sendok_raised(&self) -> bool {
1333        self.0 & Self::SENDOK_MASK != 0
1334    }
1335
1336    /// Clear the `SENDOK` interrupt by writing `1`.
1337    #[must_use = "clear_sendok returns a modified SocketInterrupt"]
1338    pub const fn clear_sendok(mut self) -> Self {
1339        self.0 |= Self::SENDOK_MASK;
1340        self
1341    }
1342
1343    /// Returns `true` if any interrupt is raised.
1344    ///
1345    /// # Example
1346    ///
1347    /// ```
1348    /// use w5500_ll::SocketInterrupt;
1349    ///
1350    /// assert!(!SocketInterrupt::DEFAULT.any_raised());
1351    /// ```
1352    pub const fn any_raised(&self) -> bool {
1353        self.0 & Self::ALL_MASK != 0
1354    }
1355}
1356
1357impl ::core::fmt::Display for SocketInterrupt {
1358    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1359        f.debug_struct("SocketInterrupt")
1360            .field("con_raised", &self.con_raised())
1361            .field("discon_raised", &self.discon_raised())
1362            .field("recv_raised", &self.recv_raised())
1363            .field("timeout_raised", &self.timeout_raised())
1364            .field("sendok_raised", &self.sendok_raised())
1365            .finish()
1366    }
1367}
1368
1369#[cfg(feature = "defmt")]
1370impl defmt::Format for SocketInterrupt {
1371    fn format(&self, fmt: defmt::Formatter) {
1372        defmt::write!(
1373            fmt,
1374            "SocketInterrupt {{ con_raised: {}, discon_raised: {}, recv_raised: {}, timeout_raised: {}, sendok_raised: {} }}",
1375            self.con_raised(),
1376            self.discon_raised(),
1377            self.recv_raised(),
1378            self.timeout_raised(),
1379            self.sendok_raised(),
1380        );
1381    }
1382}
1383
1384/// Socket Interrupt Mask Register (Sn_IMR).
1385///
1386/// This is used by the [`Registers::sn_imr`] and
1387/// [`Registers::set_sn_imr`] methods.
1388///
1389/// See the [`SocketInterrupt`] structure for more information about the
1390/// individual interrupts.
1391///
1392/// [`Registers::sn_imr`]: crate::Registers::sn_imr
1393/// [`Registers::set_sn_imr`]: crate::Registers::set_sn_imr
1394#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1395pub struct SocketInterruptMask(u8);
1396impl_boilerplate_for!(SocketInterruptMask);
1397
1398impl SocketInterruptMask {
1399    /// Socket interrupt mask register (Sn_IMR) reset value.
1400    pub const RESET: u8 = 0xFF;
1401
1402    /// Default value.
1403    ///
1404    /// This is the same as `default`, but as a `const` value.
1405    ///
1406    /// # Example
1407    ///
1408    /// ```
1409    /// use w5500_ll::SocketInterruptMask;
1410    ///
1411    /// assert_eq!(SocketInterruptMask::DEFAULT, SocketInterruptMask::default());
1412    /// ```
1413    pub const DEFAULT: Self = Self(Self::RESET);
1414
1415    /// Mask all socket interrupts.
1416    ///
1417    /// # Example
1418    ///
1419    /// ```
1420    /// use w5500_ll::SocketInterruptMask;
1421    ///
1422    /// assert!(SocketInterruptMask::ALL_MASKED.con_masked());
1423    /// assert!(SocketInterruptMask::ALL_MASKED.discon_masked());
1424    /// assert!(SocketInterruptMask::ALL_MASKED.recv_masked());
1425    /// assert!(SocketInterruptMask::ALL_MASKED.timeout_masked());
1426    /// assert!(SocketInterruptMask::ALL_MASKED.sendok_masked());
1427    /// ```
1428    pub const ALL_MASKED: SocketInterruptMask = SocketInterruptMask(0xE0);
1429
1430    /// Check if the `CON` interrupt is masked.
1431    ///
1432    /// # Example
1433    ///
1434    /// ```
1435    /// use w5500_ll::SocketInterruptMask;
1436    ///
1437    /// let simr: SocketInterruptMask = SocketInterruptMask::DEFAULT;
1438    /// assert!(!simr.con_masked());
1439    /// let simr: SocketInterruptMask = simr.mask_con();
1440    /// assert!(simr.con_masked());
1441    /// let simr: SocketInterruptMask = simr.unmask_con();
1442    /// assert!(!simr.con_masked());
1443    /// ```
1444    pub const fn con_masked(&self) -> bool {
1445        self.0 & SocketInterrupt::CON_MASK == 0
1446    }
1447
1448    /// Unmask the `CON` interrupt.
1449    #[must_use = "unmask_con returns a modified SocketInterruptMask"]
1450    pub const fn unmask_con(mut self) -> Self {
1451        self.0 |= SocketInterrupt::CON_MASK;
1452        self
1453    }
1454
1455    /// Mask the `CON` interrupt.
1456    #[must_use = "mask_con returns a modified SocketInterruptMask"]
1457    pub const fn mask_con(mut self) -> Self {
1458        self.0 &= !SocketInterrupt::CON_MASK;
1459        self
1460    }
1461
1462    /// Check if the `DISCON` interrupt is masked.
1463    ///
1464    /// # Example
1465    ///
1466    /// ```
1467    /// use w5500_ll::SocketInterruptMask;
1468    ///
1469    /// let simr: SocketInterruptMask = SocketInterruptMask::DEFAULT;
1470    /// assert!(!simr.discon_masked());
1471    /// let simr: SocketInterruptMask = simr.mask_discon();
1472    /// assert!(simr.discon_masked());
1473    /// let simr: SocketInterruptMask = simr.unmask_discon();
1474    /// assert!(!simr.discon_masked());
1475    /// ```
1476    pub const fn discon_masked(&self) -> bool {
1477        self.0 & SocketInterrupt::DISCON_MASK == 0
1478    }
1479
1480    /// Unmask the `DISCON` interrupt.
1481    #[must_use = "unmask_discon returns a modified SocketInterruptMask"]
1482    pub const fn unmask_discon(mut self) -> Self {
1483        self.0 |= SocketInterrupt::DISCON_MASK;
1484        self
1485    }
1486
1487    /// Mask the `DISCON` interrupt.
1488    #[must_use = "mask_discon returns a modified SocketInterruptMask"]
1489    pub const fn mask_discon(mut self) -> Self {
1490        self.0 &= !SocketInterrupt::DISCON_MASK;
1491        self
1492    }
1493
1494    /// Check if the `RECV` interrupt is masked.
1495    ///
1496    /// # Example
1497    ///
1498    /// ```
1499    /// use w5500_ll::SocketInterruptMask;
1500    ///
1501    /// let simr: SocketInterruptMask = SocketInterruptMask::DEFAULT;
1502    /// assert!(!simr.recv_masked());
1503    /// let simr: SocketInterruptMask = simr.mask_recv();
1504    /// assert!(simr.recv_masked());
1505    /// let simr: SocketInterruptMask = simr.unmask_recv();
1506    /// assert!(!simr.recv_masked());
1507    /// ```
1508    pub const fn recv_masked(&self) -> bool {
1509        self.0 & SocketInterrupt::RECV_MASK == 0
1510    }
1511
1512    /// Unmask the `RECV` interrupt.
1513    #[must_use = "unmask_recv returns a modified SocketInterruptMask"]
1514    pub const fn unmask_recv(mut self) -> Self {
1515        self.0 |= SocketInterrupt::RECV_MASK;
1516        self
1517    }
1518
1519    /// Mask the `RECV` interrupt.
1520    #[must_use = "mask_recv returns a modified SocketInterruptMask"]
1521    pub const fn mask_recv(mut self) -> Self {
1522        self.0 &= !SocketInterrupt::RECV_MASK;
1523        self
1524    }
1525
1526    /// Check if the `TIMEOUT` interrupt is masked.
1527    ///
1528    /// # Example
1529    ///
1530    /// ```
1531    /// use w5500_ll::SocketInterruptMask;
1532    ///
1533    /// let simr: SocketInterruptMask = SocketInterruptMask::DEFAULT;
1534    /// assert!(!simr.timeout_masked());
1535    /// let simr: SocketInterruptMask = simr.mask_timeout();
1536    /// assert!(simr.timeout_masked());
1537    /// let simr: SocketInterruptMask = simr.unmask_timeout();
1538    /// assert!(!simr.timeout_masked());
1539    /// ```
1540    pub const fn timeout_masked(&self) -> bool {
1541        self.0 & SocketInterrupt::TIMEOUT_MASK == 0
1542    }
1543
1544    /// Unmask the `TIMEOUT` interrupt.
1545    #[must_use = "unmask_timeout returns a modified SocketInterruptMask"]
1546    pub const fn unmask_timeout(mut self) -> Self {
1547        self.0 |= SocketInterrupt::TIMEOUT_MASK;
1548        self
1549    }
1550
1551    /// Mask the `TIMEOUT` interrupt.
1552    #[must_use = "mask_timeout returns a modified SocketInterruptMask"]
1553    pub const fn mask_timeout(mut self) -> Self {
1554        self.0 &= !SocketInterrupt::TIMEOUT_MASK;
1555        self
1556    }
1557
1558    /// Check if the `SENDOK` interrupt is masked.
1559    ///
1560    /// # Example
1561    ///
1562    /// ```
1563    /// use w5500_ll::SocketInterruptMask;
1564    ///
1565    /// let simr: SocketInterruptMask = SocketInterruptMask::DEFAULT;
1566    /// assert!(!simr.sendok_masked());
1567    /// let simr: SocketInterruptMask = simr.mask_sendok();
1568    /// assert!(simr.sendok_masked());
1569    /// let simr: SocketInterruptMask = simr.unmask_sendok();
1570    /// assert!(!simr.sendok_masked());
1571    /// ```
1572    pub const fn sendok_masked(&self) -> bool {
1573        self.0 & SocketInterrupt::SENDOK_MASK == 0
1574    }
1575
1576    /// Unmask the `SENDOK` interrupt.
1577    #[must_use = "unmask_sendok returns a modified SocketInterruptMask"]
1578    pub const fn unmask_sendok(mut self) -> Self {
1579        self.0 |= SocketInterrupt::SENDOK_MASK;
1580        self
1581    }
1582
1583    /// Mask the `SENDOK` interrupt.
1584    #[must_use = "mask_sendok returns a modified SocketInterruptMask"]
1585    pub const fn mask_sendok(mut self) -> Self {
1586        self.0 &= !SocketInterrupt::SENDOK_MASK;
1587        self
1588    }
1589}
1590
1591impl ::core::fmt::Display for SocketInterruptMask {
1592    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
1593        f.debug_struct("SocketInterruptMask")
1594            .field("con_masked", &self.con_masked())
1595            .field("discon_masked", &self.discon_masked())
1596            .field("recv_masked", &self.recv_masked())
1597            .field("timeout_masked", &self.timeout_masked())
1598            .field("sendok_masked", &self.sendok_masked())
1599            .finish()
1600    }
1601}
1602
1603#[cfg(feature = "defmt")]
1604impl defmt::Format for SocketInterruptMask {
1605    fn format(&self, fmt: defmt::Formatter) {
1606        defmt::write!(
1607            fmt,
1608            "SocketInterruptMask {{ con_masked: {}, discon_masked: {}, recv_masked: {}, timeout_masked: {}, sendok_masked: {} }}",
1609            self.con_masked(),
1610            self.discon_masked(),
1611            self.recv_masked(),
1612            self.timeout_masked(),
1613            self.sendok_masked(),
1614        );
1615    }
1616}