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