/*************************************************************************\
* "$RCSfile: CFeature.cpp,v $"                                            *
***************************************************************************
* Information by CVS or VSS:                                              *
*     Last check in on: $Date: 2011/10/20 07:46:31 $                      *
*     by                $Author: schluckebier $
*     Revision        : $Revision: 1.38 $                                 *
\*************************************************************************/
/*! \file CFeature.cpp
*	\brief Implementation CFeature Class
**************************************************************************/

#include "VIC_PS.h"
#include "GBit.h"
#include "common.h"
#include "CRegion.h"
#include "CLog.hpp"
#include "CPSApp.hpp"
#include "CFeature.hpp"
#include "CDlg.hpp"
#include "CDlgCamExpert.hpp"
#include "CCamFeatures.hpp"

//!@cond SHOWALL
typedef struct sSUN_CONFIG
{
	unsigned int Version;			//!< FPGA version number
	int CycleTime;					//!< Cycle time in ps
	unsigned int DSP_SourceBase;
	unsigned int DSP_SourceShift;
	int DSP_SourceAutoEvent;
	unsigned int DSP_CtrlReg;
} SUN_CONFIG;

extern SUN_CONFIG VIB_SunConfig;
//!@endcond

/*************************************************************************/
CFeature::CFeature(const char *pName, bool bIsOnlyCamProperty,
	bool bIsOnlyFGProperty, int ScaleFactor)
/*************************************************************************/
/*! @brief Constructor
	@param pName Pointer to the name of the feature
	@param bIsOnlyCamProperty Is camera module feature only and there is no
	dependency between FG and Camera
	@param bIsOnlyFGProperty Is FG feature only and there is no
	dependency between FG and Camera
	@param ScaleFactor The feature value is multiplied with this factor to
	handle \p float as \p int
	@par Example:
	@code
m_pExposureTime = new CFeature("ExposureTime", true, false, 1000);
	@endcode
**************************************************************************/
{
	m_pApp = CPSApp::GetInstance();
	m_Port = m_pApp->GetCamSerialPort();
	VIB_SStrCpy(m_Name, pName, MAX_PROPNAME);
	m_bIsOnlyCamProperty = bIsOnlyCamProperty;
	m_bIsOnlyFGProperty = bIsOnlyFGProperty;
	m_ScaleFactor = ScaleFactor;
	m_bIsVolatile = false;
	m_ModeValues[0] = 0;
	m_ValueStr[0] = '\0';
	m_Value = 0;
	m_Min = 0;
	m_Max = 0;
	m_pTempConf = NULL;
	m_Token = INVALID_TOKEN;
	m_PropertyType = PF_INVALID;
	m_StateIniParam = 1;
	m_bIsAvailable = false;
	if (m_pApp->IsCameraPresent() || m_bIsOnlyFGProperty)
		Init();
}

