Test program for Spikes when measuring 2 channels in Timer1/MAT1:0 triggering mode.

Dependencies:   mbed

Committer:
wvd_vegt
Date:
Wed Oct 31 10:31:02 2012 +0000
Revision:
2:74fd179377d9
Parent:
0:ff3d852b6266
1) Conversion to Public

Who changed what in which revision?

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