1 /*
2  * @brief LPC15xx ADC driver
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 "chip.h"
33 
34 /*****************************************************************************
35  * Private types/enumerations/variables
36  ****************************************************************************/
37 
38 /*****************************************************************************
39  * Public types/enumerations/variables
40  ****************************************************************************/
41 
42 /*****************************************************************************
43  * Private functions
44  ****************************************************************************/
45 
46 /* Set ADC interrupt bits (safe) */
Chip_ADC_SetIntBits(LPC_ADC_T * pADC,uint32_t intMask)47 void Chip_ADC_SetIntBits(LPC_ADC_T *pADC, uint32_t intMask)
48 {
49 	uint32_t temp;
50 
51 	/* Read and write values may not be the same, write 0 to
52 	   undefined bits */
53 	temp = pADC->INTEN & 0x07FFFFFF;
54 
55 	pADC->INTEN = temp | intMask;
56 }
57 
58 /* Clear ADC interrupt bits (safe) */
Chip_ADC_ClearIntBits(LPC_ADC_T * pADC,uint32_t intMask)59 void Chip_ADC_ClearIntBits(LPC_ADC_T *pADC, uint32_t intMask)
60 {
61 	uint32_t temp;
62 
63 	/* Read and write values may not be the same, write 0 to
64 	   undefined bits */
65 	temp = pADC->INTEN & 0x07FFFFFF;
66 
67 	pADC->INTEN = temp & ~intMask;
68 }
69 
70 /* Set ADC threshold selection bits (safe) */
Chip_ADC_SetTHRSELBits(LPC_ADC_T * pADC,uint32_t mask)71 void Chip_ADC_SetTHRSELBits(LPC_ADC_T *pADC, uint32_t mask)
72 {
73 	uint32_t temp;
74 
75 	/* Read and write values may not be the same, write 0 to
76 	   undefined bits */
77 	temp = pADC->CHAN_THRSEL & 0x00000FFF;
78 
79 	pADC->CHAN_THRSEL = temp | mask;
80 }
81 
82 /* Clear ADC threshold selection bits (safe) */
Chip_ADC_ClearTHRSELBits(LPC_ADC_T * pADC,uint32_t mask)83 void Chip_ADC_ClearTHRSELBits(LPC_ADC_T *pADC, uint32_t mask)
84 {
85 	uint32_t temp;
86 
87 	/* Read and write values may not be the same, write 0 to
88 	   undefined bits */
89 	temp = pADC->CHAN_THRSEL & 0x00000FFF;
90 
91 	pADC->CHAN_THRSEL = temp & ~mask;
92 }
93 
94 /*****************************************************************************
95  * Public functions
96  ****************************************************************************/
97 
98 /* Initialize the ADC peripheral */
Chip_ADC_Init(LPC_ADC_T * pADC,uint32_t flags)99 void Chip_ADC_Init(LPC_ADC_T *pADC, uint32_t flags)
100 {
101 	/* Power up ADC and enable ADC base clock */
102 	if (pADC == LPC_ADC0) {
103 		Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC0_PD);
104 		Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC0);
105 		Chip_SYSCTL_PeriphReset(RESET_ADC0);
106 	}
107 	else {
108 		Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC1_PD);
109 		Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC1);
110 		Chip_SYSCTL_PeriphReset(RESET_ADC1);
111 	}
112 
113 	/* Disable ADC interrupts */
114 	pADC->INTEN = 0;
115 
116 	/* Set ADC control options */
117 	pADC->CTRL = flags;
118 }
119 
120 /* Shutdown ADC */
Chip_ADC_DeInit(LPC_ADC_T * pADC)121 void Chip_ADC_DeInit(LPC_ADC_T *pADC)
122 {
123 	pADC->INTEN = 0;
124 	pADC->CTRL = 0;
125 
126 	/* Stop ADC clock and then power down ADC */
127 	if (pADC == LPC_ADC0) {
128 		Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_ADC0);
129 		Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_ADC0_PD);
130 	}
131 	else {
132 		Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_ADC1);
133 		Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_ADC1_PD);
134 	}
135 }
136 
137 /* Set ADC clock rate */
Chip_ADC_SetClockRate(LPC_ADC_T * pADC,uint32_t rate)138 void Chip_ADC_SetClockRate(LPC_ADC_T *pADC, uint32_t rate)
139 {
140 	uint32_t div;
141 
142 	/* Get ADC clock source to determine base ADC rate. IN sychronous mode,
143 	   the ADC base clock comes from the system clock. In ASYNC mode, it
144 	   comes from the ASYNC ADC clock and this function doesn't work. */
145 	div = Chip_Clock_GetSystemClockRate() / rate;
146 	if (div == 0) {
147 		div = 1;
148 	}
149 
150 	Chip_ADC_SetDivider(pADC, (uint8_t) div - 1);
151 }
152 
153 /* Start ADC calibration */
Chip_ADC_StartCalibration(LPC_ADC_T * pADC)154 void Chip_ADC_StartCalibration(LPC_ADC_T *pADC)
155 {
156 	/* Set calibration mode */
157 	pADC->CTRL |= ADC_CR_CALMODEBIT;
158 
159 	/* Clear ASYNC bit */
160 	pADC->CTRL &= ~ADC_CR_ASYNMODE;
161 
162 	/* Setup ADC for about 500KHz (per UM) */
163 	Chip_ADC_SetClockRate(pADC, 500000);
164 
165 	/* Clearn low power bit */
166 	pADC->CTRL &= ~ADC_CR_LPWRMODEBIT;
167 
168 	/* Calibration is only complete when ADC_CR_CALMODEBIT bit has cleared */
169 }
170 
171 /* Helper function for safely setting ADC sequencer register bits */
Chip_ADC_SetSequencerBits(LPC_ADC_T * pADC,ADC_SEQ_IDX_T seqIndex,uint32_t bits)172 void Chip_ADC_SetSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits)
173 {
174 	uint32_t temp;
175 
176 	/* Read sequencer register and mask off bits 20..25 */
177 	temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20);
178 
179 	/* OR in passed bits */
180 	pADC->SEQ_CTRL[seqIndex] = temp | bits;
181 }
182 
183 /* Helper function for safely clearing ADC sequencer register bits */
Chip_ADC_ClearSequencerBits(LPC_ADC_T * pADC,ADC_SEQ_IDX_T seqIndex,uint32_t bits)184 void Chip_ADC_ClearSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits)
185 {
186 	uint32_t temp;
187 
188 	/* Read sequencer register and mask off bits 20..25 */
189 	temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20);
190 
191 	/* OR in passed bits */
192 	pADC->SEQ_CTRL[seqIndex] = temp & ~bits;
193 }
194 
195 /* Enable interrupts in ADC (sequencers A/B and overrun) */
Chip_ADC_EnableInt(LPC_ADC_T * pADC,uint32_t intMask)196 void Chip_ADC_EnableInt(LPC_ADC_T *pADC, uint32_t intMask)
197 {
198 	Chip_ADC_SetIntBits(pADC, intMask);
199 }
200 
201 /* Disable interrupts in ADC (sequencers A/B and overrun) */
Chip_ADC_DisableInt(LPC_ADC_T * pADC,uint32_t intMask)202 void Chip_ADC_DisableInt(LPC_ADC_T *pADC, uint32_t intMask)
203 {
204 	Chip_ADC_ClearIntBits(pADC, intMask);
205 }
206 
207 /* Enable a threshold event interrupt in ADC */
Chip_ADC_SetThresholdInt(LPC_ADC_T * pADC,uint8_t ch,ADC_INTEN_THCMP_T thInt)208 void Chip_ADC_SetThresholdInt(LPC_ADC_T *pADC, uint8_t ch, ADC_INTEN_THCMP_T thInt)
209 {
210 	int shiftIndex = 3 + (ch * 2);
211 
212 	/* Clear current bits first */
213 	Chip_ADC_ClearIntBits(pADC, (ADC_INTEN_CMP_MASK << shiftIndex));
214 
215 	/* Set new threshold interrupt type */
216 	Chip_ADC_SetIntBits(pADC, ((uint32_t) thInt << shiftIndex));
217 }
218 
219 /* Select threshold 0 values for comparison for selected channels */
Chip_ADC_SelectTH0Channels(LPC_ADC_T * pADC,uint32_t channels)220 void Chip_ADC_SelectTH0Channels(LPC_ADC_T *pADC, uint32_t channels)
221 {
222 	Chip_ADC_ClearTHRSELBits(pADC, channels);
223 }
224 
225 /* Select threshold 1 value for comparison for selected channels */
Chip_ADC_SelectTH1Channels(LPC_ADC_T * pADC,uint32_t channels)226 void Chip_ADC_SelectTH1Channels(LPC_ADC_T *pADC, uint32_t channels)
227 {
228 	Chip_ADC_SetTHRSELBits(pADC, channels);
229 }
230