diff options
Diffstat (limited to 'kstars/kstars/indi/apogee/CameraIO_Linux.cpp')
-rw-r--r-- | kstars/kstars/indi/apogee/CameraIO_Linux.cpp | 1362 |
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 ] ); + ///////////////////////////////////// +} + + + + + |