1 /* @file u12-shading.c -
2 * @brief all the shading functions
3 *
4 * based on sources acquired from Plustek Inc.
5 * Copyright (C) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de>
6 *
7 * History:
8 * - 0.01 - initial version
9 * - 0.02 -
10 * .
11 * <hr>
12 * This file is part of the SANE package.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 *
27 * As a special exception, the authors of SANE give permission for
28 * additional uses of the libraries contained in this release of SANE.
29 *
30 * The exception is that, if you link a SANE library with other files
31 * to produce an executable, this does not by itself cause the
32 * resulting executable to be covered by the GNU General Public
33 * License. Your use of that executable is in no way restricted on
34 * account of linking the SANE library code into it.
35 *
36 * This exception does not, however, invalidate any other reasons why
37 * the executable file might be covered by the GNU General Public
38 * License.
39 *
40 * If you submit changes to SANE to the maintainers to be included in
41 * a subsequent release, you agree by submitting the changes that
42 * those changes may be distributed with this exception intact.
43 *
44 * If you write modifications of your own for SANE, it is your choice
45 * whether to permit this exception to apply to your modifications.
46 * If you do not wish that, delete this exception notice.
47 * <hr>
48 */
49
50 #define _GAIN_HIGH 240 /* Volt. max. value */
51 #define _GAIN_LOW 220 /* Volt. min. value */
52
53 #define _CHANNEL_RED 0
54 #define _CHANNEL_GREEN 1
55 #define _CHANNEL_BLUE 2
56
57 /* for DAC programming */
58 #define _VALUE_CONFIG 0x51
59 #define _DAC_RED (SANE_Byte)(_VALUE_CONFIG | 0x00)
60 #define _DAC_GREENCOLOR (SANE_Byte)(_VALUE_CONFIG | 0x04)
61 #define _DAC_GREENMONO (SANE_Byte)(_VALUE_CONFIG | 0x06)
62 #define _DAC_BLUE (SANE_Byte)(_VALUE_CONFIG | 0x08)
63
64
65 /* forward declarations ... */
66 static void u12tpa_Reshading( U12_Device * );
67 static void u12tpa_FindCenterPointer( U12_Device * );
68
69 /**
70 */
71 static void
u12shading_DownloadShadingTable( U12_Device *dev, SANE_Byte *buf, u_long len )72 u12shading_DownloadShadingTable( U12_Device *dev, SANE_Byte *buf, u_long len )
73 {
74 SANE_Byte *val, *rb;
75 SANE_Byte reg, regs[20];
76 int c;
77
78 DBG( _DBG_INFO, "u12shading_DownloadShadingTable()\n" );
79
80 u12io_DataToRegister( dev, REG_MODECONTROL, _ModeShadingMem );
81 u12io_DataToRegister( dev, REG_MEMORYLO, 0 );
82 u12io_DataToRegister( dev, REG_MEMORYHI, 0 );
83
84 /* set 12 bits output color */
85 u12io_DataToRegister( dev, REG_SCANCONTROL,
86 (SANE_Byte)(dev->regs.RD_ScanControl | _SCAN_12BITMODE));
87
88 u12io_MoveDataToScanner( dev, buf, len );
89
90 regs[0] = REG_MODECONTROL;
91 regs[1] = _ModeScan;
92
93 /* FillShadingDarkToShadingRegister() */
94 dev->regs.RD_RedDarkOff = dev->shade.DarkOffset.Colors.Red;
95 dev->regs.RD_GreenDarkOff = dev->shade.DarkOffset.Colors.Green;
96 dev->regs.RD_BlueDarkOff = dev->shade.DarkOffset.Colors.Blue;
97
98 val = (SANE_Byte*)&dev->regs.RD_RedDarkOff;
99 rb = ®s[2];
100 c = 1;
101 for( reg = REG_REDCHDARKOFFSETLO;
102 reg <= REG_BLUECHDARKOFFSETHI; reg++, val++) {
103
104 *(rb++) = reg;
105 *(rb++) = *val;
106 c++;
107 }
108 u12io_DataToRegs( dev, regs, c );
109 }
110
111 /**
112 */
u12shadingAdjustShadingWaveform( U12_Device *dev )113 static SANE_Status u12shadingAdjustShadingWaveform( U12_Device *dev )
114 {
115 SANE_Byte b;
116 u_short count, wR, wG, wB, tmp;
117 DataType var;
118 DataPointer pvar, psum;
119 RBGPtrDef cp;
120 RGBUShortDef *pRGB, *pwsum;
121 u_long shadingBytes;
122
123 DBG( _DBG_INFO, "u12shading_AdjustShadingWaveForm()\n" );
124
125 memset( &cp, 0, sizeof(RBGPtrDef));
126 memset( dev->bufs.b2.pSumBuf, 0, (5400 * 3 * 2));
127
128 u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle );
129
130 dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure);
131 dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure);
132 u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL,
133 dev->regs.RD_ExtLineControl );
134 u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl );
135
136 dev->regs.RD_XStepTime = _LOBYTE(dev->shade.wExposure);
137 dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wExposure);
138 u12io_DataToRegister( dev, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime );
139 u12io_DataToRegister( dev, REG_XSTEPTIME, dev->regs.RD_XStepTime );
140
141 dev->regs.RD_ModeControl = _ModeScan;
142 dev->regs.RD_StepControl = _MOTOR0_SCANSTATE;
143 dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
144
145 if( dev->shade.intermediate & _ScanMode_AverageOut ) {
146
147 dev->regs.RD_Dpi = 300;
148 dev->regs.RD_Pixels = 2700;
149 shadingBytes = 2700 * 2;
150 } else {
151 dev->regs.RD_Dpi = 600;
152 dev->regs.RD_Pixels = 5400;
153 shadingBytes = 5400 * 2;
154 }
155 dev->regs.RD_Origin = _SHADING_BEGINX;
156
157 for( pvar.pdw = (u_long*)dev->scanStates,
158 var.dwValue = _SCANSTATE_BYTES >> 2; var.dwValue--; pvar.pdw++) {
159 *pvar.pdw = 0x00f00080;
160 }
161
162 dev->scan.refreshState = SANE_FALSE;
163 u12io_PutOnAllRegisters( dev );
164 /* _DODELAY( 100 ); */
165
166 if( dev->shade.pHilight ) {
167
168 memset( dev->shade.pHilight, 0,
169 shadingBytes * dev->shade.skipHilight * 3 );
170
171 memset((SANE_Byte*)dev->shade.pHilight +
172 shadingBytes * dev->shade.skipHilight * 3, 0xff,
173 shadingBytes * dev->shade.skipShadow * 3 );
174 }
175
176 for( count = 32; count--; ) {
177
178 if( u12io_IsEscPressed()) {
179 DBG( _DBG_INFO, "* CANCEL detected!\n" );
180 return SANE_STATUS_CANCELLED;
181 }
182
183 u12io_ReadOneShadingLine( dev, ((SANE_Byte*)dev->bufs.b1.pShadingRam)+
184 _SHADING_BEGINX, shadingBytes );
185
186 if( dev->shade.pHilight ) {
187
188 if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
189
190 cp.red.usp = dev->bufs.b1.pShadingRam + _SHADING_BEGINX;
191 cp.green.usp = cp.red.usp + dev->regs.RD_Pixels;
192 cp.blue.usp = cp.green.usp + dev->regs.RD_Pixels;
193 pvar.pusrgb = (RGBUShortDef*)dev->shade.pHilight +
194 _SHADING_BEGINX;
195
196 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
197 var.dwValue--;) {
198 pRGB = pvar.pusrgb++;
199 wR = *cp.red.usp;
200 wG = *cp.green.usp;
201 wB = *cp.blue.usp;
202
203 for( b = dev->shade.skipHilight; b--;
204 pRGB += dev->regs.RD_Pixels ) {
205 if( wR > pRGB->Red ) {
206 tmp = wR;
207 wR = pRGB->Red;
208 pRGB->Red = tmp;
209 }
210 if( wG > pRGB->Green ) {
211 tmp = wG;
212 wG = pRGB->Green;
213 pRGB->Green = tmp;
214 }
215 if( wB > pRGB->Blue ) {
216 tmp = wB;
217 wB = pRGB->Blue;
218 pRGB->Blue = tmp;
219 }
220 }
221
222 wR = *cp.red.usp++;
223 wG = *cp.green.usp++;
224 wB = *cp.blue.usp++;
225
226 for( b = dev->shade.skipShadow; b--;
227 pRGB += dev->regs.RD_Pixels ) {
228 if( wR < pRGB->Red ) {
229 tmp = wR;
230 wR = pRGB->Red;
231 pRGB->Red = tmp;
232 }
233 if( wG < pRGB->Green ) {
234 tmp = wG;
235 wG = pRGB->Green;
236 pRGB->Green = tmp;
237 }
238 if( wB < pRGB->Blue ) {
239 tmp = wB;
240 wB = pRGB->Blue;
241 pRGB->Blue = tmp;
242 }
243 }
244 }
245 } else {
246
247 cp.green.usp = dev->bufs.b1.pShadingRam +
248 dev->regs.RD_Pixels + _SHADING_BEGINX;
249 cp.blue.usp = (u_short*)dev->shade.pHilight + _SHADING_BEGINX;
250
251 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
252 var.dwValue--;) {
253 cp.red.usp = cp.blue.usp++;
254 wG = *cp.green.usp;
255 for( b = dev->shade.skipHilight; b--;
256 cp.red.usp += dev->regs.RD_Pixels) {
257 if( wG > *cp.red.usp ) {
258 tmp = wG;
259 wG = *cp.red.usp;
260 *cp.red.usp = tmp;
261 }
262 }
263 wG = *cp.green.usp++;
264 for( b = dev->shade.skipShadow; b--;
265 cp.red.usp += dev->regs.RD_Pixels ) {
266 if( wG < *cp.red.usp ) {
267 tmp = wG;
268 wG = *cp.red.usp;
269 *cp.red.usp = tmp;
270 }
271 }
272 }
273 }
274 }
275
276 /* AddToSumBuffer() */
277 if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
278
279 cp.red.usp = dev->bufs.b1.pShadingRam + _SHADING_BEGINX;
280 cp.green.usp = cp.red.usp + dev->regs.RD_Pixels;
281 cp.blue.usp = cp.green.usp + dev->regs.RD_Pixels;
282
283 pvar.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
284
285 for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX;
286 var.dwValue--;
287 pvar.pulrgb++, cp.red.usp++, cp.green.usp++, cp.blue.usp++) {
288 pvar.pulrgb->Red += (u_long)*cp.red.usp;
289 pvar.pulrgb->Green += (u_long)*cp.green.usp;
290 pvar.pulrgb->Blue += (u_long)*cp.blue.usp;
291 }
292
293 } else {
294
295 cp.green.usp = dev->bufs.b1.pShadingRam +
296 dev->regs.RD_Pixels + _SHADING_BEGINX;
297 pvar.pdw = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
298 for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX;
299 var.dwValue--; pvar.pdw++, cp.green.usp++) {
300 *pvar.pdw += (u_long)*cp.green.usp;
301 }
302 }
303
304 u12io_ResetFifoLen();
305 if( u12io_GetFifoLength( dev ) < dev->regs.RD_Pixels )
306 u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE );
307 }
308
309 /* AverageAfterSubHilightShadow() */
310 if( dev->shade.pHilight ) {
311 if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
312
313 psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
314 pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
315 pvar.pusrgb = (RGBUShortDef*)dev->shade.pHilight + _SHADING_BEGINX;
316
317 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
318 var.dwValue--;) {
319 pRGB = pvar.pusrgb++;
320
321 for( b = dev->shade.skipHilight + dev->shade.skipShadow;
322 b--; pRGB += dev->regs.RD_Pixels ) {
323
324 psum.pulrgb->Red -= (u_long)pRGB->Red;
325 psum.pulrgb->Green -= (u_long)pRGB->Green;
326 psum.pulrgb->Blue -= (u_long)pRGB->Blue;
327 }
328
329 pwsum->Red = (u_short)(psum.pulrgb->Red / dev->shade.dwDiv);
330 pwsum->Green = (u_short)(psum.pulrgb->Green / dev->shade.dwDiv);
331 pwsum->Blue = (u_short)(psum.pulrgb->Blue / dev->shade.dwDiv);
332 psum.pulrgb++;
333 pwsum++;
334 }
335 } else {
336 cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
337 cp.blue.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
338 pvar.pw = (u_short*)dev->shade.pHilight + _SHADING_BEGINX;
339
340 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
341 var.dwValue--;) {
342 cp.red.usp = pvar.pw++;
343
344 for( b = dev->shade.skipHilight + dev->shade.skipShadow;
345 b--; cp.red.usp += dev->regs.RD_Pixels )
346 *cp.green.ulp -= *cp.red.usp;
347
348 *cp.blue.usp = (u_short)(*cp.green.ulp / dev->shade.dwDiv);
349 cp.blue.usp++;
350 cp.green.ulp++;
351 }
352 }
353 } else {
354
355 if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
356
357 psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
358 pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
359
360 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
361 var.dwValue--;) {
362 pwsum->Red = (u_short)(psum.pulrgb->Red >> 5);
363 pwsum->Green = (u_short)(psum.pulrgb->Green >> 5);
364 pwsum->Blue = (u_short)(psum.pulrgb->Blue >> 5);
365 psum.pulrgb++;
366 pwsum++;
367 }
368 } else {
369 cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
370 cp.blue.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
371
372 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
373 var.dwValue--;) {
374 *cp.blue.usp = (u_short)(*cp.green.ulp >> 5);
375 cp.blue.usp++;
376 cp.green.ulp++;
377 }
378 }
379 }
380
381 /* Process negative & transparency here */
382 if( dev->DataInf.dwScanFlag & _SCANDEF_TPA )
383 u12tpa_FindCenterPointer( dev );
384
385 if( dev->DataInf.dwScanFlag & _SCANDEF_Negative )
386 u12tpa_Reshading( dev );
387
388 pRGB = (RGBUShortDef*)&dev->shade.pCcdDac->GainResize;
389
390 if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
391
392 pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
393
394 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
395 var.dwValue--;) {
396
397 if ((short)(pwsum->Red -= dev->shade.DarkOffset.Colors.Red) > 0) {
398 pwsum->Red = pwsum->Red * pRGB->Red / 100U;
399 if( pwsum->Red > 0xfff )
400 pwsum->Red = 0xfff;
401 } else
402 pwsum->Red = 0;
403
404 if((short)(pwsum->Green -= dev->shade.DarkOffset.Colors.Green) > 0) {
405 pwsum->Green = pwsum->Green * pRGB->Green / 100U;
406 if( pwsum->Green > 0xfff )
407 pwsum->Green = 0xfff;
408 } else
409 pwsum->Green = 0;
410
411 if ((short)(pwsum->Blue -= dev->shade.DarkOffset.Colors.Blue) > 0) {
412 pwsum->Blue = pwsum->Blue * pRGB->Blue / 100U;
413 if( pwsum->Blue > 0xfff )
414 pwsum->Blue = 0xfff;
415 } else
416 pwsum->Blue = 0;
417
418 wR = (u_short)(pwsum->Red >> 4);
419 pwsum->Red <<= 12;
420 pwsum->Red |= wR;
421 wR = (u_short)(pwsum->Green >> 4);
422 pwsum->Green <<= 12;
423 pwsum->Green |= wR;
424 wR = (u_short)(pwsum->Blue>> 4);
425 pwsum->Blue <<= 12;
426 pwsum->Blue |= wR;
427 pwsum++;
428 }
429 } else {
430
431 cp.green.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX;
432
433 for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX;
434 var.dwValue--;) {
435
436 if((short)(*cp.green.usp -= dev->shade.DarkOffset.Colors.Green) > 0) {
437
438 *cp.green.usp = *cp.green.usp * pRGB->Green / 100U;
439 if( *cp.green.usp > 0xfff )
440 *cp.green.usp = 0xfff;
441 } else
442 *cp.green.usp = 0;
443
444 wR = (u_short)(*cp.green.usp >> 4);
445 *cp.green.usp <<= 12;
446 *cp.green.usp |= wR;
447
448 cp.green.usp++;
449 }
450 }
451
452 u12shading_DownloadShadingTable(dev, dev->bufs.b2.pSumBuf, (5400 * 3 * 2));
453 return SANE_STATUS_GOOD;
454 }
455
456 /**
457 */
u12shading_GainOffsetToDAC( U12_Device *dev, SANE_Byte ch, SANE_Byte reg, SANE_Byte d )458 static void u12shading_GainOffsetToDAC( U12_Device *dev, SANE_Byte ch,
459 SANE_Byte reg, SANE_Byte d )
460 {
461 if( dev->DACType == _DA_SAMSUNG8531 ) {
462 u12io_DataRegisterToDAC( dev, 0, ch );
463 }
464 u12io_DataRegisterToDAC( dev, reg, d );
465 }
466
467 /**
468 */
u12shading_FillToDAC( U12_Device *dev, RGBByteDef *regs, ColorByte *data )469 static void u12shading_FillToDAC( U12_Device *dev,
470 RGBByteDef *regs, ColorByte *data )
471 {
472 if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
473
474 u12shading_GainOffsetToDAC(dev, _DAC_RED, regs->Red, data->Colors.Red);
475 u12shading_GainOffsetToDAC(dev, _DAC_GREENCOLOR,
476 regs->Green, data->Colors.Green);
477 u12shading_GainOffsetToDAC(dev, _DAC_BLUE,
478 regs->Blue, data->Colors.Blue);
479 } else {
480 u12shading_GainOffsetToDAC(dev, _DAC_GREENMONO, regs->Green,
481 data->Colors.Green);
482 }
483 }
484
485 /**
486 */
u12shading_SumGains( SANE_Byte *pb, u_long pixelsLine )487 static SANE_Byte u12shading_SumGains( SANE_Byte *pb, u_long pixelsLine )
488 {
489 SANE_Byte hilight, tmp;
490 u_long dwPixels, dwAve;
491 u_short sum;
492
493 hilight = 0;
494 for( dwPixels = pixelsLine >> 4; dwPixels--; ) {
495
496 for( sum = 0, dwAve = 16; dwAve--; pb++ )
497 sum += (u_short)*pb;
498
499 sum >>= 4;
500 tmp = (SANE_Byte)sum;
501
502 if( tmp > hilight )
503 hilight = tmp;
504 }
505 return hilight;
506 }
507
508 /**
509 */
510 static void
u12shading_AdjustGain( U12_Device *dev, u_long color, SANE_Byte hilight )511 u12shading_AdjustGain( U12_Device *dev, u_long color, SANE_Byte hilight )
512 {
513 if( hilight < dev->shade.bGainLow ) {
514
515 if( dev->shade.Hilight.bColors[color] < dev->shade.bGainHigh ) {
516
517 dev->shade.fStop = SANE_FALSE;
518 dev->shade.Hilight.bColors[color] = hilight;
519
520 if( hilight <= (SANE_Byte)(dev->shade.bGainLow - hilight))
521 dev->shade.Gain.bColors[color] += dev->shade.bGainDouble;
522 else
523 dev->shade.Gain.bColors[color]++;
524 }
525 } else {
526 if( hilight > dev->shade.bGainHigh ) {
527 dev->shade.fStop = SANE_FALSE;
528 dev->shade.Hilight.bColors[color] = hilight;
529 dev->shade.Gain.bColors[color]--;
530 } else {
531 dev->shade.Hilight.bColors[color] = hilight;
532 }
533 }
534
535 if( dev->shade.Gain.bColors[color] > dev->shade.bMaxGain ) {
536 dev->shade.Gain.bColors[color] = dev->shade.bMaxGain;
537 }
538 }
539
540 /**
541 */
u12shading_AdjustRGBGain( U12_Device *dev )542 static SANE_Status u12shading_AdjustRGBGain( U12_Device *dev )
543 {
544 int i;
545 SANE_Byte hi[3];
546
547 DBG( _DBG_INFO, "u12shading_AdjustRGBGain()\n" );
548
549 dev->shade.Gain.Colors.Red =
550 dev->shade.Gain.Colors.Green =
551 dev->shade.Gain.Colors.Blue = dev->shade.bUniGain;
552
553 dev->shade.Hilight.Colors.Red =
554 dev->shade.Hilight.Colors.Green =
555 dev->shade.Hilight.Colors.Blue = 0;
556
557 dev->shade.bGainHigh = _GAIN_HIGH;
558 dev->shade.bGainLow = _GAIN_LOW;
559
560 dev->shade.fStop = SANE_FALSE;
561
562 for( i = 10; i-- && !dev->shade.fStop; ) {
563
564 if( u12io_IsEscPressed()) {
565 DBG( _DBG_INFO, "* CANCEL detected!\n" );
566 return SANE_STATUS_CANCELLED;
567 }
568
569 dev->shade.fStop = SANE_TRUE;
570
571 u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle );
572
573 dev->regs.RD_ScanControl = _SCAN_BYTEMODE;
574 u12hw_SelectLampSource( dev );
575 u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl );
576
577 u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain );
578
579 dev->regs.RD_ModeControl = _ModeScan;
580 dev->regs.RD_StepControl = _MOTOR0_SCANSTATE;
581 dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
582
583 if( dev->shade.intermediate & _ScanMode_AverageOut )
584 dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X >> 1;
585 else
586 dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X;
587
588 dev->regs.RD_Dpi = 300;
589 dev->regs.RD_Pixels = 2560;
590
591 memset( dev->scanStates, 0, _SCANSTATE_BYTES );
592 dev->scanStates[1] = 0x77;
593
594 u12io_PutOnAllRegisters( dev );
595 /* _DODELAY( 100 ); */
596
597 /* read one shading line and work on it */
598 if( u12io_ReadOneShadingLine( dev,
599 (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560)) {
600
601 if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) {
602
603 hi[1] = u12shading_SumGains(
604 (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560);
605 if( hi[1] ) {
606 u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] );
607 } else {
608 dev->shade.fStop = SANE_FALSE;
609 }
610 } else {
611 hi[0] = u12shading_SumGains(
612 (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560);
613 hi[1] = u12shading_SumGains(
614 (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560);
615 hi[2] = u12shading_SumGains(
616 (SANE_Byte*)dev->bufs.b1.pShadingRam + 5120, 2560);
617
618 if (!hi[0] || !hi[1] || !hi[2] ) {
619 dev->shade.fStop = SANE_FALSE;
620 } else {
621 u12shading_AdjustGain( dev, _CHANNEL_RED, hi[0] );
622 u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] );
623 u12shading_AdjustGain( dev, _CHANNEL_BLUE, hi[2] );
624 }
625 }
626 } else
627 dev->shade.fStop = SANE_FALSE;
628 }
629
630 if( !dev->shade.fStop )
631 DBG( _DBG_INFO, "u12shading_AdjustRGBGain() - all loops done!!!\n" );
632
633 u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain );
634 return SANE_STATUS_GOOD;
635 }
636
637 /**
638 */
u12shading_SumDarks( U12_Device *dev, u_short *data )639 static u_short u12shading_SumDarks( U12_Device *dev, u_short *data )
640 {
641 u_short i, loop;
642
643 if( dev->CCDID == _CCD_3799 ) {
644 if( dev->shade.intermediate & _ScanMode_AverageOut )
645 data += 0x18;
646 else
647 data += 0x30;
648 } else {
649 if( dev->shade.intermediate & _ScanMode_AverageOut )
650 data += 0x18;
651 else
652 data += 0x20;
653 }
654
655 for( i = 0, loop = 16; loop--; data++ )
656 i += *data;
657 i >>= 4;
658
659 return i;
660 }
661
662 /**
663 */
u12shadingAdjustDark( U12_Device *dev )664 static SANE_Status u12shadingAdjustDark( U12_Device *dev )
665 {
666 u_long i;
667 u_short wDarks[3];
668
669 DBG( _DBG_INFO, "u12shadingAdjustDark()\n" );
670 dev->shade.DarkDAC.Colors = dev->shade.pCcdDac->DarkDAC.Colors;
671 dev->shade.fStop = SANE_FALSE;
672
673 for( i = 16; i-- && !dev->shade.fStop;) {
674
675 if( u12io_IsEscPressed()) {
676 DBG( _DBG_INFO, "* CANCEL detected!\n" );
677 return SANE_STATUS_CANCELLED;
678 }
679
680 dev->shade.fStop = SANE_TRUE;
681
682 u12shading_FillToDAC( dev, &dev->RegDACOffset, &dev->shade.DarkDAC );
683 u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle );
684
685 dev->regs.RD_ScanControl = (_SCAN_12BITMODE + _SCAN_1ST_AVERAGE);
686 u12hw_SelectLampSource( dev );
687 u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl );
688
689 dev->regs.RD_StepControl = _MOTOR0_SCANSTATE;
690 dev->regs.RD_Motor0Control = _FORWARD_MOTOR;
691
692 dev->regs.RD_Origin = _SHADING_BEGINX;
693 dev->regs.RD_Pixels = 512;
694
695 if( dev->shade.intermediate & _ScanMode_AverageOut )
696 dev->regs.RD_Dpi = 300;
697 else
698 dev->regs.RD_Dpi = 600;
699
700 memset( dev->scanStates, 0, _SCANSTATE_BYTES );
701 dev->scanStates[1] = 0x77;
702
703 u12io_PutOnAllRegisters( dev );
704 /* _DODELAY( 100 ); */
705
706 /* read one shading line and work on it */
707 if( u12io_ReadOneShadingLine(dev,
708 (SANE_Byte*)dev->bufs.b1.pShadingRam, 512*2)) {
709
710 if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
711
712 wDarks[0] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam);
713 wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam +
714 dev->regs.RD_Pixels );
715 wDarks[2] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam +
716 dev->regs.RD_Pixels * 2UL);
717
718 if( !wDarks[0] || !wDarks[1] || !wDarks[2] ) {
719 dev->shade.fStop = SANE_FALSE;
720 } else {
721 dev->shade.DarkOffset.wColors[0] = wDarks[0];
722 dev->shade.DarkOffset.wColors[1] = wDarks[1];
723 dev->shade.DarkOffset.wColors[2] = wDarks[2];
724 (*dev->fnDACDark)( dev,dev->shade.pCcdDac,
725 _CHANNEL_RED, wDarks[0] );
726 (*dev->fnDACDark)( dev, dev->shade.pCcdDac,
727 _CHANNEL_GREEN, wDarks[1] );
728 (*dev->fnDACDark)( dev, dev->shade.pCcdDac,
729 _CHANNEL_BLUE, wDarks[2] );
730 }
731 } else {
732 wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam +
733 dev->regs.RD_Pixels );
734 if(!wDarks[1] ) {
735 dev->shade.fStop = SANE_FALSE;
736 } else {
737 dev->shade.DarkOffset.wColors[1] = wDarks[1];
738 (*dev->fnDACDark)( dev, dev->shade.pCcdDac,
739 _CHANNEL_GREEN, wDarks[1] );
740 }
741 }
742 } else {
743 dev->shade.fStop = SANE_FALSE;
744 }
745 }
746
747 /* CalculateDarkDependOnCCD() */
748 if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) {
749 (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_RED );
750 (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN );
751 (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_BLUE );
752 } else {
753 (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN );
754 }
755 return SANE_STATUS_GOOD;
756 }
757
758 /** here we download the current mapping table
759 */
u12shading_DownloadMapTable( U12_Device *dev, SANE_Byte *buf )760 static void u12shading_DownloadMapTable( U12_Device *dev, SANE_Byte *buf )
761 {
762 SANE_Byte addr, regs[6];
763 int i;
764
765 u12io_DataToRegister( dev, REG_SCANCONTROL,
766 (SANE_Byte)((dev->regs.RD_ScanControl & 0xfc) | _SCAN_BYTEMODE));
767
768 /* prepare register settings... */
769 regs[0] = REG_MODECONTROL;
770 regs[1] = _ModeMappingMem;
771 regs[2] = REG_MEMORYLO;
772 regs[3] = 0;
773 regs[4] = REG_MEMORYHI;
774
775 for( i = 3, addr = _MAP_ADDR_RED; i--; addr += _MAP_ADDR_SIZE ) {
776
777 regs[5] = addr;
778 u12io_DataToRegs( dev, regs, 3 );
779
780 u12io_MoveDataToScanner( dev, buf, 4096 );
781 buf += 4096;
782 }
783
784 u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl );
785 }
786
787 /**
788 */
u12shading_DoCalibration( U12_Device *dev )789 static SANE_Status u12shading_DoCalibration( U12_Device *dev )
790 {
791 SANE_Byte tb[4096*3];
792 u_long i, tmp;
793 SANE_Byte bScanControl, rb[20];
794 SANE_Status res;
795 int c;
796
797 DBG( _DBG_INFO, "u12shading_DoCalibration()\n" );
798
799 /** before getting the shading data, (re)init the ASIC
800 */
801 u12hw_InitAsic( dev, SANE_TRUE );
802
803 dev->shade.DarkOffset.Colors.Red = 0;
804 dev->shade.DarkOffset.Colors.Green = 0;
805 dev->shade.DarkOffset.Colors.Blue = 0;
806
807 c = 0;
808 _SET_REG( rb, c, REG_RESETMTSC, 0 );
809 _SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl);
810 _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType );
811 _SET_REG( rb, c, REG_SCANCONTROL1, (_SCANSTOPONBUFFULL| _MFRC_BY_XSTEP));
812
813 u12io_DataToRegs( dev, rb, c );
814
815 res = u12motor_GotoShadingPosition( dev );
816 if( SANE_STATUS_GOOD != res )
817 return res;
818
819 bScanControl = dev->regs.RD_ScanControl;
820
821 /* SetShadingMapForGainDark */
822 memset( dev->bufs.b2.pSumBuf, 0xff, (5400 * 3 * 2));
823 u12shading_DownloadShadingTable( dev, dev->bufs.b2.pSumBuf, (5400*3*2));
824
825 for( i = 0, tmp = 0; i < 1024; tmp += 0x01010101, i += 4 ) {
826 dev->bufs.b1.Buf.pdw[i] =
827 dev->bufs.b1.Buf.pdw[i+1] =
828 dev->bufs.b1.Buf.pdw[i+2] =
829 dev->bufs.b1.Buf.pdw[i+3] = tmp;
830 }
831
832 memcpy( dev->bufs.b1.pShadingMap + 4096, dev->bufs.b1.pShadingMap, 4096 );
833 memcpy( dev->bufs.b1.pShadingMap + 8192, dev->bufs.b1.pShadingMap, 4096 );
834 u12shading_DownloadMapTable( dev, dev->bufs.b1.pShadingMap );
835
836 DBG( _DBG_INFO, "* wExposure = %u\n", dev->shade.wExposure);
837 DBG( _DBG_INFO, "* wXStep = %u\n", dev->shade.wXStep);
838
839 dev->regs.RD_LineControl = (_LOBYTE(dev->shade.wExposure));
840 dev->regs.RD_ExtLineControl = (_HIBYTE(dev->shade.wExposure));
841 u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL,
842 dev->regs.RD_ExtLineControl );
843 u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl );
844
845 res = u12shading_AdjustRGBGain( dev );
846 if( SANE_STATUS_GOOD != res )
847 return res;
848
849 res = u12shadingAdjustDark( dev );
850 if( SANE_STATUS_GOOD != res )
851 return res;
852
853 res = u12shadingAdjustShadingWaveform( dev );
854 if( SANE_STATUS_GOOD != res )
855 return res;
856
857 dev->regs.RD_ScanControl = bScanControl;
858
859 /* here we have to prepare and download the table in any case...*/
860 if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) {
861 u12map_Adjust( dev, _MAP_MASTER, tb );
862 } else {
863 u12map_Adjust( dev, _MAP_RED, tb );
864 u12map_Adjust( dev, _MAP_GREEN, tb );
865 u12map_Adjust( dev, _MAP_BLUE, tb );
866 }
867
868 u12shading_DownloadMapTable( dev, tb );
869
870 u12motor_BackToHomeSensor( dev );
871 DBG( _DBG_INFO, "u12shading_DoCalibration() - done.\n" );
872 return SANE_STATUS_GOOD;
873 }
874
875 /* END U12-SHADING ..........................................................*/
876