@@ -17,10 +17,30 @@ use crate::stm32::RCC;
1717use embedded_hal:: delay:: DelayNs ;
1818
1919pub 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 > {
2032 fn set_value ( & mut self , val : V ) ;
33+ }
34+ pub trait DacOutGet < V > {
2135 fn get_value ( & mut self ) -> V ;
2236}
2337
38+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
39+ pub enum CountingDirection {
40+ Decrement = 0 ,
41+ Increment = 1 ,
42+ }
43+
2444pub struct GeneratorConfig {
2545 mode : u8 ,
2646 amp : u8 ,
@@ -34,35 +54,102 @@ impl GeneratorConfig {
3454 }
3555 }
3656
37- pub fn sawtooth ( amplitude : u8 ) -> Self {
57+ pub fn noise ( seed : u8 ) -> Self {
3858 Self {
39- mode : 0b11 ,
40- amp : amplitude ,
59+ mode : 0b01 ,
60+ amp : seed ,
4161 }
4262 }
63+ }
4364
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 {
45107 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
48113 }
49114 }
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+ }
50137}
51138
52139/// Enabled DAC (type state)
53140pub struct Enabled ;
54141// / Enabled DAC without output buffer (type state)
55142//pub struct EnabledUnbuffered;
56- /// Enabled DAC wave generator (type state)
143+ /// Enabled DAC wave generator for triangle or noise wave form (type state)
57144pub struct WaveGenerator ;
145+ /// Enabled DAC wave generator for sawtooth wave form (type state)
146+ pub struct SawtoothGenerator ;
58147/// Disabled DAC (type state)
59148pub struct Disabled ;
60149
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 { }
66153
67154pub trait Instance :
68155 rcc:: Enable
@@ -177,7 +264,8 @@ impl_pin_for_dac!(
177264impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 > DacCh < DAC , CH , MODE_BITS , Disabled > {
178265 /// TODO: The DAC does not seem to work unless `calibrate_buffer` has been callen
179266 /// 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
181269 let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
182270
183271 dac. mcr ( )
@@ -190,7 +278,9 @@ impl<DAC: Instance, const CH: u8, const MODE_BITS: u8> DacCh<DAC, CH, MODE_BITS,
190278 pub fn enable_generator (
191279 self ,
192280 config : GeneratorConfig ,
281+ _rcc : & mut Rcc ,
193282 ) -> DacCh < DAC , CH , MODE_BITS , WaveGenerator > {
283+ // We require rcc here just to ensure exclusive access to registers common to ch1 and ch2
194284 let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
195285
196286 dac. mcr ( )
@@ -204,6 +294,45 @@ impl<DAC: Instance, const CH: u8, const MODE_BITS: u8> DacCh<DAC, CH, MODE_BITS,
204294
205295 DacCh :: new ( )
206296 }
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+ }
207336}
208337
209338impl < 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
252381
253382/// DacOut implementation available in any Enabled/Disabled
254383/// 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 >
257386{
258387 fn set_value ( & mut self , val : u16 ) {
259388 let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
260389 dac. dhr12r ( CH as usize )
261390 . write ( |w| unsafe { w. bits ( val as u32 ) } ) ;
262391 }
392+ }
263393
394+ impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 , ED > DacOutGet < u16 >
395+ for DacCh < DAC , CH , MODE_BITS , ED >
396+ {
264397 fn get_value ( & mut self ) -> u16 {
265398 let dac = unsafe { & ( * DAC :: ptr ( ) ) } ;
266399 dac. dor ( CH as usize ) . read ( ) . bits ( ) as u16
267400 }
268401}
269402
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+
270413/// Wave generator state implementation
271414impl < DAC : Instance , const CH : u8 , const MODE_BITS : u8 > DacCh < DAC , CH , MODE_BITS , WaveGenerator > {
272415 pub fn trigger ( & mut self ) {
@@ -275,6 +418,26 @@ impl<DAC: Instance, const CH: u8, const MODE_BITS: u8> DacCh<DAC, CH, MODE_BITS,
275418 }
276419}
277420
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+
278441pub trait DacExt : Sized {
279442 fn constrain < PINS > ( self , pins : PINS , rcc : & mut Rcc ) -> PINS :: Output
280443 where
0 commit comments