1#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::sync::atomic::{compiler_fence, Ordering};
8use core::task::Poll;
9
10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, PeripheralType};
12use embassy_sync::waitqueue::AtomicWaker;
13use fixed::types::I7F1;
14
15use crate::chip::EASY_DMA_SIZE;
16use crate::gpio::{AnyPin, Pin as GpioPin, SealedPin, DISCONNECTED};
17use crate::interrupt::typelevel::Interrupt;
18use crate::pac::gpio::vals as gpiovals;
19use crate::pac::pdm::vals;
20pub use crate::pac::pdm::vals::Freq as Frequency;
21#[cfg(any(
22 feature = "nrf52840",
23 feature = "nrf52833",
24 feature = "_nrf5340-app",
25 feature = "_nrf91",
26))]
27pub use crate::pac::pdm::vals::Ratio;
28use crate::{interrupt, pac};
29
30pub struct InterruptHandler<T: Instance> {
32 _phantom: PhantomData<T>,
33}
34
35impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
36 unsafe fn on_interrupt() {
37 let r = T::regs();
38
39 if r.events_end().read() != 0 {
40 r.intenclr().write(|w| w.set_end(true));
41 }
42
43 if r.events_started().read() != 0 {
44 r.intenclr().write(|w| w.set_started(true));
45 }
46
47 if r.events_stopped().read() != 0 {
48 r.intenclr().write(|w| w.set_stopped(true));
49 }
50
51 T::state().waker.wake();
52 }
53}
54
55pub struct Pdm<'d, T: Instance> {
57 _peri: Peri<'d, T>,
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63#[non_exhaustive]
64pub enum Error {
65 BufferTooLong,
67 BufferZeroLength,
69 NotRunning,
71 AlreadyRunning,
73}
74
75static DUMMY_BUFFER: [i16; 1] = [0; 1];
76
77#[derive(PartialEq)]
82pub enum SamplerState {
83 Sampled,
85 Stopped,
87}
88
89impl<'d, T: Instance> Pdm<'d, T> {
90 pub fn new(
92 pdm: Peri<'d, T>,
93 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
94 clk: Peri<'d, impl GpioPin>,
95 din: Peri<'d, impl GpioPin>,
96 config: Config,
97 ) -> Self {
98 Self::new_inner(pdm, clk.into(), din.into(), config)
99 }
100
101 fn new_inner(pdm: Peri<'d, T>, clk: Peri<'d, AnyPin>, din: Peri<'d, AnyPin>, config: Config) -> Self {
102 let r = T::regs();
103
104 din.conf().write(|w| w.set_input(gpiovals::Input::CONNECT));
106 r.psel().din().write_value(din.psel_bits());
107 clk.set_low();
108 clk.conf().write(|w| w.set_dir(gpiovals::Dir::OUTPUT));
109 r.psel().clk().write_value(clk.psel_bits());
110
111 r.pdmclkctrl().write(|w| w.set_freq(config.frequency));
113 #[cfg(any(
114 feature = "nrf52840",
115 feature = "nrf52833",
116 feature = "_nrf5340-app",
117 feature = "_nrf91",
118 ))]
119 r.ratio().write(|w| w.set_ratio(config.ratio));
120 r.mode().write(|w| {
121 w.set_operation(config.operation_mode.into());
122 w.set_edge(config.edge.into());
123 });
124
125 Self::_set_gain(r, config.gain_left, config.gain_right);
126
127 r.intenclr().write(|w| w.0 = 0x003F_FFFF);
129
130 T::Interrupt::unpend();
132 unsafe { T::Interrupt::enable() };
133
134 r.enable().write(|w| w.set_enable(true));
135
136 Self { _peri: pdm }
137 }
138
139 fn _set_gain(r: pac::pdm::Pdm, gain_left: I7F1, gain_right: I7F1) {
140 let gain_to_bits = |gain: I7F1| -> vals::Gain {
141 let gain: i8 = gain.saturating_add(I7F1::from_bits(0x28)).to_bits().clamp(0, 0x50);
142 vals::Gain::from_bits(gain as u8)
143 };
144 r.gainl().write(|w| w.set_gainl(gain_to_bits(gain_left)));
145 r.gainr().write(|w| w.set_gainr(gain_to_bits(gain_right)));
146 }
147
148 pub fn set_gain(&mut self, gain_left: I7F1, gain_right: I7F1) {
150 Self::_set_gain(T::regs(), gain_left, gain_right)
151 }
152
153 pub async fn start(&mut self) {
156 let r = T::regs();
157
158 r.sample().ptr().write_value(DUMMY_BUFFER.as_ptr() as u32);
160 r.sample().maxcnt().write(|w| w.set_buffsize(DUMMY_BUFFER.len() as _));
161
162 r.tasks_start().write_value(1);
163 }
164
165 pub async fn stop(&mut self) {
167 let r = T::regs();
168 r.tasks_stop().write_value(1);
169 r.events_started().write_value(0);
170 }
171
172 pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> {
174 if buffer.is_empty() {
175 return Err(Error::BufferZeroLength);
176 }
177 if buffer.len() > EASY_DMA_SIZE {
178 return Err(Error::BufferTooLong);
179 }
180
181 let r = T::regs();
182
183 if r.events_started().read() == 0 {
184 return Err(Error::NotRunning);
185 }
186
187 let drop = OnDrop::new(move || {
188 r.intenclr().write(|w| w.set_end(true));
189 r.events_stopped().write_value(0);
190
191 r.sample().ptr().write_value(DUMMY_BUFFER.as_ptr() as u32);
193 r.sample().maxcnt().write(|w| w.set_buffsize(DUMMY_BUFFER.len() as _));
194
195 while r.events_stopped().read() == 0 {}
196 });
197
198 let ptr = buffer.as_ptr();
200 let len = buffer.len();
201 r.sample().ptr().write_value(ptr as u32);
202 r.sample().maxcnt().write(|w| w.set_buffsize(len as _));
203
204 Self::wait_for_sample().await;
206
207 r.sample().ptr().write_value(DUMMY_BUFFER.as_ptr() as u32);
209 r.sample().maxcnt().write(|w| w.set_buffsize(DUMMY_BUFFER.len() as _));
210
211 Self::wait_for_sample().await;
213
214 drop.defuse();
215
216 Ok(())
217 }
218
219 async fn wait_for_sample() {
220 let r = T::regs();
221
222 r.events_end().write_value(0);
223 r.intenset().write(|w| w.set_end(true));
224
225 compiler_fence(Ordering::SeqCst);
226
227 poll_fn(|cx| {
228 T::state().waker.register(cx.waker());
229 if r.events_end().read() != 0 {
230 return Poll::Ready(());
231 }
232 Poll::Pending
233 })
234 .await;
235
236 compiler_fence(Ordering::SeqCst);
237 }
238
239 pub async fn run_task_sampler<S, const N: usize>(
251 &mut self,
252 bufs: &mut [[i16; N]; 2],
253 mut sampler: S,
254 ) -> Result<(), Error>
255 where
256 S: FnMut(&[i16; N]) -> SamplerState,
257 {
258 let r = T::regs();
259
260 if r.events_started().read() != 0 {
261 return Err(Error::AlreadyRunning);
262 }
263
264 r.sample().ptr().write_value(bufs[0].as_mut_ptr() as u32);
265 r.sample().maxcnt().write(|w| w.set_buffsize(N as _));
266
267 r.events_end().write_value(0);
269 r.events_started().write_value(0);
270 r.events_stopped().write_value(0);
271 r.intenset().write(|w| {
272 w.set_end(true);
273 w.set_started(true);
274 w.set_stopped(true);
275 });
276
277 compiler_fence(Ordering::SeqCst);
280
281 r.tasks_start().write_value(1);
282
283 let mut current_buffer = 0;
284
285 let mut done = false;
286
287 let drop = OnDrop::new(|| {
288 r.tasks_stop().write_value(1);
289 while r.events_stopped().read() != 0 {}
291 });
292
293 poll_fn(|cx| {
295 let r = T::regs();
296
297 T::state().waker.register(cx.waker());
298
299 if r.events_end().read() != 0 {
300 compiler_fence(Ordering::SeqCst);
301
302 r.events_end().write_value(0);
303 r.intenset().write(|w| w.set_end(true));
304
305 if !done {
306 if sampler(&bufs[current_buffer]) == SamplerState::Sampled {
308 let next_buffer = 1 - current_buffer;
309 current_buffer = next_buffer;
310 } else {
311 r.tasks_stop().write_value(1);
312 done = true;
313 };
314 };
315 }
316
317 if r.events_started().read() != 0 {
318 r.events_started().write_value(0);
319 r.intenset().write(|w| w.set_started(true));
320
321 let next_buffer = 1 - current_buffer;
322 r.sample().ptr().write_value(bufs[next_buffer].as_mut_ptr() as u32);
323 }
324
325 if r.events_stopped().read() != 0 {
326 return Poll::Ready(());
327 }
328
329 Poll::Pending
330 })
331 .await;
332 drop.defuse();
333 Ok(())
334 }
335}
336
337pub struct Config {
339 pub operation_mode: OperationMode,
341 pub edge: Edge,
343 pub frequency: Frequency,
345 #[cfg(any(
347 feature = "nrf52840",
348 feature = "nrf52833",
349 feature = "_nrf5340-app",
350 feature = "_nrf91",
351 ))]
352 pub ratio: Ratio,
353 pub gain_left: I7F1,
355 pub gain_right: I7F1,
357}
358
359impl Default for Config {
360 fn default() -> Self {
361 Self {
362 operation_mode: OperationMode::Mono,
363 edge: Edge::LeftFalling,
364 frequency: Frequency::DEFAULT,
365 #[cfg(any(
366 feature = "nrf52840",
367 feature = "nrf52833",
368 feature = "_nrf5340-app",
369 feature = "_nrf91",
370 ))]
371 ratio: Ratio::RATIO80,
372 gain_left: I7F1::ZERO,
373 gain_right: I7F1::ZERO,
374 }
375 }
376}
377
378#[derive(PartialEq)]
380pub enum OperationMode {
381 Mono,
383 Stereo,
385}
386
387impl From<OperationMode> for vals::Operation {
388 fn from(mode: OperationMode) -> Self {
389 match mode {
390 OperationMode::Mono => vals::Operation::MONO,
391 OperationMode::Stereo => vals::Operation::STEREO,
392 }
393 }
394}
395
396#[derive(PartialEq)]
398pub enum Edge {
399 LeftRising,
401 LeftFalling,
403}
404
405impl From<Edge> for vals::Edge {
406 fn from(edge: Edge) -> Self {
407 match edge {
408 Edge::LeftRising => vals::Edge::LEFT_RISING,
409 Edge::LeftFalling => vals::Edge::LEFT_FALLING,
410 }
411 }
412}
413
414impl<'d, T: Instance> Drop for Pdm<'d, T> {
415 fn drop(&mut self) {
416 let r = T::regs();
417
418 r.tasks_stop().write_value(1);
419
420 r.enable().write(|w| w.set_enable(false));
421
422 r.psel().din().write_value(DISCONNECTED);
423 r.psel().clk().write_value(DISCONNECTED);
424 }
425}
426
427pub(crate) struct State {
429 waker: AtomicWaker,
430}
431
432impl State {
433 pub(crate) const fn new() -> Self {
434 Self {
435 waker: AtomicWaker::new(),
436 }
437 }
438}
439
440pub(crate) trait SealedInstance {
441 fn regs() -> crate::pac::pdm::Pdm;
442 fn state() -> &'static State;
443}
444
445#[allow(private_bounds)]
447pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
448 type Interrupt: interrupt::typelevel::Interrupt;
450}
451
452macro_rules! impl_pdm {
453 ($type:ident, $pac_type:ident, $irq:ident) => {
454 impl crate::pdm::SealedInstance for peripherals::$type {
455 fn regs() -> crate::pac::pdm::Pdm {
456 pac::$pac_type
457 }
458 fn state() -> &'static crate::pdm::State {
459 static STATE: crate::pdm::State = crate::pdm::State::new();
460 &STATE
461 }
462 }
463 impl crate::pdm::Instance for peripherals::$type {
464 type Interrupt = crate::interrupt::typelevel::$irq;
465 }
466 };
467}