/**
 *******************************************************************************
 * @file    dpm32m0xx_posif.h
 *
 * @brief   Header file for POSIF firmware driver.
 *
 * @author  DPM
 *
 * @version V1.0.0
 *
 * @date    2023-11-01
 *
 *******************************************************************************/

#ifndef __DPM32M0XX_POSIF_H__
#define __DPM32M0XX_POSIF_H__

#ifdef __cplusplus
extern "C"
{
#endif

#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif

#include "dpm32m0xx.h"


#if defined (DPM32M08x) || defined (DPM32M05x) || defined (DPM32M03x)

/**
 ******************************************************************************
 * @brief POSI filter length enumeration.
 *****************************************************************************/
typedef enum
{
  POSIF_FLT_LEN1                 = 0x00UL,   /*!< Set the input filter length as 1.  */
  POSIF_FLT_LEN8,                            /*!< Set the input filter length as 8.  */
  POSIF_FLT_LEN16,                           /*!< Set the input filter length as 16. */
  POSIF_FLT_LEN32                            /*!< Set the input filter length as 32. */
} POSIF_FilterLenEnum;


/**
 ******************************************************************************
 * @brief POSIF filter clock sample select enumeration.
 *****************************************************************************/
typedef enum
{
  POSIF_FLT_SAMPLE1              = 0x00UL,   /*!< Set the filter clock divider sample as 1.  */
  POSIF_FLT_SAMPLE4,                         /*!< Set the filter clock divider sample as 4.  */
  POSIF_FLT_SAMPLE16,                        /*!< Set the filter clock divider sample as 16. */
  POSIF_FLT_SAMPLE32                         /*!< Set the filter clock divider sample as 32. */
} POSIF_FilterSampleEnum;


/**
 ******************************************************************************
 * @brief POSIF analog compare source select enumeration.
 *****************************************************************************/
typedef enum
{
  POSIF_ACMP_ACMP0               = 0x00UL,   /*!< Select the analog comparator source as ACMP0. */
  POSIF_ACMP_ACMP1,                          /*!< Select the analog comparator source as ACMP1. */
  POSIF_ACMP_ACMP2,                          /*!< Select the analog comparator source as ACMP2. */
  POSIF_ACMP_ACMP3                           /*!< Select the analog comparator source as ACMP3. */
} POSIF_AnalogCompareSourceEnum;


/**
 ******************************************************************************
 * @brief POSIF input source select enumeration.
 *****************************************************************************/
typedef enum
{
  POSIF_SRC_PIN                  = 0x00UL,   /*!< Select signal input as pin input.               */
  POSIF_SRC_ACMP                             /*!< Select signal input as analog comparator input. */
} POSIF_InputSourceEnum;


/**
******************************************************************************
* @brief POSIF clock division value enumeration.
*****************************************************************************/
typedef enum
{
  POSIF_CLK_DIV1                 = 0x00UL,   /*!< Set the clock source of POSIFCLK as PCLK.     */
  POSIF_CLK_DIV2,                            /*!< Set the clock source of POSIFCLK as PCLK/2.   */
  POSIF_CLK_DIV4,                            /*!< Set the clock source of POSIFCLK as PCLK/4.   */
  POSIF_CLK_DIV8,                            /*!< Set the clock source of POSIFCLK as PCLK/8.   */
  POSIF_CLK_DIV16,                           /*!< Set the clock source of POSIFCLK as PCLK/16.  */
  POSIF_CLK_DIV32,                           /*!< Set the clock source of POSIFCLK as PCLK/32.  */
  POSIF_CLK_DIV64,                           /*!< Set the clock source of POSIFCLK as PCLK/64.  */
  POSIF_CLK_DIV128                           /*!< Set the clock source of POSIFCLK as PCLK/128. */
} POSIF_ClockDivEnum;


/**
 ******************************************************************************
 * @brief POSIF mode select enumeration.
 *****************************************************************************/
typedef enum
{
  POSIF_MODE_HALL                = 0x00UL,   /*!< Set POSIF to hall mode.    */
  POSIF_MODE_ENC                             /*!< Set POSIF to encoder mode. */
} POSIF_ModeEnum;


/**
 ******************************************************************************
 * @brief ENC ZIN reset action select enumeration.
 *****************************************************************************/
typedef enum
{
  ENC_ZIN_ACTION_SINGLE          = 0x00UL,   /*!< Set to reset position counter only once. */
  ENC_ZIN_ACTION_MULTIPLE                    /*!< Set to reset ENC_CUR_POS multiple times. */
} ENC_ZinActionEnum;


/**
 ******************************************************************************
 * @brief ENC ZIN enable enumeration.
 *****************************************************************************/
typedef enum
{
  ENC_ZIN_EN_DISABLE             = 0x00UL,   /*!< Set to not reset counter ENC_CUR_POS.    */
  ENC_ZIN_EN_ENABLE                          /*!< Set to enable reset counter ENC_CUR_POS. */
} ENC_ZinEnEnum;


/**
 ******************************************************************************
 * @brief ENC Pulse control enable enumeration.
 *****************************************************************************/
typedef enum
{
  ENC_PULSE_CNT_EN_DISABLE       = 0x00UL,  /*!< set to disable the pulse counter. */
  ENC_PULSE_CNT_EN_ENABLE                   /*!< Set to enable the pulse counter.  */
} ENC_PulseCntrEnEnum;


/**
 ******************************************************************************
 * @brief ENC encoder mode select enumeration.
 *****************************************************************************/
typedef enum
{
  ENC_MODE_ENCODER_IN0           = 0x00UL,  /*!< Set to quadrature encoder counts only on IN0 edges.       */
  ENC_MODE_ENCODER_IN1           = 0x01UL,  /*!< Set to quadrature encoder counts only on IN1 edges.       */
  ENC_MODE_ENCODER_IN01          = 0x02UL,  /*!< Set to quadrature encoder edge count on both IN0 and IN1. */
  ENC_MODE_DIRECTION_IN0         = 0x04UL,  /*!< Set to direction counting mode, IN0 is direction control. */
  ENC_MODE_DIRECTION_IN1         = 0x05UL   /*!< Set to direction counting mode, IN1 is direction control. */
} ENC_ModeEnum;


/**
******************************************************************************
* @brief ENC interrupt enable enumeration.
*****************************************************************************/
typedef enum
{
  ENC_INT_TYPE_PULSE_CNT_OF     = POSIF_ENC_CR_PULSE_CNT_OF_IE_Msk,  /*!< Pulse control overflow interrupt. */
  ENC_INT_TYPE_MAX_POS           = POSIF_ENC_CR_MAX_POS_IE_Msk         /*!< Max position interrupt.           */
} ENC_IntTypeEnum;


/**
 ******************************************************************************
 * @brief ENC interrupt flag enumeration.
 *****************************************************************************/
typedef enum
{
  ENC_INT_FLAG_PULSE_CNT_OF     = POSIF_ENC_SR_PULSE_CNT_OF_IF_Msk,  /*!< Pulse control overflow interrupt flag. */
  ENC_INT_FLAG_MAX_POS           = POSIF_ENC_SR_MAX_POS_IF_Msk         /*!< Max position interrupt flag.           */
} ENC_IntFlagEnum;


/**
 ******************************************************************************
 * @brief ENC Encoder direction enumeration.
 *****************************************************************************/
typedef enum
{
  ENC_DIR_REV                    = 0x00UL,   /*!< Encoder direction reversal. */
  ENC_DIR_FWD                                /*!< Encoder direction forward.  */
} ENC_DirEnum;


/**
******************************************************************************
* @brief HALL interrupt enable enumeration.
*****************************************************************************/
typedef enum
{
  HALL_INT_TYPE_MAX_WIDTH        = POSIF_HALL_CR_MAX_WIDTH_IE_Msk,  /*!< Max width interrupt enable.     */
  HALL_INT_TYPE_DELAY            = POSIF_HALL_CR_UPDATE_IE_Msk      /*!< Update status interrupt enable. */
} HALL_IntTypeEnum;


/**
 ******************************************************************************
 * @brief HALL interrupt flag enumeration.
 *****************************************************************************/
typedef enum
{
  HALL_INT_FLAG_MAX_WIDTH        = POSIF_HALL_SR_MAX_WIDTH_IF_Msk,  /*!< Max width interrupt flag.     */
  HALL_INT_FLAG_DELAY            = POSIF_HALL_SR_UPDATE_IF_Msk      /*!< Update status interrupt flag. */
} HALL_IntFlagEnum;



/**
 ******************************************************************************
 * @brief POSIF initialization structure definition.
 *****************************************************************************/
typedef struct
{
  uint32_t POSIF_In0FilterLen;              /*!< Specify input 0 filter length.
                                                 This parameter can be a value of @ref POSIF_FilterLenEnum.           */
  uint32_t POSIF_In1FilterLen;              /*!< Specify input 1 filter length.
                                                 This parameter can be a value of @ref POSIF_FilterLenEnum.           */
  uint32_t POSIF_In2FilterLen;              /*!< Specify input 2 filter length.
                                                 This parameter can be a value of @ref POSIF_FilterLenEnum.           */
  uint32_t POSIF_In0ClockSample;            /*!< Specify input 0 filtering clock division coefficient.
                                                 This parameter can be a value of @ref POSIF_FilterSampleEnum.        */
  uint32_t POSIF_In1ClockSample;            /*!< Specify input 1 filtering clock division coefficient.
                                                 This parameter can be a value of @ref POSIF_FilterSampleEnum.        */
  uint32_t POSIF_In2ClockSample;            /*!< Specify input 2 filtering clock division coefficient.
                                                 This parameter can be a value of @ref POSIF_FilterSampleEnum.        */
  uint32_t POSIF_In0AnalogCompareSource;    /*!< Specify input 0 to select the analog comparator source.
                                                 This parameter can be a value of @ref POSIF_AnalogCompareSourceEnum. */
  uint32_t POSIF_In1AnalogCompareSource;    /*!< Specify input 1 to select the analog comparator source.
                                                 This parameter can be a value of @ref POSIF_AnalogCompareSourceEnum. */
  uint32_t POSIF_In2AnalogCompareSource;    /*!< Specify input 2 to select the analog comparator source.
                                                 This parameter can be a value of @ref POSIF_AnalogCompareSourceEnum. */
  uint32_t POSIF_In0InputSource;            /*!< Specify input 0 to select signal input.
                                                 This parameter can be a value of @ref POSIF_InputSourceEnum.         */
  uint32_t POSIF_In1InputSource;            /*!< Specify input 1 to select signal input.
                                                 This parameter can be a value of @ref POSIF_InputSourceEnum.         */
  uint32_t POSIF_In2InputSource;            /*!< Specify input 2 to select signal input.
                                                 This parameter can be a value of @ref POSIF_InputSourceEnum.         */
  uint32_t POSIF_ClockDiv;                  /*!< Specify clock division coefficient.
                                                 This parameter can be a value of @ref POSIF_ClockDivEnum.            */
  uint32_t POSIF_Mode;                      /*!< Specify POSIF mode.
                                                 This parameter can be a value of @ref POSIF_ModeEnum.                */
  uint32_t ENC_ZinAction;                   /*!< Specify ZIN reset action.
                                                 This parameter can be a value of @ref ENC_ZinActionEnum.             */
  uint32_t ENC_ZinEn;                       /*!< ZIN enable.
                                                 This parameter can be a value of @ref ENC_ZinEnEnum.                 */
  uint32_t ENC_PulseCntrEn;                 /*!< Pulse control enable.
                                                 This parameter can be a value of @ref ENC_PulseCntrEnEnum.           */
  uint32_t ENC_Mode;                        /*!< Specify encoder mode.
                                                 This parameter can be a value of @ref ENC_ModeEnum.                  */
  uint16_t ENC_LoadValue;                   /*!< Specifies the value to autoload.
                                                 This parameter can be a number between 0x0000 and 0xFFFF.            */
  uint32_t HALL_MaxWidth;                   /*!< Specify the maximum value between two adjacent edges.
                                                 This parameter can be a number between 0x000000 and 0xFFFFFF.        */
} POSIF_InitTypeStruct;



/* POSIF param check. */

#define IS_POSIF_FLT_LEN(x)      (((x) == POSIF_FLT_LEN1) ||  \
                                  ((x) == POSIF_FLT_LEN8) ||  \
                                  ((x) == POSIF_FLT_LEN16) || \
                                  ((x) == POSIF_FLT_LEN32))

