10kHz ADC which reads from 17,18,19,20 pins and send the result to remote server (multicast now) via UDP

Dependencies:   EthernetNetIf mbed

Committer:
mrcandy
Date:
Mon Mar 26 15:54:08 2012 +0000
Revision:
1:beae6624e569
Parent:
0:7744cef9f8af
net::poll() added

Who changed what in which revision?

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