/////////////////////////////////////////////////////////////
//
// ApnCamData_CCD230_42.cpp:  Implementation file for the CApnCamData_CCD230_42 class.
//
// Copyright (c) 2003-2007 Apogee Instruments, Inc.
//
/////////////////////////////////////////////////////////////

#include "ApnCamData_CCD230_42.h"

#include <stdlib.h>
#include <malloc.h>
#include <string.h>


/////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////////////


CApnCamData_CCD230_42::CApnCamData_CCD230_42()
{
}


CApnCamData_CCD230_42::~CApnCamData_CCD230_42()
{
}


void CApnCamData_CCD230_42::Initialize()
{
	strcpy( m_Sensor, "CCD230_42" );
	strcpy( m_CameraModel, "230" );
	m_CameraId = 61;
	m_InterlineCCD = false;
	m_SupportsSerialA = true;
	m_SupportsSerialB = true;
	m_SensorTypeCCD = true;
	m_TotalColumns = 2148;
	m_ImagingColumns = 2048;
	m_ClampColumns = 50;
	m_PreRoiSkipColumns = 0;
	m_PostRoiSkipColumns = 0;
	m_OverscanColumns = 50;
	m_TotalRows = 2064;
	m_ImagingRows = 2048;
	m_UnderscanRows = 8;
	m_OverscanRows = 8;
	m_VFlushBinning = 1;
	m_EnableSingleRowOffset = false;
	m_RowOffsetBinning = 1;
	m_HFlushDisable = false;
	m_ShutterCloseDelay = 300;
	m_PixelSizeX = 15;
	m_PixelSizeY = 15;
	m_Color = false;
	m_ReportedGainSixteenBit = 2.4;
	m_MinSuggestedExpTime = 30;
	m_CoolingSupported = true;
	m_RegulatedCoolingSupported = true;
	m_TempSetPoint = -20;
	m_TempRampRateOne = 700;
	m_TempRampRateTwo = 4000;
	m_TempBackoffPoint = 2;
	m_PrimaryADType = ApnAdType_Alta_Sixteen;
	m_AlternativeADType = ApnAdType_Alta_Twelve;
	m_PrimaryADLatency = 1;
	m_AlternativeADLatency = 12;
	m_IRPreflashTime = 160;
	m_DefaultGainLeft = 0;
	m_DefaultOffsetLeft = 100;
	m_DefaultGainRight = 0;
	m_DefaultOffsetRight = 0;
	m_DefaultRVoltage = 1000;
	m_DefaultSpeed = 0xffff;
	m_DefaultDataReduction = false;

	set_vpattern();

	set_hpattern_clamp_sixteen();
	set_hpattern_skip_sixteen();
	set_hpattern_roi_sixteen();

	set_hpattern_clamp_twelve();
	set_hpattern_skip_twelve();
	set_hpattern_roi_twelve();
}


void CApnCamData_CCD230_42::set_vpattern()
{
	const unsigned short Mask = 0x1E;
	const unsigned short NumElements = 55;
	unsigned short Pattern[NumElements] = 
	{
		0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0018, 0x0018, 
		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 
		0x0010, 0x0010, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0016, 
		0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0006, 0x0006, 0x0006, 0x0006, 
		0x0006, 0x0006, 0x0006, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 
		0x0000, 0x0000, 0x0000, 0x0001, 0x0000
	};

	m_VerticalPattern.Mask = Mask;
	m_VerticalPattern.NumElements = NumElements;
	m_VerticalPattern.PatternData = 
		(unsigned short *)malloc(NumElements * sizeof(unsigned short));

	for ( int i=0; i<NumElements; i++ )
	{
		m_VerticalPattern.PatternData[i] = Pattern[i];
	}
}


