Full ADC driver with demo

Dependencies:   mbed

Committer:
simonb
Date:
Wed Feb 10 13:11:26 2010 +0000
Revision:
0:a2562dfbf543

        

Who changed what in which revision?

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