#define IS_POSIF_CLOCK_DIV(x)    (((x) == POSIF_CLK_DIV1) ||  \
                                  ((x) == POSIF_CLK_DIV2) ||  \
                                  ((x) == POSIF_CLK_DIV4) || \
                                  ((x) == POSIF_CLK_DIV8) ||  \
                                  ((x) == POSIF_CLK_DIV16) || \
                                  ((x) == POSIF_CLK_DIV32) ||  \
                                  ((x) == POSIF_CLK_DIV64) || \
                                  ((x) == POSIF_CLK_DIV128))

#define IS_POSIF_ACMP(x)         (((x) == POSIF_ACMP_ACMP0) || \
                                  ((x) == POSIF_ACMP_ACMP1) || \
                                  ((x) == POSIF_ACMP_ACMP2) || \
                                  ((x) == POSIF_ACMP_ACMP3))

#define IS_POSIF_FLT_SAMPLE(x)   (((x) == POSIF_FLT_SAMPLE1) ||  \
                                  ((x) == POSIF_FLT_SAMPLE4) ||  \
                                  ((x) == POSIF_FLT_SAMPLE16) || \
                                  ((x) == POSIF_FLT_SAMPLE32))

#define IS_POSIF_SRC(x)          (((x) == POSIF_SRC_PIN) || \
                                  ((x) == POSIF_SRC_ACMP))

