1 //*****************************************************************************
2 //
3 //! @file am_hal_adc.c
4 //!
5 //! @brief Functions for interfacing with the Analog to Digital Converter.
6 //!
7 //! @addtogroup adc4_4p ADC - Analog-to-Digital Converter
8 //! @ingroup apollo4p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51 
52 //*****************************************************************************
53 //
54 // Private Types.
55 //
56 //*****************************************************************************
57 #define AM_HAL_MAGIC_ADC                0xAFAFAF
58 #define AM_HAL_ADC_CHK_HANDLE(h)        ((h) && ((am_hal_handle_prefix_t *)(h))->s.bInit && (((am_hal_handle_prefix_t *)(h))->s.magic == AM_HAL_MAGIC_ADC))
59 
60 #define ADC_CRITICAL_BEGIN(ui32Module)                              \
61         if ( 1 )                                                    \
62         {                                                           \
63             uint32_t ui32adcintensave, ui32adcintstatsave;          \
64             ui32adcintensave = ADCn(ui32Module)->INTEN;             \
65             ADCn(ui32Module)->INTEN = 0x0;                          \
66             ui32adcintstatsave = ADCn(ui32Module)->INTSTAT;         \
67 
68 #define ADC_CRITICAL_END(ui32Module)                                \
69             if ( !(ui32adcintstatsave & (ADC_INTCLR_SCNCMP_Msk |    \
70                                          ADC_INTCLR_CNVCMP_Msk)))   \
71             {                                                       \
72                 ADCn(ui32Module)->INTCLR = ADC_INTCLR_SCNCMP_Msk |  \
73                                            ADC_INTCLR_CNVCMP_Msk;   \
74             }                                                       \
75             ADCn(ui32Module)->INTEN = ui32adcintensave;             \
76         }
77 
78 //*****************************************************************************
79 //
80 //! @name Calibration Coefficients
81 //! @{
82 //! Default coefficients (used when trims not provided):
83 //!  TEMP_DEFAULT    = Temperature in deg K (e.g. 299.5 - 273.15 = 26.35)
84 //!  AMBIENT_DEFAULT = Voltage measurement at default temperature.
85 //!  OFFSET_DEFAULT  = Default ADC offset at 1v.
86 //
87 //*****************************************************************************
88 #define AM_HAL_ADC_CALIB_TEMP_DEFAULT               (299.5F)
89 #define AM_HAL_ADC_CALIB_AMBIENT_DEFAULT            (1.02809F)
90 #define AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT         (-0.004281F)
91 //! @}
92 
93 // ****************************************************************************
94 //
95 // State
96 //
97 // ****************************************************************************
98 // ****************************************************************************
99 //
100 // Storage for pre-computed constant terms in the temperature sensor equation.
101 //
102 // ****************************************************************************
103 static float g_fTempEqnTerms = 0.0F;
104 
105 // ****************************************************************************
106 //
107 //! @brief ADC Power save register state.
108 //
109 // ****************************************************************************
110 typedef struct
111 {
112     bool          bValid;
113     uint32_t      regCFG;
114     uint32_t      regSL0CFG;
115     uint32_t      regSL1CFG;
116     uint32_t      regSL2CFG;
117     uint32_t      regSL3CFG;
118     uint32_t      regSL4CFG;
119     uint32_t      regSL5CFG;
120     uint32_t      regSL6CFG;
121     uint32_t      regSL7CFG;
122     uint32_t      regIntTrigTmr;
123     uint32_t      regWULIM;
124     uint32_t      regWLLIM;
125     uint32_t      regINTEN;
126 } am_hal_adc_register_state_t;
127 
128 // ****************************************************************************
129 //
130 //! @brief ADC State structure.
131 //
132 // ****************************************************************************
133 typedef struct
134 {
135     //
136     //! Handle validation prefix.
137     //
138     am_hal_handle_prefix_t      prefix;
139 
140     //
141     //! Physical module number.
142     //
143     uint32_t                    ui32Module;
144 
145     //
146     //! ADC Capabilities.
147     //
148     am_hal_adc_capabilities_t   capabilities;
149 
150     //
151     //! Power Save-Restore register state
152     //
153     am_hal_adc_register_state_t registerState;
154 
155 } am_hal_adc_state_t;
156 
157 //*****************************************************************************
158 //
159 //! @brief Private SRAM view of temperature trims.
160 //!
161 //! This static SRAM union is private to the ADC HAL functions.
162 //
163 //*****************************************************************************
164 static union
165 {
166     //! These trim values are loaded as uint32_t values.
167     struct
168     {
169         //! Temperature of the package test head (in degrees Kelvin)
170         uint32_t ui32CalibrationTemperature;
171 
172         //! Voltage corresponding to temperature measured on test head.
173         uint32_t ui32CalibrationVoltage;
174 
175         //! ADC offset voltage measured on the package test head.
176         uint32_t ui32CalibrationOffset;
177 
178         //! Flag if default (guess) or measured.
179         bool bMeasured;
180     } ui32;
181     //! These trim values are accessed as floats when used in temp calculations.
182     struct
183     {
184         //! Temperature of the package test head in degrees Kelvin
185         float    fCalibrationTemperature;
186 
187         //! Voltage corresponding to temperature measured on test head.
188         float    fCalibrationVoltage;
189 
190         //! ADC offset voltage measured on the package test head.
191         //! This value is recorded in volts, although the value
192         //! itself is likely to be on the order of millivolts.
193         float    fCalibrationOffset;
194 
195         //! Flag if default (guess) or measured.
196         float fMeasuredFlag;
197     } flt;
198 } priv_temp_trims;
199 
200 //*****************************************************************************
201 //
202 //! @brief Private SRAM view of correction trims.
203 //!
204 //! This static SRAM union is private to the ADC HAL functions.
205 //
206 //*****************************************************************************
207 static union
208 {
209     //
210     // Define access to the general ADC correction values.
211     //
212     // These correction values are loaded as uint32_t values.
213     struct
214     {
215         uint32_t ui32ADCoffset;
216         uint32_t ui32ADCgain;
217         uint32_t ui32Sample;
218     } ui32;
219     // These correction values are accessed as floats
220     struct
221     {
222         float    fADCoffset;
223         float    fADCgain;
224         float    fSample;
225     } flt;
226 } priv_correction_trims;
227 
228 //*****************************************************************************
229 //
230 // Global Variables.
231 //
232 //*****************************************************************************
233 am_hal_adc_state_t             g_ADCState[AM_REG_ADC_NUM_MODULES];
234 
235 uint32_t                       g_ADCSlotsConfigured;
236 
237 bool     g_bDoADCadjust   = false;
238 
239 //*****************************************************************************
240 //
241 //! @brief ForceFIFOpop()
242 //
243 // ERR090: ADC "No CNVCMP interrupt for first single scan"
244 // Please refer to the Apollo4 errata for further information.
245 //
246 //*****************************************************************************
247 static void
ForceFIFOpop(void * pHandle)248 ForceFIFOpop(void *pHandle)
249 {
250     uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
251 
252     //
253     // Make sure the ADC is properly configured and enabled.
254     //
255     if ( !((ADCn(ui32Module)->CFG_b.RPTEN == ADC_CFG_RPTEN_SINGLE_SCAN)     &&
256            (ADCn(ui32Module)->CFG_b.ADCEN == ADC_CFG_ADCEN_EN))                 &&
257          !((ADCn(ui32Module)->CFG_b.ADCEN == ADC_CFG_ADCEN_EN)              &&
258            (ADCn(ui32Module)->CFG_b.RPTEN == ADC_CFG_RPTEN_REPEATING_SCAN)  &&
259            (ADCn(ui32Module)->INTTRIGTIMER_b.TIMEREN == ADC_INTTRIGTIMER_TIMEREN_EN)) )
260     {
261         return;
262     }
263 
264     //
265     // ERR090: After enable, a forced FIFO pop is required to make
266     //         sure that the first sample actually emitted is valid.
267     //
268     while ( _FLD2VAL(ADC_FIFO_COUNT, ADCn(ui32Module)->FIFO) == 0 )
269     {
270         am_hal_adc_sw_trigger(pHandle);
271         am_hal_delay_us(30);
272     }
273 
274     while ( _FLD2VAL(ADC_FIFO_COUNT, ADCn(ui32Module)->FIFO) )
275     {
276         ADCn(ui32Module)->FIFO = 0;     // Pop the FIFO
277     }
278 
279 } // ForceFIFOpop()
280 
281 //*****************************************************************************
282 //
283 //! @brief ADC initialization function
284 //!
285 //! @param ui32Module - module instance.
286 //! @param ppHandle   - returns the handle for the module instance.
287 //!
288 //! This function accepts a module instance, allocates the interface and then
289 //! returns a handle to be used by the remaining interface functions.
290 //!
291 //! @return status    - generic or interface specific status.
292 //!
293 //! @note A return of AM_HAL_STATUS_SUCCESS does not infer that the
294 //! temperature calibrations are valid. The caller must check the bMeasured
295 //! structure element in order to determine that.
296 //
297 //*****************************************************************************
298 uint32_t
am_hal_adc_initialize(uint32_t ui32Module,void ** ppHandle)299 am_hal_adc_initialize(uint32_t ui32Module, void **ppHandle)
300 {
301     uint32_t ui32Ret;
302 
303 #ifndef AM_HAL_DISABLE_API_VALIDATION
304     //
305     // Validate the module number
306     //
307     if ( ui32Module >= AM_REG_ADC_NUM_MODULES )
308     {
309         return AM_HAL_STATUS_OUT_OF_RANGE;
310     }
311 
312     //
313     // Check for valid arguements.
314     //
315     if ( !ppHandle )
316     {
317         return AM_HAL_STATUS_INVALID_ARG;
318     }
319 
320     //
321     // Check if the handle is unallocated.
322     //
323     if ( g_ADCState[ui32Module].prefix.s.bInit )
324     {
325         return AM_HAL_STATUS_INVALID_OPERATION;
326     }
327 #endif // AM_HAL_DISABLE_API_VALIDATION
328 
329     //
330     // Initialize the handle.
331     //
332     g_ADCState[ui32Module].prefix.s.bInit = true;
333     g_ADCState[ui32Module].prefix.s.magic = AM_HAL_MAGIC_ADC;
334     g_ADCState[ui32Module].ui32Module = ui32Module;
335 
336     //
337     // Initialize the number of slots configured.
338     //
339     g_ADCSlotsConfigured = 0;
340 
341     //
342     // Return the handle.
343     //
344     *ppHandle = (void *)&g_ADCState[ui32Module];
345 
346     //
347     // Before returning, read the temperature trims from INFO1,
348     // which are safely read using am_hal_mram_info_read().
349     //
350     ui32Ret  = am_hal_mram_info_read(1, AM_REG_INFO1_TEMP_CAL_ATE_O / 4, 1,     // INFO1, word offset, read 1 word
351                                      &priv_temp_trims.ui32.ui32CalibrationTemperature);
352     ui32Ret |= am_hal_mram_info_read(1, AM_REG_INFO1_TEMP_CAL_MEASURED_O / 4, 1,
353                                      &priv_temp_trims.ui32.ui32CalibrationVoltage);
354     ui32Ret |= am_hal_mram_info_read(1, AM_REG_INFO1_TEMP_CAL_ADC_OFFSET_O / 4, 1,
355                                      &priv_temp_trims.ui32.ui32CalibrationOffset);
356 
357     if ( (priv_temp_trims.ui32.ui32CalibrationTemperature == 0xFFFFFFFF)    ||
358          (priv_temp_trims.ui32.ui32CalibrationVoltage     == 0xFFFFFFFF)    ||
359          (priv_temp_trims.ui32.ui32CalibrationOffset      == 0xFFFFFFFF)    ||
360          (ui32Ret != 0) )
361     {
362         //
363         // Since the device has not been calibrated on the tester, we'll load
364         // default calibration values.  These default values should result
365         // in worst-case temperature measurements of +-6 degress C.
366         //
367         priv_temp_trims.flt.fCalibrationTemperature = AM_HAL_ADC_CALIB_TEMP_DEFAULT;
368         priv_temp_trims.flt.fCalibrationVoltage     = AM_HAL_ADC_CALIB_AMBIENT_DEFAULT;
369         priv_temp_trims.flt.fCalibrationOffset      = AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT;
370         priv_temp_trims.ui32.bMeasured = false;
371     }
372     else
373     {
374         priv_temp_trims.ui32.bMeasured = true;
375     }
376 
377     //
378     // Get and save the ADC gain/offset correction values. These are really only
379     // needed for rev B0 and B1, but they will also be useful on later revs.
380     // Note: Only applies to the general ADC, not for AUDADC.
381     //
382     // If the correction values are 0xFFFFFFFF then we must disable CALONPWRUP.
383     //
384     ui32Ret  = am_hal_mram_info_read(1, AM_REG_INFO1_ADC_GAIN_ERR_O / 4, 1,
385                                      &priv_correction_trims.ui32.ui32ADCgain);
386     ui32Ret |= am_hal_mram_info_read(1, AM_REG_INFO1_ADC_OFFSET_ERR_O / 4, 1,
387                                      &priv_correction_trims.ui32.ui32ADCoffset);
388 
389     //
390     // Disable CALONPWRUP so that corrections can be applied to samples.
391     //
392     MCUCTRL->ADCCAL_b.CALONPWRUP = MCUCTRL_ADCCAL_CALONPWRUP_DIS;
393 
394     if ( (ui32Ret != 0)                                             ||
395          (priv_correction_trims.ui32.ui32ADCgain   == 0xFFFFFFFF)   ||
396          (priv_correction_trims.ui32.ui32ADCoffset == 0xFFFFFFFF) )
397     {
398         g_bDoADCadjust = false;
399     }
400     else
401     {
402         g_bDoADCadjust = true;
403     }
404 
405     //
406     // Return the status.
407     // Note - This does not infer that temperature calibrations are valid.
408     // The caller must check bMeasured to determine that.
409     //
410     return AM_HAL_STATUS_SUCCESS;
411 
412 } // am_hal_adc_initialize()
413 
414 //*****************************************************************************
415 //
416 //! @brief ADC deinitialization function
417 //!
418 //! @param pHandle       - returns the handle for the module instance.
419 //!
420 //! This function accepts a handle to an instance and de-initializes the
421 //! interface.
422 //!
423 //! @return status      - generic or interface specific status.
424 //
425 //*****************************************************************************
426 uint32_t
am_hal_adc_deinitialize(void * pHandle)427 am_hal_adc_deinitialize(void *pHandle)
428 {
429     uint32_t            status = AM_HAL_STATUS_SUCCESS;
430     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
431 
432 #ifndef AM_HAL_DISABLE_API_VALIDATION
433     //
434     // Check the handle.
435     //
436     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
437     {
438         return AM_HAL_STATUS_INVALID_HANDLE;
439     }
440 #endif // AM_HAL_DISABLE_API_VALIDATION
441 
442     if ( pADCState->prefix.s.bEnable )
443     {
444         status = am_hal_adc_disable(pHandle);
445     }
446 
447     pADCState->prefix.s.bInit = false;
448 
449     //
450     // Return the status.
451     //
452     return status;
453 
454 } // am_hal_adc_deinitialize()
455 
456 //*****************************************************************************
457 //
458 //! @brief ADC configuration function
459 //!
460 //! @param pHandle   - handle for the module instance.
461 //! @param psConfig  - pointer to the configuration structure.
462 //!
463 //! This function configures the ADC for operation.
464 //!
465 //! @return status      - generic or interface specific status.
466 //
467 //*****************************************************************************
468 uint32_t
am_hal_adc_configure(void * pHandle,am_hal_adc_config_t * psConfig)469 am_hal_adc_configure(void *pHandle,
470                      am_hal_adc_config_t *psConfig)
471 {
472     uint32_t            ui32Config;
473     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
474     uint32_t            ui32Module = pADCState->ui32Module;
475 
476 #ifndef AM_HAL_DISABLE_API_VALIDATION
477     //
478     // Check the handle.
479     //
480     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
481     {
482         return AM_HAL_STATUS_INVALID_HANDLE;
483     }
484 #endif // AM_HAL_DISABLE_API_VALIDATION
485 
486     ui32Config = 0;
487 
488     //
489     // Set the ADC clock source.
490     //
491     if ( psConfig->eClock != AM_HAL_ADC_CLKSEL_HFRC_24MHZ )
492     {
493         return AM_HAL_STATUS_INVALID_ARG;
494     }
495 
496     ui32Config |= _VAL2FLD(ADC_CFG_CLKSEL, psConfig->eClock);
497 
498     //
499     // Set the ADC periodic trigger source.
500     //
501     ui32Config |= _VAL2FLD(ADC_CFG_RPTTRIGSEL, psConfig->eRepeatTrigger);
502 
503     //
504     // Set the ADC trigger polarity.
505     //
506     ui32Config |= _VAL2FLD(ADC_CFG_TRIGPOL, psConfig->ePolarity);
507 
508     //
509     // Set the ADC trigger.
510     //
511     ui32Config |= _VAL2FLD(ADC_CFG_TRIGSEL, psConfig->eTrigger);
512 
513     //
514     // Set the Destructive FIFO read.
515     //
516     ui32Config |= _VAL2FLD(ADC_CFG_DFIFORDEN, 1);
517 
518     //
519     // Set the ADC clock mode.
520     //
521     ui32Config |= _VAL2FLD(ADC_CFG_CKMODE, psConfig->eClockMode);
522 
523     //
524     // Set the ADC low power mode.
525     //
526     ui32Config |= _VAL2FLD(ADC_CFG_LPMODE, psConfig->ePowerMode);
527 
528     //
529     // Set the ADC repetition mode.
530     //
531     ui32Config |= _VAL2FLD(ADC_CFG_RPTEN, psConfig->eRepeat);
532 
533     //
534     // Set the configuration in the ADC peripheral.
535     //
536     ADCn(ui32Module)->CFG = ui32Config;
537 
538     //
539     // Return status.
540     //
541     return AM_HAL_STATUS_SUCCESS;
542 
543 } // am_hal_adc_configure()
544 
545 //*****************************************************************************
546 //
547 //! @brief ADC slot configuration function
548 //!
549 //! @param pHandle - handle for the module instance.
550 //! @param ui32SlotNumber - ADC Slot Number
551 //! @param pSlotConfig    - pointer to the configuration structure.
552 //!
553 //! This function configures the ADC slot for operation.
554 //!
555 //! @return status      - generic or interface specific status.
556 //
557 //*****************************************************************************
558 uint32_t
am_hal_adc_configure_slot(void * pHandle,uint32_t ui32SlotNumber,am_hal_adc_slot_config_t * pSlotConfig)559 am_hal_adc_configure_slot(void *pHandle,
560                           uint32_t ui32SlotNumber,
561                           am_hal_adc_slot_config_t *pSlotConfig)
562 {
563     uint32_t            ui32Config;
564     uint32_t            ui32RegOffset;
565     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
566     uint32_t            ui32Module = pADCState->ui32Module;
567 
568 #ifndef AM_HAL_DISABLE_API_VALIDATION
569     //
570     // Check the handle.
571     //
572     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
573     {
574         return AM_HAL_STATUS_INVALID_HANDLE;
575     }
576 
577     //
578     // Check the slot number.
579     //
580     if ( ui32SlotNumber >= AM_HAL_ADC_MAX_SLOTS )
581     {
582         return AM_HAL_STATUS_OUT_OF_RANGE;
583     }
584 
585     if ( (pSlotConfig->ui32TrkCyc < AM_HAL_ADC_MIN_TRKCYC) ||
586          (pSlotConfig->ui32TrkCyc > _FLD2VAL(ADC_SL0CFG_TRKCYC0, 0xFFFFFFFF)) )
587     {
588         return AM_HAL_STATUS_INVALID_ARG;
589     }
590 #endif // AM_HAL_DISABLE_API_VALIDATION
591 
592     ui32Config = 0;
593 
594     //
595     // Set the measurements to average
596     //
597     ui32Config |= _VAL2FLD(ADC_SL0CFG_ADSEL0, pSlotConfig->eMeasToAvg);
598 
599     //
600     // Set additional sampling ADC clock cycles
601     //
602     ui32Config |= _VAL2FLD(ADC_SL0CFG_TRKCYC0, pSlotConfig->ui32TrkCyc);
603 
604     //
605     // Set the precision mode.
606     //
607     ui32Config |= _VAL2FLD(ADC_SL0CFG_PRMODE0, pSlotConfig->ePrecisionMode);
608 
609     //
610     // Set the channel.
611     //
612     ui32Config |= _VAL2FLD(ADC_SL0CFG_CHSEL0, pSlotConfig->eChannel);
613 
614     //
615     // Enable window comparison if configured.
616     //
617     ui32Config |= _VAL2FLD(ADC_SL0CFG_WCEN0, pSlotConfig->bWindowCompare);
618 
619     //
620     // Enable the slot if configured.
621     //
622     ui32Config |= _VAL2FLD(ADC_SL0CFG_SLEN0, pSlotConfig->bEnabled);
623 
624     //
625     // Locate the correct register for this ADC slot.
626     //
627     ui32RegOffset = ((uint32_t)&ADCn(ui32Module)->SL0CFG) + (4 * ui32SlotNumber);
628 
629     //
630     // Write the register with the caller's configuration value.
631     //
632     AM_REGVAL(ui32RegOffset) = ui32Config;
633 
634     //
635     // Update the nubmer of slots configured.
636     //
637     g_ADCSlotsConfigured++;
638 
639     //
640     // Return the status.
641     //
642     return AM_HAL_STATUS_SUCCESS;
643 
644 } // am_hal_adc_configure_slot()
645 
646 //*****************************************************************************
647 //
648 //! @brief ADC internal repeat trigger timer configuration function
649 //!
650 //! @param pHandle - handle for the module instance.
651 //! @param pConfig - pointer to the configuration structure.
652 //!
653 //! This function configures the ADC internal repeat trigger timer for operation.
654 //!
655 //! @return status      - generic or interface specific status.
656 //
657 //*****************************************************************************
658 uint32_t
am_hal_adc_configure_irtt(void * pHandle,am_hal_adc_irtt_config_t * pConfig)659 am_hal_adc_configure_irtt(void *pHandle,
660                           am_hal_adc_irtt_config_t *pConfig)
661 {
662     uint32_t    ui32Config = 0;
663     uint32_t    ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
664 
665 #ifndef AM_HAL_DISABLE_API_VALIDATION
666     //
667     // Check the handle.
668     //
669     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
670     {
671         return AM_HAL_STATUS_INVALID_HANDLE;
672     }
673 #endif // AM_HAL_DISABLE_API_VALIDATION
674 
675     //
676     // Disable ADC internal repeating trigger timer
677     //
678     ui32Config |= _VAL2FLD(ADC_INTTRIGTIMER_TIMEREN, ADC_INTTRIGTIMER_TIMEREN_DIS);
679 
680     //
681     // Set ADC internal repeating trigger timer clock division
682     //
683     ui32Config |= _VAL2FLD(ADC_INTTRIGTIMER_CLKDIV, pConfig->eClkDiv);
684 
685     //
686     // Set ADC internal repeating trigger timer count
687     //
688     ui32Config |= _VAL2FLD(ADC_INTTRIGTIMER_TIMERMAX, pConfig->ui32IrttCountMax);
689 
690     //
691     // Set ADC internal repeating trigger timer configuration.
692     //
693     ADCn(ui32Module)->INTTRIGTIMER = ui32Config;
694 
695     //
696     // Return the status.
697     //
698     return AM_HAL_STATUS_SUCCESS;
699 
700 } // am_hal_adc_configure_irtt()
701 
702 //*****************************************************************************
703 //
704 //! @brief ADC internal repeating trigger timer enable function
705 //!
706 //! @param pHandle   - handle for the module instance.
707 //!
708 //! This function enables internal repeating trigger timer.
709 //!
710 //! @note - am_hal_adc_enable() must be called before this function.
711 //!
712 //! @return status      - generic or interface specific status.
713 //
714 //*****************************************************************************
715 uint32_t
am_hal_adc_irtt_enable(void * pHandle)716 am_hal_adc_irtt_enable(void *pHandle)
717 {
718     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
719     uint32_t            ui32Module = pADCState->ui32Module;
720 
721 #ifndef AM_HAL_DISABLE_API_VALIDATION
722     //
723     // Check the handle.
724     //
725     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
726     {
727         return AM_HAL_STATUS_INVALID_HANDLE;
728     }
729 
730     //
731     // Make sure the ADC has been enabled.
732     //
733     if ( ADCn(ui32Module)->CFG_b.ADCEN != ADC_CFG_ADCEN_EN )
734     {
735         return AM_HAL_STATUS_INVALID_OPERATION;
736     }
737 #endif // AM_HAL_DISABLE_API_VALIDATION
738 
739     //
740     // Enable the ADC.
741     //
742     ADC_CRITICAL_BEGIN(ui32Module)
743     ADCn(ui32Module)->INTTRIGTIMER_b.TIMEREN = ADC_INTTRIGTIMER_TIMEREN_EN;
744     ForceFIFOpop(pHandle);  // See errata ERR090
745     ADC_CRITICAL_END(ui32Module)
746 
747     //
748     // Return the status.
749     //
750     return AM_HAL_STATUS_SUCCESS;
751 
752 } // am_hal_adc_irtt_enable()
753 
754 //*****************************************************************************
755 //
756 //! @brief ADC internal repeating trigger timer disable function
757 //!
758 //! @param pHandle   - handle for the module instance.
759 //!
760 //! This function disables internal repeating trigger timer.
761 //!
762 //! @return status      - generic or interface specific status.
763 //
764 //*****************************************************************************
765 uint32_t
am_hal_adc_irtt_disable(void * pHandle)766 am_hal_adc_irtt_disable(void *pHandle)
767 {
768     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
769     uint32_t            ui32Module = pADCState->ui32Module;
770 
771 #ifndef AM_HAL_DISABLE_API_VALIDATION
772     //
773     // Check the handle.
774     //
775     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
776     {
777         return AM_HAL_STATUS_INVALID_HANDLE;
778     }
779 #endif // AM_HAL_DISABLE_API_VALIDATION
780 
781     //
782     // Enable the ADC.
783     //
784     ADCn(ui32Module)->INTTRIGTIMER_b.TIMEREN = ADC_INTTRIGTIMER_TIMEREN_DIS;
785 
786     //
787     // Return the status.
788     //
789     return AM_HAL_STATUS_SUCCESS;
790 
791 } // am_hal_adc_irtt_disable()
792 
793 //*****************************************************************************
794 //
795 //! @brief ADC DMA configuration function
796 //!
797 //! @param pHandle   - handle for the module instance.
798 //! @param pDMAConfig  - pointer to the configuration structure.
799 //!
800 //! This function configures the ADC DMA for operation.
801 //!
802 //! @return status      - generic or interface specific status.
803 //
804 //*****************************************************************************
805 uint32_t
am_hal_adc_configure_dma(void * pHandle,am_hal_adc_dma_config_t * pDMAConfig)806 am_hal_adc_configure_dma(void *pHandle,
807                          am_hal_adc_dma_config_t *pDMAConfig)
808 {
809     uint32_t    ui32Config;
810     uint32_t    ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
811 
812 #ifndef AM_HAL_DISABLE_API_VALIDATION
813     //
814     // Check the handle.
815     //
816     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
817     {
818         return AM_HAL_STATUS_INVALID_HANDLE;
819     }
820 #endif // AM_HAL_DISABLE_API_VALIDATION
821 
822     ui32Config = 0;
823 
824     //
825     // Configure the DMA complete power-off.
826     //
827     ui32Config |= _VAL2FLD(ADC_DMACFG_DPWROFF, 0);      // DPWROFF not supported!
828 
829     //
830     // Configure the data to be transferred.
831     //
832     if ( g_ADCSlotsConfigured > 1 )
833     {
834         // Need slot number to distinguish between slot results.
835         ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_DIS);
836     }
837     else
838     {
839         ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_EN);
840     }
841 
842     //
843     // Enable DMA Halt on Status (DMAERR or DMACPL) by default. This bit is reserved in apollo4
844     //
845 //    ui32Config |= _VAL2FLD(ADC_DMACFG_DMAHONSTAT, ADC_DMACFG_DMAHONSTAT_EN);
846 
847     //
848     // Configure the DMA dynamic priority handling.
849     //
850     ui32Config |= _VAL2FLD(ADC_DMACFG_DMADYNPRI, pDMAConfig->bDynamicPriority);
851 
852     //
853     // Configure the DMA static priority.
854     //
855     ui32Config |= _VAL2FLD(ADC_DMACFG_DMAPRI, pDMAConfig->ePriority);
856 
857     //
858     // Enable the DMA (does not start until ADC is enabled and triggered).
859     //
860     ui32Config |= _VAL2FLD(ADC_DMACFG_DMAEN, ADC_DMACFG_DMAEN_EN);
861 
862     //
863     // Set the DMA configuration.
864     //
865     ADCn(ui32Module)->DMACFG = ui32Config;
866 
867     //
868     // Set the DMA transfer count.
869     //
870     ADCn(ui32Module)->DMATOTCOUNT_b.TOTCOUNT = pDMAConfig->ui32SampleCount;
871 
872     //
873     // Set the DMA target address.
874     //
875     ADCn(ui32Module)->DMATARGADDR = pDMAConfig->ui32TargetAddress;
876 
877     //
878     // Set the DMA trigger on FIFO 75% full.
879     //
880     ADCn(ui32Module)->DMATRIGEN = ADC_DMATRIGEN_DFIFO75_Msk;
881 
882     //
883     // Return the status.
884     //
885     return AM_HAL_STATUS_SUCCESS;
886 
887 } // am_hal_adc_configure_dma()
888 
889 //*****************************************************************************
890 //
891 // ADC device specific control function.
892 //
893 //*****************************************************************************
894 uint32_t
am_hal_adc_control(void * pHandle,am_hal_adc_request_e eRequest,void * pArgs)895 am_hal_adc_control(void *pHandle,
896                    am_hal_adc_request_e eRequest,
897                    void *pArgs)
898 {
899     uint32_t    ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
900 
901 #ifndef AM_HAL_DISABLE_API_VALIDATION
902     //
903     // Check the handle.
904     //
905     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
906     {
907         return AM_HAL_STATUS_INVALID_HANDLE;
908     }
909 #endif // AM_HAL_DISABLE_API_VALIDATION
910 
911     switch ( eRequest )
912     {
913         case AM_HAL_ADC_REQ_WINDOW_CONFIG:
914         {
915             am_hal_adc_window_config_t *pWindowConfig = (am_hal_adc_window_config_t *)pArgs;
916 
917 #ifndef AM_HAL_DISABLE_API_VALIDATION
918             //
919             // Check the window limits.
920             //
921             if ( (pWindowConfig->ui32Upper > ADC_WULIM_ULIM_Msk)   ||
922                  (pWindowConfig->ui32Lower > ADC_WLLIM_LLIM_Msk) )
923             {
924                 return AM_HAL_STATUS_OUT_OF_RANGE;
925             }
926 #endif // AM_HAL_DISABLE_API_VALIDATION
927             //
928             // Set the window comparison upper and lower limits.
929             //
930             ADCn(ui32Module)->WULIM = _VAL2FLD(ADC_WULIM_ULIM, pWindowConfig->ui32Upper);
931             ADCn(ui32Module)->WLLIM = _VAL2FLD(ADC_WLLIM_LLIM, pWindowConfig->ui32Lower);
932 
933             //
934             // Set the window scale per precision mode if indicated.
935             //
936             ADCn(ui32Module)->SCWLIM = _VAL2FLD(ADC_SCWLIM_SCWLIMEN,
937                                                 pWindowConfig->bScaleLimits);
938         }
939         break;
940 
941         case AM_HAL_ADC_REQ_TEMP_CELSIUS_GET:
942             //
943             // pArgs must point to an array of 3 floats.  To assure that the
944             // array is valid, upon calling the 3rd float (pArgs[2]) must be
945             // set to the value -123.456F.
946             //
947             if ( pArgs != NULL )
948             {
949                 float *pfArray = (float*)pArgs;
950                 float fTemp, fCalibration_temp, fCalibration_voltage, fCalibration_offset, fVoltage;
951 
952                 if ( pfArray[2] == -123.456F )
953                 {
954                     //
955                     // The caller has provided a voltage as determined from the
956                     // sample. The sample is scaled up by the reference voltage
957                     // used on the device and then scaled down by the number of
958                     // sample bits.
959                     // i.e. scaled by AM_HAL_ADC_VREF / (1 << number_bits).
960                     //
961                     // Get the scaled voltage obtained from the ADC sample.
962                     //
963                     fVoltage = pfArray[0];
964 
965                     //
966                     // Compute the calibrated temperature via the equation:
967                     //      T = m * Vmeas + T1 - m(V1 + Voff)
968                     // m     = AM_HAL_ADC_TEMPSENSOR_SLOPE (degK / V)
969                     // Vmeas = The measured voltage (as based on the ADC code)
970                     // T1    = Calibration temperature
971                     // V1    = Calibration voltage (stored in volts)
972                     // Voff  = Calibration offset (stored in volts)
973                     //
974                     fCalibration_temp    = priv_temp_trims.flt.fCalibrationTemperature;
975                     fCalibration_voltage = priv_temp_trims.flt.fCalibrationVoltage;
976                     fCalibration_offset  = priv_temp_trims.flt.fCalibrationOffset;
977 
978                     //
979                     // Compute the temperature in K
980                     //
981                     if ( g_fTempEqnTerms == 0.0F )
982                     {
983                         //
984                         // The 2nd and 3rd terms of the temperature equation are
985                         // consistent for a given device, so compute them only
986                         // the first time and save.
987                         //
988                         g_fTempEqnTerms  = -1.0F * AM_HAL_ADC_TEMPSENSOR_SLOPE;
989                         g_fTempEqnTerms *= (fCalibration_voltage + fCalibration_offset);
990                         g_fTempEqnTerms += fCalibration_temp;
991                     }
992 
993                     //
994                     // Determine the temperature in K by factoring
995                     // in the supplied sample voltage
996                     //
997                     fTemp  = AM_HAL_ADC_TEMPSENSOR_SLOPE * fVoltage;
998                     fTemp += g_fTempEqnTerms;
999 
1000                     //
1001                     // Give it back to the caller in Celsius.
1002                     //
1003                     pfArray[1] = fTemp - 273.15f;
1004                 }
1005                 else
1006                 {
1007                     return AM_HAL_STATUS_INVALID_OPERATION;
1008                 }
1009             }
1010             else
1011             {
1012                 return AM_HAL_STATUS_INVALID_ARG;
1013             }
1014             break;
1015 
1016         case AM_HAL_ADC_REQ_TEMP_TRIMS_GET:
1017             //
1018             // pArgs must point to an array of 4 floats.  To assure that the
1019             // array is valid, upon calling the 4th float (pArgs[3]) must be
1020             // set to the value -123.456.
1021             // On return, pArgs[3] is set to 1 if the returned values are
1022             //  calibrated, or 0 if default calibration values.
1023             //
1024             if ( pArgs != NULL )
1025             {
1026                 float *pfArray = (float*)pArgs;
1027                 if ( pfArray[3] == -123.456F )
1028                 {
1029                     //
1030                     // Return trim temperature as a float.
1031                     //
1032                     pfArray[0] = priv_temp_trims.flt.fCalibrationTemperature;
1033 
1034                     //
1035                     // Return trim voltage as a float.
1036                     //
1037                     pfArray[1] = priv_temp_trims.flt.fCalibrationVoltage;
1038 
1039                     //
1040                     // Return trim ADC offset voltage (in volts) as a float.
1041                     //
1042                     pfArray[2] = priv_temp_trims.flt.fCalibrationOffset;
1043 
1044                     //
1045                     // Set the calibrated or uncalibrated flag
1046                     //
1047                     *(uint32_t*)&pfArray[3] = priv_temp_trims.ui32.bMeasured;
1048                 }
1049                 else
1050                 {
1051                     return AM_HAL_STATUS_INVALID_OPERATION;
1052                 }
1053             }
1054             else
1055             {
1056                 return AM_HAL_STATUS_INVALID_ARG;
1057             }
1058             break;
1059 
1060         case AM_HAL_ADC_REQ_CORRECTION_TRIMS_GET:
1061             //
1062             // pArgs must point to an array of 4 floats.  To assure that the
1063             // array is valid, upon calling the 4th float (pArgs[3]) must be
1064             // set to the value -123.456.
1065             //
1066             // On return,
1067             //  pArgs[0] contains the offset that is applied to each sample.
1068             //  pArgs[1] contains the gain   that is applied to each sample.
1069             //
1070             //  Note that the am_hal_adc_samples_read() automatically applies
1071             //  the correction to samples. Therefore this function is primarily
1072             //  supplied to the user for informational purposes only.
1073             //
1074             if ( pArgs != NULL )
1075             {
1076                 float *pfArray = (float*)pArgs;
1077                 if ( pfArray[3] == -123.456F )
1078                 {
1079                     //
1080                     // Return ADC correction offset as a float.
1081                     //
1082                     pfArray[0] = priv_correction_trims.flt.fADCoffset;
1083 
1084                     //
1085                     // Return ADC correction gain as a float.
1086                     //
1087                     pfArray[1] = priv_correction_trims.flt.fADCgain;
1088 
1089                     //
1090                     // Set the return values.
1091                     //
1092                     ((uint32_t*)pArgs)[2] = 0;
1093                     ((uint32_t*)pArgs)[3] = 0;
1094                 }
1095                 else
1096                 {
1097                     return AM_HAL_STATUS_INVALID_OPERATION;
1098                 }
1099             }
1100             else
1101             {
1102                 return AM_HAL_STATUS_INVALID_ARG;
1103             }
1104             break;
1105 
1106         default:
1107             return AM_HAL_STATUS_INVALID_ARG;
1108     }
1109 
1110     //
1111     // Return status.
1112     //
1113     return AM_HAL_STATUS_SUCCESS;
1114 
1115 } // am_hal_adc_control()
1116 
1117 //*****************************************************************************
1118 //
1119 //! @brief ADC enable function
1120 //!
1121 //! @param pHandle   - handle for the module instance.
1122 //!
1123 //! This function enables the ADC operation.
1124 //!
1125 //! @return status      - generic or interface specific status.
1126 //
1127 //*****************************************************************************
1128 uint32_t
am_hal_adc_enable(void * pHandle)1129 am_hal_adc_enable(void *pHandle)
1130 {
1131     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
1132     uint32_t            ui32Module = pADCState->ui32Module;
1133 
1134 #ifndef AM_HAL_DISABLE_API_VALIDATION
1135     //
1136     // Check the handle.
1137     //
1138     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1139     {
1140         return AM_HAL_STATUS_INVALID_HANDLE;
1141     }
1142 
1143     if ( pADCState->prefix.s.bEnable )
1144     {
1145         return AM_HAL_STATUS_SUCCESS;
1146     }
1147 #endif // AM_HAL_DISABLE_API_VALIDATION
1148 
1149     //
1150     // Enable the ADC.
1151     //
1152     ADC_CRITICAL_BEGIN(ui32Module)
1153     ADCn(ui32Module)->CFG_b.ADCEN = ADC_CFG_ADCEN_EN;
1154 
1155     //
1156     // Set flag to indicate module is enabled.
1157     //
1158     pADCState->prefix.s.bEnable = true;
1159     ForceFIFOpop(pHandle);  // See errata ERR090
1160     ADC_CRITICAL_END(ui32Module)
1161 
1162     //
1163     // Return the status.
1164     //
1165     return AM_HAL_STATUS_SUCCESS;
1166 
1167 } // am_hal_adc_enable()
1168 
1169 //*****************************************************************************
1170 //
1171 //! @brief ADC disable function
1172 //!
1173 //! @param pHandle   - handle for the module instance.
1174 //!
1175 //! This function disables the ADC operation.
1176 //!
1177 //! @return status      - generic or interface specific status.
1178 //
1179 //*****************************************************************************
1180 uint32_t
am_hal_adc_disable(void * pHandle)1181 am_hal_adc_disable(void *pHandle)
1182 {
1183     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
1184     uint32_t            ui32Module = pADCState->ui32Module;
1185 
1186 #ifndef AM_HAL_DISABLE_API_VALIDATION
1187     //
1188     // Check the handle.
1189     //
1190     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1191     {
1192         return AM_HAL_STATUS_INVALID_HANDLE;
1193     }
1194 #endif // AM_HAL_DISABLE_API_VALIDATION
1195 
1196     //
1197     // Before disabling the ADC, clear RPTEN per the register description, "When
1198     // disabling the ADC (setting ADCEN to '0') the RPTEN bit should be cleared."
1199     //
1200     ADCn(ui32Module)->CFG_b.RPTEN = ADC_CFG_RPTEN_SINGLE_SCAN;
1201 
1202     //
1203     // Disable the ADC.
1204     //
1205     ADCn(ui32Module)->CFG_b.ADCEN = ADC_CFG_ADCEN_DIS;
1206 
1207     //
1208     // Set flag to indicate module is disabled.
1209     //
1210     pADCState->prefix.s.bEnable = false;
1211 
1212     //
1213     // Return the status.
1214     //
1215     return AM_HAL_STATUS_SUCCESS;
1216 
1217 } // am_hal_adc_disable()
1218 
1219 //*****************************************************************************
1220 //
1221 //! @brief ADC status function
1222 //!
1223 //! @param pHandle - handle for the interface.
1224 //! @param pStatus - return status for the interface
1225 //!
1226 //! This function returns the current status of the DMA operation.
1227 //!
1228 //! @return status - DMA status flags.
1229 //
1230 //*****************************************************************************
1231 uint32_t
am_hal_adc_status_get(void * pHandle,am_hal_adc_status_t * pStatus)1232 am_hal_adc_status_get(void *pHandle, am_hal_adc_status_t *pStatus )
1233 {
1234     uint32_t    ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
1235 
1236 #ifndef AM_HAL_DISABLE_API_VALIDATION
1237     //
1238     // Check the handle.
1239     //
1240     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1241     {
1242         return AM_HAL_STATUS_INVALID_HANDLE;
1243     }
1244 #endif // AM_HAL_DISABLE_API_VALIDATION
1245 
1246     //
1247     // Get the power status.
1248     //
1249     pStatus->bPoweredOn = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
1250                           _VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_ON);
1251 
1252     //
1253     // Get the low power mode 1 status.
1254     //
1255     pStatus->bLPMode1 = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
1256                         _VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_POWERED_DOWN);
1257 
1258     //
1259     //  Get the DMA status.
1260     //
1261     pStatus->bErr = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMAERR_Msk) > 0);
1262     pStatus->bCmp = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMACPL_Msk) > 0);
1263     pStatus->bTIP = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMATIP_Msk) > 0);
1264 
1265     //
1266     // Return the status.
1267     //
1268     return AM_HAL_STATUS_SUCCESS;
1269 
1270 } // am_hal_adc_status_get()
1271 
1272 //*****************************************************************************
1273 //
1274 //! @brief ADC enable interrupts function
1275 //!
1276 //! @param pHandle       - handle for the interface.
1277 //! @param ui32IntMask  - ADC interrupt mask.
1278 //!
1279 //! This function enables the specific indicated interrupts.
1280 //!
1281 //! @return status      - generic or interface specific status.
1282 //
1283 //*****************************************************************************
1284 uint32_t
am_hal_adc_interrupt_enable(void * pHandle,uint32_t ui32IntMask)1285 am_hal_adc_interrupt_enable(void *pHandle, uint32_t ui32IntMask)
1286 {
1287     uint32_t    ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1288 
1289 #ifndef AM_HAL_DISABLE_API_VALIDATION
1290     //
1291     // Check the handle.
1292     //
1293     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1294     {
1295         return AM_HAL_STATUS_INVALID_HANDLE;
1296     }
1297 #endif // AM_HAL_DISABLE_API_VALIDATION
1298 
1299     //
1300     // Enable the interrupts.
1301     //
1302     ADCn(ui32Module)->INTEN |= ui32IntMask;
1303 
1304     //
1305     // Return the status.
1306     //
1307     return AM_HAL_STATUS_SUCCESS;
1308 
1309 } // am_hal_adc_interrupt_enable()
1310 
1311 //*****************************************************************************
1312 //
1313 //! @brief ADC disable interrupts function
1314 //!
1315 //! @param pHandle       - handle for the interface.
1316 //! @param ui32IntMask  - ADC interrupt mask.
1317 //!
1318 //! This function disable the specific indicated interrupts.
1319 //!
1320 //! @return status      - generic or interface specific status.
1321 //
1322 //*****************************************************************************
1323 uint32_t
am_hal_adc_interrupt_disable(void * pHandle,uint32_t ui32IntMask)1324 am_hal_adc_interrupt_disable(void *pHandle, uint32_t ui32IntMask)
1325 {
1326     uint32_t    ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1327 
1328 #ifndef AM_HAL_DISABLE_API_VALIDATION
1329     //
1330     // Check the handle.
1331     //
1332     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1333     {
1334         return AM_HAL_STATUS_INVALID_HANDLE;
1335     }
1336 #endif // AM_HAL_DISABLE_API_VALIDATION
1337 
1338     //
1339     // Disable the interrupts.
1340     //
1341     ADCn(ui32Module)->INTEN &= ~ui32IntMask;
1342 
1343     //
1344     // Return the status.
1345     //
1346     return AM_HAL_STATUS_SUCCESS;
1347 
1348 } // am_hal_adc_interrupt_disable()
1349 
1350 //*****************************************************************************
1351 //
1352 //! @brief ADC interrupt status function
1353 //!
1354 //! @param pHandle      - handle for the interface.
1355 //! @param pui32Status  - pointer to status
1356 //! @param bEnabledOnly - if ADC enabled
1357 //!
1358 //! This function returns the specific indicated interrupt status.
1359 //!
1360 //! @return status      - generic or interface specific status.
1361 //
1362 //*****************************************************************************
1363 uint32_t
am_hal_adc_interrupt_status(void * pHandle,uint32_t * pui32Status,bool bEnabledOnly)1364 am_hal_adc_interrupt_status(void *pHandle,
1365                             uint32_t  *pui32Status,
1366                             bool bEnabledOnly)
1367 {
1368     uint32_t    ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1369 
1370 #ifndef AM_HAL_DISABLE_API_VALIDATION
1371     //
1372     // Check the handle.
1373     //
1374     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1375     {
1376         return AM_HAL_STATUS_INVALID_HANDLE;
1377     }
1378 #endif // AM_HAL_DISABLE_API_VALIDATION
1379 
1380     //
1381     // if requested, only return the interrupts that are enabled.
1382     //
1383     if ( bEnabledOnly )
1384     {
1385         uint32_t ui32RetVal = ADCn(ui32Module)->INTSTAT;
1386         *pui32Status = ADCn(ui32Module)->INTEN & ui32RetVal;
1387     }
1388     else
1389     {
1390         *pui32Status = ADCn(ui32Module)->INTSTAT;
1391     }
1392 
1393     //
1394     // Return the status.
1395     //
1396     return AM_HAL_STATUS_SUCCESS;
1397 
1398 } // am_hal_adc_interrupt_status()
1399 
1400 //*****************************************************************************
1401 //
1402 //! @brief ADC interrupt clear
1403 //!
1404 //! @param pHandle         - handle for the interface.
1405 //! @param ui32IntMask    - uint32_t for interrupts to clear
1406 //!
1407 //! This function clears the interrupts for the given peripheral.
1408 //!
1409 //! @return status      - generic or interface specific status.
1410 //
1411 //*****************************************************************************
1412 uint32_t
am_hal_adc_interrupt_clear(void * pHandle,uint32_t ui32IntMask)1413 am_hal_adc_interrupt_clear(void *pHandle, uint32_t ui32IntMask)
1414 {
1415     uint32_t    ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1416 
1417 #ifndef AM_HAL_DISABLE_API_VALIDATION
1418     //
1419     // Check the handle.
1420     //
1421     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1422     {
1423         return AM_HAL_STATUS_INVALID_HANDLE;
1424     }
1425 #endif // AM_HAL_DISABLE_API_VALIDATION
1426 
1427     //
1428     // Clear the interrupts.
1429     //
1430     ADCn(ui32Module)->INTCLR = ui32IntMask;
1431 
1432     //
1433     // Return the status.
1434     //
1435     return AM_HAL_STATUS_SUCCESS;
1436 
1437 } // am_hal_adc_interrupt_clear()
1438 
1439 //*****************************************************************************
1440 //
1441 // sample_correction_apply()
1442 //
1443 //*****************************************************************************
1444 static uint32_t
sample_correction_apply(uint32_t ui32Sample,bool bApplyCorrection)1445 sample_correction_apply(uint32_t ui32Sample, bool bApplyCorrection)
1446 {
1447     float fSampleAdj;
1448 
1449     if ( g_bDoADCadjust )
1450     {
1451         //
1452         // Apply the gain/offset correction to the full sample for all
1453         // channels except temperature.
1454         //
1455         if ( bApplyCorrection )
1456         {
1457             //
1458             // General correction equation:
1459             //  sample_corrected = (sample / (1.0F - gain)) - offset
1460             //
1461             fSampleAdj = (float)(AM_HAL_ADC_FIFO_SAMPLE(ui32Sample) * AM_HAL_ADC_VREFMV / AM_HAL_ADC_SAMPLE_DIVISOR);
1462             fSampleAdj /= (1.0F - priv_correction_trims.flt.fADCgain);
1463 
1464             //
1465             // Convert the offset from volts to mv.
1466             //
1467             fSampleAdj -= (priv_correction_trims.flt.fADCoffset * 1000.0F);
1468             fSampleAdj  = fSampleAdj * AM_HAL_ADC_SAMPLE_DIVISORF / AM_HAL_ADC_VREFMVF;
1469 
1470             //
1471             // Check for overflow
1472             //
1473             if ( fSampleAdj > 4095.0F )
1474             {
1475                 fSampleAdj = 4095.0F;
1476             }
1477 
1478             ui32Sample &= 0xFFF00000;
1479             ui32Sample |= ((((uint32_t)fSampleAdj) << 6) & AM_HAL_ADC_SAMPLE_MASK_FULL);
1480         }
1481     }
1482     return ui32Sample;
1483 } // sample_correction_apply()
1484 
1485 //*****************************************************************************
1486 //
1487 // ADC sample read function
1488 //
1489 // This function reads samples from the ADC FIFO or an SRAM sample buffer
1490 // returned by a DMA operation.
1491 //
1492 //*****************************************************************************
1493 uint32_t
am_hal_adc_samples_read(void * pHandle,bool bFullSample,uint32_t * pui32InSampleBuffer,uint32_t * pui32InOutNumberSamples,am_hal_adc_sample_t * pui32OutBuffer)1494 am_hal_adc_samples_read(void *pHandle,
1495                         bool bFullSample,
1496                         uint32_t *pui32InSampleBuffer,
1497                         uint32_t *pui32InOutNumberSamples,
1498                         am_hal_adc_sample_t *pui32OutBuffer)
1499 {
1500     uint32_t      ui32Sample;
1501     uint32_t      ui32RequestedSamples = *pui32InOutNumberSamples;
1502     uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1503     uint32_t ui32slot, ui32slotcfgaddr, ui32chsel, ui32TempMask;
1504     bool bTempChnl;
1505 
1506 #ifndef AM_HAL_DISABLE_API_VALIDATION
1507     //
1508     // Check the handle.
1509     //
1510     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1511     {
1512         return AM_HAL_STATUS_INVALID_HANDLE;
1513     }
1514 
1515     //
1516     // Check the output sample buffer pointer.
1517     //
1518     if ( NULL == pui32OutBuffer )
1519     {
1520         return AM_HAL_STATUS_INVALID_ARG;
1521     }
1522 #endif // AM_HAL_DISABLE_API_VALIDATION
1523 
1524     *pui32InOutNumberSamples = 0;
1525 
1526     //
1527     // Check if we are reading directly from FIFO or DMA SRAM buffer.
1528     //
1529     if ( pui32InSampleBuffer == NULL )
1530     {
1531         //
1532         // Grab a value from the ADC FIFO
1533         //
1534         do
1535         {
1536             ui32Sample = ADCn(ui32Module)->FIFOPR;
1537 
1538             ui32slot = AM_HAL_ADC_FIFO_SLOT(ui32Sample);
1539             ui32slotcfgaddr = ((uint32_t)(&ADCn(ui32Module)->SL0CFG)) + (4 * ui32slot);
1540             ui32chsel = _FLD2VAL(ADC_SL0CFG_CHSEL0, AM_REGVAL(ui32slotcfgaddr));
1541             bTempChnl = (ui32chsel == ADC_SL0CFG_CHSEL0_TEMP) ? true : false;
1542 
1543             //
1544             // Apply the sample correction.
1545             //
1546             ui32Sample = sample_correction_apply(ui32Sample, !bTempChnl);
1547             pui32OutBuffer->ui32Slot   = AM_HAL_ADC_FIFO_SLOT(ui32Sample);
1548             pui32OutBuffer->ui32Sample = bFullSample                             ?
1549                                          AM_HAL_ADC_FIFO_FULL_SAMPLE(ui32Sample) :
1550                                          AM_HAL_ADC_FIFO_SAMPLE(ui32Sample);
1551             pui32OutBuffer++;
1552             (*pui32InOutNumberSamples)++;
1553         } while ((AM_HAL_ADC_FIFO_COUNT(ui32Sample) > 0) &&
1554                  (*pui32InOutNumberSamples < ui32RequestedSamples));
1555     }
1556     else
1557     {
1558         //
1559         // Before processing the buffer of samples, pre-process the slot
1560         // configuration registers to build a mask of slots that might be
1561         // configured as temperature. The mask will be used later for
1562         // determining whether to apply correction.
1563         // This, of course, depends on and assumes that the slots are still
1564         // configured as they were while the samples were taken.
1565         //
1566         ui32TempMask = 0;
1567         ui32TempMask |= (_FLD2VAL(ADC_SL0CFG_CHSEL0, ADC->SL0CFG) == ADC_SL0CFG_CHSEL0_TEMP) ? 1 << 0 : 0;
1568         ui32TempMask |= (_FLD2VAL(ADC_SL1CFG_CHSEL1, ADC->SL1CFG) == ADC_SL1CFG_CHSEL1_TEMP) ? 1 << 1 : 0;
1569         ui32TempMask |= (_FLD2VAL(ADC_SL2CFG_CHSEL2, ADC->SL2CFG) == ADC_SL2CFG_CHSEL2_TEMP) ? 1 << 2 : 0;
1570         ui32TempMask |= (_FLD2VAL(ADC_SL3CFG_CHSEL3, ADC->SL3CFG) == ADC_SL3CFG_CHSEL3_TEMP) ? 1 << 3 : 0;
1571         ui32TempMask |= (_FLD2VAL(ADC_SL4CFG_CHSEL4, ADC->SL4CFG) == ADC_SL4CFG_CHSEL4_TEMP) ? 1 << 4 : 0;
1572         ui32TempMask |= (_FLD2VAL(ADC_SL5CFG_CHSEL5, ADC->SL5CFG) == ADC_SL5CFG_CHSEL5_TEMP) ? 1 << 5 : 0;
1573         ui32TempMask |= (_FLD2VAL(ADC_SL6CFG_CHSEL6, ADC->SL6CFG) == ADC_SL6CFG_CHSEL6_TEMP) ? 1 << 6 : 0;
1574         ui32TempMask |= (_FLD2VAL(ADC_SL7CFG_CHSEL7, ADC->SL7CFG) == ADC_SL7CFG_CHSEL7_TEMP) ? 1 << 7 : 0;
1575 
1576         //
1577         // Process the samples from the provided sample buffer
1578         //
1579         do
1580         {
1581             //
1582             // Apply the sample correction.
1583             // Note that the correction is not used for temperature.
1584             //
1585             ui32slot   = AM_HAL_ADC_FIFO_SLOT(*pui32InSampleBuffer);
1586             ui32Sample = AM_HAL_ADC_FIFO_FULL_SAMPLE(*pui32InSampleBuffer);
1587             bTempChnl  = ((ui32TempMask >> ui32slot) & 1) ? true : false;
1588             pui32OutBuffer->ui32Sample = AM_HAL_ADC_FIFO_SAMPLE(sample_correction_apply(ui32Sample,
1589                                                                 !bTempChnl));
1590             pui32OutBuffer->ui32Slot   = ui32slot;
1591             pui32InSampleBuffer++;
1592             pui32OutBuffer++;
1593             (*pui32InOutNumberSamples)++;
1594         } while (*pui32InOutNumberSamples < ui32RequestedSamples);
1595     }
1596 
1597     //
1598     // Return FIFO valid bits.
1599     //
1600     return AM_HAL_STATUS_SUCCESS;
1601 
1602 } // am_hal_adc_samples_read()
1603 
1604 //*****************************************************************************
1605 //
1606 //! @brief Issue Software Trigger to the ADC.
1607 //!
1608 //! @param pHandle   - handle for the module instance.
1609 //!
1610 //! This function triggers the ADC operation.
1611 //!
1612 //! @return status      - generic or interface specific status.
1613 //
1614 //*****************************************************************************
1615 uint32_t
am_hal_adc_sw_trigger(void * pHandle)1616 am_hal_adc_sw_trigger(void *pHandle)
1617 {
1618     uint32_t    ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1619 
1620 #ifndef AM_HAL_DISABLE_API_VALIDATION
1621     //
1622     // Check the handle.
1623     //
1624     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1625     {
1626         return AM_HAL_STATUS_INVALID_HANDLE;
1627     }
1628 #endif // AM_HAL_DISABLE_API_VALIDATION
1629 
1630     //
1631     // Write to the Software trigger register in the ADC.
1632     //
1633     ADCn(ui32Module)->SWT = 0x37;
1634 
1635     //
1636     // Return the status.
1637     //
1638     return AM_HAL_STATUS_SUCCESS;
1639 
1640 } // am_hal_adc_sw_trigger()
1641 
1642 //*****************************************************************************
1643 //
1644 //! @brief ADC power control function
1645 //!
1646 //! @param pHandle       - handle for the interface.
1647 //! @param ePowerState  - the desired power state to move the peripheral to.
1648 //! @param bRetainState - flag (if true) to save/restore peripheral state upon
1649 //!                       power state change.
1650 //!
1651 //! This function updates the peripheral to a given power state.
1652 //!
1653 //! @return status      - generic or interface specific status.
1654 //
1655 //*****************************************************************************
1656 uint32_t
am_hal_adc_power_control(void * pHandle,am_hal_sysctrl_power_state_e ePowerState,bool bRetainState)1657 am_hal_adc_power_control(void *pHandle,
1658                          am_hal_sysctrl_power_state_e ePowerState,
1659                          bool bRetainState)
1660 {
1661     am_hal_adc_state_t  *pADCState = (am_hal_adc_state_t *)pHandle;
1662     uint32_t            ui32Module = pADCState->ui32Module;
1663 
1664 #ifndef AM_HAL_DISABLE_API_VALIDATION
1665     //
1666     // Check the handle.
1667     //
1668     if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1669     {
1670         return AM_HAL_STATUS_INVALID_HANDLE;
1671     }
1672 #endif // AM_HAL_DISABLE_API_VALIDATION
1673 
1674     //
1675     // Decode the requested power state and update ADC operation accordingly.
1676     //
1677     switch (ePowerState)
1678     {
1679         case AM_HAL_SYSCTRL_WAKE:
1680             if ( bRetainState  &&  !pADCState->registerState.bValid )
1681             {
1682                 return AM_HAL_STATUS_INVALID_OPERATION;
1683             }
1684 
1685             //
1686             // Enable the ADC power domain.
1687             //
1688             am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_ADC);
1689 
1690             if ( bRetainState )
1691             {
1692                 ADCn(ui32Module)->SL0CFG        = pADCState->registerState.regSL0CFG;
1693                 ADCn(ui32Module)->SL1CFG        = pADCState->registerState.regSL1CFG;
1694                 ADCn(ui32Module)->SL2CFG        = pADCState->registerState.regSL2CFG;
1695                 ADCn(ui32Module)->SL3CFG        = pADCState->registerState.regSL3CFG;
1696                 ADCn(ui32Module)->SL4CFG        = pADCState->registerState.regSL4CFG;
1697                 ADCn(ui32Module)->SL5CFG        = pADCState->registerState.regSL5CFG;
1698                 ADCn(ui32Module)->SL6CFG        = pADCState->registerState.regSL6CFG;
1699                 ADCn(ui32Module)->SL7CFG        = pADCState->registerState.regSL7CFG;
1700                 ADCn(ui32Module)->INTTRIGTIMER  = pADCState->registerState.regIntTrigTmr;
1701                 ADCn(ui32Module)->WULIM         = pADCState->registerState.regWULIM;
1702                 ADCn(ui32Module)->WLLIM         = pADCState->registerState.regWLLIM;
1703 
1704                 ADCn(ui32Module)->INTEN         = 0x0;
1705                 ADC_CRITICAL_BEGIN(ui32Module)
1706                 ADCn(ui32Module)->CFG           = pADCState->registerState.regCFG;
1707                 ForceFIFOpop(pHandle);  // See errata ERR090
1708                 ADC_CRITICAL_END(ui32Module)
1709                 ADCn(ui32Module)->INTEN         = pADCState->registerState.regINTEN;
1710                 pADCState->registerState.bValid = false;
1711             }
1712 
1713             break;
1714 
1715         case AM_HAL_SYSCTRL_NORMALSLEEP:
1716         case AM_HAL_SYSCTRL_DEEPSLEEP:
1717             if ( bRetainState )
1718             {
1719                 pADCState->registerState.regSL0CFG      = ADCn(ui32Module)->SL0CFG;
1720                 pADCState->registerState.regSL1CFG      = ADCn(ui32Module)->SL1CFG;
1721                 pADCState->registerState.regSL2CFG      = ADCn(ui32Module)->SL2CFG;
1722                 pADCState->registerState.regSL3CFG      = ADCn(ui32Module)->SL3CFG;
1723                 pADCState->registerState.regSL4CFG      = ADCn(ui32Module)->SL4CFG;
1724                 pADCState->registerState.regSL5CFG      = ADCn(ui32Module)->SL5CFG;
1725                 pADCState->registerState.regSL6CFG      = ADCn(ui32Module)->SL6CFG;
1726                 pADCState->registerState.regSL7CFG      = ADCn(ui32Module)->SL7CFG;
1727                 pADCState->registerState.regIntTrigTmr  = ADCn(ui32Module)->INTTRIGTIMER;
1728                 pADCState->registerState.regWULIM       = ADCn(ui32Module)->WULIM;
1729                 pADCState->registerState.regWLLIM       = ADCn(ui32Module)->WLLIM;
1730                 pADCState->registerState.regINTEN       = ADCn(ui32Module)->INTEN;
1731                 pADCState->registerState.regCFG         = ADCn(ui32Module)->CFG;
1732 
1733                 pADCState->registerState.bValid     = true;
1734             }
1735 
1736             //
1737             // Disable the ADC power domain.
1738             //
1739             am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC);
1740             break;
1741 
1742         default:
1743             return AM_HAL_STATUS_INVALID_ARG;
1744     }
1745 
1746     //
1747     // Return the status.
1748     //
1749     return AM_HAL_STATUS_SUCCESS;
1750 
1751 } // am_hal_adc_power_control()
1752 
1753 //*****************************************************************************
1754 //
1755 // End Doxygen group.
1756 //! @}
1757 //
1758 //*****************************************************************************
1759