/*
 * Spi_Comm.c
 *
 *  Created on: 2020��10��14��
 *      Author: zhou_l4
 */
#include "S32K148.h"
#include "S32K148_features.h"
#include "osif.h"
#include "Config/Include/APP_Config.h"
#include "Abstraction/Include/OS_Interface.h"
#include "Spi_Comm.h"
#include "Spi_Util.h"
#include "Driver/SPI/LPSPI_SpiDrv.h"
#include "Driver/GPIO/Gpio_drv.h"

static OS_TaskParam Manager_Param;
static OS_TaskParam Send_Param;
static OS_TaskParam Revc_Param;
//Type_sWord nswCommMgrTmout;
//OS_StdMsg_st * nstCommMgrStdMsg_p;
//void nvdCommManagerMsgProc(OS_StdMsg_st * MsgRx);
static SpiCommMsg_st Msg;
static void* gMutex;

static uint8_t gStartFlag = 0;
static eSpiCycType gSpiCycType = SPI_CYC_INVALIDE;
static SPI_Register_t gRegisterArray[SPI_MODULE_ID_MAX];
static SPI_RetryData_t gRetryDataArray[TBOX_SPI_CACHE_MAX];
static SPI_RetryData_t gRecvArray[TBOX_SPI_RECV_COUNT];
static int PI_15_Status = 0;
static int gSpiWaitCounter = 0;
static uint8_t gPG6Flag = 0;

SPI_RetryData_t gSendData = {0};
SPI_RetryData_t gRcvData = {0};

eSpiConnectStatus gSpiConnectStatus;
eSpiDtcCheckFlag gSpiDtcCheckFlag;

void* spiRecvSemaphore;

uint8_t* gCheckRcvData = NULL;
uint8_t* gProcRcvData = NULL;
uint8_t gTempSendBuffer[SPI_COMM_TRANSER_SIZE] = {0};
uint8_t gTempRecvBuffer[SPI_COMM_TRANSER_SIZE] = {0};
uint8_t gTempProcBuffer[SPI_COMM_TRANSER_SIZE] = {0};
uint8_t gSpitHeaderSend[SPI_COMM_TRANSER_SIZE] = {0};
uint8_t gDtcdata[2] = {0};
uint8_t gArrayItems = 0;
uint32_t gRecvCounter = 0;
uint32_t gSendCounter = 0;
uint8_t gAubRet = 0;

void nvdSpi_Init()
{
	gStartFlag = 1;
	gSpiConnectStatus = SPI_CLOSED;
	gSpiDtcCheckFlag = SPI_DTC_CHECK_INVALIDE;
	nvdSpiUtil_Init();
	gMutex = OS_createLock();	//Modify by xuhb@20191116
	/*init spi cache size 10*/
	for(int i=0; i< TBOX_SPI_CACHE_MAX; i++)
	{
		gRetryDataArray[i].counter = 0;
		gRetryDataArray[i].key = 0;
		gRetryDataArray[i].isBusy = 0;
		gRetryDataArray[i].isSend = 0;
		gRetryDataArray[i].msg_len = 0;
		gRetryDataArray[i].msg_buf = (uint8_t*)pvPortMalloc(SPI_COMM_TRANSER_SIZE);
		memset(gRetryDataArray[i].msg_buf , 0, SPI_COMM_TRANSER_SIZE);
	}

	/*init Send and Receive Struct */
	gSendData.msg_buf = (uint8_t*)pvPortMalloc(SPI_COMM_TRANSER_SIZE);
	gRcvData.msg_buf = (uint8_t*)pvPortMalloc(SPI_COMM_TRANSER_SIZE);
	gCheckRcvData = (uint8_t*)pvPortMalloc(SPI_COMM_TRANSER_SIZE);
	gProcRcvData = (uint8_t*)pvPortMalloc(SPI_COMM_TRANSER_SIZE);

}
uint8_t nubSpiRt_IsEmpty()
{
	return gArrayItems == 0;
}
SPI_RetryData_t nvdSpiRt_Get(uint8_t key)
{
	gRetryDataArray[gArrayItems - 1].isSend = 1;
	return gRetryDataArray[gArrayItems - 1];
}
uint8_t nubSpiRt_Size()
{
	return gArrayItems;
}
uint8_t nvdSpiRt_Remove(uint8_t key)
{
	//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] nvdSpiRt_Remove key:%d, gArrayItems:%d ", __FUNCTION__, __LINE__,key,gArrayItems);
	if(nubSpiRt_Size() > 0)
	{
		gRetryDataArray[gArrayItems-1].key = 0;
		gRetryDataArray[gArrayItems-1].counter = 0;
		gRetryDataArray[gArrayItems-1].msg_len = 0;
		gRetryDataArray[gArrayItems-1].isBusy = 0;
		gRetryDataArray[gArrayItems-1].isSend = 0;
		//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] nvdSpiRt_Remove Aom:%02x Sct:%02x Msn:%02x !!! ", __FUNCTION__, __LINE__,gRetryDataArray[gArrayItems-1].msg_buf[3], gRetryDataArray[gArrayItems-1].msg_buf[4], gRetryDataArray[gArrayItems-1].msg_buf[5]);
		memset(gRetryDataArray[gArrayItems-1].msg_buf, 0x00, SPI_COMM_TRANSER_SIZE);
		gArrayItems --;
		return TBOX_SPI_SUCESS;
	}
	return TBOX_SPI_FAILED;
}
void nvdSpi_DtcCheckProcess(uint32_t ErrCount)
{
	// Get Check Status
#if 0//delete if for NIO DTC is not prepare
	if(DTC_CHECK_STATUS_OK == GetDTCCheckStatus(DTC_TYPE_MCU))
	{
		gSpiDtcCheckFlag = SPI_DTC_CHECK_START;
	}else
	{
		gSpiDtcCheckFlag = SPI_DTC_CHECK_STOP;
	}
#endif
	switch(gSpiDtcCheckFlag)
	{
		case SPI_DTC_CHECK_STOP:
			break;
		case SPI_DTC_CHECK_START:
			if(ErrCount > TBOX_SPI_CONNECT_DIFF_CONUNT)
			{
				if(gDtcdata[1] == 0)
				{
//					JPCC_DEBUG(6, "[ SPI ][%s:%d]  Send DTC DTC_OCCUR !!!", __FUNCTION__, __LINE__);
					// Send msg to Diag
					//gDtcdata[0] = SPI_INTERNAL_FAULT;
					//gDtcdata[1] = DTC_OCCUR;
					//nubDtcMgr_SendMessage(EV_DTC_MESSAGE,gDtcdata,DTC_BUFFER_LEN);
				}
			}else
			{
				if(gDtcdata[1] == 1)
				{
//					JPCC_DEBUG(6, "[ SPI ][%s:%d]  Send DTC DTC_REMOVE !!!", __FUNCTION__, __LINE__);
					// Send msg to Diag
					//gDtcdata[0] = SPI_INTERNAL_FAULT;
					//gDtcdata[1] = DTC_REMOVE;
					//nubDtcMgr_SendMessage(EV_DTC_MESSAGE,gDtcdata,DTC_BUFFER_LEN);
				}
			}
			break;
		case SPI_DTC_CHECK_RESTART:
			break;
		case SPI_DTC_CHECK_INVALIDE:
			break;
		default:
			break;
	}
}

