#ifndef __cpb_module_main_h__
#define __cpb_module_main_h__

#include "Processing.h"

#define PROCESS_FUNC_NONE							        0
#define PROCESS_FUNC_SETUP							      1
#define PROCESS_FUNC_STUDY							      2
#define PROCESS_FUNC_INSPECTION						    3
#define PROCESS_FUNC_PROCESSING_TEST					4
#define PROCESS_FUNC_INSPECTION_TPB					 5
#define PROCESS_FUNC_STUDY_POSITION							    6
#define PROCESS_FUNC_INSPECTION_POSITION							7

#define GETTING_POSITION_INDICATOR_FORBIDDEN    0
#define GETTING_POSITION_INDICATOR_MAIN_ACCESS  1
#define GETTING_POSITION_INDICATOR_SUB_ACCESS   2

#define SHARED_MEMORY_VALID_POINTER      0
#define SHARED_PROCESSING_ROTATION_ANGLE  12

extern int threeDminX;
extern int threeDmaxX;
extern int threeDminY;
extern int threeDmaxY;

extern int CurrentGlobalCamIndex;
volatile extern int Process_Function;

extern int Processing_Run_Time;

extern unsigned char ColorSourceImage_Temp[3 * SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT];  //900k
extern unsigned char InspectionArea_Temp[SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT];      //300k
extern short LabelImage_Virtual_Temp[SYSTEM_CAMERA_WIDTH*SYSTEM_CAMERA_HEIGHT];
extern unsigned char ThreeDImage_Temp[SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT];      //300k

extern unsigned char smallSizeProcessedImage[64 * 48];

typedef struct
{
  int ImageStartX[CACHE_CONTROL_DUMMY_SIZE];
  int ImageEndX[CACHE_CONTROL_DUMMY_SIZE];
  int ImageStartY[CACHE_CONTROL_DUMMY_SIZE];
  int ImageEndY[CACHE_CONTROL_DUMMY_SIZE];
  int ImageWidth[CACHE_CONTROL_DUMMY_SIZE];
  int ImageHeight[CACHE_CONTROL_DUMMY_SIZE];
  int ImageCenterX[CACHE_CONTROL_DUMMY_SIZE];
  int ImageCenterY[CACHE_CONTROL_DUMMY_SIZE];
  int LimitStartX[CACHE_CONTROL_DUMMY_SIZE];
  int LimitEndX[CACHE_CONTROL_DUMMY_SIZE];
  int LimitStartY[CACHE_CONTROL_DUMMY_SIZE];
  int LimitEndY[CACHE_CONTROL_DUMMY_SIZE];
  int ProtoTabletAngle[CACHE_CONTROL_DUMMY_SIZE];
}TSharedProcessingParamsForRotation;

extern int SubcoreProcessingActiveSW[MAX_PROCESSING_CORE_COUNT * CACHE_CONTROL_DUMMY_SIZE];
extern unsigned char SharedImageBuffer[MAX_IMAGE_WIDTH * MAX_IMAGE_HEIGHT];
extern TSharedProcessingParamsForRotation SharedProcessingParamsForRotation;
extern int SharedJobDistributionForRotation[MAX_PROCESSING_CORE_COUNT * CACHE_CONTROL_DUMMY_SIZE][SHARED_PROCESSING_ROTATION_ANGLE * 2 + 1];
extern int SharedProcessingResultForRotation[(SHARED_PROCESSING_ROTATION_ANGLE * 2 + 1) * CACHE_CONTROL_DUMMY_SIZE];

#ifdef __cplusplus
extern "C"
{
#endif  /* __cplusplus */
void CPB_Module_Processing(void);
void ClearInspectionData(void);
void ClearThreeDPositionMultiCoreProcessing(void);
#ifdef __cplusplus
}
#endif  /* __cplusplus */

void CPB_Processing_Setup(void);
void CPB_Processing_Study(void);
void CPB_Processing_Inspection();
void CPB_Processing_Inspection_TPB();
void CPB_Processing_Position(int mode);

void InitialImageBuffer();

// Multi Core Processing (laser complexer)
// 멀티코어는 실질적으로 메모리를 순차적으로 엑세스하는 loop에 적용할 때 효과적이다.
// r값으로 x, y 좌표의 주변을 훑는 로직의 경우 메모리 캐싱이 실패할 확률이 높아서 메모리 병목을 초래하므로 멀티코어의 효과가 매우 떨어진다.
// 또한 shared 메모리에 직접 읽고 쓰는 것보다는 각 코어의 메모리에 복사하여 작업 후 필요시 다시 shared 메모리를 통하여 결과를 전달하는 것이 더 빨랐다.
// laser complexer 외에 일반적인 검사를 멀티코어로 처리하는 시도를 해 보았으나 멀티코어를 적용할만한 부분이 생각보다 적었고 메모리 병목현상 때문에 효율도 낮았다.
// 두개의 코어를 하나로 묶어서 구현해 보았으나 성능은 15%정도 개선되고 필요한 코어의 수는 두배로 늘어나게 되어 매우 비효율적이었다.
// 따라서 멀티코어는 laser complexer 등 특수한 작업에만 사용하는 것으로 한다.
void GettingThreeDPositionInformationForLaserComplexer(int processingMode, int cameraIndex, int option);
void Analysis3DImageForLaserComplexer(int cameraIndex, int option);
void ThreeDPositionMultiCoreProcessing();
void CalculateRotataionResultWithMultiCore(int startX, int endX, int startY, int endY, int smallSizeWidth, int halfCenterX, int halfCenterY, int limStX, int limEdX, int limStY, int limEdY, int zeroAngle);

//---------------------------------------------------------------------------
#endif
