/**
 * \file    sys_pd_hook.h
 * \brief   
 * 
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-08-31
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-08-31  Original Creation
 * 
 */
 
#ifndef __SYS_PD_HOOK_H_
#define __SYS_PD_HOOK_H_

#include "sys_defs.h"
#include "sys_gpio.h"
#include "prl_msg_defs.h"
#include "usbpd.h"
#include "drivers.h"
#include "sys_reg.h"

#pragma pack(1)

/** USB-A IBAT no current flow threshold, unit mA */
#define SYS_USBA_IBUS_NO_CURRENT_FLOW_THR       (50U)
#define SYS_USBA_IBUS_HAS_CURRENT_FLOW_THR      (120U)
#define SYS_USBA_VBUS_HAS_CURRENT_FLOW_THR      (6800U)
#define SYS_USBA_VBUS_HAS_CURRENT_FLOW_THR_2    (7800U)
#define UARt1_disable_set     1

#define SYS_USBA_IBUS_ACCUM_VAL_IDX_MAX         (8U)
/** System USB-A connection timeout value, unit is 100 ms */
#define SYS_USBA_CONNECTION_TIMEOUT             (300U)
//#define SYS_USBA_CONNECTION_TIMEOUT             (300U)

#define SYS_USBA_MAX_POWER                      (25000000UL)

#define SYS_HPD_IRQ_DETECT_DURATION_MIN         (500UL)      /* 500us, system tick */
#define SYS_HPD_IRQ_DETECT_DURATION_MAX         (2000UL)     /* 2ms, system tick */
#define SYS_HPD_HOT_INSERT_DETECT_DURATION_MAX   (5000UL)     /* 5ms, system tick */

/** System continuous timer timeout value, unit is millisecond */
#define SYS_CONTINUOUS_TIMER_TIMEOUT            (100U)

typedef enum SYS_PD_LED_STATE_e
{
    SYS_PD_LED_STATE_OFF,
    SYS_PD_LED_STATE_ON,
    SYS_PD_LED_STATE_FLASH,
    SYS_PD_LED_STATE_FLASH_FAST,
    SYS_PD_LED_STATE_FLASH_INVALID
} SYS_PD_LED_STATE_t;
typedef enum SYS_C_INSERT_STATE_e
{
    SYS_INSERT_STATE_OFF,
    SYS_C1_FST_INSERT,
    SYS_C2_FST_INSERT,
    SYS_INSERT_STATE_IDLE
} SYS_C_INSERT_STATE_t;
typedef enum SYS_CHARGE_MODE_e
{
    SYS_CHARGE_IDLE,
    SYS_C1_CHARGE_MODE,
    SYS_C1_C2_CHARGE_MODE,
    SYS_CHARGE_MODE_INVALID
} SYS_CHARGE_MODE_t;
typedef enum SYS_DP_PIN_OUT_ASS_e
{
    SYS_DP_ASS_NOT,
    SYS_DP_ASS_A = 0X01,
    SYS_DP_ASS_B = 0X02,
    SYS_DP_ASS_C = 0X04,
    SYS_DP_ASS_D = 0X08,
    SYS_DP_ASS_E = 0X10,
    SYS_DP_ASS_F = 0X20,
    SYS_DP_ASS_INVALID
} SYS_DP_PIN_OUT_ASS_T;