void nvdSpi_JugeConnectStatus(uint32_t ErrCount)
{
	if(ErrCount > TBOX_SPI_DRIVER_ERROR_COUNT)
	{
		//nvdSpi_InitDriver();
//		JPCC_DEBUG(6, "[ SPI ][%s:%d]  SPI Driver error, call SPI2_Initialization_Func !!!", __FUNCTION__, __LINE__);
	}

	if(ErrCount > TBOX_SPI_CONNECT_DIFF_CONUNT)
	{
		if(gSpiConnectStatus == SPI_ESTABLISHED)
		{
//			JPCC_DEBUG(6, "[ SPI ][%s:%d]  SET TO SPI_CLOSED !!!", __FUNCTION__, __LINE__);
			gSpiConnectStatus = SPI_CLOSED;
		}
	}
	// Produce DTC
	nvdSpi_DtcCheckProcess(ErrCount);
	return;
}
void nvdSpi_RecvInit()
{
	status_t status;
	spiRecvSemaphore = OS_createSemaphore( 0);
    if (NULL != spiRecvSemaphore)
    {
    	//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] OSIF_SemaCreate failed !!!", __FUNCTION__, __LINE__);
    }
	for(int i =0 ; i< TBOX_SPI_RECV_COUNT ; i++)
	{
		gRecvArray[i].counter = 0;
		gRecvArray[i].key = 0;
		gRecvArray[i].isBusy = 0;
		gRecvArray[i].isSend = 0;
		gRecvArray[i].msg_len = 0;
		gRecvArray[i].msg_buf = (uint8_t*)pvPortMalloc(SPI_COMM_TRANSER_SIZE);
		memset(gRecvArray[i].msg_buf , 0, SPI_COMM_TRANSER_SIZE);
	}
}
void nvdSpiRt_Insert(uint32_t key, uint8_t counter, uint32_t len, uint8_t* data)
{
	//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d]timer:%d  gArrayItems:%d ", __FUNCTION__, __LINE__, key ,gArrayItems);
	int8_t x = 0;
	if(gArrayItems == 0)
	{
		gRetryDataArray[gArrayItems].key = key;
		gRetryDataArray[gArrayItems].counter = counter;
		gRetryDataArray[gArrayItems].msg_len = len;
		gRetryDataArray[gArrayItems].isBusy = 1;
		memset(gRetryDataArray[gArrayItems].msg_buf,0,SPI_COMM_TRANSER_SIZE);
		memcpy(gRetryDataArray[gArrayItems].msg_buf,data,len);
		gArrayItems++;
	}
	else
	{
		for( x=gArrayItems -1; x >= 0;x--)
		{
			if(key > gRetryDataArray[x].key)
			{
				memcpy(gRetryDataArray[x+1].msg_buf, gRetryDataArray[x].msg_buf, gRetryDataArray[x].msg_len);
				gRetryDataArray[x+1].counter = gRetryDataArray[x].counter;
				gRetryDataArray[x+1].isBusy = gRetryDataArray[x].isBusy;
				gRetryDataArray[x+1].isSend = gRetryDataArray[x].isSend;
				gRetryDataArray[x+1].key = gRetryDataArray[x].key;
				gRetryDataArray[x+1].msg_len = gRetryDataArray[x].msg_len;
				if(x == 0)
				{
					gRetryDataArray[x].key = key;
					gRetryDataArray[x].counter = counter;
					gRetryDataArray[x].msg_len = len;
					gRetryDataArray[x].isBusy = 1;
					gRetryDataArray[x].isSend = 0;
					memset(gRetryDataArray[x].msg_buf,0,SPI_COMM_TRANSER_SIZE);
					memcpy(gRetryDataArray[x].msg_buf,data,len);
					gArrayItems ++;
					break;
				}
			}else
			{
				gRetryDataArray[x+1].key = key;
				gRetryDataArray[x+1].counter = counter;
				gRetryDataArray[x+1].msg_len = len;
				gRetryDataArray[x+1].isBusy = 1;
				gRetryDataArray[x+1].isSend = 0;
				memset(gRetryDataArray[x+1].msg_buf,0,SPI_COMM_TRANSER_SIZE);
				memcpy(gRetryDataArray[x+1].msg_buf,data,len);
				gArrayItems ++;
				break;
			}
		}
	}
}

