/**************************************************************************//**
 * @file     adc.h
 * @version  V1.00
 * $Revision: 3 $
 * $Date: 14/07/28 13:27p $
 * @brief    N572 Series ADC Driver Header File
 *
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
 *
 ******************************************************************************/
#ifndef __ADC_H__
#define __ADC_H__

#ifdef __cplusplus
extern "C"
{
#endif

/** @addtogroup N572_Device_Driver N572 Device Driver
  @{
*/

/** @addtogroup N572_ADC_Driver ADC Driver
  @{
*/


/** @addtogroup N572_ADC_EXPORTED_CONSTANTS ADC Exported Constants
  @{
*/  

#define ADC_CH_0_MASK                    (0x0UL)                       /*!< ADC single channel 0 mask  \hideinitializer */
#define ADC_CH_1_MASK                    (0x1UL)                       /*!< ADC single channel 1 mask  \hideinitializer */
#define ADC_CH_2_MASK                    (0x2UL)                       /*!< ADC single channel 2 mask  \hideinitializer */
#define ADC_CH_3_MASK                    (0x3UL)                       /*!< ADC single channel 3 mask  \hideinitializer */
#define ADC_CH_4_MASK                    (0x4UL)                       /*!< ADC single channel 4 mask  \hideinitializer */
#define ADC_CH_5_MASK                    (0x5UL)                       /*!< ADC single channel 5 mask  \hideinitializer */
#define ADC_CH_6_MASK                    (0x6UL)                       /*!< ADC single channel 6 mask  \hideinitializer */
#define ADC_CH_7_MASK                    (0x7UL)                       /*!< ADC single channel 7 mask  \hideinitializer */
#define ADC_CH_01_MASK                   (0x8UL)                       /*!< ADC differential channel 0,1 mask  \hideinitializer */
#define ADC_CH_23_MASK                   (0xaUL)                       /*!< ADC differential channel 2,3 mask  \hideinitializer */
#define ADC_CH_45_MASK                   (0xcUL)                       /*!< ADC differential channel 4,5 mask  \hideinitializer */
#define ADC_NONECH_MASK                  (0xeUL)                       /*!< ADC none channel mask  \hideinitializer */
#define ADC_SCANEND_MASK                 (0xfUL)                       /*!< ADC scan sequence end mask  \hideinitializer */

#define ADC_CMP_LESS_THAN                (0x0UL << ADC_CMP_CMPCOND_Pos)   /*!< ADC compare condition less than  \hideinitializer */
#define ADC_CMP_GREATER_OR_EQUAL_TO      (ADC_CMP_CMPCOND_Msk)            /*!< ADC compare condition greater or equal to  \hideinitializer */

#define ADC_LOW_LEVEL_TRIGGER            (0x0UL << ADC_CTL_HWTRGCOND_Pos)   /*!< External pin low level trigger ADC  \hideinitializer */
#define ADC_HIGH_LEVEL_TRIGGER           (0x1UL << ADC_CTL_HWTRGCOND_Pos)   /*!< External pin high level trigger ADC  \hideinitializer */
#define ADC_FALLING_EDGE_TRIGGER         (0x2UL << ADC_CTL_HWTRGCOND_Pos)   /*!< External pin falling edge trigger ADC  \hideinitializer */
#define ADC_RISING_EDGE_TRIGGER          (0x3UL << ADC_CTL_HWTRGCOND_Pos)   /*!< External pin rising edge trigger ADC  \hideinitializer */

#define ADC_ADF_INT                      (ADC_STATUS_ADIF_Msk)           /*!< ADC convert complete interrupt \hideinitializer */
#define ADC_CMP0_INT                     (ADC_STATUS_ADCMPF0_Msk)        /*!< ADC comparator 0 interrupt  \hideinitializer */
#define ADC_CMP1_INT                     (ADC_STATUS_ADCMPF1_Msk)        /*!< ADC comparator 1 interrupt  \hideinitializer */

#define ADC_OPERATION_MODE_SINGLE        (0x0UL << ADC_CTL_OPMODE_Pos)      /*!< ADC operation mode set to single conversion  \hideinitializer */
#define ADC_OPERATION_MODE_SINGLE_CYCLE  (0x2UL << ADC_CTL_OPMODE_Pos)      /*!< ADC operation mode set to single cycle scan  \hideinitializer */
#define ADC_OPERATION_MODE_CONTINUOUS    (0x3UL << ADC_CTL_OPMODE_Pos)      /*!< ADC operation mode set to continuous scan  \hideinitializer */

#define ADC_OUT_FORMAT_UNSIGNED    (0x0UL << ADC_CTL_ADCFM_Pos)      /*!< ADC differential mode output format with unsigned  \hideinitializer */
#define ADC_OUT_FORMAT_2COMPLEMENT (ADC_CTL_ADCFM_Msk)               /*!< ADC differential mode output format with 2's complement  \hideinitializer */

#define ADC_CTRS_R10K				(0x0UL << ADC_MIBSCTL_CTRS_Pos)					/*!< AVDD/2 accelerating R~10K  \hideinitializer */
#define ADC_CTRS_R40K				(0x1UL << ADC_MIBSCTL_CTRS_Pos)					/*!< AVDD/2 accelerating R~40K  \hideinitializer */
#define ADC_CTRS_R200K			(0x2UL << ADC_MIBSCTL_CTRS_Pos)					/*!< AVDD/2 accelerating R~200K  \hideinitializer */
#define ADC_CTRS_R600K			(0x3UL << ADC_MIBSCTL_CTRS_Pos)					/*!< AVDD/2 accelerating R~600K  \hideinitializer */

#define ADC_FWU_R8K				(0x0)					/*!< Fast wake up for RC, 8k  \hideinitializer */
#define ADC_FWU_R40K			(0x1)					/*!< Fast wake up for RC, 40k  \hideinitializer */
#define ADC_FWU_R200K			(0x2)					/*!< Fast wake up for RC, 200k  \hideinitializer */
#define ADC_FWU_R400K			(0x3)					/*!< Fast wake up for RC, 400k  \hideinitializer */

/*@}*/ /* end of group N572_ADC_EXPORTED_CONSTANTS */


/** @addtogroup N572_ADC_EXPORTED_FUNCTIONS ADC Exported Functions
  @{
*/
/**
  * @brief     Get the latest ADC conversion data
  * @param[in] adc Base address of ADC module
  * @param[in] u32ChNum Channel number
  * @return    Latest ADC conversion data
  * \hideinitializer
  */
#define ADC_GET_CONVERSION_DATA(adc, u32ChNum) (adc->DAT[u32ChNum])

/**
  * @brief     Return the user-specified interrupt flags
  * @param[in] adc Base address of ADC module
  * @param[in] u32Mask The combination of following interrupt status bits. Each bit corresponds to a interrupt status.
  *            - \ref ADC_ADF_INT
  *            - \ref ADC_CMP0_INT
  *            - \ref ADC_CMP1_INT
  * @return    User specified interrupt flags
  * \hideinitializer
  */
#define ADC_GET_INT_FLAG(adc, u32Mask) (adc->STATUS & (u32Mask))

/**
  * @brief     This macro clear the selected interrupt status bits
  * @param[in] adc Base address of ADC module
  * @param[in] u32Mask The combination of following interrupt status bits. Each bit corresponds to a interrupt status.
  *            - \ref ADC_ADF_INT
  *            - \ref ADC_CMP0_INT
  *            - \ref ADC_CMP1_INT
  * @return    None
  * \hideinitializer
  */
#define ADC_CLR_INT_FLAG(adc, u32Mask) (adc->STATUS = (ADC->STATUS & ~(ADC_ADF_INT | \
                                                                       ADC_CMP0_INT | \
                                                                       ADC_CMP1_INT)) | (u32Mask))

