import static lib.mtn_lib20.*;
import static lib.mtn_lib20_com.*;
import static lib.mtn_lib20_ext.*;
import static lib.mtn_lib20_oem.*;
import static lib.mtn_lib20_err.*;
import com.sun.jna.*;
import com.sun.jna.ptr.*;

public class Main {
    static {
        String libPath = System.getProperty("user.dir") + "\\lib";
        System.setProperty("java.library.path", libPath);
        System.load(libPath + "\\msvcr100.dll");
        System.load(libPath + "\\msvcp100.dll");
        System.load(libPath + "\\nmc_lib20.dll");
    }
    private static void checkError(short rtn, String operation) {
        if (rtn != 0) {
            System.err.printf("错误: %s (代码: %d)\n", operation, rtn);
//            System.exit(1);
        }
    }
    public static void main(String[] args) {

        short rtn;// 指令返回值
        short axisNum = 0;// 轴号，从0开始
        HAND devHandle = new HAND();// 设备句柄
        PHAND pDevHandle = new PHAND();
        HAND axisHandle = new HAND();// 轴句柄
        PHAND pAxisHandle = new PHAND();
        HAND crdHandle = new HAND();// 坐标系句柄
        PHAND pcrdHandle = new PHAND();

        short[] devCount = new short[1];
        TDevInfo[] devInfoList = new TDevInfo[10];
        rtn = NMC_DevSearch(TSearchMode.Ethernet, devCount, devInfoList);
        checkError(rtn,"搜索设备出错");
        rtn = NMC_DevOpen(devInfoList[0].address, pDevHandle);				//打开控制器
        checkError(rtn,"打开控制器出错");
        devHandle = pDevHandle.getHandle();
        rtn = NMC_MtOpen(devHandle, axisNum, pAxisHandle); // 打开轴
        checkError(rtn,"打开轴出错");
        axisHandle = pAxisHandle.getHandle();
        rtn = NMC_MtSetSvOn(axisHandle);//打开轴使能(根据实际情况使用)
        checkError(rtn,"轴使能出错");
        rtn = NMC_CrdOpen(devHandle, pcrdHandle);			//打开坐标系
        checkError(rtn,"打开坐标系出错");
        crdHandle = pcrdHandle.getHandle();

        TCrdConfig crdCfg = new TCrdConfig();
        crdCfg.axCnts = 3;			// 配置三个轴
        crdCfg.pAxArray[0] = 0;		// 坐标系运动X轴为第一轴
        crdCfg.pAxArray[1] = 1;		// 坐标系运动Y轴为第二轴
        crdCfg.pAxArray[2] = 2;		// 坐标系运动Z轴为第三轴
        crdCfg.pAxArray[3] = -1;	// 坐标系运动A轴为第四轴,-1为不使用
        crdCfg.port[0] = 0;			// 端口为0
        crdCfg.port[1] = 0;			// 端口为0
        crdCfg.port[2] = 0;			// 端口为0
        crdCfg.port[3] = 0;			// 端口为0
        rtn = NMC_CrdConfig(crdHandle, crdCfg);	// Crd系统配置
        checkError(rtn,"Crd系统配置出错");

        TCrdPara crdPrm = new TCrdPara();
        crdPrm.orgFlag = 1;			// 设置坐标系原点为机械原点(0,0,0)
        crdPrm.synAccMax = 10;		// 最大合成加速度p/m^2
        crdPrm.synVelMax = 50;		// 最大合成速度,在轴允许的范围内，尽可能的大一些
        crdPrm.offset[0] = 0;		// 第一轴原点为0
        crdPrm.offset[1] = 0;		// 第二轴原点为0
        crdPrm.offset[2] = 0;		// 第三轴原点为0
        crdPrm.offset[3] = 0;		// 第四轴原点为0
        rtn = NMC_CrdSetPara(crdHandle, crdPrm);	// Crd系统参数配置
        checkError(rtn,"Crd系统参数配置出错");
        rtn = NMC_CrdBufClr(crdHandle);				// 清空缓冲区数据
        checkError(rtn,"清空缓冲区数据出错");

        // 往缓冲区压入数据，可以循环连续压入多段数据，其他缓冲区指令请参考编程手册和头文件
        NativeLong segNo = new NativeLong(1);			// 段号
        NativeLong[] targetPos = {new NativeLong(0), new NativeLong(0), new NativeLong(0)};
        NativeLong[] centerPos = {new NativeLong(5000), new NativeLong(0), new NativeLong(0)};
        double vel = 2;
        double acc = 0.5;
        // 压入目标位置targetPos

        rtn = NMC_CrdLineXYZ(crdHandle, segNo, (short) 0x7, targetPos, 0, vel, acc);	//运动到(0,0,0)
        checkError(rtn,"运动到(0,0,0)出错");
        segNo = new NativeLong(segNo.longValue() + 1);

        targetPos[0] = new NativeLong(10000);
        targetPos[1] = new NativeLong(0);
        rtn = NMC_CrdArcCenter(crdHandle, segNo, targetPos, centerPos, (short) 1, 0, vel, acc);	//圆弧插补到(10000,0,0)
        checkError(rtn,"圆弧插补到(10000,0,0)出错");
        segNo = new NativeLong(segNo.longValue() + 1);

        rtn = NMC_CrdBufDelay(crdHandle, segNo, CRD_BUFF_DELAY_SCALE_MS, new NativeLong(100));			// 延时100毫秒
        checkError(rtn,"延时100毫秒出错");
        segNo = new NativeLong(segNo.longValue() + 1);

        rtn = NMC_CrdBufDo(crdHandle, segNo, CRD_BUFF_DO_GPDO1, new NativeLong(1), new NativeLong(0));	// 输出DO
        checkError(rtn,"// 输出DO出错");
        segNo = new NativeLong(segNo.longValue() + 1);

        rtn = NMC_CrdEndMtn(crdHandle);		// 结束数据压入
        checkError(rtn,"结束数据压入出错");

        rtn = NMC_CrdStartMtn(crdHandle);	// 启动缓冲区运动
        checkError(rtn,"启动缓冲区运动出错");


        // 等待运动结束
        ShortByReference crdSts = new ShortByReference();
        while (true)
        {
            rtn = NMC_CrdGetSts(crdHandle, crdSts); // 获取缓冲区状态
            checkError(rtn,"获取缓冲区状态出错");
            if ((crdSts.getValue() & BIT_CORD_BUSY) == 0)
            {
                break;	// 运动完成
            }
        }
    }
}
