From bcd3bc604003873f485859cee75972746a6d0054 Mon Sep 17 00:00:00 2001 From: vipierozan99 Date: Tue, 5 Jan 2021 11:02:42 -0300 Subject: [PATCH 1/3] WIP: adc support --- tm4c-hal/src/gpio.rs | 16 +-- tm4c-hal/src/lib.rs | 22 +++++ tm4c123x-hal/src/adc.rs | 210 ++++++++++++++++++++++++++++++++++++++++ tm4c123x-hal/src/lib.rs | 1 + 4 files changed, 242 insertions(+), 7 deletions(-) create mode 100644 tm4c123x-hal/src/adc.rs diff --git a/tm4c-hal/src/gpio.rs b/tm4c-hal/src/gpio.rs index 45990ed..3887aa5 100644 --- a/tm4c-hal/src/gpio.rs +++ b/tm4c-hal/src/gpio.rs @@ -11,6 +11,9 @@ pub trait InputMode {} /// All output modes implement this pub trait OutputMode {} +/// All analog modes implement this +pub trait AnalogMode {} + /// OpenDrain modes implement this pub trait OpenDrainMode { /// Is pull-up enabled @@ -55,6 +58,11 @@ impl OpenDrainMode for PullUp { true } } +/// Sub-mode of Input: Analog input (type state) +pub struct AnalogInput; +impl AnalogMode for AnalogInput {} +impl InputMode for AnalogInput {} +impl IsUnlocked for AnalogInput {} /// Tri-state pub struct Tristate; @@ -73,17 +81,11 @@ impl IsUnlocked for Output where MODE: OutputMode {} pub struct AlternateFunction where AF: AlternateFunctionChoice, - MODE: OutputMode, { _func: PhantomData, _mode: PhantomData, } -impl IsUnlocked for AlternateFunction -where - AF: AlternateFunctionChoice, - MODE: OutputMode, -{ -} +impl IsUnlocked for AlternateFunction where AF: AlternateFunctionChoice {} /// Sub-mode of Output/AlternateFunction: Push pull output (type state for /// Output) diff --git a/tm4c-hal/src/lib.rs b/tm4c-hal/src/lib.rs index 790e1a5..4df6935 100644 --- a/tm4c-hal/src/lib.rs +++ b/tm4c-hal/src/lib.rs @@ -191,7 +191,29 @@ macro_rules! gpio_macro { _mode: PhantomData, } + impl $PXi { + fn number(&self) -> u8 { + $i + } + } + impl $PXi where MODE: IsUnlocked { + /// Configures the pin to analog input. + pub fn into_ain( + self, + _gpio_control: &mut GpioControl, + ) -> $PXi> { + let p = unsafe { &*$GPIOX::ptr() }; + unsafe { bb::change_bit(&p.afsel, $i, true); } + unsafe { bb::change_bit(&p.dir, $i, false); } + unsafe { bb::change_bit(&p.odr, $i, false); } + unsafe { bb::change_bit(&p.pur, $i, false); } + unsafe { bb::change_bit(&p.pdr, $i, false); } + unsafe { bb::change_bit(&p.den, $i, false); } + unsafe { bb::change_bit(&p.amsel, $i, false); } + $PXi { _mode: PhantomData } + } + /// Configures the pin to serve as alternate function 1 through 15. /// Disables open-drain to make the output a push-pull. pub fn into_af_push_pull( diff --git a/tm4c123x-hal/src/adc.rs b/tm4c123x-hal/src/adc.rs new file mode 100644 index 0000000..2b04987 --- /dev/null +++ b/tm4c123x-hal/src/adc.rs @@ -0,0 +1,210 @@ +//! Analog-to-Digital Converter +use core::marker::PhantomData; + +use crate::{ + bb, + gpio::gpiob::{PB4, PB5}, + gpio::gpiod::{PD0, PD1, PD2, PD3}, + gpio::gpioe::{PE0, PE1, PE2, PE3, PE4, PE5}, + hal::adc, + sysctl, +}; + +use tm4c123x::{ADC0, ADC1}; +use tm4c_hal::gpio::{AnalogInput, Input}; +use SampleSeq::{SS0, SS1, SS2, SS3}; + +#[allow(non_snake_case)] +/// Sample sequencers available +pub mod SampleSeq { + /// 8 Samples 8 FIFO depth + pub struct SS0; + /// 4 Samples 4 FIFO depth + pub struct SS1; + /// 4 Samples 4 FIFO depth + pub struct SS2; + /// 1 Samples 1 FIFO depth + pub struct SS3; +} + +macro_rules! ss_ctl { + ($adc:ident, SS0) => { + $adc.ssctl0 + }; + ($adc:ident, SS1) => { + $adc.ssctl1 + }; + ($adc:ident, SS2) => { + $adc.ssctl2 + }; + ($adc:ident, SS3) => { + $adc.ssctl3 + }; +} + +macro_rules! ss_mux { + ($adc:ident, SS0) => { + $adc.ssmux0 + }; + ($adc:ident, SS1) => { + $adc.ssmux1 + }; + ($adc:ident, SS2) => { + $adc.ssmux2 + }; + ($adc:ident, SS3) => { + $adc.ssmux3 + }; +} + +macro_rules! ss_num { + (SS0) => { + 0 + }; + (SS1) => { + 1 + }; + (SS2) => { + 2 + }; + (SS3) => { + 3 + }; +} + +macro_rules! ss_fifo { + ($adc:ident, SS0) => { + $adc.ssfifo0 + }; + ($adc:ident, SS1) => { + $adc.ssfifo1 + }; + ($adc:ident, SS2) => { + $adc.ssfifo2 + }; + ($adc:ident, SS3) => { + $adc.ssfifo3 + }; +} + +/// Example ADC +pub struct Adc { + /// adc peripheral + adc: ADC, + + // input pin + #[allow(dead_code)] + pin: PIN, + + // SampleSequencer being used + _ss: PhantomData, +} + +macro_rules! pin_hal { + ($ ($PXN:ident: ($num:expr), )+) => { + $( + impl adc::Channel for $PXN> { + type ID = u8; + + fn channel() -> u8 { + $num + } + } + + impl adc::Channel for $PXN> { + type ID = u8; + + fn channel() -> u8 { + $num + } + } + )+ + } +} + +macro_rules! init_hal { + ($($ADCX:ident: ($powerDomain:ident, $adcX:ident, $SSX:ident),)+) => { + $( + + impl Adc<$SSX, $ADCX, PIN> + where + PIN: adc::Channel<$ADCX>, + PIN::ID: Into + { + /// Configures the ADC peripheral to operate in full duplex master mode + pub fn $adcX( + adc: $ADCX, + pin: PIN, + pc: &sysctl::PowerControl, + ) -> Self + { + // power up + sysctl::control_power( + pc, sysctl::Domain::$powerDomain, + sysctl::RunMode::Run, sysctl::PowerState::On); + sysctl::reset(pc, sysctl::Domain::$powerDomain); + + unsafe { // disable for config + bb::change_bit(&adc.actss, ss_num!($SSX), false); + } + adc.emux.modify(|r, w| unsafe { w.bits(r.bits() & !(0xF000)) }); // software trigger + + ss_mux!(adc, $SSX).write(|w| unsafe { w.bits(PIN::channel().into()) }); + + unsafe { + bb::change_bit(&ss_ctl!(adc, $SSX), 1, true); + bb::change_bit(&ss_ctl!(adc, $SSX), 2, true); + bb::change_bit(&adc.actss, ss_num!($SSX), true); + } + + Adc { _ss: PhantomData, pin, adc } + } + + /// Configured channel + pub fn channel(&self) -> PIN::ID { + PIN::channel() + } + + /// Blocking read + pub fn read_blocking(&self) -> u16 { + unsafe { + bb::change_bit(&self.adc.pssi, ss_num!($SSX), true); // Enable SS3 conversion or start sampling data from AN0 + } + while (&self.adc.ris.read().bits() & 8) == 0 { + // cortex_m::asm::nop(); + } + let ref _adc = self.adc; + let adc_value = ss_fifo!(_adc, $SSX).read().data().bits(); //clear coversion clear flag bit + &self.adc.isc.write(|w| unsafe { w.bits(8) }); + adc_value + } + } + )+ + } +} + +init_hal! { + ADC0: (Adc0, adc0, SS0), + ADC0: (Adc0, adc0, SS1), + ADC0: (Adc0, adc0, SS2), + ADC0: (Adc0, adc0, SS3), + ADC1: (Adc1, adc1, SS0), + ADC1: (Adc1, adc1, SS1), + ADC1: (Adc1, adc1, SS2), + ADC1: (Adc1, adc1, SS3), +} + +pin_hal! { + PE3: (0), + PE2: (1), + PE1: (2), + PE0: (3), + PD3: (4), + PD2: (5), + PD1: (6), + PD0: (7), + PE5: (8), + PE4: (9), + PB4: (10), + PB5: (11), +} diff --git a/tm4c123x-hal/src/lib.rs b/tm4c123x-hal/src/lib.rs index 12137ba..e2cc947 100644 --- a/tm4c123x-hal/src/lib.rs +++ b/tm4c123x-hal/src/lib.rs @@ -32,6 +32,7 @@ pub use crate::tm4c123x::interrupt; use embedded_hal as hal; +pub mod adc; pub mod gpio; pub mod hib; pub mod i2c; From 17c1a71fae0bb29beac4e2bc3341e43d0ea65f30 Mon Sep 17 00:00:00 2001 From: Victor E Pierozan Date: Tue, 9 Feb 2021 16:08:46 -0300 Subject: [PATCH 2/3] update to sample_seq --- tm4c123x-hal/src/adc.rs | 91 +++++----------------------------- tm4c123x-hal/src/lib.rs | 1 + tm4c123x-hal/src/sample_seq.rs | 86 ++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 79 deletions(-) create mode 100644 tm4c123x-hal/src/sample_seq.rs diff --git a/tm4c123x-hal/src/adc.rs b/tm4c123x-hal/src/adc.rs index 2b04987..34bcf86 100644 --- a/tm4c123x-hal/src/adc.rs +++ b/tm4c123x-hal/src/adc.rs @@ -7,85 +7,13 @@ use crate::{ gpio::gpiod::{PD0, PD1, PD2, PD3}, gpio::gpioe::{PE0, PE1, PE2, PE3, PE4, PE5}, hal::adc, - sysctl, + ss_ctl, ss_fifo, ss_mux, sysctl, }; +pub use crate::sample_seq::{SS0, SS1, SS2, SS3}; + use tm4c123x::{ADC0, ADC1}; use tm4c_hal::gpio::{AnalogInput, Input}; -use SampleSeq::{SS0, SS1, SS2, SS3}; - -#[allow(non_snake_case)] -/// Sample sequencers available -pub mod SampleSeq { - /// 8 Samples 8 FIFO depth - pub struct SS0; - /// 4 Samples 4 FIFO depth - pub struct SS1; - /// 4 Samples 4 FIFO depth - pub struct SS2; - /// 1 Samples 1 FIFO depth - pub struct SS3; -} - -macro_rules! ss_ctl { - ($adc:ident, SS0) => { - $adc.ssctl0 - }; - ($adc:ident, SS1) => { - $adc.ssctl1 - }; - ($adc:ident, SS2) => { - $adc.ssctl2 - }; - ($adc:ident, SS3) => { - $adc.ssctl3 - }; -} - -macro_rules! ss_mux { - ($adc:ident, SS0) => { - $adc.ssmux0 - }; - ($adc:ident, SS1) => { - $adc.ssmux1 - }; - ($adc:ident, SS2) => { - $adc.ssmux2 - }; - ($adc:ident, SS3) => { - $adc.ssmux3 - }; -} - -macro_rules! ss_num { - (SS0) => { - 0 - }; - (SS1) => { - 1 - }; - (SS2) => { - 2 - }; - (SS3) => { - 3 - }; -} - -macro_rules! ss_fifo { - ($adc:ident, SS0) => { - $adc.ssfifo0 - }; - ($adc:ident, SS1) => { - $adc.ssfifo1 - }; - ($adc:ident, SS2) => { - $adc.ssfifo2 - }; - ($adc:ident, SS3) => { - $adc.ssfifo3 - }; -} /// Example ADC pub struct Adc { @@ -145,7 +73,7 @@ macro_rules! init_hal { sysctl::reset(pc, sysctl::Domain::$powerDomain); unsafe { // disable for config - bb::change_bit(&adc.actss, ss_num!($SSX), false); + bb::change_bit(&adc.actss, $SSX::num(), false); } adc.emux.modify(|r, w| unsafe { w.bits(r.bits() & !(0xF000)) }); // software trigger @@ -154,12 +82,17 @@ macro_rules! init_hal { unsafe { bb::change_bit(&ss_ctl!(adc, $SSX), 1, true); bb::change_bit(&ss_ctl!(adc, $SSX), 2, true); - bb::change_bit(&adc.actss, ss_num!($SSX), true); + bb::change_bit(&adc.actss, $SSX::num(), true); } Adc { _ss: PhantomData, pin, adc } } + /// Releases the peripheral and pin + pub fn free(self) -> ($ADCX, PIN) { + (self.adc,self.pin) + } + /// Configured channel pub fn channel(&self) -> PIN::ID { PIN::channel() @@ -168,13 +101,13 @@ macro_rules! init_hal { /// Blocking read pub fn read_blocking(&self) -> u16 { unsafe { - bb::change_bit(&self.adc.pssi, ss_num!($SSX), true); // Enable SS3 conversion or start sampling data from AN0 + bb::change_bit(&self.adc.pssi, $SSX::num(), true); // Enable SS3 conversion or start sampling data from AN0 } while (&self.adc.ris.read().bits() & 8) == 0 { // cortex_m::asm::nop(); } let ref _adc = self.adc; - let adc_value = ss_fifo!(_adc, $SSX).read().data().bits(); //clear coversion clear flag bit + let adc_value = ss_fifo!(_adc, $SSX).read().data().bits(); //clear conversion clear flag bit &self.adc.isc.write(|w| unsafe { w.bits(8) }); adc_value } diff --git a/tm4c123x-hal/src/lib.rs b/tm4c123x-hal/src/lib.rs index e2cc947..62111d3 100644 --- a/tm4c123x-hal/src/lib.rs +++ b/tm4c123x-hal/src/lib.rs @@ -38,6 +38,7 @@ pub mod hib; pub mod i2c; pub mod prelude; pub mod pwm; +pub mod sample_seq; pub mod serial; pub mod spi; pub mod sysctl; diff --git a/tm4c123x-hal/src/sample_seq.rs b/tm4c123x-hal/src/sample_seq.rs new file mode 100644 index 0000000..a87e5fb --- /dev/null +++ b/tm4c123x-hal/src/sample_seq.rs @@ -0,0 +1,86 @@ +#![macro_use] +//! Sample sequencers for ADC + +/// 8 Samples 8 FIFO depth +pub struct SS0; +impl SS0 { + /// Sample sequencer number + pub fn num() -> u8 { + return 0; + } +} +/// 4 Samples 4 FIFO depth +pub struct SS1; +impl SS1 { + /// Sample sequencer number + pub fn num() -> u8 { + return 1; + } +} +/// 4 Samples 4 FIFO depth +pub struct SS2; +impl SS2 { + /// Sample sequencer number + pub fn num() -> u8 { + return 2; + } +} +/// 1 Samples 1 FIFO depth +pub struct SS3; +impl SS3 { + /// Sample sequencer number + pub fn num() -> u8 { + return 3; + } +} + +#[macro_export] +/// ssctl field accessor +macro_rules! ss_ctl { + ($adc:ident, SS0) => { + $adc.ssctl0 + }; + ($adc:ident, SS1) => { + $adc.ssctl1 + }; + ($adc:ident, SS2) => { + $adc.ssctl2 + }; + ($adc:ident, SS3) => { + $adc.ssctl3 + }; +} + +#[macro_export] +/// ssmux field accessor +macro_rules! ss_mux { + ($adc:ident, SS0) => { + $adc.ssmux0 + }; + ($adc:ident, SS1) => { + $adc.ssmux1 + }; + ($adc:ident, SS2) => { + $adc.ssmux2 + }; + ($adc:ident, SS3) => { + $adc.ssmux3 + }; +} + +#[macro_export] +/// ssfifo field accessor +macro_rules! ss_fifo { + ($adc:ident, SS0) => { + $adc.ssfifo0 + }; + ($adc:ident, SS1) => { + $adc.ssfifo1 + }; + ($adc:ident, SS2) => { + $adc.ssfifo2 + }; + ($adc:ident, SS3) => { + $adc.ssfifo3 + }; +} From a6a5f18c23a167c88d44cd492bd94195d5bfc458 Mon Sep 17 00:00:00 2001 From: Victor E Pierozan Date: Tue, 6 Jul 2021 23:21:42 -0300 Subject: [PATCH 3/3] small fix --- tm4c123x-hal/src/adc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tm4c123x-hal/src/adc.rs b/tm4c123x-hal/src/adc.rs index 34bcf86..eed637e 100644 --- a/tm4c123x-hal/src/adc.rs +++ b/tm4c123x-hal/src/adc.rs @@ -60,7 +60,7 @@ macro_rules! init_hal { PIN::ID: Into { /// Configures the ADC peripheral to operate in full duplex master mode - pub fn $adcX( + pub fn new( adc: $ADCX, pin: PIN, pc: &sysctl::PowerControl, @@ -108,7 +108,7 @@ macro_rules! init_hal { } let ref _adc = self.adc; let adc_value = ss_fifo!(_adc, $SSX).read().data().bits(); //clear conversion clear flag bit - &self.adc.isc.write(|w| unsafe { w.bits(8) }); + self.adc.isc.write(|w| unsafe { w.bits(8) }); adc_value } }