From f03fd191eb7be58b97a480cad4de44c803ec947c Mon Sep 17 00:00:00 2001 From: Jacob Rosenthal Date: Sat, 27 Jun 2020 22:01:28 -0700 Subject: [PATCH] add dac impl copied from stm32f0xx-hal --- CHANGELOG.md | 1 + src/dac.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 +++ src/prelude.rs | 5 +++ 4 files changed, 108 insertions(+) create mode 100644 src/dac.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da7fcba..0bc27823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Reexport PAC as `pac` for consistency with other crates, consider `stm32` virtually deprecated - Added external interrupt (EXTI) support for output pins - Added `check_interrupt` method for GPIO pins +- Basic support for DAC ## [v0.8.3] - 2020-06-12 diff --git a/src/dac.rs b/src/dac.rs new file mode 100644 index 00000000..5b3485a3 --- /dev/null +++ b/src/dac.rs @@ -0,0 +1,97 @@ +//! # API for the Digital to Analog converter +//! +//! Currently only supports writing to the DR of the DAC, +//! just a basic one-shot conversion. +#![deny(unused_imports)] +use core::mem; + +use crate::gpio::gpioa::{PA4, PA5}; +use crate::gpio::Analog; +use crate::pac::DAC; +use crate::stm32::RCC; + +pub struct C1; +pub struct C2; + +pub trait DacOut { + fn set_value(&mut self, val: V); + fn get_value(&mut self) -> V; +} + +pub trait DacPin { + fn enable(&mut self); +} + +pub trait Pins { + type Output; +} + +impl Pins for PA4 { + type Output = C1; +} + +impl Pins for PA5 { + type Output = C2; +} + +impl Pins for (PA4, PA5) { + type Output = (C1, C2); +} + +pub fn dac(_dac: DAC, _pins: PINS) -> PINS::Output +where + PINS: Pins, +{ + // NOTE(unsafe) This executes only during initialisation + let rcc = unsafe { &(*RCC::ptr()) }; + + // Enable DAC clocks + rcc.apb1enr.modify(|_, w| w.dacen().set_bit()); + + // Reset DAC + rcc.apb1rstr.modify(|_, w| w.dacrst().set_bit()); + rcc.apb1rstr.modify(|_, w| w.dacrst().clear_bit()); + + unsafe { mem::MaybeUninit::uninit().assume_init() } +} + +macro_rules! dac { + ($CX:ident, $en:ident, $cen:ident, $cal_flag:ident, $trim:ident, $mode:ident, $dhrx:ident, $dac_dor:ident, $daccxdhr:ident) => { + impl DacPin for $CX { + fn enable(&mut self) { + let dac = unsafe { &(*DAC::ptr()) }; + dac.cr.modify(|_, w| w.$en().set_bit()); + } + } + + impl DacOut for $CX { + fn set_value(&mut self, val: u16) { + let dac = unsafe { &(*DAC::ptr()) }; + dac.$dhrx.write(|w| unsafe { w.bits(val as u32) }); + } + + fn get_value(&mut self) -> u16 { + let dac = unsafe { &(*DAC::ptr()) }; + dac.$dac_dor.read().bits() as u16 + } + } + }; +} + +pub trait DacExt { + fn constrain(self, pins: PINS) -> PINS::Output + where + PINS: Pins; +} + +impl DacExt for DAC { + fn constrain(self, pins: PINS) -> PINS::Output + where + PINS: Pins, + { + dac(self, pins) + } +} + +dac!(C1, en1, cen1, cal_flag1, otrim1, mode1, dhr12r1, dor1, dacc1dhr); +dac!(C2, en2, cen2, cal_flag2, otrim2, mode2, dhr12r2, dor2, dacc2dhr); diff --git a/src/lib.rs b/src/lib.rs index cfdcb965..b7f14aea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,6 +87,11 @@ pub use crate::stm32::interrupt; pub mod adc; #[cfg(feature = "device-selected")] pub mod bb; +#[cfg(all( + feature = "device-selected", + not(any(feature = "stm32f411", feature = "stm32f412", feature = "stm32f401",)) +))] +pub mod dac; #[cfg(feature = "device-selected")] pub mod delay; #[cfg(feature = "device-selected")] diff --git a/src/prelude.rs b/src/prelude.rs index 23d55710..f4dd80fc 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -4,6 +4,11 @@ pub use embedded_hal::digital::v2::StatefulOutputPin as _embedded_hal_digital_v2 pub use embedded_hal::digital::v2::ToggleableOutputPin as _embedded_hal_digital_v2_ToggleableOutputPin; pub use embedded_hal::prelude::*; +#[cfg(all( + feature = "device-selected", + not(any(feature = "stm32f411", feature = "stm32f412", feature = "stm32f401",)) +))] +pub use crate::dac::DacExt as _stm32f4xx_hal_dac_DacExt; pub use crate::gpio::GpioExt as _stm32f4xx_hal_gpio_GpioExt; pub use crate::i2c::Pins as _stm32f4xx_hal_i2c_Pins; pub use crate::rcc::RccExt as _stm32f4xx_hal_rcc_RccExt;