/***********************************************************************************************************************
 * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates.  All Rights Reserved.
 *
 * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products
 * of Renesas Electronics Corp. and its affiliates ("Renesas").  No other uses are authorized.  Renesas products are
 * sold pursuant to Renesas terms and conditions of sale.  Purchasers are solely responsible for the selection and use
 * of Renesas products and Renesas assumes no liability.  No license, express or implied, to any intellectual property
 * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas
 * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION
 * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT
 * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR
 * DOCUMENTATION.  RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH.  TO THE MAXIMUM
 * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION
 * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING,
 * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS,
 * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS.
 **********************************************************************************************************************/

#ifndef R_ADC_API_H
#define R_ADC_API_H

/*******************************************************************************************************************//**
 * @ingroup RENESAS_INTERFACES
 * @defgroup ADC_API ADC Interface
 * @brief Interface for A/D Converters.
 *
 * @section ADC_API_SUMMARY Summary
 * The ADC interface provides standard ADC functionality including one-shot mode (single scan), continuous scan and
 * group scan. It also allows configuration of hardware and software triggers for starting scans. After each conversion
 * an interrupt can be triggered, and if a callback function is provided, the call back is invoked with the
 * appropriate event information.
 *
 * Implemented by:
 * @ref ADC
 *
 * @{
 **********************************************************************************************************************/

/***********************************************************************************************************************
 * Includes
 **********************************************************************************************************************/

/* Includes board and MCU related header files. */
#include "bsp_api.h"
#include "r_elc_api.h"
#include "r_transfer_api.h"

/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */
FSP_HEADER

/**********************************************************************************************************************
 * Macro definitions
 **********************************************************************************************************************/

/*****************************************************************************
 * Typedef definitions
 ******************************************************************************/

/** ADC operation mode definitions  */
typedef enum e_adc_mode
{
    ADC_MODE_SINGLE_SCAN     = 0,      ///< Single scan - one or more channels
    ADC_MODE_GROUP_SCAN      = 1,      ///< Two trigger sources to trigger scan for two groups which contain one or more channels
    ADC_MODE_CONTINUOUS_SCAN = 2,      ///< Continuous scan - one or more channels
} adc_mode_t;

/** ADC data resolution definitions */
typedef enum e_adc_resolution
{
    ADC_RESOLUTION_12_BIT = 0,         ///< 12 bit resolution
    ADC_RESOLUTION_10_BIT = 1,         ///< 10 bit resolution
    ADC_RESOLUTION_8_BIT  = 2,         ///< 8 bit resolution
    ADC_RESOLUTION_14_BIT = 3,         ///< 14 bit resolution
    ADC_RESOLUTION_16_BIT = 4,         ///< 16 bit resolution
    ADC_RESOLUTION_24_BIT = 5,         ///< 24 bit resolution
} adc_resolution_t;

/** ADC data alignment definitions  */
typedef enum e_adc_alignment
{
    ADC_ALIGNMENT_RIGHT = 0,           ///< Data alignment right
    ADC_ALIGNMENT_LEFT  = 1            ///< Data alignment left
} adc_alignment_t;

/** ADC trigger mode definitions */
typedef enum e_adc_trigger
{
    ADC_TRIGGER_SOFTWARE       = 0,    ///< Software trigger; not for group modes
    ADC_TRIGGER_SYNC_ELC       = 2,    ///< Synchronous trigger via ELC
    ADC_TRIGGER_ASYNC_EXTERNAL = 3,    ///< External asynchronous trigger; not for group modes
} adc_trigger_t;

/** ADC callback event definitions  */
typedef enum e_adc_event
{
    ADC_EVENT_SCAN_COMPLETE,           ///< Normal/Group A scan complete
    ADC_EVENT_SCAN_COMPLETE_GROUP_B,   ///< Group B scan complete
    ADC_EVENT_CALIBRATION_COMPLETE,    ///< Calibration complete
    ADC_EVENT_CONVERSION_COMPLETE,     ///< Conversion complete
} adc_event_t;

