/**
  *****************************************************************************
  * @file    bc_qc.h
  * @author  Solution Team
  * @version V1.00
  * @date    09-November-2023
  * @brief   Battery Charge and Quick Charge process
  *****************************************************************************
  * @attention 
  *  Copyright (c) 2017 - 2023 Unicmicro Co., Ltd. 
  *  All Rights Reserved. 
  *****************************************************************************
  */
 
#ifndef BC_QC_H
#define BC_QC_H


#include "types.h"


/** \name  Quick Charge Version definitions
 * \{ 
 */
#define BC_QC_V2                            (0)         ///< 2.0
#define BC_QC_V3                            (1)         ///< 3.0
#define BC_QC_VER                           BC_QC_V3   ///< default version
/** \} */

#define BC_QC3_SRC_VOLT_INC_STEP            (200U)

/** \name Quick Charge Connection State definitions
 * \{ 
 */

typedef enum BC_QC_STATE_e
{
    BC_QC_IDLE              ,
    BC_QC_SRC_STARTUP       ,
    BC_QC_SRC_BC12          ,
    BC_QC_SRC_WAITDM        ,
    BC_QC_SRC_CONNECTED     ,
    BC_QC_SRC_CONNECTED_9V  ,
    BC_QC_SRC_CONNECTED_12V ,
    BC_QC_SRC_CONNECTED_20V ,
    BC_QC_SRC_CONNECTED_QC3 ,
    BC_QC_DISABLED          ,
    BC_QC_SNK_STARTUP       ,
    BC_QC_SNK_CONNECTING    ,
    BC_QC_SNK_CONNECTED_9V  ,
    BC_QC_SNK_CONNECTED_12V ,
    BC_QC_SNK_CONNECTED_QC3 ,
    BC_QC_SNK_QC3_INC_REQ   ,
    BC_QC_SNK_QC3_DEC_REQ   ,
    BC_SCP_SRC_DETECT
} BC_QC_STATE_t;


/** \}*/

/** Unit is millivolt, 300 mV */
#define BC_QC_DM_0P325V_MIN    (200U)

/** Unit is millivolt, 900 mV */
#define BC_QC_DM_0P325V_MAX    (900U)

/** Unit is millivolt, 300 mV */
#define BC_QC_DM_0P6V_MIN      (300U)

/** Unit is millivolt, 900 mV */
#define BC_QC_DM_0P6V_MAX      (900U)

/** Unit is millivolt, 2290 mV */
#define BC_QC_DM_3P3V_MIN      (2290U)

/** Unit is millivolt, 3300 mV */
#define BC_QC_DM_3P3V_MAX      (3600U)

/** Unit is millivolt, 2000 mV */
#define BC_APPLE_DISCONNECT_DM_MIN    (2000U)

/** Unit is millivolt, 2875 mV */
#define BC_APPLE_DISCONNECT_DM_MAX    (2875U)

/** Unit is millivolt, 400 mV */
#define BC_SAMSUNG_DM_DISCONNECT_MIN  (400U)

/** Unit is millivolt, 1050 mV */
#define BC_SAMSUNG_DM_DISCONNECT_MAX  (1050U)

/** Unit is millivolt, 900 mV */
#define BC_SAMSUNG_DM_CONNECTED_MIN  (900U)

/** Unit is millivolt, 1400 mV */
#define BC_SAMSUNG_DM_CONNETED_MAX  (1400U)


#define BC_QC_VBUS_VOLT_MARGIN (500U)

#define BC_QC_VBUS_CHANGE_STEP (200U)
#define BC_QC_VBUS_CHANGE_MIN  (100U)
#define BC_QC_VBUS_CHANGE_MAX  (256U)

#define BC_QC_VBUS_5V_MIN      (4500U)
#define BC_QC_VBUS_5V_MAX      (5500U)

#define BC_QC_VBUS_9V_MIN      (8500U)
#define BC_QC_VBUS_9V_MAX      (9500U)

#define BC_QC_VBUS_12V_MIN     (11400U)
#define BC_QC_VBUS_12V_MAX     (12600U)

#define BC_QC_MAX_POWER        (22000000UL)

/*Unit is millivolt, 400 mV*/
#define BC_HW_SCP_DP_0P4V_MIN     (450U)
/*Unit is millivolt, 400 mV*/
#define BC_HW_SCP_DP_0P4V_MAX     (800U)
//end


#pragma pack(1)

