///******************************************************************
//
// Moudle Name  :   mtn_lib20_ecat.h
// Abstract     :   GaoChuan Motion 2.0 ethercat user header 
// Note :			1.结构体定义中所有的‘reservedxxx’的成员都是保留参数,为保持兼容性,请设置为0
//					  2.无特别说明,所有API返回RTN_CMD_SUCCESS（即0值）表示执行成功,其他则表示错误代码
//					  3.所有的API参数中,无特别说明,axisHandle表示操作轴的句柄,devHandle表示目标控制器的句柄,crdHandle表示目标坐标系组句柄
//            4.mtn_lib20中所有的结构体都是以四字节对齐方式编译，为了避免结构体对齐引起的问题，请将编译环境设置为四字节对齐
// Modification History :
///******************************************************************
#ifndef _H_MTN_LIB20_ECAT_H_
#define _H_MTN_LIB20_ECAT_H_
#include "mtn_lib20.h"

#ifdef __cplusplus
extern "C" {
#endif
 

// 启动Ethercat主站
MTN_API Int16  __stdcall NMC_EcatStart(HAND devHandle);

// 停止Ethercat主站
MTN_API Int16  __stdcall NMC_EcatStop(HAND devHandle);

// 获取当前在线的从站数量
// pSlaveCnt:从站的总数
// pDriverCnt:驱动器数量
// pIoCnt:IO类型从站数量
MTN_API Int16  __stdcall NMC_EcatGetResource(HAND devHandle,Int16 *pSlaveCnt,Int16 *pDriverCnt,Int16 *pIoCnt);


// 获取从站信息结构体
typedef struct TEcatSlaveMapping
{
    Int16 slvMasterIdx;        // 主站序号，取值范围[0,n]
    Int16 slvSlaveIdx;         // 从站序号，取值范围[0,n]
    Int16 slvSlotIdx;          // 槽序号，取值范围[0,n]
    Int16 slvDevType;          // 设备类型：3：驱动器，2：IO，3：其他
    Int16 slvCtrMode;          // 控制模式，保留，写0
    Int16 slvFeedbackEn;       // 反馈位置激活

    Int16 mapToIdx;             // 映射到的规划层的序号，对于驱动器，指轴序号，取值[16,n];对于IO指组号，取值[2,n]
    Int16 reserved1;            // 保留
    double prfCoe;              // 规划下发的Coe系数
    double encCoe;              // 编码器的Coe系数
    Int16  reserved2[32];       // 保留
#ifdef MTN_ST_INIT_EN
    TEcatSlaveMapping() {
        reserved1 = 0;
        slvMasterIdx = slvSlaveIdx = slvSlotIdx = slvCtrMode = mapToIdx = 0;
        slvDevType = slvFeedbackEn = 1;
        prfCoe = encCoe = 1.0;
        memset(reserved2, 0, sizeof(Int16) * 32);
    }
#endif
}TEcatSlaveMapping;

// 设置从站的映射关系
// unitCnt:映射单元数量，取值范围[0,n),0:清除所有的映射关系
// pMappingList:映射关系列表
// 注意：映射关系如果没有配置，则在启动主站时会自动设置为默认的映射关系
MTN_API Int16  __stdcall NMC_EcatSetSaveMappingList(HAND devHandle, Int16 unitCnt, TEcatSlaveMapping* pMappingList);
// 回读从站的映射关系
// bufMaxCnt:pMappingList缓冲区最大的缓冲长度，实际数量大于该数值，则返回错误
// pUnitCnt:从站映射关系单元数量
// pMappingList:映射关系类别
MTN_API Int16  __stdcall NMC_EcatGetSaveMappingList(HAND devHandle, Int16 bufMaxCnt,Int16 *pUnitCnt, TEcatSlaveMapping* pMappingList);



/*
typedef struct TEcatSlavePdoMappingUnit
{
    Int16 bitOffset;        // 位偏移
    Int16 bitLen;           // 位长度
    Int16 mapToType;        // 映射的物理量类型，0:di 1:do 2:ad 3:da
    Int16 mapToChn;         // 映射的通道号，对于di/do指组号，取值范围[2,n]；对于ad/da指通道号，取值范围[512,n]

    Int16 ctrMode;          // 控制模式，保留，写0
    Int16 feedbackEn;       // 反馈位置激活
    Int16 mapToIdx;         // 映射到的规划层的序号，对于驱动器，指轴序号，取值[0,n];对于IO指组号，取值[2,n]
    Int16 reserved1[2];     // 保留
    double prfCoe;          // 规划下发的Coe系数
    double encCoe;          // 编码器的Coe系数
    Int16  reserved2[32];   // 保留
#ifdef MTN_ST_INIT_EN
    TEcatSlvInfo() {
        reserved[0] = reserved[1] = reserved[2] = reserved[3] = 0;
        vendor_id = 0;
        product_id = 0;
        devType = 0;
        devType = 0;
        txPdoCnt = 0;
        rxPdoCnt = 0;
    }
#endif
}TEcatSlavePdoMappingUnit;

*/





// 获取从站信息结构体
typedef struct TEcatSlvInfo
{
	UInt32 vendor_id;        //厂商ID
    UInt32 product_id;      //设备ID
	UInt16 devType;         //设备类型：1：驱动器，2：IO，3：其他
	UInt16 dcCode;          // dc码
	UInt16 txPdoCnt;        // txPdo数量
	UInt16 rxPdoCnt;        // rxPdo数量
    Int16  reserved[4];     // 保留
    #ifdef MTN_ST_INIT_EN
    TEcatSlvInfo(){
     reserved[0] = reserved[1] = reserved[2] = reserved[3] =0;
     vendor_id = 0;
     product_id = 0;
     devType = 0;
     devType = 0;
     txPdoCnt = 0;
     rxPdoCnt = 0;
    }
    #endif
}TEcatSlvInfo;
// 获取从站信息
MTN_API Int16  __stdcall NMC_EcatGetSaveInfoEx(HAND devHandle,Int16 masterIdx,Int16 slvIdx,TEcatSlvInfo *pInfo);

// 获取从站信息（用户下载的配置信息）
MTN_API Int16  __stdcall NMC_EcatGetSaveInfoEx2(HAND devHandle,Int16 masterIdx,Int16 slvIdx,TEcatSlvInfo *pInfo);

// 获取主站状态
// pSts:返回状态码
//        bit0-bit7:主站状态（取值：0x01,0x02,0x03,0x04,0x08）
//                  0x01: INIT
//                  0x02: PREOP
//                  0x03: BOOT
//                  0x04: SAFEOP
//                  0x0: OP
//        bit8-bit11:状态机步骤
MTN_API Int16  __stdcall NMC_EcatGetSts(HAND devHandle,UInt16 *pSts);

// 设置从站驱动器的工作模式，用户一般不需要调用
// mode: Control Mode : CSP:8 CSV:9  CST:10
// axisHandle:轴句柄，通过NMC_MtOpen获取，ethercat从站轴的编号从16开始
MTN_API Int16  __stdcall NMC_EcatAxisSetMode(HAND axisHandle,UInt8 mode);

// 获取从站驱动器的工作模式
// axisHandle:轴句柄，通过NMC_MtOpen获取，ethercat从站轴的编号从16开始
MTN_API Int16  __stdcall NMC_EcatAxisGetMode(HAND axisHandle,UInt8 *pMode);

// 获取从站驱动器的错误代码
// axisHandle:轴句柄，通过NMC_MtOpen获取，ethercat从站轴的编号从16开始
MTN_API Int16  __stdcall NMC_EcatAxisGetErrorCode(HAND axisHandle,UInt16 *pError);

// 获取从站驱动器的数字量输入状态
// axisHandle:轴句柄，通过NMC_MtOpen获取，ethercat从站轴的编号从16开始
MTN_API Int16  __stdcall NMC_EcatAxisGetDi(HAND axisHandle,Int32 *pDiVal);

// 获取从站驱动器的编码器
MTN_API Int16  __stdcall NMC_EcatAxisGetEncPos(HAND axisHandle,Int32 *pEncPos);

// 启动回零，回零状态可以通过NMC_MtGetHomeSts查询
// method:回零方式，根据标准，只支持402要求必须实现的，具体请参考驱动器相关的说明
// velSwitch:找原点速度command/s
// velZero:找index脉冲速度command/s
// acc:加速度command/s^2
// prmEx:保留
// axisHandle:轴句柄，通过NMC_MtOpen获取，ethercat从站轴的编号从16开始
MTN_API Int16  __stdcall NMC_EcatStartHome(HAND axisHandle,Int32 method,double velSwitch,double velZero,double acc,double prmEx);
// 启动回零，带回零偏置
MTN_API short  __stdcall NMC_EcatStartHomeEx(HAND axisHandle, Int32 method, double velSwitch, double velZero, double acc, double homeOffset);

// 获取驱动器的回零状态
// bit2    bit1    bit0
// 0       0       0       回零中
// 0       0       1       回零未开始
// 0       1       0       回零中
// 0       1       1       回零OK
// 1       0       0       回零中，但是有错误发生
// 1       0       1       回零错误终止
MTN_API Int16  __stdcall NMC_EcatGetHomeSts(HAND axisHandle,UInt8 *pStatus);

// 终止回零 
// axisHandle:轴句柄，通过NMC_MtOpen获取，ethercat从站轴的编号从16开始
MTN_API Int16  __stdcall NMC_EcatStopHome(HAND axisHandle);

// Ethercat SDO 读
// devId:从站号
// idx:SDO的Index
// sub_idx:SDO的SubIndex
// len:数据长度
// val:数据内容
// abort_code:错误码
MTN_API Int16  __stdcall NMC_EcatSdoRead(HAND devHandle,Int16 devId,UInt16 idx, UInt8 sub_idx, UInt32 len, UInt8 *val, UInt32 *abort_code);

// Ethercat SDO 写
// devId:从站号
// idx:SDO的Index
// sub_idx:SDO的SubIndex
// len:数据长度
// val:数据内容
// abort_code:错误码
MTN_API Int16  __stdcall NMC_EcatSdoWrite(HAND devHandle,Int16 devId,UInt16 idx, UInt8 sub_idx, UInt32 len, UInt8 *val, UInt32 *abort_code);

// Ethercat SDO 读,异步方式
// devId:从站号
// idx:SDO的Index
// sub_idx:SDO的SubIndex
// len:数据长度
MTN_API short  __stdcall NMC_EcatSdoReadAsyn(HAND devHandle, Int16 devId, UInt16 idx, UInt8 sub_idx, UInt32 len);

// Ethercat SDO 写,异步方式
// devId:从站号
// idx:SDO的Index
// sub_idx:SDO的SubIndex
// len:数据长度
// val:数据内容
MTN_API short  __stdcall NMC_EcatSdoWriteAsyn(HAND devHandle, short devId, UInt16 idx, UInt8 sub_idx,UInt32 len, UInt8* val);

// Ethercat SDO异步读状态查询
// len:读指令期望的数据长度
// pSts:状态 低八位，0x0:操作完成，0x01:SDO结果没有返回，需要等待，0x02:SDO发送终止，主站停止等
// pBackLen:返回的数据长度
// val:返回的数据
// abort_code:执行出错码
MTN_API short  __stdcall NMC_EcatGetSdoReadAsynSts(HAND devHandle, UInt32 len, UInt32* pSts, UInt32* pBackLen, UInt8* val, UInt32* abort_code);

// Ethercat SDO异步写状态查询
// pSts:状态 低八位，0x0:操作完成，0x01:SDO结果没有返回，需要等待，0x02:SDO发送终止，主站停止等
// abort_code:执行出错码
MTN_API short  __stdcall NMC_EcatGetSdoWriteAsynSts(HAND devHandle, UInt32* pSts, UInt32* abort_code);

// Ethercat 缓冲区SDO 写
// flag:保留，写0
MTN_API short  __stdcall OEM_CrdBufEcatSdoWrite(HAND crdHandle, Int32 segNo, Int16 slvIdx, UInt16 sdoIdx, UInt8 sdoSubIdx, UInt8 sdoDataLen, Int32 sdoValue, Int8 flag);

// Ethercat 缓冲区SDO 等待
// condition: 等待条件,定义参考EVENT_DIR_BIGGER
// waitValue:等待值
// overTime：等待超时时间,单位：毫秒
MTN_API short  __stdcall OEM_CrdBufEcatSdoWait(HAND crdHandle, Int32 segNo, Int16 slvIdx, UInt16 sdoIdx, UInt8 sdoSubIdx, UInt8 sdoDataLen,
    Int16 condition, Int32 waitValue, Int32 overTime);

// 下载Ethercat配置文件（配置文件通过配置工具生成）
// gmlFileName:配置工具路径
// masterIdx:主站序号，保留，写0
MTN_API Int16  __stdcall NMC_EcatLoadConfigFromFile(HAND devHandle, Int8* gmlFileName, Int16 masterIdx);
// saveToMc:保存到控制器（掉电不丢失），0:不保存，1:保存，注意：通常不要频繁保存，保存过程比较慢
MTN_API Int16  __stdcall NMC_EcatLoadConfigFromFileEx(HAND devHandle,Int8 *gmlFileName,Int16 masterIdx,Int16 saveToMc);

// 使用控制器保存的配置信息配置从站
// masterIdx:主站序号，保留，写0
// flag:保留，写0
MTN_API Int16  __stdcall NMC_EcatLoadConfigFromMC(HAND devHandle, Int16 masterIdx, Int16 flag);


// Ehercat:设置目标转矩，对应PDO序号0x6071
// slv:从轴号，取值范围[0,n)
// tgtTorque:目标转矩，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetTgt(HAND devHandle,Int16 slv,Int32 tgtTorque);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetTgt(HAND devHandle,Int16 slv,Int32 *pTgtTorque);

// Ehercat:设置最大转矩，对应PDO序号0x6072
// slv:从轴号，取值范围[0,n)
// maxTorque:最大转矩，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetMax(HAND devHandle,Int16 slv,Int32 maxTorque);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetMax(HAND devHandle,Int16 slv,Int32 *pMaxTorque);

// Ehercat:设置转矩斜坡值，对应PDO序号0x6087
// slv:从轴号，取值范围[0,n)
// torqueSlope:转矩斜坡值，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetSlope(HAND devHandle,Int16 slv,Int32 torqueSlope);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetSlope(HAND devHandle,Int16 slv,Int32 *pTorqueSlope);

// Ehercat:设置转矩偏移值，对应PDO序号0x60B2
// slv:从轴号，取值范围[0,n)
// torqueOffset:转矩偏移值，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetOffset(HAND devHandle,Int16 slv,Int32 torqueOffset);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetOffset(HAND devHandle,Int16 slv,Int32 *pTorqueOffset);

// Ehercat:设置转矩正向的限定值，对应PDO序号0x60E0
// slv:从轴号，取值范围[0,n)
// torquePosLmt:转矩正向的限定值，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetPosLmt(HAND devHandle,Int16 slv,Int32 torquePosLmt);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetPosLmt(HAND devHandle,Int16 slv,Int32 *pTorquePosLmt);

// Ehercat:设置转矩负向的限定值，对应PDO序号0x60E1
// slv:从轴号，取值范围[0,n)
// torquePosLmt:转矩负向的限定值，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetNegLmt(HAND devHandle,Int16 slv,Int32 torqueNegLmt);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetNegLmt(HAND devHandle,Int16 slv,Int32 *pTorqueNegLmt);

// Ehercat:设置伺服的最大电机速度，对应PDO序号0x6080
// slv:从轴号，取值范围[0,n)
// maxMotorVel:最大电机速度，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisSetMaxMotorVel(HAND devHandle,Int16 slv,Int32 maxMotorVel);
MTN_API Int16  __stdcall NMC_EcatAxisGetMaxMotorVel(HAND devHandle,Int16 slv,Int32 *pMaxMotorVel);

// Ehercat:设置伺服的最大规划速度，对应PDO序号0x607F
// slv:从轴号，取值范围[0,n)
// maxPrfVel:最大规划速度，参数范围及单位请参考对应的伺服驱动器手册
MTN_API Int16  __stdcall NMC_EcatAxisSetMaxPrfVel(HAND devHandle,Int16 slv,Int32 maxPrfVel);
MTN_API Int16  __stdcall NMC_EcatAxisGetMaxPrfVel(HAND devHandle,Int16 slv,Int32 *pMaxPrfVel);

// 设置IO模块映射的IO数量
// ioCntPerSlave:IO模块映射的IO数量,默认为32
MTN_API short  __stdcall NMC_EcatSetIOCntPerSlave(HAND devHandle, Int16 ioCntPerSlave);


// 以下为带masterIdx参数的Ex版本接口
// masterIdx:主站序号，取值范围[0,n]
// 启动Ethercat主站
MTN_API Int16  __stdcall NMC_EcatStartEx(HAND devHandle, Int16 masterIdx);

// 停止Ethercat主站
MTN_API Int16  __stdcall NMC_EcatStopEx(HAND devHandle, Int16 masterIdx);

// 获取当前在线的从站数量
MTN_API Int16  __stdcall NMC_EcatGetResourceEx(HAND devHandle, Int16 masterIdx, Int16 *pSlaveCnt, Int16 *pDriverCnt, Int16 *pIoCnt);

// 获取主站状态
MTN_API Int16  __stdcall NMC_EcatGetStsEx(HAND devHandle, Int16 masterIdx, UInt16 *pSts);

// Ethercat SDO 读
MTN_API Int16  __stdcall NMC_EcatSdoReadEx(HAND devHandle, Int16 masterIdx, Int16 devId, UInt16 idx, UInt8 sub_idx, UInt32 len, UInt8 *val, UInt32 *abort_code);

// Ethercat SDO 写
MTN_API Int16  __stdcall NMC_EcatSdoWriteEx(HAND devHandle, Int16 masterIdx, Int16 devId, UInt16 idx, UInt8 sub_idx, UInt32 len, UInt8 *val, UInt32 *abort_code);

// Ethercat SDO 读,异步方式
MTN_API short  __stdcall NMC_EcatSdoReadAsynEx(HAND devHandle, Int16 masterIdx, Int16 devId, UInt16 idx, UInt8 sub_idx, UInt32 len);

// Ethercat SDO 写,异步方式
MTN_API short  __stdcall NMC_EcatSdoWriteAsynEx(HAND devHandle, Int16 masterIdx, short devId, UInt16 idx, UInt8 sub_idx, UInt32 len, UInt8* val);

// Ethercat SDO 写,避免重发
MTN_API short __stdcall NMC_EcatSdoWriteAsynEx2(HAND devHandle, Int16 masterIdx, short devId, UInt16 idx, UInt8 sub_idx, UInt32 len, UInt8* val);

// Ethercat SDO异步读状态查询
MTN_API short  __stdcall NMC_EcatGetSdoReadAsynStsEx(HAND devHandle, Int16 masterIdx, UInt32 len, UInt32* pSts, UInt32* pBackLen, UInt8* val, UInt32* abort_code);

// Ethercat SDO异步写状态查询
MTN_API short  __stdcall NMC_EcatGetSdoWriteAsynStsEx(HAND devHandle, Int16 masterIdx, UInt32* pSts, UInt32* abort_code);

// 设置目标转矩
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetTgtEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 tgtTorque);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetTgtEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pTgtTorque);