uint8_t nvdSpi_ConstructLargePackage(eAomType aom, uint8_t* data, uint32_t size)
{
	uint8_t sum = 0;
	uint8_t *buffer = NULL;
	uint16_t length = 0;
	uint8_t num = 0;
	uint32_t key = 0;
	tSpiLargePktHeader *pLargHeader = NULL;
	num = nubSpiUtil_GenerateSequenceNum();
	length = TBOX_SPI_PROTOCOL_LARGE_DATA_MIN_LEN + size;	// 8 + size
	/* length must < 255 otherwish return -1*/
	if(length > (SPI_COMM_TRANSER_SIZE))
	{
		//JPCC_DEBUG(JPCC_LOG_LEVEL_WARNING, "[ SPI ][%s:%d][ length > SPI_COMM_TRANSER_SIZE !!!]", __FUNCTION__, __LINE__);
		return TBOX_SPI_FAILED;
	}
	pLargHeader = (tSpiLargePktHeader*)pvPortMalloc(length);
	if(NULL != pLargHeader)
	{
		pLargHeader->FBH = TBOX_SPI_PROTOCOL_LARGE_PACKET_HEADER_FIRST;
		pLargHeader->LBH = TBOX_SPI_PROTOCOL_LARGE_PACKET_HEADER_LAST;
		pLargHeader->VER = TBOX_SPI_PROTOCOL_VERSION;
		pLargHeader->AOM = aom;
		pLargHeader->MSN = num;		// only largePackage has Msn
		pLargHeader->LEN_H8 = length >> 8 & 0xff;
		pLargHeader->LEN_L8 = length & 0xff;
		if(data!=NULL)
		{
			memcpy(&pLargHeader->TOP,data,size);
		}
		/*Check Sum*/
		buffer = (uint8_t*)pLargHeader;
		sum = nubSpiUtil_GenerateCheckSum(buffer,TBOX_SPI_PROTOCOL_LARGE_HEADER_LEN+size);
		buffer[length-1] = sum;

		if((pLargHeader->AOM != SPI_ACK) && (pLargHeader->AOM != SPI_CKS_ERROR))
		{
			/*init couter and save send data*/
			key = nubSpiUtil_Generatekey();
			if(nubSpiRt_Size() < TBOX_SPI_CACHE_MAX)
			{
				nvdSpiRt_Insert(key, 0, length, buffer);

			}
			else
			{
				vPortFree(pLargHeader);//
				return TBOX_SPI_FAILED;
			}
		}
		vPortFree(pLargHeader);
	}
	return TBOX_SPI_SUCESS;
}

uint8_t nubSpi_SendDataToCache(uint8_t* data, uint8_t size)
{
	tSpiSmallPktHeader *pHeader = NULL;
	tSpiLargePktHeader *pLargeHeader = NULL;
	pHeader = (tSpiSmallPktHeader*)(data);
	//JPCC_DEBUG( SPI_LOG_LEVEL, "[ SPI ][%s:%d] nubSpi_SendDataToCache data: %02x %02x %02x %02x %02x %02x ", __FUNCTION__, __LINE__,pHeader->FBH,pHeader->LBH,pHeader->TOC,pHeader->IOC,pHeader->LEN,pHeader->TOP);
	uint8_t insertFlag = 0;
	insertFlag = 0;
	OS_lock(gMutex);
	if(nubSpiRt_Size() > 0 )
	{
		// find available Data

		int8_t i = 0;
		//for(; i >= 0; i--)
		{
			if((gRetryDataArray[i].isSend == 0) && (gRetryDataArray[i].isBusy == 1) && (gRetryDataArray[i].msg_len + size) < (SPI_COMM_TRANSER_SIZE))
			{
				uint16_t msgLen = gRetryDataArray[i].msg_len;
				memcpy(&gRetryDataArray[i].msg_buf[msgLen-1],data,size);
				gRetryDataArray[i].msg_len += size;
				msgLen = gRetryDataArray[i].msg_len;
				// add LargeHeader length
				pLargeHeader = (tSpiLargePktHeader*)(gRetryDataArray[i].msg_buf);
				pLargeHeader->LEN_H8 = gRetryDataArray[i].msg_len >> 8 & 0xff;
				pLargeHeader->LEN_L8 = gRetryDataArray[i].msg_len & 0xff;
				// large package checksum
				uint8_t checkSum  = nubSpiUtil_GenerateCheckSum(gRetryDataArray[i].msg_buf, msgLen-1);
				gRetryDataArray[i].msg_buf[msgLen-1] = checkSum;
				insertFlag = 1;
				//break;
			}
		}


		// new a Large Package
		if((insertFlag == 0))
		{
			if(nubSpiRt_Size() < TBOX_SPI_CACHE_MAX)
			{
				//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d][ new large Package 222 !!!]", __FUNCTION__, __LINE__);
				insertFlag = nvdSpi_ConstructLargePackage(SPI_SEND, data, size);
			}else
			{
				//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d][ new large Package failed because FULL !!!]", __FUNCTION__, __LINE__);
			}

		}
		else
		{
			//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d][ Add data to Large Package Done ]", __FUNCTION__, __LINE__);
		}
	}else
	{
		// new package and insert Package into Array
		//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d][ new large Package 111 !!!]", __FUNCTION__, __LINE__);
		insertFlag = nvdSpi_ConstructLargePackage(SPI_SEND, data, size);
	}
	OS_unlock(gMutex);
	if(insertFlag)
	{
		return TBOX_SPI_SUCESS;
	}else
	{
		//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d][ new large Package insert NG !!!]", __FUNCTION__, __LINE__);
		return TBOX_SPI_FAILED;
	}
}

