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