/**
 *******************************************************************************
 * @file    dpm32m0xx_wdg.c.
 *
 * @brief   Source file for WDG firmware driver.
 *          This file provides firmware functions to manage the following
 *          functionalities of the Watchdog (WDG) peripheral :
 *           + Initialization and Configuration function
 *           + Data Counter
 *           + Interrupts and flags management
 *
 * @author  DPM
 *
 * @version V1.0.0
 *
 * @date    2023-11-01
 *
 * @verbatim
 ===============================================================================
                       ##### How to use this driver #####
 ===============================================================================
    [..]
      (#) To use WDG, you need to turn on the LSCK clock and first configure the
          LSI or LSE using RCC_OscConfig(), Then select a clock source for LSCLK
          using RCC_ClockConfig().

      (#) Set the WDG counter value using WDG_CounterModeConfig() function.
          When the WWDG is enabled the counter value should be configured to
          a value greater than 0x40 to prevent generating an immediate reset.

      (#) Optionally you can enable the Early wakeup interrupt which is
          generated when the counter reach 0x40.
          Once enabled this interrupt cannot be disabled except by a system
          reset.

      (#) Then the application program must refresh the WDG counter at regular
          intervals during normal operation to prevent an MCU reset, using
          WDG_SetCounter() function. This operation must occur only when
          the counter value is lower than the refresh window value,
          programmed using WDG_SetWindowValue().

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

#include "dpm32m0xx_wdg.h"


/**
 *******************************************************************************
 * @brief   Deinitializes WDG peripheral registers to their default reset values.
 * @param   None.
 * @retval  None.
 ******************************************************************************/
void WDG_DeInit(void)
{
  /* Deinitializes WDG peripheral registers and clear WDF_IF bit. */
  WDG->CSR = (WDGKEY | WDG_CSR_IF_Msk);
}

/**
 *******************************************************************************
 * @brief  Initializes the WDC peripheral according to the specified parameters
 *         in the WDG_InitStruct.
 * @param  [in]  WDG_InitType: Structure pointer of WDG configuration.
 * @retval None.
 ******************************************************************************/
void WDG_Init(WDG_InitTypeStruct *WDG_InitType)
{
  uint32_t tmpReg = 0UL;

  /* Parameters check. */
  PARAM_ASSERT(IS_WDG_MODE(WDG_InitType->WDG_Mode));

  /* Read the value of the WDG control register. */
  tmpReg = WDG->CSR;

  /* Set WDG counter time. */
  tmpReg &= ~WDG_CSR_MODE_Msk;
  tmpReg |= ((uint32_t)(WDG_InitType->WDG_Mode));

  /* Store the new value. */
  tmpReg |= WDGKEY;
  WDG->CSR = tmpReg;
}

/**
 *******************************************************************************
 * @brief   Sets the WDG mode.
 * @param   [in]  mode: Any value of @ref WDG_ModeEnum.
 *                @arg WDG_MODE_7BIT : Maximum count value 128 selection.
 *                     3.90625ms reset.
 *                @arg WDG_MODE_8BIT : Maximum count value 256 selection.
 *                     7.8125ms reset.
 *                @arg WDG_MODE_9BIT : Maximum count value 512 selection.
 *                     15.625ms reset.
 *                @arg WDG_MODE_10BIT: Maximum count value 1024 selection.
 *                     31.25ms reset.
 *                @arg WDG_MODE_11BIT: Maximum count value 2048 selection.
 *                     62.5ms reset.
 *                @arg WDG_MODE_12BIT: Maximum count value 4096 selection.
 *                     125ms reset.
 *                @arg WDG_MODE_13BIT: Maximum count value 8192 selection.
 *                     250ms reset.
 *                @arg WDG_MODE_14BIT: Maximum count value 16384 selection.
 *                     500ms reset.
 *                @arg WDG_MODE_15BIT: Maximum count value 32768 selection.
 *                     1s reset.
 *                @arg WDG_MODE_16BIT: Maximum count value 65536 selection.
 *                     2s reset.
 *                @arg WDG_MODE_17BIT: Maximum count value 131072 selection.
 *                     4s reset.
 *                @arg WDG_MODE_18BIT: Maximum count value 262144 selection.
 *                     8s reset.
 *                @arg WDG_MODE_19BIT: Maximum count value 524288 selection.
 *                     16s reset.
 *                @arg WDG_MODE_20BIT: Maximum count value 1048576 selection.
 *                     32s reset.
 *                @arg WDG_MODE_21BIT: Maximum count value 2097152 selection.
 *                     64s reset.
 *                @arg WDG_MODE_22BIT: Maximum count value 4194304 selection.
 *                     128s reset.
 * @retval  None.
 ******************************************************************************/
void WDG_CounterModeConfig(WDG_ModeEnum WDG_Mode)
{
  uint32_t tmpReg = 0UL;

  /* Parameters check. */
  PARAM_ASSERT(IS_WDG_MODE(WDG_Mode));

  /* Read the value of the WDG control register. */
  tmpReg = WDG->CSR;

  /* Clear WDG MODE bit. */
  tmpReg &= (~WDG_CSR_MODE_Msk);

  /* Set WDG MODE bit. */
  tmpReg |= ((uint32_t)(WDG_Mode));

  /* Store the new value. */
  tmpReg |= WDGKEY;
  WDG->CSR = tmpReg;
}

