/**
 * \file    prl_msg_parser.h
 * \brief   Protocol message parser for PD 2.0
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-07-26
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-07-26  Original Creation
 * 
 */
 
#ifndef __PRL_MSG_PARSER_H_
#define __PRL_MSG_PARSER_H_


#include "types.h"
#include "reg_def_pd.h"
#include "drv_reg_intf.h"


#pragma pack(1)

/** MAX data object number of USB PD R2.0 
 */
#define MAX_DATA_OBJECT_NUM        13

/** USB PD R2.0 message buffer size
 */
#define UPD20_BUF_LEN              30

/** USB PD R3.0 message buffer size
 */
#define UPD30_BUF_LEN              268


/** USB PD message buffer size, include one packet of USB PD R3.0,
 *  9 packets of USB PD R2.0
 */
#define UPD_SMALL_BUF_LEN          64//40

/** USB PD message buffer size, include one packet of USB PD R3.0,
 *  16+1 packets of UPD_SMALL_BUF_LEN
 */
#define UPD_BUF_LEN                640

/** USB PD maximal retry number
 */
#define UPD_MSG_RETRY_MAX          2
#define UPD_MSG_RETRY_R20_MAX      3


/** \name  Local USB PD message type definitions
 * \{ 
 */
typedef enum PRL_MSG_LOCAL_TYPE_e
{
    RESERVED_MSG,
    ///< Control Message
    GOOD_CRC_MSG,
    GOTO_MIN_MSG,
    ACCEPT_MSG,
    REJECT_MSG,
    PING_MSG,
    PS_RDY_MSG,
    GET_SRC_CAP_MSG,
    GET_SNK_CAP_MSG,
    DR_SWP_MSG,
    PR_SWP_MSG,
    VCON_SWP_MSG,
    WAIT_MSG,
    SOFT_RST_MSG,
    NOT_SUPPORTED_MSG,
    GET_SRC_CAP_EXT_MSG,
    GET_STATUS_MSG,
    FR_SWAP_MSG,
    GET_PPS_STATUS_MSG,
    GET_CTRY_CODES_MSG,
    GET_SNK_CAP_EXT_MSG,

    ///< Data Message
    SRC_CAP_MSG,
    SNK_CAP_MSG,
    REQUEST_MSG,
    BIST_RECEIVE_MODE_MSG,
    BIST_TRANSMIT_MODE_MSG,
    BIST_CARRIER_MODE2_MSG,
    BIST_TEST_DATA,
    BATTERY_STATUS_MSG,
    ALERT_MSG,
    GET_CTRY_INFO_MSG,
    ENTER_USB,
    EPR_REQUEST,
    EPR_MODE,
    SOURCE_INFO,
    REVISION,
    
    ///< VDM message
    VDM_DISC_IDENT_CMD_MSG,
    VDM_DISC_IDENT_ACK_CMD_MSG,
    VDM_DISC_IDENT_NAK_CMD_MSG,
    VDM_DISC_IDENT_BUSY_CMD_MSG,

    VDM_DISC_SVID_CMD_MSG,
    VDM_DISC_SVID_ACK_CMD_MSG,
    VDM_DISC_SVID_NAK_CMD_MSG,
    VDM_DISC_SVID_BUSY_CMD_MSG,

    VDM_DISC_MODE_CMD_MSG,
    VDM_DISC_MODE_ACK_CMD_MSG,
    VDM_DISC_MODE_NAK_CMD_MSG,
    VDM_DISC_MODE_BUSY_CMD_MSG,

    VDM_ENTER_MODE_CMD_MSG,
    VDM_ENTER_MODE_ACK_CMD_MSG,
    VDM_ENTER_MODE_NAK_CMD_MSG,
    VDM_ENTER_MODE_BUSY_CMD_MSG,

    VDM_EXIT_MODE_CMD_MSG,
    VDM_EXIT_MODE_ACK_CMD_MSG,
    VDM_EXIT_MODE_NAK_CMD_MSG,
    VDM_EXIT_MODE_BUSY_CMD_MSG,

    VDM_ATTENTION_CMD_MSG,
    VDM_UNSTRUCTURED_MSG,
    
    VDM_SVID_SPECIFIC1_ACK_CMD_MSG,
    VDM_SVID_SPECIFIC1_NACK_CMD_MSG,
    VDM_SVID_SPECIFIC1_BUSY_CMD_MSG,
    VDM_SVID_SPECIFIC1_CMD_MSG,

    VDM_SVID_SPECIFIC_ACK_CMD_MSG,
    VDM_SVID_SPECIFIC_NACK_CMD_MSG,
    VDM_SVID_SPECIFIC_BUSY_CMD_MSG,
    VDM_SVID_SPECIFIC_CMD_MSG,

    EXT_MSG_SRC_CAP,
    EXT_MSG_STATUS,
    EXT_MSG_GET_BAT_CAP,
    EXT_MSG_GET_BAT_STATUS,
    EXT_MSG_BAT_CAP,
    EXT_MSG_GET_MFR_INFO,
    EXT_MSG_MFR_INFO,
    EXT_MSG_SECUR_REQ,
    EXT_MSG_SECUR_RESP,
    EXT_MSG_FW_UP_REQ,
    EXT_MSG_FW_UP_RESP,
    EXT_MSG_PPS_STATUS,
    EXT_MSG_COUNTRY_INFO,
    EXT_MSG_COUNTRY_CODES,
    EXT_MSG_SNK_CAP,
    EXT_MSG_EX_CONTROL,
    EXT_MSG_EPR_SRC_CAP,
    EXT_MSG_EPR_SNK_CAP,
    EXT_MSG_VENDOR_DEFINED_EX,
    MSG_TYPE_MAX
} PRL_MSG_LOCAL_TYPE_t;
/** \} */

