1 /* @file u12-motor.c
2  * @brief all functions for motor control
3  *
4  * based on sources acquired from Plustek Inc.
5  * Copyright (C) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de>
6  *
7  * History:
8  * - 0.01 - initial version
9  * - 0.02 - no changes
10  * .
11  * <hr>
12  * This file is part of the SANE package.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
26  *
27  * As a special exception, the authors of SANE give permission for
28  * additional uses of the libraries contained in this release of SANE.
29  *
30  * The exception is that, if you link a SANE library with other files
31  * to produce an executable, this does not by itself cause the
32  * resulting executable to be covered by the GNU General Public
33  * License.  Your use of that executable is in no way restricted on
34  * account of linking the SANE library code into it.
35  *
36  * This exception does not, however, invalidate any other reasons why
37  * the executable file might be covered by the GNU General Public
38  * License.
39  *
40  * If you submit changes to SANE to the maintainers to be included in
41  * a subsequent release, you agree by submitting the changes that
42  * those changes may be distributed with this exception intact.
43  *
44  * If you write modifications of your own for SANE, it is your choice
45  * whether to permit this exception to apply to your modifications.
46  * If you do not wish that, delete this exception notice.
47  * <hr>
48  */
49 
50 /*************************** some definitions *********************************/
51 
52 #define _BACKSTEPS     120
53 #define _FORWARDSTEPS  120
54 
55 /**************************** local vars *************************************/
56 
57 static TimerDef u12motor_Timer;
58 
59 
60 /*************************** local functions *********************************/
61 
62 /**
63  */
u12motor_DownloadNullScanStates(U12_Device * dev)64 static void u12motor_DownloadNullScanStates( U12_Device *dev )
65 {
66 	memset( dev->scanStates, 0, _SCANSTATE_BYTES );
67 	u12io_DownloadScanStates( dev );
68 }
69 
70 /**
71  */
u12motor_Force16Steps(U12_Device * dev,int dir)72 static void u12motor_Force16Steps( U12_Device *dev, int dir )
73 {
74 	u_long dw;
75 
76 	if( dir == _DIR_FW )
77 		u12io_DataToRegister( dev, REG_MOTOR0CONTROL, _FORWARD_MOTOR );
78 	else if( dir == _DIR_BW )
79 		u12io_DataToRegister( dev, REG_MOTOR0CONTROL, _BACKWARD_MOTOR );
80 
81 	for( dw = 16; dw; dw-- ) {
82 		u12io_RegisterToScanner( dev, REG_FORCESTEP );
83 		_DODELAY( 10 );
84 	}
85 }
86 
87 /**
88  */
u12motor_ModuleFreeRun(U12_Device * dev,u_long steps)89 static void u12motor_ModuleFreeRun( U12_Device *dev, u_long steps )
90 {
91 	SANE_Byte rb[6];
92 
93 	rb[0] = REG_MOTORFREERUNCOUNT1;  rb[1] = _HIBYTE(steps);
94 	rb[2] = REG_MOTORFREERUNCOUNT0;  rb[3] = _LOBYTE(steps);
95 	rb[4] = REG_MOTORFREERUNTRIGGER; rb[5] = 0;
96 
97 	u12io_DataToRegs( dev, rb, 3 );
98 }
99 
100 /**
101  */
u12motor_PositionYProc(U12_Device * dev,u_long steps)102 static SANE_Status u12motor_PositionYProc( U12_Device *dev, u_long steps )
103 {
104 	TimerDef timer;
105 
106 	DBG( _DBG_INFO, "u12motor_PositionYProc()\n" );
107 	u12io_StartTimer( &timer, _SECOND * 5 );
108 
109 	u12io_ResetFifoLen();
110 	while(!(u12io_GetScanState( dev ) & _SCANSTATE_STOP) &&
111                                                 (!u12io_CheckTimer( &timer )));
112 	_DODELAY( 12 );
113 	u12motor_ModuleFreeRun( dev, steps );
114 	_DODELAY( 15 );
115 
116 	u12io_StartTimer( &timer, _SECOND * 30 );
117 	do  {
118 		if( !(u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING)) {
119 			break;
120 		}
121 
122 		if( u12io_IsEscPressed()) {
123 			DBG( _DBG_INFO, "* CANCEL detected!\n" );
124 			return SANE_STATUS_CANCELLED;
125 		}
126 
127 	} while( !u12io_CheckTimer( &timer ));
128 	DBG( _DBG_INFO, "u12motor_PositionYProc() - done\n" );
129 	return SANE_STATUS_GOOD;
130 }
131 
132 /** initialize this module and setup the correct function pointer according
133  * to the ASIC
134  */
u12motor_PositionModuleToHome(U12_Device * dev)135 static void u12motor_PositionModuleToHome( U12_Device *dev )
136 {
137 	SANE_Byte rb[50];
138 	SANE_Byte save, saveModel;
139 	int       c = 0;
140 
141 	DBG( _DBG_INFO, "u12motor_PositionModuleToHome()\n" );
142 	saveModel = dev->regs.RD_ModelControl;
143 
144 	dev->scan.refreshState = SANE_FALSE;
145 	u12motor_DownloadNullScanStates( dev );
146 
147 	_DODELAY( 125 );
148 	save = dev->shade.intermediate;
149 
150 	dev->shade.intermediate = _ScanMode_AverageOut;
151 	u12hw_InitAsic( dev, SANE_FALSE );
152 	dev->shade.intermediate = save;
153 
154 	_SET_REG( rb, c, REG_MODECONTROL, _ModeScan );
155 	_SET_REG( rb, c, REG_RESETMTSC, 0 );
156 	_SET_REG( rb, c, REG_SCANCONTROL1, 0 );
157 	_SET_REG( rb, c, REG_MODELCONTROL, (dev->ModelCtrl | _MODEL_DPI300));
158 	_SET_REG( rb, c, REG_LINECONTROL, 80 );
159 	_SET_REG( rb, c, REG_XSTEPTIME, dev->XStepBack );
160 	_SET_REG( rb, c, REG_MOTORDRVTYPE, dev->MotorPower );
161 	_SET_REG( rb, c, REG_MOTOR0CONTROL, (_MotorHHomeStop | _MotorOn |
162 	                                  _MotorHQuarterStep | _MotorPowerEnable));
163 	_SET_REG( rb, c, REG_STEPCONTROL, (_MOTOR0_SCANSTATE | _MOTOR_FREERUN));
164 	u12io_DataToRegs( dev, rb, c );
165 
166 	memset( dev->scanStates, 0x88, _SCANSTATE_BYTES );
167 	u12io_DownloadScanStates( dev );
168 
169 	u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE );
170 	dev->regs.RD_ModelControl = saveModel;
171 }
172 
173 /** function to bring the sensor back home
174  */
u12motor_ToHomePosition(U12_Device * dev,SANE_Bool wait)175 static void u12motor_ToHomePosition( U12_Device *dev, SANE_Bool wait )
176 {
177 	TimerDef  timer;
178 
179 	DBG( _DBG_INFO, "Waiting for Sensor to be back in position\n" );
180 	if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) {
181 
182 		u12motor_PositionModuleToHome( dev );
183 
184 		if( wait ) {
185 			u12io_StartTimer( &timer, _SECOND * 20);
186 			do {
187 				if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)
188 					break;
189 			} while( !u12io_CheckTimer( &timer ));
190 		}
191 	}
192 	DBG( _DBG_INFO, "- done !\n" );
193 }
194 
195 /**
196  */
u12motor_BackToHomeSensor(U12_Device * dev)197 static SANE_Status u12motor_BackToHomeSensor( U12_Device *dev )
198 {
199 	SANE_Byte rb[20];
200 	int       c;
201 	TimerDef  timer;
202 
203 	DBG( _DBG_INFO, "u12Motor_BackToHomeSensor()\n" );
204 
205 	c = 0;
206 	_SET_REG( rb, c, REG_STEPCONTROL, _MOTOR0_SCANSTATE );
207 	_SET_REG( rb, c, REG_MODECONTROL, _ModeScan );
208 
209 	u12io_DataToRegs( dev, rb, c );
210 
211 	u12motor_Force16Steps( dev, _DIR_NONE );
212 
213 	/* stepping every state */
214 	memset( dev->scanStates, 0x88, _SCANSTATE_BYTES );
215 	u12io_DownloadScanStates( dev );
216 	_DODELAY(50);
217 
218 	u12io_StartTimer( &timer, _SECOND * 2 );
219 
220 	u12io_ResetFifoLen();
221 	while(!(u12io_GetScanState( dev ) & _SCANSTATE_STOP) &&
222                                                   !u12io_CheckTimer( &timer )) {
223 		if( u12io_IsEscPressed()) {
224 			DBG( _DBG_INFO, "* CANCEL detected!\n" );
225 			return SANE_STATUS_CANCELLED;
226 		}
227 	}
228 
229 	u12motor_Force16Steps( dev, _DIR_BW );
230 	dev->regs.RD_ModeControl = _ModeScan;
231 
232 	c = 0;
233 
234 	if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) {
235 		_SET_REG( rb, c, REG_LINECONTROL, _LOBYTE(dev->shade.wExposure));
236 		_SET_REG( rb, c, REG_XSTEPTIME,   _LOBYTE(dev->shade.wXStep));
237 	} else {
238 		_SET_REG( rb, c, REG_LINECONTROL, _DEFAULT_LINESCANTIME );
239 		_SET_REG( rb, c, REG_XSTEPTIME,   6 );
240 	}
241 
242 	_SET_REG( rb, c, REG_STEPCONTROL, (_MOTOR_FREERUN | _MOTOR0_SCANSTATE));
243 	_SET_REG( rb, c, REG_MOTOR0CONTROL,
244 	                  (_MotorHQuarterStep | _MotorOn | _MotorDirBackward |
245                                     	_MotorPowerEnable | _MotorHHomeStop));
246 	_SET_REG( rb, c, REG_REFRESHSCANSTATE, 0);
247 	u12io_DataToRegs( dev, rb, c );
248 
249 	u12io_StartTimer( &timer, _SECOND * 5 );
250 	do {
251 		if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER )
252 			break;
253 
254 		if( u12io_IsEscPressed()) {
255 			DBG( _DBG_INFO, "* CANCEL detected!\n" );
256 			return SANE_STATUS_CANCELLED;
257 		}
258 
259 		_DODELAY( 55 );
260 
261 	} while( !u12io_CheckTimer( &timer ));
262 
263 	c = 0;
264 	_SET_REG( rb, c, REG_LINECONTROL, dev->regs.RD_LineControl);
265 	_SET_REG( rb, c, REG_XSTEPTIME,   dev->regs.RD_XStepTime);
266 	u12io_DataToRegs( dev, rb, c );
267 
268 	DBG( _DBG_INFO, "* LineCtrl=0x%02x, XStepTime=0x%02x\n",
269 	                dev->regs.RD_LineControl, dev->regs.RD_XStepTime );
270 
271 	u12motor_DownloadNullScanStates( dev );
272 	return SANE_STATUS_GOOD;
273 }
274 
275 /**
276  */
u12motor_ModuleToHome(U12_Device * dev)277 static SANE_Status u12motor_ModuleToHome( U12_Device *dev )
278 {
279 	SANE_Status res;
280 
281 	DBG( _DBG_INFO, "u12motor_ModuleToHome()\n" );
282 	if(!(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) {
283 
284 		u12io_DataToRegister( dev, REG_MOTOR0CONTROL,
285 		             (SANE_Byte)(dev->regs.RD_Motor0Control|_MotorDirForward));
286 
287 		res = u12motor_PositionYProc( dev, 40 );
288 		if( SANE_STATUS_GOOD != res )
289 			return res;
290 
291 		res = u12motor_BackToHomeSensor( dev );
292 		if( SANE_STATUS_GOOD != res )
293 			return res;
294 
295 		_DODELAY( 250 );
296 	}
297 	DBG( _DBG_INFO, "* done.\n" );
298 	return SANE_STATUS_GOOD;
299 }
300 
301 /**
302  */
u12motor_WaitForPositionY(U12_Device * dev)303 static SANE_Status u12motor_WaitForPositionY( U12_Device *dev )
304 {
305 	SANE_Byte   rb[20];
306 	SANE_Status res;
307 	SANE_Byte   bXStep;
308 	int         c;
309 	u_long      dwBeginY;
310 
311 	c        = 0;
312 	dwBeginY = (u_long)dev->DataInf.crImage.y * 4 + dev->scan.dwScanOrigin;
313 
314 	if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) {
315 		if( dev->f0_8_16 )
316 			dwBeginY += 16;
317     	else
318 			dwBeginY += 8;
319 	}
320 
321 	bXStep = (SANE_Byte)((dev->DataInf.wPhyDataType <= COLOR_256GRAY) ?
322 	                      dev->XStepMono : dev->XStepColor);
323 
324 	if( dev->shade.intermediate & _ScanMode_AverageOut )
325 		bXStep = 8;
326 
327 	u12motor_Force16Steps( dev, _DIR_NONE );
328 	dwBeginY -= 16;
329 
330 	if( dwBeginY > (_RFT_SCANNING_ORG + _YOFFSET) &&
331 	                                        bXStep < dev->regs.RD_XStepTime ) {
332 
333 		u12io_DataToRegister( dev, REG_MOTORDRVTYPE, dev->MotorPower );
334 		_DODELAY( 12 );
335 		u12io_DataToRegister( dev, REG_XSTEPTIME, bXStep);
336 		u12io_DataToRegister( dev, REG_EXTENDEDXSTEP, 0 );
337 		u12io_DataToRegister( dev, REG_SCANCONTROL1,
338 		         (SANE_Byte)(dev->regs.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
339 		res = u12motor_PositionYProc( dev, dwBeginY - 64 );
340 		if( SANE_STATUS_GOOD != res )
341 			return res;
342 		dwBeginY = 64;
343 	} else {
344 		_SET_REG(rb, c, REG_SCANCONTROL1, dev->regs.RD_ScanControl1 );
345 	}
346 
347 	_SET_REG( rb, c, REG_FIFOFULLEN0, _LOBYTE(dev->regs.RD_BufFullSize));
348 	_SET_REG( rb, c, REG_FIFOFULLEN1, _HIBYTE(dev->regs.RD_BufFullSize));
349 	_SET_REG( rb, c, REG_FIFOFULLEN2, _LOBYTE(_HIWORD(dev->regs.RD_BufFullSize)));
350 	u12io_DataToRegs( dev, rb, c );
351 
352 	u12io_DataToRegister( dev, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType);
353 	_DODELAY( 12 );
354 
355 	if(!dev->f2003 || (dev->shade.intermediate & _ScanMode_AverageOut) ||
356 		    (  dev->DataInf.xyAppDpi.y <= 75 &&
357 	                              dev->DataInf.wPhyDataType <= COLOR_256GRAY)) {
358 		u12io_DataToRegister( dev, REG_MOTORDRVTYPE,
359 	                (SANE_Byte)(dev->MotorPower & (_MOTORR_MASK | _MOTORR_STRONG)));
360 	} else {
361 		u12io_DataToRegister( dev, REG_MOTORDRVTYPE,
362 	                          dev->regs.RD_MotorDriverType );
363 	}
364 
365 	c = 0;
366 	_SET_REG( rb, c, REG_XSTEPTIME,     dev->regs.RD_XStepTime );
367 	_SET_REG( rb, c, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime );
368 	_SET_REG( rb, c, REG_SCANCONTROL1,
369                     (SANE_Byte)(dev->regs.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
370 	u12io_DataToRegs( dev, rb, c );
371 
372 	if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) {
373 
374 		TimerDef timer;
375 
376 		u12motor_ModuleFreeRun( dev, dwBeginY );
377 		_DODELAY( 15 );
378 
379 		u12io_StartTimer( &timer, (_SECOND * 20));
380 
381 		while(( u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING) &&
382 		                                             !u12io_CheckTimer(&timer));
383 		u12io_DataToRegister( dev, REG_MODECONTROL, _ModeScan );
384 	} else {
385 		u12motor_PositionYProc( dev, dwBeginY );
386 		u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE );
387 	}
388 	return SANE_STATUS_GOOD;
389 }
390 
391 /**
392  */
u12motor_ForceToLeaveHomePos(U12_Device * dev)393 static void u12motor_ForceToLeaveHomePos( U12_Device *dev )
394 {
395 	SANE_Byte rb[4];
396 	TimerDef  timer;
397 
398 	DBG( _DBG_INFO, "u12motor_ForceToLeaveHomePos()\n" );
399 	rb[0] = REG_STEPCONTROL;
400 	rb[1] = _MOTOR0_ONESTEP;
401 	rb[2] = REG_MOTOR0CONTROL;
402 	rb[3] = _FORWARD_MOTOR;
403 	u12io_DataToRegs( dev, rb, 2 );
404 
405 	u12io_StartTimer( &timer, _SECOND );
406 
407 	do {
408 		if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER))
409 			break;
410 
411 		u12io_RegisterToScanner( dev, REG_FORCESTEP );
412 		_DODELAY( 10 );
413 
414 	} while( !u12io_CheckTimer( &timer ));
415 
416 	u12io_DataToRegister( dev, REG_STEPCONTROL, _MOTOR0_SCANSTATE );
417 }
418 
419 /** move the sensor to the appropriate shading position
420  */
u12motor_GotoShadingPosition(U12_Device * dev)421 static SANE_Status u12motor_GotoShadingPosition( U12_Device *dev )
422 {
423 	SANE_Byte   rb[20];
424 	SANE_Status res;
425 	int         c;
426 
427 	DBG( _DBG_INFO, "u12motor_GotoShadingPosition()\n" );
428 	res = u12motor_ModuleToHome( dev );
429 	if( SANE_STATUS_GOOD == res )
430 		return res;
431 
432 	/* position to somewhere under the transparency adapter */
433 	if( dev->DataInf.dwScanFlag & _SCANDEF_TPA ) {
434 
435 		u12motor_ForceToLeaveHomePos( dev );
436 		u12motor_DownloadNullScanStates( dev );
437 
438 		c = 0;
439 		_SET_REG( rb, c, REG_STEPCONTROL, _MOTOR0_SCANSTATE );
440 		_SET_REG( rb, c, REG_MODECONTROL, _ModeScan);
441 		_SET_REG( rb, c, REG_MOTOR0CONTROL, _FORWARD_MOTOR );
442 		_SET_REG( rb, c, REG_XSTEPTIME, 6);
443 		_SET_REG( rb, c, REG_EXTENDEDXSTEP, 0);
444 		_SET_REG( rb, c, REG_SCANCONTROL1, _MFRC_BY_XSTEP);
445 		u12io_DataToRegs( dev, rb, c );
446 
447 		res = u12motor_PositionYProc( dev, _TPA_SHADINGORG );
448 		if( SANE_STATUS_GOOD != res )
449 			return res;
450 	}
451 	DBG( _DBG_INFO, "* Position reached\n" );
452 	return SANE_STATUS_GOOD;
453 }
454 
455 /**
456  */
u12motor_ModuleForwardBackward(U12_Device * dev)457 static void u12motor_ModuleForwardBackward( U12_Device *dev )
458 {
459 	DBG( _DBG_INFO, "u12motor_ModuleForwardBackward()\n" );
460 
461 	switch( dev->scan.bModuleState ) {
462 
463 	case _MotorInNormalState:
464 		DBG( _DBG_INFO, "* _MotorInNormalState\n" );
465 		dev->scan.bModuleState = _MotorGoBackward;
466 		u12io_DataToRegister( dev, REG_SCANCONTROL1,
467 			     (SANE_Byte)(dev->regs.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE));
468 		u12io_DataToRegister( dev, REG_MOTOR0CONTROL,
469 			      (SANE_Byte)(dev->regs.RD_Motor0Control & ~_MotorDirForward));
470 
471 		u12motor_ModuleFreeRun( dev, _BACKSTEPS );
472 		u12io_StartTimer( &u12motor_Timer, (15 * _MSECOND));
473 		break;
474 
475 	case _MotorGoBackward:
476 		DBG( _DBG_INFO, "* _MotorGoBackward\n" );
477 		if( u12io_CheckTimer( &u12motor_Timer)) {
478 			if(!(u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING )) {
479 				dev->scan.bModuleState = _MotorInStopState;
480 				u12io_StartTimer( &u12motor_Timer, (50 *_MSECOND));
481 			}
482 		}
483 		break;
484 
485 	case _MotorInStopState:
486 		DBG( _DBG_INFO, "* _MotorInStopState\n" );
487 		if( u12io_CheckTimer( &u12motor_Timer )) {
488 
489 			if( u12io_GetFifoLength( dev ) < dev->scan.dwMaxReadFifo ) {
490 				dev->scan.bModuleState = _MotorAdvancing;
491 				u12io_DataToRegister( dev, REG_SCANCONTROL1,
492 				                                    dev->regs.RD_ScanControl1);
493 				u12io_DataToRegister( dev, REG_MOTOR0CONTROL,
494 				                                    dev->regs.RD_Motor0Control);
495 				u12motor_ModuleFreeRun( dev, _FORWARDSTEPS );
496 				u12io_StartTimer( &u12motor_Timer, (15 * _MSECOND));
497 			}
498 		}
499 		break;
500 
501 	case _MotorAdvancing:
502 		DBG( _DBG_INFO, "* _MotorAdvancing\n" );
503 		if( u12io_CheckTimer( &u12motor_Timer)) {
504 			if( !(u12io_GetScanState( dev ) & _SCANSTATE_STOP))
505 				dev->scan.bModuleState = _MotorInNormalState;
506 			else {
507 				if (!(u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING )) {
508 					u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE );
509 					dev->scan.bModuleState = _MotorInNormalState;
510 				}
511 			}
512 		}
513 		break;
514 	}
515 }
516 
517 /* END U12-MOTOR.C ..........................................................*/
518