testing

Dependencies:   HTTPClient PowerControl SNICInterface_mod mbed-rtos mbed

Fork of Fx0Hackson by Daisuke Kimura

Committer:
hirobe0913
Date:
Sun Feb 15 04:00:06 2015 +0000
Revision:
9:9fc77f7685b7
testing

Who changed what in which revision?

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