#include "SPB_Processing.h"
#include "SPB_Module_Main.h"
#include "data_indicator.h"
#include "environment.h"

#ifdef TARGET_SPB
#include "nfa_camera.h"
#include "image_control.h"
#include "timer.h"
#include "system_setup.h"
#else
#include "Virtual_SPB_System.h"
#endif

#define	MIN_PROCESSING_TIME				10//50
#define	MAX_PROCESSING_TIME				450//50


#define	PROCESSING_MODE_NONE			0
#define	PROCESSING_MODE_STUDY			1
#define	PROCESSING_MODE_INSPECTION		2

TStudySetupData	StudySetupData_SPB;
TInspectData InspectData_SPB;

TProcessingData	ProcessingData;
TStudyData_SPB StudyData_SPB;
TTabletStudyData StudyData_From_CPB;

#pragma	DATA_ALIGN(TabletCharacter_SPB,	8)
#pragma	DATA_ALIGN(TabletStudyResultData_SPB, 8)
#pragma	DATA_ALIGN(TabletGradeData_SPB,	8)
#pragma	DATA_ALIGN(TabletSetupData_SPB,	8)
#pragma	DATA_ALIGN(Tablet3DSetupData_SPB, 8)
#pragma	DATA_ALIGN(StudyResultData_SPB,	8)

// For SELMA200, 20180222, Rev by moon
// Stack(IDRAM)초과로 인해 CPB로 전송되는 데이터를 외부메모리로 할당함
// 기존에 SetupData는 이미 외부 메모리에 잡아놓은 상태였으니 큰 문제는 없지 않을까 싶음                                           
#pragma	DATA_SECTION(TabletCharacter_SPB, ".sdram")
#pragma	DATA_SECTION(TabletStudyResultData_SPB, ".sdram")
#pragma	DATA_SECTION(TabletGradeData_SPB, ".sdram")              
#pragma	DATA_SECTION(StudyResultData_SPB, ".sdram")
//// end

#pragma	DATA_SECTION(TabletSetupData_SPB, ".sdram")
#pragma	DATA_SECTION(Tablet3DSetupData_SPB,	".sdram")
#pragma	DATA_SECTION(PrintMatchingResult_SPB,	".sdram")

//#pragma	DATA_SECTION(CPBProcessingType,	".sdram")
//#pragma	DATA_SECTION(AssignedSubcoreCount,	".sdram")
//#pragma	DATA_SECTION(GlobalAssignedSubCoreID,	".sdram")
//#pragma	DATA_SECTION(SplitProcessingCameraType,	".sdram")
//#pragma	DATA_SECTION(ActivePositionProcessingModule,	".sdram")
//#pragma	DATA_SECTION(MustAccessPositionProcessingModule,	".sdram")

TTabletCharacter TabletCharacter_SPB;
TTabletStudyResultData TabletStudyResultData_SPB;
TTabletGradeData TabletGradeData_SPB;
TTabletSetupData TabletSetupData_SPB;
TTablet3DSetupData Tablet3DSetupData_SPB;
TWhiteBalanceInfo WhiteBalanceInfo_SPB[SYSTEM_TOTAL_CAMERA_COUNT];

TStudyResultData_SPB StudyResultData_SPB[SYSTEM_SPB_CAMERA_COUNT];

char CPBStep[SYSTEM_CPB_COUNT];
int	CPBCamIndex[SYSTEM_CPB_COUNT];
int	CPBProcessingTabletListIndex[SYSTEM_CPB_COUNT];
unsigned int CPBProcessingStartTime[SYSTEM_CPB_COUNT];

TDefectData	DefectData_FromCPB;
TDefectInformation DefectInfo_CPB;
extern TThreeDPositionInfo ThreeDPositionInfo_SPB;
TDefectData_SPB	DefectData_SPB;

#pragma	DATA_ALIGN(ProcessingTimeList, 8)
TProcessingTime	ProcessingTimeList[SPB_TABLET_LIST_COUNT];

#pragma	DATA_ALIGN(CPBProcessingInfo_SPB, 8)
TCPBProcessingInfo CPBProcessingInfo_SPB;
int check_count = 0;
int cpb_index_table[SYSTEM_CPB_MAX_COUNT] = { 0,8,16,24,
1,9,17,25,
2,10,18,26,
3,11,19,27,
4,12,20,28,
5,13,21,29,
6,14,22,30,
7,15,23,31 };

unsigned int PrintMatchingResult_SPB[512][3];

#define MAX_CPB_MODULE_COUNT	4

// 멀티코어 구동을 관리.
int CPBProcessingType[SYSTEM_CPB_MAX_COUNT];
int AssignedSubcoreCount[SYSTEM_CPB_MAX_COUNT];
int GlobalAssignedSubCoreID[SYSTEM_CPB_MAX_COUNT][MAX_PROCESSING_CORE_COUNT];

// 멀티코어가 필요한 카메라를 지정.
int SplitProcessingCameraType[SYSTEM_SPB_CAMERA_COUNT];

// 멀티코어 3D Position Processing을 구동하기 위한 변수.
int MaxSplitPositionProcessingSubCoreCount;
int ActivePositionProcessingModule[MAX_CPB_MODULE_COUNT];
int MustAccessPositionProcessingModule[MAX_CPB_MODULE_COUNT];

