1141cc406Sopenharmony_ci/* @file u12-shading.c -
2141cc406Sopenharmony_ci * @brief all the shading functions
3141cc406Sopenharmony_ci *
4141cc406Sopenharmony_ci * based on sources acquired from Plustek Inc.
5141cc406Sopenharmony_ci * Copyright (C) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de>
6141cc406Sopenharmony_ci *
7141cc406Sopenharmony_ci * History:
8141cc406Sopenharmony_ci * - 0.01 - initial version
9141cc406Sopenharmony_ci * - 0.02 -
10141cc406Sopenharmony_ci * .
11141cc406Sopenharmony_ci * <hr>
12141cc406Sopenharmony_ci * This file is part of the SANE package.
13141cc406Sopenharmony_ci *
14141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or
15141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as
16141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the
17141cc406Sopenharmony_ci * License, or (at your option) any later version.
18141cc406Sopenharmony_ci *
19141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but
20141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
21141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22141cc406Sopenharmony_ci * General Public License for more details.
23141cc406Sopenharmony_ci *
24141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License
25141cc406Sopenharmony_ci * along with this program.  If not, see <https://www.gnu.org/licenses/>.
26141cc406Sopenharmony_ci *
27141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for
28141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE.
29141cc406Sopenharmony_ci *
30141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files
31141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the
32141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public
33141cc406Sopenharmony_ci * License.  Your use of that executable is in no way restricted on
34141cc406Sopenharmony_ci * account of linking the SANE library code into it.
35141cc406Sopenharmony_ci *
36141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why
37141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public
38141cc406Sopenharmony_ci * License.
39141cc406Sopenharmony_ci *
40141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in
41141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that
42141cc406Sopenharmony_ci * those changes may be distributed with this exception intact.
43141cc406Sopenharmony_ci *
44141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice
45141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications.
46141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice.
47141cc406Sopenharmony_ci * <hr>
48141cc406Sopenharmony_ci */
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#define _GAIN_HIGH 240 /* Volt. max. value */
51141cc406Sopenharmony_ci#define _GAIN_LOW  220 /* Volt. min. value */
52141cc406Sopenharmony_ci
53141cc406Sopenharmony_ci#define _CHANNEL_RED   0
54141cc406Sopenharmony_ci#define _CHANNEL_GREEN 1
55141cc406Sopenharmony_ci#define _CHANNEL_BLUE  2
56141cc406Sopenharmony_ci
57141cc406Sopenharmony_ci/* for DAC programming */
58141cc406Sopenharmony_ci#define _VALUE_CONFIG   0x51
59141cc406Sopenharmony_ci#define _DAC_RED        (SANE_Byte)(_VALUE_CONFIG | 0x00)
60141cc406Sopenharmony_ci#define _DAC_GREENCOLOR (SANE_Byte)(_VALUE_CONFIG | 0x04)
61141cc406Sopenharmony_ci#define _DAC_GREENMONO  (SANE_Byte)(_VALUE_CONFIG | 0x06)
62141cc406Sopenharmony_ci#define _DAC_BLUE       (SANE_Byte)(_VALUE_CONFIG | 0x08)
63141cc406Sopenharmony_ci
64141cc406Sopenharmony_ci
65141cc406Sopenharmony_ci/* forward declarations ... */
66141cc406Sopenharmony_cistatic void u12tpa_Reshading( U12_Device * );
67141cc406Sopenharmony_cistatic void u12tpa_FindCenterPointer( U12_Device * );
68141cc406Sopenharmony_ci
69141cc406Sopenharmony_ci/**
70141cc406Sopenharmony_ci */
71141cc406Sopenharmony_cistatic void
72141cc406Sopenharmony_ciu12shading_DownloadShadingTable( U12_Device *dev, SANE_Byte *buf, u_long len )
73141cc406Sopenharmony_ci{
74141cc406Sopenharmony_ci	SANE_Byte *val, *rb;
75141cc406Sopenharmony_ci	SANE_Byte  reg, regs[20];
76141cc406Sopenharmony_ci	int        c;
77141cc406Sopenharmony_ci
78141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12shading_DownloadShadingTable()\n" );
79141cc406Sopenharmony_ci
80141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_MODECONTROL, _ModeShadingMem );
81141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_MEMORYLO,  0 );
82141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_MEMORYHI, 0 );
83141cc406Sopenharmony_ci
84141cc406Sopenharmony_ci	/* set 12 bits output color */
85141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_SCANCONTROL,
86141cc406Sopenharmony_ci	                  (SANE_Byte)(dev->regs.RD_ScanControl | _SCAN_12BITMODE));
87141cc406Sopenharmony_ci
88141cc406Sopenharmony_ci	u12io_MoveDataToScanner( dev, buf, len );
89141cc406Sopenharmony_ci
90141cc406Sopenharmony_ci	regs[0] = REG_MODECONTROL;
91141cc406Sopenharmony_ci	regs[1] = _ModeScan;
92141cc406Sopenharmony_ci
93141cc406Sopenharmony_ci	/* FillShadingDarkToShadingRegister() */
94141cc406Sopenharmony_ci	dev->regs.RD_RedDarkOff   = dev->shade.DarkOffset.Colors.Red;
95141cc406Sopenharmony_ci	dev->regs.RD_GreenDarkOff = dev->shade.DarkOffset.Colors.Green;
96141cc406Sopenharmony_ci	dev->regs.RD_BlueDarkOff  = dev->shade.DarkOffset.Colors.Blue;
97141cc406Sopenharmony_ci
98141cc406Sopenharmony_ci	val = (SANE_Byte*)&dev->regs.RD_RedDarkOff;
99141cc406Sopenharmony_ci	rb  = &regs[2];
100141cc406Sopenharmony_ci	c   = 1;
101141cc406Sopenharmony_ci	for( reg = REG_REDCHDARKOFFSETLO;
102141cc406Sopenharmony_ci	     reg <= REG_BLUECHDARKOFFSETHI; reg++, val++) {
103141cc406Sopenharmony_ci
104141cc406Sopenharmony_ci		*(rb++) = reg;
105141cc406Sopenharmony_ci		*(rb++) = *val;
106141cc406Sopenharmony_ci		c++;
107141cc406Sopenharmony_ci	}
108141cc406Sopenharmony_ci	u12io_DataToRegs( dev, regs, c );
109141cc406Sopenharmony_ci}
110141cc406Sopenharmony_ci
111141cc406Sopenharmony_ci/**
112141cc406Sopenharmony_ci */
113141cc406Sopenharmony_cistatic SANE_Status u12shadingAdjustShadingWaveform( U12_Device *dev )
114141cc406Sopenharmony_ci{
115141cc406Sopenharmony_ci	SANE_Byte     b;
116141cc406Sopenharmony_ci	u_short       count, wR, wG, wB, tmp;
117141cc406Sopenharmony_ci	DataType      var;
118141cc406Sopenharmony_ci	DataPointer   pvar, psum;
119141cc406Sopenharmony_ci	RBGPtrDef     cp;
120141cc406Sopenharmony_ci	RGBUShortDef *pRGB, *pwsum;
121141cc406Sopenharmony_ci	u_long        shadingBytes;
122141cc406Sopenharmony_ci
123141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12shading_AdjustShadingWaveForm()\n" );
124141cc406Sopenharmony_ci
125141cc406Sopenharmony_ci	memset( &cp, 0, sizeof(RBGPtrDef));
126141cc406Sopenharmony_ci	memset( dev->bufs.b2.pSumBuf, 0, (5400 * 3 * 2));
127141cc406Sopenharmony_ci
128141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle );
129141cc406Sopenharmony_ci
130141cc406Sopenharmony_ci	dev->regs.RD_LineControl    = _LOBYTE(dev->shade.wExposure);
131141cc406Sopenharmony_ci	dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure);
132141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL,
133141cc406Sopenharmony_ci	                      dev->regs.RD_ExtLineControl );
134141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl );
135141cc406Sopenharmony_ci
136141cc406Sopenharmony_ci	dev->regs.RD_XStepTime    = _LOBYTE(dev->shade.wExposure);
137141cc406Sopenharmony_ci	dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wExposure);
138141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime );
139141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_XSTEPTIME, dev->regs.RD_XStepTime );
140141cc406Sopenharmony_ci
141141cc406Sopenharmony_ci	dev->regs.RD_ModeControl   = _ModeScan;
142141cc406Sopenharmony_ci	dev->regs.RD_StepControl   = _MOTOR0_SCANSTATE;
143141cc406Sopenharmony_ci	dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
144141cc406Sopenharmony_ci
145141cc406Sopenharmony_ci	if( dev->shade.intermediate & _ScanMode_AverageOut ) {
146141cc406Sopenharmony_ci
147141cc406Sopenharmony_ci		dev->regs.RD_Dpi    = 300;
148141cc406Sopenharmony_ci		dev->regs.RD_Pixels = 2700;
149141cc406Sopenharmony_ci		shadingBytes        = 2700 * 2;
150141cc406Sopenharmony_ci	} else {
151141cc406Sopenharmony_ci		dev->regs.RD_Dpi    = 600;
152141cc406Sopenharmony_ci		dev->regs.RD_Pixels = 5400;
153141cc406Sopenharmony_ci		shadingBytes        = 5400 * 2;
154141cc406Sopenharmony_ci	}
155141cc406Sopenharmony_ci	dev->regs.RD_Origin = _SHADING_BEGINX;
156141cc406Sopenharmony_ci
157141cc406Sopenharmony_ci	for( pvar.pdw = (u_long*)dev->scanStates,
158141cc406Sopenharmony_ci		var.dwValue = _SCANSTATE_BYTES >> 2; var.dwValue--; pvar.pdw++) {
159141cc406Sopenharmony_ci		*pvar.pdw = 0x00f00080;
160141cc406Sopenharmony_ci	}
161141cc406Sopenharmony_ci
162141cc406Sopenharmony_ci	dev->scan.refreshState = SANE_FALSE;
163141cc406Sopenharmony_ci	u12io_PutOnAllRegisters( dev );
164141cc406Sopenharmony_ci/*	_DODELAY( 100 ); */
165141cc406Sopenharmony_ci
166141cc406Sopenharmony_ci	if( dev->shade.pHilight ) {
167141cc406Sopenharmony_ci
168141cc406Sopenharmony_ci		memset( dev->shade.pHilight, 0,
169141cc406Sopenharmony_ci		        shadingBytes * dev->shade.skipHilight * 3 );
170141cc406Sopenharmony_ci
171141cc406Sopenharmony_ci		memset((SANE_Byte*)dev->shade.pHilight +
172141cc406Sopenharmony_ci		        shadingBytes * dev->shade.skipHilight * 3, 0xff,
173141cc406Sopenharmony_ci		        shadingBytes * dev->shade.skipShadow * 3 );
174141cc406Sopenharmony_ci	}
175141cc406Sopenharmony_ci
176141cc406Sopenharmony_ci	for( count = 32; count--; ) {
177141cc406Sopenharmony_ci
178141cc406Sopenharmony_ci		if( u12io_IsEscPressed()) {
179141cc406Sopenharmony_ci			DBG( _DBG_INFO, "* CANCEL detected!\n" );
180141cc406Sopenharmony_ci			return SANE_STATUS_CANCELLED;
181141cc406Sopenharmony_ci		}
182141cc406Sopenharmony_ci
183141cc406Sopenharmony_ci		u12io_ReadOneShadingLine( dev, ((SANE_Byte*)dev->bufs.b1.pShadingRam)+
184141cc406Sopenharmony_ci		                           _SHADING_BEGINX, shadingBytes );
185141cc406Sopenharmony_ci
186141cc406Sopenharmony_ci		if( dev->shade.pHilight ) {
187141cc406Sopenharmony_ci
188141cc406Sopenharmony_ci			if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
189141cc406Sopenharmony_ci
190141cc406Sopenharmony_ci				cp.red.usp   = dev->bufs.b1.pShadingRam + _SHADING_BEGINX;
191141cc406Sopenharmony_ci				cp.green.usp = cp.red.usp   + dev->regs.RD_Pixels;
192141cc406Sopenharmony_ci				cp.blue.usp  = cp.green.usp + dev->regs.RD_Pixels;
193141cc406Sopenharmony_ci				pvar.pusrgb  = (RGBUShortDef*)dev->shade.pHilight +
194141cc406Sopenharmony_ci				                                              _SHADING_BEGINX;
195141cc406Sopenharmony_ci
196141cc406Sopenharmony_ci				for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
197141cc406Sopenharmony_ci				                                              var.dwValue--;) {
198141cc406Sopenharmony_ci					pRGB = pvar.pusrgb++;
199141cc406Sopenharmony_ci					wR = *cp.red.usp;
200141cc406Sopenharmony_ci					wG = *cp.green.usp;
201141cc406Sopenharmony_ci					wB = *cp.blue.usp;
202141cc406Sopenharmony_ci
203141cc406Sopenharmony_ci					for( b = dev->shade.skipHilight; b--;
204141cc406Sopenharmony_ci					                            pRGB += dev->regs.RD_Pixels ) {
205141cc406Sopenharmony_ci						if( wR > pRGB->Red ) {
206141cc406Sopenharmony_ci							tmp = wR;
207141cc406Sopenharmony_ci							wR  = pRGB->Red;
208141cc406Sopenharmony_ci							pRGB->Red = tmp;
209141cc406Sopenharmony_ci						}
210141cc406Sopenharmony_ci						if( wG > pRGB->Green ) {
211141cc406Sopenharmony_ci							tmp = wG;
212141cc406Sopenharmony_ci							wG  = pRGB->Green;
213141cc406Sopenharmony_ci							pRGB->Green = tmp;
214141cc406Sopenharmony_ci						}
215141cc406Sopenharmony_ci						if( wB > pRGB->Blue ) {
216141cc406Sopenharmony_ci							tmp = wB;
217141cc406Sopenharmony_ci							wB  = pRGB->Blue;
218141cc406Sopenharmony_ci							pRGB->Blue = tmp;
219141cc406Sopenharmony_ci						}
220141cc406Sopenharmony_ci					}
221141cc406Sopenharmony_ci
222141cc406Sopenharmony_ci					wR = *cp.red.usp++;
223141cc406Sopenharmony_ci					wG = *cp.green.usp++;
224141cc406Sopenharmony_ci					wB = *cp.blue.usp++;
225141cc406Sopenharmony_ci
226141cc406Sopenharmony_ci					for( b = dev->shade.skipShadow; b--;
227141cc406Sopenharmony_ci					                            pRGB += dev->regs.RD_Pixels ) {
228141cc406Sopenharmony_ci						if( wR < pRGB->Red ) {
229141cc406Sopenharmony_ci							tmp = wR;
230141cc406Sopenharmony_ci							wR  = pRGB->Red;
231141cc406Sopenharmony_ci							pRGB->Red = tmp;
232141cc406Sopenharmony_ci						}
233141cc406Sopenharmony_ci						if( wG < pRGB->Green ) {
234141cc406Sopenharmony_ci							tmp = wG;
235141cc406Sopenharmony_ci							wG  = pRGB->Green;
236141cc406Sopenharmony_ci							pRGB->Green = tmp;
237141cc406Sopenharmony_ci						}
238141cc406Sopenharmony_ci						if( wB < pRGB->Blue ) {
239141cc406Sopenharmony_ci							tmp = wB;
240141cc406Sopenharmony_ci							wB  = pRGB->Blue;
241141cc406Sopenharmony_ci							pRGB->Blue = tmp;
242141cc406Sopenharmony_ci						}
243141cc406Sopenharmony_ci					}
244141cc406Sopenharmony_ci				}
245141cc406Sopenharmony_ci			} else {
246141cc406Sopenharmony_ci
247141cc406Sopenharmony_ci				cp.green.usp = dev->bufs.b1.pShadingRam +
248141cc406Sopenharmony_ci				               dev->regs.RD_Pixels + _SHADING_BEGINX;
249141cc406Sopenharmony_ci				cp.blue.usp  = (u_short*)dev->shade.pHilight + _SHADING_BEGINX;
250141cc406Sopenharmony_ci
251141cc406Sopenharmony_ci				for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
252141cc406Sopenharmony_ci				                                              var.dwValue--;) {
253141cc406Sopenharmony_ci					cp.red.usp = cp.blue.usp++;
254141cc406Sopenharmony_ci					wG = *cp.green.usp;
255141cc406Sopenharmony_ci					for( b = dev->shade.skipHilight; b--;
256141cc406Sopenharmony_ci					                       cp.red.usp += dev->regs.RD_Pixels) {
257141cc406Sopenharmony_ci						if( wG > *cp.red.usp ) {
258141cc406Sopenharmony_ci							tmp = wG;
259141cc406Sopenharmony_ci							wG  = *cp.red.usp;
260141cc406Sopenharmony_ci							*cp.red.usp = tmp;
261141cc406Sopenharmony_ci						}
262141cc406Sopenharmony_ci					}
263141cc406Sopenharmony_ci					wG = *cp.green.usp++;
264141cc406Sopenharmony_ci					for( b = dev->shade.skipShadow; b--;
265141cc406Sopenharmony_ci					                      cp.red.usp += dev->regs.RD_Pixels ) {
266141cc406Sopenharmony_ci						if( wG < *cp.red.usp ) {
267141cc406Sopenharmony_ci							tmp = wG;
268141cc406Sopenharmony_ci							wG  = *cp.red.usp;
269141cc406Sopenharmony_ci							*cp.red.usp = tmp;
270141cc406Sopenharmony_ci						}
271141cc406Sopenharmony_ci					}
272141cc406Sopenharmony_ci				}
273141cc406Sopenharmony_ci			}
274141cc406Sopenharmony_ci		}
275141cc406Sopenharmony_ci
276141cc406Sopenharmony_ci		/* AddToSumBuffer() */
277141cc406Sopenharmony_ci		if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
278141cc406Sopenharmony_ci
279141cc406Sopenharmony_ci			cp.red.usp   = dev->bufs.b1.pShadingRam + _SHADING_BEGINX;
280141cc406Sopenharmony_ci			cp.green.usp = cp.red.usp   + dev->regs.RD_Pixels;
281141cc406Sopenharmony_ci			cp.blue.usp  = cp.green.usp + dev->regs.RD_Pixels;
282141cc406Sopenharmony_ci
283141cc406Sopenharmony_ci			pvar.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
284141cc406Sopenharmony_ci
285141cc406Sopenharmony_ci			for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX;
286141cc406Sopenharmony_ci			     var.dwValue--;
287141cc406Sopenharmony_ci			     pvar.pulrgb++, cp.red.usp++, cp.green.usp++, cp.blue.usp++) {
288141cc406Sopenharmony_ci				pvar.pulrgb->Red   += (u_long)*cp.red.usp;
289141cc406Sopenharmony_ci				pvar.pulrgb->Green += (u_long)*cp.green.usp;
290141cc406Sopenharmony_ci				pvar.pulrgb->Blue  += (u_long)*cp.blue.usp;
291141cc406Sopenharmony_ci			}
292141cc406Sopenharmony_ci
293141cc406Sopenharmony_ci		} else {
294141cc406Sopenharmony_ci
295141cc406Sopenharmony_ci			cp.green.usp = dev->bufs.b1.pShadingRam +
296141cc406Sopenharmony_ci			               dev->regs.RD_Pixels +  _SHADING_BEGINX;
297141cc406Sopenharmony_ci			pvar.pdw  = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
298141cc406Sopenharmony_ci			for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX;
299141cc406Sopenharmony_ci			     var.dwValue--; pvar.pdw++, cp.green.usp++) {
300141cc406Sopenharmony_ci				*pvar.pdw += (u_long)*cp.green.usp;
301141cc406Sopenharmony_ci			}
302141cc406Sopenharmony_ci		}
303141cc406Sopenharmony_ci
304141cc406Sopenharmony_ci		u12io_ResetFifoLen();
305141cc406Sopenharmony_ci		if( u12io_GetFifoLength( dev ) < dev->regs.RD_Pixels )
306141cc406Sopenharmony_ci			u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE );
307141cc406Sopenharmony_ci	}
308141cc406Sopenharmony_ci
309141cc406Sopenharmony_ci	/* AverageAfterSubHilightShadow() */
310141cc406Sopenharmony_ci	if( dev->shade.pHilight ) {
311141cc406Sopenharmony_ci		if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
312141cc406Sopenharmony_ci
313141cc406Sopenharmony_ci			psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
314141cc406Sopenharmony_ci			pwsum       = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
315141cc406Sopenharmony_ci			pvar.pusrgb = (RGBUShortDef*)dev->shade.pHilight + _SHADING_BEGINX;
316141cc406Sopenharmony_ci
317141cc406Sopenharmony_ci			for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
318141cc406Sopenharmony_ci                                                              var.dwValue--;) {
319141cc406Sopenharmony_ci				pRGB = pvar.pusrgb++;
320141cc406Sopenharmony_ci
321141cc406Sopenharmony_ci				for( b = dev->shade.skipHilight + dev->shade.skipShadow;
322141cc406Sopenharmony_ci				                           b--; pRGB += dev->regs.RD_Pixels ) {
323141cc406Sopenharmony_ci
324141cc406Sopenharmony_ci					psum.pulrgb->Red   -= (u_long)pRGB->Red;
325141cc406Sopenharmony_ci					psum.pulrgb->Green -= (u_long)pRGB->Green;
326141cc406Sopenharmony_ci					psum.pulrgb->Blue  -= (u_long)pRGB->Blue;
327141cc406Sopenharmony_ci				}
328141cc406Sopenharmony_ci
329141cc406Sopenharmony_ci				pwsum->Red   = (u_short)(psum.pulrgb->Red   / dev->shade.dwDiv);
330141cc406Sopenharmony_ci				pwsum->Green = (u_short)(psum.pulrgb->Green / dev->shade.dwDiv);
331141cc406Sopenharmony_ci				pwsum->Blue  = (u_short)(psum.pulrgb->Blue  / dev->shade.dwDiv);
332141cc406Sopenharmony_ci				psum.pulrgb++;
333141cc406Sopenharmony_ci				pwsum++;
334141cc406Sopenharmony_ci			}
335141cc406Sopenharmony_ci		} else {
336141cc406Sopenharmony_ci			cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
337141cc406Sopenharmony_ci			cp.blue.usp  = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
338141cc406Sopenharmony_ci			pvar.pw      = (u_short*)dev->shade.pHilight  + _SHADING_BEGINX;
339141cc406Sopenharmony_ci
340141cc406Sopenharmony_ci			for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
341141cc406Sopenharmony_ci			                                                  var.dwValue--;) {
342141cc406Sopenharmony_ci				cp.red.usp = pvar.pw++;
343141cc406Sopenharmony_ci
344141cc406Sopenharmony_ci				for( b = dev->shade.skipHilight + dev->shade.skipShadow;
345141cc406Sopenharmony_ci				                       b--; cp.red.usp += dev->regs.RD_Pixels )
346141cc406Sopenharmony_ci					*cp.green.ulp -= *cp.red.usp;
347141cc406Sopenharmony_ci
348141cc406Sopenharmony_ci				*cp.blue.usp = (u_short)(*cp.green.ulp / dev->shade.dwDiv);
349141cc406Sopenharmony_ci				cp.blue.usp++;
350141cc406Sopenharmony_ci				cp.green.ulp++;
351141cc406Sopenharmony_ci			}
352141cc406Sopenharmony_ci		}
353141cc406Sopenharmony_ci	} else {
354141cc406Sopenharmony_ci
355141cc406Sopenharmony_ci		if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
356141cc406Sopenharmony_ci
357141cc406Sopenharmony_ci			psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf  + _SHADING_BEGINX;
358141cc406Sopenharmony_ci			pwsum       = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
359141cc406Sopenharmony_ci
360141cc406Sopenharmony_ci			for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
361141cc406Sopenharmony_ci			                                                  var.dwValue--;) {
362141cc406Sopenharmony_ci				pwsum->Red   = (u_short)(psum.pulrgb->Red   >> 5);
363141cc406Sopenharmony_ci				pwsum->Green = (u_short)(psum.pulrgb->Green >> 5);
364141cc406Sopenharmony_ci				pwsum->Blue  = (u_short)(psum.pulrgb->Blue  >> 5);
365141cc406Sopenharmony_ci				psum.pulrgb++;
366141cc406Sopenharmony_ci				pwsum++;
367141cc406Sopenharmony_ci			}
368141cc406Sopenharmony_ci		} else {
369141cc406Sopenharmony_ci			cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf  + _SHADING_BEGINX;
370141cc406Sopenharmony_ci			cp.blue.usp  = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
371141cc406Sopenharmony_ci
372141cc406Sopenharmony_ci			for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
373141cc406Sopenharmony_ci			                                                  var.dwValue--;) {
374141cc406Sopenharmony_ci				*cp.blue.usp = (u_short)(*cp.green.ulp >> 5);
375141cc406Sopenharmony_ci				cp.blue.usp++;
376141cc406Sopenharmony_ci				cp.green.ulp++;
377141cc406Sopenharmony_ci			}
378141cc406Sopenharmony_ci		}
379141cc406Sopenharmony_ci	}
380141cc406Sopenharmony_ci
381141cc406Sopenharmony_ci	/* Process negative & transparency here */
382141cc406Sopenharmony_ci	if( dev->DataInf.dwScanFlag & _SCANDEF_TPA )
383141cc406Sopenharmony_ci		u12tpa_FindCenterPointer( dev );
384141cc406Sopenharmony_ci
385141cc406Sopenharmony_ci	if( dev->DataInf.dwScanFlag & _SCANDEF_Negative )
386141cc406Sopenharmony_ci		u12tpa_Reshading( dev );
387141cc406Sopenharmony_ci
388141cc406Sopenharmony_ci	pRGB = (RGBUShortDef*)&dev->shade.pCcdDac->GainResize;
389141cc406Sopenharmony_ci
390141cc406Sopenharmony_ci	if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
391141cc406Sopenharmony_ci
392141cc406Sopenharmony_ci		pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
393141cc406Sopenharmony_ci
394141cc406Sopenharmony_ci		for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
395141cc406Sopenharmony_ci		                                                      var.dwValue--;) {
396141cc406Sopenharmony_ci
397141cc406Sopenharmony_ci			if ((short)(pwsum->Red -= dev->shade.DarkOffset.Colors.Red) > 0) {
398141cc406Sopenharmony_ci				pwsum->Red = pwsum->Red * pRGB->Red / 100U;
399141cc406Sopenharmony_ci				if( pwsum->Red > 0xfff )
400141cc406Sopenharmony_ci					pwsum->Red = 0xfff;
401141cc406Sopenharmony_ci			} else
402141cc406Sopenharmony_ci				pwsum->Red = 0;
403141cc406Sopenharmony_ci
404141cc406Sopenharmony_ci			if((short)(pwsum->Green -= dev->shade.DarkOffset.Colors.Green) > 0) {
405141cc406Sopenharmony_ci				pwsum->Green = pwsum->Green * pRGB->Green / 100U;
406141cc406Sopenharmony_ci				if( pwsum->Green > 0xfff )
407141cc406Sopenharmony_ci					pwsum->Green = 0xfff;
408141cc406Sopenharmony_ci			} else
409141cc406Sopenharmony_ci				pwsum->Green = 0;
410141cc406Sopenharmony_ci
411141cc406Sopenharmony_ci			if ((short)(pwsum->Blue -= dev->shade.DarkOffset.Colors.Blue) > 0) {
412141cc406Sopenharmony_ci				pwsum->Blue = pwsum->Blue * pRGB->Blue / 100U;
413141cc406Sopenharmony_ci				if( pwsum->Blue > 0xfff )
414141cc406Sopenharmony_ci					pwsum->Blue = 0xfff;
415141cc406Sopenharmony_ci			} else
416141cc406Sopenharmony_ci				pwsum->Blue = 0;
417141cc406Sopenharmony_ci
418141cc406Sopenharmony_ci			wR = (u_short)(pwsum->Red >> 4);
419141cc406Sopenharmony_ci			pwsum->Red <<= 12;
420141cc406Sopenharmony_ci			pwsum->Red |= wR;
421141cc406Sopenharmony_ci			wR = (u_short)(pwsum->Green >> 4);
422141cc406Sopenharmony_ci			pwsum->Green <<= 12;
423141cc406Sopenharmony_ci			pwsum->Green |= wR;
424141cc406Sopenharmony_ci			wR = (u_short)(pwsum->Blue>> 4);
425141cc406Sopenharmony_ci			pwsum->Blue <<= 12;
426141cc406Sopenharmony_ci			pwsum->Blue |= wR;
427141cc406Sopenharmony_ci			pwsum++;
428141cc406Sopenharmony_ci		}
429141cc406Sopenharmony_ci	} else {
430141cc406Sopenharmony_ci
431141cc406Sopenharmony_ci		cp.green.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
432141cc406Sopenharmony_ci
433141cc406Sopenharmony_ci		for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
434141cc406Sopenharmony_ci		                                                      var.dwValue--;) {
435141cc406Sopenharmony_ci
436141cc406Sopenharmony_ci			if((short)(*cp.green.usp -= dev->shade.DarkOffset.Colors.Green) > 0) {
437141cc406Sopenharmony_ci
438141cc406Sopenharmony_ci				*cp.green.usp = *cp.green.usp * pRGB->Green / 100U;
439141cc406Sopenharmony_ci				if( *cp.green.usp > 0xfff )
440141cc406Sopenharmony_ci					*cp.green.usp = 0xfff;
441141cc406Sopenharmony_ci			} else
442141cc406Sopenharmony_ci				*cp.green.usp = 0;
443141cc406Sopenharmony_ci
444141cc406Sopenharmony_ci			wR = (u_short)(*cp.green.usp >> 4);
445141cc406Sopenharmony_ci			*cp.green.usp <<= 12;
446141cc406Sopenharmony_ci			*cp.green.usp |= wR;
447141cc406Sopenharmony_ci
448141cc406Sopenharmony_ci			cp.green.usp++;
449141cc406Sopenharmony_ci		}
450141cc406Sopenharmony_ci	}
451141cc406Sopenharmony_ci
452141cc406Sopenharmony_ci	u12shading_DownloadShadingTable(dev, dev->bufs.b2.pSumBuf, (5400 * 3 * 2));
453141cc406Sopenharmony_ci	return SANE_STATUS_GOOD;
454141cc406Sopenharmony_ci}
455141cc406Sopenharmony_ci
456141cc406Sopenharmony_ci/**
457141cc406Sopenharmony_ci */
458141cc406Sopenharmony_cistatic void u12shading_GainOffsetToDAC( U12_Device *dev, SANE_Byte ch,
459141cc406Sopenharmony_ci                                        SANE_Byte reg, SANE_Byte d )
460141cc406Sopenharmony_ci{
461141cc406Sopenharmony_ci	if( dev->DACType == _DA_SAMSUNG8531 ) {
462141cc406Sopenharmony_ci		u12io_DataRegisterToDAC( dev, 0, ch );
463141cc406Sopenharmony_ci	}
464141cc406Sopenharmony_ci	u12io_DataRegisterToDAC( dev, reg, d );
465141cc406Sopenharmony_ci}
466141cc406Sopenharmony_ci
467141cc406Sopenharmony_ci/**
468141cc406Sopenharmony_ci */
469141cc406Sopenharmony_cistatic void u12shading_FillToDAC( U12_Device *dev,
470141cc406Sopenharmony_ci                                  RGBByteDef *regs, ColorByte *data )
471141cc406Sopenharmony_ci{
472141cc406Sopenharmony_ci	if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
473141cc406Sopenharmony_ci
474141cc406Sopenharmony_ci		u12shading_GainOffsetToDAC(dev, _DAC_RED, regs->Red, data->Colors.Red);
475141cc406Sopenharmony_ci		u12shading_GainOffsetToDAC(dev, _DAC_GREENCOLOR,
476141cc406Sopenharmony_ci                                              regs->Green, data->Colors.Green);
477141cc406Sopenharmony_ci		u12shading_GainOffsetToDAC(dev, _DAC_BLUE,
478141cc406Sopenharmony_ci                                                regs->Blue, data->Colors.Blue);
479141cc406Sopenharmony_ci	} else {
480141cc406Sopenharmony_ci		u12shading_GainOffsetToDAC(dev, _DAC_GREENMONO, regs->Green,
481141cc406Sopenharmony_ci		                                                   data->Colors.Green);
482141cc406Sopenharmony_ci    }
483141cc406Sopenharmony_ci}
484141cc406Sopenharmony_ci
485141cc406Sopenharmony_ci/**
486141cc406Sopenharmony_ci */
487141cc406Sopenharmony_cistatic SANE_Byte u12shading_SumGains( SANE_Byte *pb, u_long pixelsLine )
488141cc406Sopenharmony_ci{
489141cc406Sopenharmony_ci	SANE_Byte hilight, tmp;
490141cc406Sopenharmony_ci	u_long    dwPixels, dwAve;
491141cc406Sopenharmony_ci	u_short   sum;
492141cc406Sopenharmony_ci
493141cc406Sopenharmony_ci	hilight = 0;
494141cc406Sopenharmony_ci	for( dwPixels = pixelsLine >> 4; dwPixels--; ) {
495141cc406Sopenharmony_ci
496141cc406Sopenharmony_ci		for( sum = 0, dwAve = 16; dwAve--; pb++ )
497141cc406Sopenharmony_ci			sum += (u_short)*pb;
498141cc406Sopenharmony_ci
499141cc406Sopenharmony_ci		sum >>= 4;
500141cc406Sopenharmony_ci		tmp = (SANE_Byte)sum;
501141cc406Sopenharmony_ci
502141cc406Sopenharmony_ci		if( tmp > hilight )
503141cc406Sopenharmony_ci			hilight = tmp;
504141cc406Sopenharmony_ci	}
505141cc406Sopenharmony_ci	return hilight;
506141cc406Sopenharmony_ci}
507141cc406Sopenharmony_ci
508141cc406Sopenharmony_ci/**
509141cc406Sopenharmony_ci */
510141cc406Sopenharmony_cistatic void
511141cc406Sopenharmony_ciu12shading_AdjustGain( U12_Device *dev, u_long color, SANE_Byte hilight )
512141cc406Sopenharmony_ci{
513141cc406Sopenharmony_ci	if( hilight < dev->shade.bGainLow ) {
514141cc406Sopenharmony_ci
515141cc406Sopenharmony_ci		if( dev->shade.Hilight.bColors[color] < dev->shade.bGainHigh ) {
516141cc406Sopenharmony_ci
517141cc406Sopenharmony_ci			dev->shade.fStop = SANE_FALSE;
518141cc406Sopenharmony_ci			dev->shade.Hilight.bColors[color] = hilight;
519141cc406Sopenharmony_ci
520141cc406Sopenharmony_ci			if( hilight <= (SANE_Byte)(dev->shade.bGainLow - hilight))
521141cc406Sopenharmony_ci				dev->shade.Gain.bColors[color] += dev->shade.bGainDouble;
522141cc406Sopenharmony_ci			else
523141cc406Sopenharmony_ci				dev->shade.Gain.bColors[color]++;
524141cc406Sopenharmony_ci		}
525141cc406Sopenharmony_ci	} else {
526141cc406Sopenharmony_ci		if( hilight > dev->shade.bGainHigh ) {
527141cc406Sopenharmony_ci			dev->shade.fStop = SANE_FALSE;
528141cc406Sopenharmony_ci			dev->shade.Hilight.bColors[color] = hilight;
529141cc406Sopenharmony_ci			dev->shade.Gain.bColors[color]--;
530141cc406Sopenharmony_ci		} else {
531141cc406Sopenharmony_ci			dev->shade.Hilight.bColors[color] = hilight;
532141cc406Sopenharmony_ci		}
533141cc406Sopenharmony_ci	}
534141cc406Sopenharmony_ci
535141cc406Sopenharmony_ci	if( dev->shade.Gain.bColors[color] > dev->shade.bMaxGain ) {
536141cc406Sopenharmony_ci		dev->shade.Gain.bColors[color] = dev->shade.bMaxGain;
537141cc406Sopenharmony_ci	}
538141cc406Sopenharmony_ci}
539141cc406Sopenharmony_ci
540141cc406Sopenharmony_ci/**
541141cc406Sopenharmony_ci */
542141cc406Sopenharmony_cistatic SANE_Status u12shading_AdjustRGBGain( U12_Device *dev )
543141cc406Sopenharmony_ci{
544141cc406Sopenharmony_ci	int       i;
545141cc406Sopenharmony_ci	SANE_Byte hi[3];
546141cc406Sopenharmony_ci
547141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12shading_AdjustRGBGain()\n" );
548141cc406Sopenharmony_ci
549141cc406Sopenharmony_ci	dev->shade.Gain.Colors.Red   =
550141cc406Sopenharmony_ci	dev->shade.Gain.Colors.Green =
551141cc406Sopenharmony_ci	dev->shade.Gain.Colors.Blue  =  dev->shade.bUniGain;
552141cc406Sopenharmony_ci
553141cc406Sopenharmony_ci	dev->shade.Hilight.Colors.Red   =
554141cc406Sopenharmony_ci	dev->shade.Hilight.Colors.Green =
555141cc406Sopenharmony_ci	dev->shade.Hilight.Colors.Blue  = 0;
556141cc406Sopenharmony_ci
557141cc406Sopenharmony_ci	dev->shade.bGainHigh = _GAIN_HIGH;
558141cc406Sopenharmony_ci	dev->shade.bGainLow  = _GAIN_LOW;
559141cc406Sopenharmony_ci
560141cc406Sopenharmony_ci	dev->shade.fStop = SANE_FALSE;
561141cc406Sopenharmony_ci
562141cc406Sopenharmony_ci	for( i = 10; i-- && !dev->shade.fStop; ) {
563141cc406Sopenharmony_ci
564141cc406Sopenharmony_ci		if( u12io_IsEscPressed()) {
565141cc406Sopenharmony_ci			DBG( _DBG_INFO, "* CANCEL detected!\n" );
566141cc406Sopenharmony_ci			return SANE_STATUS_CANCELLED;
567141cc406Sopenharmony_ci		}
568141cc406Sopenharmony_ci
569141cc406Sopenharmony_ci		dev->shade.fStop = SANE_TRUE;
570141cc406Sopenharmony_ci
571141cc406Sopenharmony_ci		u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle );
572141cc406Sopenharmony_ci
573141cc406Sopenharmony_ci		dev->regs.RD_ScanControl = _SCAN_BYTEMODE;
574141cc406Sopenharmony_ci		u12hw_SelectLampSource( dev );
575141cc406Sopenharmony_ci		u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl );
576141cc406Sopenharmony_ci
577141cc406Sopenharmony_ci		u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain );
578141cc406Sopenharmony_ci
579141cc406Sopenharmony_ci		dev->regs.RD_ModeControl   = _ModeScan;
580141cc406Sopenharmony_ci		dev->regs.RD_StepControl   = _MOTOR0_SCANSTATE;
581141cc406Sopenharmony_ci		dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
582141cc406Sopenharmony_ci
583141cc406Sopenharmony_ci		if( dev->shade.intermediate & _ScanMode_AverageOut )
584141cc406Sopenharmony_ci			dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X >> 1;
585141cc406Sopenharmony_ci		else
586141cc406Sopenharmony_ci			dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X;
587141cc406Sopenharmony_ci
588141cc406Sopenharmony_ci		dev->regs.RD_Dpi    = 300;
589141cc406Sopenharmony_ci		dev->regs.RD_Pixels = 2560;
590141cc406Sopenharmony_ci
591141cc406Sopenharmony_ci		memset( dev->scanStates, 0, _SCANSTATE_BYTES );
592141cc406Sopenharmony_ci		dev->scanStates[1] = 0x77;
593141cc406Sopenharmony_ci
594141cc406Sopenharmony_ci		u12io_PutOnAllRegisters( dev );
595141cc406Sopenharmony_ci/*		_DODELAY( 100 ); */
596141cc406Sopenharmony_ci
597141cc406Sopenharmony_ci		/* read one shading line and work on it */
598141cc406Sopenharmony_ci		if( u12io_ReadOneShadingLine( dev,
599141cc406Sopenharmony_ci		                         (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560)) {
600141cc406Sopenharmony_ci
601141cc406Sopenharmony_ci			if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) {
602141cc406Sopenharmony_ci
603141cc406Sopenharmony_ci				hi[1] = u12shading_SumGains(
604141cc406Sopenharmony_ci				           (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560);
605141cc406Sopenharmony_ci				if( hi[1] ) {
606141cc406Sopenharmony_ci					u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] );
607141cc406Sopenharmony_ci				} else {
608141cc406Sopenharmony_ci					dev->shade.fStop = SANE_FALSE;
609141cc406Sopenharmony_ci				}
610141cc406Sopenharmony_ci			} else {
611141cc406Sopenharmony_ci				hi[0] = u12shading_SumGains(
612141cc406Sopenharmony_ci				                   (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560);
613141cc406Sopenharmony_ci				hi[1] = u12shading_SumGains(
614141cc406Sopenharmony_ci				            (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560);
615141cc406Sopenharmony_ci				hi[2] = u12shading_SumGains(
616141cc406Sopenharmony_ci				            (SANE_Byte*)dev->bufs.b1.pShadingRam + 5120, 2560);
617141cc406Sopenharmony_ci
618141cc406Sopenharmony_ci				if (!hi[0] || !hi[1] || !hi[2] ) {
619141cc406Sopenharmony_ci					dev->shade.fStop = SANE_FALSE;
620141cc406Sopenharmony_ci				} else {
621141cc406Sopenharmony_ci					u12shading_AdjustGain( dev, _CHANNEL_RED,   hi[0] );
622141cc406Sopenharmony_ci					u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] );
623141cc406Sopenharmony_ci					u12shading_AdjustGain( dev, _CHANNEL_BLUE,  hi[2] );
624141cc406Sopenharmony_ci				}
625141cc406Sopenharmony_ci			}
626141cc406Sopenharmony_ci		} else
627141cc406Sopenharmony_ci			dev->shade.fStop = SANE_FALSE;
628141cc406Sopenharmony_ci	}
629141cc406Sopenharmony_ci
630141cc406Sopenharmony_ci	if( !dev->shade.fStop )
631141cc406Sopenharmony_ci		DBG( _DBG_INFO, "u12shading_AdjustRGBGain() - all loops done!!!\n" );
632141cc406Sopenharmony_ci
633141cc406Sopenharmony_ci	u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain );
634141cc406Sopenharmony_ci	return SANE_STATUS_GOOD;
635141cc406Sopenharmony_ci}
636141cc406Sopenharmony_ci
637141cc406Sopenharmony_ci/**
638141cc406Sopenharmony_ci */
639141cc406Sopenharmony_cistatic u_short u12shading_SumDarks( U12_Device *dev, u_short *data )
640141cc406Sopenharmony_ci{
641141cc406Sopenharmony_ci	u_short i, loop;
642141cc406Sopenharmony_ci
643141cc406Sopenharmony_ci	if( dev->CCDID == _CCD_3799 ) {
644141cc406Sopenharmony_ci		if( dev->shade.intermediate & _ScanMode_AverageOut )
645141cc406Sopenharmony_ci			data += 0x18;
646141cc406Sopenharmony_ci		else
647141cc406Sopenharmony_ci			data += 0x30;
648141cc406Sopenharmony_ci	} else {
649141cc406Sopenharmony_ci		if( dev->shade.intermediate & _ScanMode_AverageOut )
650141cc406Sopenharmony_ci			data += 0x18;
651141cc406Sopenharmony_ci    	else
652141cc406Sopenharmony_ci			data += 0x20;
653141cc406Sopenharmony_ci	}
654141cc406Sopenharmony_ci
655141cc406Sopenharmony_ci	for( i = 0, loop = 16; loop--; data++ )
656141cc406Sopenharmony_ci		i += *data;
657141cc406Sopenharmony_ci	i >>= 4;
658141cc406Sopenharmony_ci
659141cc406Sopenharmony_ci	return i;
660141cc406Sopenharmony_ci}
661141cc406Sopenharmony_ci
662141cc406Sopenharmony_ci/**
663141cc406Sopenharmony_ci */
664141cc406Sopenharmony_cistatic SANE_Status u12shadingAdjustDark( U12_Device *dev )
665141cc406Sopenharmony_ci{
666141cc406Sopenharmony_ci	u_long  i;
667141cc406Sopenharmony_ci	u_short wDarks[3];
668141cc406Sopenharmony_ci
669141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12shadingAdjustDark()\n" );
670141cc406Sopenharmony_ci	dev->shade.DarkDAC.Colors = dev->shade.pCcdDac->DarkDAC.Colors;
671141cc406Sopenharmony_ci	dev->shade.fStop = SANE_FALSE;
672141cc406Sopenharmony_ci
673141cc406Sopenharmony_ci	for( i = 16; i-- && !dev->shade.fStop;) {
674141cc406Sopenharmony_ci
675141cc406Sopenharmony_ci		if( u12io_IsEscPressed()) {
676141cc406Sopenharmony_ci			DBG( _DBG_INFO, "* CANCEL detected!\n" );
677141cc406Sopenharmony_ci			return SANE_STATUS_CANCELLED;
678141cc406Sopenharmony_ci		}
679141cc406Sopenharmony_ci
680141cc406Sopenharmony_ci		dev->shade.fStop = SANE_TRUE;
681141cc406Sopenharmony_ci
682141cc406Sopenharmony_ci		u12shading_FillToDAC( dev, &dev->RegDACOffset, &dev->shade.DarkDAC );
683141cc406Sopenharmony_ci		u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle );
684141cc406Sopenharmony_ci
685141cc406Sopenharmony_ci		dev->regs.RD_ScanControl = (_SCAN_12BITMODE + _SCAN_1ST_AVERAGE);
686141cc406Sopenharmony_ci		u12hw_SelectLampSource( dev );
687141cc406Sopenharmony_ci		u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl );
688141cc406Sopenharmony_ci
689141cc406Sopenharmony_ci		dev->regs.RD_StepControl   = _MOTOR0_SCANSTATE;
690141cc406Sopenharmony_ci		dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
691141cc406Sopenharmony_ci
692141cc406Sopenharmony_ci		dev->regs.RD_Origin = _SHADING_BEGINX;
693141cc406Sopenharmony_ci		dev->regs.RD_Pixels = 512;
694141cc406Sopenharmony_ci
695141cc406Sopenharmony_ci		if( dev->shade.intermediate & _ScanMode_AverageOut )
696141cc406Sopenharmony_ci			dev->regs.RD_Dpi = 300;
697141cc406Sopenharmony_ci		else
698141cc406Sopenharmony_ci			dev->regs.RD_Dpi = 600;
699141cc406Sopenharmony_ci
700141cc406Sopenharmony_ci		memset( dev->scanStates, 0, _SCANSTATE_BYTES );
701141cc406Sopenharmony_ci		dev->scanStates[1] = 0x77;
702141cc406Sopenharmony_ci
703141cc406Sopenharmony_ci		u12io_PutOnAllRegisters( dev );
704141cc406Sopenharmony_ci/*		_DODELAY( 100 ); */
705141cc406Sopenharmony_ci
706141cc406Sopenharmony_ci		/* read one shading line and work on it */
707141cc406Sopenharmony_ci		if( u12io_ReadOneShadingLine(dev,
708141cc406Sopenharmony_ci		                        (SANE_Byte*)dev->bufs.b1.pShadingRam, 512*2)) {
709141cc406Sopenharmony_ci
710141cc406Sopenharmony_ci			if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
711141cc406Sopenharmony_ci
712141cc406Sopenharmony_ci				wDarks[0] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam);
713141cc406Sopenharmony_ci				wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam +
714141cc406Sopenharmony_ci                                                dev->regs.RD_Pixels );
715141cc406Sopenharmony_ci				wDarks[2] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam +
716141cc406Sopenharmony_ci				                                dev->regs.RD_Pixels * 2UL);
717141cc406Sopenharmony_ci
718141cc406Sopenharmony_ci				if( !wDarks[0] || !wDarks[1] || !wDarks[2] ) {
719141cc406Sopenharmony_ci					dev->shade.fStop = SANE_FALSE;
720141cc406Sopenharmony_ci				} else {
721141cc406Sopenharmony_ci					dev->shade.DarkOffset.wColors[0] = wDarks[0];
722141cc406Sopenharmony_ci					dev->shade.DarkOffset.wColors[1] = wDarks[1];
723141cc406Sopenharmony_ci					dev->shade.DarkOffset.wColors[2] = wDarks[2];
724141cc406Sopenharmony_ci					(*dev->fnDACDark)( dev,dev->shade.pCcdDac,
725141cc406Sopenharmony_ci					                           _CHANNEL_RED, wDarks[0] );
726141cc406Sopenharmony_ci					(*dev->fnDACDark)( dev, dev->shade.pCcdDac,
727141cc406Sopenharmony_ci					                           _CHANNEL_GREEN, wDarks[1] );
728141cc406Sopenharmony_ci					(*dev->fnDACDark)( dev, dev->shade.pCcdDac,
729141cc406Sopenharmony_ci					                           _CHANNEL_BLUE, wDarks[2] );
730141cc406Sopenharmony_ci				}
731141cc406Sopenharmony_ci			} else {
732141cc406Sopenharmony_ci				wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam +
733141cc406Sopenharmony_ci                                                dev->regs.RD_Pixels );
734141cc406Sopenharmony_ci				if(!wDarks[1] ) {
735141cc406Sopenharmony_ci					dev->shade.fStop = SANE_FALSE;
736141cc406Sopenharmony_ci				} else {
737141cc406Sopenharmony_ci					dev->shade.DarkOffset.wColors[1] = wDarks[1];
738141cc406Sopenharmony_ci					(*dev->fnDACDark)( dev, dev->shade.pCcdDac,
739141cc406Sopenharmony_ci				                                   _CHANNEL_GREEN, wDarks[1] );
740141cc406Sopenharmony_ci				}
741141cc406Sopenharmony_ci			}
742141cc406Sopenharmony_ci		} else {
743141cc406Sopenharmony_ci			dev->shade.fStop = SANE_FALSE;
744141cc406Sopenharmony_ci		}
745141cc406Sopenharmony_ci	}
746141cc406Sopenharmony_ci
747141cc406Sopenharmony_ci	/* CalculateDarkDependOnCCD() */
748141cc406Sopenharmony_ci	if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
749141cc406Sopenharmony_ci		(*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_RED   );
750141cc406Sopenharmony_ci		(*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN );
751141cc406Sopenharmony_ci		(*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_BLUE  );
752141cc406Sopenharmony_ci	} else {
753141cc406Sopenharmony_ci		(*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN );
754141cc406Sopenharmony_ci	}
755141cc406Sopenharmony_ci	return SANE_STATUS_GOOD;
756141cc406Sopenharmony_ci}
757141cc406Sopenharmony_ci
758141cc406Sopenharmony_ci/** here we download the current mapping table
759141cc406Sopenharmony_ci */
760141cc406Sopenharmony_cistatic void u12shading_DownloadMapTable( U12_Device *dev, SANE_Byte *buf )
761141cc406Sopenharmony_ci{
762141cc406Sopenharmony_ci	SANE_Byte addr, regs[6];
763141cc406Sopenharmony_ci	int       i;
764141cc406Sopenharmony_ci
765141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_SCANCONTROL,
766141cc406Sopenharmony_ci	          (SANE_Byte)((dev->regs.RD_ScanControl & 0xfc) | _SCAN_BYTEMODE));
767141cc406Sopenharmony_ci
768141cc406Sopenharmony_ci	/* prepare register settings... */
769141cc406Sopenharmony_ci	regs[0] = REG_MODECONTROL;
770141cc406Sopenharmony_ci	regs[1] = _ModeMappingMem;
771141cc406Sopenharmony_ci	regs[2] = REG_MEMORYLO;
772141cc406Sopenharmony_ci	regs[3] = 0;
773141cc406Sopenharmony_ci	regs[4] = REG_MEMORYHI;
774141cc406Sopenharmony_ci
775141cc406Sopenharmony_ci	for( i = 3, addr = _MAP_ADDR_RED; i--; addr += _MAP_ADDR_SIZE ) {
776141cc406Sopenharmony_ci
777141cc406Sopenharmony_ci		regs[5] = addr;
778141cc406Sopenharmony_ci		u12io_DataToRegs( dev, regs, 3 );
779141cc406Sopenharmony_ci
780141cc406Sopenharmony_ci		u12io_MoveDataToScanner( dev, buf, 4096 );
781141cc406Sopenharmony_ci		buf += 4096;
782141cc406Sopenharmony_ci	}
783141cc406Sopenharmony_ci
784141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl );
785141cc406Sopenharmony_ci}
786141cc406Sopenharmony_ci
787141cc406Sopenharmony_ci/**
788141cc406Sopenharmony_ci */
789141cc406Sopenharmony_cistatic SANE_Status u12shading_DoCalibration( U12_Device *dev )
790141cc406Sopenharmony_ci{
791141cc406Sopenharmony_ci	SANE_Byte   tb[4096*3];
792141cc406Sopenharmony_ci	u_long      i, tmp;
793141cc406Sopenharmony_ci	SANE_Byte   bScanControl, rb[20];
794141cc406Sopenharmony_ci	SANE_Status res;
795141cc406Sopenharmony_ci	int         c;
796141cc406Sopenharmony_ci
797141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12shading_DoCalibration()\n" );
798141cc406Sopenharmony_ci
799141cc406Sopenharmony_ci	/** before getting the shading data, (re)init the ASIC
800141cc406Sopenharmony_ci	 */
801141cc406Sopenharmony_ci	u12hw_InitAsic( dev, SANE_TRUE );
802141cc406Sopenharmony_ci
803141cc406Sopenharmony_ci	dev->shade.DarkOffset.Colors.Red   = 0;
804141cc406Sopenharmony_ci	dev->shade.DarkOffset.Colors.Green = 0;
805141cc406Sopenharmony_ci	dev->shade.DarkOffset.Colors.Blue  = 0;
806141cc406Sopenharmony_ci
807141cc406Sopenharmony_ci	c = 0;
808141cc406Sopenharmony_ci	_SET_REG( rb, c, REG_RESETMTSC, 0 );
809141cc406Sopenharmony_ci	_SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl);
810141cc406Sopenharmony_ci	_SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType );
811141cc406Sopenharmony_ci	_SET_REG( rb, c, REG_SCANCONTROL1, (_SCANSTOPONBUFFULL| _MFRC_BY_XSTEP));
812141cc406Sopenharmony_ci
813141cc406Sopenharmony_ci	u12io_DataToRegs( dev, rb, c );
814141cc406Sopenharmony_ci
815141cc406Sopenharmony_ci	res = u12motor_GotoShadingPosition( dev );
816141cc406Sopenharmony_ci	if( SANE_STATUS_GOOD != res )
817141cc406Sopenharmony_ci		return res;
818141cc406Sopenharmony_ci
819141cc406Sopenharmony_ci	bScanControl = dev->regs.RD_ScanControl;
820141cc406Sopenharmony_ci
821141cc406Sopenharmony_ci    /* SetShadingMapForGainDark */
822141cc406Sopenharmony_ci	memset( dev->bufs.b2.pSumBuf, 0xff, (5400 * 3 * 2));
823141cc406Sopenharmony_ci	u12shading_DownloadShadingTable( dev, dev->bufs.b2.pSumBuf, (5400*3*2));
824141cc406Sopenharmony_ci
825141cc406Sopenharmony_ci	for( i = 0, tmp = 0; i < 1024; tmp += 0x01010101, i += 4 ) {
826141cc406Sopenharmony_ci		dev->bufs.b1.Buf.pdw[i]   =
827141cc406Sopenharmony_ci		dev->bufs.b1.Buf.pdw[i+1] =
828141cc406Sopenharmony_ci		dev->bufs.b1.Buf.pdw[i+2] =
829141cc406Sopenharmony_ci		dev->bufs.b1.Buf.pdw[i+3] = tmp;
830141cc406Sopenharmony_ci	}
831141cc406Sopenharmony_ci
832141cc406Sopenharmony_ci	memcpy( dev->bufs.b1.pShadingMap + 4096, dev->bufs.b1.pShadingMap, 4096 );
833141cc406Sopenharmony_ci	memcpy( dev->bufs.b1.pShadingMap + 8192, dev->bufs.b1.pShadingMap, 4096 );
834141cc406Sopenharmony_ci	u12shading_DownloadMapTable( dev, dev->bufs.b1.pShadingMap );
835141cc406Sopenharmony_ci
836141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* wExposure = %u\n", dev->shade.wExposure);
837141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* wXStep    = %u\n", dev->shade.wXStep);
838141cc406Sopenharmony_ci
839141cc406Sopenharmony_ci	dev->regs.RD_LineControl    = (_LOBYTE(dev->shade.wExposure));
840141cc406Sopenharmony_ci	dev->regs.RD_ExtLineControl = (_HIBYTE(dev->shade.wExposure));
841141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL,
842141cc406Sopenharmony_ci	                                            dev->regs.RD_ExtLineControl );
843141cc406Sopenharmony_ci	u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl );
844141cc406Sopenharmony_ci
845141cc406Sopenharmony_ci	res = u12shading_AdjustRGBGain( dev );
846141cc406Sopenharmony_ci	if( SANE_STATUS_GOOD != res )
847141cc406Sopenharmony_ci		return res;
848141cc406Sopenharmony_ci
849141cc406Sopenharmony_ci	res = u12shadingAdjustDark( dev );
850141cc406Sopenharmony_ci	if( SANE_STATUS_GOOD != res )
851141cc406Sopenharmony_ci		return res;
852141cc406Sopenharmony_ci
853141cc406Sopenharmony_ci	res = u12shadingAdjustShadingWaveform( dev );
854141cc406Sopenharmony_ci	if( SANE_STATUS_GOOD != res )
855141cc406Sopenharmony_ci		return res;
856141cc406Sopenharmony_ci
857141cc406Sopenharmony_ci	dev->regs.RD_ScanControl = bScanControl;
858141cc406Sopenharmony_ci
859141cc406Sopenharmony_ci	/* here we have to prepare and download the table in any case...*/
860141cc406Sopenharmony_ci	if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) {
861141cc406Sopenharmony_ci		u12map_Adjust( dev, _MAP_MASTER, tb );
862141cc406Sopenharmony_ci	} else {
863141cc406Sopenharmony_ci		u12map_Adjust( dev, _MAP_RED, tb   );
864141cc406Sopenharmony_ci		u12map_Adjust( dev, _MAP_GREEN, tb );
865141cc406Sopenharmony_ci		u12map_Adjust( dev, _MAP_BLUE, tb  );
866141cc406Sopenharmony_ci	}
867141cc406Sopenharmony_ci
868141cc406Sopenharmony_ci	u12shading_DownloadMapTable( dev, tb );
869141cc406Sopenharmony_ci
870141cc406Sopenharmony_ci	u12motor_BackToHomeSensor( dev );
871141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12shading_DoCalibration() - done.\n" );
872141cc406Sopenharmony_ci	return SANE_STATUS_GOOD;
873141cc406Sopenharmony_ci}
874141cc406Sopenharmony_ci
875141cc406Sopenharmony_ci/* END U12-SHADING ..........................................................*/
876