Understanding code for 512 sample FFT


I’ve finally gotten a working FFT solution on the Due thanks to code posted by stimmer on Github. I am trying to digest what all of it does, and have been commenting the code in my testing repo.

I’m still unsure what the function of a few parts of stimmer’s code is. He does an FFT transform on 512 values in “out”. I’m aiming to abstract this to easily switch to other FFT sizes, but for simplicity I’d like to understand how to change it to size 128.

If anyone can shed any light on any questions below, I would greatly appreciate the help.

Here are the relevant parts that collect the sound samples and put them into an array for the FFT functions to use:

volatile int bufn,obufn;
uint16_t buf[5][128];
q15_t out[640];
q15_t outsq[1280];

void ADC_Handler(){
  int f=ADC->ADC_ISR;
  if (f&(1<<27)){
int nn=0;
void loop(){
  int bb=bufn+1;if(bb==5)bb=0;
  uint16_t *q=buf[0]+128*bb;
  for(int j=0;j<512;j++){
    int t=(*q++)-2048;
  // rest of code ...

My questions:

  • Why are the 512 values being copied into an array of 5 arrays of 128, instead of perhaps a single array of 512 values? Maybe there is a 128 limit related to the chip, but the only documentation I can find isn’t friendly enough for me to know.
  • The while loop exits when obufn and bufn are not equal, after which they are made to be equal immediately. Printing these values each time loop() runs yields 3, 4, 0, 1, 2, 3, 4, 0… It seems the “out” array is being filled with 512 values each time loop() runs, which seems to be based on only 128 new readings. Am I misunderstanding this?
  • Is the “-2048” related to the 512 quantity of readings, or possibly adjusting the reading to center on 0?
  • What is the purpose of “out[j]=t<<4” instead of just “out[j]=t”?
  • Does the “int nn=0;” have any apparent purpose?

Thank you very much for your time.


I may have just gotten it working for 128 samples… still doing testing. I had previously erroneously changed the “128” values in the following snipped to my FFT size divided by 4, so “32” in this case. That may have been causing the strange output I was observing where every fourth reading was smaller than expected.

ADC->ADC_RCR=128; // Receive Counter Register
  ADC->ADC_RNPR=(uint32_t)buf[1]; // Receive Next Pointer Register
  ADC->ADC_RNCR=128; // Receive Next Counter Register

I’m still looking to understand the questions I asked, especially number 3. Thanks!