/**
  * @brief     Get the busy state of ADC
  * @param[in] adc Base address of ADC module
  * @return    busy state of ADC
  * @retval    0 ADC is not busy
  * @retval    1 ADC is busy
  * \hideinitializer
  */
#define ADC_IS_BUSY(adc) (adc->STATUS & ADC_STATUS_BUSY_Msk ? 1 : 0)

/**
  * @brief     Check if the ADC conversion data is over written or not
  * @param[in] adc Base address of ADC module
  * @param[in] u8ScanSeq desire scan sequence
  * @return    Over run state of ADC data
  * @retval    0 ADC data is not overwritten
  * @retval    1 ADC data is overwritten
  * \hideinitializer
  */
#define ADC_IS_DATA_OVERRUN(adc, u8ScanSeq) ((adc->DAT[u8ScanSeq] & ADC_DAT_OV_Msk) ? 1 : 0)

/**
  * @brief     Check if the ADC conversion data is valid or not
  * @param[in] adc Base address of ADC module
  * @param[in] u8ScanSeq desire scan sequence
  * @return    Valid state of ADC data
  * @retval    0 ADC data is not valid
  * @retval    1 ADC data is valid
  * \hideinitializer
  */
#define ADC_IS_DATA_VALID(adc, u8ScanSeq) ((adc->DAT[u8ScanSeq] & ADC_DAT_VALID_Msk) ? 1 : 0)

