1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr>
4
5
6 This file is part of the SANE package.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21 As a special exception, the authors of SANE give permission for
22 additional uses of the libraries contained in this release of SANE.
23
24 The exception is that, if you link a SANE library with other files
25 to produce an executable, this does not by itself cause the
26 resulting executable to be covered by the GNU General Public
27 License. Your use of that executable is in no way restricted on
28 account of linking the SANE library code into it.
29
30 This exception does not, however, invalidate any other reasons why
31 the executable file might be covered by the GNU General Public
32 License.
33
34 If you submit changes to SANE to the maintainers to be included in
35 a subsequent release, you agree by submitting the changes that
36 those changes may be distributed with this exception intact.
37
38 If you write modifications of your own for SANE, it is your choice
39 whether to permit this exception to apply to your modifications.
40 If you do not wish that, delete this exception notice.
41 */
42
43 #define DEBUG_DECLARE_ONLY
44
45 #include "gl843_registers.h"
46 #include "gl843.h"
47 #include "test_settings.h"
48
49 #include <string>
50 #include <vector>
51
52 namespace genesys {
53 namespace gl843 {
54
55 /**
56 * compute the step multiplier used
57 */
gl843_get_step_multiplier(Genesys_Register_Set * regs)58 static int gl843_get_step_multiplier(Genesys_Register_Set* regs)
59 {
60 switch (regs->get8(REG_0x9D) & 0x0c) {
61 case 0x04: return 2;
62 case 0x08: return 4;
63 default: return 1;
64 }
65 }
66
67 /** @brief set all registers to default values .
68 * This function is called only once at the beginning and
69 * fills register startup values for registers reused across scans.
70 * Those that are rarely modified or not modified are written
71 * individually.
72 * @param dev device structure holding register set to initialize
73 */
74 static void
gl843_init_registers(Genesys_Device * dev)75 gl843_init_registers (Genesys_Device * dev)
76 {
77 // Within this function SENSOR_DEF marker documents that a register is part
78 // of the sensors definition and the actual value is set in
79 // scanner_setup_sensor().
80
81 // 0x6c, 0x6d, 0x6e, 0x6f, 0xa6, 0xa7, 0xa8, 0xa9 are defined in the Gpo sensor struct
82
83 DBG_HELPER(dbg);
84
85 dev->reg.clear();
86
87 dev->reg.init_reg(0x01, 0x00);
88 dev->reg.init_reg(0x02, 0x78);
89 dev->reg.init_reg(0x03, 0x1f);
90 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
91 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
92 dev->model->model_id == ModelId::HP_SCANJET_4850C)
93 {
94 dev->reg.init_reg(0x03, 0x1d);
95 }
96 if (dev->model->model_id == ModelId::CANON_8400F) {
97 dev->reg.init_reg(0x03, 0x1c);
98 }
99
100 dev->reg.init_reg(0x04, 0x10);
101 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
102 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
103 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
104 {
105 dev->reg.init_reg(0x04, 0x22);
106 }
107
108 // fine tune upon device description
109 dev->reg.init_reg(0x05, 0x80);
110 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
111 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
112 dev->model->model_id == ModelId::HP_SCANJET_4850C)
113 {
114 dev->reg.init_reg(0x05, 0x08);
115 }
116
117 auto initial_scan_method = dev->model->default_method;
118 if (dev->model->model_id == ModelId::CANON_4400F ||
119 dev->model->model_id == ModelId::CANON_8600F)
120 {
121 initial_scan_method = ScanMethod::TRANSPARENCY;
122 }
123 const auto& sensor = sanei_genesys_find_sensor_any(dev);
124 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution,
125 3, initial_scan_method);
126 sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw);
127
128 // TODO: on 8600F the windows driver turns off GAIN4 which is recommended
129 dev->reg.init_reg(0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */
130 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
131 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
132 dev->model->model_id == ModelId::HP_SCANJET_4850C)
133 {
134 dev->reg.init_reg(0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */
135 }
136 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I) {
137 dev->reg.init_reg(0x06, 0xd0);
138 }
139 if (dev->model->model_id == ModelId::CANON_4400F ||
140 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
141 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
142 {
143 dev->reg.init_reg(0x06, 0xf0); /* SCANMOD=111, PWRBIT and no GAIN4 */
144 }
145
146 dev->reg.init_reg(0x08, 0x00);
147 dev->reg.init_reg(0x09, 0x00);
148 dev->reg.init_reg(0x0a, 0x00);
149 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
150 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
151 dev->model->model_id == ModelId::HP_SCANJET_4850C)
152 {
153 dev->reg.init_reg(0x0a, 0x18);
154 }
155 if (dev->model->model_id == ModelId::CANON_8400F) {
156 dev->reg.init_reg(0x0a, 0x10);
157 }
158
159 // This register controls clock and RAM settings and is further modified in
160 // gl843_boot
161 dev->reg.init_reg(0x0b, 0x6a);
162
163 if (dev->model->model_id == ModelId::CANON_4400F) {
164 dev->reg.init_reg(0x0b, 0x69); // 16M only
165 }
166 if (dev->model->model_id == ModelId::CANON_8600F) {
167 dev->reg.init_reg(0x0b, 0x89);
168 }
169 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I) {
170 dev->reg.init_reg(0x0b, 0x2a);
171 }
172 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
173 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I) {
174 dev->reg.init_reg(0x0b, 0x4a);
175 }
176 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
177 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
178 dev->model->model_id == ModelId::HP_SCANJET_4850C)
179 {
180 dev->reg.init_reg(0x0b, 0x69);
181 }
182
183 if (dev->model->model_id != ModelId::CANON_8400F &&
184 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
185 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
186 {
187 dev->reg.init_reg(0x0c, 0x00);
188 }
189
190 // EXPR[0:15], EXPG[0:15], EXPB[0:15]: Exposure time settings.
191 dev->reg.init_reg(0x10, 0x00); // SENSOR_DEF
192 dev->reg.init_reg(0x11, 0x00); // SENSOR_DEF
193 dev->reg.init_reg(0x12, 0x00); // SENSOR_DEF
194 dev->reg.init_reg(0x13, 0x00); // SENSOR_DEF
195 dev->reg.init_reg(0x14, 0x00); // SENSOR_DEF
196 dev->reg.init_reg(0x15, 0x00); // SENSOR_DEF
197 if (dev->model->model_id == ModelId::CANON_4400F ||
198 dev->model->model_id == ModelId::CANON_8600F)
199 {
200 dev->reg.set16(REG_EXPR, 0x9c40);
201 dev->reg.set16(REG_EXPG, 0x9c40);
202 dev->reg.set16(REG_EXPB, 0x9c40);
203 }
204 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
205 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
206 dev->model->model_id == ModelId::HP_SCANJET_4850C)
207 {
208 dev->reg.set16(REG_EXPR, 0x2c09);
209 dev->reg.set16(REG_EXPG, 0x22b8);
210 dev->reg.set16(REG_EXPB, 0x10f0);
211 }
212
213 // CCD signal settings.
214 dev->reg.init_reg(0x16, 0x33); // SENSOR_DEF
215 dev->reg.init_reg(0x17, 0x1c); // SENSOR_DEF
216 dev->reg.init_reg(0x18, 0x10); // SENSOR_DEF
217
218 // EXPDMY[0:7]: Exposure time of dummy lines.
219 dev->reg.init_reg(0x19, 0x2a); // SENSOR_DEF
220
221 // Various CCD clock settings.
222 dev->reg.init_reg(0x1a, 0x04); // SENSOR_DEF
223 dev->reg.init_reg(0x1b, 0x00); // SENSOR_DEF
224 dev->reg.init_reg(0x1c, 0x20); // SENSOR_DEF
225 dev->reg.init_reg(0x1d, 0x04); // SENSOR_DEF
226
227 dev->reg.init_reg(0x1e, 0x10);
228 if (dev->model->model_id == ModelId::CANON_4400F ||
229 dev->model->model_id == ModelId::CANON_8600F)
230 {
231 dev->reg.init_reg(0x1e, 0x20);
232 }
233 if (dev->model->model_id == ModelId::CANON_8400F) {
234 dev->reg.init_reg(0x1e, 0xa0);
235 }
236
237 dev->reg.init_reg(0x1f, 0x01);
238 if (dev->model->model_id == ModelId::CANON_8600F) {
239 dev->reg.init_reg(0x1f, 0xff);
240 }
241
242 dev->reg.init_reg(0x20, 0x10);
243 dev->reg.init_reg(0x21, 0x04);
244
245 dev->reg.init_reg(0x22, 0x10);
246 dev->reg.init_reg(0x23, 0x10);
247 if (dev->model->model_id == ModelId::CANON_8600F) {
248 dev->reg.init_reg(0x22, 0xc8);
249 dev->reg.init_reg(0x23, 0xc8);
250 }
251 if (dev->model->model_id == ModelId::CANON_8400F) {
252 dev->reg.init_reg(0x22, 0x50);
253 dev->reg.init_reg(0x23, 0x50);
254 }
255
256 dev->reg.init_reg(0x24, 0x04);
257 dev->reg.init_reg(0x25, 0x00);
258 dev->reg.init_reg(0x26, 0x00);
259 dev->reg.init_reg(0x27, 0x00);
260 dev->reg.init_reg(0x2c, 0x02);
261 dev->reg.init_reg(0x2d, 0x58);
262 // BWHI[0:7]: high level of black and white threshold
263 dev->reg.init_reg(0x2e, 0x80);
264 // BWLOW[0:7]: low level of black and white threshold
265 dev->reg.init_reg(0x2f, 0x80);
266 dev->reg.init_reg(0x30, 0x00);
267 dev->reg.init_reg(0x31, 0x14);
268 dev->reg.init_reg(0x32, 0x27);
269 dev->reg.init_reg(0x33, 0xec);
270
271 // DUMMY: CCD dummy and optically black pixel count
272 dev->reg.init_reg(0x34, 0x24);
273 if (dev->model->model_id == ModelId::CANON_8600F) {
274 dev->reg.init_reg(0x34, 0x14);
275 }
276 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
277 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
278 {
279 dev->reg.init_reg(0x34, 0x3c);
280 }
281
282 // MAXWD: If available buffer size is less than 2*MAXWD words, then
283 // "buffer full" state will be set.
284 dev->reg.init_reg(0x35, 0x00);
285 dev->reg.init_reg(0x36, 0xff);
286 dev->reg.init_reg(0x37, 0xff);
287
288 // LPERIOD: Line period or exposure time for CCD or CIS.
289 dev->reg.init_reg(0x38, 0x55); // SENSOR_DEF
290 dev->reg.init_reg(0x39, 0xf0); // SENSOR_DEF
291
292 // FEEDL[0:24]: The number of steps of motor movement.
293 dev->reg.init_reg(0x3d, 0x00);
294 dev->reg.init_reg(0x3e, 0x00);
295 dev->reg.init_reg(0x3f, 0x01);
296
297 // Latch points for high and low bytes of R, G and B channels of AFE. If
298 // multiple clocks per pixel are consumed, then the setting defines during
299 // which clock the corresponding value will be read.
300 // RHI[0:4]: The latch point for high byte of R channel.
301 // RLOW[0:4]: The latch point for low byte of R channel.
302 // GHI[0:4]: The latch point for high byte of G channel.
303 // GLOW[0:4]: The latch point for low byte of G channel.
304 // BHI[0:4]: The latch point for high byte of B channel.
305 // BLOW[0:4]: The latch point for low byte of B channel.
306 dev->reg.init_reg(0x52, 0x01); // SENSOR_DEF
307 dev->reg.init_reg(0x53, 0x04); // SENSOR_DEF
308 dev->reg.init_reg(0x54, 0x07); // SENSOR_DEF
309 dev->reg.init_reg(0x55, 0x0a); // SENSOR_DEF
310 dev->reg.init_reg(0x56, 0x0d); // SENSOR_DEF
311 dev->reg.init_reg(0x57, 0x10); // SENSOR_DEF
312
313 // VSMP[0:4]: The position of the image sampling pulse for AFE in cycles.
314 // VSMPW[0:2]: The length of the image sampling pulse for AFE in cycles.
315 dev->reg.init_reg(0x58, 0x1b); // SENSOR_DEF
316
317 dev->reg.init_reg(0x59, 0x00); // SENSOR_DEF
318 dev->reg.init_reg(0x5a, 0x40); // SENSOR_DEF
319
320 // 0x5b-0x5c: GMMADDR[0:15] address for gamma or motor tables download
321 // SENSOR_DEF
322
323 // DECSEL[0:2]: The number of deceleration steps after touching home sensor
324 // STOPTIM[0:4]: The stop duration between change of directions in
325 // backtracking
326 dev->reg.init_reg(0x5e, 0x23);
327 if (dev->model->model_id == ModelId::CANON_4400F) {
328 dev->reg.init_reg(0x5e, 0x3f);
329 }
330 if (dev->model->model_id == ModelId::CANON_8400F) {
331 dev->reg.init_reg(0x5e, 0x85);
332 }
333 if (dev->model->model_id == ModelId::CANON_8600F) {
334 dev->reg.init_reg(0x5e, 0x1f);
335 }
336 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
337 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
338 {
339 dev->reg.init_reg(0x5e, 0x01);
340 }
341
342 //FMOVDEC: The number of deceleration steps in table 5 for auto-go-home
343 dev->reg.init_reg(0x5f, 0x01);
344 if (dev->model->model_id == ModelId::CANON_4400F) {
345 dev->reg.init_reg(0x5f, 0xf0);
346 }
347 if (dev->model->model_id == ModelId::CANON_8600F) {
348 dev->reg.init_reg(0x5f, 0xf0);
349 }
350 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
351 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
352 {
353 dev->reg.init_reg(0x5f, 0x01);
354 }
355
356 // Z1MOD[0:20]
357 dev->reg.init_reg(0x60, 0x00);
358 dev->reg.init_reg(0x61, 0x00);
359 dev->reg.init_reg(0x62, 0x00);
360
361 // Z2MOD[0:20]
362 dev->reg.init_reg(0x63, 0x00);
363 dev->reg.init_reg(0x64, 0x00);
364 dev->reg.init_reg(0x65, 0x00);
365
366 // STEPSEL[0:1]. Motor movement step mode selection for tables 1-3 in
367 // scanning mode.
368 // MTRPWM[0:5]. Motor phase PWM duty cycle setting for tables 1-3
369 dev->reg.init_reg(0x67, 0x7f); // MOTOR_PROFILE
370 // FSTPSEL[0:1]: Motor movement step mode selection for tables 4-5 in
371 // command mode.
372 // FASTPWM[5:0]: Motor phase PWM duty cycle setting for tables 4-5
373 dev->reg.init_reg(0x68, 0x7f); // MOTOR_PROFILE
374
375 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300) {
376 dev->reg.init_reg(0x67, 0x80);
377 dev->reg.init_reg(0x68, 0x80);
378 }
379
380 // FSHDEC[0:7]: The number of deceleration steps after scanning is finished
381 // (table 3)
382 dev->reg.init_reg(0x69, 0x01); // MOTOR_PROFILE
383
384 // FMOVNO[0:7] The number of acceleration or deceleration steps for fast
385 // moving (table 4)
386 dev->reg.init_reg(0x6a, 0x04); // MOTOR_PROFILE
387
388 // GPIO-related register bits
389 dev->reg.init_reg(0x6b, 0x30);
390 if (dev->model->model_id == ModelId::CANON_4400F ||
391 dev->model->model_id == ModelId::CANON_8600F)
392 {
393 dev->reg.init_reg(0x6b, 0x72);
394 }
395 if (dev->model->model_id == ModelId::CANON_8400F) {
396 dev->reg.init_reg(0x6b, 0xb1);
397 }
398 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
399 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
400 dev->model->model_id == ModelId::HP_SCANJET_4850C)
401 {
402 dev->reg.init_reg(0x6b, 0xf4);
403 }
404 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
405 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
406 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
407 {
408 dev->reg.init_reg(0x6b, 0x31);
409 }
410
411 // 0x6c, 0x6d, 0x6e, 0x6f are set according to gpio tables. See
412 // gl843_init_gpio.
413
414 // RSH[0:4]: The position of rising edge of CCD RS signal in cycles
415 // RSL[0:4]: The position of falling edge of CCD RS signal in cycles
416 // CPH[0:4]: The position of rising edge of CCD CP signal in cycles.
417 // CPL[0:4]: The position of falling edge of CCD CP signal in cycles
418 dev->reg.init_reg(0x70, 0x01); // SENSOR_DEF
419 dev->reg.init_reg(0x71, 0x03); // SENSOR_DEF
420 dev->reg.init_reg(0x72, 0x04); // SENSOR_DEF
421 dev->reg.init_reg(0x73, 0x05); // SENSOR_DEF
422
423 if (dev->model->model_id == ModelId::CANON_4400F) {
424 dev->reg.init_reg(0x70, 0x01);
425 dev->reg.init_reg(0x71, 0x03);
426 dev->reg.init_reg(0x72, 0x01);
427 dev->reg.init_reg(0x73, 0x03);
428 }
429 if (dev->model->model_id == ModelId::CANON_8400F) {
430 dev->reg.init_reg(0x70, 0x01);
431 dev->reg.init_reg(0x71, 0x03);
432 dev->reg.init_reg(0x72, 0x03);
433 dev->reg.init_reg(0x73, 0x04);
434 }
435 if (dev->model->model_id == ModelId::CANON_8600F) {
436 dev->reg.init_reg(0x70, 0x00);
437 dev->reg.init_reg(0x71, 0x02);
438 dev->reg.init_reg(0x72, 0x02);
439 dev->reg.init_reg(0x73, 0x04);
440 }
441 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
442 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
443 dev->model->model_id == ModelId::HP_SCANJET_4850C)
444 {
445 dev->reg.init_reg(0x70, 0x00);
446 dev->reg.init_reg(0x71, 0x02);
447 dev->reg.init_reg(0x72, 0x00);
448 dev->reg.init_reg(0x73, 0x00);
449 }
450
451 // CK1MAP[0:17], CK3MAP[0:17], CK4MAP[0:17]: CCD clock bit mapping setting.
452 dev->reg.init_reg(0x74, 0x00); // SENSOR_DEF
453 dev->reg.init_reg(0x75, 0x00); // SENSOR_DEF
454 dev->reg.init_reg(0x76, 0x3c); // SENSOR_DEF
455 dev->reg.init_reg(0x77, 0x00); // SENSOR_DEF
456 dev->reg.init_reg(0x78, 0x00); // SENSOR_DEF
457 dev->reg.init_reg(0x79, 0x9f); // SENSOR_DEF
458 dev->reg.init_reg(0x7a, 0x00); // SENSOR_DEF
459 dev->reg.init_reg(0x7b, 0x00); // SENSOR_DEF
460 dev->reg.init_reg(0x7c, 0x55); // SENSOR_DEF
461
462 // various AFE settings
463 dev->reg.init_reg(0x7d, 0x00);
464 if (dev->model->model_id == ModelId::CANON_8400F) {
465 dev->reg.init_reg(0x7d, 0x20);
466 }
467
468 // GPOLED[x]: LED vs GPIO settings
469 dev->reg.init_reg(0x7e, 0x00);
470
471 // BSMPDLY, VSMPDLY
472 // LEDCNT[0:1]: Controls led blinking and its period
473 dev->reg.init_reg(0x7f, 0x00);
474
475 // VRHOME, VRMOVE, VRBACK, VRSCAN: Vref settings of the motor driver IC for
476 // moving in various situations.
477 dev->reg.init_reg(0x80, 0x00); // MOTOR_PROFILE
478 if (dev->model->model_id == ModelId::CANON_4400F) {
479 dev->reg.init_reg(0x80, 0x0c);
480 }
481 if (dev->model->model_id == ModelId::CANON_8400F) {
482 dev->reg.init_reg(0x80, 0x28);
483 }
484 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
485 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
486 dev->model->model_id == ModelId::HP_SCANJET_4850C)
487 {
488 dev->reg.init_reg(0x80, 0x50);
489 }
490 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
491 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
492 {
493 dev->reg.init_reg(0x80, 0x0f);
494 }
495
496 if (dev->model->model_id != ModelId::CANON_4400F) {
497 dev->reg.init_reg(0x81, 0x00);
498 dev->reg.init_reg(0x82, 0x00);
499 dev->reg.init_reg(0x83, 0x00);
500 dev->reg.init_reg(0x84, 0x00);
501 dev->reg.init_reg(0x85, 0x00);
502 dev->reg.init_reg(0x86, 0x00);
503 }
504
505 dev->reg.init_reg(0x87, 0x00);
506 if (dev->model->model_id == ModelId::CANON_4400F ||
507 dev->model->model_id == ModelId::CANON_8400F ||
508 dev->model->model_id == ModelId::CANON_8600F)
509 {
510 dev->reg.init_reg(0x87, 0x02);
511 }
512
513 // MTRPLS[0:7]: The width of the ADF motor trigger signal pulse.
514 if (dev->model->model_id != ModelId::CANON_8400F &&
515 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
516 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
517 {
518 dev->reg.init_reg(0x94, 0xff);
519 }
520
521 // 0x95-0x97: SCANLEN[0:19]: Controls when paper jam bit is set in sheetfed
522 // scanners.
523
524 // ONDUR[0:15]: The duration of PWM ON phase for LAMP control
525 // OFFDUR[0:15]: The duration of PWM OFF phase for LAMP control
526 // both of the above are in system clocks
527 if (dev->model->model_id == ModelId::CANON_8600F) {
528 dev->reg.init_reg(0x98, 0x00);
529 dev->reg.init_reg(0x99, 0x00);
530 dev->reg.init_reg(0x9a, 0x00);
531 dev->reg.init_reg(0x9b, 0x00);
532 }
533 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
534 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
535 dev->model->model_id == ModelId::HP_SCANJET_4850C)
536 {
537 // TODO: move to set for scan
538 dev->reg.init_reg(0x98, 0x03);
539 dev->reg.init_reg(0x99, 0x30);
540 dev->reg.init_reg(0x9a, 0x01);
541 dev->reg.init_reg(0x9b, 0x80);
542 }
543
544 // RMADLY[0:1], MOTLAG, CMODE, STEPTIM, MULDMYLN, IFRS
545 dev->reg.init_reg(0x9d, 0x04);
546 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
547 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
548 {
549 dev->reg.init_reg(0x9d, 0x00);
550 }
551 if (dev->model->model_id == ModelId::CANON_4400F ||
552 dev->model->model_id == ModelId::CANON_8400F ||
553 dev->model->model_id == ModelId::CANON_8600F ||
554 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
555 dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
556 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
557 dev->model->model_id == ModelId::HP_SCANJET_4850C)
558 {
559 dev->reg.init_reg(0x9d, 0x08); // sets the multiplier for slope tables
560 }
561
562
563 // SEL3INV, TGSTIME[0:2], TGWTIME[0:2]
564 if (dev->model->model_id != ModelId::CANON_8400F &&
565 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
566 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
567 {
568 dev->reg.init_reg(0x9e, 0x00); // SENSOR_DEF
569 }
570
571 if (dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300) {
572 dev->reg.init_reg(0xa2, 0x0f);
573 }
574
575 // RFHSET[0:4]: Refresh time of SDRAM in units of 2us
576 if (dev->model->model_id == ModelId::CANON_4400F ||
577 dev->model->model_id == ModelId::CANON_8600F)
578 {
579 dev->reg.init_reg(0xa2, 0x1f);
580 }
581
582 // 0xa6-0xa9: controls gpio, see gl843_gpio_init
583
584 // not documented
585 if (dev->model->model_id != ModelId::CANON_4400F &&
586 dev->model->model_id != ModelId::CANON_8400F &&
587 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
588 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
589 {
590 dev->reg.init_reg(0xaa, 0x00);
591 }
592
593 // GPOM9, MULSTOP[0-2], NODECEL, TB3TB1, TB5TB2, FIX16CLK.
594 if (dev->model->model_id != ModelId::CANON_8400F &&
595 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
596 dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300) {
597 dev->reg.init_reg(0xab, 0x50);
598 }
599 if (dev->model->model_id == ModelId::CANON_4400F) {
600 dev->reg.init_reg(0xab, 0x00);
601 }
602 if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
603 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
604 dev->model->model_id == ModelId::CANON_8600F ||
605 dev->model->model_id == ModelId::HP_SCANJET_4850C)
606 {
607 dev->reg.init_reg(0xab, 0x40);
608 }
609
610 // VRHOME[3:2], VRMOVE[3:2], VRBACK[3:2]: Vref setting of the motor driver IC
611 // for various situations.
612 if (dev->model->model_id == ModelId::CANON_8600F ||
613 dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
614 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
615 dev->model->model_id == ModelId::HP_SCANJET_4850C)
616 {
617 dev->reg.init_reg(0xac, 0x00);
618 }
619
620 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I) {
621 uint8_t data[32] = {
622 0x8c, 0x8f, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625 0x6a, 0x73, 0x63, 0x68, 0x69, 0x65, 0x6e, 0x00,
626 };
627
628 dev->interface->write_buffer(0x3c, 0x3ff000, data, 32);
629 }
630 }
631
gl843_set_ad_fe(Genesys_Device * dev)632 static void gl843_set_ad_fe(Genesys_Device* dev)
633 {
634 for (const auto& reg : dev->frontend.regs) {
635 dev->interface->write_fe_register(reg.address, reg.value);
636 }
637 }
638
639 // Set values of analog frontend
set_fe(Genesys_Device * dev,const Genesys_Sensor & sensor,uint8_t set) const640 void CommandSetGl843::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
641 {
642 DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
643 set == AFE_SET ? "set" :
644 set == AFE_POWER_SAVE ? "powersave" : "huh?");
645 (void) sensor;
646
647 if (set == AFE_INIT) {
648 dev->frontend = dev->frontend_initial;
649 }
650
651 // check analog frontend type
652 // FIXME: looks like we write to that register with initial data
653 uint8_t fe_type = dev->interface->read_register(REG_0x04) & REG_0x04_FESET;
654 if (fe_type == 2) {
655 gl843_set_ad_fe(dev);
656 return;
657 }
658 if (fe_type != 0) {
659 throw SaneException(SANE_STATUS_UNSUPPORTED, "unsupported frontend type %d", fe_type);
660 }
661
662 for (unsigned i = 1; i <= 3; i++) {
663 dev->interface->write_fe_register(i, dev->frontend.regs.get_value(0x00 + i));
664 }
665 for (const auto& reg : sensor.custom_fe_regs) {
666 dev->interface->write_fe_register(reg.address, reg.value);
667 }
668
669 for (unsigned i = 0; i < 3; i++) {
670 dev->interface->write_fe_register(0x20 + i, dev->frontend.get_offset(i));
671 }
672
673 if (dev->model->sensor_id == SensorId::CCD_KVSS080) {
674 for (unsigned i = 0; i < 3; i++) {
675 dev->interface->write_fe_register(0x24 + i, dev->frontend.regs.get_value(0x24 + i));
676 }
677 }
678
679 for (unsigned i = 0; i < 3; i++) {
680 dev->interface->write_fe_register(0x28 + i, dev->frontend.get_gain(i));
681 }
682 }
683
gl843_init_motor_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,const ScanSession & session,Genesys_Register_Set * reg,const MotorProfile & motor_profile,unsigned int exposure,unsigned scan_yres,unsigned int scan_lines,unsigned int scan_dummy,unsigned int feed_steps,ScanFlag flags)684 static void gl843_init_motor_regs_scan(Genesys_Device* dev,
685 const Genesys_Sensor& sensor,
686 const ScanSession& session,
687 Genesys_Register_Set* reg,
688 const MotorProfile& motor_profile,
689 unsigned int exposure,
690 unsigned scan_yres,
691 unsigned int scan_lines,
692 unsigned int scan_dummy,
693 unsigned int feed_steps,
694 ScanFlag flags)
695 {
696 DBG_HELPER_ARGS(dbg, "exposure=%d, scan_yres=%d, step_type=%d, scan_lines=%d, scan_dummy=%d, "
697 "feed_steps=%d, flags=%x",
698 exposure, scan_yres, static_cast<unsigned>(motor_profile.step_type),
699 scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
700
701 unsigned feedl, dist;
702
703 /* get step multiplier */
704 unsigned step_multiplier = gl843_get_step_multiplier (reg);
705
706 bool use_fast_fed = false;
707
708 if ((scan_yres >= 300 && feed_steps > 900) || (has_flag(flags, ScanFlag::FEEDING))) {
709 use_fast_fed = true;
710 }
711 if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) {
712 use_fast_fed = false;
713 }
714
715 reg->set24(REG_LINCNT, scan_lines);
716
717 reg->set8(REG_0x02, 0);
718 sanei_genesys_set_motor_power(*reg, true);
719
720 std::uint8_t reg02 = reg->get8(REG_0x02);
721 if (use_fast_fed) {
722 reg02 |= REG_0x02_FASTFED;
723 } else {
724 reg02 &= ~REG_0x02_FASTFED;
725 }
726
727 // in case of automatic go home, move until home sensor
728 if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
729 reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
730 }
731
732 /* disable backtracking */
733 if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) ||
734 (scan_yres>=2400 && dev->model->model_id != ModelId::CANON_4400F) ||
735 (scan_yres>=sensor.full_resolution))
736 {
737 reg02 |= REG_0x02_ACDCDIS;
738 }
739
740 if (has_flag(flags, ScanFlag::REVERSE)) {
741 reg02 |= REG_0x02_MTRREV;
742 } else {
743 reg02 &= ~REG_0x02_MTRREV;
744 }
745 reg->set8(REG_0x02, reg02);
746
747 // scan and backtracking slope table
748 auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres, exposure,
749 step_multiplier, motor_profile);
750
751 scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
752 scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
753 scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table);
754
755 reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
756 reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
757 reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
758
759 // fast table
760 const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
761 if (fast_profile == nullptr) {
762 fast_profile = &motor_profile;
763 }
764
765 auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
766 *fast_profile);
767
768 scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
769 scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
770
771 reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
772
773 if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) {
774 std::uint8_t vref = 0;
775 vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL;
776 vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK;
777 vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST;
778 vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME;
779 reg->set8(REG_0x80, vref);
780 }
781
782 /* subtract acceleration distance from feedl */
783 feedl=feed_steps;
784 feedl <<= static_cast<unsigned>(motor_profile.step_type);
785
786 dist = scan_table.table.size() / step_multiplier;
787
788 if (use_fast_fed) {
789 dist += (fast_table.table.size() / step_multiplier) * 2;
790 }
791
792 /* get sure when don't insane value : XXX STEF XXX in this case we should
793 * fall back to single table move */
794 if (dist < feedl) {
795 feedl -= dist;
796 } else {
797 feedl = 1;
798 }
799
800 reg->set24(REG_FEEDL, feedl);
801
802 // doesn't seem to matter that much
803 std::uint32_t z1, z2;
804 sanei_genesys_calculate_zmod(use_fast_fed,
805 exposure,
806 scan_table.table,
807 scan_table.table.size() / step_multiplier,
808 feedl,
809 scan_table.table.size() / step_multiplier,
810 &z1,
811 &z2);
812 if(scan_yres>600)
813 {
814 z1=0;
815 z2=0;
816 }
817
818 reg->set24(REG_Z1MOD, z1);
819 reg->set24(REG_Z2MOD, z2);
820
821 reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
822
823 reg->set8_mask(REG_0x67, static_cast<unsigned>(motor_profile.step_type) << REG_0x67S_STEPSEL, 0xc0);
824 reg->set8_mask(REG_0x68, static_cast<unsigned>(fast_profile->step_type) << REG_0x68S_FSTPSEL, 0xc0);
825
826 // steps for STOP table
827 reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
828
829 if (dev->model->model_id == ModelId::PANASONIC_KV_SS080 ||
830 dev->model->model_id == ModelId::HP_SCANJET_4850C ||
831 dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
832 dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
833 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
834 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
835 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
836 {
837 // FIXME: take this information from motor struct
838 std::uint8_t reg_vref = reg->get8(0x80);
839 reg_vref = 0x50;
840 unsigned coeff = sensor.full_resolution / scan_yres;
841 if (dev->model->motor_id == MotorId::KVSS080) {
842 if (coeff >= 1) {
843 reg_vref |= 0x05;
844 }
845 } else {
846 switch (coeff) {
847 case 4:
848 reg_vref |= 0x0a;
849 break;
850 case 2:
851 reg_vref |= 0x0f;
852 break;
853 case 1:
854 reg_vref |= 0x0f;
855 break;
856 }
857 }
858 reg->set8(REG_0x80, reg_vref);
859 }
860 }
861
862
863 /** @brief setup optical related registers
864 * start and pixels are expressed in optical sensor resolution coordinate
865 * space.
866 * @param dev device to use
867 * @param reg registers to set up
868 * @param exposure exposure time to use
869 * @param used_res scanning resolution used, may differ from
870 * scan's one
871 * @param start logical start pixel coordinate
872 * @param pixels logical number of pixels to use
873 * @param channels number of color channels used (1 or 3)
874 * @param depth bit depth of the scan (1, 8 or 16 bits)
875 * @param color_filter to choose the color channel used in gray scans
876 * @param flags to drive specific settings such no calibration, XPA use ...
877 */
gl843_init_optical_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,unsigned int exposure,const ScanSession & session)878 static void gl843_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
879 Genesys_Register_Set* reg, unsigned int exposure,
880 const ScanSession& session)
881 {
882 DBG_HELPER_ARGS(dbg, "exposure=%d", exposure);
883 unsigned int tgtime; /**> exposure time multiplier */
884
885 /* tgtime */
886 tgtime = exposure / 65536 + 1;
887 DBG(DBG_io2, "%s: tgtime=%d\n", __func__, tgtime);
888
889 // sensor parameters
890 scanner_setup_sensor(*dev, sensor, *reg);
891
892 dev->cmd_set->set_fe(dev, sensor, AFE_SET);
893
894 /* enable shading */
895 regs_set_optical_off(dev->model->asic_type, *reg);
896 if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
897 has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
898 session.use_host_side_calib)
899 {
900 reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
901
902 } else {
903 reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
904 }
905
906 bool use_shdarea = false;
907 if (dev->model->model_id == ModelId::CANON_4400F) {
908 use_shdarea = session.params.xres <= 600;
909 } else if (dev->model->model_id == ModelId::CANON_8400F) {
910 use_shdarea = session.params.xres <= 400;
911 } else if (dev->model->model_id == ModelId::CANON_8600F ||
912 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
913 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
914 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
915 {
916 use_shdarea = true;
917 } else {
918 use_shdarea = session.params.xres > 600;
919 }
920
921 if (use_shdarea) {
922 reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
923 } else {
924 reg->find_reg(REG_0x01).value &= ~REG_0x01_SHDAREA;
925 }
926
927 if (dev->model->model_id == ModelId::CANON_8600F) {
928 reg->find_reg(REG_0x03).value |= REG_0x03_AVEENB;
929 } else {
930 reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
931 }
932
933 // FIXME: we probably don't need to set exposure to registers at this point. It was this way
934 // before a refactor.
935 sanei_genesys_set_lamp_power(dev, sensor, *reg,
936 !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
937
938 /* select XPA */
939 reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL;
940 if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
941 reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL;
942 }
943 reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
944
945 // BW threshold
946 reg->set8(REG_0x2E, 0x7f);
947 reg->set8(REG_0x2F, 0x7f);
948
949 /* monochrome / color scan */
950 switch (session.params.depth) {
951 case 8:
952 reg->find_reg(REG_0x04).value &= ~(REG_0x04_LINEART | REG_0x04_BITSET);
953 break;
954 case 16:
955 reg->find_reg(REG_0x04).value &= ~REG_0x04_LINEART;
956 reg->find_reg(REG_0x04).value |= REG_0x04_BITSET;
957 break;
958 }
959
960 reg->find_reg(REG_0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
961 if (session.params.channels == 1)
962 {
963 switch (session.params.color_filter)
964 {
965 case ColorFilter::RED:
966 reg->find_reg(REG_0x04).value |= 0x14;
967 break;
968 case ColorFilter::BLUE:
969 reg->find_reg(REG_0x04).value |= 0x1c;
970 break;
971 case ColorFilter::GREEN:
972 reg->find_reg(REG_0x04).value |= 0x18;
973 break;
974 default:
975 break; // should not happen
976 }
977 } else {
978 switch (dev->frontend.layout.type) {
979 case FrontendType::WOLFSON:
980 reg->find_reg(REG_0x04).value |= 0x10; // pixel by pixel
981 break;
982 case FrontendType::ANALOG_DEVICES:
983 reg->find_reg(REG_0x04).value |= 0x20; // slow color pixel by pixel
984 break;
985 default:
986 throw SaneException("Invalid frontend type %d",
987 static_cast<unsigned>(dev->frontend.layout.type));
988 }
989 }
990
991 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution,
992 session.params.channels,
993 session.params.scan_method);
994 sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw);
995
996 if (should_enable_gamma(session, sensor)) {
997 reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB;
998 } else {
999 reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
1000 }
1001
1002 reg->set16(REG_DPISET, sensor.register_dpiset);
1003
1004 reg->set16(REG_STRPIXEL, session.pixel_startx);
1005 reg->set16(REG_ENDPIXEL, session.pixel_endx);
1006
1007 /* MAXWD is expressed in 2 words unit */
1008 /* nousedspace = (mem_bank_range * 1024 / 256 -1 ) * 4; */
1009 // BUG: the division by optical and full resolution factor likely does not make sense
1010 reg->set24(REG_MAXWD, (session.output_line_bytes *
1011 session.optical_resolution / session.full_resolution) >> 1);
1012 reg->set16(REG_LPERIOD, exposure / tgtime);
1013 reg->set8(REG_DUMMY, sensor.dummy_pixel);
1014 }
1015
init_regs_for_scan_session(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,const ScanSession & session) const1016 void CommandSetGl843::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
1017 Genesys_Register_Set* reg,
1018 const ScanSession& session) const
1019 {
1020 DBG_HELPER(dbg);
1021 session.assert_computed();
1022
1023 int exposure;
1024
1025 int slope_dpi = 0;
1026 int dummy = 0;
1027
1028 /* we enable true gray for cis scanners only, and just when doing
1029 * scan since color calibration is OK for this mode
1030 */
1031
1032 dummy = 0;
1033 if (dev->model->model_id == ModelId::CANON_4400F && session.params.yres == 1200) {
1034 dummy = 1;
1035 }
1036
1037 /* slope_dpi */
1038 /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */
1039 if (dev->model->is_cis)
1040 slope_dpi = session.params.yres * session.params.channels;
1041 else
1042 slope_dpi = session.params.yres;
1043 slope_dpi = slope_dpi * (1 + dummy);
1044
1045 /* scan_step_type */
1046 exposure = sensor.exposure_lperiod;
1047 if (exposure < 0) {
1048 throw std::runtime_error("Exposure not defined in sensor definition");
1049 }
1050 const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure, session);
1051
1052 // now _LOGICAL_ optical values used are known, setup registers
1053 gl843_init_optical_regs_scan(dev, sensor, reg, exposure, session);
1054 gl843_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure, slope_dpi,
1055 session.optical_line_count, dummy, session.params.starty,
1056 session.params.flags);
1057
1058 setup_image_pipeline(*dev, session);
1059
1060 dev->read_active = true;
1061
1062 dev->session = session;
1063
1064 dev->total_bytes_read = 0;
1065 dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines;
1066
1067 DBG(DBG_info, "%s: total bytes to send = %zu\n", __func__, dev->total_bytes_to_read);
1068 }
1069
calculate_scan_session(const Genesys_Device * dev,const Genesys_Sensor & sensor,const Genesys_Settings & settings) const1070 ScanSession CommandSetGl843::calculate_scan_session(const Genesys_Device* dev,
1071 const Genesys_Sensor& sensor,
1072 const Genesys_Settings& settings) const
1073 {
1074 DBG_HELPER(dbg);
1075 debug_dump(DBG_info, settings);
1076
1077 ScanFlag flags = ScanFlag::NONE;
1078
1079 float move = 0.0f;
1080 if (settings.scan_method == ScanMethod::TRANSPARENCY ||
1081 settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1082 {
1083 // note: scanner_move_to_ta() function has already been called and the sensor is at the
1084 // transparency adapter
1085 if (!dev->ignore_offsets) {
1086 move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
1087 }
1088 flags |= ScanFlag::USE_XPA;
1089 } else {
1090 if (!dev->ignore_offsets) {
1091 move = dev->model->y_offset;
1092 }
1093 }
1094
1095 move += settings.tl_y;
1096
1097 int move_dpi = dev->motor.base_ydpi;
1098 move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
1099
1100 float start = 0.0f;
1101 if (settings.scan_method==ScanMethod::TRANSPARENCY ||
1102 settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1103 {
1104 start = dev->model->x_offset_ta;
1105 } else {
1106 start = dev->model->x_offset;
1107 }
1108 start = start + settings.tl_x;
1109
1110 start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
1111
1112 ScanSession session;
1113 session.params.xres = settings.xres;
1114 session.params.yres = settings.yres;
1115 session.params.startx = static_cast<unsigned>(start);
1116 session.params.starty = static_cast<unsigned>(move);
1117 session.params.pixels = settings.pixels;
1118 session.params.requested_pixels = settings.requested_pixels;
1119 session.params.lines = settings.lines;
1120 session.params.depth = settings.depth;
1121 session.params.channels = settings.get_channels();
1122 session.params.scan_method = settings.scan_method;
1123 session.params.scan_mode = settings.scan_mode;
1124 session.params.color_filter = settings.color_filter;
1125 session.params.flags = flags;
1126 compute_session(dev, session, sensor);
1127
1128 return session;
1129 }
1130
1131 /**
1132 * for fast power saving methods only, like disabling certain amplifiers
1133 * @param dev device to use
1134 * @param enable true to set inot powersaving
1135 * */
save_power(Genesys_Device * dev,bool enable) const1136 void CommandSetGl843::save_power(Genesys_Device* dev, bool enable) const
1137 {
1138 DBG_HELPER_ARGS(dbg, "enable = %d", enable);
1139
1140 // switch KV-SS080 lamp off
1141 if (dev->model->gpio_id == GpioId::KVSS080) {
1142 uint8_t val = dev->interface->read_register(REG_0x6C);
1143 if (enable) {
1144 val &= 0xef;
1145 } else {
1146 val |= 0x10;
1147 }
1148 dev->interface->write_register(REG_0x6C, val);
1149 }
1150 }
1151
set_powersaving(Genesys_Device * dev,int delay) const1152 void CommandSetGl843::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const
1153 {
1154 (void) dev;
1155 DBG_HELPER_ARGS(dbg, "delay = %d", delay);
1156 }
1157
gl843_get_paper_sensor(Genesys_Device * dev)1158 static bool gl843_get_paper_sensor(Genesys_Device* dev)
1159 {
1160 DBG_HELPER(dbg);
1161
1162 uint8_t val = dev->interface->read_register(REG_0x6D);
1163
1164 return (val & 0x1) == 0;
1165 }
1166
eject_document(Genesys_Device * dev) const1167 void CommandSetGl843::eject_document(Genesys_Device* dev) const
1168 {
1169 (void) dev;
1170 DBG_HELPER(dbg);
1171 }
1172
1173
load_document(Genesys_Device * dev) const1174 void CommandSetGl843::load_document(Genesys_Device* dev) const
1175 {
1176 DBG_HELPER(dbg);
1177 (void) dev;
1178 }
1179
1180 /**
1181 * detects end of document and adjust current scan
1182 * to take it into account
1183 * used by sheetfed scanners
1184 */
detect_document_end(Genesys_Device * dev) const1185 void CommandSetGl843::detect_document_end(Genesys_Device* dev) const
1186 {
1187 DBG_HELPER(dbg);
1188 bool paper_loaded = gl843_get_paper_sensor(dev);
1189
1190 /* sheetfed scanner uses home sensor as paper present */
1191 if (dev->document && !paper_loaded) {
1192 DBG(DBG_info, "%s: no more document\n", __func__);
1193 dev->document = false;
1194
1195 unsigned scanned_lines = 0;
1196 catch_all_exceptions(__func__, [&](){ sanei_genesys_read_scancnt(dev, &scanned_lines); });
1197
1198 std::size_t output_lines = dev->session.output_line_count;
1199
1200 std::size_t offset_lines = static_cast<std::size_t>(
1201 (dev->model->post_scan * dev->session.params.yres) / MM_PER_INCH);
1202
1203 std::size_t scan_end_lines = scanned_lines + offset_lines;
1204
1205 std::size_t remaining_lines = dev->get_pipeline_source().remaining_bytes() /
1206 dev->session.output_line_bytes_raw;
1207
1208 DBG(DBG_io, "%s: scanned_lines=%u\n", __func__, scanned_lines);
1209 DBG(DBG_io, "%s: scan_end_lines=%zu\n", __func__, scan_end_lines);
1210 DBG(DBG_io, "%s: output_lines=%zu\n", __func__, output_lines);
1211 DBG(DBG_io, "%s: remaining_lines=%zu\n", __func__, remaining_lines);
1212
1213 if (scan_end_lines > output_lines) {
1214 auto skip_lines = scan_end_lines - output_lines;
1215
1216 if (remaining_lines > skip_lines) {
1217 remaining_lines -= skip_lines;
1218 dev->get_pipeline_source().set_remaining_bytes(remaining_lines *
1219 dev->session.output_line_bytes_raw);
1220 dev->total_bytes_to_read -= skip_lines * dev->session.output_line_bytes_requested;
1221 }
1222 }
1223 }
1224 }
1225
1226 // Send the low-level scan command
begin_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,bool start_motor) const1227 void CommandSetGl843::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
1228 Genesys_Register_Set* reg, bool start_motor) const
1229 {
1230 DBG_HELPER(dbg);
1231 (void) sensor;
1232
1233 /* set up GPIO for scan */
1234 switch(dev->model->gpio_id) {
1235 /* KV case */
1236 case GpioId::KVSS080:
1237 dev->interface->write_register(REG_0xA9, 0x00);
1238 dev->interface->write_register(REG_0xA6, 0xf6);
1239 // blinking led
1240 dev->interface->write_register(0x7e, 0x04);
1241 break;
1242 case GpioId::G4050:
1243 dev->interface->write_register(REG_0xA7, 0xfe);
1244 dev->interface->write_register(REG_0xA8, 0x3e);
1245 dev->interface->write_register(REG_0xA9, 0x06);
1246 if ((reg->get8(0x05) & REG_0x05_DPIHW) == REG_0x05_DPIHW_600) {
1247 dev->interface->write_register(REG_0x6C, 0x20);
1248 dev->interface->write_register(REG_0xA6, 0x44);
1249 } else {
1250 dev->interface->write_register(REG_0x6C, 0x60);
1251 dev->interface->write_register(REG_0xA6, 0x46);
1252 }
1253
1254 if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1255 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1256 }
1257
1258 if (reg->state.is_xpa_on) {
1259 dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
1260 }
1261
1262 // blinking led
1263 dev->interface->write_register(REG_0x7E, 0x01);
1264 break;
1265 case GpioId::CANON_8400F:
1266 if (dev->session.params.xres == 3200)
1267 {
1268 GenesysRegisterSettingSet reg_settings = {
1269 { 0x6c, 0x00, 0x02 },
1270 };
1271 apply_reg_settings_to_device(*dev, reg_settings);
1272 }
1273 if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1274 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1275 }
1276 if (reg->state.is_xpa_on) {
1277 dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
1278 }
1279 break;
1280 case GpioId::CANON_8600F:
1281 if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1282 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1283 }
1284 if (reg->state.is_xpa_on) {
1285 dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
1286 }
1287 break;
1288 case GpioId::PLUSTEK_OPTICFILM_7200I:
1289 case GpioId::PLUSTEK_OPTICFILM_7300:
1290 case GpioId::PLUSTEK_OPTICFILM_7500I: {
1291 if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1292 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1293 }
1294 break;
1295 }
1296 case GpioId::CANON_4400F:
1297 default:
1298 break;
1299 }
1300
1301 scanner_clear_scan_and_feed_counts(*dev);
1302
1303 // enable scan and motor
1304 uint8_t val = dev->interface->read_register(REG_0x01);
1305 val |= REG_0x01_SCAN;
1306 dev->interface->write_register(REG_0x01, val);
1307
1308 scanner_start_action(*dev, start_motor);
1309
1310 switch (reg->state.motor_mode) {
1311 case MotorMode::PRIMARY: {
1312 if (reg->state.is_motor_on) {
1313 dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
1314 }
1315 break;
1316 }
1317 case MotorMode::PRIMARY_AND_SECONDARY: {
1318 if (reg->state.is_motor_on) {
1319 dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
1320 dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
1321 }
1322 break;
1323 }
1324 case MotorMode::SECONDARY: {
1325 if (reg->state.is_motor_on) {
1326 dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
1327 }
1328 break;
1329 }
1330 }
1331 }
1332
1333
1334 // Send the stop scan command
end_scan(Genesys_Device * dev,Genesys_Register_Set * reg,bool check_stop) const1335 void CommandSetGl843::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
1336 bool check_stop) const
1337 {
1338 DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
1339
1340 // post scan gpio
1341 dev->interface->write_register(0x7e, 0x00);
1342
1343 if (reg->state.is_xpa_on) {
1344 dev->cmd_set->set_xpa_lamp_power(*dev, false);
1345 }
1346
1347 if (!dev->model->is_sheetfed) {
1348 scanner_stop_action(*dev);
1349 }
1350 }
1351
1352 /** @brief Moves the slider to the home (top) position slowly
1353 * */
move_back_home(Genesys_Device * dev,bool wait_until_home) const1354 void CommandSetGl843::move_back_home(Genesys_Device* dev, bool wait_until_home) const
1355 {
1356 scanner_move_back_home(*dev, wait_until_home);
1357 }
1358
1359 // init registers for shading calibration shading calibration is done at dpihw
init_regs_for_shading(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1360 void CommandSetGl843::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
1361 Genesys_Register_Set& regs) const
1362 {
1363 DBG_HELPER(dbg);
1364 int move;
1365
1366 float calib_size_mm = 0;
1367 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
1368 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1369 {
1370 calib_size_mm = dev->model->y_size_calib_ta_mm;
1371 } else {
1372 calib_size_mm = dev->model->y_size_calib_mm;
1373 }
1374
1375 unsigned resolution = sensor.shading_resolution;
1376
1377 unsigned channels = 3;
1378 const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
1379 dev->settings.scan_method);
1380
1381 unsigned calib_pixels = 0;
1382 unsigned calib_pixels_offset = 0;
1383
1384 if (should_calibrate_only_active_area(*dev, dev->settings)) {
1385 float offset = dev->model->x_offset_ta;
1386 // FIXME: we should use resolution here
1387 offset = static_cast<float>((offset * dev->settings.xres) / MM_PER_INCH);
1388
1389 float size = dev->model->x_size_ta;
1390 size = static_cast<float>((size * dev->settings.xres) / MM_PER_INCH);
1391
1392 calib_pixels_offset = static_cast<std::size_t>(offset);
1393 calib_pixels = static_cast<std::size_t>(size);
1394 } else {
1395 calib_pixels_offset = 0;
1396 calib_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
1397 }
1398
1399 ScanFlag flags = ScanFlag::DISABLE_SHADING |
1400 ScanFlag::DISABLE_GAMMA |
1401 ScanFlag::DISABLE_BUFFER_FULL_MOVE;
1402
1403 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
1404 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1405 {
1406 // note: scanner_move_to_ta() function has already been called and the sensor is at the
1407 // transparency adapter
1408 move = static_cast<int>(dev->model->y_offset_calib_white_ta - dev->model->y_offset_sensor_to_ta);
1409 if (dev->model->model_id == ModelId::CANON_8600F && resolution == 2400) {
1410 move /= 2;
1411 }
1412 if (dev->model->model_id == ModelId::CANON_8600F && resolution == 4800) {
1413 move /= 4;
1414 }
1415 flags |= ScanFlag::USE_XPA;
1416 } else {
1417 move = static_cast<int>(dev->model->y_offset_calib_white);
1418 }
1419
1420 move = static_cast<int>((move * resolution) / MM_PER_INCH);
1421 unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
1422
1423 ScanSession session;
1424 session.params.xres = resolution;
1425 session.params.yres = resolution;
1426 session.params.startx = calib_pixels_offset;
1427 session.params.starty = move;
1428 session.params.pixels = calib_pixels;
1429 session.params.lines = calib_lines;
1430 session.params.depth = 16;
1431 session.params.channels = channels;
1432 session.params.scan_method = dev->settings.scan_method;
1433 session.params.scan_mode = dev->settings.scan_mode;
1434 session.params.color_filter = dev->settings.color_filter;
1435 session.params.flags = flags;
1436 compute_session(dev, session, calib_sensor);
1437
1438 init_regs_for_scan_session(dev, calib_sensor, ®s, session);
1439
1440 dev->calib_session = session;
1441 }
1442
1443 /**
1444 * This function sends gamma tables to ASIC
1445 */
send_gamma_table(Genesys_Device * dev,const Genesys_Sensor & sensor) const1446 void CommandSetGl843::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
1447 {
1448 DBG_HELPER(dbg);
1449 int size;
1450 int i;
1451
1452 size = 256;
1453
1454 /* allocate temporary gamma tables: 16 bits words, 3 channels */
1455 std::vector<uint8_t> gamma(size * 2 * 3);
1456
1457 std::vector<uint16_t> rgamma = get_gamma_table(dev, sensor, GENESYS_RED);
1458 std::vector<uint16_t> ggamma = get_gamma_table(dev, sensor, GENESYS_GREEN);
1459 std::vector<uint16_t> bgamma = get_gamma_table(dev, sensor, GENESYS_BLUE);
1460
1461 // copy sensor specific's gamma tables
1462 for (i = 0; i < size; i++) {
1463 gamma[i * 2 + size * 0 + 0] = rgamma[i] & 0xff;
1464 gamma[i * 2 + size * 0 + 1] = (rgamma[i] >> 8) & 0xff;
1465 gamma[i * 2 + size * 2 + 0] = ggamma[i] & 0xff;
1466 gamma[i * 2 + size * 2 + 1] = (ggamma[i] >> 8) & 0xff;
1467 gamma[i * 2 + size * 4 + 0] = bgamma[i] & 0xff;
1468 gamma[i * 2 + size * 4 + 1] = (bgamma[i] >> 8) & 0xff;
1469 }
1470
1471 dev->interface->write_gamma(0x28, 0x0000, gamma.data(), size * 2 * 3);
1472 }
1473
1474 /* this function does the led calibration by scanning one line of the calibration
1475 area below scanner's top on white strip.
1476
1477 -needs working coarse/gain
1478 */
led_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1479 SensorExposure CommandSetGl843::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1480 Genesys_Register_Set& regs) const
1481 {
1482 return scanner_led_calibration(*dev, sensor, regs);
1483 }
1484
offset_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1485 void CommandSetGl843::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1486 Genesys_Register_Set& regs) const
1487 {
1488 scanner_offset_calibration(*dev, sensor, regs);
1489 }
1490
coarse_gain_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs,int dpi) const1491 void CommandSetGl843::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1492 Genesys_Register_Set& regs, int dpi) const
1493 {
1494 scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
1495 }
1496
1497 // wait for lamp warmup by scanning the same line until difference
1498 // between 2 scans is below a threshold
init_regs_for_warmup(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg) const1499 void CommandSetGl843::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
1500 Genesys_Register_Set* reg) const
1501 {
1502 DBG_HELPER(dbg);
1503 (void) sensor;
1504
1505 unsigned channels = 3;
1506 unsigned resolution = dev->model->get_resolution_settings(dev->settings.scan_method)
1507 .get_nearest_resolution_x(600);
1508
1509 const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
1510 dev->settings.scan_method);
1511 unsigned num_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH / 2;
1512
1513 *reg = dev->reg;
1514
1515 auto flags = ScanFlag::DISABLE_SHADING |
1516 ScanFlag::DISABLE_GAMMA |
1517 ScanFlag::SINGLE_LINE |
1518 ScanFlag::IGNORE_STAGGER_OFFSET |
1519 ScanFlag::IGNORE_COLOR_OFFSET;
1520 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
1521 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1522 {
1523 flags |= ScanFlag::USE_XPA;
1524 }
1525
1526 ScanSession session;
1527 session.params.xres = resolution;
1528 session.params.yres = resolution;
1529 session.params.startx = (num_pixels / 2) * resolution / calib_sensor.full_resolution;
1530 session.params.starty = 0;
1531 session.params.pixels = num_pixels;
1532 session.params.lines = 1;
1533 session.params.depth = dev->model->bpp_color_values.front();
1534 session.params.channels = channels;
1535 session.params.scan_method = dev->settings.scan_method;
1536 session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
1537 session.params.color_filter = dev->settings.color_filter;
1538 session.params.flags = flags;
1539
1540 compute_session(dev, session, calib_sensor);
1541
1542 init_regs_for_scan_session(dev, calib_sensor, reg, session);
1543
1544 sanei_genesys_set_motor_power(*reg, false);
1545 }
1546
1547 /**
1548 * set up GPIO/GPOE for idle state
1549 WRITE GPIO[17-21]= GPIO19
1550 WRITE GPOE[17-21]= GPOE21 GPOE20 GPOE19 GPOE18
1551 genesys_write_register(0xa8,0x3e)
1552 GPIO(0xa8)=0x3e
1553 */
gl843_init_gpio(Genesys_Device * dev)1554 static void gl843_init_gpio(Genesys_Device* dev)
1555 {
1556 DBG_HELPER(dbg);
1557 apply_registers_ordered(dev->gpo.regs, { 0x6e, 0x6f }, [&](const GenesysRegisterSetting& reg)
1558 {
1559 dev->interface->write_register(reg.address, reg.value);
1560 });
1561 }
1562
1563
1564 /* *
1565 * initialize ASIC from power on condition
1566 */
asic_boot(Genesys_Device * dev,bool cold) const1567 void CommandSetGl843::asic_boot(Genesys_Device* dev, bool cold) const
1568 {
1569 DBG_HELPER(dbg);
1570 uint8_t val;
1571
1572 if (cold) {
1573 dev->interface->write_register(0x0e, 0x01);
1574 dev->interface->write_register(0x0e, 0x00);
1575 }
1576
1577 if(dev->usb_mode == 1)
1578 {
1579 val = 0x14;
1580 }
1581 else
1582 {
1583 val = 0x11;
1584 }
1585 dev->interface->write_0x8c(0x0f, val);
1586
1587 // test CHKVER
1588 val = dev->interface->read_register(REG_0x40);
1589 if (val & REG_0x40_CHKVER) {
1590 val = dev->interface->read_register(0x00);
1591 DBG(DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val);
1592 }
1593
1594 /* Set default values for registers */
1595 gl843_init_registers (dev);
1596
1597 if (dev->model->model_id == ModelId::CANON_8600F) {
1598 // turns on vref control for maximum current of the motor driver
1599 dev->interface->write_register(REG_0x6B, 0x72);
1600 } else {
1601 dev->interface->write_register(REG_0x6B, 0x02);
1602 }
1603
1604 // Write initial registers
1605 dev->interface->write_registers(dev->reg);
1606
1607 // Enable DRAM by setting a rising edge on bit 3 of reg 0x0b
1608 val = dev->reg.find_reg(0x0b).value & REG_0x0B_DRAMSEL;
1609 val = (val | REG_0x0B_ENBDRAM);
1610 dev->interface->write_register(REG_0x0B, val);
1611 dev->reg.find_reg(0x0b).value = val;
1612
1613 if (dev->model->model_id == ModelId::CANON_8400F) {
1614 dev->interface->write_0x8c(0x1e, 0x01);
1615 dev->interface->write_0x8c(0x10, 0xb4);
1616 dev->interface->write_0x8c(0x0f, 0x02);
1617 }
1618 else if (dev->model->model_id == ModelId::CANON_8600F) {
1619 dev->interface->write_0x8c(0x10, 0xc8);
1620 } else if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
1621 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
1622 {
1623 dev->interface->write_0x8c(0x10, 0xd4);
1624 } else {
1625 dev->interface->write_0x8c(0x10, 0xb4);
1626 }
1627
1628 /* CLKSET */
1629 int clock_freq = REG_0x0B_48MHZ;
1630 switch (dev->model->model_id) {
1631 case ModelId::CANON_8600F:
1632 clock_freq = REG_0x0B_60MHZ;
1633 break;
1634 case ModelId::PLUSTEK_OPTICFILM_7200I:
1635 clock_freq = REG_0x0B_30MHZ;
1636 break;
1637 case ModelId::PLUSTEK_OPTICFILM_7300:
1638 case ModelId::PLUSTEK_OPTICFILM_7500I:
1639 clock_freq = REG_0x0B_40MHZ;
1640 break;
1641 default:
1642 break;
1643 }
1644
1645 val = (dev->reg.find_reg(0x0b).value & ~REG_0x0B_CLKSET) | clock_freq;
1646
1647 dev->interface->write_register(REG_0x0B, val);
1648 dev->reg.find_reg(0x0b).value = val;
1649
1650 /* prevent further writings by bulk write register */
1651 dev->reg.remove_reg(0x0b);
1652
1653 // set RAM read address
1654 dev->interface->write_register(REG_0x29, 0x00);
1655 dev->interface->write_register(REG_0x2A, 0x00);
1656 dev->interface->write_register(REG_0x2B, 0x00);
1657
1658 // setup gpio
1659 gl843_init_gpio(dev);
1660 dev->interface->sleep_ms(100);
1661 }
1662
1663 /* *
1664 * initialize backend and ASIC : registers, motor tables, and gamma tables
1665 * then ensure scanner's head is at home
1666 */
init(Genesys_Device * dev) const1667 void CommandSetGl843::init(Genesys_Device* dev) const
1668 {
1669 DBG_INIT ();
1670 DBG_HELPER(dbg);
1671
1672 sanei_genesys_asic_init(dev);
1673 }
1674
update_hardware_sensors(Genesys_Scanner * s) const1675 void CommandSetGl843::update_hardware_sensors(Genesys_Scanner* s) const
1676 {
1677 DBG_HELPER(dbg);
1678 /* do what is needed to get a new set of events, but try to not lose
1679 any of them.
1680 */
1681
1682 uint8_t val = s->dev->interface->read_register(REG_0x6D);
1683
1684 switch (s->dev->model->gpio_id)
1685 {
1686 case GpioId::KVSS080:
1687 s->buttons[BUTTON_SCAN_SW].write((val & 0x04) == 0);
1688 break;
1689 case GpioId::G4050:
1690 s->buttons[BUTTON_SCAN_SW].write((val & 0x01) == 0);
1691 s->buttons[BUTTON_FILE_SW].write((val & 0x02) == 0);
1692 s->buttons[BUTTON_EMAIL_SW].write((val & 0x04) == 0);
1693 s->buttons[BUTTON_COPY_SW].write((val & 0x08) == 0);
1694 break;
1695 case GpioId::CANON_4400F:
1696 case GpioId::CANON_8400F:
1697 default:
1698 break;
1699 }
1700 }
1701
update_home_sensor_gpio(Genesys_Device & dev) const1702 void CommandSetGl843::update_home_sensor_gpio(Genesys_Device& dev) const
1703 {
1704 DBG_HELPER(dbg);
1705 (void) dev;
1706 }
1707
1708 /**
1709 * Send shading calibration data. The buffer is considered to always hold values
1710 * for all the channels.
1711 */
send_shading_data(Genesys_Device * dev,const Genesys_Sensor & sensor,uint8_t * data,int size) const1712 void CommandSetGl843::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
1713 uint8_t* data, int size) const
1714 {
1715 DBG_HELPER(dbg);
1716 uint32_t final_size, i;
1717 uint8_t *buffer;
1718 int count;
1719
1720 int offset = 0;
1721 unsigned length = size;
1722
1723 if (dev->reg.get8(REG_0x01) & REG_0x01_SHDAREA) {
1724 offset = dev->session.params.startx * sensor.shading_resolution /
1725 dev->session.params.xres;
1726
1727 length = dev->session.output_pixels * sensor.shading_resolution /
1728 dev->session.params.xres;
1729
1730 offset += sensor.shading_pixel_offset;
1731
1732 // 16 bit words, 2 words per color, 3 color channels
1733 length *= 2 * 2 * 3;
1734 offset *= 2 * 2 * 3;
1735 } else {
1736 offset += sensor.shading_pixel_offset * 2 * 2 * 3;
1737 }
1738
1739 dev->interface->record_key_value("shading_offset", std::to_string(offset));
1740 dev->interface->record_key_value("shading_length", std::to_string(length));
1741
1742 /* compute and allocate size for final data */
1743 final_size = ((length+251) / 252) * 256;
1744 DBG(DBG_io, "%s: final shading size=%04x (length=%d)\n", __func__, final_size, length);
1745 std::vector<uint8_t> final_data(final_size, 0);
1746
1747 /* copy regular shading data to the expected layout */
1748 buffer = final_data.data();
1749 count = 0;
1750 if (offset < 0) {
1751 count += (-offset);
1752 length -= (-offset);
1753 offset = 0;
1754 }
1755 if (static_cast<int>(length) + offset > static_cast<int>(size)) {
1756 length = size - offset;
1757 }
1758
1759 /* loop over calibration data */
1760 for (i = 0; i < length; i++)
1761 {
1762 buffer[count] = data[offset+i];
1763 count++;
1764 if ((count % (256*2)) == (252*2))
1765 {
1766 count += 4*2;
1767 }
1768 }
1769
1770 dev->interface->write_buffer(0x3c, 0, final_data.data(), count);
1771 }
1772
needs_home_before_init_regs_for_scan(Genesys_Device * dev) const1773 bool CommandSetGl843::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
1774 {
1775 (void) dev;
1776 return true;
1777 }
1778
wait_for_motor_stop(Genesys_Device * dev) const1779 void CommandSetGl843::wait_for_motor_stop(Genesys_Device* dev) const
1780 {
1781 (void) dev;
1782 }
1783
1784 } // namespace gl843
1785 } // namespace genesys
1786