From 81d6c2537fe0be0996f26902958e1c53c88cf00b Mon Sep 17 00:00:00 2001 From: James Devine Date: Fri, 3 Jun 2016 18:59:58 +0200 Subject: [PATCH] --- Cosmic Pi ADCtrigger | 161 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 Cosmic Pi ADCtrigger diff --git a/Cosmic Pi ADCtrigger b/Cosmic Pi ADCtrigger new file mode 100644 index 0000000..769857b --- /dev/null +++ b/Cosmic Pi ADCtrigger @@ -0,0 +1,161 @@ +/*notes to Team Cosmic Pi +I just got this working in Cosimo's lab using a TTi TG5011 LXI function generator and a Tektronix TDS2024 scope. +It took a lot of fine tuning to get the right buffer read out, so that the rising edge can be consistently seen in the samples. +The buffer index (i.e. how many buffers back in time you need to go) will definitely change based on the rest of the code, but the principle is here +Don't forget that we're interleaving channels 1 and 2, therefore the nth sample is channel 1 and the n+1th sample is channel 2 etc. and if we're reading out 50, it's actually 25 from channel A etc. +Also note that the ADC seems to top out (4096) around 2.3V, I was expecting 3.3V, so maybe there's another setting to tweak here. + +If you are testing this code independently here are your parameters for connection: +Set up a SAW wave, with a vertical rising edge, then monotonically decreasing +Amplitude (max) 2.3V, never above 3.3V or you'll cook the DUE +Frequency - Tested up to 10Hz, our specification max is 5 Hz. +Pinouts: +Saw wave goes in to D2 (trigger), A6 and A7 (ADC channels) + +Unexplained - when I hook up one of the ADC inputs to 0V it crashes. I think it might be due to an offset somewhere in the signal generator/earthing mess/laptop USB grounding... + */ + +volatile int bufn,obufn,pbufn,qbufn; //obuf, pbuf and qbuf are the previously filled buffers (i.e. going backwards in time) +uint16_t buf[8][256]; // 8 buffers of 256 readings +bool bufferdump=false; //flag for event, when the buffer should be dumped + +void ADC_Handler(){ // move DMA pointers to next buffer + int f=ADC->ADC_ISR; + if (f&(1<<27)){ + //memcpy(lastbuf, buf[bufn], 256); + bufn=(bufn+1)&7; + ADC->ADC_RNPR=(uint32_t)buf[bufn]; + ADC->ADC_RNCR=256; + } +} + +void setup(){ + Serial.begin(115200); //serial output at high speed, tested up to 10Hz with this configuration (for a minute or two) + //while(!Serial); + pmc_enable_periph_clk(ID_ADC); + adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST); + + + REG_ADC_MR = 0x10380080; // Free run as fast as you can - ADC settings as current core Cosmic Pi code + REG_ADC_CHER = 3; // Channels 0 and 1 + + NVIC_EnableIRQ(ADC_IRQn); + ADC->ADC_IDR=~(1<<27); + ADC->ADC_IER=1<<27; + ADC->ADC_RPR=(uint32_t)buf[0]; // DMA buffer + ADC->ADC_RCR=256; + ADC->ADC_RNPR=(uint32_t)buf[1]; // next DMA buffer + ADC->ADC_RNCR=256; + bufn=obufn=1; + ADC->ADC_PTCR=1; + ADC->ADC_CR=2; + TimersStart(); +} + +//Routine copied out of Cosmic Pi core code, only using one interrupt on Pin 2 for this test. +void TimersStart() { + + uint32_t config = 0; + + // Set up the power management controller for TC0 and TC2 + + pmc_set_writeprotect(false); // Enable write access to power management chip + pmc_enable_periph_clk(ID_TC0); // Turn on power for timer block 0 channel 0 + pmc_enable_periph_clk(ID_TC6); // Turn on power for timer block 2 channel 0 + + // Timer block zero channel zero is connected only to the PPS + // We set it up to load regester RA on each PPS and reset + // So RA will contain the number of clock ticks between two PPS, this + // value should be very stable +/- one tick + + config = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Select fast clock MCK/2 = 42 MHz + TC_CMR_ETRGEDG_RISING | // External trigger rising edge on TIOA0 + TC_CMR_ABETRG | // Use the TIOA external input line + TC_CMR_LDRA_RISING; // Latch counter value into RA + + TC_Configure(TC0, 0, config); // Configure channel 0 of TC0 + TC_Start(TC0, 0); // Start timer running + + TC0->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS; // Enable the load AR channel 0 interrupt each PPS + TC0->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS; // and disable the rest of the interrupt sources + NVIC_EnableIRQ(TC0_IRQn); // Enable interrupt handler for channel 0 + + // Timer block 2 channel zero is connected to the OR of the PPS and the RAY event + + config = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Select fast clock MCK/2 = 42 MHz + TC_CMR_ETRGEDG_RISING | // External trigger rising edge on TIOA1 + TC_CMR_ABETRG | // Use the TIOA external input line + TC_CMR_LDRA_RISING; // Latch counter value into RA + + TC_Configure(TC2, 0, config); // Configure channel 0 of TC2 + TC_Start(TC2, 0); // Start timer running + + TC2->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS; // Enable the load AR channel 0 interrupt each PPS + TC2->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS; // and disable the rest of the interrupt sources + NVIC_EnableIRQ(TC6_IRQn); // Enable interrupt handler for channel 0 + + // Set up the PIO controller to route input pins for TC0 and TC2 + + PIO_Configure(PIOC,PIO_INPUT, + PIO_PB25B_TIOA0, // D2 Input + PIO_DEFAULT); + + PIO_Configure(PIOC,PIO_INPUT, + PIO_PC25B_TIOA6, // D5 Input + PIO_DEFAULT); +} + +// Timer chip interrupt handlers try to get time stamps to within 4 system clock ticks + +static uint32_t displ = 0; // Display values in loop + +static uint32_t ppsfl = LOW, // PPS Flag boolean + rega0 = 0, // RA reg + stsr0 = 0, // Interrupt status register + ppcnt = 0; // PPS count + +// Handle the PPS interrupt in counter block 0 ISR + + +void TC0_Handler() { + + // This ISR is connected only to the PPS (Pulse Per Second) GPS event + // Each time this runs, set the flag to tell the TC6 ISR we have seen it + // This logic only works if the TC0 handler gets called before the TC6 handler + // hence the debug flag which I look at with a scope to be sure. + // I may introduce a small delay line to ensure this is true, so far it is. + + + rega0 = TC0->TC_CHANNEL[0].TC_RA; // Read the RA reg (PPS period) + stsr0 = TC_GetStatus(TC0, 0); // Read status and clear load bits + + //Custom code for read out of ADC on trigger is here + bufferdump=true; //set the buffer dump flag + Serial.println("trigint"); //announce trigger over serial + Serial.println(rega0); //write out the counter value (how many clock counts since last trigger) + Serial.print(bufn); //write out the ADC buffer position at the time of the trigger, note that the lab configuration with this code meant the rising edge was 2 buffers back from the one in use. +} + + +void loop(){ + if (bufferdump) { + Serial.println(" bufferdump"); //confirm this part of the code is running + + //obufn=(bufn+7)&7; //look in the previous buffer (n-1) + //pbufn=(bufn+6)&7; //look in the one before that (n-2) + qbufn=(bufn+5)&7; // and look in the buffer before that (n-3) + + //SerialUSB.write((uint8_t *)buf[obufn],512); // send it - 512 bytes = 256 uint16_t - this was the original code, converted to serialise and int the buffer for simplicity + Serial.println("n-2 buffer"); //the buffer index, i.e. qbufn + for (int s=0; s < 50; s++){ + Serial.print(int(s)); //sample index within buffer + Serial.print(' '); + Serial.println(int(buf[qbufn][s])); //print the value from the buffer + } + Serial.println(); + + + bufferdump = false;//reset flag + } + + } \ No newline at end of file