1 /*
2  * @brief LPC15xx ADC example
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2014
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 #define TICKRATE_HZ (100)	/* 100 SysTicks per second */
40 
41 #if defined(BOARD_NXP_LPCXPRESSO_1549)
42 /* ADC is connected to the pot on LPCXPresso base boards */
43 #define BOARD_ADC_CH 1
44 /* ADC Clock set to 36MHz for this board as SysClk is 72MHz and max ADC clock is 50MHz*/
45 #define ADC_CLOCK_RATE (36000000)
46 
47 #else
48 #warning "Using ADC channel 8 for this example, please select for your board. Also setup ADC Clock"
49 #define BOARD_ADC_CH 8
50 #endif
51 
52 /* RAM Block Sizes for ADC ROM API */
53 #define RAMBLOCK_H 60
54 #define BUFFER_SIZE 12
55 
56 static volatile int ticks;
57 static bool sequence0Complete, sequence1Complete, threshold1Crossed;
58 
59 static uint32_t                 size_in_bytes;
60 static const ADCD_API_T *pAdcApi;	/* define pointer to type API function addr table */
61 static ADC_HANDLE_T         adc_handle[2];	/* handle to ADC API */
62 static ADC_PARAM_T          param[2];	/* Param Structure for ADC ROM API */
63 static ADC_CONFIG_T         adc_cfg[2];	/* Config Structure for ADC ROM API */
64 static uint32_t                 start_of_ram_block[2][RAMBLOCK_H];		/* RAM Block */
65 static uint32_t                 adc_buffer[2][BUFFER_SIZE];	/* Buffer for ADC data */
66 static ErrorCode_t          err_code;
67 
68 /*****************************************************************************
69  * Public types/enumerations/variables
70  ****************************************************************************/
71 
72 /*****************************************************************************
73  * Private functions
74  ****************************************************************************/
75 
showValudeADC(LPC_ADC_T * pADC)76 void showValudeADC(LPC_ADC_T *pADC)
77 {
78 	uint32_t rawSample;
79 
80 	if (pADC == LPC_ADC0) {
81 		rawSample = adc_buffer[0][0];
82 		DEBUGOUT("ADC%d_%d: Sample value = 0x%x (Data sample %d)\r\n", 0, 0, rawSample, 0);
83 	}
84 	else {
85 		rawSample = adc_buffer[1][BOARD_ADC_CH];
86 		DEBUGOUT("ADC%d_%d: Sample value = 0x%x (Data sample %d)\r\n", 1, BOARD_ADC_CH, rawSample, BOARD_ADC_CH);
87 	}
88 }
89 
adc_seq0_callback(ADC_HANDLE_T handle)90 void  adc_seq0_callback(ADC_HANDLE_T handle)
91 {
92 	ADC_DRIVER_T *driver = (ADC_DRIVER_T *) handle;
93 
94 	if ((ErrorCode_t) driver->error_code == LPC_OK) {
95 		if (driver->comp_flags & 0x01) {
96 			sequence0Complete = true;
97 		}
98 	}
99 }
100 
adc_seq1_callback(ADC_HANDLE_T handle)101 void  adc_seq1_callback(ADC_HANDLE_T handle)
102 {
103 	ADC_DRIVER_T *driver = (ADC_DRIVER_T *) handle;
104 
105 	if ((ErrorCode_t) driver->error_code == LPC_OK) {
106 		if (driver->comp_flags & (1 << BOARD_ADC_CH)) {
107 			sequence1Complete = true;
108 		}
109 	}
110 }
111 
adc_thcmp_callback(ErrorCode_t error_code,uint32_t num_channel)112 void adc_thcmp_callback(ErrorCode_t error_code, uint32_t num_channel)
113 {
114 	if (error_code == LPC_OK) {
115 		if (num_channel & (1 << BOARD_ADC_CH)) {
116 			threshold1Crossed = true;
117 		}
118 	}
119 }
120 
121 /*****************************************************************************
122  * Public functions
123  ****************************************************************************/
124 
125 /**
126  * @brief	Handle interrupt from SysTick timer
127  * @return	Nothing
128  */
SysTick_Handler(void)129 void SysTick_Handler(void)
130 {
131 	static uint32_t count;
132 
133 	/* Every 1/2 second */
134 	count++;
135 	if (count >= (TICKRATE_HZ / 2)) {
136 		count = 0;
137 		/* ADC0 Param for SEQA read */
138 		param[0].buffer = (uint32_t *) adc_buffer[0];
139 		param[0].driver_mode = 0x01;/* Interrupt Mode */
140 		param[0].seqa_hwtrig = 0;
141 		param[0].adc_cfg = &adc_cfg[0];	/* ADC0 Config */
142 		param[0].comp_flags = 0;
143 		param[0].seqa_callback_pt = adc_seq0_callback;	/* Call back for SeqA Interrupt */
144 		/* ADC1 Param for SEQA read */
145 		param[1].buffer = (uint32_t *) adc_buffer[1];
146 		param[1].driver_mode = 0x01;/* Interrupt Mode */
147 		param[1].seqa_hwtrig = 0;
148 		param[1].adc_cfg = &adc_cfg[1];	/* ADC1 Config */
149 		param[1].comp_flags = 0;
150 		param[1].seqa_callback_pt = adc_seq1_callback;	/* Call back for SeqA Interrupt */
151 		param[1].thcmp_callback_pt = adc_thcmp_callback;/* Call back for Threshold Compare Interrupt */
152 		err_code = LPC_OK;
153 		err_code |= (ErrorCode_t) pAdcApi->adc_seqa_read(adc_handle[0], &param[0]);
154 		err_code |= (ErrorCode_t) pAdcApi->adc_seqa_read(adc_handle[1], &param[1]);
155 		if (err_code != LPC_OK) {
156 			Board_LED_Toggle(0);
157 		}
158 	}
159 }
160 
161 /**
162  * @brief	Handle interrupt from ADC0 sequencer A
163  * @return	Nothing
164  */
ADC0A_IRQHandler(void)165 void ADC0A_IRQHandler(void)
166 {
167 	pAdcApi->adc_seqa_isr(adc_handle[0]);
168 }
169 
170 /**
171  * @brief	Handle interrupt from ADC1 sequencer A
172  * @return	Nothing
173  */
ADC1A_IRQHandler(void)174 void ADC1A_IRQHandler(void)
175 {
176 	pAdcApi->adc_seqa_isr(adc_handle[1]);
177 }
178 
179 /**
180  * @brief	Handle threshold interrupt from ADC1
181  * @return	Nothing
182  */
ADC1_THCMP_IRQHandler(void)183 void ADC1_THCMP_IRQHandler(void)
184 {
185 	pAdcApi->adc_thcmp_isr(adc_handle[1]);
186 }
187 
188 /**
189  * @brief	main routine for ADC example
190  * @return	Function should not exit
191  */
main(void)192 int main(void)
193 {
194 	SystemCoreClockUpdate();
195 	Board_Init();
196 	DEBUGSTR("ADC ROM sequencer demo\r\n");
197 
198 	/* Power up, enable clock and reset ADC0 */
199 	Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC0_PD);
200 	Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC0);
201 	Chip_SYSCTL_PeriphReset(RESET_ADC0);
202 	/* Power up, enable clock and reset ADC1 */
203 	Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC1_PD);
204 	Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC1);
205 	Chip_SYSCTL_PeriphReset(RESET_ADC1);
206 	/* Power up the internal temperature sensor */
207 	Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_TS_PD);
208 
209 #if defined(BOARD_NXP_LPCXPRESSO_1549)
210 	/* Disables pullups/pulldowns and disable digital mode */
211 	Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 9, (IOCON_MODE_INACT | IOCON_ADMODE_EN));
212 
213 	/* Assign ADC1_1 to PIO0_9 via SWM (fixed pin) */
214 	Chip_SWM_EnableFixedPin(SWM_FIXED_ADC1_1);
215 
216 #else
217 #warning "No ADC setup for this example"
218 #endif
219 	/* Initialize ROM API base address for ADC */
220 	pAdcApi = LPC_ADCD_API;
221 	size_in_bytes = pAdcApi->adc_get_mem_size();
222 	if (size_in_bytes / 4 > RAMBLOCK_H) {
223 		/* Adjust RAMBLOCK size in this case */
224 		return 1;
225 	}
226 	/* ADC Handle Setup*/
227 	adc_handle[0] = pAdcApi->adc_setup(LPC_ADC0_BASE, (uint8_t *) start_of_ram_block[0]);
228 	adc_handle[1] = pAdcApi->adc_setup(LPC_ADC1_BASE, (uint8_t *) start_of_ram_block[1]);
229 	/* ADC0 Config */
230 	adc_cfg[0].system_clock = SystemCoreClock;	/* System clock */
231 	adc_cfg[0].adc_clock = 500000;	/* ADC clock set to 500KHz for calibration*/
232 	/* ADC1 Config */
233 	adc_cfg[1].system_clock = SystemCoreClock;	/* System clock */
234 	adc_cfg[1].adc_clock = 500000;	/* ADC clock set to 500KHz for calibration*/
235 	pAdcApi->adc_calibration(adc_handle[0], &adc_cfg[0]);
236 	pAdcApi->adc_calibration(adc_handle[1], &adc_cfg[1]);
237 
238 	/* ADC0 Config for Init */
239 	adc_cfg[0].system_clock = SystemCoreClock;	/* System clock */
240 	adc_cfg[0].adc_clock = ADC_CLOCK_RATE;	/* ADC clock */
241 	adc_cfg[0].async_mode = 0;	/* Synchronous mode */
242 	adc_cfg[0].tenbit_mode = 0;	/* 12 Bit ADC mode */
243 	adc_cfg[0].lpwr_mode = 0;	/* Disable low power mode */
244 	adc_cfg[0].input_sel = ADC_INSEL_TS;
245 	adc_cfg[0].seqa_ctrl = (ADC_SEQ_CTRL_CHANSEL(0) | ADC_SEQ_CTRL_MODE_EOS);
246 	adc_cfg[0].channel_num = 1;	/* Channel number is one higher than the maximum channel number used */
247 	/* ADC1 Config for Init */
248 	adc_cfg[1].system_clock = SystemCoreClock;	/* System clock */
249 	adc_cfg[1].adc_clock = ADC_CLOCK_RATE;	/* ADC clock */
250 	adc_cfg[1].async_mode = 0;	/* Synchronous mode */
251 	adc_cfg[1].tenbit_mode = 0;	/* 12 Bit ADC mode */
252 	adc_cfg[1].lpwr_mode = 0;	/* Disable low power mode */
253 	adc_cfg[1].seqa_ctrl = (ADC_SEQ_CTRL_CHANSEL(BOARD_ADC_CH) | ADC_SEQ_CTRL_MODE_EOS);
254 	adc_cfg[1].thrsel = 0;
255 	adc_cfg[1].thr0_low = ((1 * 0xFFF) / 4) << 4;
256 	adc_cfg[1].thr0_high = ((3 * 0xFFF) / 4) << 4;
257 	adc_cfg[1].thcmp_en = ADC_INTEN_CMP_ENABLE(ADC_INTEN_CMP_CROSSTH, BOARD_ADC_CH);
258 	adc_cfg[1].channel_num = BOARD_ADC_CH + 1;	/* Channel number is one higher than the maximum channel number used */
259 	pAdcApi->adc_init(adc_handle[0], &adc_cfg[0]);
260 	pAdcApi->adc_init(adc_handle[1], &adc_cfg[1]);
261 
262 	/* When using ADC ROM API's lower the priority of ADC Sequence completion interrupt when compared to the threshold interrupt*/
263 	NVIC_SetPriority(ADC1_SEQA_IRQn, 1);
264 	/* Enable related ADC NVIC interrupts */
265 	NVIC_EnableIRQ(ADC0_SEQA_IRQn);
266 	NVIC_EnableIRQ(ADC1_SEQA_IRQn);
267 	NVIC_EnableIRQ(ADC1_THCMP);
268 
269 	/* This example uses the periodic sysTick to manually trigger the ADC,
270 	   but a periodic timer can be used in a match configuration to start
271 	   an ADC sequence without software intervention. */
272 	SysTick_Config(Chip_Clock_GetSysTickClockRate() / TICKRATE_HZ);
273 
274 	/* Endless loop */
275 	while (1) {
276 		/* Sleep until something happens */
277 		__WFI();
278 
279 		if (threshold1Crossed) {
280 			threshold1Crossed = false;
281 			DEBUGSTR("********ADC1 threshold event********\r\n");
282 		}
283 
284 		/* Is a conversion sequence complete? */
285 		if (sequence0Complete) {
286 			sequence0Complete = false;
287 			showValudeADC(LPC_ADC0);
288 		}
289 		if (sequence1Complete) {
290 			sequence1Complete = false;
291 			showValudeADC(LPC_ADC1);
292 		}
293 	}
294 
295 	/* Should not run to here */
296 	return 0;
297 }
298