Wim van der Vegt
/
Spiker
Test program for Spikes when measuring 2 channels in Timer1/MAT1:0 triggering mode.
main.cpp
- Committer:
- wvd_vegt
- Date:
- 2012-10-31
- Revision:
- 2:74fd179377d9
- Parent:
- 1:b6dcd0de2a17
File content as of revision 2:74fd179377d9:
#include "mbed.h" #include "ADC/adc.h" //NOTE Baudrate 115200 // Writes a . and flahes led 2 after each conversion of 1000 points (see MAX_SAMPLES) // // A spike is a point that deviates more that SpikeAmplitude of it neighbours (now 128). // // Measured on AD0 and AD1 without anything connected (so a nice humm). // // ADC Code that makes the difference is 'ADC adc(SAMPLE_RATE,1);' // Without it I had spikes (altough not now hen testing). // // ADC Code by sblandford (see ADC Folder). It is not used but // certainly initializes something i missed. // // Currently code runs nice with or without the ADC line! (but in my larger // program the ADC line DID make the difference. // // This 'cure' only worked in combination with timer1/mat1:0 triggering // Using ADC:Read Fails (no matter how timer), as did teh GPDMA based code // (Timer that schedules 2 channel DMA transfers at each interrupt). //NOTE This Value can be changed to alter the detection criteria. #define SpikeAmplitude 128 DigitalOut myled1(LED1); DigitalOut myled2(LED2); //We'll be using the Usb Serial port Serial usb(USBTX, USBRX); //tx, rx //------------------------------------------------------------------------------ //----Hardware Arrays. //------------------------------------------------------------------------------ //Define ADC array, Note p18 is used as DAC! AnalogIn adcs[5] = {AnalogIn(p15), AnalogIn(p16), AnalogIn(p17), AnalogIn(p19), AnalogIn(p20)}; //Define DAC array AnalogOut dac[1] = {AnalogOut(p18)}; //------------------------------------------------------------------------------ //----ALL ADC Methods //------------------------------------------------------------------------------ #define XTAL_FREQ 12000000 //NOTE The Number of samples per call. #define MAX_SAMPLES 1000 //NOTE Only used for the statement below, the sample-rate is 1ms or lower (by skipping points). #define SAMPLE_RATE 150000 //NOTE THIS LINE CURES THE SPIKES !! ADC adc(SAMPLE_RATE,1); //Current Skip Rate Index. (not important, left in to keep code identical) //Basically it allows me to skip points 'automatically' and thus have a varying sample time. static int adc_rate = 0; //Start with every 10th point, end with every point. (not important, left in to keep code identical) static int adc_rates[2] = {1, 1}; //Stop with first skip rate at sample 5. -1 is forever. (not important, left in to keep code identical) static int adc_skippoint[2] = {-1, -1}; //Always start with a sample. (not important, left in to keep code identical) static int adc_skip = 1; //Results and Timestamps unsigned long Samples0[MAX_SAMPLES]; unsigned long Samples1[MAX_SAMPLES]; unsigned long Timing01[MAX_SAMPLES]; Timer adc_stamper; //Timestamping Samples. Timer match_timing; //Total Sampling Time. //------------------------------------------------------------------------------ //----CID_TIMER (MAT1.0 Based ADC Triggering) //------------------------------------------------------------------------------ volatile uint32_t timer1hits = 0; // timer1 stops when timer1hits==imer1loop uint32_t match = 500; // 0.5ms (2Mhz/1000) uint32_t prescaler = 96-1; // 96Mhz/96 = 1Mhz //See http://mbed.org/forum/mbed/topic/1965/?page=1#comment-10043 //Manually start a conversion (and cause an interrupt). //NOTE: CLKDIV can be change to alter the ADC Clock. #define CLKDIV 1UL #define START_CONVERSION_NOW(ch) \ LPC_ADC->ADCR=(0x1<<24)|(1UL<<21)|(CLKDIV<<8)|ch;\ NVIC_EnableIRQ(ADC_IRQn);\ LPC_ADC->ADINTEN = 0x3 //Trigger ADC on falling edge of MAT1:0 (and have it cause an interrupt). #define START_CONVERSION_TIMED(ch) \ LPC_ADC->ADCR=(0x6<<24)|(1UL<<21)|(CLKDIV<<8)|ch;\ NVIC_EnableIRQ(ADC_IRQn);\ LPC_ADC->ADINTEN = 0x3;\ LPC_TIM1->TCR=0;\ LPC_TIM1->TCR=1 extern "C" void Adc_IRQHandler(void) __irq { //LPC_TIM1->MR0 = match-1; //* Reload MR0 does not seem to be neccesary. LPC_TIM1->IR = 0x1UL; //* Re-eanbled Timing01[timer1hits]=adc_stamper.read_us(); //TODO Toggle Channel Mask (01 to 01 in ADCR). // Take twice the number of samples at half the sampling time // So 2000 samples (1000+1000) at 0.5ms -> 1000 pairs in 1 sec. switch (LPC_ADC->ADSTAT & 0xFF) { case 0x01: Samples0[timer1hits] = LPC_ADC->ADDR0;// adc[0]; START_CONVERSION_NOW(0x02); break; case 0x02: Samples1[timer1hits] = LPC_ADC->ADDR1;// adc[1]; START_CONVERSION_TIMED(0x01); //Skip Samples to lower rates. Change adc_rate to change sample rate. adc_skip--; if (adc_skip==0) { if (adc_skippoint[adc_rate]!=-1 && timer1hits==adc_skippoint[adc_rate]) { adc_rate++; } //Reload adc_skip adc_skip = adc_rates[adc_rate]; timer1hits++; } if (timer1hits==MAX_SAMPLES) { match_timing.stop(); NVIC_DisableIRQ(ADC_IRQn); LPC_TIM1->TCR = 0x00; // Disable Timer } break; } } //******************************* //NOTE: Timer1 Driven ADC. // // Works but way to fast!! // // Did not work previously because connected // to the wrong IRQ (should be the adc one). // // Skips 1 usec every 2*10 samples. //******************************* int Measure() { int spikes=0; // Enable the ISR vector NVIC_SetVector(ADC_IRQn, (uint32_t)&Adc_IRQHandler); // Set PCLK_TIMER1 // PCLK_TIMER1 = CCLK/1 96M/1 = 96MHz LPC_SC->PCLKSEL0 &= ~(3UL << 4); // Clear bits LPC_SC->PCLKSEL0 |= (1UL << 4); // Set bit LPC_SC->PCONP |= 1 << 2; // Power on Timer 1 LPC_TIM1->TCR = 0x2UL; // Reset and set to timer mode //NOTE match-2 is to much (seems like a clock is off somehwere). LPC_TIM1->CTCR = 0x0UL; // Connect to prescaler LPC_TIM1->PR = prescaler; // Prescale -> 1Mhz LPC_TIM1->MR0 = match-1; // Match count for 5mS (we toggle so end up with half) LPC_TIM1->MCR = 2; // Reset TCR to zero on match //See http://mbed.org/forum/mbed/topic/1965/?page=1#comment-10043 LPC_TIM1->EMR = (3UL<<4)|1; // Make MAT1.0 toggle (see START_CONVERSION_TIMED MACRO). // veg - ADC Max Clock = 13MHz. One conversion takes 65cycles so 200Khz Sampling frequency! // For nice exact values for a single conversion we need the ADC Clock to be a 65 fold (So overclock). // Power up the ADC and set PCLK LPC_SC->PCLKSEL0 &= ~(3UL << 16); // PCLK = CCLK/4 96M/4 = 24MHz LPC_SC->PCONP |= (1UL << 12); // Power on ADC LPC_ADC->ADCR |= (1UL << 21) | (CLKDIV<<8); // * Enable ADC & Set Divider Sample Rate 24Mhz / CLKDIV+1 // Set the pin functions to ADC LPC_PINCON->PINSEL1 &= ~(3UL << 14); // P0.23, Mbed p15. (AD0) LPC_PINCON->PINSEL1 |= (1UL << 14); LPC_PINCON->PINSEL1 &= ~(3UL << 16); // P0.24, Mbed p16. (AD1) LPC_PINCON->PINSEL1 |= (1UL << 16); memset(Samples0, 0, sizeof(Samples0)); memset(Samples1, 0, sizeof(Samples1)); // Enable the ADC, 12MHz, ADC0.0, ADC0.1 -> Macro/Defines! // LPC_ADC->ADCR = (1UL << 21) | (1UL << 8) | (3UL << 0); //Reset Test Variable. timer1hits = 0; //Reset Skip Rate. adc_rate = 0; adc_skip = 1; // We start with a sample! adc_stamper.reset(); adc_stamper.start(); match_timing.reset(); match_timing.start(); START_CONVERSION_TIMED(0x01); //Pause until timer stops. while (LPC_TIM1->TCR==1) { wait(0.001); } //LPC_ADC->ADCR &= ~(7UL << 24); // Clear ADC Start bits -> Macro/Defines! int elapsed = match_timing.read_us(); match_timing.stop(); adc_stamper.stop(); for (int i=1; i < MAX_SAMPLES-1; i++) { int lv = (Samples0[i-1]>>4) & 0xFFF; int cv = (Samples0[i+0]>>4) & 0xFFF; int nv = (Samples0[i+1]>>4) & 0xFFF; if (((cv >= lv + SpikeAmplitude) && (cv >= nv + SpikeAmplitude)) || ((cv <= lv - SpikeAmplitude) && (cv <= nv - SpikeAmplitude))) { usb.printf("\r\nSpike on Channel AD%d @ %d [%04u] [%04u] [%04u]\r\n", 0, i, lv, cv, nv); spikes++; } } for (int i=1; i < MAX_SAMPLES-1; i++) { int lv = (Samples1[i-1]>>4) & 0xFFF; int cv = (Samples1[i+0]>>4) & 0xFFF; int nv = (Samples1[i+1]>>4) & 0xFFF; if (((cv >= lv + SpikeAmplitude) && (cv >= nv + SpikeAmplitude)) || ((cv <= lv - SpikeAmplitude) && (cv <= nv - SpikeAmplitude))) { usb.printf("\r\nSpike on Channel AD%d @ %d [%04u] [%04u] [%04u]\r\n", 1, i, lv, cv, nv); spikes++; } } //NOTE Powering the ADC ON/OFF does not seem to be neccesary. LPC_ADC->ADCR |= (1UL << 21); // * Disable ADC LPC_SC->PCONP |= (1UL << 12); // * Power off ADC match_timing.reset(); return spikes; } int main() { usb.baud(115200); while (1) { myled1=false; if (Measure()!=0) { myled1 = !myled1; } myled2 = !myled2; usb.printf("."); wait_ms(100); myled2 = !myled2; } }