typedef struct SYS_PD_INFO_s
{
    sys_tick_t current_time;
    drv_timer_t continuous_timer;
    drv_timer_t led_breathing_timer;
    u32_t continuous_timer_tick;
    u32_t attention_start_tick;
    sys_tick_t hpd_detect_start_time;

    sys_tick_t aux_en_time;

    u32_t vbus_current:16;
    u32_t ibus_current:16;

    u32_t c1_disconnet_tick;

    UPD_EXT_MSG_GET_MFR_INFO_t rx_get_mfr_info;

    u32_t pd_disc_ident_req:1;
    u32_t pd_partner_soft_reset_req:1;
    u32_t pd_power_nego_completed:1;
    u32_t vbus_source_en:1;
    u32_t sys_initializing:1;
    u32_t led_state:4;
    u32_t led_display_flash_interval:5;
    u32_t display_state:1;
    u32_t invalid_bat_sta_ref:1;
    u32_t invalid_bat_cap_ref:1;
#if SYS_SMG_DISPLAY_ENABLED  /* modified by James Gan - 2019-07-08 */
    u32_t digit_display_mode:4;
    u32_t digit_display_next_mode:4;
    u32_t reserved1:7;
#else
    u32_t ufp_tx_attention_msg_cnt:3;
    u32_t dp_mode_flg:1;
    u32_t hpd_last_state:1;
    u32_t hpd_state:1;
    u32_t hpd_irq_cnt:3;
    u32_t dr_swap_cnt:3;
    u32_t reserved1:3;
#endif /* #if SYS_SMG_DISPLAY_ENABLED */

    u32_t rated_vbus:16,
          rated_ibus:16;

    u32_t c2_power_profile:8,
          c2_operating_power_profile:8,
          c2_pe_state:8,
          c2_reserved:8;

    u32_t c2_rated_vbus:16,
          c2_rated_ibus:16;

    u32_t c2_vbus_val:16,
          c2_ibus_val:16;

    SYS_TYPE_C_STATUS_0_REG_t c2_sta;
    SYS_TYPE_C_STATUS_0_REG_t c2_sta_prev;
    SYS_PD_STATUS_REG_t c2_pd_sta;
    SYS_PD_STATUS_REG_t c2_pd_sta_prev;
    SYS_CONTROL_0_REG_t c2_sta2;
    SYS_CONTROL_0_REG_t c2_sta2_prev;
    u32_t c2_conn_changed_tick;
    u32_t c1_conn_changed_tick;

    UPD_DATA_MSG_SOURCE_CAP_t c2_cap;
    u32_t c2_req_vbus:16,
          c2_req_ibus:16;

    u32_t led_on_start_tick;

    u32_t rx_pkt_cnt;

    u32_t tx_pkt_cnt;

    u32_t c1_current_pwr:16;
    u32_t c2_current_pwr:16;
    //u32_t
    u32_t upd1_real_pwr:8;
    u32_t upd2_real_pwr:8;
    u32_t upd2_rate_pwr:8;
    u32_t upd1_rate_pwr:8;

    u32_t current_charging_pwr;
    u32_t usba_pwr;

    // 32 bits
    u32_t usba_ibus_accum_val:24;
    u32_t usba_ibus_accum_val_idx:8;

    // 32 bits
    u32_t usba_vbus_val:16,
          usba2_vbus_val:16;
    
    // 32 bits
    u32_t usba_ibus_avg_val:16;
    u32_t usba_no_current_flow_flag:1;
    u32_t usba_no_current_flow_last_flag:1;
    u32_t usba1_power_on_flag:1;
    u32_t usba1_qc_en_flag:1;
    u32_t usba1_indet_flag:1;
    u32_t usba1_indet_current_flag:1;
    u32_t usba1_indet_pre_flag:1;
    u32_t usba2_power_on_flag:1;
    u32_t usba2_qc_en_flag:1;
    u32_t usba2_indet_flag:1;
    u32_t usba2_indet_current_flag:1;
    u32_t usba2_indet_pre_flag:1;
    u32_t usba_ocp_flag:1;
    u32_t led_breathing:1;
    u32_t reserved3:2;

    // 32 bits: pd continuous_timer_tick
    u32_t usba1_disconnected_tick;

    // 32 bits: pd continuous_timer_tick
    u32_t usba2_disconnected_tick;

    // 32 bits: pd continuous_timer_tick
    u32_t usba_no_current_start_tick;

    // 32 bits
    u32_t bat_cap_indicator_pre_charge:7;
    u32_t bat_cap_indicator_pre_discharge:7;
    u32_t power_check_current_state:1;
    u32_t power_check_last_state:1;
    u32_t key_down_cnt:2;
    u32_t prevent_auto_poweroff:1;
    u32_t prevent_auto_poweroff_last_state:1;
    u32_t power_down_detect_current_state:1;
    u32_t power_down_detect_last_state:1;
    u32_t cap_low20_charge_dischage_flag:1;
    u32_t c1_c2_insert_state:2;
    u32_t c1_attached_discharge_off_flag:1;
    u32_t cable_detect_done_pre:1;
    u32_t charge_mode:4;
    u32_t attention_req_flg:1;
    //32
    u32_t sys_led_bitmap; 
    // 32 bits: pd continuous_timer_tick
    u32_t double_click_1st_hit_tick;

    // 32 bits: pd continuous_timer_tick
    u32_t low_current_mode_start_tick;

    // 64 bits: system time
    sys_tick_t power_down_detect_start_time;

    // 32 bits: pd continuous_timer_tick
    u32_t auto_power_down_last_tick;

    u32_t p60c_otp_flag:1,
          p60c_otp_pre_flag:1,
          p55c_otp_flag:1,
          p55c_otp_pre_flag:1,
          p45c_otp_flag:1,
          p45c_otp_pre_flag:1,
          p40c_otp_flag:1,
          p40c_otp_pre_flag:1,
          p0c_otp_flag:1,
          p0c_otp_pre_flag:1,
          m10c_otp_flag:1,
          m10c_otp_pre_flag:1,
          m20c_otp_flag:1,
          m20c_otp_pre_flag:1,
          ntc_test_flag:1,
          ntc_volt:16,
          reserved5:1;
    u32_t charging_current_saved:16,
          mst_ver:8,
          ibat_max:8;
          

    SYS_CONTROL_0_REG_t c1_ctrl;
    //SYS_EVENT_0_REG_t event0;
    //SYS_EVENT_1_REG_t event1;
    SYS_POWER_STA_REG_t sys_sta;
    SYS_UPD_STA_REG_t upd1_sta;
    SYS_UPD_STA_REG_t upd2_sta;
    SYS_CONTROL_1_REG_t c1_ctrl1;
    SYS_MCU_CTR_REG_t mcu_ctr;
    UPD_DATA_MSG_VDM_DP_CAPABILITIES_VDO_t ufp_d_cap;
    UPD_DATA_MSG_VDM_DP_STA_VDO_t ufp_d_sta;
    f32_t temp_current;
} SYS_PD_INFO_t;

