2#include "../hardware_api.h"
4#if defined(TARGET_PORTENTA_H7) && false
8#pragma message("SimpleFOC: compiling for Arduino/Portenta_H7")
12#include "pwmout_api.h"
13#include "pinDefinitions.h"
14#include "platform/mbed_critical.h"
15#include "platform/mbed_power_mgmt.h"
16#include "platform/mbed_assert.h"
17#include "PeripheralPins.h"
18#include "pwmout_device.h"
21#define _PWM_FREQUENCY 25000
22#define _PWM_FREQUENCY_MAX 50000
32typedef struct PortentaDriverParams {
36} PortentaDriverParams;
41uint32_t _TIM_ChannelConvert_HAL2LL(uint32_t channel, pwmout_t *obj)
43#if !defined(PWMOUT_INVERTED_NOT_SUPPORTED)
47 return LL_TIM_CHANNEL_CH1N;
49 return LL_TIM_CHANNEL_CH2N;
51 return LL_TIM_CHANNEL_CH3N;
52#if defined(LL_TIM_CHANNEL_CH4N)
54 return LL_TIM_CHANNEL_CH4N;
64 return LL_TIM_CHANNEL_CH1;
66 return LL_TIM_CHANNEL_CH2;
68 return LL_TIM_CHANNEL_CH3;
70 return LL_TIM_CHANNEL_CH4;
83int _pwm_init(pwmout_t *obj, uint32_t pin,
long frequency){
84 int peripheral = (int)pinmap_peripheral(digitalPinToPinName(pin), PinMap_PWM);
85 int function = (int)pinmap_find_function(digitalPinToPinName(pin), PinMap_PWM);
87 const PinMap static_pinmap = {digitalPinToPinName(pin), peripheral, function};
89 pwmout_init_direct(obj, &static_pinmap);
91 TIM_HandleTypeDef TimHandle;
92 TimHandle.Instance = (TIM_TypeDef *)(obj->pwm);
93 RCC_ClkInitTypeDef RCC_ClkInitStruct;
94 uint32_t PclkFreq = 0;
95 uint32_t APBxCLKDivider = RCC_HCLK_DIV1;
99 __HAL_TIM_DISABLE(&TimHandle);
103 HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &PclkFreq);
106 while (pwm_apb_map_table[i].pwm != obj->pwm) i++;
108 if (pwm_apb_map_table[i].pwm == 0)
return -1;
111 if (pwm_apb_map_table[i].pwmoutApb == PWMOUT_ON_APB1) {
112 PclkFreq = HAL_RCC_GetPCLK1Freq();
113 APBxCLKDivider = RCC_ClkInitStruct.APB1CLKDivider;
115#if !defined(PWMOUT_APB2_NOT_SUPPORTED)
116 PclkFreq = HAL_RCC_GetPCLK2Freq();
117 APBxCLKDivider = RCC_ClkInitStruct.APB2CLKDivider;
121 long period_us = 500000.0/((float)frequency);
125 if (APBxCLKDivider == RCC_HCLK_DIV1) {
126 TimHandle.Init.Prescaler = (((PclkFreq) / 1000000)) - 1;
128 TimHandle.Init.Prescaler = (((PclkFreq * 2) / 1000000)) - 1;
130 TimHandle.Init.Period = (period_us - 1);
133 while ((TimHandle.Init.Period > 0xFFFF) || (TimHandle.Init.Prescaler > 0xFFFF)) {
134 obj->prescaler = obj->prescaler * 2;
135 if (APBxCLKDivider == RCC_HCLK_DIV1) {
136 TimHandle.Init.Prescaler = (((PclkFreq) / 1000000) * obj->prescaler) - 1;
138 TimHandle.Init.Prescaler = (((PclkFreq * 2) / 1000000) * obj->prescaler) - 1;
140 TimHandle.Init.Period = (period_us - 1) / obj->prescaler;
143 if ((TimHandle.Init.Period < 0xFFFF) && (TimHandle.Init.Prescaler > 0xFFFF)) {
148 TimHandle.Init.ClockDivision = 0;
149 TimHandle.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
151 if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
155 TIM_OC_InitTypeDef sConfig;
157 sConfig.OCMode = TIM_OCMODE_PWM1;
158 sConfig.Pulse = obj->pulse / obj->prescaler;
159 sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
160 sConfig.OCFastMode = TIM_OCFAST_DISABLE;
161#if defined(TIM_OCIDLESTATE_RESET)
162 sConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
164#if defined(TIM_OCNIDLESTATE_RESET)
165 sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH;
166 sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
170 switch (obj->channel) {
172 channel = TIM_CHANNEL_1;
175 channel = TIM_CHANNEL_2;
178 channel = TIM_CHANNEL_3;
181 channel = TIM_CHANNEL_4;
187 if (LL_TIM_CC_IsEnabledChannel(TimHandle.Instance, _TIM_ChannelConvert_HAL2LL(channel, obj)) == 0) {
189 if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfig, channel) != HAL_OK) {
195 obj->period = period_us;
196#if !defined(PWMOUT_INVERTED_NOT_SUPPORTED)
198 HAL_TIMEx_PWMN_Start(&TimHandle, channel);
202 HAL_TIM_PWM_Start(&TimHandle, channel);
209void _pwm_write(pwmout_t *obj,
float value){
210 TIM_HandleTypeDef TimHandle;
213 TimHandle.Instance = (TIM_TypeDef *)(obj->pwm);
215 if (value < (
float)0.0) {
217 }
else if (value > (
float)1.0) {
221 obj->pulse = (uint32_t)((
float)obj->period * value + 0.5);
223 switch (obj->channel) {
225 channel = TIM_CHANNEL_1;
228 channel = TIM_CHANNEL_2;
231 channel = TIM_CHANNEL_3;
234 channel = TIM_CHANNEL_4;
241 __HAL_TIM_SET_COMPARE(&TimHandle, channel, obj->pulse / obj->prescaler);
277void _alignPWMTimers(pwmout_t *t1, pwmout_t *t2){
278 TIM_HandleTypeDef TimHandle1, TimHandle2;
279 TimHandle1.Instance = (TIM_TypeDef *)(t1->pwm);
280 TimHandle2.Instance = (TIM_TypeDef *)(t2->pwm);
281 __HAL_TIM_DISABLE(&TimHandle1);
282 __HAL_TIM_DISABLE(&TimHandle2);
283 __HAL_TIM_ENABLE(&TimHandle1);
284 __HAL_TIM_ENABLE(&TimHandle2);
288void _alignPWMTimers(pwmout_t *t1, pwmout_t *t2, pwmout_t *t3){
289 TIM_HandleTypeDef TimHandle1, TimHandle2, TimHandle3;
290 TimHandle1.Instance = (TIM_TypeDef *)(t1->pwm);
291 TimHandle2.Instance = (TIM_TypeDef *)(t2->pwm);
292 TimHandle3.Instance = (TIM_TypeDef *)(t3->pwm);
293 __HAL_TIM_DISABLE(&TimHandle1);
294 __HAL_TIM_DISABLE(&TimHandle2);
295 __HAL_TIM_DISABLE(&TimHandle3);
296 __HAL_TIM_ENABLE(&TimHandle1);
297 __HAL_TIM_ENABLE(&TimHandle2);
298 __HAL_TIM_ENABLE(&TimHandle3);
302void _alignPWMTimers(pwmout_t *t1, pwmout_t *t2, pwmout_t *t3, pwmout_t *t4){
303 TIM_HandleTypeDef TimHandle1, TimHandle2, TimHandle3, TimHandle4;
304 TimHandle1.Instance = (TIM_TypeDef *)(t1->pwm);
305 TimHandle2.Instance = (TIM_TypeDef *)(t2->pwm);
306 TimHandle3.Instance = (TIM_TypeDef *)(t3->pwm);
307 TimHandle4.Instance = (TIM_TypeDef *)(t4->pwm);
308 __HAL_TIM_DISABLE(&TimHandle1);
309 __HAL_TIM_DISABLE(&TimHandle2);
310 __HAL_TIM_DISABLE(&TimHandle3);
311 __HAL_TIM_DISABLE(&TimHandle4);
312 __HAL_TIM_ENABLE(&TimHandle1);
313 __HAL_TIM_ENABLE(&TimHandle2);
314 __HAL_TIM_ENABLE(&TimHandle3);
315 __HAL_TIM_ENABLE(&TimHandle4);
390 if( !pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
391 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
393 PortentaDriverParams*
params =
new PortentaDriverParams();
394 params->pwm_frequency = pwm_frequency;
396 core_util_critical_section_enter();
401 core_util_critical_section_exit();
410 if( !pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
411 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
413 PortentaDriverParams*
params =
new PortentaDriverParams();
414 params->pwm_frequency = pwm_frequency;
416 core_util_critical_section_enter();
422 core_util_critical_section_exit();
433 if( !pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
434 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
436 PortentaDriverParams*
params =
new PortentaDriverParams();
437 params->pwm_frequency = pwm_frequency;
439 core_util_critical_section_enter();
443 _pwm_init(&(
params->
pins[3]), pinD, (
long)pwm_frequency);
446 core_util_critical_section_exit();
457 core_util_critical_section_enter();
458 _pwm_write(&(((PortentaDriverParams*)
params)->pins[0]), (
float)dc_a);
459 _pwm_write(&(((PortentaDriverParams*)
params)->pins[1]), (
float)
dc_b);
460 core_util_critical_section_exit();
467 core_util_critical_section_enter();
468 _pwm_write(&(((PortentaDriverParams*)
params)->pins[0]), (
float)dc_a);
469 _pwm_write(&(((PortentaDriverParams*)
params)->pins[1]), (
float)
dc_b);
470 _pwm_write(&(((PortentaDriverParams*)
params)->pins[2]), (
float)
dc_c);
471 core_util_critical_section_exit();
479 core_util_critical_section_enter();
480 _pwm_write(&(((PortentaDriverParams*)
params)->pins[0]), (
float)dc_1a);
481 _pwm_write(&(((PortentaDriverParams*)
params)->pins[1]), (
float)
dc_1b);
482 _pwm_write(&(((PortentaDriverParams*)
params)->pins[2]), (
float)
dc_2a);
483 _pwm_write(&(((PortentaDriverParams*)
params)->pins[3]), (
float)
dc_2b);
484 core_util_critical_section_exit();
const int const int const int pinC
GenericCurrentSenseParams * params
void * _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B)
void * _configure2PWM(long pwm_frequency, const int pinA, const int pinB)
void _writeDutyCycle2PWM(float dc_a, float dc_b, void *params)
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)
void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void *params)
#define _constrain(amt, low, high)