From 3ebfbc44c333a04f8b76453862913fd749828f34 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 13 Sep 2022 08:41:04 +0200 Subject: [PATCH] ADC: Add compile time check for using unconfigured PIN, add AdcPin wrapper around PIN --- esp-hal-common/src/analog/adc/esp32.rs | 42 +++++++++++++++++------- esp-hal-common/src/analog/adc/esp32c3.rs | 38 ++++++++++++++++----- esp-hal-common/src/analog/adc/esp32s2.rs | 41 +++++++++++++++++------ esp32-hal/examples/adc.rs | 3 +- esp32c3-hal/examples/adc.rs | 13 ++++---- esp32s2-hal/examples/adc.rs | 7 ++-- 6 files changed, 103 insertions(+), 41 deletions(-) diff --git a/esp-hal-common/src/analog/adc/esp32.rs b/esp-hal-common/src/analog/adc/esp32.rs index 55afbb1ef..b1c6a415f 100644 --- a/esp-hal-common/src/analog/adc/esp32.rs +++ b/esp-hal-common/src/analog/adc/esp32.rs @@ -16,7 +16,6 @@ pub enum Resolution { Resolution12Bit = 0b11, } -/// The attenuation of the ADC pin #[derive(PartialEq, Eq, Clone, Copy)] pub enum Attenuation { Attenuation0dB = 0b00, @@ -25,6 +24,19 @@ pub enum Attenuation { Attenuation11dB = 0b11, } +pub struct AdcPin { + pub pin: PIN, + _phantom: PhantomData, +} + +impl, ADCI> Channel for AdcPin { + type ID = u8; + + fn channel() -> Self::ID { + PIN::channel() + } +} + pub struct AdcConfig { pub resolution: Resolution, pub attenuations: [Option; 10], @@ -41,10 +53,15 @@ where pub fn enable_pin>( &mut self, - _pin: &PIN, + pin: PIN, attenuation: Attenuation, - ) { + ) -> AdcPin { self.attenuations[PIN::channel() as usize] = Some(attenuation); + + AdcPin { + pin, + _phantom: PhantomData::default(), + } } } @@ -330,7 +347,7 @@ impl ADC { } } -impl OneShot for ADC +impl OneShot> for ADC where WORD: From, PIN: Channel, @@ -338,23 +355,26 @@ where { type Error = (); - fn read(&mut self, _pin: &mut PIN) -> nb::Result { - if self.attenuations[PIN::channel() as usize] == None { - panic!("Channel {} is not configured reading!", PIN::channel()); + fn read(&mut self, _pin: &mut AdcPin) -> nb::Result { + if self.attenuations[AdcPin::::channel() as usize] == None { + panic!( + "Channel {} is not configured reading!", + AdcPin::::channel() + ); } if let Some(active_channel) = self.active_channel { // There is conversion in progress: // - if it's for a different channel try again later - // - if it's for the given channel, go ahaid and check progress - if active_channel != PIN::channel() { + // - if it's for the given channel, go ahead and check progress + if active_channel != AdcPin::::channel() { return Err(nb::Error::WouldBlock); } } else { // If no conversions are in progress, start a new one for given channel - self.active_channel = Some(PIN::channel()); + self.active_channel = Some(AdcPin::::channel()); - ADCI::set_en_pad(PIN::channel() as u8); + ADCI::set_en_pad(AdcPin::::channel() as u8); ADCI::clear_start_sar(); ADCI::set_start_sar(); diff --git a/esp-hal-common/src/analog/adc/esp32c3.rs b/esp-hal-common/src/analog/adc/esp32c3.rs index 156b6c938..d849ef421 100644 --- a/esp-hal-common/src/analog/adc/esp32c3.rs +++ b/esp-hal-common/src/analog/adc/esp32c3.rs @@ -23,6 +23,18 @@ pub enum Attenuation { Attenuation11dB = 0b11, } +pub struct AdcPin { + pub pin: PIN, + _phantom: PhantomData, +} + +impl, ADCI> Channel for AdcPin { + type ID = u8; + + fn channel() -> Self::ID { + PIN::channel() + } +} pub struct AdcConfig { pub resolution: Resolution, pub attenuations: [Option; 5], @@ -39,10 +51,15 @@ where pub fn enable_pin>( &mut self, - _pin: &PIN, + pin: PIN, attenuation: Attenuation, - ) { + ) -> AdcPin { self.attenuations[PIN::channel() as usize] = Some(attenuation); + + AdcPin { + pin, + _phantom: PhantomData::default(), + } } } @@ -187,7 +204,7 @@ where } } -impl OneShot for ADC +impl OneShot> for ADC where WORD: From, PIN: Channel, @@ -195,21 +212,24 @@ where { type Error = (); - fn read(&mut self, _pin: &mut PIN) -> nb::Result { - if self.attenuations[PIN::channel() as usize] == None { - panic!("Channel {} is not configured reading!", PIN::channel()); + fn read(&mut self, _pin: &mut AdcPin) -> nb::Result { + if self.attenuations[AdcPin::::channel() as usize] == None { + panic!( + "Channel {} is not configured reading!", + AdcPin::::channel() + ); } if let Some(active_channel) = self.active_channel { // There is conversion in progress: // - if it's for a different channel try again later - // - if it's for the given channel, go ahaid and check progress - if active_channel != PIN::channel() { + // - if it's for the given channel, go ahead and check progress + if active_channel != AdcPin::::channel() { return Err(nb::Error::WouldBlock); } } else { // If no conversions are in progress, start a new one for given channel - self.active_channel = Some(PIN::channel()); + self.active_channel = Some(AdcPin::::channel()); let channel = self.active_channel.unwrap(); let attenuation = self.attenuations[channel as usize].unwrap() as u8; diff --git a/esp-hal-common/src/analog/adc/esp32s2.rs b/esp-hal-common/src/analog/adc/esp32s2.rs index d94e56ae8..2d6e5b36a 100644 --- a/esp-hal-common/src/analog/adc/esp32s2.rs +++ b/esp-hal-common/src/analog/adc/esp32s2.rs @@ -22,6 +22,19 @@ pub enum Attenuation { Attenuation11dB = 0b11, } +pub struct AdcPin { + pub pin: PIN, + _phantom: PhantomData, +} + +impl, ADCI> Channel for AdcPin { + type ID = u8; + + fn channel() -> Self::ID { + PIN::channel() + } +} + pub struct AdcConfig { pub resolution: Resolution, pub attenuations: [Option; 10], @@ -38,10 +51,15 @@ where pub fn enable_pin>( &mut self, - _pin: &PIN, + pin: PIN, attenuation: Attenuation, - ) { + ) -> AdcPin { self.attenuations[PIN::channel() as usize] = Some(attenuation); + + AdcPin { + pin, + _phantom: PhantomData::default(), + } } } @@ -314,7 +332,7 @@ where } } -impl OneShot for ADC +impl OneShot> for ADC where WORD: From, PIN: Channel, @@ -322,23 +340,26 @@ where { type Error = (); - fn read(&mut self, _pin: &mut PIN) -> nb::Result { - if self.attenuations[PIN::channel() as usize] == None { - panic!("Channel {} is not configured reading!", PIN::channel()); + fn read(&mut self, _pin: &mut AdcPin) -> nb::Result { + if self.attenuations[AdcPin::::channel() as usize] == None { + panic!( + "Channel {} is not configured reading!", + AdcPin::::channel() + ); } if let Some(active_channel) = self.active_channel { // There is conversion in progress: // - if it's for a different channel try again later - // - if it's for the given channel, go ahaid and check progress - if active_channel != PIN::channel() { + // - if it's for the given channel, go ahead and check progress + if active_channel != AdcPin::::channel() { return Err(nb::Error::WouldBlock); } } else { // If no conversions are in progress, start a new one for given channel - self.active_channel = Some(PIN::channel()); + self.active_channel = Some(AdcPin::::channel()); - ADCI::set_en_pad(PIN::channel() as u8); + ADCI::set_en_pad(AdcPin::::channel() as u8); ADCI::clear_start_sar(); ADCI::set_start_sar(); diff --git a/esp32-hal/examples/adc.rs b/esp32-hal/examples/adc.rs index d04c3a0e0..336df7b69 100644 --- a/esp32-hal/examples/adc.rs +++ b/esp32-hal/examples/adc.rs @@ -34,13 +34,12 @@ fn main() -> ! { rtc.rwdt.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let mut pin25 = io.pins.gpio25.into_analog(); // Create ADC instances let analog = peripherals.SENS.split(); let mut adc2_config = AdcConfig::new(); - adc2_config.enable_pin(&pin25, Attenuation::Attenuation11dB); + let mut pin25 = adc2_config.enable_pin(io.pins.gpio25.into_analog(), Attenuation::Attenuation11dB); let mut adc2 = ADC::::adc(analog.adc2, adc2_config).unwrap(); let mut delay = Delay::new(&clocks); diff --git a/esp32c3-hal/examples/adc.rs b/esp32c3-hal/examples/adc.rs index a01c66a73..5f68b1cca 100644 --- a/esp32c3-hal/examples/adc.rs +++ b/esp32c3-hal/examples/adc.rs @@ -41,24 +41,25 @@ fn main() -> ! { wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let mut pin = io.pins.gpio2.into_analog(); // Create ADC instances let analog = peripherals.APB_SARADC.split(); - let mut adc2_config = AdcConfig::new(); - adc2_config.enable_pin(&pin, Attenuation::Attenuation11dB); - let mut adc2 = ADC::::adc( + let mut adc1_config = AdcConfig::new(); + + let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); + + let mut adc1 = ADC::::adc( &mut system.peripheral_clock_control, analog.adc1, - adc2_config, + adc1_config, ) .unwrap(); let mut delay = Delay::new(&clocks); loop { - let pin_value: u16 = nb::block!(adc2.read(&mut pin)).unwrap(); + let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); println!("PIN ADC reading = {}", pin_value); delay.delay_ms(1500u32); } diff --git a/esp32s2-hal/examples/adc.rs b/esp32s2-hal/examples/adc.rs index f50585e73..b8a818c33 100644 --- a/esp32s2-hal/examples/adc.rs +++ b/esp32s2-hal/examples/adc.rs @@ -34,19 +34,20 @@ fn main() -> ! { rtc.rwdt.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let mut pin3 = io.pins.gpio3.into_analog(); + //let pin3 = io.pins.gpio3.into_analog(); // Create ADC instances let analog = peripherals.SENS.split(); let mut adc1_config = AdcConfig::new(); - adc1_config.enable_pin(&pin3, Attenuation::Attenuation11dB); + + let mut pin3 = adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB); + let mut adc1 = ADC::::adc(analog.adc1, adc1_config).unwrap(); let mut delay = Delay::new(&clocks); loop { - println!("About to read from ADC"); let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap(); println!("PIN3 ADC reading = {}", pin3_value); delay.delay_ms(1500u32);