/**
 *******************************************************************************
 * @brief   Enable or disable the WDG.
 * @param   [in]  NewState: New state of the watchdog.
 *                Any value of @ref FunctionalState.
 *                  @arg DISABLE: disable WDG.
 *                  @arg ENABLE: enable WDG.
 * @retval  None.
 ******************************************************************************/
void WDG_Cmd(FunctionalState NewState)
{
  uint32_t tmpReg = 0UL;

  if (DISABLE != NewState)
  {
    /* Enable WDG. */
    WDG->CSR |= (WDG_CSR_EN_Msk | WDGKEY);
  }
  else
  {
    /* Read the value of the WDG control register. */
    tmpReg = WDG->CSR;

    /* Disable WDG. */
    tmpReg &= (~WDG_CSR_EN_Msk);

    /* Store the new value. */
    tmpReg |= WDGKEY;
    WDG->CSR = tmpReg;
  }
}

/**
 *******************************************************************************
 * @brief   Enable the WDG.
 * @param   None.
 * @retval  None.
 ******************************************************************************/
void WDG_Enable(void)
{
  /* Enable WDG. */
  WDG->CSR |= (WDG_CSR_EN_Msk | WDGKEY);
}

/**
 *******************************************************************************
 * @brief   Disable  the WDG.
 * @param   None.
 * @retval  None.
 ******************************************************************************/
void WDG_Disable(void)
{
  uint32_t tmpReg = 0UL;

  /* Read the value of the WDG control register. */
  tmpReg = WDG->CSR;

  /* Disable WDG. */
  tmpReg &= (~WDG_CSR_EN_Msk);

  /* Store the new value. */
  tmpReg |= WDGKEY;
  WDG->CSR = tmpReg;
}

/**
 *******************************************************************************
 * @brief   Enable or disable the WDG interrupt.
 * @param   [in]  NewState: New state of the watchdog interrupt.
 *                Any value of @ref FunctionalState.
 *                  @arg DISABLE: disable interrupt.
 *                  @arg ENABLE: enable interrupt.
 * @retval  None.
 ******************************************************************************/
void WDG_IntCmd(FunctionalState NewState)
{
  uint32_t tmpReg = 0UL;

  if (DISABLE != NewState)
  {
    /* Enable WDG interrupt. */
    WDG->CSR |= (uint32_t)(WDG_CSR_IE_Msk | WDGKEY);
  }
  else
  {
    /* Read the value of the WDG control register. */
    tmpReg = WDG->CSR;

    /* Disable WDG interrupt. */
    tmpReg &= (~WDG_CSR_IE_Msk);

    /* Store the new value. */
    tmpReg |= WDGKEY;
    WDG->CSR = tmpReg;
  }
}

/**
 *******************************************************************************
 * @brief   Get the WDG Interrup enable status.
 * @retval  FunctionalState: WDG Interrup enable status.
 ******************************************************************************/
FunctionalState WDG_GetIntCmdStatus(void)
{
  return (FunctionalState)((WDG->CSR & WDG_CSR_IE_Msk) ? ENABLE : DISABLE);
}

/**
 *******************************************************************************
 * @brief   Get the WDG Interrup Flag.
 * @param   None.
 * @retval  FlagState: WDG Interrup Flag.
 ******************************************************************************/
FlagState WDG_GetIntFlagStatus(void)
{
  if ((WDG->CSR & WDG_CSR_IF_Msk) != RESET)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

/**
 *******************************************************************************
 * @brief   Clear the WDG Interrup Flag.
 * @param   None.
 * @retval  None.
 ******************************************************************************/
void WDG_ClearIntFlag(void)
{
  /* Clear WDG IF bit. */
  WDG->CSR |= ( WDG_CSR_IF_Msk | WDGKEY );
}

/**
 *******************************************************************************
 * @brief   Feed Dog to Resset WDG
 * @param   None.
 * @retval  None.
 ******************************************************************************/
void WDG_FeedDog(void)
{
  /* Reset watchdog CLR. */
  WDG->CLR = FEEDDOG;
}


#if defined (DPM32M036) || defined (DPM32M030) || defined (DPM32M015)   

/**
 *******************************************************************************
 * @brief   Enable or disable the WDG enable lock position.
 * @retval  None.
 ******************************************************************************/
void WDG_MaskEnable(void)
{ 
  /* Enable WDG enable lock position. */
  WDG->CSR |= (WDG_CSR_MASK_Msk | WDGKEY);
}

/**
 *******************************************************************************
 * @brief   Get the status of the WDG enable lock position.
 * @param   None.
 * @retval  FlagState: WDG enable lock position Flag.
 ******************************************************************************/
FlagState WDG_GetMaskStatus(void)
{
  if ((WDG->CSR & WDG_CSR_MASK_Msk) != RESET)
  {
    return SET;
  }
  else
  {
    return RESET;
  }
}

#endif /* DPM32M036 || DPM32M030 || DPM32M015 */

