// StCamera.h: CStCamera
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_STCAMERA_H__EADFB89B_7118_42CE_8239_B97FCDC34FC0__INCLUDED_)
#define AFX_STCAMERA_H__EADFB89B_7118_42CE_8239_B97FCDC34FC0__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "TimerFunc.h"


class CStCamera : public CTimerFunc 
{
public:
	CStCamera();
	virtual ~CStCamera();

	BOOL	InitializeCameraInfo();
	BOOL	StartTransfer();
	BOOL	StopTransfer();
	BOOL	TriggerSoftware(DWORD dwTriggerSelector);
	
	BOOL	SettingFile(BOOL bOpenFg, LPCTSTR szFileName);

	static void CALLBACK StaticExposureEndCallback(HANDLE hCamera, DWORD dwFrameNo, PVOID pvContext)
	{
		((CStCamera*)pvContext)->ExposureEndCallback(hCamera, dwFrameNo);
	};
	static void CALLBACK StaticTransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw, PVOID pvContext)
	{
		((CStCamera*)pvContext)->TransferEndCallback(hCamera, dwFrameNo, dwWidth, dwHeight, wColorArray, pbyteRaw);
	};
	static void CALLBACK StaticRcvErrorCallback(HANDLE hCamera, DWORD dwErrorCode, PVOID pvContext)
	{
		((CStCamera*)pvContext)->RcvErrorCallback(hCamera, dwErrorCode);
	};
	BOOL TimerStartProc()
	{
		//Start Trigger
#ifdef _DEBUG
		DWORD dwTime = timeGetTime();
		TRACE(TEXT("[%u]:Strat Trigger\r\n"), dwTime - m_dwLastStartTriggerTime);
		m_dwLastStartTriggerTime = dwTime;
#endif //_DEUBG
		BOOL bReval = StTrg_TriggerSoftware(m_hCamera, STCAM_TRIGGER_SELECTOR_EXPOSURE_START);
		return(bReval);
	};
	BOOL TimerStopProc()
	{
		//End Trigger
#ifdef _DEBUG
		DWORD dwTime = timeGetTime();
		TRACE(TEXT("[%u]:End Trigger\r\n"),  dwTime - m_dwLastStartTriggerTime);
		m_dwLastStartTriggerTime = dwTime;
#endif //_DEBUG
		BOOL bReval = StTrg_TriggerSoftware(m_hCamera, STCAM_TRIGGER_SELECTOR_EXPOSURE_END);
		return(bReval);
	};
	BOOL HasTriggerFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_TRIGGER, &bReval);
		return(bReval);
	};

	BOOL HasDigitalGainFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DIGITAL_GAIN, &bReval);
		return(bReval);
	};
	BOOL HasAnalogGainFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DISABLED_ANALOG_GAIN, &bReval);
		return(!bReval);
	};
	BOOL IsDitigalGainCtrl(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_AGC_GAIN_TYPE, &bReval);
		return(bReval);
	};

	BOOL HasVariablePartialMode(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_VARIABLE_PARTIAL, &bReval);
		return(bReval);
	};
	BOOL HasBinningPartialMode(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_BINNING_PARTIAL, &bReval);
		return(bReval);
	};
	BOOL HasExposureModeTriggerControlled(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_EXPOSURE_MODE_TRIGGER_CONTROLLED, &bReval);
		return(bReval);
	};
	BOOL HasExposureEndHardwareTrigger(void)
	{
		BOOL bReval = FALSE;
		if(HasExposureModeTriggerControlled())
		{
			StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_EXPOSURE_END_TRIGGER_SOURCE, &bReval);
			bReval = !bReval;
		}
		return(bReval);
	};
	BOOL HasExposureModeTriggerWidth(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_EXPOSURE_MODE_TRIGGER_WIDTH_DISABLE, &bReval);
		return(!bReval);
	};

	BOOL HasTriggerOverlapFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_TRIGGER_OVERLAP, &bReval);
		return(bReval);
	};

	BOOL HasTriggerOverlapValue(DWORD dwValue)
	{
		const DWORD pdwIndex[] = {
				STCAM_CAMERA_FUNCTION_TRIGGER_OVERLAP_OFF,
				STCAM_CAMERA_FUNCTION_TRIGGER_OVERLAP_READ_OUT,
				STCAM_CAMERA_FUNCTION_TRIGGER_OVERLAP_PREVIOUS_FRAME
			};

		BOOL bReval = FALSE;
		if(dwValue < _countof(pdwIndex))
		{
			StTrg_HasFunction(m_hCamera, pdwIndex[dwValue], &bReval);
		}
		return(bReval);
	};

	BOOL HasTriggerThroughFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_PHOTOCOUPLER, &bReval);
		return(!bReval);
	};
	BOOL HasChangeIOFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_IO_CHANGE_DIRECTION, &bReval);
		return(bReval);
	};
	BOOL HasLEDFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_LED, &bReval);
		return(bReval);
	};
	BOOL HasVGA90FPSFunction(void)
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_VGA90FPS, &bReval);
		return(bReval);
	};
	INT CDSGainType()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_CDS_GAIN_TYPE, &bReval);
		INT nType = 0;
		if(bReval)
		{
			nType = 1;
		}
		return(nType);
	};
	BOOL HasMirrorHorizontal()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_MIRROR_HORIZONTAL, &bReval);
		return(bReval);
	};
	BOOL HasMirrorVertical()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_MIRROR_VERTICAL, &bReval);
		return(bReval);
	};
	BOOL HasVBlankForFPS()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_V_BLANK_FOR_FPS, &bReval);
		return(bReval);
	};
	BOOL HasReadOut()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DISABLED_READOUT, &bReval);
		return(!bReval);
	};
	BOOL HasLineDebounceTime()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_LINE_DEBOUNCE_TIME, &bReval);
		return(bReval);
	};
	DWORD GetSupportedSensorShutterMode()
	{
		DWORD value = 0;
		DWORD pdwID[] = {
				STCAM_CAMERA_FUNCTION_CMOS_RESET_TYPE_0,
				STCAM_CAMERA_FUNCTION_CMOS_RESET_TYPE_1
			};
		DWORD dwMask = 1;
		for(int i = 0; i < sizeof(pdwID) / sizeof(DWORD); i++)
		{
			BOOL has = FALSE;
			StTrg_HasFunction(m_hCamera, pdwID[i], &has);
			if(has)
			{
				value |= dwMask;
			}
			dwMask <<= 1;
		}
		return(value);
	};
	BOOL HasTriggerValidOutput()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_TRIGGER_VALID_OUT, &bReval);
		return(bReval);
	};
	BOOL HasAE()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_AE, &bReval);
		return(bReval);
	};
	BOOL HasAGC()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_AGC, &bReval);
		return(bReval);
	};
	BOOL HasStoreCameraSetting()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_STORE_CAMERA_SETTING, &bReval);
		return(bReval);
	};
	BOOL HasCameraMemoryFunction()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_MEMORY, &bReval);
		if(bReval)
		{
			StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DISABLE_MEMORY_TYPE_SELECTION, &bReval);
			bReval = !bReval;
		}
		return(bReval);
	};

	BOOL HasCameraGamma()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_CAMERA_GAMMA, &bReval);
		return(bReval);
	};


	BOOL HasHBinningSum()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_H_BINNING_SUM, &bReval);
		return(bReval);
	};
	BOOL HasVBinningSum()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_V_BINNING_SUM, &bReval);
		return(bReval);
	};

	BOOL HasExposureStartWaitHD()
	{
		BOOL bReval = FALSE;
		if(HasTriggerFunction())
		{
			StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DISABLE_EXPOSURE_START_WAIT_HD, &bReval);
			bReval = !bReval;
		}
		return(bReval);
	};
	BOOL HasExposureStartWaitReadOut()
	{
		BOOL bReval = FALSE;
		if(HasTriggerFunction())
		{
			StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DISABLE_EXPOSURE_START_WAIT_READ_OUT, &bReval);
			bReval = !bReval;
		}
		return(bReval);
	};
	BOOL HasDigitalClamp()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DIGITAL_CLAMP, &bReval);
		return(bReval);
	};
	BOOL HasAnalogBlackLevel()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_ANALOG_BLACK_LEVEL, &bReval);
		return(bReval);
	};
	BOOL HasResetSwitchDisabledFunction()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_IO_RESET_SW_DISABLED, &bReval);
		return(bReval);
	};
	BOOL HasTransferEndOutput()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_TRANSFER_END_OUT, &bReval);
		return(bReval);
	};
	BOOL HasDeviceTemperatureMainBoard()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_DEVICE_TEMPERATURE_MAINBOARD, &bReval);
		return(bReval);
	};
	BOOL HasAdjustmentDigitalGain()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_ADJUSTMENT_MODE_DIGITAL_GAIN, &bReval);
		return(bReval);
	};
	BOOL HasGenICamIO()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_GENICAM_IO, &bReval);
		return(bReval);
	};
	DWORD GetHDRType()
	{
		DWORD dwHDRType = 0;
		StTrg_GetHDRType(m_hCamera, &dwHDRType);
		return(dwHDRType);
	};
	BOOL IsIOUnitUs()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_IO_UNIT_US, &bReval);
		return(bReval);
	};
	BOOL IsSupportedTransferBitsPerPixel(DWORD dwTransferBitsPerPixel)
	{
		return((m_dwEnableTranderBitsPerPixel & dwTransferBitsPerPixel)?TRUE:FALSE);
	};
	BOOL IsSupportedScanMode(WORD wScanMode)
	{
		return((m_wEnableScanMode & wScanMode)?TRUE:FALSE);
	};
	BOOL IsSupportedClockMode(DWORD dwClockMode)
	{
		return((m_dwEnableCloclMode & dwClockMode)?TRUE:FALSE);
	};

	BOOL IsEnableTriggerSoftware(DWORD dwTriggerSelector)
	{
		if(!HasTriggerFunction()) return(FALSE);

		DWORD dwTriggerMode;
		StTrg_GetTriggerMode2(m_hCamera, dwTriggerSelector, &dwTriggerMode);
		if(dwTriggerMode == STCAM_TRIGGER_MODE_OFF) return(FALSE);

		DWORD dwTriggerSource;
		StTrg_GetTriggerSource(m_hCamera, dwTriggerSelector, &dwTriggerSource);
		if(dwTriggerSource != STCAM_TRIGGER_SOURCE_SOFTWARE) return(FALSE);

		if(
			(dwTriggerSelector == STCAM_TRIGGER_SELECTOR_EXPOSURE_START) ||
			(dwTriggerSelector == STCAM_TRIGGER_SELECTOR_EXPOSURE_END)
			)
		{
			if(dwTriggerSelector == STCAM_TRIGGER_SELECTOR_EXPOSURE_END)
			{
				if(m_bAutoTrigger) return(FALSE);
			}
			DWORD dwExposureMode = GetExposureMode();
			if(dwExposureMode != STCAM_EXPOSURE_MODE_TRIGGER_CONTROLLED) return(FALSE);
		}
		return(TRUE);
	};

	DWORD	GetMaxVBlankForFPS()
	{
		return(m_dwMaxVBlankForFPS);
	};
	WORD GetProductID()
	{
		return(m_wUSBProductID);
	};
	
	DWORD	MaximumImageWidth()
	{
		return(m_dwMaximumImageWidth);
	};
	DWORD	MaximumImageHeight()
	{
		return(m_dwMaximumImageHeight);
	};

	DWORD	GetMaxROICount()
	{
		return(m_dwMaxROICount);
	};

	void SetDisplayPixelFormat(DWORD dwPixelFormat)
	{
		StopTransfer();
		m_dwPixelFormat = dwPixelFormat;
		StartTransfer();
	};
	DWORD GetDisplayPixelFormat()
	{
		return(m_dwPixelFormat);
	};

	void SetSensorShutterMode(DWORD dwValue)
	{
		StopTransfer();
		StTrg_SetSensorShutterMode(m_hCamera, dwValue);
		StartTransfer();
	};
	DWORD GetSensorShutterMode()
	{
		DWORD dwValue = 0;
		StTrg_GetSensorShutterMode(m_hCamera, &dwValue);
		return(dwValue);
	};

	void SetExposureMode(DWORD dwValue)
	{
		StopTransfer();
		StTrg_SetExposureMode(m_hCamera, dwValue);
		StartTransfer();
	};
	DWORD GetExposureMode()
	{
		DWORD dwValue = 0;
		StTrg_GetExposureMode(m_hCamera, &dwValue);
		return(dwValue);
	};

	DWORD GetTriggerSelector()
	{
		return(m_dwTriggerSelector);
	};
	void SetTriggerSelector(DWORD dwTriggerSelector)
	{
		m_dwTriggerSelector = dwTriggerSelector;
	};

	BOOL IsTriggerSelectorSupported(DWORD dwTriggerSelector)
	{
		BOOL bReval = FALSE;
		StTrg_IsTriggerSelectorSupported(m_hCamera, dwTriggerSelector, &bReval);
		return(bReval);
	};

	DWORD GetTriggerMode2()
	{
		DWORD dwValue = 0;
		StTrg_GetTriggerMode2(m_hCamera, m_dwTriggerSelector, &dwValue);
		return(dwValue);
	};
	void SetTriggerMode2(DWORD dwValue)
	{
		StopTransfer();
		StTrg_SetTriggerMode2(m_hCamera, m_dwTriggerSelector, dwValue);
		StartTransfer();
		return;
	};

	DWORD GetTriggerSource()
	{
		DWORD dwValue = 0;
		StTrg_GetTriggerSource(m_hCamera, m_dwTriggerSelector, &dwValue);
		return(dwValue);
	};
	void SetTriggerSource(DWORD dwValue)
	{
		StopTransfer();
		StTrg_SetTriggerSource(m_hCamera, m_dwTriggerSelector, dwValue);
		StartTransfer();
		return;
	};

	DWORD GetTriggerDelay()
	{
		DWORD dwValue = 0;
		StTrg_GetTriggerDelay(m_hCamera, m_dwTriggerSelector, &dwValue);
		return(dwValue);
	};
	void SetTriggerDelay(DWORD dwValue)
	{
		StopTransfer();
		StTrg_SetTriggerDelay(m_hCamera, m_dwTriggerSelector, dwValue);
		StartTransfer();
		return;
	};

	DWORD GetTriggerOverlap()
	{
		DWORD dwValue = 0;
		StTrg_GetTriggerOverlap(m_hCamera, m_dwTriggerSelector, &dwValue);
		return(dwValue);
	};
	void SetTriggerOverlap(DWORD dwValue)
	{
		StopTransfer();
		StTrg_SetTriggerOverlap(m_hCamera, m_dwTriggerSelector, dwValue);
		StartTransfer();
		return;
	};

	BOOL IsAnyTriggerModeON()
	{
		if(!HasTriggerFunction()) return(FALSE);

		DWORD pdwTriggerSelector[] = 
		{
			STCAM_TRIGGER_SELECTOR_FRAME_START, 
			STCAM_TRIGGER_SELECTOR_FRAME_BURST_START, 
			STCAM_TRIGGER_SELECTOR_EXPOSURE_START, 
			STCAM_TRIGGER_SELECTOR_EXPOSURE_END,
			STCAM_TRIGGER_SELECTOR_SENSOR_READ_OUT_START
		};

		for(size_t i = 0; i < _countof(pdwTriggerSelector); i++)
		{
			if(IsTriggerSelectorSupported(pdwTriggerSelector[i]))
			{
				DWORD dwValue = 0;
				StTrg_GetTriggerMode2(m_hCamera, pdwTriggerSelector[i], &dwValue);
				if(dwValue == STCAM_TRIGGER_MODE_ON)
				{
					return(TRUE);
				}
			}
		}
		return(FALSE);
	};

	BOOL HasPriorityMode()
	{
		BOOL bReval = FALSE;
		StTrg_HasFunction(m_hCamera, STCAM_CAMERA_FUNCTION_PRIORITY_MODE, &bReval);
		return(bReval);
	};

	BOOL SetPriorityMode(DWORD dwValue)
	{
		BOOL bReval = TRUE;
		do
		{
			bReval = StopTransfer();
			if(!bReval) break;
			bReval = StTrg_SetPriorityMode(m_hCamera, dwValue);
			if(!bReval) break;
			bReval = StartTransfer();
		}while(false);
		return(bReval);
	};

	HANDLE	m_hCamera;

	//Setting
	BYTE	m_byteColorInterpolationMethod;
	DWORD	m_dwTriggerMode;
	BOOL	m_bAutoTrigger;
	DWORD	m_dwNoiseReductionMode;
	BYTE	m_byteMirrorMode;
	BYTE	m_byteRotationMode;

	//SDK Version
	DWORD	m_dwFileVersionMS;
	DWORD	m_dwFileVersionLS;
	DWORD	m_dwProductVersionMS;
	DWORD	m_dwProductVersionLS;

	//Camera Info
	WORD	m_wUSBVendorID;
	WORD	m_wUSBProductID;
	WORD	m_wFPGAVersion;
	WORD	m_wFirmVersion;
	WORD	m_wColorArray;
	DWORD	m_dwCameraNo;
	TCHAR	m_szCameraName[250 / sizeof(TCHAR)];

	DWORD	m_dwMaximumImageWidth;
	DWORD	m_dwMaximumImageHeight;
	DWORD	m_dwMaxVBlankForFPS;
#ifdef _DEBUG
	//Debug
	DWORD	m_dwLastStartTriggerTime;
#endif //_DEBUG
protected:
	virtual void ExposureEndCallback(HANDLE hCamera, DWORD dwFrameNo) = 0;
	virtual void TransferEndCallback(HANDLE hCamera, DWORD dwFrameNo, DWORD dwWidth, DWORD dwHeight, WORD wColorArray, PBYTE pbyteRaw) = 0;
	virtual void RcvErrorCallback(HANDLE hCamera, DWORD dwErrorCode) = 0;
protected:
	DWORD	m_dwEnableTranderBitsPerPixel;
	WORD	m_wEnableScanMode;
	DWORD	m_dwEnableCloclMode;
	DWORD	m_dwMaxROICount;
	DWORD	m_dwPixelFormat;

	DWORD	m_dwTriggerSelector;
};

#endif // !defined(AFX_STCAMERA_H__EADFB89B_7118_42CE_8239_B97FCDC34FC0__INCLUDED_)