/*************************************************************************/
int CFeature::Init()
/*************************************************************************/
/*! @brief Init class

	Initializes the feature settings in sensor and frame-grabber module.
	The initial values are read and handled depending on the type of
	the camera property.
**************************************************************************/
{
	int error, i;
	unsigned int Flags;
	TOKEN t;
	PROPERTY p, *PropertyList;
	char tmp[MAX_PROPNAME];
	unsigned char MacAdr[8];
	char *pText;
	Config *pCurrentIni = m_pApp->GetCurrentIni();
	Config *pStringsIni = m_pApp->GetPSStringsIni();

	if (!m_bIsOnlyFGProperty)
	{
		// Get property type
		t = pfProperty_ParseName(m_Port, m_Name);
		if (t == INVALID_TOKEN)
		{
			m_Value = 0;
			m_Min = 0;
			m_Max = 0;
			return 0;
		}
		m_Token = t;
		m_bIsAvailable = true;
		// Get type
		m_PropertyType = pfProperty_GetType(m_Port, m_Token);
		// Get min max of property
		CDlgCamExpert::GetPropMinMax(m_Port, m_Token, &p);

		// Get value of property
		ReadValueFromCamera();

		// Get flags
		Flags = pfProperty_GetFlags(m_Port, m_Token);

		if ((Flags & F_INACTIVE) || (Flags & F_RO))
			m_bInactive = true;
		else
			m_bInactive = false;

		if (!(Flags & F_WO))
		{
			switch (m_PropertyType)
			{
			case PF_FLOAT:
				m_Min = (int)(p.Min.value.f * m_ScaleFactor);
				m_Max = (int)(p.Max.value.f * m_ScaleFactor);
				break;
			case PF_INT:
				m_Min = p.Min.value.i;
				if (m_Min > m_Value)
					m_Min = m_Value;
				m_Max = p.Max.value.i;
				if (m_Max < m_Value)
					m_Max = m_Value;
				break;
			case PF_BOOL:
				m_Min = 0;
				m_Max = 1;
				break;
			case PF_MODE:	// Get all modes
				PropertyList = (PROPERTY*)malloc(MAXPROPERTIES * sizeof(PROPERTY));
				error = CDlgCamExpert::GetChildren(m_Port, t, PropertyList);
				m_Min = 0;
				if (error > 0)
				{
					// Copy name of modes
					i = 0;
					m_ModeValues[0] = 0;
					while ((PropertyList[i].Name[0]))
					{
						std::snprintf(tmp, MAX_PROPNAME, "%s\n", PropertyList[i].Name);
						strcat(m_ModeValues, tmp);
						i++;
					}
					m_Max = i;
				}
				free(PropertyList);
				break;
			// --> This part needs to be checked !!!
			case PF_INVALID:
			case PF_ROOT:
			case PF_REGISTER:
			case PF_STRING:
			case PF_BUFFER:
			case PF_STRUCT:
			case PF_ARRAY:
			case PF_COMMAND:
			case PF_EVENT:
				m_StateIniParam = 0;
				break;
			}
		}
		else
		{
			m_Value = 0;
			m_Min = 0;
			m_Max = 0;
			m_StateIniParam = 0;
		}
		// Each Property is defined in current config with name, value, max, min and comment
		// the value is written to camera
		if (pCurrentIni && m_StateIniParam)
		{
			m_Value = pCurrentIni->getValue(m_Name, m_Value, m_Min, m_Max);
			pText = pStringsIni->getValue(m_Name, "No comment!");
			pCurrentIni->setComment(m_Name, pText);
			if (!(Flags & F_RO))
				WriteValueToCamera();
		}
		
		if (strcmp(m_Name, "Average.Value") == 0)
			m_bIsVolatile = true;
	}
	if (!m_bIsOnlyCamProperty)
	{
		if (strcmp(m_Name, "FG_StrobeOutput") == 0)
		{
			strcpy(m_ModeValues, "Disabled\nOpto 0\n Diff 0\n");
			if (pCurrentIni)
			{
				m_Value = m_pApp->GetStrobeOutput();
				pText = pStringsIni->getValue(m_Name, "No comment!");
				pCurrentIni->setComment(m_Name, pText);
			}
		}
		else if (strcmp(m_Name, "FG_TriggerDivisor") == 0)
		{
			m_Min = 1;
			m_Max = 1 << 24;
			if (pCurrentIni)
				m_Value = pCurrentIni->getValue(m_Name, 1, m_Min, m_Max);
			else
				m_Value = 1;
			m_bInactive = true;
		}
		else if (strcmp(m_Name, "PSCSerial") == 0)
		{
			if (VIB_GetSerialNumber(tmp) < 0)
				std::snprintf(tmp, MAX_PROPNAME, "SerialnumberInvalid");
			std::snprintf(m_ValueStr, MAX_PROPNAME, "%s", tmp);
		}
		else if (strcmp(m_Name, "DSPModuleSerial") == 0)
		{
			VIB_GetModuleSerialNumber(tmp);
			std::snprintf(m_ValueStr, MAX_PROPNAME, "%s", tmp);
		}
		else if (strcmp(m_Name, "AlteraFPGA") == 0)
		{
			if (VIB_HWInfo.FPGA_Version[0])
				error = VIB_HWInfo.FPGA_Version[0];
			else
				error = VIB_SunConfig.Version;
			sprintf(m_ValueStr, "%d", error);
		}
		else if (strcmp(m_Name, "MACAddress") == 0)
		{
			if (m_pApp->GetEthError() == 0)
			{
				GBIT_GetPhyInfo(MacAdr, &error);
				sprintf(m_ValueStr, "%02X-%02X-%02X-%02X-%02X-%02X",
						MacAdr[0], MacAdr[1], MacAdr[2], MacAdr[3], MacAdr[4], MacAdr[5]);
			}
			else
				strcpy(m_ValueStr, "00-00-00-00-00-00");
		}
		else if (strcmp(m_Name, "LineCamMode") == 0)
		{
			if (pCurrentIni && m_StateIniParam)
			{
				m_Min = 0;
				m_Max = 1;
				m_Value = pCurrentIni->getValue(m_Name, m_Value, m_Min, m_Max);
			}
		}
		else if (strcmp(m_Name, "LSImageHeight") == 0)
		{
			m_Min = 1;
			m_Max = 10000;
			if (pCurrentIni)
				m_Value = pCurrentIni->getValue(m_Name, 1024, m_Min, m_Max);
			else
				m_Value = 1024;
			m_bInactive = true;
		}
	}
	return 0;
}

