5454*/
5555
5656use core:: marker:: PhantomData ;
57+ use core:: marker:: { Copy } ;
5758use core:: mem;
5859
5960use crate :: hal;
@@ -68,6 +69,7 @@ use crate::afio::MAPR;
6869use crate :: bb;
6970use crate :: gpio:: { self , Alternate , PushPull } ;
7071use crate :: time:: Hertz ;
72+ use crate :: time:: U32Ext ;
7173use crate :: timer:: Timer ;
7274
7375pub trait Pins < REMAP , P > {
@@ -76,6 +78,26 @@ pub trait Pins<REMAP, P> {
7678 const C3 : bool = false ;
7779 const C4 : bool = false ;
7880 type Channels ;
81+
82+ fn check_used ( c : Channel ) -> Channel {
83+ if ( c == Channel :: C1 && Self :: C1 )
84+ || ( c == Channel :: C2 && Self :: C2 )
85+ || ( c == Channel :: C3 && Self :: C3 )
86+ || ( c == Channel :: C4 && Self :: C4 )
87+ {
88+ c
89+ } else {
90+ panic ! ( "Unused channel" )
91+ }
92+ }
93+ }
94+
95+ #[ derive( Clone , Copy , PartialEq ) ]
96+ pub enum Channel {
97+ C1 ,
98+ C2 ,
99+ C3 ,
100+ C4 ,
79101}
80102
81103use crate :: timer:: sealed:: { Ch1 , Ch2 , Ch3 , Ch4 , Remap } ;
@@ -89,7 +111,7 @@ macro_rules! pins_impl {
89111 $( $PINX: $TRAIT<REMAP > + gpio:: Mode <Alternate <PushPull >>, ) +
90112 {
91113 $( const $ENCHX: bool = true ; ) +
92- type Channels = ( $( Pwm <TIM , $ENCHX>) ,+) ;
114+ type Channels = ( $( PwmChannel <TIM , $ENCHX>) ,+) ;
93115 }
94116 ) +
95117 } ;
@@ -115,7 +137,7 @@ pins_impl!(
115137
116138#[ cfg( any( feature = "stm32f100" , feature = "stm32f103" , feature = "stm32f105" , ) ) ]
117139impl Timer < TIM1 > {
118- pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> PINS :: Channels
140+ pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> Pwm < TIM1 , REMAP , P , PINS >
119141 where
120142 REMAP : Remap < Periph = TIM1 > ,
121143 PINS : Pins < REMAP , P > ,
@@ -133,7 +155,7 @@ impl Timer<TIM1> {
133155}
134156
135157impl Timer < TIM2 > {
136- pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> PINS :: Channels
158+ pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> Pwm < TIM2 , REMAP , P , PINS >
137159 where
138160 REMAP : Remap < Periph = TIM2 > ,
139161 PINS : Pins < REMAP , P > ,
@@ -147,7 +169,7 @@ impl Timer<TIM2> {
147169}
148170
149171impl Timer < TIM3 > {
150- pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> PINS :: Channels
172+ pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> Pwm < TIM3 , REMAP , P , PINS >
151173 where
152174 REMAP : Remap < Periph = TIM3 > ,
153175 PINS : Pins < REMAP , P > ,
@@ -162,7 +184,7 @@ impl Timer<TIM3> {
162184
163185#[ cfg( feature = "medium" ) ]
164186impl Timer < TIM4 > {
165- pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> PINS :: Channels
187+ pub fn pwm < REMAP , P , PINS , T > ( self , _pins : PINS , mapr : & mut MAPR , freq : T ) -> Pwm < TIM4 , REMAP , P , PINS >
166188 where
167189 REMAP : Remap < Periph = TIM4 > ,
168190 PINS : Pins < REMAP , P > ,
@@ -175,7 +197,26 @@ impl Timer<TIM4> {
175197 }
176198}
177199
178- pub struct Pwm < TIM , CHANNEL > {
200+ pub struct Pwm < TIM , REMAP , P , PINS >
201+ where
202+ REMAP : Remap < Periph = TIM > ,
203+ PINS : Pins < REMAP , P >
204+ {
205+ clk : Hertz ,
206+ _pins : PhantomData < ( TIM , REMAP , P , PINS ) > ,
207+ }
208+
209+ impl < TIM , REMAP , P , PINS > Pwm < TIM , REMAP , P , PINS >
210+ where
211+ REMAP : Remap < Periph = TIM > ,
212+ PINS : Pins < REMAP , P >
213+ {
214+ pub fn split ( self ) -> PINS :: Channels {
215+ unsafe { mem:: MaybeUninit :: uninit ( ) . assume_init ( ) }
216+ }
217+ }
218+
219+ pub struct PwmChannel < TIM , CHANNEL > {
179220 _channel : PhantomData < CHANNEL > ,
180221 _tim : PhantomData < TIM > ,
181222}
@@ -193,7 +234,7 @@ macro_rules! hal {
193234 _pins: PINS ,
194235 freq: Hertz ,
195236 clk: Hertz ,
196- ) -> PINS :: Channels
237+ ) -> Pwm <$TIMX , REMAP , P , PINS >
197238 where
198239 REMAP : Remap <Periph = $TIMX>,
199240 PINS : Pins <REMAP , P >,
@@ -240,10 +281,97 @@ macro_rules! hal {
240281 . set_bit( )
241282 ) ;
242283
243- unsafe { mem:: MaybeUninit :: uninit( ) . assume_init( ) }
284+ Pwm {
285+ clk: clk,
286+ _pins: PhantomData
287+ }
288+ }
289+
290+ /*
291+ The following implemention of the embedded_hal::Pwm uses Hertz as a time type. This was choosen
292+ because of the timescales of operations being on the order of nanoseconds and not being able to
293+ efficently represent a float on the hardware. It might be possible to change the time type to
294+ a different time based using such as the nanosecond. The issue with doing so is that the max
295+ delay would then be at just a little over 2 seconds because of the 32 bit depth of the number.
296+ Using milliseconds is also an option, however, using this as a base unit means that only there
297+ could be resolution issues when trying to get a specific value, because of the integer nature.
298+
299+ To find a middle ground, the Hertz type is used as a base here and the Into trait has been
300+ defined for several base time units. This will allow for calling the set_period method with
301+ something that is natural to both the MCU and the end user.
302+ */
303+ impl <REMAP , P , PINS > hal:: Pwm for Pwm <$TIMX, REMAP , P , PINS > where
304+ REMAP : Remap <Periph = $TIMX>,
305+ PINS : Pins <REMAP , P >,
306+ {
307+ type Channel = Channel ;
308+ type Duty = u16 ;
309+ type Time = Hertz ;
310+
311+ fn enable( & mut self , channel: Self :: Channel ) {
312+ match PINS :: check_used( channel) {
313+ Channel :: C1 => unsafe { bb:: set( & ( * $TIMX:: ptr( ) ) . ccer, 0 ) } ,
314+ Channel :: C2 => unsafe { bb:: set( & ( * $TIMX:: ptr( ) ) . ccer, 4 ) } ,
315+ Channel :: C3 => unsafe { bb:: set( & ( * $TIMX:: ptr( ) ) . ccer, 8 ) } ,
316+ Channel :: C4 => unsafe { bb:: set( & ( * $TIMX:: ptr( ) ) . ccer, 12 ) }
317+ }
318+ }
319+
320+ fn disable( & mut self , channel: Self :: Channel ) {
321+ match PINS :: check_used( channel) {
322+ Channel :: C1 => unsafe { bb:: clear( & ( * $TIMX:: ptr( ) ) . ccer, 0 ) } ,
323+ Channel :: C2 => unsafe { bb:: clear( & ( * $TIMX:: ptr( ) ) . ccer, 4 ) } ,
324+ Channel :: C3 => unsafe { bb:: clear( & ( * $TIMX:: ptr( ) ) . ccer, 8 ) } ,
325+ Channel :: C4 => unsafe { bb:: clear( & ( * $TIMX:: ptr( ) ) . ccer, 12 ) } ,
326+ }
327+ }
328+
329+ fn get_duty( & self , channel: Self :: Channel ) -> Self :: Duty {
330+ match PINS :: check_used( channel) {
331+ Channel :: C1 => unsafe { ( * $TIMX:: ptr( ) ) . ccr1. read( ) . ccr( ) . bits( ) } ,
332+ Channel :: C2 => unsafe { ( * $TIMX:: ptr( ) ) . ccr2. read( ) . ccr( ) . bits( ) } ,
333+ Channel :: C3 => unsafe { ( * $TIMX:: ptr( ) ) . ccr3. read( ) . ccr( ) . bits( ) } ,
334+ Channel :: C4 => unsafe { ( * $TIMX:: ptr( ) ) . ccr4. read( ) . ccr( ) . bits( ) } ,
335+ }
336+ }
337+
338+ fn set_duty( & mut self , channel: Self :: Channel , duty: Self :: Duty ) {
339+ match PINS :: check_used( channel) {
340+ Channel :: C1 => unsafe { ( * $TIMX:: ptr( ) ) . ccr1. write( |w| w. ccr( ) . bits( duty) ) } ,
341+ Channel :: C2 => unsafe { ( * $TIMX:: ptr( ) ) . ccr2. write( |w| w. ccr( ) . bits( duty) ) } ,
342+ Channel :: C3 => unsafe { ( * $TIMX:: ptr( ) ) . ccr3. write( |w| w. ccr( ) . bits( duty) ) } ,
343+ Channel :: C4 => unsafe { ( * $TIMX:: ptr( ) ) . ccr4. write( |w| w. ccr( ) . bits( duty) ) } ,
344+ }
345+ }
346+
347+ fn get_max_duty( & self ) -> Self :: Duty {
348+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) }
349+ }
350+
351+ fn get_period( & self ) -> Self :: Time {
352+ let clk = self . clk;
353+ let psc: u16 = unsafe { ( * $TIMX:: ptr( ) ) . psc. read( ) . psc( ) . bits( ) } ;
354+ let arr: u16 = unsafe { ( * $TIMX:: ptr( ) ) . psc. read( ) . psc( ) . bits( ) } ;
355+
356+ // Length in ms of an internal clock pulse
357+ ( clk. 0 / u32 ( psc * arr) ) . hz( )
358+ }
359+
360+ fn set_period<T >( & mut self , period: T ) where
361+ T : Into <Self :: Time > {
362+ let clk = self . clk;
363+
364+ let ticks = clk. 0 / period. into( ) . 0 ;
365+ let psc = u16 ( ticks / ( 1 << 16 ) ) . unwrap( ) ;
366+ let arr = u16 ( ticks / u32 ( psc + 1 ) ) . unwrap( ) ;
367+ unsafe {
368+ ( * $TIMX:: ptr( ) ) . psc. write( |w| w. psc( ) . bits( psc) ) ;
369+ ( * $TIMX:: ptr( ) ) . arr. write( |w| w. arr( ) . bits( arr) ) ;
370+ }
371+ }
244372 }
245373
246- impl hal:: PwmPin for Pwm <$TIMX, C1 > {
374+ impl hal:: PwmPin for PwmChannel <$TIMX, C1 > {
247375 type Duty = u16 ;
248376
249377 fn disable( & mut self ) {
@@ -267,7 +395,7 @@ macro_rules! hal {
267395 }
268396 }
269397
270- impl hal:: PwmPin for Pwm <$TIMX, C2 > {
398+ impl hal:: PwmPin for PwmChannel <$TIMX, C2 > {
271399 type Duty = u16 ;
272400
273401 fn disable( & mut self ) {
@@ -291,7 +419,7 @@ macro_rules! hal {
291419 }
292420 }
293421
294- impl hal:: PwmPin for Pwm <$TIMX, C3 > {
422+ impl hal:: PwmPin for PwmChannel <$TIMX, C3 > {
295423 type Duty = u16 ;
296424
297425 fn disable( & mut self ) {
@@ -315,7 +443,7 @@ macro_rules! hal {
315443 }
316444 }
317445
318- impl hal:: PwmPin for Pwm <$TIMX, C4 > {
446+ impl hal:: PwmPin for PwmChannel <$TIMX, C4 > {
319447 type Duty = u16 ;
320448
321449 fn disable( & mut self ) {
0 commit comments