A RPi Pico powered Lightning Detector
at main 1.8 kB view raw
1use embassy_rp::{ 2 Peri, 3 adc::{self, Adc, AdcPin, Async, Config}, 4 dma, 5 peripherals::ADC, 6}; 7use embassy_sync::{blocking_mutex::raw::RawMutex, mutex::Mutex}; 8 9use crate::Irqs; 10 11struct AdcInner<'device, T: dma::Channel> { 12 adc: Adc<'device, Async>, 13 pin: adc::Channel<'device>, 14 dma: Peri<'device, T>, 15} 16 17pub struct AdcDriver<'device, M: RawMutex, T: dma::Channel> { 18 inner: Mutex<M, AdcInner<'device, T>>, 19} 20 21impl<T: dma::Channel> AdcInner<'_, T> { 22 /// Samples at 100Khz, or 10us per sample. If a sampling fails due to conversion error, 23 /// it tries again until the sampling succeeds. 24 async fn read_many(&mut self, buf: &mut [u16]) { 25 while self 26 .adc 27 .read_many(&mut self.pin, buf, 480, self.dma.reborrow()) 28 .await 29 .is_err() 30 {} 31 } 32} 33 34impl<'device, M: RawMutex, T: dma::Channel> AdcDriver<'device, M, T> { 35 pub fn new( 36 inner: Peri<'device, ADC>, 37 pin: Peri<'device, impl AdcPin + 'device>, 38 dma: Peri<'device, T>, 39 ) -> Self { 40 Self { 41 inner: Mutex::new(AdcInner { 42 adc: Adc::new(inner, Irqs, Config::default()), 43 pin: adc::Channel::new_pin(pin, embassy_rp::gpio::Pull::None), 44 dma, 45 }), 46 } 47 } 48 49 /// Samples at 100Khz, or 10us per sample. If a sampling fails due to conversion error, 50 /// it tries again until the sampling succeeds. 51 pub async fn sample(&self, buf: &mut [u16]) { 52 // Gain a lock to the inner ADC state, then do a read. 53 self.inner.lock().await.read_many(buf).await; 54 } 55 56 pub async fn sample_average(&self, buf: &mut [u16]) -> u16 { 57 self.sample(buf).await; 58 59 let len = buf.len() as u32; 60 61 (buf.iter().copied().map(u32::from).sum::<u32>() / len) as u16 62 } 63}