/**
 * \file    drv_chip.h
 * \brief   Chip global driver
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-01
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-01  Original Creation
 * 
 */
 
#ifndef __DRV_CHIP_H_
#define __DRV_CHIP_H_


#include "types.h"
#include "drv_reg_intf.h"
#include "reg_def_chip.h"

/** \brief Get the chip machine cycle counter from power on
 *
 * \return 
 */
u64_t drv_chip_mcycle_get(void);

/**
 *  If user want to do something before drv_chip_reset, please configure this handler
 */
extern v_func_v_ptr_t g_drv_chip_reset_callback_handler;

#define drv_chip_reset_callback_handler_set(vfunc) \
    do { \
        g_drv_chip_reset_callback_handler = vfunc; \
    } while(0)


/** \brief Chip reset
 *
 */
void drv_chip_reset(void);


/** Get revision number */
#define drv_chip_rev_get() \
    DRV_REG_FIELD_GET(CHIP_REG_0, VERSION_ID)


#if LOW_POWER_ENABLED  /* modified by James Gan - 2018-01-19 */
/** Get sleep wake up flag */
#define drv_chip_wkup_flg() \
    DRV_REG_FIELD_GET(DPM_LPM_REG, SLP_MODE)

/** Clear sleep wake up flag */
#define drv_chip_wkup_flg_clear() \
    do { \
        DRV_REG_FIELD_SET(DPM_LPM_REG, SLP_MODE, FALSE); \
    } \
    while(0)

/** Set chip working in sleep mode */
#define drv_chip_sleep() \
    do { \
        DRV_REG_FIELD_SET(DPM_LPM_REG, SLP_MODE, TRUE); \
    } \
    while(0)

/** Get chip auto wake up time in sleep mode, unit is millisecond */
#define drv_chip_auto_wkup_get()    ((DRV_REG_FIELD_GET(DPM_LPM_REG,SLP_AUTO_WAKEUP_TIMER)<<18U)/4000U)

/** Set chip auto wake up time in sleep mode, unit is millisecond, 
 *  valid value in multiple of 500ms 
 */
#define drv_chip_auto_wkup_set(val) \
    do { \
        DRV_REG_FIELD_SET(DPM_LPM_REG, SLP_AUTO_WAKEUP_TIMER, ((((val)/500)*0x200000)>>18)); \
    } \
    while(0)
#else
/** Get sleep wake up flag */
#define drv_chip_wkup_flg()			(0)

/** Clear sleep wake up flag */
#define drv_chip_wkup_flg_clear()

/** Set chip working in sleep mode */
#define drv_chip_sleep()

/** Get chip auto wake up time in sleep mode, unit is millisecond  */
#define drv_chip_auto_wkup_get()

/** Set chip auto wake up time in sleep mode, unit is millisecond, 
 *  valid value in multiple of 500ms 
 */
#define drv_chip_auto_wkup_set(val)

#endif /* #if LOW_POWER_ENABLED */


/** Power down control set */
#define drv_chip_pd_ctrl_set(val) \
    do { \
        drv_reg_field_set(PD_CTRL_REG, 0, 6, val); \
    } \
    while(0)

/** DA power down control set */
#define drv_chip_da_pd_ctrl_set(val) \
    do { \
        DRV_REG_SET(DA_CTRL_REG, val); \
    } \
    while(0)


/** DP0 DM0 short enable set */
#define drv_chip_dp0_dm0_short_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, SW0R20, en); \
    } \
    while(0)

/** DP0 DM0 short enable get */
#define drv_chip_dp0_dm0_short_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, SW0R20)


/** DM0 enable 20 Kohm pull-down set */
#define drv_chip_dm0_20kohm_pull_down_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, DM0SW20, en); \
    } \
    while(0)

/** DM0 enable 20 Kohm pull-down get */
#define drv_chip_dm0_20kohm_pull_down_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, DM0SW20)


/** DP0 enable 20 Kohm pull-down set */
#define drv_chip_dp0_20kohm_pull_down_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, DP0SW20, en); \
    } \
    while(0)

