audio_FFT
Published 21 Mar 2010, by
James Cobb
adc,
audio,
FFT,
sound
« Back to documentation index
Show/hide line numbers
adc.cpp Source File
adc.cpp
00001
00002
00003
00004
00005 #include "mbed.h"
00006 #include "adc.h"
00007
00008
00009 ADC *ADC::instance;
00010
00011 ADC::ADC(int sample_rate, int cclk_div)
00012 {
00013
00014 int i, adc_clk_freq, pclk, clock_div, max_div=1;
00015
00016
00017 adc_clk_freq=CLKS_PER_SAMPLE*sample_rate;
00018 int m = (LPC_SC->PLL0CFG & 0xFFFF) + 1;
00019 int n = (LPC_SC->PLL0CFG >> 16) + 1;
00020 int cclkdiv = LPC_SC->CCLKCFG + 1;
00021 int Fcco = (2 * m * XTAL_FREQ) / n;
00022 int cclk = Fcco / cclkdiv;
00023
00024
00025 LPC_SC->PCONP |= (1 << 12);
00026
00027 LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
00028 switch (cclk_div) {
00029 case 1:
00030 LPC_SC->PCLKSEL0 |= 0x1 << 24;
00031 break;
00032 case 2:
00033 LPC_SC->PCLKSEL0 |= 0x2 << 24;
00034 break;
00035 case 4:
00036 LPC_SC->PCLKSEL0 |= 0x0 << 24;
00037 break;
00038 case 8:
00039 LPC_SC->PCLKSEL0 |= 0x3 << 24;
00040 break;
00041 default:
00042 fprintf(stderr, "Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n",
00043 cclk_div);
00044 fprintf(stderr, "Defaulting to 1.\n");
00045 LPC_SC->PCLKSEL0 |= 0x1 << 24;
00046 break;
00047 }
00048 pclk = cclk / cclk_div;
00049 clock_div=pclk / adc_clk_freq;
00050
00051 if (clock_div > 0xFF) {
00052 fprintf(stderr, "Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n",
00053 clock_div);
00054 clock_div=0xFF;
00055 }
00056 if (clock_div == 0) {
00057 fprintf(stderr, "Warning: Clock division is 0. Re-Setting to 1.\n");
00058 clock_div=1;
00059 }
00060
00061 _adc_clk_freq=pclk / clock_div;
00062 if (_adc_clk_freq > MAX_ADC_CLOCK) {
00063 fprintf(stderr, "Warning: Actual ADC sample rate of %u which is above %u limit\n",
00064 _adc_clk_freq / CLKS_PER_SAMPLE, MAX_ADC_CLOCK / CLKS_PER_SAMPLE);
00065 while ((pclk / max_div) > MAX_ADC_CLOCK) max_div++;
00066 fprintf(stderr, "Maximum recommended sample rate is %u\n", (pclk / max_div) / CLKS_PER_SAMPLE);
00067 }
00068
00069 LPC_ADC->ADCR =
00070 ((clock_div - 1 ) << 8 ) |
00071 ( 1 << 21 );
00072
00073
00074 LPC_ADC->ADCR &= ~0xFF;
00075
00076 _adc_g_isr = NULL;
00077
00078 for (i=7; i>=0; i--) {
00079 _adc_data[i] = 0;
00080 _adc_isr[i] = NULL;
00081 }
00082
00083
00084
00085 instance = this;
00086 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
00087
00088
00089 LPC_ADC->ADINTEN &= ~0x100;
00090
00091 };
00092
00093 void ADC::_adcisr(void)
00094 {
00095 instance->adcisr();
00096 }
00097
00098
00099 void ADC::adcisr(void)
00100 {
00101 uint32_t stat;
00102 int chan;
00103
00104
00105 stat = LPC_ADC->ADSTAT;
00106
00107 if (stat & 0x0101) _adc_data[0] = LPC_ADC->ADDR0;
00108 if (stat & 0x0202) _adc_data[1] = LPC_ADC->ADDR1;
00109 if (stat & 0x0404) _adc_data[2] = LPC_ADC->ADDR2;
00110 if (stat & 0x0808) _adc_data[3] = LPC_ADC->ADDR3;
00111 if (stat & 0x1010) _adc_data[4] = LPC_ADC->ADDR4;
00112 if (stat & 0x2020) _adc_data[5] = LPC_ADC->ADDR5;
00113 if (stat & 0x4040) _adc_data[6] = LPC_ADC->ADDR6;
00114 if (stat & 0x8080) _adc_data[7] = LPC_ADC->ADDR7;
00115
00116
00117 chan = (LPC_ADC->ADGDR >> 24) & 0x07;
00118
00119 if (_adc_isr[chan] != NULL)
00120 _adc_isr[chan](_adc_data[chan]);
00121 if (_adc_g_isr != NULL)
00122 _adc_g_isr(chan, _adc_data[chan]);
00123 return;
00124 }
00125
00126 int ADC::_pin_to_channel(PinName pin) {
00127 int chan;
00128 switch (pin) {
00129 case p15:
00130 default:
00131 chan=0;
00132 break;
00133 case p16:
00134 chan=1;
00135 break;
00136 case p17:
00137 chan=2;
00138 break;
00139 case p18:
00140 chan=3;
00141 break;
00142 case p19:
00143 chan=4;
00144 break;
00145 case p20:
00146 chan=5;
00147 break;
00148 }
00149 return(chan);
00150 }
00151
00152 PinName ADC::channel_to_pin(int chan) {
00153 const PinName pin[8]={p15, p16, p17, p18, p19, p20, p15, p15};
00154
00155 if ((chan < 0) || (chan > 5))
00156 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
00157 return(pin[chan & 0x07]);
00158 }
00159
00160
00161 int ADC::channel_to_pin_number(int chan) {
00162 const int pin[8]={15, 16, 17, 18, 19, 20, 0, 0};
00163
00164 if ((chan < 0) || (chan > 5))
00165 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
00166 return(pin[chan & 0x07]);
00167 }
00168
00169
00170 uint32_t ADC::_data_of_pin(PinName pin) {
00171
00172
00173 if (burst() && (LPC_ADC->ADINTEN & 0x3F)) {
00174 return(_adc_data[_pin_to_channel(pin)]);
00175 } else {
00176
00177 switch (pin) {
00178 case p15:
00179 default:
00180 return(LPC_ADC->ADINTEN & 0x01?_adc_data[0]:LPC_ADC->ADDR0);
00181 case p16:
00182 return(LPC_ADC->ADINTEN & 0x02?_adc_data[1]:LPC_ADC->ADDR1);
00183 case p17:
00184 return(LPC_ADC->ADINTEN & 0x04?_adc_data[2]:LPC_ADC->ADDR2);
00185 case p18:
00186 return(LPC_ADC->ADINTEN & 0x08?_adc_data[3]:LPC_ADC->ADDR3);
00187 case p19:
00188 return(LPC_ADC->ADINTEN & 0x10?_adc_data[4]:LPC_ADC->ADDR4);
00189 case p20:
00190 return(LPC_ADC->ADINTEN & 0x20?_adc_data[5]:LPC_ADC->ADDR5);
00191 }
00192 }
00193 }
00194
00195
00196 void ADC::setup(PinName pin, int state) {
00197 int chan;
00198 chan=_pin_to_channel(pin);
00199 if ((state & 1) == 1) {
00200 switch(pin) {
00201 case p15:
00202 default:
00203 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
00204 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14;
00205 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
00206 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14;
00207 break;
00208 case p16:
00209 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
00210 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16;
00211 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
00212 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16;
00213 break;
00214 case p17:
00215 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
00216 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18;
00217 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
00218 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18;
00219 break;
00220 case p18:
00221 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
00222 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20;
00223 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
00224 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20;
00225 break;
00226 case p19:
00227 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
00228 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28;
00229 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
00230 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28;
00231 break;
00232 case p20:
00233 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
00234 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30;
00235 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
00236 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30;
00237 break;
00238 }
00239
00240 if (!burst()) LPC_ADC->ADCR &= ~0xFF;
00241
00242 LPC_ADC->ADCR |= (1 << chan);
00243 }
00244 else {
00245 switch(pin) {
00246 case p15:
00247 default:
00248 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
00249 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
00250 break;
00251 case p16:
00252 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
00253 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
00254 break;
00255 case p17:
00256 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
00257 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
00258 break;
00259 case p18:
00260 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
00261 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
00262 break;
00263 case p19:
00264 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
00265 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
00266 break;
00267 case p20:
00268 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
00269 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
00270 break;
00271 }
00272 LPC_ADC->ADCR &= ~(1 << chan);
00273 }
00274 }
00275
00276 int ADC::setup(PinName pin) {
00277 int chan;
00278
00279 chan = _pin_to_channel(pin);
00280 return((LPC_ADC->ADCR & (1 << chan)) >> chan);
00281 }
00282
00283
00284 void ADC::select(PinName pin) {
00285 int chan;
00286
00287
00288 if (!burst()) LPC_ADC->ADCR &= ~0xFF;
00289
00290 chan = _pin_to_channel(pin);
00291 LPC_ADC->ADCR |= (1 << chan);
00292 }
00293
00294
00295 void ADC::burst(int state) {
00296 if ((state & 1) == 1) {
00297 if (startmode(0) != 0)
00298 fprintf(stderr, "Warning. startmode is %u. Must be 0 for burst mode.\n", startmode(0));
00299 LPC_ADC->ADCR |= (1 << 16);
00300 }
00301 else
00302 LPC_ADC->ADCR &= ~(1 << 16);
00303 }
00304
00305 int ADC::burst(void) {
00306 return((LPC_ADC->ADCR & (1 << 16)) >> 16);
00307 }
00308
00309
00310 void ADC::startmode(int mode, int edge) {
00311 int lpc_adc_temp;
00312
00313
00314 lpc_adc_temp = LPC_ADC->ADCR & ~(0x0F << 24);
00315
00316 lpc_adc_temp |= ((mode & 7) << 24) | ((edge & 1) << 27);
00317 LPC_ADC->ADCR = lpc_adc_temp;
00318 }
00319
00320
00321 int ADC::startmode(int mode_edge){
00322 switch (mode_edge) {
00323 case 0:
00324 default:
00325 return((LPC_ADC->ADCR >> 24) & 0x07);
00326 case 1:
00327 return((LPC_ADC->ADCR >> 27) & 0x01);
00328 }
00329 }
00330
00331
00332 void ADC::start(void) {
00333 startmode(1,0);
00334 }
00335
00336
00337
00338 void ADC::interrupt_state(PinName pin, int state) {
00339 int chan;
00340
00341 chan = _pin_to_channel(pin);
00342 if (state == 1) {
00343 LPC_ADC->ADINTEN &= ~0x100;
00344 LPC_ADC->ADINTEN |= 1 << chan;
00345
00346 NVIC_EnableIRQ(ADC_IRQn);
00347 } else {
00348 LPC_ADC->ADINTEN &= ~( 1 << chan );
00349
00350 if ((LPC_ADC->ADINTEN & 0xFF) == 0)
00351 NVIC_DisableIRQ(ADC_IRQn);
00352 }
00353 }
00354
00355
00356 int ADC::interrupt_state(PinName pin) {
00357 int chan;
00358
00359 chan = _pin_to_channel(pin);
00360 return((LPC_ADC->ADINTEN >> chan) & 0x01);
00361 }
00362
00363
00364
00365 void ADC::attach(void(*fptr)(void)) {
00366
00367 NVIC_SetVector(ADC_IRQn, (uint32_t)fptr);
00368 }
00369
00370
00371 void ADC::detach(void) {
00372
00373 instance = this;
00374 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
00375 }
00376
00377
00378
00379 void ADC::append(PinName pin, void(*fptr)(uint32_t value)) {
00380 int chan;
00381
00382 chan = _pin_to_channel(pin);
00383 _adc_isr[chan] = fptr;
00384 }
00385
00386
00387 void ADC::unappend(PinName pin) {
00388 int chan;
00389
00390 chan = _pin_to_channel(pin);
00391 _adc_isr[chan] = NULL;
00392 }
00393
00394
00395 void ADC::append(void(*fptr)(int chan, uint32_t value)) {
00396 _adc_g_isr = fptr;
00397 }
00398
00399
00400 void ADC::unappend() {
00401 _adc_g_isr = NULL;
00402 }
00403
00404
00405 void offset(int offset) {
00406 LPC_ADC->ADTRM &= ~(0x07 << 4);
00407 LPC_ADC->ADTRM |= (offset & 0x07) << 4;
00408 }
00409
00410
00411 int offset(void) {
00412 return((LPC_ADC->ADTRM >> 4) & 0x07);
00413 }
00414
00415
00416 int ADC::read(PinName pin) {
00417
00418 _adc_data[_pin_to_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30));
00419
00420 return((_data_of_pin(pin) >> 4) & 0xFFF);
00421 }
00422
00423
00424 int ADC::done(PinName pin) {
00425 return((_data_of_pin(pin) >> 31) & 0x01);
00426 }
00427
00428
00429 int ADC::overrun(PinName pin) {
00430 return((_data_of_pin(pin) >> 30) & 0x01);
00431 }
00432
00433 int ADC::actual_adc_clock(void) {
00434 return(_adc_clk_freq);
00435 }
00436
00437 int ADC::actual_sample_rate(void) {
00438 return(_adc_clk_freq / CLKS_PER_SAMPLE);
00439 }