/**
  * @brief     Power down ADC module
  * @param[in] adc Base address of ADC module
  * @return    None
  * \hideinitializer
  */
#define ADC_POWER_DOWN(adc) (adc->CTL &= ~ADC_CTL_ADCEN_Msk)

/**
  * @brief     Power on ADC module
  * @param[in] adc Base address of ADC module
  * @return    None
  * \hideinitializer
  */
#define ADC_POWER_ON(adc) (adc->CTL |= ADC_CTL_ADCEN_Msk)

/**
  * @brief     Configure the comparator 0 and enable it
  * @param[in] adc Base address of ADC module
  * @param[in] u32ChNum  Specifies the source channel, valid value are from 0 to 7
  * @param[in] u32Condition Specifies the compare condition
  *            - \ref ADC_CMP_LESS_THAN
  *            - \ref ADC_CMP_GREATER_OR_EQUAL_TO
  * @param[in] u32Data Specifies the compare value. Valid value are between 0 ~ 0x3FF
  * @param[in] u32MatchCount Specifies the match count setting, valid values are between 1~16
  * @return    None
  * @details   For example, ADC_ENABLE_CMP0(ADC, 5, ADC_CMP_GREATER_OR_EQUAL_TO, 0x800, 10);
  *            Means ADC will assert comparator 0 flag if channel 5 conversion result is
  *            greater or equal to 0x800 for 10 times continuously.
  * \hideinitializer
  */
#define ADC_ENABLE_CMP0(adc, \
                        u32ChNum, \
                        u32Condition, \
                        u32Data, \
                        u32MatchCount) (adc->CMP[0] = ((u32ChNum) << ADC_CMP_CMPCH_Pos) | \
                                                                   (u32Condition) | \
                                                                   ((u32Data) << ADC_CMP_CMPDAT_Pos) | \
                                                                   (((u32MatchCount) - 1) << ADC_CMP_CMPMCNT_Pos) |\
                                                                   ADC_CMP_ADCMPEN_Msk)

/**
  * @brief     Disable comparator 0
  * @param[in] adc Base address of ADC module
  * \hideinitializer
  */
#define ADC_DISABLE_CMP0(adc) (adc->CMP[0] = 0)			

/**
  * @brief     Configure the comparator 1 and enable it
  * @param[in] adc Base address of ADC module
  * @param[in] u32ChNum  Specifies the source channel, valid value are from 0 to 7
  * @param[in] u32Condition Specifies the compare condition
  *            - \ref ADC_CMP_LESS_THAN
  *            - \ref ADC_CMP_GREATER_OR_EQUAL_TO
  * @param[in] u32Data Specifies the compare value. Valid value are between 0 ~ 0x3FF
  * @param[in] u32MatchCount Specifies the match count setting, valid values are between 1~16
  * @return    None
  * @details   For example, ADC_ENABLE_CMP1(ADC, 5, ADC_CMP_GREATER_OR_EQUAL_TO, 0x800, 10);
  *            Means ADC will assert comparator 1 flag if channel 5 conversion result is
  *            greater or equal to 0x800 for 10 times continuously.
  * \hideinitializer
  */
