4#if defined(ARDUINO_UNOR4_WIFI) || defined(ARDUINO_UNOR4_MINIMA)
8#pragma message("SimpleFOC: compiling for Arduino/Renesas (UNO R4)")
16#define GPT_OPEN (0x00475054ULL)
58bool channel_used[GPT_HOWMANY] = {
false };
61struct RenesasTimerConfig {
62 timer_cfg_t timer_cfg;
63 gpt_instance_ctrl_t ctrl;
64 gpt_extended_cfg_t ext_cfg;
65 gpt_extended_pwm_cfg_t pwm_cfg;
66 gpt_io_pin_t duty_pin;
69struct ClockDivAndRange {
70 timer_source_div_t clk_div;
74ClockDivAndRange getClockDivAndRange(uint32_t pwm_frequency, uint8_t timer_channel) {
75 ClockDivAndRange result;
76 uint32_t max_count = (timer_channel < GTP32_HOWMANY)? 4294967295 : 65535;
77 uint32_t freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD);
78 float range = (float) freq_hz / ((
float) pwm_frequency * 2.0f);
79 if(range / 1.0 < max_count) {
80 result.range = (uint32_t) (range / 1.0);
81 result.clk_div = TIMER_SOURCE_DIV_1;
83 else if (range / 2.0 < max_count) {
84 result.range = (uint32_t) (range / 2.0);
85 result.clk_div = TIMER_SOURCE_DIV_2;
87 else if(range / 4.0 < max_count) {
88 result.range = (uint32_t) (range / 4.0);
89 result.clk_div = TIMER_SOURCE_DIV_4;
91 else if(range / 8.0 < max_count) {
92 result.range = (uint32_t) (range / 8.0 );
93 result.clk_div = TIMER_SOURCE_DIV_8;
95 else if(range / 16.0 < max_count) {
96 result.range = (uint32_t) (range / 16.0 );
97 result.clk_div = TIMER_SOURCE_DIV_16;
99 else if (range / 32.0 < max_count) {
100 result.range = (uint32_t) (range / 32.0 );
101 result.clk_div = TIMER_SOURCE_DIV_32;
103 else if(range / 64.0 < max_count) {
104 result.range = (uint32_t) (range / 64.0 );
105 result.clk_div = TIMER_SOURCE_DIV_64;
107 else if(range / 128.0 < max_count) {
108 result.range = (uint32_t) (range / 128.0 );
109 result.clk_div = TIMER_SOURCE_DIV_128;
111 else if(range / 256.0 < max_count) {
112 result.range = (uint32_t) (range / 256.0 );
113 result.clk_div = TIMER_SOURCE_DIV_256;
115 else if(range / 512.0 < max_count) {
116 result.range = (uint32_t) (range / 512.0 );
117 result.clk_div = TIMER_SOURCE_DIV_512;
119 else if(range / 1024.0 < max_count) {
120 result.range = (uint32_t) (range / 1024.0 );
121 result.clk_div = TIMER_SOURCE_DIV_1024;
124 #if !defined(SIMPLEFOC_DISABLE_DEBUG)
132bool configureTimerPin(RenesasHardwareDriverParams*
params, uint8_t index,
bool active_high,
bool complementary =
false,
bool complementary_active_high =
true) {
135 std::array<uint16_t, 3> pinCfgs = getPinCfgs(pin, PIN_CFG_REQ_PWM);
136 std::array<uint16_t, 3> pinCfgs_C;
137 if(pinCfgs[0] == 0) {
141 if (IS_PIN_AGT_PWM(pinCfgs[0])) {
146 uint8_t timer_channel = GET_CHANNEL(pinCfgs[0]);
148 if (channel_used[timer_channel]) {
155 pinCfgs_C = getPinCfgs(pin_C, PIN_CFG_REQ_PWM);
156 if(pinCfgs_C[0] == 0) {
160 if (IS_PIN_AGT_PWM(pinCfgs_C[0]) || GET_CHANNEL(pinCfgs_C[0])!=timer_channel) {
165 TimerPWMChannel_t pwm_output = IS_PWM_ON_A(pinCfgs[0]) ? CHANNEL_A : CHANNEL_B;
167 TimerPWMChannel_t pwm_output_C = IS_PWM_ON_A(pinCfgs_C[0]) ? CHANNEL_A : CHANNEL_B;
168 if (pwm_output_C != CHANNEL_A || pwm_output != CHANNEL_B) {
175 fsp_err_t err = R_IOPORT_PinCfg(&g_ioport_ctrl, g_pin_cfg[pin].pin, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_GPT1));
176 if ((err == FSP_SUCCESS) && complementary)
177 err = R_IOPORT_PinCfg(&g_ioport_ctrl, g_pin_cfg[pin_C].pin, (uint32_t) (IOPORT_CFG_PERIPHERAL_PIN | IOPORT_PERIPHERAL_GPT1));
178 if (err != FSP_SUCCESS) {
185 ClockDivAndRange timings = getClockDivAndRange(
params->pwm_frequency, timer_channel);
186 #if defined(SIMPLEFOC_RENESAS_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
198 RenesasTimerConfig* t =
new RenesasTimerConfig();
200 t->timer_cfg.channel = timer_channel;
201 t->timer_cfg.mode = TIMER_MODE_TRIANGLE_WAVE_SYMMETRIC_PWM;
202 t->timer_cfg.source_div = timings.clk_div;
203 t->timer_cfg.period_counts = timings.range;
204 t->timer_cfg.duty_cycle_counts = 0;
205 t->timer_cfg.p_callback =
nullptr;
206 t->timer_cfg.p_context =
nullptr;
207 t->timer_cfg.p_extend = &(t->ext_cfg);
208 t->timer_cfg.cycle_end_ipl = BSP_IRQ_DISABLED;
209 t->timer_cfg.cycle_end_irq = FSP_INVALID_VECTOR;
211 t->ext_cfg.p_pwm_cfg = &(t->pwm_cfg);
212 t->ext_cfg.capture_a_ipl = BSP_IRQ_DISABLED;
213 t->ext_cfg.capture_a_irq = FSP_INVALID_VECTOR;
214 t->ext_cfg.capture_b_ipl = BSP_IRQ_DISABLED;
215 t->ext_cfg.capture_b_irq = FSP_INVALID_VECTOR;
216 t->pwm_cfg.trough_ipl = BSP_IRQ_DISABLED;
217 t->pwm_cfg.trough_irq = FSP_INVALID_VECTOR;
218 t->pwm_cfg.poeg_link = GPT_POEG_LINK_POEG0;
219 t->pwm_cfg.output_disable = GPT_OUTPUT_DISABLE_NONE;
220 t->pwm_cfg.adc_trigger = GPT_ADC_TRIGGER_NONE;
221 t->pwm_cfg.dead_time_count_up = 0;
222 t->pwm_cfg.dead_time_count_down = 0;
223 t->pwm_cfg.adc_a_compare_match = 0;
224 t->pwm_cfg.adc_b_compare_match = 0;
225 t->pwm_cfg.interrupt_skip_source = GPT_INTERRUPT_SKIP_SOURCE_NONE;
226 t->pwm_cfg.interrupt_skip_count = GPT_INTERRUPT_SKIP_COUNT_0;
227 t->pwm_cfg.interrupt_skip_adc = GPT_INTERRUPT_SKIP_ADC_NONE;
228 t->pwm_cfg.gtioca_disable_setting = GPT_GTIOC_DISABLE_PROHIBITED;
229 t->pwm_cfg.gtiocb_disable_setting = GPT_GTIOC_DISABLE_PROHIBITED;
232 uint32_t dt =
params->dead_zone * timings.range;
233 t->pwm_cfg.dead_time_count_up = dt;
234 t->pwm_cfg.dead_time_count_down = dt;
238 t->ext_cfg.gtior_setting.gtior = 0L;
239 if (!complementary) {
240 if(pwm_output == CHANNEL_A) {
241 t->duty_pin = GPT_IO_PIN_GTIOCA;
242 t->ext_cfg.gtioca.output_enabled =
true;
243 t->ext_cfg.gtiocb.output_enabled =
false;
244 t->ext_cfg.gtior_setting.gtior_b.gtioa = 0x03 | (active_high ? 0x00 : 0x10);
245 t->ext_cfg.gtior_setting.gtior_b.oadflt = active_high ? 0x00 : 0x01;
251 t->duty_pin = GPT_IO_PIN_GTIOCB;
252 t->ext_cfg.gtiocb.output_enabled =
true;
253 t->ext_cfg.gtioca.output_enabled =
false;
254 t->ext_cfg.gtior_setting.gtior_b.gtiob = 0x03 | (active_high ? 0x00 : 0x10);
255 t->ext_cfg.gtior_setting.gtior_b.obdflt = active_high ? 0x00 : 0x01;
259 t->duty_pin = GPT_IO_PIN_GTIOCA_AND_GTIOCB;
260 t->ext_cfg.gtioca.output_enabled =
true;
261 t->ext_cfg.gtiocb.output_enabled =
true;
262 t->ext_cfg.gtior_setting.gtior_b.gtioa = 0x03 | (!complementary_active_high ? 0x00 : 0x10);
263 t->ext_cfg.gtior_setting.gtior_b.oadflt = !complementary_active_high ? 0x00 : 0x01;
264 t->ext_cfg.gtior_setting.gtior_b.gtiob = 0x03 | (active_high ? 0x00 : 0x10);
265 t->ext_cfg.gtior_setting.gtior_b.obdflt = active_high ? 0x00 : 0x01;
267 memset(&(t->ctrl), 0,
sizeof(gpt_instance_ctrl_t));
268 err = R_GPT_Open(&(t->ctrl),&(t->timer_cfg));
269 if ((err != FSP_ERR_ALREADY_OPEN) && (err != FSP_SUCCESS)) {
273 if (err == FSP_ERR_ALREADY_OPEN) {
274 #if !defined(SIMPLEFOC_DISABLE_DEBUG)
280 err = R_GPT_PeriodSet(&(t->ctrl), t->timer_cfg.period_counts);
281 if (err != FSP_SUCCESS) {
285 err = R_GPT_OutputEnable(&(t->ctrl), t->duty_pin);
286 if (err != FSP_SUCCESS) {
291 channel_used[timer_channel] =
true;
292 params->timer_config[index] = t;
293 params->channels[index] = timer_channel;
295 params->timer_config[index+1] = t;
296 params->channels[index+1] = timer_channel;
304bool startTimerChannels(RenesasHardwareDriverParams*
params,
int num_channels) {
306 for (
int i = 0; i < num_channels; i++) {
312 mask |= (1 <<
params->channels[i]);
313#if defined(SIMPLEFOC_RENESAS_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
317 params->timer_config[0]->ctrl.p_reg->GTSTR |= mask;
318 #if defined(SIMPLEFOC_RENESAS_DEBUG) && !defined(SIMPLEFOC_DISABLE_DEBUG)
326bool isHardware6Pwm(
const int pin1,
const int pin2) {
327 std::array<uint16_t, 3> pinCfgs1 = getPinCfgs(pin1, PIN_CFG_REQ_PWM);
328 std::array<uint16_t, 3> pinCfgs2 = getPinCfgs(pin2, PIN_CFG_REQ_PWM);
329 if(pinCfgs1[0] == 0 || pinCfgs2[0] == 0)
331 if (IS_PIN_AGT_PWM(pinCfgs1[0]) || IS_PIN_AGT_PWM(pinCfgs2[0]))
333 uint8_t timer_channel1 = GET_CHANNEL(pinCfgs1[0]);
334 uint8_t timer_channel2 = GET_CHANNEL(pinCfgs2[0]);
335 return timer_channel1==timer_channel2;
341 RenesasHardwareDriverParams*
params =
new RenesasHardwareDriverParams;
343 params->pwm_frequency = (pwm_frequency==
NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
347 success = startTimerChannels(
params, 1);
355 RenesasHardwareDriverParams*
params =
new RenesasHardwareDriverParams;
357 params->pwm_frequency = (pwm_frequency==
NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
362 success &= startTimerChannels(
params, 2);
370 RenesasHardwareDriverParams*
params =
new RenesasHardwareDriverParams;
372 params->pwm_frequency = (pwm_frequency==
NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
378 success = startTimerChannels(
params, 3);
386 RenesasHardwareDriverParams*
params =
new RenesasHardwareDriverParams;
388 params->pwm_frequency = (pwm_frequency==
NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
395 success = startTimerChannels(
params, 4);
403 RenesasHardwareDriverParams*
params =
new RenesasHardwareDriverParams;
405 params->pwm_frequency = (pwm_frequency==
NOT_SET)?RENESAS_DEFAULT_PWM_FREQUENCY:pwm_frequency;
431 success = startTimerChannels(
params, 6);
441 RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)
params)->timer_config[0];
442 uint32_t duty_cycle_counts = (uint32_t)(dc_a * (
float)(t->timer_cfg.period_counts));
443 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
450 RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)
params)->timer_config[0];
451 uint32_t duty_cycle_counts = (uint32_t)(dc_a * (
float)(t->timer_cfg.period_counts));
452 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
455 t = ((RenesasHardwareDriverParams*)
params)->timer_config[1];
456 duty_cycle_counts = (uint32_t)(
dc_b * (
float)(t->timer_cfg.period_counts));
457 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
464 RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)
params)->timer_config[0];
465 uint32_t duty_cycle_counts = (uint32_t)(dc_a * (
float)(t->timer_cfg.period_counts));
466 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
469 t = ((RenesasHardwareDriverParams*)
params)->timer_config[1];
470 duty_cycle_counts = (uint32_t)(
dc_b * (
float)(t->timer_cfg.period_counts));
471 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
474 t = ((RenesasHardwareDriverParams*)
params)->timer_config[2];
475 duty_cycle_counts = (uint32_t)(
dc_c * (
float)(t->timer_cfg.period_counts));
476 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
483 RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)
params)->timer_config[0];
484 uint32_t duty_cycle_counts = (uint32_t)(dc_1a * (
float)(t->timer_cfg.period_counts));
485 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
488 t = ((RenesasHardwareDriverParams*)
params)->timer_config[1];
489 duty_cycle_counts = (uint32_t)(
dc_1b * (
float)(t->timer_cfg.period_counts));
490 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
493 t = ((RenesasHardwareDriverParams*)
params)->timer_config[2];
494 duty_cycle_counts = (uint32_t)(
dc_2a * (
float)(t->timer_cfg.period_counts));
495 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
498 t = ((RenesasHardwareDriverParams*)
params)->timer_config[3];
499 duty_cycle_counts = (uint32_t)(
dc_2b * (
float)(t->timer_cfg.period_counts));
500 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
507void _setSinglePhaseState(RenesasTimerConfig* hi, RenesasTimerConfig* lo,
PhaseState state) {
508 gpt_gtior_setting_t gtior;
509 gtior.gtior = hi->ctrl.p_reg->GTIOR;
512 if (hi->duty_pin == GPT_IO_PIN_GTIOCA_AND_GTIOCB) {
514 if (gtior.gtior_b.obe != on) {
515 gtior.gtior_b.obe = on;
519 if (gtior.gtior_b.oae != on) {
520 gtior.gtior_b.oae = on;
524 hi->ctrl.p_reg->GTIOR = gtior.gtior;
528 if (hi->duty_pin == GPT_IO_PIN_GTIOCA) {
529 if (gtior.gtior_b.oae != on) {
530 gtior.gtior_b.oae = on;
531 hi->ctrl.p_reg->GTIOR = gtior.gtior;
534 else if (hi->duty_pin == GPT_IO_PIN_GTIOCB) {
535 if (gtior.gtior_b.obe != on) {
536 gtior.gtior_b.obe = on;
537 hi->ctrl.p_reg->GTIOR = gtior.gtior;
541 gtior.gtior = lo->ctrl.p_reg->GTIOR;
543 if (lo->duty_pin == GPT_IO_PIN_GTIOCA) {
544 if (gtior.gtior_b.oae != on) {
545 gtior.gtior_b.oae = on;
546 lo->ctrl.p_reg->GTIOR = gtior.gtior;
549 else if (lo->duty_pin == GPT_IO_PIN_GTIOCB) {
550 if (gtior.gtior_b.obe != on) {
551 gtior.gtior_b.obe = on;
552 lo->ctrl.p_reg->GTIOR = gtior.gtior;
560 RenesasTimerConfig* t = ((RenesasHardwareDriverParams*)
params)->timer_config[0];
561 RenesasTimerConfig* t1 = ((RenesasHardwareDriverParams*)
params)->timer_config[1];
562 uint32_t dt = (uint32_t)(((RenesasHardwareDriverParams*)
params)->
dead_zone * (
float)(t->timer_cfg.period_counts));
563 uint32_t duty_cycle_counts = (uint32_t)(dc_a * (
float)(t->timer_cfg.period_counts));
564 bool hw_deadtime = ((RenesasHardwareDriverParams*)
params)->channels[0] == ((RenesasHardwareDriverParams*)
params)->channels[1];
565 uint32_t dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
567 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts - dt_act, t->duty_pin) != FSP_SUCCESS) {
571 if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
576 t = ((RenesasHardwareDriverParams*)
params)->timer_config[2];
577 t1 = ((RenesasHardwareDriverParams*)
params)->timer_config[3];
578 duty_cycle_counts = (uint32_t)(
dc_b * (
float)(t->timer_cfg.period_counts));
579 hw_deadtime = ((RenesasHardwareDriverParams*)
params)->channels[2] == ((RenesasHardwareDriverParams*)
params)->channels[3];
580 dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
582 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts - dt_act, t->duty_pin) != FSP_SUCCESS) {
586 if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
591 t = ((RenesasHardwareDriverParams*)
params)->timer_config[4];
592 t1 = ((RenesasHardwareDriverParams*)
params)->timer_config[5];
593 duty_cycle_counts = (uint32_t)(
dc_c * (
float)(t->timer_cfg.period_counts));
594 hw_deadtime = ((RenesasHardwareDriverParams*)
params)->channels[4] == ((RenesasHardwareDriverParams*)
params)->channels[5];
595 dt_act = (duty_cycle_counts>0 && !hw_deadtime)?dt:0;
597 if (R_GPT_DutyCycleSet(&(t->ctrl), duty_cycle_counts, t->duty_pin) != FSP_SUCCESS) {
601 if (R_GPT_DutyCycleSet(&(t1->ctrl), duty_cycle_counts + dt_act, t1->duty_pin) != FSP_SUCCESS) {
#define SIMPLEFOC_DEBUG(msg,...)
static void print(const char *msg)
const int const int const int pinC
GenericCurrentSenseParams * params
#define SIMPLEFOC_PWM_ACTIVE_HIGH
void * _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B)
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)
void * _configure2PWM(long pwm_frequency, const int pinA, const int pinB)
void _writeDutyCycle2PWM(float dc_a, float dc_b, void *params)
void _writeDutyCycle1PWM(float dc_a, void *params)
#define SIMPLEFOC_DRIVER_INIT_FAILED
void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, void *params)
void * _configure3PWM(long pwm_frequency, const int pinA, const int pinB, const int pinC)
#define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void *params)
void * _configure1PWM(long pwm_frequency, const int pinA)
#define SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH
void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void *params)
float const int const int const int pinB_h
float const int const int const int const int pinB_l
const int const int pin1B
const int const int const int pin2A
float const int const int const int const int const int pinC_h
float float PhaseState * phase_state
float const int const int const int const int const int const int pinC_l
float const int const int pinA_l
const int const int const int const int pin2B