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")

Files at this revision

API Documentation at this revision

Comitter:
Sissors
Date:
Thu May 09 17:46:32 2013 +0000
Child:
1:575f4d2d6e9c
Commit message:
v0.1
;

Changed in this revision

FastAnalogIn.cpp Show annotated file Show diff for this revision Revisions of this file
FastAnalogIn.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FastAnalogIn.cpp	Thu May 09 17:46:32 2013 +0000
@@ -0,0 +1,136 @@
+#include "FastAnalogIn.h"
+static inline int div_round_up(int x, int y)
+{
+    return (x + (y - 1)) / y;
+}
+
+const PinMap FastAnalogIn::PinMap_ADC[] = {
+    {P0_23, ADC0_0, 1},
+    {P0_24, ADC0_1, 1},
+    {P0_25, ADC0_2, 1},
+    {P0_26, ADC0_3, 1},
+    {P1_30, ADC0_4, 3},
+    {P1_31, ADC0_5, 3},
+    {P0_2,  ADC0_7, 2},
+    {P0_3,  ADC0_6, 2},
+    {NC,    NC,     0}
+};
+
+int FastAnalogIn::channel_usage[] = {0};
+
+
+FastAnalogIn::FastAnalogIn(PinName pin, bool enabled)
+{
+    ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
+    if (ADCnumber == (uint32_t)NC)
+        error("ADC pin mapping failed");
+    datareg = (uint32_t*) (&LPC_ADC->ADDR0 + ADCnumber);
+
+    // ensure power is turned on
+    LPC_SC->PCONP |= (1 << 12);
+    // set PCLK of ADC to /1
+    LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
+    LPC_SC->PCLKSEL0 |= (0x1 << 24);
+    uint32_t PCLK = SystemCoreClock;
+
+    // calculate minimum clock divider
+    //  clkdiv = divider - 1
+    uint32_t MAX_ADC_CLK = 13000000;
+    uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1;
+    // Set the clkdiv
+    LPC_ADC->ADCR &= ~(255<<8);
+    LPC_ADC->ADCR |= clkdiv<<8;
+
+    //Enable ADC:
+    LPC_ADC->ADCR |= 1<<21;
+
+    //Enable burstmode, set start as zero
+    LPC_ADC->ADCR |= 1<<16;
+    LPC_ADC->ADCR &= ~(7<<24);
+
+    //Map pins
+    pinmap_pinout(pin, PinMap_ADC);
+
+    //Enable channel
+    running = false;
+    enable(enabled);
+
+};
+
+FastAnalogIn::~FastAnalogIn(void)
+{
+    disable();
+}
+
+
+void FastAnalogIn::enable(bool enabled)
+{
+    //If currently not running
+    if (!running) {
+        if (enabled) {
+            //Enable the ADC channel
+            channel_usage[ADCnumber]++;
+            LPC_ADC->ADCR |= (1<<ADCnumber);
+            running = true;
+        } else
+            disable();
+    }
+};
+
+void FastAnalogIn::disable( void )
+{
+    //If currently running
+    if (running) {
+        channel_usage[ADCnumber]--;
+        
+        if (channel_usage[ADCnumber]==0)
+            LPC_ADC->ADCR &= ~(1<<ADCnumber);
+    }
+    running = false;
+};
+
+unsigned short FastAnalogIn::read_u16( void )
+{
+    //If object is enabled return current value of datareg
+    if (running ) {
+        unsigned int retval = *datareg;
+        retval = retval >> 4;
+        retval = retval & 4095;
+        return retval;
+    }
+    //If it isn't running, enable it and wait until new value is written to datareg
+    else {
+        //Force a read to clear done bit, enable the ADC channel
+        volatile unsigned int retval = *datareg;
+        enable();
+        //Wait until it is converted
+        while(1) {
+            wait_us(1);
+            retval = *datareg;
+            if ((retval>>31) == 1)
+                break;
+        }
+        
+        //Do a second conversion since first one always fails for some reason
+        while(1) {
+            wait_us(1);
+            retval = *datareg;
+            if ((retval>>31) == 1)
+                break;
+        }
+
+        //Disable again
+        disable();
+        retval = retval >> 4;
+        retval = retval & 4095;
+        return retval;
+    }
+
+
+};
+
+float FastAnalogIn::read( void )
+{
+    unsigned short value = read_u16();
+    return (float)value/4095;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FastAnalogIn.h	Thu May 09 17:46:32 2013 +0000
@@ -0,0 +1,83 @@
+#ifndef FASTANALOGIN_H
+#define FASTANALOGIN_H
+
+/*
+ * Includes
+ */
+#include "mbed.h"
+#include "pinmap.h"
+
+#ifndef TARGET_LPC1768
+    #error "Target not supported"
+#endif
+
+/** A class that is similar to AnalogIn, only faster
+*
+* AnalogIn does a single conversion when you read a value (actually several conversions and it takes the median of that).
+* This library has all used ADC channels running automatically in the background, and if you read a value it will immediatly return the last converted value.
+*
+* You can use several FastAnalogIn objects per ADC pin, and several ADC pins at the same time. Using more ADC pins will decrease the conversion rate.
+* If you need to generally convert one pin very fast, but sometimes also need to do AD conversions on another pin, you can disable the ADC channel and still read its value.
+* Only now it will block until conversion is complete, so more like the regular AnalogIn library. Of course you can also disable an ADC channel and enable it later.
+*
+* It does not play nicely with regular AnalogIn objects, so use only this library or only AnalogIn. Also currently only LPC1768 is supported.
+*/
+class FastAnalogIn {
+
+public:
+     /** Create a FastAnalogIn, connected to the specified pin
+     *
+     * @param pin AnalogIn pin to connect to
+     * @param enabled Enable the ADC channel (default = true)
+     */
+    FastAnalogIn( PinName pin, bool enabled = true );
+    
+    ~FastAnalogIn( void );
+    
+    /** Enable the ADC channel
+    *
+    * @param enabled Bool that is true for enable, false is equivalent to calling disable
+    */
+    void enable(bool enabled = true);
+    
+    /** Disable the ADC channel
+    *
+    * Disabling unused channels speeds up conversion in used channels. 
+    * When disabled you can still call read, that will do a single conversion (actually two since the first one always returns 0 for unknown reason).
+    * Then the function blocks until the value is read. This is handy when you sometimes needs a single conversion besides the automatic conversion
+    */
+    void disable( void );
+    
+    /** Returns the raw value
+    *
+    * @param return Unsigned integer with converted value
+    */
+    unsigned short read_u16( void );
+    
+    /** Returns the scaled value
+    *
+    * @param return Float with scaled converted value to 0.0-1.0
+    */
+    float read( void );
+    
+    /** An operator shorthand for read()
+    */
+    operator float() {
+        return read();
+    }
+
+    
+private:
+    static const PinMap PinMap_ADC[9];
+    static int channel_usage[8];
+    
+    bool running;    
+    char ADCnumber;
+    uint32_t *datareg;
+    
+    
+
+
+};
+
+#endif
\ No newline at end of file