/*----------------------------------------------------------------
* FileName    : can_rbus.h
* Create Date : 2014-02-17
*
*---------------------------------------------------------------*/
#ifndef __CANRBUS_H__
#define __CANRBUS_H__
#include "stdint.h"
#include "platmacro.h"
#include "comm_hwabs.h"
#include "define_base.h"



/*!!!!!!!!!!!!!!!!!!!Important:参照:canrbus 数据流协议.xlsx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
#define CANRBUS_PROTOCOL_FLOW_VERSION   0X41
/*!!!!!!!!!!!!!!!!!!!!Important:参照:canrbus 协议.xlsx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/


#define CANRBUS_ENDIAN_TYPE LITTLE_ENDIAN_TYPE

#if (CANRBUS_ENDIAN_TYPE != HOST_ENDIAN_TYPE)
#define HOST_TO_CANRBUS_NET_16 LITTLE_TO_BIG_ENDIAN_16
#define HOST_TO_CANRBUS_NET_32 LITTLE_TO_BIG_ENDIAN_32
#define CANRBUS_NET_TO_HOST_16 BIG_TO_LITTLE_ENDIAN_16
#define CANRBUS_NET_TO_HOST_32 BIG_TO_LITTLE_ENDIAN_32
#else
#define HOST_TO_CANRBUS_NET_16(num) (num)
#define HOST_TO_CANRBUS_NET_32(num) (num)
#define CANRBUS_NET_TO_HOST_16(num) (num)
#define CANRBUS_NET_TO_HOST_32(num) (num)
#endif


typedef enum{
    CANRBUS_OBJ_ID_1 ,
    CANRBUS_OBJ_ID_2 ,
    CANRBUS_OBJ_ID_3 ,
    CANRBUS_OBJ_ID_4 ,
    CANRBUS_OBJ_ID_5 ,
    CANRBUS_OBJ_ID_6 ,

    CANRBUS_OBJ_ID_BUTT
}CANRBUS_OBJ_ID_ENUM;


typedef enum{
    CANRBUS_WRITE_REG = 1,
    CANRBUS_WRITE_REG_RESP,
    CANRBUS_READ_REG,
    CANRBUS_READ_REG_RESP,
    CANRBUS_ERROR_RESP,
    CANRBUS_DEBUG,
    CANRBUS_DEBUG_RESP,

    CMD_MODE_BUTT
}CMD_MODE_ENUM;

/***************组网相关start*******/
#define BMS_HW_INF_NULL  0xFF /*没有端口*/
#define BMS_HW_INF_SELF  0xFE /*表示指令已经到达目的地，不需要转发*/

/***************组网相关end*******/
typedef enum
{
	CANRBUS_WRITE_ERROR = 1,
	CANRBUS_READ_ERROR,
	CANRBUS_ERROR_BUTT
} CANRBUS_ERROR_ENUM;
/*common define*/
#define DEBUG_CAN_ID     0x7FF	/*canrbus debug canid*/
#define COM_MODE_ERROR   1
#define REG_ADDR_ERROR   2
#define CMD_CODE_MASK      0x07 /*u16的bit15-13是cmdmode*/
#define CMD_CODE_SHIFT     13
#define CMD_CODE_TAIL      0x1FFF
/*write&read define*/
#define LEVEL_MASK         0x07   /*w&r中的第一个u16的bit12-10是level*/
#define LEVEL_SHIFT        10
#define DEVICE_ID_MASK     0x7F		/*w&r中的第一个u16的bit6-bit0是devid*/
#define DEVICE_ID_SHIFT    0
/*transfer define*/
#define TRANS_FRAME_ID_MASK		0x3F
#define TRANS_FRAME_ID_SHIFT    7

#define CANRBUS_MAX_READ_REG_NUM 216
#define CANRBUS_MAX_REG_NUM_PER_MSG 4

#define GET_CMD_CODE(u16)   (((u16) >> CMD_CODE_SHIFT) & CMD_CODE_MASK)
#define GET_LEVEL(u16)      (((u16) >> LEVEL_SHIFT) & LEVEL_MASK)
#define GET_DEVICE_ID(u16)  (((u16) >> DEVICE_ID_SHIFT) & DEVICE_ID_MASK)
#define GET_RESP_HEADER(devAddr, cmdCode) 	((devAddr & CMD_CODE_TAIL) | (cmdCode << CMD_CODE_SHIFT)) /*devAddr最高3位是cmdCode*/
#define GET_TRANSFER_HEADER(cmdCode, frameId, devId) (uint16_t)((cmdCode << CMD_CODE_SHIFT) | (frameId << TRANS_FRAME_ID_SHIFT) | (devId << DEVICE_ID_SHIFT))
#define GET_TRANSFER_FRAME_ID(u16) (((u16)>>TRANS_FRAME_ID_SHIFT)&TRANS_FRAME_ID_MASK)