#define IS_POSIF_MODE(x)         (((x) == POSIF_MODE_HALL) || \
                                  ((x) == POSIF_MODE_ENC))


/* ENC param check. */

#define IS_ENC_ZIN_ACTION(x)     (((x) == ENC_ZIN_ACTION_SINGLE) || \
                                  ((x) == ENC_ZIN_ACTION_MULTIPLE))

#define IS_ENC_ZIN_EN(x)         (((x) == ENC_ZIN_EN_DISABLE) || \
                                  ((x) == ENC_ZIN_EN_ENABLE))


#define IS_ENC_PULSE_CNT_EN(x)  (((x) == ENC_PULSE_CNT_EN_DISABLE) || \
                                 ((x) == ENC_PULSE_CNT_EN_ENABLE))

#define IS_ENC_LOAD_VAL(x)       (((x) <= 0xFFFF))


/* HALL param check. */

#define IS_HALL_MAX_WIDTH_VAL(x) (((x) <= 0xFFFFFF))



/* POSIF initialization and Configuration functions. */
void                    POSIF_DeInit(void);
void                    POSIF_Init(POSIF_InitTypeStruct *POSIF_InitType);
void                    POSIF_StructInit(POSIF_InitTypeStruct *POSIF_InitType);
void                    POSIF_Cmd(FunctionalState state);

