Repo for designs & driver for a TA7642 powered lightning detector
1#[cfg(any(feature = "rp2040", feature = "rp235xa", feature = "rp235xb"))]
2pub mod rp {
3 use embassy_rp::{
4 Peri,
5 adc::{self, Adc, AdcPin, Async, InterruptHandler},
6 dma,
7 interrupt::typelevel::{ADC_IRQ_FIFO, Binding},
8 peripherals::ADC,
9 pwm::{self, ChannelBPin, Pwm, SetDutyCycle, Slice},
10 };
11 use embassy_sync::{blocking_mutex::raw::RawMutex, mutex::Mutex};
12
13 use crate::traits::{AdcSource, PwmSource};
14
15 struct AdcInner<'device, T: dma::Channel> {
16 adc: Adc<'device, Async>,
17 pin: adc::Channel<'device>,
18 dma: Peri<'device, T>,
19 }
20
21 pub struct AdcDriver<'device, M: RawMutex, T: dma::Channel> {
22 inner: Mutex<M, AdcInner<'device, T>>,
23 }
24
25 impl<T: dma::Channel> AdcInner<'_, T> {
26 /// Samples at 100Khz, or 10us per sample. If a sampling fails due to conversion error,
27 /// it tries again until the sampling succeeds.
28 async fn read_many(&mut self, buf: &mut [u16]) {
29 let mut retries: u32 = 5;
30
31 while self
32 .adc
33 .read_many(&mut self.pin, buf, 480, self.dma.reborrow())
34 .await
35 .is_err()
36 {
37 retries -= 1;
38
39 if retries == 0 {
40 panic!("ADC not configured or connected correctly.");
41 }
42 }
43 }
44 }
45
46 impl<'device, M: RawMutex, T: dma::Channel> AdcDriver<'device, M, T> {
47 pub fn new(
48 inner: Peri<'device, ADC>,
49 pin: Peri<'device, impl AdcPin + 'device>,
50 dma: Peri<'device, T>,
51 irqs: impl Binding<ADC_IRQ_FIFO, InterruptHandler>,
52 ) -> Self {
53 Self {
54 inner: Mutex::new(AdcInner {
55 adc: Adc::new(inner, irqs, adc::Config::default()),
56 pin: adc::Channel::new_pin(pin, embassy_rp::gpio::Pull::None),
57 dma,
58 }),
59 }
60 }
61 }
62
63 impl<'device, M: RawMutex, T: dma::Channel> AdcSource for AdcDriver<'device, M, T> {
64 async fn sample_average(&self, samples: &mut [u16]) -> u16 {
65 self.sample(samples).await;
66
67 let len = samples.len() as u32;
68
69 (samples.iter().copied().map(u32::from).sum::<u32>() / len) as u16
70 }
71
72 async fn sample(&self, samples: &mut [u16]) {
73 self.inner.lock().await.read_many(samples).await;
74 }
75 }
76
77 pub struct PwmDriver<'device> {
78 config: pwm::Config,
79 pwm: Pwm<'device>,
80 }
81
82 impl<'device> PwmDriver<'device> {
83 pub fn new<T>(slice: Peri<'device, T>, b: Peri<'device, impl ChannelBPin<T>>) -> Self
84 where
85 T: Slice,
86 {
87 let mut config = pwm::Config::default();
88 config.top = u8::MAX as u16;
89 config.phase_correct = true;
90 config.divider = 48u8.into();
91 config.enable = true;
92 config.compare_b = 0;
93 let pwm = Pwm::new_output_b(slice, b, config.clone());
94
95 Self { pwm, config }
96 }
97 }
98
99 impl PwmSource for PwmDriver<'_> {
100 fn max_duty(&self) -> u16 {
101 self.pwm.max_duty_cycle()
102 }
103
104 fn set_duty(&mut self, duty: u16) {
105 let duty = duty.clamp(0, self.pwm.max_duty_cycle());
106
107 self.pwm.set_duty_cycle(duty).ok();
108 }
109
110 fn enable(&mut self) {
111 self.config.enable = true;
112 self.pwm.set_config(&self.config);
113 }
114
115 fn disable(&mut self) {
116 self.config.enable = false;
117 self.pwm.set_config(&self.config);
118 }
119 }
120
121 impl Drop for PwmDriver<'_> {
122 fn drop(&mut self) {
123 self.disable();
124 }
125 }
126}