mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-29 21:30:39 +00:00
Refactor the analog module (#1100)
* Create virtual peripherals for `ADC`/`DAC` * Refactor the `analog::dac` module * Refactor the `analog::adc` module * Decouple the ADC driver from the `embedded-hal` traits * Update `CHANGELOG.md` * Seal the `AdcCalScheme` trait, reduce visibility of `AdcCalEfuse` trait * Remove `APB_SARADC`/`SENS` peripherals from the `Peripherals` struct
This commit is contained in:
parent
43f212dc72
commit
f52aa1351c
@ -23,6 +23,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
### Breaking
|
||||||
|
|
||||||
|
- `ADC` and `DAC` drivers now take virtual peripherals in their constructors, instead of splitting `APB_SARADC`/`SENS` (#1100)
|
||||||
|
- The `DAC` driver's constructor is now `new` instead of `dac`, to be more consistent with other APIs (#1100)
|
||||||
|
|
||||||
## [0.15.0] - 2024-01-19
|
## [0.15.0] - 2024-01-19
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::adc::{
|
use crate::adc::{
|
||||||
|
private,
|
||||||
AdcCalEfuse,
|
AdcCalEfuse,
|
||||||
AdcCalScheme,
|
AdcCalScheme,
|
||||||
AdcCalSource,
|
AdcCalSource,
|
||||||
@ -27,6 +28,8 @@ pub struct AdcCalBasic<ADCI> {
|
|||||||
_phantom: PhantomData<ADCI>,
|
_phantom: PhantomData<ADCI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<ADCI> private::Sealed for AdcCalBasic<ADCI> {}
|
||||||
|
|
||||||
impl<ADCI> AdcCalScheme<ADCI> for AdcCalBasic<ADCI>
|
impl<ADCI> AdcCalScheme<ADCI> for AdcCalBasic<ADCI>
|
||||||
where
|
where
|
||||||
ADCI: AdcCalEfuse + CalibrationAccess,
|
ADCI: AdcCalEfuse + CalibrationAccess,
|
@ -1,6 +1,7 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::adc::{
|
use crate::adc::{
|
||||||
|
private,
|
||||||
AdcCalEfuse,
|
AdcCalEfuse,
|
||||||
AdcCalLine,
|
AdcCalLine,
|
||||||
AdcCalScheme,
|
AdcCalScheme,
|
||||||
@ -60,6 +61,8 @@ pub struct AdcCalCurve<ADCI> {
|
|||||||
_phantom: PhantomData<ADCI>,
|
_phantom: PhantomData<ADCI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<ADCI> private::Sealed for AdcCalCurve<ADCI> {}
|
||||||
|
|
||||||
impl<ADCI> AdcCalScheme<ADCI> for AdcCalCurve<ADCI>
|
impl<ADCI> AdcCalScheme<ADCI> for AdcCalCurve<ADCI>
|
||||||
where
|
where
|
||||||
ADCI: AdcCalEfuse + AdcHasLineCal + AdcHasCurveCal + CalibrationAccess,
|
ADCI: AdcCalEfuse + AdcHasLineCal + AdcHasCurveCal + CalibrationAccess,
|
||||||
@ -126,17 +129,17 @@ macro_rules! coeff_tables {
|
|||||||
mod impls {
|
mod impls {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl AdcHasCurveCal for crate::adc::ADC1 {
|
impl AdcHasCurveCal for crate::peripherals::ADC1 {
|
||||||
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
|
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32c3)]
|
#[cfg(esp32c3)]
|
||||||
impl AdcHasCurveCal for crate::adc::ADC2 {
|
impl AdcHasCurveCal for crate::peripherals::ADC2 {
|
||||||
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
|
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
#[cfg(esp32s3)]
|
||||||
impl AdcHasCurveCal for crate::adc::ADC2 {
|
impl AdcHasCurveCal for crate::peripherals::ADC2 {
|
||||||
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS2;
|
const CURVES_COEFFS: CurvesCoeffs = CURVES_COEFFS2;
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::adc::{
|
use crate::adc::{
|
||||||
|
private,
|
||||||
AdcCalBasic,
|
AdcCalBasic,
|
||||||
AdcCalEfuse,
|
AdcCalEfuse,
|
||||||
AdcCalScheme,
|
AdcCalScheme,
|
||||||
@ -48,6 +49,8 @@ pub struct AdcCalLine<ADCI> {
|
|||||||
_phantom: PhantomData<ADCI>,
|
_phantom: PhantomData<ADCI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<ADCI> private::Sealed for AdcCalLine<ADCI> {}
|
||||||
|
|
||||||
impl<ADCI> AdcCalScheme<ADCI> for AdcCalLine<ADCI>
|
impl<ADCI> AdcCalScheme<ADCI> for AdcCalLine<ADCI>
|
||||||
where
|
where
|
||||||
ADCI: AdcCalEfuse + AdcHasLineCal + CalibrationAccess,
|
ADCI: AdcCalEfuse + AdcHasLineCal + CalibrationAccess,
|
||||||
@ -96,7 +99,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
|
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
|
||||||
impl AdcHasLineCal for crate::adc::ADC1 {}
|
impl AdcHasLineCal for crate::peripherals::ADC1 {}
|
||||||
|
|
||||||
#[cfg(any(esp32c3, esp32s3))]
|
#[cfg(any(esp32c3, esp32s3))]
|
||||||
impl AdcHasLineCal for crate::adc::ADC2 {}
|
impl AdcHasLineCal for crate::peripherals::ADC2 {}
|
14
esp-hal-common/src/analog/adc/calibration/mod.rs
Normal file
14
esp-hal-common/src/analog/adc/calibration/mod.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#[cfg(any(esp32c3, esp32c6, esp32s3))]
|
||||||
|
pub use self::curve::{AdcCalCurve, AdcHasCurveCal};
|
||||||
|
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
|
||||||
|
pub use self::{
|
||||||
|
basic::AdcCalBasic,
|
||||||
|
line::{AdcCalLine, AdcHasLineCal},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
|
||||||
|
mod basic;
|
||||||
|
#[cfg(any(esp32c3, esp32c6, esp32s3))]
|
||||||
|
mod curve;
|
||||||
|
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
|
||||||
|
mod line;
|
@ -1,14 +1,12 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embedded_hal::adc::{Channel, OneShot};
|
use super::{AdcChannel, Attenuation};
|
||||||
|
|
||||||
pub use crate::analog::{ADC1, ADC2};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peripheral::PeripheralRef,
|
peripheral::PeripheralRef,
|
||||||
peripherals::{RTC_IO, SENS},
|
peripherals::{ADC1, ADC2, RTC_IO, SENS},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The sampling/readout resolution of the ADC
|
/// The sampling/readout resolution of the ADC.
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum Resolution {
|
pub enum Resolution {
|
||||||
Resolution9Bit = 0b00,
|
Resolution9Bit = 0b00,
|
||||||
@ -17,20 +15,16 @@ pub enum Resolution {
|
|||||||
Resolution12Bit = 0b11,
|
Resolution12Bit = 0b11,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
/// An I/O pin which can be read using the ADC.
|
||||||
pub enum Attenuation {
|
|
||||||
Attenuation0dB = 0b00,
|
|
||||||
Attenuation2p5dB = 0b01,
|
|
||||||
Attenuation6dB = 0b10,
|
|
||||||
Attenuation11dB = 0b11,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AdcPin<PIN, ADCI> {
|
pub struct AdcPin<PIN, ADCI> {
|
||||||
pub pin: PIN,
|
pub pin: PIN,
|
||||||
_phantom: PhantomData<ADCI>,
|
_phantom: PhantomData<ADCI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<PIN: Channel<ADCI, ID = u8>, ADCI> Channel<ADCI> for AdcPin<PIN, ADCI> {
|
impl<PIN, ADCI> embedded_hal::adc::Channel<ADCI> for AdcPin<PIN, ADCI>
|
||||||
|
where
|
||||||
|
PIN: embedded_hal::adc::Channel<ADCI, ID = u8>,
|
||||||
|
{
|
||||||
type ID = u8;
|
type ID = u8;
|
||||||
|
|
||||||
fn channel() -> Self::ID {
|
fn channel() -> Self::ID {
|
||||||
@ -38,6 +32,7 @@ impl<PIN: Channel<ADCI, ID = u8>, ADCI> Channel<ADCI> for AdcPin<PIN, ADCI> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration for the ADC.
|
||||||
pub struct AdcConfig<ADCI> {
|
pub struct AdcConfig<ADCI> {
|
||||||
pub resolution: Resolution,
|
pub resolution: Resolution,
|
||||||
pub attenuations: [Option<Attenuation>; 10],
|
pub attenuations: [Option<Attenuation>; 10],
|
||||||
@ -49,16 +44,14 @@ where
|
|||||||
ADCI: RegisterAccess,
|
ADCI: RegisterAccess,
|
||||||
{
|
{
|
||||||
pub fn new() -> AdcConfig<ADCI> {
|
pub fn new() -> AdcConfig<ADCI> {
|
||||||
crate::into_ref!();
|
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_pin<PIN: Channel<ADCI, ID = u8>>(
|
pub fn enable_pin<PIN>(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin<PIN, ADCI>
|
||||||
&mut self,
|
where
|
||||||
pin: PIN,
|
PIN: AdcChannel,
|
||||||
attenuation: Attenuation,
|
{
|
||||||
) -> AdcPin<PIN, ADCI> {
|
self.attenuations[PIN::CHANNEL as usize] = Some(attenuation);
|
||||||
self.attenuations[PIN::channel() as usize] = Some(attenuation);
|
|
||||||
|
|
||||||
AdcPin {
|
AdcPin {
|
||||||
pin,
|
pin,
|
||||||
@ -77,6 +70,7 @@ impl<ADCI> Default for AdcConfig<ADCI> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
pub trait RegisterAccess {
|
pub trait RegisterAccess {
|
||||||
fn set_bit_width(resolution: u8);
|
fn set_bit_width(resolution: u8);
|
||||||
|
|
||||||
@ -101,25 +95,21 @@ pub trait RegisterAccess {
|
|||||||
fn read_data_sar() -> u16;
|
fn read_data_sar() -> u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
impl RegisterAccess for ADC1 {
|
impl RegisterAccess for ADC1 {
|
||||||
fn set_bit_width(resolution: u8) {
|
fn set_bit_width(resolution: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_start_force()
|
.sar_start_force()
|
||||||
.modify(|_, w| unsafe { w.sar1_bit_width().bits(resolution) });
|
.modify(|_, w| unsafe { w.sar1_bit_width().bits(resolution) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sample_bit(resolution: u8) {
|
fn set_sample_bit(resolution: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_read_ctrl()
|
.sar_read_ctrl()
|
||||||
.modify(|_, w| unsafe { w.sar1_sample_bit().bits(resolution) });
|
.modify(|_, w| unsafe { w.sar1_sample_bit().bits(resolution) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_attenuation(channel: usize, attenuation: u8) {
|
fn set_attenuation(channel: usize, attenuation: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }.sar_atten1().modify(|r, w| {
|
||||||
sensors.sar_atten1().modify(|r, w| {
|
|
||||||
let new_value = (r.bits() & !(0b11 << (channel * 2)))
|
let new_value = (r.bits() & !(0b11 << (channel * 2)))
|
||||||
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
|
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
|
||||||
|
|
||||||
@ -128,50 +118,43 @@ impl RegisterAccess for ADC1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clear_dig_force() {
|
fn clear_dig_force() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_read_ctrl()
|
.sar_read_ctrl()
|
||||||
.modify(|_, w| w.sar1_dig_force().clear_bit());
|
.modify(|_, w| w.sar1_dig_force().clear_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_start_force() {
|
fn set_start_force() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start1()
|
.sar_meas_start1()
|
||||||
.modify(|_, w| w.meas1_start_force().set_bit());
|
.modify(|_, w| w.meas1_start_force().set_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_en_pad_force() {
|
fn set_en_pad_force() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start1()
|
.sar_meas_start1()
|
||||||
.modify(|_, w| w.sar1_en_pad_force().set_bit());
|
.modify(|_, w| w.sar1_en_pad_force().set_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_en_pad(channel: u8) {
|
fn set_en_pad(channel: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start1()
|
.sar_meas_start1()
|
||||||
.modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
|
.modify(|_, w| unsafe { w.sar1_en_pad().bits(1 << channel) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_start_sar() {
|
fn clear_start_sar() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start1()
|
.sar_meas_start1()
|
||||||
.modify(|_, w| w.meas1_start_sar().clear_bit());
|
.modify(|_, w| w.meas1_start_sar().clear_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_start_sar() {
|
fn set_start_sar() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start1()
|
.sar_meas_start1()
|
||||||
.modify(|_, w| w.meas1_start_sar().set_bit());
|
.modify(|_, w| w.meas1_start_sar().set_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_done_sar() -> bool {
|
fn read_done_sar() -> bool {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start1()
|
.sar_meas_start1()
|
||||||
.read()
|
.read()
|
||||||
.meas1_done_sar()
|
.meas1_done_sar()
|
||||||
@ -179,29 +162,29 @@ impl RegisterAccess for ADC1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_data_sar() -> u16 {
|
fn read_data_sar() -> u16 {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors.sar_meas_start1().read().meas1_data_sar().bits() as u16
|
.sar_meas_start1()
|
||||||
|
.read()
|
||||||
|
.meas1_data_sar()
|
||||||
|
.bits() as u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterAccess for ADC2 {
|
impl RegisterAccess for ADC2 {
|
||||||
fn set_bit_width(resolution: u8) {
|
fn set_bit_width(resolution: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_start_force()
|
.sar_start_force()
|
||||||
.modify(|_, w| unsafe { w.sar2_bit_width().bits(resolution) });
|
.modify(|_, w| unsafe { w.sar2_bit_width().bits(resolution) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sample_bit(resolution: u8) {
|
fn set_sample_bit(resolution: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_read_ctrl2()
|
.sar_read_ctrl2()
|
||||||
.modify(|_, w| unsafe { w.sar2_sample_bit().bits(resolution) });
|
.modify(|_, w| unsafe { w.sar2_sample_bit().bits(resolution) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_attenuation(channel: usize, attenuation: u8) {
|
fn set_attenuation(channel: usize, attenuation: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }.sar_atten2().modify(|r, w| {
|
||||||
sensors.sar_atten2().modify(|r, w| {
|
|
||||||
let new_value = (r.bits() & !(0b11 << (channel * 2)))
|
let new_value = (r.bits() & !(0b11 << (channel * 2)))
|
||||||
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
|
| (((attenuation as u8 & 0b11) as u32) << (channel * 2));
|
||||||
|
|
||||||
@ -210,50 +193,43 @@ impl RegisterAccess for ADC2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clear_dig_force() {
|
fn clear_dig_force() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_read_ctrl2()
|
.sar_read_ctrl2()
|
||||||
.modify(|_, w| w.sar2_dig_force().clear_bit());
|
.modify(|_, w| w.sar2_dig_force().clear_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_start_force() {
|
fn set_start_force() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start2()
|
.sar_meas_start2()
|
||||||
.modify(|_, w| w.meas2_start_force().set_bit());
|
.modify(|_, w| w.meas2_start_force().set_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_en_pad_force() {
|
fn set_en_pad_force() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start2()
|
.sar_meas_start2()
|
||||||
.modify(|_, w| w.sar2_en_pad_force().set_bit());
|
.modify(|_, w| w.sar2_en_pad_force().set_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_en_pad(channel: u8) {
|
fn set_en_pad(channel: u8) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start2()
|
.sar_meas_start2()
|
||||||
.modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
|
.modify(|_, w| unsafe { w.sar2_en_pad().bits(1 << channel) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_start_sar() {
|
fn clear_start_sar() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start2()
|
.sar_meas_start2()
|
||||||
.modify(|_, w| w.meas2_start_sar().clear_bit());
|
.modify(|_, w| w.meas2_start_sar().clear_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_start_sar() {
|
fn set_start_sar() {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start2()
|
.sar_meas_start2()
|
||||||
.modify(|_, w| w.meas2_start_sar().set_bit());
|
.modify(|_, w| w.meas2_start_sar().set_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_done_sar() -> bool {
|
fn read_done_sar() -> bool {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors
|
|
||||||
.sar_meas_start2()
|
.sar_meas_start2()
|
||||||
.read()
|
.read()
|
||||||
.meas2_done_sar()
|
.meas2_done_sar()
|
||||||
@ -261,11 +237,15 @@ impl RegisterAccess for ADC2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_data_sar() -> u16 {
|
fn read_data_sar() -> u16 {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
unsafe { &*SENS::ptr() }
|
||||||
sensors.sar_meas_start2().read().meas2_data_sar().bits() as u16
|
.sar_meas_start2()
|
||||||
|
.read()
|
||||||
|
.meas2_data_sar()
|
||||||
|
.bits() as u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Analog-to-Digital Converter peripheral driver.
|
||||||
pub struct ADC<'d, ADC> {
|
pub struct ADC<'d, ADC> {
|
||||||
_adc: PeripheralRef<'d, ADC>,
|
_adc: PeripheralRef<'d, ADC>,
|
||||||
attenuations: [Option<Attenuation>; 10],
|
attenuations: [Option<Attenuation>; 10],
|
||||||
@ -355,25 +335,29 @@ where
|
|||||||
impl<'d, ADC1> ADC<'d, ADC1> {
|
impl<'d, ADC1> ADC<'d, ADC1> {
|
||||||
pub fn enable_hall_sensor() {
|
pub fn enable_hall_sensor() {
|
||||||
// Connect hall sensor
|
// Connect hall sensor
|
||||||
let rtcio = unsafe { &*RTC_IO::ptr() };
|
unsafe { &*RTC_IO::ptr() }
|
||||||
rtcio.hall_sens().modify(|_, w| w.xpd_hall().set_bit());
|
.hall_sens()
|
||||||
|
.modify(|_, w| w.xpd_hall().set_bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_hall_sensor() {
|
pub fn disable_hall_sensor() {
|
||||||
// Disconnect hall sensor
|
// Disconnect hall sensor
|
||||||
let rtcio = unsafe { &*RTC_IO::ptr() };
|
unsafe { &*RTC_IO::ptr() }
|
||||||
rtcio.hall_sens().modify(|_, w| w.xpd_hall().clear_bit());
|
.hall_sens()
|
||||||
|
.modify(|_, w| w.xpd_hall().clear_bit());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, ADCI, PIN> OneShot<ADCI, u16, AdcPin<PIN, ADCI>> for ADC<'d, ADCI>
|
impl<'d, ADCI, PIN> embedded_hal::adc::OneShot<ADCI, u16, AdcPin<PIN, ADCI>> for ADC<'d, ADCI>
|
||||||
where
|
where
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: embedded_hal::adc::Channel<ADCI, ID = u8>,
|
||||||
ADCI: RegisterAccess,
|
ADCI: RegisterAccess,
|
||||||
{
|
{
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn read(&mut self, _pin: &mut AdcPin<PIN, ADCI>) -> nb::Result<u16, Self::Error> {
|
fn read(&mut self, _pin: &mut AdcPin<PIN, ADCI>) -> nb::Result<u16, Self::Error> {
|
||||||
|
use embedded_hal::adc::Channel;
|
||||||
|
|
||||||
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
||||||
panic!(
|
panic!(
|
||||||
"Channel {} is not configured reading!",
|
"Channel {} is not configured reading!",
|
||||||
@ -418,8 +402,11 @@ macro_rules! impl_adc_interface {
|
|||||||
($adc:ident [
|
($adc:ident [
|
||||||
$( ($pin:ident, $channel:expr) ,)+
|
$( ($pin:ident, $channel:expr) ,)+
|
||||||
]) => {
|
]) => {
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
impl $crate::analog::adc::AdcChannel for crate::gpio::$pin<crate::gpio::Analog> {
|
||||||
|
const CHANNEL: u8 = $channel;
|
||||||
|
}
|
||||||
|
|
||||||
impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin<crate::gpio::Analog> {
|
impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin<crate::gpio::Analog> {
|
||||||
type ID = u8;
|
type ID = u8;
|
||||||
|
|
||||||
@ -430,54 +417,7 @@ macro_rules! impl_adc_interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod implementation {
|
mod implementation {
|
||||||
//! # Analog to digital (ADC) conversion support.
|
use crate::peripherals::{ADC1, ADC2};
|
||||||
//!
|
|
||||||
//! ## Overview
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world
|
|
||||||
//! analog signals with high accuracy.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for reading analog values from the
|
|
||||||
//! analog to digital converter available on the ESP32: `ADC1` and `ADC2`.
|
|
||||||
//!
|
|
||||||
//! The following pins can be configured for analog readout:
|
|
||||||
//!
|
|
||||||
//! | Channel | ADC1 | ADC2 |
|
|
||||||
//! |---------|----------------------|---------------|
|
|
||||||
//! | 0 | GPIO36 (SENSOR_VP) | GPIO4 |
|
|
||||||
//! | 1 | GPIO37 (SENSOR_CAPP) | GPIO0 |
|
|
||||||
//! | 2 | GPIO38 (SENSOR_CAPN) | GPIO2 |
|
|
||||||
//! | 3 | GPIO39 (SENSOR_VN) | GPIO15 (MTDO) |
|
|
||||||
//! | 4 | GPIO33 (32K_XP) | GPIO13 (MTCK) |
|
|
||||||
//! | 5 | GPIO32 (32K_XN) | GPIO12 (MTDI) |
|
|
||||||
//! | 6 | GPIO34 (VDET_1) | GPIO14 (MTMS) |
|
|
||||||
//! | 7 | GPIO35 (VDET_2) | GPIO27 |
|
|
||||||
//! | 8 | | GPIO25 |
|
|
||||||
//! | 9 | | GPIO26 |
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//! #### ADC on Xtensa architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.SENS.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin3 =
|
|
||||||
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
|
|
||||||
//! println!("PIN3 ADC reading = {}", pin3_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use crate::analog::{ADC1, ADC2};
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
impl_adc_interface! {
|
||||||
ADC1 [
|
ADC1 [
|
||||||
|
108
esp-hal-common/src/analog/adc/mod.rs
Normal file
108
esp-hal-common/src/analog/adc/mod.rs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
//! # Analog to Digital Converter (ADC)
|
||||||
|
//!
|
||||||
|
//! The Analog to Digital Converter (ADC) is integrated on the chip, and is
|
||||||
|
//! capable of measuring analog signals from specific analog I/O pins. One or
|
||||||
|
//! more ADC units are available, depending on the device being used.
|
||||||
|
//!
|
||||||
|
//! ## Example
|
||||||
|
//!
|
||||||
|
//! ```no_run
|
||||||
|
//! let mut adc1_config = AdcConfig::new();
|
||||||
|
//! let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
|
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
||||||
|
//!
|
||||||
|
//! let mut delay = Delay::new(&clocks);
|
||||||
|
//!
|
||||||
|
//! loop {
|
||||||
|
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
||||||
|
//! println!("PIN2 ADC reading = {}", pin_value);
|
||||||
|
//!
|
||||||
|
//! delay.delay_ms(1500u32);
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
pub use self::implementation::*;
|
||||||
|
|
||||||
|
#[cfg_attr(esp32, path = "esp32.rs")]
|
||||||
|
#[cfg_attr(riscv, path = "riscv.rs")]
|
||||||
|
#[cfg_attr(any(esp32s2, esp32s3), path = "xtensa.rs")]
|
||||||
|
mod implementation;
|
||||||
|
|
||||||
|
mod private {
|
||||||
|
pub trait Sealed {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The attenuation of the ADC pin.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Attenuation {
|
||||||
|
/// 0dB attenuation, measurement range: 0-800mV
|
||||||
|
Attenuation0dB = 0b00,
|
||||||
|
/// 2.5dB attenuation, measurement range: 0-1100mV
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
Attenuation2p5dB = 0b01,
|
||||||
|
/// 6dB attenuation, measurement range: 0-1350mV
|
||||||
|
#[cfg(not(esp32c2))]
|
||||||
|
Attenuation6dB = 0b10,
|
||||||
|
/// 11dB attenuation, measurement range: 0-2600mV
|
||||||
|
Attenuation11dB = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calibration source of the ADC.
|
||||||
|
#[cfg(not(esp32))]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum AdcCalSource {
|
||||||
|
Gnd,
|
||||||
|
Ref,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A helper trait to get the ADC channel of a compatible GPIO pin.
|
||||||
|
pub trait AdcChannel {
|
||||||
|
const CHANNEL: u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait abstracting over calibration methods.
|
||||||
|
///
|
||||||
|
/// The methods in this trait are mostly for internal use. To get
|
||||||
|
/// calibrated ADC reads, all you need to do is call `enable_pin_with_cal`
|
||||||
|
/// and specify some implementor of this trait.
|
||||||
|
pub trait AdcCalScheme<ADCI>: Sized + private::Sealed {
|
||||||
|
/// Create a new calibration scheme for the given attenuation.
|
||||||
|
fn new_cal(atten: Attenuation) -> Self;
|
||||||
|
|
||||||
|
/// Return the basic ADC bias value. See [`AdcCalBasic`] for
|
||||||
|
/// details.
|
||||||
|
fn adc_cal(&self) -> u16 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert ADC value
|
||||||
|
fn adc_val(&self, val: u16) -> u16 {
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl private::Sealed for () {}
|
||||||
|
|
||||||
|
impl<ADCI> AdcCalScheme<ADCI> for () {
|
||||||
|
fn new_cal(_atten: Attenuation) -> Self {
|
||||||
|
()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A helper trait to get access to ADC calibration efuses.
|
||||||
|
trait AdcCalEfuse {
|
||||||
|
/// Get ADC calibration init code
|
||||||
|
///
|
||||||
|
/// Returns digital value for zero voltage for a given attenuation
|
||||||
|
fn get_init_code(atten: Attenuation) -> Option<u16>;
|
||||||
|
|
||||||
|
/// Get ADC calibration reference point voltage
|
||||||
|
///
|
||||||
|
/// Returns reference voltage (millivolts) for a given attenuation
|
||||||
|
fn get_cal_mv(atten: Attenuation) -> u16;
|
||||||
|
|
||||||
|
/// Get ADC calibration reference point digital value
|
||||||
|
///
|
||||||
|
/// Returns digital value for reference voltage for a given attenuation
|
||||||
|
fn get_cal_code(atten: Attenuation) -> Option<u16>;
|
||||||
|
}
|
@ -1,10 +1,7 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embedded_hal::adc::{Channel, OneShot};
|
pub use self::calibration::*;
|
||||||
|
use super::{AdcCalEfuse, AdcCalScheme, AdcCalSource, AdcChannel, Attenuation};
|
||||||
pub use crate::analog::ADC1;
|
|
||||||
#[cfg(esp32c3)]
|
|
||||||
pub use crate::analog::ADC2;
|
|
||||||
#[cfg(any(esp32c6, esp32h2))]
|
#[cfg(any(esp32c6, esp32h2))]
|
||||||
use crate::clock::clocks_ll::regi2c_write_mask;
|
use crate::clock::clocks_ll::regi2c_write_mask;
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
||||||
@ -15,21 +12,7 @@ use crate::{
|
|||||||
system::{Peripheral, PeripheralClockControl},
|
system::{Peripheral, PeripheralClockControl},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
mod calibration;
|
||||||
mod cal_basic;
|
|
||||||
#[cfg(any(esp32c3, esp32c6))]
|
|
||||||
mod cal_curve;
|
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
|
||||||
mod cal_line;
|
|
||||||
|
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
|
||||||
pub use cal_basic::AdcCalBasic;
|
|
||||||
#[cfg(any(esp32c3, esp32c6))]
|
|
||||||
pub use cal_curve::{AdcCalCurve, AdcHasCurveCal};
|
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
|
||||||
pub use cal_line::{AdcCalLine, AdcHasLineCal};
|
|
||||||
|
|
||||||
pub use crate::analog::{AdcCalEfuse, AdcCalScheme};
|
|
||||||
|
|
||||||
// polyfill for c2 and c3
|
// polyfill for c2 and c3
|
||||||
#[cfg(any(esp32c2, esp32c3))]
|
#[cfg(any(esp32c2, esp32c3))]
|
||||||
@ -118,48 +101,22 @@ cfg_if::cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The sampling/readout resolution of the ADC
|
/// The sampling/readout resolution of the ADC.
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum Resolution {
|
pub enum Resolution {
|
||||||
Resolution12Bit,
|
Resolution12Bit,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The attenuation of the ADC pin
|
/// An I/O pin which can be read using the ADC.
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
|
||||||
pub enum Attenuation {
|
|
||||||
/// 0 dB attenuation, measurement range: 0 - 800 mV
|
|
||||||
Attenuation0dB = 0b00,
|
|
||||||
/// 2.5 dB attenuation, measurement range: 0 - 1100 mV
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
Attenuation2p5dB = 0b01,
|
|
||||||
/// 6 dB attenuation, measurement range: 0 - 1350 mV
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
Attenuation6dB = 0b10,
|
|
||||||
/// 11 dB attenuation, measurement range: 0 - 2600 mV
|
|
||||||
Attenuation11dB = 0b11,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Attenuation {
|
|
||||||
/// List of all supported attenuations
|
|
||||||
pub const ALL: &'static [Attenuation] = &[
|
|
||||||
Attenuation::Attenuation0dB,
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
Attenuation::Attenuation2p5dB,
|
|
||||||
#[cfg(not(esp32c2))]
|
|
||||||
Attenuation::Attenuation6dB,
|
|
||||||
Attenuation::Attenuation11dB,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AdcPin<PIN, ADCI, CS = ()> {
|
pub struct AdcPin<PIN, ADCI, CS = ()> {
|
||||||
pub pin: PIN,
|
pub pin: PIN,
|
||||||
pub cal_scheme: CS,
|
pub cal_scheme: CS,
|
||||||
_phantom: PhantomData<ADCI>,
|
_phantom: PhantomData<ADCI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<PIN, ADCI, CS> Channel<ADCI> for AdcPin<PIN, ADCI, CS>
|
impl<PIN, ADCI, CS> embedded_hal::adc::Channel<ADCI> for AdcPin<PIN, ADCI, CS>
|
||||||
where
|
where
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: embedded_hal::adc::Channel<ADCI, ID = u8>,
|
||||||
{
|
{
|
||||||
type ID = u8;
|
type ID = u8;
|
||||||
|
|
||||||
@ -168,6 +125,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration for the ADC.
|
||||||
pub struct AdcConfig<ADCI> {
|
pub struct AdcConfig<ADCI> {
|
||||||
pub resolution: Resolution,
|
pub resolution: Resolution,
|
||||||
pub attenuations: [Option<Attenuation>; NUM_ATTENS],
|
pub attenuations: [Option<Attenuation>; NUM_ATTENS],
|
||||||
@ -184,9 +142,9 @@ where
|
|||||||
|
|
||||||
pub fn enable_pin<PIN>(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin<PIN, ADCI>
|
pub fn enable_pin<PIN>(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin<PIN, ADCI>
|
||||||
where
|
where
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: AdcChannel,
|
||||||
{
|
{
|
||||||
self.attenuations[PIN::channel() as usize] = Some(attenuation);
|
self.attenuations[PIN::CHANNEL as usize] = Some(attenuation);
|
||||||
|
|
||||||
AdcPin {
|
AdcPin {
|
||||||
pin,
|
pin,
|
||||||
@ -202,10 +160,10 @@ where
|
|||||||
) -> AdcPin<PIN, ADCI, CS>
|
) -> AdcPin<PIN, ADCI, CS>
|
||||||
where
|
where
|
||||||
ADCI: CalibrationAccess,
|
ADCI: CalibrationAccess,
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: AdcChannel,
|
||||||
CS: AdcCalScheme<ADCI>,
|
CS: AdcCalScheme<ADCI>,
|
||||||
{
|
{
|
||||||
self.attenuations[PIN::channel() as usize] = Some(attenuation);
|
self.attenuations[PIN::CHANNEL as usize] = Some(attenuation);
|
||||||
|
|
||||||
AdcPin {
|
AdcPin {
|
||||||
pin,
|
pin,
|
||||||
@ -268,12 +226,6 @@ impl<ADCI> Default for AdcConfig<ADCI> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub enum AdcCalSource {
|
|
||||||
Gnd,
|
|
||||||
Ref,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait RegisterAccess {
|
pub trait RegisterAccess {
|
||||||
/// Configure onetime sampling parameters
|
/// Configure onetime sampling parameters
|
||||||
@ -295,6 +247,7 @@ pub trait RegisterAccess {
|
|||||||
fn set_init_code(data: u16);
|
fn set_init_code(data: u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
pub trait CalibrationAccess: RegisterAccess {
|
pub trait CalibrationAccess: RegisterAccess {
|
||||||
const ADC_CAL_CNT_MAX: u16;
|
const ADC_CAL_CNT_MAX: u16;
|
||||||
const ADC_CAL_CHANNEL: u16;
|
const ADC_CAL_CHANNEL: u16;
|
||||||
@ -306,7 +259,7 @@ pub trait CalibrationAccess: RegisterAccess {
|
|||||||
fn connect_cal(source: AdcCalSource, enable: bool);
|
fn connect_cal(source: AdcCalSource, enable: bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterAccess for ADC1 {
|
impl RegisterAccess for crate::peripherals::ADC1 {
|
||||||
fn config_onetime_sample(channel: u8, attenuation: u8) {
|
fn config_onetime_sample(channel: u8, attenuation: u8) {
|
||||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||||
|
|
||||||
@ -376,7 +329,7 @@ impl RegisterAccess for ADC1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CalibrationAccess for ADC1 {
|
impl CalibrationAccess for crate::peripherals::ADC1 {
|
||||||
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
||||||
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
||||||
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
||||||
@ -417,7 +370,7 @@ impl CalibrationAccess for ADC1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32c3)]
|
#[cfg(esp32c3)]
|
||||||
impl RegisterAccess for ADC2 {
|
impl RegisterAccess for crate::peripherals::ADC2 {
|
||||||
fn config_onetime_sample(channel: u8, attenuation: u8) {
|
fn config_onetime_sample(channel: u8, attenuation: u8) {
|
||||||
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
let sar_adc = unsafe { &*APB_SARADC::PTR };
|
||||||
|
|
||||||
@ -486,7 +439,7 @@ impl RegisterAccess for ADC2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32c3)]
|
#[cfg(esp32c3)]
|
||||||
impl CalibrationAccess for ADC2 {
|
impl CalibrationAccess for crate::peripherals::ADC2 {
|
||||||
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
||||||
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
||||||
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
||||||
@ -526,6 +479,7 @@ impl CalibrationAccess for ADC2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Analog-to-Digital Converter peripheral driver.
|
||||||
pub struct ADC<'d, ADCI> {
|
pub struct ADC<'d, ADCI> {
|
||||||
_adc: PeripheralRef<'d, ADCI>,
|
_adc: PeripheralRef<'d, ADCI>,
|
||||||
attenuations: [Option<Attenuation>; NUM_ATTENS],
|
attenuations: [Option<Attenuation>; NUM_ATTENS],
|
||||||
@ -564,7 +518,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
||||||
impl AdcCalEfuse for ADC1 {
|
impl AdcCalEfuse for crate::peripherals::ADC1 {
|
||||||
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
||||||
Efuse::get_rtc_calib_init_code(1, atten)
|
Efuse::get_rtc_calib_init_code(1, atten)
|
||||||
}
|
}
|
||||||
@ -579,7 +533,7 @@ impl AdcCalEfuse for ADC1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32c3)]
|
#[cfg(esp32c3)]
|
||||||
impl AdcCalEfuse for ADC2 {
|
impl AdcCalEfuse for crate::peripherals::ADC2 {
|
||||||
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
||||||
Efuse::get_rtc_calib_init_code(2, atten)
|
Efuse::get_rtc_calib_init_code(2, atten)
|
||||||
}
|
}
|
||||||
@ -593,15 +547,18 @@ impl AdcCalEfuse for ADC2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, ADCI, PIN, CS> OneShot<ADCI, u16, AdcPin<PIN, ADCI, CS>> for ADC<'d, ADCI>
|
impl<'d, ADCI, PIN, CS> embedded_hal::adc::OneShot<ADCI, u16, AdcPin<PIN, ADCI, CS>>
|
||||||
|
for ADC<'d, ADCI>
|
||||||
where
|
where
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: embedded_hal::adc::Channel<ADCI, ID = u8>,
|
||||||
ADCI: RegisterAccess,
|
ADCI: RegisterAccess,
|
||||||
CS: AdcCalScheme<ADCI>,
|
CS: AdcCalScheme<ADCI>,
|
||||||
{
|
{
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn read(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>) -> nb::Result<u16, Self::Error> {
|
fn read(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>) -> nb::Result<u16, Self::Error> {
|
||||||
|
use embedded_hal::adc::Channel;
|
||||||
|
|
||||||
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
||||||
panic!(
|
panic!(
|
||||||
"Channel {} is not configured reading!",
|
"Channel {} is not configured reading!",
|
||||||
@ -676,8 +633,11 @@ macro_rules! impl_adc_interface {
|
|||||||
($adc:ident [
|
($adc:ident [
|
||||||
$( ($pin:ident, $channel:expr) ,)+
|
$( ($pin:ident, $channel:expr) ,)+
|
||||||
]) => {
|
]) => {
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
impl $crate::analog::adc::AdcChannel for crate::gpio::$pin<crate::gpio::Analog> {
|
||||||
|
const CHANNEL: u8 = $channel;
|
||||||
|
}
|
||||||
|
|
||||||
impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin<crate::gpio::Analog> {
|
impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin<crate::gpio::Analog> {
|
||||||
type ID = u8;
|
type ID = u8;
|
||||||
|
|
||||||
@ -689,38 +649,7 @@ macro_rules! impl_adc_interface {
|
|||||||
|
|
||||||
#[cfg(esp32c2)]
|
#[cfg(esp32c2)]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
//! # Analog to digital (ADC) conversion support.
|
use crate::peripherals::ADC1;
|
||||||
//!
|
|
||||||
//! ## Overview
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world
|
|
||||||
//! analog signals with high accuracy.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for reading analog values from the
|
|
||||||
//! analog to digital converter available on the ESP32-C2: `ADC1`.
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//! #### ADC on Risc-V architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.APB_SARADC.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
|
||||||
//! println!("PIN2 ADC reading = {}", pin_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use crate::analog::ADC1;
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
impl_adc_interface! {
|
||||||
ADC1 [
|
ADC1 [
|
||||||
@ -735,39 +664,7 @@ mod implementation {
|
|||||||
|
|
||||||
#[cfg(esp32c3)]
|
#[cfg(esp32c3)]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
//! # Analog to digital (ADC) conversion support.
|
use crate::peripherals::{ADC1, ADC2};
|
||||||
//!
|
|
||||||
//! ## Overview
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world
|
|
||||||
//! analog signals with high accuracy.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for reading analog values from the
|
|
||||||
//! analog to digital converter available on the ESP32-C3: `ADC1` and
|
|
||||||
//! `ADC2`.
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//! #### ADC on Risc-V architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.APB_SARADC.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
|
||||||
//! println!("PIN2 ADC reading = {}", pin_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use crate::analog::{ADC1, ADC2};
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
impl_adc_interface! {
|
||||||
ADC1 [
|
ADC1 [
|
||||||
@ -788,38 +685,7 @@ mod implementation {
|
|||||||
|
|
||||||
#[cfg(esp32c6)]
|
#[cfg(esp32c6)]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
//! # Analog to digital (ADC) conversion support.
|
use crate::peripherals::ADC1;
|
||||||
//!
|
|
||||||
//! ## Overview
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world
|
|
||||||
//! analog signals with high accuracy.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for reading analog values from the
|
|
||||||
//! analog to digital converter available on the ESP32-C6: `ADC1`.
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//! #### ADC on Risc-V architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.APB_SARADC.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
|
||||||
//! println!("PIN2 ADC reading = {}", pin_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use crate::analog::ADC1;
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
impl_adc_interface! {
|
||||||
ADC1 [
|
ADC1 [
|
||||||
@ -836,38 +702,7 @@ mod implementation {
|
|||||||
|
|
||||||
#[cfg(esp32h2)]
|
#[cfg(esp32h2)]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
//! # Analog to digital (ADC) conversion support.
|
use crate::peripherals::ADC1;
|
||||||
//!
|
|
||||||
//! ## Overview
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world
|
|
||||||
//! analog signals with high accuracy.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for reading analog values from the
|
|
||||||
//! analog to digital converter available on the ESP32-H2: `ADC1`.
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//! #### ADC on Risc-V architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.APB_SARADC.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
|
||||||
//! println!("PIN2 ADC reading = {}", pin_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use crate::analog::ADC1;
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
impl_adc_interface! {
|
||||||
ADC1 [
|
ADC1 [
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use embedded_hal::adc::{Channel, OneShot};
|
pub use self::calibration::*;
|
||||||
|
#[cfg(esp32s3)]
|
||||||
pub use crate::analog::{ADC1, ADC2};
|
use super::AdcCalEfuse;
|
||||||
|
use super::{AdcCalScheme, AdcCalSource, AdcChannel, Attenuation};
|
||||||
#[cfg(esp32s3)]
|
#[cfg(esp32s3)]
|
||||||
use crate::efuse::Efuse;
|
use crate::efuse::Efuse;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -10,21 +11,7 @@ use crate::{
|
|||||||
peripherals::{APB_SARADC, SENS},
|
peripherals::{APB_SARADC, SENS},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
mod calibration;
|
||||||
mod cal_basic;
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
mod cal_curve;
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
mod cal_line;
|
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
pub use cal_basic::AdcCalBasic;
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
pub use cal_curve::{AdcCalCurve, AdcHasCurveCal};
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
pub use cal_line::{AdcCalLine, AdcHasLineCal};
|
|
||||||
|
|
||||||
pub use crate::analog::{AdcCalEfuse, AdcCalScheme};
|
|
||||||
|
|
||||||
// Constants taken from:
|
// Constants taken from:
|
||||||
// https://github.com/espressif/esp-idf/blob/903af13e8/components/soc/esp32s2/include/soc/regi2c_saradc.h
|
// https://github.com/espressif/esp-idf/blob/903af13e8/components/soc/esp32s2/include/soc/regi2c_saradc.h
|
||||||
@ -85,44 +72,22 @@ cfg_if::cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The sampling/readout resolution of the ADC
|
/// The sampling/readout resolution of the ADC.
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum Resolution {
|
pub enum Resolution {
|
||||||
Resolution13Bit,
|
Resolution13Bit,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The attenuation of the ADC pin
|
/// An I/O pin which can be read using the ADC.
|
||||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
|
||||||
pub enum Attenuation {
|
|
||||||
/// 0 dB attenuation, measurement range: 0 - 800 mV
|
|
||||||
Attenuation0dB = 0b00,
|
|
||||||
/// 2.5 dB attenuation, measurement range: 0 - 1100 mV
|
|
||||||
Attenuation2p5dB = 0b01,
|
|
||||||
/// 6 dB attenuation, measurement range: 0 - 1350 mV
|
|
||||||
Attenuation6dB = 0b10,
|
|
||||||
/// 11 dB attenuation, measurement range: 0 - 2600 mV
|
|
||||||
Attenuation11dB = 0b11,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Attenuation {
|
|
||||||
/// List of all supported attenuations
|
|
||||||
pub const ALL: &'static [Attenuation] = &[
|
|
||||||
Attenuation::Attenuation0dB,
|
|
||||||
Attenuation::Attenuation2p5dB,
|
|
||||||
Attenuation::Attenuation6dB,
|
|
||||||
Attenuation::Attenuation11dB,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AdcPin<PIN, ADCI, CS = ()> {
|
pub struct AdcPin<PIN, ADCI, CS = ()> {
|
||||||
pub pin: PIN,
|
pub pin: PIN,
|
||||||
pub cal_scheme: CS,
|
pub cal_scheme: CS,
|
||||||
_phantom: PhantomData<ADCI>,
|
_phantom: PhantomData<ADCI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<PIN, ADCI, CS> Channel<ADCI> for AdcPin<PIN, ADCI, CS>
|
impl<PIN, ADCI, CS> embedded_hal::adc::Channel<ADCI> for AdcPin<PIN, ADCI, CS>
|
||||||
where
|
where
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: embedded_hal::adc::Channel<ADCI, ID = u8>,
|
||||||
{
|
{
|
||||||
type ID = u8;
|
type ID = u8;
|
||||||
|
|
||||||
@ -131,6 +96,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration for the ADC.
|
||||||
pub struct AdcConfig<ADCI> {
|
pub struct AdcConfig<ADCI> {
|
||||||
pub resolution: Resolution,
|
pub resolution: Resolution,
|
||||||
pub attenuations: [Option<Attenuation>; 10],
|
pub attenuations: [Option<Attenuation>; 10],
|
||||||
@ -147,9 +113,9 @@ where
|
|||||||
|
|
||||||
pub fn enable_pin<PIN>(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin<PIN, ADCI>
|
pub fn enable_pin<PIN>(&mut self, pin: PIN, attenuation: Attenuation) -> AdcPin<PIN, ADCI>
|
||||||
where
|
where
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: AdcChannel,
|
||||||
{
|
{
|
||||||
self.attenuations[PIN::channel() as usize] = Some(attenuation);
|
self.attenuations[PIN::CHANNEL as usize] = Some(attenuation);
|
||||||
|
|
||||||
AdcPin {
|
AdcPin {
|
||||||
pin,
|
pin,
|
||||||
@ -165,10 +131,10 @@ where
|
|||||||
) -> AdcPin<PIN, ADCI, CS>
|
) -> AdcPin<PIN, ADCI, CS>
|
||||||
where
|
where
|
||||||
ADCI: CalibrationAccess,
|
ADCI: CalibrationAccess,
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: AdcChannel,
|
||||||
CS: AdcCalScheme<ADCI>,
|
CS: AdcCalScheme<ADCI>,
|
||||||
{
|
{
|
||||||
self.attenuations[PIN::channel() as usize] = Some(attenuation);
|
self.attenuations[PIN::CHANNEL as usize] = Some(attenuation);
|
||||||
|
|
||||||
AdcPin {
|
AdcPin {
|
||||||
pin,
|
pin,
|
||||||
@ -233,12 +199,6 @@ impl<ADCI> Default for AdcConfig<ADCI> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub enum AdcCalSource {
|
|
||||||
Gnd,
|
|
||||||
Ref,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait RegisterAccess {
|
pub trait RegisterAccess {
|
||||||
fn adc_samplecfg(channel: u16);
|
fn adc_samplecfg(channel: u16);
|
||||||
@ -270,6 +230,7 @@ pub trait RegisterAccess {
|
|||||||
fn reset();
|
fn reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
pub trait CalibrationAccess: RegisterAccess {
|
pub trait CalibrationAccess: RegisterAccess {
|
||||||
const ADC_CAL_CNT_MAX: u16;
|
const ADC_CAL_CNT_MAX: u16;
|
||||||
const ADC_CAL_CHANNEL: u16;
|
const ADC_CAL_CHANNEL: u16;
|
||||||
@ -281,7 +242,7 @@ pub trait CalibrationAccess: RegisterAccess {
|
|||||||
fn connect_cal(source: AdcCalSource, enable: bool);
|
fn connect_cal(source: AdcCalSource, enable: bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterAccess for ADC1 {
|
impl RegisterAccess for crate::peripherals::ADC1 {
|
||||||
fn adc_samplecfg(channel: u16) {
|
fn adc_samplecfg(channel: u16) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
let sensors = unsafe { &*SENS::ptr() };
|
||||||
|
|
||||||
@ -395,7 +356,7 @@ impl RegisterAccess for ADC1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
#[cfg(esp32s3)]
|
||||||
impl CalibrationAccess for ADC1 {
|
impl CalibrationAccess for crate::peripherals::ADC1 {
|
||||||
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
||||||
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
||||||
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
||||||
@ -416,7 +377,7 @@ impl CalibrationAccess for ADC1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterAccess for ADC2 {
|
impl RegisterAccess for crate::peripherals::ADC2 {
|
||||||
fn adc_samplecfg(channel: u16) {
|
fn adc_samplecfg(channel: u16) {
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
let sensors = unsafe { &*SENS::ptr() };
|
||||||
|
|
||||||
@ -531,7 +492,7 @@ impl RegisterAccess for ADC2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
#[cfg(esp32s3)]
|
||||||
impl CalibrationAccess for ADC2 {
|
impl CalibrationAccess for crate::peripherals::ADC2 {
|
||||||
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
const ADC_CAL_CNT_MAX: u16 = ADC_CAL_CNT_MAX;
|
||||||
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
const ADC_CAL_CHANNEL: u16 = ADC_CAL_CHANNEL;
|
||||||
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
const ADC_VAL_MASK: u16 = ADC_VAL_MASK;
|
||||||
@ -552,6 +513,7 @@ impl CalibrationAccess for ADC2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Analog-to-Digital Converter peripheral driver.
|
||||||
pub struct ADC<'d, ADC> {
|
pub struct ADC<'d, ADC> {
|
||||||
_adc: PeripheralRef<'d, ADC>,
|
_adc: PeripheralRef<'d, ADC>,
|
||||||
attenuations: [Option<Attenuation>; 10],
|
attenuations: [Option<Attenuation>; 10],
|
||||||
@ -641,7 +603,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
#[cfg(esp32s3)]
|
||||||
impl AdcCalEfuse for ADC1 {
|
impl AdcCalEfuse for crate::peripherals::ADC1 {
|
||||||
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
||||||
Efuse::get_rtc_calib_init_code(1, atten)
|
Efuse::get_rtc_calib_init_code(1, atten)
|
||||||
}
|
}
|
||||||
@ -656,7 +618,7 @@ impl AdcCalEfuse for ADC1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
#[cfg(esp32s3)]
|
||||||
impl AdcCalEfuse for ADC2 {
|
impl AdcCalEfuse for crate::peripherals::ADC2 {
|
||||||
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
fn get_init_code(atten: Attenuation) -> Option<u16> {
|
||||||
Efuse::get_rtc_calib_init_code(2, atten)
|
Efuse::get_rtc_calib_init_code(2, atten)
|
||||||
}
|
}
|
||||||
@ -670,15 +632,18 @@ impl AdcCalEfuse for ADC2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, ADCI, PIN, CS> OneShot<ADCI, u16, AdcPin<PIN, ADCI, CS>> for ADC<'d, ADCI>
|
impl<'d, ADCI, PIN, CS> embedded_hal::adc::OneShot<ADCI, u16, AdcPin<PIN, ADCI, CS>>
|
||||||
|
for ADC<'d, ADCI>
|
||||||
where
|
where
|
||||||
PIN: Channel<ADCI, ID = u8>,
|
PIN: embedded_hal::adc::Channel<ADCI, ID = u8>,
|
||||||
ADCI: RegisterAccess,
|
ADCI: RegisterAccess,
|
||||||
CS: AdcCalScheme<ADCI>,
|
CS: AdcCalScheme<ADCI>,
|
||||||
{
|
{
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn read(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>) -> nb::Result<u16, Self::Error> {
|
fn read(&mut self, pin: &mut AdcPin<PIN, ADCI, CS>) -> nb::Result<u16, Self::Error> {
|
||||||
|
use embedded_hal::adc::Channel;
|
||||||
|
|
||||||
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
if self.attenuations[AdcPin::<PIN, ADCI>::channel() as usize] == None {
|
||||||
panic!(
|
panic!(
|
||||||
"Channel {} is not configured reading!",
|
"Channel {} is not configured reading!",
|
||||||
@ -732,6 +697,10 @@ macro_rules! impl_adc_interface {
|
|||||||
]) => {
|
]) => {
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
impl $crate::analog::adc::AdcChannel for crate::gpio::$pin<crate::gpio::Analog> {
|
||||||
|
const CHANNEL: u8 = $channel;
|
||||||
|
}
|
||||||
|
|
||||||
impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin<crate::gpio::Analog> {
|
impl embedded_hal::adc::Channel<$adc> for crate::gpio::$pin<crate::gpio::Analog> {
|
||||||
type ID = u8;
|
type ID = u8;
|
||||||
|
|
||||||
@ -741,44 +710,8 @@ macro_rules! impl_adc_interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use implementation::*;
|
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
|
||||||
mod implementation {
|
mod implementation {
|
||||||
//! # Analog to digital (ADC) conversion support.
|
use crate::peripherals::{ADC1, ADC2};
|
||||||
//!
|
|
||||||
//! ## Overview
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world
|
|
||||||
//! analog signals with high accuracy.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for reading analog values from the
|
|
||||||
//! analog to digital converter available on the ESP32-S3: `ADC1` and
|
|
||||||
//! `ADC2`.
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//! #### ADC on Xtensa architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.SENS.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin3 =
|
|
||||||
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
|
|
||||||
//! println!("PIN3 ADC reading = {}", pin3_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use crate::analog::{ADC1, ADC2};
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
impl_adc_interface! {
|
||||||
ADC1 [
|
ADC1 [
|
||||||
@ -791,75 +724,7 @@ mod implementation {
|
|||||||
(Gpio7, 6),
|
(Gpio7, 6),
|
||||||
(Gpio8, 7),
|
(Gpio8, 7),
|
||||||
(Gpio9, 8),
|
(Gpio9, 8),
|
||||||
(Gpio10,9),
|
(Gpio10, 9),
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
|
||||||
ADC2 [
|
|
||||||
(Gpio11, 0),
|
|
||||||
(Gpio12, 1),
|
|
||||||
(Gpio13, 2),
|
|
||||||
(Gpio14, 3),
|
|
||||||
(Gpio15, 4),
|
|
||||||
(Gpio16, 5),
|
|
||||||
(Gpio17, 6),
|
|
||||||
(Gpio18, 7),
|
|
||||||
(Gpio19, 8),
|
|
||||||
(Gpio20, 9),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(esp32s2)]
|
|
||||||
mod implementation {
|
|
||||||
//! # Analog to digital (ADC) conversion support.
|
|
||||||
//!
|
|
||||||
//! ## Overview
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world
|
|
||||||
//! analog signals with high accuracy.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for reading analog values from the
|
|
||||||
//! analog to digital converter available on the ESP32-S2: `ADC1` and
|
|
||||||
//! `ADC2`.
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//! #### ADC on Xtensa architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.SENS.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin3 =
|
|
||||||
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
|
|
||||||
//! println!("PIN3 ADC reading = {}", pin3_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use crate::analog::{ADC1, ADC2};
|
|
||||||
|
|
||||||
impl_adc_interface! {
|
|
||||||
ADC1 [
|
|
||||||
(Gpio1, 0),
|
|
||||||
(Gpio2, 1),
|
|
||||||
(Gpio3, 2),
|
|
||||||
(Gpio4, 3),
|
|
||||||
(Gpio5, 4),
|
|
||||||
(Gpio6, 5),
|
|
||||||
(Gpio7, 6),
|
|
||||||
(Gpio8, 7),
|
|
||||||
(Gpio9, 8),
|
|
||||||
(Gpio10,9),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,159 +1,127 @@
|
|||||||
//! # Analog peripherals - Digital to Analog Converter
|
//! # Digital to Analog Converter (DAC)
|
||||||
//!
|
//!
|
||||||
//! ## Overview
|
//! The `dac` module enables users to generate analog output signals with
|
||||||
//! The `DAC` module is part of the `Analog` driver designed for ESP
|
//! precise control over voltage levels using one of the onboard
|
||||||
//! microcontrollers, providing functionalities for `digital-to-analog`
|
//! digital-to-analog converters (DAC).
|
||||||
//! conversion.
|
|
||||||
//!
|
//!
|
||||||
//! This module simplifies digital-to-analog conversion on ESP microcontrollers,
|
//! Two 8-bit DAC channels are available. Each DAC channel can convert the
|
||||||
//! enabling precise control over analog output signals. Developers can choose
|
//! digital value 0-255 to the analog voltage 0-3.3v. Developers can choose the
|
||||||
//! the `DAC` channel they want to use based on the GPIO pin assignments for
|
//! DAC channel they want to use based on the GPIO pin assignments for each
|
||||||
//! each channel. By providing a unified interface for DAC control, the module
|
//! channel.
|
||||||
//! makes it easier for users to generate accurate analog voltages in their
|
//!
|
||||||
//! applications, such as audio generation, sensor calibration, and analog
|
//! ## Example
|
||||||
//! signal synthesis.
|
//!
|
||||||
use crate::peripherals::{RTC_IO, SENS};
|
//! ```no_run
|
||||||
pub trait DAC {
|
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
fn write(&mut self, value: u8);
|
//! let gpio25 = io.pins.gpio25.into_analog();
|
||||||
|
//! let gpio26 = io.pins.gpio26.into_analog();
|
||||||
|
//!
|
||||||
|
//! let mut dac1 = DAC1::new(peripherals.DAC1, gpio25);
|
||||||
|
//! let mut dac2 = DAC2::new(peripherals.DAC2, gpio26);
|
||||||
|
//!
|
||||||
|
//! let mut delay = Delay::new(&clocks);
|
||||||
|
//!
|
||||||
|
//! let mut voltage_dac1 = 200u8;
|
||||||
|
//! let mut voltage_dac2 = 255u8;
|
||||||
|
//!
|
||||||
|
//! // Change voltage on the pins using write function:
|
||||||
|
//! loop {
|
||||||
|
//! voltage_dac1 = voltage_dac1.wrapping_add(1);
|
||||||
|
//! dac1.write(voltage_dac1);
|
||||||
|
//!
|
||||||
|
//! voltage_dac2 = voltage_dac2.wrapping_sub(1);
|
||||||
|
//! dac2.write(voltage_dac2);
|
||||||
|
//!
|
||||||
|
//! delay.delay_ms(50u32);
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
gpio,
|
||||||
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
|
peripherals,
|
||||||
|
};
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(esp32)] {
|
||||||
|
type Dac1Gpio = gpio::Gpio25<gpio::Analog>;
|
||||||
|
type Dac2Gpio = gpio::Gpio26<gpio::Analog>;
|
||||||
|
} else if #[cfg(esp32s2)] {
|
||||||
|
type Dac1Gpio = gpio::Gpio17<gpio::Analog>;
|
||||||
|
type Dac2Gpio = gpio::Gpio18<gpio::Analog>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DAC1Impl {
|
/// Digital-to-Analog Converter (DAC) Channel 1
|
||||||
fn set_power(self) -> Self
|
pub struct DAC1<'d> {
|
||||||
where
|
_inner: PeripheralRef<'d, peripherals::DAC1>,
|
||||||
Self: Sized,
|
}
|
||||||
{
|
|
||||||
|
impl<'d> DAC1<'d> {
|
||||||
|
/// Constructs a new DAC instance.
|
||||||
|
pub fn new(dac: impl Peripheral<P = peripherals::DAC1> + 'd, _pin: Dac1Gpio) -> Self {
|
||||||
|
crate::into_ref!(dac);
|
||||||
|
|
||||||
#[cfg(esp32s2)]
|
#[cfg(esp32s2)]
|
||||||
{
|
unsafe { &*peripherals::SENS::PTR }
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
|
||||||
sensors
|
|
||||||
.sar_dac_ctrl1()
|
.sar_dac_ctrl1()
|
||||||
.modify(|_, w| w.dac_clkgate_en().set_bit());
|
.modify(|_, w| w.dac_clkgate_en().set_bit());
|
||||||
|
|
||||||
|
unsafe { &*peripherals::RTC_IO::PTR }
|
||||||
|
.pad_dac1()
|
||||||
|
.modify(|_, w| w.pdac1_dac_xpd_force().set_bit().pdac1_xpd_dac().set_bit());
|
||||||
|
|
||||||
|
Self { _inner: dac }
|
||||||
}
|
}
|
||||||
|
|
||||||
let rtcio = unsafe { &*RTC_IO::ptr() };
|
/// Writes the given value.
|
||||||
|
///
|
||||||
rtcio.pad_dac1().modify(|_, w| {
|
/// For each DAC channel, the output analog voltage can be calculated as
|
||||||
w.pdac1_dac_xpd_force().set_bit();
|
/// follows: DACn_OUT = VDD3P3_RTC * PDACn_DAC/256
|
||||||
w.pdac1_xpd_dac().set_bit()
|
pub fn write(&mut self, value: u8) {
|
||||||
});
|
unsafe { &*crate::peripherals::SENS::PTR }
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write(&mut self, value: u8) {
|
|
||||||
let rtcio = unsafe { &*RTC_IO::ptr() };
|
|
||||||
|
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
|
||||||
sensors
|
|
||||||
.sar_dac_ctrl2()
|
.sar_dac_ctrl2()
|
||||||
.modify(|_, w| w.dac_cw_en1().clear_bit());
|
.modify(|_, w| w.dac_cw_en1().clear_bit());
|
||||||
|
|
||||||
rtcio
|
unsafe { &*crate::peripherals::RTC_IO::PTR }
|
||||||
.pad_dac1()
|
.pad_dac1()
|
||||||
.modify(|_, w| unsafe { w.pdac1_dac().bits(value) });
|
.modify(|_, w| unsafe { w.pdac1_dac().bits(value) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DAC2Impl {
|
/// Digital-to-Analog Converter (DAC) Channel 2
|
||||||
fn set_power(self) -> Self
|
pub struct DAC2<'d> {
|
||||||
where
|
_inner: PeripheralRef<'d, peripherals::DAC2>,
|
||||||
Self: Sized,
|
}
|
||||||
{
|
|
||||||
|
impl<'d> DAC2<'d> {
|
||||||
|
/// Constructs a new DAC instance.
|
||||||
|
pub fn new(dac: impl Peripheral<P = peripherals::DAC2> + 'd, _pin: Dac2Gpio) -> Self {
|
||||||
|
crate::into_ref!(dac);
|
||||||
|
|
||||||
#[cfg(esp32s2)]
|
#[cfg(esp32s2)]
|
||||||
{
|
unsafe { &*peripherals::SENS::PTR }
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
|
||||||
sensors
|
|
||||||
.sar_dac_ctrl1()
|
.sar_dac_ctrl1()
|
||||||
.modify(|_, w| w.dac_clkgate_en().set_bit());
|
.modify(|_, w| w.dac_clkgate_en().set_bit());
|
||||||
|
|
||||||
|
unsafe { &*peripherals::RTC_IO::PTR }
|
||||||
|
.pad_dac2()
|
||||||
|
.modify(|_, w| w.pdac2_dac_xpd_force().set_bit().pdac2_xpd_dac().set_bit());
|
||||||
|
|
||||||
|
Self { _inner: dac }
|
||||||
}
|
}
|
||||||
|
|
||||||
let rtcio = unsafe { &*RTC_IO::ptr() };
|
/// Writes the given value.
|
||||||
|
///
|
||||||
rtcio.pad_dac2().modify(|_, w| {
|
/// For each DAC channel, the output analog voltage can be calculated as
|
||||||
w.pdac2_dac_xpd_force().set_bit();
|
/// follows: DACn_OUT = VDD3P3_RTC * PDACn_DAC/256
|
||||||
w.pdac2_xpd_dac().set_bit()
|
pub fn write(&mut self, value: u8) {
|
||||||
});
|
unsafe { &*crate::peripherals::SENS::PTR }
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write(&mut self, value: u8) {
|
|
||||||
let rtcio = unsafe { &*RTC_IO::ptr() };
|
|
||||||
|
|
||||||
let sensors = unsafe { &*SENS::ptr() };
|
|
||||||
sensors
|
|
||||||
.sar_dac_ctrl2()
|
.sar_dac_ctrl2()
|
||||||
.modify(|_, w| w.dac_cw_en2().clear_bit());
|
.modify(|_, w| w.dac_cw_en2().clear_bit());
|
||||||
|
|
||||||
rtcio
|
unsafe { &*crate::peripherals::RTC_IO::PTR }
|
||||||
.pad_dac2()
|
.pad_dac2()
|
||||||
.modify(|_, w| unsafe { w.pdac2_dac().bits(value) });
|
.modify(|_, w| unsafe { w.pdac2_dac().bits(value) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_dac {
|
|
||||||
($($number:literal => $gpio:ident),+) => {
|
|
||||||
$(
|
|
||||||
paste::paste! {
|
|
||||||
use $crate::analog::dac::[<DAC $number Impl>];
|
|
||||||
|
|
||||||
#[doc = "DAC channel " $number]
|
|
||||||
pub struct [<DAC $number>]<'d, DAC> {
|
|
||||||
_dac: $crate::peripheral::PeripheralRef<'d, DAC>,
|
|
||||||
_private: ::core::marker::PhantomData<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, DAC> [<DAC $number Impl>] for [<DAC $number>]<'d, DAC> {}
|
|
||||||
|
|
||||||
impl<'d, DAC> [<DAC $number>]<'d, DAC> {
|
|
||||||
/// Constructs a new DAC instance
|
|
||||||
pub fn dac(
|
|
||||||
dac: impl $crate::peripheral::Peripheral<P = DAC> +'d,
|
|
||||||
_pin: $crate::gpio::$gpio<$crate::gpio::Analog>,
|
|
||||||
) -> Result<Self, ()> {
|
|
||||||
let dac = Self {
|
|
||||||
_dac: dac.into_ref(),
|
|
||||||
_private: ::core::marker::PhantomData,
|
|
||||||
}
|
|
||||||
.set_power();
|
|
||||||
Ok(dac)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes the given value
|
|
||||||
///
|
|
||||||
/// For each DAC channel, the output analog voltage can be calculated as follows:
|
|
||||||
/// DACn_OUT = VDD3P3_RTC * PDACn_DAC/256
|
|
||||||
pub fn write(&mut self, value: u8) {
|
|
||||||
[<DAC $number Impl>]::write(self, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use implementation::*;
|
|
||||||
|
|
||||||
#[cfg(esp32)]
|
|
||||||
mod implementation {
|
|
||||||
//! Digital to analog (DAC) conversion.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for controlling two digital to
|
|
||||||
//! analog converters, available on ESP32: `DAC1` and `DAC2`.
|
|
||||||
//!
|
|
||||||
//! The DAC1 is available on the GPIO pin 25, and DAC2 on pin 26.
|
|
||||||
|
|
||||||
impl_dac!(1 => Gpio25, 2 => Gpio26);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(esp32s2)]
|
|
||||||
mod implementation {
|
|
||||||
//! Digital to analog (DAC) conversion.
|
|
||||||
//!
|
|
||||||
//! This module provides functions for controlling two digital to
|
|
||||||
//! analog converters, available on ESP32-S2: `DAC1` and `DAC2`.
|
|
||||||
//!
|
|
||||||
//! The DAC1 is available on the GPIO pin 17, and DAC2 on pin 18.
|
|
||||||
|
|
||||||
impl_dac!(1 => Gpio17, 2 => Gpio18);
|
|
||||||
}
|
|
||||||
|
@ -1,260 +1,10 @@
|
|||||||
//! # Analog peripherals
|
//! # Analog Peripherals
|
||||||
//!
|
//!
|
||||||
//! ## Overview
|
//! The `analog` module provides drivers for the various analog peripherals
|
||||||
//! The `Analog` Driver is a module designed for ESP microcontrollers, that
|
//! available on the device. For more information about a peripheral driver,
|
||||||
//! provides an interface to interact with analog peripherals on the chip. The
|
//! please refer to the relevant module documentation.
|
||||||
//! module includes support for `Analog-to-Digital Converters (ADC)` and
|
|
||||||
//! `Digital-to-Analog Converters (DAC)`, offering functionality for precise
|
|
||||||
//! analog measurements and generating analog output signals.
|
|
||||||
//!
|
|
||||||
//! The `ADC` module in the `analog` driver enables users to perform
|
|
||||||
//! analog-to-digital conversions, allowing them to measure real-world analog
|
|
||||||
//! signals with high accuracy. The module provides access to multiple ADC
|
|
||||||
//! units, such as `ADC1` and `ADC2`, which may differ based on the specific ESP
|
|
||||||
//! microcontroller being used.
|
|
||||||
//!
|
|
||||||
//! The `DAC` module in the `analog` driver enables users to generate
|
|
||||||
//! analog output signals with precise control over voltage levels. The module
|
|
||||||
//! supports multiple DAC units, such as `DAC1` and `DAC2`, which may vary
|
|
||||||
//! depending on the specific ESP microcontroller.
|
|
||||||
//!
|
|
||||||
//! #### Xtensa architecture
|
|
||||||
//! For ESP microcontrollers using the `Xtensa` architecture, the driver
|
|
||||||
//! provides access to the `SENS` peripheral, allowing users to split it into
|
|
||||||
//! independent parts using the [`AnalogExt`] trait. This extension trait
|
|
||||||
//! provides access to the following analog peripherals:
|
|
||||||
//! * ADC1
|
|
||||||
//! * ADC2
|
|
||||||
//! * DAC1
|
|
||||||
//! * DAC2
|
|
||||||
//!
|
|
||||||
//! #### RISC-V architecture
|
|
||||||
//! For ESP microcontrollers using the `RISC-V` architecture, the driver
|
|
||||||
//! provides access to the `APB_SARADC` peripheral. The `AnalogExt` trait allows
|
|
||||||
//! users to split this peripheral into independent parts, providing access to
|
|
||||||
//! the following analog peripheral:
|
|
||||||
//! * ADC1
|
|
||||||
//! * ADC2
|
|
||||||
//!
|
|
||||||
//! ## Examples
|
|
||||||
//! #### ADC on Risc-V architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.APB_SARADC.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap();
|
|
||||||
//! println!("PIN2 ADC reading = {}", pin_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//! #### ADC on Xtensa architecture
|
|
||||||
//! ```no_run
|
|
||||||
//! // Create ADC instances
|
|
||||||
//! let analog = peripherals.SENS.split();
|
|
||||||
//!
|
|
||||||
//! let mut adc1_config = AdcConfig::new();
|
|
||||||
//!
|
|
||||||
//! let mut pin3 =
|
|
||||||
//! adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
|
||||||
//!
|
|
||||||
//! let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
//!
|
|
||||||
//! let mut delay = Delay::new(&clocks);
|
|
||||||
//!
|
|
||||||
//! loop {
|
|
||||||
//! let pin3_value: u16 = nb::block!(adc1.read(&mut pin3)).unwrap();
|
|
||||||
//! println!("PIN3 ADC reading = {}", pin3_value);
|
|
||||||
//! delay.delay_ms(1500u32);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
#[cfg_attr(esp32, path = "adc/esp32.rs")]
|
#[cfg(adc)]
|
||||||
#[cfg_attr(riscv, path = "adc/riscv.rs")]
|
|
||||||
#[cfg_attr(any(esp32s2, esp32s3), path = "adc/xtensa.rs")]
|
|
||||||
pub mod adc;
|
pub mod adc;
|
||||||
#[cfg(dac)]
|
#[cfg(dac)]
|
||||||
pub mod dac;
|
pub mod dac;
|
||||||
|
|
||||||
/// A trait abstracting over calibration methods.
|
|
||||||
///
|
|
||||||
/// The methods in this trait are mostly for internal use. To get
|
|
||||||
/// calibrated ADC reads, all you need to do is call `enable_pin_with_cal`
|
|
||||||
/// and specify some implementor of this trait.
|
|
||||||
pub trait AdcCalScheme<ADCI>: Sized {
|
|
||||||
/// Create a new calibration scheme for the given attenuation.
|
|
||||||
fn new_cal(atten: adc::Attenuation) -> Self;
|
|
||||||
|
|
||||||
/// Return the basic ADC bias value. See [`adc::AdcCalBasic`] for
|
|
||||||
/// details.
|
|
||||||
fn adc_cal(&self) -> u16 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert ADC value
|
|
||||||
fn adc_val(&self, val: u16) -> u16 {
|
|
||||||
val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ADCI> AdcCalScheme<ADCI> for () {
|
|
||||||
fn new_cal(_atten: adc::Attenuation) -> Self {
|
|
||||||
()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A helper trait to get access to ADC calibration efuses
|
|
||||||
pub trait AdcCalEfuse {
|
|
||||||
/// Get ADC calibration init code
|
|
||||||
///
|
|
||||||
/// Returns digital value for zero voltage for a given attenuation
|
|
||||||
fn get_init_code(atten: adc::Attenuation) -> Option<u16>;
|
|
||||||
|
|
||||||
/// Get ADC calibration reference point voltage
|
|
||||||
///
|
|
||||||
/// Returns reference voltage (millivolts) for a given attenuation
|
|
||||||
fn get_cal_mv(atten: adc::Attenuation) -> u16;
|
|
||||||
|
|
||||||
/// Get ADC calibration reference point digital value
|
|
||||||
///
|
|
||||||
/// Returns digital value for reference voltage for a given attenuation
|
|
||||||
fn get_cal_code(atten: adc::Attenuation) -> Option<u16>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ADC1 {
|
|
||||||
_private: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ADC2 {
|
|
||||||
_private: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DAC1 {
|
|
||||||
_private: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DAC2 {
|
|
||||||
_private: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::ops::Deref for ADC1 {
|
|
||||||
type Target = ADC1;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::ops::DerefMut for ADC1 {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::peripheral::Peripheral for ADC1 {
|
|
||||||
type P = ADC1;
|
|
||||||
#[inline]
|
|
||||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
|
||||||
ADC1 { _private: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::peripheral::sealed::Sealed for ADC1 {}
|
|
||||||
|
|
||||||
impl crate::peripheral::Peripheral for ADC2 {
|
|
||||||
type P = ADC2;
|
|
||||||
#[inline]
|
|
||||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
|
||||||
ADC2 { _private: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::peripheral::sealed::Sealed for ADC2 {}
|
|
||||||
|
|
||||||
impl crate::peripheral::Peripheral for DAC1 {
|
|
||||||
type P = DAC1;
|
|
||||||
#[inline]
|
|
||||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
|
||||||
DAC1 { _private: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::peripheral::sealed::Sealed for DAC1 {}
|
|
||||||
|
|
||||||
impl crate::peripheral::Peripheral for DAC2 {
|
|
||||||
type P = DAC2;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
|
||||||
DAC2 { _private: () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::peripheral::sealed::Sealed for DAC2 {}
|
|
||||||
|
|
||||||
/// Extension trait to split a SENS peripheral in independent parts
|
|
||||||
pub trait AnalogExt {
|
|
||||||
fn split(self) -> AvailableAnalog;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(xtensa)] {
|
|
||||||
pub struct AvailableAnalog {
|
|
||||||
pub adc1: ADC1,
|
|
||||||
pub adc2: ADC2,
|
|
||||||
pub dac1: DAC1,
|
|
||||||
pub dac2: DAC2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AnalogExt for crate::peripherals::SENS {
|
|
||||||
fn split(self) -> AvailableAnalog {
|
|
||||||
AvailableAnalog {
|
|
||||||
adc1: ADC1 {
|
|
||||||
_private: (),
|
|
||||||
},
|
|
||||||
adc2: ADC2 {
|
|
||||||
_private: (),
|
|
||||||
},
|
|
||||||
dac1: DAC1 {
|
|
||||||
_private: (),
|
|
||||||
},
|
|
||||||
dac2: DAC2 {
|
|
||||||
_private: (),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
if #[cfg(riscv)] {
|
|
||||||
pub struct AvailableAnalog {
|
|
||||||
pub adc1: ADC1,
|
|
||||||
#[cfg(esp32c3)]
|
|
||||||
pub adc2: ADC2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AnalogExt for crate::peripherals::APB_SARADC {
|
|
||||||
fn split(self) -> AvailableAnalog {
|
|
||||||
AvailableAnalog {
|
|
||||||
adc1: ADC1 {
|
|
||||||
_private: (),
|
|
||||||
},
|
|
||||||
#[cfg(esp32c3)]
|
|
||||||
adc2: ADC2 {
|
|
||||||
_private: (),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -27,8 +27,6 @@ pub use fugit::{
|
|||||||
};
|
};
|
||||||
pub use nb;
|
pub use nb;
|
||||||
|
|
||||||
#[cfg(any(apb_saradc, sens))]
|
|
||||||
pub use crate::analog::AnalogExt as _esp_hal_analog_AnalogExt;
|
|
||||||
#[cfg(any(dport, pcr, system))]
|
#[cfg(any(dport, pcr, system))]
|
||||||
pub use crate::clock::Clock as _esp_hal_clock_Clock;
|
pub use crate::clock::Clock as _esp_hal_clock_Clock;
|
||||||
#[cfg(any(gdma, pdma))]
|
#[cfg(any(gdma, pdma))]
|
||||||
|
@ -20,9 +20,14 @@ pub(crate) use self::peripherals::*;
|
|||||||
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
||||||
// creating "virtual peripherals" for them.
|
// creating "virtual peripherals" for them.
|
||||||
crate::peripherals! {
|
crate::peripherals! {
|
||||||
|
ADC1 <= virtual,
|
||||||
|
ADC2 <= virtual,
|
||||||
AES <= AES,
|
AES <= AES,
|
||||||
APB_CTRL <= APB_CTRL,
|
APB_CTRL <= APB_CTRL,
|
||||||
BB <= BB,
|
BB <= BB,
|
||||||
|
BT <= virtual,
|
||||||
|
DAC1 <= virtual,
|
||||||
|
DAC2 <= virtual,
|
||||||
EFUSE <= EFUSE,
|
EFUSE <= EFUSE,
|
||||||
FLASH_ENCRYPTION <= FLASH_ENCRYPTION,
|
FLASH_ENCRYPTION <= FLASH_ENCRYPTION,
|
||||||
FRC_TIMER <= FRC_TIMER,
|
FRC_TIMER <= FRC_TIMER,
|
||||||
@ -39,6 +44,7 @@ crate::peripherals! {
|
|||||||
MCPWM1 <= MCPWM1,
|
MCPWM1 <= MCPWM1,
|
||||||
NRX <= NRX,
|
NRX <= NRX,
|
||||||
PCNT <= PCNT,
|
PCNT <= PCNT,
|
||||||
|
PSRAM <= virtual,
|
||||||
RMT <= RMT,
|
RMT <= RMT,
|
||||||
RNG <= RNG,
|
RNG <= RNG,
|
||||||
RSA <= RSA,
|
RSA <= RSA,
|
||||||
@ -46,7 +52,6 @@ crate::peripherals! {
|
|||||||
RTC_IO <= RTC_IO,
|
RTC_IO <= RTC_IO,
|
||||||
RTC_I2C <= RTC_I2C,
|
RTC_I2C <= RTC_I2C,
|
||||||
SDHOST <= SDHOST,
|
SDHOST <= SDHOST,
|
||||||
SENS <= SENS,
|
|
||||||
SHA <= SHA,
|
SHA <= SHA,
|
||||||
SLC <= SLC,
|
SLC <= SLC,
|
||||||
SLCHOST <= SLCHOST,
|
SLCHOST <= SLCHOST,
|
||||||
@ -54,7 +59,6 @@ crate::peripherals! {
|
|||||||
SPI1 <= SPI1,
|
SPI1 <= SPI1,
|
||||||
SPI2 <= SPI2,
|
SPI2 <= SPI2,
|
||||||
SPI3 <= SPI3,
|
SPI3 <= SPI3,
|
||||||
// SYSTEM is derived from DPORT:
|
|
||||||
SYSTEM <= DPORT,
|
SYSTEM <= DPORT,
|
||||||
TIMG0 <= TIMG0,
|
TIMG0 <= TIMG0,
|
||||||
TIMG1 <= TIMG1,
|
TIMG1 <= TIMG1,
|
||||||
@ -64,9 +68,5 @@ crate::peripherals! {
|
|||||||
UART2 <= UART2,
|
UART2 <= UART2,
|
||||||
UHCI0 <= UHCI0,
|
UHCI0 <= UHCI0,
|
||||||
UHCI1 <= UHCI1,
|
UHCI1 <= UHCI1,
|
||||||
|
|
||||||
// Virtual peripherals:
|
|
||||||
BT <= virtual,
|
|
||||||
PSRAM <= virtual,
|
|
||||||
WIFI <= virtual,
|
WIFI <= virtual,
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,10 @@ pub(crate) use self::peripherals::*;
|
|||||||
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
||||||
// creating "virtual peripherals" for them.
|
// creating "virtual peripherals" for them.
|
||||||
crate::peripherals! {
|
crate::peripherals! {
|
||||||
|
ADC1 <= virtual,
|
||||||
APB_CTRL <= APB_CTRL,
|
APB_CTRL <= APB_CTRL,
|
||||||
APB_SARADC <= APB_SARADC,
|
|
||||||
ASSIST_DEBUG <= ASSIST_DEBUG,
|
ASSIST_DEBUG <= ASSIST_DEBUG,
|
||||||
|
BT <= virtual,
|
||||||
DMA <= DMA,
|
DMA <= DMA,
|
||||||
ECC <= ECC,
|
ECC <= ECC,
|
||||||
EFUSE <= EFUSE,
|
EFUSE <= EFUSE,
|
||||||
@ -44,9 +45,6 @@ crate::peripherals! {
|
|||||||
TIMG0 <= TIMG0,
|
TIMG0 <= TIMG0,
|
||||||
UART0 <= UART0,
|
UART0 <= UART0,
|
||||||
UART1 <= UART1,
|
UART1 <= UART1,
|
||||||
XTS_AES <= XTS_AES,
|
|
||||||
|
|
||||||
// Virtual peripherals:
|
|
||||||
BT <= virtual,
|
|
||||||
WIFI <= virtual,
|
WIFI <= virtual,
|
||||||
|
XTS_AES <= XTS_AES,
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,12 @@ pub(crate) use self::peripherals::*;
|
|||||||
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
||||||
// creating "virtual peripherals" for them.
|
// creating "virtual peripherals" for them.
|
||||||
crate::peripherals! {
|
crate::peripherals! {
|
||||||
|
ADC1 <= virtual,
|
||||||
|
ADC2 <= virtual,
|
||||||
AES <= AES,
|
AES <= AES,
|
||||||
APB_CTRL <= APB_CTRL,
|
APB_CTRL <= APB_CTRL,
|
||||||
APB_SARADC <= APB_SARADC,
|
|
||||||
ASSIST_DEBUG <= ASSIST_DEBUG,
|
ASSIST_DEBUG <= ASSIST_DEBUG,
|
||||||
|
BT <= virtual,
|
||||||
DMA <= DMA,
|
DMA <= DMA,
|
||||||
DS <= DS,
|
DS <= DS,
|
||||||
EFUSE <= EFUSE,
|
EFUSE <= EFUSE,
|
||||||
@ -55,9 +57,6 @@ crate::peripherals! {
|
|||||||
UHCI0 <= UHCI0,
|
UHCI0 <= UHCI0,
|
||||||
UHCI1 <= UHCI1,
|
UHCI1 <= UHCI1,
|
||||||
USB_DEVICE <= USB_DEVICE,
|
USB_DEVICE <= USB_DEVICE,
|
||||||
XTS_AES <= XTS_AES,
|
|
||||||
|
|
||||||
// Virtual peripherals:
|
|
||||||
BT <= virtual,
|
|
||||||
WIFI <= virtual,
|
WIFI <= virtual,
|
||||||
|
XTS_AES <= XTS_AES,
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,11 @@ pub(crate) use self::peripherals::*;
|
|||||||
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
||||||
// creating "virtual peripherals" for them.
|
// creating "virtual peripherals" for them.
|
||||||
crate::peripherals! {
|
crate::peripherals! {
|
||||||
|
ADC1 <= virtual,
|
||||||
AES <= AES,
|
AES <= AES,
|
||||||
APB_SARADC <= APB_SARADC,
|
|
||||||
ASSIST_DEBUG <= ASSIST_DEBUG,
|
ASSIST_DEBUG <= ASSIST_DEBUG,
|
||||||
ATOMIC <= ATOMIC,
|
ATOMIC <= ATOMIC,
|
||||||
|
BT <= virtual,
|
||||||
DMA <= DMA,
|
DMA <= DMA,
|
||||||
DS <= DS,
|
DS <= DS,
|
||||||
ECC <= ECC,
|
ECC <= ECC,
|
||||||
@ -37,11 +38,13 @@ crate::peripherals! {
|
|||||||
HP_SYS <= HP_SYS,
|
HP_SYS <= HP_SYS,
|
||||||
I2C0 <= I2C0,
|
I2C0 <= I2C0,
|
||||||
I2S0 <= I2S0,
|
I2S0 <= I2S0,
|
||||||
|
IEEE802154 <= virtual,
|
||||||
INTERRUPT_CORE0 <= INTERRUPT_CORE0,
|
INTERRUPT_CORE0 <= INTERRUPT_CORE0,
|
||||||
INTPRI <= INTPRI,
|
INTPRI <= INTPRI,
|
||||||
IO_MUX <= IO_MUX,
|
IO_MUX <= IO_MUX,
|
||||||
LEDC <= LEDC,
|
LEDC <= LEDC,
|
||||||
LPWR <= LP_CLKRST,
|
LPWR <= LP_CLKRST,
|
||||||
|
LP_CORE <= virtual,
|
||||||
LP_PERI <= LP_PERI,
|
LP_PERI <= LP_PERI,
|
||||||
LP_ANA <= LP_ANA,
|
LP_ANA <= LP_ANA,
|
||||||
LP_AON <= LP_AON,
|
LP_AON <= LP_AON,
|
||||||
@ -70,7 +73,6 @@ crate::peripherals! {
|
|||||||
SPI0 <= SPI0,
|
SPI0 <= SPI0,
|
||||||
SPI1 <= SPI1,
|
SPI1 <= SPI1,
|
||||||
SPI2 <= SPI2,
|
SPI2 <= SPI2,
|
||||||
// SYSTEM is derived from PCR
|
|
||||||
SYSTEM <= PCR,
|
SYSTEM <= PCR,
|
||||||
SYSTIMER <= SYSTIMER,
|
SYSTIMER <= SYSTIMER,
|
||||||
TEE <= TEE,
|
TEE <= TEE,
|
||||||
@ -83,10 +85,5 @@ crate::peripherals! {
|
|||||||
UART1 <= UART1,
|
UART1 <= UART1,
|
||||||
UHCI0 <= UHCI0,
|
UHCI0 <= UHCI0,
|
||||||
USB_DEVICE <= USB_DEVICE,
|
USB_DEVICE <= USB_DEVICE,
|
||||||
|
|
||||||
// Virtual peripherals:
|
|
||||||
BT <= virtual,
|
|
||||||
IEEE802154 <= virtual,
|
|
||||||
LP_CORE <= virtual,
|
|
||||||
WIFI <= virtual,
|
WIFI <= virtual,
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,10 @@ pub(crate) use self::peripherals::*;
|
|||||||
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
||||||
// creating "virtual peripherals" for them.
|
// creating "virtual peripherals" for them.
|
||||||
crate::peripherals! {
|
crate::peripherals! {
|
||||||
|
ADC1 <= virtual,
|
||||||
AES <= AES,
|
AES <= AES,
|
||||||
APB_SARADC <= APB_SARADC,
|
|
||||||
ASSIST_DEBUG <= ASSIST_DEBUG,
|
ASSIST_DEBUG <= ASSIST_DEBUG,
|
||||||
|
BT <= virtual,
|
||||||
DMA <= DMA,
|
DMA <= DMA,
|
||||||
DS <= DS,
|
DS <= DS,
|
||||||
ECC <= ECC,
|
ECC <= ECC,
|
||||||
@ -35,6 +36,7 @@ crate::peripherals! {
|
|||||||
I2C0 <= I2C0,
|
I2C0 <= I2C0,
|
||||||
I2C1 <= I2C1,
|
I2C1 <= I2C1,
|
||||||
I2S0 <= I2S0,
|
I2S0 <= I2S0,
|
||||||
|
IEEE802154 <= virtual,
|
||||||
INTERRUPT_CORE0 <= INTERRUPT_CORE0,
|
INTERRUPT_CORE0 <= INTERRUPT_CORE0,
|
||||||
INTPRI <= INTPRI,
|
INTPRI <= INTPRI,
|
||||||
IO_MUX <= IO_MUX,
|
IO_MUX <= IO_MUX,
|
||||||
@ -63,7 +65,6 @@ crate::peripherals! {
|
|||||||
SPI0 <= SPI0,
|
SPI0 <= SPI0,
|
||||||
SPI1 <= SPI1,
|
SPI1 <= SPI1,
|
||||||
SPI2 <= SPI2,
|
SPI2 <= SPI2,
|
||||||
// SYSTEM is derived from PCR:
|
|
||||||
SYSTEM <= PCR,
|
SYSTEM <= PCR,
|
||||||
SYSTIMER <= SYSTIMER,
|
SYSTIMER <= SYSTIMER,
|
||||||
TEE <= TEE,
|
TEE <= TEE,
|
||||||
@ -75,8 +76,4 @@ crate::peripherals! {
|
|||||||
UART1 <= UART1,
|
UART1 <= UART1,
|
||||||
UHCI0 <= UHCI0,
|
UHCI0 <= UHCI0,
|
||||||
USB_DEVICE <= USB_DEVICE,
|
USB_DEVICE <= USB_DEVICE,
|
||||||
|
|
||||||
// Virtual peripherals:
|
|
||||||
BT <= virtual,
|
|
||||||
IEEE802154 <= virtual,
|
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,11 @@ pub(crate) use self::peripherals::*;
|
|||||||
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
||||||
// creating "virtual peripherals" for them.
|
// creating "virtual peripherals" for them.
|
||||||
crate::peripherals! {
|
crate::peripherals! {
|
||||||
|
ADC1 <= virtual,
|
||||||
|
ADC2 <= virtual,
|
||||||
AES <= AES,
|
AES <= AES,
|
||||||
APB_SARADC <= APB_SARADC,
|
DAC1 <= virtual,
|
||||||
|
DAC2 <= virtual,
|
||||||
DEDICATED_GPIO <= DEDICATED_GPIO,
|
DEDICATED_GPIO <= DEDICATED_GPIO,
|
||||||
DS <= DS,
|
DS <= DS,
|
||||||
EFUSE <= EFUSE,
|
EFUSE <= EFUSE,
|
||||||
@ -38,12 +41,12 @@ crate::peripherals! {
|
|||||||
LPWR <= RTC_CNTL,
|
LPWR <= RTC_CNTL,
|
||||||
PCNT <= PCNT,
|
PCNT <= PCNT,
|
||||||
PMS <= PMS,
|
PMS <= PMS,
|
||||||
|
PSRAM <= virtual,
|
||||||
RMT <= RMT,
|
RMT <= RMT,
|
||||||
RNG <= RNG,
|
RNG <= RNG,
|
||||||
RSA <= RSA,
|
RSA <= RSA,
|
||||||
RTC_IO <= RTC_IO,
|
RTC_IO <= RTC_IO,
|
||||||
RTC_I2C <= RTC_I2C,
|
RTC_I2C <= RTC_I2C,
|
||||||
SENS <= SENS,
|
|
||||||
SHA <= SHA,
|
SHA <= SHA,
|
||||||
SPI0 <= SPI0,
|
SPI0 <= SPI0,
|
||||||
SPI1 <= SPI1,
|
SPI1 <= SPI1,
|
||||||
@ -59,12 +62,9 @@ crate::peripherals! {
|
|||||||
UART0 <= UART0,
|
UART0 <= UART0,
|
||||||
UART1 <= UART1,
|
UART1 <= UART1,
|
||||||
UHCI0 <= UHCI0,
|
UHCI0 <= UHCI0,
|
||||||
|
ULP_RISCV_CORE <= virtual,
|
||||||
USB0 <= USB0,
|
USB0 <= USB0,
|
||||||
USB_WRAP <= USB_WRAP,
|
USB_WRAP <= USB_WRAP,
|
||||||
XTS_AES <= XTS_AES,
|
|
||||||
|
|
||||||
// Virtual peripherals:
|
|
||||||
PSRAM <= virtual,
|
|
||||||
ULP_RISCV_CORE <= virtual,
|
|
||||||
WIFI <= virtual,
|
WIFI <= virtual,
|
||||||
|
XTS_AES <= XTS_AES,
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,12 @@ pub(crate) use self::peripherals::*;
|
|||||||
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
// peripheral (no `PSRAM`, `RADIO`, etc. peripheral in the PACs), so we're
|
||||||
// creating "virtual peripherals" for them.
|
// creating "virtual peripherals" for them.
|
||||||
crate::peripherals! {
|
crate::peripherals! {
|
||||||
|
ADC1 <= virtual,
|
||||||
|
ADC2 <= virtual,
|
||||||
AES <= AES,
|
AES <= AES,
|
||||||
APB_CTRL <= APB_CTRL,
|
APB_CTRL <= APB_CTRL,
|
||||||
APB_SARADC <= APB_SARADC,
|
|
||||||
ASSIST_DEBUG <= ASSIST_DEBUG,
|
ASSIST_DEBUG <= ASSIST_DEBUG,
|
||||||
|
BT <= virtual,
|
||||||
DMA <= DMA,
|
DMA <= DMA,
|
||||||
DS <= DS,
|
DS <= DS,
|
||||||
EFUSE <= EFUSE,
|
EFUSE <= EFUSE,
|
||||||
@ -43,6 +45,7 @@ crate::peripherals! {
|
|||||||
LPWR <= RTC_CNTL,
|
LPWR <= RTC_CNTL,
|
||||||
PCNT <= PCNT,
|
PCNT <= PCNT,
|
||||||
PERI_BACKUP <= PERI_BACKUP,
|
PERI_BACKUP <= PERI_BACKUP,
|
||||||
|
PSRAM <= virtual,
|
||||||
MCPWM0 <= MCPWM0,
|
MCPWM0 <= MCPWM0,
|
||||||
MCPWM1 <= MCPWM1,
|
MCPWM1 <= MCPWM1,
|
||||||
RMT <= RMT,
|
RMT <= RMT,
|
||||||
@ -50,7 +53,6 @@ crate::peripherals! {
|
|||||||
RSA <= RSA,
|
RSA <= RSA,
|
||||||
RTC_I2C <= RTC_I2C,
|
RTC_I2C <= RTC_I2C,
|
||||||
RTC_IO <= RTC_IO,
|
RTC_IO <= RTC_IO,
|
||||||
SENS <= SENS,
|
|
||||||
SENSITIVE <= SENSITIVE,
|
SENSITIVE <= SENSITIVE,
|
||||||
SHA <= SHA,
|
SHA <= SHA,
|
||||||
SPI0 <= SPI0,
|
SPI0 <= SPI0,
|
||||||
@ -67,15 +69,11 @@ crate::peripherals! {
|
|||||||
UART2 <= UART2,
|
UART2 <= UART2,
|
||||||
UHCI0 <= UHCI0,
|
UHCI0 <= UHCI0,
|
||||||
UHCI1 <= UHCI1,
|
UHCI1 <= UHCI1,
|
||||||
|
ULP_RISCV_CORE <= virtual,
|
||||||
USB0 <= USB0,
|
USB0 <= USB0,
|
||||||
USB_DEVICE <= USB_DEVICE,
|
USB_DEVICE <= USB_DEVICE,
|
||||||
USB_WRAP <= USB_WRAP,
|
USB_WRAP <= USB_WRAP,
|
||||||
WCL <= WCL,
|
WCL <= WCL,
|
||||||
XTS_AES <= XTS_AES,
|
|
||||||
|
|
||||||
// Virtual peripherals:
|
|
||||||
BT <= virtual,
|
|
||||||
PSRAM <= virtual,
|
|
||||||
ULP_RISCV_CORE <= virtual,
|
|
||||||
WIFI <= virtual,
|
WIFI <= virtual,
|
||||||
|
XTS_AES <= XTS_AES,
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32_hal::{
|
use esp32_hal::{
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC2},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC2},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,12 +25,10 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.SENS.split();
|
|
||||||
|
|
||||||
let mut adc2_config = AdcConfig::new();
|
let mut adc2_config = AdcConfig::new();
|
||||||
let mut pin25 =
|
let mut pin25 =
|
||||||
adc2_config.enable_pin(io.pins.gpio25.into_analog(), Attenuation::Attenuation11dB);
|
adc2_config.enable_pin(io.pins.gpio25.into_analog(), Attenuation::Attenuation11dB);
|
||||||
let mut adc2 = ADC::<ADC2>::adc(analog.adc2, adc2_config).unwrap();
|
let mut adc2 = ADC::<ADC2>::adc(peripherals.ADC2, adc2_config).unwrap();
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -5,7 +5,14 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32_hal::{clock::ClockControl, dac, gpio::IO, peripherals::Peripherals, prelude::*, Delay};
|
use esp32_hal::{
|
||||||
|
clock::ClockControl,
|
||||||
|
dac::{DAC1, DAC2},
|
||||||
|
gpio::IO,
|
||||||
|
peripherals::Peripherals,
|
||||||
|
prelude::*,
|
||||||
|
Delay,
|
||||||
|
};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
@ -19,9 +26,8 @@ fn main() -> ! {
|
|||||||
let pin26 = io.pins.gpio26.into_analog();
|
let pin26 = io.pins.gpio26.into_analog();
|
||||||
|
|
||||||
// Create DAC instances
|
// Create DAC instances
|
||||||
let analog = peripherals.SENS.split();
|
let mut dac1 = DAC1::new(peripherals.DAC1, pin25);
|
||||||
let mut dac1 = dac::DAC1::dac(analog.dac1, pin25).unwrap();
|
let mut dac2 = DAC2::new(peripherals.DAC2, pin26);
|
||||||
let mut dac2 = dac::DAC2::dac(analog.dac2, pin26).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32c2_hal::{
|
use esp32c2_hal::{
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,13 +25,9 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.APB_SARADC.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
use esp32c2_hal::{
|
use esp32c2_hal::{
|
||||||
adc,
|
adc,
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -26,12 +26,6 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.APB_SARADC.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
|
||||||
|
|
||||||
let atten = Attenuation::Attenuation11dB;
|
|
||||||
|
|
||||||
// You can try any of the following calibration methods by uncommenting
|
// You can try any of the following calibration methods by uncommenting
|
||||||
// them. Note that only AdcCalLine returns readings in mV; the other two
|
// them. Note that only AdcCalLine returns readings in mV; the other two
|
||||||
// return raw readings in some unspecified scale.
|
// return raw readings in some unspecified scale.
|
||||||
@ -40,9 +34,12 @@ fn main() -> ! {
|
|||||||
// type AdcCal = adc::AdcCalBasic<ADC1>;
|
// type AdcCal = adc::AdcCalBasic<ADC1>;
|
||||||
type AdcCal = adc::AdcCalLine<ADC1>;
|
type AdcCal = adc::AdcCalLine<ADC1>;
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio2.into_analog(), atten);
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
io.pins.gpio2.into_analog(),
|
||||||
|
Attenuation::Attenuation11dB,
|
||||||
|
);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32c3_hal::{
|
use esp32c3_hal::{
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,13 +25,9 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.APB_SARADC.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
use esp32c3_hal::{
|
use esp32c3_hal::{
|
||||||
adc,
|
adc,
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -26,12 +26,6 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.APB_SARADC.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
|
||||||
|
|
||||||
let atten = Attenuation::Attenuation11dB;
|
|
||||||
|
|
||||||
// You can try any of the following calibration methods by uncommenting them.
|
// You can try any of the following calibration methods by uncommenting them.
|
||||||
// Note that only AdcCalLine and AdcCalCurve return readings in mV; the other
|
// Note that only AdcCalLine and AdcCalCurve return readings in mV; the other
|
||||||
// two return raw readings in some unspecified scale.
|
// two return raw readings in some unspecified scale.
|
||||||
@ -41,9 +35,12 @@ fn main() -> ! {
|
|||||||
// type AdcCal = adc::AdcCalLine<ADC1>;
|
// type AdcCal = adc::AdcCalLine<ADC1>;
|
||||||
type AdcCal = adc::AdcCalCurve<ADC1>;
|
type AdcCal = adc::AdcCalCurve<ADC1>;
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio2.into_analog(), atten);
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
io.pins.gpio2.into_analog(),
|
||||||
|
Attenuation::Attenuation11dB,
|
||||||
|
);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32c6_hal::{
|
use esp32c6_hal::{
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,13 +25,9 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.APB_SARADC.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
use esp32c6_hal::{
|
use esp32c6_hal::{
|
||||||
adc,
|
adc,
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -26,12 +26,6 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.APB_SARADC.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
|
||||||
|
|
||||||
let atten = Attenuation::Attenuation11dB;
|
|
||||||
|
|
||||||
// You can try any of the following calibration methods by uncommenting them.
|
// You can try any of the following calibration methods by uncommenting them.
|
||||||
// Note that only AdcCalLine and AdcCalCurve return readings in mV; the other
|
// Note that only AdcCalLine and AdcCalCurve return readings in mV; the other
|
||||||
// two return raw readings in some unspecified scale.
|
// two return raw readings in some unspecified scale.
|
||||||
@ -41,9 +35,12 @@ fn main() -> ! {
|
|||||||
// type AdcCal = adc::AdcCalLine<ADC1>;
|
// type AdcCal = adc::AdcCalLine<ADC1>;
|
||||||
type AdcCal = adc::AdcCalCurve<ADC1>;
|
type AdcCal = adc::AdcCalCurve<ADC1>;
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio2.into_analog(), atten);
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
io.pins.gpio2.into_analog(),
|
||||||
|
Attenuation::Attenuation11dB,
|
||||||
|
);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32h2_hal::{
|
use esp32h2_hal::{
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,13 +25,9 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.APB_SARADC.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32s2_hal::{
|
use esp32s2_hal::{
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,14 +25,10 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.SENS.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
|
||||||
let mut pin3 =
|
let mut pin3 =
|
||||||
adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
use esp32s2_hal::{
|
use esp32s2_hal::{
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
dac,
|
dac::{DAC1, DAC2},
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -26,9 +26,8 @@ fn main() -> ! {
|
|||||||
let pin18 = io.pins.gpio18.into_analog();
|
let pin18 = io.pins.gpio18.into_analog();
|
||||||
|
|
||||||
// Create DAC instances
|
// Create DAC instances
|
||||||
let analog = peripherals.SENS.split();
|
let mut dac1 = DAC1::new(peripherals.DAC1, pin17);
|
||||||
let mut dac1 = dac::DAC1::dac(analog.dac1, pin17).unwrap();
|
let mut dac2 = DAC2::new(peripherals.DAC2, pin18);
|
||||||
let mut dac2 = dac::DAC2::dac(analog.dac2, pin18).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32s3_hal::{
|
use esp32s3_hal::{
|
||||||
adc::{AdcConfig, Attenuation, ADC, ADC1},
|
adc::{AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,14 +25,10 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.SENS.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
|
||||||
let mut pin3 =
|
let mut pin3 =
|
||||||
adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
adc1_config.enable_pin(io.pins.gpio3.into_analog(), Attenuation::Attenuation11dB);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp32s3_hal::{
|
use esp32s3_hal::{
|
||||||
adc::{self, AdcConfig, Attenuation, ADC, ADC1},
|
adc::{self, AdcConfig, Attenuation, ADC},
|
||||||
clock::ClockControl,
|
clock::ClockControl,
|
||||||
gpio::IO,
|
gpio::IO,
|
||||||
peripherals::Peripherals,
|
peripherals::{Peripherals, ADC1},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
Delay,
|
Delay,
|
||||||
};
|
};
|
||||||
@ -25,12 +25,6 @@ fn main() -> ! {
|
|||||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
// Create ADC instances
|
// Create ADC instances
|
||||||
let analog = peripherals.SENS.split();
|
|
||||||
|
|
||||||
let mut adc1_config = AdcConfig::new();
|
|
||||||
|
|
||||||
let atten = Attenuation::Attenuation11dB;
|
|
||||||
|
|
||||||
// You can try any of the following calibration methods by uncommenting them.
|
// You can try any of the following calibration methods by uncommenting them.
|
||||||
// Note that only AdcCalLine and AdcCalCurve return readings in mV; the other
|
// Note that only AdcCalLine and AdcCalCurve return readings in mV; the other
|
||||||
// two return raw readings in some unspecified scale.
|
// two return raw readings in some unspecified scale.
|
||||||
@ -40,9 +34,12 @@ fn main() -> ! {
|
|||||||
// type AdcCal = adc::AdcCalLine<ADC1>;
|
// type AdcCal = adc::AdcCalLine<ADC1>;
|
||||||
type AdcCal = adc::AdcCalCurve<ADC1>;
|
type AdcCal = adc::AdcCalCurve<ADC1>;
|
||||||
|
|
||||||
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(io.pins.gpio3.into_analog(), atten);
|
let mut adc1_config = AdcConfig::new();
|
||||||
|
let mut pin = adc1_config.enable_pin_with_cal::<_, AdcCal>(
|
||||||
let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
|
io.pins.gpio3.into_analog(),
|
||||||
|
Attenuation::Attenuation11dB,
|
||||||
|
);
|
||||||
|
let mut adc1 = ADC::<ADC1>::adc(peripherals.ADC1, adc1_config).unwrap();
|
||||||
|
|
||||||
let mut delay = Delay::new(&clocks);
|
let mut delay = Delay::new(&clocks);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user