Alvaro Cassinelli
/
skinGames_forktest
just a test
Fork of scoreLight_Advanced by
Embed:
(wiki syntax)
Show/hide line numbers
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