Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

Committer:
mbedalvaro
Date:
Thu Apr 17 08:04:14 2014 +0000
Revision:
47:199042980678
Parent:
41:74e24a0e6e50
publishing for sharing with Ken Iwasaki

Who changed what in which revision?

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