
#include "curves.h"

//--------------------------------------------------
#include "trigger.h"
#include <math.h>

//--------------------------------------------------

#if (1)		// T型速度曲线加减速（四点式，三段）

//--------------------------------------------------

// 计算加减速需要的位移
// 参数: pps1 速度1
// 		 pps2 速度2
//		 ppss 加速度
// 返回:
//		位移值
u32 TTypeCalcDisplacement(float pps1, float pps2, float ppss)
{
	// 公式: d=(v2+v1)*(v2-v1)/(2a)
	//		 v1 = pps1
	//		 v2 = pps2
	// 		 a = ppss
	float temp;

	if (ppss == 0)	// 加速度为0，匀速直线运动
	{
		return 0;
	}

	if (pps1 < pps2)
	{
		temp = (pps2-pps1);
	}
	else
	{
		temp = (pps1-pps2);
	}
	temp *= (pps1+pps2);
	temp /= ppss;
	temp /= 2;
	return (temp+0.5f);
}

//--------------------------------------------------

// 功能：计算某位移下速度变化需要加速度
// 参数：
//		 disp 位移
//		 pps1 速度1
// 		 pps2 速度2
// 返回: 加速度

float TTypeCalcAddPPSS(u32 disp, float pps1, float pps2)
{
	float temp;
	// 公式: a=(v2+v1)*(v2-v1)/(2*d)
	//		 v1 = pps1
	//		 v2 = pps2
	//		 d = disp

	if (disp == 0 || pps1 == pps2)
	{
		return 0;
	}
	if (pps1 < pps2)
	{
		temp = (pps2-pps1);
	}
	else
	{
		temp = (pps1-pps2);
	}
	temp *= (pps1+pps2);
	temp /= disp;
	temp /= 2;
	return (temp);
}

//--------------------------------------------------

// 计算某位移和某加速度下，最终的速度值
// 参数：
//		 disp 位移
//		 pps1 速度1
// 		 ppss 加速度
//
// 返回:
//		 速度值

float TTypeCalcEndSpd(u32 disp, float pps1, float ppss)
{
	float temp;
	// 公式: a=(v2+v1)*(v2-v1)/(2*d)
	//		 v1 = pps1
	//		 d = disp
	// 	最终 pps2 = sqrt(2*disp*ppss + pps1*pps1)

	temp = 2.0f*disp;
	temp *= ppss;
	temp += pps1*pps1;
	if (temp > 0)
	{
		temp = sqrt(temp);
	}
	else
	{
		temp = 0;
	}

	return (temp);
}

//--------------------------------------------------
// 计算运动时间
float TTypeCalcRunTime(u32 disp, u32 startpps, u32 stoppps, u32 runpps, u32 addppss)
{
	TTypeCtrl tctrl;
	float runtime = 0;
	float time = 0;

	memset(&tctrl, 0, sizeof(TTypeCtrl));

	// 计算中间变量和结果
	tctrl.movement = disp;
	tctrl.begPPS = startpps;				// 本段初始速度
	tctrl.endPPS = stoppps;					// 本段结束速度
	tctrl.runPPS = runpps;					// 本段运行速度
	tctrl.maxPPSS = addppss;				// 最大的加速度
	TTypeCalcRunParas(&tctrl);				// 计算加减速参数

	{
		s32 newPPSS1, newPPSS2;

		newPPSS1 = tctrl.newAddPPSS;
		newPPSS2 = tctrl.newAddPPSS;

		if (tctrl.begPPS > tctrl.newRunPPS)
		{
			newPPSS1 *= -1;
		}
		if (tctrl.endPPS > tctrl.newRunPPS)
		{
			newPPSS2 *= -1;
		}

		runtime = 0;
		if (tctrl.mvmtseg[0] != 0 && newPPSS1 != 0)
		{
			time = (int)tctrl.newRunPPS - (int)tctrl.begPPS;
			time /= newPPSS1;
			runtime += time;
		}

		if (tctrl.mvmtseg[1] != 0 && tctrl.newRunPPS != 0)
		{
			time = tctrl.mvmtseg[1];
			time /= (int)tctrl.newRunPPS;
			runtime += time;
		}

		if (tctrl.mvmtseg[2] != 0 && newPPSS2 != 0)
		{
			time = (int)tctrl.newRunPPS - (int)tctrl.endPPS;
			time /= newPPSS2;
			runtime += time;
		}
	//	printf("run time = %.6f\r\n", runtime);
	}

	return runtime;
}