int32_t nuwSpi_SendMsg(uint8_t action, uint8_t type, uint8_t index,uint8_t *data, uint8_t size,eSendType sendType)
{

	int32_t ret = 0;
	uint8_t sum = 0;
	uint8_t *buffer = NULL;
	uint16_t length = 0;
	tSpiSmallPktHeader *pHeader = NULL;
	length = TBOX_SPI_PROTOCOL_SMALL_DATA_MIN_LEN + size;
	/* length must < 255 otherwish return -1*/
	if(length > (SPI_COMM_TRANSER_SIZE))
	{
		ret = -1;
		return ret;
	}
	memset(gSpitHeaderSend,0,SPI_COMM_TRANSER_SIZE);
	pHeader = (tSpiSmallPktHeader*)gSpitHeaderSend;
	pHeader->FBH = TBOX_SPI_PROTOCOL_SMALL_PACKET_HEADER_FIRST;
	pHeader->LBH = TBOX_SPI_PROTOCOL_SMALL_PACKET_HEADER_LAST;
	pHeader->TOC = type;
	pHeader->IOC = index;
	pHeader->SCT = 0x00;	//Fix me
	pHeader->LEN = length;
	if(data!=NULL)
	{
		memcpy(&pHeader->TOP,data,size);
	}
	/*Check Sum*/
	buffer = (uint8_t*)pHeader;
	sum = nubSpiUtil_GenerateCheckSum(buffer,length - 1);
	buffer[length-1] = sum;
	if(SPI_SEND_CACHE == sendType)
	{
		ret = nubSpi_SendDataToCache(buffer, length);
	}
	return ret;
}

void nvdSpi_SearchSPILargePkt(uint8_t *buff, uint32_t size,uint8_t *parseLargeBuff, uint32_t *parseLargeSize)
{
    uint8_t *tem_addrs = buff;
    uint16_t index = 0;
    for(index = 0;index < size;index++)
    {
            if((TBOX_SPI_PROTOCOL_LARGE_PACKET_HEADER_FIRST == tem_addrs[0])&&(TBOX_SPI_PROTOCOL_LARGE_PACKET_HEADER_LAST == tem_addrs[1]))
            {
                    memcpy(parseLargeBuff,tem_addrs,size-index);
#if 0
                    JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] recv data : %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x index=%02x ", __FUNCTION__, __LINE__,parseBuff[0],parseBuff[1],parseBuff[2],parseBuff[3],parseBuff[4],parseBuff[5],\
                            parseBuff[6],parseBuff[7],parseBuff[8],parseBuff[9],index);
#endif
                    break;
            }
            tem_addrs++;
    }
    *parseLargeSize = size - index;