typedef enum BC_QC_VOLT_INTF_TYPE_e
{
    BC_QC_VOLT_INTF_TYPE_DP,
    BC_QC_VOLT_INTF_TYPE_DM,
    BC_QC_VOLT_INTF_TYPE_VBUS,
    BC_QC_VOLT_INTF_TYPE_IBUS,
    BC_QC_VOLT_INTF_TYPE_END
} BC_QC_VOLT_INTF_TYPE_t;

typedef enum BC_SRC_DPDM_MODE_e
{
    BC_SRC_DPDM_MODE_OFF,      /* DP DM open, DM without pull down */
    BC_SRC_DPDM_MODE_APPLE,    /* DP DM short, DP = 2.7V, DM without pull down */
    BC_SRC_DPDM_MODE_SAMSUNG,  /* DP DM short, DP = 1.2V, DM without pull down */
    BC_SRC_DPDM_MODE_BC,       /* DP DM short, DM without pull down */
    BC_SRC_DPDM_MODE_QC2,      /* DP DM open, DM pull down */
    BC_SRC_DPDM_MODE_QC3,      /* DP DM open, DM pull down, Need to enable 
                                 * interrupt trigger for DP and DM PINs, 
                                 * DP raising edge, DM falling edge
                                 */
} BC_SRC_DPDM_MODE_t;

typedef enum BC_QC_SNK_DPDM_MODE_e
{
    BC_QC_SNK_DPDM_MODE_INPUT,
    BC_QC_SNK_DPDM_MODE_LOAD_GND,
    BC_QC_SNK_DPDM_MODE_LOAD_0P325V,
    BC_QC_SNK_DPDM_MODE_LOAD_0P6V,
    BC_QC_SNK_DPDM_MODE_LOAD_3P3V,
    BC_QC_SNK_DPDM_MODE_END
} BC_QC_SNK_DPDM_MODE_t;

