#include "GCMotion.h"

using namespace System;
using namespace System::Windows::Forms;

/*****************************************************************
* Function Name : 指令返回值
* Description   : 返回错误值 rtn
* Date			: 2022年8月3日
* Auther		: LWH
******************************************************************/
short gc_rtn_error(short rtn)
{
	if (rtn != RTN_CMD_SUCCESS) {
		return rtn;		// 指令执行错误
	}
}

/*****************************************************************
* Function Name : 坐标系(插补)运动直线和圆弧
* Description   : 略
* Date			: 2022年8月3日
* Auther		: LWH
******************************************************************/
short gc_example(void)
{	
	short rtn;						// 指令返回值
	short devNum;				    // 设备序号，从0开始
	short axisNum;					// 轴号，从0开始
	HAND devHandle;					// 设备句柄
	HAND axisHandle;			    // 轴句柄
	HAND crdHandle;					// 坐标系句柄
	rtn = NMC_DevOpen(devNum, &devHandle);				//打开控制器
	gc_rtn_error(rtn);
	rtn = NMC_MtOpen(devHandle, axisNum, &axisHandle);	//打开轴,并获得轴句柄
	gc_rtn_error(rtn);
	rtn = NMC_MtSetSvOn(axisHandle);					//打开轴使能(根据实际情况使用)
	gc_rtn_error(rtn);
	
	TCrdConfig crdCfg;							
	rtn = NMC_CrdOpen(devHandle, &crdHandle);	// 创建坐标系Crd操作句柄
	gc_rtn_error(rtn);
	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系统配置
	gc_rtn_error(rtn);

	TCrdPara crdPrm;			
	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系统参数配置
	gc_rtn_error(rtn);
	rtn = NMC_CrdBufClr(crdHandle);				// 清空缓冲区数据
	gc_rtn_error(rtn);

	// 往缓冲区压入数据，可以循环连续压入多段数据，其他缓冲区指令请参考编程手册和头文件
	long segNo = 1;			// 段号
	long targetPos[3] = { 0,0,0 }; 
	long centerPos[3] = { 5000,0,0 };
	double vel = 2;
	double acc = 0.5;
	// 压入目标位置targetPos
	rtn = NMC_CrdLineXYZ(crdHandle, segNo++, 0x7, targetPos, 0, vel, acc);	//运动到(0,0,0)
	gc_rtn_error(rtn);
	targetPos[0] = 10000;
	targetPos[1] = 0;
	rtn = NMC_CrdArcCenter(crdHandle, segNo++, targetPos, centerPos, 1, 0, vel, acc);	//圆弧插补到(10000,0,0)
	gc_rtn_error(rtn);
	rtn = NMC_CrdBufDelay(crdHandle, segNo++, CRD_BUFF_DELAY_SCALE_MS, 100);			// 延时100毫秒
	gc_rtn_error(rtn);
	rtn = NMC_CrdBufDo(crdHandle, segNo++, CRD_BUFF_DO_GPDO1, 1, 0);					// 输出DO
	gc_rtn_error(rtn);
	rtn = NMC_CrdEndMtn(crdHandle);		// 结束数据压入
	gc_rtn_error(rtn);
	rtn = NMC_CrdStartMtn(crdHandle);	// 启动缓冲区运动
	gc_rtn_error(rtn);

	// 等待运动结束
	short crdSts;
	while (true)
	{
		rtn = NMC_CrdGetSts(crdHandle, &crdSts); // 获取缓冲区状态
		gc_rtn_error(rtn);
		if ((crdSts & BIT_CORD_BUSY) == 0)
		{
			break;	// 运动完成
		}
	}
	return rtn;
}