yeah sure, here the code with the freerunning mode:
/*** DEFINES */
#define SND 3 /* PORTD0 */
#define LED 13
#define POT_A A4 /* ADC1 */
#define PRESCALER 1 /* 1 8 64 256 1024 */
#define SAMPLERATE 20000
#define TIMER_INTERVAL (uint16_t)((1000.f/(float)SAMPLERATE) / (1000.f/((float)F_CPU/(float)PRESCALER))) /* in 1/(F_CPU/PRESCALER) units */
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // ClearBIt -> 0
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // SetBIt -> 1
#endif
/* DEFINES end. */
/*** GLOBALS */
uint8_t ledStatus = 0;
uint32_t ledAcc = 0;
uint8_t sndStatus = 0;
uint32_t sndAcc = 0;
#define FIXFREQ 1000.0
uint32_t potAcc = 0;
uint16_t pota16;
/* GLOBALS end. */
void setup(){
pinMode(LED, OUTPUT);
pinMode(SND, OUTPUT);
pinMode(POT_A, INPUT);
TCNT1 = 0; // clear timer counter
TCCR1A = 0b11000000; // select the compare match A to set flag on match
TCCR1B = 0b00001000; /* CTC1 is set, so the timer will reset on compare match */
OCR1A = TIMER_INTERVAL; // set output compare value
TIMSK1 = 0b00000010; // enable timer compare match A interrupt
#if PRESCALER == 1
TCCR1B |= 0b00000001;
#elif PRESCALER == 8
TCCR1B |= 0b00000010;
#elif PRESCALER == 64
TCCR1B |= 0b00000011;
#elif PRESCALER == 256
TCCR1B |= 0b00000100;
#elif PRESCALER == 1024
TCCR1B |= 0b00000101;
#endif
// // set ADC prescale to 128, slows ADC samplerate, lightweight
// sbi(ADCSRA,ADPS2) ;
// sbi(ADCSRA,ADPS1) ;
// sbi(ADCSRA,ADPS0) ;
// free running adc
cbi(ADCSRB, ADTS3);
cbi(ADCSRB, ADTS2);
cbi(ADCSRB, ADTS1);
cbi(ADCSRB, ADTS0);
sbi(ADCSRA, ADSC); // kickstart conversion for the ADC
sei(); // enable interrupts
}
void loop(){
}
ISR (TIMER1_COMPA_vect){
sndAcc++;
if(sndAcc <= (uint32_t)(((float)SAMPLERATE / FIXFREQ) / 2.f) ){
PORTD |= 0b00000001; // digitalWrite(SND, 1);
}
else{
PORTD &= 0b11111110; // digitalWrite(SND, 0);
}
if(sndAcc >= (uint32_t)((float)SAMPLERATE / FIXFREQ) ){
sndAcc = 0;
}
if(ledAcc == (uint32_t)((float)SAMPLERATE / 2.f) ){ /* flipping led's state 2times per second */
ledAcc = 0;
ledStatus = !ledStatus;
digitalWrite(LED, ledStatus);
}
else{
ledAcc++;
}
if(potAcc == (uint32_t)((float)SAMPLERATE / 30.f) ){ /* reading pot value 30 times per second */
potAcc = 0;
pota16 = analogRead(POT_A);
}
else{
potAcc++;
}
}
I'm also using direct port addressing to flip the sound pin. Didn't seem to make a difference either, the bulk of the delay is in the analogRead()
inside the ISR that deals with a D/A Conversion complete interrupt, you can lower the global flag , and so any time timeout interrupts will still get through while you are doing stuff with your sample you just read.
not sure I understood this one, I tried doing it like that, but I get the feeling that's not what you meant:
if(potAcc == (uint32_t)((float)SAMPLERATE / 30.f) ){ /* reading pot value 30 times per second */
potAcc = 0;
cli(); /* disable global interrupt flag */
pota16 = analogRead(POT_A);
}
else{
potAcc++;
}