//--------------------------------------------------

// 梯形速度计算
int TTypeCalcRunParas(TTypeCtrl * pTTypeCtrl)
{
#define	TCDEBUG_OUT			0	// 输出调试信息

	int rslt;
// 已知量
// 条件，当前位移段的运动不能换向（速度在一个区间，不会过零）

// 用到的变量
	u32 movement;					// 本段位移量
	u32 begPPS, endPPS, runPPS;
	u32 addPPSS;					// 加速度

	movement = pTTypeCtrl->movement;
	begPPS = pTTypeCtrl->begPPS;
	endPPS = pTTypeCtrl->endPPS;
	runPPS = pTTypeCtrl->runPPS;
	addPPSS = pTTypeCtrl->maxPPSS;

	// 保证运行速度大于最低速度
	if (runPPS < begPPS || runPPS < endPPS)
	{
		runPPS = begPPS > endPPS ? begPPS:endPPS;
	}

	rslt = 0;
	// 1. 判断是否达到最大速度，并计算各个段的位移
	{
		u32 mvmt1, mvmt2, mvmt3;

		mvmt1 = TTypeCalcDisplacement(begPPS, runPPS, addPPSS);
		mvmt3 = TTypeCalcDisplacement(endPPS, runPPS, addPPSS);

		if (mvmt1 + mvmt3 >= movement)		// 不能达到运行速度
		{
			float tmpv;
			tmpv = movement * 2;
			tmpv = sqrt((tmpv*addPPSS + begPPS*begPPS + endPPS*endPPS)/2.0);		// 能够达到的峰值速度
			runPPS = (tmpv);
#if (TCDEBUG_OUT == 1)
			printf("TTypeCalcRunParas runPPS=%d\r\n", runPPS);
#endif
			if (runPPS < begPPS || runPPS < endPPS)		// 如果重新计算的速度小于启动停止速度
			{
				u32 tpmvmt;
				tpmvmt = TTypeCalcDisplacement(begPPS, endPPS, addPPSS);		// 直接变速最小位移
				if (tpmvmt > movement)		// 所需要位移太大，不足以完成加减速，规划失败
				{
					addPPSS = TTypeCalcAddPPSS(movement, begPPS, endPPS);		// 重新计算加速度
#if (TCDEBUG_OUT == 1)
					printf("TTypeCalcRunParas addPPSS=%d\r\n", addPPSS);
#endif
					if (begPPS <= endPPS)
					{
						mvmt1 = movement;
						mvmt2 = 0;
						mvmt3 = 0;
					}
					else
					{
						mvmt1 = 0;
						mvmt2 = 0;
						mvmt3 = movement;
					}
				}
				else
				{
					if (begPPS <= endPPS)
					{
						mvmt1 = tpmvmt;
						mvmt2 = movement - tpmvmt;
						mvmt3 = 0;
					}
					else
					{
						mvmt1 = 0;
						mvmt2 = movement - tpmvmt;
						mvmt3 = tpmvmt;
					}
				}
			}
			else
			{
				mvmt1 = TTypeCalcDisplacement(begPPS, runPPS, addPPSS);
				mvmt3 = TTypeCalcDisplacement(endPPS, runPPS, addPPSS);		// 重新计算位移

				if (mvmt1 + mvmt3 > movement)
				{
					mvmt2 = 0;
					mvmt3 = movement - mvmt1;
				}
				else
				{
					mvmt2 = movement - mvmt1 - mvmt3;
				}
			}
		}
		else		// 可以达到运行速度
		{
			mvmt2 = movement - mvmt1 - mvmt3;
		}

		pTTypeCtrl->mvmtseg[0] = mvmt1;	// 第一段
		pTTypeCtrl->mvmtseg[1] = mvmt2;	// 第二段
		pTTypeCtrl->mvmtseg[2] = mvmt3;	// 第三段
		pTTypeCtrl->newRunPPS = runPPS;
		pTTypeCtrl->newAddPPSS = addPPSS;
	}
#if (TCDEBUG_OUT == 1)
	printf("TTypeCalcRunParas: seg[0]=%d, seg[2]=%d, seg[1]=%d, newRunPPS[1]=%.1f, newAddPPSS=%.1f\r\n",
		pTTypeCtrl->mvmtseg[0], pTTypeCtrl->mvmtseg[2], pTTypeCtrl->mvmtseg[1], pTTypeCtrl->newRunPPS, pTTypeCtrl->newAddPPSS);
#endif

	return rslt;
}
//--------------------------------------------
// 计算分频系数表
int TTypeCalcDivTab(u32 fin, TTypeCtrl * pTTypeCtrl, u32 * pFidvTab, u32 * pTablen)
{
#define	TDEBUG_OUT	0	// 输出调试信息

#if (TDEBUG_OUT == 1)
	u32 time, tptm, lstm;
#endif
	int rslt;
	int totalclk = 0;		// 运行时间（单位是1个时间片）
	u32 movement;

	if (fin <= 0 || pTTypeCtrl == NULL || pFidvTab == NULL || pTablen == NULL)
	{
		return -1;
	}

#if (TDEBUG_OUT == 1)
	time = GetUsSoftTimer();
	lstm = time;
#endif

	// 计算运动参数
	TTypeCalcRunParas(pTTypeCtrl);

	*pTablen = 0;
	rslt = 0;
	// 计算分频系数，生成每个脉冲的分频系数表
	{
		u32 i;
		float begPPS;			// 本段初始速度
		float endPPS;			// 本段结束速度
		float runPPS;			// 本段运行速度
		float newPPSS1, newPPSS2;

		float pps;			// 速度值
		float add;
		float rpps1, rpps2;	// 单精度能够显著提高运算速度
		int runclk;
		int coef;
		u32 * pBuf;

		movement = pTTypeCtrl->movement;
		begPPS = pTTypeCtrl->begPPS;
		endPPS = pTTypeCtrl->endPPS;
		runPPS = pTTypeCtrl->newRunPPS;
		newPPSS1 = pTTypeCtrl->newAddPPSS;
		newPPSS2 = pTTypeCtrl->newAddPPSS;

		if (begPPS > runPPS)
		{
			newPPSS1 *= -1;
		}
		if (endPPS > runPPS)
		{
			newPPSS2 *= -1;
		}

#if (TDEBUG_OUT == 1)
		lstm = GetUsSoftTimer();
#endif
		pps = begPPS;
		rpps1 = pps;
		runclk = 0;
		add = newPPSS1;
		add /= fin;
		pBuf = &(pFidvTab[0]);
		for (i = 0; i < pTTypeCtrl->mvmtseg[0]; i++)		// 第一段
		{
			if (pps > runPPS)
			{
				pps = runPPS;
			}
			if (newPPSS1 < 0 && pps < endPPS)
			{
				pps = endPPS;
			}
			coef = fin / pps;				// 根据速度值得到系数
			*pBuf++ = coef;					// 记录分频系数
			runclk += coef;					// 根据分频系数得到下一个脉冲产生的时间点
			pps = begPPS + runclk * add;	// 根据速度规划，计算下一个脉冲产生时刻的速度值
		}
		rpps1 = pps;
		totalclk += runclk;

#if (TDEBUG_OUT == 1)
		tptm = GetUsSoftTimer();
		printf("TCDiv seg1 tm=%uus\r\n", tptm-lstm);
		lstm = tptm;
#endif
		// 倒序产生第三段
		pps = endPPS;
		rpps2 = pps;
		runclk = 0;
		add = newPPSS2;
		add /= fin;
		pBuf = &(pFidvTab[movement - 1]);
		for (i = 0; i < pTTypeCtrl->mvmtseg[2]; i++)
		{
			if (pps > runPPS)
			{
				pps = runPPS;
			}
			if (newPPSS2 < 0 && pps < endPPS)
			{
				pps = endPPS;
			}
			coef = fin / pps;				// 根据速度值得到系数
			*pBuf-- = coef;					// 记录分频系数
			runclk += coef;					// 根据分频系数得到下一个脉冲产生的时间点
			pps = endPPS + runclk * add;	// 根据速度规划，计算下一个脉冲产生时刻的速度值
		}
		rpps2 = pps;
		totalclk += runclk;
#if (TDEBUG_OUT == 1)
		tptm = GetUsSoftTimer();
		printf("TCDiv seg3 tm=%uus\r\n", tptm-lstm);
		lstm = tptm;
#endif
		// 匀速段
		pps = (rpps1 + rpps2) / 2;
		if (pps > runPPS)
		{
			pps = runPPS;
		}
		if (newPPSS2 < 0 && pps < endPPS)
		{
			pps = endPPS;
		}
		runclk = 0;
		pBuf = &(pFidvTab[pTTypeCtrl->mvmtseg[0]]);
		coef = fin / pps;				// 根据速度值得到系数
		for (i = 0; i < pTTypeCtrl->mvmtseg[1]; i++)
		{
			*pBuf++ = coef;	// 记录分频系数
		}
		runclk = pTTypeCtrl->mvmtseg[1] * coef;
		totalclk += runclk;
#if (TDEBUG_OUT == 1)
		tptm = GetUsSoftTimer();
		printf("TCDiv seg2 tm=%uus\r\n", tptm-lstm);
		lstm = tptm;
#endif
	}

	if (rslt < 0)
	{
		rslt++;
	}
	else
	{
		*pTablen = movement;
		rslt = totalclk;
	}
#if (TDEBUG_OUT == 1)
	tptm = GetUsSoftTimer();
	printf("TCDiv tm=%uus\r\n", tptm-time);
#endif

	return rslt;
}

