Skip to content

Commit 4351a6c

Browse files
author
Richard Unger
committed
Renesas PWM phase state setting support
1 parent 8010c3d commit 4351a6c

File tree

1 file changed

+83
-11
lines changed

1 file changed

+83
-11
lines changed

src/drivers/hardware_specific/renesas/renesas.cpp

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,40 @@
88

99
/*
1010
We use the GPT timers, there are 2 channels (32 bit) + 6 channels (16 bit)
11-
Each channel has 2 outputs (GTIOCAx and GTIOCBx) which can be complimentary
11+
Each channel has 2 outputs (GTIOCAx and GTIOCBx) which can be complimentary.
1212
13-
So each timer channel can handle one half-bridge, using either a single or
14-
two complimentary PWM signals.
13+
So each timer channel can handle one half-bridge, using either a single (3-PWM) or
14+
two complimentary PWM signals (6-PWM).
1515
1616
For 1-PWM through 4-PWM, we need as many channels as PWM signals, and we can use
17-
either output A or B of the timer (we can set the polarity).
17+
either output A or B of the timer (we can set the polarity) - but not both.
1818
1919
For 6-PWM we need 3 channels, and use both outputs A and B of each channel, then
2020
we can do hardware dead-time.
2121
Or we can use seperate channels for high and low side, with software dead-time.
22+
Each phase can be either hardware (1 channel) or software (2 channels) dead-time
23+
individually, they don't all have to be one or the other.
2224
2325
Selected channels can be started together, so we can keep the phases in sync for
2426
low-side current sensing and software 6-PWM.
2527
2628
The event system should permit low side current sensing without needing interrupts,
2729
but this will be handled by the current sense driver.
30+
31+
Supported:
32+
- arbitrary PWM frequencies between 1Hz (minimum we can set with our integer based API)
33+
and around 48kHz (more would be possible but the range will be low)
34+
- PWM range at 24kHz (default) is 1000
35+
- PWM range at 48kHz is 500
36+
- polarity setting is supported, in all modes
37+
- phase state setting is supported, in 3-PWM, 6-PWM hardware dead-time and 6-PWM software dead-time
38+
39+
TODOs:
40+
- change setDutyCycle to use register access for speed
41+
- add event system support for low-side current sensing
42+
- perhaps add support to reserve timers used also in
43+
Arduino Pwm.h code, for compatibility with analogWrite()
44+
- check if there is a better way for phase-state setting
2845
*/
2946

3047

@@ -469,47 +486,102 @@ void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, vo
469486
}
470487

471488