void CApnCamData_CCD230_42::set_hpattern_skip_sixteen()
{
	const unsigned short Mask = 0x21E;
	const unsigned short BinningLimit = 1;
	const unsigned short RefNumElements = 17;
	const unsigned short SigNumElements = 14;

	unsigned short RefPatternData[RefNumElements] = 
	{
		0x006C, 0x006A, 0x006A, 0x006A, 0x0068, 0x0068, 0x0270, 0x1270, 0x1270, 0x02F0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0
	};

	unsigned short SigPatternData[SigNumElements] = 
	{
		0x0044, 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0004, 0x0004, 0x0005, 0x0004
	};

	unsigned short BinNumElements[APN_MAX_HBINNING] = 
	{
		0x0002
	};

	unsigned short BinPatternData[1][256] = {
	{
		0x0250, 0x0250
	} };

	set_hpattern(	&m_SkipPatternSixteen,
					Mask,
					BinningLimit,
					RefNumElements,
					SigNumElements,
					BinNumElements,
					RefPatternData,
					SigPatternData,
					BinPatternData );
}


void CApnCamData_CCD230_42::set_hpattern_clamp_sixteen()
{
	const unsigned short Mask = 0x21E;
	const unsigned short BinningLimit = 1;
	const unsigned short RefNumElements = 17;
	const unsigned short SigNumElements = 14;

	unsigned short RefPatternData[RefNumElements] = 
	{
		0x006C, 0x006A, 0x006A, 0x006A, 0x0068, 0x0068, 0x0270, 0x1270, 0x1270, 0x02F0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0
	};

	unsigned short SigPatternData[SigNumElements] = 
	{
		0x0044, 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0004, 0x0004, 0x0005, 0x0004
	};

	unsigned short BinNumElements[APN_MAX_HBINNING] = 
	{
		0x0002
	};

	unsigned short BinPatternData[1][256] = {
	{
		0x0250, 0x0250
	} };

	set_hpattern(	&m_ClampPatternSixteen,
					Mask,
					BinningLimit,
					RefNumElements,
					SigNumElements,
					BinNumElements,
					RefPatternData,
					SigPatternData,
					BinPatternData );
}


void CApnCamData_CCD230_42::set_hpattern_roi_sixteen()
{
	const unsigned short Mask = 0x21E;
	const unsigned short BinningLimit = 5;
	const unsigned short RefNumElements = 41;
	const unsigned short SigNumElements = 35;

	unsigned short RefPatternData[RefNumElements] = 
	{
		0x006E, 0x006A, 0x006A, 0x006A, 0x006A, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 
		0x0270, 0x1270, 0x1270, 0x02F0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 
		0x02D0
	};

	unsigned short SigPatternData[SigNumElements] = 
	{
		0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0104, 0x8004, 0x8404, 0x0405, 0x0004
	};

	unsigned short BinNumElements[APN_MAX_HBINNING] = 
	{
		0x0002, 0x0010, 0x0020, 0x0030, 0x0040
	};

	unsigned short BinPatternData[5][256] = {
	{
		0x0250, 0x0250
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 
		0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 
		0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050
	} };

	set_hpattern(	&m_RoiPatternSixteen,
					Mask,
					BinningLimit,
					RefNumElements,
					SigNumElements,
					BinNumElements,
					RefPatternData,
					SigPatternData,
					BinPatternData );
}


void CApnCamData_CCD230_42::set_hpattern_skip_twelve()
{
	const unsigned short Mask = 0x21E;
	const unsigned short BinningLimit = 1;
	const unsigned short RefNumElements = 17;
	const unsigned short SigNumElements = 14;

	unsigned short RefPatternData[RefNumElements] = 
	{
		0x006C, 0x006A, 0x006A, 0x006A, 0x0068, 0x0068, 0x0270, 0x1270, 0x1270, 0x02F0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0
	};

	unsigned short SigPatternData[SigNumElements] = 
	{
		0x0044, 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0004, 0x0004, 0x0005, 0x0004
	};

	unsigned short BinNumElements[APN_MAX_HBINNING] = 
	{
		0x0002
	};

	unsigned short BinPatternData[1][256] = {
	{
		0x0250, 0x0250
	} };

	set_hpattern(	&m_SkipPatternTwelve,
					Mask,
					BinningLimit,
					RefNumElements,
					SigNumElements,
					BinNumElements,
					RefPatternData,
					SigPatternData,
					BinPatternData );
}


