1
use core::{
2
    sync::atomic::Ordering,
3
    task::{Context, Poll},
4
};
5

            
6
use crate::gpio::{Event, Flex, GpioBank, Input, InputPin};
7

            
8
impl Flex<'_> {
9
    /// Waits until the pin experiences a particular [`Event`].
10
    ///
11
    /// The GPIO driver will disable listening for the event once it occurs,
12
    /// or if the `Future` is dropped - which also means this method is **not**
13
    /// cancellation-safe, it will always wait for a future event.
14
    ///
15
    /// Calling this method overwrites previous [`listen`][Self::listen] operations
16
    /// for this pin.
17
    ///
18
    /// A wait continues through a light sleep, and a pin that waits also ends the sleep, like a
19
    /// listening pin. There is one exception: a wait for an edge on a pin that is already at the
20
    /// level at the end of that edge. See [`listen`][Self::listen].
21
    #[inline]
22
    #[instability::unstable]
23
20097
    pub async fn wait_for(&mut self, event: Event) {
24
        // Make sure this pin is not being processed by an interrupt handler. We need to
25
        // always take a critical section even if the pin is not listening, because the
26
        // interrupt handler may be running on another core and the interrupt handler
27
        // may be in the process of processing the pin if the interrupt status is set -
28
        // regardless of the pin actually listening or not.
29
39
        if self.is_listening() || self.is_interrupt_set() {
30
1
            self.unlisten_and_clear();
31
        }
32

            
33
        // At this point the pin is no longer listening, and not being processed, so we
34
        // can safely do our setup.
35

            
36
        // Mark pin as async. The interrupt handler clears this bit before processing a
37
        // pin and unlistens it, so this call will not race with the interrupt
38
        // handler (because it must have finished before `unlisten` above, or the
39
        // handler no longer )
40
        self.pin
41
            .bank()
42
            .async_operations()
43
            .fetch_or(self.pin.mask(), Ordering::Relaxed);
44

            
45
        // Start listening for the event. We only need to do this once, as disabling
46
        // the interrupt will signal the future to complete.
47
39
        self.pin.listen(event);
48

            
49
20087
        PinFuture { pin: self }.await;
50
    }
51

            
52
    /// Waits until the pin is high.
53
    ///
54
    /// See [Self::wait_for] for more information.
55
    #[inline]
56
    #[instability::unstable]
57
    pub async fn wait_for_high(&mut self) {
58
2
        self.wait_for(Event::HighLevel).await
59
    }
60

            
61
    /// Waits until the pin is low.
62
    ///
63
    /// See [Self::wait_for] for more information.
64
    #[inline]
65
    #[instability::unstable]
66
1
    pub async fn wait_for_low(&mut self) {
67
2
        self.wait_for(Event::LowLevel).await
68
    }
69

            
70
    /// Waits for the pin to undergo a transition from low to high.
71
    ///
72
    /// See [Self::wait_for] for more information.
73
    #[inline]
74
    #[instability::unstable]
75
76
    pub async fn wait_for_rising_edge(&mut self) {
76
77
        self.wait_for(Event::RisingEdge).await
77
    }
78

            
79
    /// Waits for the pin to undergo a transition from high to low.
80
    ///
81
    /// See [Self::wait_for] for more information.
82
    #[inline]
83
    #[instability::unstable]
84
5
    pub async fn wait_for_falling_edge(&mut self) {
85
6
        self.wait_for(Event::FallingEdge).await
86
    }
87

            
88
    /// Waits for the pin to undergo any transition, i.e. low to high or high
89
    /// to low.
90
    ///
91
    /// See [Self::wait_for] for more information.
92
    #[inline]
93
    #[instability::unstable]
94
20000
    pub async fn wait_for_any_edge(&mut self) {
95
20000
        self.wait_for(Event::AnyEdge).await
96
    }
97
}
98

            
99
impl Input<'_> {
100
    #[procmacros::doc_replace]
101
    /// Waits until the pin experiences a particular [`Event`].
102
    ///
103
    /// # Examples
104
    ///
105
    /// ```rust, no_run
106
    /// # {before_snippet}
107
    /// use esp_hal::gpio::{Event, Input, InputConfig};
108
    /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
109
    ///
110
    /// input_pin.wait_for(Event::LowLevel).await;
111
    /// # {after_snippet}
112
    /// ```
113
    ///
114
    /// # Cancellation Safety
115
    ///
116
    /// Not cancellation-safe.
117
    ///
118
    /// - Calling this method overwrites previous [`listen`][Self::listen] operations for this pin,
119
    ///   making it side-effectful.
120
    /// - Dropping the [`Future`] returned by this method cancels the wait operation. If the event
121
    ///   occurs after the future is dropped, a subsequent wait operation ignores the event.
122
    ///
123
    /// A wait continues through a light sleep, and a pin that waits also ends the sleep, like a
124
    /// listening pin. There is one exception: a wait for an edge on a pin that is already at the
125
    /// level at the end of that edge. See [`listen`][Self::listen].
126
    #[inline]
127
    #[instability::unstable]
128
    pub async fn wait_for(&mut self, event: Event) {
129
        self.pin.wait_for(event).await
130
    }
