@@ -414,6 +414,59 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) {
414
414
#endif
415
415
}
416
416
417
+ // Computes the 8-bit value for the DTG field in the BDTR register.
418
+ //
419
+ // 1 tick = 1 count of the timer's clock (source_freq) divided by div.
420
+ // 0-128 ticks in inrements of 1
421
+ // 128-256 ticks in increments of 2
422
+ // 256-512 ticks in increments of 8
423
+ // 512-1008 ticks in increments of 16
424
+ STATIC uint32_t compute_dtg_from_ticks (mp_int_t ticks ) {
425
+ if (ticks <= 0 ) {
426
+ return 0 ;
427
+ }
428
+ if (ticks < 128 ) {
429
+ return ticks ;
430
+ }
431
+ if (ticks < 256 ) {
432
+ return 0x80 | ((ticks - 128 ) / 2 );
433
+ }
434
+ if (ticks < 512 ) {
435
+ return 0xC0 | ((ticks - 256 ) / 8 );
436
+ }
437
+ if (ticks < 1008 ) {
438
+ return 0xE0 | ((ticks - 512 ) / 16 );
439
+ }
440
+ return 0xFF ;
441
+ }
442
+
443
+ // Given the 8-bit value stored in the DTG field of the BDTR register, compute
444
+ // the number of ticks.
445
+ STATIC mp_int_t compute_ticks_from_dtg (uint32_t dtg ) {
446
+ if ((dtg & 0x80 ) == 0 ) {
447
+ return dtg & 0x7F ;
448
+ }
449
+ if ((dtg & 0xC0 ) == 0x80 ) {
450
+ return 128 + ((dtg & 0x3F ) * 2 );
451
+ }
452
+ if ((dtg & 0xE0 ) == 0xC0 ) {
453
+ return 256 + ((dtg & 0x1F ) * 8 );
454
+ }
455
+ return 512 + ((dtg & 0x1F ) * 16 );
456
+ }
457
+
458
+ STATIC void config_deadtime (pyb_timer_obj_t * self , mp_int_t ticks ) {
459
+ TIM_BreakDeadTimeConfigTypeDef deadTimeConfig ;
460
+ deadTimeConfig .OffStateRunMode = TIM_OSSR_DISABLE ;
461
+ deadTimeConfig .OffStateIDLEMode = TIM_OSSI_DISABLE ;
462
+ deadTimeConfig .LockLevel = TIM_LOCKLEVEL_OFF ;
463
+ deadTimeConfig .DeadTime = compute_dtg_from_ticks (ticks );
464
+ deadTimeConfig .BreakState = TIM_BREAK_DISABLE ;
465
+ deadTimeConfig .BreakPolarity = TIM_BREAKPOLARITY_LOW ;
466
+ deadTimeConfig .AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE ;
467
+ HAL_TIMEx_ConfigBreakDeadTime (& self -> tim , & deadTimeConfig );
468
+ }
469
+
417
470
STATIC void pyb_timer_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t self_in , mp_print_kind_t kind ) {
418
471
pyb_timer_obj_t * self = self_in ;
419
472
@@ -424,7 +477,7 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
424
477
uint32_t period = __HAL_TIM_GetAutoreload (& self -> tim ) & TIMER_CNT_MASK (self );
425
478
// for efficiency, we compute and print freq as an int (not a float)
426
479
uint32_t freq = timer_get_source_freq (self -> tim_id ) / ((prescaler + 1 ) * (period + 1 ));
427
- print (env , "Timer(%u, freq=%u, prescaler=%u, period=%u, mode=%s, div=%u) " ,
480
+ print (env , "Timer(%u, freq=%u, prescaler=%u, period=%u, mode=%s, div=%u" ,
428
481
self -> tim_id ,
429
482
freq ,
430
483
prescaler ,
@@ -433,6 +486,10 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
433
486
self -> tim .Init .CounterMode == TIM_COUNTERMODE_DOWN ? "DOWN" : "CENTER" ,
434
487
self -> tim .Init .ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 :
435
488
self -> tim .Init .ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1 );
489
+ if (IS_TIM_ADVANCED_INSTANCE (self -> tim .Instance )) {
490
+ print (env , ", deadtime=%u" , compute_ticks_from_dtg (self -> tim .Instance -> BDTR & TIM_BDTR_DTG ));
491
+ }
492
+ print (env , ")" );
436
493
}
437
494
}
438
495
@@ -472,6 +529,14 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
472
529
///
473
530
/// - `callback` - as per Timer.callback()
474
531
///
532
+ /// - `deadtime` - specifies the amount of "dead" or inactive time between
533
+ /// transitions on complimentary channels (both channels will be inactive)
534
+ /// for this time). `deadtime` may be an integer between 0 and 1008, with
535
+ /// the following restrictions: 0-128 in steps of 1. 128-256 in steps of
536
+ /// 2, 256-512 in steps of 8, and 512-1008 in steps of 16. `deadime`
537
+ /// measures ticks of `source_freq` divided by `div` clock ticks.
538
+ /// `deadtime` is only available on timers 1 and 8.
539
+ ///
475
540
/// You must either specify freq or both of period and prescaler.
476
541
STATIC mp_obj_t pyb_timer_init_helper (pyb_timer_obj_t * self , mp_uint_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
477
542
static const mp_arg_t allowed_args [] = {
@@ -481,6 +546,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, mp_uint_t n_args, c
481
546
{ MP_QSTR_mode , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = TIM_COUNTERMODE_UP } },
482
547
{ MP_QSTR_div , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 1 } },
483
548
{ MP_QSTR_callback , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_obj = mp_const_none } },
549
+ { MP_QSTR_deadtime , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 0 } },
484
550
};
485
551
486
552
// parse args
@@ -537,6 +603,9 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, mp_uint_t n_args, c
537
603
538
604
// init TIM
539
605
HAL_TIM_Base_Init (& self -> tim );
606
+ if (IS_TIM_ADVANCED_INSTANCE (self -> tim .Instance )) {
607
+ config_deadtime (self , args [6 ].u_int );
608
+ }
540
609
if (args [5 ].u_obj == mp_const_none ) {
541
610
HAL_TIM_Base_Start (& self -> tim );
542
611
} else {
@@ -685,6 +754,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
685
754
/// - `Timer.FALLING` - captures on falling edge.
686
755
/// - `Timer.BOTH` - captures on both edges.
687
756
///
757
+ /// Note that capture only works on the primary channel, and not on the
758
+ /// complimentary channels.
759
+ ///
688
760
/// PWM Example:
689
761
///
690
762
/// timer = pyb.Timer(2, freq=1000)
@@ -808,6 +880,10 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
808
880
} else {
809
881
HAL_TIM_PWM_Start_IT (& self -> tim , TIMER_CHANNEL (chan ));
810
882
}
883
+ // Start the complimentary channel too (if its supported)
884
+ if (IS_TIM_CCXN_INSTANCE (self -> tim .Instance , TIMER_CHANNEL (chan ))) {
885
+ HAL_TIMEx_PWMN_Start (& self -> tim , TIMER_CHANNEL (chan ));
886
+ }
811
887
break ;
812
888
}
813
889
@@ -824,7 +900,11 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
824
900
if (oc_config .OCPolarity == 0xffffffff ) {
825
901
oc_config .OCPolarity = TIM_OCPOLARITY_HIGH ;
826
902
}
827
- oc_config .OCNPolarity = TIM_OCNPOLARITY_HIGH ;
903
+ if (oc_config .OCPolarity == TIM_OCPOLARITY_HIGH ) {
904
+ oc_config .OCNPolarity = TIM_OCNPOLARITY_HIGH ;
905
+ } else {
906
+ oc_config .OCNPolarity = TIM_OCNPOLARITY_LOW ;
907
+ }
828
908
oc_config .OCFastMode = TIM_OCFAST_DISABLE ;
829
909
oc_config .OCIdleState = TIM_OCIDLESTATE_SET ;
830
910
oc_config .OCNIdleState = TIM_OCNIDLESTATE_SET ;
@@ -838,6 +918,10 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
838
918
} else {
839
919
HAL_TIM_OC_Start_IT (& self -> tim , TIMER_CHANNEL (chan ));
840
920
}
921
+ // Start the complimentary channel too (if its supported)
922
+ if (IS_TIM_CCXN_INSTANCE (self -> tim .Instance , TIMER_CHANNEL (chan ))) {
923
+ HAL_TIMEx_OCN_Start (& self -> tim , TIMER_CHANNEL (chan ));
924
+ }
841
925
break ;
842
926
}
843
927
0 commit comments