2#include "../hardware_api.h"
4#if defined(NRF52_SERIES)
7#pragma message("SimpleFOC: compiling for NRF52")
11#define PWM_CLK (16000000)
12#define PWM_FREQ (40000)
13#define PWM_RESOLUTION (PWM_CLK/PWM_FREQ)
14#define PWM_MAX_FREQ (62500)
15#define DEAD_ZONE (250)
16#define DEAD_TIME (DEAD_ZONE / (PWM_RESOLUTION * 0.25 * 62.5))
25#define _EMPTY_SLOT (-0xAA)
26#define _TAKEN_SLOT (-0x55)
31static NRF_PWM_Type* pwms[PWM_COUNT] = {
43 uint16_t mcpwm_channel_sequence[4];
44} bldc_3pwm_motor_slots_t;
49 uint16_t mcpwm_channel_sequence[4];
50} stepper_motor_slots_t;
56 uint16_t mcpwm_channel_sequence[8];
57} bldc_6pwm_motor_slots_t;
60bldc_3pwm_motor_slots_t nrf52_bldc_3pwm_motor_slots[4] = {
61 {_EMPTY_SLOT, pwms[0], {0,0,0,0}},
62 {_EMPTY_SLOT, pwms[1], {0,0,0,0}},
63 {_EMPTY_SLOT, pwms[2], {0,0,0,0}},
64 {_EMPTY_SLOT, pwms[3], {0,0,0,0}}
68stepper_motor_slots_t nrf52_stepper_motor_slots[4] = {
69 {_EMPTY_SLOT, pwms[0], {0,0,0,0}},
70 {_EMPTY_SLOT, pwms[1], {0,0,0,0}},
71 {_EMPTY_SLOT, pwms[2], {0,0,0,0}},
72 {_EMPTY_SLOT, pwms[3], {0,0,0,0}}
76bldc_6pwm_motor_slots_t nrf52_bldc_6pwm_motor_slots[2] = {
77 {_EMPTY_SLOT, pwms[0], pwms[1], {0,0,0,0,0,0,0,0}},
78 {_EMPTY_SLOT, pwms[2], pwms[3], {0,0,0,0,0,0,0,0}}
83typedef struct NRF52DriverParams {
85 bldc_3pwm_motor_slots_t* slot3pwm;
86 bldc_6pwm_motor_slots_t* slot6pwm;
87 stepper_motor_slots_t* slotstep;
97void _configureHwPwm(NRF_PWM_Type* mcpwm1, NRF_PWM_Type* mcpwm2){
99 mcpwm1->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
100 mcpwm1->PRESCALER = (PWM_PRESCALER_PRESCALER_DIV_1 << PWM_PRESCALER_PRESCALER_Pos);
101 mcpwm1->MODE = (PWM_MODE_UPDOWN_UpAndDown << PWM_MODE_UPDOWN_Pos);
102 mcpwm1->COUNTERTOP = pwm_range;
103 mcpwm1->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos);
104 mcpwm1->DECODER = ((uint32_t)PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos) | ((uint32_t)PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);
105 mcpwm1->SEQ[0].REFRESH = 0;
106 mcpwm1->SEQ[0].ENDDELAY = 0;
108 if(mcpwm1 != mcpwm2){
109 mcpwm2->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
110 mcpwm2->PRESCALER = (PWM_PRESCALER_PRESCALER_DIV_1 << PWM_PRESCALER_PRESCALER_Pos);
111 mcpwm2->MODE = (PWM_MODE_UPDOWN_UpAndDown << PWM_MODE_UPDOWN_Pos);
112 mcpwm2->COUNTERTOP = pwm_range;
113 mcpwm2->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos);
114 mcpwm2->DECODER = ((uint32_t)PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos) | ((uint32_t)PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);
115 mcpwm2->SEQ[0].REFRESH = 0;
116 mcpwm2->SEQ[0].ENDDELAY = 0;
118 mcpwm1->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos);
137 if( !pwm_frequency || pwm_frequency ==
NOT_SET) pwm_frequency = PWM_FREQ;
138 else pwm_frequency =
_constrain(pwm_frequency, 0, PWM_MAX_FREQ);
140 pwm_range = (PWM_CLK / pwm_frequency);
142 int pA = digitalPinToPinName(
pinA);
143 int pB = digitalPinToPinName(
pinB);
144 int pC = digitalPinToPinName(
pinC);
149 for(slot_num = 0; slot_num < 4; slot_num++){
150 if(nrf52_bldc_3pwm_motor_slots[slot_num].
pinA == _EMPTY_SLOT){
151 nrf52_bldc_3pwm_motor_slots[slot_num].pinA =
pinA;
161 nrf52_stepper_motor_slots[slot_num].pin1A = _TAKEN_SLOT;
163 nrf52_bldc_6pwm_motor_slots[0].pinAH = _TAKEN_SLOT;
167 nrf52_stepper_motor_slots[slot_num].pin1A = _TAKEN_SLOT;
169 nrf52_bldc_6pwm_motor_slots[1].pinAH = _TAKEN_SLOT;
175 nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm->PSEL.OUT[0] = pA;
176 nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm->PSEL.OUT[1] = pB;
177 nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm->PSEL.OUT[2] = pC;
179 nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm->SEQ[0].PTR = (uint32_t)&nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm_channel_sequence[0];
180 nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm->SEQ[0].CNT = 4;
183 _configureHwPwm(nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm, nrf52_bldc_3pwm_motor_slots[slot_num].mcpwm);
185 NRF52DriverParams*
params =
new NRF52DriverParams();
186 params->slot.slot3pwm = &(nrf52_bldc_3pwm_motor_slots[slot_num]);
187 params->pwm_frequency = pwm_frequency;
199 if( !pwm_frequency || pwm_frequency ==
NOT_SET) pwm_frequency = PWM_FREQ;
200 else pwm_frequency =
_constrain(pwm_frequency, 0, PWM_MAX_FREQ);
202 pwm_range = (PWM_CLK / pwm_frequency);
204 int pA = digitalPinToPinName(
pinA);
205 int pB = digitalPinToPinName(
pinB);
206 int pC = digitalPinToPinName(
pinC);
207 int pD = digitalPinToPinName(pinD);
212 for(slot_num = 0; slot_num < 4; slot_num++){
213 if(nrf52_stepper_motor_slots[slot_num].
pin1A == _EMPTY_SLOT){
214 nrf52_stepper_motor_slots[slot_num].pin1A =
pinA;
224 nrf52_bldc_3pwm_motor_slots[slot_num].pinA = _TAKEN_SLOT;
226 nrf52_bldc_6pwm_motor_slots[0].pinAH = _TAKEN_SLOT;
230 nrf52_bldc_3pwm_motor_slots[slot_num].pinA = _TAKEN_SLOT;
232 nrf52_bldc_6pwm_motor_slots[1].pinAH = _TAKEN_SLOT;
238 nrf52_stepper_motor_slots[slot_num].mcpwm->PSEL.OUT[0] = pA;
239 nrf52_stepper_motor_slots[slot_num].mcpwm->PSEL.OUT[1] = pB;
240 nrf52_stepper_motor_slots[slot_num].mcpwm->PSEL.OUT[2] = pC;
241 nrf52_stepper_motor_slots[slot_num].mcpwm->PSEL.OUT[3] = pD;
243 nrf52_stepper_motor_slots[slot_num].mcpwm->SEQ[0].PTR = (uint32_t)&nrf52_stepper_motor_slots[slot_num].mcpwm_channel_sequence[0];
244 nrf52_stepper_motor_slots[slot_num].mcpwm->SEQ[0].CNT = 4;
247 _configureHwPwm(nrf52_stepper_motor_slots[slot_num].mcpwm, nrf52_stepper_motor_slots[slot_num].mcpwm);
249 NRF52DriverParams*
params =
new NRF52DriverParams();
250 params->slot.slotstep = &(nrf52_stepper_motor_slots[slot_num]);
251 params->pwm_frequency = pwm_frequency;
263 bldc_3pwm_motor_slots_t* p = ((NRF52DriverParams*)
params)->slot.slot3pwm;
264 p->mcpwm_channel_sequence[0] = (int)(dc_a * pwm_range) | 0x8000;
265 p->mcpwm_channel_sequence[1] = (int)(
dc_b * pwm_range) | 0x8000;
266 p->mcpwm_channel_sequence[2] = (int)(
dc_c * pwm_range) | 0x8000;
268 p->mcpwm->TASKS_SEQSTART[0] = 1;
279 stepper_motor_slots_t* p = ((NRF52DriverParams*)
params)->slot.slotstep;
280 p->mcpwm_channel_sequence[0] = (int)(dc_1a * pwm_range) | 0x8000;
281 p->mcpwm_channel_sequence[1] = (int)(
dc_1b * pwm_range) | 0x8000;
282 p->mcpwm_channel_sequence[2] = (int)(
dc_2a * pwm_range) | 0x8000;
283 p->mcpwm_channel_sequence[3] = (int)(
dc_2b * pwm_range) | 0x8000;
285 p->mcpwm->TASKS_SEQSTART[0] = 1;
294 if( !pwm_frequency || pwm_frequency ==
NOT_SET) pwm_frequency = PWM_FREQ;
295 else pwm_frequency =
_constrain(pwm_frequency*2, 0, PWM_MAX_FREQ);
297 pwm_range = (PWM_CLK / pwm_frequency);
304 dead_time = DEAD_TIME/2;
307 int pA_l = digitalPinToPinName(
pinA_l);
308 int pA_h = digitalPinToPinName(
pinA_h);
309 int pB_l = digitalPinToPinName(
pinB_l);
310 int pB_h = digitalPinToPinName(
pinB_h);
311 int pC_l = digitalPinToPinName(
pinC_l);
312 int pC_h = digitalPinToPinName(
pinC_h);
318 for(slot_num = 0; slot_num < 2; slot_num++){
319 if(nrf52_bldc_6pwm_motor_slots[slot_num].pinAH == _EMPTY_SLOT){
320 nrf52_bldc_6pwm_motor_slots[slot_num].pinAH =
pinA_h;
330 nrf52_bldc_3pwm_motor_slots[0].pinA = _TAKEN_SLOT;
331 nrf52_bldc_3pwm_motor_slots[1].pinA = _TAKEN_SLOT;
333 nrf52_stepper_motor_slots[0].pin1A = _TAKEN_SLOT;
334 nrf52_stepper_motor_slots[1].pin1A = _TAKEN_SLOT;
337 nrf52_bldc_3pwm_motor_slots[2].pinA = _TAKEN_SLOT;
338 nrf52_bldc_3pwm_motor_slots[3].pinA = _TAKEN_SLOT;
340 nrf52_stepper_motor_slots[2].pin1A = _TAKEN_SLOT;
341 nrf52_stepper_motor_slots[3].pin1A = _TAKEN_SLOT;
346 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1->PSEL.OUT[0] = pA_h;
347 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1->PSEL.OUT[1] = pA_l;
348 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1->PSEL.OUT[2] = pB_h;
349 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1->PSEL.OUT[3] = pB_l;
350 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1->SEQ[0].PTR = (uint32_t)&nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm_channel_sequence[0];
351 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1->SEQ[0].CNT = 4;
353 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm2->PSEL.OUT[0] = pC_h;
354 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm2->PSEL.OUT[1] = pC_l;
355 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm2->SEQ[0].PTR = (uint32_t)&nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm_channel_sequence[4];
356 nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm2->SEQ[0].CNT = 4;
360 NRF_PPI->CH[slot_num].EEP = (uint32_t)&NRF_EGU0->EVENTS_TRIGGERED[0];
361 NRF_PPI->CH[slot_num].TEP = (uint32_t)&nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1->TASKS_SEQSTART[0];
362 NRF_PPI->FORK[slot_num].TEP = (uint32_t)&nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm2->TASKS_SEQSTART[0];
363 NRF_PPI->CHEN = 1UL << slot_num;
366 _configureHwPwm(nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm1, nrf52_bldc_6pwm_motor_slots[slot_num].mcpwm2);
368 NRF52DriverParams*
params =
new NRF52DriverParams();
369 params->slot.slot6pwm = &(nrf52_bldc_6pwm_motor_slots[slot_num]);
370 params->pwm_frequency = pwm_frequency;
371 params->dead_time = dead_time;
383 bldc_6pwm_motor_slots_t* p = ((NRF52DriverParams*)
params)->slot.slot6pwm;
384 float dead_time = ((NRF52DriverParams*)
params)->dead_time;
385 p->mcpwm_channel_sequence[0] = (int)(
_constrain(dc_a-dead_time,0,1)*pwm_range) | 0x8000;
386 p->mcpwm_channel_sequence[1] = (int)(
_constrain(dc_a+dead_time,0,1)*pwm_range);
387 p->mcpwm_channel_sequence[2] = (int)(
_constrain(
dc_b-dead_time,0,1)*pwm_range) | 0x8000;
388 p->mcpwm_channel_sequence[3] = (int)(
_constrain(
dc_b+dead_time,0,1)*pwm_range);
389 p->mcpwm_channel_sequence[4] = (int)(
_constrain(
dc_c-dead_time,0,1)*pwm_range) | 0x8000;
390 p->mcpwm_channel_sequence[5] = (int)(
_constrain(
dc_c+dead_time,0,1)*pwm_range);
391 NRF_EGU0->TASKS_TRIGGER[0] = 1;
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 * _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)
#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)
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void *params)
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
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
#define _constrain(amt, low, high)