Simple guitar tuner

Dependencies:   mbed

Committer:
adurand
Date:
Wed Oct 26 02:01:28 2011 +0000
Revision:
1:ae7d0cf78b3e
Parent:
0:490e67fb09c2

        

Who changed what in which revision?

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