#pragma pack()

extern volatile SYS_PD_INFO_t g_sys_pd_info;


/** \brief Get LED state
 */
#define sys_pd_led_state_get()      (g_sys_pd_info.led_state)

/** \brief Set LED state
 *
 * \param state     defined by SYS_PD_LED_STATE_t
 */
void sys_pd_led_state_set(SYS_PD_LED_STATE_t state);

#if SYS_USBA_ENABLED  /* modified by James Gan - 2020-04-17 */
/** \brief Get USB-A1 VBUS value
 *
 * \return VBUS value
 */
u32_t sys_usba1_vbus_get();


/** \brief Get USB-A2 VBUS value
 *
 * \return VBUS value
 */
u32_t sys_usba2_vbus_get();

/** \brief Get USB-A IBUS value
 *
 * \return IBUS value
 */
#define sys_usba_ibus_get() drv_adc_ibus_get(SYS_CURRENT_SENCE_SAMPLE_RESISTER)

/** \brief USB-A interface restore
 */
void sys_usba_restore();

/** \brief USB-A initialization
 */
void sys_usba_init();

/** \brief USB-A power over checking
 */
bool_t sys_usba_power_over_check();
#else
#define sys_usba1_vbus_get()            (0)
#define sys_usba2_vbus_get()            (0)
#define sys_usba_ibus_get()             (0)
#define sys_usba_restore()
#define sys_usba_init()
#define sys_usba_power_over_check()     (0)
#endif /* #if SYS_USBA_ENABLED */

/** \brief PD USB-C ibus over current checking
 */
bool_t sys_pd_ibus_over_check();

#if SYS_POWER_POLICY_DISABLED
#define sys_pd_power_policy_process(change_asap)
#else
void sys_pd_power_policy_process(bool_t change_asap);
#endif