#define ADC_ENABLE_CMP1(adc, \
                        u32ChNum, \
                        u32Condition, \
                        u32Data, \
                        u32MatchCount) (adc->CMP[1] = ((u32ChNum) << ADC_CMP_CMPCH_Pos) | \
                                                                   (u32Condition) | \
                                                                   ((u32Data) << ADC_CMP_CMPDAT_Pos) | \
                                                                   ((u32MatchCount - 1) << ADC_CMP_CMPMCNT_Pos) |\
                                                                   ADC_CMP_ADCMPEN_Msk)

/**
  * @brief     Disable comparator 1
  * @param[in] adc Base address of ADC module
  * \hideinitializer
  */
#define ADC_DISABLE_CMP1(adc) (adc->CMP[1] = 0)

/**
  * @brief     Set ADC sacn sequence. Enabled sequence will be converted while ADC starts.
  * @param[in] adc Base address of ADC module
  * @param[in] u8Seq0,u8Seq1,u8Seq2,u8Seq3,u8Seq4,u8Seq5,u8Seq6,u8Seq7 Specifies sequence scan which channel.
  *            - \ref ADC_CH_0_MASK
  *            - \ref ADC_CH_1_MASK
  *            - \ref ADC_CH_2_MASK
  *            - \ref ADC_CH_3_MASK
  *            - \ref ADC_CH_4_MASK
  *            - \ref ADC_CH_5_MASK
  *            - \ref ADC_CH_6_MASK
  *            - \ref ADC_CH_7_MASK
  *            - \ref ADC_CH_01_MASK
  *            - \ref ADC_CH_23_MASK
  *            - \ref ADC_CH_45_MASK
  *            - \ref ADC_NONECH_MASK
  *            - \ref ADC_SCANEND_MASK
  * @return    None
  * \hideinitializer
  */
#define ADC_SET_SCAN_SEQUENCE(adc, \
							  u8Seq0, \
							  u8Seq1, \
							  u8Seq2, \
							  u8Seq3, \
							  u8Seq4, \
							  u8Seq5, \
							  u8Seq6, \
							  u8Seq7)	(adc->CHSEQ = (u8Seq0 << ADC_CHSEQ_CHSEQ0_Pos| \
													   u8Seq1 << ADC_CHSEQ_CHSEQ1_Pos| \
													   u8Seq2 << ADC_CHSEQ_CHSEQ2_Pos| \
													   u8Seq3 << ADC_CHSEQ_CHSEQ3_Pos| \
													   u8Seq4 << ADC_CHSEQ_CHSEQ4_Pos| \
													   u8Seq5 << ADC_CHSEQ_CHSEQ5_Pos| \
													   u8Seq6 << ADC_CHSEQ_CHSEQ6_Pos| \
													   u8Seq7 << ADC_CHSEQ_CHSEQ7_Pos))

/**
  * @brief     Start the A/D conversion.
  * @param[in] adc Base address of ADC module
  * @return    None
  * \hideinitializer
  */
#define ADC_START_CONV(adc) (adc->CTL |= ADC_CTL_SWTRG_Msk)

/**
  * @brief     Stop the A/D conversion.
  * @param[in] adc Base address of ADC module
  * @return    None
  * \hideinitializer
  */
#define ADC_STOP_CONV(adc) (adc->CTL &= ~ADC_CTL_SWTRG_Msk)

/**
  * @brief     Set the output format in differential input mode.
  * @param[in] adc Base address of ADC module
  * @param[in] u32Format Differential input mode output format. Valid values are:
  *            - \ref ADC_OUT_FORMAT_UNSIGNED
  *            - \ref ADC_OUT_FORMAT_2COMPLEMENT
  * @return    None
  * \hideinitializer
  */
#define ADC_SET_OUTFORMAT(adc, u32Format) (adc->CTL = (adc->CTL & ~ADC_CTL_ADCFM_Msk) | u32Format)

