/**
 *******************************************************************************
 * @file    dpm32m0xx_posif.c
 *
 * @brief   This file provides firmware functions to manage the following
 *          functions of the Hall and Encoder Interface Controller Peripheral
 *          Interface (POSIF):
 *           + Encoder/Hall initialization and Configuration
 *           + Encoder/Hall register parameter reading
 *           + Encoder/Hall interrupts and flags management
 *
 * @author  DPM
 *
 * @version V1.0.0
 *
 * @date    2023-11-01
 *
 * @verbatim
 ===============================================================================
                       ##### How to use this driver #####
 ===============================================================================
    [..]
      (#) Enable peripheral clock using the following functions
          RCC_APBPeriphClockCmd(RCC_APB_PERIPH_POSIF, ENABLE).

      (#) According to the POSIF mode, enable the GPIO clocks using
          RCC_AHBPeriphClockCmd(RCC_AHB_PERIPH_GPIO, ENABLE) function.

      (#) Peripheral's alternate function:
        (+) Connect the pin to the desired peripherals' Alternate
            Function (AF) using GPIO_AltFuncConfig() function.
        (+) Configure the desired pin in alternate function by:
            GPIO_InitStruct->GPIO_Mode = GPIO_MODE_ALT_FUNC.
        (+) Select the type, pull-up/pull-down and output speed via
            GPIO_PuPd, GPIO_OType and GPIO_Speed members.
        (+) Call GPIO_Init() function.

      (#) Program the filter, source, clock division, mode, Z action, Z enable,
          pulse control enable, encoder mode, encoder load value and hall max
          width using the POSIF_Init() function.

      (#) Enable the POSIF using the POSIF_Cmd() function.

    *** Encoder configuration ***
    ============================================
    [..]
      (#) Management position infornation using POSIF_ENC_SetMaxPosition(),
          POSIF_ENC_GetPosition() and POSIF_ENC_SetPosition();

      (#) Management pulse information using POSIF_ENC_GetPulse() and
          POSIF_ENC_SetPulse();

      (#) Get encoder direction using the POSIF_ENC_GetDirection().

      (#) POSIF encoder interrupt configuration:
        (+) To activate the POSIF encoder interrupt, using POSIF_ENC_IntCmd()
            function.
        (+) Check on POSIF encoder interrupt enable flags using
            POSIF_ENC_GetIntCmdStatus() function.
        (+) Check on POSIF encoder interrupt occur flags using
            POSIF_ENC_GetIntFlagStatus() function.
        (+) Clear POSIF encoder interrupt flags using POSIF_ENC_ClearIntFlag()
            function.

    *** Hall configuration ***
    ============================================
    [..]
      (#) Get hall information using POSIF_HALL_GetWidth(),
          POSIF_HALL_GetUnfiltered() and POSIF_HALL_GetFiltered();

      (#) Set hall parama using POSIF_HALL_SetDelay() and
          POSIF_HALL_SetMaxWidth();

      (#) POSIF hall interrupt configuration:
        (+) To activate the POSIF hall interrupt, using POSIF_HALL_IntCmd()
            function.
        (+) Check on POSIF hall interrupt enable flags using
            POSIF_HALL_GetIntCmdStatus() function.
        (+) Check on POSIF hall interrupt occur flags using
            POSIF_HALL_GetIntFlagStatus() function.
        (+) Clear POSIF hall interrupt flags using POSIF_HALL_ClearIntFlag()
            function.

 * @endverbatim
 *******************************************************************************/

#include "dpm32m0xx_posif.h"

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

/**
 *******************************************************************************
 * @brief  De-initialize the POSIF peripheral registers to their default reset values.
 * @retval None.
 ******************************************************************************/
