1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) Marian Eichholz 2001
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
38141cc406Sopenharmony_ci*/
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ci/* ======================================================================
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ciUserspace scan tool for the Microtek 3600 scanner
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_cigrayscale scan routine
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci(C) Marian Eichholz 2001
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci====================================================================== */
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#include "sm3600-scantool.h"
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_ci/* **********************************************************************
53141cc406Sopenharmony_ci
54141cc406Sopenharmony_ciDoScanGray()
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_ci********************************************************************** */
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci#define LINE_THRESHOLD   0x800
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_cistatic unsigned char uchRegs075[]={
61141cc406Sopenharmony_ci   /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x20,
62141cc406Sopenharmony_ci   /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06,
63141cc406Sopenharmony_ci   /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F,
64141cc406Sopenharmony_ci   /*R_LEN*/ 0x28, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D,
65141cc406Sopenharmony_ci   /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0,
66141cc406Sopenharmony_ci   /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x40,
67141cc406Sopenharmony_ci   /*0x13*/ 0x15, /*0x14*/ 0x80, /*0x15*/ 0x2A,
68141cc406Sopenharmony_ci   /*0x16*/ 0xC0, /*0x17*/ 0x40, /*0x18*/ 0xC0,
69141cc406Sopenharmony_ci   /*0x19*/ 0x40, /*0x1A*/ 0xFF, /*0x1B*/ 0x01,
70141cc406Sopenharmony_ci   /*0x1C*/ 0x88, /*0x1D*/ 0x40, /*0x1E*/ 0x4C,
71141cc406Sopenharmony_ci   /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C,
72141cc406Sopenharmony_ci   /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40,
73141cc406Sopenharmony_ci   /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0,
74141cc406Sopenharmony_ci   /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E,
75141cc406Sopenharmony_ci   /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00,
76141cc406Sopenharmony_ci   /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80,
77141cc406Sopenharmony_ci   /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20,
78141cc406Sopenharmony_ci   /*0x34*/ 0x83, /*0x35*/ 0x29, /*0x36*/ 0x00,
79141cc406Sopenharmony_ci   /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00,
80141cc406Sopenharmony_ci   /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF,
81141cc406Sopenharmony_ci   /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00,
82141cc406Sopenharmony_ci   /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x00,
83141cc406Sopenharmony_ci   /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00,
84141cc406Sopenharmony_ci   /*R_CTL*/ 0x39, /*0x47*/ 0xC0, /*0x48*/ 0x40,
85141cc406Sopenharmony_ci   /*0x49*/ 0x9E, /*0x4A*/ 0x8C };
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_cistatic unsigned char uchRegs100[]={
88141cc406Sopenharmony_ci   /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x20,
89141cc406Sopenharmony_ci   /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06,
90141cc406Sopenharmony_ci   /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F,
91141cc406Sopenharmony_ci   /*R_LEN*/ 0x34, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D,
92141cc406Sopenharmony_ci   /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0,
93141cc406Sopenharmony_ci   /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x42,
94141cc406Sopenharmony_ci   /*0x13*/ 0x15, /*0x14*/ 0x84, /*0x15*/ 0x2A,
95141cc406Sopenharmony_ci   /*0x16*/ 0xC2, /*0x17*/ 0x40, /*0x18*/ 0xC2,
96141cc406Sopenharmony_ci   /*0x19*/ 0x40, /*0x1A*/ 0xFF, /*0x1B*/ 0x01,
97141cc406Sopenharmony_ci   /*0x1C*/ 0x88, /*0x1D*/ 0x40, /*0x1E*/ 0x4C,
98141cc406Sopenharmony_ci   /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C,
99141cc406Sopenharmony_ci   /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40,
100141cc406Sopenharmony_ci   /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0,
101141cc406Sopenharmony_ci   /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E,
102141cc406Sopenharmony_ci   /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00,
103141cc406Sopenharmony_ci   /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80,
104141cc406Sopenharmony_ci   /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20,
105141cc406Sopenharmony_ci   /*0x34*/ 0x63, /*0x35*/ 0x29, /*0x36*/ 0x00,
106141cc406Sopenharmony_ci   /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00,
107141cc406Sopenharmony_ci   /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF,
108141cc406Sopenharmony_ci   /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00,
109141cc406Sopenharmony_ci   /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80,
110141cc406Sopenharmony_ci   /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00,
111141cc406Sopenharmony_ci   /*R_CTL*/ 0x39, /*0x47*/ 0xC2, /*0x48*/ 0x40,
112141cc406Sopenharmony_ci   /*0x49*/ 0x9E, /*0x4A*/ 0x8C };
113141cc406Sopenharmony_ci
114141cc406Sopenharmony_cistatic unsigned char uchRegs200[]={
115141cc406Sopenharmony_ci   /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x24,
116141cc406Sopenharmony_ci   /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06,
117141cc406Sopenharmony_ci   /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F,
118141cc406Sopenharmony_ci   /*R_LEN*/ 0x22, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D,
119141cc406Sopenharmony_ci   /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0,
120141cc406Sopenharmony_ci   /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x42,
121141cc406Sopenharmony_ci   /*0x13*/ 0x15, /*0x14*/ 0x42, /*0x15*/ 0x15,
122141cc406Sopenharmony_ci   /*0x16*/ 0x42, /*0x17*/ 0x15, /*0x18*/ 0x42,
123141cc406Sopenharmony_ci   /*0x19*/ 0x15, /*0x1A*/ 0x07, /*0x1B*/ 0x00,
124141cc406Sopenharmony_ci   /*0x1C*/ 0x08, /*0x1D*/ 0x12, /*0x1E*/ 0x4C,
125141cc406Sopenharmony_ci   /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C,
126141cc406Sopenharmony_ci   /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40,
127141cc406Sopenharmony_ci   /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0,
128141cc406Sopenharmony_ci   /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E,
129141cc406Sopenharmony_ci   /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00,
130141cc406Sopenharmony_ci   /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80,
131141cc406Sopenharmony_ci   /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20,
132141cc406Sopenharmony_ci   /*0x34*/ 0x43, /*0x35*/ 0x29, /*0x36*/ 0x00,
133141cc406Sopenharmony_ci   /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00,
134141cc406Sopenharmony_ci   /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF,
135141cc406Sopenharmony_ci   /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00,
136141cc406Sopenharmony_ci   /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80,
137141cc406Sopenharmony_ci   /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00,
138141cc406Sopenharmony_ci   /*R_CTL*/ 0x39, /*0x47*/ 0x42, /*0x48*/ 0x15,
139141cc406Sopenharmony_ci   /*0x49*/ 0x9E, /*0x4A*/ 0x8C };
140141cc406Sopenharmony_ci
141141cc406Sopenharmony_cistatic unsigned char uchRegs300[]={
142141cc406Sopenharmony_ci   /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x2A,
143141cc406Sopenharmony_ci   /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06,
144141cc406Sopenharmony_ci   /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x2A,
145141cc406Sopenharmony_ci   /*R_LEN*/ 0x16, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D,
146141cc406Sopenharmony_ci   /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0,
147141cc406Sopenharmony_ci   /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x40,
148141cc406Sopenharmony_ci   /*0x13*/ 0x15, /*0x14*/ 0x40, /*0x15*/ 0x15,
149141cc406Sopenharmony_ci   /*0x16*/ 0x40, /*0x17*/ 0x15, /*0x18*/ 0x40,
150141cc406Sopenharmony_ci   /*0x19*/ 0x15, /*0x1A*/ 0x07, /*0x1B*/ 0x00,
151141cc406Sopenharmony_ci   /*0x1C*/ 0x08, /*0x1D*/ 0x12, /*0x1E*/ 0x4C,
152141cc406Sopenharmony_ci   /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C,
153141cc406Sopenharmony_ci   /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40,
154141cc406Sopenharmony_ci   /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0,
155141cc406Sopenharmony_ci   /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E,
156141cc406Sopenharmony_ci   /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00,
157141cc406Sopenharmony_ci   /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80,
158141cc406Sopenharmony_ci   /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20,
159141cc406Sopenharmony_ci   /*0x34*/ 0x03, /*0x35*/ 0x29, /*0x36*/ 0x00,
160141cc406Sopenharmony_ci   /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00,
161141cc406Sopenharmony_ci   /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF,
162141cc406Sopenharmony_ci   /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00,
163141cc406Sopenharmony_ci   /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80,
164141cc406Sopenharmony_ci   /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00,
165141cc406Sopenharmony_ci   /*R_CTL*/ 0x39, /*0x47*/ 0x40, /*0x48*/ 0x15,
166141cc406Sopenharmony_ci   /*0x49*/ 0x96, /*0x4A*/ 0x8C };
167141cc406Sopenharmony_ci
168141cc406Sopenharmony_cistatic unsigned char uchRegs600[]={
169141cc406Sopenharmony_ci   /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x3F,
170141cc406Sopenharmony_ci   /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06,
171141cc406Sopenharmony_ci   /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F,
172141cc406Sopenharmony_ci   /*R_LEN*/ 0x16, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D,
173141cc406Sopenharmony_ci   /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0,
174141cc406Sopenharmony_ci   /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x42,
175141cc406Sopenharmony_ci   /*0x13*/ 0x15, /*0x14*/ 0x42, /*0x15*/ 0x15,
176141cc406Sopenharmony_ci   /*0x16*/ 0x42, /*0x17*/ 0x15, /*0x18*/ 0x42,
177141cc406Sopenharmony_ci   /*0x19*/ 0x15, /*0x1A*/ 0x07, /*0x1B*/ 0x00,
178141cc406Sopenharmony_ci   /*0x1C*/ 0x08, /*0x1D*/ 0x12, /*0x1E*/ 0x4C,
179141cc406Sopenharmony_ci   /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C,
180141cc406Sopenharmony_ci   /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40,
181141cc406Sopenharmony_ci   /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0,
182141cc406Sopenharmony_ci   /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E,
183141cc406Sopenharmony_ci   /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00,
184141cc406Sopenharmony_ci   /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80,
185141cc406Sopenharmony_ci   /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20,
186141cc406Sopenharmony_ci   /*0x34*/ 0x03, /*0x35*/ 0x29, /*0x36*/ 0x00,
187141cc406Sopenharmony_ci   /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00,
188141cc406Sopenharmony_ci   /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF,
189141cc406Sopenharmony_ci   /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00,
190141cc406Sopenharmony_ci   /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80,
191141cc406Sopenharmony_ci   /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00,
192141cc406Sopenharmony_ci   /*R_CTL*/ 0x39, /*0x47*/ 0x42, /*0x48*/ 0x15,
193141cc406Sopenharmony_ci   /*0x49*/ 0x96, /*0x4A*/ 0x8C };
194141cc406Sopenharmony_ci
195141cc406Sopenharmony_ci/* ======================================================================
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_ciReadNextGrayLine()
198141cc406Sopenharmony_ci
199141cc406Sopenharmony_ci====================================================================== */
200141cc406Sopenharmony_ci
201141cc406Sopenharmony_cistatic TState ReadNextGrayLine(PTInstance this)
202141cc406Sopenharmony_ci{
203141cc406Sopenharmony_ci  int           iWrite;
204141cc406Sopenharmony_ci  int           iDot;
205141cc406Sopenharmony_ci  unsigned char chBits;
206141cc406Sopenharmony_ci  int           iRead; /* read position in raw line */
207141cc406Sopenharmony_ci  int           nInterpolator;
208141cc406Sopenharmony_ci
209141cc406Sopenharmony_ci  iWrite=0;
210141cc406Sopenharmony_ci
211141cc406Sopenharmony_ci  while (iWrite<this->state.cxMax) /* max 1 time in reality */
212141cc406Sopenharmony_ci    {
213141cc406Sopenharmony_ci      while (iWrite<this->state.cxMax &&
214141cc406Sopenharmony_ci	     this->state.iBulkReadPos<this->state.cchBulk)
215141cc406Sopenharmony_ci	this->state.ppchLines[0][iWrite++] += /* add! */
216141cc406Sopenharmony_ci	  this->state.pchBuf[this->state.iBulkReadPos++]<<4;
217141cc406Sopenharmony_ci      if (iWrite<this->state.cxMax) /* we need an additional chunk */
218141cc406Sopenharmony_ci	{
219141cc406Sopenharmony_ci	  if (this->state.bLastBulk)
220141cc406Sopenharmony_ci	      return SANE_STATUS_EOF;
221141cc406Sopenharmony_ci	  this->state.cchBulk=BulkReadBuffer(this,this->state.pchBuf,
222141cc406Sopenharmony_ci					     USB_CHUNK_SIZE);
223141cc406Sopenharmony_ci	  dprintf(DEBUG_SCAN,"bulk read: %d byte(s), line #%d\n",
224141cc406Sopenharmony_ci		  this->state.cchBulk, this->state.iLine);
225141cc406Sopenharmony_ci	  if (this->bWriteRaw)
226141cc406Sopenharmony_ci	    fwrite(this->state.pchBuf,1,this->state.cchBulk,this->fhScan);
227141cc406Sopenharmony_ci	  INST_ASSERT();
228141cc406Sopenharmony_ci	  if (this->state.cchBulk!=USB_CHUNK_SIZE)
229141cc406Sopenharmony_ci	    this->state.bLastBulk=true;
230141cc406Sopenharmony_ci	  this->state.iBulkReadPos=0;
231141cc406Sopenharmony_ci	}
232141cc406Sopenharmony_ci    } /* while raw line buffer acquiring */
233141cc406Sopenharmony_ci  this->state.iLine++;
234141cc406Sopenharmony_ci  iDot=0; chBits=0; /* init pixelbuffer */
235141cc406Sopenharmony_ci  for (nInterpolator=50, iWrite=0, iRead=0;
236141cc406Sopenharmony_ci       iRead<this->state.cxMax;
237141cc406Sopenharmony_ci       iRead++)
238141cc406Sopenharmony_ci    {
239141cc406Sopenharmony_ci      nInterpolator+=this->state.nFixAspect;
240141cc406Sopenharmony_ci      if (nInterpolator<100) continue; /* res. reduction */
241141cc406Sopenharmony_ci      nInterpolator-=100;
242141cc406Sopenharmony_ci      if (iWrite>=this->state.cchLineOut) continue;
243141cc406Sopenharmony_ci      /* dprintf(DEBUG_SCAN," i=%d",iTo); */
244141cc406Sopenharmony_ci      if (this->mode==gray)
245141cc406Sopenharmony_ci	  this->state.pchLineOut[iWrite++]=
246141cc406Sopenharmony_ci	    this->state.ppchLines[0][iRead]>>4;
247141cc406Sopenharmony_ci      else
248141cc406Sopenharmony_ci	{
249141cc406Sopenharmony_ci	  unsigned char chBit; /* 1=white */
250141cc406Sopenharmony_ci	  if (this->mode==line)
251141cc406Sopenharmony_ci	    chBit=(this->state.ppchLines[0][iRead]<LINE_THRESHOLD);
252141cc406Sopenharmony_ci	  else
253141cc406Sopenharmony_ci	    {
254141cc406Sopenharmony_ci	      short nError=this->state.ppchLines[0][iRead];
255141cc406Sopenharmony_ci	      /* printf("(%d)",nError); */
256141cc406Sopenharmony_ci	      if (nError>=0xFF0)
257141cc406Sopenharmony_ci		{
258141cc406Sopenharmony_ci		  nError-=0xFF0;
259141cc406Sopenharmony_ci		  chBit=0;
260141cc406Sopenharmony_ci		}
261141cc406Sopenharmony_ci	      else
262141cc406Sopenharmony_ci		chBit=1;
263141cc406Sopenharmony_ci	      /* since I sketched the Floyd-Steinberg
264141cc406Sopenharmony_ci		 algorithm from heart, I have no idea, if
265141cc406Sopenharmony_ci		 there is room for improvement in the
266141cc406Sopenharmony_ci		 coefficients.  If You know, please drop
267141cc406Sopenharmony_ci		 me a line (eichholz@computer.org, 1.4.2001) */
268141cc406Sopenharmony_ci#define FASTDITHER
269141cc406Sopenharmony_ci#ifdef FASTDITHER
270141cc406Sopenharmony_ci	      this->state.ppchLines[0][iRead+1]+=(nError>>2); /* 8/16 */
271141cc406Sopenharmony_ci	      this->state.ppchLines[1][iRead+1]+=(nError>>1);
272141cc406Sopenharmony_ci	      this->state.ppchLines[1][iRead]  +=(nError>>2); /* 8/16 */
273141cc406Sopenharmony_ci#else
274141cc406Sopenharmony_ci	      this->state.ppchLines[0][iRead+1]+=(nError*5)>>4;
275141cc406Sopenharmony_ci	      this->state.ppchLines[1][iRead+1]+=(nError*8)>>4;
276141cc406Sopenharmony_ci	      this->state.ppchLines[1][iRead]  +=(nError*3)>>4;
277141cc406Sopenharmony_ci#endif
278141cc406Sopenharmony_ci	    }
279141cc406Sopenharmony_ci	  chBits=(chBits<<1)|chBit;
280141cc406Sopenharmony_ci	  iDot++;
281141cc406Sopenharmony_ci	  if (iDot==8 && iWrite<this->state.cchLineOut)
282141cc406Sopenharmony_ci	    {
283141cc406Sopenharmony_ci	      this->state.pchLineOut[iWrite++]=chBits;
284141cc406Sopenharmony_ci	      iDot=0; chBits=0;
285141cc406Sopenharmony_ci	    }
286141cc406Sopenharmony_ci	} /* gray pixel postprocessing */
287141cc406Sopenharmony_ci    } /* line postprocessing */
288141cc406Sopenharmony_ci  if (iDot && iWrite<this->state.cchLineOut)
289141cc406Sopenharmony_ci    this->state.pchLineOut[iWrite++]=chBits;
290141cc406Sopenharmony_ci  /* cycle the history lines and clear the preread buffer*/
291141cc406Sopenharmony_ci  {
292141cc406Sopenharmony_ci    short *p=this->state.ppchLines[0];
293141cc406Sopenharmony_ci    this->state.ppchLines[0]=this->state.ppchLines[1];
294141cc406Sopenharmony_ci    this->state.ppchLines[1]=p;
295141cc406Sopenharmony_ci    memset(this->state.ppchLines[1],0,(this->state.cxMax+1)*sizeof(short));
296141cc406Sopenharmony_ci  }
297141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
298141cc406Sopenharmony_ci}
299141cc406Sopenharmony_ci
300141cc406Sopenharmony_ci/* ======================================================================
301141cc406Sopenharmony_ci
302141cc406Sopenharmony_ciStartScanGray()
303141cc406Sopenharmony_ci
304141cc406Sopenharmony_ci====================================================================== */
305141cc406Sopenharmony_ci
306141cc406Sopenharmony_ci__SM3600EXPORT__
307141cc406Sopenharmony_ciTState StartScanGray(TInstance *this)
308141cc406Sopenharmony_ci{
309141cc406Sopenharmony_ci  unsigned char  *puchRegs;
310141cc406Sopenharmony_ci  int             i;
311141cc406Sopenharmony_ci  if (this->state.bScanning)
312141cc406Sopenharmony_ci    return SetError(this,SANE_STATUS_DEVICE_BUSY,"scan active");
313141cc406Sopenharmony_ci  memset(&(this->state),0,sizeof(TScanState));
314141cc406Sopenharmony_ci  this->state.ReadProc  =ReadNextGrayLine;
315141cc406Sopenharmony_ci  puchRegs=NULL;
316141cc406Sopenharmony_ci  switch (this->param.res)
317141cc406Sopenharmony_ci  {
318141cc406Sopenharmony_ci  case 75:  puchRegs=uchRegs075; break;
319141cc406Sopenharmony_ci  case 100: puchRegs=uchRegs100; break;
320141cc406Sopenharmony_ci  case 200: puchRegs=uchRegs200; break;
321141cc406Sopenharmony_ci  case 300: puchRegs=uchRegs300; break;
322141cc406Sopenharmony_ci  case 600: puchRegs=uchRegs600; break;
323141cc406Sopenharmony_ci  }
324141cc406Sopenharmony_ci  GetAreaSize(this);
325141cc406Sopenharmony_ci  this->state.cyTotalPath = this->param.y/2;
326141cc406Sopenharmony_ci  DoJog(this,this->state.cyTotalPath);
327141cc406Sopenharmony_ci  INST_ASSERT();
328141cc406Sopenharmony_ci  this->state.cyTotalPath += this->param.cy/2; /* for jogging back */
329141cc406Sopenharmony_ci
330141cc406Sopenharmony_ci  /*
331141cc406Sopenharmony_ci    regular scan is asynchronously, that is,
332141cc406Sopenharmony_ci    the scanning is issued, and the driver does bulk reads,
333141cc406Sopenharmony_ci    until there are no data left.
334141cc406Sopenharmony_ci  */
335141cc406Sopenharmony_ci  RegWriteArray(this,R_ALL, NUM_SCANREGS, puchRegs); INST_ASSERT();
336141cc406Sopenharmony_ci  RegWrite(this,R_SPOS, 2,
337141cc406Sopenharmony_ci	   this->param.x/2+this->calibration.xMargin); INST_ASSERT();
338141cc406Sopenharmony_ci  RegWrite(this,R_SLEN, 2, this->state.cyWindow); INST_ASSERT();
339141cc406Sopenharmony_ci  RegWrite(this,R_SWID, 2, this->state.cxWindow); INST_ASSERT();
340141cc406Sopenharmony_ci  RegWrite(this,R_STPS, 2, 0); INST_ASSERT();
341141cc406Sopenharmony_ci
342141cc406Sopenharmony_ci  /* upload gamma table */
343141cc406Sopenharmony_ci  RegWrite(this,0x41,1,0x01); /* gamma, gray */
344141cc406Sopenharmony_ci  RegWrite(this,0x40,1,0x20); /* FIFO at   0x08000 */
345141cc406Sopenharmony_ci  UploadGammaTable(this,0,this->agammaY); INST_ASSERT();
346141cc406Sopenharmony_ci
347141cc406Sopenharmony_ci  UploadGainCorrection(this, 0x2000);
348141cc406Sopenharmony_ci  INST_ASSERT();
349141cc406Sopenharmony_ci
350141cc406Sopenharmony_ci  /* for halftone dithering we need one history line */
351141cc406Sopenharmony_ci  this->state.pchBuf=malloc(USB_CHUNK_SIZE);
352141cc406Sopenharmony_ci  this->state.cBacklog=2;
353141cc406Sopenharmony_ci  this->state.ppchLines=calloc(this->state.cBacklog,sizeof(short *));
354141cc406Sopenharmony_ci  if (!this->state.pchBuf || !this->state.ppchLines)
355141cc406Sopenharmony_ci    return FreeState(this,SetError(this,
356141cc406Sopenharmony_ci				   SANE_STATUS_NO_MEM,"no buffers available"));
357141cc406Sopenharmony_ci  for (i=0; i<this->state.cBacklog; i++)
358141cc406Sopenharmony_ci    {
359141cc406Sopenharmony_ci      this->state.ppchLines[i]=calloc(this->state.cxMax+1,
360141cc406Sopenharmony_ci				      sizeof(short)); /* 1 dummy at right edge */
361141cc406Sopenharmony_ci      if (!this->state.ppchLines[i])
362141cc406Sopenharmony_ci	return FreeState(this,SetError(this,
363141cc406Sopenharmony_ci				       SANE_STATUS_NO_MEM,"no buffers available"));
364141cc406Sopenharmony_ci    }
365141cc406Sopenharmony_ci
366141cc406Sopenharmony_ci  /* calculate and prepare intermediate line transfer buffer */
367141cc406Sopenharmony_ci
368141cc406Sopenharmony_ci  this->state.cchLineOut=(this->mode==gray)
369141cc406Sopenharmony_ci    ? this->state.cxPixel
370141cc406Sopenharmony_ci    : (this->state.cxPixel+7)/8;
371141cc406Sopenharmony_ci
372141cc406Sopenharmony_ci  this->state.pchLineOut = malloc(this->state.cchLineOut);
373141cc406Sopenharmony_ci  if (!this->state.pchLineOut)
374141cc406Sopenharmony_ci    return FreeState(this,SetError(this,
375141cc406Sopenharmony_ci				   SANE_STATUS_NO_MEM,
376141cc406Sopenharmony_ci				   "no buffers available"));
377141cc406Sopenharmony_ci
378141cc406Sopenharmony_ci  /* start the unit, when all buffers are available */
379141cc406Sopenharmony_ci
380141cc406Sopenharmony_ci  RegWrite(this,R_CTL, 1, 0x39); INST_ASSERT();
381141cc406Sopenharmony_ci  RegWrite(this,R_CTL, 1, 0x79); INST_ASSERT();
382141cc406Sopenharmony_ci  RegWrite(this,R_CTL, 1, 0xF9); INST_ASSERT();
383141cc406Sopenharmony_ci
384141cc406Sopenharmony_ci  this->state.bScanning = true;
385141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
386141cc406Sopenharmony_ci}
387