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

3350 wiersze
90 KiB
C
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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