// 设置最大转矩
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetMaxEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 maxTorque);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetMaxEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pMaxTorque);

// 设置转矩斜坡值
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetSlopeEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 torqueSlope);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetSlopeEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pTorqueSlope);

// 设置转矩偏移值
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetOffsetEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 torqueOffset);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetOffsetEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pTorqueOffset);

// 设置转矩正向的限定值
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetPosLmtEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 torquePosLmt);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetPosLmtEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pTorquePosLmt);

// 设置转矩负向的限定值
MTN_API Int16  __stdcall NMC_EcatAxisTorqSetNegLmtEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 torqueNegLmt);
MTN_API Int16  __stdcall NMC_EcatAxisTorqGetNegLmtEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pTorqueNegLmt);

// 设置伺服的最大电机速度
MTN_API Int16  __stdcall NMC_EcatAxisSetMaxMotorVelEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 maxMotorVel);
MTN_API Int16  __stdcall NMC_EcatAxisGetMaxMotorVelEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pMaxMotorVel);

// 设置伺服的最大规划速度
MTN_API Int16  __stdcall NMC_EcatAxisSetMaxPrfVelEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 maxPrfVel);
MTN_API Int16  __stdcall NMC_EcatAxisGetMaxPrfVelEx(HAND devHandle, Int16 masterIdx, Int16 slv, Int32 *pMaxPrfVel);
 
// 获取/设置 主站OPCNT,成功进入OP状态的计数
MTN_API short __stdcall OEM_EcatGetMasterOPCnt(HAND devHandle, Int32* pEnterOPCnt, short mastIdx);
MTN_API short __stdcall OEM_EcatSetMasterOPCnt(HAND devHandle, Int32 enterOPCnt, short mastIdx);

#ifdef __cplusplus
}
#endif

#endif	// _H_MTN_LIB20_ECAT_H_
