diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-10-06 14:00:40 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-10-06 14:00:40 +0200 |
commit | 6e9c41a892ed0e0da326e0278b3221ce3f5713b8 (patch) | |
tree | 2e301d871bbeeb44aa57ff9cc070fcf3be484487 /backend/plustek-pp_dac.c |
Initial import of sane-backends version 1.0.24-1.2
Diffstat (limited to 'backend/plustek-pp_dac.c')
-rw-r--r-- | backend/plustek-pp_dac.c | 2658 |
1 files changed, 2658 insertions, 0 deletions
diff --git a/backend/plustek-pp_dac.c b/backend/plustek-pp_dac.c new file mode 100644 index 0000000..dd35ce7 --- /dev/null +++ b/backend/plustek-pp_dac.c @@ -0,0 +1,2658 @@ +/* @file plustek-pp_dac.c + * @brief all the shading function formerly found in shading.c. + * don't ask me why I called this file dac.c... + * + * based on sources acquired from Plustek Inc. + * Copyright (C) 1998 Plustek Inc. + * Copyright (C) 2000-2004 Gerhard Jaeger <gerhard@gjaeger.de> + * also based on the work done by Rick Bronson + * + * History: + * - 0.30 - initial version + * - 0.31 - no changes + * - 0.32 - no changes + * - 0.33 - added some comments + * - 0.34 - slight changes + * - 0.35 - removed SetInitialGainRAM from structure pScanData + * - 0.36 - added dacP96001WaitForShading and changed dacP96WaitForShading to + * dacP96003WaitForShading + * - changes, due to define renaming + * - 0.37 - removed dacP98FillShadingDarkToShadingRegister() + * - removed // comments + * - some code cleanup + * - 0.38 - added P12 stuff + * - 0.39 - no changes + * - 0.40 - disabled the A3I stuff + * - 0.41 - no changes + * - 0.42 - changed include names + * - 0.43 - no changes + * . + * <hr> + * This file is part of the SANE package. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * As a special exception, the authors of SANE give permission for + * additional uses of the libraries contained in this release of SANE. + * + * The exception is that, if you link a SANE library with other files + * to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public + * License. Your use of that executable is in no way restricted on + * account of linking the SANE library code into it. + * + * This exception does not, however, invalidate any other reasons why + * the executable file might be covered by the GNU General Public + * License. + * + * If you submit changes to SANE to the maintainers to be included in + * a subsequent release, you agree by submitting the changes that + * those changes may be distributed with this exception intact. + * + * If you write modifications of your own for SANE, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * <hr> + */ +#include "plustek-pp_scan.h" + +/************************** local definitions ********************************/ + +/***************************** global vars ***********************************/ + +static const Byte a_bCorrectTimesTable[4] = {0, 1, 2, 4}; + +static ULong dwADCPipeLine = 4 * 4; +static ULong dwReadyLen; + +/*************************** local functions *********************************/ + +/** + */ +static void dacP98AdjustGainAverage( pScanData ps ) +{ + pUChar pDest, pSrce; + ULong dw, dw1; + UShort wSum; + + pDest = pSrce = ps->pScanBuffer1; + + for (dw1 = 0; dw1 < (2560 * 3) / 16; dw1++, pDest++) { + for (dw = 0, wSum = 0; dw < 16; dw++, pSrce++) + wSum += *pSrce; + + *pDest = wSum / 16; + } +} + +/** + */ +static void dacP98FillDarkDAC( pScanData ps ) +{ + IODataRegisterToDAC( ps, 0x20, ps->bRedDAC ); + IODataRegisterToDAC( ps, 0x21, ps->bGreenDAC ); + IODataRegisterToDAC( ps, 0x22, ps->bBlueDAC ); +} + +/** + */ +static void dacP98SetReadFBKRegister( pScanData ps ) +{ + IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); + + ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE + _SCAN_1ST_AVERAGE; + + IOSelectLampSource( ps ); + IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); + + ps->AsicReg.RD_Motor0Control = _MotorOn; + ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; + ps->AsicReg.RD_Origin = 4; + ps->AsicReg.RD_Pixels = 512; + ps->AsicReg.RD_Motor1Control = 0; + ps->AsicReg.RD_Motor0Control = 0; + + ps->AsicReg.RD_ModelControl = _LED_CONTROL + _LED_ACTIVITY; + + if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { + ps->AsicReg.RD_Dpi = 300; + ps->AsicReg.RD_ModelControl += _ModelDpi300; + + } else { + ps->AsicReg.RD_Dpi = 600; + ps->AsicReg.RD_ModelControl += _ModelDpi600; + } +} + +/** + */ +static UShort dacP98CalDarkOff( pScanData ps, UShort wChDarkOff, + UShort wDACCompareHigh, UShort wDACOffset ) +{ + UShort wTemp; + + if ((_CCD_518 == ps->Device.bCCDID) || (_CCD_535 == ps->Device.bCCDID)) { + wTemp = wChDarkOff + wDACOffset; + } else { + + if (_CCD_3797 == ps->Device.bCCDID) { + if (wChDarkOff > wDACOffset) { + wTemp = wChDarkOff - wDACOffset; + } else { + wTemp = 0; + } + } else { + if (wChDarkOff > wDACCompareHigh) { + wTemp = wChDarkOff - wDACCompareHigh; + } else { + wTemp = 0; + } + } + } + return wTemp; +} + +/** + */ +static Bool dacP98AdjustDAC( UShort DarkOff, UShort wHigh, + UShort wLow, pUChar pbReg, Bool *fDACStopFlag ) +{ + if (DarkOff > wHigh) { + if ((DarkOff - wHigh) > 10) { + if ((DarkOff - wHigh) > 2550) + *pbReg += ((DarkOff - wHigh) / 20); + else + *pbReg += ((DarkOff - wHigh) / 10); + } else + *pbReg += 1; + + if (!(*pbReg)) + *pbReg = 0xff; + + *fDACStopFlag = _FALSE; + return _FALSE; + + } else { + if (DarkOff < wLow) { + if (DarkOff > 0) + *pbReg -= 2; + else + *pbReg -= 10; + + *fDACStopFlag = _FALSE; + return _FALSE; + } else + return _TRUE; + } +} + +/** + */ +static Bool dacP98CheckChannelDarkLevel( pScanData ps ) +{ + Bool fDACStopFlag = _TRUE; + + dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Red, + ps->Shade.pCcdDac->DarkCmpHi.Colors.Red, + ps->Shade.pCcdDac->DarkCmpLo.Colors.Red, + &ps->bRedDAC, &fDACStopFlag ); + dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Green, + ps->Shade.pCcdDac->DarkCmpHi.Colors.Green, + ps->Shade.pCcdDac->DarkCmpLo.Colors.Green, + &ps->bGreenDAC, &fDACStopFlag ); + dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Blue, + ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue, + ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue, + &ps->bBlueDAC, &fDACStopFlag ); + + return fDACStopFlag; +} + +/** Average left offset 30, 16 pixels as each color's dark level + */ +static void dacP98FillChannelDarkLevelControl( pScanData ps ) +{ + DataPointer p; + ULong dwPos, dw, dwSum; + + if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { + dwPos = 0x10 * 3; + } else { + dwPos = 0x20 * 2; + } + + for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos), dwSum = 0, dw = 16; + dw; dw--, p.pw++) { + dwSum += (ULong)(*p.pw); + } + + ps->Shade.DarkOffset.Colors.Red = (UShort)(dwSum / 16); + + for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos + 1024), dwSum = 0, dw = 16; + dw; dw--, p.pw++) { + dwSum += (ULong)(*p.pw); + } + + ps->Shade.DarkOffset.Colors.Green = (UShort)(dwSum / 16); + + for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos + 1024 * 2), dwSum = 0, dw = 16; + dw; dw--, p.pw++) { + dwSum += (ULong)(*p.pw); + } + + ps->Shade.DarkOffset.Colors.Blue = (UShort)(dwSum / 16); +} + +/** + */ +static void dacP98AdjustGain( pScanData ps ) +{ + DataPointer p; + ULong dw; + UShort w; + Byte b[3]; + pUChar pbReg[3]; + + dacP98AdjustGainAverage( ps ); + + pbReg[0] = &ps->bRedGainIndex; + pbReg[1] = &ps->bGreenGainIndex; + pbReg[2] = &ps->bBlueGainIndex; + + for (w = 0, p.pb = ps->pScanBuffer1; w < 3; w++) { + + for (dw = 2560 / 16, b [w] = 0; dw; dw--, p.pb++) { + if (b [w] < *p.pb) + b [w] = *p.pb; + } + if (b[w] < _GAIN_LOW) { + if ((_GAIN_P98_HIGH - b[w]) < b[w]) + *(pbReg[w]) += 1; + else + *(pbReg[w]) += 4; + } else { + if (b[w] > _GAIN_P98_HIGH) + *(pbReg[w]) -= 1; + } + } +} + +/** + */ +static void dacP98CheckLastGain( pScanData ps ) +{ + DataPointer p; + ULong dw; + UShort w; + Byte b[3]; + pUChar pbReg[3]; + + dacP98AdjustGainAverage( ps ); + + pbReg[0] = &ps->bRedGainIndex; + pbReg[1] = &ps->bGreenGainIndex; + pbReg[2] = &ps->bBlueGainIndex; + + for (w = 0, p.pb = ps->pScanBuffer1; w < 3; w++) { + for (dw = 2560 / 16, b [w] = 0; dw; dw--, p.pb++) { + if (b[w] < *p.pb) + b[w] = *p.pb; + } + + if (b[w] > _GAIN_P98_HIGH) { + *(pbReg [w]) -= 1; + } + } +} + +/** + */ +static void dacP98FillGainInitialRestRegister( pScanData ps ) +{ + ps->OpenScanPath( ps ); + + IODataToRegister( ps, ps->RegThresholdGapControl, ps->AsicReg.RD_ThresholdGapCtrl ); + IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); + + ps->CloseScanPath( ps ); +} + +/** + */ +static void dacP98SetInitialGainRegister( pScanData ps ) +{ + DacP98FillGainOutDirectPort( ps ); /* R/G/B GainOut to scanner */ + dacP98FillGainInitialRestRegister( ps );/* Model Control2, LED, Correct.*/ +} + +/** Find the the most ideal intensity for each color (RGB) + */ +static void dacP98SetRGBGainRegister( pScanData ps ) +{ + IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeIdle ); + + ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; + IOSelectLampSource( ps ); + + IOCmdRegisterToScanner( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); + dacP98SetInitialGainRegister( ps ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; + ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorDirForward + _MotorHEightStep; + ps->AsicReg.RD_XStepTime = ps->bSpeed4; + + if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { + ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi300; + ps->AsicReg.RD_Origin = 32 + 60 + 4; + } else { + ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi600; + ps->AsicReg.RD_Origin = 64 + 120 + 4; + } + ps->AsicReg.RD_Dpi = 300; + ps->AsicReg.RD_Pixels = 2560; + + IOPutOnAllRegisters( ps ); +} + +/** + */ +static void dacP98FillRGBMap( pUChar pBuffer ) +{ + ULong dw, dw1; + pULong pdw = (pULong)(pBuffer); + + for( dw = 256, dw1 = 0; dw; dw--, dw1 += 0x01010101 ) { + *pdw++ = dw1; + *pdw++ = dw1; + *pdw++ = dw1; + *pdw++ = dw1; + } +} + +/** here we download the current mapping table + */ +static void dacP98DownloadMapTable( pScanData ps, pUChar pBuffer ) +{ + Byte bAddr; + ULong i; + + IODataToRegister( ps, ps->RegScanControl, + (Byte)((ps->AsicReg.RD_ScanControl & 0xfc) | _SCAN_BYTEMODE)); + + for( i = 3, bAddr = _MAP_ADDR_RED; i--; bAddr += _MAP_ADDR_SIZE ) { + + IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); + IODataToRegister( ps, ps->RegMemoryLow, 0); + IODataToRegister( ps, ps->RegMemoryHigh, bAddr ); + + IOMoveDataToScanner( ps, pBuffer, 4096 ); + pBuffer += 4096; + } + + IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); +} + +/** + */ +static void dacP98DownloadShadingTable( pScanData ps, + pUChar pBuffer, ULong size ) +{ + IODataToRegister( ps, ps->RegModeControl, _ModeShadingMem ); + IODataToRegister( ps, ps->RegMemoryLow, 0 ); + IODataToRegister( ps, ps->RegMemoryHigh, 0 ); + + /* set 12 bits output color */ + IODataToRegister( ps, ps->RegScanControl, + (Byte)(ps->AsicReg.RD_ScanControl | _SCAN_12BITMODE)); + + /* MoveDataToShadingRam() */ + IOMoveDataToScanner( ps ,pBuffer, size ); + + if( _ASIC_IS_98003 == ps->sCaps.AsicID ) + IODataToRegister( ps, ps->RegModeControl, _ModeScan ); + else + IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); + + DacP98FillShadingDarkToShadingRegister( ps ); +} + +/** Build a linear map for asic (this model is 12-bit scanner, there are 4096 + * map entries but just generate 256 level output, so the content must be 0 to + * 255), then fill the shading buffer (the first 3k), and map table (the last + * 1k) to asic for R & G & B channels. + * + * I need pScanBuffer2 size = 5400 * 2 * 3 + * pScanBuffer1 size = 256 * 16 * 2 + */ +static void dacP98SetInitialGainRAM( pScanData ps ) +{ + memset( ps->pScanBuffer2, 0xff, (5400 * 2 * 3)); + + dacP98DownloadShadingTable( ps, ps->pScanBuffer2, (5400 * 2 * 3)); + + dacP98FillRGBMap( ps->pScanBuffer1 ); /* Fill 12 Bits R Map */ + dacP98FillRGBMap( ps->pScanBuffer1 + 4096 ); /* Fill 12 Bits G Map */ + dacP98FillRGBMap( ps->pScanBuffer1 + 8192 ); /* Fill 12 Bits B Map */ + + dacP98DownloadMapTable( ps, ps->pScanBuffer1 ); +} + +/** Find the the most ideal intensity for each color (RGB) + */ +static void dacP98AdjustRGBGain( pScanData ps ) +{ + int bCorrectTimes; + + DBG( DBG_LOW, "dacP98AdjustRGBGain()\n" ); + + ps->OpenScanPath( ps ); + dacP98SetInitialGainRAM( ps ); /* set shading ram and read out data to */ + ps->CloseScanPath( ps ); + + ps->bRedGainIndex = 0x02; + ps->bGreenGainIndex = 0x02; + ps->bBlueGainIndex = 0x02; + + for (bCorrectTimes = 10; bCorrectTimes; bCorrectTimes-- ) { + + dacP98SetRGBGainRegister( ps ); /* shading the most brightness &*/ + ps->PauseColorMotorRunStates( ps ); /* stop scan states */ + IOReadOneShadingLine( ps, ps->pScanBuffer1, 2560UL ); + dacP98AdjustGain( ps ); + } + + dacP98SetRGBGainRegister( ps ); /* shading the most brightness & */ + ps->PauseColorMotorRunStates( ps ); /* stop scan states */ + + IOReadOneShadingLine( ps, ps->pScanBuffer1, 2560UL ); + + dacP98CheckLastGain( ps ); + DacP98FillGainOutDirectPort( ps ); +} + +/** + */ +static void dacP98SetAdjustShadingRegister( pScanData ps ) +{ + DBG( DBG_LOW, "dacP98SetAdjustShadingRegister()\n" ); + + IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeIdle ); + + ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE + _SCAN_1ST_AVERAGE; + IOSelectLampSource( ps ); + + IOCmdRegisterToScanner( ps, ps->RegScanControl, + ps->AsicReg.RD_ScanControl ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward; + ps->AsicReg.RD_XStepTime = ps->bSpeed1; + ps->AsicReg.RD_ModelControl = _LED_ACTIVITY + _LED_CONTROL; + + if (ps->bSetScanModeFlag & _ScanMode_AverageOut) { + ps->AsicReg.RD_Dpi = 300; + ps->AsicReg.RD_Pixels = 2700; + ps->AsicReg.RD_ModelControl += _ModelDpi300; + } else { + ps->AsicReg.RD_Dpi = 600; + ps->AsicReg.RD_Pixels = 5400; + ps->AsicReg.RD_ModelControl += _ModelDpi600; + } + ps->AsicReg.RD_Origin = 4; + + IOPutOnAllRegisters( ps ); +} + +/** + */ +static void dacP98ReadShadingScanLine( pScanData ps ) +{ + TimerDef timer; + + MiscStartTimer( &timer, _SECOND ); + + ps->Scan.bFifoSelect = ps->RegGFifoOffset; + + while((IOReadFifoLength( ps ) < dwReadyLen) && + !MiscCheckTimer(&timer)) { + _DO_UDELAY( 1 ); + } + + IOReadColorData( ps, ps->pScanBuffer2, ps->dwShadingLen ); +} + +/** + */ +static void dacP98GainResize( pUShort pValue, UShort wResize) +{ + DataType Data; + Byte bTemp; + + Data.dwValue = ((ULong) *pValue) * (ULong) wResize / 100; + + if (0x1000 <= Data.dwValue) + Data.wValue = 0xfff; + + Data.wValue *= 16; + + bTemp = Data.wOverlap.b1st; + Data.wOverlap.b1st = Data.wOverlap.b2nd; + Data.wOverlap.b2nd = bTemp; + + *pValue = Data.wValue; +} + +/** + */ +static void dacP98SortHilightShadow( pScanData ps, pUShort pwData, + ULong dwHilightOff, ULong dwShadowOff ) +{ + ULong dwLines, dwPixels; + UShort wVCmp, wTmp; + pUShort pw; + + for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++) { + + pw = (pUShort)ps->Shade.pHilight + dwHilightOff + dwPixels; + wVCmp = pwData[dwPixels] & 0xfffU; + + for (dwLines = _DEF_BRIGHTEST_SKIP; dwLines--; pw += 5400UL) { + if (wVCmp > *pw) { + wTmp = wVCmp; + wVCmp = *pw; + *pw = wTmp; + } + } + } + for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++) { + + pw = ps->pwShadow + dwShadowOff + dwPixels; + wVCmp = pwData [dwPixels] & 0xfffU; + + for (dwLines = _DEF_DARKEST_SKIP; dwLines--; pw += 5400UL) { + + if (wVCmp < *pw) { + wTmp = wVCmp; + wVCmp = *pw; + *pw = wTmp; + } + } + } +} + +/** + */ +static void dacP98WriteBackToShadingRAM( pScanData ps ) +{ + ULong dw; + + pUShort pBuffer = (pUShort)ps->pScanBuffer2; + + DBG( DBG_LOW, "dacP98WriteBackToShadingRAM()\n" ); + + if (ps->DataInf.wPhyDataType >= COLOR_TRUE24) { + + for (dw = 0; dw < 5400; dw++) { + + *pBuffer = ((pUShort)ps->pScanBuffer1)[dw] - + ps->Shade.DarkOffset.Colors.Red; + dacP98GainResize( pBuffer, + ps->Shade.pCcdDac->GainResize.Colors.Red ); + pBuffer ++; + + *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400] - + ps->Shade.DarkOffset.Colors.Green; + dacP98GainResize( pBuffer, + ps->Shade.pCcdDac->GainResize.Colors.Green ); + pBuffer ++; + + *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400 * 2] - + ps->Shade.DarkOffset.Colors.Blue; + dacP98GainResize( pBuffer, + ps->Shade.pCcdDac->GainResize.Colors.Blue ); + pBuffer ++; + } + + } else { + for (dw = 0; dw < 5400; dw++) { + + DataType Data; + Byte bTemp; + + *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400] - + ps->Shade.DarkOffset.Colors.Green; + + Data.wValue = (*pBuffer) * 16; + bTemp = Data.wOverlap.b1st; + Data.wOverlap.b1st = Data.wOverlap.b2nd; + Data.wOverlap.b2nd = bTemp; + *pBuffer = Data.wValue; + pBuffer++; + } + + } + dacP98DownloadShadingTable( ps, ps->pScanBuffer2, (5400 * 2 * 3)); +} + +/** + */ +static void dacP98ShadingRunLoop( pScanData ps ) +{ + int i; + DataPointer p; + + p.pb = ps->a_nbNewAdrPointer; + + switch( ps->IO.portMode ) { + case _PORT_SPP: + case _PORT_BIDI: + *p.pw++ = 0; + for (i = 0; i < 7; i++) + *p.pdw++ = 0x00800700; + *p.pw = 0; + break; + + default: + *p.pb++ = 0; + for (i = 0; i < 15; i++) + *p.pw++ = 0xf888; + *p.pb = 0; + } + + IOSetToMotorRegister( ps ); +} + +/** + */ +static void dacP98Adjust12BitShading( pScanData ps ) +{ + DataPointer pd, pt; + ULong dw, dw1, dwLoop; + + DBG( DBG_LOW, "dacP98Adjust12BitShading()\n" ); + + memset( ps->pScanBuffer1, 0, (5400 * 4 * 3)); + + if( ps->Shade.pHilight && (_Shading_32Times == ps->bShadingTimeFlag)) { + + memset( ps->Shade.pHilight, 0, (ps->dwHilight * 2UL)); + + for (dw = 0; dw < ps->dwShadow; dw++) + ps->pwShadow[dw] = 0xfff; + } + + /* + * in the original code this function does not exist ! + * (of course the code behind the function does ;-) + */ + dacP98SetAdjustShadingRegister( ps ); + + dacP98ShadingRunLoop( ps ); + _DODELAY( 24 ); + + if ((ps->DataInf.dwScanFlag & SCANDEF_TPA ) || + (_Shading_32Times == ps->bShadingTimeFlag)) { + dwLoop = 32; + } else { + if (_Shading_16Times == ps->bShadingTimeFlag) { + dwLoop = 16; + } else { + dwLoop = 4; + } + } + + for (dw1 = 0; dw1 < dwLoop; dw1++) { + + ps->Scan.bFifoSelect = ps->RegGFifoOffset; + + dacP98ReadShadingScanLine( ps ); + + if((_Shading_32Times == ps->bShadingTimeFlag) && ps->Shade.pHilight ) { + + dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2, 0, 0 ); + dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2 + + ps->dwShadingPixels, + ps->dwHilightCh, ps->dwShadowCh ); + + dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2 + + ps->dwShadingPixels * 2, + ps->dwHilightCh * 2, ps->dwShadowCh * 2); + } + + /* SumAdd12BitShadingR */ + pd.pw = (pUShort)ps->pScanBuffer2; + pt.pdw = (pULong)(ps->pScanBuffer1 + dwADCPipeLine); + + for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++) + *pt.pdw += (ULong)(*pd.pw & 0x0fff); + + /* SumAdd10BitShadingG */ + if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) + pd.pw = (pUShort)(ps->pScanBuffer2 + 2700 * 2); + else + pd.pw = (pUShort)(ps->pScanBuffer2 + 5400 * 2); + + pt.pdw = (pULong)(ps->pScanBuffer1 + 5400 * 4 + dwADCPipeLine); + + for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++) + *pt.pdw += (ULong)(*pd.pw & 0x0fff); + + /* SumAdd12BitShadingB */ + if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) + pd.pw = (pUShort)(ps->pScanBuffer2 + 2700 * 4); + else + pd.pw = (pUShort)(ps->pScanBuffer2 + 5400 * 4); + + pt.pdw = (pULong)(ps->pScanBuffer1 + 5400 * 8 + dwADCPipeLine); + + for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++) + *pt.pdw += (ULong)(*pd.pw * 94 / 100 & 0x0fff); + + /* one line */ + if (IOReadFifoLength( ps ) <= 2500) + IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); + } + + TPAP98001AverageShadingData( ps ); + + ps->OpenScanPath( ps ); + dacP98WriteBackToShadingRAM( ps ); + ps->CloseScanPath( ps ); +} + +/** + */ +static Bool dacP98WaitForShading( pScanData ps ) +{ + Byte oldLineControl; + + DBG( DBG_LOW, "dacP98WaitForShading()\n" ); + + /* + * before getting the shading data, (re)init the ASIC + */ + ps->InitialSetCurrentSpeed( ps ); + ps->ReInitAsic( ps, _TRUE ); + + IOCmdRegisterToScanner( ps, ps->RegLineControl, + ps->AsicReg.RD_LineControl ); + + ps->Shade.DarkOffset.Colors.Red = 0; + ps->Shade.DarkOffset.Colors.Green = 0; + ps->Shade.DarkOffset.Colors.Blue = 0; + + /* + * according to the scan mode, switch on the lamp + */ + IOSelectLampSource( ps ); + IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); + + if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { + ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi300; + } else { + ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi600; + } + IOCmdRegisterToScanner( ps, ps->RegModelControl, + ps->AsicReg.RD_ModelControl ); + + IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeScan); + + oldLineControl = ps->AsicReg.RD_LineControl; + IOSetXStepLineScanTime( ps, _DEFAULT_LINESCANTIME ); + + /* set line control */ + IOCmdRegisterToScanner( ps, ps->RegLineControl, + ps->AsicReg.RD_LineControl ); + + /* Wait for Sensor to position */ + if( !ps->GotoShadingPosition( ps )) + return _FALSE; + + ps->AsicReg.RD_LineControl = oldLineControl; + IOCmdRegisterToScanner( ps, ps->RegLineControl, + ps->AsicReg.RD_LineControl ); + + dwADCPipeLine = 4 * 4; + + if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { + dwReadyLen = 2500; + ps->dwShadingLen = 2700 * 2; + ps->dwShadingPixels = 2700; + } else { + dwReadyLen = 5000; + ps->dwShadingLen = 5400 * 2; + ps->dwShadingPixels = 5400; + } + + dacP98AdjustRGBGain ( ps ); + DacP98AdjustDark ( ps ); + dacP98Adjust12BitShading( ps ); + + ps->OpenScanPath( ps ); + DacP98FillShadingDarkToShadingRegister( ps ); + + if ( COLOR_BW != ps->DataInf.wPhyDataType ) + dacP98DownloadMapTable( ps, ps->a_bMapTable ); + + ps->CloseScanPath( ps ); + + return _TRUE; +} + +/** Set RAM bank and size, then write the data to it + */ +static void dacP96FillWhole4kRAM( pScanData ps, pUChar pBuf ) +{ + ps->OpenScanPath( ps ); + + IODataToRegister( ps, ps->RegMemAccessControl, + ps->Asic96Reg.RD_MemAccessControl ); + + ps->AsicReg.RD_ModeControl = _ModeProgram; + IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); + + IOMoveDataToScanner( ps, pBuf, ps->ShadingBankSize ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); + + ps->CloseScanPath( ps ); +} + +/** + */ +static void dacP96FillChannelDarkOffset( pScanData ps ) +{ + ps->OpenScanPath( ps ); + + IODataToRegister( ps, ps->RegRedChDarkOffset, + ps->Asic96Reg.RD_RedChDarkOff ); + IODataToRegister( ps, ps->RegGreenChDarkOffset, + ps->Asic96Reg.RD_GreenChDarkOff ); + IODataToRegister( ps, ps->RegBlueChDarkOffset, + ps->Asic96Reg.RD_BlueChDarkOff ); + + ps->CloseScanPath( ps ); +} + +/** + */ +static void dacP96FillEvenOddControl( pScanData ps ) +{ + ps->OpenScanPath( ps ); + + IODataToRegister( ps, ps->RegRedChEvenOffset, + ps->Asic96Reg.RD_RedChEvenOff ); + IODataToRegister( ps, ps->RegGreenChEvenOffset, + ps->Asic96Reg.RD_GreenChEvenOff ); + IODataToRegister( ps, ps->RegBlueChEvenOffset, + ps->Asic96Reg.RD_BlueChEvenOff ); + IODataToRegister( ps, ps->RegRedChOddOffset, + ps->Asic96Reg.RD_RedChOddOff ); + IODataToRegister( ps, ps->RegGreenChOddOffset, + ps->Asic96Reg.RD_GreenChOddOff ); + IODataToRegister( ps, ps->RegBlueChOddOffset, + ps->Asic96Reg.RD_BlueChOddOff ); + + ps->CloseScanPath( ps ); +} + +/** Used for capture data to pScanData->pPrescan16. + * Used to replace: + * 1) ReadFBKScanLine (3 * 1024, 5) + * 2) ReadOneScanLine (3 * 2560, 11) + * 4) ReadShadingScanLine (3 * 1280, 6) + */ +static void dacP96ReadDataWithinOneSecond( pScanData ps, + ULong dwLen, Byte bBlks ) +{ + TimerDef timer; + + MiscStartTimer( &timer, _SECOND ); + + while((IODataRegisterFromScanner( ps, ps->RegFifoOffset) < bBlks) && + !MiscCheckTimer(&timer)); + + IOReadScannerImageData( ps, ps->pPrescan16, dwLen ); +} + +/** + */ +static void dacP96GetEvenOddOffset( pUChar pb, pWordVal pwv ) +{ + ULong dw; + UShort we, wo; + + for (dw = 8, we = wo = 0; dw; dw-- ) { + we += *pb++; + wo += *pb++; + } + + pwv->b1st = (Byte)(we >> 3); + pwv->b2nd = (Byte)(wo >> 3); +} + +/** + */ +static void dacP96SumAverageShading( pScanData ps, pUChar pDest, pUChar pSrce ) +{ + ULong dw; + UShort wLeft[6]; + UShort wSumL, wSumR; + + pSrce += ps->Offset70 + ps->Device.DataOriginX; + pDest += ps->Offset70 + ps->Device.DataOriginX; + + wLeft[0] = wLeft[1] = wLeft[2] = + wLeft[3] = wLeft[4] = wLeft[5] = (UShort)*pSrce; + + wSumL = wLeft[0] * 6; + wSumR = (UShort)pSrce[1] + pSrce[2] + pSrce[3] + pSrce[4] + + pSrce[5] + pSrce[6]; + +/* for (dw = 2772; dw; dw--, pSrce++, pDest++) */ + for (dw = ps->BufferSizePerModel - 6; dw; dw--, pSrce++, pDest++) { + + *pDest = (Byte)(((UShort)*pSrce * 4 + wSumL + wSumR) / 16); + wSumL = wSumL - wLeft [0] + (UShort)*pSrce; + + wLeft[0] = wLeft[1]; + wLeft[1] = wLeft[2]; + wLeft[2] = wLeft[3]; + wLeft[3] = wLeft[4]; + wLeft[4] = wLeft[5]; + wLeft[5] = (UShort)*pSrce; + wSumR = wSumR - (UShort) *(pSrce + 1) + (UShort) *(pSrce + 7); + } +} + +/** + */ +static void dacP96WriteLinearGamma( pScanData ps, + pUChar pBuf, ULong dwEntries, Byte bBank ) +{ + ULong dw; + pULong pdw = (pULong)(pBuf + ps->ShadingBufferSize); + + for (dw = 0; dwEntries; pdw++, dwEntries--, dw += 0x01010101) + *pdw = dw; + + ps->Asic96Reg.RD_MemAccessControl = bBank; + + dacP96FillWhole4kRAM( ps, pBuf ); +} + +/** + */ +static void dacP96FillChannelShadingOffset( pScanData ps ) +{ + ps->OpenScanPath( ps ); + + IODataToRegister( ps, ps->RegRedChShadingOffset, + ps->Asic96Reg.u28.RD_RedChShadingOff); + IODataToRegister( ps, ps->RegGreenChShadingOffset, + ps->Asic96Reg.u29.RD_GreenChShadingOff); + IODataToRegister( ps, ps->RegBlueChShadingOffset, + ps->Asic96Reg.RD_BlueChShadingOff); + + ps->CloseScanPath( ps ); +} + +/** + */ +static void dacP96GetHilightShadow( pScanData ps, + pUChar pBuf, pUChar pChOff, pUChar pHigh ) +{ + ULong dw; + + /* GetShadingImageExtent (ps) */ + if (ps->DataInf.wAppDataType < COLOR_256GRAY) + dw = (ULong)(ps->DataInf.crImage.cx & 0xfff8); + else + dw = (ULong)ps->DataInf.crImage.cx; + + for( pBuf += ps->DataInf.crImage.x, *pChOff = 0xff, *pHigh = 0; + dw; dw--, pBuf++ ) { + + if (*pChOff < *pBuf) { + if (*pHigh < *pBuf) + *pHigh = *pBuf; /* brightest */ + } else + *pChOff = *pBuf; /* darkest */ + } +} + +/** + */ +static void dacP96ReadColorShadingLine( pScanData ps ) +{ + Byte b2ndDiscard, b3rdDiscard, b1stReadLines, b2ndReadLines; + Byte b3rdReadLines; + ULong dw; + DataType Data; + + /* ClearScanBuffer1 (ps) */ + /* buffer to keep sum of data */ + memset( ps->pScanBuffer1, 0, ps->BufferForDataRead1 ); + + b2ndDiscard = ps->b2ndLinesOffset; + b3rdDiscard = ps->b1stLinesOffset; + b1stReadLines = b2ndReadLines = b3rdReadLines = 8; + + while( _TRUE ) { + + /* ReadShadingScanLine(ps) */ + dacP96ReadDataWithinOneSecond( ps, ps->ShadingScanLineLen, + ps->ShadingScanLineBlks ); + + if (b1stReadLines) { + + b1stReadLines--; + + /* SumAdd10BitShadingR */ + for (dw = 0; dw < ps->BufferSizeBase; dw++) + ((pUShort)ps->pScanBuffer1)[dw] += (UShort)ps->pPrescan16 [dw]; + } + + if (!b2ndDiscard) { + if (b2ndReadLines) { + b2ndReadLines--; + /* SumAdd10BitShadingG */ + for (dw = ps->BufferSizeBase;dw < (ULong)ps->BufferSizeBase * 2;dw++) { + ((pUShort)ps->pScanBuffer1)[dw] += + (UShort)ps->pPrescan16[dw]; + } + } + } else + b2ndDiscard--; + + if (!b3rdDiscard) { + if (b3rdReadLines) { + b3rdReadLines--; + /* SumAdd10BitShadingB */ + for (dw = ps->BufferSizeBase * 2; + dw < (ULong)ps->BufferSizeBase * 3; dw++) { + ((pUShort)ps->pScanBuffer1)[dw] += + (UShort)ps->pPrescan16[dw]; + } + } else + break; + } else + b3rdDiscard--; + + IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); + } + + for (dw = 0; dw < (ULong)ps->BufferSizeBase * 3; dw++) { + + Data.wOverlap.b1st = + Data.wOverlap.b2nd = (Byte)(((pUShort)ps->pScanBuffer1)[dw] / 8); + ((pUShort)ps->pPrescan16)[dw] = Data.wValue; + } +} + +/** + */ +static void dacP96SetShadingGainProc( pScanData ps, Byte bHigh, ULong dwCh ) +{ + Byte bDark, bGain, bGainX2, bGainX4, bMask; + pUChar pbChDark, pbSrce, pbDest; + ULong dw; + + pbChDark = NULL, pbSrce = NULL, pbDest = NULL; + bDark = 0, bGain = 0, bGainX2 = 0, bGainX4 = 0, bMask = 0; + + switch( dwCh ) { + + case 0: /* red */ + pbChDark = &ps->Asic96Reg.u28.RD_RedChShadingOff; + pbSrce = ps->pPrescan16; + pbDest = ps->pScanBuffer1 + ps->Offset70 + ps->Device.DataOriginX; + bGainX2 = 1; + bGainX4 = 3; + bMask = 0x3c; + break; + + case 1: /* green */ + pbChDark = &ps->Asic96Reg.u29.RD_GreenChShadingOff; + pbSrce = ps->pPrescan16 + ps->BufferSizePerModel; + pbDest = ps->pScanBuffer1 + ps->Offset70 + ps->ShadingBankSize + + ps->Device.DataOriginX; + bGainX2 = 4; + bGainX4 = 0x0c; + bMask = 0x33; + break; + + case 2: + pbChDark = &ps->Asic96Reg.RD_BlueChShadingOff; + pbSrce = ps->pPrescan16 + ps->BufferSizePerModel * 2; + pbDest = ps->pScanBuffer1 + ps->Offset70 + ps->ShadingBankSize * 2 + + ps->Device.DataOriginX; + bGainX2 = 0x10; + bGainX4 = 0x30; + bMask = 0x0f; + } + + bDark = *pbChDark; + if ((bHigh -= bDark) > 60U) { + /* Hilight - Shadow > 60, Quality not so good */ + bGain = bGainX2; /* Gain x 2 */ + if (bHigh > 120U) + bGain = bGainX4; /* Poor quality, Gain x 4 */ + } else + bGain = 0; + + ps->Asic96Reg.RD_ShadingCorrectCtrl &= bMask; + ps->Asic96Reg.RD_ShadingCorrectCtrl |= bGain; + + if (!bGain) { + /* GammaGain1 (ps) */ + for (dw = ps->BufferSizePerModel; dw; dw--, pbSrce++, pbDest++) + if (*pbSrce > bDark) + *pbDest = (*pbSrce - bDark) * 4; + else + *pbDest = 0; + } else + if (bGain == bGainX2) { + /* GammaGain2 */ + for (dw = ps->BufferSizePerModel; dw; dw--, pbSrce++, pbDest++) + if (*pbSrce > bDark) + *pbDest = (*pbSrce - bDark) * 2; + else + *pbDest = 0; + } else { + /* GammaGain4 (ps) */ + memcpy( pbDest, pbSrce, ps->BufferSizePerModel ); + *pbChDark = 0; + } +} + +/** + */ +static void dacP96FillShadingAndGammaTable( pScanData ps ) +{ + ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankRed; /* R */ + dacP96FillWhole4kRAM( ps, ps->pPrescan16 ); + + ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankGreen; /* G */ + dacP96FillWhole4kRAM( ps, ps->pPrescan16 ); + + ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankBlue; /* B */ + dacP96FillWhole4kRAM( ps, ps->pPrescan16 ); +} + +/** + */ +static void dacP96SetInitialGainRAM( pScanData ps ) +{ + ULong dw, dw1; + pULong pdw = (pULong)(ps->pPrescan16 + ps->ShadingBufferSize); + + memset( ps->pPrescan16, 0xff, ps->ShadingBufferSize ); + + for (dw = 256, dw1 = 0; dw; dw--, dw1 += 0x01010101, pdw++) + *pdw = dw1; + + dacP96FillShadingAndGammaTable( ps ); +} + +/** + */ +static void dacP96Adjust10BitShading( pScanData ps ) +{ + pULong pdw; + ULong dw; + Byte bRedHigh, bGreenHigh, bBlueHigh; + + /* ShadingMotorRunLoop(ps) + * set scan states as: + * 40h, 00, 00, 00, 40h, 01, 03, 02, ... (repeat) + * so, read a R/G/B line every 2 steps + */ + pdw = (pULong)ps->a_nbNewAdrPointer; + for (dw = 0; dw < 4; dw++) { + *pdw++ = 0x40; + *pdw++ = 0x02030140; + } + + dacP96SetInitialGainRAM( ps); /* initiates the shading buffers and maps */ + + /* SetAdjustShadingRegister(ps) */ + /* Prepare Physical/2 dpi, 8.5" scanning condition for reading the shading area */ + ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; + ps->Asic96Reg.RD_MotorControl = ps->IgnorePF | ps->MotorOn | + _MotorDirForward; + ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; + ps->AsicReg.RD_Dpi = ps->PhysicalDpi / 2; + ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + + ps->Device.DataOriginX); + ps->AsicReg.RD_Pixels = ps->BufferSizeBase; + IOPutOnAllRegisters( ps ); + + ps->Asic96Reg.RD_ShadingCorrectCtrl = _ShadingRCorrectX4|_ShadingGCorrectX4| + _ShadingBCorrectX4; + IOCmdRegisterToScanner( ps, ps->RegShadingCorrectCtrl, + ps->Asic96Reg.RD_ShadingCorrectCtrl ); + + /* Read shaded data and do average */ + dacP96ReadColorShadingLine( ps ); + + /* ExpandAndAverage (ps) ------------------------------------------------*/ +/* + for (dw = 0; dw < 1280 * 3; dw++) + { + Data.wOverlap.b1st = + Data.wOverlap.b2nd = (Byte)(((pUShort) ps->pScanBuffer1)[dw] / 8); + ((pULong) ps->pPrescan16)[dw] = Data.wValue; + } +*/ + /* CalculateShadingOffset (ps); */ + dacP96GetHilightShadow( ps, ps->pPrescan16, + &ps->Asic96Reg.u28.RD_RedChShadingOff, &bRedHigh ); + + dacP96GetHilightShadow( ps, ps->pPrescan16 + ps->BufferSizePerModel, + &ps->Asic96Reg.u29.RD_GreenChShadingOff, &bGreenHigh ); + + dacP96GetHilightShadow( ps, ps->pPrescan16 + ps->BufferSizePerModel * 2, + &ps->Asic96Reg.RD_BlueChShadingOff, &bBlueHigh ); + + /* SubTheImageDataBase (ps) */ + dacP96SetShadingGainProc( ps, bRedHigh, 0 ); /* red */ + dacP96SetShadingGainProc( ps, bGreenHigh, 1 ); /* green */ + dacP96SetShadingGainProc( ps, bBlueHigh, 2 ); /* blue */ + dacP96FillChannelShadingOffset( ps ); + + IOCmdRegisterToScanner( ps, ps->RegShadingCorrectCtrl, + ps->Asic96Reg.RD_ShadingCorrectCtrl ); + + dacP96SumAverageShading( ps, ps->pPrescan16, ps->pScanBuffer1 ); + dacP96SumAverageShading( ps, ps->pPrescan16 + ps->ShadingBankSize, + ps->pScanBuffer1 + ps->ShadingBankSize ); + dacP96SumAverageShading( ps, ps->pPrescan16 + ps->ShadingBankSize * 2, + ps->pScanBuffer1 + ps->ShadingBankSize * 2 ); + + /* --------------------------------------------------------------------- */ + + /* PrewriteBackToGammaShadingRAM( ps) */ + dacP96WriteLinearGamma( ps, ps->pPrescan16, 256, ps->ShadingBankRed ); + dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize, 256, + ps->ShadingBankGreen ); + dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize * 2, + 256, ps->ShadingBankBlue ); +} + +/** + */ +static Bool dacP96003WaitForShading( pScanData ps ) +{ + int bCorrectTimes; + DataPointer p; + ULong dw; + UShort w; + WordVal wv; + pUChar pbReg[3]; + Byte b[3]; + + DBG( DBG_LOW, "dacP96003WaitForShading()\n" ); + + /* TurnOnLamp () */ + ps->AsicReg.RD_ScanControl |= ps->bLampOn; + IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); + + ps->Asic96Reg.RD_LedControl = _LedActControl | _LedMotorActEnable; + IOCmdRegisterToScanner(ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl); + + if ( ps->GotoShadingPosition( ps )) { + + /* AdjustRGBGain () =================================================*/ + ps->Asic96Reg.RD_RedGainOut = ps->Asic96Reg.RD_GreenGainOut = + ps->Asic96Reg.RD_BlueGainOut = 8; + ps->Asic96Reg.u26.RD_ModelControl2 = _Model2DirectOutPort; + + IOCmdRegisterToScanner(ps, ps->RegModelControl2, _Model2DirectOutPort); + + for ( bCorrectTimes = 4; bCorrectTimes >= 1; bCorrectTimes-- ) { + + ps->PauseColorMotorRunStates( ps ); + + /* SetRGBGainRegister () ----------------------------------------*/ + ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; + dacP96SetInitialGainRAM( ps ); + + /* SetInitialGainRegister () ++++++++++++++++++++++++++++++++++++*/ + ps->Asic96Reg.u28.RD_RedChShadingOff = + ps->Asic96Reg.u29.RD_GreenChShadingOff = + ps->Asic96Reg.RD_BlueChShadingOff = + ps->Asic96Reg.RD_RedChDarkOff = + ps->Asic96Reg.RD_GreenChDarkOff = + ps->Asic96Reg.RD_BlueChDarkOff = + ps->Asic96Reg.RD_RedChEvenOff = + ps->Asic96Reg.RD_GreenChEvenOff = + ps->Asic96Reg.RD_BlueChEvenOff = + ps->Asic96Reg.RD_RedChOddOff = + ps->Asic96Reg.RD_GreenChOddOff = + ps->Asic96Reg.RD_BlueChOddOff = 0; + ps->Asic96Reg.RD_ShadingCorrectCtrl = _ShadingRCorrectX4 | + _ShadingGCorrectX4 | + _ShadingBCorrectX4; + + dacP96FillChannelShadingOffset( ps ); + dacP96FillChannelDarkOffset( ps ); + dacP96FillEvenOddControl( ps ); + + /* FillGainOutDirectPort (); */ + ps->OpenScanPath( ps ); + IODataToRegister( ps, ps->RegRedGainOutDirect, + ps->Asic96Reg.RD_RedGainOut ); + IODataToRegister( ps, ps->RegGreenGainOutDirect, + ps->Asic96Reg.RD_GreenGainOut ); + IODataToRegister( ps, ps->RegBlueGainOutDirect, + ps->Asic96Reg.RD_BlueGainOut ); + + /* FillGainInitialRestRegister (); */ + IODataToRegister( ps, ps->RegModelControl2, + ps->Asic96Reg.u26.RD_ModelControl2 ); + IODataToRegister( ps, ps->RegThresholdGapControl, + ps->AsicReg.RD_ThresholdGapCtrl ); + IODataToRegister( ps, ps->RegLedControl, + ps->Asic96Reg.RD_LedControl ); + + IODataToRegister( ps, ps->RegShadingCorrectCtrl, + ps->Asic96Reg.RD_ShadingCorrectCtrl ); + + ps->CloseScanPath( ps ); + + ps->Asic96Reg.RD_MotorControl = 0; + IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; + ps->Asic96Reg.RD_MotorControl = (ps->IgnorePF | + ps->MotorOn | _MotorDirForward); + + ps->AsicReg.RD_Origin = 142; + ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; + ps->AsicReg.RD_Dpi = ps->PhysicalDpi; + ps->AsicReg.RD_Pixels = ps->BufferSizePerModel; + + IOPutOnAllRegisters( ps ); + + /*---------------------------------------------------------------*/ + + /* ReadOneScanLine (); */ + dacP96ReadDataWithinOneSecond( ps, ps->OneScanLineLen, 11 ); + + /* AdjustGain () */ + /* FindTheMaxGain (), AdjustGainOutData (); */ + + pbReg[0] = &ps->Asic96Reg.RD_RedGainOut; + pbReg[1] = &ps->Asic96Reg.RD_GreenGainOut; + pbReg[2] = &ps->Asic96Reg.RD_BlueGainOut; + + for (w = 0, p.pb = ps->pPrescan16; w < 3; w++) { +/* CHANGE: org was: for (dw = 2560, b[w] = 0; dw; dw--, p.pb++) { */ + for (dw = (ps->OneScanLineLen/3), b[w] = 0; dw; dw--, p.pb++) { + + if (b[w] < *p.pb) + b[w] = *p.pb; + } + + if (b[w] < _GAIN_LOW) + *(pbReg[w]) += a_bCorrectTimesTable[bCorrectTimes - 1]; + else + if (b[w] > _GAIN_P96_HIGH) + *(pbReg[w]) -= a_bCorrectTimesTable[bCorrectTimes - 1]; + } + } + + /*===================================================================*/ + + /* SonyFBK ()/ToshibaFBK ()====================================*/ + /*FillRGBDarkLevel0Table (); */ + memset( ps->pPrescan16, 0xff, ps->ShadingBankSize ); + + for( dw = 0, p.pb = ps->pPrescan16 + ps->ShadingBufferSize; + dw <=255; dw++, p.pb++ ) { + *p.pb = (Byte) dw; + } + + dacP96FillShadingAndGammaTable( ps ); + + ps->PauseColorMotorRunStates( ps ); + + /* SetReadFBKRegister () */ + ps->Asic96Reg.RD_MotorControl = 0; + IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; + ps->Asic96Reg.RD_MotorControl = ps->IgnorePF | ps->MotorOn | + _MotorDirForward; + + ps->AsicReg.RD_Origin = 22; + ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; + ps->AsicReg.RD_Dpi = ps->PhysicalDpi; + ps->AsicReg.RD_Pixels = ps->FBKScanLineLenBase; + + IOPutOnAllRegisters( ps ); + + /* ReadFBKScanLine () */ + dacP96ReadDataWithinOneSecond( ps, ps->FBKScanLineLen, + ps->FBKScanLineBlks ); + + /*===================================================================*/ + if ( ps->fSonyCCD ) { + + /* FillChannelDarkLevelControl (); */ + for ( p.pb = ps->pPrescan16 + 32, w = 0, dw = 16; + dw; dw--, p.pb++) { + w += (UShort) *p.pb; + } + + ps->Asic96Reg.RD_RedChDarkOff = (Byte)(w / 16); + + for ( p.pb = ps->pPrescan16 + 32 + ps->FBKScanLineLenBase, w = 0, dw = 16; + dw; dw--, p.pb++ ) { + w += (UShort)*p.pb; + } + + ps->Asic96Reg.RD_GreenChDarkOff = (Byte)(w / 16); + + for ( p.pb = ps->pPrescan16 + 32 + ps->FBKScanLineLenBase * 2, w = 0, dw = 16; + dw; dw--, p.pb++) { + w += (UShort)*p.pb; + } + + ps->Asic96Reg.RD_BlueChDarkOff = (Byte)(w / 16); + + dacP96FillChannelDarkOffset( ps ); + + } else { + + /* FillToshibaDarkLevelControl (); */ + dacP96GetEvenOddOffset( ps->pPrescan16 + 32, &wv ); + ps->Asic96Reg.RD_RedChEvenOff = wv.b1st; + ps->Asic96Reg.RD_RedChOddOff = wv.b2nd; + + dacP96GetEvenOddOffset( ps->pPrescan16 + 32 + ps->FBKScanLineLenBase, &wv ); + ps->Asic96Reg.RD_GreenChEvenOff = wv.b1st; + ps->Asic96Reg.RD_GreenChOddOff = wv.b2nd; + + dacP96GetEvenOddOffset( ps->pPrescan16 + 32 + ps->FBKScanLineLenBase * 2, &wv ); + ps->Asic96Reg.RD_BlueChEvenOff = wv.b1st; + ps->Asic96Reg.RD_BlueChOddOff = wv.b2nd; + + dacP96FillEvenOddControl( ps ); + } + + /* SetInitialGainRAM (); */ + dacP96Adjust10BitShading( ps ); + + return _TRUE; + } + + return _FALSE; +} + +/** + */ +static void dacP96001ToSetShadingAddress( pScanData ps, pUChar pData ) +{ + ps->OpenScanPath( ps ); + + IODataToRegister( ps, ps->RegMemAccessControl, + ps->Asic96Reg.RD_MemAccessControl); + + ps->AsicReg.RD_ModeControl = _ModeProgram; + IODataToRegister( ps, ps->RegModeControl, _ModeProgram ); + + ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; + IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl); + + memset( ps->pScanBuffer1, 0, (64 + 8 + ps->Offset70)); + memcpy( ps->pScanBuffer1 + 64 + 8 + ps->Offset70, pData, + _BUF_SIZE_BASE_CONST * 2 ); + + IOMoveDataToScanner( ps, ps->pScanBuffer1, + _BUF_SIZE_BASE_CONST * 2 + 64 + 8 + ps->Offset70 ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + IODataToRegister( ps, ps->RegModeControl, _ModeScan ); + + ps->CloseScanPath( ps ); +} + +/** + */ +static void dacP96001WriteBackToColorShadingRam( pScanData ps ) +{ + ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3a); + dacP96001ToSetShadingAddress( ps, ps->pPrescan16 ); + + ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3e); + dacP96001ToSetShadingAddress( ps, ps->pPrescan16 + _BUF_SIZE_BASE_CONST*2); + + ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3c); + dacP96001ToSetShadingAddress( ps, ps->pPrescan16 + _BUF_SIZE_BASE_CONST*4); +} + +/** + */ +static void dacP96001ModifyShadingColor( pByte pData, Byte bMul ) +{ + UShort w; + ULong dw; + + for ( dw = 0; dw < _BUF_SIZE_BASE_CONST * 2; dw++ ) { + + w = (UShort)(Byte)(~pData[dw]) * bMul / 100U; + + if (w >= 255U) + pData[dw] = 0; + else + pData[dw] = (Byte)~w; + } +} + +/** + */ +static Byte dacP96001FBKReading( pScanData ps, Byte bValue, + Byte bReg, pByte pbSave, Bool bFBKModify ) +{ + TimerDef timer; + UShort w, wSum; + Byte addrSeq[8] = { 0x40, 0x20, 0x10, 0x08, 4, 2, 1, 0 }; + Byte bTemp, bFBKTemp, bFBKIndex; + + if( bFBKModify ) { + bFBKIndex = 3; + bFBKTemp = *pbSave; + } else { + bFBKTemp = 0x80; + bFBKIndex = 0; + } + + while( _TRUE ) { + + *pbSave = bFBKTemp; + IOCmdRegisterToScanner( ps, bReg, bFBKTemp ); + + /* SetColorRunTable (BYTE) */ + memset( ps->a_nbNewAdrPointer, bValue, _SCANSTATE_BYTES ); + MotorSetConstantMove( ps, 0 ); + + /* SetReadFBK (pScanData) */ + ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; + IOCmdRegisterToScanner( ps, ps->RegMotorControl, + ps->Asic96Reg.RD_MotorControl ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE | ps->bLampOn; + ps->AsicReg.RD_ModelControl = + (_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0 ); + + ps->AsicReg.RD_Dpi = 300; + ps->AsicReg.RD_Origin = 22; + ps->AsicReg.RD_Pixels = 1024; + IOPutOnAllRegisters( ps ); + + ps->Asic96Reg.RD_MotorControl = + (ps->FullStep | ps->MotorOn | _MotorDirForward); + IOCmdRegisterToScanner( ps, ps->RegMotorControl, + ps->Asic96Reg.RD_MotorControl ); + + MiscStartTimer( &timer, _SECOND ); + while((IODataRegisterFromScanner( ps, ps->RegFifoOffset) < 1) && + !MiscCheckTimer( &timer )); + + IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); + IOReadScannerImageData( ps, ps->pScanBuffer1, 64 ); + + for( w = 26, wSum = 0; w < 42; w++) + wSum += ps->pScanBuffer1[w]; + + wSum >>= 4; + bTemp = addrSeq[bFBKIndex++]; + + if( bTemp ) { + if( wSum < 0xfe ) + bFBKTemp += bTemp; + else + bFBKTemp -= bTemp; + } else { + return bFBKTemp; + } + } +} + +/** + */ +static Bool dacP96001WaitForShading( pScanData ps ) +{ + Bool bFBKModify; + Byte bRSave; + Byte bGSave; + Byte bBSave; + ULong dw; + pULong pdw; + + DBG( DBG_LOW, "dacP96001WaitForShading()\n" ); + + ps->AsicReg.RD_ScanControl |= ps->bLampOn; + IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); + + if ( ps->GotoShadingPosition( ps )) { + + _DODELAY( 250 ); + + /* AdjustMostWideOffset70 (pScanData) -------------------------------*/ + /* FillABitGray (pScanData)*/ + memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); + ps->a_nbNewAdrPointer[8] = + ps->a_nbNewAdrPointer[24] = 0x30; + + MotorSetConstantMove( ps, 32 ); + + /* SetMaxWideRegister (pScanData) */ + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE | ps->bLampOn; + + ps->Asic96Reg.RD_MotorControl = + (ps->MotorOn | ps->IgnorePF | _MotorDirForward); + ps->AsicReg.RD_ModelControl = + (_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0); + + ps->AsicReg.RD_Dpi = 300; + ps->AsicReg.RD_Origin = 64 + 8; + ps->AsicReg.RD_Pixels = 2700; + IOPutOnAllRegisters( ps ); + + IOCmdRegisterToScanner( ps, ps->RegMotorControl, + ps->Asic96Reg.RD_MotorControl ); + + /* ReadMaxWideLine */ + dacP96ReadDataWithinOneSecond( ps, 2700, 5 ); + + /* AdjustOffset70Proc (pScanData)------------------------------------*/ + { + ULong dwSum, dw, dwLeft, dwCenter; + + /* AverageWideBank (pScanData) */ + for( dwSum = 0, dw = 0; dw < 2700; dw++ ) + dwSum += (ULong)ps->pPrescan16[dw]; + + dwSum /= 2700UL; + + if( dwSum <= 0x80 ) { + + memcpy( ps->pScanBuffer1, ps->pPrescan16, 140 ); + memcpy( ps->pScanBuffer1 + 140, + ps->pPrescan16 + _BUF_SIZE_BASE_CONST * 2, 140); + + /* BlackOffsetCheck (pScanData) */ + for( dw = dwLeft = 0; dw < 140; dw++ ) { + if( ps->pScanBuffer1[dw] >= 0xe0 ) + dwLeft++; + else + break; + } + + /* WhiteOffsetCheck (pScanData) */ + for( dw = 140, dwCenter = 0; dw < 280; dw++ ) { + if( ps->pScanBuffer1[dw] < 0xe0 ) + dwCenter++; + else + break; + } + + if (dwLeft) { + ps->Offset70 = (dwLeft + dwCenter) / 2 + 14; + } else { + if (dwCenter == 140) + ps->Offset70 = 70; + else + ps->Offset70 = dwCenter / 2 + 2; + } + } + } + + memset( ps->pPrescan16, 0, ps->BufferSizePerModel * 3 ); + dacP96001WriteBackToColorShadingRam( ps ); + + /* SetFBK */ + if((IODataRegisterFromScanner(ps, ps->RegReadIOBufBus) & 0x0f) == 0x0f) + bFBKModify = 0; + else + bFBKModify = 1; + + dacP96001FBKReading(ps, 0x10, ps->RegRedDCAdjust, &bRSave,bFBKModify); + dacP96001FBKReading(ps, 0x30, ps->RegGreenDCAdjust,&bGSave,bFBKModify); + dacP96001FBKReading(ps, 0x20, ps->RegBlueDCAdjust, &bBSave,bFBKModify); + + ps->OpenScanPath( ps ); + IODataToRegister( ps, ps->RegRedDCAdjust, (Byte)(bRSave + 2)); + IODataToRegister( ps, ps->RegGreenDCAdjust, (Byte)(bGSave + 2)); + IODataToRegister( ps, ps->RegBlueDCAdjust, bBSave); + ps->CloseScanPath( ps ); + + /* Turn off and then turn on motor */ + IOCmdRegisterToScanner( ps, ps->RegMotorControl, + (Byte)(ps->Asic96Reg.RD_MotorControl & ~ps->MotorOn)); + IOCmdRegisterToScanner( ps, ps->RegMotorControl, + ps->Asic96Reg.RD_MotorControl ); + + /* FillABitColor (pScanData) */ + pdw = (pULong)ps->a_nbNewAdrPointer; + for( dw = 0; dw < 4; dw++) { + *pdw++ = 0x40; + *pdw++ = 0x2030140; + } + + IOSetToMotorRegister( ps ); + + /* SetShadingRegister (pScanData) */ + ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; + IOCmdRegisterToScanner( ps, ps->RegMotorControl, + ps->Asic96Reg.RD_MotorControl ); + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_LineControl = ps->TimePerLine; + ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE | ps->bLampOn; + ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; + + ps->AsicReg.RD_ModelControl = + (_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0); + ps->AsicReg.RD_Dpi = 150; + ps->AsicReg.RD_Origin = (UShort)(64 + 8 + ps->Offset70); + ps->AsicReg.RD_Pixels = ps->BufferSizeBase; + IOPutOnAllRegisters( ps ); + + IOCmdRegisterToScanner( ps, ps->RegMotorControl, + (Byte)(ps->MotorOn | ps->IgnorePF | _MotorDirForward)); + + dacP96ReadColorShadingLine( ps ); + + /* ModifyShadingColor (pScanData) */ + dacP96001ModifyShadingColor( ps->pPrescan16, 103 ); + dacP96001ModifyShadingColor( ps->pPrescan16 + + _BUF_SIZE_BASE_CONST * 2 * 2, 97); + dacP96001WriteBackToColorShadingRam( ps ); + return _TRUE; + } + return _FALSE; +} + +/** + */ +static void dacP98003GainOffsetToDAC( pScanData ps, Byte ch, Byte reg, Byte d ) +{ + if( ps->Device.bDACType == _DA_SAMSUNG8531 ) { + + IODataToRegister( ps, ps->RegADCAddress, 0 ); + IODataToRegister( ps, ps->RegADCData, ch ); + IODataToRegister( ps, ps->RegADCSerialOutStr, ch); + } + + IODataToRegister( ps, ps->RegADCAddress, reg ); + IODataToRegister( ps, ps->RegADCData, d ); + IODataToRegister( ps, ps->RegADCSerialOutStr, d ); +} + +/** + */ +static void dacP98003AdjustRGBGain( pScanData ps ) +{ + ULong i; + Byte bHi[3]; + + DBG( DBG_LOW, "dacP98003AdjustRGBGain()\n" ); + + ps->Shade.Gain.Colors.Red = + ps->Shade.Gain.Colors.Green = + ps->Shade.Gain.Colors.Blue = ps->Shade.bUniGain; + + ps->Shade.Hilight.Colors.Red = + ps->Shade.Hilight.Colors.Green = + ps->Shade.Hilight.Colors.Blue = 0; + + ps->Shade.bGainHigh = _GAIN_P98003_HIGH; + ps->Shade.bGainLow = _GAIN_P98003_LOW; + + ps->Shade.fStop = _FALSE; + + for( i = 10; i-- && !ps->Shade.fStop; ) { + + ps->Shade.fStop = _TRUE; + + /* SetRGBGainRegister () */ + IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); + + ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; + IOSelectLampSource( ps ); + IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); + + DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; + ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; + + if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) + ps->AsicReg.RD_Origin = (UShort)ps->Device.DataOriginX >> 1; + else + ps->AsicReg.RD_Origin = (UShort)ps->Device.DataOriginX; + + ps->AsicReg.RD_Dpi = 300; + ps->AsicReg.RD_Pixels = 2560; + + /* PauseColorMotorRunStates () */ + memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); + ps->a_nbNewAdrPointer[1] = 0x77; + + IOPutOnAllRegisters( ps ); + + _DODELAY( 70 ); + + /* read one shading line and work on it */ + if( IOReadOneShadingLine( ps, (pUChar)ps->Bufs.b1.pShadingRam, 2560)) { + + if ( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) { + + bHi[1] = DacP98003SumGains( + (pUChar)ps->Bufs.b1.pShadingRam + 2560, 2560); + if( bHi[1] ) + DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] ); + else { + ps->Shade.fStop = _FALSE; + } + } else { + bHi[0] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam, 2560); + bHi[1] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam + 2560, 2560); + bHi[2] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam + 5120, 2560); + + if (!bHi[0] || !bHi[1] || !bHi[2] ) { + ps->Shade.fStop = _FALSE; + } else { + DacP98003AdjustGain( ps, _CHANNEL_RED, bHi[0] ); + DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] ); + DacP98003AdjustGain( ps, _CHANNEL_BLUE, bHi[2] ); + } + } + } else + ps->Shade.fStop = _FALSE; + } + +#ifdef DEBUG + if( !ps->Shade.fStop ) + DBG( DBG_LOW, "dacP98003AdjustRGBGain() - all loops done!!!\n" ); +#endif + + DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain ); +} + +/** + */ +static UShort dacP98003SumDarks( pScanData ps, pUShort data ) +{ + UShort i, loop; + + if( ps->Device.bCCDID == _CCD_3799 ) { + if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) + data += 0x18; + else + data += 0x30; + } else { + if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) + data += 0x18; + else + data += 0x20; + } + + for( i = 0, loop = 16; loop--; data++ ) + i += *data; + i >>= 4; + + return i; +} + +/** + */ +static void dacP98003AdjustShadingWaveform( pScanData ps ) +{ + Byte b; + UShort count, wR, wG, wB, tmp; + DataType var; + DataPointer pvar, psum; + RBGPtrDef cp; + pRGBUShortDef pRGB, pwsum; + + DBG( DBG_LOW, "dacP98003AdjustShadingWaveForm()\n" ); + + memset( &cp, 0, sizeof(RBGPtrDef)); + memset( ps->Bufs.b2.pSumBuf, 0, (5400 * 3 * 2)); + + /* SetAdjustShadingRegister () */ + IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); + + ps->AsicReg.RD_LineControl = _LOBYTE(ps->Shade.wExposure); + ps->AsicReg.RD_ExtLineControl = _HIBYTE(ps->Shade.wExposure); + IODataToRegister( ps, ps->RegExtendedLineControl, + ps->AsicReg.RD_ExtLineControl ); + IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); + + ps->AsicReg.RD_XStepTime = _LOBYTE(ps->Shade.wExposure); + ps->AsicReg.RD_ExtXStepTime = _HIBYTE(ps->Shade.wExposure); + IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime ); + IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime ); + + ps->AsicReg.RD_ModeControl = _ModeScan; + ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; + ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; + + if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) { + + ps->AsicReg.RD_Dpi = 300; + ps->AsicReg.RD_Pixels = 2700; + ps->Shade.shadingBytes = 2700 * 2; + } else { + ps->AsicReg.RD_Dpi = 600; + ps->AsicReg.RD_Pixels = 5400; + ps->Shade.shadingBytes = 5400 * 2; + } + ps->AsicReg.RD_Origin = _SHADING_BEGINX; + + for( pvar.pdw = (pULong)ps->a_nbNewAdrPointer, + var.dwValue = _SCANSTATE_BYTES >> 2; var.dwValue--; pvar.pdw++) { + *pvar.pdw = 0x00f00080; + } + + ps->Scan.fRefreshState = _FALSE; + IOPutOnAllRegisters( ps ); + _DODELAY( 55 ); + + /* SetupHilightShadow () */ + if( ps->Shade.pHilight ) { + + memset( ps->Shade.pHilight, 0, + ps->Shade.shadingBytes * ps->Shade.skipHilight * 3 ); + + memset((pUChar)ps->Shade.pHilight + + ps->Shade.shadingBytes * ps->Shade.skipHilight * 3, 0xff, + ps->Shade.shadingBytes * ps->Shade.skipShadow * 3 ); + } + + + for( count = 32; count--;) { + + IOReadOneShadingLine( ps, + ((pUChar)ps->Bufs.b1.pShadingRam)+_SHADING_BEGINX, + ps->Shade.shadingBytes ); + + /* SaveHilightShadow() */ + if( ps->Shade.pHilight ) { + + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + + cp.red.usp = ps->Bufs.b1.pShadingRam + _SHADING_BEGINX; + cp.green.usp = cp.red.usp + ps->AsicReg.RD_Pixels; + cp.blue.usp = cp.green.usp + ps->AsicReg.RD_Pixels; + pvar.pusrgb = (pRGBUShortDef)ps->Shade.pHilight + + _SHADING_BEGINX; + + for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + pRGB = pvar.pusrgb++; + wR = *cp.red.usp; + wG = *cp.green.usp; + wB = *cp.blue.usp; + + for( b = ps->Shade.skipHilight; b--; + pRGB += ps->AsicReg.RD_Pixels) { + + if( wR > pRGB->Red ) { + tmp = wR; + wR = pRGB->Red; + pRGB->Red = tmp; + } + if( wG > pRGB->Green ) { + tmp = wG; + wG = pRGB->Green; + pRGB->Green = tmp; + } + if( wB > pRGB->Blue ) { + tmp = wB; + wB = pRGB->Blue; + pRGB->Blue = tmp; + } + } + + wR = *cp.red.usp++; + wG = *cp.green.usp++; + wB = *cp.blue.usp++; + for(b = ps->Shade.skipShadow; b--; + pRGB += ps->AsicReg.RD_Pixels) { + + if (wR < pRGB->Red) { + tmp = wR; + wR = pRGB->Red; + pRGB->Red = tmp; + } + if (wG < pRGB->Green) { + tmp = wG; + wG = pRGB->Green; + pRGB->Green = tmp; + } + if (wB < pRGB->Blue) { + tmp = wB; + wB = pRGB->Blue; + pRGB->Blue = tmp; + } + } + } + + } else { + + cp.green.usp = ps->Bufs.b1.pShadingRam + + ps->AsicReg.RD_Pixels + _SHADING_BEGINX; + cp.blue.usp = (pUShort) ps->Shade.pHilight + _SHADING_BEGINX; + + for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + cp.red.usp = cp.blue.usp++; + wG = *cp.green.usp; + for( b = ps->Shade.skipHilight; b--; + cp.red.usp += ps->AsicReg.RD_Pixels) { + if( wG > *cp.red.usp ) { + tmp = wG; + wG = *cp.red.usp; + *cp.red.usp = tmp; + } + } + wG = *cp.green.usp++; + for (b = ps->Shade.skipShadow; b--; + cp.red.usp += ps->AsicReg.RD_Pixels) { + if( wG < *cp.red.usp ) { + tmp = wG; + wG = *cp.red.usp; + *cp.red.usp = tmp; + } + } + } + } + } + + /* AddToSumBuffer() */ + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + + cp.red.usp = ps->Bufs.b1.pShadingRam + _SHADING_BEGINX; + cp.green.usp = cp.red.usp + ps->AsicReg.RD_Pixels; + cp.blue.usp = cp.green.usp + ps->AsicReg.RD_Pixels; + + pvar.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = (ULong)ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--; + pvar.pulrgb++, cp.red.usp++, cp.green.usp++, cp.blue.usp++) { + pvar.pulrgb->Red += (ULong)*cp.red.usp; + pvar.pulrgb->Green += (ULong)*cp.green.usp; + pvar.pulrgb->Blue += (ULong)*cp.blue.usp; + } + + } else { + + cp.green.usp = ps->Bufs.b1.pShadingRam + ps->AsicReg.RD_Pixels + + _SHADING_BEGINX; + pvar.pdw = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + for(var.dwValue = (ULong)ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--; pvar.pdw++, cp.green.usp++) { + *pvar.pdw += (ULong)*cp.green.usp; + } + } + + if( IOReadFifoLength( ps ) < ps->AsicReg.RD_Pixels ) + IORegisterToScanner( ps, ps->RegRefreshScanState ); + } + + /* AverageAfterSubHilightShadow() */ + if( ps->Shade.pHilight ) { + + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + + psum.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + pwsum = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + pvar.pusrgb = (pRGBUShortDef)ps->Shade.pHilight + _SHADING_BEGINX; + + for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + pRGB = pvar.pusrgb++; + + for( b = ps->Shade.skipHilight + ps->Shade.skipShadow; + b--; pRGB += ps->AsicReg.RD_Pixels ) { + + psum.pulrgb->Red -= (ULong)pRGB->Red; + psum.pulrgb->Green -= (ULong)pRGB->Green; + psum.pulrgb->Blue -= (ULong)pRGB->Blue; + } + + pwsum->Red = (UShort)(psum.pulrgb->Red / ps->Shade.dwDiv); + pwsum->Green = (UShort)(psum.pulrgb->Green / ps->Shade.dwDiv); + pwsum->Blue = (UShort)(psum.pulrgb->Blue / ps->Shade.dwDiv); + psum.pulrgb++; + pwsum++; + } + } else { + cp.green.ulp = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + cp.blue.usp = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + pvar.pw = (pUShort)ps->Shade.pHilight + _SHADING_BEGINX; + + for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + cp.red.usp = pvar.pw++; + + for( b = ps->Shade.skipHilight + ps->Shade.skipShadow; + b--; cp.red.usp += ps->AsicReg.RD_Pixels ) + *cp.green.ulp -= *cp.red.usp; + + *cp.blue.usp = (UShort)(*cp.green.ulp / ps->Shade.dwDiv); + cp.blue.usp++; + cp.green.ulp++; + } + } + } else { + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + + psum.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + pwsum = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + + for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + pwsum->Red = (UShort)(psum.pulrgb->Red >> 5); + pwsum->Green = (UShort)(psum.pulrgb->Green >> 5); + pwsum->Blue = (UShort)(psum.pulrgb->Blue >> 5); + psum.pulrgb++; + pwsum++; + } + } else { + cp.green.ulp = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + cp.blue.usp = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + + for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + *cp.blue.usp = (UShort)(*cp.green.ulp >> 5); + cp.blue.usp++; + cp.green.ulp++; + } + } + } + + /* Process negative & transparency here */ + if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) + TPAP98003FindCenterPointer( ps ); + + if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) + TPAP98003Reshading( ps ); + + pRGB = (pRGBUShortDef)&ps->Shade.pCcdDac->GainResize; + + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + + pwsum = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + + if ((short)(pwsum->Red -= ps->Shade.DarkOffset.Colors.Red) > 0) { + pwsum->Red = pwsum->Red * pRGB->Red / 100U; + if( pwsum->Red > 0xfff ) + pwsum->Red = 0xfff; + } else + pwsum->Red = 0; + + if((short)(pwsum->Green -= ps->Shade.DarkOffset.Colors.Green) > 0) { + pwsum->Green = pwsum->Green * pRGB->Green / 100U; + if( pwsum->Green > 0xfff ) + pwsum->Green = 0xfff; + } else + pwsum->Green = 0; + + if ((short)(pwsum->Blue -= ps->Shade.DarkOffset.Colors.Blue) > 0) { + pwsum->Blue = pwsum->Blue * pRGB->Blue / 100U; + if( pwsum->Blue > 0xfff ) + pwsum->Blue = 0xfff; + } else + pwsum->Blue = 0; + + wR = (UShort)(pwsum->Red >> 4); + pwsum->Red <<= 12; + pwsum->Red |= wR; + wR = (UShort)(pwsum->Green >> 4); + pwsum->Green <<= 12; + pwsum->Green |= wR; + wR = (UShort)(pwsum->Blue>> 4); + pwsum->Blue <<= 12; + pwsum->Blue |= wR; + pwsum++; + } + } else { + + cp.green.usp = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + + if((short)(*cp.green.usp -= ps->Shade.DarkOffset.Colors.Green) > 0) { + + *cp.green.usp = *cp.green.usp * pRGB->Green / 100U; + if( *cp.green.usp > 0xfff ) + *cp.green.usp = 0xfff; + } else + *cp.green.usp = 0; + + wR = (UShort)(*cp.green.usp >> 4); + *cp.green.usp <<= 12; + *cp.green.usp |= wR; + + cp.green.usp++; + } + } + + /* DownloadShadingAndSetDark() */ + dacP98DownloadShadingTable( ps, ps->Bufs.b2.pSumBuf, (5400 * 3 * 2)); +} + +/** + */ +static void dacP98003AdjustDark( pScanData ps ) +{ + ULong i; + UShort wDarks[3]; + + DBG( DBG_LOW, "dacP98003AdjustDark()\n" ); + + ps->Shade.DarkDAC.Colors = ps->Shade.pCcdDac->DarkDAC.Colors; + ps->Shade.fStop = _FALSE; + + for( i = 16; i-- && !ps->Shade.fStop;) { + + ps->Shade.fStop = _TRUE; + + /* FillDarkToDAC() */ + DacP98003FillToDAC( ps, &ps->Device.RegDACOffset, &ps->Shade.DarkDAC ); + + IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); + + ps->AsicReg.RD_ScanControl = (_SCAN_12BITMODE + _SCAN_1ST_AVERAGE); + IOSelectLampSource( ps ); + IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); + + ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; + ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; + + ps->AsicReg.RD_Origin = _SHADING_BEGINX; + ps->AsicReg.RD_Pixels = 512; + + if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) + ps->AsicReg.RD_Dpi = 300; + else + ps->AsicReg.RD_Dpi = 600; + + + /* PauseColorMotorRunStates () */ + memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); + ps->a_nbNewAdrPointer[1] = 0x77; + + IOPutOnAllRegisters( ps ); + _DODELAY( 70 ); + + /* read one shading line and work on it */ + if( IOReadOneShadingLine(ps, (pUChar)ps->Bufs.b1.pShadingRam, 512*2)) { + + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + + wDarks[0] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam ); + wDarks[1] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam + + ps->AsicReg.RD_Pixels ); + wDarks[2] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam + + ps->AsicReg.RD_Pixels * 2UL); + + if( !wDarks[0] || !wDarks[1] || !wDarks[2] ) { + ps->Shade.fStop = _FALSE; + } else { + ps->Shade.DarkOffset.wColors[0] = wDarks[0]; + ps->Shade.DarkOffset.wColors[1] = wDarks[1]; + ps->Shade.DarkOffset.wColors[2] = wDarks[2]; + (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, + _CHANNEL_RED, wDarks[0] ); + (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, + _CHANNEL_GREEN, wDarks[1] ); + (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, + _CHANNEL_BLUE, wDarks[2] ); + } + } else { + wDarks[1] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam + + ps->AsicReg.RD_Pixels ); + if (!wDarks[1] ) + ps->Shade.fStop = _FALSE; + else { + ps->Shade.DarkOffset.wColors[1] = wDarks[1]; + (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, + _CHANNEL_GREEN, wDarks[1] ); + } + } + } else + ps->Shade.fStop = _FALSE; + } + + /* CalculateDarkDependOnCCD() */ + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_RED ); + (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN ); + (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_BLUE ); + } else + (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN ); +} + +/** + */ +static Bool dacP98003WaitForShading( pScanData ps ) +{ + ULong i, tmp; + Byte bScanControl; + + DBG( DBG_LOW, "dacP98003WaitForShading()\n" ); + + /* + * before getting the shading data, (re)init the ASIC + */ + ps->ReInitAsic( ps, _TRUE ); + + ps->Shade.DarkOffset.Colors.Red = 0; + ps->Shade.DarkOffset.Colors.Green = 0; + ps->Shade.DarkOffset.Colors.Blue = 0; + + IORegisterToScanner( ps, ps->RegResetMTSC ); + + IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl); + IODataToRegister( ps, ps->RegMotorDriverType, + ps->AsicReg.RD_MotorDriverType ); + IODataToRegister( ps, ps->RegScanControl1, + (_SCANSTOPONBUFFULL| _MFRC_BY_XSTEP)); + ps->GotoShadingPosition( ps ); + + bScanControl = ps->AsicReg.RD_ScanControl; + + /* SetShadingMapForGainDark */ + memset( ps->Bufs.b2.pSumBuf, 0xff, (5400 * 3 * 2)); + + /* DownloadShadingAndSetDark() */ + dacP98DownloadShadingTable( ps, ps->Bufs.b2.pSumBuf, (5400 * 3 * 2)); + + for( i = 0, tmp = 0; i < 1024; tmp += 0x01010101, i += 4 ) { + ps->Bufs.b1.Buf.pdw[i] = + ps->Bufs.b1.Buf.pdw[i+1] = + ps->Bufs.b1.Buf.pdw[i+2] = + ps->Bufs.b1.Buf.pdw[i+3] = tmp; + } + + memcpy( ps->Bufs.b1.pShadingMap + 4096, ps->Bufs.b1.pShadingMap, 4096 ); + memcpy( ps->Bufs.b1.pShadingMap + 8192, ps->Bufs.b1.pShadingMap, 4096 ); + dacP98DownloadMapTable( ps, ps->Bufs.b1.pShadingMap ); + + DBG( DBG_LOW, "wExposure = %u\n", ps->Shade.wExposure); + DBG( DBG_LOW, "wXStep = %u\n", ps->Shade.wXStep); + + ps->AsicReg.RD_LineControl = (_LOBYTE(ps->Shade.wExposure)); + ps->AsicReg.RD_ExtLineControl = (_HIBYTE(ps->Shade.wExposure)); + IODataToRegister(ps, ps->RegExtendedLineControl, + ps->AsicReg.RD_ExtLineControl ); + IODataToRegister(ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); + + dacP98003AdjustRGBGain( ps ); + dacP98003AdjustDark( ps ); + dacP98003AdjustShadingWaveform( ps ); + + ps->AsicReg.RD_ScanControl = bScanControl; + + /* here we have to download the table in any case...*/ + dacP98DownloadMapTable( ps, ps->a_bMapTable ); + + MotorP98003BackToHomeSensor( ps ); + + return _TRUE; +} + +/************************ exported functions *********************************/ + +/** + */ +_LOC int DacInitialize( pScanData ps ) +{ + DBG( DBG_HIGH, "DacInitialize()\n" ); + + if( NULL == ps ) + return _E_NULLPTR; + + /* + * depending on the asic, we set some functions + */ + if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { + + ps->WaitForShading = dacP98003WaitForShading; + + } else if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { + + ps->WaitForShading = dacP98WaitForShading; + + } else if( _ASIC_IS_96003 == ps->sCaps.AsicID ) { + + ps->WaitForShading = dacP96003WaitForShading; + + } else if( _ASIC_IS_96001 == ps->sCaps.AsicID ) { + + ps->WaitForShading = dacP96001WaitForShading; + + } else { + + DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); + return _E_NOSUPP; + } + return _OK; +} + +/** Fill out the R/G/B GainOut value + */ +_LOC void DacP98FillGainOutDirectPort( pScanData ps ) +{ + ps->OpenScanPath( ps ); + + IODataRegisterToDAC( ps, 0x28, ps->bRedGainIndex ); + IODataRegisterToDAC( ps, 0x29, ps->bGreenGainIndex ); + IODataRegisterToDAC( ps, 0x2a, ps->bBlueGainIndex ); + + ps->CloseScanPath( ps ); +} + +/** + */ +_LOC void DacP98FillShadingDarkToShadingRegister( pScanData ps ) +{ + pUChar pValue; + Byte bReg; + + DBG( DBG_LOW, "DacP98FillShadingDarkToShadingRegister()\n" ); + + ps->AsicReg.RD_RedDarkOff = ps->Shade.DarkOffset.Colors.Red; + ps->AsicReg.RD_GreenDarkOff = ps->Shade.DarkOffset.Colors.Green; + ps->AsicReg.RD_BlueDarkOff = ps->Shade.DarkOffset.Colors.Blue; + + pValue = (pUChar)&ps->AsicReg.RD_RedDarkOff; + for (bReg = ps->RegRedChDarkOffsetLow; bReg <= ps->RegBlueChDarkOffsetHigh; + bReg++, pValue++) { + + IODataToRegister( ps, bReg, *pValue ); + } +} + +/** + */ +_LOC void DacP98AdjustDark( pScanData ps ) +{ + Byte bCorrectTimes; /* used to be a global var !*/ + + DBG( DBG_LOW, "DacP98AdjustDark()\n" ); + + ps->Shade.pCcdDac->DarkDAC.Colors.Red = ps->bsPreRedDAC; + ps->Shade.pCcdDac->DarkDAC.Colors.Green = ps->bsPreGreenDAC; + ps->Shade.pCcdDac->DarkDAC.Colors.Blue = ps->bsPreBlueDAC; + + if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) { + bCorrectTimes = 6; + } else { + bCorrectTimes = 5; + } + +/* CHANGE +** original code seems to be buggy : for (bCorrectTimes ; bCorrectTimes--;) { +*/ + for (;bCorrectTimes ; bCorrectTimes-- ) { + + ps->OpenScanPath( ps ); + dacP98FillDarkDAC( ps ); + dacP98SetReadFBKRegister( ps ); + ps->CloseScanPath( ps ); + + IOPutOnAllRegisters( ps ); + + ps->PauseColorMotorRunStates( ps ); /* stop scan states */ + + IOReadOneShadingLine( ps, ps->pScanBuffer1, 512*2 ); + + dacP98FillChannelDarkLevelControl( ps ); + + if(dacP98CheckChannelDarkLevel( ps )) + break; + } + + ps->Shade.DarkOffset.Colors.Red= + dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Red, + ps->Shade.pCcdDac->DarkCmpHi.Colors.Red, + ps->Shade.pCcdDac->DarkOffSub.Colors.Red ); + + ps->Shade.DarkOffset.Colors.Green = + dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Green, + ps->Shade.pCcdDac->DarkCmpHi.Colors.Green, + ps->Shade.pCcdDac->DarkOffSub.Colors.Green ); + + ps->Shade.DarkOffset.Colors.Blue = + dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Blue, + ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue, + ps->Shade.pCcdDac->DarkOffSub.Colors.Blue ); +} + +/** + */ +_LOC void DacP96WriteBackToGammaShadingRAM( pScanData ps ) +{ + /* ModifyGammaShadingOffset(ps) */ + ps->OpenScanPath( ps); + + IODataToRegister( ps, ps->RegRedChShadingOffset, + ps->Asic96Reg.u28.RD_RedChShadingOff ); + IODataToRegister( ps, ps->RegGreenChShadingOffset, + (Byte)((ULong)ps->Asic96Reg.u29.RD_GreenChShadingOff * 96UL/100UL)); + + IODataToRegister( ps, ps->RegBlueChShadingOffset, + (Byte)((ULong)ps->Asic96Reg.RD_BlueChShadingOff * 91UL/100UL)); + + ps->CloseScanPath( ps ); + + dacP96WriteLinearGamma( ps, ps->pPrescan16, 256, ps->ShadingBankRed); + dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize, + 256, ps->ShadingBankGreen); + dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize * 2, + 256, ps->ShadingBankBlue); +} + +/** + */ +_LOC void DacP98003FillToDAC( pScanData ps, pRGBByteDef regs, pColorByte data ) +{ + if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { + + dacP98003GainOffsetToDAC( ps, _DAC_RED, regs->Red, data->Colors.Red ); + dacP98003GainOffsetToDAC( ps, _DAC_GREENCOLOR, + regs->Green, data->Colors.Green ); + dacP98003GainOffsetToDAC( ps, _DAC_BLUE, + regs->Blue, data->Colors.Blue ); + } else { + dacP98003GainOffsetToDAC( ps, _DAC_GREENMONO, regs->Green, + data->Colors.Green ); + } +} + +/** + */ +_LOC void DacP98003AdjustGain( pScanData ps, ULong color, Byte hilight ) +{ + if( hilight < ps->Shade.bGainLow ) { + + if( ps->Shade.Hilight.bColors[color] < ps->Shade.bGainHigh ) { + + ps->Shade.fStop = _FALSE; + ps->Shade.Hilight.bColors[color] = hilight; + + if( hilight <= (Byte)(ps->Shade.bGainLow - hilight)) + ps->Shade.Gain.bColors[color] += ps->Shade.bGainDouble; + else + ps->Shade.Gain.bColors[color]++; + } + } else { + if( hilight > ps->Shade.bGainHigh ) { + ps->Shade.fStop = _FALSE; + ps->Shade.Hilight.bColors[color] = hilight; + ps->Shade.Gain.bColors[color]--; + } else + ps->Shade.Hilight.bColors[color] = hilight; + } + + if( ps->Shade.Gain.bColors[color] > ps->Shade.bMaxGain ) { + ps->Shade.Gain.bColors[color] = ps->Shade.bMaxGain; + } +} + +/** + */ +_LOC Byte DacP98003SumGains( pUChar pb, ULong pixelsLine ) +{ + Byte bHilight, tmp; + ULong dwPixels, dwAve; + UShort sum; + + for( bHilight = 0, dwPixels = pixelsLine >> 4; dwPixels--; ) { + + for( sum = 0, dwAve = 16; dwAve--; pb++) + sum += (UShort)*pb; + + sum >>= 4; + tmp = (Byte)sum; + + if( tmp > bHilight ) + bHilight = tmp; + } + return bHilight; +} + +/* END PLUSTEK-PP_DAC.C .....................................................*/ |