@@ -17,10 +17,30 @@ use crate::stm32::RCC;
17
17
use embedded_hal:: delay:: DelayNs ;
18
18
19
19
pub trait DacOut < V > {
20
+ fn get_value ( & mut self ) -> V ;
21
+ fn set_value ( & mut self , val : V ) ;
22
+ }
23
+ impl < V , D : DacOutGet < V > + DacOutSet < V > > DacOut < V > for D {
24
+ fn get_value ( & mut self ) -> V {
25
+ DacOutGet :: get_value ( self )
26
+ }
27
+ fn set_value ( & mut self , val : V ) {
28
+ DacOutSet :: set_value ( self , val) ;
29
+ }
30
+ }
31
+ pub trait DacOutSet < V > {
20
32
fn set_value ( & mut self , val : V ) ;
33
+ }
34
+ pub trait DacOutGet < V > {
21
35
fn get_value ( & mut self ) -> V ;
22
36
}
23
37
38
+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
39
+ pub enum CountingDirection {
40
+ Decrement = 0 ,
41
+ Increment = 1 ,
42
+ }
43
+
24
44
pub struct GeneratorConfig {
25
45
mode : u8 ,
26
46
amp : u8 ,
@@ -34,35 +54,102 @@ impl GeneratorConfig {
34
54
}
35
55
}
36
56
37
- pub fn sawtooth ( amplitude : u8 ) -> Self {
57
+ pub fn noise ( seed : u8 ) -> Self {
38
58
Self {
39
- mode : 0b11 ,
40
- amp : amplitude ,
59
+ mode : 0b01 ,
60
+ amp : seed ,
41
61
}
42
62
}
63
+ }
43
64
44
- pub fn noise ( seed : u8 ) -> Self {
65
+ /// Used as regular trigger source and sawtooth generator reset trigger source
66
+ ///
67
+ /// # Safety
68
+ /// This trait should only be implemented for valid trigger sources with correct
69
+ /// bit patterns.
70
+ pub unsafe trait TriggerSource {
71
+ /// See stinctrigsel in reference manual for bit patterns
72
+ const BITS : u8 ;
73
+ }
74
+
75
+ /// Used as sawtooth generator inc trigger source
76
+ /// # Safety
77
+ /// This trait should only be implemented for valid trigger sources with correct
78
+ /// bit patterns.
79
+ pub unsafe trait IncTriggerSource {
80
+ /// See strsttrigsel in reference manual for bit patterns
81
+ const BITS : u8 ;
82
+ }
83
+
84
+ // https://www.youtube.com/watch?v=fUQaHyaXikw&ab_channel=STMicroelectronics
85
+ #[ derive( Debug , Clone , Copy ) ]
86
+ pub struct SawtoothConfig {
87
+ /// The sawtooth counter initial value (12 bits)
88
+ reset_value : u16 ,
89
+
90
+ dir : CountingDirection ,
91
+ step_size : u16 ,
92
+
93
+ inc_trigger : u8 ,
94
+ reset_trigger : u8 ,
95
+ }
96
+
97
+ impl Default for SawtoothConfig {
98
+ fn default ( ) -> Self {
99
+ Self :: with_slope ( CountingDirection :: Decrement , 0x10 )
100
+ }
101
+ }
102
+
103
+ impl SawtoothConfig {
104
+ /// NOTE: The DAC output is used from 12 MSBs of the sawtooth counter so
105
+ /// a step_size of 1 will only increment the output by 1 every 16th inc trigger
106
+ pub const fn with_slope ( dir : CountingDirection , step_size : u16 ) -> Self {
45
107
Self {
46
- mode : 0b01 ,
47
- amp : seed,
108
+ reset_value : u16:: MAX ,
109
+ dir,
110
+ step_size,
111
+ inc_trigger : 0b0000 , // SW trigger using `trigger_inc`-method
112
+ reset_trigger : 0b0000 , // SW trigger using `trigger_reset`-method
48
113
}
49
114
}
115
+
116
+ /// The sawtooth counter reset value (12 bits)
117
+ pub const fn reset_value ( mut self , reset_value : u16 ) -> Self {
118
+ self . reset_value = reset_value;
119
+ self
120
+ }
121
+
122
+ pub const fn slope ( mut self , dir : CountingDirection , step_size : u16 ) -> Self {
123
+ self . dir = dir;
124
+ self . step_size = step_size;
125
+ self
126
+ }
127
+
128
+ pub fn inc_trigger < T : IncTriggerSource > ( mut self , _inc_trigger : T ) -> Self {
129
+ self . inc_trigger = T :: BITS ;
130
+ self
131
+ }
132
+
133
+ pub fn reset_trigger < T : TriggerSource > ( mut self , _reset_trigger : T ) -> Self {
134
+ self . reset_trigger = T :: BITS ;
135
+ self
136
+ }
50
137
}
51
138
52
139
/// Enabled DAC (type state)
53
140
pub struct Enabled ;
54
141
// / Enabled DAC without output buffer (type state)
55
142
//pub struct EnabledUnbuffered;
56
- /// Enabled DAC wave generator (type state)
143
+ /// Enabled DAC wave generator for triangle or noise wave form (type state)
57
144
pub struct WaveGenerator ;
145
+ /// Enabled DAC wave generator for sawtooth wave form (type state)
146
+ pub struct SawtoothGenerator ;
58
147
/// Disabled DAC (type state)
59
148
pub struct Disabled ;
60
149
61
- pub trait ED { }
62
- impl ED for Enabled { }
63
- //impl ED for EnabledUnbuffered {}
64
- impl ED for WaveGenerator { }
65
- impl ED for Disabled { }
150
+ pub trait Generator { }
151
+ impl Generator for WaveGenerator { }
152
+ impl Generator for SawtoothConfig { }
66
153
67
154
pub trait Instance :
68
155
rcc:: Enable
@@ -177,7 +264,8 @@ impl_pin_for_dac!(
177
264
impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 > DacCh < DAC , CH , MODE_BITS , Disabled > {
178
265
/// TODO: The DAC does not seem to work unless `calibrate_buffer` has been callen
179
266
/// even when only using dac output internally
180
- pub fn enable ( self ) -> DacCh < DAC , CH , MODE_BITS , Enabled > {
267
+ pub fn enable ( self , _rcc : & mut Rcc ) -> DacCh < DAC , CH , MODE_BITS , Enabled > {
268
+ // We require rcc here just to ensure exclusive access to registers common to ch1 and ch2
181
269
let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
182
270
183
271
dac. mcr ( )
@@ -190,7 +278,9 @@ impl<DAC: Instance, const CH: u8, const MODE_BITS: u8> DacCh<DAC, CH, MODE_BITS,
190
278
pub fn enable_generator (
191
279
self ,
192
280
config : GeneratorConfig ,
281
+ _rcc : & mut Rcc ,
193
282
) -> DacCh < DAC , CH , MODE_BITS , WaveGenerator > {
283
+ // We require rcc here just to ensure exclusive access to registers common to ch1 and ch2
194
284
let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
195
285
196
286
dac. mcr ( )
@@ -204,6 +294,45 @@ impl<DAC: Instance, const CH: u8, const MODE_BITS: u8> DacCh<DAC, CH, MODE_BITS,
204
294
205
295
DacCh :: new ( )
206
296
}
297
+
298
+ pub fn enable_sawtooth_generator (
299
+ self ,
300
+ config : SawtoothConfig ,
301
+ _rcc : & mut Rcc ,
302
+ ) -> DacCh < DAC , CH , MODE_BITS , SawtoothGenerator > {
303
+ // TODO: We require rcc here just to ensure exclusive access to registers common to ch1 and ch2
304
+ let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
305
+
306
+ dac. mcr ( )
307
+ . modify ( |_, w| unsafe { w. mode ( CH ) . bits ( MODE_BITS ) } ) ;
308
+
309
+ unsafe {
310
+ dac. stmodr ( ) . modify ( |_, w| {
311
+ w. stinctrigsel ( CH )
312
+ . bits ( config. inc_trigger )
313
+ . strsttrigsel ( CH )
314
+ . bits ( config. reset_trigger )
315
+ } ) ;
316
+ }
317
+
318
+ dac. cr ( ) . modify ( |_, w| unsafe { w. wave ( CH ) . bits ( 0b11 ) } ) ;
319
+
320
+ unsafe {
321
+ dac. str ( CH as usize ) . write ( |w| {
322
+ w. stdir ( )
323
+ . bit ( config. dir == CountingDirection :: Increment )
324
+ . stincdata ( )
325
+ . bits ( config. step_size )
326
+ . strstdata ( )
327
+ . bits ( config. reset_value )
328
+ } ) ;
329
+ }
330
+
331
+ dac. cr ( ) . modify ( |_, w| w. en ( CH ) . set_bit ( ) ) ;
332
+ while dac. sr ( ) . read ( ) . dacrdy ( CH ) . bit_is_clear ( ) { }
333
+
334
+ DacCh :: new ( )
335
+ }
207
336
}
208
337
209
338
impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 , ED > DacCh < DAC , CH , MODE_BITS , ED > {
@@ -252,21 +381,35 @@ impl<DAC: Instance, const CH: u8, const MODE_BITS: u8, ED> DacCh<DAC, CH, MODE_B
252
381
253
382
/// DacOut implementation available in any Enabled/Disabled
254
383
/// state
255
- impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 , ED > DacOut < u16 >
256
- for DacCh < DAC , CH , MODE_BITS , ED >
384
+ impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 > DacOutSet < u16 >
385
+ for DacCh < DAC , CH , MODE_BITS , Enabled >
257
386
{
258
387
fn set_value ( & mut self , val : u16 ) {
259
388
let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
260
389
dac. dhr12r ( CH as usize )
261
390
. write ( |w| unsafe { w. bits ( val as u32 ) } ) ;
262
391
}
392
+ }
263
393
394
+ impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 , ED > DacOutGet < u16 >
395
+ for DacCh < DAC , CH , MODE_BITS , ED >
396
+ {
264
397
fn get_value ( & mut self ) -> u16 {
265
398
let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
266
399
dac. dor ( CH as usize ) . read ( ) . bits ( ) as u16
267
400
}
268
401
}
269
402
403
+ impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 > DacOutSet < u16 >
404
+ for DacCh < DAC , CH , MODE_BITS , SawtoothGenerator >
405
+ {
406
+ fn set_value ( & mut self , reset_value : u16 ) {
407
+ let dac = unsafe { & ( * <DAC >:: ptr ( ) ) } ;
408
+ dac. str ( CH as usize )
409
+ . modify ( |_r, w| unsafe { w. strstdata ( ) . bits ( reset_value) } ) ;
410
+ }
411
+ }
412
+
270
413
/// Wave generator state implementation
271
414
impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 > DacCh < DAC , CH , MODE_BITS , WaveGenerator > {
272
415
pub fn trigger ( & mut self ) {
@@ -275,6 +418,26 @@ impl<DAC: Instance, const CH: u8, const MODE_BITS: u8> DacCh<DAC, CH, MODE_BITS,
275
418
}
276
419
}
277
420
421
+ /// Sawtooth generator state implementation
422
+ impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 >
423
+ DacCh < DAC , CH , MODE_BITS , SawtoothGenerator >
424
+ {
425
+ pub fn trigger_reset ( & mut self ) {
426
+ let dac = unsafe { & ( * <DAC >:: ptr ( ) ) } ;
427
+ dac. swtrgr ( ) . write ( |w| w. swtrig ( CH ) . set_bit ( ) ) ;
428
+ }
429
+
430
+ pub fn trigger_inc ( & mut self ) {
431
+ let dac = unsafe { & ( * <DAC >:: ptr ( ) ) } ;
432
+ // TODO: Update once arrayified
433
+ if CH == 0 {
434
+ dac. swtrgr ( ) . write ( |w| w. swtrigb1 ( ) . set_bit ( ) ) ;
435
+ } else {
436
+ dac. swtrgr ( ) . write ( |w| w. swtrigb2 ( ) . set_bit ( ) ) ;
437
+ }
438
+ }
439
+ }
440
+
278
441
pub trait DacExt : Sized {
279
442
fn constrain < PINS > ( self , pins : PINS , rcc : & mut Rcc ) -> PINS :: Output
280
443
where
0 commit comments