return;
}
void nvdSpi_GeneralProcess(uint16_t eventCode)
{
	uint8_t type = 0;
	uint8_t index = 0;
	uint8_t mcuSysFlag = TBOX_MCU_UPDATE_FLAG;
	switch(eventCode)
	{
	case EV_SPI_MCU_RECV_MPU_REQUEST_HAND_SHAKE_1:
		/* mcu handshake connecting */
		//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] handshake 1", __FUNCTION__, __LINE__);
		type = (EV_SPI_MCU_SEND_MPU_RESPOND_HAND_SHAKE_1) >> 8 & 0xFF;
		index = EV_SPI_MCU_SEND_MPU_RESPOND_HAND_SHAKE_1 & 0xFF;
		nuwSpi_SendMsg(SPI_SEND, type, index, &mcuSysFlag, (uint8_t)TBOX_MCU_UPDATE_FLAG_SIZE, SPI_SEND_CACHE);
		if(gSpiConnectStatus != SPI_ESTABLISHED)
		{
			gSpiConnectStatus = SPI_ESTABLISHED;
		}
		break;

	case EV_SPI_MCU_RECV_MPU_REQUEST_HAND_SHAKE_2:
		/* mcu handshake sucess */
		//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] handshake 2", __FUNCTION__, __LINE__);
		gSpiConnectStatus = SPI_ESTABLISHED;
		break;

	case EV_SPI_MCU_RECV_MPU_REQUEST_SECRET_KEY:
		/* secret key*/
		break;

	default:
		break;
	}

}
void nvdSpi_DataParse(uint8_t *buffer, uint8_t size, uint8_t isError)
{
	tSpiSmallPktHeader *pHeader = NULL;
	uint8_t index = 0x00;
    uint8_t type = 0x00;
    uint8_t data[SPI_COMM_TRANSER_SIZE] = {0};
    uint16_t EventCode = 0x0000;
	OS_Error sendRet =OS_ERROR_NG;
    eSpiModulId moduleId = SPI_MODULE_ID_MAX;
    uint8_t ret = 0x00;
	if(buffer != NULL)
	{
		pHeader = (tSpiSmallPktHeader*)buffer;
		type = pHeader->TOC;
		index = pHeader->IOC;
		memcpy(data,&(pHeader->TOP),(size - TBOX_SPI_PROTOCOL_SMALL_DATA_MIN_LEN));
		EventCode = (type << 8 & 0xFF00) + index;
		//JPCC_DEBUG( SPI_LOG_LEVEL, "[ SPI ][%s:%d] nvdSpi_DataParse type: %02x  index: %02x", __FUNCTION__, __LINE__,type,index);

		if(EventCode <= 0x00FF)	//GENERAL
		{
			nvdSpi_GeneralProcess(EventCode);
			return;
		}
		else if(EventCode >= 0xF000 && EventCode < 0xF100)	//POWER
		{
			 ret = OS_sndMsg(MSG_ID_POWERMGR,EventCode,NULL,0,OS_WAIT_INFINITE);
		}
		else if(EventCode >= 0x1200 && EventCode < 0x1400)	//SYSTEM
		{
			moduleId = SPI_MODULE_SYSTEM_ID;
		}
		else if(EventCode >= 0x1400 && EventCode < 0x1600)	//BLE
		{
			moduleId = SPI_MODULE_BLE_ID;
		}
		else if(EventCode >= 0x1600 && EventCode < 0x1800)	//MODEM
		{
			moduleId = SPI_MODULE_MODEM_ID;
		}
		else if(EventCode >= 0x1800 && EventCode < 0x1a00)	//CAN
		{
			/* moduleId = SPI_MODULE_CAN_ID; */
			 ret = OS_sndMsg(MSG_ID_CANAPP,EventCode,&(pHeader->TOP),pHeader->LEN,OS_WAIT_INFINITE);
		}
		else if(EventCode >= 0x1a00 && EventCode < 0x1c00)	//DIAGNOSTIC
		{
			moduleId = SPI_MODULE_DIAGNOSTIC_ID;
		}
		else if(EventCode >= 0x1c00 && EventCode < 0x1e00)	//UPGRADE
		{
			moduleId = SPI_MODULE_UPGRADE_ID;
		}
		else if(EventCode >= 0x1e00 && EventCode < 0x2000)	//SHARE TASK
		{
			//moduleId = SPI_MODULE_RTC_ID;
			sendRet = OS_sndMsg(MSG_ID_SHARETASK, EventCode, (void *)data, 9, OS_WAIT_INFINITE);
			if(sendRet != OS_ERROR_OK)
			{
				//retry and print error code
			}
		}
		else if(EventCode >= 0x2000 && EventCode < 0x2100)	//XCALL
		{
			moduleId = SPI_MODULE_XCALL_ID;
		}
		else if(EventCode >= 0x2100 && EventCode < 0x2200)	//Sensor
		{
			moduleId = SPI_MODULE_SENSOR_ID;
		}
		else if(EventCode >= 0x2200 && EventCode < 0x2400)	//Jtools
		{
			//moduleId = SPI_MODULE_JTOOLS_ID;
			ret = OS_sndMsg(MSG_ID_PCTOOLS,EventCode,data,(size-TBOX_SPI_PROTOCOL_SMALL_DATA_MIN_LEN),OS_WAIT_INFINITE);
		}
		else if(EventCode >= 0x2400 && EventCode < 0x2500)	//Eeprom
		{
			moduleId = SPI_MODULE_EEPROM_ID;
		}
		else if(EventCode >= 0x2500 && EventCode < 0x2600)	//SpareBattery
		{
			moduleId = SPI_MODULE_SPAREBATTERY_ID;
		}
		else if(EventCode >= 0x2700 && EventCode < 0x2900)	//	DTC
		{
			moduleId = SPI_MODULE_DTC_ID;
		}
		else if(EventCode >= 0x2A00 && EventCode < 0x2B00)	//	IMU
		{
			moduleId = SPI_MODULE_IMU_ID;
		}
		else if(EventCode >= 0x2B00 && EventCode < 0x2C00)	//	System Monitor
		{
			moduleId = SPI_MODULE_SYS_MONITOR;
		}
	}

	if((moduleId < SPI_MODULE_ID_MAX) && (NULL != gRegisterArray[moduleId].registerFunc))
	{
		gRegisterArray[moduleId].registerFunc(EventCode,data,(size-TBOX_SPI_PROTOCOL_SMALL_DATA_MIN_LEN));
	}
	return;
}
void nvdSpi_ParsePkt(uint8_t *msg_data, uint32_t msg_len)
{
	uint32_t parseSize = msg_len;
	tSpiSmallPktHeader *pHeader = NULL;
	uint8_t parse_flag = 1;
	uint8_t sum = 0;
	uint16_t n = 0;

	 /* Determine the validity of the input parameters */
	if ((NULL == msg_data) || (msg_len < TBOX_SPI_PROTOCOL_SMALL_DATA_MIN_LEN))
	{
		//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] Input Error!!", __FUNCTION__, __LINE__);
		parse_flag = 0;
		return;
	}

	memset(gProcRcvData,0,SPI_COMM_TRANSER_SIZE);
	memcpy(gProcRcvData,msg_data,msg_len);

	while (1 == parse_flag)
	{
        pHeader = (tSpiSmallPktHeader *)&gProcRcvData[0];
    	if ((pHeader->FBH == TBOX_SPI_PROTOCOL_SMALL_PACKET_HEADER_FIRST)&&(pHeader->LBH == TBOX_SPI_PROTOCOL_SMALL_PACKET_HEADER_LAST))
		{
			if((pHeader->LEN <= msg_len) && (pHeader->LEN >= TBOX_SPI_PROTOCOL_SMALL_DATA_MIN_LEN))
			{
				// Calc the checksum
				for (n = 0; n < pHeader->LEN; n++)
				{
					sum ^= gProcRcvData[n];
				}

				if (sum == 0)	// Checksum is right
				{
					nvdSpi_DataParse(gProcRcvData, pHeader->LEN, 0);

					parseSize -= pHeader->LEN;
					if (parseSize > 0)
					{
						//JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] parseSize > 0 need to ayalize data !!!", __FUNCTION__, __LINE__);
						memset(gTempProcBuffer, 0, SPI_COMM_TRANSER_SIZE);
						memcpy(gTempProcBuffer, &gProcRcvData[pHeader->LEN], parseSize);
						memset(gProcRcvData, 0, SPI_COMM_TRANSER_SIZE);
						memcpy(gProcRcvData, gTempProcBuffer, parseSize);
					}
					else
					{
						parse_flag = 0;
					}
				}
				else
				{
					//JPCC_DEBUG(JPCC_LOG_LEVEL_ERROR, "[ SPI ][%s:%d] Small Package Checksum Error!!", __FUNCTION__, __LINE__);
					parse_flag = 0;
				}
			}
			else
			{
				// Input data length is wrong
				parse_flag = 0;
			}
		}
		else
		{
			// Input data is wrong
			parse_flag = 0;
		}
	}
	return;
}
void nvdSpi_SearchSPIPkt(uint8_t *buff, uint32_t size,uint8_t *parseBuff, uint32_t *parseSize)
{
        uint8_t *tem_addrs = buff;
        uint16_t index = 0;
        for(index = 0;index < size;index++)
        {
                if((TBOX_SPI_PROTOCOL_SMALL_PACKET_HEADER_FIRST == tem_addrs[0])&&(TBOX_SPI_PROTOCOL_SMALL_PACKET_HEADER_LAST == tem_addrs[1]))
                {
                        memcpy(parseBuff,tem_addrs,size-index);
#if 0
                        JPCC_DEBUG(SPI_LOG_LEVEL, "[ SPI ][%s:%d] recv data : %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x index=%02x ", __FUNCTION__, __LINE__,parseBuff[0],parseBuff[1],parseBuff[2],parseBuff[3],parseBuff[4],parseBuff[5],\
                                parseBuff[6],parseBuff[7],parseBuff[8],parseBuff[9],index);
#endif
                        break;
                }
                tem_addrs++;
        }
        *parseSize = size - index;
    return;
}
void nvdSpi_HandleMultipleSmallData(uint8_t* largeData, uint32_t largeLen)
{
	// get small package
	uint8_t smallTempData[SPI_COMM_TRANSER_SIZE] = {0};
	uint32_t smallDataSize = 0;
	memset(smallTempData,0,SPI_COMM_TRANSER_SIZE);
	nvdSpi_SearchSPIPkt(largeData,largeLen,smallTempData,&smallDataSize);
	memset(largeData, 0, SPI_COMM_TRANSER_SIZE);
	memcpy(largeData, smallTempData, smallDataSize - 1);
	nvdSpi_ParsePkt(largeData, smallDataSize - 1);
}