typedef struct BC_QC_INFO_s
{
    // 32 bits
    u32_t state:5;              ///< QC runtime state
    u32_t apple_samsung_mode_enabled:1; ///< Apple Samsung mode enabled flag
    u32_t dm_falling_entered:1; ///< QC src runtime flag, DM falling entered
    u32_t vbus_volt_change_req:1;   ///< QC runtime flag, vbus change request
    u32_t vbus_volt_changed:1;  ///< QC runtime flag, vbus changed flag
    u32_t is_snk:1;             ///< Indicate if it is sink mode
    u32_t snk_operating_volt:15;///< QC snk operating voltage, system configuration, 20V max
    u32_t snk_qc3_req:1;        ///< QC snk runtime flag, QC3.0 request
    u32_t snk_qc3_failed:1;     ///< QC snk runtime flag, QC3.0 failed
    u32_t snk_reset_req:1;      ///< QC snk runtime flag, reset request
    u32_t snk_load_0p6v:1;      ///< QC snk runtime flag, need to try load 0.6v
    u32_t snk_change_volt_miss_cnt:3;   ///< QC snk runtime variable, miss count of changing voltage 

    // 32 bits
    u32_t src_dp_dm_mode:3;     ///< QC src runtime DP DM mode
    u32_t dm_volt:13;           ///< DM current voltage
    u32_t dm_volt_pre:13;       ///< DM previous voltage
    u32_t samsung_mode_disabled:1;
    u32_t bc_qc_disable:1;
    u32_t qc_2p8v_judge_apple_mode_dis:1; ///< apple mode no judge 2.8v

    // 32 bits
    u32_t dp_volt:13;           ///< DP ADC current value
    u32_t dp_volt_pre:13;       ///< DP ADC previous value
    u32_t state_pre:5;          ///< QC runtime previous state
    u32_t src_v3_int_mode:1;    ///< if support interrupt mode, please set to 1

    // 32 bits
    u32_t vbus_volt:16;         ///< vbus current value
    u32_t vbus_volt_pre:16;     ///< vbus previous value
    //32 bits
    u32_t ibus_current:16;      ///< ibus current value
    u32_t ibus_current_pre:16;  ///< ibus previous value
    //32 bits
    u32_t dm_gpio_pin:5;
    u32_t dp_gpio_pin:5;
    u32_t dm_gpio_pin_val:1;
    u32_t dp_gpio_pin_val:1;
    u32_t dp_toggle_cnt:8;
    u32_t qc_v3_disabled:1;
    u32_t reserved2:11;

    u32_t vooc_not_supported:1; ///< VOOC is not supported by partner
    u32_t vooc_initialized:1;   ///< VOOC protocol is initialized
    u32_t vooc_state:4;         ///< VOOC state
    u32_t vooc_state_pre:4;     ///< VOOC previous state
    u32_t vooc_fast:1;          ///< VOOC fast charge flag
    u32_t vooc_impedance:9;     ///< VOOC circult impedance (mOh)
    u32_t vooc_vbus_fb_flg:2;   ///< VOOC device: vbus feedback flag, 3:OK,2:High,1:Low,0:Error
    u32_t vooc_vbus_reduce_req:1;///< VOOC device: request to check vbus
    u32_t vooc_vbus_check_req2:1;///< VOOC device: request to check vbus
    u32_t reserved3:8;
    u32_t vooc_timer_tick;
    //32 bits
    u32_t vooc_vbus_check_req:1;///< VOOC device: request to check vbus
    u32_t vooc_max_curr:15;     ///< VOOC device: max current (mA)
    u32_t vooc_vbat_chg_flg:1;  ///< VOOC device: battery charging flag
    u32_t vooc_vbat:15;         ///< VOOC device: battery voltage (mV)
    // 64 bits
    sys_tick_t vooc_state_entered_time;

    // 64 bits
    sys_tick_t state_entered_time;

    // 32 bits
    drv_timer_t dpdm_mode_timer;
    //32bits
    drv_timer_t scp_rx_msg_timer;
    // 32 bits
    /** Get voltage callback, type: dm = 0, dp = 1, vbus = 2 */
    u32_t (*volt_get)(BC_QC_VOLT_INTF_TYPE_t type);
    /*get current callback*/
    u32_t (*current_get)(BC_QC_VOLT_INTF_TYPE_t type);

    // 32 bits
    /** Get vbus voltage callback */
    bool_t (*vbus_set)(u32_t volt);

    // 32 bits
    /** BC1.2 connected callback */
    void (*src_bc_connected)(void);

    // 32 bits
    /** QC dp dm mode, Set mode callback */
    void (*src_dpdm_mode_set)(BC_SRC_DPDM_MODE_t mode);

    // 32 bits
    /** QC dp dm mode, Set mode callback */
    void (*snk_dpdm_mode_set)(BC_QC_SNK_DPDM_MODE_t dp, BC_QC_SNK_DPDM_MODE_t dm);
    //hw scp flag 32bit
    u32_t scp_state:5;
    u32_t scp_rx_state:5;
    u32_t scp_exit_state :1;
    u32_t scp_msg_byte_num :5;
    u32_t scp_tx_lenth:5;
    u32_t scp_tx_err_cnt:3;
    u32_t scp_rx_err_cnt:3;
    u32_t scp_not_support:1;
    u32_t scp_rxdata_lenth:4;
    //u32_t
    u32_t scp_b_volt_set_en:1;
    u32_t scp_b_curr_set_en:1;
    u32_t scp_b_volt_setted:1;
    u32_t scp_b_rx_setting_volt:1;
    u32_t scp_b_current_setted :1;
    u32_t scp_b_curr:16;
    u32_t reserved4:11;
    //u32_t
    u32_t scp_b_volt_boundary:16;
    u32_t scp_b_curr_boundary:16;
    //32_t
    u32_t scp_b_volt_setting:16;
    u32_t scp_b_volt_setting_pre:16;
    // 64 bits
    sys_tick_t scp_state_entered_time;
} BC_QC_INFO_t;

#pragma pack()

#define bc_qc_state_get(ptr) \
    (((BC_QC_INFO_t *)(ptr))->state)

#define bc_qc_state_set(ptr,v) \
    do { \
        ((BC_QC_INFO_t *)(ptr))->state = v; \
    } while(0)


#define bc_qc_io_init(ptr) \
    do { \
        if (((BC_QC_INFO_t *)(ptr))->snk_dpdm_mode_set) { \
            ((BC_QC_INFO_t *)(ptr))->snk_dpdm_mode_set(BC_QC_SNK_DPDM_MODE_INPUT, BC_QC_SNK_DPDM_MODE_INPUT); \
        } \
    } while(0)

#define bc_qc_snk_io_init(ptr) \
    do { \
        if (((BC_QC_INFO_t *)(ptr))->snk_dpdm_mode_set) { \
            ((BC_QC_INFO_t *)(ptr))->snk_dpdm_mode_set(BC_QC_SNK_DPDM_MODE_LOAD_0P325V, BC_QC_SNK_DPDM_MODE_INPUT); \
        } \
    } while(0)


bool_t bc_qc_enable_get(volatile BC_QC_INFO_t *p_info);
void bc_qc_enable_set(volatile BC_QC_INFO_t *p_info, bool_t on, bool_t snk);
void bc_qc_state_init(volatile BC_QC_INFO_t *p_info, bool_t snk);
void bc_qc_state_machine(volatile BC_QC_INFO_t *p_info);


#endif /* #ifndef BC_QC_H */

