Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

Committer:
mbedalvaro
Date:
Wed Mar 28 14:40:01 2012 +0000
Revision:
0:345b3bc7a0ea
This version (using rigid frame, base and child classes, etc) works, but the blob is strangely smaller. Need to check this.

Who changed what in which revision?

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