1#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
7use core::sync::atomic::{Ordering, compiler_fence};
8use core::task::Poll;
9
10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, impl_peripheral};
12use embassy_sync::waitqueue::AtomicWaker;
13#[cfg(not(feature = "_nrf54l"))]
14pub(crate) use vals::Psel as InputChannel;
15
16use crate::interrupt::InterruptExt;
17use crate::pac::saadc::vals;
18use crate::ppi::{ConfigurableChannel, Event, Ppi, Task};
19use crate::timer::{Frequency, Instance as TimerInstance, Timer};
20use crate::{interrupt, pac, peripherals};
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25#[non_exhaustive]
26pub enum Error {}
27
28pub struct InterruptHandler {
30 _private: (),
31}
32
33impl interrupt::typelevel::Handler<interrupt::typelevel::SAADC> for InterruptHandler {
34 unsafe fn on_interrupt() {
35 let r = pac::SAADC;
36
37 if r.events_calibratedone().read() != 0 {
38 r.intenclr().write(|w| w.set_calibratedone(true));
39 WAKER.wake();
40 }
41
42 if r.events_end().read() != 0 {
43 r.intenclr().write(|w| w.set_end(true));
44 WAKER.wake();
45 }
46
47 if r.events_started().read() != 0 {
48 r.intenclr().write(|w| w.set_started(true));
49 WAKER.wake();
50 }
51 }
52}
53
54static WAKER: AtomicWaker = AtomicWaker::new();
55
56#[non_exhaustive]
60pub struct Config {
61 pub resolution: Resolution,
63 pub oversample: Oversample,
65}
66
67impl Default for Config {
68 fn default() -> Self {
70 Self {
71 resolution: Resolution::_12BIT,
72 oversample: Oversample::BYPASS,
73 }
74 }
75}
76
77#[non_exhaustive]
82pub struct ChannelConfig<'d> {
83 pub reference: Reference,
85 pub gain: Gain,
87 #[cfg(not(feature = "_nrf54l"))]
89 pub resistor: Resistor,
90 pub time: Time,
92 p_channel: AnyInput<'d>,
94 n_channel: Option<AnyInput<'d>>,
96}
97
98impl<'d> ChannelConfig<'d> {
99 pub fn single_ended(input: impl Input + 'd) -> Self {
101 Self {
102 reference: Reference::INTERNAL,
103 #[cfg(not(feature = "_nrf54l"))]
104 gain: Gain::GAIN1_6,
105 #[cfg(feature = "_nrf54l")]
106 gain: Gain::GAIN2_8,
107 #[cfg(not(feature = "_nrf54l"))]
108 resistor: Resistor::BYPASS,
109 time: Time::_10US,
110 p_channel: input.degrade_saadc(),
111 n_channel: None,
112 }
113 }
114 pub fn differential(p_input: impl Input + 'd, n_input: impl Input + 'd) -> Self {
116 Self {
117 reference: Reference::INTERNAL,
118 #[cfg(not(feature = "_nrf54l"))]
119 gain: Gain::GAIN1_6,
120 #[cfg(feature = "_nrf54l")]
121 gain: Gain::GAIN2_8,
122 #[cfg(not(feature = "_nrf54l"))]
123 resistor: Resistor::BYPASS,
124 time: Time::_10US,
125 p_channel: p_input.degrade_saadc(),
126 n_channel: Some(n_input.degrade_saadc()),
127 }
128 }
129}
130
131const CNT_UNIT: usize = if cfg!(feature = "_nrf54l") { 2 } else { 1 };
132
133#[derive(PartialEq)]
135pub enum CallbackResult {
136 Continue,
138 Stop,
140}
141
142pub struct Saadc<'d, const N: usize> {
144 _p: Peri<'d, peripherals::SAADC>,
145}
146
147impl<'d, const N: usize> Saadc<'d, N> {
148 pub fn new(
150 saadc: Peri<'d, peripherals::SAADC>,
151 _irq: impl interrupt::typelevel::Binding<interrupt::typelevel::SAADC, InterruptHandler> + 'd,
152 config: Config,
153 channel_configs: [ChannelConfig; N],
154 ) -> Self {
155 let r = pac::SAADC;
156
157 let Config { resolution, oversample } = config;
158
159 r.enable().write(|w| w.set_enable(true));
161 r.resolution().write(|w| w.set_val(resolution.into()));
162 r.oversample().write(|w| w.set_oversample(oversample.into()));
163
164 for (i, cc) in channel_configs.iter().enumerate() {
165 #[cfg(not(feature = "_nrf54l"))]
166 r.ch(i).pselp().write(|w| w.set_pselp(cc.p_channel.channel()));
167 #[cfg(feature = "_nrf54l")]
168 r.ch(i).pselp().write(|w| {
169 w.set_port(cc.p_channel.port());
170 w.set_pin(cc.p_channel.pin());
171 w.set_internal(cc.p_channel.internal());
172 w.set_connect(cc.p_channel.connect());
173 });
174 if let Some(n_channel) = &cc.n_channel {
175 #[cfg(not(feature = "_nrf54l"))]
176 r.ch(i).pseln().write(|w| w.set_pseln(n_channel.channel()));
177 #[cfg(feature = "_nrf54l")]
178 r.ch(i).pseln().write(|w| {
179 w.set_port(n_channel.port());
180 w.set_pin(n_channel.pin());
181 w.set_connect(n_channel.connect().to_bits().into());
182 });
183 }
184 r.ch(i).config().write(|w| {
185 w.set_refsel(cc.reference.into());
186 w.set_gain(cc.gain.into());
187 w.set_tacq(cc.time.into());
188 #[cfg(feature = "_nrf54l")]
189 w.set_tconv(7); w.set_mode(match cc.n_channel {
191 None => vals::ConfigMode::SE,
192 Some(_) => vals::ConfigMode::DIFF,
193 });
194 #[cfg(not(feature = "_nrf54l"))]
195 w.set_resp(cc.resistor.into());
196 #[cfg(not(feature = "_nrf54l"))]
197 w.set_resn(vals::Resn::BYPASS);
198 #[cfg(not(feature = "_nrf54l"))]
199 w.set_burst(!matches!(oversample, Oversample::BYPASS));
200 });
201 }
202
203 r.intenclr().write(|w| w.0 = 0x003F_FFFF);
205
206 interrupt::SAADC.unpend();
207 unsafe { interrupt::SAADC.enable() };
208
209 Self { _p: saadc }
210 }
211
212 fn regs() -> pac::saadc::Saadc {
213 pac::SAADC
214 }
215
216 pub async fn calibrate(&self) {
218 let r = Self::regs();
219
220 r.events_calibratedone().write_value(0);
222 r.intenset().write(|w| w.set_calibratedone(true));
223
224 compiler_fence(Ordering::SeqCst);
226
227 r.tasks_calibrateoffset().write_value(1);
228
229 poll_fn(|cx| {
231 let r = Self::regs();
232
233 WAKER.register(cx.waker());
234
235 if r.events_calibratedone().read() != 0 {
236 r.events_calibratedone().write_value(0);
237 return Poll::Ready(());
238 }
239
240 Poll::Pending
241 })
242 .await;
243 }
244
245 pub async fn sample(&mut self, buf: &mut [i16; N]) {
250 let on_drop = OnDrop::new(Self::stop_sampling_immediately);
252
253 let r = Self::regs();
254
255 r.result().ptr().write_value(buf.as_mut_ptr() as u32);
257 r.result().maxcnt().write(|w| w.set_maxcnt((N * CNT_UNIT) as _));
258
259 r.events_end().write_value(0);
261 r.intenset().write(|w| w.set_end(true));
262
263 compiler_fence(Ordering::SeqCst);
266
267 r.tasks_start().write_value(1);
268 r.tasks_sample().write_value(1);
269
270 poll_fn(|cx| {
272 let r = Self::regs();
273
274 WAKER.register(cx.waker());
275
276 if r.events_end().read() != 0 {
277 r.events_end().write_value(0);
278 return Poll::Ready(());
279 }
280
281 Poll::Pending
282 })
283 .await;
284
285 drop(on_drop);
286 }
287
288 pub async fn run_task_sampler<F, T: TimerInstance, const N0: usize>(
312 &mut self,
313 timer: Peri<'_, T>,
314 ppi_ch1: Peri<'_, impl ConfigurableChannel>,
315 ppi_ch2: Peri<'_, impl ConfigurableChannel>,
316 frequency: Frequency,
317 sample_counter: u32,
318 bufs: &mut [[[i16; N]; N0]; 2],
319 callback: F,
320 ) where
321 F: FnMut(&[[i16; N]]) -> CallbackResult,
322 {
323 let r = Self::regs();
324
325 let mut start_ppi = Ppi::new_one_to_one(
329 ppi_ch1,
330 Event::from_reg(r.events_end()),
331 Task::from_reg(r.tasks_start()),
332 );
333 start_ppi.enable();
334
335 let timer = Timer::new(timer);
336 timer.set_frequency(frequency);
337 timer.cc(0).write(sample_counter);
338 timer.cc(0).short_compare_clear();
339
340 let timer_cc = timer.cc(0);
341
342 let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer_cc.event_compare(), Task::from_reg(r.tasks_sample()));
343
344 timer.start();
345
346 self.run_sampler(
347 bufs,
348 None,
349 || {
350 sample_ppi.enable();
351 },
352 callback,
353 )
354 .await;
355 }
356
357 async fn run_sampler<I, F, const N0: usize>(
358 &mut self,
359 bufs: &mut [[[i16; N]; N0]; 2],
360 sample_rate_divisor: Option<u16>,
361 mut init: I,
362 mut callback: F,
363 ) where
364 I: FnMut(),
365 F: FnMut(&[[i16; N]]) -> CallbackResult,
366 {
367 let on_drop = OnDrop::new(Self::stop_sampling_immediately);
369
370 let r = Self::regs();
371
372 match sample_rate_divisor {
374 Some(sr) => {
375 r.samplerate().write(|w| {
376 w.set_cc(sr);
377 w.set_mode(vals::SamplerateMode::TIMERS);
378 });
379 r.tasks_sample().write_value(1); }
381 None => r.samplerate().write(|w| {
382 w.set_cc(0);
383 w.set_mode(vals::SamplerateMode::TASK);
384 }),
385 }
386
387 r.result().ptr().write_value(bufs[0].as_mut_ptr() as u32);
389 r.result().maxcnt().write(|w| w.set_maxcnt((N0 * N * CNT_UNIT) as _));
390
391 r.events_end().write_value(0);
393 r.events_started().write_value(0);
394 r.intenset().write(|w| {
395 w.set_end(true);
396 w.set_started(true);
397 });
398
399 compiler_fence(Ordering::SeqCst);
402
403 r.tasks_start().write_value(1);
404
405 let mut inited = false;
406 let mut current_buffer = 0;
407
408 let r = poll_fn(|cx| {
410 let r = Self::regs();
411
412 WAKER.register(cx.waker());
413
414 if r.events_end().read() != 0 {
415 compiler_fence(Ordering::SeqCst);
416
417 r.events_end().write_value(0);
418 r.intenset().write(|w| w.set_end(true));
419
420 match callback(&bufs[current_buffer]) {
421 CallbackResult::Continue => {
422 let next_buffer = 1 - current_buffer;
423 current_buffer = next_buffer;
424 }
425 CallbackResult::Stop => {
426 return Poll::Ready(());
427 }
428 }
429 }
430
431 if r.events_started().read() != 0 {
432 r.events_started().write_value(0);
433 r.intenset().write(|w| w.set_started(true));
434
435 if !inited {
436 init();
437 inited = true;
438 }
439
440 let next_buffer = 1 - current_buffer;
441 r.result().ptr().write_value(bufs[next_buffer].as_mut_ptr() as u32);
442 }
443
444 Poll::Pending
445 })
446 .await;
447
448 drop(on_drop);
449
450 r
451 }
452
453 fn stop_sampling_immediately() {
455 let r = Self::regs();
456
457 compiler_fence(Ordering::SeqCst);
458
459 r.events_stopped().write_value(0);
460 r.tasks_stop().write_value(1);
461
462 while r.events_stopped().read() == 0 {}
463 r.events_stopped().write_value(0);
464 }
465}
466
467impl<'d> Saadc<'d, 1> {
468 pub async fn run_timer_sampler<I, S, const N0: usize>(
479 &mut self,
480 bufs: &mut [[[i16; 1]; N0]; 2],
481 sample_rate_divisor: u16,
482 sampler: S,
483 ) where
484 S: FnMut(&[[i16; 1]]) -> CallbackResult,
485 {
486 self.run_sampler(bufs, Some(sample_rate_divisor), || {}, sampler).await;
487 }
488}
489
490impl<'d, const N: usize> Drop for Saadc<'d, N> {
491 fn drop(&mut self) {
492 #[cfg(feature = "_nrf52")]
500 {
501 unsafe { core::ptr::write_volatile(0x40007FFC as *mut u32, 0) }
502 unsafe { core::ptr::read_volatile(0x40007FFC as *const ()) }
503 unsafe { core::ptr::write_volatile(0x40007FFC as *mut u32, 1) }
504 }
505 let r = Self::regs();
506 r.enable().write(|w| w.set_enable(false));
507 for i in 0..N {
508 #[cfg(not(feature = "_nrf54l"))]
509 {
510 r.ch(i).pselp().write(|w| w.set_pselp(InputChannel::NC));
511 r.ch(i).pseln().write(|w| w.set_pseln(InputChannel::NC));
512 }
513 #[cfg(feature = "_nrf54l")]
514 {
515 r.ch(i).pselp().write(|w| w.set_connect(vals::PselpConnect::NC));
516 r.ch(i).pseln().write(|w| w.set_connect(vals::PselnConnect::NC));
517 }
518 }
519 }
520}
521
522#[cfg(not(feature = "_nrf54l"))]
523impl From<Gain> for vals::Gain {
524 fn from(gain: Gain) -> Self {
525 match gain {
526 Gain::GAIN1_6 => vals::Gain::GAIN1_6,
527 Gain::GAIN1_5 => vals::Gain::GAIN1_5,
528 Gain::GAIN1_4 => vals::Gain::GAIN1_4,
529 Gain::GAIN1_3 => vals::Gain::GAIN1_3,
530 Gain::GAIN1_2 => vals::Gain::GAIN1_2,
531 Gain::GAIN1 => vals::Gain::GAIN1,
532 Gain::GAIN2 => vals::Gain::GAIN2,
533 Gain::GAIN4 => vals::Gain::GAIN4,
534 }
535 }
536}
537
538#[cfg(feature = "_nrf54l")]
539impl From<Gain> for vals::Gain {
540 fn from(gain: Gain) -> Self {
541 match gain {
542 Gain::GAIN2_8 => vals::Gain::GAIN2_8,
543 Gain::GAIN2_7 => vals::Gain::GAIN2_7,
544 Gain::GAIN2_6 => vals::Gain::GAIN2_6,
545 Gain::GAIN2_5 => vals::Gain::GAIN2_5,
546 Gain::GAIN2_4 => vals::Gain::GAIN2_4,
547 Gain::GAIN2_3 => vals::Gain::GAIN2_3,
548 Gain::GAIN1 => vals::Gain::GAIN1,
549 Gain::GAIN2 => vals::Gain::GAIN2,
550 }
551 }
552}
553
554#[cfg(not(feature = "_nrf54l"))]
556#[non_exhaustive]
557#[derive(Clone, Copy)]
558pub enum Gain {
559 GAIN1_6 = 0,
561 GAIN1_5 = 1,
563 GAIN1_4 = 2,
565 GAIN1_3 = 3,
567 GAIN1_2 = 4,
569 GAIN1 = 5,
571 GAIN2 = 6,
573 GAIN4 = 7,
575}
576
577#[cfg(feature = "_nrf54l")]
579#[non_exhaustive]
580#[derive(Clone, Copy)]
581pub enum Gain {
582 GAIN2_8 = 0,
584 GAIN2_7 = 1,
586 GAIN2_6 = 2,
588 GAIN2_5 = 3,
590 GAIN2_4 = 4,
592 GAIN2_3 = 5,
594 GAIN1 = 6,
596 GAIN2 = 7,
598}
599
600impl From<Reference> for vals::Refsel {
601 fn from(reference: Reference) -> Self {
602 match reference {
603 Reference::INTERNAL => vals::Refsel::INTERNAL,
604 #[cfg(not(feature = "_nrf54l"))]
605 Reference::VDD1_4 => vals::Refsel::VDD1_4,
606 #[cfg(feature = "_nrf54l")]
607 Reference::EXTERNAL => vals::Refsel::EXTERNAL,
608 }
609 }
610}
611
612#[non_exhaustive]
614#[derive(Clone, Copy)]
615pub enum Reference {
616 INTERNAL = 0,
618 #[cfg(not(feature = "_nrf54l"))]
619 VDD1_4 = 1,
621 #[cfg(feature = "_nrf54l")]
623 EXTERNAL = 1,
624}
625
626#[cfg(not(feature = "_nrf54l"))]
627impl From<Resistor> for vals::Resp {
628 fn from(resistor: Resistor) -> Self {
629 match resistor {
630 Resistor::BYPASS => vals::Resp::BYPASS,
631 Resistor::PULLDOWN => vals::Resp::PULLDOWN,
632 Resistor::PULLUP => vals::Resp::PULLUP,
633 Resistor::VDD1_2 => vals::Resp::VDD1_2,
634 }
635 }
636}
637
638#[non_exhaustive]
640#[derive(Clone, Copy)]
641#[cfg(not(feature = "_nrf54l"))]
642pub enum Resistor {
643 BYPASS = 0,
645 PULLDOWN = 1,
647 PULLUP = 2,
649 VDD1_2 = 3,
651}
652
653#[cfg(not(feature = "_nrf54l"))]
654impl From<Time> for vals::Tacq {
655 fn from(time: Time) -> Self {
656 match time {
657 Time::_3US => vals::Tacq::_3US,
658 Time::_5US => vals::Tacq::_5US,
659 Time::_10US => vals::Tacq::_10US,
660 Time::_15US => vals::Tacq::_15US,
661 Time::_20US => vals::Tacq::_20US,
662 Time::_40US => vals::Tacq::_40US,
663 }
664 }
665}
666
667#[cfg(feature = "_nrf54l")]
668impl From<Time> for u16 {
669 fn from(time: Time) -> Self {
670 match time {
671 Time::_3US => (3000 / 125) - 1,
672 Time::_5US => (5000 / 125) - 1,
673 Time::_10US => (10000 / 125) - 1,
674 Time::_15US => (15000 / 125) - 1,
675 Time::_20US => (20000 / 125) - 1,
676 Time::_40US => (40000 / 125) - 1,
677 }
678 }
679}
680
681#[non_exhaustive]
683#[derive(Clone, Copy)]
684pub enum Time {
685 _3US = 0,
687 _5US = 1,
689 _10US = 2,
691 _15US = 3,
693 _20US = 4,
695 _40US = 5,
697}
698
699impl From<Oversample> for vals::Oversample {
700 fn from(oversample: Oversample) -> Self {
701 match oversample {
702 Oversample::BYPASS => vals::Oversample::BYPASS,
703 Oversample::OVER2X => vals::Oversample::OVER2X,
704 Oversample::OVER4X => vals::Oversample::OVER4X,
705 Oversample::OVER8X => vals::Oversample::OVER8X,
706 Oversample::OVER16X => vals::Oversample::OVER16X,
707 Oversample::OVER32X => vals::Oversample::OVER32X,
708 Oversample::OVER64X => vals::Oversample::OVER64X,
709 Oversample::OVER128X => vals::Oversample::OVER128X,
710 Oversample::OVER256X => vals::Oversample::OVER256X,
711 }
712 }
713}
714
715#[non_exhaustive]
717#[derive(Clone, Copy)]
718pub enum Oversample {
719 BYPASS = 0,
721 OVER2X = 1,
723 OVER4X = 2,
725 OVER8X = 3,
727 OVER16X = 4,
729 OVER32X = 5,
731 OVER64X = 6,
733 OVER128X = 7,
735 OVER256X = 8,
737}
738
739impl From<Resolution> for vals::Val {
740 fn from(resolution: Resolution) -> Self {
741 match resolution {
742 Resolution::_8BIT => vals::Val::_8BIT,
743 Resolution::_10BIT => vals::Val::_10BIT,
744 Resolution::_12BIT => vals::Val::_12BIT,
745 Resolution::_14BIT => vals::Val::_14BIT,
746 }
747 }
748}
749
750#[non_exhaustive]
752#[derive(Clone, Copy)]
753pub enum Resolution {
754 _8BIT = 0,
756 _10BIT = 1,
758 _12BIT = 2,
760 _14BIT = 3,
762}
763
764pub(crate) trait SealedInput {
765 #[cfg(not(feature = "_nrf54l"))]
766 fn channel(&self) -> InputChannel;
767
768 #[cfg(feature = "_nrf54l")]
769 fn pin(&self) -> u8;
770
771 #[cfg(feature = "_nrf54l")]
772 fn port(&self) -> u8;
773
774 #[cfg(feature = "_nrf54l")]
775 fn internal(&self) -> vals::PselpInternal;
776
777 #[cfg(feature = "_nrf54l")]
778 fn connect(&self) -> vals::PselpConnect;
779}
780
781#[allow(private_bounds)]
783pub trait Input: SealedInput + Sized {
784 #[cfg(not(feature = "_nrf54l"))]
789 fn degrade_saadc<'a>(self) -> AnyInput<'a>
790 where
791 Self: 'a,
792 {
793 AnyInput {
794 channel: self.channel(),
795 _phantom: core::marker::PhantomData,
796 }
797 }
798
799 #[cfg(feature = "_nrf54l")]
804 fn degrade_saadc<'a>(self) -> AnyInput<'a>
805 where
806 Self: 'a,
807 {
808 AnyInput {
809 pin: self.pin(),
810 port: self.port(),
811 internal: self.internal(),
812 connect: self.connect(),
813 _phantom: core::marker::PhantomData,
814 }
815 }
816}
817
818#[cfg(not(feature = "_nrf54l"))]
823pub struct AnyInput<'a> {
824 channel: InputChannel,
825 _phantom: PhantomData<&'a ()>,
826}
827
828#[cfg(feature = "_nrf54l")]
833pub struct AnyInput<'a> {
834 pin: u8,
835 port: u8,
836 internal: vals::PselpInternal,
837 connect: vals::PselpConnect,
838 _phantom: PhantomData<&'a ()>,
839}
840
841impl<'a> AnyInput<'a> {
842 pub fn reborrow(&mut self) -> AnyInput<'_> {
846 #[cfg(not(feature = "_nrf54l"))]
849 {
850 Self {
851 channel: self.channel,
852 _phantom: PhantomData,
853 }
854 }
855 #[cfg(feature = "_nrf54l")]
856 {
857 Self {
858 pin: self.pin,
859 port: self.port,
860 internal: self.internal,
861 connect: self.connect,
862 _phantom: PhantomData,
863 }
864 }
865 }
866}
867
868impl SealedInput for AnyInput<'_> {
869 #[cfg(not(feature = "_nrf54l"))]
870 fn channel(&self) -> InputChannel {
871 self.channel
872 }
873
874 #[cfg(feature = "_nrf54l")]
875 fn pin(&self) -> u8 {
876 self.pin
877 }
878
879 #[cfg(feature = "_nrf54l")]
880 fn port(&self) -> u8 {
881 self.port
882 }
883
884 #[cfg(feature = "_nrf54l")]
885 fn internal(&self) -> vals::PselpInternal {
886 self.internal
887 }
888
889 #[cfg(feature = "_nrf54l")]
890 fn connect(&self) -> vals::PselpConnect {
891 self.connect
892 }
893}
894
895impl Input for AnyInput<'_> {}
896
897#[cfg(not(feature = "_nrf54l"))]
898macro_rules! impl_saadc_input {
899 ($pin:ident, $ch:ident) => {
900 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $ch);
901 };
902 (@local, $pin:ty, $ch:ident) => {
903 impl crate::saadc::SealedInput for $pin {
904 fn channel(&self) -> crate::saadc::InputChannel {
905 crate::saadc::InputChannel::$ch
906 }
907 }
908 impl crate::saadc::Input for $pin {}
909 };
910}
911
912#[cfg(feature = "_nrf54l")]
913macro_rules! impl_saadc_input {
914 ($pin:ident, $port:expr, $ain:expr) => {
915 impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $port, $ain, AVDD, ANALOG_INPUT);
916 };
917 (@local, $pin:ty, $port:expr, $ain:expr, $internal:ident, $connect:ident) => {
918 impl crate::saadc::SealedInput for $pin {
919 fn pin(&self) -> u8 {
920 $ain
921 }
922
923 fn port(&self) -> u8 {
924 $port
925 }
926
927 fn internal(&self) -> crate::pac::saadc::vals::PselpInternal {
928 crate::pac::saadc::vals::PselpInternal::$internal
929 }
930
931 fn connect(&self) -> crate::pac::saadc::vals::PselpConnect {
932 crate::pac::saadc::vals::PselpConnect::$connect
933 }
934 }
935 impl crate::saadc::Input for $pin {}
936 };
937}
938
939pub struct VddInput;
942
943impl_peripheral!(VddInput);
944#[cfg(not(feature = "_nrf54l"))]
945#[cfg(not(feature = "_nrf91"))]
946impl_saadc_input!(@local, VddInput, VDD);
947#[cfg(feature = "_nrf91")]
948impl_saadc_input!(@local, VddInput, VDD_GPIO);
949#[cfg(feature = "_nrf54l")]
950impl_saadc_input!(@local, VddInput, 0, 0, VDD, INTERNAL);
951
952#[cfg(any(feature = "_nrf5340-app", feature = "nrf52833", feature = "nrf52840"))]
955pub struct VddhDiv5Input;
956
957#[cfg(any(feature = "_nrf5340-app", feature = "nrf52833", feature = "nrf52840"))]
958impl_peripheral!(VddhDiv5Input);
959
960#[cfg(any(feature = "_nrf5340-app", feature = "nrf52833", feature = "nrf52840"))]
961impl_saadc_input!(@local, VddhDiv5Input, VDDHDIV5);
962
963#[cfg(feature = "_nrf54l")]
966pub struct AVddInput;
967#[cfg(feature = "_nrf54l")]
968embassy_hal_internal::impl_peripheral!(AVddInput);
969#[cfg(feature = "_nrf54l")]
970impl_saadc_input!(@local, AVddInput, 0, 0, AVDD, INTERNAL);
971
972#[cfg(feature = "_nrf54l")]
975pub struct DVddInput;
976#[cfg(feature = "_nrf54l")]
977embassy_hal_internal::impl_peripheral!(DVddInput);
978#[cfg(feature = "_nrf54l")]
979impl_saadc_input!(@local, DVddInput, 0, 0, DVDD, INTERNAL);