typedef enum PRL_MSG_DIR_TYPE_e
{
    PRL_MSG_DIR_RX,
    PRL_MSG_DIR_TX,
    PRL_MSG_DIR_MAX
} PRL_MSG_DIR_TYPE_t;


/** USB PD transmit message descriptor definition
 */
typedef struct prl_msg_tx_desc_s
{
    union {
        struct {
#if __LITTLE_ENDIAN__
            u32_t len:9;
            u32_t sop:3;
            u32_t num:1;
            u32_t reserved:19;
#else
            u32_t reserved:19;
            u32_t num:1;
            u32_t sop:3;
            u32_t len:9;
#endif
        } desc;
        u32_t u32;
    } u;
} prl_msg_tx_desc_t;

/** USB PD receive message descriptor definition
 */
typedef struct prl_msg_rx_desc_s
{
    union {
        struct {
#if __LITTLE_ENDIAN__
            u32_t len:9;
            u32_t sop:3;
            u32_t num:5;
            u32_t reserved:15;
#else
            u32_t reserved:15;
            u32_t num:5;
            u32_t sop:3;
            u32_t len:9;
#endif
        } desc;
        u32_t u32;
    } u;
} prl_msg_rx_desc_t;

#pragma pack()

/** USB PD rx message buffer
 */
extern volatile u8_t rx_data[UPD_SMALL_BUF_LEN];
extern volatile u8_t rx_chunk_data[UPD_SMALL_BUF_LEN];

/** USB PD rx message buffer read pointer
 */
extern volatile u32_t rx_dma_rptr;

/** USB PD tx message buffer
 */
extern volatile u8_t tx_data[UPD_SMALL_BUF_LEN];

extern volatile u8_t tx_chunk_data[UPD_SMALL_BUF_LEN];

/** \brief Protocol message parser initialization
 *
 */
void prl_msg_parser_init();

/** \brief Protocol receive message for capture mode
 */
void prl_msg_capture_rx();

/** \brief Protocol receive message
 */
void prl_msg_rx();

/** \brief Protocol transmit message
 *
 * \param tx_msg_type       local USB PD message type
 * \param tx_sop_type       message SOP type
 */
void prl_msg_tx(u32_t tx_msg_type, u32_t tx_sop_type);

/** Set DMA tx message buffer start address
 */
