/* * Common IO - basic V1.0.0 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * http://aws.amazon.com/freertos * http://www.FreeRTOS.org */ /** * @file iot_adc.h * @brief File for the HAL APIs of ADC called by application layer. */ #ifndef _IOT_ADC_H_ #define _IOT_ADC_H_ /** * @brief Error code returned by ADC driver */ #define IOT_ADC_SUCCESS ( 0 ) /*!< ADC operation completed successfully. */ #define IOT_ADC_FAILED ( 1 ) /*!< ADC operation failed. */ #define IOT_ADC_INVALID_VALUE ( 2 ) /*!< At least one parameter is invalid. */ #define IOT_ADC_NOT_OPEN ( 3 ) /*!< ADC operation not possible unless ADC instance is opened. */ #define IOT_ADC_FUNCTION_NOT_SUPPORTED ( 4 ) /*!< ADC operation not supported. */ #define IOT_ADC_CH_BUSY ( 5 ) /*!< ADC channel is busy at current time. */ /** * @brief The handle for a ADC peripheral, defined in the source file. * This is an anonymous struct that is vendor/driver specific. */ struct IotAdcDescriptor; /** * @brief IotAdcHandle_t is the handle type returned by calling iot_adc_open(). * This is initialized in open and returned to caller. The caller must pass * this pointer to the rest of the ADC APIs. */ typedef struct IotAdcDescriptor * IotAdcHandle_t; /** * @brief ADC notification callback type * * @param[in] pvUserContext User Context passed when setting the callback. * This is not used or modified by the driver. The context is * provided by the caller when setting the callback, and is * passed back to the caller in the callback. * @param[out] pusConvertedData pointer to converted ADC sample data. */ typedef void ( * IotAdcCallback_t )( uint16_t * pusConvertedData, void * pvUserContext ); /** * @brief Initializes ADC controller with default configuration. * init ADC controller, enable ADC clock, reset HW FIFO, set default * configuration parameters, etc. Also allocate all required resources * for ADC operation such as software data buffer etc. * * @warning Must be called prior to any other ADC api's so that a valid handle is obtained. * @warning Once opened, the same ADC instance must be closed before calling open again. * * @param[in] lAdc The instance of ADC controller to initialize. * * @return * - handle to the ADC controller on success * - NULL, if * - invalid instance number * - open same instance more than once before closing it. */ IotAdcHandle_t iot_adc_open( int32_t lAdc ); /** * @brief Close ADC controller. * All pending operation will be cancelled, put ADC module in reset state or low * power state if possible. Release all resources claimed during open call * * @param[in] pxAdc handle to ADC controller returned from iot_adc_open() call. * * @return * - IOT_ADC_SUCCESS, on success; * - IOT_I2C_INVALID_VALUE, if pxAdc is NULL * - IOT_ADC_NOT_OPEN, if is not in open state (already closed). */ int32_t iot_adc_close( IotAdcHandle_t const pxAdc ); /** * @brief Sets channel callback on availability of channel scan data. * On availability of ADC scan data, the application is notified with a * function callback. The callback function and user context for callback * are set using iot_adc_set_callback. * * @note This callback is per AdcChannel for each handle. * @note If input handle or AdcChannel is invalid, or if callback function is NULL, * this function silently takes no action. * * @param[in] pxAdc The ADC handle returned in the open() call. * @param[in] ucAdcChannel The ADC channel for which the callback is set * @param[in] xAdcCallback The callback function to be called on availability of ADC channel data. * @param[in] pvUserContext The user context to be passed when callback is called. * * Example Callback Function * For asynchronous ADC calls, a callback function is used to signal when the async * task is complete. This example uses a Semaphore to signal the completion. * @code{c} * static void prvAdcChCallback( uint16_t * pusConvertedData, * void * pvUserContext ) * { * BaseType_t xHigherPriorityTaskWoken; * xSemaphoreGiveFromISR( xIotAdcSemaphore, &xHigherPriorityTaskWoken ); * } * @endcode */ void iot_adc_set_callback( IotAdcHandle_t const pxAdc, uint8_t ucAdcChannel, IotAdcCallback_t xAdcCallback, void * pvUserContext ); /** * @brief Start data acquisition for ADC channel until iot_adc_stop API is called. * Data will be passed back to client using callback function. * By default each callback will pass back one data sample, however if client has * used ioctl to pass in data buffer, only when buffer is full will callback * be triggered. * * @warning iot_adc_set_callback() must be called prior to this in order to get notification * when ADC scan is complete and data is available. * * @note iot_adc_set_callback() must be called prior to iot_adc_start(). * * @param[in] pxAdc The ADC handle returned in the open() call * @param[in] ucAdcChannel The ADC channel to start data acquisition * * @return * - IOT_ADC_SUCCESS on success * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid AdcChannel * - IOT_ADC_NOT_OPEN if ADC has not been opened yet. * - IOT_ADC_CH_BUSY if ADC operation has started but is not complete * - IOT_ADC_FAILED if not callback function has been set. * Example Asynchronous read * @code{c} * // ADC Instance to open * int32_t lAdcInstance = 0; * * // Return value of ADC functions * int32_t lRetVal; * * // ADC Channel to read * int32_t lAdcChannel = 0; * * // User/Driver context; if necessary * void xUserContext = NULL; * * // Open the ADC instance and get a handle. * xAdcHandle = iot_adc_open( lAdcInstance ); * // assert(lRetVal == IOT_ADC_SUCCESS); * * // set the callback function * iot_adc_set_callback( xAdcHandle, lAdcChannel, prvAdcChCallback, &xUserCntx ); * * // start channel data scan on channel * lRetVal = iot_adc_start( xAdcHandle, lAdcChannel ); * // assert( IOT_ADC_SUCCESS == lRetVal ); * * // wait for the ADC operation to complete * lRetVal = xSemaphoreTake( xIotAdcSemaphore, lIotAdcChWaitTime ); * // assert ( pdTRUE == lRetVal ); * * // stop channel data scan * lRetVal = iot_adc_stop( xAdcHandle, lAdcChannel ); * assert( IOT_ADC_SUCCESS == lRetVal ); * * // close ADC module * lRetVal = iot_adc_close( xAdcHandle ); * // assert( IOT_ADC_SUCCESS == lRetVal ); * @endcode */ int32_t iot_adc_start( IotAdcHandle_t const pxAdc, uint8_t ucAdcChannel ); /** * @brief Stop data acquisition for ADC channel * * @param[in] pxAdc The ADC handle returned in the open() call * @param[in] ucAdcChannel The ADC channel to stop data acquisition * * @return * - IOT_ADC_SCUCCESS on success * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid AdcChannel * - IOT_ADC_NOT_OPEN if ADC has been closed without re-opening. */ int32_t iot_adc_stop( IotAdcHandle_t const pxAdc, uint8_t ucAdcChannel ); /** * @brief read one ADC data sample. This API will return one ADC sample. * * @param[in] pxAdc The ADC handle returned in the open() call. * @param[in] ucAdcChannel The ADC channel to read data from. * @param[out] pusAdcSample ADC channel read sample value. * * @return * - IOT_ADC_SCUCCESS on success. * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid AdcChannel. * - IOT_ADC_CH_BUSY if ADC operation not complete. * - IOT_ADC_NOT_OPEN if ADC has been closed without re-opening. * Example Synchronous read * @code{c} * // ADC Instance to open * int32_t lAdcInstance = 0; * * // ADC Channel to read * int32_t lAdcChannel = 0; * * // Declare and ADC handle * IotAdcHandle_t xAdcHandle; * * // Return value of ADC functions * int32_t lRetVal; * * // ADC value read * uint16_t usSample; * * // Open the ADC instance and get a handle. * xAdcHandle = iot_adc_open( lAdcInstance ); * // assert(lRetVal == IOT_ADC_SUCCESS); * * // Read sample from ADC channel * lRetVal = iot_adc_read_sample( xAdcHandle, lAdcChannel, &usSample); * // assert(lRetVal == IOT_ADC_SUCCESS); * * // Close the ADC instance and get a handle. * lRetVal = iot_adc_close( xAdcHandle ); * // assert(lRetVal == IOT_ADC_SUCCESS); * @endcode * */ int32_t iot_adc_read_sample( IotAdcHandle_t const pxAdc, uint8_t ucAdcChannel, uint16_t * pusAdcSample ); /** * @brief data structures for ioctl request */ /** * @brief data structure for ioctl SetAdcConfig and GetAdcConfig */ typedef struct IotAdcConfig_s { uint32_t ulAdcSampleTime; /*!< Sample time in ADC clock cycles, apply to all channels. *!< Shortest sample time maximize conversion speed for lower impedance input *!< Extending sample time improve sample accuracy for higher impedance input. *!< Sample time is reported as the closest possible value, rounded up, the hardware can support. */ uint8_t ucAdcResolution; /*!< ADC channel resolution, reported as the closest possible value, rounded up. *!< value = resolution bits; 12 = 12bit, 13 = 13bit, etc */ } IotAdcConfig_t; /** * @brief enum for ADC channel state (idle/busy) */ typedef enum { eChStateIdle, /*!< ADC channel is idle. */ eChStateBusy, /*!< ADC channel is busy. */ } IotAdcChState_t; /** * @brief data structure for ioctl GetChStatus */ typedef struct IotAdcChStatus_s { uint8_t ucAdcChannel; /*!< ADC Channel number */ IotAdcChState_t xAdcChState; /*!< ADC Channel State */ } IotAdcChStatus_t; /** * @brief data structure for ioctl SetChBuffer * setting channel data buffer is optional using this ioctl * if client doesn't pass in data buffer for driver to use, callback is triggered * for every ADC sample to pass data back to client as driver doesn't have buffer * to accumulate data. As soon as callback returns, xConverted_Data becomes invalid. * On the other hand however if client does pass a buffer for driver to use, * callback is triggered only after driver has filled buffer with xBufLen samples, * client buffer is passed back in callback as XConverted_Data whose life span is * controlled by the client even after callback returns. */ typedef struct IotAdcChBuffer_s { uint8_t ucAdcChannel; /*!< Adc Channel number */ void * pvBuffer; /*!< Buffer to store adc results in */ uint8_t ucBufLen; /*!< Max buffer length to write into pvBuffer */ } IotAdcChBuffer_t; /** * @brief Some ADC host controller supports grouping multiple ADC channels into a chain. * When the chain is triggered to sample ADC data, all ADC channels in the group * are sampled in sequence so that client doesn't need to trigger each channel * individually. Converted ADC samples from such chain group can be passed back * to the client with a single callback. * This data structure is used for ioctl to define ADC chain setting. */ typedef struct IoTAdcChain_s { uint8_t ucAdcChannel; /*!< logical ADC channel number as input to ioctl. It is recommended *!< that client uses the first ADC channel number in the group as its *!< logical number which client can use later to trigger group sampling */ void * pvBuffer; /*!< data buffer used by driver to save converted sample data. *!< The buffer is allocated by client and passed to driver to use. */ uint8_t ucBufLen; /*!< Data buffer length, shall be large enough to hold group sample data. */ uint16_t usChainMask; /*!< Define which ADC channels are in the chain group. *!< e.g. 'x' bit set to 1 means ADC channel x is included in the group. *!< Client shall manage potential ADC channel use conflict. */ } IotAdcChain_t; /** * @brief adc ioctl request types. */ typedef enum IotAdcIoctlRequest_s { eSetAdcConfig, /*!< Set the ADC Configuration. Takes IotAdcConfig_t parameter. */ eGetAdcConfig, /*!< Get the ADC Configuration. Returns results in IotAdcConfig_t parameter. */ eGetChStatus, /*!< Get the Channel Status. Returns results in IotAdcChStatus_t parameter. */ eSetChBuffer, /*!< Set the buffer for ADC values to be stored in. Takes IotAdcChBuffer_t parameter. */ eSetAdcChain, /*!< ADC Chain for multiple ADC channels. Takes IotAdcChain_t parameter. */ } IotAdcIoctlRequest_t; /** * @brief Used for various ADC control functions. * * @param[in] pxAdc The ADC handle returned in the open() call. * @param[in] xRequest ioctl request defined by IotAdcIoctlRequest_s enums. * @param[in,out] pvBuffer data buffer for ioctl request. * * @return * - IOT_ADC_SCUCCESS on success * - IOT_ADC_INVALID_VALUE, on NULL handle or invalid request or NULL or invalid buffer pointer * - IOT_ADC_CH_BUSY if ADC operation not complete. * - IOT_ADC_NOT_OPEN if ADC has been closed without re-opening. * - IOT_ADC_FAILED if invalid ADC chain is requested. * - IOT_ADC_FUNCTION_NOT_SUPPORTED only valid for eSetAdcChain, if feature is not supported. */ int32_t iot_adc_ioctl( IotAdcHandle_t const pxAdc, IotAdcIoctlRequest_t xRequest, void * const pvBuffer ); #endif /* _IOT_ADC_H_ */