/***************************以下为CANRBUS CANID非隧道方式定义*******************************************/
#define CANRBUS_CANID_REGADDR_POS           (0U)
#define CANRBUS_CANID_REGADDR_MASK          (0xffff<<CANRBUS_CANID_REGADDR_POS)
#define CANRBUS_CANID_FUNCODE_POS           (16U)
#define CANRBUS_CANID_FUNCCODE_MASK         (0x07<<CANRBUS_CANID_FUNCODE_POS)
#define CANRBUS_CANID_DSTID_POS             (19U)
#define CANRBUS_CANID_DSTID_MASK            (0x3F<<CANRBUS_CANID_DSTID_POS)
#define CANRBUS_CANID_DSTDEVT_POS           (25U)
#define CANRBUS_CANID_DSTDEVT_MASK          (0x07<<CANRBUS_CANID_DSTDEVT_POS)
#define CANRBUS_CANID_EXTFUNC_POS           (28U)
#define CANRBUS_CANID_EXTFUNC_MASK          (1<<CANRBUS_CANID_EXTFUNC_POS)

#define CANRBUS_CANID_GET_REGADDR(can_id)   ((can_id&CANRBUS_CANID_REGADDR_MASK)>>CANRBUS_CANID_REGADDR_POS)
#define CANRBUS_CANID_GET_FUNCCODE(can_id)  ((can_id&CANRBUS_CANID_FUNCCODE_MASK)>>CANRBUS_CANID_FUNCODE_POS)
#define CANRBUS_CANID_GET_DSTID(can_id)     ((can_id&CANRBUS_CANID_DSTID_MASK)>>CANRBUS_CANID_DSTID_POS)
#define CANRBUS_CANID_GET_WORKID(can_id)   ((can_id&CANRBUS_CANID_FLOW_WORKID_MASK)>>CANRBUS_CANID_FLOW_WORKID_POS)
#define CANRBUS_CANID_GET_DSTDEVT(can_id)   ((can_id&CANRBUS_CANID_DSTDEVT_MASK)>>CANRBUS_CANID_DSTDEVT_POS)
#define CANRBUS_CANID_GET_EXTFUNC(can_id)   ((can_id&CANRBUS_CANID_EXTFUNC_MASK)>>CANRBUS_CANID_EXTFUNC_POS)

#define CANRBUS_CANID_FLOW_BAUID_INVALD           (0x00)
#define CANRBUS_CANID_FLOW_BAUID_BRO              (0x07)
#define CANRBUS_CANID_FLOW_BAUID_POS              (25u)
#define CANRBUS_CANID_FLOW_BAUID_MASK             (0X07<<CANRBUS_CANID_FLOW_BAUID_POS)
#define CANRBUS_CANID_FLOW_GET_BAUID(can_id)      ((can_id & CANRBUS_CANID_FLOW_BAUID_MASK)>>CANRBUS_CANID_FLOW_BAUID_POS)

#define CANRBUS_CANID_FLOW_BCUID_INVALD           (0x00)
#define CANRBUS_CANID_FLOW_BCUID_BRO              (0x3f)
#define CANRBUS_CANID_FLOW_BCUID_POS              (19u)
#define CANRBUS_CANID_FLOW_BCUID_MASK             (0X3f<<CANRBUS_CANID_FLOW_BCUID_POS)
#define CANRBUS_CANID_FLOW_GET_BCUID(can_id)      ((can_id & CANRBUS_CANID_FLOW_BCUID_MASK)>>CANRBUS_CANID_FLOW_BCUID_POS)

#define CANRBUS_CANID_FLOW_BMUID_INVALD           (0x00)
#define CANRBUS_CANID_FLOW_BMUID_BRO              (0x7f)
#define CANRBUS_CANID_FLOW_BMUID_POS              (9u)
#define CANRBUS_CANID_FLOW_BMUID_MASK             (0X7f<<CANRBUS_CANID_FLOW_BMUID_POS)
#define CANRBUS_CANID_FLOW_GET_BMUID(can_id)      ((can_id & CANRBUS_CANID_FLOW_BMUID_MASK)>>CANRBUS_CANID_FLOW_BMUID_POS)