/** \brief Configuration channel(CC) hook when in Unattached.SNK
 */
void sys_pd_sink_unattached_hook();

/** \brief CC hook when in AttachWait.SNK
 */
void sys_pd_sink_attachwait_hook();

/** \brief CC hook when in Attached.SNK
 */
void sys_pd_sink_attached_hook();

/** \brief PD hook while sink mode require new power transition
 *
 * \return              see the error code of status_t
 */
status_t sys_pd_sink_transit_to_new_power_hook();

/** \brief CC hook when in Unattached.SRC
 *
 */
void sys_pd_source_unattached_hook();

/** \brief CC hook when in AttachWait.SRC
 *
 */
void sys_pd_source_attachwait_hook();

/** \brief CC hook when in Attached.SRC
 *
 */
void sys_pd_source_attached_hook();

/** \brief PD hook while source require new power transition
 *
 * \param pos           the position of source capabilities
 * \return              see the error code of status_t
 */
status_t sys_pd_source_transit_to_new_power_hook(u32_t pos);

/** \brief CC or PD hook when get PD VBUS source enable status
 *
 * \return              0: disabled, 1: enabled
 */
bool_t sys_pd_vbus_source_en_get(void);

/** \brief CC or PD hook when enable or disable PD VBUS sourcing
 *
 * \param flg           0: disable, 1: enable
 */
void sys_pd_vbus_source_en_set(bool_t flg);

/** \brief CC or PD hook when get PD VBUS source enable discharge
 *
 * \return              0: disabled, 1: enabled
 */
bool_t sys_pd_vbus_discharge_en_get(void);

/** \brief CC or PD hook when enable or disable PD VBUS discharge
 *
 * \param flg           0: disable, 1: enable
 */
void sys_pd_vbus_discharge_en_set(bool_t flg);

/** \brief CC or PD hook when get PD CC1 VCONN source enable status
 *
 * \return              0: disabled, 1: enabled
 */
bool_t sys_pd_cc1_vconn_en_get(void);

/** \brief CC or PD hook when enable or disable PD CC1 VCONN sourcing
 *
 * \param flg           0: disable, 1: enable
 */
void sys_pd_cc1_vconn_en_set(bool_t flg);

/** \brief CC or PD hook when get PD CC2 VCONN source enable status
 *
 * \return              0: disabled, 1: enabled
 */
bool_t sys_pd_cc2_vconn_en_get(void);


/** \brief PD hook when power role swap started
 *
 * \param arg           unused argument
 */
void sys_pd_prs_started_hook(u32_t arg);

/** \brief PD hook when power role swap completed
 *
 * \param arg           unused argument
 */
void sys_pd_prs_completed_hook(u32_t arg);


/** \brief PD hook when data role swap started
 *
 * \param arg           unused argument
 */
void sys_pd_drs_started_hook(u32_t arg);

/** \brief PD hook when data role swap completed
 *
 * \param arg           unused argument
 */
void sys_pd_drs_completed_hook(u32_t arg);


/** \brief PD hook when vconn source swap started
 *
 * \param arg           unused argument
 */
void sys_pd_vcs_started_hook(u32_t arg);

/** \brief PD hook when vconn source swap completed
 *
 * \param arg           unused argument
 */
void sys_pd_vcs_completed_hook(u32_t arg);

/** \brief PD power profile change request hook
 *
 * \param arg           unused argument
 */
void sys_pd_power_change_req_hook(u32_t arg);

/** \brief PD hook when message received
 *
 * \param arg           unused argument
 */
void sys_pd_prl_msg_received_hook(u32_t arg);

/** \brief PD hook when message sent
 *
 * \param arg           unused argument
 */
void sys_pd_prl_msg_sent_hook(u32_t arg);

/** \brief PD task IDLE hook when task is IDLE
 *
 * \param arg           unused argument
 */
void sys_pd_idle_hook(u32_t arg);

/** \brief PD hook when VDM discover identity response ack is received
 *
 * \param arg           unused argument
 */
