Skip to content

Commit f26598f

Browse files
committed
Add PGA mode to opamp
1 parent e8522c4 commit f26598f

File tree

2 files changed

+118
-19
lines changed

2 files changed

+118
-19
lines changed

src/adc.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
gpio::*,
1616
rcc::{Enable, Rcc, Reset},
1717
signature::{VtempCal110, VtempCal30, VDDA_CALIB},
18-
stm32,
18+
stm32, opamp,
1919
};
2020
use core::fmt;
2121
use core::marker::PhantomData;
@@ -66,6 +66,17 @@ macro_rules! adc_pins {
6666
};
6767
}
6868

69+
macro_rules! adc_op {
70+
($($opamp:ty => ($adc:ident, $chan:expr)),+ $(,)*) => {
71+
$(
72+
impl<A, B> Channel<stm32::$adc> for $opamp {
73+
type ID = u8;
74+
fn channel() -> u8 { $chan }
75+
}
76+
)+
77+
};
78+
}
79+
6980
/// Contains types related to ADC configuration
7081
pub mod config {
7182
use embedded_hal::adc::Channel;
@@ -2338,6 +2349,29 @@ adc_pins!(
23382349
Vref => (ADC5, 18),
23392350
);
23402351

2352+
// See https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf#page=782
2353+
#[cfg(any(
2354+
feature = "stm32g473",
2355+
feature = "stm32g474",
2356+
feature = "stm32g483",
2357+
feature = "stm32g484",
2358+
))]
2359+
adc_op!(
2360+
opamp::opamp1::Pga<A, B> => (ADC1, 3),
2361+
2362+
opamp::opamp2::Pga<A, B> => (ADC2, 3),
2363+
2364+
opamp::opamp3::Pga<A, B> => (ADC1, 12),
2365+
2366+
opamp::opamp4::Pga<A, B> => (ADC4, 3),
2367+
opamp::opamp4::Pga<A, B> => (ADC1, 11),
2368+
2369+
opamp::opamp5::Pga<A, B> => (ADC5, 1),
2370+
2371+
opamp::opamp6::Pga<A, B> => (ADC1, 14),
2372+
opamp::opamp6::Pga<A, B> => (ADC2, 14),
2373+
);
2374+
23412375
#[cfg(any(feature = "stm32g491", feature = "stm32g4a1",))]
23422376
adc_pins!(
23432377
gpioa::PA0<Analog> => (ADC1, 1),

src/opamp.rs

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ macro_rules! opamps {
5555
$opamp:ident
5656
:
5757
{
58+
vinm0: $vinm0:ty,
59+
5860
inverting
5961
:
6062
{
@@ -95,6 +97,13 @@ macro_rules! opamps {
9597
$(
9698
/// States for opampX.
9799
pub mod $opamp {
100+
use crate::stm32::opamp::[<$opamp _csr>]::PGA_GAIN_A;
101+
102+
#[allow(unused_imports)]
103+
use crate::gpio::gpioa::*;
104+
105+
#[allow(unused_imports)]
106+
use crate::gpio::gpiob::*;
98107

99108
/// State type for disabled opamp.
100109
pub struct Disabled;
@@ -115,26 +124,69 @@ macro_rules! opamps {
115124
/// State type for opamp running in programmable-gain mode.
116125
pub struct Pga<NonInverting, MODE> {
117126
non_inverting: NonInverting,
118-
config: Config<MODE>,
127+
config: MODE,
119128
output: Option<$output>,
120129
}
121130

131+
trait PgaMode{
132+
fn pga_gain_bits(&self) -> PGA_GAIN_A;
133+
}
134+
135+
struct PgaModeInternal(NonInvertingGain);
136+
impl PgaMode for PgaModeInternal {
137+
fn pga_gain_bits(&self) -> PGA_GAIN_A {
138+
match self.0 {
139+
NonInvertingGain::Gain2 => PGA_GAIN_A::Gain2,
140+
NonInvertingGain::Gain4 => PGA_GAIN_A::Gain4,
141+
NonInvertingGain::Gain8 => PGA_GAIN_A::Gain8,
142+
NonInvertingGain::Gain16 => PGA_GAIN_A::Gain16,
143+
NonInvertingGain::Gain32 => PGA_GAIN_A::Gain32,
144+
NonInvertingGain::Gain64 => PGA_GAIN_A::Gain64,
145+
}
146+
}
147+
}
148+
149+
/// Same as PgaModeInternal but the inverted signal is routed to pin to allow external filter
150+
struct PgaModeInvertedInputFiltered<PIN> {
151+
gain: NonInvertingGain,
152+
pin: core::marker::PhantomData<PIN>
153+
}
154+
impl<PIN> PgaMode for PgaModeInvertedInputFiltered<PIN> {
155+
fn pga_gain_bits(&self) -> PGA_GAIN_A {
156+
match self.gain {
157+
NonInvertingGain::Gain2 => PGA_GAIN_A::Gain2FilteringVinm0,
158+
NonInvertingGain::Gain4 => PGA_GAIN_A::Gain4FilteringVinm0,
159+
NonInvertingGain::Gain8 => PGA_GAIN_A::Gain8FilteringVinm0,
160+
NonInvertingGain::Gain16 => PGA_GAIN_A::Gain16FilteringVinm0,
161+
NonInvertingGain::Gain32 => PGA_GAIN_A::Gain32FilteringVinm0,
162+
NonInvertingGain::Gain64 => PGA_GAIN_A::Gain64FilteringVinm0,
163+
}
164+
}
165+
}
166+
167+
/// PGA Gain for non inverted modes
122168
pub enum NonInvertingGain {
169+
/// 2x Gain
123170
Gain2 = 0,
171+
172+
/// 4x Gain
124173
Gain4 = 1,
174+
175+
/// 8x Gain
125176
Gain8 = 2,
177+
178+
/// 16x Gain
126179
Gain16 = 3,
180+
181+
/// 32x Gain
127182
Gain32 = 4,
183+
184+
/// 64x Gain
128185
Gain64 = 5
129186
}
130187

131188
// TODO: Inverting gain
132189

133-
pub struct Config<MODE> {
134-
mode: MODE,
135-
pga_gain: crate::stm32::opamp::[<$opamp _csr>]::PGA_GAIN_A,
136-
}
137-
138190
/// Trait for opamps that can be run in follower mode.
139191
pub trait IntoFollower <IntoInput, IntoOutput, Input>
140192
where
@@ -160,7 +212,7 @@ macro_rules! opamps {
160212
IntoOutput: Into<$output>,
161213
{
162214
/// Configures the opamp for programmable gain operation.
163-
fn pga(self, non_inverting: IntoNonInverting, config: Config<MODE>, output: Option<IntoOutput>)
215+
fn pga(self, non_inverting: IntoNonInverting, config: MODE, output: Option<IntoOutput>)
164216
-> Pga<NonInverting, MODE>;
165217
}
166218

@@ -225,7 +277,7 @@ macro_rules! opamps {
225277
impl<NonInverting, MODE> Pga<NonInverting, MODE> {
226278

227279
/// Disables the opamp and returns the resources it held.
228-
pub fn disable(self) -> (Disabled, NonInverting, Config<MODE>, Option<$output>) {
280+
pub fn disable(self) -> (Disabled, NonInverting, MODE, Option<$output>) {
229281
unsafe { (*crate::stm32::OPAMP::ptr()).[<$opamp _csr>].reset() }
230282
(Disabled, self.non_inverting, self.config, self.output)
231283
}
@@ -253,7 +305,7 @@ macro_rules! opamps {
253305

254306
opamps!{ @follower $opamp, $output, $($non_inverting_mask, $non_inverting),* }
255307
opamps!{ @open_loop_tt $opamp, $output, $($non_inverting_mask, $non_inverting),* : ($($inverting_mask, $inverting),*) }
256-
opamps!{ @pga_tt $opamp, $output, $($non_inverting_mask, $non_inverting),* : ($($inverting),*) }
308+
opamps!{ @pga_tt $opamp, $output, $($non_inverting_mask, $non_inverting),* : $vinm0 }
257309
}
258310
)*
259311

@@ -411,10 +463,13 @@ macro_rules! opamps {
411463
,
412464
$($non_inverting_mask:tt, $non_inverting:ty),*
413465
:
414-
$invertings:tt
466+
$vinm0:ident
415467
} => {
416468
$(
417-
opamps!{ @pga $opamp, $output, $non_inverting_mask, $non_inverting, $invertings }
469+
opamps!{ @pga $opamp, $output, $non_inverting_mask, $non_inverting, PgaModeInternal }
470+
opamps!{ @pga $opamp, $output, $non_inverting_mask, $non_inverting, PgaModeInvertedInputFiltered<$vinm0<crate::gpio::Analog>> }
471+
// TODO: Add `PGA mode, non-inverting gain setting (x2/x4/x8/x16/x32/x64) or inverting gain setting (x-1/x-3/x-7/x-15/x-31/x-63)`
472+
// TODO: Add `PGA mode, non-inverting gain setting (x2/x4/x8/x16/x32/x64) or inverting gain setting (x-1/x-3/x-7/x-15/x-31/x-63) with filtering`
418473
)*
419474
};
420475

@@ -428,25 +483,26 @@ macro_rules! opamps {
428483
,
429484
$non_inverting:ty
430485
,
431-
($($invertings:ty),*)
486+
$mode:ty
432487
} => {
433488
paste::paste!{
434-
$(impl <IntoNonInverting, $mode, IntoOutput> IntoPga
435-
<IntoNonInverting, Config<$mode>, IntoOutput, $non_inverting> for Disabled
489+
impl <IntoNonInverting, IntoOutput> IntoPga
490+
<IntoNonInverting, $mode, IntoOutput, $non_inverting> for Disabled
436491
where
437492
IntoNonInverting: Into<$non_inverting>,
438493
IntoOutput: Into<$output>,
439494
{
440495
fn pga(
441496
self,
442497
non_inverting: IntoNonInverting,
443-
config: Config<$mode>,
498+
config: $mode,
444499
output: Option<IntoOutput>,
445-
) -> Pga<$non_inverting, $config> {
500+
) -> Pga<$non_inverting, $mode> {
446501
let non_inverting = non_inverting.into();
447502
let output = output.map(|output| output.into());
448503
unsafe {
449504
use crate::stm32::opamp::[<$opamp _csr>]::OPAINTOEN_A;
505+
450506
(*crate::stm32::OPAMP::ptr())
451507
.[<$opamp _csr>]
452508
.write(|csr_w|
@@ -455,7 +511,7 @@ macro_rules! opamps {
455511
.vm_sel()
456512
.pga()
457513
.pga_gain()
458-
.variant(config.pga_gain)
514+
.variant(config.pga_gain_bits())
459515
.opaintoen()
460516
.variant(match output {
461517
Some(_) => OPAINTOEN_A::OutputPin,
@@ -467,14 +523,15 @@ macro_rules! opamps {
467523
}
468524
Pga {non_inverting, config, output}
469525
}
470-
})*
526+
}
471527
}
472528
};
473529
}
474530

475531
#[cfg(any(feature = "stm32g431", feature = "stm32g441", feature = "stm32g471",))]
476532
opamps! {
477533
opamp1: {
534+
vinm0: PA3,
478535
inverting: {
479536
crate::gpio::gpioa::PA3<crate::gpio::Analog>: vinm0,
480537
crate::gpio::gpioc::PC5<crate::gpio::Analog>: vinm1,
@@ -487,6 +544,7 @@ opamps! {
487544
output: crate::gpio::gpioa::PA2<crate::gpio::Analog>,
488545
},
489546
opamp2: {
547+
vinm0: PA5,
490548
inverting: {
491549
crate::gpio::gpioa::PA5<crate::gpio::Analog>: vinm0,
492550
crate::gpio::gpioc::PC5<crate::gpio::Analog>: vinm1,
@@ -500,6 +558,7 @@ opamps! {
500558
output: crate::gpio::gpioa::PA6<crate::gpio::Analog>,
501559
},
502560
opamp3: {
561+
vinm0: PB2,
503562
inverting: {
504563
crate::gpio::gpiob::PB2<crate::gpio::Analog>: vinm0,
505564
crate::gpio::gpiob::PB10<crate::gpio::Analog>: vinm1,
@@ -521,6 +580,7 @@ opamps! {
521580
))]
522581
opamps! {
523582
opamp1: {
583+
vinm0: PA3,
524584
inverting: {
525585
crate::gpio::gpioa::PA3<crate::gpio::Analog>: vinm0,
526586
crate::gpio::gpioc::PC5<crate::gpio::Analog>: vinm1,
@@ -533,6 +593,7 @@ opamps! {
533593
output: crate::gpio::gpioa::PA2<crate::gpio::Analog>,
534594
},
535595
opamp2: {
596+
vinm0: PA5,
536597
inverting: {
537598
crate::gpio::gpioa::PA5<crate::gpio::Analog>: vinm0,
538599
crate::gpio::gpioc::PC5<crate::gpio::Analog>: vinm1,
@@ -546,6 +607,7 @@ opamps! {
546607
output: crate::gpio::gpioa::PA6<crate::gpio::Analog>,
547608
},
548609
opamp3: {
610+
vinm0: PB2,
549611
inverting: {
550612
crate::gpio::gpiob::PB2<crate::gpio::Analog>: vinm0,
551613
crate::gpio::gpiob::PB10<crate::gpio::Analog>: vinm1,
@@ -558,6 +620,7 @@ opamps! {
558620
output: crate::gpio::gpiob::PB1<crate::gpio::Analog>,
559621
},
560622
opamp4: {
623+
vinm0: PB10,
561624
inverting: {
562625
crate::gpio::gpiob::PB10<crate::gpio::Analog>: vinm0,
563626
crate::gpio::gpiod::PD8<crate::gpio::Analog>: vinm1,
@@ -570,6 +633,7 @@ opamps! {
570633
output: crate::gpio::gpiob::PB12<crate::gpio::Analog>,
571634
},
572635
opamp5: {
636+
vinm0: PB15,
573637
inverting: {
574638
crate::gpio::gpiob::PB15<crate::gpio::Analog>: vinm0,
575639
crate::gpio::gpioa::PA3<crate::gpio::Analog>: vinm1,
@@ -582,6 +646,7 @@ opamps! {
582646
output: crate::gpio::gpioa::PA8<crate::gpio::Analog>,
583647
},
584648
opamp6: {
649+
vinm0: PA1,
585650
inverting: {
586651
crate::gpio::gpioa::PA1<crate::gpio::Analog>: vinm0,
587652
crate::gpio::gpiob::PB1<crate::gpio::Analog>: vinm1,

0 commit comments

Comments
 (0)