summaryrefslogtreecommitdiff
path: root/backend/plustek-pp_motor.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2014-10-06 14:00:40 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2014-10-06 14:00:40 +0200
commit6e9c41a892ed0e0da326e0278b3221ce3f5713b8 (patch)
tree2e301d871bbeeb44aa57ff9cc070fcf3be484487 /backend/plustek-pp_motor.c
Initial import of sane-backends version 1.0.24-1.2
Diffstat (limited to 'backend/plustek-pp_motor.c')
-rw-r--r--backend/plustek-pp_motor.c3348
1 files changed, 3348 insertions, 0 deletions
diff --git a/backend/plustek-pp_motor.c b/backend/plustek-pp_motor.c
new file mode 100644
index 0000000..f377b7e
--- /dev/null
+++ b/backend/plustek-pp_motor.c
@@ -0,0 +1,3348 @@
+/* @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 <gerhard@gjaeger.de>
+ * 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
+ * .
+ * <hr>
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * 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.
+ * <hr>
+ */
+#include "plustek-pp_scan.h"
+
+/*************************** some definitons *********************************/
+
+/* #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 reachs 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;
+ 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 loosing 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 loosing 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, loosing 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 ...................................................*/