void nvdSpi_ParseLargePkt(uint8_t *msg_data, uint32_t msg_len)
{
	tSpiLargePktHeader *pLargeHeader = NULL;
	uint32_t largePackageLen = 0;
	uint8_t largeSum = 0;
	uint16_t n = 0;

	 /* Determine the validity of the input parameters */
	if ((NULL == msg_data) || (msg_len < TBOX_SPI_PROTOCOL_LARGE_DATA_MIN_LEN))
	{
		//JPCC_DEBUG(JPCC_LOG_LEVEL_ERROR, "[ SPI ][%s:%d] Input Large Package Error!!", __FUNCTION__, __LINE__);
		return;
	}

	pLargeHeader = (tSpiLargePktHeader *)msg_data;

   	if ((pLargeHeader->FBH == TBOX_SPI_PROTOCOL_LARGE_PACKET_HEADER_FIRST)&&(pLargeHeader->LBH == TBOX_SPI_PROTOCOL_LARGE_PACKET_HEADER_LAST))
		{
			largePackageLen = ((pLargeHeader->LEN_H8 << 8) & 0xff00) + (pLargeHeader->LEN_L8 & 0xff);
			if((largePackageLen <= msg_len) && (largePackageLen >= TBOX_SPI_PROTOCOL_LARGE_DATA_MIN_LEN))
			{
				// Calc the checksum
				for (n = 0; n < largePackageLen; n++)
				{
					largeSum ^= msg_data[n];
				}
				if (largeSum == 0)	// Checksum is right
				{
					// handle Multiple small package
					if(largePackageLen > TBOX_SPI_PROTOCOL_LARGE_DATA_MIN_LEN)
					{
						nvdSpi_HandleMultipleSmallData(msg_data, largePackageLen);
					}
				}
				else			// Checksum is Wrong
				{
					//JPCC_DEBUG(JPCC_LOG_LEVEL_ERROR, "[ SPI ][%s:%d] CheckSum is Error!!", __FUNCTION__, __LINE__);
					if(largePackageLen > TBOX_SPI_PROTOCOL_LARGE_DATA_MIN_LEN)
					{
						nvdSpi_HandleMultipleSmallData(msg_data, largePackageLen);
					}
					/* ack check sum error*/
				}
			}
			else
			{
				// Input data length is wrong
				//JPCC_DEBUG(JPCC_LOG_LEVEL_ERROR, "[ SPI ][%s:%d] Input Large Package Length is Error!!", __FUNCTION__, __LINE__);
			}
		}
		else
		{
			// Input data is wrong
			//JPCC_DEBUG(JPCC_LOG_LEVEL_ERROR, "[ SPI ][%s:%d] Input Large Package Header is Error!!", __FUNCTION__, __LINE__);
		}
}

void nvdSpi_HandleLargePkt(uint8_t *largeData, uint32_t LargeSize)
{
	uint32_t rcvDataSize = 0;
	memset(gCheckRcvData,0,SPI_COMM_TRANSER_SIZE);
	nvdSpi_SearchSPILargePkt(largeData, LargeSize, gCheckRcvData, &rcvDataSize);
	if(rcvDataSize == 0)
	{
    	//JPCC_DEBUG(JPCC_LOG_LEVEL_ERROR, "[ SPI ][%s:%d] Recv Data error rcvDataSize == 0!!!", __FUNCTION__, __LINE__);
    	return;
	}
	memset(gRcvData.msg_buf, 0, SPI_COMM_TRANSER_SIZE);
	memcpy(gRcvData.msg_buf, gCheckRcvData, rcvDataSize);
	gRcvData.msg_len = rcvDataSize;
	nvdSpi_ParseLargePkt(gRcvData.msg_buf, gRcvData.msg_len);
}
void nvdSpi_StandbyOut()
{
	//uint8_t aubTaskID = TSK_ID_SPI_MANAGER;
	// init SPI driver
	// SPI2_Initialization_Func();

	if(gStartFlag == 0)
	{
		nvdSpi_Init();
	}
	//wvdPowerMgr_CallBack(MSG_POWER_MGR_RES_STANDBYOUT, &aubTaskID, sizeof(Type_uByte));
}

