• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* @file plustek-pp_dac.c
2  * @brief all the shading function formerly found in shading.c.
3  *        don't ask me why I called this file dac.c...
4  *
5  * based on sources acquired from Plustek Inc.
6  * Copyright (C) 1998 Plustek Inc.
7  * Copyright (C) 2000-2004 Gerhard Jaeger <gerhard@gjaeger.de>
8  * also based on the work done by Rick Bronson
9  *
10  * History:
11  * - 0.30 - initial version
12  * - 0.31 - no changes
13  * - 0.32 - no changes
14  * - 0.33 - added some comments
15  * - 0.34 - slight changes
16  * - 0.35 - removed SetInitialGainRAM from structure pScanData
17  * - 0.36 - added dacP96001WaitForShading and changed dacP96WaitForShading to
18  *          dacP96003WaitForShading
19  *        - changes, due to define renaming
20  * - 0.37 - removed dacP98FillShadingDarkToShadingRegister()
21  *        - removed // comments
22  *        - some code cleanup
23  * - 0.38 - added P12 stuff
24  * - 0.39 - no changes
25  * - 0.40 - disabled the A3I stuff
26  * - 0.41 - no changes
27  * - 0.42 - changed include names
28  * - 0.43 - no changes
29  * .
30  * <hr>
31  * This file is part of the SANE package.
32  *
33  * This program is free software; you can redistribute it and/or
34  * modify it under the terms of the GNU General Public License as
35  * published by the Free Software Foundation; either version 2 of the
36  * License, or (at your option) any later version.
37  *
38  * This program is distributed in the hope that it will be useful, but
39  * WITHOUT ANY WARRANTY; without even the implied warranty of
40  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41  * General Public License for more details.
42  *
43  * You should have received a copy of the GNU General Public License
44  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
45  *
46  * As a special exception, the authors of SANE give permission for
47  * additional uses of the libraries contained in this release of SANE.
48  *
49  * The exception is that, if you link a SANE library with other files
50  * to produce an executable, this does not by itself cause the
51  * resulting executable to be covered by the GNU General Public
52  * License.  Your use of that executable is in no way restricted on
53  * account of linking the SANE library code into it.
54  *
55  * This exception does not, however, invalidate any other reasons why
56  * the executable file might be covered by the GNU General Public
57  * License.
58  *
59  * If you submit changes to SANE to the maintainers to be included in
60  * a subsequent release, you agree by submitting the changes that
61  * those changes may be distributed with this exception intact.
62  *
63  * If you write modifications of your own for SANE, it is your choice
64  * whether to permit this exception to apply to your modifications.
65  * If you do not wish that, delete this exception notice.
66  * <hr>
67  */
68 #include "plustek-pp_scan.h"
69 
70 /************************** local definitions ********************************/
71 
72 /***************************** global vars ***********************************/
73 
74 static const Byte a_bCorrectTimesTable[4] = {0, 1, 2, 4};
75 
76 static ULong dwADCPipeLine = 4 * 4;
77 static ULong dwReadyLen;
78 
79 /*************************** local functions *********************************/
80 
81 /**
82  */
dacP98AdjustGainAverage(pScanData ps)83 static void dacP98AdjustGainAverage( pScanData ps )
84 {
85 	pUChar pDest, pSrce;
86     ULong  dw, dw1;
87     UShort wSum;
88 
89     pDest = pSrce = ps->pScanBuffer1;
90 
91     for (dw1 = 0; dw1 < (2560 * 3) / 16; dw1++, pDest++) {
92 		for (dw = 0, wSum = 0; dw < 16; dw++, pSrce++)
93 		    wSum += *pSrce;
94 
95 		*pDest = wSum / 16;
96     }
97 }
98 
99 /**
100  */
dacP98FillDarkDAC(pScanData ps)101 static void dacP98FillDarkDAC( pScanData ps )
102 {
103     IODataRegisterToDAC( ps, 0x20, ps->bRedDAC   );
104     IODataRegisterToDAC( ps, 0x21, ps->bGreenDAC );
105     IODataRegisterToDAC( ps, 0x22, ps->bBlueDAC  );
106 }
107 
108 /**
109  */
dacP98SetReadFBKRegister(pScanData ps)110 static void dacP98SetReadFBKRegister( pScanData ps )
111 {
112     IODataToRegister( ps, ps->RegModeControl, _ModeIdle );
113 
114     ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE + _SCAN_1ST_AVERAGE;
115 
116     IOSelectLampSource( ps );
117     IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
118 
119 	ps->AsicReg.RD_Motor0Control = _MotorOn;
120 	ps->AsicReg.RD_StepControl 	 = _MOTOR0_SCANSTATE;
121 	ps->AsicReg.RD_Origin 		 = 4;
122 	ps->AsicReg.RD_Pixels 		 = 512;
123 	ps->AsicReg.RD_Motor1Control = 0;
124 	ps->AsicReg.RD_Motor0Control = 0;
125 
126 	ps->AsicReg.RD_ModelControl  = _LED_CONTROL + _LED_ACTIVITY;
127 
128     if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) {
129 		ps->AsicReg.RD_Dpi = 300;
130 		ps->AsicReg.RD_ModelControl += _ModelDpi300;
131 
132     } else {
133 		ps->AsicReg.RD_Dpi = 600;
134 		ps->AsicReg.RD_ModelControl += _ModelDpi600;
135     }
136 }
137 
138 /**
139  */
dacP98CalDarkOff(pScanData ps,UShort wChDarkOff,UShort wDACCompareHigh,UShort wDACOffset)140 static UShort dacP98CalDarkOff( pScanData ps, UShort wChDarkOff,
141 							    UShort wDACCompareHigh, UShort wDACOffset )
142 {
143     UShort wTemp;
144 
145     if ((_CCD_518 == ps->Device.bCCDID) || (_CCD_535 == ps->Device.bCCDID)) {
146 		wTemp = wChDarkOff + wDACOffset;
147 	} else  {
148 
149 		if (_CCD_3797 == ps->Device.bCCDID) {
150 		    if (wChDarkOff > wDACOffset) {
151 				wTemp = wChDarkOff - wDACOffset;
152 			} else {
153 				wTemp = 0;
154 			}
155 		} else {
156 		    if (wChDarkOff > wDACCompareHigh) {
157 				wTemp = wChDarkOff - wDACCompareHigh;
158 			} else {
159 				wTemp = 0;
160 			}
161 		}
162     }
163     return wTemp;
164 }
165 
166 /**
167  */
dacP98AdjustDAC(UShort DarkOff,UShort wHigh,UShort wLow,pUChar pbReg,Bool * fDACStopFlag)168 static Bool dacP98AdjustDAC( UShort DarkOff, UShort wHigh,
169 							 UShort wLow, pUChar pbReg, Bool *fDACStopFlag )
170 {
171     if (DarkOff > wHigh) {
172 		if ((DarkOff - wHigh) > 10) {
173 		    if ((DarkOff - wHigh) > 2550)
174 				*pbReg += ((DarkOff - wHigh) / 20);
175 		    else
176 			*pbReg += ((DarkOff - wHigh) / 10);
177 		} else
178 	    	*pbReg += 1;
179 
180 		if (!(*pbReg))
181 		    *pbReg = 0xff;
182 
183 		*fDACStopFlag = _FALSE;
184 		return _FALSE;
185 
186     } else {
187 		if (DarkOff < wLow) {
188 		    if (DarkOff > 0)
189 				*pbReg -= 2;
190 		    else
191 				*pbReg -= 10;
192 
193 		    *fDACStopFlag = _FALSE;
194 		    return _FALSE;
195 		} else
196 		    return _TRUE;
197 	}
198 }
199 
200 /**
201  */
dacP98CheckChannelDarkLevel(pScanData ps)202 static Bool dacP98CheckChannelDarkLevel( pScanData ps )
203 {
204 	Bool fDACStopFlag = _TRUE;
205 
206     dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Red,
207                      ps->Shade.pCcdDac->DarkCmpHi.Colors.Red,
208                      ps->Shade.pCcdDac->DarkCmpLo.Colors.Red,
209 			         &ps->bRedDAC, &fDACStopFlag );
210     dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Green,
211                      ps->Shade.pCcdDac->DarkCmpHi.Colors.Green,
212                      ps->Shade.pCcdDac->DarkCmpLo.Colors.Green,
213 			         &ps->bGreenDAC, &fDACStopFlag );
214     dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Blue,
215                      ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue,
216                      ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue,
217 			         &ps->bBlueDAC, &fDACStopFlag );
218 
219     return  fDACStopFlag;
220 }
221 
222 /** Average left offset 30, 16 pixels as each color's dark level
223  */
dacP98FillChannelDarkLevelControl(pScanData ps)224 static void dacP98FillChannelDarkLevelControl( pScanData ps )
225 {
226     DataPointer p;
227 	ULong	    dwPos, dw, dwSum;
228 
229     if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) {
230 		dwPos = 0x10 * 3;
231 	} else {
232 		dwPos = 0x20 * 2;
233 	}
234 
235     for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos), dwSum = 0, dw = 16;
236 	     dw; dw--, p.pw++) {
237 		dwSum += (ULong)(*p.pw);
238 	}
239 
240 	ps->Shade.DarkOffset.Colors.Red = (UShort)(dwSum / 16);
241 
242     for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos + 1024), dwSum = 0, dw = 16;
243 	    dw; dw--, p.pw++) {
244 		dwSum += (ULong)(*p.pw);
245 	}
246 
247     ps->Shade.DarkOffset.Colors.Green = (UShort)(dwSum / 16);
248 
249     for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos + 1024 * 2), dwSum = 0, dw = 16;
250 	    dw; dw--, p.pw++) {
251 		dwSum += (ULong)(*p.pw);
252 	}
253 
254 	ps->Shade.DarkOffset.Colors.Blue = (UShort)(dwSum / 16);
255 }
256 
257 /**
258  */
dacP98AdjustGain(pScanData ps)259 static void dacP98AdjustGain( pScanData ps )
260 {
261 	DataPointer	p;
262 	ULong		dw;
263 	UShort		w;
264     Byte		b[3];
265     pUChar		pbReg[3];
266 
267     dacP98AdjustGainAverage( ps );
268 
269     pbReg[0] = &ps->bRedGainIndex;
270     pbReg[1] = &ps->bGreenGainIndex;
271     pbReg[2] = &ps->bBlueGainIndex;
272 
273     for (w = 0, p.pb = ps->pScanBuffer1; w < 3; w++) {
274 
275 		for (dw = 2560 / 16, b [w] = 0; dw; dw--, p.pb++) {
276 		    if (b [w] < *p.pb)
277 				b [w] = *p.pb;
278 		}
279 		if (b[w] < _GAIN_LOW) {
280 		    if ((_GAIN_P98_HIGH - b[w]) < b[w])
281 				*(pbReg[w]) += 1;
282 		    else
283 				*(pbReg[w]) += 4;
284 		} else {
285 		    if (b[w] > _GAIN_P98_HIGH)
286 				*(pbReg[w]) -= 1;
287 		}
288     }
289 }
290 
291 /**
292  */
dacP98CheckLastGain(pScanData ps)293 static void dacP98CheckLastGain( pScanData ps )
294 {
295     DataPointer p;
296  	ULong	    dw;
297     UShort	    w;
298     Byte	    b[3];
299     pUChar	    pbReg[3];
300 
301     dacP98AdjustGainAverage( ps );
302 
303     pbReg[0] = &ps->bRedGainIndex;
304     pbReg[1] = &ps->bGreenGainIndex;
305     pbReg[2] = &ps->bBlueGainIndex;
306 
307     for (w = 0, p.pb = ps->pScanBuffer1; w < 3; w++) {
308 		for (dw = 2560 / 16, b [w] = 0; dw; dw--, p.pb++) {
309 		    if (b[w] < *p.pb)
310 				b[w] = *p.pb;
311 		}
312 
313 		if (b[w] > _GAIN_P98_HIGH) {
314 		    *(pbReg [w]) -= 1;
315 		}
316     }
317 }
318 
319 /**
320  */
dacP98FillGainInitialRestRegister(pScanData ps)321 static void dacP98FillGainInitialRestRegister( pScanData ps )
322 {
323 	ps->OpenScanPath( ps );
324 
325 	IODataToRegister( ps, ps->RegThresholdGapControl, ps->AsicReg.RD_ThresholdGapCtrl );
326 	IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl );
327 
328 	ps->CloseScanPath( ps );
329 }
330 
331 /**
332  */
dacP98SetInitialGainRegister(pScanData ps)333 static void dacP98SetInitialGainRegister( pScanData ps )
334 {
335 	DacP98FillGainOutDirectPort( ps );	   	/* R/G/B GainOut to scanner		*/
336     dacP98FillGainInitialRestRegister( ps );/* Model Control2, LED, Correct.*/
337 }
338 
339 /** Find the most ideal intensity for each color (RGB)
340  */
dacP98SetRGBGainRegister(pScanData ps)341 static void dacP98SetRGBGainRegister( pScanData ps )
342 {
343     IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeIdle );
344 
345 	ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
346     IOSelectLampSource( ps );
347 
348     IOCmdRegisterToScanner( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl);
349     dacP98SetInitialGainRegister( ps );
350 
351     ps->AsicReg.RD_ModeControl   = _ModeScan;
352     ps->AsicReg.RD_StepControl   = _MOTOR0_SCANSTATE;
353     ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorDirForward + _MotorHEightStep;
354     ps->AsicReg.RD_XStepTime 	 = ps->bSpeed4;
355 
356     if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) {
357 		ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi300;
358 		ps->AsicReg.RD_Origin = 32 +  60 + 4;
359     } else {
360 		ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi600;
361 		ps->AsicReg.RD_Origin = 64 + 120 + 4;
362     }
363     ps->AsicReg.RD_Dpi    = 300;
364     ps->AsicReg.RD_Pixels = 2560;
365 
366 	IOPutOnAllRegisters( ps );
367 }
368 
369 /**
370  */
dacP98FillRGBMap(pUChar pBuffer)371 static void dacP98FillRGBMap( pUChar pBuffer )
372 {
373     ULong  dw, dw1;
374 	pULong pdw = (pULong)(pBuffer);
375 
376     for( dw = 256, dw1 = 0; dw; dw--, dw1 += 0x01010101 ) {
377 		*pdw++ = dw1;
378 		*pdw++ = dw1;
379 		*pdw++ = dw1;
380 		*pdw++ = dw1;
381     }
382 }
383 
384 /** here we download the current mapping table
385  */
dacP98DownloadMapTable(pScanData ps,pUChar pBuffer)386 static void dacP98DownloadMapTable( pScanData ps, pUChar pBuffer )
387 {
388     Byte  bAddr;
389     ULong i;
390 
391     IODataToRegister( ps, ps->RegScanControl,
392 	   			(Byte)((ps->AsicReg.RD_ScanControl & 0xfc) | _SCAN_BYTEMODE));
393 
394     for( i = 3, bAddr = _MAP_ADDR_RED; i--; bAddr += _MAP_ADDR_SIZE ) {
395 
396         IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem );
397         IODataToRegister( ps, ps->RegMemoryLow, 0);
398         IODataToRegister( ps, ps->RegMemoryHigh, bAddr );
399 
400     	IOMoveDataToScanner( ps, pBuffer, 4096 );
401     	pBuffer += 4096;
402     }
403 
404     IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
405 }
406 
407 /**
408  */
dacP98DownloadShadingTable(pScanData ps,pUChar pBuffer,ULong size)409 static void dacP98DownloadShadingTable( pScanData ps,
410                                         pUChar pBuffer, ULong size )
411 {
412     IODataToRegister( ps, ps->RegModeControl, _ModeShadingMem );
413 	IODataToRegister( ps, ps->RegMemoryLow,  0 );
414     IODataToRegister( ps, ps->RegMemoryHigh, 0 );
415 
416     /* set 12 bits output color */
417     IODataToRegister( ps, ps->RegScanControl,
418 					  (Byte)(ps->AsicReg.RD_ScanControl | _SCAN_12BITMODE));
419 
420 	/* MoveDataToShadingRam() */
421     IOMoveDataToScanner( ps ,pBuffer, size );
422 
423     if( _ASIC_IS_98003 == ps->sCaps.AsicID )
424         IODataToRegister( ps, ps->RegModeControl, _ModeScan );
425     else
426         IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
427 
428     DacP98FillShadingDarkToShadingRegister( ps );
429 }
430 
431 /** Build a linear map for asic (this model is 12-bit scanner, there are 4096
432  *  map entries but just generate 256 level output, so the content must be 0 to
433  *  255), then fill the shading buffer (the first 3k), and map table (the last
434  *  1k) to asic for R & G & B channels.
435  *
436  *  I need pScanBuffer2 size = 5400 * 2 * 3
437  *  pScanBuffer1 size = 256 * 16 * 2
438  */
dacP98SetInitialGainRAM(pScanData ps)439 static void dacP98SetInitialGainRAM( pScanData ps )
440 {
441     memset( ps->pScanBuffer2, 0xff, (5400 * 2 * 3));
442 
443 	dacP98DownloadShadingTable( ps, ps->pScanBuffer2, (5400 * 2 * 3));
444 
445     dacP98FillRGBMap( ps->pScanBuffer1 );		   	/* Fill 12 Bits R Map */
446     dacP98FillRGBMap( ps->pScanBuffer1 + 4096 );    /* Fill 12 Bits G Map */
447     dacP98FillRGBMap( ps->pScanBuffer1 + 8192 );    /* Fill 12 Bits B Map */
448 
449 	dacP98DownloadMapTable( ps, ps->pScanBuffer1 );
450 }
451 
452 /** Find the most ideal intensity for each color (RGB)
453  */
dacP98AdjustRGBGain(pScanData ps)454 static void dacP98AdjustRGBGain( pScanData ps )
455 {
456 	int bCorrectTimes;
457 
458 	DBG( DBG_LOW, "dacP98AdjustRGBGain()\n" );
459 
460 	ps->OpenScanPath( ps );
461 	dacP98SetInitialGainRAM( ps );	/* set shading ram and read out data to */
462     ps->CloseScanPath( ps );
463 
464     ps->bRedGainIndex   = 0x02;
465 	ps->bGreenGainIndex = 0x02;
466 	ps->bBlueGainIndex  = 0x02;
467 
468     for (bCorrectTimes = 10; bCorrectTimes; bCorrectTimes-- ) {
469 
470 		dacP98SetRGBGainRegister( ps );	   	 /* shading the most brightness &*/
471 		ps->PauseColorMotorRunStates( ps );	 /* stop scan states			 */
472 		IOReadOneShadingLine( ps, ps->pScanBuffer1, 2560UL );
473 		dacP98AdjustGain( ps );
474     }
475 
476     dacP98SetRGBGainRegister( ps );		/* shading the most brightness &	*/
477 	ps->PauseColorMotorRunStates( ps ); /* stop scan states                */
478 
479     IOReadOneShadingLine( ps, ps->pScanBuffer1, 2560UL );
480 
481     dacP98CheckLastGain( ps );
482 	DacP98FillGainOutDirectPort( ps );
483 }
484 
485 /**
486  */
dacP98SetAdjustShadingRegister(pScanData ps)487 static void dacP98SetAdjustShadingRegister( pScanData ps )
488 {
489 	DBG( DBG_LOW, "dacP98SetAdjustShadingRegister()\n" );
490 
491 	IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeIdle );
492 
493 	ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE + _SCAN_1ST_AVERAGE;
494 	IOSelectLampSource( ps );
495 
496     IOCmdRegisterToScanner( ps, ps->RegScanControl,
497 							ps->AsicReg.RD_ScanControl );
498 
499 	ps->AsicReg.RD_ModeControl 	 = _ModeScan;
500 	ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward;
501 	ps->AsicReg.RD_XStepTime 	 = ps->bSpeed1;
502 	ps->AsicReg.RD_ModelControl  = _LED_ACTIVITY + _LED_CONTROL;
503 
504     if (ps->bSetScanModeFlag & _ScanMode_AverageOut) {
505 		ps->AsicReg.RD_Dpi 	  = 300;
506 		ps->AsicReg.RD_Pixels = 2700;
507 		ps->AsicReg.RD_ModelControl += _ModelDpi300;
508     } else {
509 		ps->AsicReg.RD_Dpi 	  = 600;
510 		ps->AsicReg.RD_Pixels = 5400;
511 		ps->AsicReg.RD_ModelControl += _ModelDpi600;
512     }
513 	ps->AsicReg.RD_Origin = 4;
514 
515 	IOPutOnAllRegisters( ps );
516 }
517 
518 /**
519  */
dacP98ReadShadingScanLine(pScanData ps)520 static void dacP98ReadShadingScanLine( pScanData ps )
521 {
522 	TimerDef timer;
523 
524 	MiscStartTimer( &timer, _SECOND );
525 
526     ps->Scan.bFifoSelect = ps->RegGFifoOffset;
527 
528     while((IOReadFifoLength( ps ) < dwReadyLen) &&
529 		   !MiscCheckTimer(&timer)) {
530 		_DO_UDELAY( 1 );
531 	}
532 
533     IOReadColorData( ps, ps->pScanBuffer2, ps->dwShadingLen );
534 }
535 
536 /**
537  */
dacP98GainResize(pUShort pValue,UShort wResize)538 static void dacP98GainResize( pUShort pValue, UShort wResize)
539 {
540 	DataType Data;
541     Byte	 bTemp;
542 
543     Data.dwValue = ((ULong) *pValue) * (ULong) wResize / 100;
544 
545     if (0x1000 <= Data.dwValue)
546 		Data.wValue = 0xfff;
547 
548     Data.wValue *= 16;
549 
550     bTemp = Data.wOverlap.b1st;
551     Data.wOverlap.b1st = Data.wOverlap.b2nd;
552     Data.wOverlap.b2nd = bTemp;
553 
554     *pValue = Data.wValue;
555 }
556 
557 /**
558  */
dacP98SortHilightShadow(pScanData ps,pUShort pwData,ULong dwHilightOff,ULong dwShadowOff)559 static void dacP98SortHilightShadow( pScanData ps, pUShort pwData,
560 					 			     ULong dwHilightOff, ULong dwShadowOff )
561 {
562 	ULong   dwLines, dwPixels;
563     UShort  wVCmp, wTmp;
564     pUShort pw;
565 
566     for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++) {
567 
568 		pw    = (pUShort)ps->Shade.pHilight + dwHilightOff + dwPixels;
569 		wVCmp = pwData[dwPixels] & 0xfffU;
570 
571 		for (dwLines = _DEF_BRIGHTEST_SKIP; dwLines--; pw += 5400UL) {
572 		    if (wVCmp > *pw) {
573 				wTmp  = wVCmp;
574 				wVCmp = *pw;
575 				*pw   = wTmp;
576 		    }
577 		}
578     }
579     for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++) {
580 
581 		pw    = ps->pwShadow + dwShadowOff + dwPixels;
582 		wVCmp = pwData [dwPixels] & 0xfffU;
583 
584 		for (dwLines = _DEF_DARKEST_SKIP; dwLines--; pw += 5400UL) {
585 
586 		    if (wVCmp < *pw) {
587 				wTmp  = wVCmp;
588 				wVCmp = *pw;
589 				*pw   = wTmp;
590 	    	}
591 		}
592     }
593 }
594 
595 /**
596  */
dacP98WriteBackToShadingRAM(pScanData ps)597 static void dacP98WriteBackToShadingRAM( pScanData ps )
598 {
599 	ULong   dw;
600 
601 	pUShort	pBuffer = (pUShort)ps->pScanBuffer2;
602 
603 	DBG( DBG_LOW, "dacP98WriteBackToShadingRAM()\n" );
604 
605     if (ps->DataInf.wPhyDataType >= COLOR_TRUE24) {
606 
607 		for (dw = 0; dw < 5400; dw++) {
608 
609 		    *pBuffer = ((pUShort)ps->pScanBuffer1)[dw] -
610                                             ps->Shade.DarkOffset.Colors.Red;
611 			dacP98GainResize( pBuffer,
612                               ps->Shade.pCcdDac->GainResize.Colors.Red );
613 		    pBuffer ++;
614 
615 		    *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400] -
616                                             ps->Shade.DarkOffset.Colors.Green;
617 			dacP98GainResize( pBuffer,
618                               ps->Shade.pCcdDac->GainResize.Colors.Green );
619 		    pBuffer ++;
620 
621 		    *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400 * 2] -
622                                              ps->Shade.DarkOffset.Colors.Blue;
623 			dacP98GainResize( pBuffer,
624                               ps->Shade.pCcdDac->GainResize.Colors.Blue );
625 		    pBuffer ++;
626 		}
627 
628     } else {
629 		for (dw = 0; dw < 5400; dw++) {
630 
631 			DataType Data;
632 			Byte	 bTemp;
633 
634 		    *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400] -
635                                             ps->Shade.DarkOffset.Colors.Green;
636 
637 		    Data.wValue = (*pBuffer) * 16;
638 		    bTemp = Data.wOverlap.b1st;
639 	    	Data.wOverlap.b1st = Data.wOverlap.b2nd;
640 		    Data.wOverlap.b2nd = bTemp;
641 		    *pBuffer = Data.wValue;
642 		    pBuffer++;
643 		}
644 
645     }
646 	dacP98DownloadShadingTable( ps, ps->pScanBuffer2, (5400 * 2 * 3));
647 }
648 
649 /**
650  */
dacP98ShadingRunLoop(pScanData ps)651 static void dacP98ShadingRunLoop( pScanData ps )
652 {
653 	int		    i;
654 	DataPointer p;
655 
656     p.pb = ps->a_nbNewAdrPointer;
657 
658     switch( ps->IO.portMode ) {
659 	case _PORT_SPP:
660 	case _PORT_BIDI:
661 	    *p.pw++ = 0;
662 	    for (i = 0; i < 7; i++)
663 			*p.pdw++ = 0x00800700;
664 	    *p.pw = 0;
665 	    break;
666 
667 	default:
668 	    *p.pb++ = 0;
669 	    for (i = 0; i < 15; i++)
670 			*p.pw++ = 0xf888;
671 	    *p.pb = 0;
672     }
673 
674 	IOSetToMotorRegister( ps );
675 }
676 
677 /**
678  */
dacP98Adjust12BitShading(pScanData ps)679 static void dacP98Adjust12BitShading( pScanData ps )
680 {
681 	DataPointer pd, pt;
682     ULong		dw, dw1, dwLoop;
683 
684 	DBG( DBG_LOW, "dacP98Adjust12BitShading()\n" );
685 
686     memset( ps->pScanBuffer1, 0, (5400 * 4 * 3));
687 
688     if( ps->Shade.pHilight && (_Shading_32Times == ps->bShadingTimeFlag)) {
689 
690 		memset( ps->Shade.pHilight, 0, (ps->dwHilight * 2UL));
691 
692 		for (dw = 0; dw < ps->dwShadow; dw++)
693 		    ps->pwShadow[dw] = 0xfff;
694     }
695 
696 	/*
697 	 * in the original code this function does not exist !
698 	 * (of course the code behind the function does ;-)
699 	 */
700 	dacP98SetAdjustShadingRegister( ps );
701 
702     dacP98ShadingRunLoop( ps );
703     _DODELAY( 24 );
704 
705     if ((ps->DataInf.dwScanFlag & SCANDEF_TPA ) ||
706 	  	(_Shading_32Times == ps->bShadingTimeFlag)) {
707 		dwLoop = 32;
708 	} else {
709 		if (_Shading_16Times == ps->bShadingTimeFlag) {
710 		   dwLoop = 16;
711 		} else {
712 		   dwLoop = 4;
713 		}
714     }
715 
716     for (dw1 = 0; dw1 < dwLoop; dw1++) {
717 
718         ps->Scan.bFifoSelect = ps->RegGFifoOffset;
719 
720 		dacP98ReadShadingScanLine( ps );
721 
722 		if((_Shading_32Times == ps->bShadingTimeFlag) && ps->Shade.pHilight ) {
723 
724 		    dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2, 0, 0 );
725 	    	dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2 +
726 												  ps->dwShadingPixels,
727 						       	     ps->dwHilightCh, ps->dwShadowCh );
728 
729 		    dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2 +
730 												  ps->dwShadingPixels * 2,
731 							       	  ps->dwHilightCh * 2, ps->dwShadowCh * 2);
732 		}
733 
734 	    /* SumAdd12BitShadingR */
735 		pd.pw  = (pUShort)ps->pScanBuffer2;
736 		pt.pdw = (pULong)(ps->pScanBuffer1 + dwADCPipeLine);
737 
738 		for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++)
739 		    *pt.pdw += (ULong)(*pd.pw & 0x0fff);
740 
741 	    /* SumAdd10BitShadingG */
742 		if( ps->bSetScanModeFlag & _ScanMode_AverageOut )
743 		    pd.pw = (pUShort)(ps->pScanBuffer2 + 2700 * 2);
744 		else
745 		    pd.pw = (pUShort)(ps->pScanBuffer2 + 5400 * 2);
746 
747 		pt.pdw = (pULong)(ps->pScanBuffer1 + 5400 * 4 + dwADCPipeLine);
748 
749 		for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++)
750 	    	*pt.pdw += (ULong)(*pd.pw & 0x0fff);
751 
752 	    /* SumAdd12BitShadingB */
753 		if( ps->bSetScanModeFlag & _ScanMode_AverageOut )
754 		    pd.pw = (pUShort)(ps->pScanBuffer2 + 2700 * 4);
755 		else
756 	    	pd.pw = (pUShort)(ps->pScanBuffer2 + 5400 * 4);
757 
758 		pt.pdw = (pULong)(ps->pScanBuffer1 + 5400 * 8 + dwADCPipeLine);
759 
760 		for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++)
761 		    *pt.pdw += (ULong)(*pd.pw * 94 / 100 & 0x0fff);
762 
763 		/* one line */
764 		if (IOReadFifoLength( ps ) <= 2500)
765 	    	IORegisterDirectToScanner( ps, ps->RegRefreshScanState );
766     }
767 
768     TPAP98001AverageShadingData( ps );
769 
770 	ps->OpenScanPath( ps );
771 	dacP98WriteBackToShadingRAM( ps );
772 	ps->CloseScanPath( ps );
773 }
774 
775 /**
776  */
dacP98WaitForShading(pScanData ps)777 static Bool dacP98WaitForShading( pScanData ps )
778 {
779     Byte oldLineControl;
780 
781 	DBG( DBG_LOW, "dacP98WaitForShading()\n" );
782 
783 	/*
784 	 * before getting the shading data, (re)init the ASIC
785 	 */
786     ps->InitialSetCurrentSpeed( ps );
787 	ps->ReInitAsic( ps, _TRUE );
788 
789 	IOCmdRegisterToScanner( ps, ps->RegLineControl,
790 							ps->AsicReg.RD_LineControl );
791 
792     ps->Shade.DarkOffset.Colors.Red   = 0;
793 	ps->Shade.DarkOffset.Colors.Green = 0;
794 	ps->Shade.DarkOffset.Colors.Blue  = 0;
795 
796 	/*
797 	 * according to the scan mode, switch on the lamp
798 	 */
799     IOSelectLampSource( ps );
800     IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl);
801 
802     if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) {
803 		ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi300;
804 	} else {
805 		ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi600;
806 	}
807     IOCmdRegisterToScanner( ps, ps->RegModelControl,
808 							ps->AsicReg.RD_ModelControl );
809 
810     IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeScan);
811 
812     oldLineControl = ps->AsicReg.RD_LineControl;
813 	IOSetXStepLineScanTime( ps, _DEFAULT_LINESCANTIME );
814 
815 	/* set line control */
816 	IOCmdRegisterToScanner( ps, ps->RegLineControl,
817 							ps->AsicReg.RD_LineControl );
818 
819 	/* Wait for Sensor to position */
820 	if( !ps->GotoShadingPosition( ps ))
821 		return _FALSE;
822 
823     ps->AsicReg.RD_LineControl = oldLineControl;
824     IOCmdRegisterToScanner( ps, ps->RegLineControl,
825 							ps->AsicReg.RD_LineControl );
826 
827     dwADCPipeLine = 4 * 4;
828 
829     if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) {
830 		dwReadyLen			= 2500;
831 		ps->dwShadingLen	= 2700 * 2;
832 		ps->dwShadingPixels	= 2700;
833     } else {
834 		dwReadyLen			= 5000;
835 		ps->dwShadingLen	= 5400 * 2;
836 		ps->dwShadingPixels	= 5400;
837     }
838 
839 	dacP98AdjustRGBGain		( ps );
840 	DacP98AdjustDark		( ps );
841 	dacP98Adjust12BitShading( ps );
842 
843     ps->OpenScanPath( ps );
844 	DacP98FillShadingDarkToShadingRegister( ps );
845 
846 	if ( COLOR_BW != ps->DataInf.wPhyDataType )
847 		dacP98DownloadMapTable( ps, ps->a_bMapTable );
848 
849     ps->CloseScanPath( ps );
850 
851     return _TRUE;
852 }
853 
854 /** Set RAM bank and size, then write the data to it
855  */
dacP96FillWhole4kRAM(pScanData ps,pUChar pBuf)856 static void dacP96FillWhole4kRAM( pScanData ps, pUChar pBuf )
857 {
858     ps->OpenScanPath( ps );
859 
860 	IODataToRegister( ps, ps->RegMemAccessControl,
861 		    			  ps->Asic96Reg.RD_MemAccessControl );
862 
863     ps->AsicReg.RD_ModeControl = _ModeProgram;
864     IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
865 
866     IOMoveDataToScanner( ps, pBuf, ps->ShadingBankSize );
867 
868     ps->AsicReg.RD_ModeControl = _ModeScan;
869     IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
870 
871     ps->CloseScanPath( ps );
872 }
873 
874 /**
875  */
dacP96FillChannelDarkOffset(pScanData ps)876 static void	dacP96FillChannelDarkOffset( pScanData ps )
877 {
878     ps->OpenScanPath( ps );
879 
880 	IODataToRegister( ps, ps->RegRedChDarkOffset,
881 					  ps->Asic96Reg.RD_RedChDarkOff );
882     IODataToRegister( ps, ps->RegGreenChDarkOffset,
883 					  ps->Asic96Reg.RD_GreenChDarkOff );
884     IODataToRegister( ps, ps->RegBlueChDarkOffset,
885 					  ps->Asic96Reg.RD_BlueChDarkOff );
886 
887     ps->CloseScanPath( ps );
888 }
889 
890 /**
891  */
dacP96FillEvenOddControl(pScanData ps)892 static void dacP96FillEvenOddControl( pScanData ps )
893 {
894     ps->OpenScanPath( ps );
895 
896 	IODataToRegister( ps, ps->RegRedChEvenOffset,
897 					  ps->Asic96Reg.RD_RedChEvenOff );
898 	IODataToRegister( ps, ps->RegGreenChEvenOffset,
899 					  ps->Asic96Reg.RD_GreenChEvenOff );
900 	IODataToRegister( ps, ps->RegBlueChEvenOffset,
901 					  ps->Asic96Reg.RD_BlueChEvenOff );
902 	IODataToRegister( ps, ps->RegRedChOddOffset,
903 					  ps->Asic96Reg.RD_RedChOddOff );
904 	IODataToRegister( ps, ps->RegGreenChOddOffset,
905 					  ps->Asic96Reg.RD_GreenChOddOff );
906 	IODataToRegister( ps, ps->RegBlueChOddOffset,
907 					  ps->Asic96Reg.RD_BlueChOddOff );
908 
909     ps->CloseScanPath( ps );
910 }
911 
912 /** Used for capture data to pScanData->pPrescan16.
913  *  Used to replace:
914  *	1) ReadFBKScanLine (3 * 1024, 5)
915  *	2) ReadOneScanLine (3 * 2560, 11)
916  *	4) ReadShadingScanLine (3 * 1280, 6)
917  */
dacP96ReadDataWithinOneSecond(pScanData ps,ULong dwLen,Byte bBlks)918 static void dacP96ReadDataWithinOneSecond( pScanData ps,
919 										   ULong dwLen, Byte bBlks )
920 {
921 	TimerDef timer;
922 
923     MiscStartTimer( &timer, _SECOND );
924 
925     while((IODataRegisterFromScanner( ps, ps->RegFifoOffset) < bBlks) &&
926 	   		!MiscCheckTimer(&timer));
927 
928     IOReadScannerImageData( ps, ps->pPrescan16, dwLen );
929 }
930 
931 /**
932  */
dacP96GetEvenOddOffset(pUChar pb,pWordVal pwv)933 static void dacP96GetEvenOddOffset( pUChar pb, pWordVal pwv )
934 {
935 	ULong	dw;
936     UShort	we, wo;
937 
938     for (dw = 8, we = wo = 0; dw; dw-- ) {
939 		we += *pb++;
940 		wo += *pb++;
941     }
942 
943     pwv->b1st = (Byte)(we >> 3);
944     pwv->b2nd = (Byte)(wo >> 3);
945 }
946 
947 /**
948  */
dacP96SumAverageShading(pScanData ps,pUChar pDest,pUChar pSrce)949 static void dacP96SumAverageShading( pScanData ps, pUChar pDest, pUChar pSrce )
950 {
951 	ULong  dw;
952 	UShort wLeft[6];
953 	UShort wSumL, wSumR;
954 
955     pSrce += ps->Offset70 + ps->Device.DataOriginX;
956     pDest += ps->Offset70 + ps->Device.DataOriginX;
957 
958     wLeft[0] = wLeft[1] = wLeft[2] =
959 	wLeft[3] = wLeft[4] = wLeft[5] = (UShort)*pSrce;
960 
961     wSumL = wLeft[0] * 6;
962     wSumR = (UShort)pSrce[1] + pSrce[2] + pSrce[3] + pSrce[4] +
963 		            pSrce[5] + pSrce[6];
964 
965 /*  for (dw = 2772; dw; dw--, pSrce++, pDest++) */
966     for (dw = ps->BufferSizePerModel - 6; dw; dw--, pSrce++, pDest++) {
967 
968 		*pDest = (Byte)(((UShort)*pSrce * 4 + wSumL + wSumR) / 16);
969 		wSumL  = wSumL - wLeft [0] + (UShort)*pSrce;
970 
971 		wLeft[0] = wLeft[1];
972 		wLeft[1] = wLeft[2];
973 		wLeft[2] = wLeft[3];
974 		wLeft[3] = wLeft[4];
975 		wLeft[4] = wLeft[5];
976 		wLeft[5] = (UShort)*pSrce;
977 		wSumR = wSumR - (UShort) *(pSrce + 1) + (UShort) *(pSrce + 7);
978     }
979 }
980 
981 /**
982  */
dacP96WriteLinearGamma(pScanData ps,pUChar pBuf,ULong dwEntries,Byte bBank)983 static void dacP96WriteLinearGamma( pScanData ps,
984 								    pUChar pBuf, ULong dwEntries, Byte bBank )
985 {
986 	ULong   dw;
987     pULong	pdw = (pULong)(pBuf + ps->ShadingBufferSize);
988 
989     for (dw = 0; dwEntries; pdw++, dwEntries--, dw += 0x01010101)
990 		*pdw = dw;
991 
992     ps->Asic96Reg.RD_MemAccessControl = bBank;
993 
994     dacP96FillWhole4kRAM( ps, pBuf );
995 }
996 
997 /**
998  */
dacP96FillChannelShadingOffset(pScanData ps)999 static void dacP96FillChannelShadingOffset( pScanData ps )
1000 {
1001     ps->OpenScanPath( ps );
1002 
1003 	IODataToRegister( ps, ps->RegRedChShadingOffset,
1004 					  ps->Asic96Reg.u28.RD_RedChShadingOff);
1005 	IODataToRegister( ps, ps->RegGreenChShadingOffset,
1006 					  ps->Asic96Reg.u29.RD_GreenChShadingOff);
1007 	IODataToRegister( ps, ps->RegBlueChShadingOffset,
1008 					  ps->Asic96Reg.RD_BlueChShadingOff);
1009 
1010     ps->CloseScanPath( ps );
1011 }
1012 
1013 /**
1014  */
dacP96GetHilightShadow(pScanData ps,pUChar pBuf,pUChar pChOff,pUChar pHigh)1015 static void dacP96GetHilightShadow( pScanData ps,
1016 									pUChar pBuf, pUChar pChOff, pUChar pHigh )
1017 {
1018  	ULong dw;
1019 
1020 	/* GetShadingImageExtent (ps) */
1021 	if (ps->DataInf.wAppDataType < COLOR_256GRAY)
1022 		dw = (ULong)(ps->DataInf.crImage.cx & 0xfff8);
1023 	else
1024 		dw = (ULong)ps->DataInf.crImage.cx;
1025 
1026     for( pBuf += ps->DataInf.crImage.x, *pChOff = 0xff, *pHigh = 0;
1027 		 dw; dw--, pBuf++ ) {
1028 
1029 		if (*pChOff < *pBuf) {
1030 		    if (*pHigh < *pBuf)
1031 				*pHigh = *pBuf; /* brightest */
1032 		} else
1033 		    *pChOff = *pBuf;	/* darkest */
1034     }
1035 }
1036 
1037 /**
1038  */
dacP96ReadColorShadingLine(pScanData ps)1039 static void dacP96ReadColorShadingLine( pScanData ps )
1040 {
1041     Byte	 b2ndDiscard, b3rdDiscard, b1stReadLines, b2ndReadLines;
1042     Byte	 b3rdReadLines;
1043 	ULong	 dw;
1044     DataType Data;
1045 
1046     /* ClearScanBuffer1 (ps) */
1047 	/* buffer to keep sum of data */
1048     memset( ps->pScanBuffer1, 0, ps->BufferForDataRead1 );
1049 
1050     b2ndDiscard   = ps->b2ndLinesOffset;
1051     b3rdDiscard   = ps->b1stLinesOffset;
1052     b1stReadLines = b2ndReadLines = b3rdReadLines = 8;
1053 
1054     while( _TRUE ) {
1055 
1056 		/* ReadShadingScanLine(ps) */
1057 		dacP96ReadDataWithinOneSecond( ps, ps->ShadingScanLineLen,
1058 					 				   ps->ShadingScanLineBlks );
1059 
1060 		if (b1stReadLines) {
1061 
1062 		    b1stReadLines--;
1063 
1064 	    	/* SumAdd10BitShadingR */
1065 		    for (dw = 0; dw < ps->BufferSizeBase; dw++)
1066     			((pUShort)ps->pScanBuffer1)[dw] += (UShort)ps->pPrescan16 [dw];
1067 		}
1068 
1069 		if (!b2ndDiscard) {
1070 		    if (b2ndReadLines) {
1071 				b2ndReadLines--;
1072 				/* SumAdd10BitShadingG */
1073 				for (dw = ps->BufferSizeBase;dw < (ULong)ps->BufferSizeBase * 2;dw++) {
1074 				    ((pUShort)ps->pScanBuffer1)[dw] +=
1075 													(UShort)ps->pPrescan16[dw];
1076 				}
1077 		    }
1078 		} else
1079 		    b2ndDiscard--;
1080 
1081 		if (!b3rdDiscard) {
1082 		    if (b3rdReadLines) {
1083 				b3rdReadLines--;
1084 				/* SumAdd10BitShadingB */
1085 				for (dw = ps->BufferSizeBase * 2;
1086 						dw < (ULong)ps->BufferSizeBase * 3; dw++) {
1087 				    ((pUShort)ps->pScanBuffer1)[dw] +=
1088 													(UShort)ps->pPrescan16[dw];
1089 				}
1090 		    } else
1091 				break;
1092 		} else
1093 		    b3rdDiscard--;
1094 
1095 		IORegisterDirectToScanner( ps, ps->RegRefreshScanState );
1096     }
1097 
1098     for (dw = 0; dw < (ULong)ps->BufferSizeBase * 3; dw++) {
1099 
1100 		Data.wOverlap.b1st =
1101 		Data.wOverlap.b2nd = (Byte)(((pUShort)ps->pScanBuffer1)[dw] / 8);
1102 		((pUShort)ps->pPrescan16)[dw] = Data.wValue;
1103     }
1104 }
1105 
1106 /**
1107  */
dacP96SetShadingGainProc(pScanData ps,Byte bHigh,ULong dwCh)1108 static void dacP96SetShadingGainProc( pScanData ps, Byte bHigh, ULong dwCh )
1109 {
1110 	Byte	bDark, bGain, bGainX2, bGainX4, bMask;
1111 	pUChar	pbChDark, pbSrce, pbDest;
1112 	ULong	dw;
1113 
1114     pbChDark = NULL, pbSrce = NULL, pbDest = NULL;
1115     bDark = 0, bGain = 0, bGainX2 = 0, bGainX4 = 0, bMask = 0;
1116 
1117     switch( dwCh ) {
1118 
1119 	case 0: 	/* red */
1120 	    pbChDark = &ps->Asic96Reg.u28.RD_RedChShadingOff;
1121 	    pbSrce   = ps->pPrescan16;
1122 	    pbDest   = ps->pScanBuffer1 + ps->Offset70 + ps->Device.DataOriginX;
1123 	    bGainX2  = 1;
1124 	    bGainX4  = 3;
1125 	    bMask    = 0x3c;
1126 	    break;
1127 
1128 	case 1: 	/* green */
1129 	    pbChDark = &ps->Asic96Reg.u29.RD_GreenChShadingOff;
1130 	    pbSrce   = ps->pPrescan16 + ps->BufferSizePerModel;
1131 	    pbDest   = ps->pScanBuffer1 + ps->Offset70 + ps->ShadingBankSize +
1132 				   ps->Device.DataOriginX;
1133 	    bGainX2  = 4;
1134 	    bGainX4  = 0x0c;
1135 	    bMask    = 0x33;
1136 	    break;
1137 
1138 	case 2:
1139 	    pbChDark = &ps->Asic96Reg.RD_BlueChShadingOff;
1140 	    pbSrce   = ps->pPrescan16 + ps->BufferSizePerModel * 2;
1141 	    pbDest   = ps->pScanBuffer1 + ps->Offset70 + ps->ShadingBankSize * 2 +
1142 				   ps->Device.DataOriginX;
1143 	    bGainX2  = 0x10;
1144 	    bGainX4  = 0x30;
1145 	    bMask    = 0x0f;
1146     }
1147 
1148     bDark = *pbChDark;
1149     if ((bHigh -= bDark) > 60U) {
1150 		/* Hilight - Shadow > 60, Quality not so good */
1151 		bGain = bGainX2;		/* Gain x 2 */
1152 		if (bHigh > 120U)
1153 		    bGain = bGainX4;	/* Poor quality, Gain x 4 */
1154     } else
1155 		bGain = 0;
1156 
1157     ps->Asic96Reg.RD_ShadingCorrectCtrl &= bMask;
1158     ps->Asic96Reg.RD_ShadingCorrectCtrl |= bGain;
1159 
1160     if (!bGain) {
1161 		/* GammaGain1 (ps) */
1162 		for (dw = ps->BufferSizePerModel; dw; dw--, pbSrce++, pbDest++)
1163 		    if (*pbSrce > bDark)
1164 				*pbDest = (*pbSrce - bDark) * 4;
1165 	    	else
1166 				*pbDest = 0;
1167     } else
1168 		if (bGain == bGainX2) {
1169 			/* GammaGain2 */
1170 		    for (dw = ps->BufferSizePerModel; dw; dw--, pbSrce++, pbDest++)
1171 				if (*pbSrce > bDark)
1172 				    *pbDest = (*pbSrce - bDark) * 2;
1173 				else
1174 				    *pbDest = 0;
1175 		} else {
1176 			/* GammaGain4 (ps) */
1177 			memcpy( pbDest, pbSrce, ps->BufferSizePerModel );
1178 		    *pbChDark = 0;
1179 		}
1180 }
1181 
1182 /**
1183  */
dacP96FillShadingAndGammaTable(pScanData ps)1184 static void dacP96FillShadingAndGammaTable( pScanData ps )
1185 {
1186     ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankRed;		/* R */
1187 	dacP96FillWhole4kRAM( ps, ps->pPrescan16 );
1188 
1189     ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankGreen;	/* G */
1190 	dacP96FillWhole4kRAM( ps, ps->pPrescan16 );
1191 
1192     ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankBlue;	/* B */
1193 	dacP96FillWhole4kRAM( ps, ps->pPrescan16 );
1194 }
1195 
1196 /**
1197  */
dacP96SetInitialGainRAM(pScanData ps)1198 static void dacP96SetInitialGainRAM( pScanData ps )
1199 {
1200     ULong  dw, dw1;
1201 	pULong pdw = (pULong)(ps->pPrescan16 + ps->ShadingBufferSize);
1202 
1203 	memset( ps->pPrescan16, 0xff, ps->ShadingBufferSize );
1204 
1205     for (dw = 256, dw1 = 0; dw; dw--, dw1 += 0x01010101, pdw++)
1206 		*pdw = dw1;
1207 
1208 	dacP96FillShadingAndGammaTable( ps );
1209 }
1210 
1211 /**
1212  */
dacP96Adjust10BitShading(pScanData ps)1213 static void dacP96Adjust10BitShading( pScanData ps )
1214 {
1215 	pULong	pdw;
1216 	ULong	dw;
1217 	Byte	bRedHigh, bGreenHigh, bBlueHigh;
1218 
1219     /* ShadingMotorRunLoop(ps)
1220 	 * set scan states as:
1221      *	 40h, 00, 00, 00, 40h, 01, 03, 02, ... (repeat)
1222      * so, read a R/G/B line every 2 steps
1223 	 */
1224     pdw = (pULong)ps->a_nbNewAdrPointer;
1225     for (dw = 0; dw < 4; dw++) {
1226 		*pdw++ = 0x40;
1227 		*pdw++ = 0x02030140;
1228 	}
1229 
1230     dacP96SetInitialGainRAM( ps);	/* initiates the shading buffers and maps */
1231 
1232     /* SetAdjustShadingRegister(ps) */
1233     /* Prepare Physical/2 dpi, 8.5" scanning condition for reading the shading area */
1234     ps->AsicReg.RD_ScanControl    = ps->bLampOn | _SCAN_BYTEMODE;
1235     ps->Asic96Reg.RD_MotorControl = ps->IgnorePF | ps->MotorOn |
1236 									_MotorDirForward;
1237     ps->AsicReg.RD_ModelControl   = ps->Device.ModelCtrl | _ModelWhiteIs0;
1238     ps->AsicReg.RD_Dpi    		  = ps->PhysicalDpi / 2;
1239     ps->AsicReg.RD_Origin 		  = (UShort)(ps->Offset70 +
1240                                              ps->Device.DataOriginX);
1241     ps->AsicReg.RD_Pixels 		  = ps->BufferSizeBase;
1242     IOPutOnAllRegisters( ps );
1243 
1244     ps->Asic96Reg.RD_ShadingCorrectCtrl = _ShadingRCorrectX4|_ShadingGCorrectX4|
1245 									      _ShadingBCorrectX4;
1246 	IOCmdRegisterToScanner( ps, ps->RegShadingCorrectCtrl,
1247 						 			    ps->Asic96Reg.RD_ShadingCorrectCtrl );
1248 
1249     /* Read shaded data and do average */
1250 	dacP96ReadColorShadingLine( ps );
1251 
1252     /* ExpandAndAverage (ps) ------------------------------------------------*/
1253 /*
1254 	 for (dw = 0; dw < 1280 * 3; dw++)
1255    {
1256 	Data.wOverlap.b1st =
1257 	Data.wOverlap.b2nd = (Byte)(((pUShort) ps->pScanBuffer1)[dw] / 8);
1258 	((pULong) ps->pPrescan16)[dw] = Data.wValue;
1259   }
1260 */
1261 	/* CalculateShadingOffset (ps); */
1262     dacP96GetHilightShadow( ps, ps->pPrescan16,
1263 						&ps->Asic96Reg.u28.RD_RedChShadingOff, &bRedHigh );
1264 
1265     dacP96GetHilightShadow( ps, ps->pPrescan16 + ps->BufferSizePerModel,
1266 			      &ps->Asic96Reg.u29.RD_GreenChShadingOff, &bGreenHigh );
1267 
1268     dacP96GetHilightShadow( ps, ps->pPrescan16 + ps->BufferSizePerModel * 2,
1269 				      &ps->Asic96Reg.RD_BlueChShadingOff, &bBlueHigh );
1270 
1271 	/* SubTheImageDataBase (ps) */
1272 	dacP96SetShadingGainProc( ps, bRedHigh,   0 );	/* red	 */
1273 	dacP96SetShadingGainProc( ps, bGreenHigh, 1 );	/* green */
1274 	dacP96SetShadingGainProc( ps, bBlueHigh,  2 );	/* blue	 */
1275 	dacP96FillChannelShadingOffset( ps );
1276 
1277 	IOCmdRegisterToScanner( ps, ps->RegShadingCorrectCtrl,
1278 						    ps->Asic96Reg.RD_ShadingCorrectCtrl );
1279 
1280 	dacP96SumAverageShading( ps, ps->pPrescan16, ps->pScanBuffer1 );
1281 	dacP96SumAverageShading( ps, ps->pPrescan16 + ps->ShadingBankSize,
1282 			  			     ps->pScanBuffer1 + ps->ShadingBankSize );
1283 	dacP96SumAverageShading( ps, ps->pPrescan16 + ps->ShadingBankSize * 2,
1284 					         ps->pScanBuffer1 + ps->ShadingBankSize * 2 );
1285 
1286     /* --------------------------------------------------------------------- */
1287 
1288     /* PrewriteBackToGammaShadingRAM( ps) */
1289     dacP96WriteLinearGamma( ps, ps->pPrescan16, 256, ps->ShadingBankRed );
1290    	dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize, 256,
1291 							ps->ShadingBankGreen );
1292    	dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize * 2,
1293     					    256, ps->ShadingBankBlue );
1294 }
1295 
1296 /**
1297  */
dacP96003WaitForShading(pScanData ps)1298 static Bool dacP96003WaitForShading( pScanData ps )
1299 {
1300 	int 		bCorrectTimes;
1301 	DataPointer	p;
1302     ULong		dw;
1303     UShort		w;
1304     WordVal 	wv;
1305 	pUChar		pbReg[3];
1306     Byte		b[3];
1307 
1308 	DBG( DBG_LOW, "dacP96003WaitForShading()\n" );
1309 
1310     /* TurnOnLamp () */
1311 	ps->AsicReg.RD_ScanControl |= ps->bLampOn;
1312 	IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl);
1313 
1314 	ps->Asic96Reg.RD_LedControl = _LedActControl | _LedMotorActEnable;
1315 	IOCmdRegisterToScanner(ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl);
1316 
1317     if ( ps->GotoShadingPosition( ps )) {
1318 
1319     	/* AdjustRGBGain () =================================================*/
1320 		ps->Asic96Reg.RD_RedGainOut  = ps->Asic96Reg.RD_GreenGainOut =
1321 		ps->Asic96Reg.RD_BlueGainOut = 8;
1322 		ps->Asic96Reg.u26.RD_ModelControl2 = _Model2DirectOutPort;
1323 
1324 		IOCmdRegisterToScanner(ps, ps->RegModelControl2, _Model2DirectOutPort);
1325 
1326 		for ( bCorrectTimes = 4; bCorrectTimes >= 1; bCorrectTimes-- ) {
1327 
1328 			ps->PauseColorMotorRunStates( ps );
1329 
1330 			/* SetRGBGainRegister () ----------------------------------------*/
1331 		    ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE;
1332 		    dacP96SetInitialGainRAM( ps );
1333 
1334 		    /* SetInitialGainRegister () ++++++++++++++++++++++++++++++++++++*/
1335 		    ps->Asic96Reg.u28.RD_RedChShadingOff	=
1336 			ps->Asic96Reg.u29.RD_GreenChShadingOff	=
1337 		    ps->Asic96Reg.RD_BlueChShadingOff		=
1338 		    ps->Asic96Reg.RD_RedChDarkOff		 	=
1339 		    ps->Asic96Reg.RD_GreenChDarkOff			=
1340 		    ps->Asic96Reg.RD_BlueChDarkOff			=
1341 		    ps->Asic96Reg.RD_RedChEvenOff			=
1342 		    ps->Asic96Reg.RD_GreenChEvenOff			=
1343 		    ps->Asic96Reg.RD_BlueChEvenOff			=
1344 		    ps->Asic96Reg.RD_RedChOddOff			=
1345 		    ps->Asic96Reg.RD_GreenChOddOff			=
1346 		    ps->Asic96Reg.RD_BlueChOddOff			= 0;
1347 		    ps->Asic96Reg.RD_ShadingCorrectCtrl = _ShadingRCorrectX4 |
1348 					 					    	  _ShadingGCorrectX4 |
1349 											      _ShadingBCorrectX4;
1350 
1351 			dacP96FillChannelShadingOffset( ps );
1352 		    dacP96FillChannelDarkOffset( ps );
1353 			dacP96FillEvenOddControl( ps );
1354 
1355 		    /* FillGainOutDirectPort (); */
1356 			ps->OpenScanPath( ps );
1357 			IODataToRegister( ps, ps->RegRedGainOutDirect,
1358 							  ps->Asic96Reg.RD_RedGainOut );
1359 			IODataToRegister( ps, ps->RegGreenGainOutDirect,
1360 							  ps->Asic96Reg.RD_GreenGainOut );
1361 			IODataToRegister( ps, ps->RegBlueGainOutDirect,
1362 							  ps->Asic96Reg.RD_BlueGainOut );
1363 
1364 		    /* FillGainInitialRestRegister (); */
1365 		    IODataToRegister( ps, ps->RegModelControl2,
1366 							  ps->Asic96Reg.u26.RD_ModelControl2 );
1367 			IODataToRegister( ps, ps->RegThresholdGapControl,
1368 			 			      ps->AsicReg.RD_ThresholdGapCtrl );
1369 			IODataToRegister( ps, ps->RegLedControl,
1370 							  ps->Asic96Reg.RD_LedControl );
1371 
1372 		    IODataToRegister( ps, ps->RegShadingCorrectCtrl,
1373 						      ps->Asic96Reg.RD_ShadingCorrectCtrl );
1374 
1375 			ps->CloseScanPath( ps );
1376 
1377 		    ps->Asic96Reg.RD_MotorControl = 0;
1378 			IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
1379 
1380 			ps->AsicReg.RD_ModeControl    = _ModeScan;
1381 			ps->AsicReg.RD_ScanControl    = ps->bLampOn | _SCAN_BYTEMODE;
1382 			ps->Asic96Reg.RD_MotorControl = (ps->IgnorePF |
1383 										     ps->MotorOn | _MotorDirForward);
1384 
1385 			ps->AsicReg.RD_Origin       = 142;
1386 			ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0;
1387             ps->AsicReg.RD_Dpi          = ps->PhysicalDpi;
1388 			ps->AsicReg.RD_Pixels       = ps->BufferSizePerModel;
1389 
1390 			IOPutOnAllRegisters( ps );
1391 
1392 			/*---------------------------------------------------------------*/
1393 
1394 		    /* ReadOneScanLine (); */
1395 		    dacP96ReadDataWithinOneSecond( ps, ps->OneScanLineLen, 11 );
1396 
1397 			/* AdjustGain () */
1398 			/*	FindTheMaxGain (), AdjustGainOutData (); */
1399 
1400 		    pbReg[0] = &ps->Asic96Reg.RD_RedGainOut;
1401 		    pbReg[1] = &ps->Asic96Reg.RD_GreenGainOut;
1402 	    	pbReg[2] = &ps->Asic96Reg.RD_BlueGainOut;
1403 
1404 		    for (w = 0, p.pb = ps->pPrescan16; w < 3; w++) {
1405 /* CHANGE: org was:	for (dw = 2560, b[w] = 0; dw; dw--, p.pb++) { */
1406 				for (dw = (ps->OneScanLineLen/3), b[w] = 0; dw; dw--, p.pb++) {
1407 
1408 				    if (b[w] < *p.pb)
1409 						b[w] = *p.pb;
1410 				}
1411 
1412 				if (b[w] < _GAIN_LOW)
1413 				    *(pbReg[w]) += a_bCorrectTimesTable[bCorrectTimes - 1];
1414 				else
1415 				    if (b[w] > _GAIN_P96_HIGH)
1416 						*(pbReg[w]) -= a_bCorrectTimesTable[bCorrectTimes - 1];
1417 		    }
1418 		}
1419 
1420     	/*===================================================================*/
1421 
1422 	    /* SonyFBK ()/ToshibaFBK ()====================================*/
1423 		/*FillRGBDarkLevel0Table (); */
1424 		memset( ps->pPrescan16, 0xff, ps->ShadingBankSize );
1425 
1426 		for( dw = 0, p.pb = ps->pPrescan16 + ps->ShadingBufferSize;
1427                                     		    dw <=255; dw++, p.pb++ ) {
1428 		    *p.pb = (Byte) dw;
1429 		}
1430 
1431 		dacP96FillShadingAndGammaTable( ps );
1432 
1433 		ps->PauseColorMotorRunStates( ps );
1434 
1435 		/* SetReadFBKRegister () */
1436 		ps->Asic96Reg.RD_MotorControl = 0;
1437 		IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
1438 
1439 		ps->AsicReg.RD_ModeControl    = _ModeScan;
1440 		ps->AsicReg.RD_ScanControl    = ps->bLampOn | _SCAN_BYTEMODE;
1441 		ps->Asic96Reg.RD_MotorControl = ps->IgnorePF | ps->MotorOn |
1442 								        _MotorDirForward;
1443 
1444 		ps->AsicReg.RD_Origin       = 22;
1445 		ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0;
1446         ps->AsicReg.RD_Dpi          = ps->PhysicalDpi;
1447 		ps->AsicReg.RD_Pixels       = ps->FBKScanLineLenBase;
1448 
1449 		IOPutOnAllRegisters( ps );
1450 
1451 		/* ReadFBKScanLine () */
1452 		dacP96ReadDataWithinOneSecond( ps, ps->FBKScanLineLen,
1453 													   ps->FBKScanLineBlks );
1454 
1455 	    /*===================================================================*/
1456 		if ( ps->fSonyCCD ) {
1457 
1458 		    /* FillChannelDarkLevelControl (); */
1459 		    for ( p.pb = ps->pPrescan16 + 32, w = 0, dw = 16;
1460 				  dw; dw--, p.pb++) {
1461 				  w += (UShort) *p.pb;
1462 			}
1463 
1464 		    ps->Asic96Reg.RD_RedChDarkOff = (Byte)(w / 16);
1465 
1466 		    for ( p.pb = ps->pPrescan16 + 32 + ps->FBKScanLineLenBase, w = 0, dw = 16;
1467 				  dw; dw--, p.pb++ ) {
1468 				w += (UShort)*p.pb;
1469 			}
1470 
1471 			ps->Asic96Reg.RD_GreenChDarkOff = (Byte)(w / 16);
1472 
1473 	    	for ( p.pb = ps->pPrescan16 + 32 + ps->FBKScanLineLenBase * 2, w = 0, dw = 16;
1474 				  dw; dw--,	p.pb++) {
1475 				w += (UShort)*p.pb;
1476 			}
1477 
1478 		    ps->Asic96Reg.RD_BlueChDarkOff = (Byte)(w / 16);
1479 
1480 		    dacP96FillChannelDarkOffset( ps );
1481 
1482 		} else {
1483 
1484 		    /* FillToshibaDarkLevelControl (); */
1485 			dacP96GetEvenOddOffset( ps->pPrescan16 + 32, &wv );
1486 		    ps->Asic96Reg.RD_RedChEvenOff = wv.b1st;
1487 		    ps->Asic96Reg.RD_RedChOddOff  = wv.b2nd;
1488 
1489 			dacP96GetEvenOddOffset( ps->pPrescan16 + 32 + ps->FBKScanLineLenBase, &wv );
1490 		    ps->Asic96Reg.RD_GreenChEvenOff = wv.b1st;
1491 		    ps->Asic96Reg.RD_GreenChOddOff = wv.b2nd;
1492 
1493 			dacP96GetEvenOddOffset( ps->pPrescan16 + 32 + ps->FBKScanLineLenBase * 2, &wv );
1494 			ps->Asic96Reg.RD_BlueChEvenOff = wv.b1st;
1495 			ps->Asic96Reg.RD_BlueChOddOff  = wv.b2nd;
1496 
1497 			dacP96FillEvenOddControl( ps );
1498 		}
1499 
1500 		/*	SetInitialGainRAM (); */
1501 		dacP96Adjust10BitShading( ps );
1502 
1503 		return _TRUE;
1504     }
1505 
1506     return _FALSE;
1507 }
1508 
1509 /**
1510  */
dacP96001ToSetShadingAddress(pScanData ps,pUChar pData)1511 static void dacP96001ToSetShadingAddress( pScanData ps, pUChar pData )
1512 {
1513     ps->OpenScanPath( ps );
1514 
1515     IODataToRegister( ps, ps->RegMemAccessControl,
1516 											ps->Asic96Reg.RD_MemAccessControl);
1517 
1518     ps->AsicReg.RD_ModeControl = _ModeProgram;
1519     IODataToRegister( ps, ps->RegModeControl, _ModeProgram );
1520 
1521     ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward;
1522     IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl);
1523 
1524     memset( ps->pScanBuffer1, 0, (64 + 8 + ps->Offset70));
1525   	memcpy( ps->pScanBuffer1 + 64 + 8 + ps->Offset70, pData,
1526     												_BUF_SIZE_BASE_CONST * 2 );
1527 
1528     IOMoveDataToScanner( ps, ps->pScanBuffer1,
1529 							_BUF_SIZE_BASE_CONST * 2 + 64 + 8 + ps->Offset70 );
1530 
1531     ps->AsicReg.RD_ModeControl = _ModeScan;
1532     IODataToRegister( ps, ps->RegModeControl, _ModeScan );
1533 
1534     ps->CloseScanPath( ps );
1535 }
1536 
1537 /**
1538  */
dacP96001WriteBackToColorShadingRam(pScanData ps)1539 static void dacP96001WriteBackToColorShadingRam( pScanData ps )
1540 {
1541     ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3a);
1542     dacP96001ToSetShadingAddress( ps, ps->pPrescan16 );
1543 
1544     ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3e);
1545     dacP96001ToSetShadingAddress( ps, ps->pPrescan16 + _BUF_SIZE_BASE_CONST*2);
1546 
1547     ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3c);
1548     dacP96001ToSetShadingAddress( ps, ps->pPrescan16 + _BUF_SIZE_BASE_CONST*4);
1549 }
1550 
1551 /**
1552  */
dacP96001ModifyShadingColor(pByte pData,Byte bMul)1553 static void dacP96001ModifyShadingColor( pByte pData, Byte bMul )
1554 {
1555     UShort w;
1556 	ULong  dw;
1557 
1558     for ( dw = 0; dw < _BUF_SIZE_BASE_CONST * 2; dw++ ) {
1559 
1560 		w = (UShort)(Byte)(~pData[dw]) * bMul / 100U;
1561 
1562 		if (w >= 255U)
1563 	    	pData[dw] = 0;
1564 		else
1565 		    pData[dw] = (Byte)~w;
1566     }
1567 }
1568 
1569 /**
1570  */
dacP96001FBKReading(pScanData ps,Byte bValue,Byte bReg,pByte pbSave,Bool bFBKModify)1571 static Byte dacP96001FBKReading( pScanData ps, Byte bValue,
1572 								 Byte bReg, pByte pbSave, Bool bFBKModify )
1573 {
1574     TimerDef timer;
1575     UShort	 w, wSum;
1576     Byte	 addrSeq[8] = { 0x40, 0x20, 0x10, 0x08, 4, 2, 1, 0 };
1577     Byte	 bTemp, bFBKTemp, bFBKIndex;
1578 
1579     if( bFBKModify ) {
1580 		bFBKIndex = 3;
1581 		bFBKTemp = *pbSave;
1582     } else {
1583 		bFBKTemp = 0x80;
1584 		bFBKIndex = 0;
1585     }
1586 
1587     while( _TRUE ) {
1588 
1589 		*pbSave = bFBKTemp;
1590 		IOCmdRegisterToScanner( ps, bReg, bFBKTemp );
1591 
1592 		/* SetColorRunTable (BYTE) */
1593 		memset( ps->a_nbNewAdrPointer, bValue, _SCANSTATE_BYTES );
1594 		MotorSetConstantMove( ps, 0 );
1595 
1596 		/* SetReadFBK (pScanData) */
1597 		ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward;
1598 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1599 										ps->Asic96Reg.RD_MotorControl );
1600 
1601 		ps->AsicReg.RD_ModeControl  = _ModeScan;
1602 		ps->AsicReg.RD_ScanControl  = _SCAN_BYTEMODE | ps->bLampOn;
1603 		ps->AsicReg.RD_ModelControl =
1604 					(_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0 );
1605 
1606 		ps->AsicReg.RD_Dpi    = 300;
1607 		ps->AsicReg.RD_Origin = 22;
1608 		ps->AsicReg.RD_Pixels = 1024;
1609 		IOPutOnAllRegisters( ps );
1610 
1611 		ps->Asic96Reg.RD_MotorControl =
1612 						  	   (ps->FullStep | ps->MotorOn | _MotorDirForward);
1613 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1614 											   ps->Asic96Reg.RD_MotorControl );
1615 
1616 		MiscStartTimer( &timer, _SECOND );
1617 		while((IODataRegisterFromScanner( ps, ps->RegFifoOffset) < 1) &&
1618 													!MiscCheckTimer( &timer ));
1619 
1620 		IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
1621 		IOReadScannerImageData( ps, ps->pScanBuffer1, 64 );
1622 
1623 		for( w = 26, wSum = 0; w < 42; w++)
1624 		    wSum += ps->pScanBuffer1[w];
1625 
1626 		wSum >>= 4;
1627 		bTemp = addrSeq[bFBKIndex++];
1628 
1629 		if( bTemp ) {
1630 		    if( wSum < 0xfe )
1631 				bFBKTemp += bTemp;
1632 		    else
1633 				bFBKTemp -= bTemp;
1634 		} else {
1635 		    return bFBKTemp;
1636 		}
1637     }
1638 }
1639 
1640 /**
1641  */
dacP96001WaitForShading(pScanData ps)1642 static Bool dacP96001WaitForShading( pScanData ps )
1643 {
1644 	Bool   bFBKModify;
1645     Byte   bRSave;
1646     Byte   bGSave;
1647     Byte   bBSave;
1648     ULong  dw;
1649     pULong pdw;
1650 
1651 	DBG( DBG_LOW, "dacP96001WaitForShading()\n" );
1652 
1653     ps->AsicReg.RD_ScanControl |= ps->bLampOn;
1654     IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl);
1655 
1656     if ( ps->GotoShadingPosition( ps )) {
1657 
1658 		_DODELAY( 250 );
1659 
1660 	    /* AdjustMostWideOffset70 (pScanData) -------------------------------*/
1661 		/* FillABitGray (pScanData)*/
1662 		memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1663 		ps->a_nbNewAdrPointer[8]  =
1664 		ps->a_nbNewAdrPointer[24] = 0x30;
1665 
1666 		MotorSetConstantMove( ps, 32 );
1667 
1668 		/* SetMaxWideRegister (pScanData) */
1669 		ps->AsicReg.RD_ModeControl = _ModeScan;
1670 		ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE | ps->bLampOn;
1671 
1672 		ps->Asic96Reg.RD_MotorControl =
1673  							  (ps->MotorOn | ps->IgnorePF | _MotorDirForward);
1674 		ps->AsicReg.RD_ModelControl =
1675 					  (_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0);
1676 
1677 		ps->AsicReg.RD_Dpi    = 300;
1678 		ps->AsicReg.RD_Origin = 64 + 8;
1679 		ps->AsicReg.RD_Pixels = 2700;
1680 		IOPutOnAllRegisters( ps );
1681 
1682 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1683                                 ps->Asic96Reg.RD_MotorControl );
1684 
1685 		/* ReadMaxWideLine */
1686 		dacP96ReadDataWithinOneSecond( ps, 2700, 5 );
1687 
1688 	    /* AdjustOffset70Proc (pScanData)------------------------------------*/
1689 		{
1690 		    ULong dwSum, dw, dwLeft, dwCenter;
1691 
1692 		    /* AverageWideBank (pScanData) */
1693 		    for( dwSum = 0, dw = 0; dw < 2700; dw++ )
1694 				dwSum += (ULong)ps->pPrescan16[dw];
1695 
1696 			dwSum /= 2700UL;
1697 
1698 		    if( dwSum <= 0x80 ) {
1699 
1700 				memcpy( ps->pScanBuffer1, ps->pPrescan16, 140 );
1701 				memcpy( ps->pScanBuffer1 + 140,
1702        						ps->pPrescan16 + _BUF_SIZE_BASE_CONST * 2, 140);
1703 
1704 				/* BlackOffsetCheck (pScanData) */
1705 				for( dw = dwLeft = 0; dw < 140; dw++ ) {
1706 				    if( ps->pScanBuffer1[dw] >= 0xe0 )
1707 						dwLeft++;
1708 				    else
1709 						break;
1710 				}
1711 
1712 				/* WhiteOffsetCheck (pScanData) */
1713 				for( dw = 140, dwCenter = 0; dw < 280; dw++ ) {
1714 				    if( ps->pScanBuffer1[dw] < 0xe0 )
1715 						dwCenter++;
1716 				    else
1717 						break;
1718 				}
1719 
1720 				if (dwLeft) {
1721 				    ps->Offset70 = (dwLeft + dwCenter) / 2 + 14;
1722 				} else {
1723 				    if (dwCenter == 140)
1724 						ps->Offset70 = 70;
1725 		    		else
1726 						ps->Offset70 = dwCenter / 2 + 2;
1727 				}
1728 	    	}
1729 		}
1730 
1731 		memset( ps->pPrescan16, 0, ps->BufferSizePerModel * 3 );
1732 		dacP96001WriteBackToColorShadingRam( ps );
1733 
1734 		/* SetFBK */
1735 		if((IODataRegisterFromScanner(ps, ps->RegReadIOBufBus) & 0x0f) == 0x0f)
1736 	    	bFBKModify = 0;
1737 		else
1738 		    bFBKModify = 1;
1739 
1740 		dacP96001FBKReading(ps, 0x10, ps->RegRedDCAdjust,  &bRSave,bFBKModify);
1741 		dacP96001FBKReading(ps, 0x30, ps->RegGreenDCAdjust,&bGSave,bFBKModify);
1742 		dacP96001FBKReading(ps, 0x20, ps->RegBlueDCAdjust, &bBSave,bFBKModify);
1743 
1744 		ps->OpenScanPath( ps );
1745 		IODataToRegister( ps, ps->RegRedDCAdjust,   (Byte)(bRSave + 2));
1746 		IODataToRegister( ps, ps->RegGreenDCAdjust, (Byte)(bGSave + 2));
1747 		IODataToRegister( ps, ps->RegBlueDCAdjust,  bBSave);
1748 		ps->CloseScanPath( ps );
1749 
1750 		/* Turn off and then turn on motor */
1751 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1752 				         (Byte)(ps->Asic96Reg.RD_MotorControl & ~ps->MotorOn));
1753 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1754 											   ps->Asic96Reg.RD_MotorControl );
1755 
1756 		/* FillABitColor (pScanData) */
1757 		pdw = (pULong)ps->a_nbNewAdrPointer;
1758 		for( dw = 0; dw < 4; dw++) {
1759 		    *pdw++ = 0x40;
1760 		    *pdw++ = 0x2030140;
1761 		}
1762 
1763 		IOSetToMotorRegister( ps );
1764 
1765 		/* SetShadingRegister (pScanData) */
1766 		ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward;
1767 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1768 												ps->Asic96Reg.RD_MotorControl );
1769 		ps->AsicReg.RD_ModeControl    = _ModeScan;
1770 		ps->AsicReg.RD_LineControl    = ps->TimePerLine;
1771 		ps->AsicReg.RD_ScanControl    = _SCAN_BYTEMODE | ps->bLampOn;
1772 		ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward;
1773 
1774 		ps->AsicReg.RD_ModelControl =
1775 						(_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0);
1776 		ps->AsicReg.RD_Dpi    = 150;
1777 		ps->AsicReg.RD_Origin = (UShort)(64 + 8 + ps->Offset70);
1778 		ps->AsicReg.RD_Pixels = ps->BufferSizeBase;
1779 		IOPutOnAllRegisters( ps );
1780 
1781 		IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1782 					    (Byte)(ps->MotorOn | ps->IgnorePF | _MotorDirForward));
1783 
1784 		dacP96ReadColorShadingLine( ps );
1785 
1786 		/* ModifyShadingColor (pScanData) */
1787 		dacP96001ModifyShadingColor( ps->pPrescan16, 103 );
1788 		dacP96001ModifyShadingColor( ps->pPrescan16 +
1789 											_BUF_SIZE_BASE_CONST * 2 * 2, 97);
1790 		dacP96001WriteBackToColorShadingRam( ps );
1791 		return _TRUE;
1792     }
1793     return _FALSE;
1794 }
1795 
1796 /**
1797  */
dacP98003GainOffsetToDAC(pScanData ps,Byte ch,Byte reg,Byte d)1798 static void dacP98003GainOffsetToDAC( pScanData ps, Byte ch, Byte reg, Byte d )
1799 {
1800     if( ps->Device.bDACType == _DA_SAMSUNG8531 ) {
1801 
1802     	IODataToRegister( ps, ps->RegADCAddress, 0 );
1803     	IODataToRegister( ps, ps->RegADCData, ch );
1804     	IODataToRegister( ps, ps->RegADCSerialOutStr, ch);
1805     }
1806 
1807     IODataToRegister( ps, ps->RegADCAddress, reg );
1808     IODataToRegister( ps, ps->RegADCData, d );
1809     IODataToRegister( ps, ps->RegADCSerialOutStr, d );
1810 }
1811 
1812 /**
1813  */
dacP98003AdjustRGBGain(pScanData ps)1814 static void dacP98003AdjustRGBGain( pScanData ps )
1815 {
1816     ULong i;
1817     Byte  bHi[3];
1818 
1819     DBG( DBG_LOW, "dacP98003AdjustRGBGain()\n" );
1820 
1821     ps->Shade.Gain.Colors.Red   =
1822     ps->Shade.Gain.Colors.Green =
1823     ps->Shade.Gain.Colors.Blue  =  ps->Shade.bUniGain;
1824 
1825     ps->Shade.Hilight.Colors.Red   =
1826     ps->Shade.Hilight.Colors.Green =
1827     ps->Shade.Hilight.Colors.Blue  = 0;
1828 
1829     ps->Shade.bGainHigh = _GAIN_P98003_HIGH;
1830     ps->Shade.bGainLow  = _GAIN_P98003_LOW;
1831 
1832     ps->Shade.fStop = _FALSE;
1833 
1834     for( i = 10; i-- && !ps->Shade.fStop; ) {
1835 
1836         ps->Shade.fStop = _TRUE;
1837 
1838         /* SetRGBGainRegister () */
1839         IODataToRegister( ps, ps->RegModeControl, _ModeIdle );
1840 
1841         ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE;
1842         IOSelectLampSource( ps );
1843     	IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
1844 
1845         DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain );
1846 
1847         ps->AsicReg.RD_ModeControl   = _ModeScan;
1848         ps->AsicReg.RD_StepControl   = _MOTOR0_SCANSTATE;
1849         ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR;
1850 
1851     	if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
1852 	        ps->AsicReg.RD_Origin = (UShort)ps->Device.DataOriginX >> 1;
1853     	else
1854 	        ps->AsicReg.RD_Origin = (UShort)ps->Device.DataOriginX;
1855 
1856         ps->AsicReg.RD_Dpi    = 300;
1857         ps->AsicReg.RD_Pixels = 2560;
1858 
1859     	/* PauseColorMotorRunStates () */
1860     	memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1861 	    ps->a_nbNewAdrPointer[1] = 0x77;
1862 
1863 	    IOPutOnAllRegisters( ps );
1864 
1865     	_DODELAY( 70 );
1866 
1867         /* read one shading line and work on it */
1868 	    if( IOReadOneShadingLine( ps, (pUChar)ps->Bufs.b1.pShadingRam, 2560)) {
1869 
1870         	if ( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) {
1871 
1872         		bHi[1] = DacP98003SumGains(
1873                                  (pUChar)ps->Bufs.b1.pShadingRam + 2560, 2560);
1874 		        if( bHi[1] )
1875         		    DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] );
1876 		        else {
1877         		    ps->Shade.fStop = _FALSE;
1878 		        }
1879     	    } else {
1880         		bHi[0] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam, 2560);
1881 		        bHi[1] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam + 2560, 2560);
1882         		bHi[2] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam + 5120, 2560);
1883 
1884 		        if (!bHi[0] || !bHi[1] || !bHi[2] ) {
1885         		    ps->Shade.fStop = _FALSE;
1886 		        } else {
1887         		    DacP98003AdjustGain( ps, _CHANNEL_RED,   bHi[0] );
1888         		    DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] );
1889         		    DacP98003AdjustGain( ps, _CHANNEL_BLUE,  bHi[2] );
1890 		        }
1891     	    }
1892 	    } else
1893     	    ps->Shade.fStop = _FALSE;
1894     }
1895 
1896 #ifdef DEBUG
1897     if( !ps->Shade.fStop )
1898         DBG( DBG_LOW, "dacP98003AdjustRGBGain() - all loops done!!!\n" );
1899 #endif
1900 
1901     DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain );
1902 }
1903 
1904 /**
1905  */
dacP98003SumDarks(pScanData ps,pUShort data)1906 static UShort dacP98003SumDarks( pScanData ps, pUShort data )
1907 {
1908     UShort i, loop;
1909 
1910     if( ps->Device.bCCDID == _CCD_3799 ) {
1911     	if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
1912     	    data += 0x18;
1913 	    else
1914 	        data += 0x30;
1915     } else {
1916     	if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
1917 	        data += 0x18;
1918     	else
1919 	        data += 0x20;
1920     }
1921 
1922     for( i = 0, loop = 16; loop--; data++ )
1923     	i += *data;
1924     i >>= 4;
1925 
1926     return i;
1927 }
1928 
1929 /**
1930  */
dacP98003AdjustShadingWaveform(pScanData ps)1931 static void dacP98003AdjustShadingWaveform( pScanData ps )
1932 {
1933     Byte	       b;
1934     UShort         count, wR, wG, wB, tmp;
1935     DataType       var;
1936     DataPointer    pvar, psum;
1937     RBGPtrDef      cp;
1938     pRGBUShortDef  pRGB, pwsum;
1939 
1940     DBG( DBG_LOW, "dacP98003AdjustShadingWaveForm()\n" );
1941 
1942     memset( &cp, 0, sizeof(RBGPtrDef));
1943     memset( ps->Bufs.b2.pSumBuf, 0, (5400 * 3 * 2));
1944 
1945     /* SetAdjustShadingRegister () */
1946     IODataToRegister( ps, ps->RegModeControl, _ModeIdle );
1947 
1948     ps->AsicReg.RD_LineControl    = _LOBYTE(ps->Shade.wExposure);
1949     ps->AsicReg.RD_ExtLineControl = _HIBYTE(ps->Shade.wExposure);
1950     IODataToRegister( ps, ps->RegExtendedLineControl,
1951                       ps->AsicReg.RD_ExtLineControl );
1952     IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl );
1953 
1954     ps->AsicReg.RD_XStepTime    = _LOBYTE(ps->Shade.wExposure);
1955     ps->AsicReg.RD_ExtXStepTime = _HIBYTE(ps->Shade.wExposure);
1956     IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime );
1957     IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime );
1958 
1959     ps->AsicReg.RD_ModeControl   = _ModeScan;
1960     ps->AsicReg.RD_StepControl   = _MOTOR0_SCANSTATE;
1961     ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR;
1962 
1963    	if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) {
1964 
1965     	ps->AsicReg.RD_Dpi     = 300;
1966     	ps->AsicReg.RD_Pixels  = 2700;
1967     	ps->Shade.shadingBytes = 2700 * 2;
1968     } else {
1969     	ps->AsicReg.RD_Dpi     = 600;
1970     	ps->AsicReg.RD_Pixels  = 5400;
1971     	ps->Shade.shadingBytes = 5400 * 2;
1972     }
1973     ps->AsicReg.RD_Origin = _SHADING_BEGINX;
1974 
1975     for( pvar.pdw = (pULong)ps->a_nbNewAdrPointer,
1976          var.dwValue = _SCANSTATE_BYTES >> 2; var.dwValue--; pvar.pdw++) {
1977     	*pvar.pdw = 0x00f00080;
1978     }
1979 
1980     ps->Scan.fRefreshState = _FALSE;
1981     IOPutOnAllRegisters( ps );
1982     _DODELAY( 55 );
1983 
1984     /* SetupHilightShadow () */
1985     if( ps->Shade.pHilight ) {
1986 
1987         memset( ps->Shade.pHilight, 0,
1988     	        ps->Shade.shadingBytes * ps->Shade.skipHilight * 3 );
1989 
1990         memset((pUChar)ps->Shade.pHilight +
1991                 ps->Shade.shadingBytes * ps->Shade.skipHilight * 3, 0xff,
1992 			    ps->Shade.shadingBytes * ps->Shade.skipShadow * 3 );
1993     }
1994 
1995 
1996     for( count = 32; count--;) {
1997 
1998         IOReadOneShadingLine( ps,
1999                              ((pUChar)ps->Bufs.b1.pShadingRam)+_SHADING_BEGINX,
2000 	                                                     ps->Shade.shadingBytes );
2001 
2002 	    /* SaveHilightShadow() */
2003     	if( ps->Shade.pHilight ) {
2004 
2005            	if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2006 
2007         		cp.red.usp   = ps->Bufs.b1.pShadingRam + _SHADING_BEGINX;
2008 		        cp.green.usp = cp.red.usp   + ps->AsicReg.RD_Pixels;
2009         		cp.blue.usp  = cp.green.usp + ps->AsicReg.RD_Pixels;
2010 		        pvar.pusrgb = (pRGBUShortDef)ps->Shade.pHilight +
2011                                                          _SHADING_BEGINX;
2012 
2013         		for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2014                                                               var.dwValue--;) {
2015         		    pRGB = pvar.pusrgb++;
2016 		            wR = *cp.red.usp;
2017         		    wG = *cp.green.usp;
2018 		            wB = *cp.blue.usp;
2019 
2020         		    for( b = ps->Shade.skipHilight; b--;
2021                                                pRGB += ps->AsicReg.RD_Pixels) {
2022 
2023             			if( wR > pRGB->Red ) {
2024             			    tmp = wR;
2025 			                wR  = pRGB->Red;
2026             			    pRGB->Red = tmp;
2027 			            }
2028             			if( wG > pRGB->Green ) {
2029             			    tmp = wG;
2030 			                wG  = pRGB->Green;
2031             			    pRGB->Green = tmp;
2032 			            }
2033             			if( wB > pRGB->Blue ) {
2034             			    tmp = wB;
2035 			                wB  = pRGB->Blue;
2036             			    pRGB->Blue = tmp;
2037 			            }
2038         		    }
2039 
2040         		    wR = *cp.red.usp++;
2041 		            wG = *cp.green.usp++;
2042         		    wB = *cp.blue.usp++;
2043 		            for(b = ps->Shade.skipShadow; b--;
2044                                                pRGB += ps->AsicReg.RD_Pixels) {
2045 
2046             			if (wR < pRGB->Red) {
2047             			    tmp = wR;
2048 			                wR  = pRGB->Red;
2049             			    pRGB->Red = tmp;
2050 			            }
2051             			if (wG < pRGB->Green) {
2052             			    tmp = wG;
2053 			                wG  = pRGB->Green;
2054             			    pRGB->Green = tmp;
2055 			            }
2056             			if (wB < pRGB->Blue) {
2057             			    tmp = wB;
2058 			                wB  = pRGB->Blue;
2059             			    pRGB->Blue = tmp;
2060 			            }
2061         		    }
2062     	        }
2063 
2064     	    } else {
2065 
2066         		cp.green.usp = ps->Bufs.b1.pShadingRam +
2067                                ps->AsicReg.RD_Pixels + _SHADING_BEGINX;
2068         		cp.blue.usp  = (pUShort) ps->Shade.pHilight + _SHADING_BEGINX;
2069 
2070         		for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2071                                                               var.dwValue--;) {
2072         		    cp.red.usp = cp.blue.usp++;
2073 		            wG = *cp.green.usp;
2074         		    for( b = ps->Shade.skipHilight; b--;
2075 	                                    cp.red.usp += ps->AsicReg.RD_Pixels) {
2076             			if( wG > *cp.red.usp ) {
2077             			    tmp = wG;
2078 			                wG  = *cp.red.usp;
2079             			    *cp.red.usp = tmp;
2080 			            }
2081         		    }
2082 		            wG = *cp.green.usp++;
2083         		    for (b = ps->Shade.skipShadow; b--;
2084                   		                cp.red.usp += ps->AsicReg.RD_Pixels) {
2085             			if( wG < *cp.red.usp ) {
2086             			    tmp = wG;
2087 			                wG  = *cp.red.usp;
2088             			    *cp.red.usp = tmp;
2089 			            }
2090         		    }
2091 		        }
2092     	    }
2093 	    }
2094 
2095     	/* AddToSumBuffer() */
2096        	if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2097 
2098     	    cp.red.usp   = ps->Bufs.b1.pShadingRam + _SHADING_BEGINX;
2099 	        cp.green.usp = cp.red.usp   + ps->AsicReg.RD_Pixels;
2100 	        cp.blue.usp  = cp.green.usp + ps->AsicReg.RD_Pixels;
2101 
2102     	    pvar.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2103 
2104 	        for( var.dwValue = (ULong)ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2105      	         var.dwValue--;
2106                  pvar.pulrgb++, cp.red.usp++, cp.green.usp++, cp.blue.usp++) {
2107         		pvar.pulrgb->Red   += (ULong)*cp.red.usp;
2108 		        pvar.pulrgb->Green += (ULong)*cp.green.usp;
2109         		pvar.pulrgb->Blue  += (ULong)*cp.blue.usp;
2110 	        }
2111 
2112     	} else {
2113 
2114     	    cp.green.usp = ps->Bufs.b1.pShadingRam + ps->AsicReg.RD_Pixels +
2115                                                                _SHADING_BEGINX;
2116 	        pvar.pdw  = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2117 	        for(var.dwValue = (ULong)ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2118                             	    var.dwValue--; pvar.pdw++, cp.green.usp++) {
2119 		        *pvar.pdw += (ULong)*cp.green.usp;
2120     	    }
2121         }
2122 
2123    	    if( IOReadFifoLength( ps ) < ps->AsicReg.RD_Pixels )
2124            IORegisterToScanner( ps, ps->RegRefreshScanState );
2125     }
2126 
2127     /* AverageAfterSubHilightShadow() */
2128     if( ps->Shade.pHilight ) {
2129 
2130         if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2131 
2132       	    psum.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2133 	        pwsum       = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2134 	        pvar.pusrgb = (pRGBUShortDef)ps->Shade.pHilight + _SHADING_BEGINX;
2135 
2136       	    for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2137                                                               var.dwValue--;) {
2138            		pRGB = pvar.pusrgb++;
2139 
2140 	            for( b = ps->Shade.skipHilight + ps->Shade.skipShadow;
2141                                         b--; pRGB += ps->AsicReg.RD_Pixels ) {
2142 
2143            		    psum.pulrgb->Red   -= (ULong)pRGB->Red;
2144     	            psum.pulrgb->Green -= (ULong)pRGB->Green;
2145            		    psum.pulrgb->Blue  -= (ULong)pRGB->Blue;
2146 	            }
2147 
2148            		pwsum->Red   = (UShort)(psum.pulrgb->Red   / ps->Shade.dwDiv);
2149     	        pwsum->Green = (UShort)(psum.pulrgb->Green / ps->Shade.dwDiv);
2150            		pwsum->Blue  = (UShort)(psum.pulrgb->Blue  / ps->Shade.dwDiv);
2151        	    	psum.pulrgb++;
2152 	            pwsum++;
2153    	        }
2154         } else {
2155        	    cp.green.ulp = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2156             cp.blue.usp  = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2157    	        pvar.pw      = (pUShort)ps->Shade.pHilight  + _SHADING_BEGINX;
2158 
2159        	    for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2160                                                               var.dwValue--;) {
2161            		cp.red.usp = pvar.pw++;
2162 
2163     	        for( b = ps->Shade.skipHilight + ps->Shade.skipShadow;
2164                                      b--; cp.red.usp += ps->AsicReg.RD_Pixels )
2165    		            *cp.green.ulp -= *cp.red.usp;
2166 
2167            		*cp.blue.usp = (UShort)(*cp.green.ulp / ps->Shade.dwDiv);
2168            		cp.blue.usp++;
2169 	            cp.green.ulp++;
2170        	    }
2171         }
2172     } else {
2173        	if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2174 
2175    	        psum.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf  + _SHADING_BEGINX;
2176             pwsum       = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2177 
2178    	        for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2179                                                               var.dwValue--;) {
2180            		pwsum->Red   = (UShort)(psum.pulrgb->Red   >> 5);
2181     	        pwsum->Green = (UShort)(psum.pulrgb->Green >> 5);
2182            		pwsum->Blue  = (UShort)(psum.pulrgb->Blue  >> 5);
2183 	            psum.pulrgb++;
2184        		    pwsum++;
2185        	    }
2186         } else {
2187    	        cp.green.ulp = (pULong)ps->Bufs.b2.pSumBuf  + _SHADING_BEGINX;
2188             cp.blue.usp  = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2189 
2190    	        for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2191                                                               var.dwValue--;) {
2192            		*cp.blue.usp = (UShort)(*cp.green.ulp >> 5);
2193            		cp.blue.usp++;
2194        	    	cp.green.ulp++;
2195        	    }
2196         }
2197     }
2198 
2199     /* Process negative & transparency here */
2200     if( ps->DataInf.dwScanFlag & SCANDEF_TPA )
2201    	    TPAP98003FindCenterPointer( ps );
2202 
2203     if( ps->DataInf.dwScanFlag & SCANDEF_Negative )
2204 		TPAP98003Reshading( ps );
2205 
2206     pRGB = (pRGBUShortDef)&ps->Shade.pCcdDac->GainResize;
2207 
2208    	if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2209 
2210         	pwsum = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2211 
2212        	    for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2213                                                             var.dwValue--;) {
2214 
2215   	        if ((short)(pwsum->Red -= ps->Shade.DarkOffset.Colors.Red) > 0) {
2216        	    	pwsum->Red = pwsum->Red * pRGB->Red / 100U;
2217 	            if( pwsum->Red > 0xfff )
2218        		        pwsum->Red = 0xfff;
2219        	    } else
2220                	pwsum->Red = 0;
2221 
2222        	    if((short)(pwsum->Green -= ps->Shade.DarkOffset.Colors.Green) > 0) {
2223                	pwsum->Green = pwsum->Green * pRGB->Green / 100U;
2224            	    if( pwsum->Green > 0xfff )
2225                	    pwsum->Green = 0xfff;
2226            	} else
2227                	pwsum->Green = 0;
2228 
2229        	    if ((short)(pwsum->Blue -= ps->Shade.DarkOffset.Colors.Blue) > 0) {
2230            	    pwsum->Blue = pwsum->Blue * pRGB->Blue / 100U;
2231                	if( pwsum->Blue > 0xfff )
2232     	            pwsum->Blue = 0xfff;
2233            	} else
2234                	pwsum->Blue = 0;
2235 
2236            	wR = (UShort)(pwsum->Red >> 4);
2237          	pwsum->Red <<= 12;
2238    	        pwsum->Red |= wR;
2239             wR = (UShort)(pwsum->Green >> 4);
2240        	    pwsum->Green <<= 12;
2241    	        pwsum->Green |= wR;
2242        	    wR = (UShort)(pwsum->Blue>> 4);
2243        	    pwsum->Blue <<= 12;
2244    	        pwsum->Blue |= wR;
2245        	    pwsum++;
2246        	}
2247    } else {
2248 
2249        	cp.green.usp = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX;
2250 
2251    	    for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX;
2252                                                             var.dwValue--;) {
2253 
2254    	        if((short)(*cp.green.usp -= ps->Shade.DarkOffset.Colors.Green) > 0) {
2255 
2256            		*cp.green.usp = *cp.green.usp * pRGB->Green / 100U;
2257            		if( *cp.green.usp > 0xfff )
2258            		    *cp.green.usp = 0xfff;
2259             } else
2260            		*cp.green.usp = 0;
2261 
2262        	    wR = (UShort)(*cp.green.usp >> 4);
2263    	        *cp.green.usp <<= 12;
2264        	    *cp.green.usp |= wR;
2265 
2266        	    cp.green.usp++;
2267         }
2268     }
2269 
2270     /* DownloadShadingAndSetDark() */
2271     dacP98DownloadShadingTable( ps, ps->Bufs.b2.pSumBuf, (5400 * 3 * 2));
2272 }
2273 
2274 /**
2275  */
dacP98003AdjustDark(pScanData ps)2276 static void dacP98003AdjustDark( pScanData ps )
2277 {
2278     ULong  i;
2279     UShort wDarks[3];
2280 
2281     DBG( DBG_LOW, "dacP98003AdjustDark()\n" );
2282 
2283     ps->Shade.DarkDAC.Colors = ps->Shade.pCcdDac->DarkDAC.Colors;
2284     ps->Shade.fStop = _FALSE;
2285 
2286     for( i = 16; i-- && !ps->Shade.fStop;) {
2287 
2288     	ps->Shade.fStop = _TRUE;
2289 
2290     	/* FillDarkToDAC() */
2291         DacP98003FillToDAC( ps, &ps->Device.RegDACOffset, &ps->Shade.DarkDAC );
2292 
2293         IODataToRegister( ps, ps->RegModeControl, _ModeIdle );
2294 
2295         ps->AsicReg.RD_ScanControl = (_SCAN_12BITMODE + _SCAN_1ST_AVERAGE);
2296         IOSelectLampSource( ps );
2297     	IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl );
2298 
2299         ps->AsicReg.RD_StepControl   = _MOTOR0_SCANSTATE;
2300         ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR;
2301 
2302         ps->AsicReg.RD_Origin = _SHADING_BEGINX;
2303         ps->AsicReg.RD_Pixels = 512;
2304 
2305     	if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
2306 	        ps->AsicReg.RD_Dpi = 300;
2307     	else
2308 	        ps->AsicReg.RD_Dpi = 600;
2309 
2310 
2311     	/* PauseColorMotorRunStates () */
2312     	memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
2313 	    ps->a_nbNewAdrPointer[1] = 0x77;
2314 
2315 	    IOPutOnAllRegisters( ps );
2316     	_DODELAY( 70 );
2317 
2318         /* read one shading line and work on it */
2319 	    if( IOReadOneShadingLine(ps, (pUChar)ps->Bufs.b1.pShadingRam, 512*2)) {
2320 
2321         	if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2322 
2323             	wDarks[0] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam );
2324                 wDarks[1] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam +
2325                                                ps->AsicReg.RD_Pixels );
2326 		        wDarks[2] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam +
2327                                                ps->AsicReg.RD_Pixels * 2UL);
2328 
2329                 if( !wDarks[0] || !wDarks[1] || !wDarks[2] ) {
2330 		            ps->Shade.fStop = _FALSE;
2331 		        } else {
2332 		            ps->Shade.DarkOffset.wColors[0] = wDarks[0];
2333 		            ps->Shade.DarkOffset.wColors[1] = wDarks[1];
2334 		            ps->Shade.DarkOffset.wColors[2] = wDarks[2];
2335 		            (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac,
2336                                                _CHANNEL_RED, wDarks[0] );
2337 		            (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac,
2338                                                _CHANNEL_GREEN, wDarks[1] );
2339         		    (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac,
2340                                                _CHANNEL_BLUE, wDarks[2] );
2341 	        	}
2342 	        } else {
2343         		wDarks[1] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam +
2344                                                ps->AsicReg.RD_Pixels );
2345         		if (!wDarks[1] )
2346         		    ps->Shade.fStop = _FALSE;
2347         		else {
2348         		    ps->Shade.DarkOffset.wColors[1] = wDarks[1];
2349 		            (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac,
2350                                                _CHANNEL_GREEN, wDarks[1] );
2351         		}
2352 	        }
2353     	} else
2354             ps->Shade.fStop = _FALSE;
2355     }
2356 
2357     /* CalculateDarkDependOnCCD() */
2358    	if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2359     	(*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_RED   );
2360     	(*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN );
2361     	(*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_BLUE  );
2362     } else
2363     	(*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN );
2364 }
2365 
2366 /**
2367  */
dacP98003WaitForShading(pScanData ps)2368 static Bool dacP98003WaitForShading( pScanData ps )
2369 {
2370     ULong i, tmp;
2371     Byte  bScanControl;
2372 
2373 	DBG( DBG_LOW, "dacP98003WaitForShading()\n" );
2374 
2375 	/*
2376 	 * before getting the shading data, (re)init the ASIC
2377 	 */
2378 	ps->ReInitAsic( ps, _TRUE );
2379 
2380     ps->Shade.DarkOffset.Colors.Red   = 0;
2381     ps->Shade.DarkOffset.Colors.Green = 0;
2382     ps->Shade.DarkOffset.Colors.Blue  = 0;
2383 
2384     IORegisterToScanner( ps, ps->RegResetMTSC );
2385 
2386     IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl);
2387     IODataToRegister( ps, ps->RegMotorDriverType,
2388                                             ps->AsicReg.RD_MotorDriverType );
2389     IODataToRegister( ps, ps->RegScanControl1,
2390                                         (_SCANSTOPONBUFFULL| _MFRC_BY_XSTEP));
2391     ps->GotoShadingPosition( ps );
2392 
2393     bScanControl = ps->AsicReg.RD_ScanControl;
2394 
2395     /* SetShadingMapForGainDark */
2396     memset( ps->Bufs.b2.pSumBuf, 0xff, (5400 * 3 * 2));
2397 
2398     /* DownloadShadingAndSetDark() */
2399     dacP98DownloadShadingTable( ps, ps->Bufs.b2.pSumBuf, (5400 * 3 * 2));
2400 
2401     for( i = 0, tmp = 0; i < 1024; tmp += 0x01010101, i += 4 ) {
2402     	ps->Bufs.b1.Buf.pdw[i]   =
2403     	ps->Bufs.b1.Buf.pdw[i+1] =
2404     	ps->Bufs.b1.Buf.pdw[i+2] =
2405     	ps->Bufs.b1.Buf.pdw[i+3] = tmp;
2406     }
2407 
2408     memcpy( ps->Bufs.b1.pShadingMap + 4096, ps->Bufs.b1.pShadingMap, 4096 );
2409     memcpy( ps->Bufs.b1.pShadingMap + 8192, ps->Bufs.b1.pShadingMap, 4096 );
2410     dacP98DownloadMapTable( ps, ps->Bufs.b1.pShadingMap );
2411 
2412     DBG( DBG_LOW, "wExposure = %u\n", ps->Shade.wExposure);
2413     DBG( DBG_LOW, "wXStep    = %u\n", ps->Shade.wXStep);
2414 
2415     ps->AsicReg.RD_LineControl    = (_LOBYTE(ps->Shade.wExposure));
2416     ps->AsicReg.RD_ExtLineControl = (_HIBYTE(ps->Shade.wExposure));
2417     IODataToRegister(ps, ps->RegExtendedLineControl,
2418                                             ps->AsicReg.RD_ExtLineControl );
2419     IODataToRegister(ps, ps->RegLineControl, ps->AsicReg.RD_LineControl );
2420 
2421     dacP98003AdjustRGBGain( ps );
2422     dacP98003AdjustDark( ps );
2423     dacP98003AdjustShadingWaveform( ps );
2424 
2425     ps->AsicReg.RD_ScanControl = bScanControl;
2426 
2427 	/* here we have to download the table in any case...*/
2428 	dacP98DownloadMapTable( ps, ps->a_bMapTable );
2429 
2430     MotorP98003BackToHomeSensor( ps );
2431 
2432     return _TRUE;
2433 }
2434 
2435 /************************ exported functions *********************************/
2436 
2437 /**
2438  */
DacInitialize(pScanData ps)2439 _LOC int DacInitialize( pScanData ps )
2440 {
2441 	DBG( DBG_HIGH, "DacInitialize()\n" );
2442 
2443 	if( NULL == ps )
2444 		return _E_NULLPTR;
2445 
2446 	/*
2447 	 * depending on the asic, we set some functions
2448 	 */
2449 	if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
2450 
2451 		ps->WaitForShading = dacP98003WaitForShading;
2452 
2453     } else if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2454 
2455 		ps->WaitForShading = dacP98WaitForShading;
2456 
2457 	} else if( _ASIC_IS_96003 == ps->sCaps.AsicID ) {
2458 
2459 		ps->WaitForShading = dacP96003WaitForShading;
2460 
2461 	} else if( _ASIC_IS_96001 == ps->sCaps.AsicID ) {
2462 
2463 		ps->WaitForShading = dacP96001WaitForShading;
2464 
2465 	} else {
2466 
2467 		DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
2468 		return _E_NOSUPP;
2469 	}
2470 	return _OK;
2471 }
2472 
2473 /** Fill out the R/G/B GainOut value
2474  */
DacP98FillGainOutDirectPort(pScanData ps)2475 _LOC void DacP98FillGainOutDirectPort( pScanData ps )
2476 {
2477 	ps->OpenScanPath( ps );
2478 
2479     IODataRegisterToDAC( ps, 0x28, ps->bRedGainIndex   );
2480     IODataRegisterToDAC( ps, 0x29, ps->bGreenGainIndex );
2481     IODataRegisterToDAC( ps, 0x2a, ps->bBlueGainIndex  );
2482 
2483 	ps->CloseScanPath( ps );
2484 }
2485 
2486 /**
2487  */
DacP98FillShadingDarkToShadingRegister(pScanData ps)2488 _LOC void DacP98FillShadingDarkToShadingRegister( pScanData ps )
2489 {
2490 	pUChar pValue;
2491 	Byte   bReg;
2492 
2493 	DBG( DBG_LOW, "DacP98FillShadingDarkToShadingRegister()\n" );
2494 
2495 	ps->AsicReg.RD_RedDarkOff   = ps->Shade.DarkOffset.Colors.Red;
2496     ps->AsicReg.RD_GreenDarkOff = ps->Shade.DarkOffset.Colors.Green;
2497     ps->AsicReg.RD_BlueDarkOff  = ps->Shade.DarkOffset.Colors.Blue;
2498 
2499     pValue = (pUChar)&ps->AsicReg.RD_RedDarkOff;
2500     for (bReg = ps->RegRedChDarkOffsetLow; bReg <= ps->RegBlueChDarkOffsetHigh;
2501 	 	 bReg++, pValue++) {
2502 
2503 		IODataToRegister( ps, bReg, *pValue );
2504 	}
2505 }
2506 
2507 /**
2508  */
DacP98AdjustDark(pScanData ps)2509 _LOC void DacP98AdjustDark( pScanData ps )
2510 {
2511 	Byte bCorrectTimes;		/* used to be a global var !*/
2512 
2513 	DBG( DBG_LOW, "DacP98AdjustDark()\n" );
2514 
2515     ps->Shade.pCcdDac->DarkDAC.Colors.Red   = ps->bsPreRedDAC;
2516     ps->Shade.pCcdDac->DarkDAC.Colors.Green = ps->bsPreGreenDAC;
2517     ps->Shade.pCcdDac->DarkDAC.Colors.Blue  = ps->bsPreBlueDAC;
2518 
2519     if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) {
2520 		bCorrectTimes = 6;
2521 	} else {
2522 		bCorrectTimes = 5;
2523 	}
2524 
2525 /* CHANGE
2526 ** original code seems to be buggy : for (bCorrectTimes ; bCorrectTimes--;) {
2527 */
2528 	for (;bCorrectTimes ; bCorrectTimes-- ) {
2529 
2530     	ps->OpenScanPath( ps );
2531   		dacP98FillDarkDAC( ps );
2532 		dacP98SetReadFBKRegister( ps );
2533        	ps->CloseScanPath( ps );
2534 
2535     	IOPutOnAllRegisters( ps );
2536 
2537 		ps->PauseColorMotorRunStates( ps );		/* stop scan states */
2538 
2539 		IOReadOneShadingLine( ps, ps->pScanBuffer1, 512*2 );
2540 
2541 		dacP98FillChannelDarkLevelControl( ps );
2542 
2543 		if(dacP98CheckChannelDarkLevel( ps ))
2544 	    	break;
2545     }
2546 
2547 	ps->Shade.DarkOffset.Colors.Red=
2548                 dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Red,
2549                                   ps->Shade.pCcdDac->DarkCmpHi.Colors.Red,
2550                                   ps->Shade.pCcdDac->DarkOffSub.Colors.Red );
2551 
2552     ps->Shade.DarkOffset.Colors.Green =
2553                 dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Green,
2554                                   ps->Shade.pCcdDac->DarkCmpHi.Colors.Green,
2555                                   ps->Shade.pCcdDac->DarkOffSub.Colors.Green );
2556 
2557     ps->Shade.DarkOffset.Colors.Blue  =
2558                 dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Blue,
2559                                   ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue,
2560                                   ps->Shade.pCcdDac->DarkOffSub.Colors.Blue );
2561 }
2562 
2563 /**
2564  */
DacP96WriteBackToGammaShadingRAM(pScanData ps)2565 _LOC void DacP96WriteBackToGammaShadingRAM( pScanData ps )
2566 {
2567 	/* ModifyGammaShadingOffset(ps) */
2568     ps->OpenScanPath( ps);
2569 
2570     IODataToRegister( ps, ps->RegRedChShadingOffset,
2571 					  ps->Asic96Reg.u28.RD_RedChShadingOff );
2572 	IODataToRegister( ps, ps->RegGreenChShadingOffset,
2573 	     (Byte)((ULong)ps->Asic96Reg.u29.RD_GreenChShadingOff * 96UL/100UL));
2574 
2575 	IODataToRegister( ps, ps->RegBlueChShadingOffset,
2576 			    (Byte)((ULong)ps->Asic96Reg.RD_BlueChShadingOff * 91UL/100UL));
2577 
2578     ps->CloseScanPath( ps );
2579 
2580 	dacP96WriteLinearGamma( ps, ps->pPrescan16, 256, ps->ShadingBankRed);
2581 	dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize,
2582            										    256, ps->ShadingBankGreen);
2583 	dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize * 2,
2584 					  					            256, ps->ShadingBankBlue);
2585 }
2586 
2587 /**
2588  */
DacP98003FillToDAC(pScanData ps,pRGBByteDef regs,pColorByte data)2589 _LOC void DacP98003FillToDAC( pScanData ps, pRGBByteDef regs, pColorByte data )
2590 {
2591    	if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) {
2592 
2593         dacP98003GainOffsetToDAC( ps, _DAC_RED, regs->Red, data->Colors.Red );
2594         dacP98003GainOffsetToDAC( ps, _DAC_GREENCOLOR,
2595                                             regs->Green, data->Colors.Green );
2596         dacP98003GainOffsetToDAC( ps, _DAC_BLUE,
2597                                             regs->Blue, data->Colors.Blue );
2598     } else {
2599         dacP98003GainOffsetToDAC( ps, _DAC_GREENMONO, regs->Green,
2600                                           			      data->Colors.Green );
2601     }
2602 }
2603 
2604 /**
2605  */
DacP98003AdjustGain(pScanData ps,ULong color,Byte hilight)2606 _LOC void DacP98003AdjustGain( pScanData ps, ULong color, Byte hilight )
2607 {
2608     if( hilight < ps->Shade.bGainLow ) {
2609 
2610         if( ps->Shade.Hilight.bColors[color] < ps->Shade.bGainHigh ) {
2611 
2612     	    ps->Shade.fStop = _FALSE;
2613     	    ps->Shade.Hilight.bColors[color] = hilight;
2614 
2615     	    if( hilight <= (Byte)(ps->Shade.bGainLow - hilight))
2616         		ps->Shade.Gain.bColors[color] += ps->Shade.bGainDouble;
2617 	        else
2618     		    ps->Shade.Gain.bColors[color]++;
2619 	    }
2620     } else {
2621     	if( hilight > ps->Shade.bGainHigh ) {
2622     	    ps->Shade.fStop = _FALSE;
2623 	        ps->Shade.Hilight.bColors[color] = hilight;
2624     	    ps->Shade.Gain.bColors[color]--;
2625     	} else
2626     	    ps->Shade.Hilight.bColors[color] = hilight;
2627 	}
2628 
2629     if( ps->Shade.Gain.bColors[color] > ps->Shade.bMaxGain ) {
2630         ps->Shade.Gain.bColors[color] = ps->Shade.bMaxGain;
2631     }
2632 }
2633 
2634 /**
2635  */
DacP98003SumGains(pUChar pb,ULong pixelsLine)2636 _LOC Byte DacP98003SumGains( pUChar pb, ULong pixelsLine )
2637 {
2638     Byte   bHilight, tmp;
2639     ULong  dwPixels, dwAve;
2640     UShort sum;
2641 
2642     for( bHilight = 0, dwPixels = pixelsLine >> 4; dwPixels--; ) {
2643 
2644     	for( sum = 0, dwAve = 16; dwAve--; pb++)
2645 	        sum += (UShort)*pb;
2646 
2647     	sum >>= 4;
2648         tmp = (Byte)sum;
2649 
2650 	    if( tmp > bHilight )
2651 	        bHilight = tmp;
2652     }
2653     return bHilight;
2654 }
2655 
2656 /* END PLUSTEK-PP_DAC.C .....................................................*/
2657