1 /* @file plustek-pp_motor.c
2 * @brief all functions for motor control
3 *
4 * based on sources acquired from Plustek Inc.
5 * Copyright (C) 1998 Plustek Inc.
6 * Copyright (C) 2000-2013 Gerhard Jaeger <gerhard@gjaeger.de>
7 * also based on the work done by Rick Bronson
8 *
9 * History:
10 * - 0.30 - initial version
11 * - 0.31 - no changes
12 * - 0.32 - slight cosmetic changes
13 * - added function MotorToHomePosition()
14 * - 0.33 - added additional debug-messages
15 * - increased speed for returning to homeposition for Models >= 9630
16 * (and ASIC 96003)
17 * - 0.34 - added FIFO overflow check in motorP96SetSpeed
18 * - removed WaitBack() function from pScanData structure
19 * - removed wStayMaxStep from pScanData structure
20 * - 0.35 - changed motorP96UpdateDataCurrentReadLine() to handle proper
21 * - work of ASIC96003 based 600dpi models
22 * - 0.36 - merged motorP96WaitBack and motorP98WaitBack to motorWaitBack
23 * - merged motorP96SetSpeed and motorP98SetSpedd to motorSetSpeed
24 * - added Sensor-Check in function MotorToHomePosition
25 * - reduced number of forward steps for MotorToHomePosition
26 * - 0.37 - removed function motorP96GetStartStopGap() - no longer used
27 * - removed a_bStepDown1Table and a_bStepUp1Table
28 * - removed // comments
29 * - added A3I stuff
30 * - 0.38 - cosmetic changes
31 * - added P12 stuff
32 * - 0.39 - Did some finetuning in MotorP98003ModuleForwardBackward()
33 * - Fixed a problem, that could cause the driver to throw a
34 * kernel exception
35 * - 0.40 - changed back to build 0.39-3 (disabled A3I stuff)
36 * - 0.41 - no changes
37 * - 0.42 - changed include names
38 * - 0.43 - no changes
39 * - 0.44 - fix format string issues, as Long types default to int32_t
40 * now
41 * .
42 * <hr>
43 * This file is part of the SANE package.
44 *
45 * This program is free software; you can redistribute it and/or
46 * modify it under the terms of the GNU General Public License as
47 * published by the Free Software Foundation; either version 2 of the
48 * License, or (at your option) any later version.
49 *
50 * This program is distributed in the hope that it will be useful, but
51 * WITHOUT ANY WARRANTY; without even the implied warranty of
52 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 * General Public License for more details.
54 *
55 * You should have received a copy of the GNU General Public License
56 * along with this program. If not, see <https://www.gnu.org/licenses/>.
57 *
58 * As a special exception, the authors of SANE give permission for
59 * additional uses of the libraries contained in this release of SANE.
60 *
61 * The exception is that, if you link a SANE library with other files
62 * to produce an executable, this does not by itself cause the
63 * resulting executable to be covered by the GNU General Public
64 * License. Your use of that executable is in no way restricted on
65 * account of linking the SANE library code into it.
66 *
67 * This exception does not, however, invalidate any other reasons why
68 * the executable file might be covered by the GNU General Public
69 * License.
70 *
71 * If you submit changes to SANE to the maintainers to be included in
72 * a subsequent release, you agree by submitting the changes that
73 * those changes may be distributed with this exception intact.
74 *
75 * If you write modifications of your own for SANE, it is your choice
76 * whether to permit this exception to apply to your modifications.
77 * If you do not wish that, delete this exception notice.
78 * <hr>
79 */
80 #include "plustek-pp_scan.h"
81
82 /*************************** some definitions *********************************/
83
84 /* #define _A3I_EN */
85
86 /*
87 * adjustments for scanning in negative and tranparency mode
88 */
89 #define _NEG_SCANNINGPOS 770
90 #define _POS_SCANNINGPOS 660 /* original value was 710 */
91
92 #define _P98_BACKMOVES 0x3d
93 #define _P98_FORWARDMOVES 0x3b /* Origin = 3c */
94
95 #define _P98003_BACKSTEPS 120
96 #define _P98003_FORWARDSTEPS 120
97
98 #define _P96_BACKMOVES 130
99 #define _P96_FORWARDMOVES 87 /* 95 */
100 #define _P96_FIFOOVERFLOWTHRESH 180
101
102
103 #define _COLORRUNTABLE_RED 0x11
104 #define _COLORRUNTABLE_GREEN 0x22
105 #define _COLORRUNTABLE_BLUE 0x44
106
107 #define _BW_ORIGIN 0x0D
108 #define _GRAY_ORIGIN 0x0B
109 #define _COLOR_ORIGIN 0x0B
110
111 #define _P98003_YOFFSET 300
112
113 /**************************** local vars *************************************/
114
115 static TimerDef p98003MotorTimer;
116
117 static UShort a_wMoveStepTable [_NUMBER_OF_SCANSTEPS];
118 static Byte a_bScanStateTable[_SCANSTATE_TABLE_SIZE];
119 static Byte a_bHalfStepTable [_NUMBER_OF_SCANSTEPS];
120 static Byte a_bColorByteTable[_NUMBER_OF_SCANSTEPS];
121 static Byte a_bColorsSum[8] = {0, 1, 1, 2, 1, 2, 2, 3};
122
123 static pUShort pwEndMoveStepTable = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS;
124 static pUChar pbEndColorByteTable = a_bColorByteTable + _NUMBER_OF_SCANSTEPS;
125 static pUChar pbEndHalfStepTable = a_bHalfStepTable + _NUMBER_OF_SCANSTEPS;
126
127 /*
128 * for the 96001/3 based units
129 */
130 static UShort wP96BaseDpi = 0;
131
132 static Byte a_bStepDown1Table[20] = {3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
133 static Byte a_bStepUp1Table[20] = {4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
134 static Byte a_bMotorDown2Table[20] = {0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
135
136 #ifndef _A3I_EN
137 static Byte a_bHalfStep2Table[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
138 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
139 static Byte a_bHalfStep4Table[16] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
140 static Byte a_bHalfStep6Table[12] = {3,3,3,3,3,3,3,3,3,3,3,3};
141 static Byte a_bHalfStep8Table[8] = {4,4,4,4,4,4,4,4};
142 static Byte a_bHalfStep10Table[8] = {5,5,5,5,5,5,5,5};
143 static Byte a_bHalfStep12Table[6] = {6,6,6,6,6,6};
144 static Byte a_bHalfStep14Table[6] = {7,7,7,7,7,7};
145 static Byte a_bHalfStep16Table[4] = {8,8,8,8};
146 static Byte a_bHalfStep18Table[4] = {9,9,9,9};
147 static Byte a_bHalfStep20Table[4] = {10,10,10,10};
148 static Byte a_bHalfStep22Table[4] = {11,11,11,11};
149 static Byte a_bHalfStep24Table[4] = {12,12,12,12};
150 static Byte a_bHalfStep26Table[4] = {13,13,13,13};
151 static Byte a_bHalfStep28Table[4] = {14,14,14,14};
152 static Byte a_bHalfStep30Table[4] = {15,15,15,15};
153 static Byte a_bHalfStep32Table[2] = {16,16};
154 static Byte a_bHalfStep34Table[2] = {17,17};
155 static Byte a_bHalfStep36Table[2] = {18,18};
156 static Byte a_bHalfStep38Table[2] = {19,19};
157 static Byte a_bHalfStep40Table[2] = {20,20};
158
159
160 static pUChar a_pbHalfStepTables[20] = {
161 a_bHalfStep2Table, a_bHalfStep4Table,
162 a_bHalfStep6Table, a_bHalfStep8Table,
163 a_bHalfStep10Table, a_bHalfStep12Table,
164 a_bHalfStep14Table, a_bHalfStep16Table,
165 a_bHalfStep18Table, a_bHalfStep20Table,
166 a_bHalfStep22Table, a_bHalfStep24Table,
167 a_bHalfStep26Table, a_bHalfStep28Table,
168 a_bHalfStep30Table, a_bHalfStep32Table,
169 a_bHalfStep34Table, a_bHalfStep36Table,
170 a_bHalfStep38Table, a_bHalfStep40Table
171 };
172 #endif
173
174 /*************************** local functions *********************************/
175
176 /*.............................................................................
177 *
178 */
motorP96GetStartStopGap(pScanData ps,Bool fCheckState)179 static void motorP96GetStartStopGap( pScanData ps, Bool fCheckState )
180 {
181 UChar bMotorCountDownIndex;
182
183 if( fCheckState ) {
184
185 ps->bMotorStepTableNo = 0xff;
186 if( ps->Scan.bModuleState == _MotorInNormalState )
187 return;
188 }
189
190 bMotorCountDownIndex = ps->bMotorSpeedData / 2;
191
192 if( ps->bCurrentSpeed == 4 && ps->AsicReg.RD_Dpi < 80 )
193 ps->bMotorStepTableNo = 4;
194 else
195 if( ps->Scan.bModuleState == _MotorGoBackward )
196 ps->bMotorStepTableNo = a_bStepUp1Table[bMotorCountDownIndex];
197 else
198 ps->bMotorStepTableNo = a_bStepDown1Table[bMotorCountDownIndex];
199 }
200
201
202
203 /*.............................................................................
204 * wait for the ScanState stop or ScanState reaches the dwScanStateCount
205 */
motorCheckMotorPresetLength(pScanData ps)206 static Bool motorCheckMotorPresetLength( pScanData ps )
207 {
208 Byte bScanState;
209 TimerDef timer;
210
211 MiscStartTimer( &timer, (_SECOND * 4));
212 do {
213
214 bScanState = IOGetScanState( ps, _FALSE );
215
216 if (ps->fFullLength) {
217 if (!(bScanState & _SCANSTATE_STOP)) /* still running */
218 if ((ULong)(bScanState & _SCANSTATE_MASK) != ps->dwScanStateCount )
219 continue;
220 return ps->fFullLength;
221 }
222
223 if (bScanState & _SCANSTATE_STOP)
224 break;
225
226 /*
227 * the code may work for all units
228 */
229 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
230
231 if (bScanState < ps->bOldStateCount)
232 bScanState += _NUMBER_OF_SCANSTEPS;
233
234 bScanState -= ps->bOldStateCount;
235
236 if (bScanState >= 40)
237 return ps->fFullLength;
238 }
239
240 } while ( !MiscCheckTimer( &timer ));
241
242 _DODELAY(1); /* delay one ms */
243
244 return ps->fFullLength;
245 }
246
247 /*.............................................................................
248 * 1) Keep the valid content of a_bColorByteTable, and fill others to 0:
249 * BeginFill = ((bCurrentLineCount + DL) < 64) ? bCurrentLineCount + DL :
250 * bCurrentLineCount + DL - 64;
251 * FillLength = 64 - DL
252 * [NOTE] Keep the content of a_bColorByteTable that begin at
253 * bCurrentLineCount and in DL bytes
254 * 2) Keep the valid content of a_bHalfStepTable, and fill the others to 0:
255 * BeginFill = ((bCurrentLineCount + bCurrentSpeed / 2 + 1) < 64) ?
256 * bCurrentLineCount + bCurrentSpeed / 2 + 1 :
257 * bCurrentLineCount + bCurrentSpeed / 2 + 1 - 64;
258 * FillLength = 64 - (bMotorSpeedData / 2 + 1);
259 */
motorClearColorByteTableLoop0(pScanData ps,Byte bColors)260 static void motorClearColorByteTableLoop0( pScanData ps, Byte bColors )
261 {
262 ULong dw;
263 pUChar pb;
264
265 if ((ps->bCurrentLineCount + bColors) >= _NUMBER_OF_SCANSTEPS) {
266 pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors -
267 _NUMBER_OF_SCANSTEPS);
268 } else {
269 pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors);
270 }
271
272 for (dw = _NUMBER_OF_SCANSTEPS - bColors; dw; dw--) {
273
274 *pb++ = 0;
275 if (pb >= pbEndColorByteTable)
276 pb = a_bColorByteTable;
277 }
278
279 if ((ps->bCurrentLineCount+ps->bCurrentSpeed/2+1) >= _NUMBER_OF_SCANSTEPS) {
280
281 pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount +
282 ps->bCurrentSpeed / 2 + 1 - _NUMBER_OF_SCANSTEPS);
283 } else {
284 pb = a_bHalfStepTable +
285 (ULong)(ps->bCurrentLineCount + ps->bCurrentSpeed / 2 + 1);
286 }
287
288 for (dw = _NUMBER_OF_SCANSTEPS - ps->bMotorSpeedData / 2 - 1; dw; dw--) {
289 *pb++ = 0;
290 if (pb >= pbEndHalfStepTable)
291 pb = a_bHalfStepTable;
292 }
293 }
294
295 /*.............................................................................
296 * motorClearColorByteTableLoop1 ()
297 * 1) Adjust bNewGap:
298 * bNewGap = (bNewGap <= bNewCurrentLineCountGap) ?
299 * 0 : bNewGap - bNewCurrentLineCount - 1;
300 * 2) Fill the 0 to a_bColorByteTable:
301 * FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ?
302 * bCurrentLineCount + bNewGap + 1 :
303 * bCurrentLineCount + bNewGap + 1 - 64;
304 * FillCount = 64 - bNewGap - 1;
305 * 3) Adjust bNewGap:
306 * bNewGap = (bCurrentLineCount <= bNewCurrentLineCountGap) ?
307 * 0 : bNewGap - bNewCurrentLineCount - 1;
308 * 4) Fill the a_bHalfStepTable:
309 * FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ?
310 * bCurrentLineCount + bNewGap + 1 :
311 * bCurrentLineCount + bNewGap + 1 - 64;
312 * FillCount = 64 - bNewGap - 1;
313 */
motorClearColorByteTableLoop1(pScanData ps)314 static void motorClearColorByteTableLoop1( pScanData ps )
315 {
316 ULong dw = _NUMBER_OF_SCANSTEPS - 1;
317 pUChar pb;
318
319 if (ps->bNewGap > ps->bNewCurrentLineCountGap) {
320 ps->bNewGap = ps->bNewGap - ps->bNewCurrentLineCountGap - 1;
321 dw -= (ULong)ps->bNewGap;
322 } else {
323 ps->bNewGap = 0;
324 }
325
326 if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) {
327 pb = a_bColorByteTable +
328 (ULong)(ps->bCurrentLineCount+ps->bNewGap+1-_NUMBER_OF_SCANSTEPS);
329 } else {
330 pb = a_bColorByteTable +
331 (ULong)(ps->bCurrentLineCount + ps->bNewGap + 1);
332 }
333
334 for (; dw; dw--) {
335 *pb++ = 0;
336 if (pb >= pbEndColorByteTable)
337 pb = a_bColorByteTable;
338 }
339
340 if (ps->bCurrentSpeed > ps->bNewCurrentLineCountGap) {
341 ps->bNewGap = ps->bCurrentSpeed - ps->bNewCurrentLineCountGap;
342 dw = _NUMBER_OF_SCANSTEPS - 1 - (ULong)ps->bNewGap;
343 } else {
344 dw = _NUMBER_OF_SCANSTEPS - 1;
345 ps->bNewGap = 0;
346 }
347
348 if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) {
349 pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount +
350 ps->bNewGap + 1 - _NUMBER_OF_SCANSTEPS);
351 } else {
352 pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount+ps->bNewGap +1);
353 }
354
355 for (; dw; dw--) {
356 *pb++ = 0;
357 if (pb >= pbEndHalfStepTable)
358 pb = a_bHalfStepTable;
359 }
360 }
361
362 /*.............................................................................
363 * According the flag to set motor direction
364 */
motorSetRunPositionRegister(pScanData ps)365 static void motorSetRunPositionRegister( pScanData ps )
366 {
367 Byte bData;
368
369 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
370 if( ps->Scan.fMotorBackward ) {
371 bData = ps->AsicReg.RD_Motor0Control & ~_MotorDirForward;
372 } else {
373 bData = ps->AsicReg.RD_Motor0Control | _MotorDirForward;
374 }
375
376 IOCmdRegisterToScanner( ps, ps->RegMotor0Control, bData );
377
378 } else {
379
380 if( ps->Scan.fMotorBackward ) {
381 bData = ps->Asic96Reg.RD_MotorControl & ~_MotorDirForward;
382 } else {
383 bData = ps->Asic96Reg.RD_MotorControl | _MotorDirForward;
384 }
385
386 IOCmdRegisterToScanner( ps, ps->RegMotorControl, bData );
387 }
388 }
389
390 /*.............................................................................
391 *
392 */
motorPauseColorMotorRunStates(pScanData ps)393 static void motorPauseColorMotorRunStates( pScanData ps )
394 {
395 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES);
396
397 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
398
399 ps->a_nbNewAdrPointer[2] = 0x77; /* Read color at the same time */
400
401 } else {
402 ps->a_nbNewAdrPointer[2] = 1;
403 ps->a_nbNewAdrPointer[3] = 3;
404 ps->a_nbNewAdrPointer[4] = 2;
405 }
406
407 MotorSetConstantMove( ps, 0 );
408 }
409
410 /*.............................................................................
411 * Setup the a_nbNewAdrPointer for ASIC stepping register
412 */
motorP98FillDataToColorTable(pScanData ps,Byte bIndex,ULong dwSteps)413 static void motorP98FillDataToColorTable( pScanData ps,
414 Byte bIndex, ULong dwSteps)
415 {
416 pUChar pb;
417 pUShort pw;
418 Byte bColor;
419 UShort w;
420
421 for ( pb = &a_bColorByteTable[bIndex],
422 pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps-- ) {
423
424 if (*pw) { /* valid state */
425
426 if( *pw >= ps->BufferForColorRunTable ) {
427 DBG( DBG_LOW, "*pw = %u > %u !!\n",
428 *pw, ps->BufferForColorRunTable );
429 } else {
430 bColor = ps->pColorRunTable[*pw]; /* get the colors */
431 if (a_bColorsSum[bColor & 7]) /* need to read data */
432 *pb = bColor & 7;
433 }
434 }
435
436 if (++pw >= pwEndMoveStepTable) {
437 pw = a_wMoveStepTable;
438 pb = a_bColorByteTable;
439 } else
440 pb++;
441 }
442
443 /* ToCondense */
444 pb = a_bColorByteTable;
445
446 for (w = 0; w < _SCANSTATE_BYTES; w++, pb += 2)
447 ps->a_nbNewAdrPointer[w] = (Byte)((*pb & 7) + ((*(pb + 1) & 7) << 4));
448
449 /* ToCondenseMotor */
450 for (pb = a_bHalfStepTable, w = 0; w < _SCANSTATE_BYTES; w++) {
451 if (*pb++)
452 ps->a_nbNewAdrPointer [w] |= 8;
453
454 if (*pb++)
455 ps->a_nbNewAdrPointer [w] |= 0x80;
456 }
457 }
458
459 /*.............................................................................
460 *
461 */
motorP98FillHalfStepTable(pScanData ps)462 static void motorP98FillHalfStepTable( pScanData ps )
463 {
464 pUChar pbHalfStepTbl, pb;
465 pUShort pwMoveStep;
466 DataType Data;
467 ULong dw;
468
469 if (1 == ps->bMotorSpeedData) {
470 for (dw = 0; dw < _NUMBER_OF_SCANSTEPS; dw++)
471 a_bHalfStepTable [dw] =
472 (a_wMoveStepTable [dw] > ps->wMaxMoveStep) ? 0: 1;
473 } else {
474 pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount];
475 pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount];
476
477 if (ps->DataInf.wAppDataType >= COLOR_TRUE24)
478 Data.dwValue = _NUMBER_OF_SCANSTEPS - 1;
479 else
480 Data.dwValue = _NUMBER_OF_SCANSTEPS;
481
482 for (; Data.dwValue; Data.dwValue--, pbHalfStepTbl++, pwMoveStep++ ) {
483
484 if (pwMoveStep >= pwEndMoveStepTable) {
485 pbHalfStepTbl = a_bHalfStepTable;
486 pwMoveStep = a_wMoveStepTable;
487 }
488
489 if (*pwMoveStep) { /* need to exposure */
490
491 dw = (ULong)ps->bMotorSpeedData;
492 if (Data.bValue < ps->bMotorSpeedData)
493 *pwMoveStep = 0;
494 else {
495 *pbHalfStepTbl = 1;
496
497 if (ps->dwFullStateSpeed) {
498 dw -= ps->dwFullStateSpeed;
499 for (pb = pbHalfStepTbl; dw;
500 dw -= ps->dwFullStateSpeed) {
501 pb += ps->dwFullStateSpeed;
502 if (pb >= pbEndHalfStepTable)
503 pb -= _NUMBER_OF_SCANSTEPS;
504 *pb = 1;
505 }
506 }
507 }
508 }
509 }
510 }
511 }
512
513 /*.............................................................................
514 *
515 */
motorP98FillBackColorDataTable(pScanData ps)516 static void motorP98FillBackColorDataTable( pScanData ps )
517 {
518 Byte bIndex;
519
520 if ((bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >=
521 _NUMBER_OF_SCANSTEPS) {
522 bIndex -= _NUMBER_OF_SCANSTEPS;
523 }
524
525 motorP98FillDataToColorTable( ps, bIndex, (ULong)(_NUMBER_OF_SCANSTEPS -
526 ps->bNewCurrentLineCountGap));
527 }
528
529 /*.............................................................................
530 * i/p:
531 * pScanStep = pColorRunTable if forward, a_bScanStateTable if backward
532 * dwState = how many states is requested to process
533 * NOTE:
534 * The content of pScanStep contain:
535 * 0: Idle state
536 * 0xff: End mark
537 * others: The motor speed value
538 */
motorP98FillBackLoop(pScanData ps,pUChar pScanStep,ULong dwStates)539 static void motorP98FillBackLoop( pScanData ps,
540 pUChar pScanStep, ULong dwStates )
541 {
542 for (ps->fFullLength = _FALSE; dwStates; dwStates--) {
543
544 if (*pScanStep == 0xff ) {
545
546 ULong dw = ps->dwScanStateCount;
547
548 for (; dwStates; dwStates--) {
549 ps->a_nbNewAdrPointer [dw / 2] &= ((dw & 1) ? 0x7f: 0xf7);
550 dw = (dw + 1U) & _SCANSTATE_MASK;
551 }
552 if (!ps->dwScanStateCount)
553 ps->dwScanStateCount = _NUMBER_OF_SCANSTEPS;
554
555 ps->dwScanStateCount--;
556 ps->fFullLength = _TRUE;
557 break;
558 } else {
559 ps->a_nbNewAdrPointer [ps->dwScanStateCount / 2] |=
560 ((ps->dwScanStateCount & 1) ? 0x80 : 0x08);
561 if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS)
562 ps->dwScanStateCount = 0; /* reset to begin */
563
564 pScanStep++;
565 }
566 }
567 IOSetToMotorStepCount( ps ); /* put all scan states to ASIC */
568 }
569
570 /*.............................................................................
571 *
572 */
motorP98SetRunFullStep(pScanData ps)573 static void motorP98SetRunFullStep( pScanData ps )
574 {
575 ps->OpenScanPath( ps );
576
577 ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE;
578 IODataToRegister( ps, ps->RegStepControl,
579 ps->AsicReg.RD_StepControl );
580 IODataToRegister( ps, ps->RegLineControl, 96 );
581
582 if ( ps->bFastMoveFlag == _FastMove_Low_C75_G150_Back ) {
583 IODataToRegister( ps, ps->RegMotor0Control,
584 (_MotorHQuarterStep + _MotorOn + _MotorDirBackward));
585 } else {
586 IODataToRegister( ps, ps->RegMotor0Control,
587 (_MotorHQuarterStep + _MotorOn + _MotorDirForward));
588 }
589
590 if (ps->bFastMoveFlag == _FastMove_Film_150) {
591 ps->AsicReg.RD_XStepTime = 12;
592 } else {
593 if (ps->bFastMoveFlag == _FastMove_Fast_C50_G100) {
594 ps->AsicReg.RD_XStepTime =
595 ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 4 : 8);
596 } else {
597 ps->AsicReg.RD_XStepTime =
598 ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 6 : 12);
599 }
600 }
601
602 DBG( DBG_LOW, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime );
603 IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime);
604 ps->CloseScanPath( ps );
605 }
606
607 /*.............................................................................
608 * moves the sensor back home...
609 */
motorP98BackToHomeSensor(pScanData ps)610 static int motorP98BackToHomeSensor( pScanData ps )
611 {
612 int result = _OK;
613 TimerDef timer;
614
615 MotorSetConstantMove( ps, 1 );
616
617 ps->OpenScanPath( ps );
618
619 ps->AsicReg.RD_StepControl =
620 (_MOTOR_FREERUN + _MOTOR0_SCANSTATE+ _MOTOR0_ONESTEP);
621 IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl);
622
623 ps->AsicReg.RD_ModeControl = _ModeScan;
624 IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
625
626 ps->AsicReg.RD_Motor0Control = _MotorHQuarterStep +
627 _MotorOn + _MotorDirBackward;
628 IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control );
629
630
631 if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) {
632 ps->AsicReg.RD_XStepTime = ps->bSpeed24;
633 } else {
634 ps->AsicReg.RD_XStepTime = ps->bSpeed12;
635 }
636
637 DBG( DBG_HIGH, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime );
638
639 IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime );
640 IORegisterToScanner( ps, ps->RegRefreshScanState );
641
642 /* CHANGE: We allow up to 25 seconds for returning (org. val was 10) */
643 MiscStartTimer( &timer, _SECOND * 25 );
644
645 do {
646 if (IODataFromRegister( ps, ps->RegStatus) & _FLAG_P98_PAPER ) {
647 IODataToRegister( ps, ps->RegModelControl,
648 (Byte)(ps->AsicReg.RD_ModelControl | _HOME_SENSOR_POLARITY));
649 if(!(IODataFromRegister(ps, ps->RegStatus) & _FLAG_P98_PAPER))
650 break;
651 }
652 _DODELAY( 10 ); /* delay 10 ms */
653
654 } while ( !(result = MiscCheckTimer( &timer )));
655
656 ps->CloseScanPath( ps );
657
658 if( _OK != result )
659 return result;
660
661 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
662
663 IOSetToMotorRegister( ps );
664
665 return _OK;
666 }
667
668 /*.............................................................................
669 * 1) Clear scan states
670 * 2) Adjust the new scan state
671 */
motorP98FillRunNewAdrPointer1(pScanData ps)672 static void motorP98FillRunNewAdrPointer1( pScanData ps )
673 {
674 ScanState sState;
675 Byte bTemp;
676
677 IOGetCurrentStateCount( ps, &sState);
678 bTemp = sState.bStep;
679 if (sState.bStep < ps->bOldStateCount) {
680 sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can */
681 } /* holds 64 step, then reset to */
682 /* 0, so if less than means over*/
683 /* the table) */
684 sState.bStep -= ps->bOldStateCount; /* how many states passed */
685 ps->pScanState += sState.bStep;
686
687 /*
688 * if current state != no stepped or stepped a cycle, fill the table with
689 * 1 in NOT STEPPED length. (1 means to this state has to be processing).
690 */
691 ps->bOldStateCount = bTemp;
692 ps->dwScanStateCount = (ULong)((bTemp + 1) & _SCANSTATE_MASK);
693
694 motorP98FillBackLoop( ps, ps->pScanState, _NUMBER_OF_SCANSTEPS );
695 }
696
697 /*.............................................................................
698 *
699 */
motorP98FillRunNewAdrPointer(pScanData ps)700 static void motorP98FillRunNewAdrPointer( pScanData ps )
701 {
702 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
703
704 motorP98FillRunNewAdrPointer1( ps );
705 }
706
707 /*.............................................................................
708 * move the sensor to a specific Y-position
709 */
motorP98PositionYProc(pScanData ps,ULong dwStates)710 static void motorP98PositionYProc( pScanData ps, ULong dwStates )
711 {
712 ScanState sState;
713
714 memset( ps->pColorRunTable, 1, dwStates );
715 memset( ps->pColorRunTable + dwStates, 0xff, (3800UL - dwStates));
716
717 IOGetCurrentStateCount( ps, &sState);
718
719 ps->bOldStateCount = sState.bStep;
720
721 ps->OpenScanPath( ps );
722 IODataToRegister( ps, ps->RegMotor0Control,
723 (Byte)(_MotorOn + _MotorHEightStep +(ps->Scan.fMotorBackward)?
724 _MotorDirBackward : _MotorDirForward));
725
726 DBG( DBG_LOW, "XStepTime = %u\n", ps->bSpeed6 );
727 IODataToRegister( ps, ps->RegXStepTime, ps->bSpeed6 );
728 ps->CloseScanPath( ps );
729
730 ps->pScanState = ps->pColorRunTable;
731
732 ps->FillRunNewAdrPointer( ps );
733
734 while(!motorCheckMotorPresetLength( ps ))
735 motorP98FillRunNewAdrPointer1( ps );
736 }
737
738 /*.............................................................................
739 * checks if the sensor is in it´s home position and moves it back if necessary
740 */
motorP98CheckSensorInHome(pScanData ps)741 static int motorP98CheckSensorInHome( pScanData ps )
742 {
743 int result;
744
745 if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){
746
747 MotorSetConstantMove( ps, 1 );
748 ps->Scan.fMotorBackward = _FALSE;
749 ps->bExtraMotorCtrl = 0;
750 motorP98PositionYProc( ps, 20 );
751
752 result = motorP98BackToHomeSensor( ps );
753 if( _OK != result )
754 return result;
755
756 _DODELAY( 250 );
757 }
758
759 return _OK;
760 }
761
762 /*.............................................................................
763 * move the sensor to the scan-start position
764 */
motorP98WaitForPositionY(pScanData ps)765 static void motorP98WaitForPositionY( pScanData ps )
766 {
767 ULong dw;
768 ULong dwBX, dwDX;
769
770 if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
771
772 motorP98BackToHomeSensor( ps );
773 _DODELAY( 100 );
774
775 /* CHECK do we need this block ? was test code in the original source code */
776 ps->OpenScanPath( ps );
777 IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl);
778 IODataToRegister( ps, ps->RegStepControl, (Byte)(_MOTOR_FREERUN +
779 _MOTOR0_SCANSTATE + _MOTOR0_ONESTEP));
780 IODataToRegister( ps, ps->RegMotor0Control, (Byte)(_MotorOn +
781 _MotorHQuarterStep + _MotorDirForward));
782 ps->CloseScanPath( ps );
783
784 for (dw=1000; dw; dw--) {
785 if (IODataRegisterFromScanner( ps, ps->RegStatus) & _FLAG_P98_PAPER) {
786 IORegisterDirectToScanner( ps, ps->RegForceStep );
787 _DODELAY( 1000 / 400 );
788 }
789 }
790 /*-*/
791 ps->AsicReg.RD_ModeControl = _ModeScan;
792 IOCmdRegisterToScanner( ps, ps->RegModeControl,
793 ps->AsicReg.RD_ModeControl );
794
795 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
796
797 ps->Scan.fMotorBackward = _FALSE;
798 ps->bExtraMotorCtrl = 0;
799 ps->bFastMoveFlag = _FastMove_Film_150;
800
801 if (ps->DataInf.dwScanFlag & SCANDEF_Negative) {
802 MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_NEG_SCANNINGPOS)/2);
803 } else {
804 MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_POS_SCANNINGPOS)/2);
805 }
806
807 return;
808 }
809
810 ps->AsicReg.RD_ModeControl = _ModeScan;
811
812 IOCmdRegisterToScanner( ps, ps->RegModeControl,
813 ps->AsicReg.RD_ModeControl );
814
815 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
816
817 ps->Scan.fMotorBackward = _FALSE;
818 ps->bExtraMotorCtrl = 0;
819
820 /* SetStartPoint */
821 dw = ps->wInitialStep + ps->DataInf.crImage.y;
822
823 /*
824 * CHANGE: when checking out the values from the NT registry
825 * I found that the values are NOT 0
826 */
827 switch (ps->DataInf.wPhyDataType) {
828 case COLOR_BW: dw += _BW_ORIGIN; break;
829 case COLOR_256GRAY: dw += _GRAY_ORIGIN; break;
830 default: dw += _COLOR_ORIGIN; break;
831 }
832
833 if (dw & 0x80000000)
834 dw = 0; /* negative */
835
836 if (dw > 180) {
837 if (ps->bSetScanModeFlag & _ScanMode_Mono) {
838 dwBX = 90; /* go via 150 dpi, so 180 / 2 = 90 */
839 dwDX = (dw -180) % 3;
840 dw = (dw -180) / 3; /* 100 dpi */
841 } else {
842 dwBX = 45; /* go via 75 dpi, so 180 / 4 = 45 */
843 dwDX = (dw -180) % 6;
844 dw = (dw -180) / 6; /* 50 dpi */
845 }
846
847 dwDX = (dwDX * 3 + 1) / 2 + dwBX;
848
849 /*
850 * 100/50 dpi lines is 3/2 times of 150/75
851 * eax = (remainder * 3 + 1) / 2 + 180 / (2 or 4) lines
852 */
853 ps->bFastMoveFlag = _FastMove_Low_C75_G150;
854 MotorP98GoFullStep( ps, dwDX);
855
856 if (dw) {
857 DBG( DBG_LOW, "FAST MOVE MODE !!!\n" );
858 ps->bFastMoveFlag = _FastMove_Fast_C50_G100;
859 MotorP98GoFullStep( ps, dw);
860 }
861 } else {
862 dwBX = ((ps->bSetScanModeFlag & _ScanMode_Mono) ? 2: 4);
863 dw = (dw + dwBX/2) / dwBX;
864 ps->bFastMoveFlag = _FastMove_Low_C75_G150;
865
866 MotorP98GoFullStep(ps, dw);
867 }
868 }
869
870 /*.............................................................................
871 * PreMove/EndMove
872 * PreMove is only in ADF and CFB mode
873 * In ADF version, there is a distance gap between Paper flag and Real initial
874 * position and it need premove to real initial position and turn the motor
875 * Inverse and start Fast move to start scan position
876 * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then
877 * fast move
878 * In CIS and CSP although there have not PreMove but there have End move
879 * when paper out there still have several mm need to read,
880 * So it need EndMove 2mm and set Inverse Paper
881 */
motorP98GotoShadingPosition(pScanData ps)882 static Bool motorP98GotoShadingPosition( pScanData ps )
883 {
884 int result;
885
886 DBG( DBG_LOW, "motorP98GotoShadingPosition()\n" );
887
888 /* Modify Lamp Back to Home step for Scan twice in short time */
889 result = motorP98CheckSensorInHome( ps );
890
891 if( _OK != result )
892 return _FALSE;
893
894 MotorSetConstantMove( ps, 0 ); /* clear scan states */
895
896 IOCmdRegisterToScanner( ps, ps->RegModelControl,
897 ps->AsicReg.RD_ModelControl );
898
899 ps->Scan.fMotorBackward = _FALSE; /* forward */
900 ps->bExtraMotorCtrl = 0;
901
902 if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
903
904 ps->bFastMoveFlag = _FastMove_Low_C75_G150;
905 MotorP98GoFullStep( ps, 0x40 );
906
907 ps->bFastMoveFlag = _FastMove_Middle_C75_G150;
908 MotorP98GoFullStep( ps, ps->Device.dwModelOriginY );
909 }
910
911 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
912 IOSetToMotorRegister( ps );
913
914 return _TRUE;
915 }
916
917 /*.............................................................................
918 * round to the next physical available value
919 */
motorP98SetMaxDpiAndLength(pScanData ps,pUShort wLengthY,pUShort wBaseDpi)920 static void motorP98SetMaxDpiAndLength( pScanData ps,
921 pUShort wLengthY, pUShort wBaseDpi )
922 {
923 if (ps->DataInf.xyAppDpi.y > 600)
924 *wLengthY = ps->LensInf.rExtentY.wMax * 4 + 200;
925 else
926 *wLengthY = ps->LensInf.rExtentY.wMax * 2 + 200;
927
928 if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) &&
929 (ps->DataInf.xyAppDpi.y <= ps->wMinCmpDpi)) {
930 *wBaseDpi = ps->wMinCmpDpi;
931 } else {
932 if ((ps->DataInf.wPhyDataType < COLOR_TRUE24) &&
933 (ps->DataInf.xyAppDpi.y <= 75)) {
934 *wBaseDpi = 75;
935 } else {
936 if (ps->DataInf.xyAppDpi.y <= 150) {
937 *wBaseDpi = 150;
938 } else {
939 if (ps->DataInf.xyAppDpi.y <= 300) {
940 *wBaseDpi = 300;
941 } else {
942 if (ps->DataInf.xyAppDpi.y <= 600)
943 *wBaseDpi = 600;
944 else
945 *wBaseDpi = 1200;
946 }
947 }
948 }
949 }
950
951 DBG( DBG_LOW, "wBaseDPI = %u, %u\n", *wBaseDpi, ps->wMinCmpDpi );
952 }
953
954 /*.............................................................................
955 *
956 */
motorP98FillGBColorRunTable(pScanData ps,pUChar pTable,Byte bHi,Byte bLo,UShort wBaseDpi)957 static void motorP98FillGBColorRunTable( pScanData ps, pUChar pTable,
958 Byte bHi, Byte bLo, UShort wBaseDpi )
959 {
960
961 if( ps->Device.f0_8_16 ) {
962
963 if (wBaseDpi == ps->wMinCmpDpi) {
964 *pTable |= bHi;
965 *(pTable + 1) |= bLo;
966 } else {
967 switch (wBaseDpi) {
968 case 150:
969 *(pTable + 2) |= bHi;
970 *(pTable + 4) |= bLo;
971 break;
972
973 case 300:
974 *(pTable + 4) |= bHi;
975 *(pTable + 8) |= bLo;
976 break;
977
978 case 600:
979 *(pTable + 8) |= bHi;
980 *(pTable + 16) |= bLo;
981 break;
982
983 default:
984 *(pTable + 16) |= bHi;
985 *(pTable + 32) |= bLo;
986 break;
987 }
988 }
989 } else {
990
991 if (wBaseDpi == ps->wMinCmpDpi) {
992 *pTable |= bHi;
993 *(pTable + 1) |= bLo;
994 } else {
995 switch(wBaseDpi) {
996
997 case 150:
998 *(pTable + 1) |= bHi;
999 *(pTable + 2) |= bLo;
1000 break;
1001
1002 case 300:
1003 *(pTable + 2) |= bHi;
1004 *(pTable + 4) |= bLo;
1005 break;
1006
1007 case 600:
1008 *(pTable + 4) |= bHi;
1009 *(pTable + 8) |= bLo;
1010 break;
1011
1012 default:
1013 *(pTable + 8) |= bHi;
1014 *(pTable + 16) |= bLo;
1015 break;
1016 }
1017 }
1018 }
1019 }
1020
1021 /*.............................................................................
1022 *
1023 */
motorP98SetupRunTable(pScanData ps)1024 static void motorP98SetupRunTable( pScanData ps )
1025 {
1026 UShort wDpi, w, wBaseDpi, wLengthY;
1027 pUChar pTable;
1028
1029 motorP98SetMaxDpiAndLength( ps, &wLengthY, &wBaseDpi );
1030
1031 /*ClearColorRunTable(); */
1032 memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable );
1033
1034 wDpi = wBaseDpi;
1035 w = wLengthY + 1000;
1036 pTable = ps->pColorRunTable + (_NUMBER_OF_SCANSTEPS / 4);
1037
1038 if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) {
1039
1040 for(; w; w--, pTable++) {
1041 if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) {
1042 wDpi += wBaseDpi;
1043 *pTable |= 0x44;
1044 motorP98FillGBColorRunTable( ps, pTable, 0x22, 0x11, wBaseDpi );
1045 }
1046 }
1047 } else {
1048 for(; w; w--, pTable++) {
1049 if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) {
1050 wDpi += wBaseDpi;
1051 *pTable = 0x22;
1052 }
1053 }
1054 }
1055 ps->dwColorRunIndex = 0;
1056 }
1057
1058 /*.............................................................................
1059 *
1060 */
motorP98UpdateDataCurrentReadLine(pScanData ps)1061 static void motorP98UpdateDataCurrentReadLine( pScanData ps )
1062 {
1063 if(!(ps->Scan.bNowScanState & _SCANSTATE_STOP)) {
1064
1065 Byte b;
1066
1067 if (ps->Scan.bNowScanState >= ps->bCurrentLineCount)
1068 b = ps->Scan.bNowScanState - ps->bCurrentLineCount;
1069 else
1070 b = ps->Scan.bNowScanState + _NUMBER_OF_SCANSTEPS - ps->bCurrentLineCount;
1071
1072 if (b < 40)
1073 return;
1074 }
1075
1076 ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE );
1077 IOSetToMotorRegister( ps );
1078
1079 ps->Scan.bModuleState = _MotorAdvancing;
1080 }
1081
1082 /*.............................................................................
1083 * Byte - Scan State Index (0-63) and StopStep bit
1084 * pScanState->bStep - Scan State Index (0-63)
1085 * pScanState->bStatus - Scanner Status Register value
1086 */
motorP96GetScanStateAndStatus(pScanData ps,pScanState pScanStep)1087 static void motorP96GetScanStateAndStatus( pScanData ps, pScanState pScanStep )
1088 {
1089 ps->OpenScanPath( ps );
1090
1091 pScanStep->bStep = IOGetScanState(ps, _TRUE);
1092 pScanStep->bStep &= _SCANSTATE_MASK; /* org was. ~_ScanStateStop; */
1093 pScanStep->bStatus = IODataFromRegister( ps, ps->RegStatus );
1094
1095 ps->CloseScanPath( ps );
1096 }
1097
1098 /*.............................................................................
1099 * Capture the image data and average them.
1100 */
motorP96ReadDarkData(pScanData ps)1101 static Byte motorP96ReadDarkData( pScanData ps )
1102 {
1103 Byte bFifoOffset;
1104 UShort wSum, w;
1105 TimerDef timer;
1106
1107 MiscStartTimer( &timer, _SECOND/2);
1108
1109 do {
1110
1111 bFifoOffset = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
1112
1113 /* stepped 1 block */
1114 if( bFifoOffset ) {
1115
1116 /* read data */
1117 IOReadScannerImageData( ps, ps->pScanBuffer1, 512UL);
1118
1119 /* 320 = 192 + 128 (128 is size to fetch data) */
1120 for (w = 192, wSum = 0; w < 320; w++)
1121 wSum += (UShort)ps->pScanBuffer1[w];/* average data from */
1122 /* offset 192 and size 128*/
1123 return (Byte)(wSum >> 7); /* divided by 128 */
1124 }
1125
1126 } while (!MiscCheckTimer(&timer));
1127
1128 return 0xff; /* timed-out */
1129 }
1130
1131 /*.............................................................................
1132 * move the sensor to a specific Y-position
1133 */
motorP96PositionYProc(pScanData ps,ULong dwStates)1134 static void motorP96PositionYProc( pScanData ps, ULong dwStates )
1135 {
1136 ScanState sState;
1137
1138 memset( ps->pColorRunTable, 1, dwStates );
1139
1140 #ifdef DEBUG
1141 if( dwStates > 800UL )
1142 DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" );
1143 #endif
1144 memset( ps->pColorRunTable + dwStates, 0xff, 800UL - dwStates );
1145
1146 IOGetCurrentStateCount( ps, &sState );
1147 ps->bOldStateCount = sState.bStep;
1148
1149 /* TurnOnMotorAndSetDirection (); */
1150 if( ps->Scan.fMotorBackward ) {
1151 IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1152 (Byte)(ps->IgnorePF | ps->MotorOn));
1153 } else {
1154 IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1155 (Byte)(ps->IgnorePF | ps->MotorOn | _MotorDirForward));
1156 }
1157
1158 ps->pScanState = ps->pColorRunTable;
1159 do {
1160 ps->FillRunNewAdrPointer( ps );
1161
1162 } while (!motorCheckMotorPresetLength( ps ));
1163 }
1164
1165 /*.............................................................................
1166 * move the sensor to the scan-start position
1167 */
motorP96WaitForPositionY(pScanData ps)1168 static void motorP96WaitForPositionY( pScanData ps )
1169 {
1170 /* scheint OKAY zu sein fuer OP4830 */
1171 #ifdef _A3I_EN
1172 #warning "compiling for A3I"
1173 ULong dw;
1174 ScanState sState;
1175
1176 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1177
1178 ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward;
1179 ps->Scan.fMotorBackward = _FALSE;
1180 ps->bExtraMotorCtrl = ps->IgnorePF;
1181
1182 if( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi )
1183 dw = 30UL;
1184 else
1185 dw = 46UL;
1186
1187 dw = (dw + ps->DataInf.crImage.y) * 4 / 3;
1188
1189 if( ps->DataInf.wPhyDataType == COLOR_TRUE24 )
1190 dw += 99; /* dwStepsForColor; */
1191
1192 else if( ps->DataInf.wPhyDataType == COLOR_256GRAY )
1193 dw += 99; /* dwStepsForGray; */
1194 else
1195 dw += 99; /* dwStepsForBW; */
1196
1197 if( dw >= 130UL ) {
1198
1199 dw -= 100UL;
1200 dw <<= 1;
1201 /* GoFullStep (dw); */
1202
1203 memset( ps->pColorRunTable, 1, dw );
1204 memset( ps->pColorRunTable + dw, 0xff, ps->BufferForColorRunTable - dw );
1205
1206 IOGetCurrentStateCount( ps, &sState );
1207 ps->bOldStateCount = sState.bStep;
1208
1209 /* AdjustMotorTime () */
1210 IOCmdRegisterToScanner( ps, ps->RegLineControl, 31 );
1211
1212 /* SetRunHalfStep () */
1213 if( ps->Scan.fMotorBackward )
1214 IOCmdRegisterToScanner( ps, ps->RegMotorControl, _Motor1FullStep |
1215 ps->IgnorePF | ps->MotorOn );
1216 else
1217 IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->IgnorePF |
1218 ps->MotorOn | _MotorDirForward );
1219
1220 ps->pScanState = ps->pColorRunTable;
1221
1222 do {
1223 ps->FillRunNewAdrPointer( ps );
1224
1225 } while (!motorCheckMotorPresetLength(ps));
1226
1227 /* RestoreMotorTime () */
1228 IOCmdRegisterToScanner( ps, ps->RegLineControl,
1229 ps->AsicReg.RD_LineControl );
1230
1231 dw = 100UL;
1232 }
1233
1234 if( ps->DataInf.wPhyDataType != COLOR_TRUE24 )
1235 dw += 20;
1236
1237 motorP96PositionYProc( ps, dw );
1238
1239 #else
1240
1241 ULong dw;
1242 ScanState sState;
1243
1244 TimerDef timer;
1245
1246 MiscStartTimer( &timer, _SECOND / 4);
1247 while (!MiscCheckTimer( &timer ));
1248
1249 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1250
1251 ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward;
1252 ps->Scan.fMotorBackward = _FALSE;
1253 ps->bExtraMotorCtrl = ps->IgnorePF;
1254
1255 if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ||
1256 (ps->DataInf.xyAppDpi.y <= 300)) {
1257 dw = 6UL;
1258
1259 } else {
1260
1261 if (ps->DataInf.xyAppDpi.y <= 600) {
1262 /* 50 is from 6/300 */
1263 dw = (ULong)ps->DataInf.xyAppDpi.y / 50UL + 3UL;
1264 } else
1265 dw = 15; /* 6UL * 600UL / 300UL + 3; */
1266 }
1267
1268 dw += ps->DataInf.crImage.y;
1269
1270 if (dw >= 180UL) {
1271
1272 dw -= 180UL;
1273 /* GoFullStep (ps, dw);----------------------------------------------*/
1274 memset( ps->pColorRunTable, 1, dw );
1275 #ifdef DEBUG
1276 if( dw > 8000UL )
1277 DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" );
1278 #endif
1279 memset( ps->pColorRunTable + dw, 0xff, 8000UL - dw );
1280
1281 IOGetCurrentStateCount( ps, &sState );
1282 ps->bOldStateCount = sState.bStep;
1283
1284 /* SetRunFullStep (ps) */
1285 if( ps->Scan.fMotorBackward ) {
1286 IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1287 (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn));
1288 } else {
1289 IOCmdRegisterToScanner( ps, ps->RegMotorControl,
1290 (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn |
1291 _MotorDirForward));
1292 }
1293
1294 ps->pScanState = ps->pColorRunTable;
1295
1296 do {
1297 ps->FillRunNewAdrPointer (ps);
1298
1299 } while (!motorCheckMotorPresetLength(ps));
1300
1301 /*-------------------------------------------------------------------*/
1302
1303 dw = 180UL;
1304 }
1305
1306 if (ps->DataInf.wPhyDataType != COLOR_TRUE24)
1307 dw = dw * 2 + 16;
1308 else
1309 dw *= 2;
1310
1311 motorP96PositionYProc( ps, dw );
1312 #endif
1313 }
1314
1315 /*.............................................................................
1316 * Position Scan Module to specified line number (Forward or Backward & wait
1317 * for paper flag ON)
1318 */
motorP96ConstantMoveProc1(pScanData ps,ULong dwLines)1319 static void motorP96ConstantMoveProc1( pScanData ps, ULong dwLines )
1320 {
1321 Byte bRemainder, bLastState;
1322 UShort wQuotient;
1323 ULong dwDelayMaxTime;
1324 ScanState StateStatus;
1325 TimerDef timer;
1326 Bool fTimeout = _FALSE;
1327
1328 /* state cycles */
1329 wQuotient = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS);
1330 bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS);
1331
1332 /* 3.3 ms per line */
1333 #ifdef _A3I_EN
1334 dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2;
1335 #else
1336 dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 20;
1337 #endif
1338
1339 /* step every time */
1340 MotorSetConstantMove( ps, 1 );
1341
1342 ps->OpenScanPath( ps );
1343
1344 ps->AsicReg.RD_ModeControl = _ModeScan;
1345 IODataToRegister( ps, ps->RegModeControl, _ModeScan );
1346
1347 ps->Asic96Reg.RD_MotorControl = ps->MotorFreeRun |
1348 ps->MotorOn | _MotorDirForward;
1349 IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl );
1350
1351 ps->CloseScanPath( ps );
1352
1353 bLastState = 0;
1354
1355 MiscStartTimer( &timer, dwDelayMaxTime );
1356
1357 do {
1358
1359 /* GetStatusAndScanStateAddr () */
1360 motorP96GetScanStateAndStatus( ps, &StateStatus );
1361 if (StateStatus.bStatus & _FLAG_P96_PAPER ) {
1362 if (wQuotient) {
1363
1364 if (StateStatus.bStep != bLastState) {
1365 bLastState = StateStatus.bStep;
1366
1367 if (!bLastState)
1368 wQuotient--;
1369 }
1370 } else
1371 if (StateStatus.bStep >= bRemainder)
1372 break;
1373 } else
1374 break;
1375 } while (!(fTimeout = MiscCheckTimer( &timer )));
1376
1377 if (!fTimeout) {
1378 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
1379 IOSetToMotorRegister( ps );
1380 }
1381 }
1382
1383 /*.............................................................................
1384 * PreMove/EndMove
1385 * PreMove is only in ADF and CFB mode
1386 * In ADF version, there is a distance gap between Paper flag and Real initial
1387 * position and it need premove to real initial position and turn the motor
1388 * Inverse and start Fast move to start scan position
1389 * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then
1390 * fast move
1391 * In CIS and CSP although there have not PreMove but there have End move
1392 * when paper out there still have several mm need to read,
1393 * So it need EndMove 2mm and set Inverse Paper
1394 */
motorP96GotoShadingPosition(pScanData ps)1395 static Bool motorP96GotoShadingPosition( pScanData ps )
1396 {
1397 DBG( DBG_LOW, "motorP96GotoShadingPosition()\n" );
1398
1399 MotorSetConstantMove( ps, 0 ); /* clear scan states */
1400 ps->Scan.fMotorBackward = _FALSE; /* forward */
1401 ps->bExtraMotorCtrl = ps->IgnorePF;
1402
1403 MotorP96ConstantMoveProc( ps, 15 * 12 ); /* forward 180 lines */
1404
1405 if (IODataRegisterFromScanner(ps, ps->RegStatus) & _FLAG_P96_PAPER ) {
1406 ps->Asic96Reg.RD_MotorControl = 0;
1407 IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
1408
1409 DBG( DBG_LOW, "motorP96GotoShadingPosition() failed\n" );
1410 return _FALSE;
1411 }
1412 ps->Scan.fMotorBackward = _TRUE; /* backward */
1413 ps->bExtraMotorCtrl = 0; /* no extra action for motor */
1414
1415 /* backward a few thousand lines to touch sensor */
1416 MotorP96ConstantMoveProc( ps, ps->BackwardSteps );
1417
1418 _DODELAY( 250 );
1419
1420 IOCmdRegisterToScanner( ps, ps->RegModelControl,
1421 (Byte)(ps->AsicReg.RD_ModelControl | _ModelInvertPF));
1422
1423 ps->Scan.fMotorBackward = _FALSE; /* forward */
1424 motorP96ConstantMoveProc1( ps, 14 * 12 * 2); /* ahead 336 lines */
1425
1426 if( MODEL_OP_A3I == ps->sCaps.Model ) {
1427
1428 motorP96PositionYProc( ps, 80 );
1429
1430 } else {
1431 /* forward 24 + pScanData->wOverBlue lines */
1432 if (!ps->fColorMoreRedFlag)
1433 motorP96PositionYProc( ps, ps->wOverBlue + 12 * 2);
1434 }
1435
1436 if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
1437 ps->Scan.fMotorBackward = _FALSE;
1438 ps->bExtraMotorCtrl = ps->IgnorePF;
1439 MotorP96ConstantMoveProc( ps, 1200 );
1440 }
1441
1442 IOCmdRegisterToScanner( ps, ps->RegModelControl,
1443 ps->AsicReg.RD_ModelControl );
1444 return _TRUE;
1445 }
1446
1447 /*.............................................................................
1448 *
1449 */
motorP96FillHalfStepTable(pScanData ps)1450 static void motorP96FillHalfStepTable( pScanData ps )
1451 {
1452 #ifdef _A3I_EN
1453 if ( ps->Scan.bModuleState == _MotorInStopState ) {
1454
1455 /* clear the table and get the step value */
1456 memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS );
1457 ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2];
1458 }
1459
1460 /* the fastest stepping */
1461 if( ps->bMotorSpeedData & 1 ) {
1462
1463 memset( a_bHalfStepTable,
1464 ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0),
1465 _NUMBER_OF_SCANSTEPS );
1466 } else {
1467
1468 pUChar pbHalfStepTbl;
1469 Byte bHalfSteps;
1470 pUShort pwMoveStep;
1471 DataType Data;
1472
1473 bHalfSteps = ps->bMotorSpeedData / 2;
1474 pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount];
1475 pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount];
1476
1477 if( ps->DataInf.wAppDataType == COLOR_TRUE24)
1478 Data.dwValue = _NUMBER_OF_SCANSTEPS - 1;
1479 else
1480 Data.dwValue = _NUMBER_OF_SCANSTEPS;
1481
1482 /* FillDataToHalfStepTable */
1483 for(; Data.dwValue; Data.dwValue-- ) {
1484
1485 if( *pwMoveStep ) { /* need to exposure */
1486
1487 if( Data.bValue >= bHalfSteps ) {
1488
1489 pUChar pb = pbHalfStepTbl + bHalfSteps;
1490
1491 /* AdjustHalfStepStart */
1492 if( ps->DataInf.wAppDataType == COLOR_TRUE24 ) {
1493
1494 if (bHalfSteps >= 2)
1495 pb -= (bHalfSteps - 1);
1496 }
1497 if( pb >= pbEndHalfStepTable )
1498 pb -= _NUMBER_OF_SCANSTEPS;
1499
1500 if( wP96BaseDpi <= ps->PhysicalDpi && *pwMoveStep != 2 )
1501 *pb = 1;
1502
1503 pb += bHalfSteps;
1504
1505 if( pb >= pbEndHalfStepTable )
1506 pb -= _NUMBER_OF_SCANSTEPS;
1507
1508 *pb = 1;
1509 }
1510 else
1511 *pwMoveStep = 0; /* idle state */
1512 }
1513 if( ++pwMoveStep >= pwEndMoveStepTable ) {
1514 pwMoveStep = a_wMoveStepTable;
1515
1516 pbHalfStepTbl = a_bHalfStepTable;
1517 }
1518 else
1519 pbHalfStepTbl++;
1520 }
1521 }
1522
1523 #else
1524
1525 #ifdef DEBUG
1526 if( 0 == wP96BaseDpi )
1527 DBG( DBG_HIGH, "!!!! WARNING - motorP96FillHalfStepTable(), "
1528 "wP96BaseDpi == 0 !!!!\n" );
1529 #endif
1530
1531 if ( ps->Scan.bModuleState == _MotorInStopState ) {
1532
1533 /* clear the table and get the step value */
1534 memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS );
1535 ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2];
1536 }
1537
1538 /* the fastest stepping */
1539 if( ps->bMotorSpeedData & 1 ) {
1540
1541 memset( a_bHalfStepTable,
1542 ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0),
1543 _NUMBER_OF_SCANSTEPS );
1544 } else {
1545
1546 pUChar pbHalfStepTbl, pbHalfStepContent;
1547 pUShort pwMoveStep;
1548 DataType Data;
1549
1550 pbHalfStepContent = a_pbHalfStepTables[ps->bMotorSpeedData / 2 - 1];
1551
1552 pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount];
1553 pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount];
1554
1555 if (ps->DataInf.wAppDataType == COLOR_TRUE24)
1556 Data.dwValue = _NUMBER_OF_SCANSTEPS - 1;
1557 else
1558 Data.dwValue = _NUMBER_OF_SCANSTEPS;
1559
1560 /* FillDataToHalfStepTable */
1561 for (; Data.dwValue; Data.dwValue--) {
1562
1563 if (*pwMoveStep) { /* need to exposure */
1564
1565 if (Data.bValue >= *pbHalfStepContent) {
1566
1567 pUChar pb = pbHalfStepTbl + *pbHalfStepContent;
1568
1569 if (pb >= pbEndHalfStepTable)
1570 pb -= _NUMBER_OF_SCANSTEPS;
1571
1572 /* JudgeStep1 () */
1573 if ((wP96BaseDpi != 600) && (*pwMoveStep != 2)) {
1574 if (ps->Scan.bModuleState != _MotorInStopState) {
1575 *pb = 1;
1576 } else {
1577 if (ps->bMotorStepTableNo) {
1578 ps->bMotorStepTableNo--;
1579 *pb = 1;
1580 }
1581 }
1582 }
1583
1584 pb += *pbHalfStepContent;
1585 if (pb >= pbEndHalfStepTable)
1586 pb -= _NUMBER_OF_SCANSTEPS;
1587
1588 /* JudgeStep2 () */
1589 if (ps->Scan.bModuleState == _MotorInStopState) {
1590 if (ps->bMotorStepTableNo) {
1591 ps->bMotorStepTableNo--;
1592 *pb = 1;
1593 }
1594 } else {
1595 *pb = 1;
1596 }
1597
1598 pbHalfStepContent++;
1599 } else {
1600 *pwMoveStep = 0; /* idle state */
1601 }
1602 }
1603
1604 if (++pwMoveStep >= pwEndMoveStepTable) {
1605 pwMoveStep = a_wMoveStepTable;
1606 pbHalfStepTbl = a_bHalfStepTable;
1607 } else {
1608 pbHalfStepTbl++;
1609 }
1610 }
1611 }
1612 #endif
1613 }
1614
1615 /*.............................................................................
1616 *
1617 */
motorP96FillDataToColorTable(pScanData ps,Byte bIndex,ULong dwSteps)1618 static void motorP96FillDataToColorTable( pScanData ps,
1619 Byte bIndex, ULong dwSteps)
1620 {
1621 Byte bColor, bColors;
1622 pUChar pb, pb1;
1623 pUShort pw;
1624 DataType Data;
1625
1626 for (pb = &a_bColorByteTable[bIndex],
1627 pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps--) {
1628
1629 if (*pw) { /* valid state */
1630
1631 if( *pw >= ps->BufferForColorRunTable ) {
1632 DBG( DBG_LOW, "*pw = %u > %u !!\n",
1633 *pw, ps->BufferForColorRunTable );
1634 } else {
1635
1636 bColor = ps->pColorRunTable [*pw]; /* get the colors */
1637 bColors = a_bColorsSum [bColor & 7];/* number of colors */
1638
1639 if (bColors) { /* need to read data */
1640 if (dwSteps >= bColors) { /* enough room */
1641
1642 /* separate the colors to byte */
1643 pb1 = pb;
1644 if (bColor & ps->b1stColor) {
1645
1646 *pb1 = ps->b1stColorByte;
1647 if (++pb1 >= pbEndColorByteTable)
1648 pb1 = a_bColorByteTable;
1649 }
1650
1651 if (bColor & ps->b2ndColor) {
1652
1653 *pb1 = ps->b2ndColorByte;
1654 if (++pb1 >= pbEndColorByteTable)
1655 pb1 = a_bColorByteTable;
1656 }
1657
1658 if (bColor & ps->b3rdColor)
1659 *pb1 = ps->b3rdColorByte;
1660 } else
1661 *pw = 0;
1662 }
1663 }
1664 }
1665
1666 if (++pw >= pwEndMoveStepTable) {
1667 pw = a_wMoveStepTable;
1668 pb = a_bColorByteTable;
1669 } else
1670 pb++;
1671 }
1672
1673 /* ps->bOldSpeed = ps->bMotorRunStatus; non functional */
1674
1675 /* ToCondense, CondenseColorByteTable */
1676 for (dwSteps = _SCANSTATE_BYTES, pw = (pUShort)a_bColorByteTable,
1677 pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pw++, pb++) {
1678
1679 Data.wValue = *pw & 0x0303;
1680 *pb = Data.wOverlap.b1st | (Data.wOverlap.b2nd << 4);
1681 }
1682
1683 /* ToCondenseMotor */
1684 for (dwSteps = _SCANSTATE_BYTES, pb1 = a_bHalfStepTable,
1685 pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pb1++, pb++) {
1686
1687 if (*pb1++)
1688 *pb |= 4;
1689
1690 if (*pb1)
1691 *pb |= 0x40;
1692 }
1693 }
1694
1695 /*.............................................................................
1696 *
1697 */
motorP96FillBackColorDataTable(pScanData ps)1698 static void motorP96FillBackColorDataTable( pScanData ps )
1699 {
1700 Byte bIndex;
1701 ULong dw;
1702
1703 if ((ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >=
1704 _NUMBER_OF_SCANSTEPS){
1705 bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1 -
1706 _NUMBER_OF_SCANSTEPS;
1707 } else {
1708 bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1;
1709 }
1710 dw = _NUMBER_OF_SCANSTEPS - ps->bNewCurrentLineCountGap;
1711
1712 motorP96FillDataToColorTable( ps, bIndex, dw );
1713 }
1714
1715 /*.............................................................................
1716 * i/p:
1717 * pScanStep = pScanData->pColorRunTable if forward, a_bScanStateTable if backward
1718 * dwState = how many states is requested to process
1719 * NOTE:
1720 * The content of pScanStep contain:
1721 * 0: Idle state
1722 * 0xff: End mark
1723 * others: The motor speed value
1724 */
motorP96FillBackLoop(pScanData ps,pUChar pScanStep,ULong dwStates)1725 static void motorP96FillBackLoop( pScanData ps,
1726 pUChar pScanStep, ULong dwStates )
1727 {
1728 for (; dwStates; dwStates--) {
1729
1730 if (*pScanStep == 0xff)
1731 break; /* end of states */
1732
1733 if (*pScanStep) {
1734 if (*pScanStep == 1) { /* speed == 1, this state has to step */
1735
1736 if (ps->dwScanStateCount & 1)
1737 ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x40;
1738 else
1739 ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x04;
1740 }
1741
1742 *pScanStep -= 1; /* speed decrease by 1 */
1743
1744 if (!(*pScanStep))
1745 pScanStep++; /* state processed */
1746 } else
1747 pScanStep++; /* skip this state */
1748
1749 if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS)
1750 ps->dwScanStateCount = 0; /* reset to begin */
1751 }
1752
1753 if (*pScanStep != 0xff)
1754 ps->fFullLength = _FALSE;
1755 else
1756 ps->fFullLength = _TRUE;
1757
1758 IOSetToMotorStepCount( ps ); /* put all scan states to ASIC */
1759 }
1760
1761 /*.............................................................................
1762 * 1) Clear scan states
1763 * 2) Adjust the new scan state
1764 */
motorP96FillRunNewAdrPointer(pScanData ps)1765 static void motorP96FillRunNewAdrPointer( pScanData ps )
1766 {
1767 ScanState sState;
1768
1769 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES);
1770
1771 IOGetCurrentStateCount( ps, &sState );
1772
1773 if (sState.bStep < ps->bOldStateCount )
1774 sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can */
1775 /* holds 64 step, then reset to */
1776 /* 0, so if less than means over*/
1777 /* the table) */
1778
1779 sState.bStep -= ps->bOldStateCount; /* how many states passed */
1780 ps->pScanState += sState.bStep;
1781
1782 /*
1783 * if current state != no stepped or stepped a cycle, fill the table with
1784 * 1 in NOT STEPPED length. (1 means to this state has to be processing).
1785 */
1786 if (sState.bStep && sState.bStep != (_NUMBER_OF_SCANSTEPS - 1))
1787 memset( ps->pScanState, 1, _NUMBER_OF_SCANSTEPS - sState.bStep - 1 );
1788
1789 IOGetCurrentStateCount( ps, &sState);
1790 ps->bOldStateCount = sState.bStep; /* update current state */
1791 ps->dwScanStateCount = (ULong)((sState.bStep + 1) & (_NUMBER_OF_SCANSTEPS - 1));
1792
1793 /* fill begin at next step */
1794 motorP96FillBackLoop( ps, ps->pScanState, (_NUMBER_OF_SCANSTEPS - 1));
1795 }
1796
1797 /*.............................................................................
1798 *
1799 */
motorP96SetupRunTable(pScanData ps)1800 static void motorP96SetupRunTable( pScanData ps )
1801 {
1802 Short siSum;
1803 UShort wLoop;
1804 UShort wLengthY;
1805 DataPointer p;
1806
1807 DBG( DBG_LOW, "motorP96SetupRunTable()\n" );
1808
1809 /* SetMaxDpiAndLength (ps) */
1810 #ifdef _A3I_EN
1811 if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi ) {
1812
1813 wLengthY = 6800 * 2;
1814 wP96BaseDpi = ps->PhysicalDpi *2;
1815 } else {
1816 wLengthY = 6800;
1817 wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1;
1818 }
1819 #else
1820 if( ps->DataInf.xyPhyDpi.y > (ps->LensInf.rDpiY.wPhyMax / 2)) {
1821
1822 wLengthY = ps->LensInf.rExtentY.wMax << 1;
1823 wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax;
1824 } else {
1825 wLengthY = ps->LensInf.rExtentY.wMax;
1826 wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1;
1827 }
1828 #endif
1829
1830 DBG( DBG_LOW, "wLengthY = %u, wP96BaseDpi = %u\n", wLengthY, wP96BaseDpi );
1831
1832 /* ClearColorRunTable (ps) */
1833 memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable ); /*wLengthY + 0x60 ); */
1834
1835 p.pb = ps->pColorRunTable + _SCANSTATE_BYTES;
1836 #ifdef _A3I_EN
1837 wLoop = wLengthY + 200;
1838 #else
1839 wLoop = wLengthY + 0x20;
1840 #endif
1841 siSum = (Short)wP96BaseDpi;
1842
1843 if (ps->DataInf.wPhyDataType != COLOR_TRUE24) {
1844 for (; wLoop; wLoop--, p.pb++) {
1845 if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) {
1846 siSum += (Short)wP96BaseDpi;
1847 *p.pb = _COLORRUNTABLE_GREEN;
1848 }
1849 }
1850
1851 #ifdef _A3I_EN
1852 memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY,
1853 0x77, 0x100 );
1854 #endif
1855 } else {
1856 /* CalColorRunTable */
1857 DataType Data;
1858
1859 if (ps->fSonyCCD) {
1860
1861 if((ps->sCaps.Model == MODEL_OP_12000P) ||
1862 (ps->sCaps.Model == MODEL_OP_A3I)) {
1863 Data.wValue = (_COLORRUNTABLE_RED << 8) | _COLORRUNTABLE_BLUE;
1864 } else {
1865 Data.wValue = (_COLORRUNTABLE_GREEN << 8) | _COLORRUNTABLE_BLUE;
1866 }
1867 } else {
1868 Data.wValue = (_COLORRUNTABLE_BLUE << 8) | _COLORRUNTABLE_GREEN;
1869 }
1870
1871 for (; wLoop; wLoop--, p.pb++) {
1872
1873 if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) {
1874 siSum += (Short)wP96BaseDpi;
1875
1876 if((ps->sCaps.Model == MODEL_OP_12000P)||
1877 (ps->sCaps.Model == MODEL_OP_A3I)) {
1878 *p.pb |= _COLORRUNTABLE_GREEN;
1879 } else {
1880 *p.pb |= _COLORRUNTABLE_RED;
1881 }
1882
1883 /* Sony:Green,Toshiba:Blue */
1884 *(p.pb + 8) |= Data.wOverlap.b2nd;
1885 *(p.pb + 16) |= Data.wOverlap.b1st;
1886 }
1887 }
1888
1889 #ifdef _A3I_EN
1890 memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY,
1891 0x77, 0x100 );
1892 #endif
1893 if (ps->DataInf.xyPhyDpi.y < 100) {
1894
1895 Byte bColor;
1896
1897 /* CheckColorTable () */
1898 if (ps->fSonyCCD)
1899 Data.wValue = 0xdd22;
1900 else
1901 Data.wValue = 0xbb44;
1902
1903 for (wLoop = wLengthY - _SCANSTATE_BYTES,
1904 p.pb = ps->pColorRunTable + _SCANSTATE_BYTES;
1905 wLoop; wLoop--, p.pb++) {
1906 bColor = 0;
1907
1908 switch (a_bColorsSum[*p.pb & 0x0f]) {
1909
1910 case 3:
1911 if (*(p.pb + 2))
1912 bColor = 1;
1913 // fall through
1914 case 2:
1915 if (*(p.pb + 1))
1916 bColor++;
1917 if (bColor == 2) {
1918 *p.pb &= ~_COLORRUNTABLE_RED;
1919 *(p.pb - 2) = _COLORRUNTABLE_RED;
1920 }
1921
1922 if (bColor) {
1923 if (*p.pb & ps->RedDataReady) {
1924 *p.pb &= ~_COLORRUNTABLE_RED;
1925 *(p.pb - 1) = _COLORRUNTABLE_RED;
1926 } else {
1927 *p.pb &= Data.wOverlap.b2nd;
1928 *(p.pb - 1) = Data.wOverlap.b1st;
1929 }
1930 }
1931 }
1932 }
1933 }
1934 }
1935 }
1936
1937 /*.............................................................................
1938 *
1939 */
motorP96UpdateDataCurrentReadLine(pScanData ps)1940 static void motorP96UpdateDataCurrentReadLine( pScanData ps )
1941 {
1942 ScanState State1, State2;
1943 TimerDef timer;
1944
1945 IOGetCurrentStateCount( ps, &State1 );
1946 IOGetCurrentStateCount( ps, &State2 );
1947
1948 if (State1.bStatus == State2.bStatus) {
1949
1950 if (!(State2.bStatus & _SCANSTATE_STOP)) {
1951
1952 /* motor still running */
1953 if (State2.bStep < ps->bCurrentLineCount) {
1954 State2.bStep = State2.bStep + _NUMBER_OF_SCANSTEPS -
1955 ps->bCurrentLineCount;
1956 } else
1957 State2.bStep -= ps->bCurrentLineCount;
1958
1959 if (State2.bStep >= (_NUMBER_OF_SCANSTEPS - 3)) {
1960
1961 MiscStartTimer( &timer, _SECOND );
1962
1963 do {
1964 State2.bStatus = IOGetScanState( ps, _FALSE );
1965
1966 } while (!(State2.bStatus & _SCANSTATE_STOP) &&
1967 !MiscCheckTimer( &timer ));
1968 } else
1969 if (State2.bStep < 40)
1970 return;
1971 }
1972
1973 #ifdef _A3I_EN
1974 if( ps->bFifoCount >= 140) {
1975 #else
1976 if( ps->bFifoCount >= 20) {
1977 #endif
1978 if( 1 == ps->bCurrentSpeed ) {
1979 ps->bCurrentSpeed *= 2;
1980 } else {
1981 if( COLOR_TRUE24 == ps->DataInf.wPhyDataType )
1982 ps->bCurrentSpeed += 4;
1983 else
1984 ps->bCurrentSpeed += 2;
1985 }
1986
1987 MotorP96AdjustCurrentSpeed( ps, ps->bCurrentSpeed );
1988 }
1989
1990 /*
1991 * when using the full-step speed on 600 dpi models, then set
1992 * the motor into half-step mode, to avoid that the scanner hits
1993 * the back of its bed
1994 */
1995 /* HEINER:A3I */
1996 #if 1
1997 if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) {
1998
1999 if( ps->Asic96Reg.RD_MotorControl & ps->FullStep ) {
2000 ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep;
2001 IOCmdRegisterToScanner( ps, ps->RegMotorControl,
2002 ps->Asic96Reg.RD_MotorControl );
2003 }
2004 }
2005 #endif
2006 ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE );
2007
2008 IOSetToMotorRegister( ps);
2009 }
2010 }
2011
2012 /*.............................................................................
2013 * 1) Save the current scan state
2014 * 2) Set the motor direction
2015 */
2016 static void motorGoHalfStep1( pScanData ps )
2017 {
2018 ScanState sState;
2019
2020 IOGetCurrentStateCount( ps, &sState );
2021
2022 ps->bOldStateCount = sState.bStep;
2023
2024 motorSetRunPositionRegister(ps);
2025 ps->pScanState = a_bScanStateTable;
2026
2027 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2028
2029 ps->FillRunNewAdrPointer( ps );
2030
2031 while (!motorCheckMotorPresetLength(ps))
2032 motorP98FillRunNewAdrPointer1( ps );
2033 } else {
2034
2035 while (!motorCheckMotorPresetLength( ps ))
2036 ps->FillRunNewAdrPointer( ps );
2037 }
2038 }
2039
2040 /*.............................................................................
2041 * when losing data, we use this function to go back some lines and read them
2042 * again...
2043 */
2044 static void motorP96WaitBack( pScanData ps )
2045 {
2046 DataPointer p;
2047 DataType Data;
2048 ULong dw;
2049 UShort w;
2050 UShort wStayMaxStep;
2051
2052 /* FindMaxMoveStepIndex () */
2053
2054 p.pw = a_wMoveStepTable;
2055
2056 for( Data.dwValue = _NUMBER_OF_SCANSTEPS, wStayMaxStep = 1; Data.dwValue;
2057 Data.dwValue--, p.pw++ )
2058 if( *p.pw > wStayMaxStep )
2059 wStayMaxStep = *p.pw; /* save the largest step number */
2060
2061 if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi )
2062 wStayMaxStep -= 40;
2063 else
2064 wStayMaxStep -= 20;
2065
2066 IORegisterDirectToScanner( ps, ps->RegInitDataFifo );
2067
2068 memset( a_bScanStateTable, 1, _P96_BACKMOVES );
2069 memset(&a_bScanStateTable[_P96_BACKMOVES], 0xff, 250 - _P96_BACKMOVES );
2070
2071 ps->Scan.fMotorBackward = _TRUE;
2072 motorGoHalfStep1( ps ); /* backward 130 lines */
2073
2074 _DODELAY(200); /* let the motor stable */
2075
2076 if( ps->DataInf.xyPhyDpi.y <= ps->PhysicalDpi ) {
2077 if( ps->DataInf.wPhyDataType == COLOR_TRUE24 ) {
2078 dw = _P96_FORWARDMOVES - 1;
2079 } else {
2080 dw = _P96_FORWARDMOVES - 2;
2081 }
2082 } else {
2083 dw = _P96_FORWARDMOVES;
2084 }
2085
2086 memset( a_bScanStateTable, 1, dw );
2087 memset(&a_bScanStateTable[dw], 0xff, 250 - dw );
2088
2089 ps->Scan.fMotorBackward = _FALSE;
2090 motorGoHalfStep1( ps ); /* move forward */
2091
2092 /* GetNowStepTable () */
2093 ps->bCurrentLineCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK;
2094 ps->bNewCurrentLineCountGap = 0;
2095
2096 /* ClearColorByteTable () */
2097 memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS );
2098
2099 /* ClearHalfStepTable () */
2100 memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS );
2101
2102 /* FillWaitMoveStepTable () */
2103 p.pw = &a_wMoveStepTable[((ps->bCurrentLineCount + 1) & 0x3f)];
2104 *p.pw = 1;
2105 p.pw++;
2106
2107 for(w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData, dw = 60;dw;dw--) {
2108
2109 if( p.pw >= pwEndMoveStepTable ) /* make sure pointer in range */
2110 p.pw = a_wMoveStepTable;
2111
2112 if (--Data.bValue)
2113 *p.pw = 0; /* don't step */
2114 else {
2115 Data.bValue = ps->bMotorSpeedData; /* speed value */
2116 *p.pw = w; /* the ptr to pColorRunTable */
2117 w++; /* pointer++ */
2118 }
2119
2120 p.pw++; /* to next entry */
2121 }
2122 motorP96FillHalfStepTable( ps );
2123 motorP96FillBackColorDataTable( ps );
2124 }
2125
2126 /*.............................................................................
2127 * when losing data, we use this function to go back some lines and read them
2128 * again...
2129 */
2130 static void motorP98WaitBack( pScanData ps )
2131 {
2132 DataPointer p;
2133 DataType Data;
2134 ULong dw;
2135 UShort w;
2136 UShort wStayMaxStep;
2137 UShort back, forward;
2138
2139 p.pw = &a_wMoveStepTable[ps->bCurrentLineCount];
2140
2141 if (0 == *p.pw) {
2142
2143 for (w = _NUMBER_OF_SCANSTEPS; w && !*p.pw; w--) {
2144 p.pw--;
2145 if (p.pw < a_wMoveStepTable)
2146 p.pw = &a_wMoveStepTable[_NUMBER_OF_SCANSTEPS - 1];
2147 }
2148 wStayMaxStep = *p.pw + 1;
2149 } else {
2150 wStayMaxStep = *p.pw; /* save the largest step number */
2151 }
2152
2153 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2154
2155 forward = _P98_FORWARDMOVES;
2156 back = _P98_BACKMOVES;
2157 } else {
2158 forward = _P96_FORWARDMOVES;
2159 back = _P96_BACKMOVES;
2160 }
2161
2162 /*
2163 * Off to avoid the problem of block data re-read/lost
2164 */
2165 memset( a_bScanStateTable, 1, back );
2166 memset( &a_bScanStateTable[back], 0xff, (_SCANSTATE_TABLE_SIZE - back));
2167 ps->Scan.fMotorBackward = _TRUE;
2168 motorGoHalfStep1( ps );
2169
2170 _DODELAY(200); /* let the motor stable */
2171
2172 memset(a_bScanStateTable, 1, forward );
2173 memset(&a_bScanStateTable[forward], 0xff, (_SCANSTATE_TABLE_SIZE-forward));
2174 ps->Scan.fMotorBackward = _FALSE;
2175 motorGoHalfStep1( ps );
2176
2177 ps->bNewCurrentLineCountGap = 0;
2178
2179 memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS );
2180 memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS );
2181
2182 ps->bCurrentLineCount = (ps->bCurrentLineCount + 1) & 0x3f;
2183
2184 p.pw = &a_wMoveStepTable[ps->bCurrentLineCount];
2185
2186 for (w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData,
2187 dw = _NUMBER_OF_SCANSTEPS; dw; dw--) {
2188 if (--Data.bValue) {
2189 *p.pw = 0; /* don't step */
2190 } else {
2191
2192 /* speed value */
2193 Data.bValue = ps->bMotorSpeedData;
2194 *p.pw = w; /* the pointer to pColorRunTable*/
2195 w++; /* pointer++ */
2196 }
2197 /* make sure pointer in range */
2198 if (++p.pw >= pwEndMoveStepTable)
2199 p.pw = a_wMoveStepTable;
2200 }
2201
2202 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2203 motorP98FillHalfStepTable( ps );
2204 motorP98FillBackColorDataTable( ps );
2205 } else {
2206 motorP96FillHalfStepTable( ps );
2207 motorP96FillBackColorDataTable( ps );
2208 }
2209 }
2210
2211 /*.............................................................................
2212 *
2213 */
2214 static void motorFillMoveStepTable( pScanData ps,
2215 UShort wIndex, Byte bStep, pUShort pw )
2216 {
2217 UShort w;
2218 Byte b;
2219
2220 if (++pw >= pwEndMoveStepTable )
2221 pw = a_wMoveStepTable;
2222
2223 wIndex++;
2224
2225 b = ps->bMotorSpeedData;
2226
2227 for (w = _NUMBER_OF_SCANSTEPS - bStep; w; w--) {
2228 if (b == 1) {
2229 b = ps->bMotorSpeedData;
2230 *pw = wIndex;
2231 wIndex++;
2232 } else {
2233 b--;
2234 *pw = 0;
2235 }
2236 if (++pw >= pwEndMoveStepTable)
2237 pw = a_wMoveStepTable;
2238 }
2239
2240 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2241 motorP98FillHalfStepTable( ps );
2242 else
2243 motorP96FillHalfStepTable( ps );
2244
2245 if ((ps->bCurrentLineCount + 1) >= _NUMBER_OF_SCANSTEPS) {
2246 b = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS;
2247 } else {
2248 b = ps->bCurrentLineCount + 1;
2249 }
2250
2251 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2252 motorP98FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1);
2253 else
2254 motorP96FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1);
2255 }
2256
2257 /*.............................................................................
2258 *
2259 */
2260 static void noMotorRunStatusStop( pScanData ps, Byte bScanState )
2261 {
2262 Byte b, b1, bCur;
2263 pUShort pw;
2264 pByte pb;
2265 UShort w;
2266
2267 ps->bCurrentLineCount = (bScanState & _SCANSTATE_MASK);
2268
2269 ps->Scan.fRefreshState = _FALSE;
2270
2271 IORegisterDirectToScanner( ps, ps->RegRefreshScanState );
2272
2273 bCur = ps->bCurrentLineCount;
2274 pw = &a_wMoveStepTable[bCur];
2275 pb = ps->pColorRunTable;
2276 b = 0;
2277 b1 = 0;
2278 w = _NUMBER_OF_SCANSTEPS;
2279
2280 if (*pw) {
2281 b = a_bColorsSum[pb [*pw] >> 4];
2282 if (b) {
2283 motorClearColorByteTableLoop0( ps, b );
2284 ps->bNewCurrentLineCountGap = b;
2285
2286 motorFillMoveStepTable( ps, *pw, 1, pw );
2287 return;
2288 }
2289 b1++;
2290 bCur--;
2291
2292 if (--pw < a_wMoveStepTable) {
2293 pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1];
2294 bCur = _NUMBER_OF_SCANSTEPS - 1;
2295 }
2296 }
2297
2298 for(; w; w--) {
2299 if (*pw) {
2300 if (*pw < _SCANSTATE_BYTES) {
2301 b = 0;
2302 break;
2303 } else
2304 if ((b = a_bColorsSum [pb [*pw] >> 4]))
2305 break;
2306 }
2307 b1++;
2308 bCur--;
2309
2310 if (--pw < a_wMoveStepTable) {
2311 pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1];
2312 bCur = _NUMBER_OF_SCANSTEPS - 1;
2313 }
2314 }
2315
2316 if (b1 == _NUMBER_OF_SCANSTEPS) {
2317 ps->bNewCurrentLineCountGap = 0;
2318 ps->bNewGap = 0;
2319 } else {
2320 ps->bNewCurrentLineCountGap = b1;
2321 ps->bNewGap = b;
2322 }
2323
2324 motorClearColorByteTableLoop1( ps );
2325
2326 motorFillMoveStepTable( ps, *pw, 0, pw);
2327 }
2328
2329 /*.............................................................................
2330 *
2331 */
2332 static void motorP96SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState )
2333 {
2334 #if 0
2335 PUCHAR pb;
2336 Byte bScanState;
2337 #endif
2338 Byte bState, bData;
2339 UShort wMoveStep;
2340 pUShort pw;
2341 ULong dw;
2342 TimerDef timer;
2343
2344 if( fSetRunState )
2345 ps->Scan.bModuleState = _MotorInNormalState;
2346
2347 ps->bMotorSpeedData = bSpeed;
2348
2349 if( ps->bMoveDataOutFlag == _DataAfterRefreshState) {
2350
2351 ps->bMoveDataOutFlag = _DataInNormalState;
2352
2353 MiscStartTimer( &timer, (_SECOND /2));
2354
2355 while (!MiscCheckTimer(&timer)) {
2356 if ((bState = IOGetScanState( ps, _FALSE)) & _SCANSTATE_STOP) {
2357 ps->bCurrentLineCount = bState & ~_SCANSTATE_STOP;
2358 motorP96WaitBack( ps );
2359 return;
2360 }
2361 }
2362 }
2363
2364 bState = IOGetScanState( ps, _FALSE );
2365
2366 if((ps->Scan.bModuleState != _MotorInStopState) ||
2367 !(bState & _SCANSTATE_STOP)) {
2368
2369 /* Try to find the available step for all rest steps.
2370 * 1) if current step is valid (with data request), fill all steps
2371 * after it
2372 * 2) if current step is NULL (for delay purpose), backward search the
2373 * valid entry, then fill all steps after it
2374 * 3) if no step is valid, fill all entries
2375 */
2376 Byte bColors = 0;
2377 UShort w;
2378
2379 /* NoMotorRunStatusStop () */
2380 ps->bCurrentLineCount = (bState &= _SCANSTATE_MASK);
2381 ps->Scan.fRefreshState = _TRUE;
2382
2383 IORegisterDirectToScanner( ps, ps->RegRefreshScanState );
2384
2385 pw = &a_wMoveStepTable[bState];
2386 bData = 0;
2387 bState = ps->bCurrentLineCount;
2388 dw = _NUMBER_OF_SCANSTEPS;
2389
2390 if( (wMoveStep = *pw) ) {
2391
2392 bColors = a_bColorsSum[ ps->pColorRunTable[*pw] / 16];
2393
2394 if( bColors ) {
2395
2396 motorClearColorByteTableLoop0( ps, bColors );
2397 ps->bNewCurrentLineCountGap = bColors;
2398 bColors = 1;
2399 goto FillMoveStepTable;
2400
2401 } else {
2402
2403 bData++;
2404 dw--;
2405 if( --pw < a_wMoveStepTable ) {
2406 pw = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1;
2407 bState = _NUMBER_OF_SCANSTEPS - 1;
2408 }
2409 else
2410 bState--;
2411 }
2412 }
2413
2414 /* FindNextStep */
2415 while( dw-- ) {
2416
2417 if( (wMoveStep = *pw) ) {
2418 if (wMoveStep < (_NUMBER_OF_SCANSTEPS / 2)) {
2419 bColors = 0;
2420 break;
2421 }
2422 if((bColors = a_bColorsSum [ps->pColorRunTable[wMoveStep] / 16]))
2423 break;
2424 }
2425
2426 bData++;
2427 if( --pw < a_wMoveStepTable ) {
2428 pw = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1;
2429 bState = _NUMBER_OF_SCANSTEPS - 1;
2430 }
2431 else
2432 bState--;
2433 }
2434
2435 if (bData == _NUMBER_OF_SCANSTEPS )
2436 bData = bColors = 0;
2437
2438 ps->bNewCurrentLineCountGap = bData;
2439 ps->bNewGap = bColors;
2440 motorClearColorByteTableLoop1( ps );
2441 bColors = 0;
2442
2443 /* use pw (new pointer) and new speed to recreate MoveStepTable
2444 * wMoveStep = Index number from a_wMoveStepTable ([esi])
2445 * bColors = number of steps should be reserved
2446 * pw = where to fill
2447 */
2448
2449 FillMoveStepTable:
2450
2451 motorP96GetStartStopGap( ps, _TRUE );
2452
2453 if( !ps->bMotorStepTableNo )
2454 ps->bMotorStepTableNo = 1;
2455
2456 if( ps->bMotorStepTableNo != 0xff && ps->IO.portMode == _PORT_SPP &&
2457 ps->DataInf.xyPhyDpi.y <= 200) {
2458 ps->bMotorStepTableNo++;
2459 }
2460
2461 if (++pw >= pwEndMoveStepTable)
2462 pw = a_wMoveStepTable;
2463
2464 for( dw = _NUMBER_OF_SCANSTEPS - bColors, wMoveStep++,
2465 bData = ps->bMotorSpeedData; dw; dw-- ) {
2466 if( bData == 1 ) {
2467
2468 bData = ps->bMotorSpeedData;
2469 if( ps->bMotorStepTableNo ) {
2470
2471 ps->bMotorStepTableNo--;
2472 w = wMoveStep;
2473 wMoveStep++;
2474
2475 } else {
2476 bData--;
2477 w = 0;
2478 }
2479 } else {
2480 bData--;
2481 w = 0;
2482 }
2483 *pw = w;
2484
2485 if (++pw >= pwEndMoveStepTable)
2486 pw = a_wMoveStepTable;
2487 }
2488
2489 motorP96FillHalfStepTable( ps );
2490
2491 /* FillColorBytesTable */
2492 if((ps->bCurrentLineCount + 1) < _NUMBER_OF_SCANSTEPS )
2493 bState = ps->bCurrentLineCount + 1;
2494 else
2495 bState = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS;
2496
2497 motorP96FillDataToColorTable( ps, bState, _NUMBER_OF_SCANSTEPS - 1);
2498 }
2499 }
2500
2501 /*.............................................................................
2502 *
2503 */
2504 static void motorP98SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState )
2505 {
2506 static Byte lastFifoState = 0;
2507
2508 Bool overflow;
2509 Byte bOld1ScanState, bData;
2510
2511 if( fSetRunState )
2512 ps->Scan.bModuleState = _MotorInNormalState;
2513
2514 ps->bMotorSpeedData = bSpeed;
2515 overflow = _FALSE;
2516
2517 if( _ASIC_IS_98001 != ps->sCaps.AsicID ) {
2518 ps->bMoveDataOutFlag = _DataInNormalState;
2519
2520 bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
2521
2522 if((lastFifoState > _P96_FIFOOVERFLOWTHRESH) &&
2523 (bData < lastFifoState)) {
2524 DBG( DBG_HIGH, "FIFO OVERFLOW, losing data !!\n" );
2525 overflow = _TRUE;
2526 }
2527 lastFifoState = bData;
2528 }
2529
2530 bOld1ScanState = IOGetScanState( ps, _FALSE );
2531
2532 if(!(bOld1ScanState & _SCANSTATE_STOP) && !overflow)
2533 noMotorRunStatusStop( ps, bOld1ScanState );
2534 else {
2535 ps->bCurrentLineCount = (bOld1ScanState & 0x3f);
2536 ps->Scan.bModuleState = _MotorGoBackward;
2537
2538 motorP98WaitBack( ps );
2539
2540 if( overflow )
2541 lastFifoState = 0;
2542
2543 if( _ASIC_IS_98001 != ps->sCaps.AsicID )
2544 ps->bMoveDataOutFlag = _DataFromStopState;
2545 }
2546 }
2547
2548 /*.............................................................................
2549 *
2550 */
2551 static void motorP98003ModuleFreeRun( pScanData ps, ULong steps )
2552 {
2553 IODataToRegister( ps, ps->RegMotorFreeRunCount1, (_HIBYTE(steps)));
2554 IODataToRegister( ps, ps->RegMotorFreeRunCount0, (_LOBYTE(steps)));
2555 IORegisterToScanner( ps, ps->RegMotorFreeRunTrigger );
2556 }
2557
2558 /*.............................................................................
2559 *
2560 */
2561 static void motorP98003ModuleToHome( pScanData ps )
2562 {
2563 if(!(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) {
2564
2565 IODataToRegister( ps, ps->RegMotor0Control,
2566 (Byte)(ps->AsicReg.RD_Motor0Control|_MotorDirForward));
2567
2568 MotorP98003PositionYProc( ps, 40 );
2569 MotorP98003BackToHomeSensor( ps );
2570 _DODELAY( 250 );
2571 }
2572 }
2573
2574 /*.............................................................................
2575 *
2576 */
2577 static void motorP98003DownloadNullScanStates( pScanData ps )
2578 {
2579 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
2580 IODownloadScanStates( ps );
2581 }
2582
2583 /*.............................................................................
2584 *
2585 */
2586 static void motorP98003Force16Steps( pScanData ps )
2587 {
2588 ULong dw;
2589
2590 IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP);
2591 IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR );
2592
2593 for(dw = 16; dw; dw--) {
2594 IORegisterToScanner( ps, ps->RegForceStep );
2595 _DODELAY( 10 );
2596 }
2597
2598 IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
2599 }
2600
2601 /*.............................................................................
2602 *
2603 */
2604 static void motorP98003WaitForPositionY( pScanData ps )
2605 {
2606 Byte bXStep;
2607 ULong dwBeginY;
2608
2609 dwBeginY = (ULong)ps->DataInf.crImage.y * 4 + ps->Scan.dwScanOrigin;
2610
2611 if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) {
2612 if( ps->Device.f0_8_16 )
2613 dwBeginY += 16;
2614 else
2615 dwBeginY += 8;
2616 }
2617
2618 bXStep = (Byte)((ps->DataInf.wPhyDataType <= COLOR_256GRAY) ?
2619 ps->Device.XStepMono : ps->Device.XStepColor);
2620
2621 if( ps->Shade.bIntermediate & _ScanMode_AverageOut )
2622 bXStep = 8;
2623
2624 motorP98003Force16Steps( ps);
2625 dwBeginY -= 16;
2626
2627 if (dwBeginY > (_RFT_SCANNING_ORG + _P98003_YOFFSET) &&
2628 bXStep < ps->AsicReg.RD_XStepTime) {
2629
2630 IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower );
2631 _DODELAY( 12 );
2632 IODataToRegister( ps, ps->RegXStepTime, bXStep);
2633 IODataToRegister( ps, ps->RegExtendedXStep, 0 );
2634 IODataToRegister( ps, ps->RegScanControl1,
2635 (UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
2636 MotorP98003PositionYProc( ps, dwBeginY - 64 );
2637 dwBeginY = 64;
2638 }
2639
2640 IODataToRegister( ps, ps->RegFifoFullLength0, _LOBYTE(ps->AsicReg.RD_BufFullSize));
2641 IODataToRegister( ps, ps->RegFifoFullLength1, _HIBYTE(ps->AsicReg.RD_BufFullSize));
2642 IODataToRegister( ps, ps->RegFifoFullLength2, _LOBYTE(_HIWORD(ps->AsicReg.RD_BufFullSize)));
2643
2644 IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType);
2645 _DODELAY( 12 );
2646
2647 if(!ps->Device.f2003 || (ps->Shade.bIntermediate & _ScanMode_AverageOut) ||
2648 ( ps->DataInf.xyAppDpi.y <= 75 &&
2649 ps->DataInf.wPhyDataType <= COLOR_256GRAY)) {
2650 IODataToRegister( ps, ps->RegMotorDriverType,
2651 (Byte)(ps->Scan.motorPower & (_MOTORR_MASK | _MOTORR_STRONG)));
2652 } else {
2653 IODataToRegister( ps, ps->RegMotorDriverType,
2654 ps->AsicReg.RD_MotorDriverType );
2655 }
2656
2657 IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime );
2658 IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime );
2659 IODataToRegister( ps, ps->RegScanControl1,
2660 (Byte)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
2661
2662 if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) {
2663
2664 TimerDef timer;
2665
2666 motorP98003ModuleFreeRun( ps, dwBeginY );
2667 _DODELAY( 15 );
2668
2669 MiscStartTimer( &timer, (_SECOND * 20));
2670
2671 while(( IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) &&
2672 !MiscCheckTimer(&timer));
2673 IODataToRegister( ps, ps->RegModeControl, _ModeScan );
2674 } else {
2675 MotorP98003PositionYProc( ps, dwBeginY );
2676 IORegisterToScanner( ps, ps->RegRefreshScanState );
2677 }
2678 }
2679
2680 /*.............................................................................
2681 * move the sensor to the appropriate shading position
2682 */
2683 static Bool motorP98003GotoShadingPosition( pScanData ps )
2684 {
2685 motorP98003ModuleToHome( ps );
2686
2687 /* position to somewhere under the transparency adapter */
2688 if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) {
2689
2690 MotorP98003ForceToLeaveHomePos( ps );
2691 motorP98003DownloadNullScanStates( ps );
2692
2693 IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
2694 IODataToRegister( ps, ps->RegModeControl, _ModeScan);
2695 IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR );
2696 IODataToRegister( ps, ps->RegXStepTime, 6);
2697 IODataToRegister( ps, ps->RegExtendedXStep, 0);
2698 IODataToRegister( ps, ps->RegScanControl1, _MFRC_BY_XSTEP);
2699
2700 MotorP98003PositionYProc( ps, _TPA_P98003_SHADINGORG );
2701 }
2702
2703 return _TRUE;
2704 }
2705
2706 /*.............................................................................
2707 * initialize this module and setup the correct function pointer according
2708 * to the ASIC
2709 */
2710 static void motorP98003PositionModuleToHome( pScanData ps )
2711 {
2712 Byte save, saveModel;
2713
2714 saveModel = ps->AsicReg.RD_ModelControl;
2715
2716 ps->Scan.fRefreshState = _FALSE;
2717 motorP98003DownloadNullScanStates( ps );
2718
2719 _DODELAY( 1000UL / 8UL);
2720
2721 save = ps->Shade.bIntermediate;
2722
2723 ps->Shade.bIntermediate = _ScanMode_AverageOut;
2724 ps->ReInitAsic( ps, _FALSE );
2725 ps->Shade.bIntermediate = save;
2726
2727 IODataToRegister( ps, ps->RegModeControl, _ModeScan );
2728 IORegisterToScanner( ps, ps->RegResetMTSC );
2729 IODataToRegister( ps, ps->RegScanControl1, 0 );
2730
2731 IODataToRegister( ps, ps->RegModelControl,
2732 ps->Device.ModelCtrl | _ModelDpi300 );
2733
2734 IODataToRegister( ps, ps->RegLineControl, 80);
2735 IODataToRegister( ps, ps->RegXStepTime, ps->Device.XStepBack);
2736 IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower);
2737
2738 _DODELAY( 12 );
2739
2740 IODataToRegister( ps, ps->RegMotor0Control,
2741 (_MotorHHomeStop | _MotorOn | _MotorHQuarterStep |
2742 _MotorPowerEnable));
2743 IODataToRegister( ps, ps->RegStepControl,
2744 (_MOTOR0_SCANSTATE | _MOTOR_FREERUN));
2745
2746 memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES );
2747 IODownloadScanStates( ps );
2748 IORegisterToScanner( ps, ps->RegRefreshScanState );
2749
2750 ps->AsicReg.RD_ModelControl = saveModel;
2751 }
2752
2753 /************************ exported functions *********************************/
2754
2755 /*.............................................................................
2756 * initialize this module and setup the correct function pointer according
2757 * to the ASIC
2758 */
2759 _LOC int MotorInitialize( pScanData ps )
2760 {
2761 DBG( DBG_HIGH, "MotorInitialize()\n" );
2762
2763 if( NULL == ps )
2764 return _E_NULLPTR;
2765
2766 ps->a_wMoveStepTable = a_wMoveStepTable;
2767 ps->a_bColorByteTable = a_bColorByteTable;
2768 wP96BaseDpi = 0;
2769
2770 ps->PauseColorMotorRunStates = motorPauseColorMotorRunStates;
2771
2772 /*
2773 * depending on the asic, we set some functions
2774 */
2775 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2776
2777 ps->WaitForPositionY = motorP98WaitForPositionY;
2778 ps->GotoShadingPosition = motorP98GotoShadingPosition;
2779 ps->FillRunNewAdrPointer = motorP98FillRunNewAdrPointer;
2780 ps->SetupMotorRunTable = motorP98SetupRunTable;
2781 ps->UpdateDataCurrentReadLine = motorP98UpdateDataCurrentReadLine;
2782 ps->SetMotorSpeed = motorP98SetSpeed;
2783
2784 } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
2785
2786 ps->WaitForPositionY = motorP98003WaitForPositionY;
2787 ps->GotoShadingPosition = motorP98003GotoShadingPosition;
2788 ps->SetMotorSpeed = motorP98SetSpeed;
2789
2790 } else if( _IS_ASIC96(ps->sCaps.AsicID)) {
2791
2792 ps->WaitForPositionY = motorP96WaitForPositionY;
2793 ps->GotoShadingPosition = motorP96GotoShadingPosition;
2794 ps->FillRunNewAdrPointer = motorP96FillRunNewAdrPointer;
2795 ps->SetupMotorRunTable = motorP96SetupRunTable;
2796 ps->UpdateDataCurrentReadLine = motorP96UpdateDataCurrentReadLine;
2797 ps->SetMotorSpeed = motorP96SetSpeed;
2798
2799 } else {
2800
2801 DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" );
2802 return _E_NOSUPP;
2803 }
2804 return _OK;
2805 }
2806
2807 /*.............................................................................
2808 *
2809 */
2810 _LOC void MotorSetConstantMove( pScanData ps, Byte bMovePerStep )
2811 {
2812 DataPointer p;
2813 ULong dw;
2814
2815 p.pb = ps->a_nbNewAdrPointer;
2816
2817 switch( bMovePerStep )
2818 {
2819 case 0: /* doesn't move at all */
2820 for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) {
2821
2822 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2823 *p.pdw &= 0x77777777;
2824 else
2825 *p.pdw &= 0xbbbbbbbb;
2826 }
2827 break;
2828
2829 case 1:
2830 for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) {
2831 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2832 *p.pdw |= 0x88888888;
2833 else
2834 *p.pdw |= 0x44444444;
2835 }
2836 break;
2837
2838 case 2:
2839 for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) {
2840 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2841 *p.pdw |= 0x80808080;
2842 else
2843 *p.pdw |= 0x40404040;
2844 }
2845 break;
2846
2847 default:
2848 {
2849 Byte bMoves = bMovePerStep;
2850
2851 for (dw = _SCANSTATE_BYTES; dw; dw--, p.pb++) {
2852 if (!(--bMoves)) {
2853 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2854 *p.pb |= 8;
2855 else
2856 *p.pb |= 4;
2857 bMoves = bMovePerStep;
2858 }
2859 if (!(--bMoves)) {
2860 if( _ASIC_IS_98001 == ps->sCaps.AsicID )
2861 *p.pb |= 0x80;
2862 else
2863 *p.pb |= 0x40;
2864 bMoves = bMovePerStep;
2865 }
2866 }
2867 }
2868 }
2869 IOSetToMotorRegister( ps );
2870 }
2871
2872 /*.............................................................................
2873 * function to bring the sensor back home
2874 */
2875 _LOC void MotorToHomePosition( pScanData ps )
2876 {
2877 TimerDef timer;
2878 ScanState StateStatus;
2879
2880 DBG( DBG_HIGH, "Waiting for Sensor to be back in position\n" );
2881 _DODELAY( 250 );
2882
2883 if( _ASIC_IS_98001 == ps->sCaps.AsicID ) {
2884
2885 if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){
2886 ps->GotoShadingPosition( ps );
2887 }
2888 } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) {
2889
2890 ps->OpenScanPath( ps );
2891
2892 if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) {
2893
2894 motorP98003PositionModuleToHome( ps );
2895
2896 MiscStartTimer( &timer, _SECOND * 20);
2897 do {
2898
2899 if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)
2900 break;
2901 } while( !MiscCheckTimer( &timer));
2902 }
2903 ps->CloseScanPath( ps );
2904
2905 } else {
2906
2907 if( ps->sCaps.Model >= MODEL_OP_9630P ) {
2908 if( ps->sCaps.Model == MODEL_OP_A3I )
2909 IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x34 );
2910 else
2911 IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x30 );
2912 }
2913
2914 ps->bExtraMotorCtrl = 0;
2915 ps->Scan.fMotorBackward = _FALSE;
2916 MotorP96ConstantMoveProc( ps, 25 );
2917
2918 ps->Scan.fMotorBackward = _TRUE;
2919 for(;;) {
2920
2921 motorP96GetScanStateAndStatus( ps, &StateStatus );
2922
2923 if ( StateStatus.bStatus & _FLAG_P96_PAPER ) {
2924 break;
2925 }
2926
2927 MotorP96ConstantMoveProc( ps, 50000 );
2928 }
2929
2930 ps->Scan.fMotorBackward = _FALSE;
2931 ps->Asic96Reg.RD_MotorControl = 0;
2932 IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
2933
2934 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
2935 IOSetToMotorRegister( ps );
2936 _DODELAY(250);
2937
2938 ps->Asic96Reg.RD_LedControl = 0;
2939 IOCmdRegisterToScanner(ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl);
2940 }
2941
2942 DBG( DBG_HIGH, "- done !\n" );
2943 }
2944
2945 /*.............................................................................
2946 *
2947 */
2948 _LOC void MotorP98GoFullStep( pScanData ps, ULong dwStep )
2949 {
2950 memset( ps->pColorRunTable, 1, dwStep );
2951 memset( ps->pColorRunTable + dwStep, 0xff, 0x40);
2952
2953 ps->bOldStateCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK;
2954 motorP98SetRunFullStep( ps );
2955
2956 ps->pScanState = ps->pColorRunTable;
2957 ps->FillRunNewAdrPointer( ps );
2958
2959 while(!motorCheckMotorPresetLength( ps ))
2960 motorP98FillRunNewAdrPointer1( ps );
2961 }
2962
2963 /*.............................................................................
2964 *
2965 */
2966 _LOC void MotorP96SetSpeedToStopProc( pScanData ps )
2967 {
2968 Byte bData;
2969 TimerDef timer;
2970
2971 MiscStartTimer( &timer, _SECOND);
2972 while( !MiscCheckTimer( &timer )) {
2973
2974 bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset );
2975
2976 if ((bData > ps->bMinReadFifo) && (bData != ps->bFifoCount))
2977 break;
2978 }
2979 bData = IOGetScanState( ps, _FALSE );
2980
2981 if (!(bData & _SCANSTATE_STOP)) {
2982
2983 MiscStartTimer( &timer, (_SECOND / 2));
2984
2985 while (!MiscCheckTimer( &timer )) {
2986
2987 if (IOGetScanState( ps, _FALSE) != bData )
2988 break;
2989 }
2990 }
2991
2992 ps->Scan.bModuleState = _MotorInStopState;
2993 ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _FALSE );
2994
2995 IOSetToMotorRegister( ps );
2996 }
2997
2998 /*.............................................................................
2999 * Position Scan Module to specified line number (Forward or Backward & wait
3000 * for paper flag ON)
3001 */
3002 _LOC void MotorP96ConstantMoveProc( pScanData ps, ULong dwLines )
3003 {
3004 Byte bRemainder, bLastState;
3005 UShort wQuotient;
3006 ULong dwDelayMaxTime;
3007 ScanState StateStatus;
3008 TimerDef timer;
3009 Bool fTimeout = _FALSE;
3010
3011 wQuotient = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS); /* state cycles */
3012 bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS);
3013
3014 /* 3.3 ms per line */
3015 dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2;
3016
3017 MotorSetConstantMove( ps, 1 ); /* step every time */
3018
3019 ps->OpenScanPath( ps );
3020
3021 ps->AsicReg.RD_ModeControl = _ModeScan;
3022 IODataToRegister( ps, ps->RegModeControl, _ModeScan );
3023
3024 if( ps->Scan.fMotorBackward ) {
3025 ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn |
3026 ps->FullStep | ps->bExtraMotorCtrl);
3027 } else {
3028 ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn |
3029 _MotorDirForward | ps->bExtraMotorCtrl);
3030 }
3031
3032 IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl );
3033 ps->CloseScanPath( ps );
3034
3035 bLastState = 0;
3036
3037 MiscStartTimer( &timer, dwDelayMaxTime );
3038
3039 do {
3040
3041 motorP96GetScanStateAndStatus( ps, &StateStatus );
3042
3043 if( ps->Scan.fMotorBackward && (StateStatus.bStatus&_FLAG_P96_PAPER)) {
3044 break;
3045 } else {
3046
3047 /*
3048 * 1) Forward will not reach the sensor.
3049 * 2) Backwarding, doesn't reach the sensor
3050 */
3051 if (wQuotient) {
3052
3053 /* stepped */
3054 if (StateStatus.bStep != bLastState) {
3055 bLastState = StateStatus.bStep;
3056 if (!bLastState) /* done a cycle! */
3057 wQuotient--;
3058 }
3059 } else {
3060 if (StateStatus.bStep >= bRemainder) {
3061 break;
3062 }
3063 }
3064 }
3065
3066 fTimeout = MiscCheckTimer( &timer );
3067
3068 } while ( _OK == fTimeout );
3069
3070 if ( _OK == fTimeout ) {
3071 memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES );
3072 IOSetToMotorRegister( ps );
3073 }
3074 }
3075
3076 /*.............................................................................
3077 *
3078 */
3079 _LOC Bool MotorP96AheadToDarkArea( pScanData ps )
3080 {
3081 Byte bDark;
3082 UShort wTL;
3083 UShort wTotalLastLine;
3084 TimerDef timer;
3085
3086 ps->fColorMoreRedFlag = _FALSE;
3087 ps->fColorMoreBlueFlag = _FALSE;
3088 ps->wOverBlue = 0;
3089
3090 /* FillToDarkCounter () */
3091 memset( ps->a_nbNewAdrPointer, 0x30, _SCANSTATE_BYTES);
3092 MotorSetConstantMove( ps, 2 );
3093
3094 /* SetToDarkRegister () */
3095 ps->AsicReg.RD_ModeControl = _ModeScan;
3096 ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE;
3097 ps->Asic96Reg.RD_MotorControl = _MotorDirForward | ps->FullStep;
3098 ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0;
3099
3100 ps->AsicReg.RD_Dpi = 300;
3101 wTL = 296;
3102 /* if( MODEL_OP_A3I == ps->sCaps.Model ) { */
3103 if( ps->PhysicalDpi > 300 ) {
3104 wTL = 400;
3105 ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 2048);
3106 } else {
3107 ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 1024);
3108 }
3109 ps->AsicReg.RD_Pixels = 512;
3110
3111 IOPutOnAllRegisters( ps );
3112
3113 ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->IgnorePF |
3114 ps->MotorOn | _MotorDirForward );
3115
3116 IOCmdRegisterToScanner( ps, ps->RegMotorControl,
3117 ps->Asic96Reg.RD_MotorControl );
3118
3119 MiscStartTimer( &timer, _SECOND * 2 );
3120 wTotalLastLine = 0;
3121
3122 #ifdef _A3I_EN
3123 while( !MiscCheckTimer( &timer )) {
3124
3125 bDark = motorP96ReadDarkData( ps );
3126
3127 wTotalLastLine++;
3128 if((bDark < 0x80) || (wTotalLastLine==wTL)) {
3129
3130 IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 );
3131 return _TRUE;
3132 }
3133 }
3134 #else
3135 while (!MiscCheckTimer( &timer )) {
3136
3137 bDark = motorP96ReadDarkData( ps );
3138
3139 wTotalLastLine++;
3140 if (((ps->sCaps.AsicID == _ASIC_IS_96001) && (bDark > 0x80)) ||
3141 ((ps->sCaps.AsicID != _ASIC_IS_96001) && (bDark < 0x80)) ||
3142 (wTotalLastLine==wTL)) {
3143
3144 IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeProgram );
3145
3146 if (wTotalLastLine <= 24)
3147 ps->fColorMoreRedFlag = _TRUE;
3148 else
3149 if (wTotalLastLine >= 120) {
3150 ps->wOverBlue = wTotalLastLine - 80;
3151 ps->fColorMoreBlueFlag = _TRUE;
3152 }
3153
3154 return _TRUE;
3155 }
3156 }
3157 #endif
3158
3159 return _FALSE; /* already timed out */
3160 }
3161
3162 /*.............................................................................
3163 * limit the speed settings for 96001/3 based models
3164 */
3165 _LOC void MotorP96AdjustCurrentSpeed( pScanData ps, Byte bSpeed )
3166 {
3167 if (bSpeed != 1) {
3168
3169 if (bSpeed > 34)
3170 ps->bCurrentSpeed = 34;
3171 else
3172 ps->bCurrentSpeed = (bSpeed + 1) & 0xfe;
3173 }
3174 }
3175
3176 /*.............................................................................
3177 *
3178 */
3179 _LOC void MotorP98003ForceToLeaveHomePos( pScanData ps )
3180 {
3181 TimerDef timer;
3182
3183 IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP );
3184 IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR );
3185
3186 MiscStartTimer( &timer, _SECOND );
3187
3188 do {
3189 if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER))
3190 break;
3191
3192 IORegisterToScanner( ps, ps->RegForceStep );
3193 _DODELAY( 10 );
3194
3195 } while( _OK == MiscCheckTimer( &timer ));
3196
3197 IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
3198 }
3199
3200 /*.............................................................................
3201 *
3202 */
3203 _LOC void MotorP98003BackToHomeSensor( pScanData ps )
3204 {
3205 TimerDef timer;
3206
3207 DBG( DBG_HIGH, "MotorP98003BackToHomeSensor()\n" );
3208
3209 IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE );
3210 IODataToRegister( ps, ps->RegModeControl, _ModeScan );
3211
3212 /* stepping every state */
3213 memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES );
3214 IODownloadScanStates( ps );
3215
3216 MiscStartTimer( &timer, _SECOND * 2 );
3217
3218 while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) &&
3219 !MiscCheckTimer( &timer ))
3220 ;
3221
3222 _DODELAY( 1000UL );
3223
3224 ps->AsicReg.RD_ModeControl = _ModeScan;
3225
3226 if (!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) {
3227 IODataToRegister( ps, ps->RegLineControl, _LOBYTE(ps->Shade.wExposure));
3228 IODataToRegister( ps, ps->RegXStepTime, _LOBYTE(ps->Shade.wXStep));
3229
3230 } else {
3231 IODataToRegister( ps, ps->RegLineControl, _DEFAULT_LINESCANTIME );
3232 IODataToRegister( ps, ps->RegXStepTime, 6);
3233 }
3234
3235 IODataToRegister( ps, ps->RegStepControl,
3236 (_MOTOR_FREERUN | _MOTOR0_SCANSTATE));
3237 IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl );
3238 IODataToRegister( ps, ps->RegMotor0Control,
3239 (_MotorHQuarterStep | _MotorOn | _MotorDirBackward |
3240 _MotorPowerEnable | _MotorHHomeStop));
3241 IORegisterToScanner( ps, ps->RegRefreshScanState );
3242
3243 MiscStartTimer( &timer, _SECOND * 5 );
3244
3245 do {
3246 if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER )
3247 break;
3248
3249 _DODELAY( 55 );
3250
3251 } while( !MiscCheckTimer( &timer ));
3252
3253 IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl);
3254 IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime);
3255
3256 DBG( DBG_HIGH, "LineCtrl=%u, XStepTime=%u\n",
3257 ps->AsicReg.RD_LineControl, ps->AsicReg.RD_XStepTime );
3258
3259 motorP98003DownloadNullScanStates( ps );
3260 }
3261
3262 /*.............................................................................
3263 *
3264 */
3265 _LOC void MotorP98003ModuleForwardBackward( pScanData ps )
3266 {
3267 switch( ps->Scan.bModuleState ) {
3268
3269 case _MotorInNormalState:
3270 ps->Scan.bModuleState = _MotorGoBackward;
3271 IODataToRegister( ps, ps->RegScanControl1,
3272 (UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
3273 IODataToRegister( ps, ps->RegMotor0Control,
3274 (UChar)(ps->AsicReg.RD_Motor0Control & ~_MotorDirForward));
3275 motorP98003ModuleFreeRun( ps, _P98003_BACKSTEPS );
3276 MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND));
3277 break;
3278
3279 case _MotorGoBackward:
3280 if( MiscCheckTimer(& p98003MotorTimer)) {
3281 if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) {
3282 ps->Scan.bModuleState = _MotorInStopState;
3283 MiscStartTimer( &p98003MotorTimer, (50 *_MSECOND));
3284 }
3285 }
3286 break;
3287
3288 case _MotorInStopState:
3289 if( MiscCheckTimer(&p98003MotorTimer)) {
3290
3291 if( IOReadFifoLength( ps ) < ps->Scan.dwMaxReadFifo ) {
3292 ps->Scan.bModuleState = _MotorAdvancing;
3293 IODataToRegister( ps, ps->RegScanControl1, ps->AsicReg.RD_ScanControl1);
3294 IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control);
3295 motorP98003ModuleFreeRun( ps, _P98003_FORWARDSTEPS );
3296 MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND));
3297 }
3298 }
3299 break;
3300
3301 case _MotorAdvancing:
3302 if( MiscCheckTimer(&p98003MotorTimer)) {
3303 if( !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP))
3304 ps->Scan.bModuleState = _MotorInNormalState;
3305 else {
3306 if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) {
3307 IORegisterToScanner( ps, ps->RegRefreshScanState );
3308 ps->Scan.bModuleState = _MotorInNormalState;
3309 }
3310 }
3311 }
3312 break;
3313 }
3314 }
3315
3316 /*.............................................................................
3317 *
3318 */
3319 _LOC void MotorP98003PositionYProc( pScanData ps, ULong steps)
3320 {
3321 TimerDef timer;
3322
3323 DBG( DBG_HIGH, "MotorP98003PositionYProc()\n" );
3324
3325 MiscStartTimer( &timer, _SECOND * 5 );
3326
3327 while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) &&
3328 !MiscCheckTimer( &timer ))
3329 ;
3330
3331 _DODELAY( 12 );
3332
3333 motorP98003ModuleFreeRun( ps, steps );
3334
3335 _DODELAY( 15 );
3336
3337 MiscStartTimer( &timer, _SECOND * 30 );
3338
3339 do {
3340 if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) ||
3341 !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP))
3342 break;
3343
3344 } while( !MiscCheckTimer( &timer ));
3345
3346 DBG( DBG_HIGH, "MotorP98003PositionYProc() - done\n" );
3347 }
3348
3349 /* END PLUSTEK-PP_MOTOR.C ...................................................*/
3350