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 74static const Byte a_bCorrectTimesTable[4] = {0, 1, 2, 4}; 75 76static ULong dwADCPipeLine = 4 * 4; 77static ULong dwReadyLen; 78 79/*************************** local functions *********************************/ 80 81/** 82 */ 83static 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 */ 101static 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 */ 110static 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 */ 140static 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 */ 168static 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 */ 202static 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 */ 224static 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 */ 259static 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 */ 293static 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 */ 321static 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 */ 333static 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 */ 341static 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 */ 371static 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 */ 386static 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 */ 409static 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 */ 439static 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 */ 454static 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 */ 487static 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 */ 520static 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 */ 538static 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 */ 559static 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 */ 597static 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 */ 651static 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 */ 679static 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 */ 777static 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 */ 856static 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 */ 876static 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 */ 892static 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 */ 918static 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 */ 933static 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 */ 949static 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 */ 983static 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 */ 999static 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 */ 1015static 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 */ 1039static 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 */ 1108static 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 */ 1184static 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 */ 1198static 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 */ 1213static 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 */ 1298static 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 */ 1511static 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 */ 1539static 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 */ 1553static 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 */ 1571static 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 */ 1642static 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 */ 1798static 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 */ 1814static 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 */ 1906static 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 */ 1931static 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 */ 2276static 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 */ 2368static 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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