I'm new to microcontroller programming and to arduino, so please excuse me if I'm asking obvious things.
I'm trying to generate a TLL pulse with a predefined length after the ADC has detected the defined threshold. So far succeeded to detect the threshold (I used this post as an example Example of driving ADC and DAC from timer for regular sampling - Arduino Due - Arduino Forum).
For my application it is important to minimize the jitter between the detection of the threshold and the generation of the pulse. So I can't use arduionos functions.
My idea was to use a second timer to define the length of the pulse. In the datasheet I've found that I can restart the timer after a number of counts defined in the TC_RC register, which should raise a flag in the TC_SRx in the CPCS byte.
So I definde the value of RC to correspond to a 75 ms long pulse but the CPCS bit appears to never be set. The code compiles and I don't get any errors.
I've inserted the whole code here:
void setup()
{
Serial.begin (115200) ; // was for debugging
adc_setup () ; // setup ADC
pmc_enable_periph_clk (TC_INTERFACE_ID + 0*3+0) ; // clock the TC0 channel 0 (timer for the adc)
pmc_enable_periph_clk (TC_INTERFACE_ID + 0*3+1) ; // clock the TC0 channel 1 (timer for the pulse length)
TcChannel * t = &(TC0->TC_CHANNEL)[0] ; // pointer to TC0 registers for its channel 0
t->TC_CCR = TC_CCR_CLKDIS |TC_CCR_CLKEN; // disable internal clocking while setup regs
t->TC_IDR = 0xFFFFFFFF ; // disable interrupts
t->TC_SR ; // read int status reg to clear pending
t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // use TCLK1 (prescale by 2, = 42MHz)
TC_CMR_WAVE | // waveform mode
TC_CMR_WAVSEL_UP_RC | // count-up PWM using RC as threshold
TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output)
TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ;
t->TC_RC = 875 ; // counter resets on RC, so sets period in terms of 42MHz clockTC
t->TC_RA = 440 ; // roughly square wave
t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ; // set clear and set from RA and RC compares
t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; // re-enable local clocking and switch to hardware trigger source.
TcChannel * t1 = &(TC0->TC_CHANNEL)[1] ; // pointer to TC0 registers for its channel 1
t1->TC_CCR = TC_CCR_CLKDIS |TC_CCR_CLKEN; // disable internal clocking while setup regs
t1->TC_IER |= 0x10 ; // enable RC interrupt
//t1->TC_SR ; // read int status reg to clear pending
t1->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // use TCLK1 (prescale by 2, = 42MHz)
TC_CMR_WAVE | // waveform mode
TC_CMR_WAVSEL_UP_RC | // count-up PWM using RC as threshold
TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output)
TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR ;
t1->TC_RC = 300000000 ; // counter resets on RC, so sets period in terms of 13,88 Hz clock (for laser trigger)
t1->TC_RA = 440 ; // roughly square wave
t1->TC_CMR = (t1->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET ; // set clear and set from RA and RC compares
t1->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; // re-enable local clocking and switch to hardware trigger source.
setup_pio_TIOA0 () ; // drive Arduino pin 2 at 48kHz to bring clock out
pio_out_setup();
}
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 pio_out_setup()//set pin 23 as output
{
pmc_enable_periph_clk(ID_PIOA);
PIOA->PIO_MDDR = PIO_MDDR_P14;
PIOA->PIO_CODR = PIO_CODR_P14;
PIOA->PIO_OWER = PIO_OWER_P14;
PIOA->PIO_OER = PIO_OER_P14;
PIOA->PIO_PER = PIO_PER_P14;
}
void adc_setup ()
{
NVIC_EnableIRQ (ADC_IRQn) ; // enable ADC interrupt vector
ADC->ADC_IDR = 0xFFFFFFFF ; // disable interrupts
ADC->ADC_IER = 0x80 ; // enable AD7 End-Of-Conv interrupt (Arduino pin A0)
ADC->ADC_CHDR = 0xFFFF ; // disable all channels
ADC->ADC_CHER = 0x80 ; // enable just A0
ADC->ADC_CGR = 0x15555555 ; // All gains set to x1
ADC->ADC_COR = 0x00000000 ; // All offsets off
ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN ; // 1 = trig source TIO from TC0
ADC->ADC_EMR = 0x201; // generate an event when the data is higher than the threashold, raise flag after one event, compare all channels
ADC->ADC_CWR = ADC_CWR_HIGHTHRES(2000); //set threshold to 1.5 (12 Bit resolution)
}
void ADC_Handler (void)
{
if (ADC->ADC_ISR & ADC_ISR_COMPE) // ensure there was COMPE flag raised
{
PIOA->PIO_SODR=PIO_SODR_P14;
//Serial.println(TC0->TC_CHANNEL[1].TC_SR,BIN);
while(TC0->TC_CHANNEL[1].TC_SR&0x10==0)
{//v= TC0->TC_CHANNEL[1].TC_CV;
}
PIOA->PIO_CODR= PIO_CODR_P14;
}
}
void loop()
{
}
on the scope I see the following result (see the attached image)
the yellow signal is intup of the ADC channel and the blue is the TTL pulse. it is 70 ns wide and I want 75ms.
I'll appreciate if anybody has an idea how to get the timer going or any other suggestions how to generate such a pulse.
Thanks alot for your help!