Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of scoreLight_Advanced by
adc.cpp
00001 /* mbed Library - ADC 00002 * Copyright (c) 2010, sblandford 00003 * released under MIT license http://mbed.org/licence/mit 00004 */ 00005 #include "mbed.h" 00006 #include "adc.h" 00007 00008 00009 ADC adc(ADC_SAMPLE_RATE, 1); 00010 00011 ADC *ADC::instance; 00012 00013 ADC::ADC(int sample_rate, int cclk_div) 00014 { 00015 00016 int i, adc_clk_freq, pclk, clock_div, max_div=1; 00017 00018 //Work out CCLK 00019 adc_clk_freq=CLKS_PER_SAMPLE*sample_rate; 00020 int m = (LPC_SC->PLL0CFG & 0xFFFF) + 1; 00021 int n = (LPC_SC->PLL0CFG >> 16) + 1; 00022 int cclkdiv = LPC_SC->CCLKCFG + 1; 00023 int Fcco = (2 * m * XTAL_FREQ) / n; 00024 int cclk = Fcco / cclkdiv; 00025 00026 //Power up the ADC 00027 LPC_SC->PCONP |= (1 << 12); 00028 //Set clock at cclk / 1. 00029 LPC_SC->PCLKSEL0 &= ~(0x3 << 24); 00030 switch (cclk_div) { 00031 case 1: 00032 LPC_SC->PCLKSEL0 |= 0x1 << 24; 00033 break; 00034 case 2: 00035 LPC_SC->PCLKSEL0 |= 0x2 << 24; 00036 break; 00037 case 4: 00038 LPC_SC->PCLKSEL0 |= 0x0 << 24; 00039 break; 00040 case 8: 00041 LPC_SC->PCLKSEL0 |= 0x3 << 24; 00042 break; 00043 default: 00044 fprintf(stderr, "Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n", 00045 cclk_div); 00046 fprintf(stderr, "Defaulting to 1.\n"); 00047 LPC_SC->PCLKSEL0 |= 0x1 << 24; 00048 break; 00049 } 00050 pclk = cclk / cclk_div; 00051 clock_div=pclk / adc_clk_freq; 00052 00053 if (clock_div > 0xFF) { 00054 fprintf(stderr, "Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n", 00055 clock_div); 00056 clock_div=0xFF; 00057 } 00058 if (clock_div == 0) { 00059 fprintf(stderr, "Warning: Clock division is 0. Re-Setting to 1.\n"); 00060 clock_div=1; 00061 } 00062 00063 _adc_clk_freq=pclk / clock_div; 00064 if (_adc_clk_freq > MAX_ADC_CLOCK) { 00065 fprintf(stderr, "Warning: Actual ADC sample rate of %u which is above %u limit\n", 00066 _adc_clk_freq / CLKS_PER_SAMPLE, MAX_ADC_CLOCK / CLKS_PER_SAMPLE); 00067 while ((pclk / max_div) > MAX_ADC_CLOCK) max_div++; 00068 fprintf(stderr, "Maximum recommended sample rate is %u\n", (pclk / max_div) / CLKS_PER_SAMPLE); 00069 } 00070 00071 LPC_ADC->ADCR = 00072 ((clock_div - 1 ) << 8 ) | //Clkdiv 00073 ( 1 << 21 ); //A/D operational 00074 00075 //Default no channels enabled 00076 LPC_ADC->ADCR &= ~0xFF; 00077 //Default NULL global custom isr 00078 _adc_g_isr = NULL; 00079 //Initialize arrays 00080 for (i=7; i>=0; i--) { 00081 _adc_data[i] = 0; 00082 _adc_isr[i] = NULL; 00083 } 00084 00085 00086 //* Attach IRQ 00087 instance = this; 00088 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr); 00089 00090 //Disable global interrupt 00091 LPC_ADC->ADINTEN &= ~0x100; 00092 00093 }; 00094 00095 void ADC::_adcisr(void) 00096 { 00097 instance->adcisr(); 00098 } 00099 00100 00101 void ADC::adcisr(void) 00102 { 00103 uint32_t stat; 00104 int chan; 00105 00106 // Read status 00107 stat = LPC_ADC->ADSTAT; 00108 //Scan channels for over-run or done and update array 00109 if (stat & 0x0101) _adc_data[0] = LPC_ADC->ADDR0; 00110 if (stat & 0x0202) _adc_data[1] = LPC_ADC->ADDR1; 00111 if (stat & 0x0404) _adc_data[2] = LPC_ADC->ADDR2; 00112 if (stat & 0x0808) _adc_data[3] = LPC_ADC->ADDR3; 00113 if (stat & 0x1010) _adc_data[4] = LPC_ADC->ADDR4; 00114 if (stat & 0x2020) _adc_data[5] = LPC_ADC->ADDR5; 00115 if (stat & 0x4040) _adc_data[6] = LPC_ADC->ADDR6; 00116 if (stat & 0x8080) _adc_data[7] = LPC_ADC->ADDR7; 00117 00118 // Channel that triggered interrupt 00119 chan = (LPC_ADC->ADGDR >> 24) & 0x07; 00120 //User defined interrupt handlers 00121 if (_adc_isr[chan] != NULL) 00122 _adc_isr[chan](_adc_data[chan]); 00123 if (_adc_g_isr != NULL) 00124 _adc_g_isr(chan, _adc_data[chan]); 00125 return; 00126 } 00127 00128 int ADC::_pin_to_channel(PinName pin) { 00129 int chan; 00130 switch (pin) { 00131 case p15://=p0.23 of LPC1768 00132 default: 00133 chan=0; 00134 break; 00135 case p16://=p0.24 of LPC1768 00136 chan=1; 00137 break; 00138 case p17://=p0.25 of LPC1768 00139 chan=2; 00140 break; 00141 case p18://=p0.26 of LPC1768 00142 chan=3; 00143 break; 00144 case p19://=p1.30 of LPC1768 00145 chan=4; 00146 break; 00147 case p20://=p1.31 of LPC1768 00148 chan=5; 00149 break; 00150 } 00151 return(chan); 00152 } 00153 00154 PinName ADC::channel_to_pin(int chan) { 00155 const PinName pin[8]={p15, p16, p17, p18, p19, p20, p15, p15}; 00156 00157 if ((chan < 0) || (chan > 5)) 00158 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan); 00159 return(pin[chan & 0x07]); 00160 } 00161 00162 00163 int ADC::channel_to_pin_number(int chan) { 00164 const int pin[8]={15, 16, 17, 18, 19, 20, 0, 0}; 00165 00166 if ((chan < 0) || (chan > 5)) 00167 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan); 00168 return(pin[chan & 0x07]); 00169 } 00170 00171 00172 uint32_t ADC::_data_of_pin(PinName pin) { 00173 //If in burst mode and at least one interrupt enabled then 00174 //take all values from _adc_data 00175 if (burst() && (LPC_ADC->ADINTEN & 0x3F)) { 00176 return(_adc_data[_pin_to_channel(pin)]); 00177 } else { 00178 //Return current register value or last value from interrupt 00179 switch (pin) { 00180 case p15://=p0.23 of LPC1768 00181 default: 00182 return(LPC_ADC->ADINTEN & 0x01?_adc_data[0]:LPC_ADC->ADDR0); 00183 case p16://=p0.24 of LPC1768 00184 return(LPC_ADC->ADINTEN & 0x02?_adc_data[1]:LPC_ADC->ADDR1); 00185 case p17://=p0.25 of LPC1768 00186 return(LPC_ADC->ADINTEN & 0x04?_adc_data[2]:LPC_ADC->ADDR2); 00187 case p18://=p0.26 of LPC1768: 00188 return(LPC_ADC->ADINTEN & 0x08?_adc_data[3]:LPC_ADC->ADDR3); 00189 case p19://=p1.30 of LPC1768 00190 return(LPC_ADC->ADINTEN & 0x10?_adc_data[4]:LPC_ADC->ADDR4); 00191 case p20://=p1.31 of LPC1768 00192 return(LPC_ADC->ADINTEN & 0x20?_adc_data[5]:LPC_ADC->ADDR5); 00193 } 00194 } 00195 } 00196 00197 //Enable or disable an ADC pin 00198 void ADC::setup(PinName pin, int state) { 00199 int chan; 00200 chan=_pin_to_channel(pin); 00201 if ((state & 1) == 1) { 00202 switch(pin) { 00203 case p15://=p0.23 of LPC1768 00204 default: 00205 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14); 00206 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14; 00207 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14); 00208 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14; 00209 break; 00210 case p16://=p0.24 of LPC1768 00211 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16); 00212 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16; 00213 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16); 00214 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16; 00215 break; 00216 case p17://=p0.25 of LPC1768 00217 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18); 00218 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18; 00219 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18); 00220 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18; 00221 break; 00222 case p18://=p0.26 of LPC1768: 00223 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20); 00224 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20; 00225 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20); 00226 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20; 00227 break; 00228 case p19://=p1.30 of LPC1768 00229 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28); 00230 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28; 00231 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28); 00232 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28; 00233 break; 00234 case p20://=p1.31 of LPC1768 00235 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30); 00236 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30; 00237 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30); 00238 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30; 00239 break; 00240 } 00241 //Only one channel can be selected at a time if not in burst mode 00242 if (!burst()) LPC_ADC->ADCR &= ~0xFF; 00243 //Select channel 00244 LPC_ADC->ADCR |= (1 << chan); 00245 } 00246 else { 00247 switch(pin) { 00248 case p15://=p0.23 of LPC1768 00249 default: 00250 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14); 00251 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14); 00252 break; 00253 case p16://=p0.24 of LPC1768 00254 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16); 00255 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16); 00256 break; 00257 case p17://=p0.25 of LPC1768 00258 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18); 00259 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18); 00260 break; 00261 case p18://=p0.26 of LPC1768: 00262 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20); 00263 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20); 00264 break; 00265 case p19://=p1.30 of LPC1768 00266 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28); 00267 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28); 00268 break; 00269 case p20://=p1.31 of LPC1768 00270 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30); 00271 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30); 00272 break; 00273 } 00274 LPC_ADC->ADCR &= ~(1 << chan); 00275 } 00276 } 00277 //Return channel enabled/disabled state 00278 int ADC::setup(PinName pin) { 00279 int chan; 00280 00281 chan = _pin_to_channel(pin); 00282 return((LPC_ADC->ADCR & (1 << chan)) >> chan); 00283 } 00284 00285 //Select channel already setup 00286 void ADC::select(PinName pin) { 00287 int chan; 00288 00289 //Only one channel can be selected at a time if not in burst mode 00290 if (!burst()) LPC_ADC->ADCR &= ~0xFF; 00291 //Select channel 00292 chan = _pin_to_channel(pin); 00293 LPC_ADC->ADCR |= (1 << chan); 00294 } 00295 00296 //Enable or disable burst mode 00297 void ADC::burst(int state) { 00298 if ((state & 1) == 1) { 00299 if (startmode(0) != 0) 00300 fprintf(stderr, "Warning. startmode is %u. Must be 0 for burst mode.\n", startmode(0)); 00301 LPC_ADC->ADCR |= (1 << 16); 00302 } 00303 else 00304 LPC_ADC->ADCR &= ~(1 << 16); 00305 } 00306 //Return burst mode state 00307 int ADC::burst(void) { 00308 return((LPC_ADC->ADCR & (1 << 16)) >> 16); 00309 } 00310 00311 //Set startmode and edge 00312 void ADC::startmode(int mode, int edge) { 00313 int lpc_adc_temp; 00314 00315 //Reset start mode and edge bit, 00316 lpc_adc_temp = LPC_ADC->ADCR & ~(0x0F << 24); 00317 //Write with new values 00318 lpc_adc_temp |= ((mode & 7) << 24) | ((edge & 1) << 27); 00319 LPC_ADC->ADCR = lpc_adc_temp; 00320 } 00321 00322 //Return startmode state according to mode_edge=0: mode and mode_edge=1: edge 00323 int ADC::startmode(int mode_edge){ 00324 switch (mode_edge) { 00325 case 0: 00326 default: 00327 return((LPC_ADC->ADCR >> 24) & 0x07); 00328 case 1: 00329 return((LPC_ADC->ADCR >> 27) & 0x01); 00330 } 00331 } 00332 00333 //Start ADC conversion 00334 void ADC::start(void) { 00335 startmode(1,0); 00336 } 00337 00338 00339 //Set interrupt enable/disable for pin to state 00340 void ADC::interrupt_state(PinName pin, int state) { 00341 int chan; 00342 00343 chan = _pin_to_channel(pin); 00344 if (state == 1) { 00345 LPC_ADC->ADINTEN &= ~0x100; 00346 LPC_ADC->ADINTEN |= 1 << chan; 00347 /* Enable the ADC Interrupt */ 00348 NVIC_EnableIRQ(ADC_IRQn); 00349 } else { 00350 LPC_ADC->ADINTEN &= ~( 1 << chan ); 00351 //Disable interrrupt if no active pins left 00352 if ((LPC_ADC->ADINTEN & 0xFF) == 0) 00353 NVIC_DisableIRQ(ADC_IRQn); 00354 } 00355 } 00356 00357 //Return enable/disable state of interrupt for pin 00358 int ADC::interrupt_state(PinName pin) { 00359 int chan; 00360 00361 chan = _pin_to_channel(pin); 00362 return((LPC_ADC->ADINTEN >> chan) & 0x01); 00363 } 00364 00365 00366 //Attach custom interrupt handler replacing default 00367 void ADC::attach(void(*fptr)(void)) { 00368 //* Attach IRQ 00369 NVIC_SetVector(ADC_IRQn, (uint32_t)fptr); 00370 } 00371 00372 //Restore default interrupt handler 00373 void ADC::detach(void) { 00374 //* Attach IRQ 00375 instance = this; 00376 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr); 00377 } 00378 00379 00380 //Append interrupt handler for pin to function isr 00381 void ADC::append(PinName pin, void(*fptr)(uint32_t value)) { 00382 int chan; 00383 00384 chan = _pin_to_channel(pin); 00385 _adc_isr[chan] = fptr; 00386 } 00387 00388 //Append interrupt handler for pin to function isr 00389 void ADC::unappend(PinName pin) { 00390 int chan; 00391 00392 chan = _pin_to_channel(pin); 00393 _adc_isr[chan] = NULL; 00394 } 00395 00396 //Unappend global interrupt handler to function isr 00397 void ADC::append(void(*fptr)(int chan, uint32_t value)) { 00398 _adc_g_isr = fptr; 00399 } 00400 00401 //Detach global interrupt handler to function isr 00402 void ADC::unappend() { 00403 _adc_g_isr = NULL; 00404 } 00405 00406 //Set ADC offset 00407 void offset(int offset) { 00408 LPC_ADC->ADTRM &= ~(0x07 << 4); 00409 LPC_ADC->ADTRM |= (offset & 0x07) << 4; 00410 } 00411 00412 //Return current ADC offset 00413 int offset(void) { 00414 return((LPC_ADC->ADTRM >> 4) & 0x07); 00415 } 00416 00417 //Return value of ADC on pin 00418 int ADC::read(PinName pin) { 00419 //Reset DONE and OVERRUN flags of interrupt handled ADC data 00420 _adc_data[_pin_to_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30)); 00421 //Return value 00422 return((_data_of_pin(pin) >> 4) & 0xFFF); 00423 } 00424 00425 //Return DONE flag of ADC on pin 00426 int ADC::done(PinName pin) { 00427 return((_data_of_pin(pin) >> 31) & 0x01); 00428 } 00429 00430 //Return OVERRUN flag of ADC on pin 00431 int ADC::overrun(PinName pin) { 00432 return((_data_of_pin(pin) >> 30) & 0x01); 00433 } 00434 00435 int ADC::actual_adc_clock(void) { 00436 return(_adc_clk_freq); 00437 } 00438 00439 int ADC::actual_sample_rate(void) { 00440 return(_adc_clk_freq / CLKS_PER_SAMPLE); 00441 }
Generated on Tue Jul 12 2022 18:50:26 by
1.7.2
