Skip to content

Commit 91e6ceb

Browse files
committed
WIP
1 parent c765117 commit 91e6ceb

File tree

1 file changed

+124
-1
lines changed

1 file changed

+124
-1
lines changed

src/opamp.rs

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
//! }
4646
//! ```
4747
48+
// TODO: Add support for locking using the `LOCK` bit in `OPAMPx_CSR`
49+
// TODO: Add support for calibration
50+
// TODO: Add support for PGA mode
51+
4852
macro_rules! opamps {
4953
{
5054
$(
@@ -108,6 +112,18 @@ macro_rules! opamps {
108112
output: Option<$output>,
109113
}
110114

115+
/// State type for opamp running in programmable-gain mode.
116+
pub struct Pga<NonInverting, MODE> {
117+
non_inverting: NonInverting,
118+
config: Config<MODE>,
119+
output: Option<$output>,
120+
}
121+
122+
pub struct Config<MODE> {
123+
mode: MODE,
124+
pga_gain: crate::stm32::opamp::[<$opamp _csr>]::PGA_GAIN_A,
125+
}
126+
111127
/// Trait for opamps that can be run in follower mode.
112128
pub trait IntoFollower <IntoInput, IntoOutput, Input>
113129
where
@@ -127,6 +143,16 @@ macro_rules! opamps {
127143
-> OpenLoop<NonInverting, Inverting>;
128144
}
129145

146+
/// Trait for opamps that can be run in programmable gain mode.
147+
pub trait IntoPga <IntoNonInverting, MODE, IntoOutput, NonInverting>
148+
where
149+
IntoOutput: Into<$output>,
150+
{
151+
/// Configures the opamp for programmable gain operation.
152+
fn pga(self, non_inverting: IntoNonInverting, config: Config<MODE>, output: Option<IntoOutput>)
153+
-> Pga<NonInverting, MODE>;
154+
}
155+
130156
impl<Input> Follower<Input> {
131157

132158
/// Disables the opamp and returns the resources it held.
@@ -185,9 +211,38 @@ macro_rules! opamps {
185211
}
186212
}
187213

214+
impl<NonInverting, MODE> Pga<NonInverting, MODE> {
215+
216+
/// Disables the opamp and returns the resources it held.
217+
pub fn disable(self) -> (Disabled, NonInverting, Config<MODE>, Option<$output>) {
218+
unsafe { (*crate::stm32::OPAMP::ptr()).[<$opamp _csr>].reset() }
219+
(Disabled, self.non_inverting, self.config, self.output)
220+
}
221+
222+
/// Enables the external output pin.
223+
pub fn enable_output(&mut self, output: $output) {
224+
self.output = Some(output);
225+
unsafe {
226+
(*crate::stm32::OPAMP::ptr()).[<$opamp _csr>].write(|w|
227+
w.opaintoen().output_pin());
228+
}
229+
}
230+
231+
/// Disables the external output.
232+
/// This will connect the opamp output to the internal ADC.
233+
/// If the output was enabled, the output pin is returned.
234+
pub fn disable_output(&mut self) -> Option<$output> {
235+
unsafe {
236+
(*crate::stm32::OPAMP::ptr()).[<$opamp _csr>].write(|w|
237+
w.opaintoen().adcchannel());
238+
}
239+
self.output.take()
240+
}
241+
}
242+
188243
opamps!{ @follower $opamp, $output, $($non_inverting_mask, $non_inverting),* }
189244
opamps!{ @open_loop_tt $opamp, $output, $($non_inverting_mask, $non_inverting),* : ($($inverting_mask, $inverting),*) }
190-
245+
opamps!{ @pga_tt $opamp, $output, $($non_inverting_mask, $non_inverting),* : ($($inverting_mask),*) }
191246
}
192247
)*
193248

@@ -336,6 +391,74 @@ macro_rules! opamps {
336391
})*
337392
}
338393
};
394+
395+
{
396+
@pga_tt
397+
$opamp:ident
398+
,
399+
$output:ty
400+
,
401+
$($non_inverting_mask:tt, $non_inverting:ty),*
402+
:
403+
$invertings:tt
404+
} => {
405+
$(
406+
opamps!{ @pga $opamp, $output, $non_inverting_mask, $non_inverting, $invertings }
407+
)*
408+
};
409+
410+
{
411+
@pga
412+
$opamp:ident
413+
,
414+
$output:ty
415+
,
416+
$non_inverting_mask:tt
417+
,
418+
$non_inverting:ty
419+
,
420+
($($inverting_mask:tt,),*)
421+
} => {
422+
paste::paste!{
423+
$(impl <IntoNonInverting, MODE, IntoOutput> IntoPga
424+
<IntoNonInverting, Config<MODE>, IntoOutput, $non_inverting> for Disabled
425+
where
426+
IntoNonInverting: Into<$non_inverting>,
427+
IntoOutput: Into<$output>,
428+
{
429+
fn pga(
430+
self,
431+
non_inverting: IntoNonInverting,
432+
config: Config<MODE>,
433+
output: Option<IntoOutput>,
434+
) -> Pga<$non_inverting, $config> {
435+
let non_inverting = non_inverting.into();
436+
let output = output.map(|output| output.into());
437+
unsafe {
438+
use crate::stm32::opamp::[<$opamp _csr>]::OPAINTOEN_A;
439+
(*crate::stm32::OPAMP::ptr())
440+
.[<$opamp _csr>]
441+
.write(|csr_w|
442+
csr_w.vp_sel()
443+
.$non_inverting_mask()
444+
.vm_sel()
445+
.pga()
446+
.pga_gain()
447+
.variant(config.pga_gain)
448+
.opaintoen()
449+
.variant(match output {
450+
Some(_) => OPAINTOEN_A::OutputPin,
451+
None => OPAINTOEN_A::Adcchannel,
452+
})
453+
.opaen()
454+
.enabled()
455+
);
456+
}
457+
Pga {non_inverting, config, output}
458+
}
459+
})*
460+
}
461+
};
339462
}
340463

341464
#[cfg(any(feature = "stm32g431", feature = "stm32g441", feature = "stm32g471",))]

0 commit comments

Comments
 (0)