sane-project-backends/backend/plustek-pp_motor.c

3347 wiersze
90 KiB
C
Czysty Wina Historia

/* @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-2004 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
* .
* <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 > %lu !!\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<69>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 > %lu !!\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 ...................................................*/