#define CANRBUS_CANID_FLOW_HIER_POS              (6u)
#define CANRBUS_CANID_FLOW_HIER_MASK             (0X01<<CANRBUS_CANID_FLOW_HIER_POS)
#define CANRBUS_CANID_FLOW_GET_HIER_FLAG(can_id) ((can_id & CANRBUS_CANID_FLOW_HIER_MASK)>>CANRBUS_CANID_FLOW_HIER_POS)


#define CANRBUS_CANID_FLOW_WORKID_POS              (7u)
#define CANRBUS_CANID_FLOW_WORKID_MASK             (0X03<<CANRBUS_CANID_FLOW_WORKID_POS)
#define CANRBUS_CANID_FLOW_GET_WORKID(can_id)      ((can_id & CANRBUS_CANID_FLOW_WORKID_MASK)>>CANRBUS_CANID_FLOW_WORKID_POS)

#define CANRBUS_CANID_FLOW_PACKID_POS              (0u)
#define CANRBUS_CANID_FLOW_PACKID_MASK             (0X3f<<CANRBUS_CANID_FLOW_PACKID_POS)
#define CANRBUS_CANID_FLOW_GET_PACKID(can_id)      ((can_id & CANRBUS_CANID_FLOW_PACKID_MASK)>>CANRBUS_CANID_FLOW_PACKID_POS)

#define CANRBUS_CANID_FLOW_IS_CMD(cmdCode)         (cmdCode == CANRBUS_DEBUG)
#define CANRBUS_CANID_FLOW_IS_RESP(cmdCode)        (cmdCode == CANRBUS_DEBUG_RESP)
#define CANRBUS_FLOW_WORKTT_IS_HIERM(canId)       (CANRBUS_CANID_FLOW_GET_HIER_FLAG(canId) > 0)


#define CANRBUS_FLOW_ALL_HIER_PACK_LEN  16*64       /*分级管理的最大的response包数据 16*64*/
#define CANRBUS_FLOW_ONE_HIER_PACK_LEN  16          /*分级管理的最大一个包的数据长度 RESP类型16*/
#define CANRBUS_FLOW_ONE_FRAME_VD_LEN   8           /*分级管理一个CAN包的最大有效帧长度*/

#define CANRBUS_DEBUG_ONE_FRAME_BYTE                8
#define CANRBUS_FLOW_CAL_TRANSFER_CANID(bauId,bcuId,bmuId,cmdCode,packId,workId, isHier) \
    (uint32_t)(((uint32_t)cmdCode << CANRBUS_CANID_FUNCODE_POS) | ((uint32_t)packId << CANRBUS_CANID_FLOW_PACKID_POS) \
                | ((uint32_t)bmuId<<CANRBUS_CANID_FLOW_BMUID_POS)|((uint32_t)bcuId << CANRBUS_CANID_FLOW_BCUID_POS) \
                |((uint32_t)bauId<<CANRBUS_CANID_FLOW_BAUID_POS)|((uint32_t)workId <<CANRBUS_CANID_FLOW_WORKID_POS )| \
                (isHier << CANRBUS_CANID_FLOW_HIER_POS))
typedef enum
{
    CANRBUS_FLOW_WORKTT_UPGRADE = 0,
    CANRBUS_FLOW_WORKTT_UPGRADE_HIERM = 1,
}CANRBUS_FLOW_WORKTT_ENUM;

/***************************结束CANRBUS非隧道方式定义*******************************************/


typedef int32_t (*CANRBUS_PROCESS_FUNC)(uint32_t canbusId,	uint8_t* pData, uint32_t dataLen);
typedef int32_t (*CANRBUS_POST_PROCESS_FUNC)(uint32_t canbusId, uint8_t *pData, uint32_t dataLen);
typedef int32_t (*BMS_DB_WR_FUNC)(uint16_t startAddr, uint8_t *pData, uint16_t *pLength);


typedef struct{
    uint8_t cmdCode;
    uint8_t packFrameId;
    uint8_t *buf;
    uint8_t len;
    uint8_t devId;              /*当前接收的消息的DevId*/
    uint8_t endSonDevId;        /*最后一个设备地址用于在HIER模式下的选择当前作为代表*/
    uint16_t maxVdLenOneFrame;
}CANRBUS_FlowMsg_Packformat_Stru;


