analyse audio input

Dependencies:   PololuLedStrip mbed

Committer:
KongXiangyue
Date:
Thu Aug 07 14:24:47 2014 +0000
Revision:
0:bd2ecb743ed5
AUDIO fft led

Who changed what in which revision?

UserRevisionLine numberNew contents of line
KongXiangyue 0:bd2ecb743ed5 1 /* mbed Library - ADC
KongXiangyue 0:bd2ecb743ed5 2 * Copyright (c) 2010, sblandford
KongXiangyue 0:bd2ecb743ed5 3 * released under MIT license http://mbed.org/licence/mit
KongXiangyue 0:bd2ecb743ed5 4 */
KongXiangyue 0:bd2ecb743ed5 5 #include "mbed.h"
KongXiangyue 0:bd2ecb743ed5 6 #include "adc.h"
KongXiangyue 0:bd2ecb743ed5 7
KongXiangyue 0:bd2ecb743ed5 8
KongXiangyue 0:bd2ecb743ed5 9 ADC *ADC::instance;
KongXiangyue 0:bd2ecb743ed5 10
KongXiangyue 0:bd2ecb743ed5 11 ADC::ADC(int sample_rate, int cclk_div)
KongXiangyue 0:bd2ecb743ed5 12 {
KongXiangyue 0:bd2ecb743ed5 13
KongXiangyue 0:bd2ecb743ed5 14 int i, adc_clk_freq, pclk, clock_div, max_div=1;
KongXiangyue 0:bd2ecb743ed5 15
KongXiangyue 0:bd2ecb743ed5 16 //Work out CCLK
KongXiangyue 0:bd2ecb743ed5 17 adc_clk_freq=CLKS_PER_SAMPLE*sample_rate;
KongXiangyue 0:bd2ecb743ed5 18 int m = (LPC_SC->PLL0CFG & 0xFFFF) + 1;
KongXiangyue 0:bd2ecb743ed5 19 int n = (LPC_SC->PLL0CFG >> 16) + 1;
KongXiangyue 0:bd2ecb743ed5 20 int cclkdiv = LPC_SC->CCLKCFG + 1;
KongXiangyue 0:bd2ecb743ed5 21 int Fcco = (2 * m * XTAL_FREQ) / n;
KongXiangyue 0:bd2ecb743ed5 22 int cclk = Fcco / cclkdiv;
KongXiangyue 0:bd2ecb743ed5 23
KongXiangyue 0:bd2ecb743ed5 24 //Power up the ADC
KongXiangyue 0:bd2ecb743ed5 25 LPC_SC->PCONP |= (1 << 12);
KongXiangyue 0:bd2ecb743ed5 26 //Set clock at cclk / 1.
KongXiangyue 0:bd2ecb743ed5 27 LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
KongXiangyue 0:bd2ecb743ed5 28 switch (cclk_div) {
KongXiangyue 0:bd2ecb743ed5 29 case 1:
KongXiangyue 0:bd2ecb743ed5 30 LPC_SC->PCLKSEL0 |= 0x1 << 24;
KongXiangyue 0:bd2ecb743ed5 31 break;
KongXiangyue 0:bd2ecb743ed5 32 case 2:
KongXiangyue 0:bd2ecb743ed5 33 LPC_SC->PCLKSEL0 |= 0x2 << 24;
KongXiangyue 0:bd2ecb743ed5 34 break;
KongXiangyue 0:bd2ecb743ed5 35 case 4:
KongXiangyue 0:bd2ecb743ed5 36 LPC_SC->PCLKSEL0 |= 0x0 << 24;
KongXiangyue 0:bd2ecb743ed5 37 break;
KongXiangyue 0:bd2ecb743ed5 38 case 8:
KongXiangyue 0:bd2ecb743ed5 39 LPC_SC->PCLKSEL0 |= 0x3 << 24;
KongXiangyue 0:bd2ecb743ed5 40 break;
KongXiangyue 0:bd2ecb743ed5 41 default:
KongXiangyue 0:bd2ecb743ed5 42 fprintf(stderr, "Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n",
KongXiangyue 0:bd2ecb743ed5 43 cclk_div);
KongXiangyue 0:bd2ecb743ed5 44 fprintf(stderr, "Defaulting to 1.\n");
KongXiangyue 0:bd2ecb743ed5 45 LPC_SC->PCLKSEL0 |= 0x1 << 24;
KongXiangyue 0:bd2ecb743ed5 46 break;
KongXiangyue 0:bd2ecb743ed5 47 }
KongXiangyue 0:bd2ecb743ed5 48 pclk = cclk / cclk_div;
KongXiangyue 0:bd2ecb743ed5 49 clock_div=pclk / adc_clk_freq;
KongXiangyue 0:bd2ecb743ed5 50
KongXiangyue 0:bd2ecb743ed5 51 if (clock_div > 0xFF) {
KongXiangyue 0:bd2ecb743ed5 52 fprintf(stderr, "Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n",
KongXiangyue 0:bd2ecb743ed5 53 clock_div);
KongXiangyue 0:bd2ecb743ed5 54 clock_div=0xFF;
KongXiangyue 0:bd2ecb743ed5 55 }
KongXiangyue 0:bd2ecb743ed5 56 if (clock_div == 0) {
KongXiangyue 0:bd2ecb743ed5 57 fprintf(stderr, "Warning: Clock division is 0. Re-Setting to 1.\n");
KongXiangyue 0:bd2ecb743ed5 58 clock_div=1;
KongXiangyue 0:bd2ecb743ed5 59 }
KongXiangyue 0:bd2ecb743ed5 60
KongXiangyue 0:bd2ecb743ed5 61 _adc_clk_freq=pclk / clock_div;
KongXiangyue 0:bd2ecb743ed5 62 if (_adc_clk_freq > MAX_ADC_CLOCK) {
KongXiangyue 0:bd2ecb743ed5 63 fprintf(stderr, "Warning: Actual ADC sample rate of %u which is above %u limit\n",
KongXiangyue 0:bd2ecb743ed5 64 _adc_clk_freq / CLKS_PER_SAMPLE, MAX_ADC_CLOCK / CLKS_PER_SAMPLE);
KongXiangyue 0:bd2ecb743ed5 65 while ((pclk / max_div) > MAX_ADC_CLOCK) max_div++;
KongXiangyue 0:bd2ecb743ed5 66 fprintf(stderr, "Maximum recommended sample rate is %u\n", (pclk / max_div) / CLKS_PER_SAMPLE);
KongXiangyue 0:bd2ecb743ed5 67 }
KongXiangyue 0:bd2ecb743ed5 68
KongXiangyue 0:bd2ecb743ed5 69 LPC_ADC->ADCR =
KongXiangyue 0:bd2ecb743ed5 70 ((clock_div - 1 ) << 8 ) | //Clkdiv
KongXiangyue 0:bd2ecb743ed5 71 ( 1 << 21 ); //A/D operational
KongXiangyue 0:bd2ecb743ed5 72
KongXiangyue 0:bd2ecb743ed5 73 //Default no channels enabled
KongXiangyue 0:bd2ecb743ed5 74 LPC_ADC->ADCR &= ~0xFF;
KongXiangyue 0:bd2ecb743ed5 75 //Default NULL global custom isr
KongXiangyue 0:bd2ecb743ed5 76 _adc_g_isr = NULL;
KongXiangyue 0:bd2ecb743ed5 77 //Initialize arrays
KongXiangyue 0:bd2ecb743ed5 78 for (i=7; i>=0; i--) {
KongXiangyue 0:bd2ecb743ed5 79 _adc_data[i] = 0;
KongXiangyue 0:bd2ecb743ed5 80 _adc_isr[i] = NULL;
KongXiangyue 0:bd2ecb743ed5 81 }
KongXiangyue 0:bd2ecb743ed5 82
KongXiangyue 0:bd2ecb743ed5 83
KongXiangyue 0:bd2ecb743ed5 84 //* Attach IRQ
KongXiangyue 0:bd2ecb743ed5 85 instance = this;
KongXiangyue 0:bd2ecb743ed5 86 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
KongXiangyue 0:bd2ecb743ed5 87
KongXiangyue 0:bd2ecb743ed5 88 //Disable global interrupt
KongXiangyue 0:bd2ecb743ed5 89 LPC_ADC->ADINTEN &= ~0x100;
KongXiangyue 0:bd2ecb743ed5 90
KongXiangyue 0:bd2ecb743ed5 91 };
KongXiangyue 0:bd2ecb743ed5 92
KongXiangyue 0:bd2ecb743ed5 93 void ADC::_adcisr(void)
KongXiangyue 0:bd2ecb743ed5 94 {
KongXiangyue 0:bd2ecb743ed5 95 instance->adcisr();
KongXiangyue 0:bd2ecb743ed5 96 }
KongXiangyue 0:bd2ecb743ed5 97
KongXiangyue 0:bd2ecb743ed5 98
KongXiangyue 0:bd2ecb743ed5 99 void ADC::adcisr(void)
KongXiangyue 0:bd2ecb743ed5 100 {
KongXiangyue 0:bd2ecb743ed5 101 uint32_t stat;
KongXiangyue 0:bd2ecb743ed5 102 int chan;
KongXiangyue 0:bd2ecb743ed5 103
KongXiangyue 0:bd2ecb743ed5 104 // Read status
KongXiangyue 0:bd2ecb743ed5 105 stat = LPC_ADC->ADSTAT;
KongXiangyue 0:bd2ecb743ed5 106 //Scan channels for over-run or done and update array
KongXiangyue 0:bd2ecb743ed5 107 if (stat & 0x0101) _adc_data[0] = LPC_ADC->ADDR0;
KongXiangyue 0:bd2ecb743ed5 108 if (stat & 0x0202) _adc_data[1] = LPC_ADC->ADDR1;
KongXiangyue 0:bd2ecb743ed5 109 if (stat & 0x0404) _adc_data[2] = LPC_ADC->ADDR2;
KongXiangyue 0:bd2ecb743ed5 110 if (stat & 0x0808) _adc_data[3] = LPC_ADC->ADDR3;
KongXiangyue 0:bd2ecb743ed5 111 if (stat & 0x1010) _adc_data[4] = LPC_ADC->ADDR4;
KongXiangyue 0:bd2ecb743ed5 112 if (stat & 0x2020) _adc_data[5] = LPC_ADC->ADDR5;
KongXiangyue 0:bd2ecb743ed5 113 if (stat & 0x4040) _adc_data[6] = LPC_ADC->ADDR6;
KongXiangyue 0:bd2ecb743ed5 114 if (stat & 0x8080) _adc_data[7] = LPC_ADC->ADDR7;
KongXiangyue 0:bd2ecb743ed5 115
KongXiangyue 0:bd2ecb743ed5 116 // Channel that triggered interrupt
KongXiangyue 0:bd2ecb743ed5 117 chan = (LPC_ADC->ADGDR >> 24) & 0x07;
KongXiangyue 0:bd2ecb743ed5 118 //User defined interrupt handlers
KongXiangyue 0:bd2ecb743ed5 119 if (_adc_isr[chan] != NULL)
KongXiangyue 0:bd2ecb743ed5 120 _adc_isr[chan](_adc_data[chan]);
KongXiangyue 0:bd2ecb743ed5 121 if (_adc_g_isr != NULL)
KongXiangyue 0:bd2ecb743ed5 122 _adc_g_isr(chan, _adc_data[chan]);
KongXiangyue 0:bd2ecb743ed5 123 return;
KongXiangyue 0:bd2ecb743ed5 124 }
KongXiangyue 0:bd2ecb743ed5 125
KongXiangyue 0:bd2ecb743ed5 126 int ADC::_pin_to_channel(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 127 int chan;
KongXiangyue 0:bd2ecb743ed5 128 switch (pin) {
KongXiangyue 0:bd2ecb743ed5 129 case p15://=p0.23 of LPC1768
KongXiangyue 0:bd2ecb743ed5 130 default:
KongXiangyue 0:bd2ecb743ed5 131 chan=0;
KongXiangyue 0:bd2ecb743ed5 132 break;
KongXiangyue 0:bd2ecb743ed5 133 case p16://=p0.24 of LPC1768
KongXiangyue 0:bd2ecb743ed5 134 chan=1;
KongXiangyue 0:bd2ecb743ed5 135 break;
KongXiangyue 0:bd2ecb743ed5 136 case p17://=p0.25 of LPC1768
KongXiangyue 0:bd2ecb743ed5 137 chan=2;
KongXiangyue 0:bd2ecb743ed5 138 break;
KongXiangyue 0:bd2ecb743ed5 139 case p18://=p0.26 of LPC1768
KongXiangyue 0:bd2ecb743ed5 140 chan=3;
KongXiangyue 0:bd2ecb743ed5 141 break;
KongXiangyue 0:bd2ecb743ed5 142 case p19://=p1.30 of LPC1768
KongXiangyue 0:bd2ecb743ed5 143 chan=4;
KongXiangyue 0:bd2ecb743ed5 144 break;
KongXiangyue 0:bd2ecb743ed5 145 case p20://=p1.31 of LPC1768
KongXiangyue 0:bd2ecb743ed5 146 chan=5;
KongXiangyue 0:bd2ecb743ed5 147 break;
KongXiangyue 0:bd2ecb743ed5 148 }
KongXiangyue 0:bd2ecb743ed5 149 return(chan);
KongXiangyue 0:bd2ecb743ed5 150 }
KongXiangyue 0:bd2ecb743ed5 151
KongXiangyue 0:bd2ecb743ed5 152 PinName ADC::channel_to_pin(int chan) {
KongXiangyue 0:bd2ecb743ed5 153 const PinName pin[8]={p15, p16, p17, p18, p19, p20, p15, p15};
KongXiangyue 0:bd2ecb743ed5 154
KongXiangyue 0:bd2ecb743ed5 155 if ((chan < 0) || (chan > 5))
KongXiangyue 0:bd2ecb743ed5 156 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
KongXiangyue 0:bd2ecb743ed5 157 return(pin[chan & 0x07]);
KongXiangyue 0:bd2ecb743ed5 158 }
KongXiangyue 0:bd2ecb743ed5 159
KongXiangyue 0:bd2ecb743ed5 160
KongXiangyue 0:bd2ecb743ed5 161 int ADC::channel_to_pin_number(int chan) {
KongXiangyue 0:bd2ecb743ed5 162 const int pin[8]={15, 16, 17, 18, 19, 20, 0, 0};
KongXiangyue 0:bd2ecb743ed5 163
KongXiangyue 0:bd2ecb743ed5 164 if ((chan < 0) || (chan > 5))
KongXiangyue 0:bd2ecb743ed5 165 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
KongXiangyue 0:bd2ecb743ed5 166 return(pin[chan & 0x07]);
KongXiangyue 0:bd2ecb743ed5 167 }
KongXiangyue 0:bd2ecb743ed5 168
KongXiangyue 0:bd2ecb743ed5 169
KongXiangyue 0:bd2ecb743ed5 170 uint32_t ADC::_data_of_pin(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 171 //If in burst mode and at least one interrupt enabled then
KongXiangyue 0:bd2ecb743ed5 172 //take all values from _adc_data
KongXiangyue 0:bd2ecb743ed5 173 if (burst() && (LPC_ADC->ADINTEN & 0x3F)) {
KongXiangyue 0:bd2ecb743ed5 174 return(_adc_data[_pin_to_channel(pin)]);
KongXiangyue 0:bd2ecb743ed5 175 } else {
KongXiangyue 0:bd2ecb743ed5 176 //Return current register value or last value from interrupt
KongXiangyue 0:bd2ecb743ed5 177 switch (pin) {
KongXiangyue 0:bd2ecb743ed5 178 case p15://=p0.23 of LPC1768
KongXiangyue 0:bd2ecb743ed5 179 default:
KongXiangyue 0:bd2ecb743ed5 180 return(LPC_ADC->ADINTEN & 0x01?_adc_data[0]:LPC_ADC->ADDR0);
KongXiangyue 0:bd2ecb743ed5 181 case p16://=p0.24 of LPC1768
KongXiangyue 0:bd2ecb743ed5 182 return(LPC_ADC->ADINTEN & 0x02?_adc_data[1]:LPC_ADC->ADDR1);
KongXiangyue 0:bd2ecb743ed5 183 case p17://=p0.25 of LPC1768
KongXiangyue 0:bd2ecb743ed5 184 return(LPC_ADC->ADINTEN & 0x04?_adc_data[2]:LPC_ADC->ADDR2);
KongXiangyue 0:bd2ecb743ed5 185 case p18://=p0.26 of LPC1768:
KongXiangyue 0:bd2ecb743ed5 186 return(LPC_ADC->ADINTEN & 0x08?_adc_data[3]:LPC_ADC->ADDR3);
KongXiangyue 0:bd2ecb743ed5 187 case p19://=p1.30 of LPC1768
KongXiangyue 0:bd2ecb743ed5 188 return(LPC_ADC->ADINTEN & 0x10?_adc_data[4]:LPC_ADC->ADDR4);
KongXiangyue 0:bd2ecb743ed5 189 case p20://=p1.31 of LPC1768
KongXiangyue 0:bd2ecb743ed5 190 return(LPC_ADC->ADINTEN & 0x20?_adc_data[5]:LPC_ADC->ADDR5);
KongXiangyue 0:bd2ecb743ed5 191 }
KongXiangyue 0:bd2ecb743ed5 192 }
KongXiangyue 0:bd2ecb743ed5 193 }
KongXiangyue 0:bd2ecb743ed5 194
KongXiangyue 0:bd2ecb743ed5 195 //Enable or disable an ADC pin
KongXiangyue 0:bd2ecb743ed5 196 void ADC::setup(PinName pin, int state) {
KongXiangyue 0:bd2ecb743ed5 197 int chan;
KongXiangyue 0:bd2ecb743ed5 198 chan=_pin_to_channel(pin);
KongXiangyue 0:bd2ecb743ed5 199 if ((state & 1) == 1) {
KongXiangyue 0:bd2ecb743ed5 200 switch(pin) {
KongXiangyue 0:bd2ecb743ed5 201 case p15://=p0.23 of LPC1768
KongXiangyue 0:bd2ecb743ed5 202 default:
KongXiangyue 0:bd2ecb743ed5 203 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
KongXiangyue 0:bd2ecb743ed5 204 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14;
KongXiangyue 0:bd2ecb743ed5 205 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
KongXiangyue 0:bd2ecb743ed5 206 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14;
KongXiangyue 0:bd2ecb743ed5 207 break;
KongXiangyue 0:bd2ecb743ed5 208 case p16://=p0.24 of LPC1768
KongXiangyue 0:bd2ecb743ed5 209 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
KongXiangyue 0:bd2ecb743ed5 210 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16;
KongXiangyue 0:bd2ecb743ed5 211 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
KongXiangyue 0:bd2ecb743ed5 212 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16;
KongXiangyue 0:bd2ecb743ed5 213 break;
KongXiangyue 0:bd2ecb743ed5 214 case p17://=p0.25 of LPC1768
KongXiangyue 0:bd2ecb743ed5 215 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
KongXiangyue 0:bd2ecb743ed5 216 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18;
KongXiangyue 0:bd2ecb743ed5 217 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
KongXiangyue 0:bd2ecb743ed5 218 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18;
KongXiangyue 0:bd2ecb743ed5 219 break;
KongXiangyue 0:bd2ecb743ed5 220 case p18://=p0.26 of LPC1768:
KongXiangyue 0:bd2ecb743ed5 221 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
KongXiangyue 0:bd2ecb743ed5 222 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20;
KongXiangyue 0:bd2ecb743ed5 223 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
KongXiangyue 0:bd2ecb743ed5 224 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20;
KongXiangyue 0:bd2ecb743ed5 225 break;
KongXiangyue 0:bd2ecb743ed5 226 case p19://=p1.30 of LPC1768
KongXiangyue 0:bd2ecb743ed5 227 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
KongXiangyue 0:bd2ecb743ed5 228 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28;
KongXiangyue 0:bd2ecb743ed5 229 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
KongXiangyue 0:bd2ecb743ed5 230 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28;
KongXiangyue 0:bd2ecb743ed5 231 break;
KongXiangyue 0:bd2ecb743ed5 232 case p20://=p1.31 of LPC1768
KongXiangyue 0:bd2ecb743ed5 233 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
KongXiangyue 0:bd2ecb743ed5 234 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30;
KongXiangyue 0:bd2ecb743ed5 235 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
KongXiangyue 0:bd2ecb743ed5 236 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30;
KongXiangyue 0:bd2ecb743ed5 237 break;
KongXiangyue 0:bd2ecb743ed5 238 }
KongXiangyue 0:bd2ecb743ed5 239 //Only one channel can be selected at a time if not in burst mode
KongXiangyue 0:bd2ecb743ed5 240 if (!burst()) LPC_ADC->ADCR &= ~0xFF;
KongXiangyue 0:bd2ecb743ed5 241 //Select channel
KongXiangyue 0:bd2ecb743ed5 242 LPC_ADC->ADCR |= (1 << chan);
KongXiangyue 0:bd2ecb743ed5 243 }
KongXiangyue 0:bd2ecb743ed5 244 else {
KongXiangyue 0:bd2ecb743ed5 245 switch(pin) {
KongXiangyue 0:bd2ecb743ed5 246 case p15://=p0.23 of LPC1768
KongXiangyue 0:bd2ecb743ed5 247 default:
KongXiangyue 0:bd2ecb743ed5 248 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
KongXiangyue 0:bd2ecb743ed5 249 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
KongXiangyue 0:bd2ecb743ed5 250 break;
KongXiangyue 0:bd2ecb743ed5 251 case p16://=p0.24 of LPC1768
KongXiangyue 0:bd2ecb743ed5 252 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
KongXiangyue 0:bd2ecb743ed5 253 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
KongXiangyue 0:bd2ecb743ed5 254 break;
KongXiangyue 0:bd2ecb743ed5 255 case p17://=p0.25 of LPC1768
KongXiangyue 0:bd2ecb743ed5 256 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
KongXiangyue 0:bd2ecb743ed5 257 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
KongXiangyue 0:bd2ecb743ed5 258 break;
KongXiangyue 0:bd2ecb743ed5 259 case p18://=p0.26 of LPC1768:
KongXiangyue 0:bd2ecb743ed5 260 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
KongXiangyue 0:bd2ecb743ed5 261 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
KongXiangyue 0:bd2ecb743ed5 262 break;
KongXiangyue 0:bd2ecb743ed5 263 case p19://=p1.30 of LPC1768
KongXiangyue 0:bd2ecb743ed5 264 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
KongXiangyue 0:bd2ecb743ed5 265 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
KongXiangyue 0:bd2ecb743ed5 266 break;
KongXiangyue 0:bd2ecb743ed5 267 case p20://=p1.31 of LPC1768
KongXiangyue 0:bd2ecb743ed5 268 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
KongXiangyue 0:bd2ecb743ed5 269 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
KongXiangyue 0:bd2ecb743ed5 270 break;
KongXiangyue 0:bd2ecb743ed5 271 }
KongXiangyue 0:bd2ecb743ed5 272 LPC_ADC->ADCR &= ~(1 << chan);
KongXiangyue 0:bd2ecb743ed5 273 }
KongXiangyue 0:bd2ecb743ed5 274 }
KongXiangyue 0:bd2ecb743ed5 275 //Return channel enabled/disabled state
KongXiangyue 0:bd2ecb743ed5 276 int ADC::setup(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 277 int chan;
KongXiangyue 0:bd2ecb743ed5 278
KongXiangyue 0:bd2ecb743ed5 279 chan = _pin_to_channel(pin);
KongXiangyue 0:bd2ecb743ed5 280 return((LPC_ADC->ADCR & (1 << chan)) >> chan);
KongXiangyue 0:bd2ecb743ed5 281 }
KongXiangyue 0:bd2ecb743ed5 282
KongXiangyue 0:bd2ecb743ed5 283 //Select channel already setup
KongXiangyue 0:bd2ecb743ed5 284 void ADC::select(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 285 int chan;
KongXiangyue 0:bd2ecb743ed5 286
KongXiangyue 0:bd2ecb743ed5 287 //Only one channel can be selected at a time if not in burst mode
KongXiangyue 0:bd2ecb743ed5 288 if (!burst()) LPC_ADC->ADCR &= ~0xFF;
KongXiangyue 0:bd2ecb743ed5 289 //Select channel
KongXiangyue 0:bd2ecb743ed5 290 chan = _pin_to_channel(pin);
KongXiangyue 0:bd2ecb743ed5 291 LPC_ADC->ADCR |= (1 << chan);
KongXiangyue 0:bd2ecb743ed5 292 }
KongXiangyue 0:bd2ecb743ed5 293
KongXiangyue 0:bd2ecb743ed5 294 //Enable or disable burst mode
KongXiangyue 0:bd2ecb743ed5 295 void ADC::burst(int state) {
KongXiangyue 0:bd2ecb743ed5 296 if ((state & 1) == 1) {
KongXiangyue 0:bd2ecb743ed5 297 if (startmode(0) != 0)
KongXiangyue 0:bd2ecb743ed5 298 fprintf(stderr, "Warning. startmode is %u. Must be 0 for burst mode.\n", startmode(0));
KongXiangyue 0:bd2ecb743ed5 299 LPC_ADC->ADCR |= (1 << 16);
KongXiangyue 0:bd2ecb743ed5 300 }
KongXiangyue 0:bd2ecb743ed5 301 else
KongXiangyue 0:bd2ecb743ed5 302 LPC_ADC->ADCR &= ~(1 << 16);
KongXiangyue 0:bd2ecb743ed5 303 }
KongXiangyue 0:bd2ecb743ed5 304 //Return burst mode state
KongXiangyue 0:bd2ecb743ed5 305 int ADC::burst(void) {
KongXiangyue 0:bd2ecb743ed5 306 return((LPC_ADC->ADCR & (1 << 16)) >> 16);
KongXiangyue 0:bd2ecb743ed5 307 }
KongXiangyue 0:bd2ecb743ed5 308
KongXiangyue 0:bd2ecb743ed5 309 //Set startmode and edge
KongXiangyue 0:bd2ecb743ed5 310 void ADC::startmode(int mode, int edge) {
KongXiangyue 0:bd2ecb743ed5 311 int lpc_adc_temp;
KongXiangyue 0:bd2ecb743ed5 312
KongXiangyue 0:bd2ecb743ed5 313 //Reset start mode and edge bit,
KongXiangyue 0:bd2ecb743ed5 314 lpc_adc_temp = LPC_ADC->ADCR & ~(0x0F << 24);
KongXiangyue 0:bd2ecb743ed5 315 //Write with new values
KongXiangyue 0:bd2ecb743ed5 316 lpc_adc_temp |= ((mode & 7) << 24) | ((edge & 1) << 27);
KongXiangyue 0:bd2ecb743ed5 317 LPC_ADC->ADCR = lpc_adc_temp;
KongXiangyue 0:bd2ecb743ed5 318 }
KongXiangyue 0:bd2ecb743ed5 319
KongXiangyue 0:bd2ecb743ed5 320 //Return startmode state according to mode_edge=0: mode and mode_edge=1: edge
KongXiangyue 0:bd2ecb743ed5 321 int ADC::startmode(int mode_edge){
KongXiangyue 0:bd2ecb743ed5 322 switch (mode_edge) {
KongXiangyue 0:bd2ecb743ed5 323 case 0:
KongXiangyue 0:bd2ecb743ed5 324 default:
KongXiangyue 0:bd2ecb743ed5 325 return((LPC_ADC->ADCR >> 24) & 0x07);
KongXiangyue 0:bd2ecb743ed5 326 case 1:
KongXiangyue 0:bd2ecb743ed5 327 return((LPC_ADC->ADCR >> 27) & 0x01);
KongXiangyue 0:bd2ecb743ed5 328 }
KongXiangyue 0:bd2ecb743ed5 329 }
KongXiangyue 0:bd2ecb743ed5 330
KongXiangyue 0:bd2ecb743ed5 331 //Start ADC conversion
KongXiangyue 0:bd2ecb743ed5 332 void ADC::start(void) {
KongXiangyue 0:bd2ecb743ed5 333 startmode(1,0);
KongXiangyue 0:bd2ecb743ed5 334 }
KongXiangyue 0:bd2ecb743ed5 335
KongXiangyue 0:bd2ecb743ed5 336
KongXiangyue 0:bd2ecb743ed5 337 //Set interrupt enable/disable for pin to state
KongXiangyue 0:bd2ecb743ed5 338 void ADC::interrupt_state(PinName pin, int state) {
KongXiangyue 0:bd2ecb743ed5 339 int chan;
KongXiangyue 0:bd2ecb743ed5 340
KongXiangyue 0:bd2ecb743ed5 341 chan = _pin_to_channel(pin);
KongXiangyue 0:bd2ecb743ed5 342 if (state == 1) {
KongXiangyue 0:bd2ecb743ed5 343 LPC_ADC->ADINTEN &= ~0x100;
KongXiangyue 0:bd2ecb743ed5 344 LPC_ADC->ADINTEN |= 1 << chan;
KongXiangyue 0:bd2ecb743ed5 345 /* Enable the ADC Interrupt */
KongXiangyue 0:bd2ecb743ed5 346 NVIC_EnableIRQ(ADC_IRQn);
KongXiangyue 0:bd2ecb743ed5 347 } else {
KongXiangyue 0:bd2ecb743ed5 348 LPC_ADC->ADINTEN &= ~( 1 << chan );
KongXiangyue 0:bd2ecb743ed5 349 //Disable interrrupt if no active pins left
KongXiangyue 0:bd2ecb743ed5 350 if ((LPC_ADC->ADINTEN & 0xFF) == 0)
KongXiangyue 0:bd2ecb743ed5 351 NVIC_DisableIRQ(ADC_IRQn);
KongXiangyue 0:bd2ecb743ed5 352 }
KongXiangyue 0:bd2ecb743ed5 353 }
KongXiangyue 0:bd2ecb743ed5 354
KongXiangyue 0:bd2ecb743ed5 355 //Return enable/disable state of interrupt for pin
KongXiangyue 0:bd2ecb743ed5 356 int ADC::interrupt_state(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 357 int chan;
KongXiangyue 0:bd2ecb743ed5 358
KongXiangyue 0:bd2ecb743ed5 359 chan = _pin_to_channel(pin);
KongXiangyue 0:bd2ecb743ed5 360 return((LPC_ADC->ADINTEN >> chan) & 0x01);
KongXiangyue 0:bd2ecb743ed5 361 }
KongXiangyue 0:bd2ecb743ed5 362
KongXiangyue 0:bd2ecb743ed5 363
KongXiangyue 0:bd2ecb743ed5 364 //Attach custom interrupt handler replacing default
KongXiangyue 0:bd2ecb743ed5 365 void ADC::attach(void(*fptr)(void)) {
KongXiangyue 0:bd2ecb743ed5 366 //* Attach IRQ
KongXiangyue 0:bd2ecb743ed5 367 NVIC_SetVector(ADC_IRQn, (uint32_t)fptr);
KongXiangyue 0:bd2ecb743ed5 368 }
KongXiangyue 0:bd2ecb743ed5 369
KongXiangyue 0:bd2ecb743ed5 370 //Restore default interrupt handler
KongXiangyue 0:bd2ecb743ed5 371 void ADC::detach(void) {
KongXiangyue 0:bd2ecb743ed5 372 //* Attach IRQ
KongXiangyue 0:bd2ecb743ed5 373 instance = this;
KongXiangyue 0:bd2ecb743ed5 374 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
KongXiangyue 0:bd2ecb743ed5 375 }
KongXiangyue 0:bd2ecb743ed5 376
KongXiangyue 0:bd2ecb743ed5 377
KongXiangyue 0:bd2ecb743ed5 378 //Append interrupt handler for pin to function isr
KongXiangyue 0:bd2ecb743ed5 379 void ADC::append(PinName pin, void(*fptr)(uint32_t value)) {
KongXiangyue 0:bd2ecb743ed5 380 int chan;
KongXiangyue 0:bd2ecb743ed5 381
KongXiangyue 0:bd2ecb743ed5 382 chan = _pin_to_channel(pin);
KongXiangyue 0:bd2ecb743ed5 383 _adc_isr[chan] = fptr;
KongXiangyue 0:bd2ecb743ed5 384 }
KongXiangyue 0:bd2ecb743ed5 385
KongXiangyue 0:bd2ecb743ed5 386 //Append interrupt handler for pin to function isr
KongXiangyue 0:bd2ecb743ed5 387 void ADC::unappend(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 388 int chan;
KongXiangyue 0:bd2ecb743ed5 389
KongXiangyue 0:bd2ecb743ed5 390 chan = _pin_to_channel(pin);
KongXiangyue 0:bd2ecb743ed5 391 _adc_isr[chan] = NULL;
KongXiangyue 0:bd2ecb743ed5 392 }
KongXiangyue 0:bd2ecb743ed5 393
KongXiangyue 0:bd2ecb743ed5 394 //Unappend global interrupt handler to function isr
KongXiangyue 0:bd2ecb743ed5 395 void ADC::append(void(*fptr)(int chan, uint32_t value)) {
KongXiangyue 0:bd2ecb743ed5 396 _adc_g_isr = fptr;
KongXiangyue 0:bd2ecb743ed5 397 }
KongXiangyue 0:bd2ecb743ed5 398
KongXiangyue 0:bd2ecb743ed5 399 //Detach global interrupt handler to function isr
KongXiangyue 0:bd2ecb743ed5 400 void ADC::unappend() {
KongXiangyue 0:bd2ecb743ed5 401 _adc_g_isr = NULL;
KongXiangyue 0:bd2ecb743ed5 402 }
KongXiangyue 0:bd2ecb743ed5 403
KongXiangyue 0:bd2ecb743ed5 404 //Set ADC offset
KongXiangyue 0:bd2ecb743ed5 405 void offset(int offset) {
KongXiangyue 0:bd2ecb743ed5 406 LPC_ADC->ADTRM &= ~(0x07 << 4);
KongXiangyue 0:bd2ecb743ed5 407 LPC_ADC->ADTRM |= (offset & 0x07) << 4;
KongXiangyue 0:bd2ecb743ed5 408 }
KongXiangyue 0:bd2ecb743ed5 409
KongXiangyue 0:bd2ecb743ed5 410 //Return current ADC offset
KongXiangyue 0:bd2ecb743ed5 411 int offset(void) {
KongXiangyue 0:bd2ecb743ed5 412 return((LPC_ADC->ADTRM >> 4) & 0x07);
KongXiangyue 0:bd2ecb743ed5 413 }
KongXiangyue 0:bd2ecb743ed5 414
KongXiangyue 0:bd2ecb743ed5 415 //Return value of ADC on pin
KongXiangyue 0:bd2ecb743ed5 416 int ADC::read(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 417 //Reset DONE and OVERRUN flags of interrupt handled ADC data
KongXiangyue 0:bd2ecb743ed5 418 _adc_data[_pin_to_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30));
KongXiangyue 0:bd2ecb743ed5 419 //Return value
KongXiangyue 0:bd2ecb743ed5 420 return((_data_of_pin(pin) >> 4) & 0xFFF);
KongXiangyue 0:bd2ecb743ed5 421 }
KongXiangyue 0:bd2ecb743ed5 422
KongXiangyue 0:bd2ecb743ed5 423 //Return DONE flag of ADC on pin
KongXiangyue 0:bd2ecb743ed5 424 int ADC::done(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 425 return((_data_of_pin(pin) >> 31) & 0x01);
KongXiangyue 0:bd2ecb743ed5 426 }
KongXiangyue 0:bd2ecb743ed5 427
KongXiangyue 0:bd2ecb743ed5 428 //Return OVERRUN flag of ADC on pin
KongXiangyue 0:bd2ecb743ed5 429 int ADC::overrun(PinName pin) {
KongXiangyue 0:bd2ecb743ed5 430 return((_data_of_pin(pin) >> 30) & 0x01);
KongXiangyue 0:bd2ecb743ed5 431 }
KongXiangyue 0:bd2ecb743ed5 432
KongXiangyue 0:bd2ecb743ed5 433 int ADC::actual_adc_clock(void) {
KongXiangyue 0:bd2ecb743ed5 434 return(_adc_clk_freq);
KongXiangyue 0:bd2ecb743ed5 435 }
KongXiangyue 0:bd2ecb743ed5 436
KongXiangyue 0:bd2ecb743ed5 437 int ADC::actual_sample_rate(void) {
KongXiangyue 0:bd2ecb743ed5 438 return(_adc_clk_freq / CLKS_PER_SAMPLE);
KongXiangyue 0:bd2ecb743ed5 439 }