void POSIF_DeInit(void)
{
  /* Reset POSIF_CR register. */
  POSIF->CR = (uint32_t)0x00000000;
  /* Reset ENC_CR register. */
  POSIF->ENC_CR = (uint32_t)0x00000000;
  /* Reset ENC_SR register. */
  POSIF->ENC_SR = (uint32_t)(POSIF_ENC_SR_PULSE_CNT_OF_IF_Msk | POSIF_ENC_SR_MAX_POS_IF_Msk);
  /* Reset ENC_MAX_POS register. */
  POSIF->ENC_MAX_POS = (uint32_t)0x00000000;
  /* Reset ENC_CUR_POS register. */
  POSIF->ENC_CUR_POS = (uint32_t)0x00000000;
  /* Reset ENC_PULSE_CNT register. */
  POSIF->ENC_PULSE_CNT = (uint32_t)0x00000000;
  /* Reset HALL_CR register. */
  POSIF->HALL_CR = (uint32_t)0x00000000;
  /* Reset HALL_SR register. */
  POSIF->HALL_SR = (uint32_t)(POSIF_HALL_SR_UPDATE_IF_Msk | POSIF_HALL_SR_MAX_WIDTH_IF_Msk);
  /* Reset HALL_MAX_WIDTH register. */
  POSIF->HALL_MAX_WIDTH = (uint32_t)0x00000000;
}

/**
 *******************************************************************************
 * @brief  Initializes the POSIF peripheral according to the specified parameters
 *         in the POSIF_InitType.
 * @param  [in]  POSIF_InitType: Structure pointer of POSIF configuration.
 * @retval None.
 ******************************************************************************/