void nvdSpi_StandbyIn()
{
	//uint8_t aubTaskID = TSK_ID_SPI_MANAGER;
	//wvdPowerMgr_CallBack(MSG_POWER_MGR_RES_STANDBYIN, &aubTaskID, sizeof(Type_uByte));
}
void nvdCommManagerMsgProc(SpiCommMsg_st * MsgRx)
{
	uint8_t type = 0;
	uint8_t index = 0;

	if(MsgRx!=NULL)
	{
		switch(MsgRx->event_code)
		{
			case EV_SPI_MCU_SEND_MCU_STANDBY_OUT:
				//nvdSpi_StandbyOut();
				return;
			case EV_SPI_MCU_SEND_MCU_STANDBY_IN:
				//nvdSpi_StandbyIn();
				return;
			case EV_SPI_MCU_SEND_MCU_SPI_DRIVER_INIT:
				//nvdSpi_InitDriver();
				return;
			//case EVENT_TASK_ALIVE:
				//wubSysMonitor_SendMessage(EVENT_TASK_ALIVE_ACK, 0x00, 0x00);
				//return;
			default:
				break;
		}

		index = (uint8_t)(MsgRx->event_code & 0xFF);
		type = (uint8_t)(MsgRx->event_code >>8 & 0xFF);
		nuwSpi_SendMsg(SPI_SEND, type, index,MsgRx->data_buff, MsgRx->data_size, SPI_SEND_CACHE);
	}
}
void SPI2_InterruptCallBack( uint8_t *DATA )
{
	if(NULL != DATA)
	{
		gRecvCounter++;
		gSendCounter = gRecvCounter;
		if(gRecvArray[0].isBusy == 0)
		{
			memcpy(gRecvArray[0].msg_buf, DATA, SPI_COMM_TRANSER_SIZE);
			gRecvArray[0].isBusy = 1;
		}else if(gRecvArray[1].isBusy == 0)
		{
			memcpy(gRecvArray[1].msg_buf, DATA, SPI_COMM_TRANSER_SIZE);
			gRecvArray[1].isBusy = 1;
		}
		OS_post(spiRecvSemaphore);
		//memcpy(gTempRecvBuffer, DATA, SPI_COMM_TRANSER_SIZE);
		//OSIF_SemaPost(spiRecvSemaphore);
	}
}
static void manager_on_task_init()
{
	nvdSpi_Init();
}

static void manager_on_recv_msg(uint16_t event_code, void* data, uint32_t data_size)
{
	Msg.event_code = event_code;
	Msg.data_buff = data;
	Msg.data_size = data_size;

	nvdCommManagerMsgProc(&Msg);
}

static void manager_on_recv_time_out()
{

}

static void manager_on_loop()
{

}

uint8_t test1=0;
static void send_on_task_init()
{
	 //WDOG_disable();		   /* Disable WDOG */
	 // SOSC_init_8MHz();        /* Initialize system oscillator for 8 MHz xtal */
	//  SPLL_init_160MHz();      /* Initialize SPLL to 160 MHz with 8 MHz SOSC */
	 // NormalRUNmode_80MHz();
//	 SPI0_init();
	      /* Initialize LPSPI 1 as master */
	  PTD->PDDR |= 1<<6;
	  PTD->PSOR |= 1<<6;
	  test1=1;
}

static void send_on_recv_msg(uint16_t event_code, void* data, uint32_t data_size)
{
	( void ) event_code;
    ( void ) data;
	( void ) data_size;
}
uint32_t spi_send_delay = 0;
static void send_on_recv_time_out()
{

#if 0
#if 0
	// check cycType
	if(gSpiCycType != SPI_CYC_NORMAL)
	{
		if(gPG6Flag == 0)
		{
			//GPIO_ACTIVE_LOW(PI_14);
			gPG6Flag = 1;
		}
		OS_sleep(TBOX_SPI_HANDSHAKE_CYC_TIME_50);
		return;
	}
	gPG6Flag = 0;
#endif
	//delete this for NIO because gpio is not sure

	if(SPI_ESTABLISHED == gSpiConnectStatus)
	{
		if(PI_15_Status == GPIO_INPUT_Port_Lev_Read(PTA,PIN_INDEX_31))
		{
			if(gSpiWaitCounter <= TBOX_SPI_WAIT_PIN_CHANGE_COUNT ) //GPIO_INPUT_Port_Lev_Read(PTA,PIN_INDEX_31);
			{
    			gSpiWaitCounter++;
    			//OS_sleep(TBOX_SPI_CYC_TIME_5);
    			return;
			}else
			{
				gSpiWaitCounter = 0;
				//JPCC_DEBUG(JPCC_LOG_LEVEL_INFO, "[ SPI ] WAITE SOC SOC PI_15 50ms");
			}
		}else
		{
			//PI_15_Status = GPIO_Read(PI_15);
			PI_15_Status = GPIO_INPUT_Port_Lev_Read(PTA,PIN_INDEX_31);
			gSpiWaitCounter = 0;
		}
	}else
	{
		//PI_15_Status = GPIO_Read(PI_15);
		PI_15_Status = GPIO_INPUT_Port_Lev_Read(PTA,PIN_INDEX_31);
	}
#endif

	// get send data from array
#if 0
	OS_lock(gMutex);
	if(!nubSpiRt_IsEmpty())
	{
		gSendData = nvdSpiRt_Get(0);
		memcpy(gTempSendBuffer, gSendData.msg_buf, SPI_COMM_TRANSER_SIZE);

	}else
	{
		memset(gTempSendBuffer, 0x00, SPI_COMM_TRANSER_SIZE);
	}
	OS_unlock(gMutex);
#endif
	memset(gTempSendBuffer, 0x0A, SPI_COMM_TRANSER_SIZE);
	// Send data at here
//	DMA0_TCD_init(gTempSendBuffer,512);
	PTD->PCOR |= 1<<6;
	//OS_sleep(1);
	PTD->PSOR |= 1<<6;
	//DISABLE_INTERRUPTS(); //zhoulx delete this for HVB532
	//GPIO_ACTIVE_HIGH(PI_14);
	//SPI2_Data_Transmit_Func(gTempSendBuffer, SPI_COMM_TRANSER_SIZE);
	//GPIO_ACTIVE_LOW(PI_14);
	//GPIO_ACTIVE_HIGH(PI_14);
	//ENABLE_INTERRUPTS();

	// delete data from array
	OS_lock(gMutex);
	if(nubSpiRt_Size()>0)
	{
		nvdSpiRt_Remove(0);
	}
	OS_unlock(gMutex);
	// Send counter add
	gSendCounter++;
	// check connect status and dtc
#if 0
	if(gSpiConnectStatus == SPI_ESTABLISHED)
	{
		nvdSpi_JugeConnectStatus(gSendCounter - gRecvCounter);
	}
	else
	{
		gRecvCounter = gSendCounter;

		if(gSendCounter < TBOX_SPI_MPU_START_COUNT)
		{
			nvdSpi_DtcCheckProcess(gSendCounter - gRecvCounter);
		}else
		{
			//nvdSpi_InitDriver();
			nvdSpi_DtcCheckProcess(gSendCounter);
		}
	}
	//OS_sleep(TBOX_SPI_CYC_TIME_5);
#endif

}

