/**
  *********************************************************************************
  *
  * @file    hal_opamp.h
  * @brief   Header file of OPAMP module driver.
  *
  * @version V1.0
  * @date    16 Dec 2017
  * @author  AE Team
  * @note
  *
  * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
  *
  *********************************************************************************
  */

#ifndef __HAL_OPAMP_H__
#define __HAL_OPAMP_H__

#ifdef __cplusplus
 extern "C" {
#endif

#include "utils.h"

/** @addtogroup ES32FXXX_HAL
  * @{
  */

/** @addtogroup OPAMP
  * @{
  */

/** @defgroup OPAMP_Public_Types OPAMP Public Types
  * @{
  */

/**
  * @brief Opa index
  */
typedef enum {
	OPAMP_INDEX_0 = 0, /**< Select opa0 */
	OPAMP_INDEX_1 = 1, /**< Select opa1 */
	OPAMP_INDEX_2 = 2  /**< Select opa2 */
} opamp_index_t;

/**
  * @brief Non-inverting input
  */
typedef enum {
	OPAMP_DISABLE_POS_INPUT = 0, /**< Disable input */
	OPAMP_DAC_POS_INPUT = 1,     /**< Dac as input */
	OPAMP_POS_PAD_POS_INPUT = 2, /**< Pos pad as input */
	OPAMP_OPAXINP_POS_INPUT = 3, /**< Opa x as input */
	OPAMP_OPATAP_POS_INPUT  = 4  /**< Opa x resistor ladder as input */
} opamp_possel_t;

/**
  * @brief Inverting input
  */
typedef enum {
	OPAMP_DISABLE_NEG_INPUT = 0, /**< Disable input */
	OPAMP_UG_NEG_INPUT = 1,      /**< Gain feedback path */
	OPAMP_OPATAP_NEG_INPUT = 2,  /**< Opa x resistor ladder as input */
	OPAMP_NEG_PAD_NEG_INPUT = 3  /**< Neg pad as input */
} opamp_negsel_t;

/**
  * @brief Resistor ladder input
  */
typedef enum {
	OPAMP_DISABLE = 0, /**< Set for unity gain */
	OPAMP_OPAXINP = 1, /**< Set for opa x input */
	OPAMP_NEG_PAD = 2, /**< Neg pad connect */
	OPAMP_POS_PAD = 3, /**< Pos pad connect */
	OPAMP_VSS = 4      /**< Vss connect */
} opamp_res_in_t;

/**
  * @brief Resistor ladder select
  */
typedef enum {
	OPAMP_RES0 = 0, /**< R2 = 1/3 * R1,inverting gain is -1/3,non-inverting gain is 4/3 */
	OPAMP_RES1 = 1, /**< R2 = R1,inverting gain is -1,non-inverting gain is 2 */
	OPAMP_RES2 = 2, /**< R2 = 5/3 * R1,inverting gain is -5/3,non-inverting gain is 8/3 */
	OPAMP_RES3 = 3, /**< R2 = 2 * R1,inverting gain is -11/5,non-inverting gain is 16/5 */
	OPAMP_RES4 = 4, /**< R2 = 3 * R1,inverting gain is -3,non-inverting gain is 4 */
	OPAMP_RES5 = 5, /**< R2 = 13/3 * R1,inverting gain is -13/3,non-inverting gain is 16/3 */
	OPAMP_RES6 = 6, /**< R2 = 7 * R1,inverting gain is -7/3,non-inverting gain is 8 */
	OPAMP_RES7 = 7  /**< R2 = 15 * R1,inverting gain is -15,non-inverting gain is 16 */
} opamp_ressel_t;

/**
  * @brief Select output channel
  */
typedef enum {
	OPAMP_OUTPUT_DISABLE = 0, /**< Opa 1/2/3 output is disable */
	OPAMP_MAIN_OUTPUT = 1,    /**< Main opa 1/2/3 output to pin enabled */
	OPAMP_ALT_OUTPUT = 2,     /**< Opa 1/2 altemative output enable */
	OPAMP_ALL_OUTPUT = 3      /**< Main opa 1/2 output drives both main and altemative outputs */
} opamp_out_mode_t;

/**
  * @brief Opamp next function
  */
typedef enum {
	OPAMP_NEXTOUT_DISABLE = 0, /**< Disable next output */
	OPAMP_NEXTOUT_ENABLE = 1   /**< Makes output of OPA0/OPA1 available to OPA1/OPA2 */
} opamp_next_out_t;

/**
  * @brief Output enable value
  */
typedef enum {
	OPAMP_ALTEMATE_OUTPUT_O = (1U << 0), /**< Enable altemate output 0 */
	OPAMP_ALTEMATE_OUTPUT_1 = (1U << 1), /**< Enable altemate output 1 */
	OPAMP_ALTEMATE_OUTPUT_2 = (1U << 2), /**< Enable altemate output 2 */
	OPAMP_ALTEMATE_OUTPUT_3 = (1U << 3), /**< Enable altemate output 3 */
	OPAMP_ALTEMATE_OUTPUT_4 = (1U << 4)  /**< Enable altemate output 4 */
} opamp_out_en_t;

/**
  * @brief Opamp output config structure definition
  */
typedef struct {
	opamp_out_mode_t out_mode;   /**< Select output channel */
	opamp_next_out_t next_en;    /**< Opamp next enable/disable */
	opamp_out_en_t altemate_out; /**< Output enable value */
} opamp_output_config_t;

/**
  * @brief Opamp init structure definition
  */
typedef struct {
	opamp_possel_t pos_input; /**< Non-inverting input */
	opamp_negsel_t neg_input; /**< Inverting input */
	opamp_res_in_t res_input; /**< Resistor ladder input choose */
	opamp_ressel_t ressel;    /**< Resistor ladder select */
} opamp_init_t;

/**
  * @brief  OPAMP Handle Structure definition
  */
typedef struct opamp_handle_s {
	OPAMP_TypeDef *perh; /**< Register base address */
	opamp_init_t init;   /**< Opamp required parameters */
	lock_state_t lock;   /**< Locking object */
} opamp_handle_t;
/**
  * @}
  */

/** @defgroup OPAMP_Public_Macros OPAMP Public Macros
  * @{
  */
#define OPAMP0_ENABLE()		(OPAMP->OPACTRL.OPA0EN = 1)
#define OPAMP0_DISABLE()	(OPAMP->OPACTRL.OPA0EN = 0)

#define OPAMP1_ENABLE()		(OPAMP->OPACTRL.OPA1EN = 1)
#define OPAMP1_DISABLE()	(OPAMP->OPACTRL.OPA1EN = 0)

#define OPAMP2_ENABLE()		(OPAMP->OPACTRL.OPA2EN = 1)
#define OPAMP2_DISABLE()	(OPAMP->OPACTRL.OPA2EN = 0)
/**
  * @}
  */

/** @defgroup OPAMP_Private_Macros   OPAMP Private Macros
  * @{
  */
#define IS_OPAMP_TYPE(x)		((x) == OPAMP)
#define IS_OPAMP_INDEX_TYPE(x)		(((x) == OPAMP_INDEX_0) || \
					 ((x) == OPAMP_INDEX_1) || \
					 ((x) == OPAMP_INDEX_2))