//--------------------------------------------

#endif

//----------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------

#if (0)		// S型速度曲线加减速（七段）


typedef struct
{
// 输入参数
	u32 movement;			// 本段位移量

	float begPPS;			// 本段初始速度
	float endPPS;			// 本段结束速度
	float runPPS;			// 本段运行速度（v）
	float maxPPSS;			// 最大的加速度（a）
	float maxPPSSS;			// 最大的加加速度（j）

// 计算中间变量和结果
	u32 timeseg[7];			// 七段时间长度, 单位为1个时间片
	u32 mvmtseg[7];			// 七段位移, 分段的位移量 (如果位移量不为零, 说明存在这个段)
	float newRunPPS;		// 新的运行速度

}STypeCtrl;

// 计算位移量
u32 STypeCalcDisplacement(float pps1, float pps2, float ppss);

// 计算加速度
float STypeCalcAddPPSS(u32 disp, float pps1, float pps2);

// 计算运动结束的速度
float STypeCalcEndSpd(u32 disp, float pps1, float ppss);

// 计算运动的时间
float STypeCalcRunTime(u32 disp, u32 startpps, u32 stoppps, u32 runpps, u32 addppss);

// 计算运动相关参数
int STypeCalcRunParas(STypeCtrl * pSTypeCtrl);

// 计算生成分频系数表
int STypeCalcDivTab(u32 fin, STypeCtrl * pSTypeCtrl, u32 * pFidvTab, u32 * pTablen);










#endif
