Dependencies:   mbed

main.cpp

Committer:
bobanderson
Date:
2011-02-16
Revision:
0:7c70badd2847
Child:
1:ecca38babc13

File content as of revision 0:7c70badd2847:

/*  Bob Anderson   (bob.anderson.ok@gmail.com)

This program...

   1) Uses AnalogIn but speeds it up by setting
      the ADC clock to 12MHz (13MHz is max from spec sheet)
      
   2) Produces a histogram of deviations around a center
      value that is determined at the beginning of a run
      by a "vote" taken from three successive readings.
      
   3) Introduces a "glitch" suppression method that appears
      to be effective.
      
With a 100nf capacitor from the analog pin to ground and
a reasonably low impedance source ( < 5K ) and glitch suppression
enabled, the LPC1768/9 onboard analog to digital converter subsystem
becomes quite useable.  Without the capacitor and glitch suppression,
it is not a reliable ADC --- it is glitch prone, even with the
cleanest of inputs.  This program will help you determine for
yourself whether that statement is true.  Play with it.

*/

#include "mbed.h"
#include "Serial.h"
#include "AnalogIn.h"

Serial pc( USBTX, USBRX );

AnalogIn ain( p20 );

#define NUM_SAMPLES 1000000
#define HGRAM_MAX_INDEX 60
int histoGram[ HGRAM_MAX_INDEX + 1 ];

int glitchCount = 0;
bool glitchSuppressionWanted = false;

void setADCclockToMaxConversionRate(void);
int glitchSuppressedAnalogIn( void );

int max( int a, int b ) {
    if ( a > b ) return a;
    return b;
}

int min( int a, int b ) {
    if ( a < b ) return a;
    return b;
}

// middle( a, b, c ) returns true if a is between b and c
bool middle( int a, int b, int c ) {
    return (a <= max(b,c)) && (a >= min(b,c));
}

int main() {

    int referenceValue;
    int delta;
    int newValue;
    
    // Speedup the AnalogIn conversion rate by readjusting
    // the ADC clock to 12 MHz (assuming SystemCoreClock = 96MHz)
    setADCclockToMaxConversionRate();
    
    while(1) {
    
        printf( "\nPress the s key to start stats gathering\n" );
        printf( "Press the g key to toggle glitch suppression...\n" );
        bool waitingForKeyInput = true;
        
        while ( waitingForKeyInput ){
            switch (pc.getc()) {
              case 'g':
              case 'G': 
                glitchSuppressionWanted = ! glitchSuppressionWanted;
                if ( glitchSuppressionWanted )
                  printf( "...glitch suppression on...\n" );
                else
                  printf( "...glitch suppression off...\n" );
                break;
              case 's':
              case 'S': waitingForKeyInput = false;
            }
        }
        
        // Establish center point for histogram by taking three readings
        // and selecting the one in the middle as the reference value around
        // which deviations will be calculated.
        int value1 = ain.read_u16() >> 4;
        int value2 = ain.read_u16() >> 4;
        int value3 = ain.read_u16() >> 4;
   
        if ( middle(value1,value2,value3) ) 
            referenceValue = value1;
        else if ( middle(value2,value1,value3) )
            referenceValue = value2;
        else
            referenceValue = value3;
    
        printf( "\nreferenceValue: %d   value1: %d   value2: %d   value3: %d\n",
            referenceValue, value1, value2, value3 );
        printf( "\n...now gathering...\n\n" );
             
        // Clear the histogram array.
        for ( int k = 0; k <= HGRAM_MAX_INDEX; k++ ) histoGram[k] = 0;
        
        glitchCount = 0;
             
        for ( int i = 0; i < NUM_SAMPLES; i++ ) {
            newValue = glitchSuppressedAnalogIn();
            delta = newValue - referenceValue + (HGRAM_MAX_INDEX / 2);
            if ( delta < 0 ) histoGram[0]++;
            else if ( delta > HGRAM_MAX_INDEX ) histoGram[HGRAM_MAX_INDEX]++;
            else histoGram[delta]++;
        }
        
        // Output histoGram
        for ( int j = 0; j <= HGRAM_MAX_INDEX; j++ ) {
            printf( "%4d %8d\n", j, histoGram[j] );
        }
        
        printf( "glitchCount: %d\n", glitchCount );
    }
}

void setADCclockToMaxConversionRate(void) {
    // Set pclk = cclk / 4  (pclk = 96Mhz/4 = 24Mhz)
    LPC_SC->PCLKSEL0 &= ~(0x3 << 24); // Clear bits 25:24   
        
    // software-controlled ADC settings
    LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected
              | (1 << 8 )    // CLKDIV: ADCCLK = PCLK / (CLKDIV + 1) (12MHz)
              | (0 << 16)    // BURST: 0 = software control 
              | (0 << 17)    // CLKS: not applicable 
              | (1 << 21)    // PDN: 1 = operational
              | (0 << 24)    // START: 0 = no start
              | (0 << 27);   // EDGE: not applicable}
    return;
}

int glitchSuppressedAnalogIn( void ) {
    int v1,v2,delta;
    
    v1 = ain.read_u16() >> 4;
    if ( ! glitchSuppressionWanted ) return v1;
    
    // While this has the possiblity of never returning,
    // the probability of that is vanishingly small.  We assume
    // that we will eventually find two successive readings that are
    // within the tolerance band --- i.e., no glitch
    while(1){
        v2 = ain.read_u16() >> 4;
        delta = v1 - v2;
        if ( (delta > -10) && (delta < 10)) return (v1+v2)/2;
        v1 = v2;
        glitchCount++;
    }
}