/******************************************************************************
文 件 名:DoCAN_ISO15765.h
功能描述:ISO 15765 规范规定的诊断服务函数头文件
作    者:张暄
版    本:V1.0
日    期:2016.7.18
******************************************************************************/

/******************************************************************************
                         诊断服务的OSI模型映射
===============================================================================
  *     NO.     OSI Layer        Diagnostics services
-------------------------------------------------------------------------------
         7      Application      ISO 14229-1 ISO 14229-3
         6      Presentation     -
         5      Session          ISO 14229-2
  *      4      Transport        ISO 15765-2
  *      3      Network          ISO 15765-2
         2      Data Link        ISO 11898
         1      Physical         ISO 11898
===============================================================================
******************************************************************************/

#ifndef _DOCAN_ISO15765_H_
#define _DOCAN_ISO15765_H_

#include "stdint.h"
#include "UDS_ISO14229_Server.h"
#include "DoCAN_ISO15765_Config.h"

/*-----------------------------------------------------------------------------
Transfer_Status
-----------------------------------------------------------------------------*/
#ifndef COMPLETE
    #define COMPLETE 0x00
#endif

#ifndef NOT_COMPLETE
    #define NOT_COMPLETE (! COMPLETE)
#endif

/*-----------------------------------------------------------------------------
N_PDU 名称
-----------------------------------------------------------------------------*/
#define SINGLE_FRAME      0x00
#define FIRST_FRAME       0x01
#define CONSECUTIVE_FRAME 0x02
#define FLOW_CONTROL      0x03

/*-----------------------------------------------------------------------------
流控帧类型
-----------------------------------------------------------------------------*/
#define FC_FS_CTS  0x00
#define FC_FS_WAIT 0x01
#define FC_FS_OVFL 0x02

/*-----------------------------------------------------------------------------
时序参数名称
-----------------------------------------------------------------------------*/
#define TIMING_PARA_NONE 0X00
#define TIMING_PARA_N_As 0X01
#define TIMING_PARA_N_Ar 0X02
#define TIMING_PARA_N_Bs 0X03
#define TIMING_PARA_N_Br 0X04
#define TIMING_PARA_N_Cs 0X05
#define TIMING_PARA_N_Cr 0X06

/*-----------------------------------------------------------------------------
STmin计时状态
-----------------------------------------------------------------------------*/
#define STmin_TIMER_IDLE 0X00    // STmin定时器空闲
#define STmin_TIME_UP    0X01    // STmin定时时间到
#define STmin_TIMING     0X02    // STmin定时器计时中

/*-----------------------------------------------------------------------------
传输层收发控制
-----------------------------------------------------------------------------*/
#define TP_DIR_MASK 0x80    // 收发标志位
#define TP_RX       0x00    // 传输层接收状态
#define TP_TX       0x80    // 传输层发送状态

#define TP_IDLE 0x00    // Rx:空闲状态
// Tx:空闲状态
#define TP_ERR 0x01    // Rx:接收系统错误
// Tx:发送系统错误

#define TP_RX_INIT 0x10    // Rx:已接收到首帧,初始化多帧接收
#define TP_TX_INIT 0x90    // Tx:发送初始化完成,正在发送首帧或单帧(注意单帧也使用此标志)
#define TP_RX_CTS  0x11    // Rx:接收机允许发送机发送连续帧(Clear To Send)
#define TP_TX_CTS  0x91    // Tx:发送机被许可发送连续帧(Clear To Send)

#define TP_RX_RTS  0x20    // Rx:请求继续发送多帧(Request To Send)
#define TP_TX_RTS  0xA0    // Tx:等待接收机许可多帧发送(Request To Send)
#define TP_RX_WAIT 0x21    // Rx:请求发送机暂停发送
#define TP_TX_WAIT 0xA1    // Tx:接收机请求等待
#define TP_RX_OVFL 0x22    // Rx:接收机接收溢出
#define TP_TX_OVFL 0xA2    // Tx:接收机接收溢出

/******************************************************************************
结构体声明
******************************************************************************/

/*** 链路层数据帧结构 ***/
typedef struct
{
    uint16_t Identifier;    // 帧ID
    uint8_t  Data [ 8 ];    // 帧数据
    uint8_t  DLC;           // 帧长度
} LinkDataStruct;

