Running ADC triggered by TIMER1_COMPB

Hi,
I’m trying to run ADC on channel 0 triggered by TIMER1_COMPB.
Everything seem to work ok but basic arithmetics is not working and variables inside ISR and even main loop don’t get updated (x == 2 all the time)

Can somebody explain me why is it so? Even volatile variable was not changing…
Arduino UNO,
IDE v 1.8.6

Code:

#define SAMPLES_SIZE  205

const int adc_channel = 0;
const uint16_t t1_load = 0;

// 250 corresponds to 8kHz
const uint16_t t1_comp = 25000; 

uint16_t samples[SAMPLES_SIZE];
volatile uint8_t samplePos = 0;

static int x = 0;

void initADC() {
  // Init ADC free-run mode; f = ( 16MHz/prescaler ) / 13 cycles/conversion 
  ADMUX  = adc_channel; // Channel sel, right-adj, use AREF pin
  ADCSRA = _BV(ADEN)  | // ADC enable
           _BV(ADSC)  | // ADC start
           _BV(ADATE) | // Auto trigger
           _BV(ADIE)  | // Interrupt enable
           _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128:1 / 13 = 9615 Hz
  ADCSRB = _BV(ADTS2) | _BV(ADTS0);              // Timer/Counter1 Compare Match B
  DIDR0  = _BV(adc_channel); // Turn off digital input for ADC pin      
}

void initTimer() {
  // Reset Timer1 Control Reg A
  TCCR1A = 0;

// Set CTC mode
  TCCR1B &= ~(1 << WGM13);
  TCCR1B |= (1 << WGM12);

// Set prescaler to 8
  TCCR1B &= ~(1 << CS12);
  TCCR1B |= (1 << CS11);
  TCCR1B &= ~(1 << CS10);
  
// Reset Timer 1 and set compare value
  TCNT1 = t1_load;
  OCR1B = t1_comp;

// Enable Timer 1 compare interrupt
  TIMSK1 = (1 << OCIE1B);
}

void setup() {  
  cli();
  initADC();
  initTimer(); 
  sei();
  
  Serial.begin(115200);
}

void loop() {
  while(ADCSRA & _BV(ADIE)); // Wait for audio sampling to finish
  cli();
  x = x + 2;
  Serial.print(samples[0]);
  Serial.print("\t");
  Serial.println(x);
//  for (int i = 0; i < SAMPLES_SIZE; i++) {
//    Serial.println(samples[i]);
//  }
//  samplePos = 0;
  
  ADCSRA |= _BV(ADIE);       // Resume sampling interrupt
  sei();
}

ISR(ADC_vect) { 
  int16_t sample = ADC;

  samples[0] = sample;
//  samplePos++;
  ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off

  if(samplePos >= SAMPLES_SIZE) {
    ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off
  }
}

//ISR(TIMER1_COMPB_vect) {
//}

Thanks in advance

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

I've found the solution, it's strange since I enabled CTC mode, but it started to work normally as soon as I reset Timer 1:

ISR(TIMER1_COMPB_vect) { TCNT1 = 0; }

but it started to work normally as soon as I reset Timer 1:

It's not the resetting, but the uncommenting of the ISR block. I think you could leave it empty and the code would work.

Without the ISR code enabled, the compare interrupt vector jumps to some default memory location which if I remember correctly, resets the sketch.

cattledog: I think you could leave it empty and the code would work.

There is even a declaration for such things...

EMPTY_INTERRUPT(TIMER1_COMPB_vect);

There is even a declaration for such things…

EMPTY_INTERRUPT(TIMER1_COMPB_vect);

Nice. Definitely saves processor cycles over having an actual interrupt vector entered and exited.

Actually, I’m not certain that an interrupt needs to be enabled and for there to be any interrupt vector for the auto trigger of the ADC to function as long as you clear the interrupt flag in the ISR(ADC_vect)

// Enable Timer 1 compare interrupt
  //TIMSK1 = (1 << OCIE1B);
TIMSK1 = 0;
ISR(ADC_vect) {

  TIF1R =(1<<OCF1B); //clear compare match B interrupt flag
  int16_t sample = ADC;

  samples[0] = sample;
//  samplePos++;
  ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off

  if(samplePos >= SAMPLES_SIZE) {
    ADCSRA &= ~_BV(ADIE); // Buffer full, interrupt off
  }
}

I’m not sure if the flag clearing takes any fewer processor cycles than the EMPTY_INTERRUPT