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.
406 lines
9.4 KiB
406 lines
9.4 KiB
// CameraIO_PCI.cpp: implementation of the CCameraIO_PCI class.
|
|
//
|
|
// Copyright (c) 2000 Apogee Instruments Inc.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include <winioctl.h>
|
|
|
|
#include "ApogeeLinux.h" // This defines the IOCTL constants.
|
|
#include "CameraIO_PCI.h"
|
|
#include "time.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CCameraIO_PCI::CCameraIO_PCI()
|
|
{
|
|
m_IsWDM = false;
|
|
m_hDriver = NULL;
|
|
}
|
|
|
|
CCameraIO_PCI::~CCameraIO_PCI()
|
|
{
|
|
CloseDriver();
|
|
}
|
|
|
|
long CCameraIO_PCI::Read(unsigned short reg, unsigned short& val)
|
|
{
|
|
BOOLEAN IoctlResult;
|
|
ULONG ReturnedLength;
|
|
USHORT RegNumber;
|
|
USHORT ReadBuffer;
|
|
|
|
switch ( reg )
|
|
{
|
|
case Reg_Command:
|
|
RegNumber = RegPCI_CommandRead;
|
|
break;
|
|
case Reg_Timer:
|
|
RegNumber = RegPCI_TimerRead;
|
|
break;
|
|
case Reg_VBinning:
|
|
RegNumber = RegPCI_VBinningRead;
|
|
break;
|
|
case Reg_AICCounter:
|
|
RegNumber = RegPCI_AICCounterRead;
|
|
break;
|
|
case Reg_TempSetPoint:
|
|
RegNumber = RegPCI_TempSetPointRead;
|
|
break;
|
|
case Reg_PixelCounter:
|
|
RegNumber = RegPCI_PixelCounterRead;
|
|
break;
|
|
case Reg_LineCounter:
|
|
RegNumber = RegPCI_LineCounterRead;
|
|
break;
|
|
case Reg_BICCounter:
|
|
RegNumber = RegPCI_BICCounterRead;
|
|
break;
|
|
case Reg_ImageData:
|
|
RegNumber = RegPCI_ImageData;
|
|
break;
|
|
case Reg_TempData:
|
|
RegNumber = RegPCI_TempData;
|
|
break;
|
|
case Reg_Status:
|
|
RegNumber = RegPCI_Status;
|
|
break;
|
|
case Reg_CommandReadback:
|
|
RegNumber = RegPCI_CommandReadback;
|
|
break;
|
|
default:
|
|
_ASSERT( FALSE ); // Application program bug
|
|
val = 0;
|
|
return 0;
|
|
}
|
|
|
|
if ( m_IsWDM )
|
|
{
|
|
IoctlResult = DeviceIoControl(
|
|
m_hDriver, // Handle to device
|
|
IOCTL_WDM_READ_PCI_USHORT, // IO Control code for Read
|
|
&RegNumber, // Buffer to driver.
|
|
sizeof(RegNumber), // Length of buffer in bytes.
|
|
&ReadBuffer, // Buffer from driver.
|
|
sizeof(ReadBuffer), // Length of buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in DataBuffer.
|
|
NULL // NULL means wait till op. completes.
|
|
);
|
|
}
|
|
else
|
|
{
|
|
IoctlResult = DeviceIoControl(
|
|
m_hDriver, // Handle to device
|
|
IOCTL_GPD_READ_PCI_USHORT, // IO Control code for Read
|
|
&RegNumber, // Buffer to driver.
|
|
sizeof(RegNumber), // Length of buffer in bytes.
|
|
&ReadBuffer, // Buffer from driver.
|
|
sizeof(ReadBuffer), // Length of buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in DataBuffer.
|
|
NULL // NULL means wait till op. completes.
|
|
);
|
|
}
|
|
|
|
if ( (ReturnedLength != 2) || (IoctlResult == FALSE) )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
val = ReadBuffer;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long CCameraIO_PCI::Write(unsigned short reg, unsigned short val)
|
|
{
|
|
BOOLEAN IoctlResult;
|
|
ULONG InBuffer[2];
|
|
ULONG ReturnedLength;
|
|
USHORT RegNumber;
|
|
|
|
switch ( reg )
|
|
{
|
|
case Reg_Command:
|
|
RegNumber = RegPCI_Command;
|
|
break;
|
|
case Reg_Timer:
|
|
RegNumber = RegPCI_Timer;
|
|
break;
|
|
case Reg_VBinning:
|
|
RegNumber = RegPCI_VBinning;
|
|
break;
|
|
case Reg_AICCounter:
|
|
RegNumber = RegPCI_AICCounter;
|
|
break;
|
|
case Reg_TempSetPoint:
|
|
RegNumber = RegPCI_TempSetPoint;
|
|
break;
|
|
case Reg_PixelCounter:
|
|
RegNumber = RegPCI_PixelCounter;
|
|
break;
|
|
case Reg_LineCounter:
|
|
RegNumber = RegPCI_LineCounter;
|
|
break;
|
|
case Reg_BICCounter:
|
|
RegNumber = RegPCI_BICCounter;
|
|
break;
|
|
default:
|
|
_ASSERT ( false );
|
|
return 0;
|
|
}
|
|
|
|
InBuffer[0] = RegNumber;
|
|
InBuffer[1] = val;
|
|
|
|
// Do an I/O write
|
|
if ( m_IsWDM )
|
|
{
|
|
IoctlResult = DeviceIoControl(
|
|
m_hDriver, // Handle to device
|
|
IOCTL_WDM_WRITE_PCI_USHORT, // IO Control code for Write
|
|
&InBuffer, // Buffer to driver. Holds register/data.
|
|
sizeof ( InBuffer ), // Length of buffer in bytes.
|
|
NULL, // Buffer from driver. Not used.
|
|
0, // Length of buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in outbuf. Should be 0.
|
|
NULL // NULL means wait till I/O completes.
|
|
);
|
|
}
|
|
else
|
|
{
|
|
IoctlResult = DeviceIoControl(
|
|
m_hDriver, // Handle to device
|
|
IOCTL_GPD_WRITE_PCI_USHORT, // IO Control code for Write
|
|
&InBuffer, // Buffer to driver. Holds register/data.
|
|
sizeof ( InBuffer ), // Length of buffer in bytes.
|
|
NULL, // Buffer from driver. Not used.
|
|
0, // Length of buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in outbuf. Should be 0.
|
|
NULL // NULL means wait till I/O completes.
|
|
);
|
|
}
|
|
|
|
if ( (IoctlResult == FALSE) || (ReturnedLength != 0) )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
long CCameraIO_PCI::ReadLine( long SkipPixels, long Pixels, unsigned short* pLineBuffer )
|
|
{
|
|
BOOLEAN IoctlResult;
|
|
ULONG InBuffer[3];
|
|
ULONG ReturnedLength; // Number of bytes returned in output buffer
|
|
ULONG NumBytes;
|
|
USHORT* DataBuffer;
|
|
|
|
InBuffer[0] = RegPCI_ImageData;
|
|
InBuffer[1] = SkipPixels; // Data points to skip
|
|
InBuffer[2] = Pixels; // Data points to keep
|
|
|
|
NumBytes = Pixels * sizeof( unsigned short );
|
|
DataBuffer = pLineBuffer;
|
|
|
|
if ( !m_TDI )
|
|
{
|
|
/////////////////////////////////////
|
|
// 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 ] );
|
|
/////////////////////////////////////
|
|
}
|
|
|
|
if ( m_IsWDM )
|
|
{
|
|
IoctlResult = DeviceIoControl(
|
|
m_hDriver, // Handle to device
|
|
IOCTL_WDM_READ_PCI_LINE, // IO Control code for Read line
|
|
&InBuffer, // Buffer to driver.
|
|
sizeof(InBuffer), // Length of buffer in bytes.
|
|
DataBuffer, // Buffer from driver.
|
|
NumBytes, // Length of buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in DataBuffer.
|
|
NULL // NULL means wait till op. completes.
|
|
);
|
|
}
|
|
else
|
|
{
|
|
IoctlResult = DeviceIoControl(
|
|
m_hDriver, // Handle to device
|
|
IOCTL_GPD_READ_PCI_LINE, // IO Control code for Read line
|
|
&InBuffer, // Buffer to driver.
|
|
sizeof(InBuffer), // Length of buffer in bytes.
|
|
DataBuffer, // Buffer from driver.
|
|
NumBytes, // Length of buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in DataBuffer.
|
|
NULL // NULL means wait till op. completes.
|
|
);
|
|
}
|
|
|
|
if ( (ReturnedLength != NumBytes) || (!IoctlResult) )
|
|
{
|
|
return 1; // Failed to get line info
|
|
}
|
|
|
|
/////////////////////////////////////
|
|
// Assert done reading line
|
|
m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
|
|
m_RegShadow[ Reg_Command ] &= ~RegBit_DoneReading; // set bit to 0
|
|
Write( Reg_Command, m_RegShadow[ Reg_Command ] );
|
|
/////////////////////////////////////
|
|
|
|
if ( !m_TDI )
|
|
{
|
|
/////////////////////////////////////
|
|
// Wait until camera is done
|
|
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 ) return 1; // Timed out
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool CCameraIO_PCI::InitDriver()
|
|
{
|
|
OSVERSIONINFO OSVerInfo;
|
|
BOOLEAN IsPostWin98OS;
|
|
BOOLEAN IsNT4OS;
|
|
BOOLEAN IsPostNT4OS;
|
|
|
|
IsPostWin98OS = false;
|
|
IsNT4OS = false;
|
|
IsPostNT4OS = false;
|
|
|
|
CloseDriver();
|
|
|
|
OSVerInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
|
|
GetVersionEx( &OSVerInfo );
|
|
|
|
// Check for Win9x versions. Pre-Win98 is unsupported.
|
|
if ( OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
|
{
|
|
// Check for pre-Win98
|
|
if (( OSVerInfo.dwMajorVersion < 4 ) ||
|
|
(( OSVerInfo.dwMajorVersion == 4 ) && ( OSVerInfo.dwMinorVersion == 0 )))
|
|
{
|
|
return false; // Pre-Win98 not supported
|
|
}
|
|
else
|
|
{
|
|
IsPostWin98OS = true;
|
|
}
|
|
|
|
}
|
|
else if ( OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
// Check if NT4
|
|
if ( OSVerInfo.dwMajorVersion < 4 )
|
|
{
|
|
// NT3.51 is not supported. Right??
|
|
return false;
|
|
}
|
|
else if (OSVerInfo.dwMajorVersion == 4 )
|
|
{
|
|
IsNT4OS = true;
|
|
}
|
|
else if (OSVerInfo.dwMajorVersion > 4 )
|
|
{
|
|
IsPostNT4OS = true;
|
|
}
|
|
}
|
|
|
|
if ( IsNT4OS )
|
|
{
|
|
ULONG ReturnedLength;
|
|
ULONG DataBuffer[2];
|
|
|
|
// Open the driver
|
|
m_hDriver = CreateFile(
|
|
"\\\\.\\ApogeeIO",
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if ( m_hDriver == INVALID_HANDLE_VALUE )
|
|
{
|
|
m_hDriver = NULL;
|
|
return false;
|
|
}
|
|
|
|
BOOL IoctlResult = DeviceIoControl(
|
|
m_hDriver, // Handle to device
|
|
IOCTL_PCI_BUS_SCAN, // IO Control code for PCI Bus Scan
|
|
NULL, // Buffer to driver.
|
|
0, // Length of buffer in bytes.
|
|
DataBuffer, // Buffer from driver.
|
|
sizeof( DataBuffer ), // Length of buffer in bytes.
|
|
&ReturnedLength, // Bytes placed in DataBuffer.
|
|
NULL // NULL means wait till op. completes.
|
|
);
|
|
|
|
if ( (!IoctlResult) || (ReturnedLength != sizeof(DataBuffer)) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if ( IsPostWin98OS || IsPostNT4OS )
|
|
{
|
|
// Should be okay to use the WDM driver. Note that the kernel
|
|
// driver will actually check to see if WDM services are available
|
|
|
|
// Open the driver
|
|
m_hDriver = CreateFile(
|
|
"\\\\.\\ApPCI",
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if ( m_hDriver == INVALID_HANDLE_VALUE )
|
|
{
|
|
m_hDriver = NULL;
|
|
return false;
|
|
}
|
|
|
|
// Safe to assume we're using the WDM driver at this point.
|
|
m_IsWDM = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CCameraIO_PCI::CloseDriver()
|
|
{
|
|
// Close the driver if it already exists
|
|
if ( m_hDriver != NULL )
|
|
{
|
|
CloseHandle ( m_hDriver );
|
|
}
|
|
|
|
m_hDriver = NULL;
|
|
}
|