summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/indi/apogee/CameraIO_Linux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/indi/apogee/CameraIO_Linux.cpp')
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_Linux.cpp1362
1 files changed, 1362 insertions, 0 deletions
diff --git a/kstars/kstars/indi/apogee/CameraIO_Linux.cpp b/kstars/kstars/indi/apogee/CameraIO_Linux.cpp
new file mode 100644
index 00000000..67d217ec
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_Linux.cpp
@@ -0,0 +1,1362 @@
+// 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 ] );
+ /////////////////////////////////////
+}
+
+
+
+
+