Files
lemon-pepper-stepper/firmware/lib/Arduino-FOC/src/drivers/hardware_specific/renesas/renesas.cpp
2023-11-09 19:02:15 -05:00

609 lines
23 KiB
C++

#include "./renesas.h"
#if defined(ARDUINO_UNOR4_WIFI) || defined(ARDUINO_UNOR4_MINIMA)
#pragma message("")
#pragma message("SimpleFOC: compiling for Arduino/Renesas (UNO R4)")
#pragma message("")
#include "communication/SimpleFOCDebug.h"
#include "FspTimer.h"
#define GPT_OPEN (0x00475054ULL)
/*
We use the GPT timers, there are 2 channels (32 bit) + 6 channels (16 bit)
Each channel has 2 outputs (GTIOCAx and GTIOCBx) which can be complimentary.
So each timer channel can handle one half-bridge, using either a single (3-PWM) or
two complimentary PWM signals (6-PWM).
For 1-PWM through 4-PWM, we need as many channels as PWM signals, and we can use
either output A or B of the timer (we can set the polarity) - but not both.
For 6-PWM we need 3 channels, and use both outputs A and B of each channel, then
we can do hardware dead-time.
Or we can use seperate channels for high and low side, with software dead-time.
Each phase can be either hardware (1 channel) or software (2 channels) dead-time
individually, they don't all have to be one or the other.
Selected channels can be started together, so we can keep the phases in sync for
low-side current sensing and software 6-PWM.
The event system should permit low side current sensing without needing interrupts,
but this will be handled by the current sense driver.
Supported:
- arbitrary PWM frequencies between 1Hz (minimum we can set with our integer based API)
and around 48kHz (more would be possible but the range will be low)
- PWM range at 24kHz (default) is 1000
- PWM range at 48kHz is 500
- polarity setting is supported, in all modes
- phase state setting is supported, in 3-PWM, 6-PWM hardware dead-time and 6-PWM software dead-time
TODOs:
- change setDutyCycle to use register access for speed
- add event system support for low-side current sensing
- perhaps add support to reserve timers used also in
Arduino Pwm.h code, for compatibility with analogWrite()
- check if there is a better way for phase-state setting
*/
// track which channels are used
bool channel_used[GPT_HOWMANY] = { false };
struct RenesasTimerConfig {
timer_cfg_t timer_cfg;
gpt_instance_ctrl_t ctrl;
gpt_extended_cfg_t ext_cfg;
gpt_extended_pwm_cfg_t pwm_cfg;
gpt_io_pin_t duty_pin;
};
struct ClockDivAndRange {
timer_source_div_t clk_div;
uint32_t range;
};
ClockDivAndRange getClockDivAndRange(uint32_t pwm_frequency, uint8_t timer_channel) {
ClockDivAndRange result;
uint32_t max_count = (timer_channel < GTP32_HOWMANY)? 4294967295 : 65535;
uint32_t freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD);
float range = (float) freq_hz / ((float) pwm_frequency * 2.0f);
if(range / 1.0 < max_count) {
result.range = (uint32_t) (range / 1.0);
result.clk_div = TIMER_SOURCE_DIV_1;
}
else if (range / 2.0 < max_count) {
result.range = (uint32_t) (range / 2.0);
result.clk_div = TIMER_SOURCE_DIV_2;
}
else if(range / 4.0 < max_count) {
result.range = (uint32_t) (range / 4.0);
result.clk_div = TIMER_SOURCE_DIV_4;
}
else if(range / 8.0 < max_count) {
result.range = (uint32_t) (range / 8.0 );
result.clk_div = TIMER_SOURCE_DIV_8;
}
else if(range / 16.0 < max_count) {
result.range = (uint32_t) (range / 16.0 );
result.clk_div = TIMER_SOURCE_DIV_16;
}
else if (range / 32.0 < max_count) {
result.range = (uint32_t) (range / 32.0 );
result.clk_div = TIMER_SOURCE_DIV_32;
}
else if(range / 64.0 < max_count) {
result.range = (uint32_t) (range / 64.0 );
result.clk_div = TIMER_SOURCE_DIV_64;
}
else if(range / 128.0 < max_count) {
result.range = (uint32_t) (range / 128.0 );
result.clk_div = TIMER_SOURCE_DIV_128;
}
else if(range / 256.0 < max_count) {
result.range = (uint32_t) (range / 256.0 );
result.clk_div = TIMER_SOURCE_DIV_256;
}
else if(range / 512.0 < max_count) {
result.range = (uint32_t) (range / 512.0 );
result.clk_div = TIMER_SOURCE_DIV_512;
}
else if(range / 1024.0 < max_count) {
result.range = (uint32_t) (range / 1024.0 );
result.clk_div = TIMER_SOURCE_DIV_1024;
}
else {
SimpleFOCDebug::println("DRV: PWM frequency too low");
}
return result;
};
bool configureTimerPin(RenesasHardwareDriverParams* params, uint8_t index, bool active_high, bool complementary = false, bool complementary_active_high = true) {
uint8_t pin = params->pins[index];
uint8_t pin_C;
std::array<uint16_t, 3> pinCfgs = getPinCfgs(pin, PIN_CFG_REQ_PWM);
std::array<uint16_t, 3> pinCfgs_C;
if(pinCfgs[0] == 0) {
SIMPLEFOC_DEBUG("DRV: no PWM on pin ", pin);
return false;
}
if (IS_PIN_AGT_PWM(pinCfgs[0])) {
SIMPLEFOC_DEBUG("DRV: AGT timer not supported");
return false;
}
// get the timer channel
uint8_t timer_channel = GET_CHANNEL(pinCfgs[0]);
// check its not used
if (channel_used[timer_channel]) {
SIMPLEFOC_DEBUG("DRV: channel in use");
return false;
}
if (complementary) {
pin_C = params->pins[index+1];
pinCfgs_C = getPinCfgs(pin_C, PIN_CFG_REQ_PWM);
if(pinCfgs_C[0] == 0) {
SIMPLEFOC_DEBUG("DRV: no PWM on pin ", pin_C);
return false;
}
if (IS_PIN_AGT_PWM(pinCfgs_C[0]) || GET_CHANNEL(pinCfgs_C[0])!=timer_channel) {
SIMPLEFOC_DEBUG("DRV: comp. channel different");
return false;
}
}
TimerPWMChannel_t pwm_output = IS_PWM_ON_A(pinCfgs[0]) ? CHANNEL_A : CHANNEL_B;
if (complementary) {
TimerPWMChannel_t pwm_output_C = IS_PWM_ON_A(pinCfgs_C[0]) ? CHANNEL_A : CHANNEL_B;
if (pwm_output_C != CHANNEL_A || pwm_output != CHANNEL_B) {
SIMPLEFOC_DEBUG("DRV: output A/B mismatch");
return false;
}
}
// configure GPIO pin
fsp_err_t err = R_IOPORT_PinCfg(&g_ioport_ctrl, g_pin_cfg[pin].pin, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_GPT1));
if ((err == FSP_SUCCESS) && complementary)
err = R_IOPORT_PinCfg(&g_ioport_ctrl, g_pin_cfg[pin_C].pin, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_GPT1));
if (err != FSP_SUCCESS) {
SIMPLEFOC_DEBUG("DRV: pin config failed");
return false;
}
// configure timer channel - frequency / top value
ClockDivAndRange timings = getClockDivAndRange(params->pwm_frequency, timer_channel);
#if defined(SIMPLEFOC_RENESAS_DEBUG)
SimpleFOCDebug::println("---PWM Config---");
SimpleFOCDebug::println("DRV: pwm pin: ", pin);
if (complementary)
SimpleFOCDebug::println("DRV: compl. pin: ", pin_C);
SimpleFOCDebug::println("DRV: pwm channel: ", timer_channel);
SimpleFOCDebug::print("DRV: pwm A/B: "); SimpleFOCDebug::println(complementary?"A+B":((pwm_output==CHANNEL_A)?"A":"B"));
SimpleFOCDebug::println("DRV: pwm freq: ", (int)params->pwm_frequency);
SimpleFOCDebug::println("DRV: pwm range: ", (int)timings.range);
SimpleFOCDebug::println("DRV: pwm clkdiv: ", timings.clk_div);
#endif
RenesasTimerConfig* t = new RenesasTimerConfig();
// configure timer channel - count mode
t->timer_cfg.channel = timer_channel;
t->timer_cfg.mode = TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM;
t->timer_cfg.source_div = timings.clk_div;
t->timer_cfg.period_counts = timings.range;
t->timer_cfg.duty_cycle_counts = 0;
t->timer_cfg.p_callback = nullptr;
t->timer_cfg.p_context = nullptr;
t->timer_cfg.p_extend = &(t->ext_cfg);
t->timer_cfg.cycle_end_ipl = BSP_IRQ_DISABLED;
t->timer_cfg.cycle_end_irq = FSP_INVALID_VECTOR;
t->ext_cfg.p_pwm_cfg = &(t->pwm_cfg);
t->pwm_cfg.trough_ipl = BSP_IRQ_DISABLED;
t->pwm_cfg.trough_irq = FSP_INVALID_VECTOR;
t->pwm_cfg.poeg_link = GPT_POEG_LINK_POEG0;
t->pwm_cfg.output_disable = GPT_OUTPUT_DISABLE_NONE;
t->pwm_cfg.adc_trigger = GPT_ADC_TRIGGER_NONE;
t->pwm_cfg.dead_time_count_up = 0;
t->pwm_cfg.dead_time_count_down = 0;
t->pwm_cfg.adc_a_compare_match = 0;
t->pwm_cfg.adc_b_compare_match = 0;
t->pwm_cfg.interrupt_skip_source = GPT_INTERRUPT_SKIP_SOURCE_NONE;
t->pwm_cfg.interrupt_skip_count = GPT_INTERRUPT_SKIP_COUNT_0;
t->pwm_cfg.interrupt_skip_adc = GPT_INTERRUPT_SKIP_ADC_NONE;
t->pwm_cfg.gtioca_disable_setting = GPT_GTIOC_DISABLE_PROHIBITED;
t->pwm_cfg.gtiocb_disable_setting = GPT_GTIOC_DISABLE_PROHIBITED;
// configure dead-time if both outputs are used
if (complementary) {
uint32_t dt = params->dead_zone * timings.range;
t->pwm_cfg.dead_time_count_up = dt;
t->pwm_cfg.dead_time_count_down = dt;
}
// configure timer channel - outputs and polarity
t->ext_cfg.gtior_setting.gtior = 0L;
if (!complementary) {
if(pwm_output == CHANNEL_A) {
t->duty_pin = GPT_IO_PIN_GTIOCA;
t->ext_cfg.gtioca.output_enabled = true;
t->ext_cfg.gtiocb.output_enabled = false;
t->ext_cfg.gtior_setting.gtior_b.gtioa = 0x03 | (active_high ? 0x00 : 0x10);
t->ext_cfg.gtior_setting.gtior_b.oadflt = active_high ? 0x00 : 0x01;
// t->ext_cfg.gtior_setting.gtior_b.oahld = 0x0;
// t->ext_cfg.gtior_setting.gtior_b.oadf = 0x0;
// t->ext_cfg.gtior_setting.gtior_b.nfaen = 0x0;
}
else {
t->duty_pin = GPT_IO_PIN_GTIOCB;
t->ext_cfg.gtiocb.output_enabled = true;
t->ext_cfg.gtioca.output_enabled = false;
t->ext_cfg.gtior_setting.gtior_b.gtiob = 0x03 | (active_high ? 0x00 : 0x10);
t->ext_cfg.gtior_setting.gtior_b.obdflt = active_high ? 0x00 : 0x01;
}
}
else {
t->duty_pin = GPT_IO_PIN_GTIOCA_AND_GTIOCB;
t->ext_cfg.gtioca.output_enabled = true;
t->ext_cfg.gtiocb.output_enabled = true;
t->ext_cfg.gtior_setting.gtior_b.gtioa = 0x03 | (!complementary_active_high ? 0x00 : 0x10);
t->ext_cfg.gtior_setting.gtior_b.oadflt = !complementary_active_high ? 0x00 : 0x01;
t->ext_cfg.gtior_setting.gtior_b.gtiob = 0x03 | (active_high ? 0x00 : 0x10);
t->ext_cfg.gtior_setting.gtior_b.obdflt = active_high ? 0x00 : 0x01;
}
// lets stop the timer in case its running
if (GPT_OPEN == t->ctrl.open) {
if (R_GPT_Stop(&(t->ctrl)) != FSP_SUCCESS) {
SIMPLEFOC_DEBUG("DRV: timer stop failed");
return false;
}
}
memset(&(t->ctrl), 0, sizeof(gpt_instance_ctrl_t));
err = R_GPT_Open(&(t->ctrl),&(t->timer_cfg));
if ((err != FSP_ERR_ALREADY_OPEN) && (err != FSP_SUCCESS)) {
SIMPLEFOC_DEBUG("DRV: open failed");
return false;
}
#if defined(SIMPLEFOC_RESENSAS_DEBUG)
if (err == FSP_ERR_ALREADY_OPEN) {
SimpleFOCDebug::println("DRV: timer already open");
}
#endif
err = R_GPT_PeriodSet(&(t->ctrl), t->timer_cfg.period_counts);
if (err != FSP_SUCCESS) {
SIMPLEFOC_DEBUG("DRV: period set failed");
return false;
}
err = R_GPT_OutputEnable(&(t->ctrl), t->duty_pin);
if (err != FSP_SUCCESS) {
SIMPLEFOC_DEBUG("DRV: pin enable failed");
return false;
}
channel_used[timer_channel] = true;
params->timer_config[index] = t;
params->channels[index] = timer_channel;
if (complementary) {
params->timer_config[index+1] = t;
params->channels[index+1] = timer_channel;
}
return true;
}
// start the timer channels for the motor, synchronously
bool startTimerChannels(RenesasHardwareDriverParams* params, int num_channels) {
uint32_t mask = 0;
for (int i = 0; i < num_channels; i++) {
// RenesasTimerConfig* t = params->timer_config[i];
// if (R_GPT_Start(&(t->ctrl)) != FSP_SUCCESS) {
// SIMPLEFOC_DEBUG("DRV: timer start failed");
// return false;
// }
mask |= (1 << params->channels[i]);
#if defined(SIMPLEFOC_RENESAS_DEBUG)
SimpleFOCDebug::println("DRV: starting timer: ", params->channels[i]);
#endif
}
params->timer_config[0]->ctrl.p_reg->GTSTR |= mask;
#if defined(SIMPLEFOC_RENESAS_DEBUG)
SimpleFOCDebug::println("DRV: timers started");
#endif
return true;
}
// check if the given pins are on the same timer channel
bool isHardware6Pwm(const int pin1, const int pin2) {
std::array<uint16_t, 3> pinCfgs1 = getPinCfgs(pin1, PIN_CFG_REQ_PWM);
std::array<uint16_t, 3> pinCfgs2 = getPinCfgs(pin2, PIN_CFG_REQ_PWM);
if(pinCfgs1[0] == 0 || pinCfgs2[0] == 0)
return false;
if (IS_PIN_AGT_PWM(pinCfgs1[0]) || IS_PIN_AGT_PWM(pinCfgs2[0]))
return false;
uint8_t timer_channel1 = GET_CHANNEL(pinCfgs1[0]);
uint8_t timer_channel2 = GET_CHANNEL(pinCfgs2[0]);
return timer_channel1==timer_channel2;
}
void* _configure1PWM(long pwm_frequency, const int pinA) {
RenesasHardwareDriverParams* params = new RenesasHardwareDriverParams;
params->pins[0] = pinA;
params->pwm_frequency = (pwm_frequency==NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
bool success = true;
success = configureTimerPin(params, 0, SIMPLEFOC_PWM_ACTIVE_HIGH);
if (success)
success = startTimerChannels(params, 1);
if (!success)
return SIMPLEFOC_DRIVER_INIT_FAILED;
return params;
}
void* _configure2PWM(long pwm_frequency,const int pinA, const int pinB) {
RenesasHardwareDriverParams* params = new RenesasHardwareDriverParams;
params->pins[0] = pinA; params->pins[1] = pinB;
params->pwm_frequency = (pwm_frequency==NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
bool success = true;
success = configureTimerPin(params, 0, SIMPLEFOC_PWM_ACTIVE_HIGH);
success &= configureTimerPin(params, 1, SIMPLEFOC_PWM_ACTIVE_HIGH);
if (!success)
success &= startTimerChannels(params, 2);
if (!success)
return SIMPLEFOC_DRIVER_INIT_FAILED;
return params;
}
void* _configure3PWM(long pwm_frequency,const int pinA, const int pinB, const int pinC) {
RenesasHardwareDriverParams* params = new RenesasHardwareDriverParams;
params->pins[0] = pinA; params->pins[1] = pinB; params->pins[2] = pinC;
params->pwm_frequency = (pwm_frequency==NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
bool success = true;
success = configureTimerPin(params, 0, SIMPLEFOC_PWM_ACTIVE_HIGH);
success &= configureTimerPin(params, 1, SIMPLEFOC_PWM_ACTIVE_HIGH);
success &= configureTimerPin(params, 2, SIMPLEFOC_PWM_ACTIVE_HIGH);
if (success)
success = startTimerChannels(params, 3);
if (!success)
return SIMPLEFOC_DRIVER_INIT_FAILED;
return params;
}
void* _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B) {
RenesasHardwareDriverParams* params = new RenesasHardwareDriverParams;
params->pins[0] = pin1A; params->pins[1] = pin1B; params->pins[2] = pin2A; params->pins[3] = pin2B;
params->pwm_frequency = (pwm_frequency==NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
bool success = true;
success = configureTimerPin(params, 0, SIMPLEFOC_PWM_ACTIVE_HIGH);
success &= configureTimerPin(params, 1, SIMPLEFOC_PWM_ACTIVE_HIGH);
success &= configureTimerPin(params, 2, SIMPLEFOC_PWM_ACTIVE_HIGH);
success &= configureTimerPin(params, 3, SIMPLEFOC_PWM_ACTIVE_HIGH);
if (success)
success = startTimerChannels(params, 4);
if (!success)
return SIMPLEFOC_DRIVER_INIT_FAILED;
return params;
}
void* _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, const int pinA_l, const int pinB_h, const int pinB_l, const int pinC_h, const int pinC_l){
RenesasHardwareDriverParams* params = new RenesasHardwareDriverParams;
params->pins[0] = pinA_h; params->pins[1] = pinA_l; params->pins[2] = pinB_h; params->pins[3] = pinB_l; params->pins[4] = pinC_h; params->pins[5] = pinC_l;
params->pwm_frequency = (pwm_frequency==NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
params->dead_zone = (dead_zone==NOT_SET)?RENESAS_DEFAULT_DEAD_ZONE:dead_zone;
bool success = true;
if (isHardware6Pwm(pinA_h, pinA_l))
success &= configureTimerPin(params, 0, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, true, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH);
else {
success &= configureTimerPin(params, 0, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH);
success &= configureTimerPin(params, 1, !SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH); // reverse polarity on low side gives desired active high/low behaviour
}
if (isHardware6Pwm(pinB_h, pinB_l))
success &= configureTimerPin(params, 2, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, true, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH);
else {
success &= configureTimerPin(params, 2, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH);
success &= configureTimerPin(params, 3, !SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH);
}
if (isHardware6Pwm(pinC_h, pinC_l))
success &= configureTimerPin(params, 4, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, true, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH);
else {
success &= configureTimerPin(params, 4, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH);
success &= configureTimerPin(params, 5, !SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH);
}
if (success)
success = startTimerChannels(params, 6);
if (!success)
return SIMPLEFOC_DRIVER_INIT_FAILED;
return params;
}
void _writeDutyCycle1PWM(float dc_a, void* params){
RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)params)->timer_config[0];
uint32_t duty_cycle_counts = (uint32_t)(dc_a * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
}
void _writeDutyCycle2PWM(float dc_a, float dc_b, void* params){
RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)params)->timer_config[0];
uint32_t duty_cycle_counts = (uint32_t)(dc_a * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[1];
duty_cycle_counts = (uint32_t)(dc_b * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
}
void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void* params){
RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)params)->timer_config[0];
uint32_t duty_cycle_counts = (uint32_t)(dc_a * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[1];
duty_cycle_counts = (uint32_t)(dc_b * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[2];
duty_cycle_counts = (uint32_t)(dc_c * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
}
void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, void* params){
RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)params)->timer_config[0];
uint32_t duty_cycle_counts = (uint32_t)(dc_1a * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[1];
duty_cycle_counts = (uint32_t)(dc_1b * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[2];
duty_cycle_counts = (uint32_t)(dc_2a * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[3];
duty_cycle_counts = (uint32_t)(dc_2b * (float)(t->timer_cfg.period_counts));
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
}
void _setSinglePhaseState(RenesasTimerConfig* hi, RenesasTimerConfig* lo, PhaseState state) {
gpt_gtior_setting_t gtior;
gtior.gtior = hi->ctrl.p_reg->GTIOR;
bool on = (state==PHASE_ON) || (state==PHASE_HI);
if (hi->duty_pin == GPT_IO_PIN_GTIOCA_AND_GTIOCB) {
bool ch = false;
if (gtior.gtior_b.obe != on) {
gtior.gtior_b.obe = on;
ch = true;
} // B is high side
on = (state==PHASE_ON) || (state==PHASE_LO);
if (gtior.gtior_b.oae != on) {
gtior.gtior_b.oae = on;
ch = true;
}
if (ch)
hi->ctrl.p_reg->GTIOR = gtior.gtior;
return;
}
if (hi->duty_pin == GPT_IO_PIN_GTIOCA) {
if (gtior.gtior_b.oae != on) {
gtior.gtior_b.oae = on;
hi->ctrl.p_reg->GTIOR = gtior.gtior;
}
}
else if (hi->duty_pin == GPT_IO_PIN_GTIOCB) {
if (gtior.gtior_b.obe != on) {
gtior.gtior_b.obe = on;
hi->ctrl.p_reg->GTIOR = gtior.gtior;
}
}
gtior.gtior = lo->ctrl.p_reg->GTIOR;
on = (state==PHASE_ON) || (state==PHASE_LO);
if (lo->duty_pin == GPT_IO_PIN_GTIOCA) {
if (gtior.gtior_b.oae != on) {
gtior.gtior_b.oae = on;
lo->ctrl.p_reg->GTIOR = gtior.gtior;
}
}
else if (lo->duty_pin == GPT_IO_PIN_GTIOCB) {
if (gtior.gtior_b.obe != on) {
gtior.gtior_b.obe = on;
lo->ctrl.p_reg->GTIOR = gtior.gtior;
}
}
}
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void* params){
RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)params)->timer_config[0];
RenesasTimerConfig* t1 = ((RenesasHardwareDriverParams*)params)->timer_config[1];
uint32_t dt = (uint32_t)(((RenesasHardwareDriverParams*)params)->dead_zone * (float)(t->timer_cfg.period_counts));
uint32_t duty_cycle_counts = (uint32_t)(dc_a * (float)(t->timer_cfg.period_counts));
bool hw_deadtime = ((RenesasHardwareDriverParams*)params)->channels[0] == ((RenesasHardwareDriverParams*)params)->channels[1];
uint32_t dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
_setSinglePhaseState(t, t1, phase_state[0]);
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts - dt_act, t->duty_pin) != FSP_SUCCESS) {
// error
}
if (!hw_deadtime) {
if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
// error
}
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[2];
t1 = ((RenesasHardwareDriverParams*)params)->timer_config[3];
duty_cycle_counts = (uint32_t)(dc_b * (float)(t->timer_cfg.period_counts));
hw_deadtime = ((RenesasHardwareDriverParams*)params)->channels[2] == ((RenesasHardwareDriverParams*)params)->channels[3];
dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
_setSinglePhaseState(t, t1, phase_state[1]);
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts - dt_act, t->duty_pin) != FSP_SUCCESS) {
// error
}
if (!hw_deadtime) {
if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
// error
}
}
t = ((RenesasHardwareDriverParams*)params)->timer_config[4];
t1 = ((RenesasHardwareDriverParams*)params)->timer_config[5];
duty_cycle_counts = (uint32_t)(dc_c * (float)(t->timer_cfg.period_counts));
hw_deadtime = ((RenesasHardwareDriverParams*)params)->channels[4] == ((RenesasHardwareDriverParams*)params)->channels[5];
dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
_setSinglePhaseState(t, t1, phase_state[2]);
if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
// error
}
if (!hw_deadtime) {
if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
// error
}
}
}
#endif