1210 lines
29 KiB
C++
1210 lines
29 KiB
C++
#include "stdafx.h"
|
|
#include "pmxe3.h"
|
|
|
|
#include "datadump.h"
|
|
|
|
|
|
CPMXE3::CPMXE3(PDEVCTRL pDeviceControl)
|
|
{
|
|
m_pDeviceControl = pDeviceControl;
|
|
m_scanmode = scHalftone;
|
|
InitializeRegisters();
|
|
}
|
|
|
|
CPMXE3::~CPMXE3()
|
|
{
|
|
|
|
}
|
|
|
|
VOID CPMXE3::InitializeRegisters()
|
|
{
|
|
Register0 =0x00;
|
|
//Register1 =0x5a;
|
|
//Register2 =0x00;
|
|
Register3 =0x0f;
|
|
Register4 =0x32;
|
|
Register5 =0x14;
|
|
Register6 =0x95;
|
|
Register7 =0x07;
|
|
Register8 =0xd0;
|
|
Register9 =0x0a;
|
|
Register10=0x0f;
|
|
Register11=0xa0;
|
|
Register12=0x40;
|
|
Register13=0x80;
|
|
//Register14=0x00;
|
|
//Register15=0x00;
|
|
//Register16=0x00;
|
|
//Register17=0x00;
|
|
//Register18=0x00;
|
|
//Register19=0x00;
|
|
Register20=0x00;
|
|
Register21=0x00;
|
|
Register22=0x13;
|
|
Register23=0xec;
|
|
//Register24=0xff;
|
|
Register25=0x14;
|
|
Register26=0x18;
|
|
Register27=0x11;
|
|
Register28=0x2c;
|
|
Register29=0x2c;
|
|
//Register30=0x00;
|
|
Register31=0x00;
|
|
//Register32=0x00;
|
|
//Register33=0x00;
|
|
//Register34=0x00;
|
|
//Register35=0x00;
|
|
|
|
#ifdef DEBUG
|
|
Trace(TEXT("Register Dump - At InitRegisters() Call"));
|
|
DebugDumpRegisters();
|
|
#endif
|
|
|
|
}
|
|
|
|
VOID CPMXE3::DebugDumpRegisters()
|
|
{
|
|
//
|
|
// dump Init registers initial values
|
|
//
|
|
|
|
WORD CarriageStep = MAKEWORD(Register8,Register7); // 2000
|
|
WORD ScanAreaStart = MAKEWORD(Register21,Register20); // 0
|
|
WORD ScanAreaWidth = MAKEWORD(Register23,Register22); // 5100
|
|
WORD XResolution = MAKEWORD(Register28,((E3_REG27*)&Register27)->XRes); // 300 dpi
|
|
WORD YResolution = MAKEWORD(Register29,((E3_REG27*)&Register27)->YRes); // 300 dpi
|
|
WORD TriggerPeriod = MAKEWORD(Register11,Register10); // 4000
|
|
|
|
Trace(TEXT("- WORD constructed Register values -"));
|
|
Trace(TEXT("Carriage Step: %d"),CarriageStep);
|
|
Trace(TEXT("ScanAreaStart: %d"),ScanAreaStart);
|
|
Trace(TEXT("ScanAreaWidth: %d"),ScanAreaWidth);
|
|
Trace(TEXT("XResolution: %d"),XResolution);
|
|
Trace(TEXT("YResolution: %d"),YResolution);
|
|
Trace(TEXT("TriggerPeriod %d"),TriggerPeriod);
|
|
Trace(TEXT("------------------------------------"));
|
|
|
|
E3_REG3* pRegister3 = (E3_REG3*)&Register3;
|
|
Trace(TEXT("- Register3 -"));
|
|
Trace(TEXT("EppUsb = %d"),pRegister3->EppUsb);
|
|
Trace(TEXT("FifoReset = %d"),pRegister3->FifoReset);
|
|
Trace(TEXT("ScanSpeed = %d"),pRegister3->ScanSpeed);
|
|
Trace(TEXT("SelfTest = %d"),pRegister3->SelfTest);
|
|
Trace(TEXT("SystemReset = %d"),pRegister3->SystemReset);
|
|
Trace(TEXT("WatchDog = %d"),pRegister3->WatchDog);
|
|
Trace(TEXT("----------------"));
|
|
|
|
|
|
E3_REG4* pRegister4 = (E3_REG4*)&Register4;
|
|
Trace(TEXT("- Register4 -"));
|
|
Trace(TEXT("AsicTest = %d"),pRegister4->AsicTest);
|
|
Trace(TEXT("Refresh = %d"),pRegister4->Refresh);
|
|
Trace(TEXT("RefreshForever = %d"),pRegister4->RefreshForever);
|
|
Trace(TEXT("ScanMode = %d"),pRegister4->ScanMode);
|
|
Trace(TEXT("WaitDelay = %d"),pRegister4->WaitDelay);
|
|
Trace(TEXT("YTable = %d"),pRegister4->YTable);
|
|
Trace(TEXT("----------------"));
|
|
|
|
E3_REG5* pRegister5 = (E3_REG5*)&Register5;
|
|
Trace(TEXT("- Register5 -"));
|
|
Trace(TEXT("Adc1210 = %d"),pRegister5->Adc1210);
|
|
Trace(TEXT("Afe = %d"),pRegister5->Afe);
|
|
Trace(TEXT("Sensor = %d"),pRegister5->Sensor);
|
|
Trace(TEXT("Sensor_Res = %d"),pRegister5->Sensor_Res);
|
|
Trace(TEXT("----------------"));
|
|
|
|
E3_REG6* pRegister6 = (E3_REG6*)&Register6;
|
|
Trace(TEXT("- Register6 -"));
|
|
Trace(TEXT("FullHalf = %d"),pRegister6->FullHalf);
|
|
Trace(TEXT("LineOffset = %d"),pRegister6->LineOffset);
|
|
Trace(TEXT("MotorPower = %d"),pRegister6->MotorPower);
|
|
Trace(TEXT("Operation = %d"),pRegister6->Operation);
|
|
Trace(TEXT("----------------"));
|
|
|
|
E3_REG12* pRegister12 = (E3_REG12*)&Register12;
|
|
Trace(TEXT("- Register12 -"));
|
|
Trace(TEXT("FifoEmpty = %d"),pRegister12->FifoEmpty);
|
|
Trace(TEXT("FinishFlag = %d"),pRegister12->FinishFlag);
|
|
Trace(TEXT("HomeSensor = %d"),pRegister12->HomeSensor);
|
|
Trace(TEXT("HwSelfTest = %d"),pRegister12->HwSelfTest);
|
|
Trace(TEXT("Lamp = %d"),pRegister12->Lamp);
|
|
Trace(TEXT("MotorMove = %d"),pRegister12->MotorMove);
|
|
Trace(TEXT("MotorStop = %d"),pRegister12->MotorStop);
|
|
Trace(TEXT("ScanStatus = %d"),pRegister12->ScanStatus);
|
|
Trace(TEXT("----------------"));
|
|
|
|
|
|
E3_REG13* pRegister13 = (E3_REG13*)&Register13;
|
|
Trace(TEXT("- Register13 -"));
|
|
Trace(TEXT("Cs = %d"),pRegister13->Cs);
|
|
Trace(TEXT("Reserved = %d"),pRegister13->Reserved);
|
|
Trace(TEXT("Sclk = %d"),pRegister13->Sclk);
|
|
Trace(TEXT("Sdi = %d"),pRegister13->Sdi);
|
|
Trace(TEXT("Sdo = %d"),pRegister13->Sdo);
|
|
Trace(TEXT("WmVsamp = %d"),pRegister13->WmVsamp);
|
|
Trace(TEXT("----------------"));
|
|
|
|
|
|
E3_REG26* pRegister26 = (E3_REG26*)&Register26;
|
|
Trace(TEXT("- Register26 -"));
|
|
Trace(TEXT("Start = %d"),pRegister26->Start);
|
|
Trace(TEXT("Stop = %d"),pRegister26->Stop);
|
|
Trace(TEXT("----------------"));
|
|
|
|
E3_REG31* pRegister31 = (E3_REG31*)&Register31;
|
|
Trace(TEXT("- Register31 -"));
|
|
Trace(TEXT("Key0 = %d"),pRegister31->Key0);
|
|
Trace(TEXT("Key1 = %d"),pRegister31->Key1);
|
|
Trace(TEXT("Key2 = %d"),pRegister31->Key2);
|
|
Trace(TEXT("Key3 = %d"),pRegister31->Key3);
|
|
Trace(TEXT("Key4 = %d"),pRegister31->Key4);
|
|
Trace(TEXT("Key5 = %d"),pRegister31->Key5);
|
|
Trace(TEXT("Key6 = %d"),pRegister31->Key6);
|
|
Trace(TEXT("Key7 = %d"),pRegister31->Key7);
|
|
Trace(TEXT("----------------"));
|
|
|
|
Trace(TEXT("--- END REGISTER DUMP ---"));
|
|
}
|
|
|
|
BOOL CPMXE3::WriteRegister(INT RegisterNumber, BYTE Value)
|
|
{
|
|
|
|
DWORD cbRet = 0;
|
|
BOOL bSuccess = FALSE;
|
|
BYTE pData[2];
|
|
|
|
pData[0] = BYTE(RegisterNumber);
|
|
pData[1] = Value;
|
|
|
|
IO_BLOCK IoBlock;
|
|
|
|
IoBlock.uOffset = (BYTE)IOCTL_EPP_WRITE;
|
|
IoBlock.uLength = 2;
|
|
IoBlock.pbyData = pData;
|
|
|
|
bSuccess = DeviceIoControl(m_pDeviceControl->DeviceIOHandles[m_pDeviceControl->BulkInPipeIndex],
|
|
(DWORD) IOCTL_WRITE_REGISTERS,
|
|
&IoBlock,
|
|
sizeof(IO_BLOCK),
|
|
NULL,
|
|
0,
|
|
&cbRet,
|
|
NULL);
|
|
|
|
return bSuccess;
|
|
}
|
|
BOOL CPMXE3::WriteRegisterEx(INT RegisterNumber, BYTE Value)
|
|
{
|
|
BYTE pbuffer[64];
|
|
memset(pbuffer,0,sizeof(pbuffer));
|
|
pbuffer[0] = CMD_WRITE;
|
|
pbuffer[1] = (BYTE)RegisterNumber;
|
|
pbuffer[2] = 0; // length: low byte
|
|
pbuffer[3] = 1; // length: high byte
|
|
pbuffer[4] = Value;
|
|
|
|
return RawWrite(m_pDeviceControl->BulkInPipeIndex,
|
|
pbuffer,
|
|
64,
|
|
0);
|
|
}
|
|
|
|
BOOL CPMXE3::ReadRegister(INT RegisterNumber, BYTE *pValue)
|
|
{
|
|
DWORD cbRet = 0;
|
|
BOOL bSuccess = FALSE;
|
|
IO_BLOCK IoBlock;
|
|
|
|
IoBlock.uOffset = MAKEWORD(IOCTL_EPP_READ, (BYTE)RegisterNumber);
|
|
IoBlock.uLength = 1;
|
|
IoBlock.pbyData = pValue;
|
|
|
|
bSuccess = DeviceIoControl(m_pDeviceControl->DeviceIOHandles[m_pDeviceControl->BulkOutPipeIndex],
|
|
(DWORD) IOCTL_READ_REGISTERS,
|
|
(PVOID)&IoBlock,
|
|
(DWORD)sizeof(IO_BLOCK),
|
|
(PVOID)pValue,
|
|
(DWORD)sizeof(BYTE),
|
|
&cbRet,
|
|
NULL);
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL CPMXE3::ReadRegisterEx(INT RegisterNumber, BYTE *pValue)
|
|
{
|
|
BYTE pbuffer[64];
|
|
memset(pbuffer,0,sizeof(pbuffer));
|
|
pbuffer[0] = CMD_READ;
|
|
pbuffer[1] = (BYTE)RegisterNumber;
|
|
pbuffer[2] = 0; // length: low byte
|
|
pbuffer[3] = 1; // length: high byte
|
|
|
|
LONG BytesRead = 0;
|
|
*pValue = 0;
|
|
|
|
if(!RawWrite(m_pDeviceControl->BulkInPipeIndex, pbuffer, 64, 0)){
|
|
return FALSE;
|
|
}
|
|
if(!RawRead(m_pDeviceControl->BulkOutPipeIndex, pbuffer, 64, &BytesRead,0)){
|
|
return FALSE;
|
|
}
|
|
|
|
*pValue = pbuffer[0];
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetXRes(LONG xRes)
|
|
{
|
|
m_xres = xRes;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetYRes(LONG yRes)
|
|
{
|
|
m_yres = yRes;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetXPos(LONG xPos)
|
|
{
|
|
m_xpos = xPos;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetYPos(LONG yPos)
|
|
{
|
|
m_ypos = yPos;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetXExt(LONG xExt)
|
|
{
|
|
m_xext = xExt;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetYExt(LONG yExt)
|
|
{
|
|
m_yext = yExt;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetDataType(LONG DataType)
|
|
{
|
|
m_datatype = DataType;
|
|
switch (m_datatype) {
|
|
case 0: // WIA_DATA_THRESHOLD
|
|
m_scanmode = scHalftone;
|
|
break;
|
|
case 1: // WIA_DATA_GRAYSCALE
|
|
m_scanmode = scGrayScale;
|
|
break;
|
|
case 2: // WIA_DATA_COLOR
|
|
m_scanmode = scFullColor;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
///////////////////////
|
|
// //
|
|
// DEVICE OPERATIONS //
|
|
// //
|
|
///////////////////////
|
|
|
|
|
|
BOOL CPMXE3::Lamp(BOOL bON)
|
|
{
|
|
if(!ReadRegister(12,&Register12))
|
|
return FALSE;
|
|
|
|
if(bON) // lamp ON
|
|
((E3_REG12*)&Register12)->Lamp = 1;
|
|
else // lamp OFF
|
|
((E3_REG12*)&Register12)->Lamp = 0;
|
|
|
|
if(!WriteRegister(12,Register12))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::IsLampON()
|
|
{
|
|
if(!ReadRegister(12,&Register12))
|
|
return FALSE;
|
|
|
|
if (((E3_REG12*)&Register12)->Lamp == 1)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CPMXE3::Motor(BOOL bON)
|
|
{
|
|
if(!ReadRegister(6,&Register6))
|
|
return FALSE;
|
|
|
|
if(bON){ // Turn Motor ON
|
|
((E3_REG6*)&Register6)->MotorPower = 1;
|
|
} else { // Turn Motor OFF
|
|
((E3_REG6*)&Register6)->MotorPower = 0;
|
|
}
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::HomeCarriage()
|
|
{
|
|
|
|
StopScan(); // must issue a STOP before homing carriage...or the device makes
|
|
// a rather nasty grinding noise...("That can't be good.." -Cooper Partin, May 19,2000)
|
|
|
|
INT TriggerPeriod = 0;
|
|
INT ScanSpeed = 7;
|
|
INT OverCLK = 2; // perfect for E3 series models
|
|
INT ExposureTimeMin = 2000; // 2 seconds exposure time
|
|
INT ExposureTime = 12000; // possible choices, (13800,5610,11400,12000)
|
|
|
|
//
|
|
// calculate TriggerPeriod
|
|
//
|
|
|
|
if((ExposureTime / ( ScanSpeed + 1 ) ) * OverCLK < ExposureTimeMin * OverCLK)
|
|
TriggerPeriod = (INT)(ExposureTimeMin * OverCLK);
|
|
else
|
|
TriggerPeriod = (INT)((ExposureTime / ( ScanSpeed + 1 ) ) * OverCLK);
|
|
|
|
|
|
Register25 = 0x14;
|
|
|
|
if(!WriteRegister(25,Register25))
|
|
return FALSE;
|
|
|
|
if(!SetMotorSpeed(TriggerPeriod,ScanSpeed))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(6,&Register6))
|
|
return FALSE;
|
|
|
|
if(!StopMode())
|
|
return FALSE;
|
|
|
|
((E3_REG6*)&Register6)->MotorPower = 1; // motor ON
|
|
((E3_REG6*)&Register6)->Operation = 5; // auto home
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
//
|
|
// Prevent any operations until scanner is in HOME position...
|
|
// If any operations are done... could result in nasty noises
|
|
// and system hangs... :) (just like forcing a car into reverse, while
|
|
// driving down the freeway...)
|
|
//
|
|
|
|
while(!IsCarriageHOME()) {
|
|
Sleep(100);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::StopMode()
|
|
{
|
|
((E3_REG6*)&Register6)->Operation = 0;
|
|
return WriteRegister(6,Register6);
|
|
}
|
|
|
|
BOOL CPMXE3::WriteStopImageRegister()
|
|
{
|
|
BYTE pbuffer[64];
|
|
memset(pbuffer,0,sizeof(pbuffer));
|
|
pbuffer[0] = CMD_STOPIMAGE;
|
|
|
|
return RawWrite(m_pDeviceControl->BulkInPipeIndex,
|
|
pbuffer,
|
|
64,
|
|
0);
|
|
}
|
|
|
|
BOOL CPMXE3::StopScan()
|
|
{
|
|
|
|
if(!WriteStopImageRegister())
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(6,&Register6))
|
|
return FALSE;
|
|
|
|
((E3_REG6*)&Register6)->MotorPower = 0;
|
|
((E3_REG6*)&Register6)->Operation = 0;
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
((E3_REG13*)&Register13)->Sdo = 0;
|
|
((E3_REG13*)&Register13)->Sclk = 0;
|
|
if(!WriteRegister(13,Register13))
|
|
return FALSE;
|
|
|
|
Register25 = 0x14;
|
|
if(!WriteRegister(25,Register25))
|
|
return FALSE;
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetMotorSpeed(INT TriggerPeriod, INT ScanSpeed)
|
|
{
|
|
//
|
|
// set trigger period
|
|
//
|
|
|
|
Register10 = HIBYTE(TriggerPeriod/2);
|
|
Register11 = LOBYTE(TriggerPeriod/2);
|
|
if(!WriteRegister(10,Register10))
|
|
return FALSE;
|
|
if(!WriteRegister(11,Register11))
|
|
return FALSE;
|
|
|
|
//
|
|
// set scan speed
|
|
//
|
|
|
|
// Register3 = 0;
|
|
if(!ReadRegister(3,&Register3))
|
|
return FALSE;
|
|
|
|
((E3_REG3*)&Register3)->ScanSpeed = ScanSpeed;
|
|
if(!WriteRegister(3,Register3))
|
|
return FALSE;
|
|
|
|
//
|
|
// initialize motor
|
|
//
|
|
|
|
// Register6 = 0;
|
|
|
|
((E3_REG6*)&Register6)->MotorPower = 1;
|
|
((E3_REG6*)&Register6)->FullHalf = 1;
|
|
((E3_REG6*)&Register6)->Operation = 0;
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::MoveCarriage(BOOL bForward, INT Steps)
|
|
{
|
|
INT TriggerPeriod = 0;
|
|
INT ScanSpeed = 7; // perfect for E3 series models
|
|
INT OverCLK = 2; // perfect for E3 series models
|
|
INT ExposureTimeMin = 2000; // 2 seconds exposure time
|
|
INT ExposureTime = 12000; // possible choices, (13800,5610,11400,12000)
|
|
|
|
//
|
|
// calculate TriggerPeriod
|
|
//
|
|
|
|
if((ExposureTime / ( ScanSpeed + 1 ) ) * OverCLK < ExposureTimeMin * OverCLK)
|
|
TriggerPeriod = (INT)(ExposureTimeMin * OverCLK);
|
|
else
|
|
TriggerPeriod = (INT)((ExposureTime / ( ScanSpeed + 1 ) ) * OverCLK);
|
|
|
|
if(!SetMotorSpeed(TriggerPeriod,ScanSpeed))
|
|
return FALSE;
|
|
|
|
Register7 = HIBYTE(Steps*2); // high byte (move step)
|
|
Register8 = LOBYTE(Steps*2); // low byte (move step)
|
|
|
|
if(!WriteRegister(7,Register7))
|
|
return FALSE;
|
|
if(!WriteRegister(8,Register8))
|
|
return FALSE;
|
|
|
|
if(!StopMode())
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(6,&Register6))
|
|
return FALSE;
|
|
|
|
((E3_REG6*)&Register6)->MotorPower = 1;
|
|
|
|
if(bForward) // move forward
|
|
((E3_REG6*)&Register6)->Operation = 2;
|
|
else // move backward
|
|
((E3_REG6*)&Register6)->Operation = 3;
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::IsCarriageHOME()
|
|
{
|
|
ReadRegister(12,&Register12);
|
|
if((Register12&CARRIAGE_HOME) != CARRIAGE_HOME)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::IsMotorBusy()
|
|
{
|
|
ReadRegister(12,&Register12);
|
|
if((Register12&MOTOR_BUSY) != MOTOR_BUSY)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
INT CPMXE3::GetScanSpeed()
|
|
{
|
|
//
|
|
// return a preferred scan speed, with respect to
|
|
// the current y resolution.
|
|
//
|
|
|
|
if (m_yres>300)
|
|
return 0;
|
|
else if(m_yres>200)
|
|
return 1;
|
|
else if(m_yres>150)
|
|
return 2;
|
|
else if(m_yres>100)
|
|
return 3;
|
|
else if(m_yres>75)
|
|
return 5;
|
|
else if(m_yres>0)
|
|
return 7;
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL CPMXE3::SetXandYResolution()
|
|
{
|
|
//
|
|
// X and Y resolution have to be set at the same time..
|
|
//
|
|
|
|
if(!ReadRegister(27,&Register27)){
|
|
return FALSE;
|
|
}
|
|
|
|
if(!ReadRegister(28,&Register28)){
|
|
return FALSE;
|
|
}
|
|
|
|
if(!ReadRegister(29,&Register29)){
|
|
return FALSE;
|
|
}
|
|
|
|
((E3_REG27*)&Register27)->XRes = HIBYTE(m_xres);
|
|
((E3_REG28*)&Register28)->XRes = LOBYTE(m_xres);
|
|
|
|
((E3_REG27*)&Register27)->YRes = HIBYTE(m_yres);
|
|
((E3_REG29*)&Register29)->YRes = LOBYTE(m_yres);
|
|
|
|
if(!WriteRegister(27,Register27)){
|
|
return FALSE;
|
|
}
|
|
|
|
if(!WriteRegister(28,Register28)){
|
|
return FALSE;
|
|
}
|
|
|
|
if(!WriteRegister(29,Register29)){
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::SetScanWindow()
|
|
{
|
|
//
|
|
// set all three (xpos,ypos,xext,and current yext)
|
|
// at this point..
|
|
//
|
|
|
|
if(!ReadRegister(7,&Register7))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(8,&Register8))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(20,&Register20))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(21,&Register21))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(22,&Register22))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(23,&Register23))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(26,&Register26))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(4,&Register4))
|
|
return FALSE;
|
|
|
|
LONG AreaStart = m_xpos;
|
|
LONG AreaStartOffset = 146; //180;
|
|
|
|
AreaStart = (AreaStart * (600/*Hardware DPI*// m_xres));
|
|
AreaStart += AreaStartOffset;
|
|
|
|
((E3_REG20*)&Register20)->AreaStart = HIBYTE(AreaStart);
|
|
((E3_REG21*)&Register21)->AreaStart = LOBYTE(AreaStart);
|
|
|
|
if(!WriteRegister(20,Register20))
|
|
return FALSE;
|
|
if(!WriteRegister(21,Register21))
|
|
return FALSE;
|
|
|
|
((E3_REG22*)&Register22)->AreaWidth = HIBYTE(m_xext);
|
|
((E3_REG23*)&Register23)->AreaWidth = LOBYTE(m_xext);
|
|
|
|
if(!WriteRegister(22,Register22))
|
|
return FALSE;
|
|
|
|
if(!WriteRegister(23,Register23))
|
|
return FALSE;
|
|
|
|
if(!WriteRegister(27,Register27))
|
|
return FALSE;
|
|
|
|
if(!WriteRegister(28,Register28))
|
|
return FALSE;
|
|
|
|
if(!WriteRegister(29,Register29))
|
|
return FALSE;
|
|
|
|
LONG Length = 0;
|
|
LONG CutLine = 2;
|
|
LONG LineOffset = 0;
|
|
|
|
Length = (LONG)(((m_yext + 1 + CutLine) * 600) + (m_yres - 1)) / m_yres;
|
|
Length += ((GetScanSpeed()+1)*(LineOffset + 1) * 2);
|
|
//Length = 6620;
|
|
|
|
Trace(TEXT("Caculated Length for Motor stepping.. = %d (6620?)"),Length);
|
|
Trace(TEXT("ScanSpeed used.. = %d"),GetScanSpeed());
|
|
|
|
Register7 = HIBYTE(Length);
|
|
Register8 = LOBYTE(Length);
|
|
|
|
if(!WriteRegister(7,Register7))
|
|
return FALSE;
|
|
|
|
if(!WriteRegister(8,Register8))
|
|
return FALSE;
|
|
|
|
((E3_REG26*)&Register26)->Stop = 0x08;
|
|
((E3_REG26*)&Register26)->Start = (BYTE)1;
|
|
|
|
if(!WriteRegister(26,Register26))
|
|
return FALSE;
|
|
|
|
((E3_REG4*)&Register4)->WaitDelay = 1; // USB models
|
|
|
|
if(!WriteRegister(4,Register4))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
VOID CPMXE3::GrayScaleToThreshold(LPBYTE lpSrc, LPBYTE lpDst, LONG RowBytes)
|
|
{
|
|
//
|
|
// code is borrowed from Visioneer scanner driver
|
|
// could be optimized.
|
|
//
|
|
|
|
BYTE val = 0;
|
|
BYTE nValueBW = 0;
|
|
INT nCount1 = 0;
|
|
INT nCount = 0;
|
|
INT LineArtThreshold = 110;
|
|
|
|
for(nCount = 0, nCount1 = 0, nValueBW = 0;nCount < RowBytes; nCount++) {
|
|
val = *(lpSrc + nCount);
|
|
|
|
if(val > LineArtThreshold)
|
|
nValueBW |= 1;
|
|
|
|
if((nCount & 7)==7) {
|
|
*(lpDst+nCount1) = nValueBW;
|
|
nValueBW=0;
|
|
nCount1++;
|
|
} else
|
|
nValueBW = nValueBW << 1;
|
|
}
|
|
|
|
if((nCount&7)!=0) {
|
|
nValueBW=nValueBW << ( 8 - (nCount & 7));
|
|
*(lpDst + nCount1) = nValueBW;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CPMXE3::GetButtonStatus(PBYTE pButtons)
|
|
{
|
|
//
|
|
// button status for 5 button scanners only
|
|
//
|
|
// this may need to be rewritten using E3_REG31
|
|
// which has Key values.
|
|
//
|
|
|
|
Register31 = 0;
|
|
INT ButtonMask = 1;
|
|
|
|
if(!ReadRegister(31,&Register31))
|
|
return FALSE;
|
|
|
|
for(INT index = 0; index < 5 ; index++){
|
|
if(Register31&ButtonMask)
|
|
pButtons[index] = 1;
|
|
else
|
|
pButtons[index] = 0;
|
|
ButtonMask<<=1;
|
|
}
|
|
|
|
if(Register31&0x01)
|
|
pButtons[6] = 1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::ClearButtonPress()
|
|
{
|
|
Register31 = 0;
|
|
if(!WriteRegister(31,Register31))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::WakeupScanner()
|
|
{
|
|
//
|
|
// turn on lamp
|
|
// and turn on motor power
|
|
//
|
|
|
|
if(!Lamp(TRUE))
|
|
return FALSE;
|
|
return Motor(TRUE);
|
|
}
|
|
|
|
BOOL CPMXE3::SleepScanner()
|
|
{
|
|
//
|
|
// turn off the lamp
|
|
// and turn of the motor power
|
|
//
|
|
|
|
if(!Lamp(FALSE))
|
|
return FALSE;
|
|
return Motor(FALSE);
|
|
}
|
|
|
|
BOOL CPMXE3::StartScan()
|
|
{
|
|
if(!ResetFIFO())
|
|
return FALSE;
|
|
|
|
if(!Lamp(TRUE))
|
|
return FALSE;
|
|
|
|
// DownLoadLUT ??
|
|
|
|
if(!SetXandYResolution())
|
|
return FALSE;
|
|
|
|
//
|
|
// settings commit is done at scan time
|
|
//
|
|
|
|
if(!SetScanWindow())
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(13,&Register13))
|
|
return FALSE;
|
|
|
|
((E3_REG13*)&Register13)->Sdo = 0;
|
|
((E3_REG13*)&Register13)->Sclk = 1;
|
|
|
|
if(!WriteRegister(13,Register13))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(6,&Register6))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(9,&Register9))
|
|
return FALSE;
|
|
|
|
if(!ReadRegister(27,&Register27))
|
|
return FALSE;
|
|
|
|
((E3_REG6*)&Register6)->LineOffset = 1;
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
((E3_REG4*)&Register4)->ScanMode = m_scanmode; // changes for data type
|
|
((E3_REG4*)&Register4)->YTable = 1;
|
|
|
|
if(!WriteRegister(4,Register4))
|
|
return FALSE;
|
|
|
|
((E3_REG27*)&Register27)->True16Bits = 0;
|
|
((E3_REG27*)&Register27)->AutoPattern = 0;
|
|
|
|
if(!WriteRegister(27,Register27))
|
|
return FALSE;
|
|
|
|
INT TriggerPeriod = 5700;
|
|
|
|
Register10 = HIBYTE(TriggerPeriod);
|
|
Register11 = LOBYTE(TriggerPeriod);
|
|
|
|
if(!WriteRegister(10,Register10))
|
|
return FALSE;
|
|
|
|
if(!WriteRegister(11,Register11))
|
|
return FALSE;
|
|
|
|
((E3_REG3*)&Register3)->ScanSpeed = GetScanSpeed();
|
|
|
|
if(!WriteRegister(3,Register3))
|
|
return FALSE;
|
|
|
|
((E3_REG6*)&Register6)->FullHalf = 0;
|
|
((E3_REG6*)&Register6)->Operation = 0;
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
Register9 = (BYTE)10; // backstep
|
|
|
|
if(!WriteRegister(9,Register9))
|
|
return FALSE;
|
|
|
|
((E3_REG6*)&Register6)->Operation = 0;
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
((E3_REG6*)&Register6)->MotorPower = 1;
|
|
((E3_REG6*)&Register6)->Operation = 4; // scan
|
|
|
|
if(!WriteRegister(6,Register6))
|
|
return FALSE;
|
|
|
|
// clear buttons
|
|
if(!ClearButtonPress())
|
|
return FALSE;
|
|
|
|
Register25 = 0x10; // GIO?
|
|
if(!WriteRegister(25,Register25))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::ResetFIFO()
|
|
{
|
|
for(INT nResetTimes = 0; nResetTimes < 2;nResetTimes++){
|
|
|
|
StopMode();
|
|
|
|
if(!ReadRegister(3,&Register3))
|
|
return FALSE;
|
|
|
|
((E3_REG3*)&Register3)->FifoReset = 0;
|
|
if(!WriteRegister(3,Register3))
|
|
return FALSE;
|
|
|
|
((E3_REG3*)&Register3)->FifoReset = 1;
|
|
if(!WriteRegister(3,Register3))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::InitADC()
|
|
{
|
|
if(!ReadRegister(5,&Register5))
|
|
return FALSE;
|
|
|
|
((E3_REG5*)&Register5)->Adc1210 = 1;
|
|
((E3_REG5*)&Register5)->Afe = 0;
|
|
((E3_REG5*)&Register5)->Sensor_Res = 1; // 600dpi model
|
|
((E3_REG5*)&Register5)->Sensor = 0x02;
|
|
|
|
if(!WriteRegister(5,Register5))
|
|
return FALSE;
|
|
|
|
Register25 = 0x14;
|
|
|
|
if(!WriteRegister(25,Register25))
|
|
return FALSE;
|
|
|
|
if(!ClearButtonPress())
|
|
return FALSE;
|
|
|
|
/*
|
|
|
|
BYTE RDark = 0x000000be;
|
|
BYTE GDark = 0x000000be;
|
|
BYTE BDark = 0x000000be;
|
|
|
|
E3_WriteWm(1,0x03);
|
|
E3_WriteWm(2,0x04);
|
|
E3_WriteWm(3,0x22);
|
|
E3_WriteWm(5,0x12);
|
|
E3_WriteWm(0x20,(unsigned char)gRDark); //Red channel Dark Value
|
|
E3_WriteWm(0x21,(unsigned char)gGDark); //Green channel Dark Value
|
|
E3_WriteWm(0x22,(unsigned char)gBDark); //Blue channel Dark Value
|
|
E3_WriteWm(0x27,0x00);
|
|
E3_WriteWm(0x2b,0x02); //global Gain Value
|
|
|
|
*/
|
|
|
|
((E3_REG13*)&Register13)->WmVsamp = 1;
|
|
|
|
if(!WriteRegister(13,Register13))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::Scan()
|
|
{
|
|
|
|
//
|
|
// check carriage position (needs to be in HOME, for a proper scan)
|
|
//
|
|
|
|
if (!IsCarriageHOME()) {
|
|
if (!HomeCarriage())
|
|
return FALSE;
|
|
}
|
|
|
|
if(!StopMode())
|
|
return FALSE;
|
|
|
|
if(!InitADC())
|
|
return FALSE;
|
|
|
|
if(!MoveCarriage(TRUE,CALIBRATION_STEPSIZE)) // calibration offset position
|
|
return FALSE;
|
|
|
|
if(!MoveCarriage(TRUE,SCAN_STARTPOS_STEPSIZE)) // scan start position
|
|
return FALSE;
|
|
|
|
if(!StopMode())
|
|
return FALSE;
|
|
|
|
if(!StartScan())
|
|
return FALSE;
|
|
|
|
LONG lBytesRead = 1;
|
|
DWORD dwTotalImageSize = 0;
|
|
DWORD dwbpp = 0;
|
|
DWORD BytesPerLine = 0;
|
|
|
|
switch(m_datatype){
|
|
case 0:
|
|
dwbpp = 1;
|
|
BytesPerLine = ((m_xext +7)/8);
|
|
dwTotalImageSize = (BytesPerLine * m_yext);
|
|
break;
|
|
case 1:
|
|
dwbpp = 8;
|
|
BytesPerLine = m_xext;
|
|
dwTotalImageSize = (m_xext * m_yext);
|
|
break;
|
|
case 2:
|
|
dwbpp = 24;
|
|
BytesPerLine = (m_xext * 3);
|
|
dwTotalImageSize = ((m_xext * m_yext) * 3);
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// setup data dumper, so we can see if the image needs
|
|
// work.
|
|
//
|
|
|
|
DATA_DESCRIPTION DataDesc;
|
|
|
|
DataDesc.dwbpp = dwbpp;
|
|
DataDesc.dwDataSize = dwTotalImageSize;
|
|
DataDesc.dwHeight = m_yext;
|
|
DataDesc.dwWidth = m_xext;
|
|
DataDesc.pRawData = (PBYTE)LocalAlloc(LPTR,DataDesc.dwDataSize + 1024);
|
|
|
|
PBYTE pbuffer = DataDesc.pRawData;
|
|
Trace(TEXT("Total bytes to Read: = %d"),dwTotalImageSize);
|
|
Trace(TEXT("Data BYTES PER LINE = %d"),BytesPerLine);
|
|
|
|
LONG NumLinesToRead = (65535)/BytesPerLine;
|
|
DWORD dwImageDataRead = 0;
|
|
DWORD dwTotalLinesRead = 0;
|
|
DWORD dwTotalBytesRead = 0;
|
|
|
|
while (dwImageDataRead < dwTotalImageSize) {
|
|
|
|
//
|
|
// Send request for chunk
|
|
//
|
|
|
|
/*
|
|
BYTE pRegisters[64];
|
|
memset(pRegisters,0,sizeof(pRegisters));
|
|
|
|
pRegisters[0] = CMD_GETIMAGE;
|
|
pRegisters[1] = (BYTE)NumLinesToRead; // 255 or less
|
|
pRegisters[2] = HIBYTE(BytesPerLine);
|
|
pRegisters[3] = LOBYTE(BytesPerLine);
|
|
|
|
if (!RawWrite(m_pDeviceControl->BulkInPipeIndex,pRegisters,64,0))
|
|
return FALSE;
|
|
*/
|
|
|
|
DWORD cbRet = 0;
|
|
BOOL bSuccess = FALSE;
|
|
IO_BLOCK IoBlock;
|
|
BYTE Command[8];
|
|
Command[0] = 0;
|
|
Command[1] = 0xc;
|
|
Command[2] = 128;
|
|
Command[3] = 0;
|
|
Command[4] = LOBYTE(BytesPerLine);
|
|
Command[5] = HIBYTE(BytesPerLine);
|
|
Command[6] = LOBYTE(NumLinesToRead);
|
|
Command[7] = HIBYTE(NumLinesToRead);
|
|
|
|
IoBlock.uOffset = (BYTE)IOCTL_READ_WRITE_DATA;
|
|
IoBlock.uLength = (BYTE)8;
|
|
IoBlock.pbyData = Command;
|
|
|
|
Trace(TEXT("Issuing DeviceIOControl() call request for more data..."));
|
|
|
|
bSuccess = DeviceIoControl(m_pDeviceControl->DeviceIOHandles[m_pDeviceControl->BulkInPipeIndex],
|
|
(DWORD) IOCTL_WRITE_REGISTERS,
|
|
&IoBlock,
|
|
sizeof(IO_BLOCK),
|
|
NULL,
|
|
0,
|
|
&cbRet,
|
|
NULL);
|
|
|
|
//
|
|
// read scanned data until requested chunk is recieved
|
|
//
|
|
|
|
LONG LinesRead = 0;
|
|
lBytesRead = 0;
|
|
|
|
Trace(TEXT("Requesting %d BYTES from device"),(BytesPerLine * NumLinesToRead));
|
|
if (!RawRead(m_pDeviceControl->BulkOutPipeIndex,pbuffer,(BytesPerLine * NumLinesToRead),&lBytesRead,0)) {
|
|
MessageBox(NULL,TEXT("Reading data band failed"),TEXT(""),MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
dwTotalBytesRead += lBytesRead;
|
|
pbuffer += lBytesRead;
|
|
dwTotalLinesRead += (lBytesRead/BytesPerLine);
|
|
|
|
if((m_yext - dwTotalLinesRead) < (DWORD)NumLinesToRead){
|
|
NumLinesToRead = (m_yext - dwTotalLinesRead);
|
|
}
|
|
|
|
Trace(TEXT("Total Lines Read %d of %d"),dwTotalLinesRead,m_yext);
|
|
|
|
if (lBytesRead == 0) {
|
|
MessageBox(NULL,TEXT("No data returned from Read call"),TEXT(""),MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
Trace(TEXT("Recieved %d BYTES from device"),lBytesRead);
|
|
|
|
//
|
|
// increment buffers/counters
|
|
//
|
|
|
|
Sleep(400);
|
|
dwImageDataRead += dwTotalBytesRead;
|
|
dwTotalBytesRead = 0;
|
|
Trace(TEXT("Total Bytes Read So Far: = %d"),dwImageDataRead);
|
|
}
|
|
|
|
StopScan();
|
|
HomeCarriage();
|
|
|
|
CDATADUMP Data;
|
|
Data.DumpDataToBitmap(TEXT("PMXE3.BMP"),&DataDesc);
|
|
|
|
if(NULL != DataDesc.pRawData)
|
|
LocalFree(DataDesc.pRawData);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPMXE3::RawWrite(LONG lPipeNum,BYTE *pbuffer,LONG lbuffersize,LONG lTimeout)
|
|
{
|
|
DWORD dwBytesWritten = 0;
|
|
BOOL bSuccess = TRUE;
|
|
OVERLAPPED Overlapped;
|
|
memset(&Overlapped,0,sizeof(OVERLAPPED));
|
|
|
|
bSuccess = WriteFile(m_pDeviceControl->DeviceIOHandles[lPipeNum],
|
|
pbuffer,
|
|
lbuffersize,
|
|
&dwBytesWritten,
|
|
&Overlapped);
|
|
if(dwBytesWritten < (ULONG)lbuffersize)
|
|
return FALSE;
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL CPMXE3::RawRead(LONG lPipeNum,BYTE *pbuffer,LONG lbuffersize,LONG *plbytesread,LONG lTimeout)
|
|
{
|
|
DWORD dwBytesRead = 0;
|
|
OVERLAPPED Overlapped;
|
|
memset(&Overlapped,0,sizeof(OVERLAPPED));
|
|
|
|
BOOL bSuccess = ReadFile(m_pDeviceControl->DeviceIOHandles[lPipeNum],
|
|
pbuffer,
|
|
lbuffersize,
|
|
&dwBytesRead,
|
|
&Overlapped);
|
|
*plbytesread = dwBytesRead;
|
|
return bSuccess;
|
|
}
|
|
|
|
VOID CPMXE3::Trace(LPCTSTR format,...)
|
|
{
|
|
|
|
TCHAR Buffer[1024];
|
|
va_list arglist;
|
|
va_start(arglist, format);
|
|
wvsprintf(Buffer, format, arglist);
|
|
va_end(arglist);
|
|
OutputDebugString(Buffer);
|
|
OutputDebugString(TEXT("\n"));
|
|
|
|
} |