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