TTabletCaptureSetupData	TabletCaptureSetupData;
void AccumulateStudyData(int camIndex);
void CPBJobDistributionForInspection(int forDebug, int cameraMask);
void CPBJobDistributionForStudy(int forDebug, int cameraMask);
void InitMulticoreProcessParams();
//---------------------------------------------------------------------------
void InitCPBStep(void)
{
	int	cpbIndex;
	for (cpbIndex = 0; cpbIndex < SYSTEM_CPB_COUNT; cpbIndex++)
	{
		CPBStep[cpbIndex] = 0;
	}
}
//---------------------------------------------------------------------------
void SPB_Inspection_Ready(int maxProcessingWaitingTime)
{
	ProcessingData.ProcessingMode = PROCESSING_MODE_INSPECTION;
	ProcessingData.MaxProcessingWaitingTime = maxProcessingWaitingTime;

	InitCPBStep();
	ClearCPBStatus();
	ClearInspectImage();
	InitMulticoreProcessParams();
}
//---------------------------------------------------------------------------
void SPB_Inspection_Clear(void)
{
	int	cpbIndex, func;
	int camIndex;
	func = 0;

	ClearHPIHeap();
	AddL2DataToHPIHeap(&func, sizeof(int));

	for (cpbIndex = 0; cpbIndex < SYSTEM_CPB_MAX_COUNT; cpbIndex++)
	{
		if (IsAvailableCPB(cpbIndex))
		{
			Request_SendData(IND_CLEAR, GetHPIHeapAddr(), GetHPIHeapSize(), cpbIndex, 0);
		}
	}

	memset(PrintMatchingResult_SPB, 0, sizeof(unsigned int) * 512 * 3);
}
//---------------------------------------------------------------------------
void SPB_Inspection_Stop(void)
{
	ProcessingData.ProcessingMode = PROCESSING_MODE_NONE;
}
//---------------------------------------------------------------------------
void InitMulticoreProcessParams()
{
	int bLaserProcessing;
	int camIndex;

	memset(CPBProcessingType, 0, sizeof(CPBProcessingType));
	memset(AssignedSubcoreCount, 0, sizeof(AssignedSubcoreCount));
	memset(GlobalAssignedSubCoreID, 0, sizeof(GlobalAssignedSubCoreID));
	memset(SplitProcessingCameraType, 0, sizeof(SplitProcessingCameraType));
	memset(ActivePositionProcessingModule, 0, sizeof(ActivePositionProcessingModule));
	memset(MustAccessPositionProcessingModule, 0, sizeof(MustAccessPositionProcessingModule));

	MaxSplitPositionProcessingSubCoreCount = 0;
	bLaserProcessing = 0;

	for (camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_COUNT; camIndex++)
	{
		if (SystemSetupData.CamMask & ((0x01) << camIndex))
		{
			SplitProcessingCameraType[camIndex] = 0;
			if ((SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX)
			{
				if (SystemSetupData.Laser_complexer_Enable == 1)
				{
					SplitProcessingCameraType[camIndex] = 1; // DISK1의 3D 카메라는 3D Position processing의 처리가 필요함을 지정.
					bLaserProcessing = 1;
				}
			}
		}
	}

	if (bLaserProcessing)
	{
		MaxSplitPositionProcessingSubCoreCount = 3; // main core + MaxSplitPositionProcessingSubCoreCount(3) : 4 core split process

		MustAccessPositionProcessingModule[0] = 0;
		MustAccessPositionProcessingModule[1] = 0;
		MustAccessPositionProcessingModule[2] = 1; // 3D Position processing으로 예약된 모듈에는 다른 카메라의 처리를 맡기지 않음. 이것은 SD1_3D_FRONT_FACE_CAMERA_INDEX가 연결된 SPB에서만 지정된다.
		MustAccessPositionProcessingModule[3] = 1;
	}

	/*
	// for test
	TabletGradeData_SPB.dummy[5] = 77613;

	MaxSplitPositionProcessingSubCoreCount = 3;
	for (camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_COUNT; camIndex++)
	{
		SplitProcessingCameraType[camIndex] = 0;
		if (MaxSplitPositionProcessingSubCoreCount)
		{
			SplitProcessingCameraType[1] = 1;
		}
	}

	MustAccessPositionProcessingModule[0] = 0;
	MustAccessPositionProcessingModule[1] = 0;
	MustAccessPositionProcessingModule[2] = 1;
	MustAccessPositionProcessingModule[3] = 1;
	*/
}
//---------------------------------------------------------------------------
void SPB_Study_Ready(void)
{
	int	dataIndex, camIndex;

	// init	result data
	for (camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
	{
		StudyResultData_SPB[camIndex].DataCount = 0;
		for (dataIndex = 0; dataIndex < 256; dataIndex++)
		{
			StudyResultData_SPB[camIndex].ThreeDMaxHeight1[dataIndex] = 0;
			StudyResultData_SPB[camIndex].ThreeDMaxHeight2[dataIndex] = 0;
			StudyResultData_SPB[camIndex].ThreeDCenterHeight1[dataIndex] = 0;
			StudyResultData_SPB[camIndex].ThreeDCenterHeight2[dataIndex] = 0;
		}
		for (dataIndex = 0; dataIndex < 256; dataIndex++)
		{
			StudyResultData_SPB[camIndex].ColorB[dataIndex] = 0;
			StudyResultData_SPB[camIndex].ColorG[dataIndex] = 0;
			StudyResultData_SPB[camIndex].ColorR[dataIndex] = 0;

			StudyResultData_SPB[camIndex].RearColorB[dataIndex] = 0;
			StudyResultData_SPB[camIndex].RearColorG[dataIndex] = 0;
			StudyResultData_SPB[camIndex].RearColorR[dataIndex] = 0;

			StudyResultData_SPB[camIndex].TabletPrintColorB[dataIndex] = 0;
			StudyResultData_SPB[camIndex].TabletPrintColorG[dataIndex] = 0;
			StudyResultData_SPB[camIndex].TabletPrintColorR[dataIndex] = 0;

			StudyResultData_SPB[camIndex].TabletRearPrintColorB[dataIndex] = 0;
			StudyResultData_SPB[camIndex].TabletRearPrintColorG[dataIndex] = 0;
			StudyResultData_SPB[camIndex].TabletRearPrintColorR[dataIndex] = 0;
		}
		for (dataIndex = 0; dataIndex < 3000; dataIndex++)
		{
			StudyResultData_SPB[camIndex].PrintMatchingValue1[dataIndex] = 0;
			StudyResultData_SPB[camIndex].PrintMatchingValue2[dataIndex] = 0;
		}
		StudyResultData_SPB[camIndex].AccTabletEngraveMisMatchCount_Remaining = 0;
		StudyResultData_SPB[camIndex].AccTabletEngraveMisMatchCount_Empty = 0;
		StudyResultData_SPB[camIndex].AccTabletEngraveMisMatch_AddCount_Remaining = 0;
		StudyResultData_SPB[camIndex].AccTabletEngraveMisMatch_AddCount_Empty = 0;
	}
	ProcessingData.ProcessingMode = PROCESSING_MODE_STUDY;

	InitCPBStep();
	ClearCPBStatus();
	ClearInspectImage();
	InitMulticoreProcessParams();
}
//---------------------------------------------------------------------------
void SPB_Study_Stop(void)
{
	ProcessingData.ProcessingMode = PROCESSING_MODE_NONE;
}
//---------------------------------------------------------------------------
void SPB_Processing_Init(void)
{
	//	SPB_Module_Init();
}
//---------------------------------------------------------------------------
void SPB_Processing_Loop(void)
{
	if (ProcessingData.ProcessingMode == PROCESSING_MODE_INSPECTION)
	{
		CPBJobDistributionForInspection(0, NULL);
	}
	else if (ProcessingData.ProcessingMode == PROCESSING_MODE_STUDY)
	{
		CPBJobDistributionForStudy(0, NULL);
	}
}
//---------------------------------------------------------------------------
void ProcessCaptureOverflow(int	camIndex)
{

}
//---------------------------------------------------------------------------
void ProcessImageReady(int camIndex, int imageIndex)
{

}
//---------------------------------------------------------------------------
void AccumulateStudyData(int camIndex)
{
	int	dataIntegrity;
	int	globalCamIndex;
	if (StudyResultData_SPB[camIndex].DataCount >= StudySetupData_SPB.StudyCount) return;

	globalCamIndex = SystemSetupData.GlobalCameraIndex[camIndex] + 1;
	dataIntegrity = 1;

	if (globalCamIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
	{
		if (StudyData_From_CPB.tabletColorB_ForCamera1 < 0 || StudyData_From_CPB.tabletColorB_ForCamera1 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletColorG_ForCamera1 < 0 || StudyData_From_CPB.tabletColorG_ForCamera1 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletColorR_ForCamera1 < 0 || StudyData_From_CPB.tabletColorR_ForCamera1 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearColorB_ForCamera1 < 0 || StudyData_From_CPB.tabletRearColorB_ForCamera1 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearColorG_ForCamera1 < 0 || StudyData_From_CPB.tabletRearColorG_ForCamera1 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearColorR_ForCamera1 < 0 || StudyData_From_CPB.tabletRearColorR_ForCamera1 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletEngraveColorForCamera1[0] < 0 || StudyData_From_CPB.tabletEngraveColorForCamera1[0] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletEngraveColorForCamera1[1] < 0 || StudyData_From_CPB.tabletEngraveColorForCamera1[1] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletEngraveColorForCamera1[2] < 0 || StudyData_From_CPB.tabletEngraveColorForCamera1[2] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearEngraveColorForCamera1[0] < 0 || StudyData_From_CPB.tabletRearEngraveColorForCamera1[0] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearEngraveColorForCamera1[1] < 0 || StudyData_From_CPB.tabletRearEngraveColorForCamera1[1] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearEngraveColorForCamera1[2] < 0 || StudyData_From_CPB.tabletRearEngraveColorForCamera1[2] > 255) dataIntegrity = 0;

		if (StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera1 < 0 || StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera1 > 2999)
		{
			dataIntegrity = 0;
		}
		if (StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera1 < 0 || StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera1 > 2999)
		{
			dataIntegrity = 0;
		}
	}
	else if (globalCamIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
	{
		if (StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera5 < 0 || StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera5 > 1999)
		{
			dataIntegrity = 0;
		}
		if (StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera5 < 0 || StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera5 > 1999)
		{
			dataIntegrity = 0;
		}
		if (StudyData_From_CPB.tabletMaxThickForFirstDisk < 0 || StudyData_From_CPB.tabletMaxThickForFirstDisk > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletCenterThickForFirstDisk < 0 || StudyData_From_CPB.tabletCenterThickForFirstDisk > 255) dataIntegrity = 0;
	}
	else if (globalCamIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
	{
		if (StudyData_From_CPB.tabletColorB_ForCamera9 < 0 || StudyData_From_CPB.tabletColorB_ForCamera9 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletColorG_ForCamera9 < 0 || StudyData_From_CPB.tabletColorG_ForCamera9 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletColorR_ForCamera9 < 0 || StudyData_From_CPB.tabletColorR_ForCamera9 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearColorB_ForCamera9 < 0 || StudyData_From_CPB.tabletRearColorB_ForCamera9 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearColorG_ForCamera9 < 0 || StudyData_From_CPB.tabletRearColorG_ForCamera9 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearColorR_ForCamera9 < 0 || StudyData_From_CPB.tabletRearColorR_ForCamera9 > 255)	dataIntegrity = 0;
		if (StudyData_From_CPB.tabletEngraveColorForCamera9[0] < 0 || StudyData_From_CPB.tabletEngraveColorForCamera9[0] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletEngraveColorForCamera9[1] < 0 || StudyData_From_CPB.tabletEngraveColorForCamera9[1] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletEngraveColorForCamera9[2] < 0 || StudyData_From_CPB.tabletEngraveColorForCamera9[2] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearEngraveColorForCamera9[0] < 0 || StudyData_From_CPB.tabletRearEngraveColorForCamera9[0] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearEngraveColorForCamera9[1] < 0 || StudyData_From_CPB.tabletRearEngraveColorForCamera9[1] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.tabletRearEngraveColorForCamera9[2] < 0 || StudyData_From_CPB.tabletRearEngraveColorForCamera9[2] > 255) dataIntegrity = 0;

		if (StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera9 < 0 || StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera9 > 2999)
		{
			dataIntegrity = 0;
		}
		if (StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera9 < 0 || StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera9 > 2999)
		{
			dataIntegrity = 0;
		}
	}
	else if (globalCamIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
	{
		if (StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera13 < 0 || StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera13 > 1999)
		{
			dataIntegrity = 0;
		}
		if (StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera13 < 0 || StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera13 > 1999)
		{
			dataIntegrity = 0;
		}
		if (StudyData_From_CPB.tabletMaxThickForSecondDisk < 0 || StudyData_From_CPB.tabletMaxThickForSecondDisk > 255)
		{
			dataIntegrity = 0;
		}
		if (StudyData_From_CPB.tabletCenterThickForSecondDisk < 0 || StudyData_From_CPB.tabletCenterThickForSecondDisk > 255)
		{
			dataIntegrity = 0;
		}
	}
	else
	{
		// Side Camera
		if (StudyData_From_CPB.SideFaceTabletBColor[globalCamIndex - 1] < 0 || StudyData_From_CPB.SideFaceTabletBColor[globalCamIndex - 1] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.SideFaceTabletGColor[globalCamIndex - 1] < 0 || StudyData_From_CPB.SideFaceTabletGColor[globalCamIndex - 1] > 255) dataIntegrity = 0;
		if (StudyData_From_CPB.SideFaceTabletRColor[globalCamIndex - 1] < 0 || StudyData_From_CPB.SideFaceTabletRColor[globalCamIndex - 1] > 255) dataIntegrity = 0;
	}

	if (dataIntegrity)
	{
		if (globalCamIndex == SD1_2D_FRONT_FACE_CAMERA_INDEX)
		{
			if (StudyData_From_CPB.tabletColorB_ForCamera1 || StudyData_From_CPB.tabletColorG_ForCamera1 || StudyData_From_CPB.tabletColorR_ForCamera1)
			{
				StudyResultData_SPB[camIndex].ColorB[StudyData_From_CPB.tabletColorB_ForCamera1]++;
				StudyResultData_SPB[camIndex].ColorG[StudyData_From_CPB.tabletColorG_ForCamera1]++;
				StudyResultData_SPB[camIndex].ColorR[StudyData_From_CPB.tabletColorR_ForCamera1]++;
			}
			if (StudyData_From_CPB.tabletRearColorB_ForCamera1 || StudyData_From_CPB.tabletRearColorG_ForCamera1 || StudyData_From_CPB.tabletRearColorR_ForCamera1)
			{
				StudyResultData_SPB[camIndex].RearColorB[StudyData_From_CPB.tabletRearColorB_ForCamera1]++;
				StudyResultData_SPB[camIndex].RearColorG[StudyData_From_CPB.tabletRearColorG_ForCamera1]++;
				StudyResultData_SPB[camIndex].RearColorR[StudyData_From_CPB.tabletRearColorR_ForCamera1]++;
			}
			if (StudyData_From_CPB.tabletEngraveColorForCamera1[0] || StudyData_From_CPB.tabletEngraveColorForCamera1[1] || StudyData_From_CPB.tabletEngraveColorForCamera1[2])
			{
				StudyResultData_SPB[camIndex].TabletPrintColorB[StudyData_From_CPB.tabletEngraveColorForCamera1[0]]++;
				StudyResultData_SPB[camIndex].TabletPrintColorG[StudyData_From_CPB.tabletEngraveColorForCamera1[1]]++;
				StudyResultData_SPB[camIndex].TabletPrintColorR[StudyData_From_CPB.tabletEngraveColorForCamera1[2]]++;
			}
			if (StudyData_From_CPB.tabletRearEngraveColorForCamera1[0] || StudyData_From_CPB.tabletRearEngraveColorForCamera1[1] || StudyData_From_CPB.tabletRearEngraveColorForCamera1[2])
			{
				StudyResultData_SPB[camIndex].TabletRearPrintColorB[StudyData_From_CPB.tabletRearEngraveColorForCamera1[0]]++;
				StudyResultData_SPB[camIndex].TabletRearPrintColorG[StudyData_From_CPB.tabletRearEngraveColorForCamera1[1]]++;
				StudyResultData_SPB[camIndex].TabletRearPrintColorR[StudyData_From_CPB.tabletRearEngraveColorForCamera1[2]]++;
			}

			StudyResultData_SPB[camIndex].PrintMatchingValue1[StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera1]++;
			StudyResultData_SPB[camIndex].PrintMatchingValue2[StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera1]++;

			if (StudyData_From_CPB.TabletEngraveMisMatchCount_Empty_CAM1 != 0)
			{
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatchCount_Empty += StudyData_From_CPB.TabletEngraveMisMatchCount_Empty_CAM1;
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatch_AddCount_Empty++;
			}

			if (StudyData_From_CPB.TabletEngraveMisMatchCount_Remaining_CAM1 != 0)
			{
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatchCount_Remaining += StudyData_From_CPB.TabletEngraveMisMatchCount_Remaining_CAM1;
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatch_AddCount_Remaining++;
			}
		}
		else if (globalCamIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX)
		{
			StudyResultData_SPB[camIndex].PrintMatchingValue1[StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera5]++;
			StudyResultData_SPB[camIndex].PrintMatchingValue2[StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera5]++;
			StudyResultData_SPB[camIndex].ThreeDMaxHeight1[StudyData_From_CPB.tabletMaxThickForFirstDisk]++;
			StudyResultData_SPB[camIndex].ThreeDCenterHeight1[StudyData_From_CPB.tabletCenterThickForFirstDisk]++;
		}
		else if (globalCamIndex == SD2_2D_FRONT_FACE_CAMERA_INDEX)
		{
			if (StudyData_From_CPB.tabletColorB_ForCamera9 || StudyData_From_CPB.tabletColorG_ForCamera9 || StudyData_From_CPB.tabletColorR_ForCamera9)
			{
				StudyResultData_SPB[camIndex].ColorB[StudyData_From_CPB.tabletColorB_ForCamera9]++;
				StudyResultData_SPB[camIndex].ColorG[StudyData_From_CPB.tabletColorG_ForCamera9]++;
				StudyResultData_SPB[camIndex].ColorR[StudyData_From_CPB.tabletColorR_ForCamera9]++;
			}
			if (StudyData_From_CPB.tabletRearColorB_ForCamera9 || StudyData_From_CPB.tabletRearColorG_ForCamera9 || StudyData_From_CPB.tabletRearColorR_ForCamera9)
			{
				StudyResultData_SPB[camIndex].RearColorB[StudyData_From_CPB.tabletRearColorB_ForCamera9]++;
				StudyResultData_SPB[camIndex].RearColorG[StudyData_From_CPB.tabletRearColorG_ForCamera9]++;
				StudyResultData_SPB[camIndex].RearColorR[StudyData_From_CPB.tabletRearColorR_ForCamera9]++;
			}
			if (StudyData_From_CPB.tabletEngraveColorForCamera9[0] || StudyData_From_CPB.tabletEngraveColorForCamera9[1] || StudyData_From_CPB.tabletEngraveColorForCamera9[2])
			{
				StudyResultData_SPB[camIndex].TabletPrintColorB[StudyData_From_CPB.tabletEngraveColorForCamera9[0]]++;
				StudyResultData_SPB[camIndex].TabletPrintColorG[StudyData_From_CPB.tabletEngraveColorForCamera9[1]]++;
				StudyResultData_SPB[camIndex].TabletPrintColorR[StudyData_From_CPB.tabletEngraveColorForCamera9[2]]++;
			}
			if (StudyData_From_CPB.tabletRearEngraveColorForCamera9[0] || StudyData_From_CPB.tabletRearEngraveColorForCamera9[1] || StudyData_From_CPB.tabletRearEngraveColorForCamera9[2])
			{
				StudyResultData_SPB[camIndex].TabletRearPrintColorB[StudyData_From_CPB.tabletRearEngraveColorForCamera9[0]]++;
				StudyResultData_SPB[camIndex].TabletRearPrintColorG[StudyData_From_CPB.tabletRearEngraveColorForCamera9[1]]++;
				StudyResultData_SPB[camIndex].TabletRearPrintColorR[StudyData_From_CPB.tabletRearEngraveColorForCamera9[2]]++;
			}

			StudyResultData_SPB[camIndex].PrintMatchingValue1[StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera9]++;
			StudyResultData_SPB[camIndex].PrintMatchingValue2[StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera9]++;

			if (StudyData_From_CPB.TabletEngraveMisMatchCount_Empty_CAM9 != 0)
			{
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatchCount_Empty += StudyData_From_CPB.TabletEngraveMisMatchCount_Empty_CAM9;
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatch_AddCount_Empty++;
			}

			if (StudyData_From_CPB.TabletEngraveMisMatchCount_Remaining_CAM9 != 0)
			{
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatchCount_Remaining += StudyData_From_CPB.TabletEngraveMisMatchCount_Remaining_CAM9;
				StudyResultData_SPB[camIndex].AccTabletEngraveMisMatch_AddCount_Remaining++;
			}
		}
		else if (globalCamIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX)
		{
			StudyResultData_SPB[camIndex].PrintMatchingValue1[StudyData_From_CPB.Print1_IsOrNotThreshold_ForCamera13]++;
			StudyResultData_SPB[camIndex].PrintMatchingValue2[StudyData_From_CPB.Print2_IsOrNotThreshold_ForCamera13]++;
			StudyResultData_SPB[camIndex].ThreeDMaxHeight2[StudyData_From_CPB.tabletMaxThickForSecondDisk]++;
			StudyResultData_SPB[camIndex].ThreeDCenterHeight2[StudyData_From_CPB.tabletCenterThickForSecondDisk]++;
		}
		else
		{
			// Side Camera
			if (StudyData_From_CPB.SideFaceTabletBColor[globalCamIndex - 1] != 0 ||
				StudyData_From_CPB.SideFaceTabletGColor[globalCamIndex - 1] != 0 ||
				StudyData_From_CPB.SideFaceTabletRColor[globalCamIndex - 1])
			{
				StudyResultData_SPB[camIndex].ColorB[StudyData_From_CPB.SideFaceTabletBColor[globalCamIndex - 1]]++;
				StudyResultData_SPB[camIndex].ColorG[StudyData_From_CPB.SideFaceTabletGColor[globalCamIndex - 1]]++;
				StudyResultData_SPB[camIndex].ColorR[StudyData_From_CPB.SideFaceTabletRColor[globalCamIndex - 1]]++;
			}
		}
		StudyResultData_SPB[camIndex].DataCount++;
	}
}
//---------------------------------------------------------------------------
#ifdef TARGET_SPB
void Virtual_Inspection(int cameraMask)
{
	CPBJobDistributionForInspection(1, cameraMask);
}
//---------------------------------------------------------------------------
#endif

void CPBJobDistributionForInspection(int forDebug, int cameraMask)
{
	int	camIndex, imageIndex, tabletListIndex;
	int	cpbIndex, cpbcount;
	int	cpbProcessingStatus;
	int	imageLeft, imageTop, imageRight, imageBottom;
	TSPBTabletUnit* tabletUnit;
	int	availCPBExist;
	int	bComError;
	int	Processing_Run_Time;
	int cpbRunSW;
	int srcImageWidth;
	int srcImageHeight;
	int resultListIndex;
	int coreIndex;
	int subCoreCount;
	int ModuleCoreIndex;
	int scModuleNum;
	int mcModuleNum;
	int subCoreIndex;
	int moduleIndex;
	unsigned char* RTImageDst;
	int maxValidRealtimeDataCount;
	int m;
	int currentBufferCount;

	for (cpbcount = SYSTEM_CPB_MAX_COUNT - 1; cpbcount >= 0; cpbcount--)
	{
		cpbIndex = cpb_index_table[cpbcount];
		if (!IsAvailableCPB(cpbIndex))
		{
			continue;
		}
		if (CPBStep[cpbIndex] == 1 && (Board1MSTmr - CPBProcessingStartTime[cpbIndex] > MIN_PROCESSING_TIME))
		{
			camIndex = CPBCamIndex[cpbIndex];
			tabletListIndex = CPBProcessingTabletListIndex[cpbIndex];
			tabletUnit = &(SPBTabletProcessInfo.TabletList[tabletListIndex]);

			if (forDebug)
			{
				if (CPBVirtualInspectionData.ProcessOption == 0)
				{
					if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_PROCESSING)
					{
						if (ActivePositionProcessingModule[cpbIndex>>3] == cpbIndex)
							ActivePositionProcessingModule[cpbIndex>>3] = 0;
					}

					tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_GOOD;
					tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_COMPLETE;

					ProcessingTimeList[tabletListIndex].ProcessingEndTime[camIndex] = Board1MSTmr;
					CPBStep[cpbIndex] = 0;

					for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
					{
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
					}

					break;
				}
			}

			if (CPBProcessingType[cpbIndex] == SPLIT_PROCESSING_MODE_SUB) continue; // 단독 코어 또는 메인 코어에서만 결과를 받아옴.

			cpbProcessingStatus = Check_Process_Finished(cpbIndex);
			if (cpbProcessingStatus == CPB_PROCESSING_FINISHED)
			{
				if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_PROCESSING)
				{
					if (Request_ReceiveData(IND_3D_POSITION_INFO, &ThreeDPositionInfo_SPB, sizeof(TThreeDPositionInfo), cpbIndex))
					{
#ifdef TARGET_SPB
						// valid process result
						if (SystemSetupData.Laser_complexer_Enable == 1)
						{
							if (SystemSetupData.GlobalCameraIndex[camIndex] + 1 == SD1_3D_FRONT_FACE_CAMERA_INDEX)
							{
								// 3D 카메라에서 Position 결과 취합
								if (RealtimeImageStartQueue <= RealtimeImageEndQueue)
								{
									currentBufferCount = RealtimeImageEndQueue - RealtimeImageStartQueue;
								}
								else
								{
									currentBufferCount = RealtimeImageEndQueue + (MAX_REALTIME_BUFFER_SIZE - RealtimeImageStartQueue);
								}

								if (currentBufferCount < MAX_REALTIME_BUFFER_SIZE - 1)
								{
									if (tabletUnit->TabletNumber % ImageControlInterval == 0)
									{
										RTImageDst = RealtimeImageBuffer + REALTIME_IMAGE_SIZE * RealtimeImageEndQueue;
										Request_ImageScaleConversion(ProcessingImageInfo.ImageBuffer[tabletUnit->ImageFrameIndex][camIndex] + 1, RTImageDst, SYSTEM_CAMERA_WIDTH, SYSTEM_CAMERA_HEIGHT); // Address + 1 : 3D 영상의 유효 바이트를 적용하기 위함

										maxValidRealtimeDataCount = 6 * sizeof(int); //  cameraIndex, tablet number, theta, x, y, dummy

										// initial
										for (m = 0; m < maxValidRealtimeDataCount; m++)
										{
											*(RTImageDst + m) = 0;
										}

										*((int*)RTImageDst + 0) = SystemSetupData.GlobalCameraIndex[camIndex] + 1;
										*((int*)RTImageDst + 1) = tabletUnit->TabletNumber;

										if (ThreeDPositionInfo_SPB.TabletCenterX == 0xFFFF && ThreeDPositionInfo_SPB.TabletCenterY == 0xFFFF)
										{
											// image error
											*((int*)RTImageDst + 2) = 0;
											*((int*)RTImageDst + 3) = 0;
											*((int*)RTImageDst + 4) = 0;
											*((int*)RTImageDst + 5) = 0;
										}
										else
										{
											*((int*)RTImageDst + 2) = ThreeDPositionInfo_SPB.TabletRotationAngle;
											*((int*)RTImageDst + 3) = ThreeDPositionInfo_SPB.TabletCenterX;
											*((int*)RTImageDst + 4) = ThreeDPositionInfo_SPB.TabletCenterY;
											*((int*)RTImageDst + 5) = 1;
										}

										RealtimeImageEndQueue = RealtimeImageEndQueue + 1;
										if (RealtimeImageEndQueue >= MAX_REALTIME_BUFFER_SIZE) RealtimeImageEndQueue = 0;
									}
								}
							}
						}
#endif

						tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_COMPLETE;
					}
					else
					{
						// CPB로부터 데이터를 받지 못한 경우
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RECEIVE, __LINE__, Board1MSTmr - CPBProcessingStartTime[cpbIndex], cpbIndex);
						tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
						tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_ERROR;
						ProcessingTimeList[tabletListIndex].ProcessingEndTime[camIndex] = Board1MSTmr;
					}
					CPBStep[cpbIndex] = 0;

					if (ActivePositionProcessingModule[cpbIndex>>3] == cpbIndex)
						ActivePositionProcessingModule[cpbIndex>>3] = 0;

					for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
					{
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
					}

					break;
				}
				else
				{
					if (Request_ReceiveData(IND_INSPECTION_RESULT, &DefectData_FromCPB, sizeof(TDefectData), cpbIndex))
					{
						tabletUnit->PrintResult[camIndex] = DefectData_FromCPB.PrintIsSW;
						tabletUnit->PrintType[camIndex] = DefectData_FromCPB.PrintType;
						tabletUnit->ThickErrorSW[camIndex] = DefectData_FromCPB.ThickErrorSW;
						tabletUnit->Front_Rear[camIndex] = DefectData_FromCPB.Front_Rear;
						if ((SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX || (SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
						{
							resultListIndex = tabletUnit->TabletNumber % 512;
							PrintMatchingResult_SPB[resultListIndex][0] = tabletUnit->TabletNumber;
							if (tabletUnit->PrintResult[camIndex] == 1)
							{
								PrintMatchingResult_SPB[resultListIndex][1] = 2;
							}
							else if (tabletUnit->PrintResult[camIndex] == 0)
							{
								PrintMatchingResult_SPB[resultListIndex][1] = 1;
							}

							if (tabletUnit->PrintType[camIndex] == 1)
							{
								PrintMatchingResult_SPB[resultListIndex][2] = 2;
							}
							else if (tabletUnit->PrintType[camIndex] == 0)
							{
								PrintMatchingResult_SPB[resultListIndex][2] = 1;
							}
						}

#ifdef TARGET_SPB
						if ((DefectData_FromCPB.IsDefectA == ('O' << 8) + 'K' && DefectData_FromCPB.IsDefectB == ('K' << 8) + 'O') ||
							(DefectData_FromCPB.IsDefectA == ('N' << 8) + 'G' && DefectData_FromCPB.IsDefectB == ('G' << 8) + 'N') ||
							(DefectData_FromCPB.IsDefectA == ('U' << 8) + 'I' && DefectData_FromCPB.IsDefectB == ('I' << 8) + 'U'))
						{
							// valid process result
							if (SystemSetupData.Laser_complexer_Enable == 1)
							{
								if (SystemSetupData.GlobalCameraIndex[camIndex] + 1 == SD1_2D_FRONT_FACE_CAMERA_INDEX)
								{
									// 2D 카메라에서 인쇄 검사 결과 취합
									if (RealtimeImageStartQueue <= RealtimeImageEndQueue)
									{
										currentBufferCount = RealtimeImageEndQueue - RealtimeImageStartQueue;
									}
									else
									{
										currentBufferCount = RealtimeImageEndQueue + (MAX_REALTIME_BUFFER_SIZE - RealtimeImageStartQueue);
									}

									if (currentBufferCount < MAX_REALTIME_BUFFER_SIZE - 1)
									{
										if (tabletUnit->TabletNumber % ImageControlInterval == 0)
										{
											RTImageDst = RealtimeImageBuffer + REALTIME_IMAGE_SIZE * RealtimeImageEndQueue;
											Request_ImageScaleConversion(ProcessingImageInfo.ImageBuffer[tabletUnit->ImageFrameIndex][camIndex], RTImageDst, SYSTEM_CAMERA_WIDTH, SYSTEM_CAMERA_HEIGHT);

											maxValidRealtimeDataCount = 6 * sizeof(int); //  cameraIndex, tablet number, Brightness, theta, x, y

											// initial
											for (m = 0; m < maxValidRealtimeDataCount; m++)
											{
												*(RTImageDst + m) = 0;
											}

											*((int*)RTImageDst + 0) = SystemSetupData.GlobalCameraIndex[camIndex] + 1;
											*((int*)RTImageDst + 1) = tabletUnit->TabletNumber;

											if (DefectData_FromCPB.PrintIsSW)
											{
												*((int*)RTImageDst + 2) = DefectData_FromCPB.PrintMatchingResult_PrintBrightness;
												*((int*)RTImageDst + 3) = DefectData_FromCPB.PrintMatchingResult_PrintTheta;
												*((int*)RTImageDst + 4) = DefectData_FromCPB.PrintMatchingResult_PrintX;
												*((int*)RTImageDst + 5) = DefectData_FromCPB.PrintMatchingResult_PrintY;
											}

											RealtimeImageEndQueue = RealtimeImageEndQueue + 1;
											if (RealtimeImageEndQueue >= MAX_REALTIME_BUFFER_SIZE) RealtimeImageEndQueue = 0;
										}
									}
								}
							}
						}
#endif

						if (DefectData_FromCPB.IsDefectA == ('O' << 8) + 'K' && DefectData_FromCPB.IsDefectB == ('K' << 8) + 'O')
						{
							if (forDebug)
							{
								VirtualProcessedDataCount++;
								if (VirtualProcessedDataCount > 800)
									VirtualProcessedDataCount = 1;

								VirtualCPBProcessedData[VirtualProcessedDataCount].ProcessingNumber = tabletUnit->TabletNumber;
								VirtualCPBProcessedData[VirtualProcessedDataCount].camIndex = camIndex;
								VirtualCPBProcessedData[VirtualProcessedDataCount].ProcessingResult = 0;
							}

							if ((SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD1_3D_FRONT_FACE_CAMERA_INDEX || (SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD2_3D_FRONT_FACE_CAMERA_INDEX)
							{
								// get position information for laser printing
								if (tabletUnit->ThickErrorSW[camIndex] != 0)
								{
									Request_ReceiveData(IND_DEFECT_DATA, &DefectInfo_CPB, sizeof(TDefectInformation), cpbIndex);

									switch (tabletUnit->ThickErrorSW[camIndex])
									{
									case 1:
										DefectData_SPB.TabletNumber = tabletUnit->TabletNumber;
										DefectData_SPB.GlobalCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
										DefectData_SPB.CPBDefectInfo.size = 0;
										DefectData_SPB.CPBDefectInfo.defectPositionStartX = 10;
										DefectData_SPB.CPBDefectInfo.defectPositionEndX = 630;
										DefectData_SPB.CPBDefectInfo.defectPositionStartY = 10;
										DefectData_SPB.CPBDefectInfo.defectPositionEndY = 470;
										DefectData_SPB.CPBDefectInfo.size = DefectInfo_CPB.size;
										DefectData_SPB.CPBDefectInfo.defectSeries = THIN_TALBET;
										tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_THIN_TABLET;
										Request_CopyData(&(DefectDataList[tabletUnit->ImageFrameIndex][camIndex]), &DefectData_SPB, sizeof(TDefectData_SPB));
										break;
									case 2:
										DefectData_SPB.TabletNumber = tabletUnit->TabletNumber;
										DefectData_SPB.GlobalCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
										DefectData_SPB.CPBDefectInfo.size = 0;
										DefectData_SPB.CPBDefectInfo.defectPositionStartX = 10;
										DefectData_SPB.CPBDefectInfo.defectPositionEndX = 630;
										DefectData_SPB.CPBDefectInfo.defectPositionStartY = 10;
										DefectData_SPB.CPBDefectInfo.defectPositionEndY = 470;
										DefectData_SPB.CPBDefectInfo.size = DefectInfo_CPB.size;
										DefectData_SPB.CPBDefectInfo.defectSeries = FAT_TALBET;
										tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_FAT_TABLET;
										Request_CopyData(&(DefectDataList[tabletUnit->ImageFrameIndex][camIndex]), &DefectData_SPB, sizeof(TDefectData_SPB));
										break;
									default:
										tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_GOOD;
										break;
									}
								}
								else
								{
									tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_GOOD;
								}
							}
							else
							{
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_GOOD;
							}

							if ((SystemSetupData.Laser_complexer_Enable == 1) && TabletGradeData_SPB.EngravePositionDefectCheckSW && TabletCharacter_SPB.discriminationDisplay_kind == PRINT)
							{
								if ((SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD1_2D_FRONT_FACE_CAMERA_INDEX || (SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD2_2D_FRONT_FACE_CAMERA_INDEX)
								{
									if (tabletUnit->PrintResult[camIndex] == 0)
									{
										// Laser 장비에서 Disk1 2D 정면 카메라의 cpb 처리결과가 인쇄가 없으며 양품으로 판정이 된 경우
										DefectData_SPB.TabletNumber = tabletUnit->TabletNumber;
										DefectData_SPB.GlobalCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
										DefectData_SPB.CPBDefectInfo.size = 0;
										DefectData_SPB.CPBDefectInfo.defectPositionStartX = 10;
										DefectData_SPB.CPBDefectInfo.defectPositionEndX = 630;
										DefectData_SPB.CPBDefectInfo.defectPositionStartY = 10;
										DefectData_SPB.CPBDefectInfo.defectPositionEndY = 470;
										DefectData_SPB.CPBDefectInfo.defectSeries = DEFECT_UNPRINT;

										Request_CopyData(&(DefectDataList[tabletUnit->ImageFrameIndex][camIndex]), &DefectData_SPB, sizeof(TDefectData_SPB));
									}
								}
							}
						}
						else if (DefectData_FromCPB.IsDefectA == ('N' << 8) + 'G' && DefectData_FromCPB.IsDefectB == ('G' << 8) + 'N')
						{
							if (forDebug)
							{
								VirtualProcessedDataCount++;
								if (VirtualProcessedDataCount > 800)
									VirtualProcessedDataCount = 1;

								VirtualCPBProcessedData[VirtualProcessedDataCount].ProcessingNumber = tabletUnit->TabletNumber;
								VirtualCPBProcessedData[VirtualProcessedDataCount].camIndex = camIndex;
								VirtualCPBProcessedData[VirtualProcessedDataCount].ProcessingResult = 1;
							}

							Request_ReceiveData(IND_DEFECT_DATA, &DefectInfo_CPB, sizeof(TDefectInformation), cpbIndex);

							tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_DEFECT;

							DefectData_SPB.TabletNumber = tabletUnit->TabletNumber;
							DefectData_SPB.GlobalCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
							memcpy(&(DefectData_SPB.CPBDefectInfo), &DefectInfo_CPB, sizeof(TDefectInformation));

							Request_CopyData(&(DefectDataList[tabletUnit->ImageFrameIndex][camIndex]), &DefectData_SPB, sizeof(TDefectData_SPB));

							if ((SystemSetupData.Laser_complexer_Enable == 1) && TabletGradeData_SPB.EngravePositionDefectCheckSW && TabletCharacter_SPB.discriminationDisplay_kind == PRINT)
							{
								if ((SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD1_2D_FRONT_FACE_CAMERA_INDEX || (SystemSetupData.GlobalCameraIndex[camIndex] + 1) == SD2_2D_FRONT_FACE_CAMERA_INDEX)
								{
									if (tabletUnit->PrintResult[camIndex] == 0)
									{
/*
										if(DefectData_SPB.CPBDefectInfo.defectSeries==DEFECT_FRONT_STAIN || DefectData_SPB.CPBDefectInfo.defectSeries ==DEFECT_FRONT_DIRTY || DefectData_SPB.CPBDefectInfo.defectSeries==DEFECT_FRONT_EDGE_DIRTY  ||DefectData_SPB.CPBDefectInfo.defectSeries==DEFECT_FRONT_EDGE_STAIN)
										{
											tabletUnit->ProcessingResult[camIndex] =TABLET_PROCESSING_RESULT_DEFECT;
										}
										else
										{
											tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_GOOD;
										// Laser 장비에서 Disk1 2D 정면 카메라의 cpb 처리결과가 인쇄가 없으며 양품으로 판정이 된 경우
											DefectData_SPB.TabletNumber = tabletUnit->TabletNumber;
											DefectData_SPB.GlobalCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
											DefectData_SPB.CPBDefectInfo.size = 0;
											DefectData_SPB.CPBDefectInfo.defectPositionStartX = 10;
											DefectData_SPB.CPBDefectInfo.defectPositionEndX = 630;
											DefectData_SPB.CPBDefectInfo.defectPositionStartY = 10;
											DefectData_SPB.CPBDefectInfo.defectPositionEndY = 470;
											DefectData_SPB.CPBDefectInfo.defectSeries = DEFECT_UNPRINT;											
										}
*/
										tabletUnit->ProcessingResult[camIndex] =TABLET_PROCESSING_RESULT_DEFECT;
										Request_CopyData(&(DefectDataList[tabletUnit->ImageFrameIndex][camIndex]), &DefectData_SPB, sizeof(TDefectData_SPB));
									}
								}
							}
						}
						else if (DefectData_FromCPB.IsDefectA == ('U' << 8) + 'I' && DefectData_FromCPB.IsDefectB == ('I' << 8) + 'U')
						{
							if (forDebug)
							{
								VirtualProcessedDataCount++;
								if (VirtualProcessedDataCount > 800)
									VirtualProcessedDataCount = 1;

								VirtualCPBProcessedData[VirtualProcessedDataCount].ProcessingNumber = tabletUnit->TabletNumber;
								VirtualCPBProcessedData[VirtualProcessedDataCount].camIndex = camIndex;
								VirtualCPBProcessedData[VirtualProcessedDataCount].ProcessingResult = 2;
							}

							DefectData_SPB.TabletNumber = tabletUnit->TabletNumber;
							DefectData_SPB.GlobalCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
							DefectData_SPB.CPBDefectInfo.size = 0;
							DefectData_SPB.CPBDefectInfo.defectPositionStartX = 10;
							DefectData_SPB.CPBDefectInfo.defectPositionEndX = 630;
							DefectData_SPB.CPBDefectInfo.defectPositionStartY = 10;
							DefectData_SPB.CPBDefectInfo.defectPositionEndY = 470;
							DefectData_SPB.CPBDefectInfo.cameraIndex = DefectData_SPB.GlobalCameraIndex + 1;

							switch (DefectData_FromCPB.EvalValue)
							{
							case 0:
								DefectData_SPB.CPBDefectInfo.defectSeries = UNINS_CLOSED;
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_CLOSED_TABLET;
								break;
							case 1:
								DefectData_SPB.CPBDefectInfo.defectSeries = UNINS_TABLET_POSITION;
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_UNINS_TABLET_POSITION;
								break;
							case 2:
								DefectData_SPB.CPBDefectInfo.defectSeries = UNINS_BRIGHTNESS_DROPPED;
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_UNINS_BRIGHTNESS_DROPPED;
								break;
							case 3:
								DefectData_SPB.CPBDefectInfo.defectSeries = UNINS_BRIGHTNESS_CHASE;
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_UNINS_BRIGHTNESS_CHASE;
								break;
							}

							Request_CopyData(&(DefectDataList[tabletUnit->ImageFrameIndex][camIndex]), &DefectData_SPB, sizeof(TDefectData_SPB));
						}
						else
						{
							ErrorUnit_Put(BoardID, ERROR_TYPE_MESSAGE, ERROR_CODE_PROCESS_WRONG_RESULT, DefectData_FromCPB.IsDefectA, DefectData_FromCPB.IsDefectB, cpbIndex);
							tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
							tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;

							CPBStatus[cpbIndex].IsDown = TRUE;
							CPBStatus[cpbIndex].Enabled = FALSE;
							CPBStep[cpbIndex] = -1;

							for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
							{
								cpbProcessingStatus = Check_Process_Finished(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
								if (cpbProcessingStatus != CPB_PROCESSING_FINISHED)
								{
									ErrorUnit_Put(BoardID, ERROR_TYPE_MESSAGE, ERROR_CODE_PROCESS_WRONG_RESULT, DefectData_FromCPB.IsDefectA, DefectData_FromCPB.IsDefectB, cpbIndex);
									CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].IsDown = TRUE;
									CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].Enabled = FALSE;
									CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = -1;
								}
								else
								{
									CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
								}
							}

							break;
						}

						ProcessingTimeList[tabletListIndex].ProcessingEndTime[camIndex] = Board1MSTmr;
						CPBStep[cpbIndex] = 0;

						for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
						{
							CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
						}

						tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_COMPLETE;
					}
					else
					{
						// CPB로부터 데이터를 받지 못한 경우
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RECEIVE, __LINE__, Board1MSTmr - CPBProcessingStartTime[cpbIndex], cpbIndex);
						tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
						tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;

						ProcessingTimeList[tabletListIndex].ProcessingEndTime[camIndex] = Board1MSTmr;

						CPBStatus[cpbIndex].IsDown = TRUE;
						CPBStatus[cpbIndex].Enabled = FALSE;
						CPBStep[cpbIndex] = -1;

						for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
						{
							cpbProcessingStatus = Check_Process_Finished(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
							if (cpbProcessingStatus != CPB_PROCESSING_FINISHED)
							{
								ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RECEIVE, __LINE__, Board1MSTmr - CPBProcessingStartTime[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]], GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
								CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].IsDown = TRUE;
								CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].Enabled = FALSE;
								CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = -1;

							}
							else
							{
								CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
							}
						}
					}

					break;
				}
			}
			else if (cpbProcessingStatus == -1)
			{
				// CPB에서 아무런 반응이 없는 경우
				ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, Board1MSTmr - CPBProcessingStartTime[cpbIndex], cpbIndex);

				if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_PROCESSING)
				{
					if (ActivePositionProcessingModule[cpbIndex>>3] == cpbIndex)
						ActivePositionProcessingModule[cpbIndex>>3] = 0;
				}

				tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
				tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
				CPBStatus[cpbIndex].IsDown = TRUE;
				CPBStatus[cpbIndex].Enabled = FALSE;
				CPBStep[cpbIndex] = -1;

				for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
				{
					cpbProcessingStatus = Check_Process_Finished(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
					if (cpbProcessingStatus != CPB_PROCESSING_FINISHED)
					{
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, camIndex, GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
						CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].IsDown = TRUE;
						CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].Enabled = FALSE;
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = -1;
					}
					else
					{
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
					}
				}

				break;
			}
			else
			{
				if (Board1MSTmr - CPBProcessingStartTime[cpbIndex] > MAX_PROCESSING_TIME)
				{
					if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_PROCESSING)
					{
						if (ActivePositionProcessingModule[cpbIndex>>3] == cpbIndex)
							ActivePositionProcessingModule[cpbIndex>>3] = 0;
					}
					
					tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
					tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;

					ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, camIndex, cpbIndex);
					CPBStatus[cpbIndex].IsDown = TRUE;
					CPBStatus[cpbIndex].Enabled = FALSE;
					CPBStep[cpbIndex] = -1;

					for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
					{
						cpbProcessingStatus = Check_Process_Finished(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
						if (cpbProcessingStatus != CPB_PROCESSING_FINISHED)
						{
							ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, camIndex, GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
							CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].IsDown = TRUE;
							CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].Enabled = FALSE;
							CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = -1;
							CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
						}
						else
						{
							CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
						}
					}
				}
				ProcessingTimeList[tabletListIndex].BeforePollingTime[camIndex] = Board1MSTmr;
			}
		}
	}

	for (camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
	{
		if (forDebug)
		{
			if (!(cameraMask & (0x01 << camIndex))) continue;
		}

		tabletUnit = &(SPBTabletProcessInfo.TabletList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]]);

		if (InspectData_SPB.SubSamplingMode[camIndex] == SRC_FULL_SCALE_IMAGE)
		{
			srcImageWidth = HD_IMAGE_WIDTH;
			srcImageHeight = HD_IMAGE_HEIGHT;
		}
		else
		{
			srcImageWidth = SYSTEM_CAMERA_WIDTH;
			srcImageHeight = SYSTEM_CAMERA_HEIGHT;
		}

		if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_PROCESSING_READY)
		{
			if ((int)(Board1MSTmr - ProcessingTimeList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]].CaptureEndTime[camIndex]) > ProcessingData.MaxProcessingWaitingTime)
			{
				tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_CPB_FULL;
				tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
			}
			else
			{
				if (forDebug)
				{
					imageIndex = 0;
				}
				else
				{
					imageIndex = tabletUnit->ImageFrameIndex;
				}

				availCPBExist = 0;
				for (cpbcount = SYSTEM_CPB_MAX_COUNT - 1; cpbcount >= 0; cpbcount--)
				{
					cpbIndex = cpb_index_table[cpbcount];
					if (!IsAvailableCPB(cpbIndex))
					{
						continue;
					}
					else
					{
						if (CPBStep[cpbIndex] == 0)
						{
							AssignedSubcoreCount[cpbIndex] = 0;

							// 3D Position processing으로 예약된 모듈에는 다른 카메라의 처리를 맡기지 않음.
							if (MustAccessPositionProcessingModule[cpbIndex>>3]) continue;

							availCPBExist = 1;
							bComError = 0;

							// SELMA150, 이미지 방향
							switch (SystemSetupData.GlobalCameraIndex[camIndex] + 1)
							{
							case SD2_2D_SIDE_FACE_P45_CAMERA_INDEX:
							case SD2_2D_SIDE_FACE_M45_CAMERA_INDEX:
								imageLeft = srcImageWidth - TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageTop = TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageRight = srcImageWidth - TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageBottom = TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
								break;

							case SD1_3D_FRONT_FACE_CAMERA_INDEX:
							case SD2_3D_FRONT_FACE_CAMERA_INDEX:
								imageLeft = 0;
								imageTop = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageRight = 480;
								imageBottom = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
								break;

							case SD1_2D_SIDE_FACE_P45_CAMERA_INDEX:
							case SD1_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX:
							case SD1_2D_SIDE_FACE_M45_CAMERA_INDEX:
							case SD1_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX:
							case SD1_2D_FRONT_FACE_CAMERA_INDEX:
							case SD2_2D_FRONT_FACE_CAMERA_INDEX:
							case SD1_2D_SIDE_FACE_00_CAMERA_INDEX:
							case SD1_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX:
								imageLeft = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageTop = srcImageHeight - TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageRight = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageBottom = srcImageHeight - TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
								break;

							default:
								imageLeft = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageTop = TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageRight = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageBottom = TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
								break;
							}

							if (forDebug)
							{
								if (CPBVirtualInspectionData.ProcessOption == 0)
								{
									CPBCamIndex[cpbIndex] = camIndex;
									CPBProcessingStartTime[cpbIndex] = Board1MSTmr;
									CPBProcessingTabletListIndex[cpbIndex] = SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex];
									ProcessingTimeList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]].ImageSendStartTime[camIndex] = Board1MSTmr;
									ProcessingTimeList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]].ProcessingCPB[camIndex] = cpbIndex;
									ProcessingTimeList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]].ProcessingStartTime[camIndex] = Board1MSTmr;
									tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING;
									CPBStep[cpbIndex] = 1;

									for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
									{
										CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 1;
									}

									break;
								}
							}

							cpbRunSW = 0;
							ProcessingTimeList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]].ImageSendStartTime[camIndex] = Board1MSTmr;
							if (!Request_SendPartialImage(camIndex, imageIndex, imageLeft, imageTop, imageRight - imageLeft, imageBottom - imageTop, cpbIndex))
							{
								ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, cpbIndex, imageIndex);
								bComError = 1;
								cpbRunSW = 1;
							}

							ProcessingTimeList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]].ProcessingStartTime[camIndex] = Board1MSTmr;

							if (!bComError)
							{
								CPBCamIndex[cpbIndex] = camIndex;
								CPBProcessingTabletListIndex[cpbIndex] = SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex];
								CPBProcessingStartTime[cpbIndex] = Board1MSTmr;
								InspectData_SPB.CurrentCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
								InspectData_SPB.ShutterDelay[0] = 1;
								InspectData_SPB.ShutterDelay[1] = 1;
								InspectData_SPB.ShutterDelay[2] = 1;
								InspectData_SPB.ShutterDelay[3] = 1;

								InspectData_SPB.ActiveSplitProcessing = 0;
								for (coreIndex = 0; coreIndex < MAX_PROCESSING_CORE_COUNT; coreIndex++)
								{
									InspectData_SPB.CoreProcessingMode[coreIndex] = SPLIT_PROCESSING_MODE_NONE;
								}

								CPBProcessingType[cpbIndex] = SPLIT_PROCESSING_MODE_NONE;

								if (!Request_SendData(IND_INSPECTION, &InspectData_SPB, sizeof(TInspectData), cpbIndex, 0))
								{
									bComError = 1;
								}
							}

							if (!bComError)
							{
								CPBProcessingCheckStart(cpbIndex);

								ProcessingTimeList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]].ProcessingCPB[camIndex] = cpbIndex;
								tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING;
								CPBStep[cpbIndex] = 1;

								break;
							}
							else if (bComError && cpbRunSW == 0)
							{
								// 이미지가 아닌 이외의 데이터를 CPB로 보내는 과정에서 에러가 발생한 경우
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
								tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
								//CPBStep[cpbIndex] = -1;
							}
							else if (bComError && cpbRunSW == 1)
							{
								// 이미지 전송과정에서 발생한 에러는 CPU를 Enabled 상태로 유지
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
								tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
							}
						}
					}
				}
			}
		}
	}

	for (camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
	{
		tabletUnit = &(SPBTabletProcessInfo.TabletList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]]);
		if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_READY)
		{
			if ((int)(Board1MSTmr - ProcessingTimeList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]].CaptureEndTime[camIndex]) > ProcessingData.MaxProcessingWaitingTime)
			{
				tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_CPB_FULL;
				tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_ERROR;
			}
			else
			{
				imageIndex = tabletUnit->ImageFrameIndex;
				availCPBExist = 0;
				for (cpbcount = SYSTEM_CPB_MAX_COUNT - 1; cpbcount >= 0; cpbcount--)
				{
					cpbIndex = cpb_index_table[cpbcount];
					if (!IsAvailableCPB(cpbIndex))
					{
						continue;
					}
					else
					{
						if (CPBStep[cpbIndex] == 0)
						{
							AssignedSubcoreCount[cpbIndex] = 0;

							if (SplitProcessingCameraType[camIndex] == 1 && MaxSplitPositionProcessingSubCoreCount)
							{
								mcModuleNum = cpbIndex>>3;

								// 3D Position processing에서는 shared buffer의 관리 편의성을 위하여 멀티 프로세싱을 모듈별로 하나씩만 실행한다.
								if (ActivePositionProcessingModule[mcModuleNum]) continue;

								for (subCoreIndex = 0; subCoreIndex < SYSTEM_CPB_MAX_COUNT; subCoreIndex++)
								{
									if (subCoreIndex == cpbIndex) continue;

									scModuleNum = subCoreIndex>>3;
									if (mcModuleNum == scModuleNum)
									{
										if (IsAvailableCPB(subCoreIndex) && CPBStep[subCoreIndex] == 0)
										{
											GlobalAssignedSubCoreID[cpbIndex][AssignedSubcoreCount[cpbIndex]] = subCoreIndex;
											AssignedSubcoreCount[cpbIndex]++;

											if (AssignedSubcoreCount[cpbIndex] == MaxSplitPositionProcessingSubCoreCount)
											{
												break;
											}
										}
									}
								}

								if (AssignedSubcoreCount[cpbIndex] != MaxSplitPositionProcessingSubCoreCount) continue; // 같은 module 내에 사용 가능한 코어가 분할 처리할만큼 되지 않는 경우
							}
							else
							{
								// 3D Position processing으로 예약된 모듈에는 다른 카메라의 처리를 맡기지 않음.
								if (MustAccessPositionProcessingModule[cpbIndex>>3]) continue;
							}

							availCPBExist = 1;
							bComError = 0;

							switch (SystemSetupData.GlobalCameraIndex[camIndex] + 1)
							{
							case SD1_3D_FRONT_FACE_CAMERA_INDEX:
							case SD2_3D_FRONT_FACE_CAMERA_INDEX:
								imageLeft = 0;
								imageTop = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageRight = 480;
								imageBottom = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
								break;
							default:
								imageLeft = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageTop = TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageRight = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
								imageBottom = TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
								break;
							}
							cpbRunSW = 0;
							ProcessingTimeList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]].ImageSendStartTime[camIndex] = Board1MSTmr;
							if (!Request_SendPartialImage(camIndex, imageIndex, imageLeft, imageTop, imageRight - imageLeft, imageBottom - imageTop, cpbIndex))
							{
								ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, cpbIndex, imageIndex);
								bComError = 1;
								cpbRunSW = 1;
							}

							ProcessingTimeList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]].ProcessingStartTime[camIndex] = Board1MSTmr;

							if (!bComError)
							{
								CPBCamIndex[cpbIndex] = camIndex;
								CPBProcessingTabletListIndex[cpbIndex] = SPBTabletProcessInfo.processingPositionListIndex[camIndex];
								CPBProcessingStartTime[cpbIndex] = Board1MSTmr;
								InspectData_SPB.CurrentCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
								InspectData_SPB.ShutterDelay[0] = 1;
								InspectData_SPB.ShutterDelay[1] = 1;
								InspectData_SPB.ShutterDelay[2] = 1;
								InspectData_SPB.ShutterDelay[3] = 1;

								InspectData_SPB.ActiveSplitProcessing = 0;								
								for (coreIndex = 0; coreIndex < MAX_PROCESSING_CORE_COUNT; coreIndex++)
								{
									InspectData_SPB.CoreProcessingMode[coreIndex] = SPLIT_PROCESSING_MODE_NONE; // 할당된 Main & Sub 외의 다른 코어에 대한 정보는 무시하고 None으로 전달해도 OK.
								}

								CPBProcessingType[cpbIndex] = SPLIT_PROCESSING_MODE_NONE;
								if (SplitProcessingCameraType[camIndex] == 1 && AssignedSubcoreCount[cpbIndex])
								{
									// 메인 코어에게 shared memory의 스위치 초기화를 지시.
									Request_SendData(IND_3D_MULTICORE_CLEAR, GetHPIHeapAddr(), GetHPIHeapSize(), cpbIndex, 0);

									ActivePositionProcessingModule[cpbIndex>>3] = cpbIndex;
									CPBProcessingType[cpbIndex] = SPLIT_PROCESSING_MODE_MAIN;

									InspectData_SPB.ActiveSplitProcessing = 1;
									InspectData_SPB.CoreProcessingMode[cpbIndex % MAX_PROCESSING_CORE_COUNT] = SPLIT_PROCESSING_MODE_MAIN;
									for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
									{
										// 모듈 내에서의 코어 번호를 구함.
										ModuleCoreIndex = GlobalAssignedSubCoreID[cpbIndex][subCoreCount] % MAX_PROCESSING_CORE_COUNT;
										InspectData_SPB.CoreProcessingMode[ModuleCoreIndex] = SPLIT_PROCESSING_MODE_SUB;
									}

									for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
									{
										// subcore processing standby
										ModuleCoreIndex = GlobalAssignedSubCoreID[cpbIndex][subCoreCount] % MAX_PROCESSING_CORE_COUNT;
										if (InspectData_SPB.CoreProcessingMode[ModuleCoreIndex] == SPLIT_PROCESSING_MODE_SUB)
										{
											Request_SendData(IND_INSPECTION_POSITION, &InspectData_SPB, sizeof(TInspectData), GlobalAssignedSubCoreID[cpbIndex][subCoreCount], 0);
											CPBProcessingCheckStart(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
											CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 1;
											CPBProcessingType[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = SPLIT_PROCESSING_MODE_SUB;
										}
									}
								}

								if (!Request_SendData(IND_INSPECTION_POSITION, &InspectData_SPB, sizeof(TInspectData), cpbIndex, 0))
								{
									bComError = 1;
								}
							}

							if (!bComError)
							{
								CPBProcessingCheckStart(cpbIndex);
								ProcessingTimeList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]].ProcessingCPB[camIndex] = cpbIndex;
								tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING;
								CPBStep[cpbIndex] = 1;
								break;
							}
							else if (bComError && cpbRunSW == 0)
							{
								// 이미지가 아닌 이외의 데이터를 CPB로 보내는 과정에서 에러가 발생한 경우
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
								tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_ERROR;
								//CPBStep[cpbIndex] = -1;
							}
							else if (bComError && cpbRunSW == 1)
							{
								// 이미지 전송과정에서 발생한 에러는 CPU를 Enabled 상태로 유지
								tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
								tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_ERROR;
							}
						}
					}
				}
			}
		}
	}
}

