//-------------------------------------------------------------------------------
// File Name:	comm.cpp
// Brief: 
// Version:		1.0.0
// Create Date: 2017/05/08
// Create by: 	Marshal Lee
// Copyright: 
//				Copyright (c)  2017, Richpeace Co., LTD.
//				All rights reserved.
//
// Modify by:	Marshal Lee
// Modify Date:	2017/05/08
//-------------------------------------------------------------------------------

#define _IN_COMM_CPP

#include "comm.h"
#include "crc16.h"


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

// 读空缓冲区
void readBuffEmpty(DataExFuns * funs)
{
	int rslt, len;
	u8 temp;

    len = funs->getRsvLen();

	while (len > 0)
	{
        rslt = funs->getCommData(&temp, 1);
		if (rslt != 1)
		{
			rslt = 0;
			break;
		}
		len--;
	}
}

//--------------------------------------------------------------------------------------------------
// 功能: 从通讯口接收缓冲区中得到一个数据包, 如果有附加数据，包括附加数据
// 参数: pPacket, 数据包指针
// 返回: >=0, 成功取得一个数据包，包括定长数据包和可变长度数据包，返回值为数据包长度
//		 -1, 参数错误
//		 -2, CRC错误
//		 -3, 数据不足
//		 -4, 没有找到同步序列
//		 -5，等待接收数据超时
//		 -6, 数据包参数错误
//		 -7, 附加数据CRC错误
// 		 -8, 发生未知错误

// 结果: 如果正确取得数据包，或通讯口没有命令, 循环队列尾指针回向后移动

int getANormalPacket(DataExFuns * funs, DataPacket * pPacket)
{
	int rslt, len;
	int i;
	int phase;
	int status;
	int exlen;
    static int rdstatus = 0;
    static u8 odBuf[LEN_NORMAL_PACKET];

    u8 temp;
	u8 rdBuf[LEN_NORMAL_PACKET];
	DataPacket * pDat;

	u8 getBuf[LEN_NORMAL_PACKET-DP_SYNC_LEN];
	int getBuflen;
	int getIdx;

	u8 tmpBuf[LEN_NORMAL_PACKET-DP_SYNC_LEN];
	int tmpBuflen;

	if (funs == NULL || pPacket == NULL)
	{
		return -1;
	}

    rslt = 0;
	i = 0;				// 扫描字节计数器
	getBuflen = 0;
	getIdx = 0;
	tmpBuflen = 0;
	pDat = (DataPacket *)rdBuf;	

    if (rdstatus == 0)
    {
        do
        {
            len = funs->getRsvLen();    // 得到接收长度
            len += getBuflen;       // 加上已经获取的长度

            if (len < LEN_NORMAL_PACKET)
            {
                rslt = -3;
                break;			// 没有足够数据
            }

            phase = 0;
            status = 0;
            rslt = 0;

            // 从接收缓冲区中找数据包
            while(((len + phase) >= LEN_NORMAL_PACKET) && (phase < LEN_NORMAL_PACKET))
            {
                if (getBuflen == 0)
                {
                    if (phase == 0 && i > MAX_ONCE_SCAN)
                    {
                        rslt = -4;
                        break;		// 查找同步序列超出最大单次扫描字节数
                    }

                    rslt = funs->getCommData(&temp, 1);
                    if (rslt != 1)
                    {
                        printf("error at GetCommData rslt\r\n");
                        rslt = -8;
                        break;
                    }
                    rslt = 0;
                    i++;				// 扫描字数增加
                }
                else
                {
                    temp = getBuf[getIdx];
                    getIdx++;
                    getBuflen--;
                }

                len--;				// 剩余长度减小

                pDat->buff.normal[phase] = temp;
                if (phase < DP_SYNC_LEN)			// 识别同步序列
                {
                    tmpBuflen = 0;

                    if (phase == 0)
                    {
                        if (temp == FLDP_SYNC[0])
                        {
                            status = 1;
                        }
                        else if (temp == VLDP_SYNC[0])
                        {
                            status = 2;
                        }
                        else
                        {
                            status = 0;
                            phase = 0;
                            rslt = 0;		// 非同步序列
                            break;
                        }
                    }
                    else
                    {
                        if (status == 1)
                        {
                            if (temp != FLDP_SYNC[phase])
                            {
                                status = 0;
                                phase = 0;
                                rslt = 0;
                                break;
                            }
                        }
                        else if (status == 2)
                        {
                            if (temp != VLDP_SYNC[phase])
                            {
                                status = 0;
                                phase = 0;
                                rslt = 0;
                                break;
                            }
                        }
                        else
                        {
                            printf("error status in GetANormalPacket\r\n");
                            rslt = -8;
                            break;
                        }
                    }
                }
                else
                {
                    tmpBuf[tmpBuflen] = temp;
                    tmpBuflen++;
                }

                phase++;
            }

            if (rslt != 0)
            {
                break;
            }

            if (phase >= LEN_NORMAL_PACKET)		// 得到数据包
            {
                u16 crc;
                crc = calcCrc16(pDat->normal.content, DP_CONT_LEN);
                if (crc == pDat->normal.crc)
                {
                    // 得到正确数据包
                    memcpy(pPacket, pDat, LEN_NORMAL_PACKET);

    //				printf("GetANormalPacket ok\r\n");
                    rslt = LEN_NORMAL_PACKET;
                    break;
                }
                else
                {
                    // CRC 不正确
                    printf("crc error in GetANormalPacket\r\n");
                    // 拷贝需要再判断的数据
                    if (tmpBuflen != 0)
                    {
                        memcpy(getBuf, tmpBuf, tmpBuflen);
                    }
                    getBuflen = tmpBuflen;
                    getIdx = 0;
    //				continue;
                }
            }
            else
            {
                // 没有找到同步序列的情况
                getBuflen = 0;
                getIdx = 0;
    //			continue;
            }
        }while(1);
    }

    if (rdstatus == 1)
    {
        memcpy(pPacket, odBuf, LEN_NORMAL_PACKET);
        rslt = LEN_NORMAL_PACKET;
    }

	// 附加数据
	if (rslt == LEN_NORMAL_PACKET)
	{
		if (memcmp(pPacket->normal.sync, VLDP_SYNC, DP_SYNC_LEN) == 0)	// 是可变长度数据包
		{
			exlen = pPacket->vldp.exlen;
			if (exlen > MAX_EXDP_LEN)
			{
				printf("data exlen error, len=%d\r\n", exlen);
				return -6;	// 数据包参数错误
			}

			memset(pPacket->buff.exData, 0, MAX_EXDP_LEN);	

			i = 0;
			status = 0;		// 作为历史计数器
			// 读取附加数据
			do
			{
                rslt = funs->getCommData(pPacket->buff.exData, exlen);
				if (rslt == exlen)
				{
					u16 crc;
					// 校验CRC
                    crc = calcCrc16(pPacket->buff.exData, exlen);
					if (crc == pPacket->vldp.excrc)
					{
//						printf("get exdata ok\r\n");
						rslt = exlen+LEN_NORMAL_PACKET;
					}
					else
					{
						printf("crc error at get exdata\r\n");
						rslt = -7;		// CRC错误
					}
                    rdstatus = 0;
					break;		// 得到数据
				}
				else if (rslt == 0)
				{
                    memcpy(odBuf, pPacket, LEN_NORMAL_PACKET);
                    rdstatus = 1;
                    rslt = -3;
                    break;
                    /*
                    // 数据不足
                    if (funs->delay != NULL)
                    {
                        funs->delay(1);				// 延时等待
                    }
                    len = funs->getRsvLen();	// 得到接收数据长度
                    qDebug()<<"getRsvLen"<<len;
					if (len != status)			// 和上次长度比较
					{
						status = len;
						i = 0;
					}
					else	// 如果没有变化，则计数器增加
					{
						i++;
						if (i > GTEX_TIME_OUT)	// 如果无变化计数器值大于超时值
						{
                            qDebug()<<"call GetCommData timeout";
							rslt = -5;
							break;
						}
					}
                    */
				}
				else
				{
                    qDebug()<<"error after call GetCommData";
					break;
				}
			}while(1);

		}
	}
	return rslt;
}

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

