Skip to content

Commit

Permalink
wip(adc): generate adc pin traits
Browse files Browse the repository at this point in the history
  • Loading branch information
andelf committed Jul 17, 2024
1 parent 0f2ec67 commit 1fa907a
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 7 deletions.
24 changes: 21 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ fn main() {
})
}

// Spi is special
// SPI is special, CS pins are numbered
if regs.kind == "spi" && pin.signal.starts_with("CS") {
let peri = format_ident!("{}", p.name);
let pin_name = format_ident!("{}", pin.pin);
Expand All @@ -346,8 +346,26 @@ fn main() {
}

// ADC is special
if regs.kind == "adc" {
// TODO
if regs.kind == "adc16" {
let peri = format_ident!("{}", p.name);
let pin_name = format_ident!("{}", pin.pin);

// HPM67 has differential voltage measurements
let ch: Option<u8> = if pin.signal.starts_with("INP") {
Some(pin.signal.strip_prefix("INP").unwrap().parse().unwrap())
} else if pin.signal.starts_with("INN") {
// TODO handle in the future when embassy supports differential measurements
None
} else if pin.signal.starts_with("IN") {
Some(pin.signal.strip_prefix("IN").unwrap().parse().unwrap())
} else {
None
};
if let Some(ch) = ch {
g.extend(quote! {
impl_adc_pin!( #peri, #pin_name, #ch);
})
}
}
// if regs.kind == "dac"
}
Expand Down
89 changes: 89 additions & 0 deletions src/adc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#![macro_use]

use core::marker::PhantomData;

use embassy_sync::waitqueue::AtomicWaker;

/// Analog to Digital driver.
pub struct Adc<'d, T: Instance> {
#[allow(unused)]
adc: crate::PeripheralRef<'d, T>,
}

pub struct State {
pub waker: AtomicWaker,
}

impl State {
pub const fn new() -> Self {
Self {
waker: AtomicWaker::new(),
}
}
}

trait SealedInstance {
#[allow(unused)]
fn regs() -> crate::pac::adc16::Adc;

fn state() -> &'static State;
}

pub(crate) trait SealedAdcChannel<T> {
fn setup(&mut self) {}

#[allow(unused)]
fn channel(&self) -> u8;
}

/// ADC instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance + crate::Peripheral<P = Self> {
type Interrupt: crate::interrupt::typelevel::Interrupt;
}

/// ADC channel.
#[allow(private_bounds)]
pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
#[allow(unused_mut)]
fn degrade_adc(mut self) -> AnyAdcChannel<T> {
#[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4))]
self.setup();

AnyAdcChannel {
channel: self.channel(),
_phantom: PhantomData,
}
}
}

/// A type-erased channel for a given ADC instance.
///
/// This is useful in scenarios where you need the ADC channels to have the same type, such as
/// storing them in an array.
pub struct AnyAdcChannel<T> {
channel: u8,
_phantom: PhantomData<T>,
}

impl<T: Instance> AdcChannel<T> for AnyAdcChannel<T> {}
impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<T> {
fn channel(&self) -> u8 {
self.channel
}
}

macro_rules! impl_adc_pin {
($inst:ident, $pin:ident, $ch:expr) => {
impl crate::adc::AdcChannel<peripherals::$inst> for crate::peripherals::$pin {}
impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::peripherals::$pin {
fn setup(&mut self) {
<Self as crate::gpio::SealedPin>::set_as_analog(self);
}

fn channel(&self) -> u8 {
$ch
}
}
};
}
9 changes: 5 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@ pub mod mode {
}

// required peripherals
pub mod gpio;
pub mod mbx;
pub mod sysctl;

pub mod dma;
pub mod sysctl;

// other peripherals
#[cfg(adc16)]
pub mod adc;
pub mod gpio;
pub mod i2c;
pub mod mbx;
pub mod spi;
pub mod uart;

Expand Down

0 comments on commit 1fa907a

Please sign in to comment.