/**
  ******************************************************************************
 * @file    hal_dac.h
 * @brief   Header file of DAC Module library.
 *
 * @version V1.0
 * @date    15 Dec 2017
 * @author  AE Team
 * @note
 *
 * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
 *
 ******************************************************************************
 */

#ifndef __HAL_DAC_H
#define __HAL_DAC_H

#ifdef __cplusplus
 extern "C" {
#endif

#include "utils.h"
#include "hal_dma.h"
#include "hal_pis.h"

/** @addtogroup ES32FXXX_HAL
  * @{
  */

/** @addtogroup DAC
  * @{
  */

/** @defgroup DAC_Pubulic_Types DAC Pubulic Types
  * @{
  */
/**
  * @brief Dac channel
  */
typedef enum {
	DAC_CHANNEL_0 = 0, /**< Dac channel 0 */
	DAC_CHANNEL_1 = 1  /**< Dac channel 1 */
} dac_channel_t;

/**
  * @brief Dac convert mode
  */
typedef enum {
	DAC_CONV_MODE_CONTINUOUS = 0, /**< Dac set in continuous mode */
	DAC_CONV_MODE_SAMPLEHOLD = 1, /**< Dac set in sample/hold mode */
	DAC_CONV_MODE_SAMPLEOFF = 2   /**< Dac set in sample/shut off mode */
} dac_conv_mode_t;

/**
  * @brief Dac out mode
  */
typedef enum {
	DAC_OUTPUT_DISABLE = 0, /**< Dac output disable */
	DAC_OUTPUT_PIN = 1,     /**< Dac output to pin enable */
	DAC_OUTPUT_ADC = 2,     /**< Dac output to adc and acmp enable */
	DAC_OUTPUT_PIN_ADC = 3  /**< Dac output to pin,adc and acmp enable */
} dac_out_mode_t;

/**
  * @brief Dac prs input channel
  */
typedef enum {
	DAC_PRSSEL_CH_0 = 0,   /**< Prs channel 0 triggers dac channel conversion */
	DAC_PRSSEL_CH_1 = 1,   /**< Prs channel 1 triggers dac channel conversion */
	DAC_PRSSEL_CH_2 = 2,   /**< Prs channel 2 triggers dac channel conversion */
	DAC_PRSSEL_CH_3 = 3,   /**< Prs channel 3 triggers dac channel conversion */
	DAC_PRSSEL_CH_4 = 4,   /**< Prs channel 4 triggers dac channel conversion */
	DAC_PRSSEL_CH_5 = 5,   /**< Prs channel 5 triggers dac channel conversion */
	DAC_PRSSEL_CH_6 = 6,   /**< Prs channel 6 triggers dac channel conversion */
	DAC_PRSSEL_CH_7 = 7,   /**< Prs channel 7 triggers dac channel conversion */
	DAC_PRSSEL_CH_8 = 8,   /**< Prs channel 8 triggers dac channel conversion */
	DAC_PRSSEL_CH_9 = 9,   /**< Prs channel 9 triggers dac channel conversion */
	DAC_PRSSEL_CH_10 = 10, /**< Prs channel 10 triggers dac channel conversion */
	DAC_PRSSEL_CH_11 = 11  /**< Prs channel 11 triggers dac channel conversion */
} dac_prssel_t;

/**
  * @brief Dac reference selection
  */
typedef enum {
	DAC_REFSEL_1V25 = 0, /**< Internal 1.25V reference */
	DAC_REFSEL_2V5 = 1,  /**< Internal 2.5V reference */
	DAC_REF_VDD = 2      /**< Vdd reference */
} dac_ref_t;

/**
  * @brief Refresh interval select
  */
typedef enum {
	DAC_REFRESH_8 = 0,  /**< Channel refreshed every 8 cycles */
	DAC_REFRESH_16 = 1, /**< Channel refreshed every 16 cycles */
	DAC_REFRESH_32 = 2, /**< Channel refreshed every 32 cycles */
	DAC_REFRESH_64 = 3  /**< Channel refreshed every 64 cycles */
} dac_refresh_t;

/**
  * @brief Dac prescale
  */
typedef enum {
	DAC_PRESCALE_0 = 0, /**< No division */
	DAC_PRESCALE_1 = 1, /**< 2 clock division */
	DAC_PRESCALE_2 = 2, /**< 4 clock division */
	DAC_PRESCALE_3 = 3, /**< 8 clock division */
	DAC_PRESCALE_4 = 4, /**< 16 clock division */
	DAC_PRESCALE_5 = 5, /**< 32 clock division */
	DAC_PRESCALE_6 = 6, /**< 64 clock division */
	DAC_PRESCALE_7 = 7, /**< 128 clock division */
} dac_prescale_t;

/**
  * @brief Dac funciton
  */
typedef enum {
	DAC_FUNCTION_DISABLE = 0, /**< Dac function set disable */
	DAC_FUNCITON_ENABLE = 1   /**< Dac function set enable */
} dac_function_t;

/**
  * @brief Dac output trigger select
  */
typedef enum {
	DAC_TRIGGER_BY_DATA = 0, /**< Channel is triggered by CHxDATA or COMBDATA write */
	DAC_TRIGGER_BY_PRS = 1   /**< Channel is triggered by PRS input */
} dac_trigger_t;

/**
  * @brief Dac interrupt type
  */
typedef enum {
	DAC_IT_CH0 = (1U << 0),    /**< Channel 0 conversion complete interrupt */
	DAC_IT_CH1 = (1U << 1),    /**< Channel 1 conversion complete interrupt */
	DAC_IT_CH0_UF = (1U << 4), /**< Channel 0 data underflow interrupt */
	DAC_IT_CH1_UF = (1U << 5), /**< Channel 1 data underflow interrupt */
} dac_it_t;

/**
  * @brief Dac state flag
  */
typedef enum {
	DAC_CH0_DATA_CONV = (1U << 0), /**< Ch0data is weitten flag */
	DAC_CH1_DATA_CONV = (1U << 1)  /**< Ch1data is weitten flag */
} dac_flag_t;

/**
  * @brief Dac init structure definition
  */
typedef struct {
	dac_conv_mode_t convert_mode; /**< Conversion mode */
	dac_out_mode_t out_mode;      /**< Select output mode */
	dac_ref_t reference;          /**< Reference selection */
	dac_refresh_t refresh;        /**< Refresh interval select */
	dac_prescale_t prescale;      /**< Prescaler setting */
	dac_function_t ch0reset_prs;  /**< Select if prescaler is reset on channel 0 start */
	dac_function_t outenable_prs; /**< Enable prs control of dac output enable */
	dac_function_t sine_enable;   /**< Sine mode enable/disable */
	dac_function_t diff;          /**< Differential mode enable/disable */
	dac_function_t self_calen;    /**< Self calculate enable/disable */
} dac_init_t;

/**
  * @brief Dac channel initialize structure definition
  */
typedef struct {
	dac_function_t enable;         /**< Dac channel output enable/disable */
	dac_trigger_t trigger;         /**< Select channel conversion trigger */
	dac_function_t refresh_enable; /**< Set automatic refresh of channel function */
	dac_prssel_t prs_sel;          /**< Select channel prs input channel */
} dac_channel_config_t;

/**
  * @brief  Dac handle Structure definition
  */
typedef struct dac_handle_s {
	DAC_TypeDef *perh; /**< Register base address */
	dac_init_t init;   /**< Dac initialize parameters */
	lock_state_t lock; /**< Locking object */

	void (*ch0_cplt_cbk)(struct dac_handle_s *arg);      /**< Channel 0 completed callback */
	void (*ch1_cplt_cbk)(struct dac_handle_s *arg);      /**< Channel 1 completed callback */
	void (*ch0_underflow_cbk)(struct dac_handle_s *arg); /**< Channel 0 data underflow callback */
	void (*ch1_underflow_cbk)(struct dac_handle_s *arg); /**< Channel 0 data underflow callback */
} dac_handle_t;
/**
  * @}
  */

/** @defgroup DAC_Public_Macros DAC Public Macros
  * @{
  */
#define DAC_CH0_ENABLE()	(DAC0->CH0CTRL.EN = 1)
#define DAC_CH1_ENABLE()	(DAC0->CH1CTRL.EN = 1)

#define DAC_CH0_DISABLE()	(DAC0->CH0CTRL.EN = 0)
#define DAC_CH1_DISABLE()	(DAC0->CH1CTRL.EN = 0)
/**
  * @}
  */

/** @defgroup DAC_Private_Macros DAC Private Macros
  * @{
  */
#define IS_DAC_TYPE(x)			((x) == DAC0)
#define IS_DAC_CONVERT_TYPE(x)		(((x) == DAC_CONV_MODE_CONTINUOUS) || \
					 ((x) == DAC_CONV_MODE_SAMPLEHOLD) || \
					 ((x) == DAC_CONV_MODE_SAMPLEOFF))
