Stopping Timer and starting it again.

Hello,

I have Arduino Due and I faced cruel that I am stuck in for days… I have launched Timer (TC0, 0) and ADC is triggered by Timer. I nead to stop Timer (and ADC as well) after a number of samples, do calculations and start it again to read another batch of data. However, I cannot manage to solve this batch reading issue. With UNO, I used to read data (with interrupts) and meanwhile run while in loop function, but now it does not work - controller just stucks. Is there something specific to DUE? How to handle such issue, where one has to read data by starting ADC and Timer → stop reading → do calculations → Start reading again etc.

#define   SMP_RATE         140000UL 
#define   CLK_MAIN       84000000UL
#define   TMR_CNTR       CLK_MAIN / (2 * SMP_RATE)

const int sampleQty = 64;
double samples[sampleQty];
double samples2[sampleQty];
int currSample;
volatile int isr_counter = 0;
volatile int dur, nowT;
TcChannel *t;

void setup_pio_TIOA0 () { // Configure Ard pin 2 as output from TC0 channel A (copy of trigger event)
	PIOB->PIO_PDR = PIO_PB25B_TIOA0 ;  // disable PIO control
	PIOB->PIO_IDR = PIO_PB25B_TIOA0 ;   // disable PIO interrupts
	PIOB->PIO_ABSR |= PIO_PB25B_TIOA0 ;  // switch to B peripheral
}

void timerConfig() {
	pmc_enable_periph_clk(ID_TC0); // enable timer 0, chan 0.

	TcChannel *pTcChan = &(TC0->TC_CHANNEL)[0];  // get TC0, chan 0 pointer.
	pTcChan->TC_CCR = TC_CCR_CLKDIS; // disable TC clock.
	pTcChan->TC_IDR = 0xFFFFFFFF; // disable interrupts.
	pTcChan->TC_SR; // clear status register.
 
	pTcChan->TC_CMR =	TC_CMR_TCCLKS_TIMER_CLOCK1 |  // use TCLK1 (prescale by 2, so 42MHz).
						TC_CMR_WAVE | // // waveform mode.
						TC_CMR_WAVSEL_UP_RC | // RC as threshold for PWM. 
						TC_CMR_EEVT_XC0 | // external events from XC0.
						TC_CMR_ACPA_CLEAR | 
						TC_CMR_ACPC_CLEAR |
						TC_CMR_BCPB_CLEAR |
						TC_CMR_BCPC_CLEAR;
	pTcChan->TC_RA = TMR_CNTR / 2;  // counter resets on RC.
	pTcChan->TC_RC = TMR_CNTR; // square wave.
	pTcChan->TC_CMR = (pTcChan->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ;  // set clear and set from RA and RC compares
	
	setup_pio_TIOA0();
}

void adcConfig() {
	pmc_enable_periph_clk(ID_ADC); // enable ADC.
	adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST); // dar paž?t d?l šito parametr?.
	NVIC_EnableIRQ (ADC_IRQn);   // enable ADC interrupt vector.
	
	ADC->ADC_IDR = 0xFFFFFFFF; 
	ADC->ADC_CGR = 0x15555555; 
	ADC->ADC_COR = 0x00000000; 
	adc_disable_all_channel(ADC);

	adc_enable_interrupt(ADC, ADC_IER_EOC7); // enable EOC7 interrupt.
	adc_enable_channel(ADC, ADC_CHANNEL_7);
	adc_enable_channel(ADC, ADC_CHANNEL_6);
	adc_configure_trigger(ADC, ADC_TRIG_TIO_CH_0, 0);
}

void ADC_Handler(void) {
	if ((ADC->ADC_ISR & ADC_ISR_EOC7) && (ADC->ADC_ISR & ADC_ISR_EOC6)) {
		int val = *(ADC->ADC_CDR + 7);
		samples[currSample] = val - 2048;
		val = *(ADC->ADC_CDR + 6);
		samples2[currSample] = val - 2048;
		currSample += 1;
		if (currSample == sampleQty) {dur = micros() - nowT; currSample = 0; TC_Stop(TC0, 0);} 
	}
	isr_counter += 1;
}

void setup() {
    Serial.begin(115200);
	adcConfig();	
	timerConfig();
	t = &(TC0->TC_CHANNEL)[0];

	isr_counter = 0;
} 

void loop() {
	delay(100);
	
	// how to avoid serial commands and do that continuously?
        // I used to do like while (!sample_buf_full); 
        // and sample_buf_full would be changed in ADC ISR somewhere (being a volatile variable).
	while (Serial.available()) {
		uint8_t a = Serial.read();
		if (a == 'x') {
			TC_Start(TC0, 0);
		} else {
			for (int i = 0; i < sampleQty; i++) {Serial.print(samples[i]); Serial.print("  "); Serial.println(samples2[i]);}
		}
	}
}

Appreciate for your help.

Why do you need to use timers and interrupts at all?

...R

Thanks for your reply .

The main reason is that I need to read/capture ultrasonic frequencies (up to 5 or 6 mics). Simple analogread, as far as I have tested, does not provide required sampling freq., so I have to use this approach. I might use adc in free runninh mode, but I am not sure whether I will be able to solve this batch reading issue as well... Do you have any ideas for this? Thanks alot. P.S. with ultrasonic freq. I mean 40KHz sound waves

I think the ADC can only capture about 10k samples per second at full 10bit precision. Read the Atmel datasheet for the details.

You need at least 80ksps to capture one 40kHz signal. You say you want to collect data from 5 or 6 microphones.

The timers are not going to solve this problem.

On the other hand if you want to detect 40,000 digital events per second on a digital I/O pin that should be easily possible.

...R