#define IS_OPAMP_POSSEL_TYPE(x)		(((x) == OPAMP_DISABLE_POS_INPUT) || \
					 ((x) == OPAMP_DAC_POS_INPUT)     || \
					 ((x) == OPAMP_POS_PAD_POS_INPUT) || \
					 ((x) == OPAMP_OPAXINP_POS_INPUT) || \
					 ((x) == OPAMP_OPATAP_POS_INPUT))
#define IS_OPAMP_NEGSEL_TYPE(x)		(((x) == OPAMP_DISABLE_NEG_INPUT) || \
					 ((x) == OPAMP_UG_NEG_INPUT)      || \
					 ((x) == OPAMP_OPATAP_NEG_INPUT)  || \
					 ((x) == OPAMP_NEG_PAD_NEG_INPUT))
#define IS_OPAMP_RES_IN_TYPE(x) 	(((x) == OPAMP_DISABLE) || \
					 ((x) == OPAMP_OPAXINP) || \
					 ((x) == OPAMP_NEG_PAD) || \
					 ((x) == OPAMP_POS_PAD) || \
					 ((x) == OPAMP_VSS))
#define IS_OPAMP_RESSEL_TYPE(x)		(((x) == OPAMP_RES0) || \
					 ((x) == OPAMP_RES1) || \
					 ((x) == OPAMP_RES2) || \
					 ((x) == OPAMP_RES3) || \
					 ((x) == OPAMP_RES4) || \
					 ((x) == OPAMP_RES5) || \
					 ((x) == OPAMP_RES6) || \
					 ((x) == OPAMP_RES7))
#define IS_OPAMP_OUT_MODE_TYPE(x) 	(((x) == OPAMP_OUTPUT_DISABLE) || \
					 ((x) == OPAMP_MAIN_OUTPUT)    || \
					 ((x) == OPAMP_ALT_OUTPUT)     || \
					 ((x) == OPAMP_ALL_OUTPUT))
#define IS_OPAMP_NEXT_OUT_TYPE(x)	(((x) == OPAMP_NEXTOUT_DISABLE) || \
					 ((x) == OPAMP_NEXTOUT_ENABLE))
/**
  * @}
  */

/** @addtogroup OPAMP_Public_Functions
  * @{
  */
hal_status_t opamp_init(opamp_handle_t *hperh, opamp_index_t index);
hal_status_t opamp_output_config(opamp_handle_t *hperh, opamp_output_config_t *config, opamp_index_t index);
/**
  * @}
  */

/**
  * @}
  */

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

#endif
