2 * Copyright (c) 2010, sblandford
3 * released under MIT license http://mbed.org/licence/mit
11 ADC::ADC(int sample_rate
, int cclk_div
)
14 int i
, adc_clk_freq
, pclk
, clock_div
, max_div
=1;
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
;
25 LPC_SC
->PCONP
|= (1 << 12);
26 //Set clock at cclk / 1.
27 LPC_SC
->PCLKSEL0
&= ~(0x3 << 24);
30 LPC_SC
->PCLKSEL0
|= 0x1 << 24;
33 LPC_SC
->PCLKSEL0
|= 0x2 << 24;
36 LPC_SC
->PCLKSEL0
|= 0x0 << 24;
39 LPC_SC
->PCLKSEL0
|= 0x3 << 24;
42 printf("Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n",
44 printf("Defaulting to 1.\n");
45 LPC_SC
->PCLKSEL0
|= 0x1 << 24;
48 pclk
= cclk
/ cclk_div
;
49 clock_div
=pclk
/ adc_clk_freq
;
51 if (clock_div
> 0xFF) {
52 //printf("Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n",
57 printf("Warning: Clock division is 0. Re-Setting to 1.\n");
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
);
70 ((clock_div
- 1 ) << 8 ) | //Clkdiv
71 ( 1 << 21 ); //A/D operational
73 //Default no channels enabled
74 LPC_ADC
->ADCR
&= ~0xFF;
75 //Default NULL global custom isr
78 for (i
=7; i
>=0; i
--) {
86 NVIC_SetVector(ADC_IRQn
, (uint32_t)&_adcisr
);
88 //Disable global interrupt
89 LPC_ADC
->ADINTEN
&= ~0x100;
93 void ADC::_adcisr(void)
99 void ADC::adcisr(void)
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
;
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
]);
126 int ADC::_pin_to_channel(PinName pin
) {
129 case p15
://=p0.23 of LPC1768
133 case p16
://=p0.24 of LPC1768
136 case p17
://=p0.25 of LPC1768
139 case p18
://=p0.26 of LPC1768
142 case p19
://=p1.30 of LPC1768
145 case p20
://=p1.31 of LPC1768
152 PinName
ADC::channel_to_pin(int chan
) {
153 const PinName pin
[8]={p15
, p16
, p17
, p18
, p19
, p20
, p15
, p15
};
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]);
161 int ADC::channel_to_pin_number(int chan
) {
162 const int pin
[8]={15, 16, 17, 18, 19, 20, 0, 0};
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]);
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
)]);
176 //Return current register value or last value from interrupt
178 case p15
://=p0.23 of LPC1768
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
);
195 //Enable or disable an ADC pin
196 void ADC::setup(PinName pin
, int state
) {
198 chan
=_pin_to_channel(pin
);
199 if ((state
& 1) == 1) {
201 case p15
://=p0.23 of LPC1768
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;
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;
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;
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;
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;
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;
239 //Only one channel can be selected at a time if not in burst mode
240 if (!burst()) LPC_ADC
->ADCR
&= ~0xFF;
242 LPC_ADC
->ADCR
|= (1 << chan
);
246 case p15
://=p0.23 of LPC1768
248 LPC_PINCON
->PINSEL1
&= ~((unsigned int)0x3 << 14);
249 LPC_PINCON
->PINMODE1
&= ~((unsigned int)0x3 << 14);
251 case p16
://=p0.24 of LPC1768
252 LPC_PINCON
->PINSEL1
&= ~((unsigned int)0x3 << 16);
253 LPC_PINCON
->PINMODE1
&= ~((unsigned int)0x3 << 16);
255 case p17
://=p0.25 of LPC1768
256 LPC_PINCON
->PINSEL1
&= ~((unsigned int)0x3 << 18);
257 LPC_PINCON
->PINMODE1
&= ~((unsigned int)0x3 << 18);
259 case p18
://=p0.26 of LPC1768:
260 LPC_PINCON
->PINSEL1
&= ~((unsigned int)0x3 << 20);
261 LPC_PINCON
->PINMODE1
&= ~((unsigned int)0x3 << 20);
263 case p19
://=p1.30 of LPC1768
264 LPC_PINCON
->PINSEL3
&= ~((unsigned int)0x3 << 28);
265 LPC_PINCON
->PINMODE3
&= ~((unsigned int)0x3 << 28);
267 case p20
://=p1.31 of LPC1768
268 LPC_PINCON
->PINSEL3
&= ~((unsigned int)0x3 << 30);
269 LPC_PINCON
->PINMODE3
&= ~((unsigned int)0x3 << 30);
272 LPC_ADC
->ADCR
&= ~(1 << chan
);
275 //Return channel enabled/disabled state
276 int ADC::setup(PinName pin
) {
279 chan
= _pin_to_channel(pin
);
280 return((LPC_ADC
->ADCR
& (1 << chan
)) >> chan
);
283 //Select channel already setup
284 void ADC::select(PinName pin
) {
287 //Only one channel can be selected at a time if not in burst mode
288 if (!burst()) LPC_ADC
->ADCR
&= ~0xFF;
290 chan
= _pin_to_channel(pin
);
291 LPC_ADC
->ADCR
|= (1 << chan
);
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);
302 LPC_ADC
->ADCR
&= ~(1 << 16);
304 //Return burst mode state
305 int ADC::burst(void) {
306 return((LPC_ADC
->ADCR
& (1 << 16)) >> 16);
309 //Set startmode and edge
310 void ADC::startmode(int mode
, int edge
) {
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
;
320 //Return startmode state according to mode_edge=0: mode and mode_edge=1: edge
321 int ADC::startmode(int mode_edge
){
325 return((LPC_ADC
->ADCR
>> 24) & 0x07);
327 return((LPC_ADC
->ADCR
>> 27) & 0x01);
331 //Start ADC conversion
332 void ADC::start(void) {
337 //Set interrupt enable/disable for pin to state
338 void ADC::interrupt_state(PinName pin
, int state
) {
341 chan
= _pin_to_channel(pin
);
343 LPC_ADC
->ADINTEN
&= ~0x100;
344 LPC_ADC
->ADINTEN
|= 1 << chan
;
345 /* Enable the ADC Interrupt */
346 NVIC_EnableIRQ(ADC_IRQn
);
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
);
355 //Return enable/disable state of interrupt for pin
356 int ADC::interrupt_state(PinName pin
) {
359 chan
= _pin_to_channel(pin
);
360 return((LPC_ADC
->ADINTEN
>> chan
) & 0x01);
364 //Attach custom interrupt handler replacing default
365 void ADC::attach(void(*fptr
)(void)) {
367 NVIC_SetVector(ADC_IRQn
, (uint32_t)fptr
);
370 //Restore default interrupt handler
371 void ADC::detach(void) {
374 NVIC_SetVector(ADC_IRQn
, (uint32_t)&_adcisr
);
378 //Append interrupt handler for pin to function isr
379 void ADC::append(PinName pin
, void(*fptr
)(uint32_t value
)) {
382 chan
= _pin_to_channel(pin
);
383 _adc_isr
[chan
] = fptr
;
386 //Append interrupt handler for pin to function isr
387 void ADC::unappend(PinName pin
) {
390 chan
= _pin_to_channel(pin
);
391 _adc_isr
[chan
] = NULL
;
394 //Unappend global interrupt handler to function isr
395 void ADC::append(void(*fptr
)(int chan
, uint32_t value
)) {
399 //Detach global interrupt handler to function isr
400 void ADC::unappend() {
405 void offset(int offset
) {
406 LPC_ADC
->ADTRM
&= ~(0x07 << 4);
407 LPC_ADC
->ADTRM
|= (offset
& 0x07) << 4;
410 //Return current ADC offset
412 return((LPC_ADC
->ADTRM
>> 4) & 0x07);
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));
420 return((_data_of_pin(pin
) >> 4) & 0xFFF);
423 //Return DONE flag of ADC on pin
424 int ADC::done(PinName pin
) {
425 return((_data_of_pin(pin
) >> 31) & 0x01);
428 //Return OVERRUN flag of ADC on pin
429 int ADC::overrun(PinName pin
) {
430 return((_data_of_pin(pin
) >> 30) & 0x01);
433 int ADC::actual_adc_clock(void) {
434 return(_adc_clk_freq
);
437 int ADC::actual_sample_rate(void) {
438 return(_adc_clk_freq
/ CLKS_PER_SAMPLE
);