Makes 100 samples on maximum sample rate and transmits it over UART

Dependencies:   mbed

Committer:
gno
Date:
Wed Jun 09 12:54:21 2010 +0000
Revision:
0:55ea5a2921b2

        

Who changed what in which revision?

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