#define IS_DAC_OUTPUT_TYPE(x)		(((x) == DAC_OUTPUT_DISABLE) || \
					 ((x) == DAC_OUTPUT_PIN)     || \
					 ((x) == DAC_OUTPUT_ADC)     || \
					 ((x) == DAC_OUTPUT_PIN_ADC))
#define IS_DAC_REFERENCE_TYPE(x)	(((x) == DAC_REFSEL_1V25) || \
					 ((x) == DAC_REFSEL_2V5)  || \
					 ((x) == DAC_REF_VDD))
#define IS_DAC_REFRESH_TYPE(x)		(((x) == DAC_REFRESH_8)  || \
					 ((x) == DAC_REFRESH_16) || \
					 ((x) == DAC_REFRESH_32) || \
					 ((x) == DAC_REFRESH_64))
#define IS_DAC_FUNCTION_TYPE(x)		(((x) == DAC_FUNCTION_DISABLE) || \
					 ((x) == DAC_FUNCITON_ENABLE))
#define IS_DAC_CHANNEL_TYPE(x)		(((x) == DAC_CHANNEL_0) || \
					 ((x) == DAC_CHANNEL_1))
#define IS_DAC_PRESCALE_TYPE(x)		(((x) == DAC_PRESCALE_0) || \
					 ((x) == DAC_PRESCALE_1) || \
					 ((x) == DAC_PRESCALE_2) || \
					 ((x) == DAC_PRESCALE_3) || \
					 ((x) == DAC_PRESCALE_4) || \
					 ((x) == DAC_PRESCALE_5) || \
					 ((x) == DAC_PRESCALE_6) || \
					 ((x) == DAC_PRESCALE_7))
