@@ -8,19 +8,28 @@ use embedded_hal as hal;
8
8
9
9
pub trait Pins < TIM , P > {
10
10
const C1 : bool = false ;
11
+ const C1N : bool = false ;
11
12
const C2 : bool = false ;
13
+ const C2N : bool = false ;
12
14
const C3 : bool = false ;
15
+ const C3N : bool = false ;
13
16
const C4 : bool = false ;
14
17
type Channels ;
15
18
}
16
19
use crate :: timers:: PinC1 ;
20
+ use crate :: timers:: PinC1N ;
17
21
use crate :: timers:: PinC2 ;
22
+ use crate :: timers:: PinC2N ;
18
23
use crate :: timers:: PinC3 ;
24
+ use crate :: timers:: PinC3N ;
19
25
use crate :: timers:: PinC4 ;
20
26
21
27
pub struct C1 ;
28
+ pub struct C1N ;
22
29
pub struct C2 ;
30
+ pub struct C2N ;
23
31
pub struct C3 ;
32
+ pub struct C3N ;
24
33
pub struct C4 ;
25
34
26
35
pub struct PwmChannels < TIM , CHANNELS > {
@@ -45,6 +54,9 @@ macro_rules! pins_impl {
45
54
46
55
pins_impl ! (
47
56
( P1 , P2 , P3 , P4 ) , ( PinC1 , PinC2 , PinC3 , PinC4 ) , ( C1 , C2 , C3 , C4 ) ;
57
+ ( P1 , P1N , P2 , P2N ) , ( PinC1 , PinC1N , PinC2 , PinC2N ) , ( C1 , C1N , C2 , C2N ) ;
58
+ ( P2 , P2N , P3 , P3N ) , ( PinC2 , PinC2N , PinC3 , PinC3N ) , ( C2 , C2N , C3 , C3N ) ;
59
+ ( P1 , P1N , P3 , P3N ) , ( PinC1 , PinC1N , PinC3 , PinC3N ) , ( C1 , C1N , C3 , C3N ) ;
48
60
( P2 , P3 , P4 ) , ( PinC2 , PinC3 , PinC4 ) , ( C2 , C3 , C4 ) ;
49
61
( P1 , P3 , P4 ) , ( PinC1 , PinC3 , PinC4 ) , ( C1 , C3 , C4 ) ;
50
62
( P1 , P2 , P4 ) , ( PinC1 , PinC2 , PinC4 ) , ( C1 , C2 , C4 ) ;
@@ -55,6 +67,9 @@ pins_impl!(
55
67
( P1 , P4 ) , ( PinC1 , PinC4 ) , ( C1 , C4 ) ;
56
68
( P1 , P3 ) , ( PinC1 , PinC3 ) , ( C1 , C3 ) ;
57
69
( P1 , P2 ) , ( PinC1 , PinC2 ) , ( C1 , C2 ) ;
70
+ ( P1 , P1N ) , ( PinC1 , PinC1N ) , ( C1 , C1N ) ;
71
+ ( P2 , P2N ) , ( PinC2 , PinC2N ) , ( C2 , C2N ) ;
72
+ ( P3 , P3N ) , ( PinC3 , PinC3N ) , ( C3 , C3N ) ;
58
73
( P1 ) , ( PinC1 ) , ( C1 ) ;
59
74
( P2 ) , ( PinC2 ) , ( C2 ) ;
60
75
( P3 ) , ( PinC3 ) , ( C3 ) ;
@@ -291,6 +306,282 @@ macro_rules! pwm_4_channels {
291
306
} ;
292
307
}
293
308
309
+ // Timer with four output channels three with complements 16 Bit Timer
310
+ macro_rules! pwm_4_channels_with_3_complementary_outputs {
311
+ ( $( $TIMX: ident: ( $timX: ident, $timXen: ident, $timXrst: ident, $apbenr: ident, $apbrstr: ident) , ) +) => {
312
+ $(
313
+ pub fn $timX<P , PINS , T >( tim: $TIMX, _pins: PINS , rcc: & mut Rcc , freq: T ) -> PINS :: Channels
314
+ where
315
+ PINS : Pins <$TIMX, P >,
316
+ T : Into <Hertz >,
317
+ {
318
+ // enable and reset peripheral to a clean slate state
319
+ rcc. regs. $apbenr. modify( |_, w| w. $timXen( ) . set_bit( ) ) ;
320
+ rcc. regs. $apbrstr. modify( |_, w| w. $timXrst( ) . set_bit( ) ) ;
321
+ rcc. regs. $apbrstr. modify( |_, w| w. $timXrst( ) . clear_bit( ) ) ;
322
+
323
+ if PINS :: C1N | PINS :: C1N | PINS :: C1N {
324
+ tim. bdtr. modify( |_, w| w. ossr( ) . set_bit( ) ) ;
325
+ }
326
+ if PINS :: C1 {
327
+ tim. ccmr1_output( )
328
+ . modify( |_, w| w. oc1pe( ) . set_bit( ) . oc1m( ) . pwm_mode1( ) ) ;
329
+ }
330
+ if PINS :: C2 {
331
+ tim. ccmr1_output( )
332
+ . modify( |_, w| w. oc2pe( ) . set_bit( ) . oc2m( ) . pwm_mode1( ) ) ;
333
+ }
334
+ if PINS :: C3 {
335
+ tim. ccmr2_output( )
336
+ . modify( |_, w| w. oc3pe( ) . set_bit( ) . oc3m( ) . pwm_mode1( ) ) ;
337
+ }
338
+ if PINS :: C4 {
339
+ tim. ccmr2_output( )
340
+ . modify( |_, w| w. oc4pe( ) . set_bit( ) . oc4m( ) . pwm_mode1( ) ) ;
341
+ }
342
+
343
+ // If pclk is prescaled from hclk, the frequency fed into the timers is doubled
344
+ let tclk = if rcc. clocks. hclk( ) . 0 == rcc. clocks. pclk( ) . 0 {
345
+ rcc. clocks. pclk( ) . 0
346
+ } else {
347
+ rcc. clocks. pclk( ) . 0 * 2
348
+ } ;
349
+ let ticks = tclk / freq. into( ) . 0 ;
350
+
351
+ let psc = u16 ( ( ticks - 1 ) / ( 1 << 16 ) ) . unwrap( ) ;
352
+ tim. psc. write( |w| w. psc( ) . bits( psc) ) ;
353
+ let arr = u16 ( ticks / u32 ( psc + 1 ) ) . unwrap( ) ;
354
+ tim. arr. write( |w| unsafe { w. bits( u32 ( arr) ) } ) ;
355
+
356
+ // enable auto-reload preload
357
+ tim. cr1. modify( |_, w| w. arpe( ) . set_bit( ) ) ;
358
+
359
+ // Trigger update event to load the registers
360
+ tim. cr1. modify( |_, w| w. urs( ) . set_bit( ) ) ;
361
+ tim. egr. write( |w| w. ug( ) . set_bit( ) ) ;
362
+ tim. cr1. modify( |_, w| w. urs( ) . clear_bit( ) ) ;
363
+
364
+ brk!( $TIMX, tim) ;
365
+ tim. cr1. write( |w|
366
+ w. cms( )
367
+ . bits( 0b00 )
368
+ . dir( )
369
+ . clear_bit( )
370
+ . opm( )
371
+ . clear_bit( )
372
+ . cen( )
373
+ . set_bit( )
374
+ ) ;
375
+ //NOTE(unsafe) `PINS::Channels` is a ZST
376
+ unsafe { MaybeUninit :: uninit( ) . assume_init( ) }
377
+ }
378
+
379
+ impl hal:: PwmPin for PwmChannels <$TIMX, C1 > {
380
+ type Duty = u16 ;
381
+
382
+ //NOTE(unsafe) atomic write with no side effects
383
+ fn disable( & mut self ) {
384
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc1e( ) . clear_bit( ) ) } ;
385
+ }
386
+
387
+ //NOTE(unsafe) atomic write with no side effects
388
+ fn enable( & mut self ) {
389
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc1e( ) . set_bit( ) ) } ;
390
+ }
391
+
392
+ //NOTE(unsafe) atomic read with no side effects
393
+ fn get_duty( & self ) -> u16 {
394
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr1. read( ) . ccr( ) . bits( ) as u16 }
395
+ }
396
+
397
+ //NOTE(unsafe) atomic read with no side effects
398
+ fn get_max_duty( & self ) -> u16 {
399
+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) as u16 }
400
+ }
401
+
402
+ //NOTE(unsafe) atomic write with no side effects
403
+ fn set_duty( & mut self , duty: u16 ) {
404
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr1. write( |w| w. ccr( ) . bits( duty. into( ) ) ) }
405
+ }
406
+ }
407
+
408
+ impl hal:: PwmPin for PwmChannels <$TIMX, C1N > {
409
+ type Duty = u16 ;
410
+
411
+ //NOTE(unsafe) atomic write with no side effects
412
+ fn disable( & mut self ) {
413
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc1ne( ) . clear_bit( ) ) } ;
414
+ }
415
+
416
+ //NOTE(unsafe) atomic write with no side effects
417
+ fn enable( & mut self ) {
418
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc1ne( ) . set_bit( ) ) } ;
419
+ }
420
+
421
+ //NOTE(unsafe) atomic read with no side effects
422
+ fn get_duty( & self ) -> u16 {
423
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr1. read( ) . ccr( ) . bits( ) as u16 }
424
+ }
425
+
426
+ //NOTE(unsafe) atomic read with no side effects
427
+ fn get_max_duty( & self ) -> u16 {
428
+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) as u16 }
429
+ }
430
+
431
+ //NOTE(unsafe) atomic write with no side effects
432
+ fn set_duty( & mut self , duty: u16 ) {
433
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr1. write( |w| w. ccr( ) . bits( duty. into( ) ) ) }
434
+ }
435
+ }
436
+
437
+ impl hal:: PwmPin for PwmChannels <$TIMX, C2 > {
438
+ type Duty = u16 ;
439
+
440
+ //NOTE(unsafe) atomic write with no side effects
441
+ fn disable( & mut self ) {
442
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc2e( ) . clear_bit( ) ) } ;
443
+ }
444
+
445
+ //NOTE(unsafe) atomic write with no side effects
446
+ fn enable( & mut self ) {
447
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc2e( ) . set_bit( ) ) } ;
448
+ }
449
+
450
+ //NOTE(unsafe) atomic read with no side effects
451
+ fn get_duty( & self ) -> u16 {
452
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr2. read( ) . ccr( ) . bits( ) as u16 }
453
+ }
454
+
455
+ //NOTE(unsafe) atomic read with no side effects
456
+ fn get_max_duty( & self ) -> u16 {
457
+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) as u16 }
458
+ }
459
+
460
+ //NOTE(unsafe) atomic write with no side effects
461
+ fn set_duty( & mut self , duty: u16 ) {
462
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr2. write( |w| w. ccr( ) . bits( duty. into( ) ) ) }
463
+ }
464
+ }
465
+
466
+ impl hal:: PwmPin for PwmChannels <$TIMX, C2N > {
467
+ type Duty = u16 ;
468
+
469
+ //NOTE(unsafe) atomic write with no side effects
470
+ fn disable( & mut self ) {
471
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc2ne( ) . clear_bit( ) ) } ;
472
+ }
473
+
474
+ //NOTE(unsafe) atomic write with no side effects
475
+ fn enable( & mut self ) {
476
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc2ne( ) . set_bit( ) ) } ;
477
+ }
478
+
479
+ //NOTE(unsafe) atomic read with no side effects
480
+ fn get_duty( & self ) -> u16 {
481
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr2. read( ) . ccr( ) . bits( ) as u16 }
482
+ }
483
+
484
+ //NOTE(unsafe) atomic read with no side effects
485
+ fn get_max_duty( & self ) -> u16 {
486
+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) as u16 }
487
+ }
488
+
489
+ //NOTE(unsafe) atomic write with no side effects
490
+ fn set_duty( & mut self , duty: u16 ) {
491
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr2. write( |w| w. ccr( ) . bits( duty. into( ) ) ) }
492
+ }
493
+ }
494
+
495
+ impl hal:: PwmPin for PwmChannels <$TIMX, C3 > {
496
+ type Duty = u16 ;
497
+
498
+ //NOTE(unsafe) atomic write with no side effects
499
+ fn disable( & mut self ) {
500
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc3e( ) . clear_bit( ) ) } ;
501
+ }
502
+
503
+ //NOTE(unsafe) atomic write with no side effects
504
+ fn enable( & mut self ) {
505
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc3e( ) . set_bit( ) ) } ;
506
+ }
507
+
508
+ //NOTE(unsafe) atomic read with no side effects
509
+ fn get_duty( & self ) -> u16 {
510
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr3. read( ) . ccr( ) . bits( ) as u16 }
511
+ }
512
+
513
+ //NOTE(unsafe) atomic read with no side effects
514
+ fn get_max_duty( & self ) -> u16 {
515
+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) as u16 }
516
+ }
517
+
518
+ //NOTE(unsafe) atomic write with no side effects
519
+ fn set_duty( & mut self , duty: u16 ) {
520
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr3. write( |w| w. ccr( ) . bits( duty. into( ) ) ) }
521
+ }
522
+ }
523
+
524
+ impl hal:: PwmPin for PwmChannels <$TIMX, C3N > {
525
+ type Duty = u16 ;
526
+
527
+ //NOTE(unsafe) atomic write with no side effects
528
+ fn disable( & mut self ) {
529
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc3ne( ) . clear_bit( ) ) } ;
530
+ }
531
+
532
+ //NOTE(unsafe) atomic write with no side effects
533
+ fn enable( & mut self ) {
534
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc3ne( ) . set_bit( ) ) } ;
535
+ }
536
+
537
+ //NOTE(unsafe) atomic read with no side effects
538
+ fn get_duty( & self ) -> u16 {
539
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr3. read( ) . ccr( ) . bits( ) as u16 }
540
+ }
541
+
542
+ //NOTE(unsafe) atomic read with no side effects
543
+ fn get_max_duty( & self ) -> u16 {
544
+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) as u16 }
545
+ }
546
+
547
+ //NOTE(unsafe) atomic write with no side effects
548
+ fn set_duty( & mut self , duty: u16 ) {
549
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr3. write( |w| w. ccr( ) . bits( duty. into( ) ) ) }
550
+ }
551
+ }
552
+
553
+ impl hal:: PwmPin for PwmChannels <$TIMX, C4 > {
554
+ type Duty = u16 ;
555
+
556
+ //NOTE(unsafe) atomic write with no side effects
557
+ fn disable( & mut self ) {
558
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc4e( ) . clear_bit( ) ) } ;
559
+ }
560
+
561
+ //NOTE(unsafe) atomic write with no side effects
562
+ fn enable( & mut self ) {
563
+ unsafe { ( * ( $TIMX:: ptr( ) ) ) . ccer. modify( |_, w| w. cc4e( ) . set_bit( ) ) } ;
564
+ }
565
+
566
+ //NOTE(unsafe) atomic read with no side effects
567
+ fn get_duty( & self ) -> u16 {
568
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr4. read( ) . ccr( ) . bits( ) as u16 }
569
+ }
570
+
571
+ //NOTE(unsafe) atomic read with no side effects
572
+ fn get_max_duty( & self ) -> u16 {
573
+ unsafe { ( * $TIMX:: ptr( ) ) . arr. read( ) . arr( ) . bits( ) as u16 }
574
+ }
575
+
576
+ //NOTE(unsafe) atomic write with no side effects
577
+ fn set_duty( & mut self , duty: u16 ) {
578
+ unsafe { ( * $TIMX:: ptr( ) ) . ccr4. write( |w| w. ccr( ) . bits( duty. into( ) ) ) }
579
+ }
580
+ }
581
+ ) +
582
+ } ;
583
+ }
584
+
294
585
// General purpose timer with two output channels
295
586
#[ cfg( any(
296
587
feature = "stm32f030x8" ,
@@ -583,10 +874,12 @@ macro_rules! pwm_1_channel_with_complementary_outputs {
583
874
use crate :: pac:: * ;
584
875
585
876
pwm_4_channels ! (
586
- TIM1 : ( tim1, tim1en, tim1rst, apb2enr, apb2rstr) ,
587
877
TIM3 : ( tim3, tim3en, tim3rst, apb1enr, apb1rstr) ,
588
878
) ;
589
879
880
+ pwm_4_channels_with_3_complementary_outputs ! (
881
+ TIM1 : ( tim1, tim1en, tim1rst, apb2enr, apb2rstr) ,
882
+ ) ;
590
883
pwm_1_channel ! ( TIM14 : ( tim14, tim14en, tim14rst, apb1enr, apb1rstr) , ) ;
591
884
592
885
pwm_1_channel_with_complementary_outputs ! (
0 commit comments