Skip to content

Commit d27b9bf

Browse files
committed
Improved hardware PWM with frequency - still can't do >1 pin
1 parent f875e27 commit d27b9bf

File tree

1 file changed

+95
-16
lines changed

1 file changed

+95
-16
lines changed

targets/nrf5x/jshardware.c

Lines changed: 95 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ volatile bool hadEvent = false; // set if we've had an event we need to deal wit
7070
bool uartIsSending = false;
7171
bool uartInitialised = false;
7272

73+
JshPinFunction pinStates[JSH_PIN_COUNT];
74+
75+
76+
7377
/// Called when we have had an event that means we should execute JS
7478
void jshHadEvent() {
7579
hadEvent = true;
@@ -111,6 +115,32 @@ unsigned int getNRFBaud(int baud) {
111115
}
112116
}
113117

118+
static NO_INLINE void jshPinSetFunction_int(JshPinFunction func, uint32_t pin) {
119+
JshPinFunction fType = func&JSH_MASK_TYPE;
120+
JshPinFunction fInfo = func&JSH_MASK_INFO;
121+
switch (fType) {
122+
case JSH_NOTHING: break;
123+
#ifdef NRF52
124+
case JSH_TIMER1: NRF_PWM0->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin; break;
125+
case JSH_TIMER2: NRF_PWM1->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin; break;
126+
case JSH_TIMER3: NRF_PWM2->PSEL.OUT[fInfo>>JSH_SHIFT_INFO] = pin; break;
127+
#endif
128+
case JSH_USART1: if (fInfo==JSH_USART_RX) NRF_UART0->PSELRXD = pin;
129+
else NRF_UART0->PSELTXD = pin; break;
130+
default: assert(0);
131+
}
132+
}
133+
134+
static NO_INLINE void jshPinSetFunction(Pin pin, JshPinFunction func) {
135+
if (pinStates[pin]==func) return;
136+
// disconnect existing peripheral (if there was one)
137+
if (pinStates[pin])
138+
jshPinSetFunction_int(pinStates[pin], 0xFFFFFFFF);
139+
// connect new peripheral
140+
pinStates[pin] = func;
141+
jshPinSetFunction_int(pinStates[pin], pinInfo[pin].pin);
142+
}
143+
114144
#ifdef BLUETOOTH
115145
APP_TIMER_DEF(m_wakeup_timer_id);
116146

