optical/NxFuncs/comm/comm.c
2025-09-04 09:45:08 +08:00

462 lines
9.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define _IN_COMM_C
#include "comm.h"
#include "crc16.h"
//--------------------------------------------------------------------------------------------------
// 读空缓冲区
// 读空缓冲区
int ReadBuffEmpty(DataExFuns * funs)
{
int rslt, len;
int rdlen;
#define ONCE_READ 16
u8 tempbuf[ONCE_READ];
len = funs->GetRsvLen();
while (len > 0)
{
if (len < ONCE_READ)
{
rdlen = len;
}
else
{
rdlen = ONCE_READ;
}
rslt = funs->GetCommData(tempbuf, rdlen);
if (rslt <= 0)
{
rslt = 0;
break;
}
len -= rslt;
}
return len;
}
//--------------------------------------------------------------------------------------------------
// 功能: 从通讯口接收缓冲区中得到一个数据包,
// 只能取得普通数据包结构. 如果数据包还有附加数据, 那么需要用 GetExCommData 函数取得
// 参数: pPacket, 数据包指针
// 返回: >=0, 成功取得一个数据包,包括定长数据包和可变长度数据包,返回值为数据包长度
// -1, 参数错误
// -2, CRC错误
// -3, 数据不足
// -4, 没有找到同步序列
// -5等待接收数据超时
// -6, 数据包参数错误
// -7, 附加数据CRC错误
// -8, 发生未知错误
// 结果: 如果正确取得数据包,或通讯口没有命令, 循环队列尾指针回向后移动
#define MAX_TCP_PACKET 1500
typedef struct
{
int len; // 已读取数据长度
u8 buff[LEN_NORMAL_PACKET+MAX_TCP_PACKET]; // 接收缓冲区
}GetPacketCtrl;
GetPacketCtrl g_gtpCtrl = {0};
#define MAX_ONCE_SCAN (LEN_NORMAL_PACKET) // 一次扫描最大字节数
/*
* return: -1,参数错误
* -2,CRC校验错误
* -3,没有足够的数据
*/
int GetANormalPacket(DataExFuns * funs, DataPacket * pPacket)
{
int rslt, len;
int i;
int phase;
int status; // 同步序列 1,FLDP 2,VLDP
int exlen;
int begidx;
u8 temp;
u8 rdBuf[LEN_NORMAL_PACKET];
DataPacket * pDat = (DataPacket *)(rdBuf);
if (funs == NULL || pPacket == NULL)
{
return -1;
}
// 读取一次数据包到缓冲区
if (g_gtpCtrl.len < LEN_NORMAL_PACKET + MAX_EXDP_LEN)
{
len = funs->GetRsvLen(); // 读取已接收数据长度
if (len <= 0)
{
rslt = -3; // 没有足够数据
}
else
{
if (len + g_gtpCtrl.len <= MAX_TCP_PACKET)
{
rslt = funs->GetCommData(&(g_gtpCtrl.buff[g_gtpCtrl.len]), len); // 读取一段数据
}
else
{
// printf("Get a big packet, len=%d\r\n", len);
rslt = funs->GetCommData(&(g_gtpCtrl.buff[g_gtpCtrl.len]), MAX_TCP_PACKET-g_gtpCtrl.len); // 读取一段数据
}
g_gtpCtrl.len += rslt; // 实际数据长度增加
// printf("load a packet to buff, len=%d, buflen=%d\r\n", len, g_gtpCtrl.len);
}
}
len = g_gtpCtrl.len;
if (len < LEN_NORMAL_PACKET)
{
rslt = -3;
return rslt; // 没有足够数据
}
i = 0; // 扫描字节计数器
begidx = 0; // 正确数据包起始计数器
phase = 0;
status = 0;
rslt = 0;
while(phase < LEN_NORMAL_PACKET)
{
if (phase == 0 && i > MAX_ONCE_SCAN)
{
rslt = -4;
break; // 查找同步序列超出最大单次扫描字节数
}
if (i < g_gtpCtrl.len)
{
temp = g_gtpCtrl.buff[i];
i++; // 扫描字数增加
}
else
{
// printf("data not enough\r\n");
rslt = -3; // 数据不足
break;
}
pDat->buff.normal[phase] = temp; // 保存数据
if (phase < DP_SYNC_LEN) // 识别同步序列
{
if (phase == 0)
{
if (temp == FLDP_SYNC[0])
{
begidx = i-1;
status = 1;
}
else if (temp == VLDP_SYNC[0])
{
begidx = i-1;
status = 2;
}
else
{
begidx = i;
status = 0;
phase = 0;
rslt = 0; // 非同步序列,继续扫描
continue;
}
}
else
{
if (status == 1)
{
if (temp != FLDP_SYNC[phase]) // 同步序列不正确,继续扫描
{
begidx = 0;
status = 0;
phase = 0;
rslt = 0;
continue;
}
}
else if (status == 2)
{
if (temp != VLDP_SYNC[phase]) // 同步序列不正确,继续扫描
{
begidx = 0;
status = 0;
phase = 0;
rslt = 0;
continue;
}
}
else
{
begidx = 0;
status = 0;
phase = 0;
rslt = -8;
printf("1. error status in GetANormalPacket\r\n");
break;
}
}
}
phase++;
}
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;
}
else
{
// CRC 不正确
begidx = i;
printf("2. crc error in GetANormalPacket\r\n");
rslt = -2;
}
}
if (rslt == LEN_NORMAL_PACKET) // 正确得到
{
if (memcmp(pPacket->normal.sync, VLDP_SYNC, DP_SYNC_LEN) == 0) // 是可变长度数据包 vldp
{
// 附加数据
exlen = pPacket->vldp.exlen;
if (exlen > MAX_EXDP_LEN)
{
begidx += LEN_NORMAL_PACKET+exlen;
printf("data exlen error, len=%d\r\n", exlen);
rslt = -6; // 数据包参数错误
}
else if (exlen == 0)
{
begidx += LEN_NORMAL_PACKET;
rslt = LEN_NORMAL_PACKET;
}
else if (exlen + LEN_NORMAL_PACKET > g_gtpCtrl.len)
{
// 数据不足, 暂时退出
// printf("exdata not enough, exlen=%d, g_gtpCtrl.len=%d\r\n", exlen, g_gtpCtrl.len);
rslt = -3; // 数据不足
}
else
{
// 20240606 ljs 修复拷贝数据时的地址错误
#if (1)
// 增加扩展数据CRC校验(1k字节校验耗时约1ms)
u16 crc;
crc = CalcCrc16(&g_gtpCtrl.buff[i], exlen);
if (crc == pDat->vldp.excrc)
{
memcpy(pPacket->buff.exData, &(g_gtpCtrl.buff[i]), exlen); // 拷贝数据
if (exlen < MAX_EXDP_LEN)
{
pPacket->buff.exData[exlen] = 0;
}
rslt = LEN_NORMAL_PACKET+exlen;
}
else
{
printf("3. excrc error in GetANormalPacket\r\n");
rslt = -2;
}
begidx += LEN_NORMAL_PACKET+exlen;
#else
begidx += LEN_NORMAL_PACKET+exlen;
memcpy(pPacket->buff.exData, &(g_gtpCtrl.buff[i]), exlen); // 拷贝数据
if (exlen < MAX_EXDP_LEN)
{
pPacket->buff.exData[exlen] = 0;
}
rslt = LEN_NORMAL_PACKET+exlen;
#endif
}
}
else
{
begidx += LEN_NORMAL_PACKET; // 固定长度数据包
}
}
// 拷贝剩余数据到最前端
if (begidx > 0 && begidx <= g_gtpCtrl.len)
{
if (begidx < g_gtpCtrl.len)
{
// printf("copy data, begidx=%d, len=%d\r\n", begidx, (g_gtpCtrl.len - begidx));
memcpy(&(g_gtpCtrl.buff[0]), &g_gtpCtrl.buff[begidx], (g_gtpCtrl.len - begidx));
}
g_gtpCtrl.len -= begidx;
begidx = 0;
}
else if (begidx < 0)
{
printf("beginidx < 0\r\n");
}
else if (begidx > g_gtpCtrl.len)
{
g_gtpCtrl.len = 0;
printf("begidx=%d > g_gtpCtrl.len=%d, set g_gtpCtrl.len = 0\r\n", begidx, g_gtpCtrl.len);
}
else
{
}
return rslt;
}
//--------------------------------------------------------------------------------------------------
// 功能: 添加数据到发送队列中, 通过通讯口发送数据
// 参数: pPacket, 需要发送的数据,已经正确存放在了相应字段。
// 结果:
// 0, 可以发送, 添加到了发送数据队列中
// -1, 参数错误
// -2发送错误
// 1, 队列已满, 不能发送
int SendAPacket(DataExFuns * funs, DataPacket * pPacket, int waittime)
{
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;
}
rslt = 0;
do
{
freelen = funs->GetTrsFreeLen();
if (freelen <= 0) // 可能网络未连接
{
// printf("error at call GetTrsFreeLen, freelen=%d\r\n", freelen);
rslt = -2;
break;
}
if (freelen >= sendlen)
{
break;
}
waittime--;
if (waittime <= 0)
{
rslt = 1;
// printf("buff is full in SendAPacket, timout\r\n");
break;
}
if (funs->Delay != NULL)
{
funs->Delay(1);
}
}while(1);
if (rslt == 0)
{
rslt = funs->SendCommData(pPacket->datbuff, sendlen);
if (rslt != sendlen)
{
printf("error at call SendCommData, rslt=%d\r\n", rslt);
return -2;
}
}
else
{
//printf("error:Not SendCommData\r\n");
}
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, const 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 && pPacket->vldp.exData != pExdat)
{
memcpy(pPacket->vldp.exData, pExdat, exlen);
}
return 0;
}
//--------------------------------------------------------------------------------------------------