Class similar to AnalogIn that uses burst mode to run continious background conversions so when the input is read, the last value can immediatly be returned.

Fork of FastAnalogIn by Erik -

Obsolete!

Has been already merged with Erik's original repository => take the original!

  • Added support for LPC4088.
  • Fixed linker error (missing definition of static member "channel_usage")

FastAnalogIn_KLXX.cpp

Committer:
humlet
Date:
2014-04-21
Revision:
5:55274430c8df
Parent:
3:a9b753c25073

File content as of revision 5:55274430c8df:

#ifdef TARGET_KLXX

#include "FastAnalogIn.h"
#include "clk_freqs.h"

#define MAX_FADC            6000000
#define CHANNELS_A_SHIFT    5

int FastAnalogIn::channel_usage[8] = {0,0,0,0,0,0,0,0};

FastAnalogIn::FastAnalogIn(PinName pin, bool enabled)
{
    ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
    if (ADCnumber == (ADCName)NC) {
        error("ADC pin mapping failed");
    }

    SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;

    uint32_t port = (uint32_t)pin >> PORT_SHIFT;
    SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);

    uint32_t cfg2_muxsel = ADC_CFG2_MUXSEL_MASK;
    if (ADCnumber & (1 << CHANNELS_A_SHIFT)) {
        cfg2_muxsel = 0;
    }
    
    // bus clk
    uint32_t PCLK = bus_frequency();
    uint32_t clkdiv;
    for (clkdiv = 0; clkdiv < 4; clkdiv++) {
        if ((PCLK >> clkdiv) <= MAX_FADC)
            break;
    }
    if (clkdiv == 4)                    //Set max div
        clkdiv = 0x7;

    ADC0->SC1[1] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));

    ADC0->CFG1 = ADC_CFG1_ADIV(clkdiv & 0x3)    // Clock Divide Select: (Input Clock)/8
               | ADC_CFG1_MODE(3)               // (16)bits Resolution
               | ADC_CFG1_ADICLK(clkdiv >> 2);  // Input Clock: (Bus Clock)/2

    ADC0->CFG2 = cfg2_muxsel            // ADxxb or ADxxa channels
               | ADC_CFG2_ADACKEN_MASK  // Asynchronous Clock Output Enable
               | ADC_CFG2_ADHSC_MASK;   // High-Speed Configuration

    ADC0->SC2 = ADC_SC2_REFSEL(0);      // Default Voltage Reference

    pinmap_pinout(pin, PinMap_ADC);

    //Enable channel
    running = false;
    enable(enabled);
}

void FastAnalogIn::enable(bool enabled)
{
    //If currently not running
    if (!running) {
        if (enabled) {
            //Enable the ADC channel
            ADC0->SC3 |= ADC_SC3_ADCO_MASK;       // Enable continuous conversion
            ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));  //Start conversion
            running = true;
        } else
            disable();
    }
}
 
void FastAnalogIn::disable( void )
{
    //If currently running
    if (running) {
        ADC0->SC3 &= ~ADC_SC3_ADCO_MASK;      // Disable continuous conversion
    }
    running = false;
}

uint16_t FastAnalogIn::read_u16()
{
    if (!running)
    {
        // start conversion
        ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));
        // Wait Conversion Complete
        while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
    }
    if(running && ((ADC0->SC1[0]&ADC_SC1_ADCH_MASK) != (ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)))))
    {
        running = false;
        enable();
        while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
    }
    // Return value
    return (uint16_t)ADC0->R[0];
}

#endif //defined TARGET_KLXX