/*** 链路层接收FIFO结构 ***/
typedef struct
{
    LinkDataStruct LinkData [ LINK_RX_FIFO_MAX_DEPTH ];
    uint8_t        Depth;    // FIFO深度
    uint8_t        IPtr;     // 输入指针
    uint8_t        OPtr;     // 输出指针
} LinkRxFIFOStruct;

/*** 链路层发送控制结构 ***/
typedef struct
{
    uint16_t Identifier;    // 帧ID
    uint8_t  Data [ 8 ];    // 帧数据
    uint8_t  Busy;          // 发送器忙标志
} LinkTxCtrlStruct;

/*---------------------------------------------------------------------------*/

/*** 传输层数据帧结构 ***/
typedef struct
{
    uint16_t Identifier;
    uint8_t  Data [ 8 ];
    uint8_t  DLC;
    uint8_t  New;
} TP_Data_Struct;

/*** 通用N_PCI解析结构 ***/
typedef struct
{
    uint8_t Rsvd : 4;
    uint8_t Type : 4;
} TP_N_PCI_Struct;

/*** 通用N_PDU解析结构 ***/
typedef struct
{
    uint16_t        N_TAtype;
    TP_N_PCI_Struct N_PCI;
    uint8_t         N_Data [ 7 ];
    uint8_t         DLC;
    uint8_t         New;
} TP_N_PDU_Struct;

/*** 单帧N_PCI解析结构 ***/
typedef struct
{
    uint8_t SF_DL : 4;
    uint8_t Type  : 4;
} TP_SF_N_PCI_Struct;

/*** 单帧N_PDU解析结构 ***/
typedef struct
{
    uint16_t           N_TAtype;
    TP_SF_N_PCI_Struct N_PCI;
    uint8_t            N_Data [ 7 ];
    uint8_t            DLC;
    uint8_t            New;
} TP_N_PDU_SF_Struct;

/*** 首帧N_PCI解析结构 ***/
typedef struct
{
    uint8_t  FF_DL_H : 4;
    uint8_t  Type    : 4;
    uint16_t FF_DL_L : 8;
} TP_FF_N_PCI_Struct;

/*** 首帧N_PDU解析结构 ***/
typedef struct
{
    uint16_t           N_TAtype;
    TP_FF_N_PCI_Struct N_PCI;
    uint8_t            N_Data [ 6 ];
    uint8_t            DLC;
    uint8_t            New;
} TP_N_PDU_FF_Struct;

/*** 连续帧N_PCI解析结构 ***/
typedef struct
{
    uint8_t SN   : 4;
    uint8_t Type : 4;
} TP_CF_N_PCI_Struct;

/*** 连续帧N_PDU解析结构 ***/
typedef struct
{
    uint16_t           N_TAtype;
    TP_CF_N_PCI_Struct N_PCI;
    uint8_t            N_Data [ 7 ];
    uint8_t            DLC;
    uint8_t            New;
} TP_N_PDU_CF_Struct;

/*** 流控帧N_PCI解析结构 ***/
typedef struct
{
    uint8_t FS    : 4;
    uint8_t Type  : 4;
    uint8_t BS    : 8;
    uint8_t STmin : 8;
} TP_FC_N_PCI_Struct;

/*** 流控帧N_PDU解析结构 ***/
typedef struct
{
    uint16_t           N_TAtype;
    TP_FC_N_PCI_Struct N_PCI;
    uint8_t            N_Data [ 5 ];
    uint8_t            DLC;
    uint8_t            New;
} TP_N_PDU_FC_Struct;

/*** 传输层数据解析联合体 ***/
typedef union
{
    TP_Data_Struct     Frame;
    TP_N_PDU_Struct    N_PDU;
    TP_N_PDU_SF_Struct N_PDU_SF;
    TP_N_PDU_FF_Struct N_PDU_FF;
    TP_N_PDU_CF_Struct N_PDU_CF;
    TP_N_PDU_FC_Struct N_PDU_FC;
} TransportDataUnion;