/*************************************************************************/
int CFeature::GetValue()
/*************************************************************************/
/*! @brief Gets (protected) Value
	@return Value of feature
**************************************************************************/
{
	if (m_bIsVolatile)
		ReadValueFromCamera();
	return m_Value;
}

/*************************************************************************/
void CFeature::Event()
/*************************************************************************/
/*! @brief Reads value

	Event() loads the value from the camera module when an update is
	necessary because of dependency to another feature.
**************************************************************************/
{
	CCamFeatures *pCF = CCamFeatures::GetInstance();

	// First read value from camera
	if (!m_bIsOnlyFGProperty)
		ReadValueFromCamera();
	
	if (strcmp(m_Name, "ExposureTime") == 0)
		pCF->m_ExpV = m_Value;
	if (strcmp(m_Name, "FrameTime") == 0)
		pCF->m_FrameTV = m_Value;
	if (strcmp(m_Name, "FineGain") == 0)
		pCF->m_FineGainV = m_Value;

	// Set the read Value in temp config
	if (m_pTempConf != NULL)
		m_pTempConf->setValue(m_Name, m_Value);

	if (!m_bIsOnlyFGProperty)
	{
		// Get flags
		unsigned int flags = pfProperty_GetFlags(m_Port, m_Token);

		if ((flags & F_INACTIVE) || (flags & F_RO))
		{
			m_bInactive = true;
		}
		else
		{
			if (!strcmp(m_Name, "Trigger.LevelControlled"))
				m_bInactive = (pCF->m_pTriggerSource->GetValue() == 4);
			else
				m_bInactive = false;
		}
	}
	else
	{
		if (strcmp(m_Name, "FG_TriggerDivisor") == 0)
			m_bInactive = (pCF->m_pTriggerSource->GetValue() != 4);
	}
}

/*************************************************************************/
void CFeature::ReadValueFromCamera()
/*************************************************************************/
/*! @brief Reads value from camera module.
**************************************************************************/
{
	PFValue value;

	pfDevice_GetProperty(m_Port, m_Token, &value);

	switch (m_PropertyType)
	{
	case PF_INT:
	case PF_BOOL:
	case PF_COMMAND:
		m_Value = (int)value.value.i;
		sprintf(m_ValueStr, "%d", m_Value);
		break;
	case PF_MODE:
		m_Value = (int)value.value.i + 1;
		sprintf(m_ValueStr, "%d", m_Value);
		break;
	case PF_FLOAT:
		m_Value = (int)(value.value.f * m_ScaleFactor);
		sprintf(m_ValueStr, "%d", m_Value);
		break;
	case PF_STRING:
		VIB_SStrCpy(m_ValueStr, (char*)value.value.p, MAX_PROPNAME);
		break;
	}
}

/*************************************************************************/
int CFeature::WriteValueToCamera()
/*************************************************************************/
/*! @brief Writes value to camera module.
	@return Error code
**************************************************************************/
{
	int error;
	PFValue value;

	switch (m_PropertyType)
	{
	case PF_INT:
	case PF_BOOL:
	case PF_COMMAND:
		value.value.i = m_Value;
		break;
	case PF_MODE:
		value.value.i = m_Value - 1;
		break;
	case PF_FLOAT:
		value.value.f = (float)m_Value / (float)m_ScaleFactor;
		break;
	case PF_STRING:
		value.value.p = m_ValueStr;
		break;
	case PF_INVALID:
		return -1;
	}
	value.type = m_PropertyType;
	error = pfDevice_SetProperty(m_Port, m_Token, &value);

	if (error != 0)
		ReadValueFromCamera();
	if (error < 0)
	{
		CLog::Print("Camera write error: %s\n       Feature: %s, Value: %d\n", pfGetErrorString(error), m_Name, m_Value);
		m_bInactive = true;
		return error;
	}
	return 0;
}

//! Strobe output types
enum eSTROBE_OUTPUT
{
	STROBE_DISABLED = 0x00,
	STROBE_OPTO_0 =   0x10,
	STROBE_DIFF_0 =   0x04
};