void POSIF_Init(POSIF_InitTypeStruct *POSIF_InitType)
{
  uint32_t tmpReg = 0UL;

  /*---------------------------- Parameters check ------------------------*/
  /* Input0 parameters check */
  PARAM_ASSERT(IS_POSIF_FLT_LEN(POSIF_InitType->POSIF_In0FilterLen));
  PARAM_ASSERT(IS_POSIF_ACMP(POSIF_InitType->POSIF_In0AnalogCompareSource));
  PARAM_ASSERT(IS_POSIF_FLT_SAMPLE(POSIF_InitType->POSIF_In0ClockSample));
  PARAM_ASSERT(IS_POSIF_SRC(POSIF_InitType->POSIF_In0InputSource));
  /* Input1 parameters check */
  PARAM_ASSERT(IS_POSIF_FLT_LEN(POSIF_InitType->POSIF_In1FilterLen));
  PARAM_ASSERT(IS_POSIF_ACMP(POSIF_InitType->POSIF_In1AnalogCompareSource));
  PARAM_ASSERT(IS_POSIF_FLT_SAMPLE(POSIF_InitType->POSIF_In1ClockSample));
  PARAM_ASSERT(IS_POSIF_SRC(POSIF_InitType->POSIF_In1InputSource));
  /* Input2 parameters check */
  PARAM_ASSERT(IS_POSIF_FLT_LEN(POSIF_InitType->POSIF_In2FilterLen));
  PARAM_ASSERT(IS_POSIF_ACMP(POSIF_InitType->POSIF_In2AnalogCompareSource));
  PARAM_ASSERT(IS_POSIF_FLT_SAMPLE(POSIF_InitType->POSIF_In2ClockSample));
  PARAM_ASSERT(IS_POSIF_SRC(POSIF_InitType->POSIF_In2InputSource));
  /* POSIF parameters check */
  PARAM_ASSERT(IS_POSIF_CLOCK_DIV(POSIF_InitType->POSIF_ClockDiv));
  PARAM_ASSERT(IS_POSIF_MODE(POSIF_InitType->POSIF_Mode));

  if(POSIF_MODE_ENC == POSIF_InitType->POSIF_Mode)
  {
    /* ENC parameters check */
    PARAM_ASSERT(IS_ENC_ZIN_ACTION(POSIF_InitType->ENC_ZinAction));
    PARAM_ASSERT(IS_ENC_ZIN_EN(POSIF_InitType->ENC_ZinEn));
    PARAM_ASSERT(IS_ENC_PULSE_CNT_EN(POSIF_InitType->ENC_PulseCntrEn));
    PARAM_ASSERT(IS_ENC_LOAD_VAL(POSIF_InitType->ENC_LoadValue));
  }
  else
  {
    /* ENC parameters check */
    PARAM_ASSERT(IS_HALL_MAX_WIDTH_VAL(POSIF_InitType->HALL_MaxWidth));
  }

  /*---------------------------- POSIF CR Configuration ------------------------*/
  /* Get the POSIF CR value */
  tmpReg = POSIF->CR;

  /* Clear IN(0~2)_FLT_LEN[1:0] bits. */
  tmpReg &= ~(POSIF_CR_IN0_FLT_LEN_Msk | POSIF_CR_IN1_FLT_LEN_Msk | POSIF_CR_IN2_FLT_LEN_Msk);
  /* Set IN(0~2)_FLT_LEN[1:0] bits according to POSIF_InitType. */
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In0FilterLen) << POSIF_CR_IN0_FLT_LEN_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In1FilterLen) << POSIF_CR_IN1_FLT_LEN_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In2FilterLen) << POSIF_CR_IN2_FLT_LEN_Pos);

  /* Clear IN(0~2)_FLT_SAMPLE[1:0] bits. */
  tmpReg &= ~(POSIF_CR_IN0_FLT_SAMPLE_Msk | POSIF_CR_IN1_FLT_SAMPLE_Msk | POSIF_CR_IN2_FLT_SAMPLE_Msk);
  /* Set IN(0~2)_FLT_SAMPLE[1:0] bits according to POSIF_InitType. */
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In0ClockSample) << POSIF_CR_IN0_FLT_SAMPLE_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In1ClockSample) << POSIF_CR_IN1_FLT_SAMPLE_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In2ClockSample) << POSIF_CR_IN2_FLT_SAMPLE_Pos);

  /* Clear IN(0~2)_ACMP_SEL[1:0] bits. */
  tmpReg &= ~(POSIF_CR_IN0_ACMP_SEL_Msk | POSIF_CR_IN1_ACMP_SEL_Msk | POSIF_CR_IN2_ACMP_SEL_Msk);
  /* Set IN(0~2)_ACMP_SEL[1:0] bits according to POSIF_InitType. */
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In0AnalogCompareSource) << POSIF_CR_IN0_ACMP_SEL_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In1AnalogCompareSource) << POSIF_CR_IN1_ACMP_SEL_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In2AnalogCompareSource) << POSIF_CR_IN2_ACMP_SEL_Pos);

  /* Clear IN(0~2)_SEL[1:0] bits. */
  tmpReg &= ~(POSIF_CR_IN0_SEL_Msk | POSIF_CR_IN1_SEL_Msk | POSIF_CR_IN2_SEL_Msk);
  /* Set IN(0~2)_SEL[1:0] bits according to POSIF_InitType. */
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In0InputSource) << POSIF_CR_IN0_SEL_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In1InputSource) << POSIF_CR_IN1_SEL_Pos);
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_In2InputSource) << POSIF_CR_IN2_SEL_Pos);

  /* Clear CLK_DIV[2:0] bits. */
  tmpReg &= ~POSIF_CR_CLK_DIV_Msk;
  /* Set CLK_DIV[2:0] bits according to POSIF_InitType. */
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_ClockDiv) << POSIF_CR_CLK_DIV_Pos);

  /* Clear bits. */
  tmpReg &= ~POSIF_CR_MODE_Msk;
  /* Set POSIF_MODE bits according to POSIF_InitType. */
  tmpReg |= (((uint32_t)POSIF_InitType->POSIF_Mode) << POSIF_CR_MODE_Pos);

  /* Write to POSIF CR */
  POSIF->CR = tmpReg;

  if(POSIF_MODE_ENC == POSIF_InitType->POSIF_Mode)
  {
    /*---------------------------- POSIF ENC_CR Configuration ------------------------*/
    /* Get the POSIF ENC_CR value */
    tmpReg = POSIF->ENC_CR;

    /* Clear ZIN_ACTION bits. */
    tmpReg &= ~POSIF_ENC_CR_ZIN_ACTION_Msk;
    /* Set ZIN_ACTION bits according to POSIF_InitType. */
    tmpReg |= (((uint32_t)POSIF_InitType->ENC_ZinAction) << POSIF_ENC_CR_ZIN_ACTION_Pos);

    /* Clear ZIN_EN bits. */
    tmpReg &= ~POSIF_ENC_CR_ZIN_EN_Msk;
    /* Set ZIN_EN bits according to POSIF_InitType. */
    tmpReg |= (((uint32_t)POSIF_InitType->ENC_ZinEn) << POSIF_ENC_CR_ZIN_EN_Pos);

    /* Clear PULSE_CNT_EN bits. */
    tmpReg &= ~POSIF_ENC_CR_PULSE_CNT_EN_Msk;
    /* Set PULSE_CNT_EN bits according to POSIF_InitType. */
    tmpReg |= (((uint32_t)POSIF_InitType->ENC_PulseCntrEn) << POSIF_ENC_CR_PULSE_CNT_EN_Pos);

    /* Clear ENC_MODE bits. */
    tmpReg &= ~POSIF_ENC_CR_ENC_MODE_Msk;
    /* Set ENC_MODE bits according to POSIF_InitType. */
    tmpReg |= (((uint32_t)POSIF_InitType->ENC_Mode) << POSIF_ENC_CR_ENC_MODE_Pos);

    /* Write to POSIF ENC_CR */
    POSIF->ENC_CR = tmpReg;

    /*---------------------------- POSIF ENC_MAX_POS Configuration ------------------------*/
    /* Get the POSIF ENC_MAX_POS value */
    tmpReg = POSIF->ENC_MAX_POS;

    /* Clear LOAD_VALUE[15:0] bits. */
    tmpReg &= ~POSIF_ENC_MAX_POS_MAX_POS_Msk;
    /* Set LOAD_VALUE[15:0] bits according to POSIF_InitType. */
    tmpReg |= (((uint32_t)POSIF_InitType->ENC_LoadValue) << POSIF_ENC_MAX_POS_MAX_POS_Pos);

    /* Write to POSIF ENC_MAX_POS */
    POSIF->ENC_MAX_POS = tmpReg;
  }
  else
  {
    /*---------------------------- POSIF HALL_MAX_WIDTH Configuration ------------------------*/
    /* Get the POSIF HALL_MAX_WIDTH value */
    tmpReg = POSIF->HALL_MAX_WIDTH;

    /* Clear HALL_MAX_WIDTH[23:0] bits. */
    tmpReg &= ~POSIF_HALL_MAX_WIDTH_MAX_WIDTH_Msk;
    /* Set HALL_MAX_WIDTH[23:0] bits according to POSIF_InitType. */
    tmpReg |= (POSIF_InitType->HALL_MaxWidth << POSIF_HALL_MAX_WIDTH_MAX_WIDTH_Pos);

    /* Write to POSIF HALL_MAX_WIDTH */
    POSIF->HALL_MAX_WIDTH = tmpReg;
  }
}

