Skip to content

Commit b2cf69d

Browse files
committed
allow nRF51 to use up to 6 pwm pins
by using also NRF_TIMER2
1 parent 13664e7 commit b2cf69d

File tree

1 file changed

+79
-22
lines changed

1 file changed

+79
-22
lines changed

cores/nRF5/wiring_analog_nRF51.c

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,37 @@
2828
extern "C" {
2929
#endif
3030

31-
#define PWM_COUNT 3
31+
#define PWM_COUNT 6
3232
#define PIN_FREE 0xffffffff
3333

34+
struct PWMSrc {
35+
NRF_TIMER_Type* timer;
36+
bool used;
37+
};
38+
39+
struct PWMSrc srcs[2]={
40+
{NRF_TIMER1,false},
41+
{NRF_TIMER2,false}
42+
};
43+
3444
struct PWMContext {
3545
uint32_t pin;
3646
uint32_t value;
3747
uint32_t channel;
3848
uint32_t mask;
3949
uint32_t event;
50+
int src;
4051
};
4152

4253
static struct PWMContext pwmContext[PWM_COUNT] = {
43-
{ PIN_FREE, 0, 1, TIMER_INTENSET_COMPARE1_Msk, 1 },
44-
{ PIN_FREE, 0, 2, TIMER_INTENSET_COMPARE2_Msk, 2 },
45-
{ PIN_FREE, 0, 3, TIMER_INTENSET_COMPARE3_Msk, 3 }
54+
{ PIN_FREE, 0, 1, TIMER_INTENSET_COMPARE1_Msk, 1, 0 },
55+
{ PIN_FREE, 0, 2, TIMER_INTENSET_COMPARE2_Msk, 2, 0 },
56+
{ PIN_FREE, 0, 3, TIMER_INTENSET_COMPARE3_Msk, 3, 0 },
57+
{ PIN_FREE, 0, 1, TIMER_INTENSET_COMPARE1_Msk, 1, 1 },
58+
{ PIN_FREE, 0, 2, TIMER_INTENSET_COMPARE2_Msk, 2, 1 },
59+
{ PIN_FREE, 0, 3, TIMER_INTENSET_COMPARE3_Msk, 3, 1 }
4660
};
4761

48-
static int timerEnabled = 0;
49-
5062
static uint32_t adcReference = ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling;
5163
static uint32_t adcPrescaling = ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling;
5264

@@ -217,6 +229,18 @@ uint32_t analogRead( uint32_t ulPin )
217229
return mapResolution(value, resolution, readResolution);
218230
}
219231

232+
int getFreePwm() {
233+
for (int i = 0; i < PWM_COUNT; i++)
234+
if (pwmContext[i].pin == PIN_FREE) return i;
235+
return -1;
236+
}
237+
238+
int getPwmFromPin(uint32_t ulPin) {
239+
for (int i = 0; i < PWM_COUNT; i++)
240+
if (pwmContext[i].pin == ulPin||pwmContext[i].pin==PIN_FREE) return i;
241+
return -1;
242+
}
243+
220244
// Right now, PWM output only works on the pins with
221245
// hardware support. These are defined in the appropriate
222246
// pins_*.c file. For the rest of the pins, we default
@@ -229,24 +253,34 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue )
229253

230254
ulPin = g_ADigitalPinMap[ulPin];
231255

