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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! seeed LoRa-E5 development kit board support package.

#![cfg_attr(not(test), no_std)]
#![warn(missing_docs)]

pub mod led;
pub mod pb;

pub use stm32wlxx_hal as hal;

use hal::{
    cortex_m::interrupt::CriticalSection,
    gpio::{self, pins, Output, OutputArgs, PinState},
};

/// RF switch
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct RfSwitch {
    a4: Output<pins::A4>,
    a5: Output<pins::A5>,
}

impl RfSwitch {
    /// Create a new `RfSwitch` struct from GPIOs.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use lora_e5_bsp::{
    ///     hal::{cortex_m, gpio::PortA, pac},
    ///     RfSwitch,
    /// };
    ///
    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
    ///
    /// let gpioa: PortA = PortA::split(dp.GPIOA, &mut dp.RCC);
    /// let rfs: RfSwitch = cortex_m::interrupt::free(|cs| RfSwitch::new(gpioa.a4, gpioa.a5, cs));
    /// ```
    pub fn new(a4: pins::A4, a5: pins::A5, cs: &CriticalSection) -> RfSwitch {
        const ARGS: OutputArgs = OutputArgs {
            speed: gpio::Speed::Fast,
            level: gpio::PinState::High,
            ot: gpio::OutputType::PushPull,
            pull: gpio::Pull::None,
        };
        RfSwitch {
            a4: Output::new(a4, &ARGS, cs),
            a5: Output::new(a5, &ARGS, cs),
        }
    }

    /// Steal the RF switch from whatever is currently using it.
    ///
    /// # Safety
    ///
    /// 1. Ensure that the code stealing the RF switch has exclusive access.
    ///    Singleton checks are bypassed with this method.
    /// 2. You must set up the RF switch pins.
    ///    No setup will occur when using this method.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use lora_e5_bsp::{
    ///     hal::{
    ///         cortex_m,
    ///         gpio::{pins, Output, PortA},
    ///         pac,
    ///     },
    ///     RfSwitch,
    /// };
    ///
    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
    ///
    /// let pa: PortA = PortA::split(dp.GPIOA, &mut dp.RCC);
    /// cortex_m::interrupt::free(|cs| {
    ///     let _: Output<pins::A4> = Output::default(pa.a4, cs);
    ///     let _: Output<pins::A5> = Output::default(pa.a5, cs);
    /// });
    ///
    /// // safety:
    /// // 1. we have exclusive access to the underlying pins
    /// // 2. the pins have been setup
    /// let rfs: RfSwitch = unsafe { RfSwitch::steal() };
    /// ```
    #[inline]
    pub unsafe fn steal() -> Self {
        RfSwitch {
            a4: Output::steal(),
            a5: Output::steal(),
        }
    }

    /// Set the RF switch to receive.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use lora_e5_bsp::{
    ///     hal::{cortex_m, gpio::PortA, pac},
    ///     RfSwitch,
    /// };
    ///
    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
    ///
    /// let gpioa: PortA = PortA::split(dp.GPIOA, &mut dp.RCC);
    /// let mut rfs: RfSwitch = cortex_m::interrupt::free(|cs| RfSwitch::new(gpioa.a4, gpioa.a5, cs));
    /// rfs.set_rx();
    /// ```
    #[inline]
    pub fn set_rx(&mut self) {
        self.a5.set_level(PinState::Low);
        self.a4.set_level(PinState::High);
    }

    /// Set the RF switch to high power transmit.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use lora_e5_bsp::{
    ///     hal::{cortex_m, gpio::PortA, pac},
    ///     RfSwitch,
    /// };
    ///
    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
    ///
    /// let gpioa: PortA = PortA::split(dp.GPIOA, &mut dp.RCC);
    /// let mut rfs: RfSwitch = cortex_m::interrupt::free(|cs| RfSwitch::new(gpioa.a4, gpioa.a5, cs));
    /// rfs.set_tx_hp();
    /// ```
    #[inline]
    pub fn set_tx_hp(&mut self) {
        self.a4.set_level(PinState::Low);
        self.a5.set_level(PinState::High);
    }
}