/**
 *******************************************************************************
 * @file  menu_timer.c
 * @brief This file provides firmware functions to manage the menu timer.
 @verbatim
   Change Logs:
   Date             Author          Notes
   2022-06-30       CDT             First version
   2023-01-17       CDT             Typo: funciont -> function
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by XHSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "console_conf.h"
#include "menu_timer.h"

/**
 * @addtogroup Serial_Port_Console
 * @{
 */

/**
 * @defgroup Menu_Timer Menu Timer
 * @{
 */

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/
/**
 * @defgroup Menu_Timer_Local_Variables Menu Timer Local Variables
 * @{
 */
static stc_slist_t m_stcMenuTimerHead;
/**
 * @}
 */

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
/**
 * @defgroup Menu_Timer_Global_Functions Menu Timer Global Functions
 * @{
 */

/**
 * @brief  Create timer.
 * @param  [in] u32TickPeriod       Period tick
 * @param  [in] bReloadState        Reload command state
 * @param  [in] pfnCallback         Pointer to callback function
 * @retval Pointer to a @ref stc_menu_timer_t structure
 */
stc_menu_timer_t *Menu_Timer_Create(uint32_t u32TickPeriod, bool bReloadState,
                                    int32_t (*pfnCallback)(stc_menu_timer_t *))
{
    stc_menu_timer_t *pstcTimer = NULL;

    if (u32TickPeriod != 0UL) {
        pstcTimer = (stc_menu_timer_t *)malloc(sizeof(stc_menu_timer_t));
        if (pstcTimer != NULL) {
            pstcTimer->bReloadCmd = bReloadState;
            pstcTimer->u32InitTick = u32TickPeriod;
            pstcTimer->u32RemainTick = u32TickPeriod;
            pstcTimer->pfnCallback = pfnCallback;
            INIT_SLIST_HEAD(&pstcTimer->stcNode);
        }
    }

    return pstcTimer;
}

/**
 * @brief  Start timer.
 * @param  [in] pstcTimer           Pointer to a @ref stc_menu_timer_t structure
 * @retval None
 */
void Menu_Timer_Start(stc_menu_timer_t *pstcTimer)
{
    uint32_t u32SR;

    if (pstcTimer != NULL) {
        u32SR = CRITICAL_ZONE_ENTER();
        slist_add_tail(&m_stcMenuTimerHead, &pstcTimer->stcNode);
        CRITICAL_ZONE_EXIT(u32SR);
    }
}

/**
 * @brief  Stop timer.
 * @param  [in] pstcTimer           Pointer to a @ref stc_menu_timer_t structure
 * @retval None
 */
void Menu_Timer_Stop(stc_menu_timer_t *pstcTimer)
{
    uint32_t u32SR;

    if (pstcTimer != NULL) {
        u32SR = CRITICAL_ZONE_ENTER();
        slist_del(&m_stcMenuTimerHead, &pstcTimer->stcNode);
        CRITICAL_ZONE_EXIT(u32SR);
    }
}

/**
 * @brief  Delete timer.
 * @param  [in] pstcTimer           Pointer to a @ref stc_menu_timer_t structure
 * @retval None
 */
void Menu_Timer_Delete(stc_menu_timer_t *pstcTimer)
{
    if (pstcTimer != NULL) {
        Menu_Timer_Stop(pstcTimer);
        free(pstcTimer);
    }
}

/**
 * @brief  Delete timer.
 * @param  [in] pstcTimer           Pointer to a @ref stc_menu_timer_t structure
 * @param  [in] bReloadState        Reload command state
 * @retval None
 */
void Menu_Timer_ReloadCmd(stc_menu_timer_t *pstcTimer, bool bReloadState)
{
    uint32_t u32SR;

    if (pstcTimer != NULL) {
        u32SR = CRITICAL_ZONE_ENTER();
        pstcTimer->bReloadCmd = bReloadState;
        CRITICAL_ZONE_EXIT(u32SR);
    }
}

/**
 * @brief  Timer increase tick.
 * @param  None
 * @retval None
 */
void Menu_Timer_IncTick(void)
{
    stc_slist_t *pstcPos;
    stc_menu_timer_t *pstcTimer;

    slist_for_each(pstcPos, &m_stcMenuTimerHead) {
        pstcTimer = (stc_menu_timer_t *)pstcPos;
        if (--pstcTimer->u32RemainTick == 0UL) {
            if (pstcTimer->pfnCallback != NULL) {
                pstcTimer->pfnCallback(pstcTimer);
            }

            if (true == pstcTimer->bReloadCmd) {
                pstcTimer->u32RemainTick = pstcTimer->u32InitTick;
            } else {
                Menu_Timer_Delete(pstcTimer);
            }
        }
    }
}

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
