ADC: Refactor, join S2 and S3 together and C2 and C3 as well (#245)
* ADC: Refactor, join S2 and S3 together and C2 and C3 as well * S3: Update PAC version
This commit is contained in:
parent
a876d8d344
commit
f6ba237e76
@ -49,7 +49,7 @@ esp32 = { version = "0.14.0", features = ["critical-section"], optional = true
|
||||
esp32c2 = { version = "0.3.0", features = ["critical-section"], optional = true }
|
||||
esp32c3 = { version = "0.6.0", features = ["critical-section"], optional = true }
|
||||
esp32s2 = { version = "0.5.0", features = ["critical-section"], optional = true }
|
||||
esp32s3 = { version = "0.5.0", features = ["critical-section"], optional = true }
|
||||
esp32s3 = { version = "0.6.0", features = ["critical-section"], optional = true }
|
||||
|
||||
[features]
|
||||
esp32 = ["esp32/rt" , "procmacros/xtensa", "xtensa-lx-rt/esp32", "xtensa-lx/esp32", "critical-section/restore-state-u32", "lock_api"]
|
||||
|
||||
@ -1,243 +0,0 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use embedded_hal::adc::{Channel, OneShot};
|
||||
|
||||
use crate::{
|
||||
analog::ADC1,
|
||||
pac::APB_SARADC,
|
||||
system::{Peripheral, PeripheralClockControl},
|
||||
};
|
||||
|
||||
/// The sampling/readout resolution of the ADC
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Resolution {
|
||||
Resolution12Bit,
|
||||
}
|
||||
|
||||
/// The attenuation of the ADC pin
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Attenuation {
|
||||
Attenuation0dB = 0b00,
|
||||
Attenuation2p5dB = 0b01,
|
||||
Attenuation6dB = 0b10,
|
||||
Attenuation11dB = 0b11,
|
||||
}
|
||||
|
||||
pub struct AdcPin<PIN, ADCI> {
|
||||
pub pin: PIN,
|
||||
_phantom: PhantomData<ADCI>,
|
||||
}
|
||||
|
||||
impl<PIN: Channel<ADCI, ID = u8>, ADCI> Channel<ADCI> for AdcPin<PIN, ADCI> {
|
||||
type ID = u8;
|
||||
|
||||
fn channel() -> Self::ID {
|
||||
PIN::channel()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AdcConfig<ADCI> {
|
||||
pub resolution: Resolution,
|
||||
pub attenuations: [Option<Attenuation>; 5],
|
||||
_phantom: PhantomData<ADCI>,
|
||||
}
|
||||
|
||||
impl<ADCI> AdcConfig<ADCI>
|
||||
where
|
||||
ADCI: RegisterAccess,
|
||||
{
|
||||
pub fn new() -> AdcConfig<ADCI> {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn enable_pin<PIN: Channel<ADCI, ID = u8>>(
|
||||
&mut self,
|
||||
pin: PIN,
|
||||
attenuation: Attenuation,
|
||||
) -> AdcPin<PIN, ADCI> {
|
||||
self.attenuations[PIN::channel() as usize] = Some(attenuation);
|
||||
|
||||
AdcPin {
|
||||
pin,
|
||||
_phantom: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<ADCI> Default for AdcConfig<ADCI> {
|
||||
fn default() -> Self {
|
||||
AdcConfig {
|
||||
resolution: Resolution::Resolution12Bit,
|
||||
attenuations: [None; 5],
|
||||
_phantom: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait RegisterAccess {
|
||||
fn start_onetime_sample(channel: u8, attenuation: u8);
|
||||
|
||||
fn is_done() -> bool;
|
||||
|
||||
fn read_data() -> u16;
|
||||
|
||||
fn reset();
|
||||
}
|
||||
|
||||
impl RegisterAccess for ADC1 {
|
||||
fn start_onetime_sample(channel: u8, attenuation: u8) {
|
||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||
|
||||
sar_adc.onetime_sample.modify(|_, w| unsafe {
|
||||
w.saradc1_onetime_sample()
|
||||
.set_bit()
|
||||
.saradc_onetime_channel()
|
||||
.bits(channel)
|
||||
.saradc_onetime_atten()
|
||||
.bits(attenuation)
|
||||
.saradc_onetime_start()
|
||||
.set_bit()
|
||||
});
|
||||
}
|
||||
|
||||
fn is_done() -> bool {
|
||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||
|
||||
sar_adc.int_raw.read().apb_saradc1_done_int_raw().bit()
|
||||
}
|
||||
|
||||
fn read_data() -> u16 {
|
||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||
|
||||
(sar_adc.sar1data_status.read().apb_saradc1_data().bits() as u16) & 0xfff
|
||||
}
|
||||
|
||||
fn reset() {
|
||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||
|
||||
sar_adc
|
||||
.int_clr
|
||||
.write(|w| w.apb_saradc1_done_int_clr().set_bit());
|
||||
|
||||
sar_adc
|
||||
.onetime_sample
|
||||
.modify(|_, w| w.saradc_onetime_start().clear_bit());
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ADC<ADC> {
|
||||
adc: PhantomData<ADC>,
|
||||
attenuations: [Option<Attenuation>; 5],
|
||||
active_channel: Option<u8>,
|
||||
}
|
||||
|
||||
impl<ADCI> ADC<ADCI>
|
||||
where
|
||||
ADCI: RegisterAccess,
|
||||
{
|
||||
pub fn adc(
|
||||
peripheral_clock_controller: &mut PeripheralClockControl,
|
||||
_adc_instance: ADCI,
|
||||
config: AdcConfig<ADCI>,
|
||||
) -> Result<Self, ()> {
|
||||
peripheral_clock_controller.enable(Peripheral::ApbSarAdc);
|
||||
|
||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||
sar_adc.ctrl.modify(|_, w| unsafe {
|
||||
w.saradc_start_force()
|
||||
.set_bit()
|
||||
.saradc_start()
|
||||
.set_bit()
|
||||
.saradc_sar_clk_gated()
|
||||
.set_bit()
|
||||
.saradc_xpd_sar_force()
|
||||
.bits(0b11)
|
||||
});
|
||||
let adc = ADC {
|
||||
adc: PhantomData,
|
||||
attenuations: config.attenuations,
|
||||
active_channel: None,
|
||||
};
|
||||
|
||||
Ok(adc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<ADCI, WORD, PIN> OneShot<ADCI, WORD, AdcPin<PIN, ADCI>> for ADC<ADCI>
|
||||
where
|
||||
WORD: From<u16>,
|
||||
PIN: Channel<ADCI, ID = u8>,
|
||||
ADCI: RegisterAccess,
|
||||
{
|
||||
type Error = ();
|
||||
|
||||
fn read(&mut self, _pin: &mut AdcPin<PIN, ADCI>) -> nb::Result<WORD, Self::Error> {
|
||||
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
||||
panic!(
|
||||
"Channel {} is not configured reading!",
|
||||
AdcPin::<PIN, ADCI>::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 ahead and check progress
|
||||
if active_channel != AdcPin::<PIN, ADCI>::channel() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
} else {
|
||||
// If no conversions are in progress, start a new one for given channel
|
||||
self.active_channel = Some(AdcPin::<PIN, ADCI>::channel());
|
||||
|
||||
let channel = self.active_channel.unwrap();
|
||||
let attenuation = self.attenuations[channel as usize].unwrap() as u8;
|
||||
ADCI::start_onetime_sample(channel, attenuation);
|
||||
}
|
||||
|
||||
// Wait for ADC to finish conversion
|
||||
let conversion_finished = ADCI::is_done();
|
||||
if !conversion_finished {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
|
||||
// Get converted value
|
||||
let converted_value = ADCI::read_data();
|
||||
ADCI::reset();
|
||||
|
||||
// There is a hardware limitation. If the APB clock frequency is high, the step
|
||||
// of this reg signal: ``onetime_start`` may not be captured by the
|
||||
// ADC digital controller (when its clock frequency is too slow). A rough
|
||||
// estimate for this step should be at least 3 ADC digital controller
|
||||
// clock cycle.
|
||||
//
|
||||
// This limitation will be removed in hardware future versions.
|
||||
// We reset ``onetime_start`` in `reset` and assume enough time has passed until
|
||||
// the next sample is requested.
|
||||
|
||||
// Mark that no conversions are currently in progress
|
||||
self.active_channel = None;
|
||||
|
||||
Ok(converted_value.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_adc_interface {
|
||||
($adc:ident [
|
||||
$( ($pin:ident, $channel:expr) ,)+
|
||||
]) => {
|
||||
|
||||
$(
|
||||
impl Channel<$adc> for $pin<Analog> {
|
||||
type ID = u8;
|
||||
|
||||
fn channel() -> u8 { $channel }
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
pub use impl_adc_interface;
|
||||
@ -1,409 +0,0 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use embedded_hal::adc::{Channel, OneShot};
|
||||
|
||||
use crate::{
|
||||
analog::{ADC1, ADC2},
|
||||
pac::{APB_SARADC, SENS},
|
||||
};
|
||||
|
||||
/// The sampling/readout resolution of the ADC
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Resolution {
|
||||
Resolution13Bit,
|
||||
}
|
||||
|
||||
/// The attenuation of the ADC pin
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Attenuation {
|
||||
Attenuation0dB = 0b00,
|
||||
Attenuation2p5dB = 0b01,
|
||||
Attenuation6dB = 0b10,
|
||||
Attenuation11dB = 0b11,
|
||||
}
|
||||
|
||||
pub struct AdcPin<PIN, ADCI> {
|
||||
pub pin: PIN,
|
||||
_phantom: PhantomData<ADCI>,
|
||||
}
|
||||
|
||||
impl<PIN: Channel<ADCI, ID = u8>, ADCI> Channel<ADCI> for AdcPin<PIN, ADCI> {
|
||||
type ID = u8;
|
||||
|
||||
fn channel() -> Self::ID {
|
||||
PIN::channel()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AdcConfig<ADCI> {
|
||||
pub resolution: Resolution,
|
||||
pub attenuations: [Option<Attenuation>; 10],
|
||||
_phantom: PhantomData<ADCI>,
|
||||
}
|
||||
|
||||
impl<ADCI> AdcConfig<ADCI>
|
||||
where
|
||||
ADCI: RegisterAccess,
|
||||
{
|
||||
pub fn new() -> AdcConfig<ADCI> {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn enable_pin<PIN: Channel<ADCI, ID = u8>>(
|
||||
&mut self,
|
||||
pin: PIN,
|
||||
attenuation: Attenuation,
|
||||
) -> AdcPin<PIN, ADCI> {
|
||||
self.attenuations[PIN::channel() as usize] = Some(attenuation);
|
||||
|
||||
AdcPin {
|
||||
pin,
|
||||
_phantom: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<ADCI> Default for AdcConfig<ADCI> {
|
||||
fn default() -> Self {
|
||||
AdcConfig {
|
||||
resolution: Resolution::Resolution13Bit,
|
||||
attenuations: [None; 10],
|
||||
_phantom: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait RegisterAccess {
|
||||
fn set_bit_width(resolution: u8);
|
||||
|
||||
fn set_sample_bit(resolution: u8);
|
||||
|
||||
fn set_attenuation(channel: usize, attenuation: u8);
|
||||
|
||||
fn clear_dig_force();
|
||||
|
||||
fn set_start_force();
|
||||
|
||||
fn set_en_pad_force();
|
||||
|
||||
fn set_en_pad(channel: u8);
|
||||
|
||||
fn clear_start_sar();
|
||||
|
||||
fn set_start_sar();
|
||||
|
||||
fn read_done_sar() -> bool;
|
||||
|
||||
fn read_data_sar() -> u16;
|
||||
}
|
||||
|
||||
impl RegisterAccess for ADC1 {
|
||||
fn set_bit_width(_resolution: u8) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
fn set_sample_bit(_resolution: u8) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
fn set_attenuation(channel: usize, attenuation: u8) {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors.sar_atten1.modify(|r, w| {
|
||||
let new_value = (r.bits() & !(0b11 << (channel * 2)))
|
||||
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
|
||||
|
||||
unsafe { w.sar_sar1_atten().bits(new_value) }
|
||||
});
|
||||
}
|
||||
|
||||
fn clear_dig_force() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas1_mux
|
||||
.modify(|_, w| w.sar_sar1_dig_force().clear_bit());
|
||||
}
|
||||
|
||||
fn set_start_force() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas1_ctrl2
|
||||
.modify(|_, w| w.sar_meas1_start_force().set_bit());
|
||||
}
|
||||
|
||||
fn set_en_pad_force() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas1_ctrl2
|
||||
.modify(|_, w| w.sar_sar1_en_pad_force().set_bit());
|
||||
}
|
||||
|
||||
fn set_en_pad(channel: u8) {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas1_ctrl2
|
||||
.modify(|_, w| unsafe { w.sar_sar1_en_pad().bits(1 << channel) });
|
||||
}
|
||||
|
||||
fn clear_start_sar() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas1_ctrl2
|
||||
.modify(|_, w| w.sar_meas1_start_sar().clear_bit());
|
||||
}
|
||||
|
||||
fn set_start_sar() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas1_ctrl2
|
||||
.modify(|_, w| w.sar_meas1_start_sar().set_bit());
|
||||
}
|
||||
|
||||
fn read_done_sar() -> bool {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas1_ctrl2
|
||||
.read()
|
||||
.sar_meas1_done_sar()
|
||||
.bit_is_set()
|
||||
}
|
||||
|
||||
fn read_data_sar() -> u16 {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors.sar_meas1_ctrl2.read().sar_meas1_data_sar().bits() as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl RegisterAccess for ADC2 {
|
||||
fn set_bit_width(_resolution: u8) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
fn set_sample_bit(_resolution: u8) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
fn set_attenuation(channel: usize, attenuation: u8) {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors.sar_atten2.modify(|r, w| {
|
||||
let new_value = (r.bits() & !(0b11 << (channel * 2)))
|
||||
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
|
||||
|
||||
unsafe { w.sar_sar2_atten().bits(new_value) }
|
||||
});
|
||||
}
|
||||
|
||||
fn clear_dig_force() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas2_mux
|
||||
.modify(|_, w| w.sar_sar2_rtc_force().set_bit());
|
||||
|
||||
let sar_apb = unsafe { &*APB_SARADC::ptr() };
|
||||
sar_apb
|
||||
.apb_adc_arb_ctrl
|
||||
.modify(|_, w| w.adc_arb_rtc_force().set_bit());
|
||||
}
|
||||
|
||||
fn set_start_force() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas2_ctrl2
|
||||
.modify(|_, w| w.sar_meas2_start_force().set_bit());
|
||||
}
|
||||
|
||||
fn set_en_pad_force() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas2_ctrl2
|
||||
.modify(|_, w| w.sar_sar2_en_pad_force().set_bit());
|
||||
}
|
||||
|
||||
fn set_en_pad(channel: u8) {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas2_ctrl2
|
||||
.modify(|_, w| unsafe { w.sar_sar2_en_pad().bits(1 << channel) });
|
||||
}
|
||||
|
||||
fn clear_start_sar() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas2_ctrl2
|
||||
.modify(|_, w| w.sar_meas2_start_sar().clear_bit());
|
||||
}
|
||||
|
||||
fn set_start_sar() {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas2_ctrl2
|
||||
.modify(|_, w| w.sar_meas2_start_sar().set_bit());
|
||||
}
|
||||
|
||||
fn read_done_sar() -> bool {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors
|
||||
.sar_meas2_ctrl2
|
||||
.read()
|
||||
.sar_meas2_done_sar()
|
||||
.bit_is_set()
|
||||
}
|
||||
|
||||
fn read_data_sar() -> u16 {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors.sar_meas2_ctrl2.read().sar_meas2_data_sar().bits() as u16
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ADC<ADC> {
|
||||
adc: PhantomData<ADC>,
|
||||
attenuations: [Option<Attenuation>; 10],
|
||||
active_channel: Option<u8>,
|
||||
}
|
||||
|
||||
impl<ADCI> ADC<ADCI>
|
||||
where
|
||||
ADCI: RegisterAccess,
|
||||
{
|
||||
pub fn adc(_adc_instance: ADCI, config: AdcConfig<ADCI>) -> Result<Self, ()> {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
|
||||
// Set reading and sampling resolution
|
||||
let resolution: u8 = config.resolution as u8;
|
||||
|
||||
ADCI::set_bit_width(resolution);
|
||||
ADCI::set_sample_bit(resolution);
|
||||
|
||||
// Set attenuation for pins
|
||||
let attenuations = config.attenuations;
|
||||
|
||||
for channel in 0..attenuations.len() {
|
||||
if let Some(attenuation) = attenuations[channel] {
|
||||
ADC1::set_attenuation(channel, attenuation as u8);
|
||||
}
|
||||
}
|
||||
|
||||
// Set controller to RTC
|
||||
ADCI::clear_dig_force();
|
||||
ADCI::set_start_force();
|
||||
ADCI::set_en_pad_force();
|
||||
sensors
|
||||
.sar_hall_ctrl
|
||||
.modify(|_, w| w.sar_xpd_hall_force().set_bit());
|
||||
sensors
|
||||
.sar_hall_ctrl
|
||||
.modify(|_, w| w.sar_hall_phase_force().set_bit());
|
||||
|
||||
// Set power to SW power on
|
||||
sensors
|
||||
.sar_peri_clk_gate_conf
|
||||
.modify(|_, w| w.sar_saradc_clk_en().set_bit());
|
||||
|
||||
sensors
|
||||
.sar_power_xpd_sar
|
||||
.modify(|_, w| w.sar_sarclk_en().set_bit());
|
||||
|
||||
sensors
|
||||
.sar_power_xpd_sar
|
||||
.modify(|_, w| unsafe { w.sar_force_xpd_sar().bits(0b11) });
|
||||
|
||||
// disable AMP
|
||||
sensors
|
||||
.sar_meas1_ctrl1
|
||||
.modify(|_, w| unsafe { w.sar_force_xpd_amp().bits(0b11) });
|
||||
sensors
|
||||
.sar_amp_ctrl3
|
||||
.modify(|_, w| unsafe { w.sar_amp_rst_fb_fsm().bits(0) });
|
||||
sensors
|
||||
.sar_amp_ctrl3
|
||||
.modify(|_, w| unsafe { w.sar_amp_short_ref_fsm().bits(0) });
|
||||
sensors
|
||||
.sar_amp_ctrl3
|
||||
.modify(|_, w| unsafe { w.sar_amp_short_ref_gnd_fsm().bits(0) });
|
||||
sensors
|
||||
.sar_amp_ctrl1
|
||||
.modify(|_, w| unsafe { w.sar_amp_wait1().bits(1) });
|
||||
sensors
|
||||
.sar_amp_ctrl1
|
||||
.modify(|_, w| unsafe { w.sar_amp_wait2().bits(1) });
|
||||
sensors
|
||||
.sar_amp_ctrl2
|
||||
.modify(|_, w| unsafe { w.sar_amp_wait3().bits(1) });
|
||||
|
||||
let adc = ADC {
|
||||
adc: PhantomData,
|
||||
attenuations: config.attenuations,
|
||||
active_channel: None,
|
||||
};
|
||||
|
||||
Ok(adc)
|
||||
}
|
||||
}
|
||||
|
||||
impl<ADCI, WORD, PIN> OneShot<ADCI, WORD, AdcPin<PIN, ADCI>> for ADC<ADCI>
|
||||
where
|
||||
WORD: From<u16>,
|
||||
PIN: Channel<ADCI, ID = u8>,
|
||||
ADCI: RegisterAccess,
|
||||
{
|
||||
type Error = ();
|
||||
|
||||
fn read(&mut self, _pin: &mut AdcPin<PIN, ADCI>) -> nb::Result<WORD, Self::Error> {
|
||||
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
||||
panic!(
|
||||
"Channel {} is not configured reading!",
|
||||
AdcPin::<PIN, ADCI>::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 ahead and check progress
|
||||
if active_channel != AdcPin::<PIN, ADCI>::channel() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
} else {
|
||||
// If no conversions are in progress, start a new one for given channel
|
||||
self.active_channel = Some(AdcPin::<PIN, ADCI>::channel());
|
||||
|
||||
ADCI::set_en_pad(AdcPin::<PIN, ADCI>::channel() as u8);
|
||||
|
||||
ADCI::clear_start_sar();
|
||||
ADCI::set_start_sar();
|
||||
}
|
||||
|
||||
// Wait for ADC to finish conversion
|
||||
let conversion_finished = ADCI::read_done_sar();
|
||||
if !conversion_finished {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
}
|
||||
|
||||
// Get converted value
|
||||
let converted_value = ADCI::read_data_sar();
|
||||
|
||||
// Mark that no conversions are currently in progress
|
||||
self.active_channel = None;
|
||||
|
||||
Ok(converted_value.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_adc_interface {
|
||||
($adc:ident [
|
||||
$( ($pin:ident, $channel:expr) ,)+
|
||||
]) => {
|
||||
|
||||
$(
|
||||
impl Channel<$adc> for $pin<Analog> {
|
||||
type ID = u8;
|
||||
|
||||
fn channel() -> u8 { $channel }
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
pub use impl_adc_interface;
|
||||
@ -2,8 +2,10 @@ use core::marker::PhantomData;
|
||||
|
||||
use embedded_hal::adc::{Channel, OneShot};
|
||||
|
||||
#[cfg(esp32c3)]
|
||||
use crate::analog::ADC2;
|
||||
use crate::{
|
||||
analog::{ADC1, ADC2},
|
||||
analog::ADC1,
|
||||
pac::APB_SARADC,
|
||||
system::{Peripheral, PeripheralClockControl},
|
||||
};
|
||||
@ -35,6 +37,7 @@ impl<PIN: Channel<ADCI, ID = u8>, ADCI> Channel<ADCI> for AdcPin<PIN, ADCI> {
|
||||
PIN::channel()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AdcConfig<ADCI> {
|
||||
pub resolution: Resolution,
|
||||
pub attenuations: [Option<Attenuation>; 5],
|
||||
@ -125,6 +128,7 @@ impl RegisterAccess for ADC1 {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(esp32c3)]
|
||||
impl RegisterAccess for ADC2 {
|
||||
fn start_onetime_sample(channel: u8, attenuation: u8) {
|
||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||
@ -161,7 +161,11 @@ impl RegisterAccess for ADC1 {
|
||||
|
||||
fn read_done_sar() -> bool {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors.sar_meas1_ctrl2.read().meas1_done_sar().bit_is_set()
|
||||
sensors.
|
||||
sar_meas1_ctrl2.
|
||||
read().
|
||||
meas1_done_sar().
|
||||
bit_is_set()
|
||||
}
|
||||
|
||||
fn read_data_sar() -> u16 {
|
||||
@ -238,7 +242,11 @@ impl RegisterAccess for ADC2 {
|
||||
|
||||
fn read_done_sar() -> bool {
|
||||
let sensors = unsafe { &*SENS::ptr() };
|
||||
sensors.sar_meas2_ctrl2.read().meas2_done_sar().bit_is_set()
|
||||
sensors.
|
||||
sar_meas2_ctrl2.
|
||||
read().
|
||||
meas2_done_sar().
|
||||
bit_is_set()
|
||||
}
|
||||
|
||||
fn read_data_sar() -> u16 {
|
||||
@ -287,10 +295,16 @@ where
|
||||
.modify(|_, w| w.hall_phase_force().set_bit());
|
||||
|
||||
// Set power to SW power on
|
||||
#[cfg(esp32s2)]
|
||||
sensors
|
||||
.sar_meas1_ctrl1
|
||||
.modify(|_, w| w.rtc_saradc_clkgate_en().set_bit());
|
||||
|
||||
#[cfg(esp32s3)]
|
||||
sensors
|
||||
.sar_peri_clk_gate_conf
|
||||
.modify(|_, w| w.saradc_clk_en().set_bit());
|
||||
|
||||
sensors
|
||||
.sar_power_xpd_sar
|
||||
.modify(|_, w| w.sarclk_en().set_bit());
|
||||
@ -1,8 +1,8 @@
|
||||
#[cfg_attr(esp32, path = "adc/esp32.rs")]
|
||||
#[cfg_attr(esp32c2, path = "adc/esp32c2.rs")]
|
||||
#[cfg_attr(esp32c3, path = "adc/esp32c3.rs")]
|
||||
#[cfg_attr(esp32s2, path = "adc/esp32s2.rs")]
|
||||
#[cfg_attr(esp32s3, path = "adc/esp32s3.rs")]
|
||||
#[cfg_attr(esp32c2, path = "adc/riscv.rs")]
|
||||
#[cfg_attr(esp32c3, path = "adc/riscv.rs")]
|
||||
#[cfg_attr(esp32s2, path = "adc/xtensa.rs")]
|
||||
#[cfg_attr(esp32s3, path = "adc/xtensa.rs")]
|
||||
pub mod adc;
|
||||
#[cfg(not(any(esp32c2, esp32c3, esp32s3)))]
|
||||
pub mod dac;
|
||||
|
||||
@ -93,7 +93,7 @@ where
|
||||
{
|
||||
let rtc = &*pac::RTC_CNTL::PTR;
|
||||
rtc.usb_conf
|
||||
.modify(|_, w| w.sw_hw_usb_phy_sel().set_bit().sw_usb_phy_sel().set_bit());
|
||||
.modify(|_, w| w.sw_hw_usb_phy_sel().set_bit().sw_usb_phy_sel().set_bit());
|
||||
}
|
||||
|
||||
crate::gpio::connect_high_to_peripheral(InputSignal::USB_OTG_IDDIG); // connected connector is mini-B side
|
||||
|
||||
@ -1332,7 +1332,6 @@ pub trait Instance {
|
||||
}
|
||||
|
||||
fn ch_bus_freq(&mut self, frequency: HertzU32, clocks: &Clocks) {
|
||||
|
||||
// Disable clock source
|
||||
#[cfg(not(any(feature = "esp32", feature = "esp32s2")))]
|
||||
self.register_block().clk_gate.modify(|_, w| {
|
||||
|
||||
@ -57,7 +57,7 @@ fn main() -> ! {
|
||||
|
||||
loop {
|
||||
let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
||||
println!("PIN ADC reading = {}", pin_value);
|
||||
println!("PIN2 ADC reading = {}", pin_value);
|
||||
delay.delay_ms(1500u32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ fn main() -> ! {
|
||||
|
||||
loop {
|
||||
let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
||||
println!("PIN ADC reading = {}", pin_value);
|
||||
println!("PIN2 ADC reading = {}", pin_value);
|
||||
delay.delay_ms(1500u32);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user