1 /*
2 * Copyright 2021 MindMotion Microelectronics Co., Ltd.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "hal_adc.h"
9
ADC_Init(ADC_Type * ADCx,ADC_Init_Type * init)10 void ADC_Init(ADC_Type * ADCx, ADC_Init_Type * init)
11 {
12 uint32_t cfg;
13
14 if (!init)
15 {
16 return;
17 }
18
19 cfg = ADCx->ADCFG & ~( ADC_ADCFG_ADCPREH_MASK
20 | ADC_ADCFG_ADCPREL_MASK
21 | ADC_ADCFG_RSLTCTL_MASK
22 | ADC_ADCR_ALIGN_MASK )
23 ;
24 /* Prescaler & Resolution. */
25 cfg |= ADC_ADCFG_ADCPREL(init->ClockDiv)
26 | ADC_ADCFG_ADCPREH((init->ClockDiv)>>1)
27 | ADC_ADCFG_RSLTCTL(init->Resolution)
28 ;
29 ADCx->ADCFG = cfg;
30 /* ADC conversion mode and conversion data result align. */
31 ADCx->ADCR = (ADCx->ADCR & ~( ADC_ADCR_ADMD_MASK | ADC_ADCR_ALIGN_MASK) )
32 | ADC_ADCR_ADMD(init->ConvMode)
33 | ADC_ADCR_ALIGN(init->Align)
34 ;
35 }
36
ADC_Enable(ADC_Type * ADCx,bool enable)37 void ADC_Enable(ADC_Type * ADCx, bool enable)
38 {
39 if (enable)
40 {
41 ADCx->ADCFG |= ADC_ADCFG_ADEN_MASK;
42 }
43 else
44 {
45 ADCx->ADCFG &= ~ADC_ADCFG_ADEN_MASK;
46 }
47 }
48
ADC_EnableTempSensor(ADC_Type * ADCx,bool enable)49 void ADC_EnableTempSensor(ADC_Type * ADCx, bool enable)
50 {
51 if (enable)
52 {
53 ADCx->ADCFG |= ADC_ADCFG_TSEN_MASK;
54 }
55 else
56 {
57 ADCx->ADCFG &= ~ADC_ADCFG_TSEN_MASK;
58 }
59 }
60
61 /* Use VBG 1.2V as default voltage sensor. */
ADC_EnableVoltSensor(ADC_Type * ADCx,bool enable)62 void ADC_EnableVoltSensor(ADC_Type * ADCx, bool enable)
63 {
64 if (enable)
65 {
66 ADCx ->ADCFG |= ADC_ADCFG_VSEN_MASK;
67 }
68 else
69 {
70 ADCx->ADCFG &= ~ADC_ADCFG_VSEN_MASK;
71 }
72 }
73
ADC_EnableDMA(ADC_Type * ADCx,bool enable)74 void ADC_EnableDMA(ADC_Type * ADCx, bool enable)
75 {
76 if (enable)
77 {
78 ADCx->ADCR |= ADC_ADCR_DMAEN_MASK;
79 }
80 else
81 {
82 ADCx->ADCR &= ~ADC_ADCR_DMAEN_MASK;
83 }
84 }
85
ADC_EnableInterrupts(ADC_Type * ADCx,uint32_t interrupts,bool enable)86 void ADC_EnableInterrupts(ADC_Type * ADCx, uint32_t interrupts, bool enable)
87 {
88 if (enable)
89 {
90 if ( 0u != (ADC_STATUS_CONV_SLOT_DONE & interrupts) )
91 {
92 ADCx->ADCR |= ADC_ADCR_EOCIE_MASK;
93 }
94 if ( 0u != (ADC_STATUS_CONV_SAMPLE_DONE & interrupts) )
95 {
96 ADCx->ADCR |= ADC_ADCR_EOSMPIE_MASK;
97 }
98 if ( 0u != (ADC_STATUS_CONV_SEQ_DONE & interrupts) )
99 {
100 ADCx->ADCR |= ADC_ADCR_ADIE_MASK;
101 }
102 if ( 0u != (ADC_STATUS_COMPARE_DONE & interrupts) )
103 {
104 ADCx->ADCR |= ADC_ADCR_ADWIE_MASK;
105 }
106 }
107 else
108 {
109 if ( 0u != (ADC_STATUS_CONV_SLOT_DONE & interrupts) )
110 {
111 ADCx->ADCR &= ~ADC_ADCR_EOCIE_MASK;
112 }
113 if ( 0u != (ADC_STATUS_CONV_SAMPLE_DONE & interrupts) )
114 {
115 ADCx->ADCR &= ~ADC_ADCR_EOSMPIE_MASK;
116 }
117 if ( 0u != (ADC_STATUS_CONV_SEQ_DONE & interrupts) )
118 {
119 ADCx->ADCR &= ~ADC_ADCR_ADIE_MASK;
120 }
121 if ( 0u != (ADC_STATUS_COMPARE_DONE & interrupts) )
122 {
123 ADCx->ADCR &= ~ADC_ADCR_ADWIE_MASK;
124 }
125 }
126 }
127
ADC_GetStatus(ADC_Type * ADCx)128 uint32_t ADC_GetStatus(ADC_Type * ADCx)
129 {
130 uint32_t flags = 0u;
131
132 if ( 0u != (ADC_ADSTAEXT_EOCIF_MASK & ADCx->ADSTAEXT) )
133 {
134 flags |= ADC_STATUS_CONV_SLOT_DONE;
135 }
136 if ( 0u != (ADC_ADSTAEXT_EOSMPIF_MASK & ADCx->ADSTAEXT) )
137 {
138 flags |= ADC_STATUS_CONV_SAMPLE_DONE;
139 }
140 if ( 0u != (ADC_ADSTA_ADIF_MASK & ADCx->ADSTA) )
141 {
142 flags |= ADC_STATUS_CONV_SEQ_DONE;
143 }
144 if ( 0u != (ADC_ADSTA_ADWIF_MASK & ADCx->ADSTA) )
145 {
146 flags |= ADC_STATUS_COMPARE_DONE;
147 }
148
149 return flags;
150 }
151
ADC_ClearStatus(ADC_Type * ADCx,uint32_t flags)152 void ADC_ClearStatus(ADC_Type * ADCx, uint32_t flags)
153 {
154
155 if ( 0u != (ADC_STATUS_CONV_SLOT_DONE & flags) )
156 {
157 ADCx->ADSTAEXT = ADC_ADSTAEXT_EOCIF_MASK;
158 }
159 if ( 0u != (ADC_STATUS_CONV_SAMPLE_DONE & flags) )
160 {
161 ADCx->ADSTAEXT = ADC_ADSTAEXT_EOSMPIF_MASK;
162 }
163 if ( 0u != (ADC_STATUS_CONV_SEQ_DONE & flags) )
164 {
165 ADCx->ADSTA = ADC_ADSTA_ADIF_MASK;
166 }
167 if ( 0u != (ADC_STATUS_COMPARE_DONE & flags) )
168 {
169 ADCx->ADSTA = ADC_ADSTA_ADWIF_MASK;
170 }
171 }
172
ADC_GetConvResult(ADC_Type * ADCx,uint32_t * channel,uint32_t * flags)173 uint32_t ADC_GetConvResult(ADC_Type * ADCx, uint32_t * channel, uint32_t * flags)
174 {
175 uint32_t tmp32 = ADCx->ADDATA;
176
177 *channel = (tmp32 & ADC_ADDATA_CHANNELSEL_MASK) >> ADC_ADDATA_CHANNELSEL_SHIFT;
178 if (flags)
179 {
180 *flags = (tmp32 & (ADC_ADDATA_OVERRUN_MASK | ADC_ADDATA_VALID_MASK) ) >> ADC_ADDATA_OVERRUN_SHIFT;
181 }
182
183 return (tmp32 & ADC_ADDATA_DATA_MASK ) >> ADC_ADDATA_DATA_SHIFT;
184 }
185
ADC_GetChnConvResult(ADC_Type * ADCx,uint32_t channel,uint32_t * flags)186 uint32_t ADC_GetChnConvResult(ADC_Type * ADCx, uint32_t channel, uint32_t * flags)
187 {
188 uint32_t tmp32 = ADCx ->ADDR[channel];
189
190 if (flags)
191 {
192 *flags = (tmp32 & (ADC_ADDR_OVERRUN_MASK | ADC_ADDR_VALID_MASK) ) >> ADC_ADDR_OVERRUN_SHIFT;
193 }
194
195 return (tmp32 & ADC_ADDR_DATA_MASK ) >> ADC_ADDR_DATA_SHIFT;
196 }
197
ADC_SetChnSampleTime(ADC_Type * ADCx,uint32_t channel,ADC_SampleTime_Type sample_time)198 void ADC_SetChnSampleTime(ADC_Type * ADCx, uint32_t channel, ADC_SampleTime_Type sample_time)
199 {
200 if (channel < 8u)
201 {
202 ADCx->SMPR1 = (ADCx->SMPR1 & ~(0xF << (4u * channel))) | (sample_time << (4u * channel));
203 }
204 else
205 {
206 channel-= 8u;
207 ADCx->SMPR2 = (ADCx->SMPR2 & ~(0xF << (4u * channel))) | (sample_time << (4u * channel));
208 }
209 }
210
ADC_EnableHwTrigger(ADC_Type * ADCx,ADC_HwTrgConf_Type * conf)211 void ADC_EnableHwTrigger(ADC_Type * ADCx, ADC_HwTrgConf_Type * conf)
212 {
213 if ( !conf )
214 {
215 ADCx->ADCR &= ~ADC_ADCR_TRGEN_MASK;
216 return;
217 }
218 /* Enable the hardware trigger. */
219 ADCx->ADCR = ( ADCx->ADCR & ~(ADC_ADCR_TRGSELL_MASK | ADC_ADCR_TRGSELH_MASK | ADC_ADCR_TRGSHIFT_MASK | ADC_ADCR_TRGEDGE_MASK) )
220 | ADC_ADCR_TRGEN_MASK
221 | ADC_ADCR_TRGSELL(conf->Source & 0x7)
222 | ADC_ADCR_TRGSELH(conf->Source >> 3u)
223 | ADC_ADCR_TRGSHIFT(conf->DelayCycle)
224 | ADC_ADCR_TRGEDGE(conf->Edge)
225 ;
226 }
227
ADC_EnableRegSeq(ADC_Type * ADCx,ADC_RegSeqConf_Type * conf)228 void ADC_EnableRegSeq(ADC_Type * ADCx, ADC_RegSeqConf_Type * conf)
229 {
230 if (!conf)
231 {
232 return;
233 }
234
235 ADCx->ANYCR &= ~ADC_ANYCR_CHANYMDEN_MASK;
236
237 /* enable regular channels. */
238 ADCx->ADCHS = conf->SeqSlots;
239 ADCx->ADCR = (ADCx->ADCR & ~ADC_ADCR_SCANDIR_MASK)
240 | ADC_ADCR_SCANDIR(conf->SeqDirection)
241 ;
242 }
243
ADC_EnableAnySeq(ADC_Type * ADCx,ADC_AnySeqConf_Type * conf)244 void ADC_EnableAnySeq(ADC_Type * ADCx, ADC_AnySeqConf_Type * conf)
245 {
246 if (!conf)
247 {
248 ADCx->ANYCR &= ~ADC_ANYCR_CHANYMDEN_MASK;
249 return;
250 }
251
252 if (conf->SeqLen > 16u)
253 {
254 return; /* the available range of seq length is within 16u. */
255 }
256
257 /* enable any channel sequence mode. */
258 ADCx->ANYCR |= ADC_ANYCR_CHANYMDEN_MASK;
259 /* select the any slots number. */
260 ADCx->ANYCFG = ADC_ANYCFG_CHANYNUM(conf->SeqLen - 1u);
261
262 /* fill the channels into each slot of ANY sequence. */
263 uint32_t offset;
264 for (uint32_t i = 0u; i < conf->SeqLen; i++)
265 {
266 if (i < 8u)
267 {
268 offset = i;
269 ADCx->CHANY0 = (ADCx->CHANY0 & ~(0xF << (4u * offset))) | (conf->SeqChannels[i] << (4u * offset));
270 }
271 else if (i < 16)
272 {
273 offset = i - 8u;
274 ADCx->CHANY1 = (ADCx->CHANY1 & ~(0xF << (4u * offset))) | (conf->SeqChannels[i] << (4u * offset));
275 }
276 }
277 }
278
ADC_DoSwTrigger(ADC_Type * ADCx,bool enable)279 void ADC_DoSwTrigger(ADC_Type * ADCx, bool enable)
280 {
281 if (enable)
282 {
283 ADCx->ADCR |= ADC_ADCR_ADST_MASK;
284 }
285 else
286 {
287 ADCx->ADCR &= ~ADC_ADCR_ADST_MASK;
288 }
289 }
290
ADC_EnableHwComp(ADC_Type * ADCx,ADC_HwCompConf_Type * conf)291 void ADC_EnableHwComp(ADC_Type * ADCx, ADC_HwCompConf_Type * conf)
292 {
293 if ( !conf )
294 {
295 /* disable the hardware compare feature for both regular & any seq. */
296 ADCx->ADCFG &= ~ADC_ADCFG_ADWEN_MASK;
297 return;
298 }
299
300 /* enable the hardware compare feature. */
301 ADCx->ADCFG |= ADC_ADCFG_ADWEN_MASK;
302
303 /* setup the channel in monitor. */
304 ADCx->ADCR = (ADCx->ADCR & ~ADC_ADCR_CMPCH_MASK) | ADC_ADCR_CMPCH(conf->ChnNum);
305
306 /* setup the compare boundary. */
307 ADCx->ADCMPR = ADC_ADCMPR_CMPLDATA(conf->LowLimit)
308 | ADC_ADCMPR_CMPHDATA(conf->HighLimit)
309 ;
310 }
311
312 /* EOF. */
313
314