#include "GCMotion.h"

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

/*****************************************************************
* Function Name : 指令返回值
* Description   : 返回错误值 rtn
* Date			: 2022年8月3日
* Auther		: LWH
******************************************************************/
short gc_example_crd_many(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);

	rtn = NMC_CrdOpen(devHandle, &crdHandle);	// 创建CRD操作句柄
	gc_rtn_error(rtn);
	TCrdConfig crdCfg;
	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;			// 设置坐标系原点为机械原点
	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 };
	double vel = 20;
	double acc = 0.5;
	long freeSpace;
	short crdStartFlag = 0;
	for (int i = 0; i < 1000; i++)	//计划压入1000段数据
	{
		targetPos[0] = i * 100;
		targetPos[1] = i * 0;
		targetPos[2] = i * 20;
		rtn = NMC_CrdBufGetFree(crdHandle, &freeSpace); // 读取指令缓冲区空闲长度 ：21925
		gc_rtn_error(rtn);
		if (freeSpace > 1)
		{
			rtn = NMC_CrdLineXYZ(crdHandle, segNo++, 0x7, targetPos, 0, vel, acc);
			gc_rtn_error(rtn);
		}
		else
		{
			//提示缓冲区长度不足
			crdStartFlag = 1;
			break;
		}
	}
	rtn = NMC_CrdEndMtn(crdHandle);// 结束数据压入
	gc_rtn_error(rtn);
	if (crdStartFlag == 0)
	{
		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;	// 运动完成
		}
		
		// 如果运动数据大于21000，可以边运动边压入数据
		rtn = NMC_CrdBufGetFree(crdHandle, &freeSpace); // 读取指令缓冲区空闲长度 ：21925    指令运动完后，freeSpace会自动增加，
		gc_rtn_error(rtn);
		if(freeSpace>15000)
		{
			for (int i = 0; i < 10000; i++)	//计划压入10000段数据
			{
			targetPos[0] = i * 100;
			targetPos[1] = i * 0;
			targetPos[2] = i * 20;
			rtn = NMC_CrdLineXYZ(crdHandle, segNo++, 0x7, targetPos, 0, vel, acc);
			gc_rtn_error(rtn);
		}
		rtn = NMC_CrdEndMtn(crdHandle);// 结束数据压入
		gc_rtn_error(rtn);
	}
	return rtn;
}