

#ifndef _IEC104_H
#define _IEC104_H

#include "iec104_conf.h"
#include "iec104_queue.h"
#include "iec104_types.h"

#define IEC104_MAX_BUF_LEN 256

#define IEC104_HEAD 0X68

/*
 * PRIO
 * */
#define IEC104_PRIO_INITLINK  0
#define IEC104_PRIO_CALLALL   1
#define IEC104_PRIO_CALLGROUP 2
#define IEC104_PRIO_CLOCK     3
#define IEC104_PRIO_DELAY     3
#define IEC104_PRIO_PULSE     0
#define IEC104_PRIO_SPON      0

/*
 * Ctrl U Function
 * */
#define IEC104_U_FUNC_STARTDT 0x07 // 0B00000111
#define IEC104_U_FUNC_STOPDT  0x13 // 0B00010011
#define IEC104_U_FUNC_TESTER  0x43 // 0B01000011

#define IEC104_U_FUNC_STARTDT_ACK 0x0b // 0B00001011
#define IEC104_U_FUNC_STOPDT_ACK  0x23 // 0B00100011
#define IEC104_U_FUNC_TESTER_ACK  0x83 // 0B10000011

/*
 * ASDU Type Upload station address
 * */
#define IEC104_ASDU_TYPE_M_DTU_INF_1 180
#define IEC104_INFO_SIGNATURE        0XEB90EB90

/*
 * Info Address
 * */
#define IEC104_DEV_TYPE_HXGF 0X03
#define IEC104_DEV_TYPE_HXTM 0X01

#define IEC104_INFOADDR_VALUE_HXGF 0X004001
#define IEC104_INFOADDR_VALUE_HXTM 0X004201

#define IEC104_INFOADDR_STATE_HXGF 0X000001
#define IEC104_INFOADDR_STATE_HXTM 0X000301

/* base device information */
#define IEC104_INFOADDR_BASE_DEVINFO 0X102001

/*
 * device type
 */
// #define       ENDDEVICE_TYPE_ERR                  0
// #define       ENDDEVICE_TYPE_HXPF                 2
#define ENDDEVICE_TYPE_HXTM 1
#define ENDDEVICE_TYPE_HXGF 3

#define AP_TYPE_BASE_INFO 4

/* COT */
#define AP_COT_BASE_INFO 18

#pragma pack(1)

/*
 *  Iec104 package
 * */
/* Control filed I type */
typedef struct
{

    iec_32u type    : 1;
    iec_32u send_sn : 15;
    iec_32u reserve : 1;
    iec_32u recv_sn : 15;
} iec104_ctrl_i_t, *p_iec104_ctrl_i_t;

/* Control filed S type */
typedef struct
{

    iec_32u type_1  : 1;
    iec_32u type_2  : 1;
    iec_32u reserve : 15;
    iec_32u recv_sn : 15;
} iec104_ctrl_s_t, *p_iec104_ctrl_s_t;

/* Control filed U type */
typedef struct
{

    iec_32u type_1      : 1;
    iec_32u type_2      : 1;
    iec_32u startdt     : 1;
    iec_32u startdt_ack : 1;
    iec_32u stopdt      : 1;
    iec_32u stopdt_ack  : 1;
    iec_32u tester      : 1;
    iec_32u tester_ack  : 1;
    iec_32u reserve     : 24;
} iec104_ctrl_u_t, *p_iec104_ctrl_u_t;

/* Control filed type */
typedef struct
{

    iec_32u type_1  : 1;
    iec_32u type_2  : 1;
    iec_32u reserve : 30;

} iec104_ctrl_type_t, *p_iec104_ctrl_type_t;

/* Control filed type */
typedef struct
{

    iec_32u func    : 8;
    iec_32u reserve : 24;

} iec104_ctrl_func_t, *p_iec104_ctrl_func_t;

typedef union
{

    iec104_ctrl_i_t    i;
    iec104_ctrl_s_t    s;
    iec104_ctrl_u_t    u;
    iec104_ctrl_type_t type;
    iec104_ctrl_func_t func;
} iec104_ctrl_t, *p_iec104_ctrl_t;

typedef struct
{

    iec_8u        head;
    iec_8u        len;
    iec104_ctrl_t ctrl;
    iec_8u        asdu[1];
} iec104_data_t, *p_iec104_data_t;

typedef struct
{

    float Current;
    float Temperature;
} iec10x_dev_a_info_t, *p_iec10x_dev_a_info_t;

#pragma pack()

/*
 * length
 * */
#define IEC104_HEAD_LEN (sizeof(iec104_data_t) - 1)
#define IEC104_ASDU_LEN (sizeof(iec10x_asdu_t) - 1)
#define IEC104_INFO_LEN (sizeof(asdu_info_t) - 1)
#define IEC104_DATA_LEN (IEC104_HEAD_LEN + IEC104_ASDU_LEN + IEC104_INFO_LEN)

enum
{
    IEC104_FLAG_RECV_CLOSED,       /*0*/
    IEC104_FLAG_SEND_CLOSED,       /*1*/
    IEC104_FLAG_CLOSED,            /*2*/
    IEC104_FLAG_LINK_INIT,         /*3*/
    IEC104_FLAG_IDLE,              /*4*/
    IEC104_FLAG_UPLOAD_ADDR,       /*5*/
    IEC104_FLAG_START_LINK,        /*6*/
    IEC104_FLAG_REQ_LINK,          /*7*/
    IEC104_FLAG_RESET_REMOTE_LINK, /*8*/
    IEC104_FLAG_INIT_FIN,          /*9*/
    IEC104_FLAG_CALL_ALLDATA,      /*10*/
    IEC101_FLAG_CALL_GROURPDATA,   /*11*/
    IEC104_FLAG_CALL_ACT_FIN,      /*12*/
    IEC104_FLAG_CALL_SIG_TOTAL,    /*13*/
    IEC104_FLAG_CALL_DET_TOTAL,    /*14*/
    IEC104_FLAG_CLOCK_SYS,         /*15*/
    IEC104_FLAG_TESTER,            /*16*/
    IEC104_FLAG_TESTER_STOP,       /*17*/
    IEC104_FLAG_CALL_GROUP,        /*18*/
    IEC104_FLAG_CONNECT_SUCESS,    /*19*/
    IEC104_FLAG_S_ACK,             /*20*/
};

/*
*********************************************************************************************************
*                          EXTERN  VARIABLE
*********************************************************************************************************
*/
extern iec_8u IEC104_STATE_FLAG_INIT;
extern iec_8u IEC104_STATE_FLAG_CALLALL;
extern iec_8u IEC104_STATE_FLAG_GROUP;
extern iec_8u IEC104_STATE_FLAG_CLOCK;
extern iec_8u IEC104_STATE_FLAG_PULSE;

/*
*********************************************************************************************************
*                          FUNCTION
*********************************************************************************************************
*/
iec_8u iec104_state_machine(void);
iec_8u iec104_build_signal_spon(iec_8u TimeFlag, iec_8u signalV, iec_16u addrV);
iec_8u iec104_build_detect_f_spont(iec_8u TimeFlag, float detectV, iec_16u addrV);
void   iec104_receive(iec_8u *buf, iec_16u len);
iec_8u iec104_build_detect_spont(iec_8u TimeFlag, PIEC10X_DETECT_T detectV, iec_16u addrV);

#endif