#define prl_msg_tx_dma_start_addr_set(v) DRV_REG_SET(DMA_BUFF_REG1,(v))

/** Get DMA tx message buffer start address
 */
#define prl_msg_tx_dma_start_addr_get()  DRV_REG_GET(DMA_BUFF_REG1)

/** Set DMA tx message buffer end address
 */
#define prl_msg_tx_dma_end_addr_set(v)  DRV_REG_SET(DMA_BUFF_REG2,(v))

/** Get DMA tx message buffer end address
 */
#define prl_msg_tx_dma_end_addr_get()   DRV_REG_GET(DMA_BUFF_REG2)


/** Set DMA rx message buffer start address
 */
#define prl_msg_rx_dma_start_addr_set(v) DRV_REG_SET(DMA_BUFF_REG5,(v))

/** Get DMA rx message buffer start address
 */
#define prl_msg_rx_dma_start_addr_get()  DRV_REG_GET(DMA_BUFF_REG5)

/** Set DMA rx message buffer end address
 */
#define prl_msg_rx_dma_end_addr_set(v)  DRV_REG_SET(DMA_BUFF_REG6,(v))

/** Get DMA rx message buffer end address
 */
#define prl_msg_rx_dma_end_addr_get()   DRV_REG_GET(DMA_BUFF_REG6)


/** \brief Get transmitting message buffer write pointer, maintained by software
 *
 * \return Transmitting message buffer write pointer
 */
#define prl_msg_tx_wptr_get()       ((u32_t)&tx_data[0])

/** Get transmitting message buffer read pointer, maintained by hardware
 */
#define prl_msg_tx_rptr_get()       DRV_REG_GET(DMA_BUFF_REG3)

/** Get receiving message buffer write pointer, maintained by hardware
 */
#define prl_msg_rx_wptr_get()       DRV_REG_GET(DMA_BUFF_REG7)

/** \brief Get receiving message buffer read pointer, maintained by software
 *
 * \return Receiving message buffer read pointer
 */
#define prl_msg_rx_rptr_get()       (rx_dma_rptr)

/** \brief Get receiving message buffer read pointer, maintained by software
 *
 * \return Receiving message buffer read pointer
 */
#define prl_msg_rx_rptr_set(v)       (rx_dma_rptr=v)

/** Get transmitting message buffer descripter
 */
#define prl_msg_tx_desc_get()       DRV_REG_GET(DMA_BUFF_REG0)

/** Set transmitting message buffer descripter
 */
#define prl_msg_tx_desc_set(v) \
    do { \
        DRV_REG_SET(DMA_BUFF_REG0,(v)); \
        usbpd_event_hook(prl_msg_sent,0); \
    } while(0)
    

/** Get receiving message buffer descripter
 */
#define prl_msg_rx_desc_get()       DRV_REG_GET(DMA_BUFF_REG4)

/** Set receiving message buffer descripter
 */
#define prl_msg_rx_desc_set(v)      DRV_REG_SET(DMA_BUFF_REG4,(v))

/** Get receiving message head
 */
#define prl_msg_rx_head_get()       ((volatile UPD_MSG_HEAD_t *)&rx_data[0])

/** Get transmitting message head
 */
#define prl_msg_tx_head_get()       ((volatile UPD_MSG_HEAD_t *)&tx_data[0])

/** Get receiving extended message head
 */
#define prl_msg_rx_ext_head_get()   ((volatile UPD_MSG_EXT_HEAD_t *)&rx_data[UPD_MSG_HEAD_LEN])

/** Get receiving extended message payload
 */
#define prl_msg_rx_ext_data_get()   (&rx_data[UPD_MSG_HEAD_LEN+UPD_MSG_EXT_HEAD_LEN])


/** \brief Copy DMA data buffer to local memory
 */
void prl_msg_rx_dma_copy();

void prl_tx_chunk_req(u32_t tx_msg_type,u32_t tx_sop_type,u32_t num);

void prl_msg_chunk_rx();

void prl_tx_chunk_msg();

#endif /* #ifndef __PRL_MSG_PARSER_H_ */

