Sampling audio with interrupt

Hello,

I need to sample audio for my spectrum analyazer. For now i’m sampling my data in de loop routine with the following code:

for (i = 0; i < 128; i++)
{
    val = analogRead(A5);
    data[i] = val/4;
    im[i] = 0;
}

what i’m trying to achieve is to sample in an interrupt routine. I already setup my timer interrupt on 9600Hz.

void timer2Init()
{
  cli();//stop interrupts
  
  //set timer1 interrupt at 1Hz
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 9600Hz increments
  OCR2A = 207;// = (16*10^6) / (9600*8) - 1 (must be <256) +-207,3333333
  // turn on CTC mode
  TCCR2B |= (1 << WGM21);
  // Set CS21 for 8 prescaler
  TCCR2B |= (1 << CS21);  
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);
  
  sei();//allow interrupts
}
ISR(TIMER2_COMPA_vect)//interrupt routine
  {
     val = analogRead(A5);
     data[i] = val/4;
     im[i] = 0;
  }

Now my question is how do I exchange my data that i sampled to my loop routine?
I’m also not sure if i’m sampling correctly…

any help will be greatly appreciated!

A 100us delay in an interrupt routine doesn't seem a great idea to me. Break up analogRead into its components.

You don't exchange any data - it's global.

9600 Hz is a 600 usec pulse. That's 1,666.7 clock cycles. A 10 bit analog read takes 105.

You could make that pulse with BlinkWithoutDelay using micros() instead of millis() and still be able to run code that does something with that pulse "at the same time".

With BWD, don't forget to change the 2 longs to unsigned longs and put UL at the end of every unsigned long constant value.

9600 Hz is a 600 usec pulse.

?

What are you doing with the array im[] ?

1/9600 = 104uS, so your 600uS seems a little off.

Maybe an external ADC would be better. http://www.digikey.com/product-detail/en/MCP3008-I%2FP/MCP3008-I%2FP-ND/319422

With SPI set for 2 Mhz, and 24 clocks for a sample, takes 12uS. Couple more uS for setting SS low & high.

AWOL:

9600 Hz is a 600 usec pulse.

?

I musta hit a wrong button. I should know it’s just over 1/10000, 0.0001, 100 usecs.

There is still 16 cycles per usec and 8-bit ADC takes… errrr… never done that.

CrossRoads: What are you doing with the array im[] ?

1/9600 = 104uS, so your 600uS seems a little off.

im[ ] array stands for Imaginary[ ]. I need real number arguments and Imaginary number arguments to put in a fix_fft functions to execute a FFT. Because i only need the real data i set up 0 into de im array. 128 stands for the numbers of samples.

thanks for the fast replies!

AWOL: A 100us delay in an interrupt routine doesn't seem a great idea to me. Break up analogRead into its components.

You don't exchange any data - it's global.

I'm not realy sure what u mean with "breaking up analogRead into its components" Are you talking about the ADCSRA, ADCSRB, ADMUX, ... registers?

I'm pretty sure that you can get 8 bit ADC faster than 10 bit was discussed a while back now.

You can set the ATmega328P's ADC into a freerunning mode that will start a new conversion as soon as the old one completes. With an x64 prescaler clock I have been able to push the ADC to about 19,200 samples per second. That's probably the fastest you're going to get while maintaining reasonable accuracy. It complicates your code a little bit though since you have to use the ISR(ADC_vect) to process the output.

Could you set a 1 byte flag in the ISR and act on that in turn in loop()?