kopia lustrzana https://gitlab.com/sane-project/backends
782 wiersze
25 KiB
C
782 wiersze
25 KiB
C
/*.............................................................................
|
|
* Project : SANE library for Plustek parallelport flatbed scanners.
|
|
*.............................................................................
|
|
*/
|
|
|
|
/* @file plustek-pp_p12.c
|
|
* @brief p12 and pt12 specific stuff
|
|
*
|
|
* based on sources acquired from Plustek Inc.
|
|
* Copyright (C) 2000 Plustek Inc.
|
|
* Copyright (C) 2001-2003 Gerhard Jaeger <gerhard@gjaeger.de>
|
|
*
|
|
* History:
|
|
* - 0.38 - initial version
|
|
* - 0.39 - added Genius Colorpage Vivid III V2 stuff
|
|
* - 0.40 - no changes
|
|
* - 0.41 - no changes
|
|
* - 0.42 - removed setting of ps->sCaps.dwFlag in p12InitiateComponentModel()
|
|
* .
|
|
* <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 local vars *********************************/
|
|
|
|
static RegDef p12CcdStop[] = {
|
|
{0x41, 0xff}, {0x42, 0xff}, {0x60, 0xff}, {0x61, 0xff},
|
|
{0x4b, 0xff}, {0x4c, 0xff}, {0x4d, 0xff}, {0x4e, 0xff},
|
|
{0x2a, 0x01}, {0x2b, 0x00}, {0x2d, 0x00}, {0x1b, 0x19}, {0x15, 0x00}
|
|
};
|
|
|
|
/*************************** local functions *********************************/
|
|
|
|
/** init the stuff according to the buttons
|
|
*/
|
|
static void p12ButtonSetup( pScanData ps, Byte nrOfButtons )
|
|
{
|
|
ps->Device.buttons = nrOfButtons;
|
|
|
|
ps->Device.Model1Mono &= ~_BUTTON_MODE;
|
|
ps->Device.Model1Color &= ~_BUTTON_MODE;
|
|
|
|
ps->AsicReg.RD_MotorDriverType |= _BUTTON_DISABLE;
|
|
ps->Scan.motorPower |= _BUTTON_DISABLE;
|
|
ps->sCaps.dwFlag |= (SFLAG_MULTIFUNC | SFLAG_BUTTONOPT);
|
|
}
|
|
|
|
/** According to what we have detected, set the other stuff
|
|
*/
|
|
static void p12InitiateComponentModel( pScanData ps )
|
|
{
|
|
/* preset some stuff and do the differences later */
|
|
ps->Device.buttons = 0;
|
|
ps->Device.Model1Mono = _BUTTON_MODE + _CCD_SHIFT_GATE + _SCAN_GRAYTYPE;
|
|
ps->Device.Model1Color = _BUTTON_MODE + _CCD_SHIFT_GATE;
|
|
ps->Device.dwModelOriginY = 64;
|
|
ps->Device.fTpa = _FALSE;
|
|
ps->Device.ModelCtrl = (_LED_ACTIVITY | _LED_CONTROL);
|
|
|
|
/* ps->sCaps.dwFlag should have been set correctly in models.c */
|
|
|
|
switch( ps->Device.bPCBID ) {
|
|
|
|
case _PLUSTEK_SCANNER:
|
|
DBG( DBG_LOW, "We have a Plustek Scanner\n" );
|
|
ps->sCaps.Model = MODEL_OP_P12;
|
|
break;
|
|
|
|
case _SCANNER_WITH_TPA:
|
|
DBG( DBG_LOW, "Scanner has TPA\n" );
|
|
ps->Device.fTpa = _TRUE;
|
|
ps->sCaps.dwFlag |= SFLAG_TPA;
|
|
break;
|
|
|
|
case _SCANNER4Button:
|
|
DBG( DBG_LOW, "Scanner has 4 Buttons\n" );
|
|
p12ButtonSetup( ps, 4 );
|
|
break;
|
|
|
|
case _SCANNER4ButtonTPA:
|
|
DBG( DBG_LOW, "Scanner has 4 Buttons & TPA\n" );
|
|
ps->Device.fTpa = _TRUE;
|
|
ps->sCaps.dwFlag |= SFLAG_TPA;
|
|
p12ButtonSetup( ps, 4 );
|
|
break;
|
|
|
|
case _SCANNER5Button:
|
|
DBG( DBG_LOW, "Scanner has 5 Buttons\n" );
|
|
ps->Device.dwModelOriginY = 64 + 20;
|
|
p12ButtonSetup( ps, 5 );
|
|
break;
|
|
|
|
case _SCANNER5ButtonTPA:
|
|
DBG( DBG_LOW, "Scanner has 5 Buttons & TPA\n" );
|
|
ps->Device.dwModelOriginY = 64 + 20;
|
|
ps->Device.fTpa = _TRUE;
|
|
ps->sCaps.dwFlag |= SFLAG_TPA;
|
|
p12ButtonSetup( ps, 5 );
|
|
break;
|
|
|
|
case _SCANNER1Button:
|
|
DBG( DBG_LOW, "Scanner has 1 Button\n" );
|
|
p12ButtonSetup( ps, 1 );
|
|
break;
|
|
|
|
case _SCANNER1ButtonTPA:
|
|
DBG( DBG_LOW, "Scanner has 1 Button & TPA\n" );
|
|
ps-> Device.fTpa = _TRUE;
|
|
ps->sCaps.dwFlag |= SFLAG_TPA;
|
|
p12ButtonSetup( ps, 1 );
|
|
break;
|
|
|
|
case _AGFA_SCANNER:
|
|
DBG( DBG_LOW, "Agfa Scanner\n" );
|
|
ps->Device.dwModelOriginY = 24; /* 1200 dpi */
|
|
break;
|
|
|
|
case _SCANNER2Button:
|
|
DBG( DBG_LOW, "Scanner has 2 Buttons\n" );
|
|
DBG( DBG_LOW, "Seems we have a Genius Colorpage Vivid III V2\n" );
|
|
ps->Device.dwModelOriginY = 64 - 33;
|
|
p12ButtonSetup( ps, 2 );
|
|
ps->sCaps.Model = MODEL_GEN_CPV2;
|
|
break;
|
|
|
|
default:
|
|
DBG( DBG_LOW, "Default Model: P12\n" );
|
|
ps->sCaps.Model = MODEL_OP_P12;
|
|
break;
|
|
}
|
|
|
|
if( _MOTOR0_2003 == ps->Device.bMotorID ) {
|
|
ps->Device.f2003 = _TRUE;
|
|
ps->Device.XStepMono = 10;
|
|
ps->Device.XStepColor = 6;
|
|
ps->Device.XStepBack = 5;
|
|
ps->AsicReg.RD_MotorDriverType |= _MOTORR_STRONG;
|
|
} else {
|
|
ps->Device.f2003 = _FALSE;
|
|
ps->Device.XStepMono = 8;
|
|
ps->Device.XStepColor = 4;
|
|
ps->Device.XStepBack = 5;
|
|
ps->AsicReg.RD_MotorDriverType |= _MOTORR_WEAK;
|
|
}
|
|
}
|
|
|
|
/*.............................................................................
|
|
* prepare all the necessary variables -
|
|
*/
|
|
static void p12SetupScannerVariables( pScanData ps )
|
|
{
|
|
DBG( DBG_LOW, "p12SetupScannerVariables()\n" );
|
|
|
|
/*
|
|
* these values were originally altered by registry entries (NT-driver)
|
|
* and used to adjust the picture position...
|
|
*/
|
|
ps->Device.lUpNormal = 0;
|
|
ps->Device.lUpNegative = 20;
|
|
ps->Device.lUpPositive = -30;
|
|
|
|
ps->Device.lLeftNormal = 51;
|
|
|
|
ps->OpenScanPath( ps );
|
|
ps->ReInitAsic( ps, _FALSE );
|
|
ps->CloseScanPath( ps );
|
|
}
|
|
|
|
/*.............................................................................
|
|
*
|
|
*/
|
|
static void p12SetupScanningCondition( pScanData ps )
|
|
{
|
|
TimerDef timer;
|
|
ULong channel;
|
|
Byte bState;
|
|
pUChar pState = ps->Bufs.b1.pReadBuf;
|
|
|
|
DBG( DBG_LOW, "p12SetupScanningCondition()\n" );
|
|
|
|
P12SetGeneralRegister( ps );
|
|
|
|
IORegisterToScanner( ps, ps->RegResetMTSC );
|
|
|
|
/* ------- Setup MinRead/MaxRead Fifo size ------- */
|
|
if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) {
|
|
ps->Scan.dwMaxReadFifo =
|
|
ps->Scan.dwMinReadFifo = ps->DataInf.dwAsicBytesPerPlane * 2;
|
|
} else {
|
|
ps->Scan.dwMaxReadFifo =
|
|
ps->Scan.dwMinReadFifo = ps->DataInf.dwAppPixelsPerLine << 1;
|
|
}
|
|
|
|
if( ps->Scan.dwMinReadFifo < 1024)
|
|
ps->Scan.dwMinReadFifo = ps->Scan.dwMaxReadFifo = 1024;
|
|
|
|
ps->Scan.dwMaxReadFifo += (ps->DataInf.dwAsicBytesPerPlane / 2);
|
|
|
|
|
|
DBG( DBG_LOW, "MinReadFifo=%lu, MaxReadFifo=%lu\n",
|
|
ps->Scan.dwMinReadFifo, ps->Scan.dwMaxReadFifo );
|
|
|
|
/* ------- Set the max. read fifo to asic ------- */
|
|
if( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
|
|
|
|
ps->Scan.bFifoSelect = ps->RegBFifoOffset;
|
|
|
|
if( !ps->Scan.p48BitBuf.pb ) {
|
|
|
|
Long lRed, lGreen;
|
|
|
|
lRed = (_SIZE_REDFIFO - _SIZE_BLUEFIFO) /
|
|
ps->DataInf.dwAsicBytesPerPlane - ps->Scan.bd_rk.wRedKeep;
|
|
|
|
lGreen = (_SIZE_GREENFIFO - _SIZE_BLUEFIFO) /
|
|
ps->DataInf.dwAsicBytesPerPlane - ps->Scan.gd_gk.wGreenKeep;
|
|
|
|
if((lRed < 0) || (lGreen < 0)) {
|
|
|
|
if( lRed < lGreen ) {
|
|
channel = _RED_FULLSIZE << 16;
|
|
ps->AsicReg.RD_BufFullSize = _SIZE_REDFIFO;
|
|
lGreen = lRed;
|
|
} else {
|
|
channel = _GREEN_FULLSIZE << 16;
|
|
ps->AsicReg.RD_BufFullSize = _SIZE_GREENFIFO;
|
|
}
|
|
|
|
lGreen = (ULong)(-lGreen * ps->DataInf.dwAsicBytesPerPlane);
|
|
|
|
if( ps->DataInf.wPhyDataType > COLOR_TRUE24 )
|
|
lGreen >>= 1;
|
|
|
|
ps->Scan.dwMinReadFifo += (ULong)lGreen;
|
|
ps->Scan.dwMaxReadFifo += (ULong)lGreen;
|
|
|
|
} else {
|
|
channel = _BLUE_FULLSIZE << 16;
|
|
ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO;
|
|
}
|
|
} else {
|
|
channel = _BLUE_FULLSIZE << 16;
|
|
ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO;
|
|
}
|
|
} else {
|
|
ps->Scan.bFifoSelect = ps->RegGFifoOffset;
|
|
channel = _GREEN_FULLSIZE << 16;
|
|
ps->AsicReg.RD_BufFullSize = _SIZE_GRAYFIFO;
|
|
}
|
|
|
|
ps->AsicReg.RD_BufFullSize -= (ps->DataInf.dwAsicBytesPerPlane << 1);
|
|
|
|
if( ps->DataInf.wPhyDataType > COLOR_TRUE24 )
|
|
ps->AsicReg.RD_BufFullSize >>= 1;
|
|
|
|
ps->AsicReg.RD_BufFullSize |= channel;
|
|
|
|
ps->Scan.bRefresh = (Byte)(ps->Scan.dwInterval << 1);
|
|
ps->AsicReg.RD_LineControl = (_LOBYTE (ps->Shade.wExposure));
|
|
ps->AsicReg.RD_ExtLineControl = (_HIBYTE (ps->Shade.wExposure));
|
|
ps->AsicReg.RD_XStepTime = (_LOBYTE (ps->Shade.wXStep));
|
|
ps->AsicReg.RD_ExtXStepTime = (_HIBYTE (ps->Shade.wXStep));
|
|
ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR;
|
|
ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE;
|
|
ps->AsicReg.RD_ModeControl = (_ModeScan | _ModeFifoGSel);
|
|
|
|
DBG( DBG_LOW, "bRefresh = %i\n", ps->Scan.bRefresh );
|
|
|
|
if( ps->DataInf.wPhyDataType == COLOR_BW ) {
|
|
ps->AsicReg.RD_ScanControl = _SCAN_BITMODE;
|
|
|
|
if( !(ps->DataInf.dwScanFlag & SCANDEF_Inverse))
|
|
ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT;
|
|
|
|
} else if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 )
|
|
ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
|
|
else {
|
|
ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE;
|
|
|
|
if(!(ps->DataInf.dwScanFlag & SCANDEF_RightAlign))
|
|
ps->AsicReg.RD_ScanControl |= _BITALIGN_LEFT;
|
|
|
|
if( ps->DataInf.dwScanFlag & SCANDEF_Inverse)
|
|
ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT;
|
|
}
|
|
|
|
ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE;
|
|
IOSelectLampSource( ps );
|
|
|
|
DBG( DBG_LOW, "RD_ScanControl = 0x%02x\n", ps->AsicReg.RD_ScanControl );
|
|
|
|
ps->AsicReg.RD_MotorTotalSteps = (ULong)ps->DataInf.crImage.cy * 4 +
|
|
((ps->Device.f0_8_16) ? 32 : 16) +
|
|
((ps->Scan.bDiscardAll) ? 32 : 0);
|
|
|
|
ps->AsicReg.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL |
|
|
_MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP);
|
|
|
|
ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x;
|
|
|
|
if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA )) {
|
|
|
|
ps->AsicReg.RD_Origin = (UShort)(ps->Device.lLeftNormal * 2 +
|
|
ps->Device.DataOriginX +
|
|
ps->DataInf.crImage.x );
|
|
|
|
} else if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) {
|
|
ps->AsicReg.RD_Origin =
|
|
(UShort)(ps->Scan.posBegin + ps->DataInf.crImage.x);
|
|
} else {
|
|
ps->AsicReg.RD_Origin =
|
|
(UShort)(ps->Scan.negBegin + ps->DataInf.crImage.x);
|
|
}
|
|
|
|
if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
|
|
ps->AsicReg.RD_Origin >>= 1;
|
|
|
|
if( ps->DataInf.wPhyDataType == COLOR_BW )
|
|
ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicBytesPerPlane;
|
|
else
|
|
ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAppPixelsPerLine;
|
|
|
|
DBG( DBG_LOW, "RD_Origin = %u, RD_Pixels = %u\n",
|
|
ps->AsicReg.RD_Origin, ps->AsicReg.RD_Pixels );
|
|
|
|
/* ------- Prepare scan states ------- */
|
|
memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
|
|
memset( ps->Bufs.b1.pReadBuf, 0, _NUMBER_OF_SCANSTEPS );
|
|
|
|
if( ps->DataInf.wPhyDataType <= COLOR_256GRAY )
|
|
bState = (_SS_MONO | _SS_STEP);
|
|
else
|
|
bState = (_SS_COLOR | _SS_STEP);
|
|
|
|
for( channel = _NUMBER_OF_SCANSTEPS;
|
|
channel; channel -= ps->Scan.dwInterval ) {
|
|
*pState = bState;
|
|
if( ps->Scan.dwInterlace )
|
|
pState[ ps->Scan.dwInterlace] = _SS_STEP;
|
|
pState += ps->Scan.dwInterval;
|
|
}
|
|
for( channel = 0, pState = ps->Bufs.b1.pReadBuf;
|
|
channel < _SCANSTATE_BYTES; channel++) {
|
|
ps->a_nbNewAdrPointer[channel] = pState [0] | (pState [1] << 4);
|
|
pState += 2;
|
|
}
|
|
|
|
/* ------- Wait for scan state stop ------- */
|
|
MiscStartTimer( &timer, _SECOND * 2 );
|
|
|
|
while(!(IOGetScanState( ps, _FALSE ) & _SCANSTATE_STOP) &&
|
|
!MiscCheckTimer(&timer));
|
|
|
|
/* CHECK: Replace by IOPutAll.... */
|
|
IODownloadScanStates( ps );
|
|
IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl);
|
|
IODataToRegister( ps, ps->RegExtendedLineControl,
|
|
ps->AsicReg.RD_ExtLineControl);
|
|
IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime);
|
|
IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime);
|
|
IODataToRegister( ps, ps->RegMotorDriverType,
|
|
ps->AsicReg.RD_MotorDriverType);
|
|
IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl);
|
|
IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control);
|
|
IODataToRegister( ps, ps->RegModelControl,ps->AsicReg.RD_ModelControl);
|
|
IODataToRegister( ps, ps->RegDpiLow, (_LOBYTE(ps->AsicReg.RD_Dpi)));
|
|
IODataToRegister( ps, ps->RegDpiHigh, (_HIBYTE(ps->AsicReg.RD_Dpi)));
|
|
IODataToRegister( ps, ps->RegScanPosLow, (_LOBYTE(ps->AsicReg.RD_Origin)));
|
|
IODataToRegister( ps, ps->RegScanPosHigh,(_HIBYTE(ps->AsicReg.RD_Origin)));
|
|
IODataToRegister( ps, ps->RegWidthPixelsLow,
|
|
(_LOBYTE(ps->AsicReg.RD_Pixels)));
|
|
IODataToRegister( ps, ps->RegWidthPixelsHigh,
|
|
(_HIBYTE(ps->AsicReg.RD_Pixels)));
|
|
IODataToRegister( ps, ps->RegThresholdLow,
|
|
(_LOBYTE(ps->AsicReg.RD_ThresholdControl)));
|
|
IODataToRegister( ps, ps->RegThresholdHigh,
|
|
(_HIBYTE(ps->AsicReg.RD_ThresholdControl)));
|
|
IODataToRegister( ps, ps->RegMotorTotalStep0,
|
|
(_LOBYTE(ps->AsicReg.RD_MotorTotalSteps)));
|
|
IODataToRegister( ps, ps->RegMotorTotalStep1,
|
|
(_HIBYTE(ps->AsicReg.RD_MotorTotalSteps)));
|
|
IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl);
|
|
|
|
IORegisterToScanner( ps, ps->RegInitDataFifo);
|
|
}
|
|
|
|
/*.............................................................................
|
|
* program the CCD relevant stuff
|
|
*/
|
|
static void p12ProgramCCD( pScanData ps)
|
|
{
|
|
UShort w;
|
|
pRegDef rp;
|
|
|
|
DBG( DBG_IO, "p12ProgramCCD: 0x%08lx[%lu]\n",
|
|
(ULong)ps->Device.pCCDRegisters,
|
|
((ULong)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate));
|
|
|
|
DBG( DBG_IO, " %u regs * %u (intermediate)\n",
|
|
ps->Device.wNumCCDRegs, ps->Shade.bIntermediate );
|
|
|
|
rp = ps->Device.pCCDRegisters +
|
|
(ULong)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate;
|
|
|
|
for( w = ps->Device.wNumCCDRegs; w--; rp++ ) {
|
|
|
|
DBG( DBG_IO, "[0x%02x] = 0x%02x\n", rp->bReg, rp->bParam );
|
|
IODataToRegister( ps, rp->bReg, rp->bParam );
|
|
}
|
|
}
|
|
|
|
/*.............................................................................
|
|
* this initializes the ASIC and prepares the different functions for shading
|
|
* and scanning
|
|
*/
|
|
static void p12Init98003( pScanData ps, Bool shading )
|
|
{
|
|
DBG( DBG_LOW, "p12InitP98003(%d)\n", shading );
|
|
|
|
/* get DAC and motor stuff */
|
|
ps->Device.bDACType = IODataFromRegister( ps, ps->RegResetConfig );
|
|
ps->Device.bMotorID = (Byte)(ps->Device.bDACType & _MOTOR0_MASK);
|
|
|
|
ps->AsicReg.RD_MotorDriverType =
|
|
(Byte)((ps->Device.bDACType & _MOTOR0_MASK) >> 3);
|
|
ps->AsicReg.RD_MotorDriverType |=
|
|
(Byte)((ps->Device.bDACType & _MOTOR1_MASK) >> 1);
|
|
|
|
|
|
ps->Scan.motorPower = ps->AsicReg.RD_MotorDriverType | _MOTORR_STRONG;
|
|
|
|
ps->Device.bDACType &= _ADC_MASK;
|
|
|
|
/*get CCD and PCB ID */
|
|
ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration );
|
|
ps->Device.bCCDID = ps->Device.bPCBID & 0x07;
|
|
ps->Device.bPCBID &= 0xf0;
|
|
|
|
if( _AGFA_SCANNER == ps->Device.bPCBID )
|
|
ps->Device.bDACType = _DA_WOLFSON8141;
|
|
|
|
DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x, DAC-TYPE=0x%02x\n",
|
|
ps->Device.bPCBID, ps->Device.bCCDID, ps->Device.bDACType );
|
|
|
|
p12InitiateComponentModel( ps );
|
|
|
|
/* encode the CCD-id into the flag parameter */
|
|
ps->sCaps.dwFlag |= ((ULong)(ps->Device.bCCDID | ps->Device.bPCBID) << 16);
|
|
|
|
P12InitCCDandDAC( ps, shading );
|
|
|
|
if( ps->Shade.bIntermediate & _ScanMode_Mono )
|
|
ps->AsicReg.RD_Model1Control = ps->Device.Model1Mono;
|
|
else
|
|
ps->AsicReg.RD_Model1Control = ps->Device.Model1Color;
|
|
|
|
IODataToRegister( ps, ps->RegPllPredivider, 1 );
|
|
IODataToRegister( ps, ps->RegPllMaindivider, 0x20 );
|
|
IODataToRegister( ps, ps->RegPllPostdivider, 2 );
|
|
IODataToRegister( ps, ps->RegClockSelector, 3 ); /* 2 */
|
|
IODataToRegister( ps, ps->RegMotorDriverType,
|
|
ps->AsicReg.RD_MotorDriverType );
|
|
|
|
/* this might be changed, def value is 11 */
|
|
IODataToRegister( ps, ps->RegWaitStateInsert, 11 );
|
|
IODataToRegister( ps, ps->RegModel1Control, ps->AsicReg.RD_Model1Control );
|
|
|
|
p12ProgramCCD( ps );
|
|
}
|
|
|
|
/*.............................................................................
|
|
* initialize the register values for the 98003 asic and preset other stuff
|
|
*/
|
|
static void p12InitializeAsicRegister( pScanData ps )
|
|
{
|
|
memset( &ps->AsicReg, 0, sizeof(RegData));
|
|
}
|
|
|
|
/*.............................................................................
|
|
* as the function name says
|
|
*/
|
|
static void p12PutToIdleMode( pScanData ps )
|
|
{
|
|
ULong i;
|
|
|
|
ps->OpenScanPath( ps );
|
|
|
|
DBG( DBG_IO, "CCD-Stop\n" );
|
|
|
|
for( i = 0; i < 13; i++ ) {
|
|
|
|
DBG( DBG_IO, "[0x%02x] = 0x%02x\n",
|
|
p12CcdStop[i].bReg, p12CcdStop[i].bParam );
|
|
|
|
IODataToRegister( ps, p12CcdStop[i].bReg, p12CcdStop[i].bParam );
|
|
}
|
|
|
|
ps->CloseScanPath( ps );
|
|
}
|
|
|
|
/*.............................................................................
|
|
* here we simply call the WaitForShading function which performs this topic
|
|
*/
|
|
static int p12Calibration( pScanData ps )
|
|
{
|
|
Bool result;
|
|
|
|
DBG( DBG_LOW, "p12Calibration()\n" );
|
|
|
|
/*
|
|
* wait for shading to be done
|
|
*/
|
|
ps->OpenScanPath( ps );
|
|
|
|
_ASSERT(ps->WaitForShading);
|
|
result = ps->WaitForShading( ps );
|
|
ps->CloseScanPath( ps );
|
|
|
|
if( !result )
|
|
return _E_TIMEOUT;
|
|
|
|
return _OK;
|
|
}
|
|
|
|
/************************ exported functions *********************************/
|
|
|
|
/*.............................................................................
|
|
* initialize the register values and function calls for the 98003 asic
|
|
*/
|
|
_LOC int P12InitAsic( pScanData ps )
|
|
{
|
|
int result;
|
|
|
|
DBG( DBG_LOW, "P12InitAsic()\n" );
|
|
|
|
/*
|
|
* preset the asic shadow registers
|
|
*/
|
|
p12InitializeAsicRegister( ps );
|
|
|
|
ps->IO.bOpenCount = 0;
|
|
|
|
/*
|
|
* setup the register values
|
|
*/
|
|
ps->RegSwitchBus = 0;
|
|
ps->RegEPPEnable = 1;
|
|
ps->RegECPEnable = 2;
|
|
ps->RegReadDataMode = 3;
|
|
ps->RegWriteDataMode = 4;
|
|
ps->RegInitDataFifo = 5;
|
|
ps->RegForceStep = 6;
|
|
ps->RegInitScanState = 7;
|
|
ps->RegRefreshScanState = 8;
|
|
ps->RegWaitStateInsert = 0x0a;
|
|
ps->RegRFifoOffset = 0x0a;
|
|
ps->RegGFifoOffset = 0x0b;
|
|
ps->RegBFifoOffset = 0x0c;
|
|
ps->RegBitDepth = 0x13;
|
|
ps->RegStepControl = 0x14;
|
|
ps->RegMotor0Control = 0x15;
|
|
ps->RegXStepTime = 0x16;
|
|
ps->RegGetScanState = 0x17;
|
|
ps->RegAsicID = 0x18;
|
|
ps->RegMemoryLow = 0x19;
|
|
ps->RegMemoryHigh = 0x1a;
|
|
ps->RegModeControl = 0x1b;
|
|
ps->RegLineControl = 0x1c;
|
|
ps->RegScanControl = 0x1d;
|
|
ps->RegConfiguration = 0x1e;
|
|
ps->RegModelControl = 0x1f;
|
|
ps->RegModel1Control = 0x20;
|
|
ps->RegDpiLow = 0x21;
|
|
ps->RegDpiHigh = 0x22;
|
|
ps->RegScanPosLow = 0x23;
|
|
ps->RegScanPosHigh = 0x24;
|
|
ps->RegWidthPixelsLow = 0x25;
|
|
ps->RegWidthPixelsHigh = 0x26;
|
|
ps->RegThresholdLow = 0x27;
|
|
ps->RegThresholdHigh = 0x28;
|
|
ps->RegThresholdGapControl = 0x29;
|
|
ps->RegADCAddress = 0x2a;
|
|
ps->RegADCData = 0x2b;
|
|
ps->RegADCPixelOffset = 0x2c;
|
|
ps->RegADCSerialOutStr = 0x2d;
|
|
ps->RegResetConfig = 0x2e;
|
|
ps->RegLensPosition = 0x2f;
|
|
ps->RegStatus = 0x30;
|
|
ps->RegScanStateControl = 0x31;
|
|
ps->RegRedChDarkOffsetLow = 0x33;
|
|
ps->RegRedChDarkOffsetHigh = 0x34;
|
|
ps->RegGreenChDarkOffsetLow = 0x35;
|
|
ps->RegGreenChDarkOffsetHigh= 0x36;
|
|
ps->RegBlueChDarkOffsetLow = 0x37;
|
|
ps->RegBlueChDarkOffsetHigh = 0x38;
|
|
ps->RegResetPulse0 = 0x39;
|
|
ps->RegResetPulse1 = 0x3a;
|
|
ps->RegCCDClampTiming0 = 0x3b;
|
|
ps->RegCCDClampTiming1 = 0x3c;
|
|
ps->RegVSMPTiming0 = 0x41;
|
|
ps->RegVSMPTiming1 = 0x42;
|
|
ps->RegCCDQ1Timing0 = 0x43;
|
|
ps->RegCCDQ1Timing1 = 0x44;
|
|
ps->RegCCDQ1Timing2 = 0x45;
|
|
ps->RegCCDQ1Timing3 = 0x46;
|
|
ps->RegCCDQ2Timing0 = 0x47;
|
|
ps->RegCCDQ2Timing1 = 0x48;
|
|
ps->RegCCDQ2Timing2 = 0x49;
|
|
ps->RegCCDQ2Timing3 = 0x4a;
|
|
ps->RegADCclockTiming0 = 0x4b;
|
|
ps->RegADCclockTiming1 = 0x4c;
|
|
ps->RegADCclockTiming2 = 0x4d;
|
|
ps->RegADCclockTiming3 = 0x4e;
|
|
ps->RegADCDVTiming0 = 0x50;
|
|
ps->RegADCDVTiming1 = 0x51;
|
|
ps->RegADCDVTiming2 = 0x52;
|
|
ps->RegADCDVTiming3 = 0x53;
|
|
|
|
ps->RegFifoFullLength0 = 0x54;
|
|
ps->RegFifoFullLength1 = 0x55;
|
|
ps->RegFifoFullLength2 = 0x56;
|
|
|
|
ps->RegMotorTotalStep0 = 0x57;
|
|
ps->RegMotorTotalStep1 = 0x58;
|
|
ps->RegMotorFreeRunCount0 = 0x59;
|
|
ps->RegMotorFreeRunCount1 = 0x5a;
|
|
ps->RegScanControl1 = 0x5b;
|
|
ps->RegMotorFreeRunTrigger = 0x5c;
|
|
|
|
ps->RegResetMTSC = 0x5d;
|
|
|
|
ps->RegMotor1Control = 0x62;
|
|
ps->RegMotor2Control = 0x63;
|
|
ps->RegMotorDriverType = 0x64;
|
|
|
|
ps->RegStatus2 = 0x66;
|
|
|
|
ps->RegExtendedLineControl = 0x6d;
|
|
ps->RegExtendedXStep = 0x6e;
|
|
|
|
ps->RegPllPredivider = 0x71;
|
|
ps->RegPllMaindivider = 0x72;
|
|
ps->RegPllPostdivider = 0x73;
|
|
ps->RegClockSelector = 0x74;
|
|
ps->RegTestMode = 0xf0;
|
|
|
|
/*
|
|
* setup function calls
|
|
*/
|
|
ps->SetupScannerVariables = p12SetupScannerVariables;
|
|
ps->SetupScanningCondition = p12SetupScanningCondition;
|
|
ps->Calibration = p12Calibration;
|
|
ps->PutToIdleMode = p12PutToIdleMode;
|
|
ps->ReInitAsic = p12Init98003;
|
|
|
|
ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE;
|
|
ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF;
|
|
|
|
ps->IO.useEPPCmdMode = _FALSE;
|
|
|
|
/*
|
|
* initialize the other modules and set some
|
|
* function pointer
|
|
*/
|
|
result = DacInitialize( ps );
|
|
if( _OK != result )
|
|
return result;
|
|
|
|
result = ImageInitialize( ps );
|
|
if( _OK != result )
|
|
return result;
|
|
|
|
result = IOFuncInitialize( ps );
|
|
if( _OK != result )
|
|
return result;
|
|
|
|
result = IOInitialize( ps );
|
|
if( _OK != result )
|
|
return result;
|
|
|
|
result = MotorInitialize( ps );
|
|
if( _OK != result )
|
|
return result;
|
|
|
|
if( _FALSE == ps->OpenScanPath( ps )) {
|
|
DBG( DBG_LOW, "P12InitAsic() failed.\n" );
|
|
return _E_NO_DEV;
|
|
}
|
|
|
|
/*get CCD and PCB ID */
|
|
ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration );
|
|
ps->Device.bCCDID = ps->Device.bPCBID & 0x07;
|
|
ps->Device.bPCBID &= 0xf0;
|
|
|
|
DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x\n", ps->Device.bPCBID, ps->Device.bCCDID );
|
|
|
|
/* get a more closer model description...*/
|
|
p12InitiateComponentModel( ps );
|
|
|
|
ps->CloseScanPath( ps );
|
|
|
|
/* here we check for the OpticWorks 2000, which is not supported */
|
|
if( _OPTICWORKS2000 == ps->Device.bPCBID ) {
|
|
DBG( DBG_LOW, "OpticWorks 2000 not supported!\n" );
|
|
return _E_NOSUPP;
|
|
}
|
|
|
|
DBG( DBG_LOW, "P12InitAsic() done.\n" );
|
|
return _OK;
|
|
}
|
|
|
|
/*.............................................................................
|
|
* set all necessary register contents
|
|
*/
|
|
_LOC void P12SetGeneralRegister( pScanData ps )
|
|
{
|
|
DBG( DBG_LOW, "P12SetGeneralRegister()\n" );
|
|
|
|
ps->Scan.fMotorBackward = _FALSE;
|
|
ps->Scan.fRefreshState = _FALSE;
|
|
|
|
if( COLOR_BW == ps->DataInf.wPhyDataType )
|
|
ps->AsicReg.RD_ScanControl = _SCAN_BITMODE;
|
|
else {
|
|
if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 )
|
|
ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
|
|
else
|
|
ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE;
|
|
}
|
|
|
|
IOSelectLampSource( ps );
|
|
|
|
if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
|
|
ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi300;
|
|
else
|
|
ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi600;
|
|
|
|
ps->AsicReg.RD_Motor0Control = _MotorOn | _MotorHQuarterStep | _MotorPowerEnable;
|
|
ps->AsicReg.RD_ScanControl1 = _SCANSTOPONBUFFULL | _MFRC_BY_XSTEP;
|
|
ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE;
|
|
}
|
|
|
|
/* END PLUSTEK-PP_P12.C .....................................................*/
|