void CApnCamData_CCD230_42::set_hpattern_clamp_twelve()
{
	const unsigned short Mask = 0x21E;
	const unsigned short BinningLimit = 1;
	const unsigned short RefNumElements = 17;
	const unsigned short SigNumElements = 14;

	unsigned short RefPatternData[RefNumElements] = 
	{
		0x006C, 0x006A, 0x006A, 0x006A, 0x0068, 0x0068, 0x0270, 0x1270, 0x1270, 0x02F0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0
	};

	unsigned short SigPatternData[SigNumElements] = 
	{
		0x0044, 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0004, 0x0004, 0x0005, 0x0004
	};

	unsigned short BinNumElements[APN_MAX_HBINNING] = 
	{
		0x0002
	};

	unsigned short BinPatternData[1][256] = {
	{
		0x0250, 0x0250
	} };

	set_hpattern(	&m_ClampPatternTwelve,
					Mask,
					BinningLimit,
					RefNumElements,
					SigNumElements,
					BinNumElements,
					RefPatternData,
					SigPatternData,
					BinPatternData );
}


void CApnCamData_CCD230_42::set_hpattern_roi_twelve()
{
	const unsigned short Mask = 0x21E;
	const unsigned short BinningLimit = 5;
	const unsigned short RefNumElements = 41;
	const unsigned short SigNumElements = 35;

	unsigned short RefPatternData[RefNumElements] = 
	{
		0x006E, 0x006A, 0x006A, 0x006A, 0x006A, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 
		0x0270, 0x1270, 0x1270, 0x02F0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 
		0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 0x02D0, 
		0x02D0
	};

	unsigned short SigPatternData[SigNumElements] = 
	{
		0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 
		0x0104, 0x8004, 0x8404, 0x0405, 0x0004
	};

	unsigned short BinNumElements[APN_MAX_HBINNING] = 
	{
		0x0002, 0x0010, 0x0020, 0x0030, 0x0040
	};

	unsigned short BinPatternData[5][256] = {
	{
		0x0250, 0x0250
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 
		0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050
	},
	{
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 
		0x0048, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0044, 0x0044, 
		0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0050, 0x0050, 0x0050, 
		0x0050, 0x0050, 0x0050, 0x0050
	} };

	set_hpattern(	&m_RoiPatternTwelve,
					Mask,
					BinningLimit,
					RefNumElements,
					SigNumElements,
					BinNumElements,
					RefPatternData,
					SigPatternData,
					BinPatternData );
}


void CApnCamData_CCD230_42::set_hpattern(	APN_HPATTERN_FILE	*Pattern,
											unsigned short	Mask,
											unsigned short	BinningLimit,
											unsigned short	RefNumElements,
											unsigned short	SigNumElements,
											unsigned short	BinNumElements[],
											unsigned short	RefPatternData[],
											unsigned short	SigPatternData[],
											unsigned short	BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
{
	int i, j;

	Pattern->Mask = Mask;
	Pattern->BinningLimit = BinningLimit;
	Pattern->RefNumElements = RefNumElements;
	Pattern->SigNumElements = SigNumElements;

	if ( RefNumElements > 0 )
	{
		Pattern->RefPatternData = 
			(unsigned short *)malloc(RefNumElements * sizeof(unsigned short));

		for ( i=0; i<RefNumElements; i++ )
		{
			Pattern->RefPatternData[i] = RefPatternData[i];
		}
	}

	if ( SigNumElements > 0 )
	{
		Pattern->SigPatternData = 
			(unsigned short *)malloc(SigNumElements * sizeof(unsigned short));

		for ( i=0; i<SigNumElements; i++ )
		{
			Pattern->SigPatternData[i] = SigPatternData[i];
		}
	}

	if ( BinningLimit > 0 )
	{
		for ( i=0; i<BinningLimit; i++ )
		{
			Pattern->BinNumElements[i] = BinNumElements[i];

			Pattern->BinPatternData[i] = 
				(unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));

			for ( j=0; j<BinNumElements[i]; j++ )
			{
				Pattern->BinPatternData[i][j] = BinPatternData[i][j];
			}
		}
	}
}