#define IS_DAC_INTERRUPT_TYPE(x)	(((x) == DAC_IT_CH0)    || \
					 ((x) == DAC_IT_CH1)    || \
					 ((x) == DAC_IT_CH0_UF) || \
					 ((x) == DAC_IT_CH1_UF))
#define IS_DAC_PRSSEL_CH_TYPE(x)	(((x) == DAC_PRSSEL_CH_0)  || \
					 ((x) == DAC_PRSSEL_CH_1)  || \
					 ((x) == DAC_PRSSEL_CH_2)  || \
					 ((x) == DAC_PRSSEL_CH_3)  || \
					 ((x) == DAC_PRSSEL_CH_4)  || \
					 ((x) == DAC_PRSSEL_CH_5)  || \
					 ((x) == DAC_PRSSEL_CH_6)  || \
					 ((x) == DAC_PRSSEL_CH_7)  || \
					 ((x) == DAC_PRSSEL_CH_8)  || \
					 ((x) == DAC_PRSSEL_CH_9)  || \
					 ((x) == DAC_PRSSEL_CH_10) || \
					 ((x) == DAC_PRSSEL_CH_11))
#define IS_DAC_FLAG_TYPE(x)		(((x) == DAC_CH0_DATA_CONV) || \
					 ((x) == DAC_CH1_DATA_CONV))
#define IS_DAC_TRIGGER_TYPE(x)		(((x) == DAC_TRIGGER_BY_DATA) || \
					 ((x) == DAC_TRIGGER_BY_PRS))
/**
  * @}
  */

/** @addtogroup DAC_Public_Functions
  * @{
  */
hal_status_t dac_reset(dac_handle_t *hperh);
hal_status_t dac_init(dac_handle_t *hperh);
hal_status_t dac_channel_config(dac_handle_t *hperh, dac_channel_config_t *config, dac_channel_t ch);
hal_status_t dac_ch_output_set(dac_handle_t *hperh, dac_channel_t ch, uint32_t value);
flag_status_t dac_get_status(dac_handle_t *hperh, dac_flag_t dac_flag);
hal_status_t dac_interrupt_config(dac_handle_t *hperh, dac_it_t it, type_func_t state);
it_status_t dac_get_it_status(dac_handle_t *hperh, dac_it_t interrupt);
hal_status_t dac_clear_it_status(dac_handle_t *hperh, dac_it_t interrupt);
void dac_irq_handler(dac_handle_t *hperh);
/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */
#ifdef __cplusplus
 extern "C" }
#endif

#endif /* __HAL_DAC_H */
