From 6e9c41a892ed0e0da326e0278b3221ce3f5713b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 6 Oct 2014 14:00:40 +0200 Subject: Initial import of sane-backends version 1.0.24-1.2 --- backend/u12-shading.c | 877 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 877 insertions(+) create mode 100644 backend/u12-shading.c (limited to 'backend/u12-shading.c') diff --git a/backend/u12-shading.c b/backend/u12-shading.c new file mode 100644 index 0000000..e31c7ee --- /dev/null +++ b/backend/u12-shading.c @@ -0,0 +1,877 @@ +/* @file u12-shading.c - + * @brief all the shading functions + * + * based on sources acquired from Plustek Inc. + * Copyright (C) 2003-2004 Gerhard Jaeger + * + * History: + * - 0.01 - initial version + * - 0.02 - + * . + *
+ * 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. + *
+ */ + +#define _GAIN_HIGH 240 /* Volt. max. value */ +#define _GAIN_LOW 220 /* Volt. min. value */ + +#define _CHANNEL_RED 0 +#define _CHANNEL_GREEN 1 +#define _CHANNEL_BLUE 2 + +/* for DAC programming */ +#define _VALUE_CONFIG 0x51 +#define _DAC_RED (SANE_Byte)(_VALUE_CONFIG | 0x00) +#define _DAC_GREENCOLOR (SANE_Byte)(_VALUE_CONFIG | 0x04) +#define _DAC_GREENMONO (SANE_Byte)(_VALUE_CONFIG | 0x06) +#define _DAC_BLUE (SANE_Byte)(_VALUE_CONFIG | 0x08) + + +/* forward declarations ... */ +static void u12tpa_Reshading( U12_Device * ); +static void u12tpa_FindCenterPointer( U12_Device * ); + +/** + */ +static void +u12shading_DownloadShadingTable( U12_Device *dev, SANE_Byte *buf, u_long len ) +{ + SANE_Byte *val, *rb; + SANE_Byte reg, regs[20]; + int c; + + DBG( _DBG_INFO, "u12shading_DownloadShadingTable()\n" ); + + u12io_DataToRegister( dev, REG_MODECONTROL, _ModeShadingMem ); + u12io_DataToRegister( dev, REG_MEMORYLO, 0 ); + u12io_DataToRegister( dev, REG_MEMORYHI, 0 ); + + /* set 12 bits output color */ + u12io_DataToRegister( dev, REG_SCANCONTROL, + (SANE_Byte)(dev->regs.RD_ScanControl | _SCAN_12BITMODE)); + + u12io_MoveDataToScanner( dev, buf, len ); + + regs[0] = REG_MODECONTROL; + regs[1] = _ModeScan; + + /* FillShadingDarkToShadingRegister() */ + dev->regs.RD_RedDarkOff = dev->shade.DarkOffset.Colors.Red; + dev->regs.RD_GreenDarkOff = dev->shade.DarkOffset.Colors.Green; + dev->regs.RD_BlueDarkOff = dev->shade.DarkOffset.Colors.Blue; + + val = (SANE_Byte*)&dev->regs.RD_RedDarkOff; + rb = ®s[2]; + c = 1; + for( reg = REG_REDCHDARKOFFSETLO; + reg <= REG_BLUECHDARKOFFSETHI; reg++, val++) { + + *(rb++) = reg; + *(rb++) = *val; + c++; + } + u12io_DataToRegs( dev, regs, c ); +} + +/** + */ +static SANE_Status u12shadingAdjustShadingWaveform( U12_Device *dev ) +{ + SANE_Byte b; + u_short count, wR, wG, wB, tmp; + DataType var; + DataPointer pvar, psum; + RBGPtrDef cp; + RGBUShortDef *pRGB, *pwsum; + u_long shadingBytes; + + DBG( _DBG_INFO, "u12shading_AdjustShadingWaveForm()\n" ); + + memset( &cp, 0, sizeof(RBGPtrDef)); + memset( dev->bufs.b2.pSumBuf, 0, (5400 * 3 * 2)); + + u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); + + dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure); + dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure); + u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL, + dev->regs.RD_ExtLineControl ); + u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl ); + + dev->regs.RD_XStepTime = _LOBYTE(dev->shade.wExposure); + dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wExposure); + u12io_DataToRegister( dev, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime ); + u12io_DataToRegister( dev, REG_XSTEPTIME, dev->regs.RD_XStepTime ); + + dev->regs.RD_ModeControl = _ModeScan; + dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; + dev->regs.RD_Motor0Control = _FORWARD_MOTOR; + + if( dev->shade.intermediate & _ScanMode_AverageOut ) { + + dev->regs.RD_Dpi = 300; + dev->regs.RD_Pixels = 2700; + shadingBytes = 2700 * 2; + } else { + dev->regs.RD_Dpi = 600; + dev->regs.RD_Pixels = 5400; + shadingBytes = 5400 * 2; + } + dev->regs.RD_Origin = _SHADING_BEGINX; + + for( pvar.pdw = (u_long*)dev->scanStates, + var.dwValue = _SCANSTATE_BYTES >> 2; var.dwValue--; pvar.pdw++) { + *pvar.pdw = 0x00f00080; + } + + dev->scan.refreshState = SANE_FALSE; + u12io_PutOnAllRegisters( dev ); +/* _DODELAY( 100 ); */ + + if( dev->shade.pHilight ) { + + memset( dev->shade.pHilight, 0, + shadingBytes * dev->shade.skipHilight * 3 ); + + memset((SANE_Byte*)dev->shade.pHilight + + shadingBytes * dev->shade.skipHilight * 3, 0xff, + shadingBytes * dev->shade.skipShadow * 3 ); + } + + for( count = 32; count--; ) { + + if( u12io_IsEscPressed()) { + DBG( _DBG_INFO, "* CANCEL detected!\n" ); + return SANE_STATUS_CANCELLED; + } + + u12io_ReadOneShadingLine( dev, ((SANE_Byte*)dev->bufs.b1.pShadingRam)+ + _SHADING_BEGINX, shadingBytes ); + + if( dev->shade.pHilight ) { + + if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + + cp.red.usp = dev->bufs.b1.pShadingRam + _SHADING_BEGINX; + cp.green.usp = cp.red.usp + dev->regs.RD_Pixels; + cp.blue.usp = cp.green.usp + dev->regs.RD_Pixels; + pvar.pusrgb = (RGBUShortDef*)dev->shade.pHilight + + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + pRGB = pvar.pusrgb++; + wR = *cp.red.usp; + wG = *cp.green.usp; + wB = *cp.blue.usp; + + for( b = dev->shade.skipHilight; b--; + pRGB += dev->regs.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 = dev->shade.skipShadow; b--; + pRGB += dev->regs.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 = dev->bufs.b1.pShadingRam + + dev->regs.RD_Pixels + _SHADING_BEGINX; + cp.blue.usp = (u_short*)dev->shade.pHilight + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + cp.red.usp = cp.blue.usp++; + wG = *cp.green.usp; + for( b = dev->shade.skipHilight; b--; + cp.red.usp += dev->regs.RD_Pixels) { + if( wG > *cp.red.usp ) { + tmp = wG; + wG = *cp.red.usp; + *cp.red.usp = tmp; + } + } + wG = *cp.green.usp++; + for( b = dev->shade.skipShadow; b--; + cp.red.usp += dev->regs.RD_Pixels ) { + if( wG < *cp.red.usp ) { + tmp = wG; + wG = *cp.red.usp; + *cp.red.usp = tmp; + } + } + } + } + } + + /* AddToSumBuffer() */ + if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + + cp.red.usp = dev->bufs.b1.pShadingRam + _SHADING_BEGINX; + cp.green.usp = cp.red.usp + dev->regs.RD_Pixels; + cp.blue.usp = cp.green.usp + dev->regs.RD_Pixels; + + pvar.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--; + pvar.pulrgb++, cp.red.usp++, cp.green.usp++, cp.blue.usp++) { + pvar.pulrgb->Red += (u_long)*cp.red.usp; + pvar.pulrgb->Green += (u_long)*cp.green.usp; + pvar.pulrgb->Blue += (u_long)*cp.blue.usp; + } + + } else { + + cp.green.usp = dev->bufs.b1.pShadingRam + + dev->regs.RD_Pixels + _SHADING_BEGINX; + pvar.pdw = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--; pvar.pdw++, cp.green.usp++) { + *pvar.pdw += (u_long)*cp.green.usp; + } + } + + u12io_ResetFifoLen(); + if( u12io_GetFifoLength( dev ) < dev->regs.RD_Pixels ) + u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); + } + + /* AverageAfterSubHilightShadow() */ + if( dev->shade.pHilight ) { + if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + + psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + pvar.pusrgb = (RGBUShortDef*)dev->shade.pHilight + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + pRGB = pvar.pusrgb++; + + for( b = dev->shade.skipHilight + dev->shade.skipShadow; + b--; pRGB += dev->regs.RD_Pixels ) { + + psum.pulrgb->Red -= (u_long)pRGB->Red; + psum.pulrgb->Green -= (u_long)pRGB->Green; + psum.pulrgb->Blue -= (u_long)pRGB->Blue; + } + + pwsum->Red = (u_short)(psum.pulrgb->Red / dev->shade.dwDiv); + pwsum->Green = (u_short)(psum.pulrgb->Green / dev->shade.dwDiv); + pwsum->Blue = (u_short)(psum.pulrgb->Blue / dev->shade.dwDiv); + psum.pulrgb++; + pwsum++; + } + } else { + cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + cp.blue.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + pvar.pw = (u_short*)dev->shade.pHilight + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + cp.red.usp = pvar.pw++; + + for( b = dev->shade.skipHilight + dev->shade.skipShadow; + b--; cp.red.usp += dev->regs.RD_Pixels ) + *cp.green.ulp -= *cp.red.usp; + + *cp.blue.usp = (u_short)(*cp.green.ulp / dev->shade.dwDiv); + cp.blue.usp++; + cp.green.ulp++; + } + } + } else { + + if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + + psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + pwsum->Red = (u_short)(psum.pulrgb->Red >> 5); + pwsum->Green = (u_short)(psum.pulrgb->Green >> 5); + pwsum->Blue = (u_short)(psum.pulrgb->Blue >> 5); + psum.pulrgb++; + pwsum++; + } + } else { + cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + cp.blue.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + *cp.blue.usp = (u_short)(*cp.green.ulp >> 5); + cp.blue.usp++; + cp.green.ulp++; + } + } + } + + /* Process negative & transparency here */ + if( dev->DataInf.dwScanFlag & _SCANDEF_TPA ) + u12tpa_FindCenterPointer( dev ); + + if( dev->DataInf.dwScanFlag & _SCANDEF_Negative ) + u12tpa_Reshading( dev ); + + pRGB = (RGBUShortDef*)&dev->shade.pCcdDac->GainResize; + + if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + + pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + + if ((short)(pwsum->Red -= dev->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 -= dev->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 -= dev->shade.DarkOffset.Colors.Blue) > 0) { + pwsum->Blue = pwsum->Blue * pRGB->Blue / 100U; + if( pwsum->Blue > 0xfff ) + pwsum->Blue = 0xfff; + } else + pwsum->Blue = 0; + + wR = (u_short)(pwsum->Red >> 4); + pwsum->Red <<= 12; + pwsum->Red |= wR; + wR = (u_short)(pwsum->Green >> 4); + pwsum->Green <<= 12; + pwsum->Green |= wR; + wR = (u_short)(pwsum->Blue>> 4); + pwsum->Blue <<= 12; + pwsum->Blue |= wR; + pwsum++; + } + } else { + + cp.green.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; + + for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; + var.dwValue--;) { + + if((short)(*cp.green.usp -= dev->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 = (u_short)(*cp.green.usp >> 4); + *cp.green.usp <<= 12; + *cp.green.usp |= wR; + + cp.green.usp++; + } + } + + u12shading_DownloadShadingTable(dev, dev->bufs.b2.pSumBuf, (5400 * 3 * 2)); + return SANE_STATUS_GOOD; +} + +/** + */ +static void u12shading_GainOffsetToDAC( U12_Device *dev, SANE_Byte ch, + SANE_Byte reg, SANE_Byte d ) +{ + if( dev->DACType == _DA_SAMSUNG8531 ) { + u12io_DataRegisterToDAC( dev, 0, ch ); + } + u12io_DataRegisterToDAC( dev, reg, d ); +} + +/** + */ +static void u12shading_FillToDAC( U12_Device *dev, + RGBByteDef *regs, ColorByte *data ) +{ + if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + + u12shading_GainOffsetToDAC(dev, _DAC_RED, regs->Red, data->Colors.Red); + u12shading_GainOffsetToDAC(dev, _DAC_GREENCOLOR, + regs->Green, data->Colors.Green); + u12shading_GainOffsetToDAC(dev, _DAC_BLUE, + regs->Blue, data->Colors.Blue); + } else { + u12shading_GainOffsetToDAC(dev, _DAC_GREENMONO, regs->Green, + data->Colors.Green); + } +} + +/** + */ +static SANE_Byte u12shading_SumGains( SANE_Byte *pb, u_long pixelsLine ) +{ + SANE_Byte hilight, tmp; + u_long dwPixels, dwAve; + u_short sum; + + hilight = 0; + for( dwPixels = pixelsLine >> 4; dwPixels--; ) { + + for( sum = 0, dwAve = 16; dwAve--; pb++ ) + sum += (u_short)*pb; + + sum >>= 4; + tmp = (SANE_Byte)sum; + + if( tmp > hilight ) + hilight = tmp; + } + return hilight; +} + +/** + */ +static void +u12shading_AdjustGain( U12_Device *dev, u_long color, SANE_Byte hilight ) +{ + if( hilight < dev->shade.bGainLow ) { + + if( dev->shade.Hilight.bColors[color] < dev->shade.bGainHigh ) { + + dev->shade.fStop = SANE_FALSE; + dev->shade.Hilight.bColors[color] = hilight; + + if( hilight <= (SANE_Byte)(dev->shade.bGainLow - hilight)) + dev->shade.Gain.bColors[color] += dev->shade.bGainDouble; + else + dev->shade.Gain.bColors[color]++; + } + } else { + if( hilight > dev->shade.bGainHigh ) { + dev->shade.fStop = SANE_FALSE; + dev->shade.Hilight.bColors[color] = hilight; + dev->shade.Gain.bColors[color]--; + } else { + dev->shade.Hilight.bColors[color] = hilight; + } + } + + if( dev->shade.Gain.bColors[color] > dev->shade.bMaxGain ) { + dev->shade.Gain.bColors[color] = dev->shade.bMaxGain; + } +} + +/** + */ +static SANE_Status u12shading_AdjustRGBGain( U12_Device *dev ) +{ + int i; + SANE_Byte hi[3]; + + DBG( _DBG_INFO, "u12shading_AdjustRGBGain()\n" ); + + dev->shade.Gain.Colors.Red = + dev->shade.Gain.Colors.Green = + dev->shade.Gain.Colors.Blue = dev->shade.bUniGain; + + dev->shade.Hilight.Colors.Red = + dev->shade.Hilight.Colors.Green = + dev->shade.Hilight.Colors.Blue = 0; + + dev->shade.bGainHigh = _GAIN_HIGH; + dev->shade.bGainLow = _GAIN_LOW; + + dev->shade.fStop = SANE_FALSE; + + for( i = 10; i-- && !dev->shade.fStop; ) { + + if( u12io_IsEscPressed()) { + DBG( _DBG_INFO, "* CANCEL detected!\n" ); + return SANE_STATUS_CANCELLED; + } + + dev->shade.fStop = SANE_TRUE; + + u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); + + dev->regs.RD_ScanControl = _SCAN_BYTEMODE; + u12hw_SelectLampSource( dev ); + u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl ); + + u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain ); + + dev->regs.RD_ModeControl = _ModeScan; + dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; + dev->regs.RD_Motor0Control = _FORWARD_MOTOR; + + if( dev->shade.intermediate & _ScanMode_AverageOut ) + dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X >> 1; + else + dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X; + + dev->regs.RD_Dpi = 300; + dev->regs.RD_Pixels = 2560; + + memset( dev->scanStates, 0, _SCANSTATE_BYTES ); + dev->scanStates[1] = 0x77; + + u12io_PutOnAllRegisters( dev ); +/* _DODELAY( 100 ); */ + + /* read one shading line and work on it */ + if( u12io_ReadOneShadingLine( dev, + (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560)) { + + if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { + + hi[1] = u12shading_SumGains( + (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560); + if( hi[1] ) { + u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] ); + } else { + dev->shade.fStop = SANE_FALSE; + } + } else { + hi[0] = u12shading_SumGains( + (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560); + hi[1] = u12shading_SumGains( + (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560); + hi[2] = u12shading_SumGains( + (SANE_Byte*)dev->bufs.b1.pShadingRam + 5120, 2560); + + if (!hi[0] || !hi[1] || !hi[2] ) { + dev->shade.fStop = SANE_FALSE; + } else { + u12shading_AdjustGain( dev, _CHANNEL_RED, hi[0] ); + u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] ); + u12shading_AdjustGain( dev, _CHANNEL_BLUE, hi[2] ); + } + } + } else + dev->shade.fStop = SANE_FALSE; + } + + if( !dev->shade.fStop ) + DBG( _DBG_INFO, "u12shading_AdjustRGBGain() - all loops done!!!\n" ); + + u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain ); + return SANE_STATUS_GOOD; +} + +/** + */ +static u_short u12shading_SumDarks( U12_Device *dev, u_short *data ) +{ + u_short i, loop; + + if( dev->CCDID == _CCD_3799 ) { + if( dev->shade.intermediate & _ScanMode_AverageOut ) + data += 0x18; + else + data += 0x30; + } else { + if( dev->shade.intermediate & _ScanMode_AverageOut ) + data += 0x18; + else + data += 0x20; + } + + for( i = 0, loop = 16; loop--; data++ ) + i += *data; + i >>= 4; + + return i; +} + +/** + */ +static SANE_Status u12shadingAdjustDark( U12_Device *dev ) +{ + u_long i; + u_short wDarks[3]; + + DBG( _DBG_INFO, "u12shadingAdjustDark()\n" ); + dev->shade.DarkDAC.Colors = dev->shade.pCcdDac->DarkDAC.Colors; + dev->shade.fStop = SANE_FALSE; + + for( i = 16; i-- && !dev->shade.fStop;) { + + if( u12io_IsEscPressed()) { + DBG( _DBG_INFO, "* CANCEL detected!\n" ); + return SANE_STATUS_CANCELLED; + } + + dev->shade.fStop = SANE_TRUE; + + u12shading_FillToDAC( dev, &dev->RegDACOffset, &dev->shade.DarkDAC ); + u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); + + dev->regs.RD_ScanControl = (_SCAN_12BITMODE + _SCAN_1ST_AVERAGE); + u12hw_SelectLampSource( dev ); + u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl ); + + dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; + dev->regs.RD_Motor0Control = _FORWARD_MOTOR; + + dev->regs.RD_Origin = _SHADING_BEGINX; + dev->regs.RD_Pixels = 512; + + if( dev->shade.intermediate & _ScanMode_AverageOut ) + dev->regs.RD_Dpi = 300; + else + dev->regs.RD_Dpi = 600; + + memset( dev->scanStates, 0, _SCANSTATE_BYTES ); + dev->scanStates[1] = 0x77; + + u12io_PutOnAllRegisters( dev ); +/* _DODELAY( 100 ); */ + + /* read one shading line and work on it */ + if( u12io_ReadOneShadingLine(dev, + (SANE_Byte*)dev->bufs.b1.pShadingRam, 512*2)) { + + if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + + wDarks[0] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam); + wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam + + dev->regs.RD_Pixels ); + wDarks[2] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam + + dev->regs.RD_Pixels * 2UL); + + if( !wDarks[0] || !wDarks[1] || !wDarks[2] ) { + dev->shade.fStop = SANE_FALSE; + } else { + dev->shade.DarkOffset.wColors[0] = wDarks[0]; + dev->shade.DarkOffset.wColors[1] = wDarks[1]; + dev->shade.DarkOffset.wColors[2] = wDarks[2]; + (*dev->fnDACDark)( dev,dev->shade.pCcdDac, + _CHANNEL_RED, wDarks[0] ); + (*dev->fnDACDark)( dev, dev->shade.pCcdDac, + _CHANNEL_GREEN, wDarks[1] ); + (*dev->fnDACDark)( dev, dev->shade.pCcdDac, + _CHANNEL_BLUE, wDarks[2] ); + } + } else { + wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam + + dev->regs.RD_Pixels ); + if(!wDarks[1] ) { + dev->shade.fStop = SANE_FALSE; + } else { + dev->shade.DarkOffset.wColors[1] = wDarks[1]; + (*dev->fnDACDark)( dev, dev->shade.pCcdDac, + _CHANNEL_GREEN, wDarks[1] ); + } + } + } else { + dev->shade.fStop = SANE_FALSE; + } + } + + /* CalculateDarkDependOnCCD() */ + if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { + (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_RED ); + (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN ); + (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_BLUE ); + } else { + (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN ); + } + return SANE_STATUS_GOOD; +} + +/** here we download the current mapping table + */ +static void u12shading_DownloadMapTable( U12_Device *dev, SANE_Byte *buf ) +{ + SANE_Byte addr, regs[6]; + int i; + + u12io_DataToRegister( dev, REG_SCANCONTROL, + (SANE_Byte)((dev->regs.RD_ScanControl & 0xfc) | _SCAN_BYTEMODE)); + + /* prepare register settings... */ + regs[0] = REG_MODECONTROL; + regs[1] = _ModeMappingMem; + regs[2] = REG_MEMORYLO; + regs[3] = 0; + regs[4] = REG_MEMORYHI; + + for( i = 3, addr = _MAP_ADDR_RED; i--; addr += _MAP_ADDR_SIZE ) { + + regs[5] = addr; + u12io_DataToRegs( dev, regs, 3 ); + + u12io_MoveDataToScanner( dev, buf, 4096 ); + buf += 4096; + } + + u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl ); +} + +/** + */ +static SANE_Status u12shading_DoCalibration( U12_Device *dev ) +{ + SANE_Byte tb[4096*3]; + u_long i, tmp; + SANE_Byte bScanControl, rb[20]; + SANE_Status res; + int c; + + DBG( _DBG_INFO, "u12shading_DoCalibration()\n" ); + + /** before getting the shading data, (re)init the ASIC + */ + u12hw_InitAsic( dev, SANE_TRUE ); + + dev->shade.DarkOffset.Colors.Red = 0; + dev->shade.DarkOffset.Colors.Green = 0; + dev->shade.DarkOffset.Colors.Blue = 0; + + c = 0; + _SET_REG( rb, c, REG_RESETMTSC, 0 ); + _SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl); + _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType ); + _SET_REG( rb, c, REG_SCANCONTROL1, (_SCANSTOPONBUFFULL| _MFRC_BY_XSTEP)); + + u12io_DataToRegs( dev, rb, c ); + + res = u12motor_GotoShadingPosition( dev ); + if( SANE_STATUS_GOOD != res ) + return res; + + bScanControl = dev->regs.RD_ScanControl; + + /* SetShadingMapForGainDark */ + memset( dev->bufs.b2.pSumBuf, 0xff, (5400 * 3 * 2)); + u12shading_DownloadShadingTable( dev, dev->bufs.b2.pSumBuf, (5400*3*2)); + + for( i = 0, tmp = 0; i < 1024; tmp += 0x01010101, i += 4 ) { + dev->bufs.b1.Buf.pdw[i] = + dev->bufs.b1.Buf.pdw[i+1] = + dev->bufs.b1.Buf.pdw[i+2] = + dev->bufs.b1.Buf.pdw[i+3] = tmp; + } + + memcpy( dev->bufs.b1.pShadingMap + 4096, dev->bufs.b1.pShadingMap, 4096 ); + memcpy( dev->bufs.b1.pShadingMap + 8192, dev->bufs.b1.pShadingMap, 4096 ); + u12shading_DownloadMapTable( dev, dev->bufs.b1.pShadingMap ); + + DBG( _DBG_INFO, "* wExposure = %u\n", dev->shade.wExposure); + DBG( _DBG_INFO, "* wXStep = %u\n", dev->shade.wXStep); + + dev->regs.RD_LineControl = (_LOBYTE(dev->shade.wExposure)); + dev->regs.RD_ExtLineControl = (_HIBYTE(dev->shade.wExposure)); + u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL, + dev->regs.RD_ExtLineControl ); + u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl ); + + res = u12shading_AdjustRGBGain( dev ); + if( SANE_STATUS_GOOD != res ) + return res; + + res = u12shadingAdjustDark( dev ); + if( SANE_STATUS_GOOD != res ) + return res; + + res = u12shadingAdjustShadingWaveform( dev ); + if( SANE_STATUS_GOOD != res ) + return res; + + dev->regs.RD_ScanControl = bScanControl; + + /* here we have to prepare and download the table in any case...*/ + if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { + u12map_Adjust( dev, _MAP_MASTER, tb ); + } else { + u12map_Adjust( dev, _MAP_RED, tb ); + u12map_Adjust( dev, _MAP_GREEN, tb ); + u12map_Adjust( dev, _MAP_BLUE, tb ); + } + + u12shading_DownloadMapTable( dev, tb ); + + u12motor_BackToHomeSensor( dev ); + DBG( _DBG_INFO, "u12shading_DoCalibration() - done.\n" ); + return SANE_STATUS_GOOD; +} + +/* END U12-SHADING ..........................................................*/ -- cgit v1.2.3