//---------------------------------------------------------------------------
void CPBJobDistributionForStudy(int forDebug, int cameraMask)
{
	int	camIndex, imageIndex, tabletListIndex;
	int	cpbIndex, cpbcount;
	int	cpbProcessingStatus;
	int	imageLeft, imageTop, imageRight, imageBottom;
	TSPBTabletUnit* tabletUnit;
	int	availCPBExist;
	int	bComError;
	int	Processing_Run_Time;
	int cpbRunSW;
	int srcImageWidth;
	int srcImageHeight;
	int resultListIndex;
	int coreIndex;
	int subCoreCount;
	int ModuleCoreIndex;
	int scModuleNum;
	int mcModuleNum;
	int subCoreIndex;
	int moduleIndex;

	for (camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
	{
		tabletUnit = &(SPBTabletProcessInfo.TabletList[SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex]]);

		if (StudySetupData_SPB.SubSamplingMode[camIndex] == SRC_FULL_SCALE_IMAGE)
		{
			srcImageWidth = HD_IMAGE_WIDTH;
			srcImageHeight = HD_IMAGE_HEIGHT;
		}
		else
		{
			srcImageWidth = SYSTEM_CAMERA_WIDTH;
			srcImageHeight = SYSTEM_CAMERA_HEIGHT;
		}

		if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_PROCESSING_READY)
		{
			imageIndex = tabletUnit->ImageFrameIndex;
			availCPBExist = 0;
			for (cpbcount = SYSTEM_CPB_MAX_COUNT - 1; cpbcount >= 0; cpbcount--)
			{
				cpbIndex = cpb_index_table[cpbcount];
				if (!IsAvailableCPB(cpbIndex))
				{
					continue;
				}
				else
				{
					if (CPBStep[cpbIndex] == 0)
					{
						// 3D Position processing으로 예약된 모듈에는 다른 카메라의 처리를 맡기지 않음.
						if (MustAccessPositionProcessingModule[cpbIndex>>3]) continue;

						// 3D Position processing이 아닌 경우 학습중에 멀티코어를 사용하지 않음.
						// subcore를 할당하지 않는다.

						availCPBExist = 1;
						bComError = 0;

						switch (SystemSetupData.GlobalCameraIndex[camIndex] + 1)
						{
						case SD2_2D_SIDE_FACE_P45_CAMERA_INDEX:
						case SD2_2D_SIDE_FACE_M45_CAMERA_INDEX:
							imageLeft = srcImageWidth - TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageTop = TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageRight = srcImageWidth - TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageBottom = TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
							break;

						case SD1_3D_FRONT_FACE_CAMERA_INDEX:
						case SD2_3D_FRONT_FACE_CAMERA_INDEX:
							imageLeft = 0;
							imageTop = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageRight = 480;
							imageBottom = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
							break;

						case SD1_2D_SIDE_FACE_P45_CAMERA_INDEX:
						case SD1_2D_OTHER_SIDE_FACE_P45_CAMERA_INDEX:
						case SD1_2D_SIDE_FACE_M45_CAMERA_INDEX:
						case SD1_2D_OTHER_SIDE_FACE_M45_CAMERA_INDEX:
						case SD1_2D_FRONT_FACE_CAMERA_INDEX:
						case SD2_2D_FRONT_FACE_CAMERA_INDEX:
						case SD1_2D_SIDE_FACE_00_CAMERA_INDEX:
						case SD1_2D_OTHER_SIDE_FACE_00_CAMERA_INDEX:
							imageLeft = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageTop = srcImageHeight - TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageRight = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageBottom = srcImageHeight - TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
							break;

						default:
							imageLeft = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageTop = TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageRight = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageBottom = TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
							break;
						}

						cpbRunSW = 0;
						if (!Request_SendPartialImage(camIndex, imageIndex, imageLeft, imageTop, imageRight - imageLeft, imageBottom - imageTop, cpbIndex))
						{
							bComError = 1;
							cpbRunSW = 1;
						}

						if (!bComError)
						{
							CPBCamIndex[cpbIndex] = camIndex;
							CPBProcessingTabletListIndex[cpbIndex] = SPBTabletProcessInfo.ProcessingTabletListIndex[camIndex];
							CPBProcessingStartTime[cpbIndex] = Board1MSTmr;
							tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING;
							StudyData_SPB.CurrentCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
							ClearHPIHeap();
							AddL2DataToHPIHeap(&StudyData_SPB, sizeof(TStudyData_SPB));
							if (!Request_SendData(IND_STUDY, GetHPIHeapAddr(), GetHPIHeapSize(), cpbIndex, 0))
							{
								bComError = 1;
							}
						}

						if (!bComError)
						{
							CPBProcessingCheckStart(cpbIndex);
							CPBStep[cpbIndex] = 1;
							break;
						}
						else if (cpbRunSW == 0)
						{
							// 이미지가 아닌 이외의 데이터를 CPB로 보내는 과정에서 에러가 발생한 경우
						}
					}
				}
			}

			if (availCPBExist == 0)
			{
				tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_CPB_FULL;
				tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
			}
		}
	}

	for (camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
	{
		tabletUnit = &(SPBTabletProcessInfo.TabletList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]]);
		if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_READY)
		{
			imageIndex = tabletUnit->ImageFrameIndex;
			availCPBExist = 0;
			for (cpbcount = SYSTEM_CPB_MAX_COUNT - 1; cpbcount >= 0; cpbcount--)
			{
				cpbIndex = cpb_index_table[cpbcount];
				if (!IsAvailableCPB(cpbIndex))
				{
					continue;
				}
				else
				{
					if (CPBStep[cpbIndex] == 0)
					{
						AssignedSubcoreCount[cpbIndex] = 0;

						if (SplitProcessingCameraType[camIndex] == 1 && MaxSplitPositionProcessingSubCoreCount)
						{
							mcModuleNum = cpbIndex>>3;

							// 3D Position processing에서는 shared buffer의 관리 편의성을 위하여 멀티 프로세싱을 모듈별로 하나씩만 실행한다.
							if (ActivePositionProcessingModule[mcModuleNum]) continue;

							for (subCoreIndex = 0; subCoreIndex < SYSTEM_CPB_MAX_COUNT; subCoreIndex++)
							{
								if (subCoreIndex == cpbIndex) continue;

								scModuleNum = subCoreIndex>>3;
								if (mcModuleNum == scModuleNum)
								{
									if (IsAvailableCPB(subCoreIndex) && CPBStep[subCoreIndex] == 0)
									{
										GlobalAssignedSubCoreID[cpbIndex][AssignedSubcoreCount[cpbIndex]] = subCoreIndex;
										AssignedSubcoreCount[cpbIndex]++;

										if (AssignedSubcoreCount[cpbIndex] == MaxSplitPositionProcessingSubCoreCount)
										{
											break;
										}
									}
								}
							}

							if (AssignedSubcoreCount[cpbIndex] != MaxSplitPositionProcessingSubCoreCount) continue; // 같은 module 내에 사용 가능한 코어가 분할 처리할만큼 되지 않는 경우
						}
						else
						{
							// 3D Position processing으로 예약된 모듈에는 다른 카메라의 처리를 맡기지 않음.
							if (MustAccessPositionProcessingModule[cpbIndex>>3]) continue;
						}

						availCPBExist = 1;
						bComError = 0;

						switch (SystemSetupData.GlobalCameraIndex[camIndex] + 1)
						{
						case SD1_3D_FRONT_FACE_CAMERA_INDEX:
						case SD2_3D_FRONT_FACE_CAMERA_INDEX:
							imageLeft = 0;
							imageTop = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageRight = 480;
							imageBottom = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
							break;
						default:
							imageLeft = TabletCaptureSetupData.RangeLeft[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageTop = TabletCaptureSetupData.RangeTop[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageRight = TabletCaptureSetupData.RangeRight[SystemSetupData.GlobalCameraIndex[camIndex]];
							imageBottom = TabletCaptureSetupData.RangeBottom[SystemSetupData.GlobalCameraIndex[camIndex]];
							break;
						}
						cpbRunSW = 0;
						ProcessingTimeList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]].ImageSendStartTime[camIndex] = Board1MSTmr;
						if (!Request_SendPartialImage(camIndex, imageIndex, imageLeft, imageTop, imageRight - imageLeft, imageBottom - imageTop, cpbIndex))
						{
							bComError = 1;
							cpbRunSW = 1;
						}

						ProcessingTimeList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]].ProcessingStartTime[camIndex] = Board1MSTmr;

						if (!bComError)
						{
							CPBCamIndex[cpbIndex] = camIndex;
							CPBProcessingTabletListIndex[cpbIndex] = SPBTabletProcessInfo.processingPositionListIndex[camIndex];
							CPBProcessingStartTime[cpbIndex] = Board1MSTmr;
							InspectData_SPB.CurrentCameraIndex = SystemSetupData.GlobalCameraIndex[camIndex];
							InspectData_SPB.ShutterDelay[0] = 1;
							InspectData_SPB.ShutterDelay[1] = 1;
							InspectData_SPB.ShutterDelay[2] = 1;
							InspectData_SPB.ShutterDelay[3] = 1;

							InspectData_SPB.ActiveSplitProcessing = 0;
							for (coreIndex = 0; coreIndex < MAX_PROCESSING_CORE_COUNT; coreIndex++)
							{
								InspectData_SPB.CoreProcessingMode[coreIndex] = SPLIT_PROCESSING_MODE_NONE; // 할당된 Main & Sub 외의 다른 코어에 대한 정보는 무시하고 None으로 전달해도 OK.
							}

							CPBProcessingType[cpbIndex] = SPLIT_PROCESSING_MODE_NONE;
							if (SplitProcessingCameraType[camIndex] == 1 && AssignedSubcoreCount[cpbIndex])
							{
								// 메인 코어에게 shared memory의 스위치 초기화를 지시.
								Request_SendData(IND_3D_MULTICORE_CLEAR, GetHPIHeapAddr(), GetHPIHeapSize(), cpbIndex, 0);

								ActivePositionProcessingModule[cpbIndex>>3] = cpbIndex;
								CPBProcessingType[cpbIndex] = SPLIT_PROCESSING_MODE_MAIN;

								InspectData_SPB.ActiveSplitProcessing = 1;
								InspectData_SPB.CoreProcessingMode[cpbIndex % MAX_PROCESSING_CORE_COUNT] = SPLIT_PROCESSING_MODE_MAIN;
								for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
								{
									// 모듈 내에서의 코어 번호를 구함.
									ModuleCoreIndex = GlobalAssignedSubCoreID[cpbIndex][subCoreCount] % MAX_PROCESSING_CORE_COUNT;
									InspectData_SPB.CoreProcessingMode[ModuleCoreIndex] = SPLIT_PROCESSING_MODE_SUB;
								}

								for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
								{
									// subcore processing standby
									ModuleCoreIndex = GlobalAssignedSubCoreID[cpbIndex][subCoreCount] % MAX_PROCESSING_CORE_COUNT;
									if (InspectData_SPB.CoreProcessingMode[ModuleCoreIndex] == SPLIT_PROCESSING_MODE_SUB)
									{
										Request_SendData(IND_STUDY_POSITION, &InspectData_SPB, sizeof(TInspectData), GlobalAssignedSubCoreID[cpbIndex][subCoreCount], 0);
										CPBProcessingCheckStart(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
										CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 1;
										CPBProcessingType[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = SPLIT_PROCESSING_MODE_SUB;
									}
								}
							}

							if (!Request_SendData(IND_STUDY_POSITION, &InspectData_SPB, sizeof(TInspectData), cpbIndex, 0))
							{
								bComError = 1;
							}
						}

						if (!bComError)
						{
							CPBProcessingCheckStart(cpbIndex);
							ProcessingTimeList[SPBTabletProcessInfo.processingPositionListIndex[camIndex]].ProcessingCPB[camIndex] = cpbIndex;
							tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING;
							CPBStep[cpbIndex] = 1;
							break;
						}
						else if (bComError && cpbRunSW == 0)
						{
							// 이미지가 아닌 이외의 데이터를 CPB로 보내는 과정에서 에러가 발생한 경우
							tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
							tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_ERROR;
							//CPBStep[cpbIndex] = -1;
						}
						else if (bComError && cpbRunSW == 1)
						{
							// 이미지 전송과정에서 발생한 에러는 CPU를 Enabled 상태로 유지
							tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
							tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_ERROR;
						}
					}
				}
			}
			if (availCPBExist == 0)
			{
				tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_CPB_FULL;
				tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
			}
		}
	}

	for (cpbcount = SYSTEM_CPB_MAX_COUNT - 1; cpbcount >= 0; cpbcount--)
	{
		cpbIndex = cpb_index_table[cpbcount];
		if (!IsAvailableCPB(cpbIndex))
		{
			continue;
		}

		if (CPBStep[cpbIndex] == 1 && (Board1MSTmr - CPBProcessingStartTime[cpbIndex] > MIN_PROCESSING_TIME))
		{
			camIndex = CPBCamIndex[cpbIndex];
			tabletListIndex = CPBProcessingTabletListIndex[cpbIndex];
			tabletUnit = &(SPBTabletProcessInfo.TabletList[tabletListIndex]);

			if (CPBProcessingType[cpbIndex] == SPLIT_PROCESSING_MODE_SUB) continue; // 단독 코어 또는 메인 코어에서만 결과를 받아옴.

			cpbProcessingStatus = Check_Process_Finished(cpbIndex);

			if (cpbProcessingStatus == CPB_PROCESSING_FINISHED)
			{
				if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_PROCESSING)
				{
					if (Request_ReceiveData(IND_3D_POSITION_INFO, &ThreeDPositionInfo_SPB, sizeof(TThreeDPositionInfo), cpbIndex))
					{
						tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_COMPLETE;
					}
					else
					{
						// CPB로부터 데이터를 받지 못한 경우
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RECEIVE, __LINE__, Board1MSTmr - CPBProcessingStartTime[cpbIndex], cpbIndex);
						tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
						tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_POSITION_PROCESSING_ERROR;
						ProcessingTimeList[tabletListIndex].ProcessingEndTime[camIndex] = Board1MSTmr;
					}
					CPBStep[cpbIndex] = 0;

					if (ActivePositionProcessingModule[cpbIndex>>3] == cpbIndex)
						ActivePositionProcessingModule[cpbIndex>>3] = 0;

					for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
					{
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
					}
				}
				else
				{
					if (Request_ReceiveData(IND_STUDY_RESULT, &StudyData_From_CPB, sizeof(TTabletStudyData), cpbIndex))
					{
						AccumulateStudyData(camIndex);
						ProcessingTimeList[tabletListIndex].ProcessingEndTime[camIndex] = Board1MSTmr;
					}
					else
					{
						// CPB로부터 데이터를 받지 못한 경우
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RECEIVE, __LINE__, Board1MSTmr - CPBProcessingStartTime[cpbIndex], cpbIndex);
						tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
						ProcessingTimeList[tabletListIndex].ProcessingEndTime[camIndex] = Board1MSTmr;
					}
					tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_COMPLETE;
					tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_GOOD;

					CPBStep[cpbIndex] = 0;

					for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
					{
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
					}
				}
			}
			else if (cpbProcessingStatus == -1)
			{
				if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_PROCESSING)
				{
					if (ActivePositionProcessingModule[cpbIndex>>3] == cpbIndex)
						ActivePositionProcessingModule[cpbIndex>>3] = 0;
				}

				tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
				tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
				ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, camIndex, cpbIndex);

				CPBStatus[cpbIndex].IsDown = TRUE;
				CPBStatus[cpbIndex].Enabled = FALSE;
				CPBStep[cpbIndex] = -1;

				for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
				{
					cpbProcessingStatus = Check_Process_Finished(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
					if (cpbProcessingStatus != CPB_PROCESSING_FINISHED)
					{
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RECEIVE, __LINE__, Board1MSTmr - CPBProcessingStartTime[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]], GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
						CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].IsDown = TRUE;
						CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].Enabled = FALSE;
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = -1;
					}
					else
					{
						CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
					}
				}
				break;
			}
			else
			{
				if (Board1MSTmr - CPBProcessingStartTime[cpbIndex] > MAX_PROCESSING_TIME)
				{
					if (tabletUnit->InspectionState[camIndex] == TABLET_INSPECTION_STATE_POSITION_PROCESSING)
					{
						if (ActivePositionProcessingModule[cpbIndex>>3] == cpbIndex)
							ActivePositionProcessingModule[cpbIndex>>3] = 0;
					}

					tabletUnit->InspectionState[camIndex] = TABLET_INSPECTION_STATE_PROCESSING_ERROR;
					tabletUnit->ProcessingResult[camIndex] = TABLET_PROCESSING_RESULT_ERROR;
					ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, camIndex, cpbIndex);

					CPBStatus[cpbIndex].IsDown = TRUE;
					CPBStatus[cpbIndex].Enabled = FALSE;
					CPBStep[cpbIndex] = -1;

					for (subCoreCount = 0; subCoreCount < AssignedSubcoreCount[cpbIndex]; subCoreCount++)
					{
						cpbProcessingStatus = Check_Process_Finished(GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
						if (cpbProcessingStatus != CPB_PROCESSING_FINISHED)
						{
							ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RECEIVE, __LINE__, Board1MSTmr - CPBProcessingStartTime[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]], GlobalAssignedSubCoreID[cpbIndex][subCoreCount]);
							CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].IsDown = TRUE;
							CPBStatus[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]].Enabled = FALSE;
							CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = -1;
						}
						else
						{
							CPBStep[GlobalAssignedSubCoreID[cpbIndex][subCoreCount]] = 0;
						}
					}
				}
			}
		}
	}
}