/**
 *******************************************************************************
 * @brief   Initialize the POSIF_InitType with default parameters.
 * @param   [out]  POSIF_InitType: Pointer to a POSIF_InitTypeStruct structure
 *                 which will be initialized.
 * @retval  None.
 ******************************************************************************/
void POSIF_StructInit(POSIF_InitTypeStruct *POSIF_InitType)
{
  POSIF_InitType->POSIF_In0FilterLen = POSIF_FLT_LEN1;
  POSIF_InitType->POSIF_In1FilterLen = POSIF_FLT_LEN1;
  POSIF_InitType->POSIF_In2FilterLen = POSIF_FLT_LEN1;
  POSIF_InitType->POSIF_In0ClockSample = POSIF_FLT_SAMPLE1;
  POSIF_InitType->POSIF_In1ClockSample = POSIF_FLT_SAMPLE1;
  POSIF_InitType->POSIF_In2ClockSample = POSIF_FLT_SAMPLE1;
  POSIF_InitType->POSIF_In0AnalogCompareSource = POSIF_ACMP_ACMP0;
  POSIF_InitType->POSIF_In1AnalogCompareSource = POSIF_ACMP_ACMP0;
  POSIF_InitType->POSIF_In2AnalogCompareSource = POSIF_ACMP_ACMP0;
  POSIF_InitType->POSIF_In0InputSource = POSIF_SRC_ACMP;
  POSIF_InitType->POSIF_In1InputSource = POSIF_SRC_ACMP;
  POSIF_InitType->POSIF_In2InputSource = POSIF_SRC_ACMP;
  POSIF_InitType->POSIF_ClockDiv = POSIF_CLK_DIV1;
  POSIF_InitType->POSIF_Mode = POSIF_MODE_ENC;
  POSIF_InitType->ENC_ZinAction = ENC_ZIN_ACTION_MULTIPLE;
  POSIF_InitType->ENC_ZinEn = ENC_ZIN_EN_ENABLE;
  POSIF_InitType->ENC_PulseCntrEn = ENC_PULSE_CNT_EN_ENABLE;
  POSIF_InitType->ENC_Mode = ENC_MODE_ENCODER_IN1;
  POSIF_InitType->ENC_LoadValue = 0xFFFF;
  POSIF_InitType->HALL_MaxWidth = 0xFFFFFF;
}

