1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/// Startup configurations when exiting sleep mode.
///
/// Argument of [`SleepCfg::set_startup`].
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum Startup {
    /// Cold startup when exiting Sleep mode, configuration registers reset.
    Cold = 0,
    /// Warm startup when exiting Sleep mode,
    /// configuration registers kept in retention.
    ///
    /// **Note:** Only the configuration of the activated modem,
    /// before going to sleep mode, is retained.
    /// The configuration of the other modes is lost and must be re-configured
    /// when exiting sleep mode.
    #[default]
    Warm = 1,
}

/// Sleep configuration.
///
/// Argument of [`set_sleep`].
///
/// [`set_sleep`]: super::SubGhz::set_sleep
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SleepCfg(u8);

impl SleepCfg {
    /// Create a new `SleepCfg` structure.
    ///
    /// This is the same as `default`, but in a `const` function.
    ///
    /// The defaults are a warm startup, with RTC wakeup enabled.
    ///
    /// # Example
    ///
    /// ```
    /// use stm32wlxx_hal::subghz::SleepCfg;
    ///
    /// const SLEEP_CFG: SleepCfg = SleepCfg::new();
    /// assert_eq!(SLEEP_CFG, SleepCfg::default());
    /// # assert_eq!(u8::from(SLEEP_CFG), 0b101);
    /// ```
    pub const fn new() -> SleepCfg {
        SleepCfg(0)
            .set_startup(Startup::Warm)
            .set_rtc_wakeup_en(true)
    }

    /// Set the startup mode.
    ///
    /// # Example
    ///
    /// ```
    /// use stm32wlxx_hal::subghz::{SleepCfg, Startup};
    ///
    /// const SLEEP_CFG: SleepCfg = SleepCfg::new().set_startup(Startup::Cold);
    /// # assert_eq!(u8::from(SLEEP_CFG), 0b001);
    /// # assert_eq!(u8::from(SLEEP_CFG.set_startup(Startup::Warm)), 0b101);
    /// ```
    pub const fn set_startup(mut self, startup: Startup) -> SleepCfg {
        if startup as u8 == 1 {
            self.0 |= 1 << 2
        } else {
            self.0 &= !(1 << 2)
        }
        self
    }

    /// Set the RTC wakeup enable.
    ///
    /// # Example
    ///
    /// ```
    /// use stm32wlxx_hal::subghz::SleepCfg;
    ///
    /// const SLEEP_CFG: SleepCfg = SleepCfg::new().set_rtc_wakeup_en(false);
    /// # assert_eq!(u8::from(SLEEP_CFG), 0b100);
    /// # assert_eq!(u8::from(SLEEP_CFG.set_rtc_wakeup_en(true)), 0b101);
    /// ```
    #[must_use = "set_rtc_wakeup_en returns a modified SleepCfg"]
    pub const fn set_rtc_wakeup_en(mut self, en: bool) -> SleepCfg {
        if en {
            self.0 |= 0b1
        } else {
            self.0 &= !0b1
        }
        self
    }
}

impl From<SleepCfg> for u8 {
    fn from(sc: SleepCfg) -> Self {
        sc.0
    }
}

impl Default for SleepCfg {
    fn default() -> Self {
        Self::new()
    }
}