How to implement a Timer Capture for measuring a PWM signal on the Particle Xenon

I need to measure a PWM signal ranging from 1 to 1023 us, using the Xenon. The nRF52840 has a number of internal timers, with Capture register, that are suited for this task, better than using GPIO interrupt and the microsecond counter.

1 - Does anyone know of examples of how to use one of the timers, mixing it with the particle firmware libs / deviceOS, i am thinking in terms of interrupt handling and processor events.

2 - Where to find an overview of what timers and resources are consumed and used by the particle deviceOS

Any inputs are welcome :slight_smile:

/Morten

But all but one are already used by the device OS.

There were some discussions about exposing timer(s) to application code in regards to the SparkTimerInterval and ParticleSoftSerial libraries with @avtolstoy so he might know which timer is not used.

1 Like

2 - Where to find an overview of what timers and resources are consumed and used by the particle deviceOS

Currently, the timers are assigned to the following peripeherals:

Timer0: Softdevice
Timer1: Radio
Timer2: Serial1
Timer3: Serial2
Timer4: NFC

Timer2 and Timer4 should be available for user applications, as long as Serial1 or NFC are not in use accordingly. Additionally on Xenons Timer3 should be available, unless Serial2 is used.

4 Likes

Thanks, i managed to hack my way through, using a mix of interrupt disable/enables and the microsecond counter.
I can’t quite figure where to start, if i need to mix my own peripheral driver modules with the device OS.

Depending on how you are planning to access Nordic peripherals (e.g. nrfx API or straight register manipulation) there might be some additional things to take care of since in case of nrfx there will be two instances of the SDK living in both the system DeviceOS and the user part, the main thing you are probably looking for is attachInterruptDirect to take control over the interrupt handling of a particular peripheral.

1 Like

:point_up_2::point_up_2::point_up_2: This would be great stuff for a tutorial :+1:

@rickkas7 or @bsatrom any “urge” to jump in :wink:
Would also help getting SparkIntervalTimer unstuck (@peekay123?)

4 Likes

This project from Wojtek can also be used as a reference and in particular the usage of nrfx I2S driver: https://github.com/suda/ps-01/blob/master/src/synth/synth.cpp

3 Likes

@avtolstoy, the Wojtek’s work is not really useful for nRF timers. I need to dig up the interrupt vectors I would need to attach to along with understanding the nrfx_timer class functions. Not sure how all this will work above the HAL.

Well, I didn’t say that project would show an example of timers specifically, but it does show the general approach to using the nrfx API and taking over the interrupts. If we are talking about timers specifically, perhaps using nrf API (simple inline function interface over the peripheral registers) would be even simpler.

2 Likes

I put a bookmark on this post because I knew I’d get back to it eventually!!

I have some example code of PPI working with Timer4 and GPIOTE to generate accurate pulses without processor intervention. In my case I was using it to generate an 88µS pulse for DMX over RS-485. It would obviously have to be modified a little for PWM but the general concept is there.

I did a whole writeup comparing an ISR vs PPI based. Though ISR works it may not work in processor heavy applications or if you have strict timing requirements!

I’m just excited I got it working especially with everything else going on in the system/Device OS.

Hopefully you guys find it useful. :slight_smile:

4 Likes

@jaredwolff, great work! This will help me resolve some issues I have setting up the PPI. Note that Timer4 is only useable on the Xenon as per the following:

// TIMER0: Softdevice
// TIMER1: Radio
// TIMER2: NFC
// TIMER3: Usart (Serial1)
// TIMER4: Usart (Serial2 on Xenon, cannot be used on Argon or Boron because of NCP)

Timer2 can be used if NFC is not required and is turned OFF with NFC.off(). I’m not sure if it might be a good idea to do a Serial2.end() to disable the USART on Xenon prior to using Timer4. Thanks for sharing!

1 Like

@peekay123 ahh gotcha. Did this change since @avtolstoy’s comment above? I’ll have to edit my blog post. :sweat_smile:

@jaredwolff, I am going off comments in @rickkas7’s latest ADCDMA library: