#include "srio_slave.h"
#include "com.h"
#include "common.h"
#include "CPB_Module_Main.h"
#include "CPB_Module.h"
#include "data_indicator.h"
#include "environment.h"
#include "CPB_Global.h"
/* Time stamp includes */

int gGpioLedFlag = 0;
typedef struct
{
	unsigned int cpb_status;
}TStatus_Data;

TSRIOPacket *SrioSlavePacket;
TStatus_Data *Status_Data;
#pragma DATA_SECTION(SRIOTempBuffer, "cache");
#pragma DATA_ALIGN(SRIOTempBuffer, 8);
#pragma DATA_SECTION(SrioSlavePacket, ".cache");
#pragma DATA_ALIGN(SrioSlavePacket, 8);
#pragma DATA_SECTION(Status_Data, ".cache");
#pragma DATA_ALIGN(Status_Data, 8);
unsigned char SRIOTempBuffer[8192];
int SRIOTempBufferPosition = 0;

#pragma DATA_ALIGN(SRIOEchoBuffer, 8);
unsigned int SRIOEchoBuffer[1024];



TStudyData_SPB StudyData_FromSPB;
volatile unsigned int processing_status = CPB_PROCESSING_READY;

unsigned int transfer_addr;
int transfer_size = 0;
int *ptr;
void Srio_Slave_Init()
{
	SrioSlavePacket = (TSRIOPacket*)(SRIO_SLAVE_DATA_BASE_ADDRESS+SRIO_SLAVE_L2_CORE_INTERVAL*CPB_CORE_NUMBER);
	Status_Data = (TStatus_Data*)(SRIO_SLAVE_STATUS_BASE_ADDRESS+SRIO_SLAVE_L2_CORE_INTERVAL*CPB_CORE_NUMBER);
	memset(SrioSlavePacket, 0x00, sizeof(TSRIOPacket));
//	Status_Data->cpb_status = 100;
}

void Srio_Slave_Process()
{
	int packet_index = 0;
	unsigned int checksum;
	
//	Set_Status();
	if(SrioSlavePacket->CompleteSW==SRIO_TRANSFER_COMPLETE_CODE)
	{
		SrioSlavePacket->CompleteSW = 0;
		if(SrioSlavePacket->SRIO_State == SRIO_STATE_RECEIVE_REQUEST)
		{
			Srio_Packet_Process(packet_index);
		}
		else 
		{
			checksum = CheckSum((unsigned int *)&SrioSlavePacket->PRI_Indicator, SrioSlavePacket->DataLength_Word + SRIO_PACKET_HEADER_SIZE_WORD - 3);
			if(checksum != SrioSlavePacket->SPB_CheckSum)
			{
				SrioSlavePacket->SPB_CheckSum = checksum;
				SrioSlavePacket->SRIO_State = SRIO_STATE_READ_ERR_CHECKSUM; // checksum error
			}
			else if(SrioSlavePacket->DataLength_Word > SRIO_PACKET_DATA_SIZE_WORD)
			{
				SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_ERR_SIZE;
			}
			else
			{
				Srio_Packet_Process(packet_index);
			}
		}
	}
	
}


void Srio_Packet_Process(int packet_index)
{
	int elementLength_word;
	int dataPos;
	int ImageWidth;
	unsigned char *dstAddress, *srcAddress;

	if (SrioSlavePacket->SRIO_State == SRIO_STATE_SEND_REQUEST)
	{
		if (SrioSlavePacket->Address == 0)
		{
	//		Lamp1On();
		}
		if(SrioSlavePacket->SEC_Indicator == IND_IMAGE_BUFFER_1)
		{
			if(TabletCharacter.HighResolutionImage)
				ImageWidth = HD_IMAGE_WIDTH;
			else
				ImageWidth = MAX_IMAGE_WIDTH;
			
			elementLength_word = SrioSlavePacket->DataLength_Word / SrioSlavePacket->FrameCount;
			dstAddress = ReadData_GetAddress(SrioSlavePacket->SEC_Indicator);
			if (dstAddress != NULL)
			{
				for(dataPos = 0; dataPos < SrioSlavePacket->FrameCount; dataPos++)
				{
					memcpy(dstAddress + SrioSlavePacket->Address + ImageWidth * dataPos,
						(unsigned char*)SrioSlavePacket->Data + elementLength_word * sizeof(unsigned int) * dataPos,
						elementLength_word * sizeof(unsigned int));
				}
				SrioSlavePacket->SRIO_State = SRIO_STATE_READ_COMPLETE;
			}
			else
			{
				SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_ERR_ADDRESS;
				return ;
			}
		}
		else if(SrioSlavePacket->SEC_Indicator == IND_IMAGE_BUFFER_3D)
		{
			ImageWidth = SYSTEM_CAMERA_WIDTH_3D;
			elementLength_word = SrioSlavePacket->DataLength_Word / SrioSlavePacket->FrameCount;
			dstAddress = ReadData_GetAddress(SrioSlavePacket->SEC_Indicator);
			if (dstAddress != NULL)
			{
				for(dataPos = 0; dataPos < SrioSlavePacket->FrameCount; dataPos++)
				{
					memcpy(dstAddress + SrioSlavePacket->Address + ImageWidth * dataPos,
						(unsigned char*)SrioSlavePacket->Data + elementLength_word * sizeof(unsigned int) * dataPos,
						elementLength_word * sizeof(unsigned int));
				}
				SrioSlavePacket->SRIO_State = SRIO_STATE_READ_COMPLETE;
			}
			else
			{
				SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_ERR_ADDRESS;
				return ;
			}
		}
		else
		{
			if (SrioSlavePacket->Address == 0)
			{
//				Lamp1On();
			}
			if (SrioSlavePacket->PRI_Indicator == PRI_IND_PROCESSING)
			{
				dstAddress = ReadData_GetAddress(SrioSlavePacket->SEC_Indicator);
				if (dstAddress != NULL)
				{
					memcpy(dstAddress + SrioSlavePacket->Address, SrioSlavePacket->Data, SrioSlavePacket->DataLength_Word * sizeof(unsigned int));
					SrioSlavePacket->SRIO_State = SRIO_STATE_READ_COMPLETE;
				}
			}
		}
//		SrioSlavePacket->SRIO_State = SRIO_STATE_READ_COMPLETE;
	}
	else if (SrioSlavePacket->SRIO_State == SRIO_STATE_SEND_LAST) // spb's write finished
	{
		SrioSlavePacket->SRIO_State = SRIO_STATE_PROCESSING_LAST;
		if (SrioSlavePacket->PRI_Indicator == PRI_IND_PROCESSING)
		{
			ReadData_Complete(SrioSlavePacket->SEC_Indicator, SrioSlavePacket->DataLength_Word);
		}
//		Lamp1Off();
		SrioSlavePacket->SRIO_State = SRIO_STATE_COMPLETE_LAST;
	}
	else if(SrioSlavePacket->SRIO_State == SRIO_STATE_RECEIVE_REQUEST)
	{
		if (SrioSlavePacket->PRI_Indicator == PRI_IND_SYSTEM)
		{
			srcAddress = WriteData_GetAddress(SrioSlavePacket->SEC_Indicator);
			if (srcAddress != NULL)
			{
				memcpy(SrioSlavePacket->Data, srcAddress + SrioSlavePacket->Address, SrioSlavePacket->DataLength_Word * sizeof(unsigned int));
				SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_COMPLETE;
				SrioSlavePacket->SPB_CheckSum = CheckSum((unsigned int *)&SrioSlavePacket->PRI_Indicator, SrioSlavePacket->DataLength_Word + (SRIO_TRANSFER_HEADER_SIZE/4 - 3));
			}
			else
			{
				SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_ERR_ADDRESS;
				return;
			}
		}
		else if (SrioSlavePacket->PRI_Indicator == PRI_IND_PROCESSING)
		{
			srcAddress = WriteData_GetAddress(SrioSlavePacket->SEC_Indicator);
			if (srcAddress != NULL)
			{
				memcpy(SrioSlavePacket->Data, srcAddress + SrioSlavePacket->Address, SrioSlavePacket->DataLength_Word * sizeof(unsigned int));
				SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_COMPLETE;
				SrioSlavePacket->SPB_CheckSum = CheckSum((unsigned int *)&SrioSlavePacket->PRI_Indicator, SrioSlavePacket->DataLength_Word + (SRIO_TRANSFER_HEADER_SIZE/4 - 3));
			}
			else
			{
				SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_ERR_ADDRESS;
				return;
			}
		}
		else
		{
			SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_ERR_INDICATOR; // checksum error
			return;
		}
//		SrioSlavePacket->SRIO_State = SRIO_STATE_WRITE_COMPLETE;
//		Lamp1Off();
	}
}

void Set_Status()
{
	Status_Data->cpb_status = processing_status;
//	BIT32_SET(Status_Data->cpb_status, SL_CPB_PROCESSING, processing_status);
}

void Set_Processing_Status(unsigned int status)
{
	processing_status = status;
	Status_Data->cpb_status = processing_status;
//	BIT32_SET(Status_Data->cpb_status, SL_CPB_PROCESSING, status);
}

int GetSRIOTempBufferDataSize()
{
	return SRIOTempBufferPosition;
}
void *GetSRIOTempBuffer()
{
	return SRIOTempBuffer;
}

void ClearSRIOTempBuffer()
{
	SRIOTempBufferPosition = 0;
}

void AddL2DataToSRIOTempBuffer(void *data, int size)
{
	memcpy(&SRIOTempBuffer[SRIOTempBufferPosition], data, size);
	SRIOTempBufferPosition += size;
}

void ReadStartSRIOTempBuffer()
{
	SRIOTempBufferPosition = 0;
}

void ReadL2DataFromSRIOTempBuffer(void *data, int size)
{
	memcpy(data, &SRIOTempBuffer[SRIOTempBufferPosition], size);
	SRIOTempBufferPosition += size;
}

void Buffer_Switching(int bufferIndex)
{
//
}


unsigned char *WriteData_GetAddress(unsigned int indicator)
{
	unsigned char *address = NULL;

	// unknown parameter ÀÏ ¶§ Ã³¸®

	if (indicator == IND_IMAGE_BUFFER_3D)
	{
		address = (unsigned char *) BayerImage;
	}
	else if (indicator == IND_IMAGE_BUFFER_1)
	{
		address = (unsigned char *) BayerImage;
	}
	else if (indicator == IND_INSPECTION_RESULT)
	{
		address = (unsigned char *) &DefectData_CPB;
	}
	else if (indicator == IND_3D_POSITION_INFO)
	{
		address = (unsigned char *) &ThreeDPositionInfo_CPB;
	}

	else if (indicator == IND_VIRTUAL_PROCESSING_RESULT)
	{
		address = (unsigned char *) smallSizeProcessedImage;
	}
	else if (indicator == IND_DEFECT_DATA)
	{
		address = (unsigned char *) &DefectInformation;
	}
	else if (indicator == IND_PROCESSING_RUNTIME)
    {
        address = (unsigned char *) &Processing_Run_Time;
    }
	else if (indicator == IND_STUDY_RESULT)
	{
		//address = (unsigned char *) &StudyData_CPB;
		address = (unsigned char *) &TabletStudyData;
	}
	else if (indicator == IND_CPB_IMAGE)
	{
		address = (unsigned char *) ThreeDImage_Temp;
	}
	else if (indicator == IND_INSPECTION_IMAGE)
	{
		address = (unsigned char *) InspectionArea_Temp;
	}
	else if (indicator == IND_INSPECTION_LABEL_IMAGE)
	{
		address = (unsigned char *) LabelImage_Virtual_Temp;
	}
	else if (indicator == IND_VIRTUAL_INSPECTION_INFO)
	{
		address = (unsigned char *) GetSRIOTempBuffer();
	}
	else if (indicator == IND_READ_COMPATIBILITY)
	{
		address = (unsigned char *) &CPBCompatibility;
	}
	else if (indicator == IND_ECHO)
	{
		address = (unsigned char *) SRIOEchoBuffer;
	}
	else
	{
		address = NULL;
	}
	return address;
}


unsigned char *ReadData_GetAddress(unsigned int indicator)
{
	unsigned char *address;

	if (indicator == IND_IMAGE_BUFFER_3D)
	{
		address = (unsigned char *) BayerImage;
	}
	else if (indicator == IND_IMAGE_BUFFER_1)
	{
		address = (unsigned char *) BayerImage;
	}
	else if (indicator == IND_SYS_SETUP)
	{
		address = (unsigned char *) &CPBSystemSetupData;
	}
	else if (indicator == IND_CHARACTER_DATA)
	{
		address = (unsigned char *) &TabletCharacter;
	}
	else if (indicator == IND_STUDY_DATA)
	{
		address = (unsigned char *) &TabletStudyData;
	}
	else if (indicator == IND_GRADE_DATA)
	{
		address = (unsigned char *) &TabletGradeData;
	}
	else if (indicator == IND_SETUP_DATA)
	{
		address = (unsigned char *) &TabletSetupData;
	}
	else if (indicator == IND_WHITE_BALANCE_DATA)
	{
		address = (unsigned char *) WhiteBalanceInfo;
	}
	else if (indicator == IND_SETUP_DATA_3D)
	{
		address = (unsigned char *) &Tablet3DSetupData;
	}
	else if (indicator == IND_ECHO)
	{
		address = (unsigned char *) SRIOEchoBuffer;
	}
	else if(indicator ==IND_INSPECTION || indicator ==IND_STUDY_POSITION || indicator ==IND_INSPECTION_POSITION)
	{
		address = (unsigned char *) &InspectData;
	}
	else if(indicator == IND_TPB_INSPECTION)
	{
		address = (unsigned char *) &InspectData_TPB;
	}	
	else
	{
		address = (unsigned char *) SRIOTempBuffer;
	}
	Set_Processing_Status(CPB_PROCESSING_READDATA);
	return address;
}

void ReadData_Complete(unsigned int indicator, unsigned int dataSize_Word)
{
	if (indicator == IND_INSPECTION)
	{
		Set_Processing_Status(CPB_PROCESSING_RUNNING);
		Process_Function = PROCESS_FUNC_INSPECTION;
		CurrentGlobalCamIndex = InspectData.CurrentCameraIndex;
	}
	else if (indicator == IND_SETUP_DATA)
	{
		Set_Processing_Status(CPB_PROCESSING_RUNNING);
		Process_Function = PROCESS_FUNC_SETUP;
	}
	else if (indicator == IND_STUDY)
	{
		ReadStartSRIOTempBuffer();
		ReadL2DataFromSRIOTempBuffer(&StudyData_FromSPB, sizeof(TStudyData_SPB));
		Set_Processing_Status(CPB_PROCESSING_RUNNING);
		Process_Function = PROCESS_FUNC_STUDY;
		CurrentGlobalCamIndex = StudyData_FromSPB.CurrentCameraIndex;
	}
	else if(indicator ==IND_STUDY_POSITION)
	{
		Set_Processing_Status(CPB_PROCESSING_RUNNING);
		Process_Function = PROCESS_FUNC_STUDY_POSITION;	
		CurrentGlobalCamIndex = InspectData.CurrentCameraIndex;		
	}
	else if(indicator ==IND_INSPECTION_POSITION)
	{
		Set_Processing_Status(CPB_PROCESSING_RUNNING);
		Process_Function = PROCESS_FUNC_INSPECTION_POSITION;	
		CurrentGlobalCamIndex = InspectData.CurrentCameraIndex;		
	}
	else if (indicator == IND_CLEAR)
	{
		ClearInspectionData();
		ClearThreeDPositionMultiCoreProcessing();
	}
	else if(indicator == IND_3D_MULTICORE_CLEAR)
	{
		ClearThreeDPositionMultiCoreProcessing();
	}
	else if (indicator == IND_SYS_SETUP)
	{

	}
	else if (indicator == IND_INVALIDATE_IMAGE)
	{
//		CACHE_invL2(BayerImage, MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT, CACHE_NOWAIT);
	}
	else if(indicator == IND_TPB_INSPECTION)
	{
		Set_Processing_Status(CPB_PROCESSING_RUNNING);
		Process_Function = PROCESS_FUNC_INSPECTION_TPB;		
	}
	
}