static void send_on_loop()
{
	uint32_t i = 0;
	OS_lock(gMutex);
	if(!nubSpiRt_IsEmpty())
	{
		gSendData = nvdSpiRt_Get(0);
		memcpy(gTempSendBuffer, gSendData.msg_buf, SPI_COMM_TRANSER_SIZE);

	}else
	{
		memset(gTempSendBuffer, 0x00, SPI_COMM_TRANSER_SIZE);
	}
	OS_unlock(gMutex);

//		DMA0_TCD_init(gTempSendBuffer,512);
		PTD->PCOR |= 1<<6;
		while(i<15000)
		{
			i++;
		}
		//OS_sleep(1);
		PTD->PSOR |= 1<<6;
		//DISABLE_INTERRUPTS(); //zhoulx delete this for HVB532
		//GPIO_ACTIVE_HIGH(PI_14);
		//SPI2_Data_Transmit_Func(gTempSendBuffer, SPI_COMM_TRANSER_SIZE);
		//GPIO_ACTIVE_LOW(PI_14);
		//GPIO_ACTIVE_HIGH(PI_14);
		//ENABLE_INTERRUPTS();

		// delete data from array
		OS_lock(gMutex);
		if(nubSpiRt_Size()>0)
		{
			nvdSpiRt_Remove(0);
		}
		OS_unlock(gMutex);
		// Send counter add
		gSendCounter++;
		OS_sleep(100);
		// check connect status and dtc
}
static void recv_on_task_init()
{
	nvdSpi_RecvInit();
	SPI_Set_Call_Back_Func( SPI2_InterruptCallBack, 0 );  /* Set the callback function for interrupt */
}

static void recv_on_recv_msg(uint16_t event_code, void* data, uint32_t data_size)
{
	( void ) event_code;
    ( void ) data;
	( void ) data_size;
}

static void recv_on_recv_time_out()
{

}

static void recv_on_loop()
{
#if 1
	status_t status;
	 OS_wait(spiRecvSemaphore,0xFFFFFFFF);
	//if(status == STATUS_SUCCESS)
	//{
		//status = STATUS_ERROR;
		if(gRecvArray[0].isBusy == 1)
		{
			memcpy(gRcvData.msg_buf, gRecvArray[0].msg_buf, SPI_COMM_TRANSER_SIZE);
			gRecvArray[0].isBusy = 0;
		}else if(gRecvArray[1].isBusy == 1)
		{
			memcpy(gRcvData.msg_buf, gRecvArray[1].msg_buf, SPI_COMM_TRANSER_SIZE);
			gRecvArray[1].isBusy = 0;
		}
		// Handle Recv Data
		//memcpy(gRcvData.msg_buf, gTempRecvBuffer, SPI_COMM_TRANSER_SIZE);
		nvdSpi_HandleLargePkt(gRcvData.msg_buf, SPI_COMM_TRANSER_SIZE);
	//}
#endif
}
void* SpiManager_getTaskParam()
{
	Manager_Param.queue_id = MSG_ID_SPIMANAGER;
	Manager_Param.wait_time = 500;  //ms
	Manager_Param.task_init = manager_on_task_init;
	Manager_Param.recv_msg = manager_on_recv_msg;
	Manager_Param.time_out = manager_on_recv_time_out;
	Manager_Param.loop = manager_on_loop;
    return &Manager_Param;
}
void* SpiSend_getTaskParam()
{
	Send_Param.queue_id = MSG_ID_SPISEND;
	//Send_Param.wait_time = 1000;  //ms
	Send_Param.task_init = send_on_task_init;
	//Send_Param.recv_msg = send_on_recv_msg;
	//Send_Param.time_out = send_on_recv_time_out;
	Send_Param.loop = send_on_loop;
	return &Send_Param;
}
void* SpiRecv_getTaskParam()
{
	Revc_Param.queue_id = MSG_ID_SPIRECV;
	//Revc_Param.wait_time = 500;  //ms
	Revc_Param.task_init = recv_on_task_init;
	//Revc_Param.recv_msg = recv_on_recv_msg;
	//Revc_Param.time_out = recv_on_recv_time_out;
	Revc_Param.loop = recv_on_loop;
    return &Revc_Param;
}