232-
if (!timerEnabled) {
233-
NVIC_SetPriority(TIMER1_IRQn, 3);
234-
NVIC_ClearPendingIRQ(TIMER1_IRQn);
235-
NVIC_EnableIRQ(TIMER1_IRQn);
256+
int pwm=getPwmFromPin(ulPin);
257+
struct PWMSrc* src=&srcs[pwmContext[pwm].src];
258+
NRF_TIMER_Type* pwmSrc=src->timer;
259+
260+
if (!src->used) {
236261

237-
NRF_TIMER1->MODE = (NRF_TIMER1->MODE & ~TIMER_MODE_MODE_Msk) | ((TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk);
262+
if (pwmSrc==NRF_TIMER1) {
263+
NVIC_SetPriority(TIMER1_IRQn, 3);
264+
NVIC_ClearPendingIRQ(TIMER1_IRQn);
265+
NVIC_EnableIRQ(TIMER1_IRQn);
266+
} else if (pwmSrc==NRF_TIMER2) {
267+
NVIC_SetPriority(TIMER2_IRQn, 4);
268+
NVIC_ClearPendingIRQ(TIMER2_IRQn);
269+
NVIC_EnableIRQ(TIMER2_IRQn);
270+
} else return;
271+
src->used = true;
238272

239-
NRF_TIMER1->BITMODE = (NRF_TIMER1->BITMODE & ~TIMER_BITMODE_BITMODE_Msk) | ((TIMER_BITMODE_BITMODE_08Bit << TIMER_BITMODE_BITMODE_Pos) & TIMER_BITMODE_BITMODE_Msk);
273+
pwmSrc->MODE = (pwmSrc->MODE & ~TIMER_MODE_MODE_Msk) | ((TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk);
240274

241-
NRF_TIMER1->PRESCALER = (NRF_TIMER1->PRESCALER & ~TIMER_PRESCALER_PRESCALER_Msk) | ((7 << TIMER_PRESCALER_PRESCALER_Pos) & TIMER_PRESCALER_PRESCALER_Msk);
275+
pwmSrc->BITMODE = (pwmSrc->BITMODE & ~TIMER_BITMODE_BITMODE_Msk) | ((TIMER_BITMODE_BITMODE_08Bit << TIMER_BITMODE_BITMODE_Pos) & TIMER_BITMODE_BITMODE_Msk);
242276

243-
NRF_TIMER1->CC[0] = 0;
277+
pwmSrc->PRESCALER = (pwmSrc->PRESCALER & ~TIMER_PRESCALER_PRESCALER_Msk) | ((7 << TIMER_PRESCALER_PRESCALER_Pos) & TIMER_PRESCALER_PRESCALER_Msk);
244278

245-
NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
279+
pwmSrc->CC[0] = 0;
246280

247-
NRF_TIMER1->TASKS_START = 0x1UL;
281+
pwmSrc->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
248282

249-
timerEnabled = true;
283+
pwmSrc->TASKS_START = 0x1UL;
250284
}
251285

252286
for (int i = 0; i < PWM_COUNT; i++) {
@@ -263,9 +297,9 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue )
263297

264298
pwmContext[i].value = ulValue;
265299

266-
NRF_TIMER1->CC[pwmContext[i].channel] = ulValue;
300+
pwmSrc->CC[pwmContext[i].channel] = ulValue;
267301

268-
NRF_TIMER1->INTENSET = pwmContext[i].mask;
302+
pwmSrc->INTENSET = pwmContext[i].mask;
269303

270304
break;
271305
}
@@ -276,7 +310,7 @@ void TIMER1_IRQHandler(void)
276310
{
277311
if (NRF_TIMER1->EVENTS_COMPARE[0]) {
278312
for (int i = 0; i < PWM_COUNT; i++) {
279-
if (pwmContext[i].pin != PIN_FREE && pwmContext[i].value != 0) {
313+
if (pwmContext[i].src==0&&pwmContext[i].pin != PIN_FREE /*&& pwmContext[i].value != 0*/) {
280314
NRF_GPIO->OUTSET = (1UL << pwmContext[i].pin);
281315
}
282316
}
@@ -285,8 +319,8 @@ void TIMER1_IRQHandler(void)
285319
}
286320

287321
for (int i = 0; i < PWM_COUNT; i++) {
288-
if (NRF_TIMER1->EVENTS_COMPARE[pwmContext[i].event]) {
289-
if (pwmContext[i].pin != PIN_FREE && pwmContext[i].value != 255) {
322+
if (pwmContext[i].src==0&&NRF_TIMER1->EVENTS_COMPARE[pwmContext[i].event]) {
323+
if (pwmContext[i].pin != PIN_FREE /*&& pwmContext[i].value != 255*/) {
290324
NRF_GPIO->OUTCLR = (1UL << pwmContext[i].pin);
291325
}
292326

@@ -295,6 +329,29 @@ void TIMER1_IRQHandler(void)
295329
}
296330
}
297331

332+
void TIMER2_IRQHandler(void)
333+
{
334+
if (NRF_TIMER2->EVENTS_COMPARE[0]) {
335+
for (int i = 0; i < PWM_COUNT; i++) {
336+
if (pwmContext[i].src==1&&pwmContext[i].pin != PIN_FREE /*&& pwmContext[i].value != 0*/) {
337+
NRF_GPIO->OUTSET = (1UL << pwmContext[i].pin);
338+
}
339+
}
340+
341+
NRF_TIMER2->EVENTS_COMPARE[0] = 0x0UL;
342+
}
343+
344+
for (int i = 0; i < PWM_COUNT; i++) {
345+
if (pwmContext[i].src==1&&NRF_TIMER2->EVENTS_COMPARE[pwmContext[i].event]) {
346+
if (pwmContext[i].pin != PIN_FREE /*&& pwmContext[i].value != 255*/) {
347+
NRF_GPIO->OUTCLR = (1UL << pwmContext[i].pin);
348+
}
349+
350+
NRF_TIMER2->EVENTS_COMPARE[pwmContext[i].event] = 0x0UL;
351+
}
352+
}
353+
}
354+
298355
#ifdef __cplusplus
299356
}
300357
#endif

0 commit comments

Comments
 (0)