@@ -12,17 +12,21 @@ mod common;
1212
1313use common:: test_pwm;
1414use fugit:: { ExtU32 , HertzU32 , MicrosDurationU32 } ;
15- use stm32_hrtim:: compare_register:: HrCompareRegister ;
16- use stm32_hrtim:: control:: HrPwmControl ;
17- use stm32_hrtim:: deadtime:: DeadtimeConfig ;
18- use stm32_hrtim:: output:: HrOutput ;
19- use stm32_hrtim:: timer:: HrTimer ;
20- use stm32_hrtim:: { HrParts , HrPwmAdvExt as _, Pscl64 } ;
21- use stm32g4xx_hal:: delay:: SYSTDelayExt ;
22- use stm32g4xx_hal:: gpio:: { GpioExt , PinExt } ;
23- use stm32g4xx_hal:: hrtim:: HrControltExt ;
24- use stm32g4xx_hal:: pwr:: PwrExt ;
25- use stm32g4xx_hal:: rcc:: { self , Rcc , RccExt } ;
15+ use stm32_hrtim:: {
16+ compare_register:: HrCompareRegister ,
17+ control:: HrPwmControl ,
18+ deadtime:: DeadtimeConfig ,
19+ output:: { HrOutput , ToHrOut } ,
20+ timer:: HrTimer ,
21+ DacResetOnCounterReset , DacStepOnCmp2 , HrParts , HrPwmAdvExt as _, Pscl64 ,
22+ } ;
23+ use stm32g4xx_hal:: {
24+ delay:: SYSTDelayExt ,
25+ gpio:: { GpioExt , PinExt } ,
26+ hrtim:: { HrControltExt , HrtimPin } ,
27+ pwr:: PwrExt ,
28+ rcc:: { self , Rcc , RccExt } ,
29+ } ;
2630
2731use hal:: stm32;
2832use stm32g4xx_hal as hal;
@@ -35,6 +39,10 @@ type Timer = crate::common::Timer<CYCLES_PER_US>;
3539#[ embedded_test:: tests]
3640mod tests {
3741 use embedded_hal:: delay:: DelayNs ;
42+ use stm32g4xx_hal:: {
43+ adc:: { self , temperature:: Temperature , AdcClaim , AdcCommonExt } ,
44+ dac:: { self , DacExt , DacOut , SawtoothConfig } ,
45+ } ;
3846
3947 #[ test]
4048 fn simple ( ) {
@@ -63,7 +71,7 @@ mod tests {
6371 ..
6472 } ,
6573 mut hr_control,
66- ) = setup ( pin, None , dp. HRTIM_TIMA , dp. HRTIM_COMMON , & mut rcc) ;
74+ ) = setup_hrtim ( pin, None , dp. HRTIM_TIMA , dp. HRTIM_COMMON , & mut rcc) ;
6775
6876 cr1. set_duty ( PERIOD / 2 ) ;
6977 out. enable_rst_event ( & cr1) ; // Set low on compare match with cr1
@@ -99,6 +107,104 @@ mod tests {
99107
100108 deadtime_test ( 1 , 68 ) ;
101109 }
110+
111+ /// Test adc trigger and DAC trigger
112+ ///
113+ /// Setup hrtim with DAC to generate a Sawtooth waveform. Use a compare register to accurately
114+ /// place the measurement point.
115+ ///
116+ /// | /| /| /|
117+ /// | * / | / | / |
118+ /// | * / | / | / |
119+ /// | X | / | / |
120+ /// | / * | / | / |
121+ /// |/ * |/ |/ |
122+ /// |--->*
123+ /// cr3 indicates where in waveform to trigger ADC
124+ ///
125+ #[ test]
126+ fn adc_trigger ( ) {
127+ use super :: * ;
128+
129+ let mut cp = stm32:: CorePeripherals :: take ( ) . unwrap ( ) ;
130+ let dp = stm32:: Peripherals :: take ( ) . unwrap ( ) ;
131+
132+ // Set system frequency to 16MHz * 15/1/2 = 120MHz
133+ // This would lead to HrTim running at 120MHz * 32 = 3.84...
134+ let mut rcc = setup_rcc_120MHz ( dp. PWR , dp. RCC ) ;
135+ assert_eq ! ( rcc. clocks. sys_clk, F_SYS ) ;
136+ let mut delay = cp. SYST . delay ( & rcc. clocks ) ;
137+
138+ let gpioa = dp. GPIOA . split ( & mut rcc) ;
139+ let pa1 = gpioa. pa1 . into_analog ( ) ;
140+ let pa4 = gpioa. pa4 ;
141+ let pin = gpioa. pa8 ;
142+
143+ let ( mut hrtimer, mut hr_control) =
144+ setup_hrtim ( pin, None , dp. HRTIM_TIMA , dp. HRTIM_COMMON , & mut rcc) ;
145+
146+ hrtimer. cr1 . set_duty ( PERIOD / 2 ) ;
147+ hrtimer. out . enable_rst_event ( & hrtimer. cr1 ) ; // Set low on compare match with cr1
148+ hrtimer. out . enable_set_event ( & hrtimer. timer ) ; // Set high at new period
149+
150+ let dac_step_per_trigger = 16 ;
151+ let cr2_ticks_per_dac_trigger = dac_step_per_trigger;
152+ hrtimer. cr2 . set_duty ( cr2_ticks_per_dac_trigger) ;
153+ let dac1ch1 = dp. DAC1 . constrain ( pa4, & mut rcc) ;
154+ let mut ref_dac = dac1ch1. enable_sawtooth_generator (
155+ SawtoothConfig :: with_slope ( dac:: CountingDirection :: Decrement , dac_step_per_trigger)
156+ . inc_trigger ( & hrtimer. cr2 )
157+ . reset_trigger ( & hrtimer. timer ) ,
158+ & mut rcc,
159+ ) ;
160+
161+ hr_control. adc_trigger1 . enable_source ( & hrtimer. cr3 ) ;
162+
163+ defmt:: debug!( "Setup Adc1" ) ;
164+ let mut adc12_common = dp
165+ . ADC12_COMMON
166+ . claim ( adc:: config:: ClockMode :: AdcHclkDiv4 , & mut rcc) ;
167+ let mut adc = adc12_common. claim ( dp. ADC1 , & mut delay) ;
168+
169+ adc. set_external_trigger ( (
170+ adc:: config:: TriggerMode :: RisingEdge ,
171+ ( & hr_control. adc_trigger1 ) . into ( ) ,
172+ ) ) ;
173+ adc12_common. enable_temperature ( ) ;
174+ adc. set_continuous ( hal:: adc:: config:: Continuous :: Discontinuous ) ;
175+ adc. reset_sequence ( ) ;
176+ adc. configure_channel (
177+ & pa1,
178+ adc:: config:: Sequence :: One ,
179+ adc:: config:: SampleTime :: Cycles_12_5 ,
180+ ) ;
181+ let mut adc = adc. enable ( ) . into_dynamic_adc ( ) ;
182+ hrtimer. timer . start ( & mut hr_control. control ) ;
183+
184+ ref_dac. set_value ( 4095 ) ;
185+
186+ defmt:: debug!( "Awaiting first dac rst trigger" ) ;
187+ while ref_dac. get_value ( ) == 0 { }
188+
189+ //out.enable();
190+
191+ adc. start_conversion ( ) ;
192+
193+ for _ in 0 ..2 {
194+ let margin = 256 ;
195+ for sampling_point in ( margin..( PERIOD - margin) ) . step_by ( 16 ) {
196+ hrtimer. cr3 . set_duty ( sampling_point) ; // Set sampling point
197+ let sampling_point_as_12bit = sampling_point >> 4 ;
198+
199+ // Dac generates a sawtooth with negative slope which starts at 4095 every new period
200+ let expected_dac_value = 4095 - sampling_point_as_12bit;
201+ adc. wait_for_conversion_sequence ( ) ;
202+ let adc_value = adc. current_sample ( ) ;
203+ let diff = adc_value. abs_diff ( expected_dac_value) ;
204+ assert ! ( diff < 20 ) ;
205+ }
206+ }
207+ }
102208}
103209
104210#[ allow( non_snake_case) ]
@@ -120,16 +226,26 @@ fn setup_rcc_120MHz(pwr: stm32::PWR, rcc: stm32::RCC) -> Rcc {
120226 )
121227}
122228
123- fn setup < P : stm32g4xx_hal :: hrtim :: HrtimPin < stm32 :: HRTIM_TIMA > > (
229+ fn setup_hrtim < P > (
124230 pins : P ,
125231 deadtime_cfg : Option < DeadtimeConfig > ,
126232 hrtim_tima : stm32:: HRTIM_TIMA ,
127233 hrtim_common : stm32:: HRTIM_COMMON ,
128234 rcc : & mut Rcc ,
129235) -> (
130- HrParts < stm32:: HRTIM_TIMA , Pscl64 , P :: Out < Pscl64 > > ,
236+ HrParts <
237+ stm32:: HRTIM_TIMA ,
238+ Pscl64 ,
239+ <P as ToHrOut < stm32:: HRTIM_TIMA , DacResetOnCounterReset , DacStepOnCmp2 > >:: Out < Pscl64 > ,
240+ DacResetOnCounterReset ,
241+ DacStepOnCmp2 ,
242+ > ,
131243 HrPwmControl ,
132- ) {
244+ )
245+ where
246+ P : HrtimPin < stm32:: HRTIM_TIMA >
247+ + ToHrOut < stm32:: HRTIM_TIMA , DacResetOnCounterReset , DacStepOnCmp2 > ,
248+ {
133249 use stm32g4xx_hal:: hrtim:: HrPwmBuilderExt ;
134250 let ( hr_control, ..) = hrtim_common. hr_control ( rcc) . wait_for_calibration ( ) ;
135251 let mut hr_control = hr_control. constrain ( ) ;
@@ -138,19 +254,20 @@ fn setup<P: stm32g4xx_hal::hrtim::HrtimPin<stm32::HRTIM_TIMA>>(
138254 // With a period of 60_000 set, this would be 60MHz/60_000 = 1kHz
139255 let prescaler = Pscl64 ;
140256
141- let mut hr_tim_builder: stm32_hrtim:: HrPwmBuilder <
142- stm32:: HRTIM_TIMA ,
143- Pscl64 ,
144- stm32_hrtim:: PreloadSource ,
145- P ,
146- > = hrtim_tima
257+ let mut hr_tim_builder = hrtim_tima
147258 . pwm_advanced ( pins)
148259 . prescaler ( prescaler)
149260 . period ( PERIOD ) ;
261+
150262 if let Some ( dt) = deadtime_cfg {
151263 hr_tim_builder = hr_tim_builder. deadtime ( dt) ;
152264 }
153- ( hr_tim_builder. finalize ( & mut hr_control) , hr_control)
265+ (
266+ hr_tim_builder
267+ . dac_trigger_cfg ( DacResetOnCounterReset , DacStepOnCmp2 )
268+ . finalize ( & mut hr_control) ,
269+ hr_control,
270+ )
154271}
155272
156273fn deadtime_test ( deadtime_rising_us : u32 , deadtime_falling_us : u32 ) {
@@ -189,7 +306,7 @@ fn deadtime_test(deadtime_rising_us: u32, deadtime_falling_us: u32) {
189306 ..
190307 } ,
191308 mut hr_control,
192- ) = setup (
309+ ) = setup_hrtim (
193310 ( pin, complementary_pin) ,
194311 Some ( deadtime_cfg) ,
195312 dp. HRTIM_TIMA ,
0 commit comments