
#define _IN_TRANSDATA_C

#include "transdata.h"

#if (TRANS_APP_FILE == 1 || TRANS_DATA_FILE == 1)

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

void InitFileTransCtrl(FileTransCtrl * pfileTransCtrl)
{
	//printf("InitFileTransCtrl\r\n");
	memset(pfileTransCtrl, 0, sizeof(FileTransCtrl));
}

int WriteRsvBitmap(u32 idx, u8 sta, FileTransCtrl * pfileTransCtrl)
{
	u8 mod;
	u32 baddr, yus;

	if (idx >= LEN_RSV_BMP*8)
	{
		printf("error in WriteRsvBitmap idx=%d, packetNum=%d\r\n", idx, pfileTransCtrl->packetNum);
		return -1;
	}

	baddr = (idx)/8;
	if (baddr >= LEN_RSV_BMP)
	{
		printf("error in WriteRsvBitmap baddr=%d, lenBmp=%d\r\n",baddr, pfileTransCtrl->lenBmp);
		return -1;
	}

	yus = idx%8;
	mod = 0x01;
	while (yus != 0)
	{
		yus--;
		mod <<= 1;
	}

	if (sta == 0)
	{
		pfileTransCtrl->rsvBitmap[baddr] &= ~mod;
	}
	else
	{
		pfileTransCtrl->rsvBitmap[baddr] |= mod;
	}
	return 0;
}

int IsResvFinish(FileTransCtrl * pfileTransCtrl)
{
	u8 mod;
	u32 zss, yus;
	u32 i;

	zss = (pfileTransCtrl->packetNum)/8;
	yus = pfileTransCtrl->packetNum%8;

	for (i = 0; i < zss; i++)
	{
		if (pfileTransCtrl->rsvBitmap[i] != 0xff)
		{
			return FALSE;
		}
	}

	mod = 0x01;
	for (i = 0; i < yus; i++)
	{
		if ((pfileTransCtrl->rsvBitmap[zss] & mod) == 0)
		{
			return FALSE;
		}
		mod <<= 1;
	}

	return TRUE;
}

/*
 *  数据传输处理
 *return: 0:正常
 *
 */