@@ -255,6 +285,8 @@ bool jshPinGetValue(Pin pin) {
255285

256286
// Set the pin state
257287
void jshPinSetState(Pin pin, JshPinState state) {
288+
// If this was set to be some kind of AF (USART, etc), reset it.
289+
jshPinSetFunction(pin, JSH_NOTHING);
258290
/* Make sure we kill software PWM if we set the pin state
259291
* after we've started it */
260292
if (BITFIELD_GET(jshPinSoftPWM, pin)) {
@@ -427,36 +459,79 @@ int jshPinAnalogFast(Pin pin) {
427459
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) {
428460
/* we set the bit field here so that if the user changes the pin state
429461
* later on, we can get rid of the IRQs */
430-
/* if (!jshGetPinStateIsManual(pin)) {
431-
BITFIELD_SET(jshPinSoftPWM, pin, 0);
432-
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
462+
#ifdef NRF52
463+
if (flags & JSAOF_FORCE_SOFTWARE) {
464+
#endif
465+
if (!jshGetPinStateIsManual(pin)) {
466+
BITFIELD_SET(jshPinSoftPWM, pin, 0);
467+
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
468+
}
469+
BITFIELD_SET(jshPinSoftPWM, pin, 1);
470+
if (freq<=0) freq=50;
471+
jstPinPWM(freq, value, pin);
472+
return JSH_NOTHING;
473+
#ifdef NRF52
433474
}
434-
BITFIELD_SET(jshPinSoftPWM, pin, 1);
435-
if (freq<=0) freq=50;
436-
jstPinPWM(freq, value, pin);
437-
return JSH_NOTHING;*/
438-
439-
NRF_PWM_Type *pwm = NRF_PWM0;
475+
JshPinFunction func = JSH_TIMER1 | JSH_TIMER_CH1;
476+
// FIXME: Search for free timers to use (based on freq as well)
477+
478+
NRF_PWM_Type *pwm;
479+
if ((func&JSH_MASK_TYPE) == JSH_TIMER1) pwm = NRF_PWM0;
480+
else if ((func&JSH_MASK_TYPE) == JSH_TIMER2) pwm = NRF_PWM1;
481+
else if ((func&JSH_MASK_TYPE) == JSH_TIMER3) pwm = NRF_PWM2;
482+
else { assert(0); return 0; };
440483
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
441-
uint32_t out_pins[NRF_PWM_CHANNEL_COUNT] = { pin, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED };
442-
nrf_pwm_pins_set(pwm, out_pins);
484+
jshPinSetFunction(pin, func);
443485
nrf_pwm_enable(pwm);
486+
487+
nrf_pwm_clk_t clk;
488+
if (freq<=0) freq = 1000;
489+
int counter = (int)(16000000.0 / freq);
490+
491+
if (counter<32768) {
492+
clk = NRF_PWM_CLK_16MHz;
493+
if (counter<1) counter=1;
494+
} else if (counter < (32768<<1)) {
495+
clk = NRF_PWM_CLK_8MHz;
496+
counter >>= 1;
497+
} else if (counter < (32768<<2)) {
498+
clk = NRF_PWM_CLK_4MHz;
499+
counter >>= 2;
500+
} else if (counter < (32768<<3)) {
501+
clk = NRF_PWM_CLK_2MHz;
502+
counter >>= 3;
503+
} else if (counter < (32768<<4)) {
504+
clk = NRF_PWM_CLK_1MHz;
505+
counter >>= 4;
506+
} else if (counter < (32768<<5)) {
507+
clk = NRF_PWM_CLK_500kHz;
508+
counter >>= 5;
509+
} else if (counter < (32768<<6)) {
510+
clk = NRF_PWM_CLK_250kHz;
511+
counter >>= 6;
512+
} else {
513+
clk = NRF_PWM_CLK_125kHz;
514+
counter >>= 7;
515+
if (counter>32767) counter = 32767;
516+
// Warn that we're out of range?
517+
}
518+
444519
nrf_pwm_configure(pwm,
445-
NRF_PWM_CLK_1MHz, NRF_PWM_MODE_UP, 32767 /* top value - 15 bits, not 16! */);
520+
clk, NRF_PWM_MODE_UP, counter /* top value - 15 bits, not 16! */);
446521
nrf_pwm_decoder_set(pwm,
447522
NRF_PWM_LOAD_INDIVIDUAL, // allow all 4 channels to be used
448523
NRF_PWM_STEP_TRIGGERED); // Only step on NEXTSTEP task
449524

450-
nrf_pwm_shorts_set(pwm, 0);
525+
/*nrf_pwm_shorts_set(pwm, 0);
451526
nrf_pwm_int_set(pwm, 0);
452527
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_LOOPSDONE);
453528
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND0);
454529
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_SEQEND1);
455530
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_STOPPED);
456-
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_STOPPED);
531+
nrf_pwm_event_clear(pwm, NRF_PWM_EVENT_STOPPED);*/
457532

458533
static uint16_t pwmValues[4];
459-
pwmValues[0] = 32767 - (uint16_t)(value*32767);
534+
pwmValues[func >> JSH_SHIFT_INFO] = counter - (uint16_t)(value*counter);
460535
nrf_pwm_loop_set(pwm, PWM_LOOP_CNT_Disabled);
461536
nrf_pwm_seq_ptr_set( pwm, 0, pwmValues);
462537
nrf_pwm_seq_cnt_set( pwm, 0, 4);
@@ -465,7 +540,8 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, Js
465540

466541
nrf_pwm_task_trigger(pwm, NRF_PWM_TASK_SEQSTART0);
467542
// nrf_pwm_disable(pwm);
468-
543+
return func;
544+
#endif
469545
} // if freq<=0, the default is used
470546

471547
void jshPinPulse(Pin pin, bool pulsePolarity, JsVarFloat pulseTime) {
@@ -599,6 +675,9 @@ void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
599675
inf->parity!=0, // TODO: ODD or EVEN parity?
600676
baud
601677
};
678+
// APP_UART_INIT will set pins, but this ensures we know so can reset state later
679+
jshPinSetFunction(inf->pinRX, JSH_USART1|JSH_USART_RX);
680+
jshPinSetFunction(inf->pinTX, JSH_USART1|JSH_USART_TX);
602681

603682
APP_UART_INIT(&comm_params,
604683
uart0_event_handle,

0 commit comments

Comments
 (0)