54
54
*/
55
55
56
56
use core:: marker:: PhantomData ;
57
+ use core:: marker:: { Copy } ;
57
58
use core:: mem;
58
59
59
60
use crate :: hal;
@@ -68,6 +69,7 @@ use crate::afio::MAPR;
68
69
use crate :: bb;
69
70
use crate :: gpio:: { self , Alternate , PushPull } ;
70
71
use crate :: time:: Hertz ;
72
+ use crate :: time:: U32Ext ;
71
73
use crate :: timer:: Timer ;
72
74
73
75
pub trait Pins < REMAP , P > {
@@ -76,6 +78,26 @@ pub trait Pins<REMAP, P> {
76
78
const C3 : bool = false ;
77
79
const C4 : bool = false ;
78
80
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 ,
79
101
}
80
102
81
103
use crate :: timer:: sealed:: { Ch1 , Ch2 , Ch3 , Ch4 , Remap } ;
@@ -89,7 +111,7 @@ macro_rules! pins_impl {
89
111
$( $PINX: $TRAIT<REMAP > + gpio:: Mode <Alternate <PushPull >>, ) +
90
112
{
91
113
$( const $ENCHX: bool = true ; ) +
92
- type Channels = ( $( Pwm <TIM , $ENCHX>) ,+) ;
114
+ type Channels = ( $( PwmChannel <TIM , $ENCHX>) ,+) ;
93
115
}
94
116
) +
95
117
} ;
@@ -115,7 +137,7 @@ pins_impl!(
115
137
116
138
#[ cfg( any( feature = "stm32f100" , feature = "stm32f103" , feature = "stm32f105" , ) ) ]
117
139
impl 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 >
119
141
where
120
142
REMAP : Remap < Periph = TIM1 > ,
121
143
PINS : Pins < REMAP , P > ,
@@ -133,7 +155,7 @@ impl Timer<TIM1> {
133
155
}
134
156
135
157
impl 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 >
137
159
where
138
160
REMAP : Remap < Periph = TIM2 > ,
139
161
PINS : Pins < REMAP , P > ,
@@ -147,7 +169,7 @@ impl Timer<TIM2> {
147
169
}
148
170
149
171
impl 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 >
151
173
where
152
174
REMAP : Remap < Periph = TIM3 > ,
153
175
PINS : Pins < REMAP , P > ,
@@ -162,7 +184,7 @@ impl Timer<TIM3> {
162
184
163
185
#[ cfg( feature = "medium" ) ]
164
186
impl 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 >
166
188
where
167
189
REMAP : Remap < Periph = TIM4 > ,
168
190
PINS : Pins < REMAP , P > ,
@@ -175,7 +197,26 @@ impl Timer<TIM4> {
175
197
}
176
198
}
177
199
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 > {
179
220
_channel : PhantomData < CHANNEL > ,
180
221
_tim : PhantomData < TIM > ,
181
222
}
@@ -193,7 +234,7 @@ macro_rules! hal {
193
234
_pins: PINS ,
194
235
freq: Hertz ,
195
236
clk: Hertz ,
196
- ) -> PINS :: Channels
237
+ ) -> Pwm <$TIMX , REMAP , P , PINS >
197
238
where
198
239
REMAP : Remap <Periph = $TIMX>,
199
240
PINS : Pins <REMAP , P >,
@@ -240,10 +281,97 @@ macro_rules! hal {
240
281
. set_bit( )
241
282
) ;
242
283
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
+ }
244
372
}
245
373
246
- impl hal:: PwmPin for Pwm <$TIMX, C1 > {
374
+ impl hal:: PwmPin for PwmChannel <$TIMX, C1 > {
247
375
type Duty = u16 ;
248
376
249
377
fn disable( & mut self ) {
@@ -267,7 +395,7 @@ macro_rules! hal {
267
395
}
268
396
}
269
397
270
- impl hal:: PwmPin for Pwm <$TIMX, C2 > {
398
+ impl hal:: PwmPin for PwmChannel <$TIMX, C2 > {
271
399
type Duty = u16 ;
272
400
273
401
fn disable( & mut self ) {
@@ -291,7 +419,7 @@ macro_rules! hal {
291
419
}
292
420
}
293
421
294
- impl hal:: PwmPin for Pwm <$TIMX, C3 > {
422
+ impl hal:: PwmPin for PwmChannel <$TIMX, C3 > {
295
423
type Duty = u16 ;
296
424
297
425
fn disable( & mut self ) {
@@ -315,7 +443,7 @@ macro_rules! hal {
315
443
}
316
444
}
317
445
318
- impl hal:: PwmPin for Pwm <$TIMX, C4 > {
446
+ impl hal:: PwmPin for PwmChannel <$TIMX, C4 > {
319
447
type Duty = u16 ;
320
448
321
449
fn disable( & mut self ) {
0 commit comments