@@ -35,6 +35,7 @@ void setupPWM(int pin_nr, long pwm_frequency, bool active_high, SilabsDriverPara
35
35
int8_t timer_nr = getTimerNumber (timer);
36
36
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
37
37
timerCCInit.mode = timerCCModePWM;
38
+ timerCCInit.coist = !active_high;
38
39
timerCCInit.outInvert = !active_high;
39
40
switch (channel) {
40
41
case 0 :
@@ -65,7 +66,7 @@ void setupPWM(int pin_nr, long pwm_frequency, bool active_high, SilabsDriverPara
65
66
printPortLetter (port);
66
67
SimpleFOCDebug::print ((int )pin);
67
68
SimpleFOCDebug::print (" ) on TIMER" );
68
- SimpleFOCDebug::print (getTimerNumber (timer) );
69
+ SimpleFOCDebug::print (timer_nr );
69
70
SimpleFOCDebug::print (" CH" );
70
71
SimpleFOCDebug::print (channel);
71
72
SimpleFOCDebug::print (" top " );
@@ -74,6 +75,50 @@ void setupPWM(int pin_nr, long pwm_frequency, bool active_high, SilabsDriverPara
74
75
75
76
76
77
78
+ void setupComplementaryPWM (int pin_nr, SilabsDriverParams* params, uint8_t index, TIMER_TypeDef* timer, uint8_t channel){
79
+ int8_t timer_nr = getTimerNumber (timer);
80
+ PinName pin_n = pinToPinName (pin_nr);
81
+ GPIO_Port_TypeDef port = getSilabsPortFromArduinoPin (pin_n);
82
+ uint32_t pin = getSilabsPinFromArduinoPin (pin_n);
83
+ switch (channel) {
84
+ case 0 :
85
+ GPIO->TIMERROUTE [timer_nr].ROUTEEN |= GPIO_TIMER_ROUTEEN_CCC0PEN;
86
+ GPIO->TIMERROUTE [timer_nr].CDTI0ROUTE = (port << _GPIO_TIMER_CDTI0ROUTE_PORT_SHIFT)
87
+ | (pin << _GPIO_TIMER_CDTI0ROUTE_PIN_SHIFT);
88
+ break ;
89
+ case 1 :
90
+ GPIO->TIMERROUTE [timer_nr].ROUTEEN |= GPIO_TIMER_ROUTEEN_CCC1PEN;
91
+ GPIO->TIMERROUTE [timer_nr].CDTI1ROUTE = (port << _GPIO_TIMER_CDTI1ROUTE_PORT_SHIFT)
92
+ | (pin << _GPIO_TIMER_CDTI1ROUTE_PIN_SHIFT);
93
+ break ;
94
+ case 2 :
95
+ GPIO->TIMERROUTE [timer_nr].ROUTEEN |= GPIO_TIMER_ROUTEEN_CCC2PEN;
96
+ GPIO->TIMERROUTE [timer_nr].CDTI2ROUTE = (port << _GPIO_TIMER_CDTI2ROUTE_PORT_SHIFT)
97
+ | (pin << _GPIO_TIMER_CDTI2ROUTE_PIN_SHIFT);
98
+ break ;
99
+ }
100
+
101
+ params->pins [index] = pin_nr;
102
+ params->timer [index] = timer;
103
+ params->channel [index] = channel;
104
+
105
+ SimpleFOCDebug::print (" DRV (Silabs): Pin " );
106
+ SimpleFOCDebug::print (pin_nr);
107
+ SimpleFOCDebug::print (" (P" );
108
+ printPortLetter (port);
109
+ SimpleFOCDebug::print ((int )pin);
110
+ SimpleFOCDebug::print (" ) on TIMER" );
111
+ SimpleFOCDebug::print (timer_nr);
112
+ SimpleFOCDebug::print (" CH" );
113
+ SimpleFOCDebug::print (channel);
114
+ SimpleFOCDebug::print (" COMP top " );
115
+ SimpleFOCDebug::println ((int )params->resolution );
116
+ }
117
+
118
+
119
+
120
+
121
+
77
122
bool isTimerUsed (TIMER_TypeDef* timer) {
78
123
for (int i=0 ;i<num_configured_motors;i++) {
79
124
for (int j=0 ;j<6 ;j++) {
@@ -139,9 +184,29 @@ void initTimer(TIMER_TypeDef* timer, long pwm_frequency, SilabsDriverParams* par
139
184
140
185
141
186
142
- // if( !pwm_frequency || !_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
143
- // else pwm_frequency = _constrain(pwm_frequency, _PWM_FREQUENCY_MIN, _PWM_FREQUENCY_MAX);
144
- // params->pwm_frequency = pwm_frequency;
187
+
188
+ void initDeadTimeInsertion (TIMER_TypeDef* timer, long pwm_frequency, bool highside_active_high, bool lowside_active_high, SilabsDriverParams* params){
189
+ TIMER_InitDTI_TypeDef dtiInit = TIMER_INITDTI_DEFAULT;
190
+ dtiInit.enable = false ; // or true? need to check first PWM cycle for this
191
+ dtiInit.activeLowOut = !highside_active_high;
192
+ dtiInit.invertComplementaryOut = !lowside_active_high;
193
+ dtiInit.riseTime = params->dead_zone * params->resolution ; // divided by 2 for symmetric dead-time, times 2 due to up-down counting
194
+ if (dtiInit.riseTime > 64 ) dtiInit.riseTime = 64 ; // max dead-time is 64 counts (each side)
195
+ dtiInit.fallTime = dtiInit.riseTime ;
196
+ dtiInit.autoRestart = true ;
197
+ SimpleFOCDebug::print (" DRV (Silabs): Dead time " );
198
+ Serial.println (dtiInit.riseTime );
199
+ dtiInit.outputsEnableMask = TIMER_DTOGEN_DTOGCC0EN | TIMER_DTOGEN_DTOGCDTI0EN
200
+ | TIMER_DTOGEN_DTOGCC1EN | TIMER_DTOGEN_DTOGCDTI1EN
201
+ | TIMER_DTOGEN_DTOGCC2EN | TIMER_DTOGEN_DTOGCDTI2EN;
202
+ unsigned long long max = TIMER_MaxCount (timer) + 1 ;
203
+ CMU_Clock_TypeDef timer_clock = getTimerClock (timer);
204
+ dtiInit.prescale = (TIMER_Prescale_TypeDef)(CMU_ClockFreqGet (timer_clock) / pwm_frequency / 2 / max);
205
+ TIMER_InitDTI (timer, &dtiInit);
206
+ }
207
+
208
+
209
+
145
210
146
211
void * _configure1PWM (long pwm_frequency, const int pinA) {
147
212
SilabsDriverParams* params = new SilabsDriverParams ();
@@ -203,14 +268,20 @@ void* _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const
203
268
204
269
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) {
205
270
SilabsDriverParams* params = new SilabsDriverParams ();
271
+ int pins[6 ] = {pinA_h, pinA_l, pinB_h, pinB_l, pinC_h, pinC_l};
272
+ TIMER_TypeDef* timer = findFreeTimer (pins, 6 );
273
+ initTimer (timer, pwm_frequency, params);
274
+ // init using DTI
206
275
params->dead_zone = dead_zone;
207
- // TODO init using DTI if posssible
208
- // setupPWM(pinA_h, pwm_frequency, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 0);
209
- // setupPWM(pinB_h, pwm_frequency, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 2);
210
- // setupPWM(pinC_h, pwm_frequency, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 4);
211
- // setupPWM(pinA_l, pwm_frequency, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH, params, 1);
212
- // setupPWM(pinB_l, pwm_frequency, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH, params, 3);
213
- // setupPWM(pinC_l, pwm_frequency, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH, params, 5);
276
+ setupPWM (pinA_h, pwm_frequency, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 0 , timer, 0 );
277
+ setupPWM (pinB_h, pwm_frequency, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 2 , timer, 1 );
278
+ setupPWM (pinC_h, pwm_frequency, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, params, 4 , timer, 2 );
279
+ initDeadTimeInsertion (timer, pwm_frequency, SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH, SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH, params);
280
+ setupComplementaryPWM (pinA_l, params, 1 , timer, 0 );
281
+ setupComplementaryPWM (pinB_l, params, 3 , timer, 1 );
282
+ setupComplementaryPWM (pinC_l, params, 5 , timer, 2 );
283
+ TIMER_EnableDTI (timer, true );
284
+ TIMER_Enable (timer, true );
214
285
return params;
215
286
}
216
287
@@ -256,6 +327,14 @@ void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, vo
256
327
}
257
328
258
329
330
+ void _writeDutyCycle6PWM (float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void * params) {
331
+ // TODO: handle phase state
332
+ writeDutyCycle (dc_a, ((SilabsDriverParams*)params)->timer [0 ], ((SilabsDriverParams*)params)->channel [0 ]);
333
+ writeDutyCycle (dc_b, ((SilabsDriverParams*)params)->timer [2 ], ((SilabsDriverParams*)params)->channel [2 ]);
334
+ writeDutyCycle (dc_c, ((SilabsDriverParams*)params)->timer [4 ], ((SilabsDriverParams*)params)->channel [4 ]);
335
+ }
336
+
337
+
259
338
260
339
CMU_Clock_TypeDef getTimerClock (TIMER_TypeDef* timer) {
261
340
if (timer == TIMER0) return cmuClock_TIMER0;
0 commit comments