8000 Merge pull request #900 from dhylands/comp-deadtime · mimoccc/circuitpython@1ce916a · GitHub
[go: up one dir, main page]

Skip to content
< 8000 header class="HeaderMktg header-logged-out js-details-container js-header Details f4 py-3" role="banner" data-is-top="true" data-color-mode=light data-light-theme=light data-dark-theme=dark>

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1ce916a

Browse files
committed
Merge pull request adafruit#900 from dhylands/comp-deadtime
Add support for complimentary channel output and deadtime.
2 parents c36c75c + 1c79544 commit 1ce916a

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed

stmhal/qstrdefsport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ Q(pulse_width_percent)
198198
Q(compare)
199199
Q(capture)
200200
Q(polarity)
201+
Q(deadtime)
201202

202203
// for ExtInt class
203204
Q(ExtInt)

stmhal/timer.c

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,59 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) {
414414
#endif
415415
}
416416

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+
417470
STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
418471
pyb_timer_obj_t *self = self_in;
419472

@@ -424,7 +477,7 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
424477
uint32_t period = __HAL_TIM_GetAutoreload(&self->tim) & TIMER_CNT_MASK(self);
425478
// fo 8000 r efficiency, we compute and print freq as an int (not a float)
426479
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",
428481
self->tim_id,
429482
freq,
430483
prescaler,
@@ -433,6 +486,10 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
433486
self->tim.Init.CounterMode == TIM_COUNTERMODE_DOWN ? "DOWN" : "CENTER",
434487
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 :
435488
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, ")");
436493
}
437494
}
438495

@@ -472,6 +529,14 @@ STATIC void pyb_timer_print(void (*print)(void *env, const char *fmt, ...), void
472529
///
473530
/// - `callback` - as per Timer.callback()
474531
///
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+
///
475540
/// You must either specify freq or both of period and prescaler.
476541
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) {
477542
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
481546
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_COUNTERMODE_UP} },
482547
{ MP_QSTR_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
483548
{ 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} },
484550
};
485551

486552
// 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
537603

538604
// init TIM
539605
HAL_TIM_Base_Init(&self->tim);
606+
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) {
607+
config_deadtime(self, args[6].u_int);
608+
}
540609
if (args[5].u_obj == mp_const_none) {
541610
HAL_TIM_Base_Start(&self->tim);
542611
} else {
@@ -685,6 +754,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
685754
/// - `Timer.FALLING` - captures on falling edge.
686755
/// - `Timer.BOTH` - captures on both edges.
687756
///
757+
/// Note that capture only works on the primary channel, and not on the
758+
/// complimentary channels.
759+
///
688760
/// PWM Example:
689761
///
690762
/// 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
808880
} else {
809881
HAL_TIM_PWM_Start_IT(&self->tim, TIMER_CHANNEL(chan));
810882
}
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+
}
811887
break;
812888
}
813889

@@ -824,7 +900,11 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
824900
if (oc_config.OCPolarity == 0xffffffff) {
825901
oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
826902
}
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+
}
828908
oc_config.OCFastMode = TIM_OCFAST_DISABLE;
829909
oc_config.OCIdleState = TIM_OCIDLESTATE_SET;
830910
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
838918
} else {
839919
HAL_TIM_OC_Start_IT(&self->tim, TIMER_CHANNEL(chan));
840920
}
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+
}
841925
break;
842926
}
843927

0 commit comments

Comments
 (0)
0