You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1363 lines
36 KiB
1363 lines
36 KiB
// CameraIO.cpp: implementation of the CCameraIO class.
|
|
//
|
|
// Copyright (c) 2000 Apogee Instruments Inc.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include <assert.h>
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <string.h>
|
|
#include <sched.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#define HANDLE int
|
|
#define FALSE 0
|
|
#define DWORD long
|
|
#define _ASSERT assert
|
|
#define REALTIME_PRIORITY_CLASS 1
|
|
#define GetCurrentProcess getpid
|
|
#define LOBYTE(x) ((x) & 0xff)
|
|
#define HIBYTE(x) ((x >> 8) & 0xff)
|
|
|
|
#define MIRQ1 0x21
|
|
#define MIRQ2 0xA1
|
|
|
|
#include "time.h"
|
|
//#include "tcl.h"
|
|
//#include "ccd.h"
|
|
#include "CameraIO_Linux.h"
|
|
#include "ApogeeLinux.h"
|
|
|
|
const int NUM_POSITIONS = 6;
|
|
const int NUM_STEPS_PER_FILTER = 48;
|
|
const int STEP_DELAY = 10;
|
|
|
|
const unsigned char Steps[] = { 0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0x80, 0x90 };
|
|
const int NUM_STEPS = sizeof ( Steps );
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CCameraIO::CCameraIO()
|
|
{
|
|
InitDefaults();
|
|
|
|
m_TDI = false;
|
|
|
|
m_Shutter = false;
|
|
m_FilterPosition = 0;
|
|
m_FilterStepPos = 0;
|
|
|
|
m_WaitingforImage = false;
|
|
m_WaitingforLine = false;
|
|
|
|
m_WaitingforTrigger = false;
|
|
m_Status = Camera_Status_Idle;
|
|
m_CoolerStatus = Camera_CoolerStatus_Off;
|
|
|
|
m_ExposureBinX = 0;
|
|
m_ExposureBinY = 0;
|
|
m_ExposureStartX = 0;
|
|
m_ExposureStartY = 0;
|
|
m_ExposureNumX = 0;
|
|
m_ExposureNumY = 0;
|
|
m_ExposureColumns = 0;
|
|
m_ExposureRows = 0;
|
|
m_ExposureSkipC = 0;
|
|
m_ExposureSkipR = 0;
|
|
m_ExposureHFlush = 0;
|
|
m_ExposureVFlush = 0;
|
|
m_ExposureBIC = 0;
|
|
m_ExposureBIR = 0;
|
|
m_ExposureAIC = 0;
|
|
m_ExposureRemainingLines = 0;
|
|
m_ExposureAIR = 0;
|
|
|
|
m_RegShadow[ Reg_Command ] = 0;
|
|
m_RegShadow[ Reg_Timer ] = 0;
|
|
m_RegShadow[ Reg_VBinning ] = 0;
|
|
m_RegShadow[ Reg_AICCounter ] = 0;
|
|
m_RegShadow[ Reg_TempSetPoint ] = 0;
|
|
m_RegShadow[ Reg_PixelCounter ] = 0;
|
|
m_RegShadow[ Reg_LineCounter ] = 0;
|
|
m_RegShadow[ Reg_BICCounter ] = 0;
|
|
|
|
m_FastShutterBits_Mode = 0;
|
|
m_FastShutterBits_Test = 0;
|
|
m_IRQMask = 0;
|
|
saveIRQS = 0;
|
|
|
|
}
|
|
|
|
CCameraIO::~CCameraIO()
|
|
{
|
|
|
|
//::close(fileHandle);
|
|
close(fileHandle);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// System methods
|
|
|
|
int GetPriorityClass ( HANDLE /*hProcess*/ )
|
|
{
|
|
int i;
|
|
i = sched_getscheduler(0);
|
|
return(i);
|
|
}
|
|
|
|
int SetPriorityClass ( HANDLE /*hProcess*/, int hPriority)
|
|
{
|
|
int i;
|
|
sched_param p;
|
|
|
|
if (hPriority) {
|
|
i = sched_setscheduler(0,SCHED_RR,&p);
|
|
} else {
|
|
i = sched_setscheduler(0,SCHED_OTHER,&p);
|
|
}
|
|
return(i);
|
|
}
|
|
|
|
void Sleep (int hTime)
|
|
{
|
|
timespec t;
|
|
t.tv_sec= 0;
|
|
t.tv_nsec = hTime*1000000;
|
|
// nanosleep(&t);
|
|
}
|
|
|
|
|
|
|
|
void ATLTRACE (char * /*msg*/)
|
|
{
|
|
}
|
|
|
|
|
|
void CCameraIO::Reset()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val ); // Take snapshot of currrent status
|
|
m_RegShadow[ Reg_Command ] = val; // remember it in our write shadow
|
|
|
|
// In case these were left on, turn them off
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_TDIMode; // set bit to 0
|
|
|
|
m_RegShadow[ Reg_Command ] |= RegBit_ResetSystem; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_ResetSystem; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_WaitingforImage = false;
|
|
m_WaitingforLine = false;
|
|
m_WaitingforTrigger = false;
|
|
}
|
|
|
|
void CCameraIO::AuxOutput( unsigned char val )
|
|
{
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_TempSetPoint ] &= ~( RegBitMask_PortControl << RegBitShift_PortControl );
|
|
|
|
// set our new bits
|
|
m_RegShadow[ Reg_TempSetPoint ] |= val << RegBitShift_PortControl;
|
|
|
|
Write( Reg_TempSetPoint, m_RegShadow[ Reg_TempSetPoint ] );
|
|
}
|
|
|
|
// Input reg is from 0 to 7, val is any 16 bit number
|
|
void CCameraIO::RegWrite( short reg, unsigned short val )
|
|
{
|
|
Write( reg, val );
|
|
|
|
// Update our shadow register
|
|
switch ( reg )
|
|
{
|
|
case Reg_Command:
|
|
m_RegShadow[ Reg_Command ] = val;
|
|
break;
|
|
case Reg_Timer:
|
|
m_RegShadow[ Reg_Timer ] = val;
|
|
break;
|
|
case Reg_VBinning:
|
|
m_RegShadow[ Reg_VBinning ] = val;
|
|
break;
|
|
case Reg_AICCounter:
|
|
m_RegShadow[ Reg_AICCounter ] = val;
|
|
break;
|
|
case Reg_TempSetPoint:
|
|
m_RegShadow[ Reg_TempSetPoint ] = val;
|
|
break;
|
|
case Reg_PixelCounter:
|
|
m_RegShadow[ Reg_PixelCounter ] = val;
|
|
break;
|
|
case Reg_LineCounter:
|
|
m_RegShadow[ Reg_LineCounter ] = val;
|
|
break;
|
|
case Reg_BICCounter:
|
|
m_RegShadow[ Reg_BICCounter ] = val;
|
|
break;
|
|
default:
|
|
_ASSERT( FALSE ); // application program bug
|
|
}
|
|
}
|
|
|
|
// Input reg is from 8 to 12, returned val is any 16 bit number
|
|
void CCameraIO::RegRead( short reg, unsigned short& val )
|
|
{
|
|
Read( reg, val );
|
|
}
|
|
|
|
bool CCameraIO::FilterHome()
|
|
{
|
|
HANDLE hProcess(0);
|
|
DWORD Class(0);
|
|
|
|
if ( m_HighPriority )
|
|
{ // Store current process class and priority
|
|
hProcess = GetCurrentProcess();
|
|
Class = GetPriorityClass ( hProcess );
|
|
SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
|
|
}
|
|
|
|
// Find the home position
|
|
m_FilterPosition = 0;
|
|
int Safety = 0;
|
|
for (int I = 0; I < NUM_POSITIONS * NUM_STEPS_PER_FILTER * 2; I++)
|
|
{
|
|
// Advance the filter one step
|
|
m_FilterStepPos += 1;
|
|
if (m_FilterStepPos >= NUM_STEPS) m_FilterStepPos = 0;
|
|
unsigned char Step = Steps[ m_FilterStepPos ];
|
|
|
|
AuxOutput( Step );
|
|
Sleep ( STEP_DELAY );
|
|
|
|
// Check for strobe
|
|
unsigned short val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( val & RegBit_GotTrigger )
|
|
{
|
|
// Cycle all the way around if it's on the first time
|
|
if (I < NUM_STEPS_PER_FILTER)
|
|
{
|
|
if (++Safety > NUM_STEPS_PER_FILTER * 2)
|
|
{
|
|
// Restore normal priority
|
|
if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
|
|
return false;
|
|
}
|
|
I = 0;
|
|
continue;
|
|
}
|
|
|
|
// Continue cycling until we get clear of the opto mirror
|
|
for (int J = 0; J < NUM_STEPS_PER_FILTER; J++)
|
|
{
|
|
// Advance the filter one step
|
|
m_FilterStepPos += 1;
|
|
if (m_FilterStepPos >= NUM_STEPS) m_FilterStepPos = 0;
|
|
unsigned char Step = Steps[ m_FilterStepPos ];
|
|
|
|
AuxOutput( Step );
|
|
Sleep ( STEP_DELAY );
|
|
|
|
val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( val & RegBit_GotTrigger )
|
|
{
|
|
Sleep ( 10 );
|
|
|
|
val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( val & RegBit_GotTrigger )
|
|
{
|
|
// Restore normal priority
|
|
if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Restore normal priority
|
|
if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Restore normal priority
|
|
if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
|
|
return false;
|
|
}
|
|
|
|
void CCameraIO::FilterSet( short Slot )
|
|
{
|
|
// Determine how far we have to move
|
|
int Pos = Slot - m_FilterPosition;
|
|
if (Pos < 0) Pos += NUM_POSITIONS;
|
|
|
|
HANDLE hProcess(0);
|
|
DWORD Class(0);
|
|
|
|
if ( m_HighPriority )
|
|
{ // Store current process class and priority
|
|
hProcess = GetCurrentProcess();
|
|
Class = GetPriorityClass ( hProcess );
|
|
SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
|
|
}
|
|
|
|
for (int I = 0; I < Pos; I++)
|
|
{
|
|
// Advance one position
|
|
for (int J = 0; J < NUM_STEPS_PER_FILTER; J++)
|
|
{
|
|
m_FilterStepPos += 1;
|
|
if (m_FilterStepPos >= NUM_STEPS) m_FilterStepPos = 0;
|
|
unsigned char Step = Steps[ m_FilterStepPos ];
|
|
|
|
AuxOutput( Step );
|
|
Sleep ( STEP_DELAY );
|
|
}
|
|
}
|
|
|
|
if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
|
|
|
|
m_FilterPosition = Slot;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Normal exposure methods
|
|
|
|
bool CCameraIO::Expose( double Duration, bool Light )
|
|
{
|
|
if ( !m_TDI && ( Duration < m_MinExposure || Duration > m_MaxExposure ) ) return false;
|
|
|
|
// Validate all input variables
|
|
if ( m_Columns < 1 || m_Columns > MAXCOLUMNS ) return false;
|
|
m_ExposureColumns = m_Columns;
|
|
|
|
if ( m_Rows < 1 || m_Rows > MAXROWS ) return false;
|
|
m_ExposureRows = m_Rows;
|
|
|
|
if ( m_SkipC < 0 ) return false;
|
|
m_ExposureSkipC = m_SkipC;
|
|
|
|
if ( m_SkipR < 0 ) return false;
|
|
m_ExposureSkipR = m_SkipR;
|
|
|
|
if ( m_HFlush < 1 || m_HFlush > MAXHBIN ) return false;
|
|
m_ExposureHFlush = m_HFlush;
|
|
|
|
if ( m_VFlush < 1 || m_VFlush > MAXVBIN ) return false;
|
|
m_ExposureVFlush = m_VFlush;
|
|
|
|
if ( m_BIC < 1 || m_BIC > MAXCOLUMNS ) return false;
|
|
m_ExposureBIC = m_BIC;
|
|
|
|
if ( m_BIR < 1 || m_BIR > MAXROWS ) return false;
|
|
m_ExposureBIR = m_BIR;
|
|
|
|
// Validate all input variables
|
|
if ( m_BinX < 1 || m_BinX > MAXHBIN ) return false;
|
|
m_ExposureBinX = m_BinX;
|
|
|
|
if ( m_StartX < 0 || m_StartX >= MAXCOLUMNS ) return false;
|
|
m_ExposureStartX = m_StartX;
|
|
|
|
if ( m_NumX < 1 || m_NumX * m_BinX > m_ImgColumns ) return false;
|
|
m_ExposureNumX = m_NumX;
|
|
|
|
// Calculate BIC, RawPixelCount, AIC
|
|
unsigned short BIC = m_ExposureBIC + m_ExposureStartX; // unbinned columns
|
|
unsigned short RawPixelCount = m_ExposureNumX * m_ExposureBinX;
|
|
m_ExposureAIC = m_ExposureColumns - BIC - RawPixelCount; // unbinned columns
|
|
|
|
if ( m_BinY < 1 || m_BinY > MAXVBIN ) return false;
|
|
m_ExposureBinY = m_BinY;
|
|
|
|
unsigned short VBin(0), row_offset(0);
|
|
|
|
if ( m_TDI )
|
|
{ // row_offset is the drift time in milliseconds when in TDI mode
|
|
row_offset = (unsigned short) (Duration * 1000 + 0.5);
|
|
Duration = 0.0;
|
|
}
|
|
else
|
|
{
|
|
if ( m_StartY < 0 || m_StartX >= MAXROWS ) return false;
|
|
m_ExposureStartY = m_StartY;
|
|
|
|
if ( m_NumY < 1 || m_NumY * m_BinY > m_ImgRows ) return false;
|
|
m_ExposureNumY = m_NumY;
|
|
|
|
unsigned short BIR = m_ExposureBIR + m_ExposureStartY; // unbinned rows
|
|
if ( BIR >= MAXROWS ) return false;
|
|
m_ExposureAIR = m_ExposureRows - BIR - m_ExposureNumY * m_ExposureBinY; // unbinned rows
|
|
|
|
if ( m_VFlush > BIR )
|
|
{
|
|
VBin = BIR;
|
|
m_ExposureRemainingLines = 0;
|
|
}
|
|
else
|
|
{
|
|
VBin = m_VFlush;
|
|
m_ExposureRemainingLines = BIR % VBin; // unbinned rows
|
|
}
|
|
row_offset = BIR - m_ExposureRemainingLines; // unbinned rows
|
|
}
|
|
|
|
StopFlushing();
|
|
Reset();
|
|
|
|
LoadColumnLayout( m_ExposureAIC, BIC, (unsigned short) m_ExposureNumX + m_ExposureSkipC );
|
|
LoadTimerAndBinning( Duration, (unsigned short) m_ExposureHFlush, VBin );
|
|
LoadLineCounter( row_offset );
|
|
|
|
if ( m_TDI )
|
|
{
|
|
// Turn on TDI
|
|
m_RegShadow[ Reg_Command ] |= RegBit_TDIMode; // set bit to 1
|
|
|
|
// Disable FIFO cache
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
|
|
|
|
// Set shutter override
|
|
if ( Light )
|
|
m_RegShadow[ Reg_Command ] |= RegBit_ShutterOverride; // set bit to 1
|
|
else
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterOverride; // set bit to 0
|
|
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
// Update our status
|
|
m_Shutter = Light;
|
|
m_WaitingforTrigger = false;
|
|
m_WaitingforLine = false;
|
|
}
|
|
else
|
|
{
|
|
// Set shutter
|
|
if ( Light )
|
|
m_RegShadow[ Reg_Command ] |= RegBit_ShutterEnable; // set bit to 1
|
|
else
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterEnable; // set bit to 0
|
|
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
// Update our status
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val );
|
|
if ( val & RegBit_ShutterOverride )
|
|
m_Shutter = true;
|
|
else
|
|
m_Shutter = Light;
|
|
|
|
if ( ( val & RegBit_TriggerEnable ) )
|
|
m_WaitingforTrigger = true;
|
|
else
|
|
m_WaitingforTrigger = false;
|
|
|
|
// Start the exposure
|
|
m_RegShadow[ Reg_Command ] |= RegBit_StartTimer; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_StartTimer; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_WaitingforImage = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*bool CCameraIO::BufferImage(char *bufferName )
|
|
{
|
|
unsigned short *pImageData;
|
|
bool status;
|
|
short cols,rows,hbin,vbin;
|
|
short xSize, ySize;
|
|
|
|
cols = m_NumX*m_BinX;
|
|
rows = m_NumY*m_BinY;
|
|
hbin = m_BinX;
|
|
vbin = m_BinY;
|
|
|
|
pImageData = (unsigned short *)CCD_locate_buffer(bufferName, 2 , cols, rows, hbin, vbin );
|
|
if (pImageData == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
status = GetImage(pImageData, xSize, ySize);
|
|
return status;
|
|
}*/
|
|
|
|
bool CCameraIO::GetImage( unsigned short* pImageData, short& xSize, short& ySize )
|
|
{
|
|
int i;
|
|
unsigned short BIC = m_ExposureBIC + m_ExposureStartX;
|
|
|
|
// Update internal variables in case application did not poll read_Status
|
|
m_WaitingforTrigger = false;
|
|
m_WaitingforLine = false;
|
|
|
|
if ( m_WaitingforImage )
|
|
{ // In case application did not poll read_Status
|
|
m_WaitingforImage = false;
|
|
|
|
/////////////////////////////////////
|
|
// Wait until camera is done flushing
|
|
clock_t StopTime = clock() + long( m_Timeout * CLOCKS_PER_SEC ); // wait at most m_Timeout seconds
|
|
while ( true )
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( ( val & RegBit_FrameDone ) != 0 ) break;
|
|
|
|
if ( clock() > StopTime ) return false; // Timed out
|
|
}
|
|
}
|
|
|
|
// MaskIrqs();
|
|
|
|
/////////////////////////////////////
|
|
// Update our internal status
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val );
|
|
if ( !( val & RegBit_ShutterOverride ) ) m_Shutter = false;
|
|
|
|
StopFlushing();
|
|
LoadColumnLayout( m_ExposureAIC, BIC, (unsigned short) m_ExposureNumX + m_ExposureSkipC );
|
|
|
|
if ( m_ExposureRemainingLines > 0 )
|
|
{
|
|
LoadTimerAndBinning( 0.0, m_ExposureHFlush, m_ExposureRemainingLines );
|
|
|
|
/////////////////////////////////////
|
|
// Clock out the remaining lines
|
|
m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
/////////////////////////////////////
|
|
|
|
/////////////////////////////////////
|
|
// Wait until camera is done clocking
|
|
clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
|
|
while ( true )
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( ( val & RegBit_LineDone ) != 0 ) break; // Line done
|
|
|
|
if ( clock() > StopTime )
|
|
{
|
|
Flush();
|
|
return false; // Timed out, no image available
|
|
}
|
|
}
|
|
}
|
|
|
|
LoadTimerAndBinning( 0.0, m_ExposureBinX, m_ExposureBinY );
|
|
|
|
bool ret = false; // assume failure
|
|
|
|
// NB Application must have allocated enough memory or else !!!
|
|
if ( pImageData != NULL )
|
|
{
|
|
HANDLE hProcess(0);
|
|
DWORD Class(0);
|
|
|
|
if ( m_HighPriority )
|
|
{ // Store current process class and priority
|
|
hProcess = GetCurrentProcess();
|
|
Class = GetPriorityClass ( hProcess );
|
|
SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
|
|
}
|
|
|
|
m_RegShadow[ Reg_Command ] |= RegBit_FIFOCache; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
long XPixels = long( m_ExposureNumX );
|
|
long SkipPixels = long( m_ExposureSkipC );
|
|
for (i = 0; i < m_ExposureSkipR; i++)
|
|
{
|
|
if ( ReadLine( SkipPixels, XPixels, pImageData ) ) break;
|
|
}
|
|
|
|
if ( i == m_ExposureSkipR )
|
|
{ // We have skipped all the lines
|
|
long YPixels = long( m_ExposureNumY );
|
|
unsigned short* pLineBuffer = pImageData;
|
|
for (i = 0; i < YPixels; i++)
|
|
{
|
|
if ( ReadLine( SkipPixels, XPixels, pLineBuffer ) ) break;
|
|
pLineBuffer += XPixels;
|
|
}
|
|
|
|
if ( i == YPixels ) ret = true; // We have read all the lines
|
|
}
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
//Restore priority
|
|
if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
|
|
}
|
|
|
|
// UnmaskIrqs();
|
|
|
|
if ( ret )
|
|
{ // We were successfull
|
|
Flush( m_ExposureAIR ); // flush after imaging rows
|
|
|
|
xSize = m_ExposureNumX;
|
|
ySize = m_ExposureNumY;
|
|
|
|
if ( m_DataBits == 16 )
|
|
{ // Take care of two's complement converters
|
|
unsigned short *Ptr = pImageData;
|
|
short *Ptr2 = (short *) pImageData;
|
|
long Size = m_ExposureNumX * m_ExposureNumY;
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
*Ptr++ = (unsigned short) *Ptr2++ + 32768 ;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{ // Something went wrong
|
|
xSize = 0;
|
|
ySize = 0;
|
|
}
|
|
|
|
Flush(); // start normal flushing
|
|
|
|
return ret;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Drift scan methods
|
|
|
|
bool CCameraIO::DigitizeLine()
|
|
{
|
|
/////////////////////////////////////
|
|
// All of these are done just in case
|
|
// since they are called in Expose()
|
|
StopFlushing();
|
|
|
|
unsigned short BIC = m_ExposureBIC + m_ExposureStartX;
|
|
LoadColumnLayout( m_ExposureAIC, BIC, (unsigned short) m_ExposureNumX + m_ExposureSkipC );
|
|
LoadTimerAndBinning( 0.0, m_ExposureBinX, m_ExposureBinY );
|
|
|
|
// Disable FIFO cache
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
|
|
/////////////////////////////////////
|
|
|
|
/////////////////////////////////////
|
|
// Clock out the line
|
|
m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
/////////////////////////////////////
|
|
|
|
m_WaitingforLine = true;
|
|
return true;
|
|
}
|
|
|
|
bool CCameraIO::GetLine( unsigned short* pLineData, short& xSize )
|
|
{
|
|
int i;
|
|
|
|
if ( m_WaitingforLine )
|
|
{ // In case application did not poll read_Status
|
|
m_WaitingforLine = false;
|
|
|
|
/////////////////////////////////////
|
|
// Wait until camera is done clocking
|
|
clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
|
|
while ( true )
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( ( val & RegBit_LineDone ) != 0 ) break; // Line done
|
|
|
|
if ( clock() > StopTime )
|
|
{
|
|
Flush();
|
|
return false; // Timed out, no line available
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ret = false; // assume failure
|
|
|
|
// MaskIrqs();
|
|
|
|
// NB Application must have allocated enough memory or else !!!
|
|
if ( pLineData != NULL )
|
|
{
|
|
HANDLE hProcess(0);
|
|
DWORD Class(0);
|
|
|
|
if ( m_HighPriority )
|
|
{ // Store current process class and priority
|
|
hProcess = GetCurrentProcess();
|
|
Class = GetPriorityClass ( hProcess );
|
|
SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
|
|
}
|
|
|
|
long XPixels = long( m_ExposureNumX );
|
|
long SkipPixels = long( m_ExposureSkipC );
|
|
|
|
if ( ReadLine( SkipPixels, XPixels, pLineData ) )
|
|
{ // Something went wrong
|
|
xSize = 0;
|
|
ret = false;
|
|
}
|
|
else
|
|
{
|
|
xSize = m_ExposureNumX;
|
|
|
|
if ( m_DataBits == 16 )
|
|
{ // Take care of two's complement converters
|
|
unsigned short *Ptr = pLineData;
|
|
short *Ptr2 = (short *) pLineData;
|
|
long Size = m_ExposureNumX;
|
|
for (i = 0; i < Size; i++)
|
|
{
|
|
*Ptr++ = (unsigned short) *Ptr2++ + 32768 ;
|
|
}
|
|
}
|
|
|
|
ret = true;
|
|
}
|
|
|
|
//Restore priority
|
|
if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
|
|
}
|
|
|
|
// UnmaskIrqs();
|
|
return ret;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Easy to use methods
|
|
|
|
bool CCameraIO::Snap( double Duration, bool Light, unsigned short* pImageData, short& xSize, short& ySize )
|
|
{
|
|
// NB This also demonstrates how an application might use the
|
|
// Expose and GetImage routines.
|
|
|
|
bool ret = Expose( Duration, Light );
|
|
if ( !ret ) return false;
|
|
|
|
if ( m_WaitingforTrigger )
|
|
{
|
|
Camera_Status stat;
|
|
while ( true )
|
|
{ // This will wait forever if no trigger happens
|
|
stat = read_Status();
|
|
if ( stat == Camera_Status_Exposing ) break;
|
|
Sleep( 220 ); // dont bog down the CPU while polling
|
|
}
|
|
m_WaitingforTrigger = false;
|
|
}
|
|
|
|
// Only wait a time slightly greater than the duration of the exposure
|
|
// but enough for the BIR to flush out
|
|
clock_t StopTime = clock() + long( ( 1.2 * Duration + m_Timeout ) * CLOCKS_PER_SEC );
|
|
while ( true )
|
|
{
|
|
Camera_Status stat = read_Status();
|
|
if ( stat == Camera_Status_ImageReady ) break;
|
|
|
|
if ( clock() > StopTime ) return false; // Timed out, no image available
|
|
Sleep( 220 ); // dont bog down the CPU while polling
|
|
}
|
|
|
|
return GetImage( pImageData, xSize, ySize );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Camera Settings
|
|
|
|
Camera_Status CCameraIO::read_Status()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_Status, val );
|
|
|
|
if ( val & RegBit_Exposing ) //11.0
|
|
{
|
|
ATLTRACE( "Exposing\r\n" );
|
|
m_WaitingforTrigger = false;
|
|
m_Status = Camera_Status_Exposing;
|
|
}
|
|
|
|
else if ( m_WaitingforTrigger )
|
|
m_Status = Camera_Status_Waiting;
|
|
|
|
else if ( m_WaitingforImage && ( val & RegBit_FrameDone ) ) //11.11
|
|
{
|
|
ATLTRACE( "ImageReady\r\n" );
|
|
m_WaitingforImage = false;
|
|
m_Status = Camera_Status_ImageReady;
|
|
}
|
|
|
|
else if ( m_WaitingforLine && ( val & RegBit_LineDone ) ) //11.1
|
|
{
|
|
ATLTRACE( "LineReady\r\n" );
|
|
m_WaitingforLine = false;
|
|
m_Status = Camera_Status_LineReady;
|
|
}
|
|
else if ( m_WaitingforImage || m_WaitingforLine )
|
|
{
|
|
ATLTRACE( "Flushing\r\n" );
|
|
m_Status = Camera_Status_Flushing;
|
|
}
|
|
else
|
|
m_Status = Camera_Status_Idle;
|
|
|
|
return m_Status;
|
|
}
|
|
|
|
bool CCameraIO::read_Present()
|
|
{
|
|
// This does not work on all cameras
|
|
/*
|
|
m_RegShadow[ Reg_BICCounter ] |= RegBit_LoopbackTest; // set bit to 1
|
|
Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
|
|
|
|
bool FailedLoopback = false;
|
|
unsigned short val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( !( val & RegBit_LoopbackTest ) ) FailedLoopback = true;
|
|
|
|
m_RegShadow[ Reg_BICCounter ] &= ~RegBit_LoopbackTest; // clear bit to 0
|
|
Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
|
|
|
|
Read( Reg_Status, val );
|
|
if ( val & RegBit_LoopbackTest ) FailedLoopback = true;
|
|
*/
|
|
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val ); // Take snapshot of currrent status
|
|
m_RegShadow[ Reg_Command ] = val; // remember it in our write shadow
|
|
|
|
bool TriggerEnabled = ( val & RegBit_TriggerEnable ) != 0;
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_TriggerEnable;// clear bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
Read( Reg_CommandReadback, val ); // get currrent status
|
|
if ( val & RegBit_TriggerEnable ) return false;
|
|
|
|
m_RegShadow[ Reg_Command ] |= RegBit_TriggerEnable; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
Read( Reg_CommandReadback, val ); // get currrent status
|
|
if ( !(val & RegBit_TriggerEnable) ) return false;
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_TriggerEnable;// clear bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
Read( Reg_CommandReadback, val ); // get currrent status
|
|
if ( val & RegBit_TriggerEnable ) return false;
|
|
|
|
if ( TriggerEnabled )
|
|
{ // Set it back the way it was
|
|
m_RegShadow[ Reg_Command ] |= RegBit_TriggerEnable; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CCameraIO::read_Shutter()
|
|
{
|
|
unsigned short regval = 0;
|
|
Read( Reg_Status, regval );
|
|
if ( !( regval & RegBit_Exposing ) )
|
|
{ // We are not exposing, but might have finnshed an exposure
|
|
// and have not called GetImage yet, so update our internal variable
|
|
regval = 0;
|
|
Read( Reg_CommandReadback, regval );
|
|
if ( !( regval & RegBit_ShutterOverride ) )
|
|
// The shutter override is not on, so the shutter must be closed
|
|
m_Shutter = false;
|
|
}
|
|
|
|
return m_Shutter;
|
|
}
|
|
|
|
bool CCameraIO::read_ForceShutterOpen()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val );
|
|
return ( ( val & RegBit_ShutterOverride ) != 0 );
|
|
}
|
|
|
|
void CCameraIO::write_ForceShutterOpen( bool val )
|
|
{
|
|
if ( val )
|
|
{
|
|
m_RegShadow[ Reg_Command ] |= RegBit_ShutterOverride; // set bit to 1
|
|
m_Shutter = true; // shutter will open immediately now matter what is going on
|
|
}
|
|
else
|
|
{
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterOverride; // clear bit to 0
|
|
|
|
unsigned short regval = 0;
|
|
Read( Reg_Status, regval );
|
|
if ( ( regval & RegBit_Exposing ) )
|
|
{
|
|
// Shutter will remain open if a Light frame is being taken
|
|
// however if a dark frame was being exposed while the
|
|
// override was on or the override is turned on during the exposure
|
|
// and now is turned off (dumb idea but some app might do it!)
|
|
// we must update our variable since the shutter will close
|
|
// when override gets turned off below
|
|
regval = 0;
|
|
Read( Reg_CommandReadback, regval );
|
|
if ( !( regval & RegBit_ShutterEnable ) ) m_Shutter = false;
|
|
}
|
|
else
|
|
{ // Not currently exposing so shutter will close
|
|
// once override is turned off, update our variable
|
|
m_Shutter = false;
|
|
}
|
|
}
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
}
|
|
|
|
|
|
|
|
bool CCameraIO::read_LongCable()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val );
|
|
return ( ( val & RegBit_CableLength ) != 0 );
|
|
}
|
|
|
|
void CCameraIO::write_Shutter( bool val )
|
|
{
|
|
if ( val )
|
|
m_RegShadow[ Reg_Command ] |= RegBit_ShutterEnable; // set bit to 1
|
|
else
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterEnable; // clear bit to 0
|
|
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
}
|
|
|
|
void CCameraIO::write_LongCable( bool val )
|
|
{
|
|
if ( val )
|
|
m_RegShadow[ Reg_Command ] |= RegBit_CableLength; // set bit to 1
|
|
else
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_CableLength; // clear bit to 0
|
|
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
}
|
|
|
|
|
|
short CCameraIO::read_Mode()
|
|
{
|
|
return ( ( m_RegShadow[ Reg_LineCounter ] >> RegBitShift_Mode ) & RegBitMask_Mode );
|
|
}
|
|
|
|
void CCameraIO::write_Mode( short val )
|
|
{
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_LineCounter ] &= ~( RegBitMask_Mode << RegBitShift_Mode );
|
|
|
|
// set our new bits
|
|
m_RegShadow[ Reg_LineCounter ] |= ( (unsigned short) val & RegBitMask_Mode ) << RegBitShift_Mode;
|
|
|
|
Write( Reg_LineCounter, m_RegShadow[ Reg_LineCounter ] );
|
|
}
|
|
|
|
short CCameraIO::read_TestBits()
|
|
{
|
|
return ( ( m_RegShadow[ Reg_BICCounter ] >> RegBitShift_Test ) & RegBitMask_Test );
|
|
}
|
|
|
|
void CCameraIO::write_TestBits( short val )
|
|
{
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_BICCounter ] &= ~( RegBitMask_Test << RegBitShift_Test );
|
|
|
|
// set our new bits
|
|
m_RegShadow[ Reg_BICCounter ] |= ( (unsigned short) val & RegBitMask_Test ) << RegBitShift_Test;
|
|
|
|
Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
|
|
}
|
|
|
|
|
|
short CCameraIO::read_Test2Bits()
|
|
{
|
|
return ( ( m_RegShadow[ Reg_AICCounter ] >> RegBitShift_Test2 ) & RegBitMask_Test2 );
|
|
}
|
|
|
|
void CCameraIO::write_Test2Bits( short val )
|
|
{
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_AICCounter ] &= ~( RegBitMask_Test2 << RegBitShift_Test2 );
|
|
|
|
// set our new bits
|
|
m_RegShadow[ Reg_AICCounter ] |= ( (unsigned short) val & RegBitMask_Test2 ) << RegBitShift_Test2;
|
|
|
|
Write( Reg_AICCounter, m_RegShadow[ Reg_AICCounter ] );
|
|
}
|
|
|
|
bool CCameraIO::read_FastReadout()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback , val );
|
|
return ( ( val & RegBit_Focus ) != 0 );
|
|
}
|
|
|
|
void CCameraIO::write_FastReadout( bool val )
|
|
{
|
|
if ( val )
|
|
m_RegShadow[ Reg_Command ] |= RegBit_Focus; // set bit to 1
|
|
else
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_Focus; // clear bit to 0
|
|
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
}
|
|
|
|
bool CCameraIO::read_UseTrigger()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback , val );
|
|
return ( ( val & RegBit_TriggerEnable ) != 0 );
|
|
}
|
|
|
|
void CCameraIO::write_UseTrigger( bool val )
|
|
{
|
|
if ( val )
|
|
m_RegShadow[ Reg_Command ] |= RegBit_TriggerEnable; // set bit to 1
|
|
else
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_TriggerEnable; // clear bit to 0
|
|
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Cooler Settings
|
|
|
|
double CCameraIO::read_CoolerSetPoint()
|
|
{
|
|
// Get the setting from the shadow registers
|
|
short DACunits = short( ( m_RegShadow[ Reg_TempSetPoint ] >> RegBitShift_TempSetPoint ) & RegBitMask_TempSetPoint );
|
|
return ( DACunits - m_TempCalibration ) / m_TempScale;
|
|
}
|
|
|
|
void CCameraIO::write_CoolerSetPoint( double val )
|
|
{
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_TempSetPoint ] &= ~( RegBitMask_TempSetPoint << RegBitShift_TempSetPoint );
|
|
|
|
// Calculate DAC units from degrees Celcius
|
|
unsigned short DACunits = (unsigned )( m_TempScale * val ) + m_TempCalibration ;
|
|
|
|
// set our new bits
|
|
m_RegShadow[ Reg_TempSetPoint ] |= ( DACunits & RegBitMask_TempSetPoint ) << RegBitShift_TempSetPoint;
|
|
|
|
Write( Reg_TempSetPoint, m_RegShadow[ Reg_TempSetPoint ] );
|
|
}
|
|
|
|
Camera_CoolerStatus CCameraIO::read_CoolerStatus()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val );
|
|
|
|
if ( val & RegBit_CoolerEnable ) //12.15
|
|
{
|
|
unsigned short val2 = 0;
|
|
Read( Reg_Status, val2 );
|
|
|
|
if ( val & RegBit_CoolerShutdown ) //12.8
|
|
{
|
|
if ( val2 & RegBit_ShutdownComplete ) //11.6
|
|
m_CoolerStatus = Camera_CoolerStatus_AtAmbient;
|
|
else
|
|
m_CoolerStatus = Camera_CoolerStatus_RampingToAmbient;
|
|
}
|
|
else
|
|
{
|
|
if ( val2 & RegBit_TempAtMax ) //11.5
|
|
m_CoolerStatus = Camera_CoolerStatus_AtMax;
|
|
else if ( val2 & RegBit_TempAtMin ) //11.4
|
|
m_CoolerStatus = Camera_CoolerStatus_AtMin;
|
|
else if ( val2 & RegBit_TempAtSetPoint ) //11.7
|
|
m_CoolerStatus = Camera_CoolerStatus_AtSetPoint;
|
|
// Check against last known cooler status
|
|
else if ( m_CoolerStatus == Camera_CoolerStatus_AtSetPoint )
|
|
m_CoolerStatus = Camera_CoolerStatus_Correcting;
|
|
else
|
|
m_CoolerStatus = Camera_CoolerStatus_RampingToSetPoint;
|
|
}
|
|
}
|
|
else
|
|
m_CoolerStatus = Camera_CoolerStatus_Off;
|
|
|
|
return m_CoolerStatus;
|
|
}
|
|
|
|
Camera_CoolerMode CCameraIO::read_CoolerMode()
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_CommandReadback, val );
|
|
|
|
if ( val & RegBit_CoolerShutdown )
|
|
return Camera_CoolerMode_Shutdown;
|
|
else if ( val & RegBit_CoolerEnable )
|
|
return Camera_CoolerMode_On;
|
|
else
|
|
return Camera_CoolerMode_Off;
|
|
}
|
|
|
|
void CCameraIO::write_CoolerMode( Camera_CoolerMode val )
|
|
{
|
|
switch ( val )
|
|
{
|
|
case Camera_CoolerMode_Off:
|
|
m_RegShadow[ Reg_Command ] &= ~( RegBit_CoolerEnable ); // clear bit to 0
|
|
m_RegShadow[ Reg_Command ] &= ~( RegBit_CoolerShutdown ); // clear bit to 0
|
|
break;
|
|
case Camera_CoolerMode_On:
|
|
m_RegShadow[ Reg_Command ] |= RegBit_CoolerEnable; // set bit to 1
|
|
break;
|
|
case Camera_CoolerMode_Shutdown:
|
|
m_RegShadow[ Reg_Command ] |= RegBit_CoolerShutdown; // set bit to 1
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
}
|
|
|
|
double CCameraIO::read_Temperature()
|
|
{
|
|
if ( m_TempScale == 0.0 )
|
|
return 0.0;
|
|
else
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_TempData, val );
|
|
|
|
short DACunits = short( ( val >> RegBitShift_TempData ) & RegBitMask_TempData );
|
|
|
|
return ( DACunits - m_TempCalibration ) / m_TempScale;
|
|
}
|
|
}
|
|
|
|
// Load line counter
|
|
void CCameraIO::LoadLineCounter( unsigned short rows )
|
|
{
|
|
/////////////////////////////////////
|
|
// Write out Line_Count - in unbinned rows
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_LineCounter ] &= ~( RegBitMask_LineCounter << RegBitShift_LineCounter );
|
|
// set our new bits
|
|
m_RegShadow[ Reg_LineCounter ] |= ( rows & RegBitMask_LineCounter ) << RegBitShift_LineCounter;
|
|
|
|
Write( Reg_LineCounter, m_RegShadow[ Reg_LineCounter ] );
|
|
/////////////////////////////////////
|
|
}
|
|
|
|
// Load AIC, BIC and pixel count into registers
|
|
void CCameraIO::LoadColumnLayout( unsigned short aic, unsigned short bic, unsigned short pixels )
|
|
{
|
|
/////////////////////////////////////
|
|
// Write out AIC - in unbinned columns
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_AICCounter ] &= ~( RegBitMask_AICCounter << RegBitShift_AICCounter );
|
|
// set our new bits
|
|
m_RegShadow[ Reg_AICCounter ] |= ( aic & RegBitMask_AICCounter ) << RegBitShift_AICCounter;
|
|
|
|
Write( Reg_AICCounter, m_RegShadow[ Reg_AICCounter ] );
|
|
/////////////////////////////////////
|
|
|
|
/////////////////////////////////////
|
|
// Write out BIC - in unbinned columns
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_BICCounter ] &= ~( RegBitMask_BICCounter << RegBitShift_BICCounter );
|
|
// set our new bits
|
|
m_RegShadow[ Reg_BICCounter ] |= ( bic & RegBitMask_BICCounter ) << RegBitShift_BICCounter;
|
|
|
|
Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
|
|
/////////////////////////////////////
|
|
|
|
/////////////////////////////////////
|
|
// Write out pixel count - in binned columns
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_PixelCounter ] &= ~( RegBitMask_PixelCounter << RegBitShift_PixelCounter );
|
|
// set our new bits
|
|
m_RegShadow[ Reg_PixelCounter ] |= ( pixels & RegBitMask_PixelCounter ) << RegBitShift_PixelCounter;
|
|
|
|
Write( Reg_PixelCounter, m_RegShadow[ Reg_PixelCounter ] );
|
|
/////////////////////////////////////
|
|
}
|
|
|
|
// Load timer, vertical binning and horizontal binning in to registers
|
|
// If Duration parameter is 0 the current timer value will be retained.
|
|
// The VBin and HBin parameters are one based, the HBin value
|
|
// is converted to zero base inside this routine.
|
|
void CCameraIO::LoadTimerAndBinning( double Duration, unsigned short HBin, unsigned short VBin )
|
|
{
|
|
/////////////////////////////////////
|
|
// Write out HBin for flushing
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_PixelCounter ] &= ~( RegBitMask_HBinning << RegBitShift_HBinning );
|
|
// set our new bits
|
|
m_RegShadow[ Reg_PixelCounter ] |= ( ( HBin - 1 ) & RegBitMask_HBinning ) << RegBitShift_HBinning;
|
|
|
|
Write( Reg_PixelCounter, m_RegShadow[ Reg_PixelCounter ] );
|
|
/////////////////////////////////////
|
|
|
|
/////////////////////////////////////
|
|
// Write out VBin for flushing and Timer
|
|
if ( Duration > 0.0 )
|
|
{
|
|
if ( Duration > m_MaxExposure ) Duration = m_MaxExposure;
|
|
|
|
long valTimer;
|
|
if ( m_FastShutter && Duration <= 1048.575 )
|
|
{ // Automatically switch to high precision mode
|
|
valTimer = long( ( Duration * 1000 ) + 0.5 );
|
|
m_RegShadow[ Reg_LineCounter ] |= ( m_FastShutterBits_Mode & RegBitMask_Mode ) << RegBitShift_Mode;
|
|
m_RegShadow[ Reg_BICCounter ] |= ( m_FastShutterBits_Test & RegBitMask_Test ) << RegBitShift_Test;
|
|
}
|
|
else
|
|
{
|
|
valTimer = long( ( Duration * 100 ) + 0.5 );
|
|
if ( m_FastShutter )
|
|
{ // Disable high precision mode
|
|
m_RegShadow[ Reg_LineCounter ] &= ~( m_FastShutterBits_Mode & RegBitMask_Mode ) << RegBitShift_Mode;
|
|
m_RegShadow[ Reg_BICCounter ] &= ~( m_FastShutterBits_Test & RegBitMask_Test ) << RegBitShift_Test;
|
|
}
|
|
}
|
|
|
|
if ( m_FastShutter )
|
|
{
|
|
Write( Reg_LineCounter, m_RegShadow[ Reg_LineCounter ] );
|
|
Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
|
|
}
|
|
|
|
if ( valTimer <= 0 ) valTimer = 1; // Safety since firmware doesnt like zero
|
|
|
|
unsigned short valTimerLow = (unsigned short) (valTimer & 0x0000FFFF);
|
|
unsigned short valTimerHigh = (unsigned short) (valTimer >> 16);
|
|
|
|
// Enable loading of timer values
|
|
m_RegShadow[ Reg_Command ] |= RegBit_TimerLoad; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_Timer ] = 0;
|
|
// set our new bits
|
|
m_RegShadow[ Reg_Timer ] |= ( valTimerLow & RegBitMask_Timer )<< RegBitShift_Timer;
|
|
Write( Reg_Timer, m_RegShadow[ Reg_Timer ] );
|
|
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_VBinning ] = 0;
|
|
|
|
// set our new bits
|
|
m_RegShadow[ Reg_VBinning ] |= ( VBin & RegBitMask_VBinning ) << RegBitShift_VBinning;
|
|
m_RegShadow[ Reg_VBinning ] |= ( valTimerHigh & RegBitMask_Timer2 ) << RegBitShift_Timer2;
|
|
Write( Reg_VBinning, m_RegShadow[ Reg_VBinning ] );
|
|
|
|
// Disable loading of timer values
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_TimerLoad; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
/////////////////////////////////////
|
|
}
|
|
else
|
|
{
|
|
// clear bits to 0
|
|
m_RegShadow[ Reg_VBinning ] &= ~( RegBitMask_VBinning << RegBitShift_VBinning );
|
|
|
|
// set our new bits
|
|
m_RegShadow[ Reg_VBinning ] |= ( VBin & RegBitMask_VBinning ) << RegBitShift_VBinning;
|
|
Write( Reg_VBinning, m_RegShadow[ Reg_VBinning ] );
|
|
}
|
|
|
|
}
|
|
|
|
// Start flushing the entire CCD (rows = -1) or a specific number or rows
|
|
void CCameraIO::Flush( short Rows )
|
|
{
|
|
if ( Rows == 0 ) return;
|
|
|
|
unsigned short AIC = (unsigned short) ( m_Columns - m_BIC - m_ImgColumns );
|
|
unsigned short Pixels = (unsigned short) ( m_ImgColumns / m_HFlush );
|
|
if ( m_ImgColumns % m_HFlush > 0 ) Pixels++; // round up if necessary
|
|
LoadColumnLayout( AIC, (unsigned short) m_BIC, Pixels );
|
|
|
|
LoadTimerAndBinning( 0.0, m_HFlush, m_VFlush );
|
|
|
|
if ( Rows > 0 )
|
|
{
|
|
LoadLineCounter( (unsigned short) Rows );
|
|
StartFlushing();
|
|
|
|
/////////////////////////////////////
|
|
// Wait until camera is done flushing
|
|
clock_t StopTime = clock() + long( m_Timeout * CLOCKS_PER_SEC ); // wait at most m_Timeout seconds
|
|
while ( true )
|
|
{
|
|
unsigned short val = 0;
|
|
Read( Reg_Status, val );
|
|
if ( ( val & RegBit_FrameDone ) != 0 ) break;
|
|
|
|
if ( clock() > StopTime ) break; // Timed out
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LoadLineCounter( (unsigned short) m_ImgRows );
|
|
StartFlushing();
|
|
}
|
|
}
|
|
|
|
void CCameraIO::StartFlushing()
|
|
{
|
|
/////////////////////////////////////
|
|
// Start flushing
|
|
m_RegShadow[ Reg_Command ] |= RegBit_StartFlushing; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_StartFlushing;// set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
/////////////////////////////////////
|
|
}
|
|
|
|
void CCameraIO::StopFlushing()
|
|
{
|
|
/////////////////////////////////////
|
|
// Stop flushing
|
|
m_RegShadow[ Reg_Command ] |= RegBit_StopFlushing; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_StopFlushing; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
/////////////////////////////////////
|
|
}
|
|
|
|
|
|
|
|
|
|
|