/** DP0 enable 20 Kohm pull-down get */
#define drv_chip_dp0_20kohm_pull_down_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, DP0SW20)


/** DP0 enable 500 Kohm pull-down set */
#define drv_chip_dp0_500kohm_pull_down_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, DP0SW500, en); \
    } \
    while(0)

/** DP0 enable 500 Kohm pull-down get */
#define drv_chip_dp0_500kohm_pull_down_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, DP0SW500)


/** DP1 DM1 short enable set */
#define drv_chip_dp1_dm1_short_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, SW1R20, en); \
    } \
    while(0)

#define drv_chip_dp1_dm1_short_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, SW1R20)


/** DM1 enable 20 Kohm pull-down set */
#define drv_chip_dm1_20kohm_pull_down_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, DM1SW20, en); \
    } \
    while(0)

/** DM1 enable 20 Kohm pull-down get */
#define drv_chip_dm1_20kohm_pull_down_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, DM1SW20)


/** DP1 enable 20 Kohm pull-down set */
#define drv_chip_dp1_20kohm_pull_down_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, DP1SW20, en); \
    } \
    while(0)

/** DP1 enable 20 Kohm pull-down get */
#define drv_chip_dp1_20kohm_pull_down_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, DP1SW20)


/** DP1 enable 500 Kohm pull-down set */
#define drv_chip_dp1_500kohm_pull_down_set(en) \
    do { \
        DRV_REG_FIELD_SET(SW_CTRL_REG, DP1SW500, en); \
    } \
    while(0)

/** DP1 enable 500 Kohm pull-down get */
#define drv_chip_dp1_500kohm_pull_down_get() \
    DRV_REG_FIELD_GET(SW_CTRL_REG, DP1SW500)


/** \brief Chip control initialization
 *         Include power down control, chip frequency and RTC
 */
void drv_chip_ctrl_init(void);

typedef enum DRV_CHIP_FREQ_e
{
    DRV_CHIP_FREQ_33M = 33000000UL,      // 33MHz    DN/DP=33/1   Default
    DRV_CHIP_FREQ_29M = 29000000UL,      // 29MHz    DN/DP=29/1
    DRV_CHIP_FREQ_22M = 22000000UL,      // 22MHz    DN/DP=22/1
    DRV_CHIP_FREQ_16P5M = 16500000UL,    // 16.5MHz  DN/DP=33/2
    DRV_CHIP_FREQ_11M = 11000000UL,      // 11MHz    DN/DP=22/2
    DRV_CHIP_FREQ_7P375M = 7375000UL,    // 7.375MHz DN/DP=59/8
    DRV_CHIP_FREQ_5P5M = 5500000UL,      // 5.5MHz   DN/DP=22/4
    DRV_CHIP_FREQ_3P625M = 3625000UL,    // 3.625MHz DN/DP=29/8
    DRV_CHIP_FREQ_INVALID = 0
} DRV_CHIP_FREQ_t;

/** Default chip frequency type, can be redifined in platform_config.h */
#ifndef DEFAULT_CHIP_FREQ
#define DEFAULT_CHIP_FREQ                       DRV_CHIP_FREQ_33M
#endif

/** \brief Configure chip runtime frequency
 *
 * \param freq      predefined frequency type, see DRV_CHIP_FREQ_t
 */
void drv_chip_freq_set(DRV_CHIP_FREQ_t freq);

/** \brief Get chip runtime frequency
 *
 * \return The chip runtime frequency
 */
u32_t drv_chip_freq_get(void);

/** \brief Get the chip clock tick
 *
 * \return  the chip clock tick
 */
f32_t drv_chip_clock_tick_get(void);

/** \brief Get chip runtime frequency for UART baudrate calculation
 *
 * \return The chip runtime frequency for UART baudrate calculation
 */
u32_t drv_chip_freq_to_baudrate_get(void);


#endif /* #ifndef __DRV_CHIP_H_ */