/**
 *******************************************************************************
 * @brief  Enables or disables the specified POSIF peripheral.
 * @param  [in]  state: New state of the POSIF peripheral.
 *               Any value of @ref FunctionalState.
 *                 @arg DISABLE: disbale POSIF peripheral.
 *                 @arg ENABLE: enable POSIF peripheral.
 * @retval None.
 ******************************************************************************/
void POSIF_Cmd(FunctionalState state)
{
  if(DISABLE != state)
  {
    /* Enable POSIF peripheral. */
    POSIF->CR |= (1 << POSIF_CR_EN_Pos);
  }
  else
  {
    /* Disable POSIF peripheral. */
    POSIF->CR &= ~POSIF_CR_EN_Msk;
  }
}

/**
 *******************************************************************************
 * @brief   Sets the POSIF ENC max position register value.
 * @param   [in]  val: Specifies the max position register new value.
 * @retval  None.
 ******************************************************************************/
void POSIF_ENC_SetMaxPosition(uint16_t val)
{
  /* Set the LOAD_VALUE[15:0] register value. */
  POSIF->ENC_MAX_POS = (((uint32_t)val) << POSIF_ENC_MAX_POS_MAX_POS_Pos);
}

/**
 *******************************************************************************
 * @brief  Returns the current counter value by the POSIF peripheral.
 * @retval uint16_t: The counter value.
 ******************************************************************************/
uint16_t POSIF_ENC_GetPosition(void)
{
  /* Return the CUR_POS[15:0] register value. */
  return (uint16_t)((POSIF->ENC_CUR_POS & POSIF_ENC_CUR_POS_CUR_POS_Msk) >> POSIF_ENC_CUR_POS_CUR_POS_Pos);
}

/**
 *******************************************************************************
 * @brief  Set the current counter value of the POSIF peripheral.
 * @param  [in]  val: The counter value.
 * @retval None.
 ******************************************************************************/
void POSIF_ENC_SetPosition(uint16_t val)
{
  /* Set the CUR_POS[15:0] register value. */
  POSIF->ENC_CUR_POS = (((uint32_t)val) << POSIF_ENC_CUR_POS_CUR_POS_Pos);
}

/**
 *******************************************************************************
 * @brief  Returns the pulse counter value by the POSIF peripheral.
 * @retval uint32_t: The pulse counter value.
 ******************************************************************************/