472-
// TODO phase-state
489+
490+
void _setSinglePhaseState(RenesasTimerConfig* hi, RenesasTimerConfig* lo, PhaseState state) {
491+
gpt_gtior_setting_t gtior;
492+
gtior.gtior = hi->ctrl.p_reg->GTIOR;
493+
bool on = (state==PHASE_ON) || (state==PHASE_HI);
494+
495+
if (hi->duty_pin == GPT_IO_PIN_GTIOCA_AND_GTIOCB) {
496+
bool ch = false;
497+
if (gtior.gtior_b.obe != on) {
498+
gtior.gtior_b.obe = on;
499+
ch = true;
500+
} // B is high side
501+
on = (state==PHASE_ON) || (state==PHASE_LO);
502+
if (gtior.gtior_b.oae != on) {
503+
gtior.gtior_b.oae = on;
504+
ch = true;
505+
}
506+
if (ch)
507+
hi->ctrl.p_reg->GTIOR = gtior.gtior;
508+
return;
509+
}
510+
511+
if (hi->duty_pin == GPT_IO_PIN_GTIOCA) {
512+
if (gtior.gtior_b.oae != on) {
513+
gtior.gtior_b.oae = on;
514+
hi->ctrl.p_reg->GTIOR = gtior.gtior;
515+
}
516+
}
517+
else if (hi->duty_pin == GPT_IO_PIN_GTIOCB) {
518+
if (gtior.gtior_b.obe != on) {
519+
gtior.gtior_b.obe = on;
520+
hi->ctrl.p_reg->GTIOR = gtior.gtior;
521+
}
522+
}
523+
524+
gtior.gtior = lo->ctrl.p_reg->GTIOR;
525+
on = (state==PHASE_ON) || (state==PHASE_LO);
526+
if (lo->duty_pin == GPT_IO_PIN_GTIOCA) {
527+
if (gtior.gtior_b.oae != on) {
528+
gtior.gtior_b.oae = on;
529+
lo->ctrl.p_reg->GTIOR = gtior.gtior;
530+
}
531+
}
532+
else if (lo->duty_pin == GPT_IO_PIN_GTIOCB) {
533+
if (gtior.gtior_b.obe != on) {
534+
gtior.gtior_b.obe = on;
535+
lo->ctrl.p_reg->GTIOR = gtior.gtior;
536+
}
537+
}
538+
539+
}
540+
541+
473542
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void* params){
474543
RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)params)->timer_config[0];
544+
RenesasTimerConfig* t1 = ((RenesasHardwareDriverParams*)params)->timer_config[1];
475545
uint32_t dt = (uint32_t)(((RenesasHardwareDriverParams*)params)->dead_zone * (float)(t->timer_cfg.period_counts));
476546
uint32_t duty_cycle_counts = (uint32_t)(dc_a * (float)(t->timer_cfg.period_counts));
477547
bool hw_deadtime = ((RenesasHardwareDriverParams*)params)->channels[0] == ((RenesasHardwareDriverParams*)params)->channels[1];
478548
uint32_t dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
549+
_setSinglePhaseState(t, t1, phase_state[0]);
479550
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts - dt_act, t->duty_pin) != FSP_SUCCESS) {
480551
// error
481552
}
482553
if (!hw_deadtime) {
483-
t = ((RenesasHardwareDriverParams*)params)->timer_config[1];
484-
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts + dt_act, t->duty_pin) != FSP_SUCCESS) {
554+
if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
485555
// error
486556
}
487557
}
488558

489559
t = ((RenesasHardwareDriverParams*)params)->timer_config[2];
560+
t1 = ((RenesasHardwareDriverParams*)params)->timer_config[3];
490561
duty_cycle_counts = (uint32_t)(dc_b * (float)(t->timer_cfg.period_counts));
491562
hw_deadtime = ((RenesasHardwareDriverParams*)params)->channels[2] == ((RenesasHardwareDriverParams*)params)->channels[3];
492563
dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
564+
_setSinglePhaseState(t, t1, phase_state[1]);
493565
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts - dt_act, t->duty_pin) != FSP_SUCCESS) {
494566
// error
495567
}
496568
if (!hw_deadtime) {
497-
t = ((RenesasHardwareDriverParams*)params)->timer_config[3];
498-
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts + dt_act, t->duty_pin) != FSP_SUCCESS) {
569+
if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
499570
// error
500571
}
501572
}
502573

503574
t = ((RenesasHardwareDriverParams*)params)->timer_config[4];
575+
t1 = ((RenesasHardwareDriverParams*)params)->timer_config[5];
504576
duty_cycle_counts = (uint32_t)(dc_c * (float)(t->timer_cfg.period_counts));
505577
hw_deadtime = ((RenesasHardwareDriverParams*)params)->channels[4] == ((RenesasHardwareDriverParams*)params)->channels[5];
506578
dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
579+
_setSinglePhaseState(t, t1, phase_state[2]);
507580
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
508581
// error
509582
}
510583
if (!hw_deadtime) {
511-
t = ((RenesasHardwareDriverParams*)params)->timer_config[5];
512-
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts + dt_act, t->duty_pin) != FSP_SUCCESS) {
584+
if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
513585
// error
514586
}
515587
}

0 commit comments

Comments
 (0)