#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")); }