/** ADC channels */
typedef enum e_adc_channel
{
    ADC_CHANNEL_0           = 0,       ///< ADC channel 0
    ADC_CHANNEL_1           = 1,       ///< ADC channel 1
    ADC_CHANNEL_2           = 2,       ///< ADC channel 2
    ADC_CHANNEL_3           = 3,       ///< ADC channel 3
    ADC_CHANNEL_4           = 4,       ///< ADC channel 4
    ADC_CHANNEL_5           = 5,       ///< ADC channel 5
    ADC_CHANNEL_6           = 6,       ///< ADC channel 6
    ADC_CHANNEL_7           = 7,       ///< ADC channel 7
    ADC_CHANNEL_8           = 8,       ///< ADC channel 8
    ADC_CHANNEL_9           = 9,       ///< ADC channel 9
    ADC_CHANNEL_10          = 10,      ///< ADC channel 10
    ADC_CHANNEL_11          = 11,      ///< ADC channel 11
    ADC_CHANNEL_12          = 12,      ///< ADC channel 12
    ADC_CHANNEL_13          = 13,      ///< ADC channel 13
    ADC_CHANNEL_14          = 14,      ///< ADC channel 14
    ADC_CHANNEL_15          = 15,      ///< ADC channel 15
    ADC_CHANNEL_16          = 16,      ///< ADC channel 16
    ADC_CHANNEL_17          = 17,      ///< ADC channel 17
    ADC_CHANNEL_18          = 18,      ///< ADC channel 18
    ADC_CHANNEL_19          = 19,      ///< ADC channel 19
    ADC_CHANNEL_20          = 20,      ///< ADC channel 20
    ADC_CHANNEL_21          = 21,      ///< ADC channel 21
    ADC_CHANNEL_22          = 22,      ///< ADC channel 22
    ADC_CHANNEL_23          = 23,      ///< ADC channel 23
    ADC_CHANNEL_24          = 24,      ///< ADC channel 24
    ADC_CHANNEL_25          = 25,      ///< ADC channel 25
    ADC_CHANNEL_26          = 26,      ///< ADC channel 26
    ADC_CHANNEL_27          = 27,      ///< ADC channel 27
    ADC_CHANNEL_DUPLEX_A    = 50,      ///< Data duplexing register A
    ADC_CHANNEL_DUPLEX_B    = 51,      ///< Data duplexing register B
    ADC_CHANNEL_DUPLEX      = -4,      ///< Data duplexing register
    ADC_CHANNEL_TEMPERATURE = -3,      ///< Temperature sensor output
    ADC_CHANNEL_VOLT        = -2,      ///< Internal reference voltage
} adc_channel_t;

/** ADC states. */
typedef enum e_adc_state
{
    ADC_STATE_IDLE             = 0,    ///< ADC is idle
    ADC_STATE_SCAN_IN_PROGRESS = 1,    ///< ADC scan in progress
} adc_state_t;

/** ADC status. */
typedef struct st_adc_status
{
    adc_state_t state;                 ///< Current state
} adc_status_t;

/** ADC callback arguments definitions  */
typedef struct st_adc_callback_args
{
    uint16_t      unit;                ///< ADC device in use
    adc_event_t   event;               ///< ADC callback event
    void const  * p_context;           ///< Placeholder for user data
    adc_channel_t channel;             ///< Channel of conversion result.  Only valid for ADC_EVENT_CONVERSION_COMPLETE
} adc_callback_args_t;

/** ADC Information Structure for Transfer Interface */
typedef struct st_adc_info
{
    __I uint16_t   * p_address;           ///< The address to start reading the data from
    uint32_t         length;              ///< The total number of transfers to read
    transfer_size_t  transfer_size;       ///< The size of each transfer
    elc_peripheral_t elc_peripheral;      ///< Name of the peripheral in the ELC list
    elc_event_t      elc_event;           ///< Name of the ELC event for the peripheral
    uint32_t         calibration_data;    ///< Temperature sensor calibration data (0xFFFFFFFF if unsupported) for reference voltage
    int16_t          slope_microvolts;    ///< Temperature sensor slope in microvolts/degrees C
    bool             calibration_ongoing; ///< Calibration is in progress.
} adc_info_t;