/* ENC get register value functions. */
void                    POSIF_ENC_SetMaxPosition(uint16_t val);
uint16_t                POSIF_ENC_GetPosition(void);
void                    POSIF_ENC_SetPosition(uint16_t val);
uint32_t                POSIF_ENC_GetPulse(void);
void                    POSIF_ENC_SetPulse(uint32_t val);
ENC_DirEnum             POSIF_ENC_GetDirection(void);

/* ENC interrupts and flags management functions. */
void                    POSIF_ENC_IntCmd(ENC_IntTypeEnum ENC_IntType, FunctionalState state);
FunctionalState         POSIF_ENC_GetIntCmdStatus(ENC_IntTypeEnum ENC_IntType);
FlagState               POSIF_ENC_GetIntFlagStatus(ENC_IntFlagEnum ENC_IntFlag);
void                    POSIF_ENC_ClearIntFlag(ENC_IntFlagEnum ENC_IntFlag);

/* HALL get register value functions. */
uint32_t                POSIF_HALL_GetWidth(void);
uint8_t                 POSIF_HALL_GetUnfiltered(void);
uint8_t                 POSIF_HALL_GetFiltered(void);
void                    POSIF_HALL_SetDelay(uint16_t val);
void                    POSIF_HALL_SetMaxWidth(uint32_t val);

/* HALL interrupts and flags management functions. */
void                    POSIF_HALL_IntCmd(HALL_IntTypeEnum HALL_IntType, FunctionalState state);
FunctionalState         POSIF_HALL_GetIntCmdStatus(HALL_IntTypeEnum HALL_IntType);
FlagState               POSIF_HALL_GetIntFlagStatus(HALL_IntFlagEnum HALL_IntFlag);
void                    POSIF_HALL_ClearIntFlag(HALL_IntFlagEnum HALL_IntFlag);

#endif /* DPM32M08x || DPM32M05x || DPM32M03x */

#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang diagnostic pop
#endif

#ifdef __cplusplus
}

#endif

#endif /* __DPM32M0XX_POSIF_H__ */