/**
  * @brief     Set A/D converter operation mode.
  * @param[in] adc Base address of ADC module
  * @param[in] u8Mode operation mode
  *            - \ref ADC_OPERATION_MODE_SINGLE
  *            - \ref ADC_OPERATION_MODE_SINGLE_CYCLE
  *            - \ref ADC_OPERATION_MODE_CONTINUOUS
  * @return    None
  * \hideinitializer
  */
#define ADC_SET_OPERATION(adc, u8Mode)	(adc->CTL = (adc->CTL & ~ADC_CTL_OPMODE_Msk) | u8Mode)

/**
  * @brief     Set Pre-amp OP offset bias compensation voltage.
  * @param[in] adc Base address of ADC module
  * @param[in] u16Offset . Pre-amp OP offset bias compensation voltage.
  * @return    None
  * \hideinitializer
  */
#define ADC_SET_BIASCOMPENSATION(adc, \
								 u16Offset)		((adc->PGCTL = (adc->PGCTL&~ADC_PGCTL_OS_Msk) | ((uint32_t)u16Offset) << ADC_PGCTL_OS_Pos))

/**
  * @brief     Mute on control of first stage pre-amp for offset bias calibration.
  * @param[in] adc Base address of ADC module
  * @return    None
  * \hideinitializer
  */
#define ADC_MUTEON_PGA(adc)		(adc->PGCTL |= ADC_PGCTL_OPMUTE_Msk)

/**
  * @brief     Mute off control of first stage pre-amp.
  * @param[in] adc Base address of ADC module
  * @return    None
  * \hideinitializer
  */
#define ADC_MUTEOFF_PGA(adc)		(adc->PGCTL &= ~ADC_PGCTL_OPMUTE_Msk)

/**
  * @brief     Enable triggering of A/D conversion by external STADC pin.
  * @param[in] adc Base address of ADC module
  * @param[in] u8TrgCond decide external pin STADC trigger event is level or edge
  *            - \ref ADC_LOW_LEVEL_TRIGGER
  *            - \ref ADC_HIGH_LEVEL_TRIGGER
  *            - \ref ADC_FALLING_EDGE_TRIGGER
  *            - \ref ADC_RISING_EDGE_TRIGGER
  * @return    None
  * \hideinitializer
  */
#define ADC_ENABLE_EXTRG(adc, u8TrgCond)		(adc->CTL = (adc->CTL&~ADC_CTL_HWTRGCOND_Msk) | u8TrgCond |ADC_CTL_HWTRGEN_Msk)

/**
  * @brief     Disable triggering of A/D conversion by external STADC pin.
  * @param[in] adc Base address of ADC module
  * @return    None
  * \hideinitializer
  */
#define ADC_DISABLE_EXTRG(adc)		(adc->CTL &= ~ADC_CTL_HWTRGEN_Msk)

void ADC_Open(ADC_T *adc);
void ADC_Close(ADC_T *adc);
void ADC_EnableInt(ADC_T *adc, uint32_t u32Mask);
void ADC_DisableInt(ADC_T *adc, uint32_t u32Mask);
void ADC_EnableRegulator(ADC_T *adc);
void ADC_DisableRegulator(ADC_T *adc);
void ADC_SetRegulatorRC(ADC_T *adc, uint32_t u32ACC_R, uint32_t u32WAKE_R);
void ADC_GetRegulatorRC(ADC_T *adc,	uint32_t *p32ACC_R, uint32_t 	*pu32WAKE_R);
int32_t ADC_SetPGAGain1dB(ADC_T *adc, int32_t i32PGAGain1IndB);
int32_t ADC_SetPGAGain2dB(ADC_T *adc, int32_t i32PGAGain2IndB);
int32_t ADC_GetPGAGain1dB(ADC_T *adc);
int32_t ADC_GetPGAGain2dB(ADC_T *adc);
void ADC_AnalysisCalibration(ADC_T *adc);

/*@}*/ /* end of group N572_ADC_EXPORTED_FUNCTIONS */

/*@}*/ /* end of group N572_ADC_Driver */

/*@}*/ /* end of group N572_Device_Driver */

#ifdef __cplusplus
}
#endif

#endif //__ADC_H__

/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