typedef struct{
    uint8_t cmdCode;                /*操作指令*/
    uint8_t destLevel;              /*目标设备所处等级*/
    uint8_t isTunnelMode;           /*是否隧道模式*/
    uint8_t inBMUId;                /*消息传入BMUID*/
    uint8_t inBCUId;                /*消息传入BCUID*/
    uint8_t inBAUId;                /*消息传入BAUID*/
    uint8_t style;                  /*CMD_OR_RESP_ENUM*/
    uint8_t outBMUId;               /*消息传出BMUID*/
    uint8_t outBCUId;               /*消息传出BCUID*/
    uint8_t outBAUId;               /*消息传出BAUID*/
    uint8_t workId;                 /*处理事务类型*/
    uint8_t isHierMode;             /*CANID 或者消息流中 是否分层管理方式*/
    uint8_t isHierService;          /*根据下层是否是广播决定当前是否开启分层的服务*/
    uint8_t *frame;                 /*帧内容的指针*/
    uint16_t len;                    /*帧长度*/

    uint8_t isIn40Proto;            /*是否输入为4.0协议框架协议*/
    uint8_t msgType;                /*4.0协议框架中的消息类型*/
}CANRBUS_FlowMsg_Infor_Stru;


int32_t CANRBUS_InterfaceInit(uint8_t canbusId);


/*!
 * @brief       新收入到一条CAN调试信息
 *
 * @param[in]   msg       :打包信息
 * @param[in]   len       :数据长度指针
 * @param[in]   pDstBuf   :数据对象指针
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-7-11     dfs      Create             \n
 *
 */
int32_t CANRBUS_AddOneNewDebugFrame(CANRBUS_FlowMsg_Packformat_Stru *msg, uint8_t **pDstBuf, uint16_t *len);

/*----------------------------------------------------------------------------------------------------
 Discription:CANRBUS初始化
 Param:    @param1:CANRBUS_OBJ_ID_X(1-6)
           @param2:工作类型(CANRBUS_MASTER_OPRATOR, CANRBUS_SLAVE_OPRATOR,CANRBUS_SLAVE_DEBUG_OPRATOR)
           @param3:设备ID
 Return:   0:执行正常 非0:执行错误
*----------------------------------------------------------------------------------------------------*/
/*int32_t CANRBUS_InterfaceInit(CAN_FIFO_INFO* pCanFifo, CANRBUS_OPRATOR_TYPE_ENUM workMode);*/
int32_t CANRBUS_RegPostCallback(uint32_t CanRBusId, uint8_t cmdCode, CANRBUS_POST_PROCESS_FUNC pfCallback);

/*----------------------------------------------------------------------------------------------------
 Discription:CAN消息处理函数
 Param:    @param1:CANRBUS_OBJ_ID_X(1-6)
           @param2:CAN接收的消息
 Return:   0:执行正常 非0:执行错误
*----------------------------------------------------------------------------------------------------*/
int32_t CANRBUS_RxMsgProcess(uint32_t canbusId,CanMsg *pRxMsg);
/*----------------------------------------------------------------------------------------------------
 Discription:使能CanRbus的debug功能
 Param:    @param1:CANRBUS_OBJ_ID_X(1-6)
 Return:   0:执行正常 非0:执行错误
*----------------------------------------------------------------------------------------------------*/
int32_t CANRBUS_EnableDebugFunc(uint8_t canRBusId, uint32_t debugCanId);

/*----------------------------------------------------------------------------------------------------
 Discription:注册DB读写的回调函数
 Param:    @param1:CANRBUS_OBJ_ID_X(1-6)
           @param2:DB的读回调函数
           @param3:DB的写回调函数
 Return:   0:执行正常 非0:执行错误
*----------------------------------------------------------------------------------------------------*/
int32_t CANRBUS_RegDBCmdCallback(uint32_t CanRBusId, BMS_DB_WR_FUNC pfReadCallback, BMS_DB_WR_FUNC pfWriteCallback);


/*!
 * @brief      收到一条分层管理的报文
 *
 * @param[in]   dataLen
 * @param[in]   pData
 * @return
 * @retval      None
 *
 * @par         modify    log
 * Date        Author     Description             \n
 * 2022-7-11     dfs      Create             \n
 * 2022-07-25    dfs      当回复的长度超过 CANRBUS_FLOW_ONE_HIER_PACK_LEN，
                          使用从控/选择最后一个代替全部的Hier响应消息 \n
 */
int32_t CANRBUS_AddOneNewHierDebugFrame(CANRBUS_FlowMsg_Packformat_Stru *msg,uint8_t **pDstBuf, uint16_t *len);

#endif /* __CANRBUS_H__ */