uint32_t POSIF_ENC_GetPulse(void)
{
  /* Return the PULSE_CNT[23:0] register value. */
  return (uint32_t)((POSIF->ENC_PULSE_CNT & POSIF_ENC_PULSE_CNT_CNT_Msk) >> POSIF_ENC_PULSE_CNT_CNT_Pos);
}

/**
 *******************************************************************************
 * @brief  Set the pulse counter value of the POSIF peripheral.
 * @param  [in]  val: The pulse counter value.
 * @retval None.
 ******************************************************************************/
void POSIF_ENC_SetPulse(uint32_t val)
{
  /* Clear the PULSE_CNT[23:0] register value. */
  POSIF->ENC_PULSE_CNT = (val << POSIF_ENC_PULSE_CNT_CNT_Pos);
}

/**
 *******************************************************************************
 * @brief  Enables or disables the specified ENC interrupts.
 * @param  [in]  ENC_IntType: Specifies the ENC interrupt.
 *               Any value of @ref ENC_IntTypeEnum.
 *                 @arg ENC_INT_TYPE_PULSE_CNT_OF: pulse control overflow interrupt.
 *                 @arg ENC_INT_TYPE_MAX_POS: max position interrupt.
 * @param  [in]  state: New state of the ENC interrupt.
 *               Any value of @ref FunctionalState.
 *                 @arg DISABLE: disbale ENC interrupt.
 *                 @arg ENABLE: enable ENC interrupt.
 * @retval None.
 ******************************************************************************/
void POSIF_ENC_IntCmd(ENC_IntTypeEnum ENC_IntType, FunctionalState state)
{
  if(DISABLE != state)
  {
    /* Enable the interrupt for selected. */
    POSIF->ENC_CR |= ENC_IntType;
  }
  else
  {
    /* Disable the interrupt for selected. */
    POSIF->ENC_CR &= ~ENC_IntType;
  }
}

/**
 *******************************************************************************
 * @brief  Get the specified ENC interrupt has enable or not.
 * @param  [in]  ENC_IntType: Specifies the ENC interrupt.
 *               Any value of @ref ENC_IntTypeEnum.
 *                 @arg ENC_INT_TYPE_PULSE_CNT_OF: pulse control overflow interrupt.
 *                 @arg ENC_INT_TYPE_MAX_POS: max position interrupt.
 * @retval FunctionalState: Interrupt enable bit has enable or not.
 *               Any value of @ref FunctionalState.
 *                 @arg DISABLE: Interrupt is disable.
 *                 @arg ENABLE: Interrupt is enable.
 ******************************************************************************/
