This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Suggestions audio processing (Input ADC, buffer, DSP, output PWM)

Hello everyone, I am trying to implement audio processings algorithms with my nrf52DK.

What i need to do in order : 
1- Sample my audio signal ( It will be guitar sound ,so fmax= 1200 Hz , let's say fs=2400Hz  )
2- Push my sampe into a FIFO
3- Start my algorithm with data inside FIFO ( Low pass, high pass, phaser etc..)
4- Change the duty cycle of my pwm 
5- Go back to 1

Im starting with the SDK, i see many differents ways to use ADC and PWM (SAADC from what i saw in documentations).


So i wouldike to know if you have any suggestion on :

  1. What's the best way to configure my ADC to 2.4Khz ?
  2. I see in SADC example that a ADC buffer aldready exist, but i wonder how it work. When the SAADC interrupt, is it when the SAADC sample a single value or a n=buffer_size value ?
  3. I see in pwm examples that it work with sequences, but i do not want a sequence to be played, i just wouldlike to ouptut a pwm signal with a duty cycle proportionnal to my values. Should i use a sequence of 1 value and then change the value ?

How can i make my pwm and SAADC synchronized, i mean doing the five steps above in order (in SAADC interrupt) ?

Thanks a lot, any help is welcomed :) 

    1. Use a TIMER to trigger the SAADC's sample task. This is already set-up in the SAADC example in the SDK, you just need to change the frequency of the TIMER. 

    2. The SAADC uses EasyDMA to transfer the sampled values into the buffer with the address written to RESULT.PTR of size RESULT.MAXCNT. With only one channel enabled you the EVENTS_END will fire after you have triggered the sample task 'n' times, and 'n' samples have been transferred to RAM, where 'n' is RESULT.MAXCNT
      If you enable more than one channel each triggered sample task will take a number of samples equal to the number of enabled channels. 

    3. Yes, you can do that.
      But just using a few samples in a sequence will offload your CPU quite a bit, without sacrificing the latency too much. If you're going to do any sort of DSP on the sampled signals you will probably operate on fixed-width buffers anyways so you might as well use a PWM sequence for playback and save the overhead of manually updating each sample at 2.4kHz.  If you're going to have any BLE activity concurrently with PWM you will need to use sequencing or else you'll drop some of the PWM samples. 
      With buffer size of 24 you'll get 10ms latency at a sample rate of 2.4kHz, add a few ms of DSP per buffer and you should still be under 20ms, who I believe is deemed good enough for most audio application. 
  • OK i think i understood for 1 and 2, thanks a lot.
    Concerning the PWM, you advise me to use a sequence (with the length of my buffer size for exemple), and to update the values periodically (inside the SAADC interrupt ? or using separate timer).
    Thanks

  • You can use a separate TIMER to control the triggering of the PWM's TASKS_SEQSTART[n] task. This task starts outputting a sequence of PWM samples on the selected pin. 

    The idea is to find how much time is required to process the SAADC samples and update the PWM sequence in RAM, and then to fire the PWM regularly based on this offset in time. You can, for example, start the second TIMER on the SAADC's END event, and have it trigger the PWM sequence start task after x amount of time. 

    All TIMER's run on the same clock source so there's no drift between the individual TIMER peripherals. 

    You really have to read the PWM — Pulse width modulation spec and PWM driver API ref, and try out the PWM Driver Example

Related