Repo for designs & driver for a TA7642 powered lightning detector
at main 126 lines 3.8 kB view raw
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}