FunctionalState POSIF_ENC_GetIntCmdStatus(ENC_IntTypeEnum ENC_IntType)
{
  FunctionalState state = DISABLE;

  if(RESET != (POSIF->ENC_CR & ENC_IntType))
  {
    /* Interrupt is enable. */
    state = ENABLE;
  }
  else
  {
    /* Interrupt is disbale. */
    state = DISABLE;
  }

  /* Return the status of the interrupt enable bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief  Get the specified ENC flag is set or not.
 * @param  [in]  ENC_IntFlag: Specifies the ENC interrupt flag.
 *               Any value of @ref ENC_IntFlagEnum.
 *                 @arg ENC_INT_FLAG_PULSE_CNT_OF: pulse control overflow interrupt flag.
 *                 @arg ENC_INT_FLAG_MAX_POS: max position interrupt flag.
 * @retval FlagState: Interrupt flag has occurred or not.
 *               Any value of @ref FlagState.
 *                 @arg SET: Interrupt has occurred.
 *                 @arg RESET: Interrupt has not occurred.
 ******************************************************************************/
FlagState POSIF_ENC_GetIntFlagStatus(ENC_IntFlagEnum ENC_IntFlag)
{
  FlagState state = RESET;

  if(RESET != (POSIF->ENC_SR & ENC_IntFlag))
  {
    /* Interrupt has occurred. */
    state = SET;
  }
  else
  {
    /* Interrupt has not occurred. */
    state = RESET;
  }

  /* Return the status of the interrupt flag bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief  Clears the ENC interrupt flags.
 * @param  [in]  ENC_IntFlag: Specifies the ENC interrupt flag.
 *               Any value of @ref ENC_IntFlagEnum.
 *                 @arg ENC_INT_FLAG_PULSE_CNT_OF: pulse control overflow interrupt flag.
 *                 @arg ENC_INT_FLAG_MAX_POS: max position interrupt flag.
 * @retval None.
 ******************************************************************************/
void POSIF_ENC_ClearIntFlag(ENC_IntFlagEnum ENC_IntFlag)
{
  /* Clear interrupt flags.*/
  POSIF->ENC_SR = ENC_IntFlag;
}

/**
 *******************************************************************************
 * @brief  Get the direction flag of the ENC encoder.
 * @retval ENC_DirEnum: Encoder direction.
 *               Any value of @ref ENC_DirEnum.
 *                 @arg ENC_DIR_REV: Encoder direction reversal.
 *                 @arg ENC_DIR_FWD: Encoder direction forward.
 ******************************************************************************/
ENC_DirEnum POSIF_ENC_GetDirection(void)
{
  ENC_DirEnum dir = ENC_DIR_REV;

  if(RESET != (POSIF->ENC_SR & POSIF_ENC_SR_ENC_DIR_Msk))
  {
    /* Encoder direction forward. */
    dir = ENC_DIR_FWD;
  }
  else
  {
    /* Encoder direction reversal. */
    dir = ENC_DIR_REV;
  }

  /* Returns the encoder direction bits. */
  return dir;
}

/**
 *******************************************************************************
 * @brief  Returns the maximum value between two adjacent edges via the HALL peripheral.
 * @retval uint32_t: The width data.
 ******************************************************************************/
uint32_t POSIF_HALL_GetWidth(void)
{
  /* Return the HALL_WIDTH[23:0] register value. */
  return (uint32_t)((POSIF->HALL_WIDTH & POSIF_HALL_WIDTH_HALL_WIDTH_Msk) >> POSIF_HALL_WIDTH_HALL_WIDTH_Pos);
}

/**
 *******************************************************************************
 * @brief  Set the POSIF hall delay value.
 * @param  [in]  val: The delay value.
 * @retval None.
 ******************************************************************************/
void POSIF_HALL_SetDelay(uint16_t val)
{
  /* Set the HALL_DELAY[15:0] register value. */
  POSIF->HALL_DELAY = (((uint32_t)val) << POSIF_HALL_DELAY_VAL_Pos);
}

/**
 *******************************************************************************
 * @brief  Set the POSIF peripheral device Max Width value.
 * @param  [in]  val: The counter value.
 * @retval None.
 ******************************************************************************/
void POSIF_HALL_SetMaxWidth(uint32_t val)
{
  /* Set the HALL_MAX_WIDTH[23:0] register value. */
  POSIF->HALL_MAX_WIDTH = (((uint32_t)val) << POSIF_HALL_MAX_WIDTH_MAX_WIDTH_Pos);
}

/**
 *******************************************************************************
 * @brief  Enables or disables the specified HALL interrupts.
 * @param  [in]  HALL_IntType: Specifies the HALL interrupt.
 *               Any value of @ref HALL_IntTypeEnum.
 *                 @arg HALL_INT_TYPE_MAX_WIDTH: max width interrupt enable.
 *                 @arg HALL_INT_TYPE_DELAY: delay interrupt enable.
 * @param  [in]  state: New state of the HALL interrupt.
 *               Any value of @ref FunctionalState.
 *                 @arg DISABLE: disbale HALL interrupt.
 *                 @arg ENABLE: enable HALL interrupt.
 * @retval None.
 ******************************************************************************/
void POSIF_HALL_IntCmd(HALL_IntTypeEnum HALL_IntType, FunctionalState state)
{
  if(DISABLE != state)
  {
    /* Enable the interrupt for selected. */
    POSIF->HALL_CR |= HALL_IntType;
  }
  else
  {
    /* Disable the interrupt for selected. */
    POSIF->HALL_CR &= ~HALL_IntType;
  }
}

/**
 *******************************************************************************
 * @brief  Get the specified HALL interrupt has enable or not.
 * @param  [in]  HALL_IntType: Specifies the HALL interrupt.
 *               Any value of @ref HALL_IntTypeEnum.
 *                 @arg HALL_INT_TYPE_MAX_WIDTH: max width interrupt enable.
 *                 @arg HALL_INT_TYPE_DELAY: delay interrupt enable.
 * @retval FunctionalState:    Interrupt enable bit has enable or not.
 *               Any value of @ref FunctionalState.
 *                 @arg DISABLE: Interrupt is disable.
 *                 @arg ENABLE: Interrupt is enable.
 ******************************************************************************/
FunctionalState POSIF_HALL_GetIntCmdStatus(HALL_IntTypeEnum HALL_IntType)
{
  FunctionalState state = DISABLE;

  if(RESET != (POSIF->HALL_CR & HALL_IntType))
  {
    /* Interrupt is enable. */
    state = ENABLE;
  }
  else
  {
    /* Interrupt is disbale. */
    state = DISABLE;
  }

  /* Return the status of the interrupt enable bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief  Get the specified HALL flag is set or not.
 * @param  [in]  HALL_IntFlag: Specifies the HALL interrupt flag.
 *               Any value of @ref HALL_IntFlagEnum.
 *                 @arg HALL_INT_FLAG_MAX_WIDTH: max width interrupt flag.
 *                 @arg HALL_INT_FLAG_DELAY: delay interrupt flag.
 * @retval FlagState: Interrupt flag has occurred or not.
 *               Any value of @ref FlagState.
 *                 @arg SET: Interrupt has occurred.
 *                 @arg RESET: Interrupt has not occurred.
 ******************************************************************************/
FlagState POSIF_HALL_GetIntFlagStatus(HALL_IntFlagEnum HALL_IntFlag)
{
  FlagState state = RESET;

  if(RESET != (POSIF->HALL_SR & HALL_IntFlag))
  {
    /* Interrupt has occurred. */
    state = SET;
  }
  else
  {
    /* Interrupt has not occurred. */
    state = RESET;
  }

  /* Return the status of the interrupt flag bit. */
  return state;
}

/**
 *******************************************************************************
 * @brief  Clears the HALL interrupt flags.
 * @param  [in]  HALL_IntFlag: Specifies the HALL interrupt flag.
 *               Any value of @ref HALL_IntFlagEnum.
 *                 @arg HALL_INT_FLAG_MAX_WIDTH: max width interrupt flag.
 *                 @arg HALL_INT_FLAG_DELAY: delay interrupt flag.
 * @retval None.
 ******************************************************************************/
void POSIF_HALL_ClearIntFlag(HALL_IntFlagEnum HALL_IntFlag)
{
  /* Clear interrupt flags.*/
  POSIF->HALL_SR = HALL_IntFlag;
}

/**
 *******************************************************************************
 * @brief  Return unfiltered value through HALL peripheral.
 * @retval uint8_t: The unfiltered data.
 ******************************************************************************/
uint8_t POSIF_HALL_GetUnfiltered(void)
{
  /* Return the RAW[2:0] register value. */
  return (uint8_t)((POSIF->HALL_SR & POSIF_HALL_SR_RAW_Msk) >> POSIF_HALL_SR_RAW_Pos);
}

/**
 *******************************************************************************
 * @brief  Filtered value returned by the HALL peripheral.
 * @retval uint8_t: The filtered data.
 ******************************************************************************/
uint8_t POSIF_HALL_GetFiltered(void)
{
  /* Return the DATA[2:0] register value. */
  return (uint8_t)((POSIF->HALL_SR & POSIF_HALL_SR_DATA_Msk) >> POSIF_HALL_SR_DATA_Pos);
}

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