1 /*
2  * @brief LPC11u6x 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 bool tempSequenceComplete;
40 static volatile int tempSampleIdx;
41 
42 /* Temperature sample ADC read buffer - only index 9 is used for the valid
43    temperature sample. */
44 #define TEMPSAMPLES 10
45 static uint32_t temp[TEMPSAMPLES];
46 
47 #define TICKRATE_HZ (100)	/* 100 ticks per second */
48 
49 /*****************************************************************************
50  * Public types/enumerations/variables
51  ****************************************************************************/
52 
53 /*****************************************************************************
54  * Private functions
55  ****************************************************************************/
56 
57 /* This starts an ADC temperature sampling sequence using the recommended
58    burst method. It bursts 10 temperature sensor samples via the ADC and
59    then stops the ADC sequencer. The single sequence (non-burst) mode can
60    also be used for ADC temperature sensor read. */
tempStartCycle(void)61 static void tempStartCycle(void)
62 {
63 	tempSampleIdx = 0;
64 	tempSequenceComplete = false;
65 
66 	/* Enable burst mode */
67 	Chip_ADC_StartBurstSequencer(LPC_ADC0, ADC_SEQA_IDX);
68 }
69 
70 /* Used to indicate when a temperature cycle is complete and the sample
71    is ready */
tempCycleComplete(void)72 static bool tempCycleComplete(void)
73 {
74 	return tempSequenceComplete;
75 }
76 
77 /* Returns the last temperature sample only. Only valid if tempCycleComplete()
78    returns true */
tempGetSample(void)79 static uint32_t tempGetSample(void)
80 {
81 	tempSequenceComplete = false;
82 	return temp[TEMPSAMPLES - 1];
83 }
84 
85 /*****************************************************************************
86  * Public functions
87  ****************************************************************************/
88 
89 /**
90  * @brief	Handle interrupt from SysTick timer
91  * @return	Nothing
92  */
SysTick_Handler(void)93 void SysTick_Handler(void)
94 {
95 	static uint32_t count;
96 
97 	/* Every 1/2 second */
98 	count++;
99 	if (count >= (TICKRATE_HZ / 1)) {
100 		count = 0;
101 
102 		/* Restart temperature cycle */
103 		tempStartCycle();
104 	}
105 }
106 
107 /**
108  * @brief	Handle interrupt from ADC sequencer A
109  * @return	Nothing
110  */
ADC0A_IRQHandler(void)111 void ADC0A_IRQHandler(void)
112 {
113 	uint32_t pending;
114 
115 	/* Get pending interrupts */
116 	pending = Chip_ADC_GetFlags(LPC_ADC0);
117 
118 	/* Sequence A completion interrupt */
119 	if (pending & ADC_FLAGS_SEQA_INT_MASK) {
120 		if (tempSampleIdx < TEMPSAMPLES) {
121 			/* Save sample */
122 			temp[tempSampleIdx] = Chip_ADC_GetDataReg(LPC_ADC0, 0);
123 			tempSampleIdx++;
124 
125 			if (tempSampleIdx >= TEMPSAMPLES) {
126 				Chip_ADC_StopBurstSequencer(LPC_ADC0, ADC_SEQA_IDX);
127 				tempSequenceComplete = true;
128 			}
129 		}
130 	}
131 
132 	/* Clear any pending interrupts */
133 	Chip_ADC_ClearFlags(LPC_ADC0, pending);
134 }
135 
136 /**
137  * @brief	main routine for ADC example
138  * @return	Function should not exit
139  */
main(void)140 int main(void)
141 {
142 	uint32_t rawSample;
143 
144 	SystemCoreClockUpdate();
145 	Board_Init();
146 	DEBUGSTR("Temperature sensor demo\r\n");
147 
148 	/* Setup ADC for 12-bit mode and normal power */
149 	Chip_ADC_Init(LPC_ADC0, 0);
150 
151 	/* Setup ADC clock rate */
152 	Chip_ADC_SetClockRate(LPC_ADC0, 250000);
153 
154 	/* For ADC0, select temperature sensor for channel 0 on ADC0 */
155 	Chip_ADC_SetADC0Input(LPC_ADC0, ADC_INSEL_TS);
156 
157 	/* Setup a sequencer to do the following:
158 	   Perform ADC conversion of ADC channels 0 with EOS interrupt */
159 	Chip_ADC_SetupSequencer(LPC_ADC0, ADC_SEQA_IDX, (ADC_SEQ_CTRL_CHANSEL(0) |
160 													 ADC_SEQ_CTRL_MODE_EOS));
161 
162 	/* Power up the internal temperature sensor - this also selects the
163 	    temperature sensor as the input for the ADC0 input */
164 	Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_TS_PD);
165 
166 	/* Use higher voltage trim */
167 	Chip_ADC_SetTrim(LPC_ADC0, ADC_TRIM_VRANGE_HIGHV);
168 
169 	/* Need to do a calibration after initialization and trim */
170 	Chip_ADC_StartCalibration(LPC_ADC0);
171 	while (!(Chip_ADC_IsCalibrationDone(LPC_ADC0))) {}
172 
173 	/* Clear all pending interrupts */
174 	Chip_ADC_ClearFlags(LPC_ADC0, Chip_ADC_GetFlags(LPC_ADC0));
175 
176 	/* Enable ADC sequence A completion interrupt */
177 	Chip_ADC_EnableInt(LPC_ADC0, ADC_INTEN_SEQA_ENABLE);
178 
179 	/* Enable ADC NVIC interrupt */
180 	NVIC_EnableIRQ(ADC0_SEQA_IRQn);
181 
182 	/* Enable sequencer */
183 	Chip_ADC_EnableSequencer(LPC_ADC0, ADC_SEQA_IDX);
184 
185 	/* This example uses the periodic sysTick to manually trigger
186 	   the ADC burst cycle */
187 	SysTick_Config(SystemCoreClock / TICKRATE_HZ);
188 
189 	/* Endless loop */
190 	while (1) {
191 		/* Sleep until something happens */
192 		__WFI();
193 
194 		/* Is a conversion sequence complete? */
195 		if (tempCycleComplete()) {
196 			rawSample = tempGetSample();
197 			if ((rawSample & ADC_SEQ_GDAT_DATAVALID) != 0) {
198 				DEBUGOUT("Sampled temp value = 0x%04x (first = 0x%04x)\r", ADC_DR_RESULT(rawSample),
199 						 ADC_DR_RESULT(temp[0]));
200 			}
201 			else {
202 				DEBUGSTR("\r\nInvalid sample read\r\n");
203 			}
204 		}
205 	}
206 
207 	/* Should not run to here */
208 	return 0;
209 }
210