void sys_pd_vdm_disc_ident_ack_received_hook(u32_t arg);

/** \brief PD hook when received or transmited VDM Attention message
 *
 * \param p_info        Pointer to PD UPD_DATA_MSG_VDM_ATTENTION_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_vdm_attention_hook(UPD_DATA_MSG_VDM_ATTENTION_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited Unstructured VDM message
 *
 * \param p_msg         Pointer to PD message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_vdm_unstructured_hook(u8_t *p_msg, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited alert message
 *
 * \param p_info        Pointer to PD UPD_DATA_MSG_ALERT_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_alert_hook(UPD_DATA_MSG_ALERT_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received get country info message
 *
 * \param p_info        Pointer to PD UPD_DATA_MSG_GET_COUNTRY_INFO_t message
 */
void sys_pd_prl_msg_get_country_info_hook(UPD_DATA_MSG_GET_COUNTRY_INFO_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received battery status message
 *
 * \param p_info        Pointer to PD UPD_DATA_MSG_BATTERY_STATUS_t message
 */
void sys_pd_prl_msg_battery_status_hook(UPD_DATA_MSG_BATTERY_STATUS_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/*  == Extended message hook ==  */

/** \brief PD hook when received or transmited extended source capability message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_SRC_CAP_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_src_cap_hook(UPD_EXT_MSG_SRC_CAP_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended status message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_STATUS_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_status_hook(UPD_EXT_MSG_STATUS_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended get battery capability message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_GET_BAT_CAP_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_get_bat_cap_hook(UPD_EXT_MSG_GET_BAT_CAP_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended get battery status message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_GET_BAT_STATUS_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_get_bat_status_hook(UPD_EXT_MSG_GET_BAT_STATUS_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended battery capability message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_BAT_CAP_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_bat_cap_hook(UPD_EXT_MSG_BAT_CAP_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received or transmited extended get manufacturer information message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_GET_MFR_INFO_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_get_mfr_info_hook(UPD_EXT_MSG_GET_MFR_INFO_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended manufacturer information message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_MFR_INFO_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_mfr_info_hook(UPD_EXT_MSG_MFR_INFO_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received or transmited extended security request message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_SECURITY_REQ_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_secur_req_hook(UPD_EXT_MSG_SECURITY_REQ_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended security response message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_SECURITY_RESP_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_secur_resp_hook(UPD_EXT_MSG_SECURITY_RESP_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received or transmited extended firmware upgrade request message
 *
 * \param p_info        Pointer to PD firmware upgrade request message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_fw_up_req_hook(void *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended firmware upgrade response message
 *
 * \param p_info        Pointer to PD firmware upgrade response message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_fw_up_resp_hook(void *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received or transmited extended PPS status message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_PPS_STATUS_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_pps_status_hook(UPD_EXT_MSG_PPS_STATUS_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received or transmited extended country info message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_COUNTRY_INFO_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_country_info_hook(UPD_EXT_MSG_COUNTRY_INFO_t *p_info, PRL_MSG_DIR_TYPE_t dir);

/** \brief PD hook when received or transmited extended country codes message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_COUNTRY_CODES_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_country_codes_hook(UPD_EXT_MSG_COUNTRY_CODES_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook when received or transmited extended sink capability message
 *
 * \param p_info        Pointer to PD UPD_EXT_MSG_SNK_CAP_t message
 * \param dir           The hook call from receiving or transmiting, 0: rx, 1: tx
 */
void sys_pd_prl_msg_ext_snk_cap_hook(UPD_EXT_MSG_SNK_CAP_t *p_info, PRL_MSG_DIR_TYPE_t dir);


/** \brief PD hook initialization, need to be called in system init
 *
 */
void sys_pd_hook_init();

void sys_upd2_state_check();

void sys_upd_ibat_max_check();

void sys_mcu_ctr_handler();

void sys_power_state_check();

void sys_gpio_hpd_isr(u32_t arg);

#endif /* #ifndef __SYS_PD_HOOK_H_ */

