/* @file plustek-pp_motor.c * @brief all functions for motor control * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - slight cosmetic changes * - added function MotorToHomePosition() * - 0.33 - added additional debug-messages * - increased speed for returning to homeposition for Models >= 9630 * (and ASIC 96003) * - 0.34 - added FIFO overflow check in motorP96SetSpeed * - removed WaitBack() function from pScanData structure * - removed wStayMaxStep from pScanData structure * - 0.35 - changed motorP96UpdateDataCurrentReadLine() to handle proper * - work of ASIC96003 based 600dpi models * - 0.36 - merged motorP96WaitBack and motorP98WaitBack to motorWaitBack * - merged motorP96SetSpeed and motorP98SetSpedd to motorSetSpeed * - added Sensor-Check in function MotorToHomePosition * - reduced number of forward steps for MotorToHomePosition * - 0.37 - removed function motorP96GetStartStopGap() - no longer used * - removed a_bStepDown1Table and a_bStepUp1Table * - removed // comments * - added A3I stuff * - 0.38 - cosmetic changes * - added P12 stuff * - 0.39 - Did some finetuning in MotorP98003ModuleForwardBackward() * - Fixed a problem, that could cause the driver to throw a * kernel exception * - 0.40 - changed back to build 0.39-3 (disabled A3I stuff) * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some definitions *********************************/ /* #define _A3I_EN */ /* * adjustments for scanning in negative and tranparency mode */ #define _NEG_SCANNINGPOS 770 #define _POS_SCANNINGPOS 660 /* original value was 710 */ #define _P98_BACKMOVES 0x3d #define _P98_FORWARDMOVES 0x3b /* Origin = 3c */ #define _P98003_BACKSTEPS 120 #define _P98003_FORWARDSTEPS 120 #define _P96_BACKMOVES 130 #define _P96_FORWARDMOVES 87 /* 95 */ #define _P96_FIFOOVERFLOWTHRESH 180 #define _COLORRUNTABLE_RED 0x11 #define _COLORRUNTABLE_GREEN 0x22 #define _COLORRUNTABLE_BLUE 0x44 #define _BW_ORIGIN 0x0D #define _GRAY_ORIGIN 0x0B #define _COLOR_ORIGIN 0x0B #define _P98003_YOFFSET 300 /**************************** local vars *************************************/ static TimerDef p98003MotorTimer; static UShort a_wMoveStepTable [_NUMBER_OF_SCANSTEPS]; static Byte a_bScanStateTable[_SCANSTATE_TABLE_SIZE]; static Byte a_bHalfStepTable [_NUMBER_OF_SCANSTEPS]; static Byte a_bColorByteTable[_NUMBER_OF_SCANSTEPS]; static Byte a_bColorsSum[8] = {0, 1, 1, 2, 1, 2, 2, 3}; static pUShort pwEndMoveStepTable = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS; static pUChar pbEndColorByteTable = a_bColorByteTable + _NUMBER_OF_SCANSTEPS; static pUChar pbEndHalfStepTable = a_bHalfStepTable + _NUMBER_OF_SCANSTEPS; /* * for the 96001/3 based units */ static UShort wP96BaseDpi = 0; static Byte a_bStepDown1Table[20] = {3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static Byte a_bStepUp1Table[20] = {4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static Byte a_bMotorDown2Table[20] = {0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; #ifndef _A3I_EN static Byte a_bHalfStep2Table[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; static Byte a_bHalfStep4Table[16] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; static Byte a_bHalfStep6Table[12] = {3,3,3,3,3,3,3,3,3,3,3,3}; static Byte a_bHalfStep8Table[8] = {4,4,4,4,4,4,4,4}; static Byte a_bHalfStep10Table[8] = {5,5,5,5,5,5,5,5}; static Byte a_bHalfStep12Table[6] = {6,6,6,6,6,6}; static Byte a_bHalfStep14Table[6] = {7,7,7,7,7,7}; static Byte a_bHalfStep16Table[4] = {8,8,8,8}; static Byte a_bHalfStep18Table[4] = {9,9,9,9}; static Byte a_bHalfStep20Table[4] = {10,10,10,10}; static Byte a_bHalfStep22Table[4] = {11,11,11,11}; static Byte a_bHalfStep24Table[4] = {12,12,12,12}; static Byte a_bHalfStep26Table[4] = {13,13,13,13}; static Byte a_bHalfStep28Table[4] = {14,14,14,14}; static Byte a_bHalfStep30Table[4] = {15,15,15,15}; static Byte a_bHalfStep32Table[2] = {16,16}; static Byte a_bHalfStep34Table[2] = {17,17}; static Byte a_bHalfStep36Table[2] = {18,18}; static Byte a_bHalfStep38Table[2] = {19,19}; static Byte a_bHalfStep40Table[2] = {20,20}; static pUChar a_pbHalfStepTables[20] = { a_bHalfStep2Table, a_bHalfStep4Table, a_bHalfStep6Table, a_bHalfStep8Table, a_bHalfStep10Table, a_bHalfStep12Table, a_bHalfStep14Table, a_bHalfStep16Table, a_bHalfStep18Table, a_bHalfStep20Table, a_bHalfStep22Table, a_bHalfStep24Table, a_bHalfStep26Table, a_bHalfStep28Table, a_bHalfStep30Table, a_bHalfStep32Table, a_bHalfStep34Table, a_bHalfStep36Table, a_bHalfStep38Table, a_bHalfStep40Table }; #endif /*************************** local functions *********************************/ /*............................................................................. * */ static void motorP96GetStartStopGap( pScanData ps, Bool fCheckState ) { UChar bMotorCountDownIndex; if( fCheckState ) { ps->bMotorStepTableNo = 0xff; if( ps->Scan.bModuleState == _MotorInNormalState ) return; } bMotorCountDownIndex = ps->bMotorSpeedData / 2; if( ps->bCurrentSpeed == 4 && ps->AsicReg.RD_Dpi < 80 ) ps->bMotorStepTableNo = 4; else if( ps->Scan.bModuleState == _MotorGoBackward ) ps->bMotorStepTableNo = a_bStepUp1Table[bMotorCountDownIndex]; else ps->bMotorStepTableNo = a_bStepDown1Table[bMotorCountDownIndex]; } /*............................................................................. * wait for the ScanState stop or ScanState reaches the dwScanStateCount */ static Bool motorCheckMotorPresetLength( pScanData ps ) { Byte bScanState; TimerDef timer; MiscStartTimer( &timer, (_SECOND * 4)); do { bScanState = IOGetScanState( ps, _FALSE ); if (ps->fFullLength) { if (!(bScanState & _SCANSTATE_STOP)) /* still running */ if ((ULong)(bScanState & _SCANSTATE_MASK) != ps->dwScanStateCount ) continue; return ps->fFullLength; } if (bScanState & _SCANSTATE_STOP) break; /* * the code may work for all units */ if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { if (bScanState < ps->bOldStateCount) bScanState += _NUMBER_OF_SCANSTEPS; bScanState -= ps->bOldStateCount; if (bScanState >= 40) return ps->fFullLength; } } while ( !MiscCheckTimer( &timer )); _DODELAY(1); /* delay one ms */ return ps->fFullLength; } /*............................................................................. * 1) Keep the valid content of a_bColorByteTable, and fill others to 0: * BeginFill = ((bCurrentLineCount + DL) < 64) ? bCurrentLineCount + DL : * bCurrentLineCount + DL - 64; * FillLength = 64 - DL * [NOTE] Keep the content of a_bColorByteTable that begin at * bCurrentLineCount and in DL bytes * 2) Keep the valid content of a_bHalfStepTable, and fill the others to 0: * BeginFill = ((bCurrentLineCount + bCurrentSpeed / 2 + 1) < 64) ? * bCurrentLineCount + bCurrentSpeed / 2 + 1 : * bCurrentLineCount + bCurrentSpeed / 2 + 1 - 64; * FillLength = 64 - (bMotorSpeedData / 2 + 1); */ static void motorClearColorByteTableLoop0( pScanData ps, Byte bColors ) { ULong dw; pUChar pb; if ((ps->bCurrentLineCount + bColors) >= _NUMBER_OF_SCANSTEPS) { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors - _NUMBER_OF_SCANSTEPS); } else { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors); } for (dw = _NUMBER_OF_SCANSTEPS - bColors; dw; dw--) { *pb++ = 0; if (pb >= pbEndColorByteTable) pb = a_bColorByteTable; } if ((ps->bCurrentLineCount+ps->bCurrentSpeed/2+1) >= _NUMBER_OF_SCANSTEPS) { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount + ps->bCurrentSpeed / 2 + 1 - _NUMBER_OF_SCANSTEPS); } else { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount + ps->bCurrentSpeed / 2 + 1); } for (dw = _NUMBER_OF_SCANSTEPS - ps->bMotorSpeedData / 2 - 1; dw; dw--) { *pb++ = 0; if (pb >= pbEndHalfStepTable) pb = a_bHalfStepTable; } } /*............................................................................. * motorClearColorByteTableLoop1 () * 1) Adjust bNewGap: * bNewGap = (bNewGap <= bNewCurrentLineCountGap) ? * 0 : bNewGap - bNewCurrentLineCount - 1; * 2) Fill the 0 to a_bColorByteTable: * FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ? * bCurrentLineCount + bNewGap + 1 : * bCurrentLineCount + bNewGap + 1 - 64; * FillCount = 64 - bNewGap - 1; * 3) Adjust bNewGap: * bNewGap = (bCurrentLineCount <= bNewCurrentLineCountGap) ? * 0 : bNewGap - bNewCurrentLineCount - 1; * 4) Fill the a_bHalfStepTable: * FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ? * bCurrentLineCount + bNewGap + 1 : * bCurrentLineCount + bNewGap + 1 - 64; * FillCount = 64 - bNewGap - 1; */ static void motorClearColorByteTableLoop1( pScanData ps ) { ULong dw = _NUMBER_OF_SCANSTEPS - 1; pUChar pb; if (ps->bNewGap > ps->bNewCurrentLineCountGap) { ps->bNewGap = ps->bNewGap - ps->bNewCurrentLineCountGap - 1; dw -= (ULong)ps->bNewGap; } else { ps->bNewGap = 0; } if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount+ps->bNewGap+1-_NUMBER_OF_SCANSTEPS); } else { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + ps->bNewGap + 1); } for (; dw; dw--) { *pb++ = 0; if (pb >= pbEndColorByteTable) pb = a_bColorByteTable; } if (ps->bCurrentSpeed > ps->bNewCurrentLineCountGap) { ps->bNewGap = ps->bCurrentSpeed - ps->bNewCurrentLineCountGap; dw = _NUMBER_OF_SCANSTEPS - 1 - (ULong)ps->bNewGap; } else { dw = _NUMBER_OF_SCANSTEPS - 1; ps->bNewGap = 0; } if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount + ps->bNewGap + 1 - _NUMBER_OF_SCANSTEPS); } else { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount+ps->bNewGap +1); } for (; dw; dw--) { *pb++ = 0; if (pb >= pbEndHalfStepTable) pb = a_bHalfStepTable; } } /*............................................................................. * According the flag to set motor direction */ static void motorSetRunPositionRegister( pScanData ps ) { Byte bData; if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { if( ps->Scan.fMotorBackward ) { bData = ps->AsicReg.RD_Motor0Control & ~_MotorDirForward; } else { bData = ps->AsicReg.RD_Motor0Control | _MotorDirForward; } IOCmdRegisterToScanner( ps, ps->RegMotor0Control, bData ); } else { if( ps->Scan.fMotorBackward ) { bData = ps->Asic96Reg.RD_MotorControl & ~_MotorDirForward; } else { bData = ps->Asic96Reg.RD_MotorControl | _MotorDirForward; } IOCmdRegisterToScanner( ps, ps->RegMotorControl, bData ); } } /*............................................................................. * */ static void motorPauseColorMotorRunStates( pScanData ps ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES); if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->a_nbNewAdrPointer[2] = 0x77; /* Read color at the same time */ } else { ps->a_nbNewAdrPointer[2] = 1; ps->a_nbNewAdrPointer[3] = 3; ps->a_nbNewAdrPointer[4] = 2; } MotorSetConstantMove( ps, 0 ); } /*............................................................................. * Setup the a_nbNewAdrPointer for ASIC stepping register */ static void motorP98FillDataToColorTable( pScanData ps, Byte bIndex, ULong dwSteps) { pUChar pb; pUShort pw; Byte bColor; UShort w; for ( pb = &a_bColorByteTable[bIndex], pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps-- ) { if (*pw) { /* valid state */ if( *pw >= ps->BufferForColorRunTable ) { DBG( DBG_LOW, "*pw = %u > %u !!\n", *pw, ps->BufferForColorRunTable ); } else { bColor = ps->pColorRunTable[*pw]; /* get the colors */ if (a_bColorsSum[bColor & 7]) /* need to read data */ *pb = bColor & 7; } } if (++pw >= pwEndMoveStepTable) { pw = a_wMoveStepTable; pb = a_bColorByteTable; } else pb++; } /* ToCondense */ pb = a_bColorByteTable; for (w = 0; w < _SCANSTATE_BYTES; w++, pb += 2) ps->a_nbNewAdrPointer[w] = (Byte)((*pb & 7) + ((*(pb + 1) & 7) << 4)); /* ToCondenseMotor */ for (pb = a_bHalfStepTable, w = 0; w < _SCANSTATE_BYTES; w++) { if (*pb++) ps->a_nbNewAdrPointer [w] |= 8; if (*pb++) ps->a_nbNewAdrPointer [w] |= 0x80; } } /*............................................................................. * */ static void motorP98FillHalfStepTable( pScanData ps ) { pUChar pbHalfStepTbl, pb; pUShort pwMoveStep; DataType Data; ULong dw; if (1 == ps->bMotorSpeedData) { for (dw = 0; dw < _NUMBER_OF_SCANSTEPS; dw++) a_bHalfStepTable [dw] = (a_wMoveStepTable [dw] > ps->wMaxMoveStep) ? 0: 1; } else { pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount]; pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount]; if (ps->DataInf.wAppDataType >= COLOR_TRUE24) Data.dwValue = _NUMBER_OF_SCANSTEPS - 1; else Data.dwValue = _NUMBER_OF_SCANSTEPS; for (; Data.dwValue; Data.dwValue--, pbHalfStepTbl++, pwMoveStep++ ) { if (pwMoveStep >= pwEndMoveStepTable) { pbHalfStepTbl = a_bHalfStepTable; pwMoveStep = a_wMoveStepTable; } if (*pwMoveStep) { /* need to exposure */ dw = (ULong)ps->bMotorSpeedData; if (Data.bValue < ps->bMotorSpeedData) *pwMoveStep = 0; else { *pbHalfStepTbl = 1; if (ps->dwFullStateSpeed) { dw -= ps->dwFullStateSpeed; for (pb = pbHalfStepTbl; dw; dw -= ps->dwFullStateSpeed) { pb += ps->dwFullStateSpeed; if (pb >= pbEndHalfStepTable) pb -= _NUMBER_OF_SCANSTEPS; *pb = 1; } } } } } } } /*............................................................................. * */ static void motorP98FillBackColorDataTable( pScanData ps ) { Byte bIndex; if ((bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >= _NUMBER_OF_SCANSTEPS) { bIndex -= _NUMBER_OF_SCANSTEPS; } motorP98FillDataToColorTable( ps, bIndex, (ULong)(_NUMBER_OF_SCANSTEPS - ps->bNewCurrentLineCountGap)); } /*............................................................................. * i/p: * pScanStep = pColorRunTable if forward, a_bScanStateTable if backward * dwState = how many states is requested to process * NOTE: * The content of pScanStep contain: * 0: Idle state * 0xff: End mark * others: The motor speed value */ static void motorP98FillBackLoop( pScanData ps, pUChar pScanStep, ULong dwStates ) { for (ps->fFullLength = _FALSE; dwStates; dwStates--) { if (*pScanStep == 0xff ) { ULong dw = ps->dwScanStateCount; for (; dwStates; dwStates--) { ps->a_nbNewAdrPointer [dw / 2] &= ((dw & 1) ? 0x7f: 0xf7); dw = (dw + 1U) & _SCANSTATE_MASK; } if (!ps->dwScanStateCount) ps->dwScanStateCount = _NUMBER_OF_SCANSTEPS; ps->dwScanStateCount--; ps->fFullLength = _TRUE; break; } else { ps->a_nbNewAdrPointer [ps->dwScanStateCount / 2] |= ((ps->dwScanStateCount & 1) ? 0x80 : 0x08); if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS) ps->dwScanStateCount = 0; /* reset to begin */ pScanStep++; } } IOSetToMotorStepCount( ps ); /* put all scan states to ASIC */ } /*............................................................................. * */ static void motorP98SetRunFullStep( pScanData ps ) { ps->OpenScanPath( ps ); ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl ); IODataToRegister( ps, ps->RegLineControl, 96 ); if ( ps->bFastMoveFlag == _FastMove_Low_C75_G150_Back ) { IODataToRegister( ps, ps->RegMotor0Control, (_MotorHQuarterStep + _MotorOn + _MotorDirBackward)); } else { IODataToRegister( ps, ps->RegMotor0Control, (_MotorHQuarterStep + _MotorOn + _MotorDirForward)); } if (ps->bFastMoveFlag == _FastMove_Film_150) { ps->AsicReg.RD_XStepTime = 12; } else { if (ps->bFastMoveFlag == _FastMove_Fast_C50_G100) { ps->AsicReg.RD_XStepTime = ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 4 : 8); } else { ps->AsicReg.RD_XStepTime = ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 6 : 12); } } DBG( DBG_LOW, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime ); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime); ps->CloseScanPath( ps ); } /*............................................................................. * moves the sensor back home... */ static int motorP98BackToHomeSensor( pScanData ps ) { int result = _OK; TimerDef timer; MotorSetConstantMove( ps, 1 ); ps->OpenScanPath( ps ); ps->AsicReg.RD_StepControl = (_MOTOR_FREERUN + _MOTOR0_SCANSTATE+ _MOTOR0_ONESTEP); IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); ps->AsicReg.RD_Motor0Control = _MotorHQuarterStep + _MotorOn + _MotorDirBackward; IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control ); if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) { ps->AsicReg.RD_XStepTime = ps->bSpeed24; } else { ps->AsicReg.RD_XStepTime = ps->bSpeed12; } DBG( DBG_HIGH, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime ); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime ); IORegisterToScanner( ps, ps->RegRefreshScanState ); /* CHANGE: We allow up to 25 seconds for returning (org. val was 10) */ MiscStartTimer( &timer, _SECOND * 25 ); do { if (IODataFromRegister( ps, ps->RegStatus) & _FLAG_P98_PAPER ) { IODataToRegister( ps, ps->RegModelControl, (Byte)(ps->AsicReg.RD_ModelControl | _HOME_SENSOR_POLARITY)); if(!(IODataFromRegister(ps, ps->RegStatus) & _FLAG_P98_PAPER)) break; } _DODELAY( 10 ); /* delay 10 ms */ } while ( !(result = MiscCheckTimer( &timer ))); ps->CloseScanPath( ps ); if( _OK != result ) return result; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); return _OK; } /*............................................................................. * 1) Clear scan states * 2) Adjust the new scan state */ static void motorP98FillRunNewAdrPointer1( pScanData ps ) { ScanState sState; Byte bTemp; IOGetCurrentStateCount( ps, &sState); bTemp = sState.bStep; if (sState.bStep < ps->bOldStateCount) { sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can */ } /* holds 64 step, then reset to */ /* 0, so if less than means over*/ /* the table) */ sState.bStep -= ps->bOldStateCount; /* how many states passed */ ps->pScanState += sState.bStep; /* * if current state != no stepped or stepped a cycle, fill the table with * 1 in NOT STEPPED length. (1 means to this state has to be processing). */ ps->bOldStateCount = bTemp; ps->dwScanStateCount = (ULong)((bTemp + 1) & _SCANSTATE_MASK); motorP98FillBackLoop( ps, ps->pScanState, _NUMBER_OF_SCANSTEPS ); } /*............................................................................. * */ static void motorP98FillRunNewAdrPointer( pScanData ps ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); motorP98FillRunNewAdrPointer1( ps ); } /*............................................................................. * move the sensor to a specific Y-position */ static void motorP98PositionYProc( pScanData ps, ULong dwStates ) { ScanState sState; memset( ps->pColorRunTable, 1, dwStates ); memset( ps->pColorRunTable + dwStates, 0xff, (3800UL - dwStates)); IOGetCurrentStateCount( ps, &sState); ps->bOldStateCount = sState.bStep; ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegMotor0Control, (Byte)(_MotorOn + _MotorHEightStep +(ps->Scan.fMotorBackward)? _MotorDirBackward : _MotorDirForward)); DBG( DBG_LOW, "XStepTime = %u\n", ps->bSpeed6 ); IODataToRegister( ps, ps->RegXStepTime, ps->bSpeed6 ); ps->CloseScanPath( ps ); ps->pScanState = ps->pColorRunTable; ps->FillRunNewAdrPointer( ps ); while(!motorCheckMotorPresetLength( ps )) motorP98FillRunNewAdrPointer1( ps ); } /*............................................................................. * checks if the sensor is in it´s home position and moves it back if necessary */ static int motorP98CheckSensorInHome( pScanData ps ) { int result; if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){ MotorSetConstantMove( ps, 1 ); ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = 0; motorP98PositionYProc( ps, 20 ); result = motorP98BackToHomeSensor( ps ); if( _OK != result ) return result; _DODELAY( 250 ); } return _OK; } /*............................................................................. * move the sensor to the scan-start position */ static void motorP98WaitForPositionY( pScanData ps ) { ULong dw; ULong dwBX, dwDX; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { motorP98BackToHomeSensor( ps ); _DODELAY( 100 ); /* CHECK do we need this block ? was test code in the original source code */ ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl); IODataToRegister( ps, ps->RegStepControl, (Byte)(_MOTOR_FREERUN + _MOTOR0_SCANSTATE + _MOTOR0_ONESTEP)); IODataToRegister( ps, ps->RegMotor0Control, (Byte)(_MotorOn + _MotorHQuarterStep + _MotorDirForward)); ps->CloseScanPath( ps ); for (dw=1000; dw; dw--) { if (IODataRegisterFromScanner( ps, ps->RegStatus) & _FLAG_P98_PAPER) { IORegisterDirectToScanner( ps, ps->RegForceStep ); _DODELAY( 1000 / 400 ); } } /*-*/ ps->AsicReg.RD_ModeControl = _ModeScan; IOCmdRegisterToScanner( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = 0; ps->bFastMoveFlag = _FastMove_Film_150; if (ps->DataInf.dwScanFlag & SCANDEF_Negative) { MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_NEG_SCANNINGPOS)/2); } else { MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_POS_SCANNINGPOS)/2); } return; } ps->AsicReg.RD_ModeControl = _ModeScan; IOCmdRegisterToScanner( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = 0; /* SetStartPoint */ dw = ps->wInitialStep + ps->DataInf.crImage.y; /* * CHANGE: when checking out the values from the NT registry * I found that the values are NOT 0 */ switch (ps->DataInf.wPhyDataType) { case COLOR_BW: dw += _BW_ORIGIN; break; case COLOR_256GRAY: dw += _GRAY_ORIGIN; break; default: dw += _COLOR_ORIGIN; break; } if (dw & 0x80000000) dw = 0; /* negative */ if (dw > 180) { if (ps->bSetScanModeFlag & _ScanMode_Mono) { dwBX = 90; /* go via 150 dpi, so 180 / 2 = 90 */ dwDX = (dw -180) % 3; dw = (dw -180) / 3; /* 100 dpi */ } else { dwBX = 45; /* go via 75 dpi, so 180 / 4 = 45 */ dwDX = (dw -180) % 6; dw = (dw -180) / 6; /* 50 dpi */ } dwDX = (dwDX * 3 + 1) / 2 + dwBX; /* * 100/50 dpi lines is 3/2 times of 150/75 * eax = (remainder * 3 + 1) / 2 + 180 / (2 or 4) lines */ ps->bFastMoveFlag = _FastMove_Low_C75_G150; MotorP98GoFullStep( ps, dwDX); if (dw) { DBG( DBG_LOW, "FAST MOVE MODE !!!\n" ); ps->bFastMoveFlag = _FastMove_Fast_C50_G100; MotorP98GoFullStep( ps, dw); } } else { dwBX = ((ps->bSetScanModeFlag & _ScanMode_Mono) ? 2: 4); dw = (dw + dwBX/2) / dwBX; ps->bFastMoveFlag = _FastMove_Low_C75_G150; MotorP98GoFullStep(ps, dw); } } /*............................................................................. * PreMove/EndMove * PreMove is only in ADF and CFB mode * In ADF version, there is a distance gap between Paper flag and Real initial * position and it need premove to real initial position and turn the motor * Inverse and start Fast move to start scan position * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then * fast move * In CIS and CSP although there have not PreMove but there have End move * when paper out there still have several mm need to read, * So it need EndMove 2mm and set Inverse Paper */ static Bool motorP98GotoShadingPosition( pScanData ps ) { int result; DBG( DBG_LOW, "motorP98GotoShadingPosition()\n" ); /* Modify Lamp Back to Home step for Scan twice in short time */ result = motorP98CheckSensorInHome( ps ); if( _OK != result ) return _FALSE; MotorSetConstantMove( ps, 0 ); /* clear scan states */ IOCmdRegisterToScanner( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); ps->Scan.fMotorBackward = _FALSE; /* forward */ ps->bExtraMotorCtrl = 0; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { ps->bFastMoveFlag = _FastMove_Low_C75_G150; MotorP98GoFullStep( ps, 0x40 ); ps->bFastMoveFlag = _FastMove_Middle_C75_G150; MotorP98GoFullStep( ps, ps->Device.dwModelOriginY ); } memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); return _TRUE; } /*............................................................................. * round to the next physical available value */ static void motorP98SetMaxDpiAndLength( pScanData ps, pUShort wLengthY, pUShort wBaseDpi ) { if (ps->DataInf.xyAppDpi.y > 600) *wLengthY = ps->LensInf.rExtentY.wMax * 4 + 200; else *wLengthY = ps->LensInf.rExtentY.wMax * 2 + 200; if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) && (ps->DataInf.xyAppDpi.y <= ps->wMinCmpDpi)) { *wBaseDpi = ps->wMinCmpDpi; } else { if ((ps->DataInf.wPhyDataType < COLOR_TRUE24) && (ps->DataInf.xyAppDpi.y <= 75)) { *wBaseDpi = 75; } else { if (ps->DataInf.xyAppDpi.y <= 150) { *wBaseDpi = 150; } else { if (ps->DataInf.xyAppDpi.y <= 300) { *wBaseDpi = 300; } else { if (ps->DataInf.xyAppDpi.y <= 600) *wBaseDpi = 600; else *wBaseDpi = 1200; } } } } DBG( DBG_LOW, "wBaseDPI = %u, %u\n", *wBaseDpi, ps->wMinCmpDpi ); } /*............................................................................. * */ static void motorP98FillGBColorRunTable( pScanData ps, pUChar pTable, Byte bHi, Byte bLo, UShort wBaseDpi ) { if( ps->Device.f0_8_16 ) { if (wBaseDpi == ps->wMinCmpDpi) { *pTable |= bHi; *(pTable + 1) |= bLo; } else { switch (wBaseDpi) { case 150: *(pTable + 2) |= bHi; *(pTable + 4) |= bLo; break; case 300: *(pTable + 4) |= bHi; *(pTable + 8) |= bLo; break; case 600: *(pTable + 8) |= bHi; *(pTable + 16) |= bLo; break; default: *(pTable + 16) |= bHi; *(pTable + 32) |= bLo; break; } } } else { if (wBaseDpi == ps->wMinCmpDpi) { *pTable |= bHi; *(pTable + 1) |= bLo; } else { switch(wBaseDpi) { case 150: *(pTable + 1) |= bHi; *(pTable + 2) |= bLo; break; case 300: *(pTable + 2) |= bHi; *(pTable + 4) |= bLo; break; case 600: *(pTable + 4) |= bHi; *(pTable + 8) |= bLo; break; default: *(pTable + 8) |= bHi; *(pTable + 16) |= bLo; break; } } } } /*............................................................................. * */ static void motorP98SetupRunTable( pScanData ps ) { UShort wDpi, w, wBaseDpi, wLengthY; pUChar pTable; motorP98SetMaxDpiAndLength( ps, &wLengthY, &wBaseDpi ); /*ClearColorRunTable(); */ memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable ); wDpi = wBaseDpi; w = wLengthY + 1000; pTable = ps->pColorRunTable + (_NUMBER_OF_SCANSTEPS / 4); if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) { for(; w; w--, pTable++) { if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) { wDpi += wBaseDpi; *pTable |= 0x44; motorP98FillGBColorRunTable( ps, pTable, 0x22, 0x11, wBaseDpi ); } } } else { for(; w; w--, pTable++) { if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) { wDpi += wBaseDpi; *pTable = 0x22; } } } ps->dwColorRunIndex = 0; } /*............................................................................. * */ static void motorP98UpdateDataCurrentReadLine( pScanData ps ) { if(!(ps->Scan.bNowScanState & _SCANSTATE_STOP)) { Byte b; if (ps->Scan.bNowScanState >= ps->bCurrentLineCount) b = ps->Scan.bNowScanState - ps->bCurrentLineCount; else b = ps->Scan.bNowScanState + _NUMBER_OF_SCANSTEPS - ps->bCurrentLineCount; if (b < 40) return; } ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE ); IOSetToMotorRegister( ps ); ps->Scan.bModuleState = _MotorAdvancing; } /*............................................................................. * Byte - Scan State Index (0-63) and StopStep bit * pScanState->bStep - Scan State Index (0-63) * pScanState->bStatus - Scanner Status Register value */ static void motorP96GetScanStateAndStatus( pScanData ps, pScanState pScanStep ) { ps->OpenScanPath( ps ); pScanStep->bStep = IOGetScanState(ps, _TRUE); pScanStep->bStep &= _SCANSTATE_MASK; /* org was. ~_ScanStateStop; */ pScanStep->bStatus = IODataFromRegister( ps, ps->RegStatus ); ps->CloseScanPath( ps ); } /*............................................................................. * Capture the image data and average them. */ static Byte motorP96ReadDarkData( pScanData ps ) { Byte bFifoOffset; UShort wSum, w; TimerDef timer; MiscStartTimer( &timer, _SECOND/2); do { bFifoOffset = IODataRegisterFromScanner( ps, ps->RegFifoOffset ); /* stepped 1 block */ if( bFifoOffset ) { /* read data */ IOReadScannerImageData( ps, ps->pScanBuffer1, 512UL); /* 320 = 192 + 128 (128 is size to fetch data) */ for (w = 192, wSum = 0; w < 320; w++) wSum += (UShort)ps->pScanBuffer1[w];/* average data from */ /* offset 192 and size 128*/ return (Byte)(wSum >> 7); /* divided by 128 */ } } while (!MiscCheckTimer(&timer)); return 0xff; /* timed-out */ } /*............................................................................. * move the sensor to a specific Y-position */ static void motorP96PositionYProc( pScanData ps, ULong dwStates ) { ScanState sState; memset( ps->pColorRunTable, 1, dwStates ); #ifdef DEBUG if( dwStates > 800UL ) DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" ); #endif memset( ps->pColorRunTable + dwStates, 0xff, 800UL - dwStates ); IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; /* TurnOnMotorAndSetDirection (); */ if( ps->Scan.fMotorBackward ) { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->IgnorePF | ps->MotorOn)); } else { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->IgnorePF | ps->MotorOn | _MotorDirForward)); } ps->pScanState = ps->pColorRunTable; do { ps->FillRunNewAdrPointer( ps ); } while (!motorCheckMotorPresetLength( ps )); } /*............................................................................. * move the sensor to the scan-start position */ static void motorP96WaitForPositionY( pScanData ps ) { /* scheint OKAY zu sein fuer OP4830 */ #ifdef _A3I_EN #warning "compiling for A3I" ULong dw; ScanState sState; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward; ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = ps->IgnorePF; if( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) dw = 30UL; else dw = 46UL; dw = (dw + ps->DataInf.crImage.y) * 4 / 3; if( ps->DataInf.wPhyDataType == COLOR_TRUE24 ) dw += 99; /* dwStepsForColor; */ else if( ps->DataInf.wPhyDataType == COLOR_256GRAY ) dw += 99; /* dwStepsForGray; */ else dw += 99; /* dwStepsForBW; */ if( dw >= 130UL ) { dw -= 100UL; dw <<= 1; /* GoFullStep (dw); */ memset( ps->pColorRunTable, 1, dw ); memset( ps->pColorRunTable + dw, 0xff, ps->BufferForColorRunTable - dw ); IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; /* AdjustMotorTime () */ IOCmdRegisterToScanner( ps, ps->RegLineControl, 31 ); /* SetRunHalfStep () */ if( ps->Scan.fMotorBackward ) IOCmdRegisterToScanner( ps, ps->RegMotorControl, _Motor1FullStep | ps->IgnorePF | ps->MotorOn ); else IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->IgnorePF | ps->MotorOn | _MotorDirForward ); ps->pScanState = ps->pColorRunTable; do { ps->FillRunNewAdrPointer( ps ); } while (!motorCheckMotorPresetLength(ps)); /* RestoreMotorTime () */ IOCmdRegisterToScanner( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); dw = 100UL; } if( ps->DataInf.wPhyDataType != COLOR_TRUE24 ) dw += 20; motorP96PositionYProc( ps, dw ); #else ULong dw; ScanState sState; TimerDef timer; MiscStartTimer( &timer, _SECOND / 4); while (!MiscCheckTimer( &timer )); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward; ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = ps->IgnorePF; if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) || (ps->DataInf.xyAppDpi.y <= 300)) { dw = 6UL; } else { if (ps->DataInf.xyAppDpi.y <= 600) { /* 50 is from 6/300 */ dw = (ULong)ps->DataInf.xyAppDpi.y / 50UL + 3UL; } else dw = 15; /* 6UL * 600UL / 300UL + 3; */ } dw += ps->DataInf.crImage.y; if (dw >= 180UL) { dw -= 180UL; /* GoFullStep (ps, dw);----------------------------------------------*/ memset( ps->pColorRunTable, 1, dw ); #ifdef DEBUG if( dw > 8000UL ) DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" ); #endif memset( ps->pColorRunTable + dw, 0xff, 8000UL - dw ); IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; /* SetRunFullStep (ps) */ if( ps->Scan.fMotorBackward ) { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn)); } else { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn | _MotorDirForward)); } ps->pScanState = ps->pColorRunTable; do { ps->FillRunNewAdrPointer (ps); } while (!motorCheckMotorPresetLength(ps)); /*-------------------------------------------------------------------*/ dw = 180UL; } if (ps->DataInf.wPhyDataType != COLOR_TRUE24) dw = dw * 2 + 16; else dw *= 2; motorP96PositionYProc( ps, dw ); #endif } /*............................................................................. * Position Scan Module to specified line number (Forward or Backward & wait * for paper flag ON) */ static void motorP96ConstantMoveProc1( pScanData ps, ULong dwLines ) { Byte bRemainder, bLastState; UShort wQuotient; ULong dwDelayMaxTime; ScanState StateStatus; TimerDef timer; Bool fTimeout = _FALSE; /* state cycles */ wQuotient = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS); bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS); /* 3.3 ms per line */ #ifdef _A3I_EN dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2; #else dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 20; #endif /* step every time */ MotorSetConstantMove( ps, 1 ); ps->OpenScanPath( ps ); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); ps->Asic96Reg.RD_MotorControl = ps->MotorFreeRun | ps->MotorOn | _MotorDirForward; IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); ps->CloseScanPath( ps ); bLastState = 0; MiscStartTimer( &timer, dwDelayMaxTime ); do { /* GetStatusAndScanStateAddr () */ motorP96GetScanStateAndStatus( ps, &StateStatus ); if (StateStatus.bStatus & _FLAG_P96_PAPER ) { if (wQuotient) { if (StateStatus.bStep != bLastState) { bLastState = StateStatus.bStep; if (!bLastState) wQuotient--; } } else if (StateStatus.bStep >= bRemainder) break; } else break; } while (!(fTimeout = MiscCheckTimer( &timer ))); if (!fTimeout) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); } } /*............................................................................. * PreMove/EndMove * PreMove is only in ADF and CFB mode * In ADF version, there is a distance gap between Paper flag and Real initial * position and it need premove to real initial position and turn the motor * Inverse and start Fast move to start scan position * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then * fast move * In CIS and CSP although there have not PreMove but there have End move * when paper out there still have several mm need to read, * So it need EndMove 2mm and set Inverse Paper */ static Bool motorP96GotoShadingPosition( pScanData ps ) { DBG( DBG_LOW, "motorP96GotoShadingPosition()\n" ); MotorSetConstantMove( ps, 0 ); /* clear scan states */ ps->Scan.fMotorBackward = _FALSE; /* forward */ ps->bExtraMotorCtrl = ps->IgnorePF; MotorP96ConstantMoveProc( ps, 15 * 12 ); /* forward 180 lines */ if (IODataRegisterFromScanner(ps, ps->RegStatus) & _FLAG_P96_PAPER ) { ps->Asic96Reg.RD_MotorControl = 0; IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); DBG( DBG_LOW, "motorP96GotoShadingPosition() failed\n" ); return _FALSE; } ps->Scan.fMotorBackward = _TRUE; /* backward */ ps->bExtraMotorCtrl = 0; /* no extra action for motor */ /* backward a few thousand lines to touch sensor */ MotorP96ConstantMoveProc( ps, ps->BackwardSteps ); _DODELAY( 250 ); IOCmdRegisterToScanner( ps, ps->RegModelControl, (Byte)(ps->AsicReg.RD_ModelControl | _ModelInvertPF)); ps->Scan.fMotorBackward = _FALSE; /* forward */ motorP96ConstantMoveProc1( ps, 14 * 12 * 2); /* ahead 336 lines */ if( MODEL_OP_A3I == ps->sCaps.Model ) { motorP96PositionYProc( ps, 80 ); } else { /* forward 24 + pScanData->wOverBlue lines */ if (!ps->fColorMoreRedFlag) motorP96PositionYProc( ps, ps->wOverBlue + 12 * 2); } if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = ps->IgnorePF; MotorP96ConstantMoveProc( ps, 1200 ); } IOCmdRegisterToScanner( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); return _TRUE; } /*............................................................................. * */ static void motorP96FillHalfStepTable( pScanData ps ) { #ifdef _A3I_EN if ( ps->Scan.bModuleState == _MotorInStopState ) { /* clear the table and get the step value */ memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2]; } /* the fastest stepping */ if( ps->bMotorSpeedData & 1 ) { memset( a_bHalfStepTable, ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0), _NUMBER_OF_SCANSTEPS ); } else { pUChar pbHalfStepTbl; Byte bHalfSteps; pUShort pwMoveStep; DataType Data; bHalfSteps = ps->bMotorSpeedData / 2; pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount]; pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount]; if( ps->DataInf.wAppDataType == COLOR_TRUE24) Data.dwValue = _NUMBER_OF_SCANSTEPS - 1; else Data.dwValue = _NUMBER_OF_SCANSTEPS; /* FillDataToHalfStepTable */ for(; Data.dwValue; Data.dwValue-- ) { if( *pwMoveStep ) { /* need to exposure */ if( Data.bValue >= bHalfSteps ) { pUChar pb = pbHalfStepTbl + bHalfSteps; /* AdjustHalfStepStart */ if( ps->DataInf.wAppDataType == COLOR_TRUE24 ) { if (bHalfSteps >= 2) pb -= (bHalfSteps - 1); } if( pb >= pbEndHalfStepTable ) pb -= _NUMBER_OF_SCANSTEPS; if( wP96BaseDpi <= ps->PhysicalDpi && *pwMoveStep != 2 ) *pb = 1; pb += bHalfSteps; if( pb >= pbEndHalfStepTable ) pb -= _NUMBER_OF_SCANSTEPS; *pb = 1; } else *pwMoveStep = 0; /* idle state */ } if( ++pwMoveStep >= pwEndMoveStepTable ) { pwMoveStep = a_wMoveStepTable; pbHalfStepTbl = a_bHalfStepTable; } else pbHalfStepTbl++; } } #else #ifdef DEBUG if( 0 == wP96BaseDpi ) DBG( DBG_HIGH, "!!!! WARNING - motorP96FillHalfStepTable(), " "wP96BaseDpi == 0 !!!!\n" ); #endif if ( ps->Scan.bModuleState == _MotorInStopState ) { /* clear the table and get the step value */ memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2]; } /* the fastest stepping */ if( ps->bMotorSpeedData & 1 ) { memset( a_bHalfStepTable, ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0), _NUMBER_OF_SCANSTEPS ); } else { pUChar pbHalfStepTbl, pbHalfStepContent; pUShort pwMoveStep; DataType Data; pbHalfStepContent = a_pbHalfStepTables[ps->bMotorSpeedData / 2 - 1]; pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount]; pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount]; if (ps->DataInf.wAppDataType == COLOR_TRUE24) Data.dwValue = _NUMBER_OF_SCANSTEPS - 1; else Data.dwValue = _NUMBER_OF_SCANSTEPS; /* FillDataToHalfStepTable */ for (; Data.dwValue; Data.dwValue--) { if (*pwMoveStep) { /* need to exposure */ if (Data.bValue >= *pbHalfStepContent) { pUChar pb = pbHalfStepTbl + *pbHalfStepContent; if (pb >= pbEndHalfStepTable) pb -= _NUMBER_OF_SCANSTEPS; /* JudgeStep1 () */ if ((wP96BaseDpi != 600) && (*pwMoveStep != 2)) { if (ps->Scan.bModuleState != _MotorInStopState) { *pb = 1; } else { if (ps->bMotorStepTableNo) { ps->bMotorStepTableNo--; *pb = 1; } } } pb += *pbHalfStepContent; if (pb >= pbEndHalfStepTable) pb -= _NUMBER_OF_SCANSTEPS; /* JudgeStep2 () */ if (ps->Scan.bModuleState == _MotorInStopState) { if (ps->bMotorStepTableNo) { ps->bMotorStepTableNo--; *pb = 1; } } else { *pb = 1; } pbHalfStepContent++; } else { *pwMoveStep = 0; /* idle state */ } } if (++pwMoveStep >= pwEndMoveStepTable) { pwMoveStep = a_wMoveStepTable; pbHalfStepTbl = a_bHalfStepTable; } else { pbHalfStepTbl++; } } } #endif } /*............................................................................. * */ static void motorP96FillDataToColorTable( pScanData ps, Byte bIndex, ULong dwSteps) { Byte bColor, bColors; pUChar pb, pb1; pUShort pw; DataType Data; for (pb = &a_bColorByteTable[bIndex], pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps--) { if (*pw) { /* valid state */ if( *pw >= ps->BufferForColorRunTable ) { DBG( DBG_LOW, "*pw = %u > %u !!\n", *pw, ps->BufferForColorRunTable ); } else { bColor = ps->pColorRunTable [*pw]; /* get the colors */ bColors = a_bColorsSum [bColor & 7];/* number of colors */ if (bColors) { /* need to read data */ if (dwSteps >= bColors) { /* enough room */ /* separate the colors to byte */ pb1 = pb; if (bColor & ps->b1stColor) { *pb1 = ps->b1stColorByte; if (++pb1 >= pbEndColorByteTable) pb1 = a_bColorByteTable; } if (bColor & ps->b2ndColor) { *pb1 = ps->b2ndColorByte; if (++pb1 >= pbEndColorByteTable) pb1 = a_bColorByteTable; } if (bColor & ps->b3rdColor) *pb1 = ps->b3rdColorByte; } else *pw = 0; } } } if (++pw >= pwEndMoveStepTable) { pw = a_wMoveStepTable; pb = a_bColorByteTable; } else pb++; } /* ps->bOldSpeed = ps->bMotorRunStatus; non functional */ /* ToCondense, CondenseColorByteTable */ for (dwSteps = _SCANSTATE_BYTES, pw = (pUShort)a_bColorByteTable, pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pw++, pb++) { Data.wValue = *pw & 0x0303; *pb = Data.wOverlap.b1st | (Data.wOverlap.b2nd << 4); } /* ToCondenseMotor */ for (dwSteps = _SCANSTATE_BYTES, pb1 = a_bHalfStepTable, pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pb1++, pb++) { if (*pb1++) *pb |= 4; if (*pb1) *pb |= 0x40; } } /*............................................................................. * */ static void motorP96FillBackColorDataTable( pScanData ps ) { Byte bIndex; ULong dw; if ((ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >= _NUMBER_OF_SCANSTEPS){ bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1 - _NUMBER_OF_SCANSTEPS; } else { bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1; } dw = _NUMBER_OF_SCANSTEPS - ps->bNewCurrentLineCountGap; motorP96FillDataToColorTable( ps, bIndex, dw ); } /*............................................................................. * i/p: * pScanStep = pScanData->pColorRunTable if forward, a_bScanStateTable if backward * dwState = how many states is requested to process * NOTE: * The content of pScanStep contain: * 0: Idle state * 0xff: End mark * others: The motor speed value */ static void motorP96FillBackLoop( pScanData ps, pUChar pScanStep, ULong dwStates ) { for (; dwStates; dwStates--) { if (*pScanStep == 0xff) break; /* end of states */ if (*pScanStep) { if (*pScanStep == 1) { /* speed == 1, this state has to step */ if (ps->dwScanStateCount & 1) ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x40; else ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x04; } *pScanStep -= 1; /* speed decrease by 1 */ if (!(*pScanStep)) pScanStep++; /* state processed */ } else pScanStep++; /* skip this state */ if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS) ps->dwScanStateCount = 0; /* reset to begin */ } if (*pScanStep != 0xff) ps->fFullLength = _FALSE; else ps->fFullLength = _TRUE; IOSetToMotorStepCount( ps ); /* put all scan states to ASIC */ } /*............................................................................. * 1) Clear scan states * 2) Adjust the new scan state */ static void motorP96FillRunNewAdrPointer( pScanData ps ) { ScanState sState; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES); IOGetCurrentStateCount( ps, &sState ); if (sState.bStep < ps->bOldStateCount ) sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can */ /* holds 64 step, then reset to */ /* 0, so if less than means over*/ /* the table) */ sState.bStep -= ps->bOldStateCount; /* how many states passed */ ps->pScanState += sState.bStep; /* * if current state != no stepped or stepped a cycle, fill the table with * 1 in NOT STEPPED length. (1 means to this state has to be processing). */ if (sState.bStep && sState.bStep != (_NUMBER_OF_SCANSTEPS - 1)) memset( ps->pScanState, 1, _NUMBER_OF_SCANSTEPS - sState.bStep - 1 ); IOGetCurrentStateCount( ps, &sState); ps->bOldStateCount = sState.bStep; /* update current state */ ps->dwScanStateCount = (ULong)((sState.bStep + 1) & (_NUMBER_OF_SCANSTEPS - 1)); /* fill begin at next step */ motorP96FillBackLoop( ps, ps->pScanState, (_NUMBER_OF_SCANSTEPS - 1)); } /*............................................................................. * */ static void motorP96SetupRunTable( pScanData ps ) { Short siSum; UShort wLoop; UShort wLengthY; DataPointer p; DBG( DBG_LOW, "motorP96SetupRunTable()\n" ); /* SetMaxDpiAndLength (ps) */ #ifdef _A3I_EN if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi ) { wLengthY = 6800 * 2; wP96BaseDpi = ps->PhysicalDpi *2; } else { wLengthY = 6800; wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1; } #else if( ps->DataInf.xyPhyDpi.y > (ps->LensInf.rDpiY.wPhyMax / 2)) { wLengthY = ps->LensInf.rExtentY.wMax << 1; wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax; } else { wLengthY = ps->LensInf.rExtentY.wMax; wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1; } #endif DBG( DBG_LOW, "wLengthY = %u, wP96BaseDpi = %u\n", wLengthY, wP96BaseDpi ); /* ClearColorRunTable (ps) */ memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable ); /*wLengthY + 0x60 ); */ p.pb = ps->pColorRunTable + _SCANSTATE_BYTES; #ifdef _A3I_EN wLoop = wLengthY + 200; #else wLoop = wLengthY + 0x20; #endif siSum = (Short)wP96BaseDpi; if (ps->DataInf.wPhyDataType != COLOR_TRUE24) { for (; wLoop; wLoop--, p.pb++) { if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) { siSum += (Short)wP96BaseDpi; *p.pb = _COLORRUNTABLE_GREEN; } } #ifdef _A3I_EN memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY, 0x77, 0x100 ); #endif } else { /* CalColorRunTable */ DataType Data; if (ps->fSonyCCD) { if((ps->sCaps.Model == MODEL_OP_12000P) || (ps->sCaps.Model == MODEL_OP_A3I)) { Data.wValue = (_COLORRUNTABLE_RED << 8) | _COLORRUNTABLE_BLUE; } else { Data.wValue = (_COLORRUNTABLE_GREEN << 8) | _COLORRUNTABLE_BLUE; } } else { Data.wValue = (_COLORRUNTABLE_BLUE << 8) | _COLORRUNTABLE_GREEN; } for (; wLoop; wLoop--, p.pb++) { if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) { siSum += (Short)wP96BaseDpi; if((ps->sCaps.Model == MODEL_OP_12000P)|| (ps->sCaps.Model == MODEL_OP_A3I)) { *p.pb |= _COLORRUNTABLE_GREEN; } else { *p.pb |= _COLORRUNTABLE_RED; } /* Sony:Green,Toshiba:Blue */ *(p.pb + 8) |= Data.wOverlap.b2nd; *(p.pb + 16) |= Data.wOverlap.b1st; } } #ifdef _A3I_EN memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY, 0x77, 0x100 ); #endif if (ps->DataInf.xyPhyDpi.y < 100) { Byte bColor; /* CheckColorTable () */ if (ps->fSonyCCD) Data.wValue = 0xdd22; else Data.wValue = 0xbb44; for (wLoop = wLengthY - _SCANSTATE_BYTES, p.pb = ps->pColorRunTable + _SCANSTATE_BYTES; wLoop; wLoop--, p.pb++) { bColor = 0; switch (a_bColorsSum[*p.pb & 0x0f]) { case 3: if (*(p.pb + 2)) bColor = 1; // fall through case 2: if (*(p.pb + 1)) bColor++; if (bColor == 2) { *p.pb &= ~_COLORRUNTABLE_RED; *(p.pb - 2) = _COLORRUNTABLE_RED; } if (bColor) { if (*p.pb & ps->RedDataReady) { *p.pb &= ~_COLORRUNTABLE_RED; *(p.pb - 1) = _COLORRUNTABLE_RED; } else { *p.pb &= Data.wOverlap.b2nd; *(p.pb - 1) = Data.wOverlap.b1st; } } } } } } } /*............................................................................. * */ static void motorP96UpdateDataCurrentReadLine( pScanData ps ) { ScanState State1, State2; TimerDef timer; IOGetCurrentStateCount( ps, &State1 ); IOGetCurrentStateCount( ps, &State2 ); if (State1.bStatus == State2.bStatus) { if (!(State2.bStatus & _SCANSTATE_STOP)) { /* motor still running */ if (State2.bStep < ps->bCurrentLineCount) { State2.bStep = State2.bStep + _NUMBER_OF_SCANSTEPS - ps->bCurrentLineCount; } else State2.bStep -= ps->bCurrentLineCount; if (State2.bStep >= (_NUMBER_OF_SCANSTEPS - 3)) { MiscStartTimer( &timer, _SECOND ); do { State2.bStatus = IOGetScanState( ps, _FALSE ); } while (!(State2.bStatus & _SCANSTATE_STOP) && !MiscCheckTimer( &timer )); } else if (State2.bStep < 40) return; } #ifdef _A3I_EN if( ps->bFifoCount >= 140) { #else if( ps->bFifoCount >= 20) { #endif if( 1 == ps->bCurrentSpeed ) { ps->bCurrentSpeed *= 2; } else { if( COLOR_TRUE24 == ps->DataInf.wPhyDataType ) ps->bCurrentSpeed += 4; else ps->bCurrentSpeed += 2; } MotorP96AdjustCurrentSpeed( ps, ps->bCurrentSpeed ); } /* * when using the full-step speed on 600 dpi models, then set * the motor into half-step mode, to avoid that the scanner hits * the back of its bed */ /* HEINER:A3I */ #if 1 if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) { if( ps->Asic96Reg.RD_MotorControl & ps->FullStep ) { ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep; IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); } } #endif ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE ); IOSetToMotorRegister( ps); } } /*............................................................................. * 1) Save the current scan state * 2) Set the motor direction */ static void motorGoHalfStep1( pScanData ps ) { ScanState sState; IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; motorSetRunPositionRegister(ps); ps->pScanState = a_bScanStateTable; if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->FillRunNewAdrPointer( ps ); while (!motorCheckMotorPresetLength(ps)) motorP98FillRunNewAdrPointer1( ps ); } else { while (!motorCheckMotorPresetLength( ps )) ps->FillRunNewAdrPointer( ps ); } } /*............................................................................. * when losing data, we use this function to go back some lines and read them * again... */ static void motorP96WaitBack( pScanData ps ) { DataPointer p; DataType Data; ULong dw; UShort w; UShort wStayMaxStep; /* FindMaxMoveStepIndex () */ p.pw = a_wMoveStepTable; for( Data.dwValue = _NUMBER_OF_SCANSTEPS, wStayMaxStep = 1; Data.dwValue; Data.dwValue--, p.pw++ ) if( *p.pw > wStayMaxStep ) wStayMaxStep = *p.pw; /* save the largest step number */ if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi ) wStayMaxStep -= 40; else wStayMaxStep -= 20; IORegisterDirectToScanner( ps, ps->RegInitDataFifo ); memset( a_bScanStateTable, 1, _P96_BACKMOVES ); memset(&a_bScanStateTable[_P96_BACKMOVES], 0xff, 250 - _P96_BACKMOVES ); ps->Scan.fMotorBackward = _TRUE; motorGoHalfStep1( ps ); /* backward 130 lines */ _DODELAY(200); /* let the motor stable */ if( ps->DataInf.xyPhyDpi.y <= ps->PhysicalDpi ) { if( ps->DataInf.wPhyDataType == COLOR_TRUE24 ) { dw = _P96_FORWARDMOVES - 1; } else { dw = _P96_FORWARDMOVES - 2; } } else { dw = _P96_FORWARDMOVES; } memset( a_bScanStateTable, 1, dw ); memset(&a_bScanStateTable[dw], 0xff, 250 - dw ); ps->Scan.fMotorBackward = _FALSE; motorGoHalfStep1( ps ); /* move forward */ /* GetNowStepTable () */ ps->bCurrentLineCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK; ps->bNewCurrentLineCountGap = 0; /* ClearColorByteTable () */ memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS ); /* ClearHalfStepTable () */ memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); /* FillWaitMoveStepTable () */ p.pw = &a_wMoveStepTable[((ps->bCurrentLineCount + 1) & 0x3f)]; *p.pw = 1; p.pw++; for(w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData, dw = 60;dw;dw--) { if( p.pw >= pwEndMoveStepTable ) /* make sure pointer in range */ p.pw = a_wMoveStepTable; if (--Data.bValue) *p.pw = 0; /* don't step */ else { Data.bValue = ps->bMotorSpeedData; /* speed value */ *p.pw = w; /* the ptr to pColorRunTable */ w++; /* pointer++ */ } p.pw++; /* to next entry */ } motorP96FillHalfStepTable( ps ); motorP96FillBackColorDataTable( ps ); } /*............................................................................. * when losing data, we use this function to go back some lines and read them * again... */ static void motorP98WaitBack( pScanData ps ) { DataPointer p; DataType Data; ULong dw; UShort w; UShort wStayMaxStep; UShort back, forward; p.pw = &a_wMoveStepTable[ps->bCurrentLineCount]; if (0 == *p.pw) { for (w = _NUMBER_OF_SCANSTEPS; w && !*p.pw; w--) { p.pw--; if (p.pw < a_wMoveStepTable) p.pw = &a_wMoveStepTable[_NUMBER_OF_SCANSTEPS - 1]; } wStayMaxStep = *p.pw + 1; } else { wStayMaxStep = *p.pw; /* save the largest step number */ } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { forward = _P98_FORWARDMOVES; back = _P98_BACKMOVES; } else { forward = _P96_FORWARDMOVES; back = _P96_BACKMOVES; } /* * Off to avoid the problem of block data re-read/lost */ memset( a_bScanStateTable, 1, back ); memset( &a_bScanStateTable[back], 0xff, (_SCANSTATE_TABLE_SIZE - back)); ps->Scan.fMotorBackward = _TRUE; motorGoHalfStep1( ps ); _DODELAY(200); /* let the motor stable */ memset(a_bScanStateTable, 1, forward ); memset(&a_bScanStateTable[forward], 0xff, (_SCANSTATE_TABLE_SIZE-forward)); ps->Scan.fMotorBackward = _FALSE; motorGoHalfStep1( ps ); ps->bNewCurrentLineCountGap = 0; memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS ); memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); ps->bCurrentLineCount = (ps->bCurrentLineCount + 1) & 0x3f; p.pw = &a_wMoveStepTable[ps->bCurrentLineCount]; for (w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData, dw = _NUMBER_OF_SCANSTEPS; dw; dw--) { if (--Data.bValue) { *p.pw = 0; /* don't step */ } else { /* speed value */ Data.bValue = ps->bMotorSpeedData; *p.pw = w; /* the pointer to pColorRunTable*/ w++; /* pointer++ */ } /* make sure pointer in range */ if (++p.pw >= pwEndMoveStepTable) p.pw = a_wMoveStepTable; } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { motorP98FillHalfStepTable( ps ); motorP98FillBackColorDataTable( ps ); } else { motorP96FillHalfStepTable( ps ); motorP96FillBackColorDataTable( ps ); } } /*............................................................................. * */ static void motorFillMoveStepTable( pScanData ps, UShort wIndex, Byte bStep, pUShort pw ) { UShort w; Byte b; if (++pw >= pwEndMoveStepTable ) pw = a_wMoveStepTable; wIndex++; b = ps->bMotorSpeedData; for (w = _NUMBER_OF_SCANSTEPS - bStep; w; w--) { if (b == 1) { b = ps->bMotorSpeedData; *pw = wIndex; wIndex++; } else { b--; *pw = 0; } if (++pw >= pwEndMoveStepTable) pw = a_wMoveStepTable; } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) motorP98FillHalfStepTable( ps ); else motorP96FillHalfStepTable( ps ); if ((ps->bCurrentLineCount + 1) >= _NUMBER_OF_SCANSTEPS) { b = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS; } else { b = ps->bCurrentLineCount + 1; } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) motorP98FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1); else motorP96FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1); } /*............................................................................. * */ static void noMotorRunStatusStop( pScanData ps, Byte bScanState ) { Byte b, b1, bCur; pUShort pw; pByte pb; UShort w; ps->bCurrentLineCount = (bScanState & _SCANSTATE_MASK); ps->Scan.fRefreshState = _FALSE; IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); bCur = ps->bCurrentLineCount; pw = &a_wMoveStepTable[bCur]; pb = ps->pColorRunTable; b = 0; b1 = 0; w = _NUMBER_OF_SCANSTEPS; if (*pw) { b = a_bColorsSum[pb [*pw] >> 4]; if (b) { motorClearColorByteTableLoop0( ps, b ); ps->bNewCurrentLineCountGap = b; motorFillMoveStepTable( ps, *pw, 1, pw ); return; } b1++; bCur--; if (--pw < a_wMoveStepTable) { pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1]; bCur = _NUMBER_OF_SCANSTEPS - 1; } } for(; w; w--) { if (*pw) { if (*pw < _SCANSTATE_BYTES) { b = 0; break; } else if ((b = a_bColorsSum [pb [*pw] >> 4])) break; } b1++; bCur--; if (--pw < a_wMoveStepTable) { pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1]; bCur = _NUMBER_OF_SCANSTEPS - 1; } } if (b1 == _NUMBER_OF_SCANSTEPS) { ps->bNewCurrentLineCountGap = 0; ps->bNewGap = 0; } else { ps->bNewCurrentLineCountGap = b1; ps->bNewGap = b; } motorClearColorByteTableLoop1( ps ); motorFillMoveStepTable( ps, *pw, 0, pw); } /*............................................................................. * */ static void motorP96SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState ) { #if 0 PUCHAR pb; Byte bScanState; #endif Byte bState, bData; UShort wMoveStep; pUShort pw; ULong dw; TimerDef timer; if( fSetRunState ) ps->Scan.bModuleState = _MotorInNormalState; ps->bMotorSpeedData = bSpeed; if( ps->bMoveDataOutFlag == _DataAfterRefreshState) { ps->bMoveDataOutFlag = _DataInNormalState; MiscStartTimer( &timer, (_SECOND /2)); while (!MiscCheckTimer(&timer)) { if ((bState = IOGetScanState( ps, _FALSE)) & _SCANSTATE_STOP) { ps->bCurrentLineCount = bState & ~_SCANSTATE_STOP; motorP96WaitBack( ps ); return; } } } bState = IOGetScanState( ps, _FALSE ); if((ps->Scan.bModuleState != _MotorInStopState) || !(bState & _SCANSTATE_STOP)) { /* Try to find the available step for all rest steps. * 1) if current step is valid (with data request), fill all steps * after it * 2) if current step is NULL (for delay purpose), backward search the * valid entry, then fill all steps after it * 3) if no step is valid, fill all entries */ Byte bColors = 0; UShort w; /* NoMotorRunStatusStop () */ ps->bCurrentLineCount = (bState &= _SCANSTATE_MASK); ps->Scan.fRefreshState = _TRUE; IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); pw = &a_wMoveStepTable[bState]; bData = 0; bState = ps->bCurrentLineCount; dw = _NUMBER_OF_SCANSTEPS; if( (wMoveStep = *pw) ) { bColors = a_bColorsSum[ ps->pColorRunTable[*pw] / 16]; if( bColors ) { motorClearColorByteTableLoop0( ps, bColors ); ps->bNewCurrentLineCountGap = bColors; bColors = 1; goto FillMoveStepTable; } else { bData++; dw--; if( --pw < a_wMoveStepTable ) { pw = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1; bState = _NUMBER_OF_SCANSTEPS - 1; } else bState--; } } /* FindNextStep */ while( dw-- ) { if( (wMoveStep = *pw) ) { if (wMoveStep < (_NUMBER_OF_SCANSTEPS / 2)) { bColors = 0; break; } if((bColors = a_bColorsSum [ps->pColorRunTable[wMoveStep] / 16])) break; } bData++; if( --pw < a_wMoveStepTable ) { pw = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1; bState = _NUMBER_OF_SCANSTEPS - 1; } else bState--; } if (bData == _NUMBER_OF_SCANSTEPS ) bData = bColors = 0; ps->bNewCurrentLineCountGap = bData; ps->bNewGap = bColors; motorClearColorByteTableLoop1( ps ); bColors = 0; /* use pw (new pointer) and new speed to recreate MoveStepTable * wMoveStep = Index number from a_wMoveStepTable ([esi]) * bColors = number of steps should be reserved * pw = where to fill */ FillMoveStepTable: motorP96GetStartStopGap( ps, _TRUE ); if( !ps->bMotorStepTableNo ) ps->bMotorStepTableNo = 1; if( ps->bMotorStepTableNo != 0xff && ps->IO.portMode == _PORT_SPP && ps->DataInf.xyPhyDpi.y <= 200) { ps->bMotorStepTableNo++; } if (++pw >= pwEndMoveStepTable) pw = a_wMoveStepTable; for( dw = _NUMBER_OF_SCANSTEPS - bColors, wMoveStep++, bData = ps->bMotorSpeedData; dw; dw-- ) { if( bData == 1 ) { bData = ps->bMotorSpeedData; if( ps->bMotorStepTableNo ) { ps->bMotorStepTableNo--; w = wMoveStep; wMoveStep++; } else { bData--; w = 0; } } else { bData--; w = 0; } *pw = w; if (++pw >= pwEndMoveStepTable) pw = a_wMoveStepTable; } motorP96FillHalfStepTable( ps ); /* FillColorBytesTable */ if((ps->bCurrentLineCount + 1) < _NUMBER_OF_SCANSTEPS ) bState = ps->bCurrentLineCount + 1; else bState = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS; motorP96FillDataToColorTable( ps, bState, _NUMBER_OF_SCANSTEPS - 1); } } /*............................................................................. * */ static void motorP98SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState ) { static Byte lastFifoState = 0; Bool overflow; Byte bOld1ScanState, bData; if( fSetRunState ) ps->Scan.bModuleState = _MotorInNormalState; ps->bMotorSpeedData = bSpeed; overflow = _FALSE; if( _ASIC_IS_98001 != ps->sCaps.AsicID ) { ps->bMoveDataOutFlag = _DataInNormalState; bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset ); if((lastFifoState > _P96_FIFOOVERFLOWTHRESH) && (bData < lastFifoState)) { DBG( DBG_HIGH, "FIFO OVERFLOW, losing data !!\n" ); overflow = _TRUE; } lastFifoState = bData; } bOld1ScanState = IOGetScanState( ps, _FALSE ); if(!(bOld1ScanState & _SCANSTATE_STOP) && !overflow) noMotorRunStatusStop( ps, bOld1ScanState ); else { ps->bCurrentLineCount = (bOld1ScanState & 0x3f); ps->Scan.bModuleState = _MotorGoBackward; motorP98WaitBack( ps ); if( overflow ) lastFifoState = 0; if( _ASIC_IS_98001 != ps->sCaps.AsicID ) ps->bMoveDataOutFlag = _DataFromStopState; } } /*............................................................................. * */ static void motorP98003ModuleFreeRun( pScanData ps, ULong steps ) { IODataToRegister( ps, ps->RegMotorFreeRunCount1, (_HIBYTE(steps))); IODataToRegister( ps, ps->RegMotorFreeRunCount0, (_LOBYTE(steps))); IORegisterToScanner( ps, ps->RegMotorFreeRunTrigger ); } /*............................................................................. * */ static void motorP98003ModuleToHome( pScanData ps ) { if(!(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) { IODataToRegister( ps, ps->RegMotor0Control, (Byte)(ps->AsicReg.RD_Motor0Control|_MotorDirForward)); MotorP98003PositionYProc( ps, 40 ); MotorP98003BackToHomeSensor( ps ); _DODELAY( 250 ); } } /*............................................................................. * */ static void motorP98003DownloadNullScanStates( pScanData ps ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IODownloadScanStates( ps ); } /*............................................................................. * */ static void motorP98003Force16Steps( pScanData ps ) { ULong dw; IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP); IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR ); for(dw = 16; dw; dw--) { IORegisterToScanner( ps, ps->RegForceStep ); _DODELAY( 10 ); } IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); } /*............................................................................. * */ static void motorP98003WaitForPositionY( pScanData ps ) { Byte bXStep; ULong dwBeginY; dwBeginY = (ULong)ps->DataInf.crImage.y * 4 + ps->Scan.dwScanOrigin; if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) { if( ps->Device.f0_8_16 ) dwBeginY += 16; else dwBeginY += 8; } bXStep = (Byte)((ps->DataInf.wPhyDataType <= COLOR_256GRAY) ? ps->Device.XStepMono : ps->Device.XStepColor); if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) bXStep = 8; motorP98003Force16Steps( ps); dwBeginY -= 16; if (dwBeginY > (_RFT_SCANNING_ORG + _P98003_YOFFSET) && bXStep < ps->AsicReg.RD_XStepTime) { IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower ); _DODELAY( 12 ); IODataToRegister( ps, ps->RegXStepTime, bXStep); IODataToRegister( ps, ps->RegExtendedXStep, 0 ); IODataToRegister( ps, ps->RegScanControl1, (UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); MotorP98003PositionYProc( ps, dwBeginY - 64 ); dwBeginY = 64; } IODataToRegister( ps, ps->RegFifoFullLength0, _LOBYTE(ps->AsicReg.RD_BufFullSize)); IODataToRegister( ps, ps->RegFifoFullLength1, _HIBYTE(ps->AsicReg.RD_BufFullSize)); IODataToRegister( ps, ps->RegFifoFullLength2, _LOBYTE(_HIWORD(ps->AsicReg.RD_BufFullSize))); IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType); _DODELAY( 12 ); if(!ps->Device.f2003 || (ps->Shade.bIntermediate & _ScanMode_AverageOut) || ( ps->DataInf.xyAppDpi.y <= 75 && ps->DataInf.wPhyDataType <= COLOR_256GRAY)) { IODataToRegister( ps, ps->RegMotorDriverType, (Byte)(ps->Scan.motorPower & (_MOTORR_MASK | _MOTORR_STRONG))); } else { IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType ); } IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime ); IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime ); IODataToRegister( ps, ps->RegScanControl1, (Byte)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) { TimerDef timer; motorP98003ModuleFreeRun( ps, dwBeginY ); _DODELAY( 15 ); MiscStartTimer( &timer, (_SECOND * 20)); while(( IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) && !MiscCheckTimer(&timer)); IODataToRegister( ps, ps->RegModeControl, _ModeScan ); } else { MotorP98003PositionYProc( ps, dwBeginY ); IORegisterToScanner( ps, ps->RegRefreshScanState ); } } /*............................................................................. * move the sensor to the appropriate shading position */ static Bool motorP98003GotoShadingPosition( pScanData ps ) { motorP98003ModuleToHome( ps ); /* position to somewhere under the transparency adapter */ if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { MotorP98003ForceToLeaveHomePos( ps ); motorP98003DownloadNullScanStates( ps ); IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); IODataToRegister( ps, ps->RegModeControl, _ModeScan); IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR ); IODataToRegister( ps, ps->RegXStepTime, 6); IODataToRegister( ps, ps->RegExtendedXStep, 0); IODataToRegister( ps, ps->RegScanControl1, _MFRC_BY_XSTEP); MotorP98003PositionYProc( ps, _TPA_P98003_SHADINGORG ); } return _TRUE; } /*............................................................................. * initialize this module and setup the correct function pointer according * to the ASIC */ static void motorP98003PositionModuleToHome( pScanData ps ) { Byte save, saveModel; saveModel = ps->AsicReg.RD_ModelControl; ps->Scan.fRefreshState = _FALSE; motorP98003DownloadNullScanStates( ps ); _DODELAY( 1000UL / 8UL); save = ps->Shade.bIntermediate; ps->Shade.bIntermediate = _ScanMode_AverageOut; ps->ReInitAsic( ps, _FALSE ); ps->Shade.bIntermediate = save; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); IORegisterToScanner( ps, ps->RegResetMTSC ); IODataToRegister( ps, ps->RegScanControl1, 0 ); IODataToRegister( ps, ps->RegModelControl, ps->Device.ModelCtrl | _ModelDpi300 ); IODataToRegister( ps, ps->RegLineControl, 80); IODataToRegister( ps, ps->RegXStepTime, ps->Device.XStepBack); IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower); _DODELAY( 12 ); IODataToRegister( ps, ps->RegMotor0Control, (_MotorHHomeStop | _MotorOn | _MotorHQuarterStep | _MotorPowerEnable)); IODataToRegister( ps, ps->RegStepControl, (_MOTOR0_SCANSTATE | _MOTOR_FREERUN)); memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES ); IODownloadScanStates( ps ); IORegisterToScanner( ps, ps->RegRefreshScanState ); ps->AsicReg.RD_ModelControl = saveModel; } /************************ exported functions *********************************/ /*............................................................................. * initialize this module and setup the correct function pointer according * to the ASIC */ _LOC int MotorInitialize( pScanData ps ) { DBG( DBG_HIGH, "MotorInitialize()\n" ); if( NULL == ps ) return _E_NULLPTR; ps->a_wMoveStepTable = a_wMoveStepTable; ps->a_bColorByteTable = a_bColorByteTable; wP96BaseDpi = 0; ps->PauseColorMotorRunStates = motorPauseColorMotorRunStates; /* * depending on the asic, we set some functions */ if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->WaitForPositionY = motorP98WaitForPositionY; ps->GotoShadingPosition = motorP98GotoShadingPosition; ps->FillRunNewAdrPointer = motorP98FillRunNewAdrPointer; ps->SetupMotorRunTable = motorP98SetupRunTable; ps->UpdateDataCurrentReadLine = motorP98UpdateDataCurrentReadLine; ps->SetMotorSpeed = motorP98SetSpeed; } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->WaitForPositionY = motorP98003WaitForPositionY; ps->GotoShadingPosition = motorP98003GotoShadingPosition; ps->SetMotorSpeed = motorP98SetSpeed; } else if( _IS_ASIC96(ps->sCaps.AsicID)) { ps->WaitForPositionY = motorP96WaitForPositionY; ps->GotoShadingPosition = motorP96GotoShadingPosition; ps->FillRunNewAdrPointer = motorP96FillRunNewAdrPointer; ps->SetupMotorRunTable = motorP96SetupRunTable; ps->UpdateDataCurrentReadLine = motorP96UpdateDataCurrentReadLine; ps->SetMotorSpeed = motorP96SetSpeed; } else { DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); return _E_NOSUPP; } return _OK; } /*............................................................................. * */ _LOC void MotorSetConstantMove( pScanData ps, Byte bMovePerStep ) { DataPointer p; ULong dw; p.pb = ps->a_nbNewAdrPointer; switch( bMovePerStep ) { case 0: /* doesn't move at all */ for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pdw &= 0x77777777; else *p.pdw &= 0xbbbbbbbb; } break; case 1: for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pdw |= 0x88888888; else *p.pdw |= 0x44444444; } break; case 2: for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pdw |= 0x80808080; else *p.pdw |= 0x40404040; } break; default: { Byte bMoves = bMovePerStep; for (dw = _SCANSTATE_BYTES; dw; dw--, p.pb++) { if (!(--bMoves)) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pb |= 8; else *p.pb |= 4; bMoves = bMovePerStep; } if (!(--bMoves)) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pb |= 0x80; else *p.pb |= 0x40; bMoves = bMovePerStep; } } } } IOSetToMotorRegister( ps ); } /*............................................................................. * function to bring the sensor back home */ _LOC void MotorToHomePosition( pScanData ps ) { TimerDef timer; ScanState StateStatus; DBG( DBG_HIGH, "Waiting for Sensor to be back in position\n" ); _DODELAY( 250 ); if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){ ps->GotoShadingPosition( ps ); } } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->OpenScanPath( ps ); if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) { motorP98003PositionModuleToHome( ps ); MiscStartTimer( &timer, _SECOND * 20); do { if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER) break; } while( !MiscCheckTimer( &timer)); } ps->CloseScanPath( ps ); } else { if( ps->sCaps.Model >= MODEL_OP_9630P ) { if( ps->sCaps.Model == MODEL_OP_A3I ) IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x34 ); else IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x30 ); } ps->bExtraMotorCtrl = 0; ps->Scan.fMotorBackward = _FALSE; MotorP96ConstantMoveProc( ps, 25 ); ps->Scan.fMotorBackward = _TRUE; for(;;) { motorP96GetScanStateAndStatus( ps, &StateStatus ); if ( StateStatus.bStatus & _FLAG_P96_PAPER ) { break; } MotorP96ConstantMoveProc( ps, 50000 ); } ps->Scan.fMotorBackward = _FALSE; ps->Asic96Reg.RD_MotorControl = 0; IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); _DODELAY(250); ps->Asic96Reg.RD_LedControl = 0; IOCmdRegisterToScanner(ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl); } DBG( DBG_HIGH, "- done !\n" ); } /*............................................................................. * */ _LOC void MotorP98GoFullStep( pScanData ps, ULong dwStep ) { memset( ps->pColorRunTable, 1, dwStep ); memset( ps->pColorRunTable + dwStep, 0xff, 0x40); ps->bOldStateCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK; motorP98SetRunFullStep( ps ); ps->pScanState = ps->pColorRunTable; ps->FillRunNewAdrPointer( ps ); while(!motorCheckMotorPresetLength( ps )) motorP98FillRunNewAdrPointer1( ps ); } /*............................................................................. * */ _LOC void MotorP96SetSpeedToStopProc( pScanData ps ) { Byte bData; TimerDef timer; MiscStartTimer( &timer, _SECOND); while( !MiscCheckTimer( &timer )) { bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset ); if ((bData > ps->bMinReadFifo) && (bData != ps->bFifoCount)) break; } bData = IOGetScanState( ps, _FALSE ); if (!(bData & _SCANSTATE_STOP)) { MiscStartTimer( &timer, (_SECOND / 2)); while (!MiscCheckTimer( &timer )) { if (IOGetScanState( ps, _FALSE) != bData ) break; } } ps->Scan.bModuleState = _MotorInStopState; ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _FALSE ); IOSetToMotorRegister( ps ); } /*............................................................................. * Position Scan Module to specified line number (Forward or Backward & wait * for paper flag ON) */ _LOC void MotorP96ConstantMoveProc( pScanData ps, ULong dwLines ) { Byte bRemainder, bLastState; UShort wQuotient; ULong dwDelayMaxTime; ScanState StateStatus; TimerDef timer; Bool fTimeout = _FALSE; wQuotient = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS); /* state cycles */ bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS); /* 3.3 ms per line */ dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2; MotorSetConstantMove( ps, 1 ); /* step every time */ ps->OpenScanPath( ps ); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); if( ps->Scan.fMotorBackward ) { ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn | ps->FullStep | ps->bExtraMotorCtrl); } else { ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn | _MotorDirForward | ps->bExtraMotorCtrl); } IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); ps->CloseScanPath( ps ); bLastState = 0; MiscStartTimer( &timer, dwDelayMaxTime ); do { motorP96GetScanStateAndStatus( ps, &StateStatus ); if( ps->Scan.fMotorBackward && (StateStatus.bStatus&_FLAG_P96_PAPER)) { break; } else { /* * 1) Forward will not reach the sensor. * 2) Backwarding, doesn't reach the sensor */ if (wQuotient) { /* stepped */ if (StateStatus.bStep != bLastState) { bLastState = StateStatus.bStep; if (!bLastState) /* done a cycle! */ wQuotient--; } } else { if (StateStatus.bStep >= bRemainder) { break; } } } fTimeout = MiscCheckTimer( &timer ); } while ( _OK == fTimeout ); if ( _OK == fTimeout ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); } } /*............................................................................. * */ _LOC Bool MotorP96AheadToDarkArea( pScanData ps ) { Byte bDark; UShort wTL; UShort wTotalLastLine; TimerDef timer; ps->fColorMoreRedFlag = _FALSE; ps->fColorMoreBlueFlag = _FALSE; ps->wOverBlue = 0; /* FillToDarkCounter () */ memset( ps->a_nbNewAdrPointer, 0x30, _SCANSTATE_BYTES); MotorSetConstantMove( ps, 2 ); /* SetToDarkRegister () */ ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; ps->Asic96Reg.RD_MotorControl = _MotorDirForward | ps->FullStep; ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; ps->AsicReg.RD_Dpi = 300; wTL = 296; /* if( MODEL_OP_A3I == ps->sCaps.Model ) { */ if( ps->PhysicalDpi > 300 ) { wTL = 400; ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 2048); } else { ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 1024); } ps->AsicReg.RD_Pixels = 512; IOPutOnAllRegisters( ps ); ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->IgnorePF | ps->MotorOn | _MotorDirForward ); IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); MiscStartTimer( &timer, _SECOND * 2 ); wTotalLastLine = 0; #ifdef _A3I_EN while( !MiscCheckTimer( &timer )) { bDark = motorP96ReadDarkData( ps ); wTotalLastLine++; if((bDark < 0x80) || (wTotalLastLine==wTL)) { IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); return _TRUE; } } #else while (!MiscCheckTimer( &timer )) { bDark = motorP96ReadDarkData( ps ); wTotalLastLine++; if (((ps->sCaps.AsicID == _ASIC_IS_96001) && (bDark > 0x80)) || ((ps->sCaps.AsicID != _ASIC_IS_96001) && (bDark < 0x80)) || (wTotalLastLine==wTL)) { IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeProgram ); if (wTotalLastLine <= 24) ps->fColorMoreRedFlag = _TRUE; else if (wTotalLastLine >= 120) { ps->wOverBlue = wTotalLastLine - 80; ps->fColorMoreBlueFlag = _TRUE; } return _TRUE; } } #endif return _FALSE; /* already timed out */ } /*............................................................................. * limit the speed settings for 96001/3 based models */ _LOC void MotorP96AdjustCurrentSpeed( pScanData ps, Byte bSpeed ) { if (bSpeed != 1) { if (bSpeed > 34) ps->bCurrentSpeed = 34; else ps->bCurrentSpeed = (bSpeed + 1) & 0xfe; } } /*............................................................................. * */ _LOC void MotorP98003ForceToLeaveHomePos( pScanData ps ) { TimerDef timer; IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP ); IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR ); MiscStartTimer( &timer, _SECOND ); do { if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) break; IORegisterToScanner( ps, ps->RegForceStep ); _DODELAY( 10 ); } while( _OK == MiscCheckTimer( &timer )); IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); } /*............................................................................. * */ _LOC void MotorP98003BackToHomeSensor( pScanData ps ) { TimerDef timer; DBG( DBG_HIGH, "MotorP98003BackToHomeSensor()\n" ); IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); IODataToRegister( ps, ps->RegModeControl, _ModeScan ); /* stepping every state */ memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES ); IODownloadScanStates( ps ); MiscStartTimer( &timer, _SECOND * 2 ); while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) && !MiscCheckTimer( &timer )) ; _DODELAY( 1000UL ); ps->AsicReg.RD_ModeControl = _ModeScan; if (!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) { IODataToRegister( ps, ps->RegLineControl, _LOBYTE(ps->Shade.wExposure)); IODataToRegister( ps, ps->RegXStepTime, _LOBYTE(ps->Shade.wXStep)); } else { IODataToRegister( ps, ps->RegLineControl, _DEFAULT_LINESCANTIME ); IODataToRegister( ps, ps->RegXStepTime, 6); } IODataToRegister( ps, ps->RegStepControl, (_MOTOR_FREERUN | _MOTOR0_SCANSTATE)); IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); IODataToRegister( ps, ps->RegMotor0Control, (_MotorHQuarterStep | _MotorOn | _MotorDirBackward | _MotorPowerEnable | _MotorHHomeStop)); IORegisterToScanner( ps, ps->RegRefreshScanState ); MiscStartTimer( &timer, _SECOND * 5 ); do { if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER ) break; _DODELAY( 55 ); } while( !MiscCheckTimer( &timer )); IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime); DBG( DBG_HIGH, "LineCtrl=%u, XStepTime=%u\n", ps->AsicReg.RD_LineControl, ps->AsicReg.RD_XStepTime ); motorP98003DownloadNullScanStates( ps ); } /*............................................................................. * */ _LOC void MotorP98003ModuleForwardBackward( pScanData ps ) { switch( ps->Scan.bModuleState ) { case _MotorInNormalState: ps->Scan.bModuleState = _MotorGoBackward; IODataToRegister( ps, ps->RegScanControl1, (UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); IODataToRegister( ps, ps->RegMotor0Control, (UChar)(ps->AsicReg.RD_Motor0Control & ~_MotorDirForward)); motorP98003ModuleFreeRun( ps, _P98003_BACKSTEPS ); MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND)); break; case _MotorGoBackward: if( MiscCheckTimer(& p98003MotorTimer)) { if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) { ps->Scan.bModuleState = _MotorInStopState; MiscStartTimer( &p98003MotorTimer, (50 *_MSECOND)); } } break; case _MotorInStopState: if( MiscCheckTimer(&p98003MotorTimer)) { if( IOReadFifoLength( ps ) < ps->Scan.dwMaxReadFifo ) { ps->Scan.bModuleState = _MotorAdvancing; IODataToRegister( ps, ps->RegScanControl1, ps->AsicReg.RD_ScanControl1); IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control); motorP98003ModuleFreeRun( ps, _P98003_FORWARDSTEPS ); MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND)); } } break; case _MotorAdvancing: if( MiscCheckTimer(&p98003MotorTimer)) { if( !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP)) ps->Scan.bModuleState = _MotorInNormalState; else { if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) { IORegisterToScanner( ps, ps->RegRefreshScanState ); ps->Scan.bModuleState = _MotorInNormalState; } } } break; } } /*............................................................................. * */ _LOC void MotorP98003PositionYProc( pScanData ps, ULong steps) { TimerDef timer; DBG( DBG_HIGH, "MotorP98003PositionYProc()\n" ); MiscStartTimer( &timer, _SECOND * 5 ); while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) && !MiscCheckTimer( &timer )) ; _DODELAY( 12 ); motorP98003ModuleFreeRun( ps, steps ); _DODELAY( 15 ); MiscStartTimer( &timer, _SECOND * 30 ); do { if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) || !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP)) break; } while( !MiscCheckTimer( &timer )); DBG( DBG_HIGH, "MotorP98003PositionYProc() - done\n" ); } /* END PLUSTEK-PP_MOTOR.C ...................................................*/