Labrary from Simon Blandford

Dependents:   DiscoTech ADC_Test filter_implement IR_temperature ... more

Committer:
flash_ahaa
Date:
Mon Sep 23 11:18:37 2013 +0000
Revision:
0:b05e4f5e2c8c
Library from Simon Blandford

Who changed what in which revision?

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