/*** 传输层收发控制结构 ***/
typedef struct
{
    uint8_t  Process;        // 当前收发进程
    uint8_t  NonStopMode;    // 不间断收发模式(不再理会后续的FC帧)
    uint16_t Len;            // 已接收到或已发送出的数据长度
    uint16_t TotalLen;       // 数据总长
    uint16_t BlockSize;      // Block总数
    uint16_t BlockCnt;       // 已接收到或已发送出的Block数
    uint8_t  BSMax;          // 当前接收机剩余的最大Block数
    uint8_t  WFTCnt;         //[仅接收用]等待次数计数
    uint8_t  STmin;          //[仅发送用]当前接收机要求的最小间隔时间
} TransportControlStruct;

/*** 时序控制结构 ***/
typedef struct
{
    uint16_t Cnt;            // 滚动计数器
    uint16_t LastCnt;        // 上次更新时的滚动计数器
    uint32_t NTimer;         // 时序定时器,单位:us
    uint32_t STimer;         // 最小间隔时间(STmin)定时器,单位:us
    uint8_t  Type;           // 当前定时器计时参数名称
    uint8_t  STminStatus;    // STmin计时状态
} TransportTimingControlStruct;

/*---------------------------------------------------------------------------*/

/*** 数据收发结果N_Result枚举 ***/
typedef enum
{
    N_OK = 0,
    N_TIMEOUT_A,
    N_TIMEOUT_Bs,
    N_TIMEOUT_Cr,
    N_WRONG_SN,
    N_INVALID_FS,
    N_UNEXP_PDU,
    N_WFT_OVRN,
    N_BUFFER_OVFLW,
    N_ERROR,
} N_ResultEnum;

/*** 接收用N_USData数据结构 ***/
typedef struct
{
    uint16_t N_TAtype;
    uint16_t Length;
    uint8_t  MsgData [ N_USDATA_RX_BUFFER_SIZE ];
} N_USDataRxStruct;

/*** 发送用N_USData数据结构 ***/
typedef struct
{
    uint16_t N_TAtype;
    uint16_t Length;
    uint8_t  MsgData [ N_USDATA_TX_BUFFER_SIZE ];
} N_USDataTxStruct;

/******************************************************************************
函数声明
******************************************************************************/

/*-- 外部接口函数 -----------------------------------------------------------*/

/*** 后台服务函数 ***/
extern void DoCAN_Communication_Service(void);
extern void DoCAN_Timer_Update(uint16_t Interval);

/*** 网络层上层接口函数 ***/
void DoCAN_N_USData_Request(uint16_t N_TAtype, uint8_t *MessageData, uint16_t Length);
void DoCAN_N_USData_Confirm(uint16_t N_TAtype, N_ResultEnum N_Result);
void DoCAN_N_USData_FF_Indication(uint16_t N_TAtype, uint16_t Length);
void DoCAN_N_USData_Indication(uint16_t N_TAtype, uint8_t *MessageData, uint16_t Length, N_ResultEnum N_Result);

/*** 链路层下层接口函数 ***/
void        DoCAN_L_Data_Request(uint16_t Identifier, uint8_t dlc, uint8_t *Data);
void        DoCAN_L_Data_Confirm(uint16_t Identifier, uint8_t TransferStatus);
extern void DoCAN_L_Data_Indication(uint16_t Identifier, uint32_t dlc, uint8_t *pData);

extern void CAN_LLC_Ch5_Data_Request(uint32_t Identifier, uint16_t idx, uint8_t DLC, uint8_t *Data);

/*-- 内部函数 ---------------------------------------------------------------*/

/*** 传输层协议解析 ***/
void DoCAN_Receive_And_Assemble_N_USData(void);    // 接收主函数
void DoCAN_Get_N_PDU(void);
void DoCAN_Receive_Single_Frame_N_Data(void);
void DoCAN_Receive_First_Frame_N_Data(void);
void DoCAN_Receive_Consecutive_Frame_N_Data(void);
void DoCAN_Receive_Flow_Control(void);
void DoCAN_Transmit_Flow_Control(void);
void DoCAN_Handle_Unknown_N_PDU(void);
void DoCAN_Disassemble_And_Transmit_N_USData(void);    // 发送主函数

/*** 时序管理 ***/
void    DoCAN_Update_Timer(void);
void    DoCAN_Handle_Time_Out(void);
void    DoCAN_Start_Timer(uint8_t TimingParameter);
void    DoCAN_Stop_Timer(void);
void    DoCAN_Start_STmin_Timer(uint8_t STminTime);
uint8_t DoCAN_Get_STmin_Timer_Status(void);

#endif