131

            
132
    #[procmacros::doc_replace]
133
    /// Waits until the pin is high.
134
    ///
135
    /// See [Self::wait_for] for more information.
136
    ///
137
    /// # Examples
138
    ///
139
    /// ```rust, no_run
140
    /// # {before_snippet}
141
    /// use esp_hal::gpio::{Event, Input, InputConfig};
142
    /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
143
    ///
144
    /// input_pin.wait_for_high().await;
145
    /// # {after_snippet}
146
    /// ```
147
    #[inline]
148
    pub async fn wait_for_high(&mut self) {
149
2
        self.pin.wait_for_high().await
150
    }
151

            
152
    #[procmacros::doc_replace]
153
    /// Waits until the pin is low.
154
    ///
155
    /// See [Self::wait_for] for more information.
156
    ///
157
    /// # Examples
158
    ///
159
    /// ```rust, no_run
160
    /// # {before_snippet}
161
    /// use esp_hal::gpio::{Event, Input, InputConfig};
162
    /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
163
    ///
164
    /// input_pin.wait_for_low().await;
165
    /// # {after_snippet}
166
    /// ```
167
    #[inline]
168
1
    pub async fn wait_for_low(&mut self) {
169
1
        self.pin.wait_for_low().await
170
    }
171

            
172
    #[procmacros::doc_replace]
173
    /// Waits for the pin to undergo a transition from low to high.
174
    ///
175
    /// See [Self::wait_for] for more information.
176
    ///
177
    /// # Examples
178
    ///
179
    /// ```rust, no_run
180
    /// # {before_snippet}
181
    /// use esp_hal::gpio::{Event, Input, InputConfig};
182
    /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
183
    ///
184
    /// input_pin.wait_for_rising_edge().await;
185
    /// # {after_snippet}
186
    /// ```
187
    #[inline]
188
100
    pub async fn wait_for_rising_edge(&mut self) {
189
31
        self.pin.wait_for_rising_edge().await
190
    }
191

            
192
    #[procmacros::doc_replace]
193
    /// Waits for the pin to undergo a transition from high to low.
194
    ///
195
    /// See [Self::wait_for] for more information.
196
    ///
197
    /// # Examples
198
    ///
199
    /// ```rust, no_run
200
    /// # {before_snippet}
201
    /// use esp_hal::gpio::{Event, Input, InputConfig};
202
    /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
203
    ///
204
    /// input_pin.wait_for_falling_edge().await;
205
    /// # {after_snippet}
206
    /// ```
207
    #[inline]
208
5
    pub async fn wait_for_falling_edge(&mut self) {
209
1
        self.pin.wait_for_falling_edge().await
210
    }
211

            
212
    #[procmacros::doc_replace]
213
    /// Waits for the pin to undergo any transition, i.e. low to high or high
214
    /// to low.
215
    ///
216
    /// See [Self::wait_for] for more information.
217
    ///
218
    /// # Examples
219
    ///
220
    /// ```rust, no_run
221
    /// # {before_snippet}
222
    /// use esp_hal::gpio::{Event, Input, InputConfig};
223
    /// let mut input_pin = Input::new(peripherals.GPIO4, InputConfig::default());
224
    ///
225
    /// input_pin.wait_for_any_edge().await;
226
    /// # {after_snippet}
227
    /// ```
228
    #[inline]
229
20000
    pub async fn wait_for_any_edge(&mut self) {
230
2
        self.pin.wait_for_any_edge().await
231
    }
232
}
233

            
234
#[must_use = "futures do nothing unless you `.await` or poll them"]
235
struct PinFuture<'f, 'd> {
236
    pin: &'f mut Flex<'d>,
237
}
238

            
239
impl PinFuture<'_, '_> {
240
    fn bank(&self) -> GpioBank {
241
        self.pin.pin.bank()
242
    }
243

            
244
    fn mask(&self) -> u32 {
245
        self.pin.pin.mask()
246
    }
247

            
248
    fn is_done(&self) -> bool {
249
        // Only the interrupt handler should clear the async bit, and only if the
250
        // specific pin is handling an interrupt. This way the user may clear the
251
        // interrupt status without worrying about the async bit being cleared.
252
20123
        self.bank().async_operations().load(Ordering::Acquire) & self.mask() == 0
253
    }
254
}
255

            
256
impl core::future::Future for PinFuture<'_, '_> {
257
    type Output = ();
258

            
259
20123
    fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
260
20123
        self.pin.pin.waker().register(cx.waker());
261

            
262
        if self.is_done() {
263
            Poll::Ready(())
264
        } else {
265
            Poll::Pending
266
        }
267
20123
    }
268
}
269

            
270
impl Drop for PinFuture<'_, '_> {
271
    fn drop(&mut self) {
272
        // If the future has completed, unlistening and removing the async bit will have
273
        // been done by the interrupt handler.
274

            
275
39
        if !self.is_done() {
276
            self.pin.unlisten_and_clear();
277

            
278
            // Unmark pin as async so that a future listen call doesn't wake a waker for no
279
            // reason.
280
            self.bank()
281
                .async_operations()
282
11
                .fetch_and(!self.mask(), Ordering::Relaxed);
283
        }
284
39
    }
285
}