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
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
Generated on Thu Jul 14 2022 10:27:31 by 1.7.2