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. This slightly modified version allows NC pins.

Dependents:   Pinscape_Controller

Fork of FastAnalogIn by Erik -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FastAnalogIn_LPC408X.cpp Source File

FastAnalogIn_LPC408X.cpp

00001 #ifdef TARGET_LPC408X
00002 
00003 #include "FastAnalogIn.h"
00004 
00005 static inline int div_round_up(int x, int y)
00006 {
00007     return (x + (y - 1)) / y;
00008 }
00009 
00010 static const PinMap PinMap_ADC[] = {
00011     {P0_23, ADC0_0, 0x01},
00012     {P0_24, ADC0_1, 0x01},
00013     {P0_25, ADC0_2, 0x01},
00014     {P0_26, ADC0_3, 0x01},
00015     {P1_30, ADC0_4, 0x03},
00016     {P1_31, ADC0_5, 0x03},
00017     {P0_12, ADC0_6, 0x03},
00018     {P0_13, ADC0_7, 0x03},
00019     {NC   , NC    , 0   }
00020 };
00021 
00022 static int channel_usage[8] = {0,0,0,0,0,0,0,0};
00023 
00024 FastAnalogIn::FastAnalogIn(PinName pin, bool enabled)
00025 {
00026     ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
00027     if (ADCnumber == (uint32_t)NC)
00028         error("ADC pin mapping failed");
00029     datareg = (uint32_t*) (&LPC_ADC->DR[ADCnumber]);
00030 
00031     wait_us(1000); // wait for a short while before trying to initialize the ADC afer a reset (needed for those global instantiations just before main)
00032 
00033     // ensure power is turned on
00034     LPC_SC->PCONP |= (1 << 12);
00035 
00036     uint32_t PCLK = PeripheralClock;
00037 
00038     // calculate minimum clock divider
00039     //  clkdiv = divider - 1
00040     uint32_t MAX_ADC_CLK = 12400000;
00041     uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1;
00042     // Set the clkdiv
00043     LPC_ADC->CR &= ~(255<<8);
00044     LPC_ADC->CR |= clkdiv<<8;
00045 
00046     //Enable ADC:
00047     LPC_ADC->CR |= 1<<21;
00048 
00049     //Enable burstmode, set start as zero
00050     LPC_ADC->CR |= 1<<16;
00051     LPC_ADC->CR &= ~(7<<24);
00052 
00053     // must enable analog mode (ADMODE = 0)   ... ???  just copied from official LPC408X analogin_api.c
00054     __IO uint32_t *reg = (__IO uint32_t*) (LPC_IOCON_BASE + 4 * pin);
00055     *reg &= ~(1 << 7);
00056 
00057     //Map pins
00058     pinmap_pinout(pin, PinMap_ADC);
00059 
00060     //Enable channel
00061     running = false;
00062     enable(enabled);
00063 
00064 }
00065 
00066 void FastAnalogIn::enable(bool enabled)
00067 {
00068     //If currently not running
00069     if (!running) {
00070         if (enabled) {
00071             //Enable the ADC channel
00072             channel_usage[ADCnumber]++;
00073             LPC_ADC->CR |= (1<<ADCnumber);
00074             running = true;
00075         } else
00076             disable();
00077     }
00078 }
00079 
00080 void FastAnalogIn::disable( void )
00081 {
00082     //If currently running
00083     if (running) {
00084         channel_usage[ADCnumber]--;
00085         
00086         if (channel_usage[ADCnumber]==0)
00087             LPC_ADC->CR &= ~(1<<ADCnumber);
00088     }
00089     running = false;
00090 }
00091 
00092 unsigned short FastAnalogIn::read_u16( void )
00093 {
00094     volatile unsigned int retval;
00095     //If object is enabled return current value of datareg
00096     if (running ){
00097         retval = *datareg;
00098     //If it isn't running, enable it and wait until new value is written to datareg
00099     }else {
00100         //Force a read to clear done bit, enable the ADC channel
00101         retval = *datareg;
00102         enable();
00103         //Wait until it is converted
00104         while(1) {
00105             wait_us(1);
00106             retval = *datareg;
00107             if ((retval>>31) == 1)
00108                 break;
00109         }
00110         //Do a second conversion since first one always fails for some reason
00111         while(1) {
00112             wait_us(1);
00113             retval = *datareg;
00114             if ((retval>>31) == 1)
00115                 break;
00116         }
00117         //Disable again
00118         disable();
00119     }
00120     
00121     //Do same thing as standard mbed lib, unused bit 0-3, replicate 4-7 in it
00122     retval &= ~0xFFFF000F;
00123     retval |= (retval >> 8) & 0x000F;
00124     return retval;
00125 
00126 }
00127 #endif //defined TARGET_LPC408X
00128