/*************************************************************************/
int CFeature::UpdateValue(Config *pConfig)
/*************************************************************************/
/*! @brief Updates value.

	Called when the value or configuration value has changed and settings
	have to be transmitted to Camera or frame-grabber.
	@return Error code. Always 0.
**************************************************************************/
{
	CCamFeatures *pCF = CCamFeatures::GetInstance();

	if (pConfig != NULL)
	{
		m_Value = pConfig->getValue(m_Name, m_Value);
		m_pTempConf = pConfig;
	}
	else if (m_pTempConf != NULL)
	{
		m_pTempConf->setValue(m_Name, m_Value);
	}
	
	if (strcmp(m_Name, "ExposureTime") == 0)
		pCF->m_ExpV = m_Value;
	else if (strcmp(m_Name, "FrameTime") == 0)
		pCF->m_FrameTV = m_Value;
	else if (strcmp(m_Name, "FineGain") == 0)
		pCF->m_FineGainV = m_Value;

	if (m_PropertyType != PF_STRING)
		sprintf(m_ValueStr, "%d", m_Value);

	if (!m_bIsOnlyFGProperty)
		WriteValueToCamera();
	if (strcmp(m_Name, "FG_StrobeOutput") == 0)
	{
		switch (m_Value)
		{
		case 2:
			m_pApp->SetStrobeOutput(STROBE_OPTO_0);
			break;
		case 3:
			m_pApp->SetStrobeOutput(STROBE_DIFF_0);
			break;
		default:
			m_pApp->SetStrobeOutput(STROBE_DISABLED);
			break;
		}
	}

	if (!m_bIsOnlyFGProperty)
	{
		// Get flags
		const unsigned int flags = pfProperty_GetFlags(m_Port, m_Token);

		if ((flags & F_INACTIVE) || (flags & F_RO))
		{
			m_bInactive = true;
		}
		else
		{
			if (!strcmp(m_Name, "Trigger.LevelControlled"))
				m_bInactive = (pCF->m_pTriggerSource->GetValue() == 4);
			else
				m_bInactive = false;
		}
	}
	else
	{
		if (strcmp(m_Name, "FG_TriggerDivisor") == 0)
		{
			m_bInactive = (pCF->m_pTriggerSource->GetValue() != 4);
			m_pApp->SetTriggerSource();
		}
	}
	return 0;
}

/*************************************************************************/
CFeatureWindow::CFeatureWindow(const char *pName, bool bIsOnlyCamProperty, bool bIsOnlyFGProperty, int ScaleFactor)
	: CFeature(pName, bIsOnlyCamProperty, bIsOnlyFGProperty, ScaleFactor)
/*************************************************************************/
/*! @brief Constructor
	@param pName Pointer to the name of the feature
	@param bIsOnlyCamProperty Is camera module feature only and there is no
	dependency between frame-grabber and camera
	@param bIsOnlyFGProperty Is FG feature only and there is no dependency
	between frame-grabber and camera
	@param ScaleFactor For handling float as int the value is multiplied
	with this factor
	@par Example:
	@code
m_pWindowX = new CFeatureWindow("Window.X", false, false);
	@endcode
**************************************************************************/
{
}

