/**
 * \file    drv_timer.h
 * \brief   Software timer, extented by CPU core hardware timer
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-12
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-12  Original Creation
 * 
 */
 
#ifndef __DRV_TIMER_H_
#define __DRV_TIMER_H_


#include "types.h"

#define DRV_TIEMR_READ_LOCK     (0)

#pragma pack(1)

/** The maximal timer index */    
#define DRV_TIMER_ID_MAX        (12)


/** DRV software timer structure definition */
typedef struct drv_timer_s {
    u32_t id:5; ///< timer ID
    u32_t continuous:1; ///< is continuous flag
    u32_t in_use:1; ///< in use flag
    u32_t timeout:1;  ///< timeout flag
    u32_t has_param:1; ///< indicate the timer has callback function parameter
    u32_t reserved:1; ///< reserved
    u32_t param:22; ///< callback function parameter, max value = 0x3FFFFF
} drv_timer_t;

#pragma pack()

/**
 * DRV software timer init 
 */
void drv_timer_init(void);

/**
 * Start DRV software timer 
 *
 *
 * \param timeout   timeout value, the unit is milisecond (granularity: 1ms )
 * \param timer     timer pointer
 * \param cb        timer callback function
 * \return The result of start driver timer, TRUE: succeeded, FALSE: failed
 *
 * \see
 */
bool_t drv_timer_start(u32_t timeout, volatile drv_timer_t *timer, void *cb);

/**
 * Stop DRV software timer
 *
 *
 * \param timer The pointer of the software timer
 *
 * \see
 */
void drv_timer_stop(volatile drv_timer_t *timer);

#if DRV_TIEMR_READ_LOCK  /* modified by James Gan - 2020-03-25 */
/**
 * Check if a timer has started
 *
 * This macro is used to check if a timer has started.
 *
 * \param ptr       A pointer to the timer
 *
 */ 
bool_t drv_timer_started(volatile drv_timer_t *timer);

/**
 * Check if a timer has stopped
 *
 * This macro is used to check if a timer has stopped.
 *
 * \param ptr       A pointer to the timer
 *
 */ 
bool_t drv_timer_stopped(volatile drv_timer_t *timer);

/**
 * Check if a timer has expired
 *
 * This macro is used to check if a timer has stopped.
 *
 * \param ptr       A pointer to the timer
 *
 */ 
bool_t drv_timer_expired(volatile drv_timer_t *timer);
#else
/**
 * Check if a timer has started
 *
 * This macro is used to check if a timer has started.
 *
 * \param ptr       A pointer to the timer
 *
 */ 
#define drv_timer_started(ptr) \
    ((ptr)->in_use)

/**
 * Check if a timer has stopped
 *
 * This macro is used to check if a timer has stopped.
 *
 * \param ptr       A pointer to the timer
 *
 */ 
#define drv_timer_stopped(ptr) \
    ((ptr)->in_use == 0)

/**
 * Check if a timer has expired
 *
 * This macro is used to check if a timer has stopped.
 *
 * \param ptr       A pointer to the timer
 *
 */ 
#define drv_timer_expired(ptr) \
    ((ptr)->timeout)

#endif /* #if DRV_TIEMR_READ_LOCK */


/** \brief Get the tick count of driver timer, increase by one per millisecond
 *
 * \return  the tick count
 */
u32_t drv_timer_tick_get(void);

extern volatile u32_t drv_timer_tick;

#define drv_timer_tick_in_isr_get()     (drv_timer_tick)

/**
 * DRV software timer service, call by timer interrupt service
 */
void drv_timer_service(u32_t arg);

#if LIBC_PRINTF_ENABLED
void drv_timer_dump();
#endif /* LIBC_PRINTF_ENABLED */


#endif /* #ifndef __DRV_TIMER_H_ */

