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.

Dependents:   KL25Z_FFT_Demo test_armmath KL25Z_FFT_Demo_tony KL25Z_FFT_Demo_tony ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FastAnalogIn_LPC11UXX.cpp Source File

FastAnalogIn_LPC11UXX.cpp

00001 #if defined(TARGET_LPC11UXX) || defined (TARGET_LPC11XX)
00002 
00003 #include "FastAnalogIn.h"
00004 static inline int div_round_up(int x, int y)
00005 {
00006     return (x + (y - 1)) / y;
00007 }
00008 
00009 #define LPC_IOCON0_BASE (LPC_IOCON_BASE)
00010 #define LPC_IOCON1_BASE (LPC_IOCON_BASE + 0x60)
00011 #define MAX_ADC_CLK     4500000
00012 
00013 #ifdef TARGET_LPC11UXX
00014 static const PinMap PinMap_ADC[] = {
00015     {P0_11, ADC0_0, 0x02},
00016     {P0_12, ADC0_1, 0x02},
00017     {P0_13, ADC0_2, 0x02},
00018     {P0_14, ADC0_3, 0x02},
00019     {P0_15, ADC0_4, 0x02},
00020     {P0_16, ADC0_5, 0x01},
00021     {P0_22, ADC0_6, 0x01},
00022     {P0_23, ADC0_7, 0x01},
00023     {NC   , NC    , 0   }
00024 };
00025 #else
00026 static const PinMap PinMap_ADC[] = {
00027     {P0_11, ADC0_0, 2},
00028     {P1_0 , ADC0_1, 2},
00029     {P1_1 , ADC0_2, 2},
00030     {P1_2 , ADC0_3, 2},
00031     // {P1_3 , ADC0_4, 2}, -- should be mapped to SWDIO only
00032     {P1_4 , ADC0_5, 1},
00033     {P1_10, ADC0_6, 1},
00034     {P1_11, ADC0_7, 1},
00035     {NC   , NC    , 0}
00036 };
00037 #endif
00038 
00039 static int channel_usage[8] = {0,0,0,0,0,0,0,0};
00040 
00041 
00042 
00043 FastAnalogIn::FastAnalogIn(PinName pin, bool enabled)
00044 {
00045     ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
00046     if (ADCnumber == (uint32_t)NC)
00047         error("ADC pin mapping failed");
00048     
00049     //Seriously software people, can't you guys never keep the namings the same?
00050     #ifdef TARGET_LPC11UXX
00051     datareg = (uint32_t*) (&LPC_ADC->DR0 + ADCnumber);
00052     #else
00053     datareg = (uint32_t*) (&LPC_ADC->DR[ADCnumber]);
00054     #endif
00055     
00056     // Power up ADC
00057     LPC_SYSCON->PDRUNCFG &= ~ (1 << 4);
00058     LPC_SYSCON->SYSAHBCLKCTRL |= ((uint32_t)1 << 13);
00059  
00060     #ifdef TARGET_LPC11UXX
00061     uint32_t pin_number = (uint32_t)pin;
00062     __IO uint32_t *reg = (pin_number < 32) ? (__IO uint32_t*)(LPC_IOCON0_BASE + 4 * pin_number) : (__IO uint32_t*)(LPC_IOCON1_BASE + 4 * (pin_number - 32));
00063     #else
00064     uint32_t offset = (uint32_t)pin & 0xff; 
00065     __IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + offset); 
00066     #endif
00067 
00068  
00069     // set pin to ADC mode
00070     *reg &= ~(1 << 7); // set ADMODE = 0 (analog mode)
00071  
00072     uint32_t clkdiv = div_round_up(SystemCoreClock, MAX_ADC_CLK) - 1;
00073  
00074     LPC_ADC->CR = (LPC_ADC->CR & 0xFF)      // keep current channels
00075                 | (clkdiv << 8) // max of 4.5MHz
00076                 | (1 << 16)     // BURST = 1, hardware controlled
00077                 | ( 0 << 17 );  // CLKS = 0, we stick to 10 bit mode
00078     
00079     pinmap_pinout(pin, PinMap_ADC);
00080 
00081     //Enable channel
00082     running = false;
00083     enable(enabled);
00084 
00085 }
00086 
00087 void FastAnalogIn::enable(bool enabled)
00088 {
00089     //If currently not running
00090     if (!running) {
00091         if (enabled) {
00092             //Enable the ADC channel
00093             channel_usage[ADCnumber]++;
00094             LPC_ADC->CR |= (1<<ADCnumber);
00095             running = true;
00096         } else
00097             disable();
00098     }
00099 }
00100 
00101 void FastAnalogIn::disable( void )
00102 {
00103     //If currently running
00104     if (running) {
00105         channel_usage[ADCnumber]--;
00106         
00107         if (channel_usage[ADCnumber]==0)
00108             LPC_ADC->CR &= ~(1<<ADCnumber);
00109     }
00110     running = false;
00111 }
00112 
00113 unsigned short FastAnalogIn::read_u16( void )
00114 {
00115     unsigned int retval;
00116     //If object is enabled return current value of datareg
00117     if (running)
00118         retval = *datareg;
00119  
00120     //If it isn't running, enable it and wait until new value is written to datareg
00121     else {
00122         //Force a read to clear done bit, enable the ADC channel
00123         retval = *datareg;
00124         enable();
00125         //Wait until it is converted
00126         while(1) {
00127             retval = *datareg;
00128             if ((retval>>31) == 1)
00129                 break;
00130         }
00131         //Disable again
00132         disable();
00133     }
00134     
00135     //Do same thing as standard mbed lib, unused bit 0-3, replicate 4-7 in it
00136     retval &= ~0xFFFF003F;
00137     retval |= (retval >> 6) & 0x003F;
00138     return retval;
00139 }
00140 #endif //defined TARGET_LPC11UXX