int TransDataProc(BoardFileCanCtrl filecan, FileTransCtrl * pfileTransCtrl, u8 nodetype)
{
	if (filecan.head.sync[0] == CDP_SYNC[0] &&
		filecan.head.sync[1] == CDP_SYNC[1] &&
		filecan.head.sync[2] == CDP_SYNC[2] &&
		1)	// 数据包头
	{
		//printf("get a packet head,id=%d\r\n", filecan.head.pktId);
		if (filecan.head.pktId == FILE_HEAD_ID)		// 启动文件传输
		{
			printf("start receive file\r\n");
			InitFileTransCtrl(pfileTransCtrl);
			pfileTransCtrl->pBoardFile = &g_boardFile;
			pfileTransCtrl->transActive = TRANS_ACTIVE;
			pfileTransCtrl->transflag = TRANS_READY;
			pfileTransCtrl->rsvPktCount = 0;
		}
		// 记录当前接收的数据包的ID,帧个数,crc校验
		pfileTransCtrl->pBoardFile->filepkt.pktHead.head.pktId = filecan.head.pktId;
		pfileTransCtrl->pBoardFile->filepkt.pktHead.head.fnum = filecan.head.fnum;
		pfileTransCtrl->pBoardFile->filepkt.pktHead.head.crc = filecan.head.crc;
		pfileTransCtrl->rsvFrameCount = 0;
	}
	else	// 数据内容
	{
		//printf("get a packet data\r\n");
		if (pfileTransCtrl->transActive != TRANS_ACTIVE)
		{
			//printf("TransDataProc file not active\r\n");
			return -1;
		}

		if (pfileTransCtrl->transflag != TRANS_READY &&
				pfileTransCtrl->transflag != TRANS_DOING &&
			1	)
		{
			//printf("TransDataProc file not ready\r\n");
			return -2;
		}

		if (pfileTransCtrl->transflag == TRANS_READY)
		{
			pfileTransCtrl->transflag = TRANS_DOING;
		}

		// 数据拷贝
		memcpy(&pfileTransCtrl->pBoardFile->filepkt.pktData[pfileTransCtrl->rsvFrameCount].data, &filecan.data, CAN_DATA_LEN);
		pfileTransCtrl->rsvFrameCount++;

		// 判断数据包是否接收完成
		if (pfileTransCtrl->rsvFrameCount == pfileTransCtrl->pBoardFile->filepkt.pktHead.head.fnum)
		{// 接收完成,校验
			//printf("a packet receive over\r\n");
			u16 crc = CalcCrc16((u8*)&pfileTransCtrl->pBoardFile->filepkt.pktData, pfileTransCtrl->pBoardFile->filepkt.pktHead.head.fnum*CAN_DATA_LEN);
			if (crc == pfileTransCtrl->pBoardFile->filepkt.pktHead.head.crc)
			{// 校验正确
				if (pfileTransCtrl->pBoardFile->filepkt.pktHead.head.pktId == FILE_HEAD_ID)
				{// 启动文件传输数据包,拷贝至文件头
					printf("receive start over\r\n");
					memcpy(&pfileTransCtrl->pBoardFile->fileHead, &pfileTransCtrl->pBoardFile->filepkt.pktData, 6*CAN_DATA_LEN);// 6为文件头数据内容帧个数
					if (pfileTransCtrl->pBoardFile->fileHead.nodeType != nodetype)
					{
						printf("send to nodetype=0x%x\r\n", pfileTransCtrl->pBoardFile->fileHead.nodeType);
						pfileTransCtrl->transActive = TRANS_NONE;
						pfileTransCtrl->transflag = TRANS_NOT_BEG;
						return -3;
					}
					pfileTransCtrl->packetNum = ((pfileTransCtrl->pBoardFile->fileHead.dataSize+1024-1)/1024);
					pfileTransCtrl->lenBmp = (pfileTransCtrl->packetNum+CAN_DATA_LEN-1)/CAN_DATA_LEN;

					printf("now dataChecksum=%d, receive:dataSize=%d, dataChecksum=0x%x\r\n",
							pfileTransCtrl->dataChecksum,
							pfileTransCtrl->pBoardFile->fileHead.dataSize,
							pfileTransCtrl->pBoardFile->fileHead.dataChecksum);

					if (pfileTransCtrl->pBoardFile->fileHead.fileType == FILE_TYPE_PGM)
					{
						InitSaveApp();		// 需要一段时间
					}
				}
				else
				{
					pfileTransCtrl->dataChecksum += CalcCheckSum((u8*)&pfileTransCtrl->pBoardFile->filepkt.pktData, 128*CAN_DATA_LEN);// 数据内容128个CAN数据帧
					if (pfileTransCtrl->pBoardFile->fileHead.fileType == FILE_TYPE_PGM)
					{// 升级文件,存入norflash,并写入接收位图
						int rst, idx;
						u32 ofst;
						idx = (pfileTransCtrl->pBoardFile->filepkt.pktHead.head.pktId == 0 ? 0:1);
						if (pfileTransCtrl->pBoardFile->filepkt.pktHead.head.pktId == 0)
						{
							ofst = 0;
						}
						else
						{
							ofst = (pfileTransCtrl->pBoardFile->filepkt.pktHead.head.pktId-1)*pfileTransCtrl->pBoardFile->filepkt.pktHead.head.fnum*CAN_DATA_LEN;
						}
						rst = SaveAppData(idx,
								    (u8*)&pfileTransCtrl->pBoardFile->filepkt.pktData,
									pfileTransCtrl->pBoardFile->filepkt.pktHead.head.fnum*CAN_DATA_LEN,
									ofst);
						if (rst >= 0)
						{
							pfileTransCtrl->rsvPktCount++;
							WriteRsvBitmap(pfileTransCtrl->pBoardFile->filepkt.pktHead.head.pktId, 1, pfileTransCtrl);
						}
						else
						{
							printf("TransDataProc WriteFileApp error rst= %d \r\n", rst);
						}
					}
				}
				// 查看接收位图，是否接收完成
				if ((IsResvFinish(pfileTransCtrl) == TRUE) && (pfileTransCtrl->rsvPktCount == pfileTransCtrl->packetNum))
				{
					//if (pfileTransCtrl->dataChecksum == pfileTransCtrl->pBoardFile->fileHead.dataChecksum)
					if (1)
					{
						pfileTransCtrl->transflag = TRANS_DONE;		// 接收完成
						printf("TransDataProc Receive file finish\r\n");
					}
					else
					{
						printf("TransDataProc dataChecksum error, calc=0x%x, send=0x%x\r\n",
								pfileTransCtrl->dataChecksum, pfileTransCtrl->pBoardFile->fileHead.dataChecksum);
					}
				}
			}
			else
			{
				printf("TransDataProc check crc error\r\n");
			}
		}
	}
	return 0;
}

int GetLenBmp(FileTransCtrl * pfileTransCtrl)
{
	return pfileTransCtrl->lenBmp;
}


#endif
