kopia lustrzana https://gitlab.com/sane-project/backends
2700 wiersze
76 KiB
C
2700 wiersze
76 KiB
C
/* sane - Scanner Access Now Easy.
|
|
|
|
Copyright (C) 2005 Mustek.
|
|
Originally maintained by Mustek
|
|
Author:Roy 2005.5.24
|
|
|
|
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.
|
|
|
|
This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro
|
|
and similar USB2 scanners. */
|
|
|
|
#define DEBUG_DECLARE_ONLY
|
|
#include "sane/config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <math.h>
|
|
|
|
#include "byteorder.h"
|
|
#include "sane/sane.h"
|
|
#include "sane/sanei_usb.h"
|
|
#include "sane/sanei_backend.h"
|
|
|
|
#include "mustek_usb2_asic.h"
|
|
|
|
|
|
static SANE_Status PrepareScanChip (ASIC * chip);
|
|
static SANE_Status WaitCarriageHome (ASIC * chip);
|
|
static SANE_Status WaitUnitReady (ASIC * chip);
|
|
|
|
|
|
/* ---------------------- low level ASIC functions -------------------------- */
|
|
|
|
static SANE_Status
|
|
WriteIOControl (ASIC * chip, unsigned short wValue, unsigned short wIndex,
|
|
unsigned short wLength, SANE_Byte * pBuf)
|
|
{
|
|
SANE_Status status;
|
|
|
|
status = sanei_usb_control_msg (chip->fd, 0x40, 0x01, wValue, wIndex, wLength,
|
|
pBuf);
|
|
if (status != SANE_STATUS_GOOD)
|
|
DBG (DBG_ERR, "WriteIOControl error: %s\n", sane_strstatus (status));
|
|
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
ReadIOControl (ASIC * chip, unsigned short wValue, unsigned short wIndex,
|
|
unsigned short wLength, SANE_Byte * pBuf)
|
|
{
|
|
SANE_Status status;
|
|
|
|
status = sanei_usb_control_msg (chip->fd, 0xc0, 0x01, wValue, wIndex, wLength,
|
|
pBuf);
|
|
if (status != SANE_STATUS_GOOD)
|
|
DBG (DBG_ERR, "ReadIOControl error: %s\n", sane_strstatus (status));
|
|
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
ClearFIFO (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte buf[4];
|
|
DBG_ASIC_ENTER ();
|
|
|
|
buf[0] = 0;
|
|
buf[1] = 0;
|
|
buf[2] = 0;
|
|
buf[3] = 0;
|
|
|
|
status = WriteIOControl (chip, 0x05, 0, 4, buf);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = WriteIOControl (chip, 0xc0, 0, 4, buf);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
SwitchBank (ASIC * chip, unsigned short reg)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte buf[4];
|
|
SANE_Byte bank;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
bank = HIBYTE(reg);
|
|
if (bank > SELECT_REGISTER_BANK2)
|
|
{
|
|
DBG (DBG_ERR, "invalid register %d\n", reg);
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
if (chip->RegisterBankStatus != bank)
|
|
{
|
|
buf[0] = ES01_5F_REGISTER_BANK_SELECT;
|
|
buf[1] = bank;
|
|
buf[2] = ES01_5F_REGISTER_BANK_SELECT;
|
|
buf[3] = bank;
|
|
status = WriteIOControl (chip, 0xb0, 0, 4, buf);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
chip->RegisterBankStatus = bank;
|
|
DBG (DBG_ASIC, "RegisterBankStatus=%d\n", chip->RegisterBankStatus);
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
static SANE_Status
|
|
SendData (ASIC * chip, unsigned short reg, SANE_Byte data)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte buf[4];
|
|
DBG_ASIC_ENTER ();
|
|
DBG (DBG_ASIC, "reg=%x,data=%x\n", reg, data);
|
|
|
|
status = SwitchBank (chip, reg);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
buf[0] = LOBYTE (reg);
|
|
buf[1] = data;
|
|
buf[2] = LOBYTE (reg);
|
|
buf[3] = data;
|
|
status = WriteIOControl (chip, 0xb0, 0, 4, buf);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
ReceiveData (ASIC * chip, SANE_Byte * reg)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte buf[4];
|
|
DBG_ASIC_ENTER ();
|
|
|
|
status = ReadIOControl (chip, 0x07, 0, 4, buf);
|
|
*reg = buf[0];
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
WriteAddressLineForRegister (ASIC * chip, SANE_Byte x)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte buf[4];
|
|
DBG_ASIC_ENTER ();
|
|
|
|
buf[0] = x;
|
|
buf[1] = x;
|
|
buf[2] = x;
|
|
buf[3] = x;
|
|
status = WriteIOControl (chip, 0x04, x, 4, buf);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
SetRWSize (ASIC * chip, SANE_Bool isWriteAccess, unsigned int size)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (!isWriteAccess)
|
|
size >>= 1;
|
|
|
|
status = SendData (chip, ES01_7C_DMA_SIZE_BYTE0, BYTE0 (size));
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
status = SendData (chip, ES01_7D_DMA_SIZE_BYTE1, BYTE1 (size));
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
status = SendData (chip, ES01_7E_DMA_SIZE_BYTE2, BYTE2 (size));
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
status = SendData (chip, ES01_7F_DMA_SIZE_BYTE3, BYTE3 (size));
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
DMARead (ASIC * chip, unsigned int size, SANE_Byte * pData)
|
|
{
|
|
SANE_Status status;
|
|
size_t cur_read_size;
|
|
DBG_ASIC_ENTER ();
|
|
DBG (DBG_ASIC, "size=%d\n", size);
|
|
|
|
status = ClearFIFO (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
while (size > 0)
|
|
{
|
|
cur_read_size = (size > DMA_BLOCK_SIZE) ? DMA_BLOCK_SIZE : size;
|
|
|
|
status = SetRWSize (chip, SANE_FALSE, cur_read_size);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = WriteIOControl (chip, 0x03, 0, 4, (SANE_Byte *) &cur_read_size);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = sanei_usb_read_bulk (chip->fd, pData, &cur_read_size);
|
|
if (status != SANE_STATUS_GOOD)
|
|
{
|
|
DBG (DBG_ERR, "DMA read error\n");
|
|
return status;
|
|
}
|
|
|
|
size -= cur_read_size;
|
|
pData += cur_read_size;
|
|
}
|
|
|
|
if (cur_read_size < DMA_BLOCK_SIZE)
|
|
usleep (20000);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
static SANE_Status
|
|
DMAWrite (ASIC * chip, unsigned int size, SANE_Byte * pData)
|
|
{
|
|
SANE_Status status;
|
|
size_t cur_write_size;
|
|
DBG_ASIC_ENTER ();
|
|
DBG (DBG_ASIC, "size=%d\n", size);
|
|
|
|
status = ClearFIFO (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
while (size > 0)
|
|
{
|
|
cur_write_size = (size > DMA_BLOCK_SIZE) ? DMA_BLOCK_SIZE : size;
|
|
|
|
status = SetRWSize (chip, SANE_TRUE, cur_write_size);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = WriteIOControl (chip, 0x02, 0, 4, (SANE_Byte *) &cur_write_size);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = sanei_usb_write_bulk (chip->fd, pData, &cur_write_size);
|
|
if (status != SANE_STATUS_GOOD)
|
|
{
|
|
DBG (DBG_ERR, "DMA write error\n");
|
|
return status;
|
|
}
|
|
|
|
size -= cur_write_size;
|
|
pData += cur_write_size;
|
|
}
|
|
|
|
status = ClearFIFO (chip);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
SendData2Byte (ASIC * chip, unsigned short reg, SANE_Byte data)
|
|
{
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (!chip->is2ByteTransfer)
|
|
{
|
|
chip->dataBuf[0] = LOBYTE (reg);
|
|
chip->dataBuf[1] = data;
|
|
chip->is2ByteTransfer = SANE_TRUE;
|
|
}
|
|
else
|
|
{
|
|
chip->dataBuf[2] = LOBYTE (reg);
|
|
chip->dataBuf[3] = data;
|
|
chip->is2ByteTransfer = SANE_FALSE;
|
|
|
|
status = SwitchBank (chip, reg);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = WriteIOControl (chip, 0xb0, 0, 4, chip->dataBuf);
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
|
|
/* ---------------------- ASIC motor functions ----------------------------- */
|
|
|
|
static SANE_Status
|
|
SetRamAddress (ASIC * chip, unsigned int dwStartAddr, unsigned int dwEndAddr,
|
|
RAM_TYPE AccessTarget)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
/* Set start address. Unit is a word. */
|
|
SendData (chip, ES01_A0_HostStartAddr0_7, BYTE0 (dwStartAddr));
|
|
|
|
if (AccessTarget == ON_CHIP_FINAL_GAMMA)
|
|
{
|
|
SendData (chip, ES01_A1_HostStartAddr8_15,
|
|
BYTE1 (dwStartAddr) | ACCESS_FINAL_GAMMA_ES01);
|
|
SendData (chip, ES01_A2_HostStartAddr16_21,
|
|
BYTE2 (dwStartAddr) | ACCESS_GAMMA_RAM);
|
|
}
|
|
else if (AccessTarget == ON_CHIP_PRE_GAMMA)
|
|
{
|
|
SendData (chip, ES01_A1_HostStartAddr8_15,
|
|
BYTE1 (dwStartAddr) | ACCESS_PRE_GAMMA_ES01);
|
|
SendData (chip, ES01_A2_HostStartAddr16_21,
|
|
BYTE2 (dwStartAddr) | ACCESS_GAMMA_RAM);
|
|
}
|
|
else /* DRAM */
|
|
{
|
|
SendData (chip, ES01_A1_HostStartAddr8_15, BYTE1 (dwStartAddr));
|
|
SendData (chip, ES01_A2_HostStartAddr16_21,
|
|
BYTE2 (dwStartAddr) | ACCESS_DRAM);
|
|
}
|
|
|
|
/* Set end address. */
|
|
SendData (chip, ES01_A3_HostEndAddr0_7, BYTE0 (dwEndAddr));
|
|
SendData (chip, ES01_A4_HostEndAddr8_15, BYTE1 (dwEndAddr));
|
|
SendData (chip, ES01_A5_HostEndAddr16_21, BYTE2 (dwEndAddr));
|
|
|
|
status = ClearFIFO (chip);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
RamAccess (ASIC * chip, RAMACCESS * access)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte a[2];
|
|
DBG_ASIC_ENTER ();
|
|
|
|
status = SetRamAddress (chip, access->StartAddress, 0xffffff,
|
|
access->RamType);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
SendData (chip, ES01_79_AFEMCLK_SDRAMCLK_DELAY_CONTROL, SDRAMCLK_DELAY_12_ns);
|
|
|
|
if (access->IsWriteAccess)
|
|
{
|
|
status = DMAWrite (chip, access->RwSize, access->BufferPtr);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
/* steal read 2 byte */
|
|
usleep (20000);
|
|
access->RwSize = 2;
|
|
access->BufferPtr = a;
|
|
access->IsWriteAccess = SANE_FALSE;
|
|
status = RamAccess (chip, access);
|
|
DBG (DBG_ASIC, "stole 2 bytes!\n");
|
|
}
|
|
else
|
|
{
|
|
status = DMARead (chip, access->RwSize, access->BufferPtr);
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static void
|
|
SetMotorCurrentAndPhase (ASIC * chip,
|
|
MOTOR_CURRENT_AND_PHASE * MotorCurrentAndPhase)
|
|
{
|
|
static const SANE_Byte MotorPhaseFullStep[] =
|
|
{ 0x08, 0x09, 0x01, 0x00 };
|
|
static const SANE_Byte MotorPhaseHalfStep[] =
|
|
{ 0x25, 0x07, 0x24, 0x30, 0x2c, 0x0e, 0x2d, 0x39 };
|
|
|
|
SANE_Byte MotorPhaseMask;
|
|
int i;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (MotorCurrentAndPhase->MotorDriverIs3967 == 1)
|
|
MotorPhaseMask = 0xFE;
|
|
else
|
|
MotorPhaseMask = 0xFF;
|
|
DBG (DBG_ASIC, "MotorPhaseMask=0x%x\n", MotorPhaseMask);
|
|
|
|
SendData (chip, ES02_50_MOTOR_CURRENT_CONTORL, DOWN_LOAD_MOTOR_TABLE_ENABLE);
|
|
|
|
if (MotorCurrentAndPhase->MoveType == _4_TABLE_SPACE_FOR_FULL_STEP)
|
|
{
|
|
SendData (chip, ES01_AB_PWM_CURRENT_CONTROL,
|
|
MOTOR_PWM_CURRENT_0 | MOTOR1_GPO_VALUE_0);
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A,
|
|
MotorCurrentAndPhase->MotorCurrent);
|
|
SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B,
|
|
MotorCurrentAndPhase->MotorCurrent);
|
|
SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1,
|
|
MotorPhaseFullStep[i] & MotorPhaseMask);
|
|
}
|
|
}
|
|
else if (MotorCurrentAndPhase->MoveType == _8_TABLE_SPACE_FOR_1_DIV_2_STEP)
|
|
{
|
|
SendData (chip, ES01_AB_PWM_CURRENT_CONTROL,
|
|
MOTOR_PWM_CURRENT_1 | MOTOR1_GPO_VALUE_0);
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A,
|
|
MotorCurrentAndPhase->MotorCurrent);
|
|
SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B,
|
|
MotorCurrentAndPhase->MotorCurrent);
|
|
SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1,
|
|
MotorPhaseHalfStep[i] & MotorPhaseMask);
|
|
}
|
|
}
|
|
else if (MotorCurrentAndPhase->MoveType == _16_TABLE_SPACE_FOR_1_DIV_4_STEP)
|
|
{
|
|
SendData (chip, ES01_AB_PWM_CURRENT_CONTROL,
|
|
MOTOR_PWM_CURRENT_2 | MOTOR1_GPO_VALUE_0);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
double x = (((i % 4) * M_PI * 90) / 4) / 180;
|
|
SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte)
|
|
(MotorCurrentAndPhase->MotorCurrent * sin (x)));
|
|
SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte)
|
|
(MotorCurrentAndPhase->MotorCurrent * cos (x)));
|
|
SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1,
|
|
MotorPhaseFullStep[i / 4] & MotorPhaseMask);
|
|
}
|
|
}
|
|
else if (MotorCurrentAndPhase->MoveType == _32_TABLE_SPACE_FOR_1_DIV_8_STEP)
|
|
{
|
|
SendData (chip, ES01_AB_PWM_CURRENT_CONTROL,
|
|
MOTOR_PWM_CURRENT_3 | MOTOR1_GPO_VALUE_0);
|
|
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
double x = (((i % 8) * M_PI * 90) / 8) / 180;
|
|
SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte)
|
|
(MotorCurrentAndPhase->MotorCurrent * sin (x)));
|
|
SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte)
|
|
(MotorCurrentAndPhase->MotorCurrent * cos (x)));
|
|
SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1,
|
|
MotorPhaseFullStep[i / 8] & MotorPhaseMask);
|
|
}
|
|
}
|
|
|
|
SendData (chip, ES02_50_MOTOR_CURRENT_CONTORL,
|
|
MotorCurrentAndPhase->MoveType);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static SANE_Status
|
|
SetMotorTable (ASIC * chip, unsigned int dwTableBaseAddr,
|
|
unsigned short * MotorTablePtr)
|
|
{
|
|
SANE_Status status;
|
|
RAMACCESS access;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
access.IsWriteAccess = SANE_TRUE;
|
|
access.RamType = EXTERNAL_RAM;
|
|
access.StartAddress = dwTableBaseAddr;
|
|
access.RwSize = MOTOR_TABLE_SIZE * sizeof (unsigned short);
|
|
access.BufferPtr = (SANE_Byte *) MotorTablePtr;
|
|
|
|
status = RamAccess (chip, &access);
|
|
|
|
/* tell scan chip the motor table address, unit is 2^14 words */
|
|
SendData (chip, ES01_9D_MotorTableAddrA14_A21,
|
|
(SANE_Byte) (dwTableBaseAddr >> TABLE_OFFSET_BASE));
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
SetShadingTable (ASIC * chip, unsigned int dwTableBaseAddr,
|
|
unsigned int dwTableSize, unsigned short * ShadingTablePtr)
|
|
{
|
|
SANE_Status status;
|
|
RAMACCESS access;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
access.IsWriteAccess = SANE_TRUE;
|
|
access.RamType = EXTERNAL_RAM;
|
|
access.StartAddress = dwTableBaseAddr;
|
|
access.RwSize = dwTableSize;
|
|
access.BufferPtr = (SANE_Byte *) ShadingTablePtr;
|
|
|
|
status = RamAccess (chip, &access);
|
|
|
|
/* tell scan chip the shading table address, unit is 2^14 words */
|
|
SendData (chip, ES01_9B_ShadingTableAddrA14_A21,
|
|
(SANE_Byte) (dwTableBaseAddr >> TABLE_OFFSET_BASE));
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
MotorMove (ASIC * chip, MOTORMOVE * Move)
|
|
{
|
|
SANE_Status status;
|
|
unsigned int motor_steps;
|
|
SANE_Byte temp_motor_action;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
status = PrepareScanChip (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
DBG (DBG_ASIC, "set start/end pixel\n");
|
|
|
|
SendData (chip, ES01_B8_ChannelRedExpStartPixelLSB, LOBYTE (100));
|
|
SendData (chip, ES01_B9_ChannelRedExpStartPixelMSB, HIBYTE (100));
|
|
SendData (chip, ES01_BA_ChannelRedExpEndPixelLSB, LOBYTE (101));
|
|
SendData (chip, ES01_BB_ChannelRedExpEndPixelMSB, HIBYTE (101));
|
|
|
|
SendData (chip, ES01_BC_ChannelGreenExpStartPixelLSB, LOBYTE (100));
|
|
SendData (chip, ES01_BD_ChannelGreenExpStartPixelMSB, HIBYTE (100));
|
|
SendData (chip, ES01_BE_ChannelGreenExpEndPixelLSB, LOBYTE (101));
|
|
SendData (chip, ES01_BF_ChannelGreenExpEndPixelMSB, HIBYTE (101));
|
|
|
|
SendData (chip, ES01_C0_ChannelBlueExpStartPixelLSB, LOBYTE (100));
|
|
SendData (chip, ES01_C1_ChannelBlueExpStartPixelMSB, HIBYTE (100));
|
|
SendData (chip, ES01_C2_ChannelBlueExpEndPixelLSB, LOBYTE (101));
|
|
SendData (chip, ES01_C3_ChannelBlueExpEndPixelMSB, HIBYTE (101));
|
|
|
|
/* set motor acceleration steps, max. 511 steps */
|
|
SendData (chip, ES01_E0_MotorAccStep0_7, LOBYTE (Move->AccStep));
|
|
SendData (chip, ES01_E1_MotorAccStep8_8, HIBYTE (Move->AccStep));
|
|
DBG (DBG_ASIC, "AccStep=%d\n", Move->AccStep);
|
|
|
|
/* set motor deceleration steps, max. 255 steps */
|
|
SendData (chip, ES01_E5_MotorDecStep, Move->DecStep);
|
|
DBG (DBG_ASIC, "DecStep=%d\n", Move->DecStep);
|
|
|
|
/* Set motor uniform speed.
|
|
Only used for UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE. If you use acc mode,
|
|
these two registers are not used. */
|
|
SendData (chip, ES01_FD_MotorFixedspeedLSB, LOBYTE (Move->FixMoveSpeed));
|
|
SendData (chip, ES01_FE_MotorFixedspeedMSB, HIBYTE (Move->FixMoveSpeed));
|
|
DBG (DBG_ASIC, "FixMoveSpeed=%d\n", Move->FixMoveSpeed);
|
|
|
|
/* set motor type */
|
|
SendData (chip, ES01_A6_MotorOption,
|
|
MOTOR_0_ENABLE | HOME_SENSOR_0_ENABLE | TABLE_DEFINE_ES03);
|
|
|
|
/* Set motor speed unit for all motor modes, including uniform. */
|
|
SendData (chip, ES01_F6_MotorControl1,
|
|
SPEED_UNIT_1_PIXEL_TIME | MOTOR_SYNC_UNIT_1_PIXEL_TIME);
|
|
|
|
if (Move->ActionType == ACTION_TYPE_BACKTOHOME)
|
|
{
|
|
DBG (DBG_ASIC, "ACTION_TYPE_BACKTOHOME\n");
|
|
temp_motor_action = MOTOR_BACK_HOME_AFTER_SCAN_ENABLE;
|
|
motor_steps = 30000 * 2;
|
|
}
|
|
else
|
|
{
|
|
DBG (DBG_ASIC, "forward or backward\n");
|
|
temp_motor_action = MOTOR_MOVE_TO_FIRST_LINE_ENABLE;
|
|
motor_steps = Move->FixMoveSteps;
|
|
|
|
if (Move->ActionType == ACTION_TYPE_BACKWARD)
|
|
{
|
|
DBG (DBG_ASIC, "ACTION_TYPE_BACKWARD\n");
|
|
temp_motor_action |= INVERT_MOTOR_DIRECTION_ENABLE;
|
|
}
|
|
}
|
|
|
|
SendData (chip, ES01_94_PowerSaveControl,
|
|
TIMER_POWER_SAVE_ENABLE |
|
|
USB_POWER_SAVE_ENABLE | USB_REMOTE_WAKEUP_ENABLE |
|
|
LED_MODE_FLASH_SLOWLY);
|
|
|
|
/* set number of movement steps with fixed speed */
|
|
SendData (chip, ES01_E2_MotorStepOfMaxSpeed0_7, BYTE0 (motor_steps));
|
|
SendData (chip, ES01_E3_MotorStepOfMaxSpeed8_15, BYTE1 (motor_steps));
|
|
SendData (chip, ES01_E4_MotorStepOfMaxSpeed16_19, BYTE2 (motor_steps));
|
|
DBG (DBG_ASIC, "motor_steps=%d\n", motor_steps);
|
|
|
|
if (Move->ActionMode == ACTION_MODE_UNIFORM_SPEED_MOVE)
|
|
temp_motor_action |= UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE;
|
|
|
|
SendData (chip, ES01_F3_ActionOption, temp_motor_action);
|
|
SendData (chip, ES01_F4_ActiveTrigger, ACTION_TRIGGER_ENABLE);
|
|
|
|
if (Move->ActionType == ACTION_TYPE_BACKTOHOME)
|
|
{
|
|
status = WaitCarriageHome (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
}
|
|
|
|
status = WaitUnitReady (chip);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static void
|
|
SetMotorStepTable (ASIC * chip, MOTORMOVE * MotorStepsTable,
|
|
unsigned short wStartY, unsigned int dwScanImageSteps,
|
|
unsigned short wYResolution)
|
|
{
|
|
unsigned short wAccSteps = 511;
|
|
unsigned short wForwardSteps = 20;
|
|
SANE_Byte bDecSteps = 255;
|
|
unsigned short wScanAccSteps = 511;
|
|
unsigned short wFixScanSteps = 20;
|
|
SANE_Byte bScanDecSteps = 255;
|
|
unsigned short wScanBackTrackingSteps = 40;
|
|
unsigned short wScanRestartSteps = 40;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
switch (wYResolution)
|
|
{
|
|
case 2400:
|
|
case 1200:
|
|
wScanAccSteps = 100;
|
|
bScanDecSteps = 10;
|
|
wScanBackTrackingSteps = 10;
|
|
wScanRestartSteps = 10;
|
|
break;
|
|
case 600:
|
|
case 300:
|
|
wScanAccSteps = 300;
|
|
bScanDecSteps = 40;
|
|
break;
|
|
case 150:
|
|
wScanAccSteps = 300;
|
|
bScanDecSteps = 40;
|
|
break;
|
|
case 100:
|
|
case 75:
|
|
case 50:
|
|
wScanAccSteps = 300;
|
|
bScanDecSteps = 40;
|
|
break;
|
|
}
|
|
|
|
/* not including T0,T1 steps */
|
|
if (wStartY < (wAccSteps + wForwardSteps + bDecSteps + wScanAccSteps))
|
|
{
|
|
wAccSteps = 1;
|
|
bDecSteps = 1;
|
|
wFixScanSteps = (short)(wStartY - wScanAccSteps) > 0 ?
|
|
(wStartY - wScanAccSteps) : 0;
|
|
wForwardSteps = 0;
|
|
|
|
chip->isMotorMoveToFirstLine = 0;
|
|
}
|
|
else
|
|
{
|
|
wForwardSteps = (short)(wStartY - wAccSteps - (unsigned short) bDecSteps -
|
|
wScanAccSteps - wFixScanSteps) > 0 ?
|
|
(wStartY - wAccSteps - (unsigned short) bDecSteps - wScanAccSteps -
|
|
wFixScanSteps) : 0;
|
|
|
|
chip->isMotorMoveToFirstLine = MOTOR_MOVE_TO_FIRST_LINE_ENABLE;
|
|
}
|
|
|
|
dwScanImageSteps += wAccSteps;
|
|
dwScanImageSteps += wForwardSteps;
|
|
dwScanImageSteps += bDecSteps;
|
|
dwScanImageSteps += wScanAccSteps;
|
|
dwScanImageSteps += wFixScanSteps;
|
|
dwScanImageSteps += bScanDecSteps;
|
|
dwScanImageSteps += 2;
|
|
|
|
MotorStepsTable->wScanAccSteps = wScanAccSteps;
|
|
MotorStepsTable->bScanDecSteps = bScanDecSteps;
|
|
|
|
/* state 1 */
|
|
SendData (chip, ES01_E0_MotorAccStep0_7, LOBYTE (wAccSteps));
|
|
SendData (chip, ES01_E1_MotorAccStep8_8, HIBYTE (wAccSteps));
|
|
/* state 2 */
|
|
SendData (chip, ES01_E2_MotorStepOfMaxSpeed0_7, LOBYTE (wForwardSteps));
|
|
SendData (chip, ES01_E3_MotorStepOfMaxSpeed8_15, HIBYTE (wForwardSteps));
|
|
SendData (chip, ES01_E4_MotorStepOfMaxSpeed16_19, 0);
|
|
/* state 3 */
|
|
SendData (chip, ES01_E5_MotorDecStep, bDecSteps);
|
|
/* state 4 */
|
|
SendData (chip, ES01_AE_MotorSyncPixelNumberM16LSB, 0);
|
|
SendData (chip, ES01_AF_MotorSyncPixelNumberM16MSB, 0);
|
|
/* state 5 */
|
|
SendData (chip, ES01_EC_ScanAccStep0_7, LOBYTE (wScanAccSteps));
|
|
SendData (chip, ES01_ED_ScanAccStep8_8, HIBYTE (wScanAccSteps));
|
|
/* state 6 */
|
|
SendData (chip, ES01_EE_FixScanStepLSB, LOBYTE (wFixScanSteps));
|
|
SendData (chip, ES01_8A_FixScanStepMSB, HIBYTE (wFixScanSteps));
|
|
/* state 8 */
|
|
SendData (chip, ES01_EF_ScanDecStep, bScanDecSteps);
|
|
/* state 10 */
|
|
SendData (chip, ES01_E6_ScanBackTrackingStepLSB,
|
|
LOBYTE (wScanBackTrackingSteps));
|
|
SendData (chip, ES01_E7_ScanBackTrackingStepMSB,
|
|
HIBYTE (wScanBackTrackingSteps));
|
|
/* state 15 */
|
|
SendData (chip, ES01_E8_ScanRestartStepLSB, LOBYTE (wScanRestartSteps));
|
|
SendData (chip, ES01_E9_ScanRestartStepMSB, HIBYTE (wScanRestartSteps));
|
|
/* state 19 */
|
|
SendData (chip, ES01_EA_ScanBackHomeExtStepLSB, LOBYTE (100));
|
|
SendData (chip, ES01_EB_ScanBackHomeExtStepMSB, HIBYTE (100));
|
|
|
|
/* total motor steps */
|
|
SendData (chip, ES01_F0_ScanImageStep0_7, BYTE0 (dwScanImageSteps));
|
|
SendData (chip, ES01_F1_ScanImageStep8_15, BYTE1 (dwScanImageSteps));
|
|
SendData (chip, ES01_F2_ScanImageStep16_19, BYTE2 (dwScanImageSteps));
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static void
|
|
SetMotorStepTableForCalibration (ASIC * chip, MOTORMOVE * MotorStepsTable,
|
|
unsigned int dwScanImageSteps)
|
|
{
|
|
unsigned short wScanAccSteps = 1;
|
|
SANE_Byte bScanDecSteps = 1;
|
|
unsigned short wFixScanSteps = 0;
|
|
unsigned short wScanBackTrackingSteps = 20;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
chip->isMotorMoveToFirstLine = 0;
|
|
|
|
dwScanImageSteps += wScanAccSteps;
|
|
dwScanImageSteps += wFixScanSteps;
|
|
dwScanImageSteps += bScanDecSteps;
|
|
|
|
MotorStepsTable->wScanAccSteps = wScanAccSteps;
|
|
MotorStepsTable->bScanDecSteps = bScanDecSteps;
|
|
|
|
/* state 4 */
|
|
SendData (chip, ES01_AE_MotorSyncPixelNumberM16LSB, 0);
|
|
SendData (chip, ES01_AF_MotorSyncPixelNumberM16MSB, 0);
|
|
/* state 5 */
|
|
SendData (chip, ES01_EC_ScanAccStep0_7, LOBYTE (wScanAccSteps));
|
|
SendData (chip, ES01_ED_ScanAccStep8_8, HIBYTE (wScanAccSteps));
|
|
/* state 6 */
|
|
SendData (chip, ES01_EE_FixScanStepLSB, LOBYTE (wFixScanSteps));
|
|
SendData (chip, ES01_8A_FixScanStepMSB, HIBYTE (wFixScanSteps));
|
|
/* state 8 */
|
|
SendData (chip, ES01_EF_ScanDecStep, bScanDecSteps);
|
|
/* state 10 */
|
|
SendData (chip, ES01_E6_ScanBackTrackingStepLSB,
|
|
LOBYTE (wScanBackTrackingSteps));
|
|
SendData (chip, ES01_E7_ScanBackTrackingStepMSB,
|
|
HIBYTE (wScanBackTrackingSteps));
|
|
/* state 15 */
|
|
SendData (chip, ES01_E8_ScanRestartStepLSB,
|
|
LOBYTE (wScanBackTrackingSteps));
|
|
SendData (chip, ES01_E9_ScanRestartStepMSB,
|
|
HIBYTE (wScanBackTrackingSteps));
|
|
|
|
SendData (chip, ES01_F0_ScanImageStep0_7, BYTE0 (dwScanImageSteps));
|
|
SendData (chip, ES01_F1_ScanImageStep8_15, BYTE1 (dwScanImageSteps));
|
|
SendData (chip, ES01_F2_ScanImageStep16_19, BYTE2 (dwScanImageSteps));
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static void
|
|
CalculateScanMotorTable (CALCULATEMOTORTABLE * pCalculateMotorTable)
|
|
{
|
|
unsigned short wEndSpeed, wStartSpeed;
|
|
unsigned short wScanAccSteps;
|
|
SANE_Byte bScanDecSteps;
|
|
unsigned short * pMotorTable;
|
|
long double y;
|
|
unsigned short i;
|
|
|
|
wStartSpeed = pCalculateMotorTable->StartSpeed;
|
|
wEndSpeed = pCalculateMotorTable->EndSpeed;
|
|
wScanAccSteps = pCalculateMotorTable->AccStepBeforeScan;
|
|
bScanDecSteps = pCalculateMotorTable->DecStepAfterScan;
|
|
pMotorTable = pCalculateMotorTable->pMotorTable;
|
|
|
|
/* motor T0 & T6 acc table */
|
|
for (i = 0; i < 512; i++)
|
|
{
|
|
y = 6000 - 3500;
|
|
y *= pow (0.09, (M_PI_2 * i) / 512) - pow (0.09, (M_PI_2 * 511) / 512);
|
|
y += 4500;
|
|
pMotorTable[i] = htole16 ((unsigned short) y); /* T0 */
|
|
pMotorTable[i + 512 * 6] = htole16 ((unsigned short) y); /* T6 */
|
|
}
|
|
|
|
/* motor T1 & T7 dec table */
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
y = 6000 - 3500;
|
|
y *= pow (0.3, (M_PI_2 * i) / 256);
|
|
y = 6000 - y;
|
|
pMotorTable[i + 512] = htole16 ((unsigned short) y); /* T1 */
|
|
pMotorTable[i + 512 * 7] = htole16 ((unsigned short) y); /* T7 */
|
|
}
|
|
|
|
for (i = 0; i < wScanAccSteps; i++)
|
|
{
|
|
y = wStartSpeed - wEndSpeed;
|
|
y *= pow (0.09, (M_PI_2 * i) / wScanAccSteps) -
|
|
pow (0.09, (M_PI_2 * (wScanAccSteps - 1)) / wScanAccSteps);
|
|
y += wEndSpeed;
|
|
pMotorTable[i + 512 * 2] = htole16 ((unsigned short) y); /* T2 */
|
|
pMotorTable[i + 512 * 4] = htole16 ((unsigned short) y); /* T4 */
|
|
}
|
|
for (i = wScanAccSteps; i < 512; i++)
|
|
{
|
|
pMotorTable[i + 512 * 2] = htole16 (wEndSpeed); /* T2 */
|
|
pMotorTable[i + 512 * 4] = htole16 (wEndSpeed); /* T4 */
|
|
}
|
|
|
|
for (i = 0; i < (unsigned short) bScanDecSteps; i++)
|
|
{
|
|
y = wStartSpeed - wEndSpeed;
|
|
y *= pow (0.3, (M_PI_2 * i) / bScanDecSteps);
|
|
y = wStartSpeed - y;
|
|
pMotorTable[i + 512 * 3] = htole16 ((unsigned short) y); /* T3 */
|
|
pMotorTable[i + 512 * 5] = htole16 ((unsigned short) y); /* T5 */
|
|
}
|
|
for (i = bScanDecSteps; i < 256; i++)
|
|
{
|
|
pMotorTable[i + 512 * 3] = htole16 (wStartSpeed); /* T3 */
|
|
pMotorTable[i + 512 * 5] = htole16 (wStartSpeed); /* T5 */
|
|
}
|
|
}
|
|
|
|
static void
|
|
CalculateMoveMotorTable (CALCULATEMOTORTABLE * pCalculateMotorTable)
|
|
{
|
|
unsigned short wEndSpeed, wStartSpeed;
|
|
unsigned short wScanAccSteps;
|
|
unsigned short * pMotorTable;
|
|
long double y;
|
|
unsigned short i;
|
|
|
|
wStartSpeed = pCalculateMotorTable->StartSpeed;
|
|
wEndSpeed = pCalculateMotorTable->EndSpeed;
|
|
wScanAccSteps = pCalculateMotorTable->AccStepBeforeScan;
|
|
pMotorTable = pCalculateMotorTable->pMotorTable;
|
|
|
|
for (i = 0; i < 512; i++)
|
|
{
|
|
/* before scan acc table */
|
|
y = (wStartSpeed - wEndSpeed) *
|
|
pow (0.09, (M_PI_2 * i) / 512) + wEndSpeed;
|
|
pMotorTable[i] = htole16 ((unsigned short) y);
|
|
pMotorTable[i + 512 * 2] = htole16 ((unsigned short) y);
|
|
pMotorTable[i + 512 * 4] = htole16 ((unsigned short) y);
|
|
pMotorTable[i + 512 * 6] = htole16 ((unsigned short) y);
|
|
}
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
y = wStartSpeed - (wStartSpeed - wEndSpeed) *
|
|
pow (0.3, (M_PI_2 * i) / 256);
|
|
pMotorTable[i + 512] = htole16 ((unsigned short) y);
|
|
pMotorTable[i + 512 * 3] = htole16 ((unsigned short) y);
|
|
pMotorTable[i + 512 * 5] = htole16 ((unsigned short) y);
|
|
pMotorTable[i + 512 * 7] = htole16 ((unsigned short) y);
|
|
}
|
|
|
|
for (i = 0; i < wScanAccSteps; i++)
|
|
{
|
|
y = (wStartSpeed - wEndSpeed) *
|
|
(pow (0.09, (M_PI_2 * i) / wScanAccSteps) -
|
|
pow (0.09, (M_PI_2 * (wScanAccSteps - 1)) / wScanAccSteps)) +
|
|
wEndSpeed;
|
|
pMotorTable[i + 512 * 2] = htole16 ((unsigned short) y);
|
|
}
|
|
}
|
|
|
|
static SANE_Byte
|
|
CalculateMotorCurrent (unsigned short dwMotorSpeed)
|
|
{
|
|
if (dwMotorSpeed < 2000)
|
|
return 255;
|
|
else if (dwMotorSpeed < 3500)
|
|
return 200;
|
|
else if (dwMotorSpeed < 5000)
|
|
return 160;
|
|
else if (dwMotorSpeed < 10000)
|
|
return 70;
|
|
else if (dwMotorSpeed < 17000)
|
|
return 60;
|
|
else /* >= 17000 */
|
|
return 50;
|
|
}
|
|
|
|
static SANE_Status
|
|
SimpleMotorMove (ASIC * chip,
|
|
unsigned short wStartSpeed, unsigned short wEndSpeed,
|
|
unsigned int dwFixMoveSpeed, SANE_Byte bMotorCurrent,
|
|
unsigned int dwTotalSteps, SANE_Byte bActionType)
|
|
{
|
|
SANE_Status status;
|
|
unsigned short * MotorTable;
|
|
CALCULATEMOTORTABLE CalMotorTable;
|
|
MOTOR_CURRENT_AND_PHASE CurrentPhase;
|
|
MOTORMOVE Move;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
MotorTable = malloc (MOTOR_TABLE_SIZE * sizeof (unsigned short));
|
|
if (!MotorTable)
|
|
{
|
|
DBG (DBG_ASIC, "MotorTable == NULL\n");
|
|
return SANE_STATUS_NO_MEM;
|
|
}
|
|
|
|
CalMotorTable.StartSpeed = wStartSpeed;
|
|
CalMotorTable.EndSpeed = wEndSpeed;
|
|
CalMotorTable.AccStepBeforeScan = 511;
|
|
CalMotorTable.pMotorTable = MotorTable;
|
|
CalculateMoveMotorTable (&CalMotorTable);
|
|
|
|
CurrentPhase.MoveType = _4_TABLE_SPACE_FOR_FULL_STEP;
|
|
CurrentPhase.MotorDriverIs3967 = 0;
|
|
CurrentPhase.MotorCurrent = bMotorCurrent;
|
|
SetMotorCurrentAndPhase (chip, &CurrentPhase);
|
|
|
|
status = SetMotorTable (chip, 0x3000, MotorTable);
|
|
free (MotorTable);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
Move.ActionType = bActionType;
|
|
if (dwTotalSteps >= 766)
|
|
{
|
|
Move.ActionMode = ACTION_MODE_ACCDEC_MOVE;
|
|
Move.AccStep = 511;
|
|
Move.DecStep = 255;
|
|
}
|
|
else
|
|
{
|
|
Move.ActionMode = ACTION_MODE_UNIFORM_SPEED_MOVE;
|
|
Move.AccStep = 1;
|
|
Move.DecStep = 1;
|
|
}
|
|
Move.FixMoveSteps = dwTotalSteps - (Move.AccStep + Move.DecStep);
|
|
Move.FixMoveSpeed = dwFixMoveSpeed;
|
|
status = MotorMove (chip, &Move);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
|
|
/* ---------------------- medium level ASIC functions ---------------------- */
|
|
|
|
static void
|
|
InitTiming (ASIC * chip)
|
|
{
|
|
chip->Timing.AFE_ADCCLK_Timing = 0x3c3c3c00;
|
|
chip->Timing.AFE_ADCVS_Timing = 0x00c00000;
|
|
chip->Timing.AFE_ADCRS_Timing = 0x00000c00;
|
|
chip->Timing.AFE_ChannelA_LatchPos = 3080;
|
|
chip->Timing.AFE_ChannelB_LatchPos = 3602;
|
|
chip->Timing.AFE_ChannelC_LatchPos = 5634;
|
|
chip->Timing.AFE_ChannelD_LatchPos = 1546;
|
|
chip->Timing.AFE_Secondary_FF_LatchPos = 12;
|
|
|
|
chip->Timing.CCD_DummyCycleTiming = 0;
|
|
chip->Timing.PHTG_PulseWidth = 12;
|
|
chip->Timing.PHTG_WaitWidth = 1;
|
|
chip->Timing.PHTG_TimingAdj = 1;
|
|
chip->Timing.PHTG_TimingSetup = 0;
|
|
chip->Timing.ChannelR_StartPixel = 100;
|
|
chip->Timing.ChannelR_EndPixel = 200;
|
|
chip->Timing.ChannelG_StartPixel = 100;
|
|
chip->Timing.ChannelG_EndPixel = 200;
|
|
chip->Timing.ChannelB_StartPixel = 100;
|
|
chip->Timing.ChannelB_EndPixel = 200;
|
|
|
|
chip->Timing.CCD_PH2_Timing = 0x000fff00;
|
|
chip->Timing.CCD_PHRS_Timing = 0x000f0000;
|
|
chip->Timing.CCD_PHCP_Timing = 0x0000f000;
|
|
chip->Timing.CCD_PH1_Timing = 0xfff00000;
|
|
|
|
chip->Timing.wCCDPixelNumber_Full = 11250;
|
|
chip->Timing.wCCDPixelNumber_Half = 7500;
|
|
}
|
|
|
|
static SANE_Status
|
|
OpenScanChip (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte x[4];
|
|
DBG_ASIC_ENTER ();
|
|
|
|
x[0] = 0x64;
|
|
x[1] = 0x64;
|
|
x[2] = 0x64;
|
|
x[3] = 0x64;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
x[0] = 0x65;
|
|
x[1] = 0x65;
|
|
x[2] = 0x65;
|
|
x[3] = 0x65;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
x[0] = 0x44;
|
|
x[1] = 0x44;
|
|
x[2] = 0x44;
|
|
x[3] = 0x44;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
x[0] = 0x45;
|
|
x[1] = 0x45;
|
|
x[2] = 0x45;
|
|
x[3] = 0x45;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
CloseScanChip (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte x[4];
|
|
DBG_ASIC_ENTER ();
|
|
|
|
x[0] = 0x64;
|
|
x[1] = 0x64;
|
|
x[2] = 0x64;
|
|
x[3] = 0x64;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
x[0] = 0x65;
|
|
x[1] = 0x65;
|
|
x[2] = 0x65;
|
|
x[3] = 0x65;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
x[0] = 0x16;
|
|
x[1] = 0x16;
|
|
x[2] = 0x16;
|
|
x[3] = 0x16;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
x[0] = 0x17;
|
|
x[1] = 0x17;
|
|
x[2] = 0x17;
|
|
x[3] = 0x17;
|
|
status = WriteIOControl (chip, 0x90, 0, 4, x);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
PrepareScanChip (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
SendData (chip, ES01_F3_ActionOption, 0);
|
|
SendData (chip, ES01_86_DisableAllClockWhenIdle, 0);
|
|
SendData (chip, ES01_F4_ActiveTrigger, 0);
|
|
|
|
status = WaitUnitReady (chip);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
TestDRAM (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
RAMACCESS access;
|
|
SANE_Byte buf[DRAM_TEST_SIZE];
|
|
unsigned int i;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
for (i = 0; i < sizeof (buf); i++)
|
|
buf[i] = i;
|
|
|
|
access.IsWriteAccess = SANE_TRUE;
|
|
access.RamType = EXTERNAL_RAM;
|
|
access.StartAddress = 0;
|
|
access.RwSize = sizeof (buf);
|
|
access.BufferPtr = buf;
|
|
|
|
status = RamAccess (chip, &access);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
memset (buf, 0, sizeof (buf));
|
|
|
|
access.IsWriteAccess = SANE_FALSE;
|
|
|
|
status = RamAccess (chip, &access);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
for (i = 0; i < sizeof (buf); i++)
|
|
{
|
|
if (buf[i] != i)
|
|
{
|
|
DBG (DBG_ERR, "DRAM test error at offset %d\n", i);
|
|
return SANE_STATUS_IO_ERROR;
|
|
}
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
static SANE_Status
|
|
SafeInitialChip (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
status = PrepareScanChip (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
DBG (DBG_ASIC, "isFirstOpenChip=%d\n", chip->isFirstOpenChip);
|
|
if (chip->isFirstOpenChip)
|
|
{
|
|
status = TestDRAM (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
chip->isFirstOpenChip = SANE_FALSE;
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
GetChipStatus (ASIC * chip, SANE_Byte Selector, SANE_Byte * ChipStatus)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
status = SendData (chip, ES01_8B_Status, Selector);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = WriteAddressLineForRegister (chip, ES01_8B_Status);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
if (ChipStatus)
|
|
status = ReceiveData (chip, ChipStatus);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
IsCarriageHome (ASIC * chip, SANE_Bool * LampHome)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte temp;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
status = GetChipStatus (chip, H1H0L1L0_PS_MJ, &temp);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
*LampHome = (temp & SENSOR0_DETECTED) ? SANE_TRUE : SANE_FALSE;
|
|
DBG (DBG_ASIC, "LampHome=%d\n", *LampHome);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
static SANE_Status
|
|
WaitCarriageHome (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Bool LampHome;
|
|
int i;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
for (i = 0; i < 100; i++)
|
|
{
|
|
status = IsCarriageHome (chip, &LampHome);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
if (LampHome)
|
|
break;
|
|
usleep (300000);
|
|
}
|
|
DBG (DBG_ASIC, "waited %d s\n", (unsigned short) (i * 0.3));
|
|
|
|
status = SendData (chip, ES01_F4_ActiveTrigger, 0);
|
|
if ((status == SANE_STATUS_GOOD) && (i == 100))
|
|
status = SANE_STATUS_DEVICE_BUSY;
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
static SANE_Status
|
|
WaitUnitReady (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte temp;
|
|
int i;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
for (i = 0; i < 300; i++)
|
|
{
|
|
status = GetChipStatus (chip, SCAN_STATE, &temp);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
if ((temp & 0x1f) == 0)
|
|
break;
|
|
usleep (100000);
|
|
}
|
|
DBG (DBG_ASIC, "waited %d s\n", (unsigned short) (i * 0.1));
|
|
|
|
status = SendData (chip, ES01_F4_ActiveTrigger, 0);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
|
|
static void
|
|
SetCCDTiming (ASIC * chip)
|
|
{
|
|
DBG_ASIC_ENTER ();
|
|
|
|
SendData (chip, ES01_82_AFE_ADCCLK_TIMING_ADJ_BYTE0,
|
|
BYTE0 (chip->Timing.AFE_ADCCLK_Timing));
|
|
SendData (chip, ES01_83_AFE_ADCCLK_TIMING_ADJ_BYTE1,
|
|
BYTE1 (chip->Timing.AFE_ADCCLK_Timing));
|
|
SendData (chip, ES01_84_AFE_ADCCLK_TIMING_ADJ_BYTE2,
|
|
BYTE2 (chip->Timing.AFE_ADCCLK_Timing));
|
|
SendData (chip, ES01_85_AFE_ADCCLK_TIMING_ADJ_BYTE3,
|
|
BYTE3 (chip->Timing.AFE_ADCCLK_Timing));
|
|
|
|
SendData (chip, ES01_1F0_AFERS_TIMING_ADJ_B0,
|
|
BYTE0 (chip->Timing.AFE_ADCRS_Timing));
|
|
SendData (chip, ES01_1F1_AFERS_TIMING_ADJ_B1,
|
|
BYTE1 (chip->Timing.AFE_ADCRS_Timing));
|
|
SendData (chip, ES01_1F2_AFERS_TIMING_ADJ_B2,
|
|
BYTE2 (chip->Timing.AFE_ADCRS_Timing));
|
|
SendData (chip, ES01_1F3_AFERS_TIMING_ADJ_B3,
|
|
BYTE3 (chip->Timing.AFE_ADCRS_Timing));
|
|
|
|
SendData (chip, ES01_1EC_AFEVS_TIMING_ADJ_B0,
|
|
BYTE0 (chip->Timing.AFE_ADCVS_Timing));
|
|
SendData (chip, ES01_1ED_AFEVS_TIMING_ADJ_B1,
|
|
BYTE1 (chip->Timing.AFE_ADCVS_Timing));
|
|
SendData (chip, ES01_1EE_AFEVS_TIMING_ADJ_B2,
|
|
BYTE2 (chip->Timing.AFE_ADCVS_Timing));
|
|
SendData (chip, ES01_1EF_AFEVS_TIMING_ADJ_B3,
|
|
BYTE3 (chip->Timing.AFE_ADCVS_Timing));
|
|
|
|
SendData (chip, ES01_160_CHANNEL_A_LATCH_POSITION_HB,
|
|
HIBYTE (chip->Timing.AFE_ChannelA_LatchPos));
|
|
SendData (chip, ES01_161_CHANNEL_A_LATCH_POSITION_LB,
|
|
LOBYTE (chip->Timing.AFE_ChannelA_LatchPos));
|
|
|
|
SendData (chip, ES01_162_CHANNEL_B_LATCH_POSITION_HB,
|
|
HIBYTE (chip->Timing.AFE_ChannelB_LatchPos));
|
|
SendData (chip, ES01_163_CHANNEL_B_LATCH_POSITION_LB,
|
|
LOBYTE (chip->Timing.AFE_ChannelB_LatchPos));
|
|
|
|
SendData (chip, ES01_164_CHANNEL_C_LATCH_POSITION_HB,
|
|
HIBYTE (chip->Timing.AFE_ChannelC_LatchPos));
|
|
SendData (chip, ES01_165_CHANNEL_C_LATCH_POSITION_LB,
|
|
LOBYTE (chip->Timing.AFE_ChannelC_LatchPos));
|
|
|
|
SendData (chip, ES01_166_CHANNEL_D_LATCH_POSITION_HB,
|
|
HIBYTE (chip->Timing.AFE_ChannelD_LatchPos));
|
|
SendData (chip, ES01_167_CHANNEL_D_LATCH_POSITION_LB,
|
|
LOBYTE (chip->Timing.AFE_ChannelD_LatchPos));
|
|
|
|
SendData (chip, ES01_168_SECONDARY_FF_LATCH_POSITION,
|
|
chip->Timing.AFE_Secondary_FF_LatchPos);
|
|
|
|
SendData (chip, ES01_1D0_DUMMY_CYCLE_TIMING_B0,
|
|
BYTE0 (chip->Timing.CCD_DummyCycleTiming));
|
|
SendData (chip, ES01_1D1_DUMMY_CYCLE_TIMING_B1,
|
|
BYTE1 (chip->Timing.CCD_DummyCycleTiming));
|
|
SendData (chip, ES01_1D2_DUMMY_CYCLE_TIMING_B2,
|
|
BYTE2 (chip->Timing.CCD_DummyCycleTiming));
|
|
SendData (chip, ES01_1D3_DUMMY_CYCLE_TIMING_B3,
|
|
BYTE3 (chip->Timing.CCD_DummyCycleTiming));
|
|
|
|
SendData (chip, ES01_1D4_PH1_TIMING_ADJ_B0,
|
|
BYTE0 (chip->Timing.CCD_PH1_Timing));
|
|
SendData (chip, ES01_1D5_PH1_TIMING_ADJ_B1,
|
|
BYTE1 (chip->Timing.CCD_PH1_Timing));
|
|
SendData (chip, ES01_1D6_PH1_TIMING_ADJ_B2,
|
|
BYTE2 (chip->Timing.CCD_PH1_Timing));
|
|
SendData (chip, ES01_1D7_PH1_TIMING_ADJ_B3,
|
|
BYTE3 (chip->Timing.CCD_PH1_Timing));
|
|
|
|
SendData (chip, ES01_D0_PH1_0, 0);
|
|
SendData (chip, ES01_D1_PH2_0, 4);
|
|
SendData (chip, ES01_D4_PHRS_0, 0);
|
|
SendData (chip, ES01_D5_PHCP_0, 0);
|
|
|
|
SendData (chip, ES01_1D8_PH2_TIMING_ADJ_B0,
|
|
BYTE0 (chip->Timing.CCD_PH2_Timing));
|
|
SendData (chip, ES01_1D9_PH2_TIMING_ADJ_B1,
|
|
BYTE1 (chip->Timing.CCD_PH2_Timing));
|
|
SendData (chip, ES01_1DA_PH2_TIMING_ADJ_B2,
|
|
BYTE2 (chip->Timing.CCD_PH2_Timing));
|
|
SendData (chip, ES01_1DB_PH2_TIMING_ADJ_B3,
|
|
BYTE3 (chip->Timing.CCD_PH2_Timing));
|
|
|
|
SendData (chip, ES01_1E4_PHRS_TIMING_ADJ_B0,
|
|
BYTE0 (chip->Timing.CCD_PHRS_Timing));
|
|
SendData (chip, ES01_1E5_PHRS_TIMING_ADJ_B1,
|
|
BYTE1 (chip->Timing.CCD_PHRS_Timing));
|
|
SendData (chip, ES01_1E6_PHRS_TIMING_ADJ_B2,
|
|
BYTE2 (chip->Timing.CCD_PHRS_Timing));
|
|
SendData (chip, ES01_1E7_PHRS_TIMING_ADJ_B3,
|
|
BYTE3 (chip->Timing.CCD_PHRS_Timing));
|
|
|
|
SendData (chip, ES01_1E8_PHCP_TIMING_ADJ_B0,
|
|
BYTE0 (chip->Timing.CCD_PHCP_Timing));
|
|
SendData (chip, ES01_1E9_PHCP_TIMING_ADJ_B1,
|
|
BYTE1 (chip->Timing.CCD_PHCP_Timing));
|
|
SendData (chip, ES01_1EA_PHCP_TIMING_ADJ_B2,
|
|
BYTE2 (chip->Timing.CCD_PHCP_Timing));
|
|
SendData (chip, ES01_1EB_PHCP_TIMING_ADJ_B3,
|
|
BYTE3 (chip->Timing.CCD_PHCP_Timing));
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static void
|
|
SetLineTimeAndExposure (ASIC * chip)
|
|
{
|
|
DBG_ASIC_ENTER ();
|
|
|
|
SendData (chip, ES01_C4_MultiTGTimesRed, 0);
|
|
SendData (chip, ES01_C5_MultiTGTimesGreen, 0);
|
|
SendData (chip, ES01_C6_MultiTGTimesBlue, 0);
|
|
|
|
SendData (chip, ES01_C7_MultiTGDummyPixelNumberLSB, 0);
|
|
SendData (chip, ES01_C8_MultiTGDummyPixelNumberMSB, 0);
|
|
|
|
SendData (chip, ES01_C9_CCDDummyPixelNumberLSB, 0);
|
|
SendData (chip, ES01_CA_CCDDummyPixelNumberMSB, 0);
|
|
|
|
SendData (chip, ES01_CB_CCDDummyCycleNumber, 0);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static void
|
|
SetLEDTime (ASIC * chip)
|
|
{
|
|
DBG_ASIC_ENTER ();
|
|
|
|
SendData (chip, ES01_B8_ChannelRedExpStartPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelR_StartPixel));
|
|
SendData (chip, ES01_B9_ChannelRedExpStartPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelR_StartPixel));
|
|
SendData (chip, ES01_BA_ChannelRedExpEndPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelR_EndPixel));
|
|
SendData (chip, ES01_BB_ChannelRedExpEndPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelR_EndPixel));
|
|
|
|
SendData (chip, ES01_BC_ChannelGreenExpStartPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelG_StartPixel));
|
|
SendData (chip, ES01_BD_ChannelGreenExpStartPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelG_StartPixel));
|
|
SendData (chip, ES01_BE_ChannelGreenExpEndPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelG_EndPixel));
|
|
SendData (chip, ES01_BF_ChannelGreenExpEndPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelG_EndPixel));
|
|
|
|
SendData (chip, ES01_C0_ChannelBlueExpStartPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelB_StartPixel));
|
|
SendData (chip, ES01_C1_ChannelBlueExpStartPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelB_StartPixel));
|
|
SendData (chip, ES01_C2_ChannelBlueExpEndPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelB_EndPixel));
|
|
SendData (chip, ES01_C3_ChannelBlueExpEndPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelB_EndPixel));
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
void
|
|
SetAFEGainOffset (ASIC * chip)
|
|
{
|
|
int i, j;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
SendData (chip, ES01_60_AFE_AUTO_GAIN_OFFSET_RED_LB + (i * 2),
|
|
(chip->AD.Gain[i] << 1) | chip->AD.Direction[i]);
|
|
SendData (chip, ES01_61_AFE_AUTO_GAIN_OFFSET_RED_HB + (i * 2),
|
|
chip->AD.Offset[i]);
|
|
}
|
|
|
|
SendData (chip, ES01_2A0_AFE_GAIN_OFFSET_CONTROL, 0x01);
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN,
|
|
(chip->AD.Gain[i] << 1) | chip->AD.Direction[i]);
|
|
SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET,
|
|
chip->AD.Offset[i]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 36; i++)
|
|
{
|
|
SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, 0);
|
|
SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, 0);
|
|
}
|
|
|
|
SendData (chip, ES01_2A0_AFE_GAIN_OFFSET_CONTROL, 0x00);
|
|
|
|
for (i = 0; i < 3; i++)
|
|
SendData (chip, ES01_04_ADAFEPGACH1 + (i * 2), chip->AD.Gain[i]);
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
if (chip->AD.Direction[i] == DIR_NEGATIVE)
|
|
SendData (chip, ES01_0B_AD9826OffsetRedN + (i * 2), chip->AD.Offset[i]);
|
|
else
|
|
SendData (chip, ES01_0A_AD9826OffsetRedP + (i * 2), chip->AD.Offset[i]);
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static void
|
|
SetScanMode (ASIC * chip, SANE_Byte bScanBits)
|
|
{
|
|
SANE_Byte temp_f5_register;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (bScanBits >= 24)
|
|
temp_f5_register = COLOR_ES02 | GRAY_GREEN_BLUE_ES02;
|
|
else
|
|
temp_f5_register = GRAY_ES02 | GRAY_GREEN_ES02;
|
|
|
|
if ((bScanBits == 8) || (bScanBits == 24))
|
|
temp_f5_register |= _8_BITS_ES02;
|
|
else if (bScanBits == 1)
|
|
temp_f5_register |= _1_BIT_ES02;
|
|
else
|
|
temp_f5_register |= _16_BITS_ES02;
|
|
|
|
SendData (chip, ES01_F5_ScanDataFormat, temp_f5_register);
|
|
|
|
DBG (DBG_ASIC, "F5_ScanDataFormat=0x%x\n", temp_f5_register);
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static void
|
|
SetPackAddress (ASIC * chip, unsigned short wWidth, unsigned short wX,
|
|
double XRatioAdderDouble, double XRatioTypeDouble,
|
|
SANE_Byte bClearPulseWidth, unsigned short * pValidPixelNumber)
|
|
{
|
|
unsigned short ValidPixelNumber;
|
|
int i;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
ValidPixelNumber = (unsigned short) ((wWidth + 10 + 15) * XRatioAdderDouble);
|
|
ValidPixelNumber &= ~15;
|
|
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
SendData (chip, ES01_2B0_SEGMENT0_OVERLAP_SEGMENT1 + i, 0);
|
|
SendData (chip, ES01_2C0_VALID_PIXEL_PARAMETER_OF_SEGMENT1 + i, 0);
|
|
}
|
|
|
|
SendData (chip, ES01_1B0_SEGMENT_PIXEL_NUMBER_LB, LOBYTE (ValidPixelNumber));
|
|
SendData (chip, ES01_1B1_SEGMENT_PIXEL_NUMBER_HB, HIBYTE (ValidPixelNumber));
|
|
|
|
SendData (chip, ES01_169_NUMBER_OF_SEGMENT_PIXEL_LB,
|
|
LOBYTE (ValidPixelNumber));
|
|
SendData (chip, ES01_16A_NUMBER_OF_SEGMENT_PIXEL_HB,
|
|
HIBYTE (ValidPixelNumber));
|
|
SendData (chip, ES01_16B_BETWEEN_SEGMENT_INVALID_PIXEL, 0);
|
|
|
|
SendData (chip, ES01_B6_LineWidthPixelLSB, LOBYTE (ValidPixelNumber));
|
|
SendData (chip, ES01_B7_LineWidthPixelMSB, HIBYTE (ValidPixelNumber));
|
|
|
|
SendData (chip, ES01_19A_CHANNEL_LINE_GAP_LB, LOBYTE (ValidPixelNumber));
|
|
SendData (chip, ES01_19B_CHANNEL_LINE_GAP_HB, HIBYTE (ValidPixelNumber));
|
|
DBG (DBG_ASIC, "ValidPixelNumber=%d\n", ValidPixelNumber);
|
|
|
|
for (i = 0; i < 36; i++)
|
|
SendData (chip, 0x270 + i, 0);
|
|
|
|
SendData (chip, 0x270, BYTE0 (ValidPixelNumber * 2));
|
|
SendData (chip, 0x271, BYTE1 (ValidPixelNumber * 2));
|
|
SendData (chip, 0x272, BYTE2 (ValidPixelNumber * 2));
|
|
|
|
SendData (chip, 0x27C, BYTE0 (ValidPixelNumber * 4));
|
|
SendData (chip, 0x27D, BYTE1 (ValidPixelNumber * 4));
|
|
SendData (chip, 0x27E, BYTE2 (ValidPixelNumber * 4));
|
|
|
|
SendData (chip, 0x288, BYTE0 (ValidPixelNumber * 6));
|
|
SendData (chip, 0x289, BYTE1 (ValidPixelNumber * 6));
|
|
SendData (chip, 0x28A, BYTE2 (ValidPixelNumber * 6));
|
|
DBG (DBG_ASIC, "channel gap=%d\n", ValidPixelNumber * 2);
|
|
|
|
|
|
SendData (chip, ES01_B4_StartPixelLSB, LOBYTE (wX));
|
|
SendData (chip, ES01_B5_StartPixelMSB, HIBYTE (wX));
|
|
|
|
|
|
SendData (chip, ES01_1B9_LINE_PIXEL_NUMBER_LB,
|
|
LOBYTE (XRatioTypeDouble * (ValidPixelNumber - 1)));
|
|
SendData (chip, ES01_1BA_LINE_PIXEL_NUMBER_HB,
|
|
HIBYTE (XRatioTypeDouble * (ValidPixelNumber - 1)));
|
|
|
|
/* final start read out pixel */
|
|
SendData (chip, ES01_1F4_START_READ_OUT_PIXEL_LB, 0);
|
|
SendData (chip, ES01_1F5_START_READ_OUT_PIXEL_HB, 0);
|
|
|
|
if (wWidth > (ValidPixelNumber - 10))
|
|
DBG (DBG_ERR, "read out pixel greater than max pixel! image will shift!\n");
|
|
|
|
/* final read pixel width */
|
|
SendData (chip, ES01_1F6_READ_OUT_PIXEL_LENGTH_LB, LOBYTE (wWidth + 9));
|
|
SendData (chip, ES01_1F7_READ_OUT_PIXEL_LENGTH_HB, HIBYTE (wWidth + 9));
|
|
|
|
/* data output sequence */
|
|
SendData (chip, ES01_1F8_PACK_CHANNEL_SELECT_B0, 0);
|
|
SendData (chip, ES01_1F9_PACK_CHANNEL_SELECT_B1, 0);
|
|
SendData (chip, ES01_1FA_PACK_CHANNEL_SELECT_B2, 0x18);
|
|
|
|
SendData (chip, ES01_1FB_PACK_CHANNEL_SIZE_B0, BYTE0 (ValidPixelNumber * 2));
|
|
SendData (chip, ES01_1FC_PACK_CHANNEL_SIZE_B1, BYTE1 (ValidPixelNumber * 2));
|
|
SendData (chip, ES01_1FD_PACK_CHANNEL_SIZE_B2, BYTE2 (ValidPixelNumber * 2));
|
|
|
|
SendData (chip, ES01_16C_LINE_SHIFT_OUT_TIMES_DIRECTION, 0x01);
|
|
SendData (chip, ES01_1CD_DUMMY_CLOCK_NUMBER, 0);
|
|
SendData (chip, ES01_1CE_LINE_SEGMENT_NUMBER, 0x00);
|
|
SendData (chip, ES01_D8_PHTG_EDGE_TIMING_ADJUST, 0x17);
|
|
|
|
SendData (chip, ES01_D9_CLEAR_PULSE_WIDTH, bClearPulseWidth);
|
|
|
|
SendData (chip, ES01_DA_CLEAR_SIGNAL_INVERTING_OUTPUT, 0x54 | 0x01);
|
|
SendData (chip, ES01_CD_TG_R_CONTROL, 0x3C);
|
|
SendData (chip, ES01_CE_TG_G_CONTROL, 0);
|
|
SendData (chip, ES01_CF_TG_B_CONTROL, 0x3C);
|
|
|
|
/* set pack area address */
|
|
SendData (chip, ES01_16D_EXPOSURE_CYCLE1_SEGMENT1_START_ADDR_BYTE0,
|
|
BYTE0 (PACK_AREA_START_ADDRESS));
|
|
SendData (chip, ES01_16E_EXPOSURE_CYCLE1_SEGMENT1_START_ADDR_BYTE1,
|
|
BYTE1 (PACK_AREA_START_ADDRESS));
|
|
SendData (chip, ES01_16F_EXPOSURE_CYCLE1_SEGMENT1_START_ADDR_BYTE2,
|
|
BYTE2 (PACK_AREA_START_ADDRESS));
|
|
|
|
for ( i = ES01_170_EXPOSURE_CYCLE1_SEGMENT2_START_ADDR_BYTE0;
|
|
i <= ES01_18E_EXPOSURE_CYCLE3_SEGMENT4_START_ADDR_BYTE0; i += 3)
|
|
{
|
|
SendData (chip, i, BYTE0 (PACK_AREA_START_ADDRESS + 0xC0000));
|
|
SendData (chip, i + 1, BYTE1 (PACK_AREA_START_ADDRESS + 0xC0000));
|
|
SendData (chip, i + 2, BYTE2 (PACK_AREA_START_ADDRESS + 0xC0000));
|
|
}
|
|
DBG (DBG_ASIC, "PACK_AREA_START_ADDRESS=%d\n", PACK_AREA_START_ADDRESS);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
SendData (chip, 0x260 + i, 0);
|
|
DBG (DBG_ASIC, "set invalid pixel finished\n");
|
|
|
|
/* set pack start address */
|
|
SendData (chip, ES01_19E_PACK_AREA_R_START_ADDR_BYTE0,
|
|
BYTE0 (PACK_AREA_START_ADDRESS));
|
|
SendData (chip, ES01_19F_PACK_AREA_R_START_ADDR_BYTE1,
|
|
BYTE1 (PACK_AREA_START_ADDRESS));
|
|
SendData (chip, ES01_1A0_PACK_AREA_R_START_ADDR_BYTE2,
|
|
BYTE2 (PACK_AREA_START_ADDRESS));
|
|
|
|
SendData (chip, ES01_1A1_PACK_AREA_G_START_ADDR_BYTE0,
|
|
BYTE0 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 2)));
|
|
SendData (chip, ES01_1A2_PACK_AREA_G_START_ADDR_BYTE1,
|
|
BYTE1 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 2)));
|
|
SendData (chip, ES01_1A3_PACK_AREA_G_START_ADDR_BYTE2,
|
|
BYTE2 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 2)));
|
|
|
|
SendData (chip, ES01_1A4_PACK_AREA_B_START_ADDR_BYTE0,
|
|
BYTE0 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 4)));
|
|
SendData (chip, ES01_1A5_PACK_AREA_B_START_ADDR_BYTE1,
|
|
BYTE1 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 4)));
|
|
SendData (chip, ES01_1A6_PACK_AREA_B_START_ADDR_BYTE2,
|
|
BYTE2 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 4)));
|
|
|
|
/* set pack end address */
|
|
SendData (chip, ES01_1A7_PACK_AREA_R_END_ADDR_BYTE0,
|
|
BYTE0 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 2 - 1)));
|
|
SendData (chip, ES01_1A8_PACK_AREA_R_END_ADDR_BYTE1,
|
|
BYTE1 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 2 - 1)));
|
|
SendData (chip, ES01_1A9_PACK_AREA_R_END_ADDR_BYTE2,
|
|
BYTE2 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 2 - 1)));
|
|
|
|
SendData (chip, ES01_1AA_PACK_AREA_G_END_ADDR_BYTE0,
|
|
BYTE0 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 4 - 1)));
|
|
SendData (chip, ES01_1AB_PACK_AREA_G_END_ADDR_BYTE1,
|
|
BYTE1 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 4 - 1)));
|
|
SendData (chip, ES01_1AC_PACK_AREA_G_END_ADDR_BYTE2,
|
|
BYTE2 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 4 - 1)));
|
|
|
|
SendData (chip, ES01_1AD_PACK_AREA_B_END_ADDR_BYTE0,
|
|
BYTE0 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 6 - 1)));
|
|
SendData (chip, ES01_1AE_PACK_AREA_B_END_ADDR_BYTE1,
|
|
BYTE1 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 6 - 1)));
|
|
SendData (chip, ES01_1AF_PACK_AREA_B_END_ADDR_BYTE2,
|
|
BYTE2 (PACK_AREA_START_ADDRESS + (ValidPixelNumber * 6 - 1)));
|
|
DBG (DBG_ASIC, "PACK_AREA_START_ADDRESS + (ValidPixelNumber*2)=%d\n",
|
|
(PACK_AREA_START_ADDRESS + (ValidPixelNumber * 2)));
|
|
|
|
SendData (chip, ES01_19C_MAX_PACK_LINE, 2);
|
|
SendData (chip, ES01_19D_PACK_THRESHOLD_LINE, 1);
|
|
|
|
if (pValidPixelNumber)
|
|
*pValidPixelNumber = ValidPixelNumber;
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
static void
|
|
SetExtraSettings (ASIC * chip, unsigned short wXResolution,
|
|
unsigned short wCCD_PixelNumber, SANE_Bool bypassShading)
|
|
{
|
|
SANE_Byte temp_ff_register = 0;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
SendData (chip, ES01_B8_ChannelRedExpStartPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelR_StartPixel));
|
|
SendData (chip, ES01_B9_ChannelRedExpStartPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelR_StartPixel));
|
|
SendData (chip, ES01_BA_ChannelRedExpEndPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelR_EndPixel));
|
|
SendData (chip, ES01_BB_ChannelRedExpEndPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelR_EndPixel));
|
|
|
|
SendData (chip, ES01_BC_ChannelGreenExpStartPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelG_StartPixel));
|
|
SendData (chip, ES01_BD_ChannelGreenExpStartPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelG_StartPixel));
|
|
SendData (chip, ES01_BE_ChannelGreenExpEndPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelG_EndPixel));
|
|
SendData (chip, ES01_BF_ChannelGreenExpEndPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelG_EndPixel));
|
|
|
|
SendData (chip, ES01_C0_ChannelBlueExpStartPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelB_StartPixel));
|
|
SendData (chip, ES01_C1_ChannelBlueExpStartPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelB_StartPixel));
|
|
SendData (chip, ES01_C2_ChannelBlueExpEndPixelLSB,
|
|
LOBYTE (chip->Timing.ChannelB_EndPixel));
|
|
SendData (chip, ES01_C3_ChannelBlueExpEndPixelMSB,
|
|
HIBYTE (chip->Timing.ChannelB_EndPixel));
|
|
|
|
SendData (chip, ES01_B2_PHTGPulseWidth, chip->Timing.PHTG_PulseWidth);
|
|
SendData (chip, ES01_B3_PHTGWaitWidth, chip->Timing.PHTG_WaitWidth);
|
|
|
|
SendData (chip, ES01_CC_PHTGTimingAdjust, chip->Timing.PHTG_TimingAdj);
|
|
SendData (chip, ES01_D0_PH1_0, chip->Timing.PHTG_TimingSetup);
|
|
|
|
DBG (DBG_ASIC, "ChannelR_StartPixel=%d,ChannelR_EndPixel=%d\n",
|
|
chip->Timing.ChannelR_StartPixel, chip->Timing.ChannelR_EndPixel);
|
|
|
|
if (wXResolution == SENSOR_DPI)
|
|
SendData (chip, ES01_DE_CCD_SETUP_REGISTER, EVEN_ODD_ENABLE_ES01);
|
|
else
|
|
SendData (chip, ES01_DE_CCD_SETUP_REGISTER, 0);
|
|
|
|
temp_ff_register |= BYPASS_PRE_GAMMA_ENABLE;
|
|
temp_ff_register |= BYPASS_CONVOLUTION_ENABLE;
|
|
temp_ff_register |= BYPASS_MATRIX_ENABLE;
|
|
temp_ff_register |= BYPASS_GAMMA_ENABLE;
|
|
|
|
if (bypassShading)
|
|
{
|
|
temp_ff_register |= BYPASS_DARK_SHADING_ENABLE;
|
|
temp_ff_register |= BYPASS_WHITE_SHADING_ENABLE;
|
|
}
|
|
|
|
SendData (chip, ES01_FF_SCAN_IMAGE_OPTION, temp_ff_register);
|
|
DBG (DBG_ASIC, "temp_ff_register=0x%x\n", temp_ff_register);
|
|
|
|
/* pixel process time */
|
|
SendData (chip, ES01_B0_CCDPixelLSB, LOBYTE (wCCD_PixelNumber));
|
|
SendData (chip, ES01_B1_CCDPixelMSB, HIBYTE (wCCD_PixelNumber));
|
|
SendData (chip, ES01_DF_ICG_CONTROL,
|
|
BEFORE_PHRS_416_1t_ns | ICG_UNIT_4_PIXEL_TIME);
|
|
DBG (DBG_ASIC, "wCCD_PixelNumber=%d\n", wCCD_PixelNumber);
|
|
|
|
SendData (chip, ES01_88_LINE_ART_THRESHOLD_HIGH_VALUE, 128);
|
|
SendData (chip, ES01_89_LINE_ART_THRESHOLD_LOW_VALUE, 127);
|
|
|
|
usleep (50000);
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
|
|
/* ---------------------- high level ASIC functions ------------------------ */
|
|
|
|
/* HOLD: We don't want to have global vid/pids */
|
|
static const unsigned short ProductID = 0x0409;
|
|
static const unsigned short VendorID = 0x055f;
|
|
|
|
SANE_String_Const device_name;
|
|
|
|
static SANE_Status
|
|
attach_one_scanner (SANE_String_Const devname)
|
|
{
|
|
DBG (DBG_INFO, "attach_one_scanner: devname = %s\n", devname);
|
|
device_name = devname;
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_Open (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate > FS_OPENED)
|
|
{
|
|
DBG (DBG_ASIC, "chip already open, fd=%d\n", chip->fd);
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
device_name = NULL;
|
|
sanei_usb_init ();
|
|
status = sanei_usb_find_devices (VendorID, ProductID, attach_one_scanner);
|
|
if (status != SANE_STATUS_GOOD)
|
|
{
|
|
DBG (DBG_ERR, "sanei_usb_find_devices failed: %s\n",
|
|
sane_strstatus (status));
|
|
return status;
|
|
}
|
|
if (!device_name)
|
|
{
|
|
DBG (DBG_ERR, "no scanner found\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
status = sanei_usb_open (device_name, &chip->fd);
|
|
if (status != SANE_STATUS_GOOD)
|
|
{
|
|
DBG (DBG_ERR, "sanei_usb_open of %s failed: %s\n",
|
|
device_name, sane_strstatus (status));
|
|
return status;
|
|
}
|
|
|
|
status = OpenScanChip (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
{
|
|
sanei_usb_close (chip->fd);
|
|
return status;
|
|
}
|
|
|
|
SendData (chip, ES01_94_PowerSaveControl,
|
|
TIMER_POWER_SAVE_ENABLE |
|
|
USB_POWER_SAVE_ENABLE | USB_REMOTE_WAKEUP_ENABLE |
|
|
LED_MODE_FLASH_SLOWLY);
|
|
SendData (chip, ES01_86_DisableAllClockWhenIdle, 0);
|
|
SendData (chip, ES01_79_AFEMCLK_SDRAMCLK_DELAY_CONTROL, SDRAMCLK_DELAY_12_ns);
|
|
|
|
/* SDRAM initialization sequence */
|
|
SendData (chip, ES01_87_SDRAM_Timing, 0xf1);
|
|
SendData (chip, ES01_87_SDRAM_Timing, 0xa5);
|
|
SendData (chip, ES01_87_SDRAM_Timing, 0x91);
|
|
SendData (chip, ES01_87_SDRAM_Timing, 0x81);
|
|
SendData (chip, ES01_87_SDRAM_Timing, 0xf0);
|
|
|
|
chip->firmwarestate = FS_OPENED;
|
|
|
|
status = WaitUnitReady (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
{
|
|
sanei_usb_close (chip->fd);
|
|
return status;
|
|
}
|
|
|
|
status = SafeInitialChip (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
{
|
|
sanei_usb_close (chip->fd);
|
|
return status;
|
|
}
|
|
|
|
DBG (DBG_INFO, "device %s successfully opened\n", device_name);
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_Close (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate < FS_OPENED)
|
|
{
|
|
DBG (DBG_ASIC, "scanner is not open\n");
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
if (chip->firmwarestate > FS_OPENED)
|
|
{
|
|
DBG (DBG_ASIC, "scanner is scanning, trying to stop\n");
|
|
Asic_ScanStop (chip);
|
|
}
|
|
|
|
SendData (chip, ES01_86_DisableAllClockWhenIdle, CLOSE_ALL_CLOCK_ENABLE);
|
|
status = CloseScanChip (chip);
|
|
|
|
sanei_usb_close (chip->fd);
|
|
|
|
chip->firmwarestate = FS_ATTACHED;
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
void
|
|
Asic_Initialize (ASIC * chip)
|
|
{
|
|
DBG_ASIC_ENTER ();
|
|
|
|
chip->isFirstOpenChip = SANE_TRUE;
|
|
chip->isUsb20 = SANE_FALSE;
|
|
chip->dwBytesCountPerRow = 0;
|
|
chip->isMotorMoveToFirstLine = MOTOR_MOVE_TO_FIRST_LINE_ENABLE;
|
|
chip->pShadingTable = NULL;
|
|
chip->RegisterBankStatus = 0xff;
|
|
chip->is2ByteTransfer = SANE_FALSE;
|
|
|
|
InitTiming (chip);
|
|
|
|
chip->firmwarestate = FS_ATTACHED;
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_TurnLamp (ASIC * chip, SANE_Bool isLampOn)
|
|
{
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
SendData (chip, ES01_99_LAMP_PWM_FREQ_CONTROL, 1);
|
|
if (isLampOn)
|
|
SendData (chip, ES01_90_Lamp0PWM, LAMP0_PWM_DEFAULT);
|
|
else
|
|
SendData (chip, ES01_90_Lamp0PWM, 0);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_TurnTA (ASIC * chip, SANE_Bool isTAOn)
|
|
{
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
SendData (chip, ES01_99_LAMP_PWM_FREQ_CONTROL, 1);
|
|
if (isTAOn)
|
|
SendData (chip, ES01_91_Lamp1PWM, LAMP1_PWM_DEFAULT);
|
|
else
|
|
SendData (chip, ES01_91_Lamp1PWM, 0);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
|
|
static SANE_Byte
|
|
GetDummyCycleNumber (ASIC * chip, unsigned short wYResolution,
|
|
SCANSOURCE lsLightSource)
|
|
{
|
|
SANE_Byte bDummyCycleNum = 0;
|
|
if (lsLightSource == SS_REFLECTIVE)
|
|
{
|
|
if (!chip->isUsb20)
|
|
{
|
|
switch (wYResolution)
|
|
{
|
|
case 2400:
|
|
case 1200:
|
|
if (chip->dwBytesCountPerRow > 22000)
|
|
bDummyCycleNum = 4;
|
|
else if (chip->dwBytesCountPerRow > 15000)
|
|
bDummyCycleNum = 3;
|
|
else if (chip->dwBytesCountPerRow > 10000)
|
|
bDummyCycleNum = 2;
|
|
else if (chip->dwBytesCountPerRow > 5000)
|
|
bDummyCycleNum = 1;
|
|
break;
|
|
case 600:
|
|
case 300:
|
|
case 150:
|
|
case 100:
|
|
if (chip->dwBytesCountPerRow > 21000)
|
|
bDummyCycleNum = 7;
|
|
else if (chip->dwBytesCountPerRow > 18000)
|
|
bDummyCycleNum = 6;
|
|
else if (chip->dwBytesCountPerRow > 15000)
|
|
bDummyCycleNum = 5;
|
|
else if (chip->dwBytesCountPerRow > 12000)
|
|
bDummyCycleNum = 4;
|
|
else if (chip->dwBytesCountPerRow > 9000)
|
|
bDummyCycleNum = 3;
|
|
else if (chip->dwBytesCountPerRow > 6000)
|
|
bDummyCycleNum = 2;
|
|
else if (chip->dwBytesCountPerRow > 3000)
|
|
bDummyCycleNum = 1;
|
|
break;
|
|
case 75:
|
|
case 50:
|
|
bDummyCycleNum = 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (wYResolution)
|
|
{
|
|
case 2400:
|
|
case 1200:
|
|
case 75:
|
|
case 50:
|
|
bDummyCycleNum = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return bDummyCycleNum;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_SetWindow (ASIC * chip, SCANSOURCE lsLightSource,
|
|
SCAN_TYPE ScanType, SANE_Byte bScanBits,
|
|
unsigned short wXResolution, unsigned short wYResolution,
|
|
unsigned short wX, unsigned short wY,
|
|
unsigned short wWidth, unsigned short wHeight)
|
|
{
|
|
SANE_Status status;
|
|
unsigned short ValidPixelNumber;
|
|
unsigned short wThinkCCDResolution;
|
|
unsigned short wCCD_PixelNumber;
|
|
unsigned short XRatioTypeWord;
|
|
double XRatioTypeDouble;
|
|
double XRatioAdderDouble;
|
|
MOTORMOVE pMotorStepsTable;
|
|
SANE_Byte bDummyCycleNum;
|
|
unsigned short wMultiMotorStep;
|
|
SANE_Byte bMotorMoveType;
|
|
unsigned int dwLinePixelReport;
|
|
unsigned int StartSpeed, EndSpeed;
|
|
CALCULATEMOTORTABLE CalMotorTable;
|
|
MOTOR_CURRENT_AND_PHASE CurrentPhase;
|
|
unsigned int dwTableBaseAddr, dwEndAddr;
|
|
SANE_Byte isMotorMove;
|
|
SANE_Byte isMotorMoveToFirstLine;
|
|
SANE_Byte isUniformSpeedToScan;
|
|
SANE_Byte isScanBackTracking;
|
|
unsigned short * pMotorTable;
|
|
unsigned int RealTableSize;
|
|
unsigned short wFullBank;
|
|
DBG_ASIC_ENTER ();
|
|
DBG (DBG_ASIC, "lsLightSource=%d,ScanType=%d,bScanBits=%d," \
|
|
"wXResolution=%d,wYResolution=%d,wX=%d,wY=%d," \
|
|
"wWidth=%d,wHeight=%d\n",
|
|
lsLightSource, ScanType, bScanBits, wXResolution, wYResolution, wX, wY,
|
|
wWidth, wHeight);
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
status = PrepareScanChip (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
SendData (chip, ES01_94_PowerSaveControl,
|
|
TIMER_POWER_SAVE_ENABLE |
|
|
USB_POWER_SAVE_ENABLE | USB_REMOTE_WAKEUP_ENABLE |
|
|
LED_MODE_FLASH_SLOWLY | 0x40 | 0x80);
|
|
|
|
chip->dwBytesCountPerRow = (unsigned int) wWidth * (bScanBits / 8);
|
|
DBG (DBG_ASIC, "dwBytesCountPerRow=%d\n", chip->dwBytesCountPerRow);
|
|
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
bDummyCycleNum = GetDummyCycleNumber (chip, wYResolution, lsLightSource);
|
|
else
|
|
bDummyCycleNum = 1;
|
|
|
|
SetCCDTiming (chip);
|
|
|
|
if (wXResolution > (SENSOR_DPI / 2))
|
|
{
|
|
wThinkCCDResolution = SENSOR_DPI;
|
|
SendData (chip, ES01_98_GPIOControl8_15, 0x01);
|
|
SendData (chip, ES01_96_GPIOValue8_15, 0x01);
|
|
}
|
|
else
|
|
{
|
|
wThinkCCDResolution = SENSOR_DPI / 2;
|
|
SendData (chip, ES01_98_GPIOControl8_15, 0x01);
|
|
SendData (chip, ES01_96_GPIOValue8_15, 0x00);
|
|
}
|
|
|
|
if (lsLightSource == SS_REFLECTIVE)
|
|
{
|
|
if (wXResolution > (SENSOR_DPI / 2))
|
|
wCCD_PixelNumber = chip->Timing.wCCDPixelNumber_Full;
|
|
else
|
|
wCCD_PixelNumber = chip->Timing.wCCDPixelNumber_Half;
|
|
}
|
|
else
|
|
{
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
wCCD_PixelNumber = TA_IMAGE_PIXELNUMBER;
|
|
else
|
|
wCCD_PixelNumber = TA_CAL_PIXELNUMBER;
|
|
}
|
|
|
|
SetLineTimeAndExposure (chip);
|
|
SendData (chip, ES01_CB_CCDDummyCycleNumber, bDummyCycleNum);
|
|
SetLEDTime (chip);
|
|
|
|
SendData (chip, ES01_74_HARDWARE_SETTING,
|
|
MOTOR1_SERIAL_INTERFACE_G10_8_ENABLE);
|
|
|
|
SendData (chip, ES01_9A_AFEControl, AD9826_AFE);
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
SetAFEGainOffset (chip);
|
|
SendData (chip, ES01_DB_PH_RESET_EDGE_TIMING_ADJUST, 0x00);
|
|
SendData (chip, ES01_DC_CLEAR_EDGE_TO_PH_TG_EDGE_WIDTH, 0);
|
|
SendData (chip, ES01_00_ADAFEConfiguration, 0x70);
|
|
SendData (chip, ES01_02_ADAFEMuxConfig, 0x80);
|
|
|
|
SendData (chip, ES01_F7_DigitalControl, 0);
|
|
|
|
/* calculate X ratio */
|
|
XRatioTypeDouble = (double) wXResolution / wThinkCCDResolution;
|
|
XRatioTypeWord = (unsigned short) (XRatioTypeDouble * 32768);
|
|
XRatioAdderDouble = 1 / XRatioTypeDouble;
|
|
|
|
/* 32768 = 1.00000 -> get all pixel */
|
|
SendData (chip, ES01_9E_HorizontalRatio1to15LSB, LOBYTE (XRatioTypeWord));
|
|
SendData (chip, ES01_9F_HorizontalRatio1to15MSB, HIBYTE (XRatioTypeWord));
|
|
DBG (DBG_ASIC,
|
|
"XRatioTypeDouble=%.2f,XRatioAdderDouble=%.2f,XRatioTypeWord=%d\n",
|
|
XRatioTypeDouble, XRatioAdderDouble, XRatioTypeWord);
|
|
|
|
/* set motor type */
|
|
if (ScanType == SCAN_TYPE_CALIBRATE_DARK)
|
|
isMotorMove = 0;
|
|
else
|
|
isMotorMove = MOTOR_0_ENABLE;
|
|
SendData (chip, ES01_A6_MotorOption,
|
|
isMotorMove | HOME_SENSOR_0_ENABLE | TABLE_DEFINE_ES03);
|
|
SendData (chip, ES01_F6_MotorControl1,
|
|
SPEED_UNIT_1_PIXEL_TIME | MOTOR_SYNC_UNIT_1_PIXEL_TIME);
|
|
|
|
if ((ScanType == SCAN_TYPE_NORMAL) && (wYResolution >= SENSOR_DPI))
|
|
bMotorMoveType = _8_TABLE_SPACE_FOR_1_DIV_2_STEP;
|
|
else
|
|
bMotorMoveType = _4_TABLE_SPACE_FOR_FULL_STEP;
|
|
|
|
switch (bMotorMoveType)
|
|
{
|
|
default:
|
|
case _4_TABLE_SPACE_FOR_FULL_STEP:
|
|
wMultiMotorStep = 1;
|
|
break;
|
|
case _8_TABLE_SPACE_FOR_1_DIV_2_STEP:
|
|
wMultiMotorStep = 2;
|
|
break;
|
|
case _16_TABLE_SPACE_FOR_1_DIV_4_STEP:
|
|
wMultiMotorStep = 4;
|
|
break;
|
|
case _32_TABLE_SPACE_FOR_1_DIV_8_STEP:
|
|
wMultiMotorStep = 8;
|
|
break;
|
|
}
|
|
wY *= wMultiMotorStep;
|
|
|
|
SetScanMode (chip, bScanBits);
|
|
|
|
if (lsLightSource == SS_REFLECTIVE)
|
|
SendData (chip, ES01_F8_WHITE_SHADING_DATA_FORMAT,
|
|
SHADING_3_INT_13_DEC_ES01);
|
|
else
|
|
SendData (chip, ES01_F8_WHITE_SHADING_DATA_FORMAT,
|
|
SHADING_4_INT_12_DEC_ES01);
|
|
|
|
SetPackAddress (chip, wWidth, wX, XRatioAdderDouble,
|
|
XRatioTypeDouble, 0, &ValidPixelNumber);
|
|
SetExtraSettings (chip, wXResolution, wCCD_PixelNumber,
|
|
(ScanType == SCAN_TYPE_NORMAL) ? SANE_FALSE : SANE_TRUE);
|
|
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
{
|
|
SetMotorStepTable (chip, &pMotorStepsTable, wY,
|
|
wHeight * SENSOR_DPI / wYResolution * wMultiMotorStep,
|
|
wYResolution);
|
|
}
|
|
else
|
|
{
|
|
SetMotorStepTableForCalibration (chip, &pMotorStepsTable,
|
|
wHeight * SENSOR_DPI / wYResolution * wMultiMotorStep);
|
|
}
|
|
|
|
/* calculate line time */
|
|
dwLinePixelReport = (2 + (chip->Timing.PHTG_PulseWidth + 1) +
|
|
(chip->Timing.PHTG_WaitWidth + 1) +
|
|
(wCCD_PixelNumber + 1)) * (bDummyCycleNum + 1);
|
|
|
|
EndSpeed = (dwLinePixelReport * wYResolution / SENSOR_DPI) / wMultiMotorStep;
|
|
DBG (DBG_ASIC, "motor time = %d\n", EndSpeed);
|
|
if (EndSpeed > 0xffff)
|
|
{
|
|
DBG (DBG_ASIC, "Motor time overflow!\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
isMotorMoveToFirstLine = chip->isMotorMoveToFirstLine;
|
|
isUniformSpeedToScan = UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE;
|
|
isScanBackTracking = 0;
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
{
|
|
if (EndSpeed >= 20000)
|
|
{
|
|
status = SimpleMotorMove (chip, 5000, 1800, 7000, 200,
|
|
wY / wMultiMotorStep, ACTION_TYPE_FORWARD);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
isMotorMoveToFirstLine = 0;
|
|
}
|
|
else
|
|
{
|
|
isUniformSpeedToScan = 0;
|
|
isScanBackTracking = SCAN_BACK_TRACKING_ENABLE;
|
|
}
|
|
}
|
|
SendData (chip, ES01_F3_ActionOption, SCAN_ENABLE |
|
|
isMotorMoveToFirstLine | isScanBackTracking | isUniformSpeedToScan);
|
|
|
|
if (EndSpeed > 8000)
|
|
{
|
|
StartSpeed = EndSpeed;
|
|
}
|
|
else
|
|
{
|
|
if (EndSpeed <= 1000)
|
|
StartSpeed = EndSpeed + 4500;
|
|
else
|
|
StartSpeed = EndSpeed + 3500;
|
|
}
|
|
DBG (DBG_ASIC, "StartSpeed=%d,EndSpeed=%d\n", StartSpeed, EndSpeed);
|
|
|
|
SendData (chip, ES01_FD_MotorFixedspeedLSB, LOBYTE (EndSpeed));
|
|
SendData (chip, ES01_FE_MotorFixedspeedMSB, HIBYTE (EndSpeed));
|
|
|
|
pMotorTable = malloc (MOTOR_TABLE_SIZE * sizeof (unsigned short));
|
|
if (!pMotorTable)
|
|
{
|
|
DBG (DBG_ERR, "pMotorTable == NULL\n");
|
|
return SANE_STATUS_NO_MEM;
|
|
}
|
|
memset (pMotorTable, 0, MOTOR_TABLE_SIZE * sizeof (unsigned short));
|
|
|
|
CalMotorTable.StartSpeed = StartSpeed;
|
|
CalMotorTable.EndSpeed = EndSpeed;
|
|
CalMotorTable.AccStepBeforeScan = pMotorStepsTable.wScanAccSteps;
|
|
CalMotorTable.DecStepAfterScan = pMotorStepsTable.bScanDecSteps;
|
|
CalMotorTable.pMotorTable = pMotorTable;
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
CalculateScanMotorTable (&CalMotorTable);
|
|
else
|
|
CalculateMoveMotorTable (&CalMotorTable);
|
|
|
|
CurrentPhase.MoveType = bMotorMoveType;
|
|
CurrentPhase.MotorDriverIs3967 = 0;
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
CurrentPhase.MotorCurrent = CalculateMotorCurrent (EndSpeed);
|
|
else
|
|
CurrentPhase.MotorCurrent = 200;
|
|
SetMotorCurrentAndPhase (chip, &CurrentPhase);
|
|
|
|
DBG (DBG_ASIC, "MotorCurrent=%d,LinePixelReport=%d\n",
|
|
CurrentPhase.MotorCurrent, dwLinePixelReport);
|
|
|
|
/* write motor table */
|
|
RealTableSize = MOTOR_TABLE_SIZE;
|
|
dwTableBaseAddr = PACK_AREA_START_ADDRESS - RealTableSize;
|
|
status = SetMotorTable (chip, dwTableBaseAddr, pMotorTable);
|
|
free (pMotorTable);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
if (ScanType == SCAN_TYPE_NORMAL)
|
|
{
|
|
/* set image buffer range and write shading table */
|
|
RealTableSize += ShadingTableSize (ValidPixelNumber);
|
|
dwTableBaseAddr = PACK_AREA_START_ADDRESS -
|
|
((RealTableSize + (TABLE_BASE_SIZE - 1)) &
|
|
~(TABLE_BASE_SIZE - 1));
|
|
|
|
status = SetShadingTable (chip, dwTableBaseAddr, chip->dwShadingTableSize,
|
|
chip->pShadingTable);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
}
|
|
|
|
dwEndAddr = dwTableBaseAddr - 1;
|
|
|
|
/* empty bank */
|
|
SendData (chip, ES01_FB_BufferEmptySize16WordLSB,
|
|
LOBYTE (WAIT_BUFFER_ONE_LINE_SIZE >> 4));
|
|
SendData (chip, ES01_FC_BufferEmptySize16WordMSB,
|
|
HIBYTE (WAIT_BUFFER_ONE_LINE_SIZE >> 4));
|
|
|
|
/* full bank */
|
|
wFullBank = (unsigned short)
|
|
((dwEndAddr - ((chip->dwBytesCountPerRow / 2) * 3)) / BANK_SIZE);
|
|
SendData (chip, ES01_F9_BufferFullSize16WordLSB, LOBYTE (wFullBank));
|
|
SendData (chip, ES01_FA_BufferFullSize16WordMSB, HIBYTE (wFullBank));
|
|
|
|
status = SetRamAddress (chip, 0, dwEndAddr, EXTERNAL_RAM);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_ScanStart (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
status = GetChipStatus(chip, 0x1c | 0x20, NULL);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = ClearFIFO (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
SendData (chip, ES01_F4_ActiveTrigger, ACTION_TRIGGER_ENABLE);
|
|
|
|
chip->firmwarestate = FS_SCANNING;
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_ScanStop (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte buf[4];
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate < FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
if (chip->firmwarestate < FS_SCANNING)
|
|
return SANE_STATUS_GOOD;
|
|
|
|
usleep (100 * 1000);
|
|
|
|
buf[0] = 0x02; /* stop */
|
|
buf[1] = 0x02;
|
|
buf[2] = 0x02;
|
|
buf[3] = 0x02;
|
|
status = WriteIOControl (chip, 0xc0, 0, 4, buf);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
buf[0] = 0x00; /* clear */
|
|
buf[1] = 0x00;
|
|
buf[2] = 0x00;
|
|
buf[3] = 0x00;
|
|
status = WriteIOControl (chip, 0xc0, 0, 4, buf);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = DMARead (chip, 2, buf);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = PrepareScanChip (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
status = ClearFIFO (chip);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
chip->firmwarestate = FS_OPENED;
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_ReadImage (ASIC * chip, SANE_Byte * pBuffer, unsigned short LinesCount)
|
|
{
|
|
SANE_Status status;
|
|
unsigned int dwXferBytes;
|
|
DBG_ASIC_ENTER ();
|
|
DBG (DBG_ASIC, "LinesCount=%d\n", LinesCount);
|
|
|
|
if (chip->firmwarestate != FS_SCANNING)
|
|
{
|
|
DBG (DBG_ERR, "scanner is not scanning\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
dwXferBytes = (unsigned int) LinesCount * chip->dwBytesCountPerRow;
|
|
if (dwXferBytes == 0)
|
|
{
|
|
DBG (DBG_ASIC, "dwXferBytes == 0\n");
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
status = DMARead (chip, dwXferBytes, pBuffer);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_CheckFunctionKey (ASIC * chip, SANE_Byte * key)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte bBuffer_1, bBuffer_2;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
SendData (chip, ES01_97_GPIOControl0_7, 0x00);
|
|
SendData (chip, ES01_95_GPIOValue0_7, 0x17);
|
|
SendData (chip, ES01_98_GPIOControl8_15, 0x00);
|
|
SendData (chip, ES01_96_GPIOValue8_15, 0x08);
|
|
|
|
status = GetChipStatus (chip, GPIO0_7, &bBuffer_1);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
status = GetChipStatus (chip, GPIO8_15, &bBuffer_2);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
bBuffer_1 = ~bBuffer_1;
|
|
bBuffer_2 = ~bBuffer_2;
|
|
|
|
if (bBuffer_1 & 0x10)
|
|
*key = 1; /* Scan key pressed */
|
|
else if (bBuffer_1 & 0x01)
|
|
*key = 2; /* Copy key pressed */
|
|
else if (bBuffer_1 & 0x04)
|
|
*key = 3; /* Fax key pressed */
|
|
else if (bBuffer_2 & 0x08)
|
|
*key = 4; /* Email key pressed */
|
|
else if (bBuffer_1 & 0x02)
|
|
*key = 5; /* Panel key pressed */
|
|
else
|
|
*key = 0;
|
|
|
|
DBG (DBG_ASIC, "key=%d\n", *key);
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_IsTAConnected (ASIC * chip, SANE_Bool * hasTA)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte bBuffer_1 = 0xff;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
SendData (chip, ES01_97_GPIOControl0_7, 0x00);
|
|
SendData (chip, ES01_95_GPIOValue0_7, 0x00);
|
|
SendData (chip, ES01_98_GPIOControl8_15, 0x00);
|
|
SendData (chip, ES01_96_GPIOValue8_15, 0x00);
|
|
|
|
status = GetChipStatus (chip, GPIO0_7, &bBuffer_1);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
*hasTA = (~bBuffer_1 & 0x08) ? SANE_TRUE : SANE_FALSE;
|
|
|
|
DBG (DBG_ASIC, "hasTA=%d\n", *hasTA);
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_ReadCalibrationData (ASIC * chip, SANE_Byte * pBuffer,
|
|
unsigned int dwXferBytes, SANE_Bool separateColors)
|
|
{
|
|
SANE_Status status = SANE_STATUS_GOOD;
|
|
SANE_Byte * pCalBuffer;
|
|
unsigned int dwTotalReadData = 0;
|
|
unsigned int dwReadImageData;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_SCANNING)
|
|
{
|
|
DBG (DBG_ERR, "scanner is not scanning\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
if (separateColors)
|
|
{
|
|
unsigned int i;
|
|
|
|
pCalBuffer = malloc (dwXferBytes);
|
|
if (!pCalBuffer)
|
|
{
|
|
DBG (DBG_ERR, "pCalBuffer == NULL\n");
|
|
return SANE_STATUS_NO_MEM;
|
|
}
|
|
|
|
while (dwTotalReadData < dwXferBytes)
|
|
{
|
|
dwReadImageData = dwXferBytes - dwTotalReadData;
|
|
if (dwReadImageData > 65536)
|
|
dwReadImageData = 65536;
|
|
|
|
status = DMARead (chip, dwReadImageData,
|
|
pCalBuffer + dwTotalReadData);
|
|
if (status != SANE_STATUS_GOOD)
|
|
break;
|
|
dwTotalReadData += dwReadImageData;
|
|
}
|
|
|
|
dwXferBytes /= 3;
|
|
for (i = 0; i < dwXferBytes; i++)
|
|
{
|
|
pBuffer[i] = pCalBuffer[i * 3];
|
|
pBuffer[dwXferBytes + i] = pCalBuffer[i * 3 + 1];
|
|
pBuffer[dwXferBytes * 2 + i] = pCalBuffer[i * 3 + 2];
|
|
}
|
|
free (pCalBuffer);
|
|
}
|
|
else
|
|
{
|
|
while (dwTotalReadData < dwXferBytes)
|
|
{
|
|
dwReadImageData = dwXferBytes - dwTotalReadData;
|
|
if (dwReadImageData > 65536)
|
|
dwReadImageData = 65536;
|
|
|
|
status = DMARead (chip, dwReadImageData, pBuffer + dwTotalReadData);
|
|
if (status != SANE_STATUS_GOOD)
|
|
break;
|
|
dwTotalReadData += dwReadImageData;
|
|
}
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_MotorMove (ASIC * chip, SANE_Bool isForward, unsigned int dwTotalSteps)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Byte bActionType;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
bActionType = isForward ? ACTION_TYPE_FORWARD : ACTION_TYPE_BACKWARD;
|
|
status = SimpleMotorMove (chip, 5000, 1800, 7000, 200, dwTotalSteps,
|
|
bActionType);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_CarriageHome (ASIC * chip)
|
|
{
|
|
SANE_Status status;
|
|
SANE_Bool LampHome;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
status = IsCarriageHome (chip, &LampHome);
|
|
if (status != SANE_STATUS_GOOD)
|
|
return status;
|
|
|
|
if (!LampHome)
|
|
status = SimpleMotorMove (chip, 5000, 1200, 3000, 220, 766,
|
|
ACTION_TYPE_BACKTOHOME);
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return status;
|
|
}
|
|
|
|
SANE_Status
|
|
Asic_SetShadingTable (ASIC * chip, unsigned short * pWhiteShading,
|
|
unsigned short * pDarkShading,
|
|
unsigned short wXResolution, unsigned short wWidth)
|
|
{
|
|
unsigned short i, j, n;
|
|
unsigned short wValidPixelNumber;
|
|
double dbXRatioAdderDouble;
|
|
DBG_ASIC_ENTER ();
|
|
|
|
if (chip->firmwarestate != FS_OPENED)
|
|
{
|
|
DBG (DBG_ERR, "scanner is busy or not open\n");
|
|
return SANE_STATUS_INVAL;
|
|
}
|
|
|
|
if (wXResolution > (SENSOR_DPI / 2))
|
|
dbXRatioAdderDouble = SENSOR_DPI / wXResolution;
|
|
else
|
|
dbXRatioAdderDouble = (SENSOR_DPI / 2) / wXResolution;
|
|
|
|
wValidPixelNumber = (unsigned short) ((wWidth + 4) * dbXRatioAdderDouble);
|
|
DBG (DBG_ASIC, "wValidPixelNumber=%d\n", wValidPixelNumber);
|
|
|
|
/* Free old shading table, if present.
|
|
First 4 and last 5 elements of shading table cannot be used. */
|
|
chip->dwShadingTableSize = ShadingTableSize (wValidPixelNumber) *
|
|
sizeof (unsigned short);
|
|
free (chip->pShadingTable);
|
|
DBG (DBG_ASIC, "allocating a new shading table, size=%d byte\n",
|
|
chip->dwShadingTableSize);
|
|
chip->pShadingTable = malloc (chip->dwShadingTableSize);
|
|
if (!chip->pShadingTable)
|
|
{
|
|
DBG (DBG_ASIC, "pShadingTable == NULL\n");
|
|
return SANE_STATUS_NO_MEM;
|
|
}
|
|
|
|
n = 0;
|
|
for (i = 0; i <= (wValidPixelNumber / 40); i++)
|
|
{
|
|
unsigned short numPixel = 40;
|
|
if (i == (wValidPixelNumber / 40))
|
|
numPixel = wValidPixelNumber % 40;
|
|
|
|
for (j = 0; j < numPixel; j++)
|
|
{
|
|
chip->pShadingTable[i * 256 + j * 6] =
|
|
htole16 (pDarkShading[n * 3]);
|
|
chip->pShadingTable[i * 256 + j * 6 + 2] =
|
|
htole16 (pDarkShading[n * 3 + 1]);
|
|
chip->pShadingTable[i * 256 + j * 6 + 4] =
|
|
htole16 (pDarkShading[n * 3 + 2]);
|
|
|
|
chip->pShadingTable[i * 256 + j * 6 + 1] =
|
|
htole16 (pWhiteShading[n * 3]);
|
|
chip->pShadingTable[i * 256 + j * 6 + 3] =
|
|
htole16 (pWhiteShading[n * 3 + 1]);
|
|
chip->pShadingTable[i * 256 + j * 6 + 5] =
|
|
htole16 (pWhiteShading[n * 3 + 2]);
|
|
|
|
if ((j % (unsigned short) dbXRatioAdderDouble) ==
|
|
(dbXRatioAdderDouble - 1))
|
|
n++;
|
|
|
|
if (i == 0 && j < 4 * dbXRatioAdderDouble)
|
|
n = 0;
|
|
}
|
|
}
|
|
|
|
DBG_ASIC_LEAVE ();
|
|
return SANE_STATUS_GOOD;
|
|
}
|