Andrew Kuznetsov / Mbed 2 deprecated Monitor00_copy

Dependencies:   EthernetNetIf mbed

Fork of Monitor0 by Andrew Kuznetsov

Committer:
AndrewK
Date:
Tue Jun 26 06:24:23 2012 +0000
Revision:
0:72d0d2736b7f

        

Who changed what in which revision?

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