@@ -10,17 +10,21 @@ mod common;
1010
1111use common:: test_pwm;
1212use fugit:: { ExtU32 , HertzU32 , MicrosDurationU32 } ;
13- use stm32_hrtim:: compare_register:: HrCompareRegister ;
14- use stm32_hrtim:: control:: HrPwmControl ;
15- use stm32_hrtim:: deadtime:: DeadtimeConfig ;
16- use stm32_hrtim:: output:: HrOutput ;
17- use stm32_hrtim:: timer:: HrTimer ;
18- use stm32_hrtim:: { HrParts , HrPwmAdvExt as _, Pscl64 } ;
19- use stm32g4xx_hal:: delay:: SYSTDelayExt ;
20- use stm32g4xx_hal:: gpio:: { GpioExt , PinExt } ;
21- use stm32g4xx_hal:: hrtim:: HrControltExt ;
22- use stm32g4xx_hal:: pwr:: PwrExt ;
23- use stm32g4xx_hal:: rcc:: { self , Rcc , RccExt } ;
13+ use stm32_hrtim:: {
14+ compare_register:: HrCompareRegister ,
15+ control:: HrPwmControl ,
16+ deadtime:: DeadtimeConfig ,
17+ output:: { HrOutput , ToHrOut } ,
18+ timer:: HrTimer ,
19+ DacResetOnCounterReset , DacStepOnCmp2 , HrParts , HrPwmAdvExt as _, Pscl64 ,
20+ } ;
21+ use stm32g4xx_hal:: {
22+ delay:: SYSTDelayExt ,
23+ gpio:: { GpioExt , PinExt } ,
24+ hrtim:: { HrControltExt , HrtimPin } ,
25+ pwr:: PwrExt ,
26+ rcc:: { self , Rcc , RccExt } ,
27+ } ;
2428
2529use hal:: stm32;
2630use stm32g4xx_hal as hal;
@@ -33,6 +37,10 @@ type Timer = crate::common::Timer<CYCLES_PER_US>;
3337#[ embedded_test:: tests]
3438mod tests {
3539 use embedded_hal:: delay:: DelayNs ;
40+ use stm32g4xx_hal:: {
41+ adc:: { self , temperature:: Temperature , AdcClaim , AdcCommonExt } ,
42+ dac:: { self , DacExt , DacOut , SawtoothConfig } ,
43+ } ;
3644
3745 #[ test]
3846 fn simple ( ) {
@@ -61,7 +69,7 @@ mod tests {
6169 ..
6270 } ,
6371 mut hr_control,
64- ) = setup ( pin, None , dp. HRTIM_TIMA , dp. HRTIM_COMMON , & mut rcc) ;
72+ ) = setup_hrtim ( pin, None , dp. HRTIM_TIMA , dp. HRTIM_COMMON , & mut rcc) ;
6573
6674 cr1. set_duty ( PERIOD / 2 ) ;
6775 out. enable_rst_event ( & cr1) ; // Set low on compare match with cr1
@@ -97,6 +105,104 @@ mod tests {
97105
98106 deadtime_test ( 1 , 68 ) ;
99107 }
108+
109+ /// Test adc trigger and DAC trigger
110+ ///
111+ /// Setup hrtim with DAC to generate a Sawtooth waveform. Use a compare register to accurately
112+ /// place the measurement point.
113+ ///
114+ /// | /| /| /|
115+ /// | * / | / | / |
116+ /// | * / | / | / |
117+ /// | X | / | / |
118+ /// | / * | / | / |
119+ /// |/ * |/ |/ |
120+ /// |--->*
121+ /// cr3 indicates where in waveform to trigger ADC
122+ ///
123+ #[ test]
124+ fn adc_trigger ( ) {
125+ use super :: * ;
126+
127+ let mut cp = stm32:: CorePeripherals :: take ( ) . unwrap ( ) ;
128+ let dp = stm32:: Peripherals :: take ( ) . unwrap ( ) ;
129+
130+ // Set system frequency to 16MHz * 15/1/2 = 120MHz
131+ // This would lead to HrTim running at 120MHz * 32 = 3.84...
132+ let mut rcc = setup_rcc_120MHz ( dp. PWR , dp. RCC ) ;
133+ assert_eq ! ( rcc. clocks. sys_clk, F_SYS ) ;
134+ let mut delay = cp. SYST . delay ( & rcc. clocks ) ;
135+
136+ let gpioa = dp. GPIOA . split ( & mut rcc) ;
137+ let pa1 = gpioa. pa1 . into_analog ( ) ;
138+ let pa4 = gpioa. pa4 ;
139+ let pin = gpioa. pa8 ;
140+
141+ let ( mut hrtimer, mut hr_control) =
142+ setup_hrtim ( pin, None , dp. HRTIM_TIMA , dp. HRTIM_COMMON , & mut rcc) ;
143+
144+ hrtimer. cr1 . set_duty ( PERIOD / 2 ) ;
145+ hrtimer. out . enable_rst_event ( & hrtimer. cr1 ) ; // Set low on compare match with cr1
146+ hrtimer. out . enable_set_event ( & hrtimer. timer ) ; // Set high at new period
147+
148+ let dac_step_per_trigger = 16 ;
149+ let cr2_ticks_per_dac_trigger = dac_step_per_trigger;
150+ hrtimer. cr2 . set_duty ( cr2_ticks_per_dac_trigger) ;
151+ let dac1ch1 = dp. DAC1 . constrain ( pa4, & mut rcc) ;
152+ let mut ref_dac = dac1ch1. enable_sawtooth_generator (
153+ SawtoothConfig :: with_slope ( dac:: CountingDirection :: Decrement , dac_step_per_trigger)
154+ . inc_trigger ( & hrtimer. cr2 )
155+ . reset_trigger ( & hrtimer. timer ) ,
156+ & mut rcc,
157+ ) ;
158+
159+ hr_control. adc_trigger1 . enable_source ( & hrtimer. cr3 ) ;
160+
161+ defmt:: debug!( "Setup Adc1" ) ;
162+ let mut adc12_common = dp
163+ . ADC12_COMMON
164+ . claim ( adc:: config:: ClockMode :: AdcHclkDiv4 , & mut rcc) ;
165+ let mut adc = adc12_common. claim ( dp. ADC1 , & mut delay) ;
166+
167+ adc. set_external_trigger ( (
168+ adc:: config:: TriggerMode :: RisingEdge ,
169+ ( & hr_control. adc_trigger1 ) . into ( ) ,
170+ ) ) ;
171+ adc12_common. enable_temperature ( ) ;
172+ adc. set_continuous ( hal:: adc:: config:: Continuous :: Discontinuous ) ;
173+ adc. reset_sequence ( ) ;
174+ adc. configure_channel (
175+ & pa1,
176+ adc:: config:: Sequence :: One ,
177+ adc:: config:: SampleTime :: Cycles_12_5 ,
178+ ) ;
179+ let mut adc = adc. enable ( ) . into_dynamic_adc ( ) ;
180+ hrtimer. timer . start ( & mut hr_control. control ) ;
181+
182+ ref_dac. set_value ( 4095 ) ;
183+
184+ defmt:: debug!( "Awaiting first dac rst trigger" ) ;
185+ while ref_dac. get_value ( ) == 0 { }
186+
187+ //out.enable();
188+
189+ adc. start_conversion ( ) ;
190+
191+ for _ in 0 ..2 {
192+ let margin = 256 ;
193+ for sampling_point in ( margin..( PERIOD - margin) ) . step_by ( 16 ) {
194+ hrtimer. cr3 . set_duty ( sampling_point) ; // Set sampling point
195+ let sampling_point_as_12bit = sampling_point >> 4 ;
196+
197+ // Dac generates a sawtooth with negative slope which starts at 4095 every new period
198+ let expected_dac_value = 4095 - sampling_point_as_12bit;
199+ adc. wait_for_conversion_sequence ( ) ;
200+ let adc_value = adc. current_sample ( ) ;
201+ let diff = adc_value. abs_diff ( expected_dac_value) ;
202+ assert ! ( diff < 20 ) ;
203+ }
204+ }
205+ }
100206}
101207
102208#[ allow( non_snake_case) ]
@@ -118,16 +224,26 @@ fn setup_rcc_120MHz(pwr: stm32::PWR, rcc: stm32::RCC) -> Rcc {
118224 )
119225}
120226
121- fn setup < P : stm32g4xx_hal :: hrtim :: HrtimPin < stm32 :: HRTIM_TIMA > > (
227+ fn setup_hrtim < P > (
122228 pins : P ,
123229 deadtime_cfg : Option < DeadtimeConfig > ,
124230 hrtim_tima : stm32:: HRTIM_TIMA ,
125231 hrtim_common : stm32:: HRTIM_COMMON ,
126232 rcc : & mut Rcc ,
127233) -> (
128- HrParts < stm32:: HRTIM_TIMA , Pscl64 , P :: Out < Pscl64 > > ,
234+ HrParts <
235+ stm32:: HRTIM_TIMA ,
236+ Pscl64 ,
237+ <P as ToHrOut < stm32:: HRTIM_TIMA , DacResetOnCounterReset , DacStepOnCmp2 > >:: Out < Pscl64 > ,
238+ DacResetOnCounterReset ,
239+ DacStepOnCmp2 ,
240+ > ,
129241 HrPwmControl ,
130- ) {
242+ )
243+ where
244+ P : HrtimPin < stm32:: HRTIM_TIMA >
245+ + ToHrOut < stm32:: HRTIM_TIMA , DacResetOnCounterReset , DacStepOnCmp2 > ,
246+ {
131247 use stm32g4xx_hal:: hrtim:: HrPwmBuilderExt ;
132248 let ( hr_control, ..) = hrtim_common. hr_control ( rcc) . wait_for_calibration ( ) ;
133249 let mut hr_control = hr_control. constrain ( ) ;
@@ -136,19 +252,20 @@ fn setup<P: stm32g4xx_hal::hrtim::HrtimPin<stm32::HRTIM_TIMA>>(
136252 // With a period of 60_000 set, this would be 60MHz/60_000 = 1kHz
137253 let prescaler = Pscl64 ;
138254
139- let mut hr_tim_builder: stm32_hrtim:: HrPwmBuilder <
140- stm32:: HRTIM_TIMA ,
141- Pscl64 ,
142- stm32_hrtim:: PreloadSource ,
143- P ,
144- > = hrtim_tima
255+ let mut hr_tim_builder = hrtim_tima
145256 . pwm_advanced ( pins)
146257 . prescaler ( prescaler)
147258 . period ( PERIOD ) ;
259+
148260 if let Some ( dt) = deadtime_cfg {
149261 hr_tim_builder = hr_tim_builder. deadtime ( dt) ;
150262 }
151- ( hr_tim_builder. finalize ( & mut hr_control) , hr_control)
263+ (
264+ hr_tim_builder
265+ . dac_trigger_cfg ( DacResetOnCounterReset , DacStepOnCmp2 )
266+ . finalize ( & mut hr_control) ,
267+ hr_control,
268+ )
152269}
153270
154271fn deadtime_test ( deadtime_rising_us : u32 , deadtime_falling_us : u32 ) {
@@ -187,7 +304,7 @@ fn deadtime_test(deadtime_rising_us: u32, deadtime_falling_us: u32) {
187304 ..
188305 } ,
189306 mut hr_control,
190- ) = setup (
307+ ) = setup_hrtim (
191308 ( pin, complementary_pin) ,
192309 Some ( deadtime_cfg) ,
193310 dp. HRTIM_TIMA ,
0 commit comments