vos/ambiq-hal-sys/ambiq-sparkfun-sdk/mcu/apollo3p/hal/am_hal_adc.c
2022-10-23 23:45:43 -07:00

1285 lines
38 KiB
C

//*****************************************************************************
//
// am_hal_adc.c
//! @file
//!
//! @brief Functions for interfacing with the Analog to Digital Converter.
//!
//! @addtogroup adc3p Analog-to-Digital Converter (ADC)
//! @ingroup apollo3phal
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// Copyright (c) 2020, Ambiq Micro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// Third party software included in this distribution is subject to the
// additional license terms as defined in the /docs/licenses directory.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include "am_mcu_apollo.h"
//*****************************************************************************
//
// Private Types.
//
//*****************************************************************************
#define AM_HAL_MAGIC_ADC 0xAFAFAF
#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))
// ****************************************************************************
//
// Apollo3 Temperature Trim Value Locations and default coefficients.
//
// ****************************************************************************
#define AM_HAL_ADC_CALIB_TEMP_ADDR (0x50023840)
#define AM_HAL_ADC_CALIB_AMBIENT_ADDR (0x50023844)
#define AM_HAL_ADC_CALIB_ADC_OFFSET_ADDR (0x50023848)
// ****************************************************************************
//
// Default coefficients (used when trims not provided):
// TEMP_DEFAULT = Temperature in deg K (e.g. 299.5 - 273.15 = 26.35)
// AMBIENT_DEFAULT = Voltage measurement at default temperature.
// OFFSET_DEFAULT = Default ADC offset at 1v.
//
// ****************************************************************************
#define AM_HAL_ADC_CALIB_TEMP_DEFAULT (299.5F)
#define AM_HAL_ADC_CALIB_AMBIENT_DEFAULT (1.02809F)
#define AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT (-0.004281F)
//
// ADC Power save register state.
//
typedef struct
{
bool bValid;
uint32_t regCFG;
uint32_t regSL0CFG;
uint32_t regSL1CFG;
uint32_t regSL2CFG;
uint32_t regSL3CFG;
uint32_t regSL4CFG;
uint32_t regSL5CFG;
uint32_t regSL6CFG;
uint32_t regSL7CFG;
uint32_t regWULIM;
uint32_t regWLLIM;
uint32_t regINTEN;
} am_hal_adc_register_state_t;
//
// ADC State structure.
//
typedef struct
{
//
// Handle validation prefix.
//
am_hal_handle_prefix_t prefix;
//
// Physical module number.
//
uint32_t ui32Module;
//
// ADC Capabilities.
//
am_hal_adc_capabilities_t capabilities;
// Power Save-Restore register state
am_hal_adc_register_state_t registerState;
} am_hal_adc_state_t;
//*****************************************************************************
//
//! @brief Private SRAM view of temperature trims.
//!
//! This static SRAM union is private to the ADC HAL functions.
//
//*****************************************************************************
static union
{
//! These trim values are loaded as uint32_t values.
struct
{
//! Temperature of the package test head (in degrees Kelvin)
uint32_t ui32CalibrationTemperature;
//! Voltage corresponding to temperature measured on test head.
uint32_t ui32CalibrationVoltage;
//! ADC offset voltage measured on the package test head.
uint32_t ui32CalibrationOffset;
//! Flag if default (guess) or measured.
bool bMeasured;
} ui32;
//! These trim values are accessed as floats when used in temp calculations.
struct
{
//! Temperature of the package test head in degrees Kelvin
float fCalibrationTemperature;
//! Voltage corresponding to temperature measured on test head.
float fCalibrationVoltage;
//! ADC offset voltage measured on the package test head.
float fCalibrationOffset;
//! Flag if default (guess) or measured.
float fMeasuredFlag;
} flt;
} priv_temp_trims;
//*****************************************************************************
//
// Global Variables.
//
//*****************************************************************************
am_hal_adc_state_t g_ADCState[AM_REG_ADC_NUM_MODULES];
uint32_t g_ADCSlotsConfigured;
//*****************************************************************************
//
//! @brief ADC initialization function
//!
//! @param ui32Module - module instance.
//! @param handle - returns the handle for the module instance.
//!
//! This function accepts a module instance, allocates the interface and then
//! returns a handle to be used by the remaining interface functions.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_initialize(uint32_t ui32Module, void **ppHandle)
{
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Validate the module number
//
if ( ui32Module >= AM_REG_ADC_NUM_MODULES )
{
return AM_HAL_STATUS_OUT_OF_RANGE;
}
//
// Check for valid arguements.
//
if ( !ppHandle )
{
return AM_HAL_STATUS_INVALID_ARG;
}
//
// Check if the handle is unallocated.
//
if ( g_ADCState[ui32Module].prefix.s.bInit )
{
return AM_HAL_STATUS_INVALID_OPERATION;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Initialize the handle.
//
g_ADCState[ui32Module].prefix.s.bInit = true;
g_ADCState[ui32Module].prefix.s.magic = AM_HAL_MAGIC_ADC;
g_ADCState[ui32Module].ui32Module = ui32Module;
//
// Initialize the number of slots configured.
//
g_ADCSlotsConfigured = 0;
//
// Return the handle.
//
*ppHandle = (void *)&g_ADCState[ui32Module];
//
// Before returning, grab the temperature trims.
//
priv_temp_trims.ui32.ui32CalibrationTemperature =
am_hal_flash_load_ui32((uint32_t*)AM_HAL_ADC_CALIB_TEMP_ADDR);
priv_temp_trims.ui32.ui32CalibrationVoltage =
am_hal_flash_load_ui32((uint32_t*)AM_HAL_ADC_CALIB_AMBIENT_ADDR);
priv_temp_trims.ui32.ui32CalibrationOffset =
am_hal_flash_load_ui32((uint32_t*)AM_HAL_ADC_CALIB_ADC_OFFSET_ADDR);
if ( (priv_temp_trims.ui32.ui32CalibrationTemperature == 0xffffffff) ||
(priv_temp_trims.ui32.ui32CalibrationVoltage == 0xffffffff) ||
(priv_temp_trims.ui32.ui32CalibrationOffset == 0xffffffff) )
{
//
// Since the device has not been calibrated on the tester, we'll load
// default calibration values. These default values should result
// in worst-case temperature measurements of +-6 degress C.
//
priv_temp_trims.flt.fCalibrationTemperature = AM_HAL_ADC_CALIB_TEMP_DEFAULT;
priv_temp_trims.flt.fCalibrationVoltage = AM_HAL_ADC_CALIB_AMBIENT_DEFAULT;
priv_temp_trims.flt.fCalibrationOffset = AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT;
priv_temp_trims.ui32.bMeasured = false;
}
else
{
priv_temp_trims.ui32.bMeasured = true;
}
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief MSPI deinitialization function
//!
//! @param handle - returns the handle for the module instance.
//!
//! This function accepts a handle to an instance and de-initializes the
//! interface.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_deinitialize(void *pHandle)
{
uint32_t status = AM_HAL_STATUS_SUCCESS;
am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
if ( pADCState->prefix.s.bEnable )
{
status = am_hal_adc_disable(pHandle);
}
pADCState->prefix.s.bInit = false;
//
// Return the status.
//
return status;
}
//*****************************************************************************
//
//! @brief ADC configuration function
//!
//! @param handle - handle for the module instance.
//! @param pConfig - pointer to the configuration structure.
//!
//! This function configures the ADC for operation.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_configure(void *pHandle,
am_hal_adc_config_t *psConfig)
{
uint32_t ui32Config;
am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
uint32_t ui32Module = pADCState->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
ui32Config = 0;
//
// Set the ADC clock source.
//
ui32Config |= _VAL2FLD(ADC_CFG_CLKSEL, psConfig->eClock);
//
// Set the ADC trigger polarity.
//
ui32Config |= _VAL2FLD(ADC_CFG_TRIGPOL, psConfig->ePolarity);
//
// Set the ADC trigger.
//
ui32Config |= _VAL2FLD(ADC_CFG_TRIGSEL, psConfig->eTrigger);
//
// Set the ADC reference voltage.
//
ui32Config |= _VAL2FLD(ADC_CFG_REFSEL, psConfig->eReference);
//
// Set the Destructive FIFO read.
//
ui32Config |= _VAL2FLD(ADC_CFG_DFIFORDEN, 1);
//
// Set the ADC clock mode.
//
ui32Config |= _VAL2FLD(ADC_CFG_CKMODE, psConfig->eClockMode);
//
// Set the ADC low power mode.
//
ui32Config |= _VAL2FLD(ADC_CFG_LPMODE, psConfig->ePowerMode);
//
// Set the ADC repetition mode.
//
ui32Config |= _VAL2FLD(ADC_CFG_RPTEN, psConfig->eRepeat);
//
// Set the configuration in the ADC peripheral.
//
ADCn(ui32Module)->CFG = ui32Config;
//
// Return status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC slot configuration function
//!
//! @param handle - handle for the module instance.
//! @param pConfig - pointer to the configuration structure.
//!
//! This function configures the ADC slot for operation.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_configure_slot(void *pHandle,
uint32_t ui32SlotNumber,
am_hal_adc_slot_config_t *pSlotConfig)
{
uint32_t ui32Config;
uint32_t ui32RegOffset;
am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
uint32_t ui32Module = pADCState->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
//
// Check the slot number.
//
if ( ui32SlotNumber >= AM_HAL_ADC_MAX_SLOTS )
{
return AM_HAL_STATUS_OUT_OF_RANGE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
ui32Config = 0;
//
// Set the measurements to average
//
ui32Config |= _VAL2FLD(ADC_SL0CFG_ADSEL0, pSlotConfig->eMeasToAvg);
//
// Set the precision mode.
//
ui32Config |= _VAL2FLD(ADC_SL0CFG_PRMODE0, pSlotConfig->ePrecisionMode);
//
// Set the channel.
//
ui32Config |= _VAL2FLD(ADC_SL0CFG_CHSEL0, pSlotConfig->eChannel);
//
// Enable window comparison if configured.
//
ui32Config |= _VAL2FLD(ADC_SL0CFG_WCEN0, pSlotConfig->bWindowCompare);
//
// Enable the slot if configured.
//
ui32Config |= _VAL2FLD(ADC_SL0CFG_SLEN0, pSlotConfig->bEnabled);
//
// Locate the correct register for this ADC slot.
//
ui32RegOffset = ((uint32_t)&ADCn(ui32Module)->SL0CFG) + (4 * ui32SlotNumber);
//
// Write the register with the caller's configuration value.
//
AM_REGVAL(ui32RegOffset) = ui32Config;
//
// Update the nubmer of slots configured.
//
g_ADCSlotsConfigured++;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC DMA configuration function
//!
//! @param handle - handle for the module instance.
//! @param pConfig - pointer to the configuration structure.
//!
//! This function configures the ADC DMA for operation.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_configure_dma(void *pHandle,
am_hal_adc_dma_config_t *pDMAConfig)
{
uint32_t ui32Config;
uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
//
// Check for DMA to/from DTCM.
//
if ( (pDMAConfig->ui32TargetAddress >= AM_HAL_FLASH_DTCM_START) &&
(pDMAConfig->ui32TargetAddress <= AM_HAL_FLASH_DTCM_END) )
{
return AM_HAL_STATUS_OUT_OF_RANGE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
ui32Config = 0;
//
// Configure the DMA complete power-off.
//
ui32Config |= _VAL2FLD(ADC_DMACFG_DPWROFF, 0); // DPWROFF not supported!
//
// Configure the data to be transferred.
//
if ( g_ADCSlotsConfigured > 1 )
{
// Need slot number to distinguish between slot results.
ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_DIS);
}
else
{
ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_EN);
}
//
// Enable DMA Halt on Status (DMAERR or DMACPL) by default.
//
ui32Config |= _VAL2FLD(ADC_DMACFG_DMAHONSTAT, ADC_DMACFG_DMAHONSTAT_EN);
//
// Configure the DMA dynamic priority handling.
//
ui32Config |= _VAL2FLD(ADC_DMACFG_DMADYNPRI, pDMAConfig->bDynamicPriority);
//
// Configure the DMA static priority.
//
ui32Config |= _VAL2FLD(ADC_DMACFG_DMAPRI, pDMAConfig->ePriority);
//
// Enable the DMA (does not start until ADC is enabled and triggered).
//
ui32Config |= _VAL2FLD(ADC_DMACFG_DMAEN, ADC_DMACFG_DMAEN_EN);
//
// Set the DMA configuration.
//
ADCn(ui32Module)->DMACFG = ui32Config;
//
// Set the DMA transfer count.
//
ADCn(ui32Module)->DMATOTCOUNT_b.TOTCOUNT = pDMAConfig->ui32SampleCount;
//
// Set the DMA target address.
//
ADCn(ui32Module)->DMATARGADDR = pDMAConfig->ui32TargetAddress;
//
// Set the DMA trigger on FIFO 75% full.
//
ADCn(ui32Module)->DMATRIGEN = ADC_DMATRIGEN_DFIFO75_Msk;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC device specific control function.
//!
//! @param handle - handle for the module instance.
//!
//! This function provides for special control functions for the ADC operation.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t am_hal_adc_control(void *pHandle,
am_hal_adc_request_e eRequest,
void *pArgs)
{
uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
switch ( eRequest )
{
case AM_HAL_ADC_REQ_WINDOW_CONFIG:
{
am_hal_adc_window_config_t *pWindowConfig = (am_hal_adc_window_config_t *)pArgs;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the window limits.
//
if ( (pWindowConfig->ui32Upper > ADC_WULIM_ULIM_Msk) ||
(pWindowConfig->ui32Lower > ADC_WLLIM_LLIM_Msk) )
{
return AM_HAL_STATUS_OUT_OF_RANGE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Set the window comparison upper and lower limits.
//
ADCn(ui32Module)->WULIM = _VAL2FLD(ADC_WULIM_ULIM, pWindowConfig->ui32Upper);
ADCn(ui32Module)->WLLIM = _VAL2FLD(ADC_WLLIM_LLIM, pWindowConfig->ui32Lower);
//
// Set the window scale per precision mode if indicated.
//
ADCn(ui32Module)->SCWLIM = _VAL2FLD(ADC_SCWLIM_SCWLIMEN,
pWindowConfig->bScaleLimits);
}
break;
case AM_HAL_ADC_REQ_TEMP_CELSIUS_GET:
//
// pArgs must point to an array of 3 floats. To assure that the
// array is valid, upon calling the 3rd float (pArgs[2]) must be
// set to the value -123.456F.
//
if ( pArgs != NULL )
{
float *pfArray = (float*)pArgs;
float fTemp, fCalibration_temp, fCalibration_voltage, fCalibration_offset, fVoltage;
if ( pfArray[2] == -123.456F )
{
//
// Get the scaled voltage obtained from the ADC sample.
// The ADC sample value is scaled up by the reference voltage
// (e.g. 1.5F), then divided by 65536.0F.
//
fVoltage = pfArray[0];
//
// Get calibration temperature from trimmed values & convert to degrees K.
//
fCalibration_temp = priv_temp_trims.flt.fCalibrationTemperature;
fCalibration_voltage = priv_temp_trims.flt.fCalibrationVoltage;
fCalibration_offset = priv_temp_trims.flt.fCalibrationOffset;
//
// Compute the temperature.
//
fTemp = fCalibration_temp;
fTemp /= (fCalibration_voltage - fCalibration_offset);
fTemp *= (fVoltage - fCalibration_offset);
//
// Give it back to the caller in Celsius.
//
pfArray[1] = fTemp - 273.15f;
}
else
{
return AM_HAL_STATUS_INVALID_OPERATION;
}
}
else
{
return AM_HAL_STATUS_INVALID_ARG;
}
break;
case AM_HAL_ADC_REQ_TEMP_TRIMS_GET:
//
// pArgs must point to an array of 4 floats. To assure that the
// array is valid, upon calling the 4th float (pArgs[3]) must be
// set to the value -123.456.
// On return, pArgs[3] is set to 1 if the returned values are
// calibrated, or 0 if default calibration values.
//
if ( pArgs != NULL )
{
float *pfArray = (float*)pArgs;
if ( pfArray[3] == -123.456F )
{
//
// Return trim temperature as a float.
//
pfArray[0] = priv_temp_trims.flt.fCalibrationTemperature;
//
// Return trim voltage as a float.
//
pfArray[1] = priv_temp_trims.flt.fCalibrationVoltage;
//
// Return trim ADC offset voltage as a float.
//
pfArray[2] = priv_temp_trims.flt.fCalibrationOffset;
//
// Set the calibrated or uncalibrated flag
//
((uint32_t*)pArgs)[3] = priv_temp_trims.ui32.bMeasured;
}
else
{
return AM_HAL_STATUS_INVALID_OPERATION;
}
}
else
{
return AM_HAL_STATUS_INVALID_ARG;
}
break;
default:
return AM_HAL_STATUS_INVALID_ARG;
}
//
// Return status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC enable function
//!
//! @param handle - handle for the module instance.
//!
//! This function enables the ADC operation.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_enable(void *pHandle)
{
am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
uint32_t ui32Module = pADCState->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
if ( pADCState->prefix.s.bEnable )
{
return AM_HAL_STATUS_SUCCESS;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Enable the ADC.
//
ADCn(ui32Module)->CFG_b.ADCEN = 0x1;
//
// Set flag to indicate module is enabled.
//
pADCState->prefix.s.bEnable = true;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC disable function
//!
//! @param handle - handle for the module instance.
//!
//! This function disables the ADC operation.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_disable(void *pHandle)
{
am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
uint32_t ui32Module = pADCState->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Disable the ADC.
//
ADCn(ui32Module)->CFG_b.ADCEN = 0x0;
//
// Set flag to indicate module is disabled.
//
pADCState->prefix.s.bEnable = false;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC status function
//!
//! @param handle - handle for the interface.
//!
//! This function returns the current status of the DMA operation.
//!
//! @return status - DMA status flags.
//
//*****************************************************************************
uint32_t
am_hal_adc_status_get(void *pHandle, am_hal_adc_status_t *pStatus )
{
uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Get the power status.
//
pStatus->bPoweredOn = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
_VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_ON);
//
// Get the low power mode 1 status.
//
pStatus->bLPMode1 = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
_VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_POWERED_DOWN);
//
// Get the DMA status.
//
pStatus->bErr = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMAERR_Msk) > 0);
pStatus->bCmp = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMACPL_Msk) > 0);
pStatus->bTIP = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMATIP_Msk) > 0);
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC enable interrupts function
//!
//! @param handle - handle for the interface.
//! @param ui32IntMask - ADC interrupt mask.
//!
//! This function enables the specific indicated interrupts.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_interrupt_enable(void *pHandle, uint32_t ui32IntMask)
{
uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Enable the interrupts.
//
ADCn(ui32Module)->INTEN |= ui32IntMask;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC disable interrupts function
//!
//! @param handle - handle for the interface.
//! @param ui32IntMask - ADC interrupt mask.
//!
//! This function disable the specific indicated interrupts.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_interrupt_disable(void *pHandle, uint32_t ui32IntMask)
{
uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Disable the interrupts.
//
ADCn(ui32Module)->INTEN &= ~ui32IntMask;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC interrupt status function
//!
//! @param handle - handle for the interface.
//!
//! This function returns the specific indicated interrupt status.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_interrupt_status(void *pHandle,
uint32_t *pui32Status,
bool bEnabledOnly)
{
uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// if requested, only return the interrupts that are enabled.
//
if ( bEnabledOnly )
{
uint32_t ui32RetVal = ADCn(ui32Module)->INTSTAT;
*pui32Status = ADCn(ui32Module)->INTEN & ui32RetVal;
}
else
{
*pui32Status = ADCn(ui32Module)->INTSTAT;
}
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC interrupt clear
//!
//! @param handle - handle for the interface.
//! @param ui32IntMask - uint32_t for interrupts to clear
//!
//! This function clears the interrupts for the given peripheral.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_interrupt_clear(void *pHandle, uint32_t ui32IntMask)
{
uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Clear the interrupts.
//
ADCn(ui32Module)->INTCLR = ui32IntMask;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
// ADC sample read function
//
// This function reads samples from the ADC FIFO or an SRAM sample buffer
// returned by a DMA operation.
//
//*****************************************************************************
uint32_t am_hal_adc_samples_read(void *pHandle, bool bFullSample,
uint32_t *pui32InSampleBuffer,
uint32_t *pui32InOutNumberSamples,
am_hal_adc_sample_t *pui32OutBuffer)
{
uint32_t ui32Sample;
uint32_t ui32RequestedSamples = *pui32InOutNumberSamples;
uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
//
// Check the output sample buffer pointer.
//
if ( NULL == pui32OutBuffer )
{
return AM_HAL_STATUS_INVALID_ARG;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
*pui32InOutNumberSamples = 0;
//
// Check if we are reading directly from FIFO or DMA SRAM buffer.
//
if ( NULL == pui32InSampleBuffer )
{
//
// Grab a value from the ADC FIFO
//
do
{
ui32Sample = ADCn(ui32Module)->FIFOPR;
pui32OutBuffer->ui32Slot = AM_HAL_ADC_FIFO_SLOT(ui32Sample);
pui32OutBuffer->ui32Sample = bFullSample ?
AM_HAL_ADC_FIFO_FULL_SAMPLE(ui32Sample) :
AM_HAL_ADC_FIFO_SAMPLE(ui32Sample);
pui32OutBuffer++;
(*pui32InOutNumberSamples)++;
} while ((AM_HAL_ADC_FIFO_COUNT(ui32Sample) > 0) &&
(*pui32InOutNumberSamples < ui32RequestedSamples));
}
else
{
//
// Process the samples from the provided sample buffer
//
do
{
ui32Sample = ADCn(ui32Module)->FIFOPR;
pui32OutBuffer->ui32Slot = AM_HAL_ADC_FIFO_SLOT(*pui32InSampleBuffer);
pui32OutBuffer->ui32Sample = AM_HAL_ADC_FIFO_SAMPLE(*pui32InSampleBuffer);
pui32InSampleBuffer++;
pui32OutBuffer++;
(*pui32InOutNumberSamples)++;
} while (*pui32InOutNumberSamples < ui32RequestedSamples);
}
//
// Return FIFO valid bits.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief Issue Software Trigger to the ADC.
//!
//! @param handle - handle for the module instance.
//!
//! This function triggers the ADC operation.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_sw_trigger(void *pHandle)
{
uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Write to the Software trigger register in the ADC.
//
ADCn(ui32Module)->SWT = 0x37;
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
//! @brief ADC power control function
//!
//! @param handle - handle for the interface.
//! @param ePowerState - the desired power state to move the peripheral to.
//! @param bRetainState - flag (if true) to save/restore peripheral state upon
//! power state change.
//!
//! This function updates the peripheral to a given power state.
//!
//! @return status - generic or interface specific status.
//
//*****************************************************************************
uint32_t
am_hal_adc_power_control(void *pHandle,
am_hal_sysctrl_power_state_e ePowerState,
bool bRetainState)
{
am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
uint32_t ui32Module = pADCState->ui32Module;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
//
// Decode the requested power state and update MSPI operation accordingly.
//
switch (ePowerState)
{
case AM_HAL_SYSCTRL_WAKE:
if ( bRetainState && !pADCState->registerState.bValid )
{
return AM_HAL_STATUS_INVALID_OPERATION;
}
//
// Enable the ADC power domain.
//
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_ADC);
if ( bRetainState )
{
ADCn(ui32Module)->SL0CFG = pADCState->registerState.regSL0CFG;
ADCn(ui32Module)->SL1CFG = pADCState->registerState.regSL1CFG;
ADCn(ui32Module)->SL2CFG = pADCState->registerState.regSL2CFG;
ADCn(ui32Module)->SL3CFG = pADCState->registerState.regSL3CFG;
ADCn(ui32Module)->SL4CFG = pADCState->registerState.regSL4CFG;
ADCn(ui32Module)->SL5CFG = pADCState->registerState.regSL5CFG;
ADCn(ui32Module)->SL6CFG = pADCState->registerState.regSL6CFG;
ADCn(ui32Module)->SL7CFG = pADCState->registerState.regSL7CFG;
ADCn(ui32Module)->WULIM = pADCState->registerState.regWULIM;
ADCn(ui32Module)->WLLIM = pADCState->registerState.regWLLIM;
ADCn(ui32Module)->INTEN = pADCState->registerState.regINTEN;
ADCn(ui32Module)->CFG = pADCState->registerState.regCFG;
pADCState->registerState.bValid = false;
}
break;
case AM_HAL_SYSCTRL_NORMALSLEEP:
case AM_HAL_SYSCTRL_DEEPSLEEP:
if ( bRetainState )
{
pADCState->registerState.regSL0CFG = ADCn(ui32Module)->SL0CFG;
pADCState->registerState.regSL1CFG = ADCn(ui32Module)->SL1CFG;
pADCState->registerState.regSL2CFG = ADCn(ui32Module)->SL2CFG;
pADCState->registerState.regSL3CFG = ADCn(ui32Module)->SL3CFG;
pADCState->registerState.regSL4CFG = ADCn(ui32Module)->SL4CFG;
pADCState->registerState.regSL5CFG = ADCn(ui32Module)->SL5CFG;
pADCState->registerState.regSL6CFG = ADCn(ui32Module)->SL6CFG;
pADCState->registerState.regSL7CFG = ADCn(ui32Module)->SL7CFG;
pADCState->registerState.regWULIM = ADCn(ui32Module)->WULIM;
pADCState->registerState.regWLLIM = ADCn(ui32Module)->WLLIM;
pADCState->registerState.regINTEN = ADCn(ui32Module)->INTEN;
pADCState->registerState.regCFG = ADCn(ui32Module)->CFG;
pADCState->registerState.bValid = true;
}
//
// Disable the ADC power domain.
//
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC);
break;
default:
return AM_HAL_STATUS_INVALID_ARG;
}
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}
//*****************************************************************************
//
// End Doxygen group.
//! @}
//
//*****************************************************************************