/*************************************************************************/
int CFeatureWindow::UpdateValue(Config *pConfig)
/*************************************************************************/
/*! @brief Update value.

	Called when the value or configuration value has changed and settings
	have to be transmitted to camera or frame-grabber.
	@return Error code.
**************************************************************************/
{
	const bool RestartGrabtask = m_pApp->IsGrabTaskActive();
	int h, w, dec = 1;

	if (!m_pApp->IsCameraPresent())
		return -1;

	if (RestartGrabtask)
		m_pApp->StopGrabTask();

	if (pConfig != NULL)
	{
		m_Value = pConfig->getValue(m_Name, m_Value);
		m_pTempConf = pConfig;
	}
	else if (m_pTempConf != NULL)
	{
		m_pTempConf->setValue(m_Name, m_Value);
	}

	WriteValueToCamera();

	sprintf(m_ValueStr, "%d", m_Value);

	int hInterface, wInterface;
	wInterface = GetPropertyInt(m_Port, "Window.WInterface", &w);
	hInterface = GetPropertyInt(m_Port, "Window.HInterface", &h);

	if(wInterface >= 0 && hInterface >= 0)
	{
		m_pApp->m_CamReg.m_Width = w;
		m_pApp->m_CamReg.m_Height = h;
	}
	else{

		if ((strcmp(m_Name, "MROI.Enable") == 0) && (m_Value == TRUE))
		{
			if (GetPropertyInt(m_Port, "MROI.Htot", &h) >= 0)
				m_pApp->m_CamReg.m_Height = h;
		}
		else if ((strcmp(m_Name, "Window.X") == 0) || (strcmp(m_Name, "Window.W") == 0))
		{
			if (GetPropertyInt(m_Port, "Window.W", &w) >= 0)
				m_pApp->m_CamReg.m_Width = w;
		}
		else if ((strcmp(m_Name, "Window.Y") == 0) || (strcmp(m_Name, "Window.H") == 0) || (strcmp(m_Name, "Decimation.Y") == 0))
		{
			if (GetPropertyInt(m_Port, "Window.H", &h) >= 0)
			{
				GetPropertyInt(m_Port, "Decimation.Y", &dec);

				if (VIB_HWInfo.Type == VIB_TYPE_PSC)
					m_pApp->m_CamReg.m_Height = (h - 1) / dec + 1;
				else
					m_pApp->m_CamReg.m_Height = h;
			}
		}
	}
	m_pApp->UpdateScaleFactors();
	if (RestartGrabtask)
		m_pApp->StartGrabTask();
	return 0;
}

/*************************************************************************/
CFeatureTrigger::CFeatureTrigger(const char *pName, bool bIsOnlyCamProperty, bool bIsOnlyFGProperty, int ScaleFactor)
	: CFeature(pName, bIsOnlyCamProperty, bIsOnlyFGProperty, ScaleFactor)
/*************************************************************************/
/*! @brief Constructor
	@param pName Pointer to the name of the feature
	@param bIsOnlyCamProperty Is camera module feature only and there is no
	dependency between frame-grabber and camera
	@param bIsOnlyFGProperty Is FG feature only and there is no dependency
	between frame-grabber and camera
	@param ScaleFactor For handling float as int the value is multiplied
	with this factor
	@par Example:
	@code
m_pTriggerSource = new CFeatureTrigger("Trigger.Source", false, false);
	@endcode
**************************************************************************/
{
	if (VIB_HWInfo.Type == VIB_TYPE_PSC)
	{
		strcpy(m_ModeValues, "Free Running\nOpt. In 0\nRS422 In 0\n");
		if (VIB_HWInfo.FPGA_Version[0] >= 102)
			strcat(m_ModeValues, "RS422 Encoder\n");
	}
	else
	{
		strcpy(m_ModeValues, "Free Running\nInterface\nI/O\n");
	}
}

/*************************************************************************/
int CFeatureTrigger::UpdateValue(Config *pConfig)
/*************************************************************************/
/*! @brief Update value

	Called when the value or configuration value changed and settings have
	to be transmitted to camera or frame-grabber.
	@return Error code. Always 0.
**************************************************************************/
{
	if (pConfig != NULL)
	{
		m_Value = pConfig->getValue(m_Name, m_Value);
		m_pTempConf = pConfig;
	}
	else if (m_pTempConf != NULL)
	{
		m_pTempConf->setValue(m_Name, m_Value);
	}

	if (m_Value == 1)	// Set sensor to free run mode
		SetPropertyInt(m_Port, m_Name, 0);
	if (m_Value > 1)	// Set sensor to triggered mode
		SetPropertyInt(m_Port, m_Name, (VIB_HWInfo.Type == VIB_TYPE_PSC) ? 1 : (m_Value - 1));

	// Configure trigger source
	m_pApp->SetTriggerSource();

	sprintf(m_ValueStr, "%d", m_Value);
	return 0;
}

/*************************************************************************/
CFeatureResolution::CFeatureResolution(const char *pName, bool bIsOnlyCamProperty, bool bIsOnlyFGProperty, int ScaleFactor)
	: CFeature(pName, bIsOnlyCamProperty, bIsOnlyFGProperty, ScaleFactor)
/*************************************************************************/
/*! @brief Constructor
	@param pName Pointer to the name of the feature
	@param bIsOnlyCamProperty Is camera module feature only and there is no
	dependency between frame-grabber and camera
	@param bIsOnlyFGProperty Is FG feature only and there is no dependency
	between frame-grabber and camera
	@param ScaleFactor To handle float as integer, the value is multiplied with this factor
	@par Example:
	@code
m_pDataResolution = new CFeatureResolution("DataResolution", false, false);
	@endcode
**************************************************************************/
{
	m_CameraModel = 1;	// 2 Tap
	UpdateCamPixelFormat();
}

