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