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
http://forum.arduino.cc/index.php?topic=205096.0). 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!