1 /*
2  * @brief LPC15xx ADC example
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2013
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products.  This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights.  NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers.  This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include "board.h"
33 #include <stdio.h>
34 
35 /*****************************************************************************
36  * Private types/enumerations/variables
37  ****************************************************************************/
38 
39 static volatile int ticks;
40 static bool sequence0Complete, sequence1Complete, threshold1Crossed;
41 
42 #define TICKRATE_HZ (100)	/* 100 ticks per second */
43 
44 #if defined(BOARD_NXP_LPCXPRESSO_1549)
45 /* ADC is connected to the pot on LPCXPresso base boards */
46 #define BOARD_ADC_CH 1
47 
48 #else
49 #warning "Using ADC channel 8 for this example, please select for your board"
50 #define BOARD_ADC_CH 8
51 #endif
52 
53 /*****************************************************************************
54  * Public types/enumerations/variables
55  ****************************************************************************/
56 
57 /*****************************************************************************
58  * Private functions
59  ****************************************************************************/
60 
showValudeADC(LPC_ADC_T * pADC)61 void showValudeADC(LPC_ADC_T *pADC)
62 {
63 	int index, j;
64 	uint32_t rawSample;
65 
66 	if (pADC == LPC_ADC0) {
67 		index = 0;
68 	}
69 	else {
70 		index = 1;
71 	}
72 
73 	/* Get raw sample data for channels 0-11 */
74 	for (j = 0; j < 12; j++) {
75 		rawSample = Chip_ADC_GetDataReg(pADC, j);
76 
77 		/* Show some ADC data */
78 		if ((rawSample & (ADC_DR_OVERRUN | ADC_SEQ_GDAT_DATAVALID)) != 0) {
79 			DEBUGOUT("ADC%d_%d: Sample value = 0x%x (Data sample %d)\r\n", index, j,
80 					 ADC_DR_RESULT(rawSample), j);
81 
82 			/* Threshold events are only on ADC1 */
83 			if (index == 1) {
84 				DEBUGOUT("ADC%d_%d: Threshold range = 0x%x\r\n", index, j,
85 						 ADC_DR_THCMPRANGE(rawSample));
86 				DEBUGOUT("ADC%d_%d: Threshold cross = 0x%x\r\n", index, j,
87 						 ADC_DR_THCMPCROSS(rawSample));
88 			}
89 		}
90 	}
91 }
92 
93 /*****************************************************************************
94  * Public functions
95  ****************************************************************************/
96 
97 /**
98  * @brief	Handle interrupt from SysTick timer
99  * @return	Nothing
100  */
SysTick_Handler(void)101 void SysTick_Handler(void)
102 {
103 	static uint32_t count;
104 
105 	/* Every 1/2 second */
106 	count++;
107 	if (count >= (TICKRATE_HZ / 2)) {
108 		count = 0;
109 
110 		/* Manual start for ADC1 conversion sequence A */
111 		Chip_ADC_StartSequencer(LPC_ADC0, ADC_SEQA_IDX);
112 		Chip_ADC_StartSequencer(LPC_ADC1, ADC_SEQA_IDX);
113 	}
114 }
115 
116 /**
117  * @brief	Handle interrupt from ADC0 sequencer A
118  * @return	Nothing
119  */
ADC0A_IRQHandler(void)120 void ADC0A_IRQHandler(void)
121 {
122 	uint32_t pending;
123 
124 	/* Get pending interrupts */
125 	pending = Chip_ADC_GetFlags(LPC_ADC0);
126 
127 	/* Sequence A completion interrupt */
128 	if (pending & ADC_FLAGS_SEQA_INT_MASK) {
129 		sequence0Complete = true;
130 	}
131 
132 	/* Clear any pending interrupts */
133 	Chip_ADC_ClearFlags(LPC_ADC0, pending);
134 }
135 
136 /**
137  * @brief	Handle interrupt from ADC1 sequencer A
138  * @return	Nothing
139  */
ADC1A_IRQHandler(void)140 void ADC1A_IRQHandler(void)
141 {
142 	uint32_t pending;
143 
144 	/* Get pending interrupts */
145 	pending = Chip_ADC_GetFlags(LPC_ADC1);
146 
147 	/* Sequence A completion interrupt */
148 	if (pending & ADC_FLAGS_SEQA_INT_MASK) {
149 		sequence1Complete = true;
150 	}
151 
152 	/* Clear Sequence A completion interrupt */
153 	Chip_ADC_ClearFlags(LPC_ADC1, ADC_FLAGS_SEQA_INT_MASK);
154 }
155 
156 /**
157  * @brief	Handle threshold interrupt from ADC1
158  * @return	Nothing
159  */
ADC1_THCMP_IRQHandler(void)160 void ADC1_THCMP_IRQHandler(void)
161 {
162 	uint32_t pending;
163 
164 	/* Get pending interrupts */
165 	pending = Chip_ADC_GetFlags(LPC_ADC1);
166 
167 	/* Threshold crossing interrupt on ADC input channel */
168 	if (pending & ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH)) {
169 		threshold1Crossed = true;
170 	}
171 
172 	/* Clear threshold interrupt */
173 	Chip_ADC_ClearFlags(LPC_ADC1, ADC_FLAGS_THCMP_MASK(BOARD_ADC_CH));
174 }
175 
176 /**
177  * @brief	main routine for ADC example
178  * @return	Function should not exit
179  */
main(void)180 int main(void)
181 {
182 	SystemCoreClockUpdate();
183 	Board_Init();
184 	DEBUGSTR("ADC sequencer demo\r\n");
185 
186 	/* Setup ADC for 12-bit mode and normal power */
187 	Chip_ADC_Init(LPC_ADC0, 0);
188 	Chip_ADC_Init(LPC_ADC1, 0);
189 
190 	/* Setup for maximum ADC clock rate */
191 	Chip_ADC_SetClockRate(LPC_ADC0, ADC_MAX_SAMPLE_RATE);
192 	Chip_ADC_SetClockRate(LPC_ADC1, ADC_MAX_SAMPLE_RATE);
193 
194 	/* For ADC0, seqeucner A will be used without threshold events.
195 	   It will be triggered manually by the sysTick interrupt and
196 	   only monitor the internal temperature sensor. */
197 	Chip_ADC_SetupSequencer(LPC_ADC0, ADC_SEQA_IDX, (ADC_SEQ_CTRL_CHANSEL(0) |
198 													 ADC_SEQ_CTRL_MODE_EOS));
199 
200 	/* Power up the internal temperature sensor */
201 	Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_TS_PD);
202 
203 	/* For ADC0, select temperature sensor for channel 0 on ADC0 */
204 	Chip_ADC_SetADC0Input(LPC_ADC0, ADC_INSEL_TS);
205 
206 #if defined(BOARD_NXP_LPCXPRESSO_1549)
207 	/* Use higher voltage trim for both ADCs */
208 	Chip_ADC_SetTrim(LPC_ADC0, ADC_TRIM_VRANGE_HIGHV);
209 	Chip_ADC_SetTrim(LPC_ADC1, ADC_TRIM_VRANGE_HIGHV);
210 
211 	/* For ADC1, seqeucner A will be used with threshold events.
212 	   It will be triggered manually by the sysTick interrupt and
213 	   only monitors the ADC1 input. */
214 	Chip_ADC_SetupSequencer(LPC_ADC1, ADC_SEQA_IDX,
215 							(ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) | ADC_SEQ_CTRL_MODE_EOS));
216 
217 	/* Disables pullups/pulldowns and disable digital mode */
218 	Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 9, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
219 
220 	/* Assign ADC1_1 to PIO0_9 via SWM (fixed pin) */
221 	Chip_SWM_EnableFixedPin(SWM_FIXED_ADC1_1);
222 
223 #else
224 #warning "No ADC setup for this example"
225 #endif
226 
227 	/* Need to do a calibration after initialization and trim */
228 	Chip_ADC_StartCalibration(LPC_ADC0);
229 	Chip_ADC_StartCalibration(LPC_ADC1);
230 	while (!(Chip_ADC_IsCalibrationDone(LPC_ADC0))) {}
231 	while (!(Chip_ADC_IsCalibrationDone(LPC_ADC1))) {}
232 
233 	/* Setup threshold 0 low and high values to about 25% and 75% of max for
234 	     ADC1 only */
235 	Chip_ADC_SetThrLowValue(LPC_ADC1, 0, ((1 * 0xFFF) / 4));
236 	Chip_ADC_SetThrHighValue(LPC_ADC1, 0, ((3 * 0xFFF) / 4));
237 
238 	/* Clear all pending interrupts */
239 	Chip_ADC_ClearFlags(LPC_ADC0, Chip_ADC_GetFlags(LPC_ADC0));
240 	Chip_ADC_ClearFlags(LPC_ADC1, Chip_ADC_GetFlags(LPC_ADC1));
241 
242 	/* Enable sequence A completion interrupts for ADC0 */
243 	Chip_ADC_EnableInt(LPC_ADC0, ADC_INTEN_SEQA_ENABLE);
244 
245 	/* Enable sequence A completion and threshold crossing interrupts for ADC1_1 */
246 	Chip_ADC_EnableInt(LPC_ADC1, ADC_INTEN_SEQA_ENABLE |
247 					   ADC_INTEN_CMP_ENABLE(ADC_INTEN_CMP_CROSSTH, BOARD_ADC_CH));
248 
249 	/* Use threshold 0 for ADC channel and enable threshold interrupt mode for
250 	   channel as crossing */
251 	Chip_ADC_SelectTH0Channels(LPC_ADC1, ADC_THRSEL_CHAN_SEL_THR1(BOARD_ADC_CH));
252 	Chip_ADC_SetThresholdInt(LPC_ADC1, BOARD_ADC_CH, ADC_INTEN_THCMP_CROSSING);
253 
254 	/* Enable related ADC NVIC interrupts */
255 	NVIC_EnableIRQ(ADC0_SEQA_IRQn);
256 	NVIC_EnableIRQ(ADC1_SEQA_IRQn);
257 	NVIC_EnableIRQ(ADC1_THCMP);
258 
259 	/* Enable sequencers */
260 	Chip_ADC_EnableSequencer(LPC_ADC0, ADC_SEQA_IDX);
261 	Chip_ADC_EnableSequencer(LPC_ADC1, ADC_SEQA_IDX);
262 
263 	/* This example uses the periodic sysTick to manually trigger the ADC,
264 	   but a periodic timer can be used in a match configuration to start
265 	   an ADC sequence without software intervention. */
266 	SysTick_Config(Chip_Clock_GetSysTickClockRate() / TICKRATE_HZ);
267 
268 	/* Endless loop */
269 	while (1) {
270 		/* Sleep until something happens */
271 		__WFI();
272 
273 		if (threshold1Crossed) {
274 			threshold1Crossed = false;
275 			DEBUGSTR("********ADC1 threshold event********\r\n");
276 		}
277 
278 		/* Is a conversion sequence complete? */
279 		if (sequence0Complete) {
280 			showValudeADC(LPC_ADC0);
281 		}
282 		if (sequence1Complete) {
283 			showValudeADC(LPC_ADC1);
284 		}
285 	}
286 
287 	/* Should not run to here */
288 	return 0;
289 }
290