/*************************************************************************/
int CFeatureResolution::UpdateValue(Config *pConfig)
/*************************************************************************/
/*! @brief Update value.

	Called when the value or configuration value has changed and settings
	have to be transmitted to camera or frame-grabber.
	@return Error code.
**************************************************************************/
{
	const bool RestartGrabTask = m_pApp->IsGrabTaskActive();

	if (!m_pApp->IsCameraPresent())
		return -1;

	if (RestartGrabTask)
		m_pApp->StopGrabTask();

	if (pConfig != NULL)
	{
		m_Value = pConfig->getValue(m_Name, m_Value);
		m_pTempConf = pConfig;
	}
	else if (m_pTempConf != NULL)
	{
		m_pTempConf->setValue(m_Name, m_Value);
	}

	SetPropertyInt(m_Port, m_Name, m_Value - 1);

	UpdateCamPixelFormat();

	if (RestartGrabTask)
		m_pApp->StartGrabTask();

	sprintf(m_ValueStr, "%d", m_Value);
	return 0;
}

/*************************************************************************/
void CFeatureResolution::UpdateCamPixelFormat()
/*************************************************************************/
/*! @brief Sets camera pixel format depending on camera type.
**************************************************************************/
{
	switch (m_CameraModel)
	{
	case 0: //D1024: 40MHz/1Tap
		switch (m_Value)
		{
			case 1: m_pApp->SetCamPixelFormat(CamMode::_1TAP_12BIT); break;
			case 2: m_pApp->SetCamPixelFormat(CamMode::_1TAP_10BIT); break;
			default: m_pApp->SetCamPixelFormat(CamMode::_1TAP_8BIT); break;
		}
		break;
	case 1: //D1024: 40MHz/2Tap
		switch (m_Value)
		{
			case 1: m_pApp->SetCamPixelFormat(CamMode::_2TAP_12BIT); break;
			case 2: m_pApp->SetCamPixelFormat(CamMode::_2TAP_10BIT); break;
			default: m_pApp->SetCamPixelFormat(CamMode::_2TAP_8BIT); break;
		}
		break;
	case 2:
		m_pApp->SetCamPixelFormat(CamMode::_2TAP_8BIT);
		break;
	case 3: //D1312: 40MHz/1Tap
		switch (m_Value)
		{
			case 1: m_pApp->SetCamPixelFormat(CamMode::_1TAP_8BIT); break;
			case 2: m_pApp->SetCamPixelFormat(CamMode::_1TAP_10BIT); break;
			default: m_pApp->SetCamPixelFormat(CamMode::_1TAP_12BIT); break;
		}
		break;
	case 4: //D1312: 40MHz/2Tap
		switch (m_Value)
		{
			case 1: m_pApp->SetCamPixelFormat(CamMode::_2TAP_8BIT); break;
			case 2: m_pApp->SetCamPixelFormat(CamMode::_2TAP_10BIT); break;
			default: m_pApp->SetCamPixelFormat(CamMode::_2TAP_12BIT); break;
		}
		break;
	}
}

/*************************************************************************/
void CFeatureResolution::CalcCameraModel()
/*************************************************************************/
/*! @brief Calculates camera model (1/2-Tap).
**************************************************************************/
{
	if (!m_pApp->IsCameraPresent())
		return;	// m_CameraModel/ m_CamPixelFormat has default values

	const TOKEN t = pfProperty_ParseName(m_Port, "Header.InterfaceTaps");

	if (t == INVALID_TOKEN)
	{
		char ValueStr[40];

		GetPropertyString(m_Port, "CameraName", ValueStr);
		int l = strlen(ValueStr);
		int Speed = atoi(&ValueStr[l - 2]);

		switch (Speed)
		{
			case 40: m_CameraModel = 0; break;
			case 80: m_CameraModel = 1; break;
			case 60: m_CameraModel = 2; break;	// '1'60
		}
	}
	else	// D1312 and newer
	{
		int InterfaceTaps;

		GetPropertyInt(m_Port, "Header.InterfaceTaps", &InterfaceTaps);
		switch (InterfaceTaps)
		{
			case 1: m_CameraModel = 3; break;
			case 2: m_CameraModel = 4; break;
		}
	}
	UpdateCamPixelFormat();
}

/*************************************************************************/
