45
45
//! }
46
46
//! ```
47
47
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
+
48
52
macro_rules! opamps {
49
53
{
50
54
$(
@@ -108,6 +112,18 @@ macro_rules! opamps {
108
112
output: Option <$output>,
109
113
}
110
114
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
+
111
127
/// Trait for opamps that can be run in follower mode.
112
128
pub trait IntoFollower <IntoInput , IntoOutput , Input >
113
129
where
@@ -127,6 +143,16 @@ macro_rules! opamps {
127
143
-> OpenLoop <NonInverting , Inverting >;
128
144
}
129
145
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
+
130
156
impl <Input > Follower <Input > {
131
157
132
158
/// Disables the opamp and returns the resources it held.
@@ -185,9 +211,38 @@ macro_rules! opamps {
185
211
}
186
212
}
187
213
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
+
188
243
opamps!{ @follower $opamp, $output, $( $non_inverting_mask, $non_inverting) ,* }
189
244
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 ) , * ) }
191
246
}
192
247
) *
193
248
@@ -336,6 +391,74 @@ macro_rules! opamps {
336
391
} ) *
337
392
}
338
393
} ;
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
+ } ;
339
462
}
340
463
341
464
#[ cfg( any( feature = "stm32g431" , feature = "stm32g441" , feature = "stm32g471" , ) ) ]
0 commit comments