// 功能: 添加数据到发送队列中, 通过通讯口发送数据
// 参数: pPacket, 需要发送的数据，已经正确存放在了相应字段。
// 结果: 
//		 0, 可以发送, 添加到了发送数据队列中
//		 -1, 参数错误
//		 -2，发送错误
//		 1, 队列已满, 不能发送
int sendAPacket(DataExFuns * funs, DataPacket * pPacket)
{
	int rslt;
	int freelen, sendlen;
	
	if (pPacket == NULL)
	{
		return -1;
	}

	if (memcmp(pPacket->normal.sync, FLDP_SYNC, DP_SYNC_LEN) == 0)
	{
		sendlen = LEN_NORMAL_PACKET;
	}
	else if (memcmp(pPacket->normal.sync, VLDP_SYNC, DP_SYNC_LEN) == 0)
	{
		sendlen = LEN_NORMAL_PACKET + pPacket->vldp.exlen;
	}
	else
	{
		printf("para err, not a corrected packet\r\n");
		return -1;
	}

    freelen = funs->getTrsFreeLen();

	if (freelen < sendlen)
	{
//		printf("buff is full in SendAPacket\r\n");
		return 1;
	}

    rslt = funs->sendCommData(pPacket->datbuff, sendlen);
	if (rslt != sendlen)
	{
		printf("error at call SendCommData, rslt=%d\r\n", rslt);
		return -2;
	}

	return 0;
}

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

// 功能: 打包一个固定长度数据包
// 参数:
//		 pPacket, 需要打包的数据包，其中除了sync和crc的部分已经就绪
// 结果: 
//		 0, 打包好数据
//		 -1, 参数错误

int packetAFLDP(DataPacket * pPacket)
{
	if (pPacket == NULL)
	{
		return -1;
	}

	memcpy(pPacket->normal.sync, FLDP_SYNC, DP_SYNC_LEN);
    pPacket->normal.crc = calcCrc16(pPacket->normal.content, DP_CONT_LEN);

	return 0;
}

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

// 功能: 打包一个可变长度数据包
// 参数: pPacket, 需要打包的数据包，需要填充其中的 SYNC EXLEN EXCRC 和 EXDAT 等部分
//		 pExdat, 附加数据，可以为空
//		 exlen，附加数据长度，可以为0
// 结果: 
//		 0, 打包好数据
//		 -1, 参数错误
//		 -2，

int packetAVLDP(DataPacket * pPacket, u8 * pExdat, u16 exlen)
{
	if (pPacket == NULL)
	{
		return -1;
	}

	if (pExdat == NULL)
	{
		exlen = 0;
	}

	memcpy(pPacket->vldp.sync, VLDP_SYNC, DP_SYNC_LEN);
	pPacket->vldp.exlen = exlen;
    pPacket->vldp.excrc = calcCrc16(pExdat, exlen);
    pPacket->vldp.crc = calcCrc16(pPacket->normal.content, DP_CONT_LEN);
	if (exlen != 0)
	{
		memcpy(pPacket->vldp.exData, pExdat, exlen);
	}
	return 0;
}

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