/** ADC general configuration  */
typedef struct st_adc_cfg
{
    uint16_t         unit;                             ///< ADC unit to be used
    adc_mode_t       mode;                             ///< ADC operation mode
    adc_resolution_t resolution;                       ///< ADC resolution
    adc_alignment_t  alignment;                        ///< Specify left or right alignment; ignored if addition used
    adc_trigger_t    trigger;                          ///< Default and Group A trigger source
    IRQn_Type        scan_end_irq;                     ///< Scan end IRQ number
    IRQn_Type        scan_end_b_irq;                   ///< Scan end group B IRQ number
    uint8_t          scan_end_ipl;                     ///< Scan end interrupt priority
    uint8_t          scan_end_b_ipl;                   ///< Scan end group B interrupt priority
    void (* p_callback)(adc_callback_args_t * p_args); ///< Callback function; set to NULL for none
    void const * p_context;                            ///< Placeholder for user data. Passed to the user callback in @ref adc_callback_args_t.
    void const * p_extend;                             ///< Extension parameter for hardware specific settings
} adc_cfg_t;

/** ADC control block. Allocate using driver instance control structure from driver instance header file. */
typedef void adc_ctrl_t;

/** ADC functions implemented at the HAL layer will follow this API. */
typedef struct st_adc_api
{
    /** Initialize ADC Unit;  apply power, set the operational mode, trigger sources, interrupt priority,
     * and configurations common to all channels and sensors.
     * @par Implemented as
     * - @ref R_ADC_Open()
     * - @ref R_SDADC_Open()
     *
     * @pre Configure peripheral clocks, ADC pins and IRQs prior to calling this function.
     * @param[in]  p_ctrl  Pointer to control handle structure
     * @param[in]  p_cfg   Pointer to configuration structure
     */
    fsp_err_t (* open)(adc_ctrl_t * const p_ctrl, adc_cfg_t const * const p_cfg);

    /** Configure the scan including the channels, groups, and scan triggers to be used for the unit that
     * was initialized in the open call.  Some configurations are not supported for all implementations.
     * See implementation for details.
     * @par Implemented as
     * - @ref R_ADC_ScanCfg()
     * - @ref R_SDADC_ScanCfg()
     *
     * @param[in]  p_ctrl     Pointer to control handle structure
     * @param[in]  p_extend   See implementation for details
     */
    fsp_err_t (* scanCfg)(adc_ctrl_t * const p_ctrl, void const * const p_extend);

    /** Start the scan (in case of a software trigger), or enable the hardware trigger.
     * @par Implemented as
     * - @ref R_ADC_ScanStart()
     * - @ref R_SDADC_ScanStart()
     *
     * @param[in]  p_ctrl   Pointer to control handle structure
     */
    fsp_err_t (* scanStart)(adc_ctrl_t * const p_ctrl);

    /** Stop the ADC scan (in case of a software trigger), or disable the hardware trigger.
     * @par Implemented as
     * - @ref R_ADC_ScanStop()
     * - @ref R_SDADC_ScanStop()
     *
     * @param[in]  p_ctrl   Pointer to control handle structure
     */
    fsp_err_t (* scanStop)(adc_ctrl_t * const p_ctrl);

    /** Check scan status.
     * @par Implemented as
     * - @ref R_ADC_StatusGet()
     * - @ref R_SDADC_StatusGet()
     *
     * @param[in]  p_ctrl   Pointer to control handle structure
     * @param[out] p_status Pointer to store current status in
     */
    fsp_err_t (* scanStatusGet)(adc_ctrl_t * const p_ctrl, adc_status_t * p_status);

    /** Read ADC conversion result.
     * @par Implemented as
     * - @ref R_ADC_Read()
     * - @ref R_SDADC_Read()
     *
     * @param[in]  p_ctrl   Pointer to control handle structure
     * @param[in]  reg_id   ADC channel to read (see enumeration adc_channel_t)
     * @param[in]  p_data   Pointer to variable to load value into.
     */
    fsp_err_t (* read)(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, uint16_t * const p_data);

    /** Read ADC conversion result into a 32-bit word.
     * @par Implemented as
     * - @ref R_SDADC_Read32()
     *
     * @param[in]  p_ctrl   Pointer to control handle structure
     * @param[in]  reg_id   ADC channel to read (see enumeration adc_channel_t)
     * @param[in]  p_data   Pointer to variable to load value into.
     */
    fsp_err_t (* read32)(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, uint32_t * const p_data);

    /** Calibrate ADC or associated PGA (programmable gain amplifier).  The driver may require implementation specific
     * arguments to the p_extend input. Not supported for all implementations. See implementation for details.
     * @par Implemented as
     * - @ref R_SDADC_Calibrate()
     *
     * @param[in]  p_ctrl    Pointer to control handle structure
     * @param[in]  p_extend  Pointer to implementation specific arguments
     */
    fsp_err_t (* calibrate)(adc_ctrl_t * const p_ctrl, void * const p_extend);

    /** Set offset for input PGA configured for differential input. Not supported for all implementations.
     *  See implementation for details.
     * @par Implemented as
     * - @ref R_SDADC_OffsetSet()
     *
     * @param[in]  p_ctrl    Pointer to control handle structure
     * @param[in]  reg_id    ADC channel to read (see enumeration adc_channel_t)
     * @param[in]  offset    See implementation for details.
     */
    fsp_err_t (* offsetSet)(adc_ctrl_t * const p_ctrl, adc_channel_t const reg_id, int32_t const offset);

    /**
     * Specify callback function and optional context pointer and working memory pointer.
     * @par Implemented as
     * - @ref R_ADC_CallbackSet()
     *
     * @param[in]   p_ctrl                   Pointer to the ADC control block.
     * @param[in]   p_callback               Callback function
     * @param[in]   p_context                Pointer to send to callback function
     * @param[in]   p_working_memory         Pointer to volatile memory where callback structure can be allocated.
     *                                       Callback arguments allocated here are only valid during the callback.
     */
    fsp_err_t (* callbackSet)(adc_ctrl_t * const p_api_ctrl, void (* p_callback)(adc_callback_args_t *),
                              void const * const p_context, adc_callback_args_t * const p_callback_memory);

    /** Close the specified ADC unit by ending any scan in progress, disabling interrupts, and removing power to the
     * specified A/D unit.
     * @par Implemented as
     * - @ref R_ADC_Close()
     * - @ref R_SDADC_Close()
     *
     * @param[in]  p_ctrl   Pointer to control handle structure
     */
    fsp_err_t (* close)(adc_ctrl_t * const p_ctrl);

    /** Return the ADC data register address of the first (lowest number) channel and the total number of bytes
     * to be read in order for the DTC/DMAC to read the conversion results of all configured channels.
     * Return the temperature sensor calibration and slope data.
     * @par Implemented as
     * - @ref R_ADC_InfoGet()
     * - @ref R_SDADC_InfoGet()
     *
     * @param[in]   p_ctrl       Pointer to control handle structure
     * @param[out]  p_adc_info   Pointer to ADC information structure
     */
    fsp_err_t (* infoGet)(adc_ctrl_t * const p_ctrl, adc_info_t * const p_adc_info);
} adc_api_t;

/** This structure encompasses everything that is needed to use an instance of this interface. */
typedef struct st_adc_instance
{
    adc_ctrl_t      * p_ctrl;          ///< Pointer to the control structure for this instance
    adc_cfg_t const * p_cfg;           ///< Pointer to the configuration structure for this instance
    void const      * p_channel_cfg;   ///< Pointer to the channel configuration structure for this instance
    adc_api_t const * p_api;           ///< Pointer to the API structure for this instance
} adc_instance_t;

/*******************************************************************************************************************//**
 * @} (end defgroup ADC_API)
 **********************************************************************************************************************/

/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */
FSP_FOOTER

#endif
