1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2010-2016 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 "gl124.h"
46 #include "gl124_registers.h"
47 #include "test_settings.h"
48
49 #include <vector>
50
51 namespace genesys {
52 namespace gl124 {
53
54 struct Gpio_layout
55 {
56 std::uint8_t r31;
57 std::uint8_t r32;
58 std::uint8_t r33;
59 std::uint8_t r34;
60 std::uint8_t r35;
61 std::uint8_t r36;
62 std::uint8_t r38;
63 };
64
65 /** @brief gpio layout
66 * describes initial gpio settings for a given model
67 * registers 0x31 to 0x38
68 */
69 static Gpio_layout gpios[] = {
70 /* LiDE 110 */
71 { /* 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38 */
72 0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00
73 },
74 /* LiDE 210 */
75 {
76 0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00
77 },
78 /* LiDE 120 */
79 {
80 0x9f, 0x53, 0x01, 0x80, 0x5f, 0x01, 0x00
81 },
82 };
83
84
85 /** @brief set all registers to default values .
86 * This function is called only once at the beginning and
87 * fills register startup values for registers reused across scans.
88 * Those that are rarely modified or not modified are written
89 * individually.
90 * @param dev device structure holding register set to initialize
91 */
92 static void
gl124_init_registers(Genesys_Device * dev)93 gl124_init_registers (Genesys_Device * dev)
94 {
95 DBG_HELPER(dbg);
96
97 dev->reg.clear();
98
99 // default to LiDE 110
100 dev->reg.init_reg(0x01, 0xa2); // + REG_0x01_SHDAREA
101 dev->reg.init_reg(0x02, 0x90);
102 dev->reg.init_reg(0x03, 0x50);
103 dev->reg.init_reg(0x04, 0x03);
104 dev->reg.init_reg(0x05, 0x00);
105
106 if(dev->model->sensor_id == SensorId::CIS_CANON_LIDE_120) {
107 dev->reg.init_reg(0x06, 0x50);
108 dev->reg.init_reg(0x07, 0x00);
109 } else {
110 dev->reg.init_reg(0x03, 0x50 & ~REG_0x03_AVEENB);
111 dev->reg.init_reg(0x06, 0x50 | REG_0x06_GAIN4);
112 }
113 dev->reg.init_reg(0x09, 0x00);
114 dev->reg.init_reg(0x0a, 0xc0);
115 dev->reg.init_reg(0x0b, 0x2a);
116 dev->reg.init_reg(0x0c, 0x12);
117 dev->reg.init_reg(0x11, 0x00);
118 dev->reg.init_reg(0x12, 0x00);
119 dev->reg.init_reg(0x13, 0x0f);
120 dev->reg.init_reg(0x14, 0x00);
121 dev->reg.init_reg(0x15, 0x80);
122 dev->reg.init_reg(0x16, 0x10); // SENSOR_DEF
123 dev->reg.init_reg(0x17, 0x04); // SENSOR_DEF
124 dev->reg.init_reg(0x18, 0x00); // SENSOR_DEF
125 dev->reg.init_reg(0x19, 0x01); // SENSOR_DEF
126 dev->reg.init_reg(0x1a, 0x30); // SENSOR_DEF
127 dev->reg.init_reg(0x1b, 0x00); // SENSOR_DEF
128 dev->reg.init_reg(0x1c, 0x00); // SENSOR_DEF
129 dev->reg.init_reg(0x1d, 0x01); // SENSOR_DEF
130 dev->reg.init_reg(0x1e, 0x10);
131 dev->reg.init_reg(0x1f, 0x00);
132 dev->reg.init_reg(0x20, 0x15); // SENSOR_DEF
133 dev->reg.init_reg(0x21, 0x00);
134 if(dev->model->sensor_id != SensorId::CIS_CANON_LIDE_120) {
135 dev->reg.init_reg(0x22, 0x02);
136 } else {
137 dev->reg.init_reg(0x22, 0x14);
138 }
139 dev->reg.init_reg(0x23, 0x00);
140 dev->reg.init_reg(0x24, 0x00);
141 dev->reg.init_reg(0x25, 0x00);
142 dev->reg.init_reg(0x26, 0x0d);
143 dev->reg.init_reg(0x27, 0x48);
144 dev->reg.init_reg(0x28, 0x00);
145 dev->reg.init_reg(0x29, 0x56);
146 dev->reg.init_reg(0x2a, 0x5e);
147 dev->reg.init_reg(0x2b, 0x02);
148 dev->reg.init_reg(0x2c, 0x02);
149 dev->reg.init_reg(0x2d, 0x58);
150 dev->reg.init_reg(0x3b, 0x00);
151 dev->reg.init_reg(0x3c, 0x00);
152 dev->reg.init_reg(0x3d, 0x00);
153 dev->reg.init_reg(0x3e, 0x00);
154 dev->reg.init_reg(0x3f, 0x02);
155 dev->reg.init_reg(0x40, 0x00);
156 dev->reg.init_reg(0x41, 0x00);
157 dev->reg.init_reg(0x42, 0x00);
158 dev->reg.init_reg(0x43, 0x00);
159 dev->reg.init_reg(0x44, 0x00);
160 dev->reg.init_reg(0x45, 0x00);
161 dev->reg.init_reg(0x46, 0x00);
162 dev->reg.init_reg(0x47, 0x00);
163 dev->reg.init_reg(0x48, 0x00);
164 dev->reg.init_reg(0x49, 0x00);
165 dev->reg.init_reg(0x4f, 0x00);
166 dev->reg.init_reg(0x52, 0x00); // SENSOR_DEF
167 dev->reg.init_reg(0x53, 0x02); // SENSOR_DEF
168 dev->reg.init_reg(0x54, 0x04); // SENSOR_DEF
169 dev->reg.init_reg(0x55, 0x06); // SENSOR_DEF
170 dev->reg.init_reg(0x56, 0x04); // SENSOR_DEF
171 dev->reg.init_reg(0x57, 0x04); // SENSOR_DEF
172 dev->reg.init_reg(0x58, 0x04); // SENSOR_DEF
173 dev->reg.init_reg(0x59, 0x04); // SENSOR_DEF
174 dev->reg.init_reg(0x5a, 0x1a); // SENSOR_DEF
175 dev->reg.init_reg(0x5b, 0x00); // SENSOR_DEF
176 dev->reg.init_reg(0x5c, 0xc0); // SENSOR_DEF
177 dev->reg.init_reg(0x5f, 0x00);
178 dev->reg.init_reg(0x60, 0x02);
179 dev->reg.init_reg(0x61, 0x00); // SENSOR_DEF
180 dev->reg.init_reg(0x62, 0x00);
181 dev->reg.init_reg(0x63, 0x00);
182 dev->reg.init_reg(0x64, 0x00);
183 dev->reg.init_reg(0x65, 0x00);
184 dev->reg.init_reg(0x66, 0x00);
185 dev->reg.init_reg(0x67, 0x00);
186 dev->reg.init_reg(0x68, 0x00);
187 dev->reg.init_reg(0x69, 0x00);
188 dev->reg.init_reg(0x6a, 0x00);
189 dev->reg.init_reg(0x6b, 0x00);
190 dev->reg.init_reg(0x6c, 0x00);
191 dev->reg.init_reg(0x6e, 0x00);
192 dev->reg.init_reg(0x6f, 0x00);
193
194 if (dev->model->sensor_id != SensorId::CIS_CANON_LIDE_120) {
195 dev->reg.init_reg(0x6d, 0xd0);
196 dev->reg.init_reg(0x71, 0x08);
197 } else {
198 dev->reg.init_reg(0x6d, 0x00);
199 dev->reg.init_reg(0x71, 0x1f);
200 }
201 dev->reg.init_reg(0x70, 0x00); // SENSOR_DEF
202 dev->reg.init_reg(0x71, 0x08); // SENSOR_DEF
203 dev->reg.init_reg(0x72, 0x08); // SENSOR_DEF
204 dev->reg.init_reg(0x73, 0x0a); // SENSOR_DEF
205
206 // CKxMAP
207 dev->reg.init_reg(0x74, 0x00); // SENSOR_DEF
208 dev->reg.init_reg(0x75, 0x00); // SENSOR_DEF
209 dev->reg.init_reg(0x76, 0x3c); // SENSOR_DEF
210 dev->reg.init_reg(0x77, 0x00); // SENSOR_DEF
211 dev->reg.init_reg(0x78, 0x00); // SENSOR_DEF
212 dev->reg.init_reg(0x79, 0x9f); // SENSOR_DEF
213 dev->reg.init_reg(0x7a, 0x00); // SENSOR_DEF
214 dev->reg.init_reg(0x7b, 0x00); // SENSOR_DEF
215 dev->reg.init_reg(0x7c, 0x55); // SENSOR_DEF
216
217 dev->reg.init_reg(0x7d, 0x00);
218 dev->reg.init_reg(0x7e, 0x08);
219 dev->reg.init_reg(0x7f, 0x58);
220
221 if (dev->model->sensor_id != SensorId::CIS_CANON_LIDE_120) {
222 dev->reg.init_reg(0x80, 0x00);
223 dev->reg.init_reg(0x81, 0x14);
224 } else {
225 dev->reg.init_reg(0x80, 0x00);
226 dev->reg.init_reg(0x81, 0x10);
227 }
228
229 // STRPIXEL
230 dev->reg.init_reg(0x82, 0x00);
231 dev->reg.init_reg(0x83, 0x00);
232 dev->reg.init_reg(0x84, 0x00);
233
234 // ENDPIXEL
235 dev->reg.init_reg(0x85, 0x00);
236 dev->reg.init_reg(0x86, 0x00);
237 dev->reg.init_reg(0x87, 0x00);
238
239 dev->reg.init_reg(0x88, 0x00); // SENSOR_DEF
240 dev->reg.init_reg(0x89, 0x65); // SENSOR_DEF
241 dev->reg.init_reg(0x8a, 0x00);
242 dev->reg.init_reg(0x8b, 0x00);
243 dev->reg.init_reg(0x8c, 0x00);
244 dev->reg.init_reg(0x8d, 0x00);
245 dev->reg.init_reg(0x8e, 0x00);
246 dev->reg.init_reg(0x8f, 0x00);
247 dev->reg.init_reg(0x90, 0x00);
248 dev->reg.init_reg(0x91, 0x00);
249 dev->reg.init_reg(0x92, 0x00);
250 dev->reg.init_reg(0x93, 0x00); // SENSOR_DEF
251 dev->reg.init_reg(0x94, 0x14); // SENSOR_DEF
252 dev->reg.init_reg(0x95, 0x30); // SENSOR_DEF
253 dev->reg.init_reg(0x96, 0x00); // SENSOR_DEF
254 dev->reg.init_reg(0x97, 0x90); // SENSOR_DEF
255 dev->reg.init_reg(0x98, 0x01); // SENSOR_DEF
256 dev->reg.init_reg(0x99, 0x1f);
257 dev->reg.init_reg(0x9a, 0x00);
258 dev->reg.init_reg(0x9b, 0x80);
259 dev->reg.init_reg(0x9c, 0x80);
260 dev->reg.init_reg(0x9d, 0x3f);
261 dev->reg.init_reg(0x9e, 0x00);
262 dev->reg.init_reg(0x9f, 0x00);
263 dev->reg.init_reg(0xa0, 0x20);
264 dev->reg.init_reg(0xa1, 0x30);
265 dev->reg.init_reg(0xa2, 0x00);
266 dev->reg.init_reg(0xa3, 0x20);
267 dev->reg.init_reg(0xa4, 0x01);
268 dev->reg.init_reg(0xa5, 0x00);
269 dev->reg.init_reg(0xa6, 0x00);
270 dev->reg.init_reg(0xa7, 0x08);
271 dev->reg.init_reg(0xa8, 0x00);
272 dev->reg.init_reg(0xa9, 0x08);
273 dev->reg.init_reg(0xaa, 0x01);
274 dev->reg.init_reg(0xab, 0x00);
275 dev->reg.init_reg(0xac, 0x00);
276 dev->reg.init_reg(0xad, 0x40);
277 dev->reg.init_reg(0xae, 0x01);
278 dev->reg.init_reg(0xaf, 0x00);
279 dev->reg.init_reg(0xb0, 0x00);
280 dev->reg.init_reg(0xb1, 0x40);
281 dev->reg.init_reg(0xb2, 0x00);
282 dev->reg.init_reg(0xb3, 0x09);
283 dev->reg.init_reg(0xb4, 0x5b);
284 dev->reg.init_reg(0xb5, 0x00);
285 dev->reg.init_reg(0xb6, 0x10);
286 dev->reg.init_reg(0xb7, 0x3f);
287 dev->reg.init_reg(0xb8, 0x00);
288 dev->reg.init_reg(0xbb, 0x00);
289 dev->reg.init_reg(0xbc, 0xff);
290 dev->reg.init_reg(0xbd, 0x00);
291 dev->reg.init_reg(0xbe, 0x07);
292 dev->reg.init_reg(0xc3, 0x00);
293 dev->reg.init_reg(0xc4, 0x00);
294
295 /* gamma
296 dev->reg.init_reg(0xc5, 0x00);
297 dev->reg.init_reg(0xc6, 0x00);
298 dev->reg.init_reg(0xc7, 0x00);
299 dev->reg.init_reg(0xc8, 0x00);
300 dev->reg.init_reg(0xc9, 0x00);
301 dev->reg.init_reg(0xca, 0x00);
302 dev->reg.init_reg(0xcb, 0x00);
303 dev->reg.init_reg(0xcc, 0x00);
304 dev->reg.init_reg(0xcd, 0x00);
305 dev->reg.init_reg(0xce, 0x00);
306 */
307
308 if (dev->model->sensor_id == SensorId::CIS_CANON_LIDE_120) {
309 dev->reg.init_reg(0xc5, 0x20);
310 dev->reg.init_reg(0xc6, 0xeb);
311 dev->reg.init_reg(0xc7, 0x20);
312 dev->reg.init_reg(0xc8, 0xeb);
313 dev->reg.init_reg(0xc9, 0x20);
314 dev->reg.init_reg(0xca, 0xeb);
315 }
316
317 // memory layout
318 /*
319 dev->reg.init_reg(0xd0, 0x0a);
320 dev->reg.init_reg(0xd1, 0x1f);
321 dev->reg.init_reg(0xd2, 0x34);
322 */
323 dev->reg.init_reg(0xd3, 0x00);
324 dev->reg.init_reg(0xd4, 0x00);
325 dev->reg.init_reg(0xd5, 0x00);
326 dev->reg.init_reg(0xd6, 0x00);
327 dev->reg.init_reg(0xd7, 0x00);
328 dev->reg.init_reg(0xd8, 0x00);
329 dev->reg.init_reg(0xd9, 0x00);
330
331 // memory layout
332 /*
333 dev->reg.init_reg(0xe0, 0x00);
334 dev->reg.init_reg(0xe1, 0x48);
335 dev->reg.init_reg(0xe2, 0x15);
336 dev->reg.init_reg(0xe3, 0x90);
337 dev->reg.init_reg(0xe4, 0x15);
338 dev->reg.init_reg(0xe5, 0x91);
339 dev->reg.init_reg(0xe6, 0x2a);
340 dev->reg.init_reg(0xe7, 0xd9);
341 dev->reg.init_reg(0xe8, 0x2a);
342 dev->reg.init_reg(0xe9, 0xad);
343 dev->reg.init_reg(0xea, 0x40);
344 dev->reg.init_reg(0xeb, 0x22);
345 dev->reg.init_reg(0xec, 0x40);
346 dev->reg.init_reg(0xed, 0x23);
347 dev->reg.init_reg(0xee, 0x55);
348 dev->reg.init_reg(0xef, 0x6b);
349 dev->reg.init_reg(0xf0, 0x55);
350 dev->reg.init_reg(0xf1, 0x6c);
351 dev->reg.init_reg(0xf2, 0x6a);
352 dev->reg.init_reg(0xf3, 0xb4);
353 dev->reg.init_reg(0xf4, 0x6a);
354 dev->reg.init_reg(0xf5, 0xb5);
355 dev->reg.init_reg(0xf6, 0x7f);
356 dev->reg.init_reg(0xf7, 0xfd);
357 */
358
359 dev->reg.init_reg(0xf8, 0x01); // other value is 0x05
360 dev->reg.init_reg(0xf9, 0x00);
361 dev->reg.init_reg(0xfa, 0x00);
362 dev->reg.init_reg(0xfb, 0x00);
363 dev->reg.init_reg(0xfc, 0x00);
364 dev->reg.init_reg(0xff, 0x00);
365
366 // fine tune upon device description
367 const auto& sensor = sanei_genesys_find_sensor_any(dev);
368 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution,
369 3, ScanMethod::FLATBED);
370 sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw);
371 }
372
373 /** @brief * Set register values of 'special' ti type frontend
374 * Registers value are taken from the frontend register data
375 * set.
376 * @param dev device owning the AFE
377 * @param set flag AFE_INIT to specify the AFE must be reset before writing data
378 * */
gl124_set_ti_fe(Genesys_Device * dev,uint8_t set)379 static void gl124_set_ti_fe(Genesys_Device* dev, uint8_t set)
380 {
381 DBG_HELPER(dbg);
382 int i;
383
384 if (set == AFE_INIT) {
385 dev->frontend = dev->frontend_initial;
386 }
387
388 // start writing to DAC
389 dev->interface->write_fe_register(0x00, 0x80);
390
391 /* write values to analog frontend */
392 for (uint16_t addr = 0x01; addr < 0x04; addr++)
393 {
394 dev->interface->write_fe_register(addr, dev->frontend.regs.get_value(addr));
395 }
396
397 dev->interface->write_fe_register(0x04, 0x00);
398
399 /* these are not really sign for this AFE */
400 for (i = 0; i < 3; i++)
401 {
402 dev->interface->write_fe_register(0x05 + i, dev->frontend.regs.get_value(0x24 + i));
403 }
404
405 if (dev->model->adc_id == AdcId::CANON_LIDE_120) {
406 dev->interface->write_fe_register(0x00, 0x01);
407 }
408 else
409 {
410 dev->interface->write_fe_register(0x00, 0x11);
411 }
412 }
413
414
415 // Set values of analog frontend
set_fe(Genesys_Device * dev,const Genesys_Sensor & sensor,uint8_t set) const416 void CommandSetGl124::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
417 {
418 DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
419 set == AFE_SET ? "set" :
420 set == AFE_POWER_SAVE ? "powersave" : "huh?");
421 (void) sensor;
422 uint8_t val;
423
424 if (set == AFE_INIT) {
425 dev->frontend = dev->frontend_initial;
426 }
427
428 val = dev->interface->read_register(REG_0x0A);
429
430 /* route to correct analog FE */
431 switch ((val & REG_0x0A_SIFSEL) >> REG_0x0AS_SIFSEL) {
432 case 3:
433 gl124_set_ti_fe(dev, set);
434 break;
435 case 0:
436 case 1:
437 case 2:
438 default:
439 throw SaneException("unsupported analog FE 0x%02x", val);
440 }
441 }
442
gl124_init_motor_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,const MotorProfile & motor_profile,unsigned int scan_exposure_time,unsigned scan_yres,unsigned int scan_lines,unsigned int scan_dummy,unsigned int feed_steps,ScanColorMode scan_mode,ScanFlag flags)443 static void gl124_init_motor_regs_scan(Genesys_Device* dev,
444 const Genesys_Sensor& sensor,
445 Genesys_Register_Set* reg,
446 const MotorProfile& motor_profile,
447 unsigned int scan_exposure_time,
448 unsigned scan_yres,
449 unsigned int scan_lines,
450 unsigned int scan_dummy,
451 unsigned int feed_steps,
452 ScanColorMode scan_mode,
453 ScanFlag flags)
454 {
455 DBG_HELPER(dbg);
456 int use_fast_fed;
457 unsigned int lincnt, fast_dpi;
458 unsigned int feedl,dist;
459 uint32_t z1, z2;
460 unsigned yres;
461 unsigned min_speed;
462 unsigned int linesel;
463
464 DBG(DBG_info, "%s : scan_exposure_time=%d, scan_yres=%d, step_type=%d, scan_lines=%d, "
465 "scan_dummy=%d, feed_steps=%d, scan_mode=%d, flags=%x\n", __func__, scan_exposure_time,
466 scan_yres, static_cast<unsigned>(motor_profile.step_type), scan_lines, scan_dummy,
467 feed_steps, static_cast<unsigned>(scan_mode),
468 static_cast<unsigned>(flags));
469
470 /* we never use fast fed since we do manual feed for the scans */
471 use_fast_fed=0;
472
473 /* enforce motor minimal scan speed
474 * @TODO extend motor struct for this value */
475 if (scan_mode == ScanColorMode::COLOR_SINGLE_PASS)
476 {
477 min_speed = 900;
478 }
479 else
480 {
481 switch(dev->model->motor_id)
482 {
483 case MotorId::CANON_LIDE_110:
484 min_speed = 600;
485 break;
486 case MotorId::CANON_LIDE_120:
487 min_speed = 900;
488 break;
489 default:
490 min_speed = 900;
491 break;
492 }
493 }
494
495 /* compute min_speed and linesel */
496 if(scan_yres<min_speed)
497 {
498 yres=min_speed;
499 linesel = yres / scan_yres - 1;
500 /* limit case, we need a linesel > 0 */
501 if(linesel==0)
502 {
503 linesel=1;
504 yres=scan_yres*2;
505 }
506 }
507 else
508 {
509 yres=scan_yres;
510 linesel=0;
511 }
512
513 lincnt=scan_lines*(linesel+1);
514 reg->set24(REG_LINCNT, lincnt);
515
516 /* compute register 02 value */
517 uint8_t r02 = REG_0x02_NOTHOME;
518
519 if (use_fast_fed) {
520 r02 |= REG_0x02_FASTFED;
521 } else {
522 r02 &= ~REG_0x02_FASTFED;
523 }
524
525 if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
526 r02 |= REG_0x02_AGOHOME;
527 }
528
529 if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) || (yres >= sensor.full_resolution))
530 {
531 r02 |= REG_0x02_ACDCDIS;
532 }
533 if (has_flag(flags, ScanFlag::REVERSE)) {
534 r02 |= REG_0x02_MTRREV;
535 }
536
537 reg->set8(REG_0x02, r02);
538 sanei_genesys_set_motor_power(*reg, true);
539
540 reg->set16(REG_SCANFED, 4);
541
542 /* scan and backtracking slope table */
543 auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, yres,
544 scan_exposure_time, 1, motor_profile);
545 scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
546 scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
547
548 reg->set16(REG_STEPNO, scan_table.table.size());
549
550 /* fast table */
551 fast_dpi=yres;
552
553 /*
554 if (scan_mode != ScanColorMode::COLOR_SINGLE_PASS)
555 {
556 fast_dpi*=3;
557 }
558 */
559 auto fast_table = create_slope_table(dev->model->asic_type, dev->motor, fast_dpi,
560 scan_exposure_time, 1, motor_profile);
561 scanner_send_slope_table(dev, sensor, STOP_TABLE, fast_table.table);
562 scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
563
564 reg->set16(REG_FASTNO, fast_table.table.size());
565 reg->set16(REG_FSHDEC, fast_table.table.size());
566 reg->set16(REG_FMOVNO, fast_table.table.size());
567
568 /* subtract acceleration distance from feedl */
569 feedl=feed_steps;
570 feedl <<= static_cast<unsigned>(motor_profile.step_type);
571
572 dist = scan_table.table.size();
573 if (has_flag(flags, ScanFlag::FEEDING)) {
574 dist *= 2;
575 }
576 if (use_fast_fed) {
577 dist += fast_table.table.size() * 2;
578 }
579
580 /* get sure we don't use insane value */
581 if (dist < feedl) {
582 feedl -= dist;
583 } else {
584 feedl = 0;
585 }
586
587 reg->set24(REG_FEEDL, feedl);
588
589 /* doesn't seem to matter that much */
590 sanei_genesys_calculate_zmod(use_fast_fed,
591 scan_exposure_time,
592 scan_table.table,
593 scan_table.table.size(),
594 feedl,
595 scan_table.table.size(),
596 &z1,
597 &z2);
598
599 reg->set24(REG_Z1MOD, z1);
600 reg->set24(REG_Z2MOD, z2);
601
602 /* LINESEL */
603 reg->set8_mask(REG_0x1D, linesel, REG_0x1D_LINESEL);
604 reg->set8(REG_0xA0, (static_cast<unsigned>(motor_profile.step_type) << REG_0xA0S_STEPSEL) |
605 (static_cast<unsigned>(motor_profile.step_type) << REG_0xA0S_FSTPSEL));
606
607 reg->set16(REG_FMOVDEC, fast_table.table.size());
608 }
609
gl124_init_optical_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,unsigned int exposure_time,const ScanSession & session)610 static void gl124_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
611 Genesys_Register_Set* reg, unsigned int exposure_time,
612 const ScanSession& session)
613 {
614 DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time);
615 uint32_t expmax;
616
617 scanner_setup_sensor(*dev, sensor, *reg);
618
619 dev->cmd_set->set_fe(dev, sensor, AFE_SET);
620
621 /* enable shading */
622 regs_set_optical_off(dev->model->asic_type, *reg);
623 if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
624 has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION))
625 {
626 reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
627 } else {
628 reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
629 }
630
631 if ((dev->model->sensor_id != SensorId::CIS_CANON_LIDE_120) && (session.params.xres>=600)) {
632 reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
633 } else {
634 // BUG: the following is likely incorrect
635 reg->find_reg(REG_0x03).value |= ~REG_0x03_AVEENB;
636 }
637
638 sanei_genesys_set_lamp_power(dev, sensor, *reg,
639 !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
640
641 // BW threshold
642 dev->interface->write_register(REG_0x114, 0x7f);
643 dev->interface->write_register(REG_0x115, 0x7f);
644
645 /* monochrome / color scan */
646 switch (session.params.depth) {
647 case 8:
648 reg->find_reg(REG_0x04).value &= ~(REG_0x04_LINEART | REG_0x04_BITSET);
649 break;
650 case 16:
651 reg->find_reg(REG_0x04).value &= ~REG_0x04_LINEART;
652 reg->find_reg(REG_0x04).value |= REG_0x04_BITSET;
653 break;
654 }
655
656 reg->find_reg(REG_0x04).value &= ~REG_0x04_FILTER;
657 if (session.params.channels == 1)
658 {
659 switch (session.params.color_filter)
660 {
661 case ColorFilter::RED:
662 reg->find_reg(REG_0x04).value |= 0x10;
663 break;
664 case ColorFilter::BLUE:
665 reg->find_reg(REG_0x04).value |= 0x30;
666 break;
667 case ColorFilter::GREEN:
668 reg->find_reg(REG_0x04).value |= 0x20;
669 break;
670 default:
671 break; // should not happen
672 }
673 }
674
675 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution,
676 session.params.channels,
677 session.params.scan_method);
678 sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw);
679
680 if (should_enable_gamma(session, sensor)) {
681 reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB;
682 } else {
683 reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
684 }
685
686 reg->set16(REG_DPISET, sensor.register_dpiset);
687
688 reg->find_reg(REG_0x06).value |= REG_0x06_GAIN4;
689
690 /* CIS scanners can do true gray by setting LEDADD */
691 /* we set up LEDADD only when asked */
692 if (dev->model->is_cis) {
693 reg->find_reg(REG_0x60).value &= ~REG_0x60_LEDADD;
694 if (session.enable_ledadd) {
695 reg->find_reg(REG_0x60).value |= REG_0x60_LEDADD;
696 expmax = reg->get24(REG_EXPR);
697 expmax = std::max(expmax, reg->get24(REG_EXPG));
698 expmax = std::max(expmax, reg->get24(REG_EXPB));
699
700 dev->reg.set24(REG_EXPR, expmax);
701 dev->reg.set24(REG_EXPG, expmax);
702 dev->reg.set24(REG_EXPB, expmax);
703 }
704 /* RGB weighting, REG_TRUER,G and B are to be set */
705 reg->find_reg(0x01).value &= ~REG_0x01_TRUEGRAY;
706 if (session.enable_ledadd) {
707 reg->find_reg(0x01).value |= REG_0x01_TRUEGRAY;
708 dev->interface->write_register(REG_TRUER, 0x80);
709 dev->interface->write_register(REG_TRUEG, 0x80);
710 dev->interface->write_register(REG_TRUEB, 0x80);
711 }
712 }
713
714 std::uint32_t pixel_endx = session.pixel_endx;
715 if (pixel_endx == reg->get24(REG_SEGCNT)) {
716 pixel_endx = 0;
717 }
718 reg->set24(REG_STRPIXEL, session.pixel_startx);
719 reg->set24(REG_ENDPIXEL, pixel_endx);
720
721 dev->line_count = 0;
722
723 setup_image_pipeline(*dev, session);
724
725 // MAXWD is expressed in 2 words unit
726
727 // BUG: we shouldn't multiply by channels here
728 reg->set24(REG_MAXWD, session.output_line_bytes_raw * session.params.channels *
729 session.optical_resolution / session.full_resolution);
730 reg->set24(REG_LPERIOD, exposure_time);
731 reg->set16(REG_DUMMY, sensor.dummy_pixel);
732 }
733
init_regs_for_scan_session(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,const ScanSession & session) const734 void CommandSetGl124::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
735 Genesys_Register_Set* reg,
736 const ScanSession& session) const
737 {
738 DBG_HELPER(dbg);
739 session.assert_computed();
740
741 int exposure_time;
742
743 int dummy = 0;
744 int slope_dpi = 0;
745
746 /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */
747 if (dev->model->is_cis) {
748 slope_dpi = session.params.yres * session.params.channels;
749 } else {
750 slope_dpi = session.params.yres;
751 }
752
753 if (has_flag(session.params.flags, ScanFlag::FEEDING)) {
754 exposure_time = 2304;
755 } else {
756 exposure_time = sensor.exposure_lperiod;
757 }
758 const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
759
760 DBG(DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time);
761 DBG(DBG_info, "%s : scan_step_type=%d\n", __func__, static_cast<unsigned>(motor_profile.step_type));
762
763 /* we enable true gray for cis scanners only, and just when doing
764 * scan since color calibration is OK for this mode
765 */
766
767 // now _LOGICAL_ optical values used are known, setup registers
768 gl124_init_optical_regs_scan(dev, sensor, reg, exposure_time, session);
769
770 gl124_init_motor_regs_scan(dev, sensor, reg, motor_profile, exposure_time, slope_dpi,
771 session.optical_line_count,
772 dummy, session.params.starty, session.params.scan_mode,
773 session.params.flags);
774
775 /*** prepares data reordering ***/
776
777 dev->read_active = true;
778
779 dev->session = session;
780
781 dev->total_bytes_read = 0;
782 dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines;
783
784 DBG(DBG_info, "%s: total bytes to send to frontend = %zu\n", __func__,
785 dev->total_bytes_to_read);
786 }
787
calculate_scan_session(const Genesys_Device * dev,const Genesys_Sensor & sensor,const Genesys_Settings & settings) const788 ScanSession CommandSetGl124::calculate_scan_session(const Genesys_Device* dev,
789 const Genesys_Sensor& sensor,
790 const Genesys_Settings& settings) const
791 {
792 DBG(DBG_info, "%s ", __func__);
793 debug_dump(DBG_info, settings);
794
795 unsigned move_dpi = dev->motor.base_ydpi / 4;
796 float move = dev->model->y_offset;
797 move += dev->settings.tl_y;
798 move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
799
800 float start = dev->model->x_offset;
801 start += settings.tl_x;
802 start /= sensor.full_resolution / sensor.get_optical_resolution();
803 start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
804
805 ScanSession session;
806 session.params.xres = settings.xres;
807 session.params.yres = settings.yres;
808 session.params.startx = static_cast<unsigned>(start);
809 session.params.starty = static_cast<unsigned>(move);
810 session.params.pixels = settings.pixels;
811 session.params.requested_pixels = settings.requested_pixels;
812 session.params.lines = settings.lines;
813 session.params.depth = settings.depth;
814 session.params.channels = settings.get_channels();
815 session.params.scan_method = settings.scan_method;
816 session.params.scan_mode = settings.scan_mode;
817 session.params.color_filter = settings.color_filter;
818 session.params.flags = ScanFlag::NONE;
819
820 compute_session(dev, session, sensor);
821
822 return session;
823 }
824
825 /**
826 * for fast power saving methods only, like disabling certain amplifiers
827 * @param dev device to use
828 * @param enable true to set inot powersaving
829 * */
save_power(Genesys_Device * dev,bool enable) const830 void CommandSetGl124::save_power(Genesys_Device* dev, bool enable) const
831 {
832 (void) dev;
833 DBG_HELPER_ARGS(dbg, "enable = %d", enable);
834 }
835
set_powersaving(Genesys_Device * dev,int delay) const836 void CommandSetGl124::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const
837 {
838 DBG_HELPER_ARGS(dbg, "delay = %d", delay);
839
840 dev->reg.find_reg(REG_0x03).value &= ~0xf0;
841 if(delay<15)
842 {
843 dev->reg.find_reg(REG_0x03).value |= delay;
844 }
845 else
846 {
847 dev->reg.find_reg(REG_0x03).value |= 0x0f;
848 }
849 }
850
851 /** @brief setup GPIOs for scan
852 * Setup GPIO values to drive motor (or light) needed for the
853 * target resolution
854 * @param *dev device to set up
855 * @param resolution dpi of the target scan
856 */
gl124_setup_scan_gpio(Genesys_Device * dev,int resolution)857 void gl124_setup_scan_gpio(Genesys_Device* dev, int resolution)
858 {
859 DBG_HELPER(dbg);
860
861 uint8_t val = dev->interface->read_register(REG_0x32);
862
863 /* LiDE 110, 210 and 220 cases */
864 if(dev->model->gpio_id != GpioId::CANON_LIDE_120) {
865 if(resolution>=dev->motor.base_ydpi/2)
866 {
867 val &= 0xf7;
868 }
869 else if(resolution>=dev->motor.base_ydpi/4)
870 {
871 val &= 0xef;
872 }
873 else
874 {
875 val |= 0x10;
876 }
877 }
878 /* 120 : <=300 => 0x53 */
879 else
880 { /* base_ydpi is 4800 */
881 if(resolution<=300)
882 {
883 val &= 0xf7;
884 }
885 else if(resolution<=600)
886 {
887 val |= 0x08;
888 }
889 else if(resolution<=1200)
890 {
891 val &= 0xef;
892 val |= 0x08;
893 }
894 else
895 {
896 val &= 0xf7;
897 }
898 }
899 val |= 0x02;
900 dev->interface->write_register(REG_0x32, val);
901 }
902
903 // Send the low-level scan command
904 // todo: is this that useful ?
begin_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,bool start_motor) const905 void CommandSetGl124::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
906 Genesys_Register_Set* reg, bool start_motor) const
907 {
908 DBG_HELPER(dbg);
909 (void) sensor;
910 (void) reg;
911
912 // set up GPIO for scan
913 gl124_setup_scan_gpio(dev,dev->settings.yres);
914
915 scanner_clear_scan_and_feed_counts(*dev);
916
917 // enable scan and motor
918 uint8_t val = dev->interface->read_register(REG_0x01);
919 val |= REG_0x01_SCAN;
920 dev->interface->write_register(REG_0x01, val);
921
922 scanner_start_action(*dev, start_motor);
923
924 dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
925 }
926
927
928 // Send the stop scan command
end_scan(Genesys_Device * dev,Genesys_Register_Set * reg,bool check_stop) const929 void CommandSetGl124::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
930 bool check_stop) const
931 {
932 (void) reg;
933 DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
934
935 if (!dev->model->is_sheetfed) {
936 scanner_stop_action(*dev);
937 }
938 }
939
940
941 /** Park head
942 * Moves the slider to the home (top) position slowly
943 * @param dev device to park
944 * @param wait_until_home true to make the function waiting for head
945 * to be home before returning, if fals returne immediately
946 */
move_back_home(Genesys_Device * dev,bool wait_until_home) const947 void CommandSetGl124::move_back_home(Genesys_Device* dev, bool wait_until_home) const
948 {
949 scanner_move_back_home(*dev, wait_until_home);
950 }
951
952 // 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) const953 void CommandSetGl124::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
954 Genesys_Register_Set& regs) const
955 {
956 DBG_HELPER(dbg);
957
958 unsigned channels = 3;
959 unsigned resolution = sensor.shading_resolution;
960
961 unsigned calib_lines =
962 static_cast<unsigned>(dev->model->y_size_calib_mm * resolution / MM_PER_INCH);
963
964 const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
965 dev->settings.scan_method);
966
967 /* distance to move to reach white target at high resolution */
968 unsigned move=0;
969 if (dev->settings.yres >= 1200) {
970 move = static_cast<int>(dev->model->y_offset_calib_white);
971 move = static_cast<int>((move * (dev->motor.base_ydpi/4)) / MM_PER_INCH);
972 }
973
974 ScanSession session;
975 session.params.xres = resolution;
976 session.params.yres = resolution;
977 session.params.startx = 0;
978 session.params.starty = move;
979 session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
980 session.params.lines = calib_lines;
981 session.params.depth = 16;
982 session.params.channels = channels;
983 session.params.scan_method = dev->settings.scan_method;
984 session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
985 session.params.color_filter = ColorFilter::RED;
986 session.params.flags = ScanFlag::DISABLE_SHADING |
987 ScanFlag::DISABLE_GAMMA |
988 ScanFlag::DISABLE_BUFFER_FULL_MOVE;
989 compute_session(dev, session, calib_sensor);
990
991 try {
992 init_regs_for_scan_session(dev, calib_sensor, ®s, session);
993 } catch (...) {
994 catch_all_exceptions(__func__, [&](){ sanei_genesys_set_motor_power(regs, false); });
995 throw;
996 }
997 sanei_genesys_set_motor_power(regs, false);
998
999 dev->calib_session = session;
1000 }
1001
wait_for_motor_stop(Genesys_Device * dev) const1002 void CommandSetGl124::wait_for_motor_stop(Genesys_Device* dev) const
1003 {
1004 DBG_HELPER(dbg);
1005
1006 auto status = scanner_read_status(*dev);
1007 uint8_t val40 = dev->interface->read_register(REG_0x100);
1008
1009 if (!status.is_motor_enabled && (val40 & REG_0x100_MOTMFLG) == 0) {
1010 return;
1011 }
1012
1013 do {
1014 dev->interface->sleep_ms(10);
1015 status = scanner_read_status(*dev);
1016 val40 = dev->interface->read_register(REG_0x100);
1017 } while (status.is_motor_enabled ||(val40 & REG_0x100_MOTMFLG));
1018 dev->interface->sleep_ms(50);
1019 }
1020
1021 /**
1022 * Send shading calibration data. The buffer is considered to always hold values
1023 * for all the channels.
1024 */
send_shading_data(Genesys_Device * dev,const Genesys_Sensor & sensor,std::uint8_t * data,int size) const1025 void CommandSetGl124::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
1026 std::uint8_t* data, int size) const
1027 {
1028 DBG_HELPER_ARGS(dbg, "writing %d bytes of shading data", size);
1029 std::uint32_t addr, length, segcnt, pixels, i;
1030 uint8_t *ptr, *src;
1031
1032 /* logical size of a color as seen by generic code of the frontend */
1033 length = size / 3;
1034 std::uint32_t strpixel = dev->session.pixel_startx;
1035 std::uint32_t endpixel = dev->session.pixel_endx;
1036 segcnt = dev->reg.get24(REG_SEGCNT);
1037
1038 /* turn pixel value into bytes 2x16 bits words */
1039 strpixel*=2*2; /* 2 words of 2 bytes */
1040 endpixel*=2*2;
1041 segcnt*=2*2;
1042 pixels=endpixel-strpixel;
1043
1044 dev->interface->record_key_value("shading_start_pixel", std::to_string(strpixel));
1045 dev->interface->record_key_value("shading_pixels", std::to_string(pixels));
1046 dev->interface->record_key_value("shading_length", std::to_string(length));
1047 dev->interface->record_key_value("shading_factor", std::to_string(sensor.shading_factor));
1048 dev->interface->record_key_value("shading_segcnt", std::to_string(segcnt));
1049 dev->interface->record_key_value("shading_segment_count",
1050 std::to_string(dev->session.segment_count));
1051
1052 DBG( DBG_io2, "%s: using chunks of %d bytes (%d shading data pixels)\n",__func__,length, length/4);
1053 std::vector<uint8_t> buffer(pixels * dev->session.segment_count, 0);
1054
1055 /* write actual red data */
1056 for(i=0;i<3;i++)
1057 {
1058 /* copy data to work buffer and process it */
1059 /* coefficient destination */
1060 ptr = buffer.data();
1061
1062 /* iterate on both sensor segment */
1063 for (unsigned x = 0; x < pixels; x += 4 * sensor.shading_factor) {
1064 /* coefficient source */
1065 src=data+x+strpixel+i*length;
1066
1067 /* iterate over all the segments */
1068 for (unsigned s = 0; s < dev->session.segment_count; s++)
1069 {
1070 unsigned segnum = dev->session.segment_count > 1 ? sensor.segment_order[s] : 0;
1071 ptr[0+pixels*s]=src[0+segcnt*segnum];
1072 ptr[1+pixels*s]=src[1+segcnt*segnum];
1073 ptr[2+pixels*s]=src[2+segcnt*segnum];
1074 ptr[3+pixels*s]=src[3+segcnt*segnum];
1075 }
1076
1077 /* next shading coefficient */
1078 ptr+=4;
1079 }
1080 uint8_t val = dev->interface->read_register(0xd0+i);
1081 addr = val * 8192 + 0x10000000;
1082 dev->interface->write_ahb(addr, pixels * dev->session.segment_count, buffer.data());
1083 }
1084 }
1085
1086
1087 /** @brief move to calibration area
1088 * This functions moves scanning head to calibration area
1089 * by doing a 600 dpi scan
1090 * @param dev scanner device
1091 */
move_to_calibration_area(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs)1092 void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& sensor,
1093 Genesys_Register_Set& regs)
1094 {
1095 (void) sensor;
1096
1097 DBG_HELPER(dbg);
1098
1099 unsigned resolution = 600;
1100 unsigned channels = 3;
1101 const auto& move_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
1102 dev->settings.scan_method);
1103
1104 /* initial calibration reg values */
1105 regs = dev->reg;
1106
1107 ScanSession session;
1108 session.params.xres = resolution;
1109 session.params.yres = resolution;
1110 session.params.startx = 0;
1111 session.params.starty = 0;
1112 session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
1113 session.params.lines = 1;
1114 session.params.depth = 8;
1115 session.params.channels = channels;
1116 session.params.scan_method = dev->settings.scan_method;
1117 session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
1118 session.params.color_filter = dev->settings.color_filter;
1119 session.params.flags = ScanFlag::DISABLE_SHADING |
1120 ScanFlag::DISABLE_GAMMA |
1121 ScanFlag::SINGLE_LINE |
1122 ScanFlag::IGNORE_STAGGER_OFFSET |
1123 ScanFlag::IGNORE_COLOR_OFFSET;
1124 compute_session(dev, session, move_sensor);
1125
1126 dev->cmd_set->init_regs_for_scan_session(dev, move_sensor, ®s, session);
1127
1128 // write registers and scan data
1129 dev->interface->write_registers(regs);
1130
1131 DBG (DBG_info, "%s: starting line reading\n", __func__);
1132 dev->cmd_set->begin_scan(dev, move_sensor, ®s, true);
1133
1134 if (is_testing_mode()) {
1135 dev->interface->test_checkpoint("move_to_calibration_area");
1136 scanner_stop_action(*dev);
1137 return;
1138 }
1139
1140 auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
1141
1142 // stop scanning
1143 scanner_stop_action(*dev);
1144
1145 if (dbg_log_image_data()) {
1146 write_tiff_file("gl124_movetocalarea.tiff", image);
1147 }
1148 }
1149
1150 /* this function does the led calibration by scanning one line of the calibration
1151 area below scanner's top on white strip.
1152
1153 -needs working coarse/gain
1154 */
led_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1155 SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1156 Genesys_Register_Set& regs) const
1157 {
1158 return scanner_led_calibration(*dev, sensor, regs);
1159 }
1160
offset_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1161 void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1162 Genesys_Register_Set& regs) const
1163 {
1164 scanner_offset_calibration(*dev, sensor, regs);
1165 }
1166
coarse_gain_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs,int dpi) const1167 void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1168 Genesys_Register_Set& regs, int dpi) const
1169 {
1170 scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
1171 }
1172
1173 // wait for lamp warmup by scanning the same line until difference
1174 // between 2 scans is below a threshold
init_regs_for_warmup(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg) const1175 void CommandSetGl124::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
1176 Genesys_Register_Set* reg) const
1177 {
1178 DBG_HELPER(dbg);
1179
1180 *reg = dev->reg;
1181
1182 auto flags = ScanFlag::DISABLE_SHADING |
1183 ScanFlag::DISABLE_GAMMA |
1184 ScanFlag::SINGLE_LINE |
1185 ScanFlag::IGNORE_STAGGER_OFFSET |
1186 ScanFlag::IGNORE_COLOR_OFFSET;
1187 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
1188 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1189 {
1190 flags |= ScanFlag::USE_XPA;
1191 }
1192
1193 ScanSession session;
1194 session.params.xres = sensor.full_resolution;
1195 session.params.yres = dev->motor.base_ydpi;
1196 session.params.startx = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH / 4;
1197 session.params.starty = 0;
1198 session.params.pixels = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH / 2;
1199 session.params.lines = 1;
1200 session.params.depth = dev->model->bpp_color_values.front();
1201 session.params.channels = 3;
1202 session.params.scan_method = dev->settings.scan_method;
1203 session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
1204 session.params.color_filter = dev->settings.color_filter;
1205 session.params.flags = flags;
1206
1207 compute_session(dev, session, sensor);
1208
1209 init_regs_for_scan_session(dev, sensor, reg, session);
1210
1211 sanei_genesys_set_motor_power(*reg, false);
1212 }
1213
1214 /** @brief default GPIO values
1215 * set up GPIO/GPOE for idle state
1216 * @param dev device to set up
1217 */
gl124_init_gpio(Genesys_Device * dev)1218 static void gl124_init_gpio(Genesys_Device* dev)
1219 {
1220 DBG_HELPER(dbg);
1221 int idx;
1222
1223 /* per model GPIO layout */
1224 if (dev->model->model_id == ModelId::CANON_LIDE_110) {
1225 idx = 0;
1226 } else if (dev->model->model_id == ModelId::CANON_LIDE_120) {
1227 idx = 2;
1228 }
1229 else
1230 { /* canon LiDE 210 and 220 case */
1231 idx = 1;
1232 }
1233
1234 dev->interface->write_register(REG_0x31, gpios[idx].r31);
1235 dev->interface->write_register(REG_0x32, gpios[idx].r32);
1236 dev->interface->write_register(REG_0x33, gpios[idx].r33);
1237 dev->interface->write_register(REG_0x34, gpios[idx].r34);
1238 dev->interface->write_register(REG_0x35, gpios[idx].r35);
1239 dev->interface->write_register(REG_0x36, gpios[idx].r36);
1240 dev->interface->write_register(REG_0x38, gpios[idx].r38);
1241 }
1242
1243 /**
1244 * set memory layout by filling values in dedicated registers
1245 */
gl124_init_memory_layout(Genesys_Device * dev)1246 static void gl124_init_memory_layout(Genesys_Device* dev)
1247 {
1248 DBG_HELPER(dbg);
1249
1250 apply_reg_settings_to_device_write_only(*dev, dev->memory_layout.regs);
1251 }
1252
1253 /**
1254 * initialize backend and ASIC : registers, motor tables, and gamma tables
1255 * then ensure scanner's head is at home
1256 */
init(Genesys_Device * dev) const1257 void CommandSetGl124::init(Genesys_Device* dev) const
1258 {
1259 DBG_INIT ();
1260 DBG_HELPER(dbg);
1261
1262 sanei_genesys_asic_init(dev);
1263 }
1264
1265
1266 /* *
1267 * initialize ASIC from power on condition
1268 */
asic_boot(Genesys_Device * dev,bool cold) const1269 void CommandSetGl124::asic_boot(Genesys_Device* dev, bool cold) const
1270 {
1271 DBG_HELPER(dbg);
1272
1273 // reset ASIC in case of cold boot
1274 if (cold) {
1275 dev->interface->write_register(0x0e, 0x01);
1276 dev->interface->write_register(0x0e, 0x00);
1277 }
1278
1279 // enable GPOE 17
1280 dev->interface->write_register(0x36, 0x01);
1281
1282 // set GPIO 17
1283 uint8_t val = dev->interface->read_register(0x33);
1284 val |= 0x01;
1285 dev->interface->write_register(0x33, val);
1286
1287 // test CHKVER
1288 val = dev->interface->read_register(REG_0x100);
1289 if (val & REG_0x100_CHKVER) {
1290 val = dev->interface->read_register(0x00);
1291 DBG(DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val);
1292 }
1293
1294 /* Set default values for registers */
1295 gl124_init_registers (dev);
1296
1297 // Write initial registers
1298 dev->interface->write_registers(dev->reg);
1299
1300 // tune reg 0B
1301 dev->interface->write_register(REG_0x0B, REG_0x0B_30MHZ | REG_0x0B_ENBDRAM | REG_0x0B_64M);
1302 dev->reg.remove_reg(0x0b);
1303
1304 //set up end access
1305 dev->interface->write_0x8c(0x10, 0x0b);
1306 dev->interface->write_0x8c(0x13, 0x0e);
1307
1308 /* CIS_LINE */
1309 dev->reg.init_reg(0x08, REG_0x08_CIS_LINE);
1310 dev->interface->write_register(0x08, dev->reg.find_reg(0x08).value);
1311
1312 // setup gpio
1313 gl124_init_gpio(dev);
1314
1315 // setup internal memory layout
1316 gl124_init_memory_layout(dev);
1317 }
1318
1319
update_hardware_sensors(Genesys_Scanner * s) const1320 void CommandSetGl124::update_hardware_sensors(Genesys_Scanner* s) const
1321 {
1322 /* do what is needed to get a new set of events, but try to not loose
1323 any of them.
1324 */
1325 DBG_HELPER(dbg);
1326 uint8_t val = s->dev->interface->read_register(REG_0x31);
1327
1328 /* TODO : for the next scanner special case,
1329 * add another per scanner button profile struct to avoid growing
1330 * hard-coded button mapping here.
1331 */
1332 if ((s->dev->model->gpio_id == GpioId::CANON_LIDE_110) ||
1333 (s->dev->model->gpio_id == GpioId::CANON_LIDE_120))
1334 {
1335 s->buttons[BUTTON_SCAN_SW].write((val & 0x01) == 0);
1336 s->buttons[BUTTON_FILE_SW].write((val & 0x08) == 0);
1337 s->buttons[BUTTON_EMAIL_SW].write((val & 0x04) == 0);
1338 s->buttons[BUTTON_COPY_SW].write((val & 0x02) == 0);
1339 }
1340 else
1341 { /* LiDE 210 case */
1342 s->buttons[BUTTON_EXTRA_SW].write((val & 0x01) == 0);
1343 s->buttons[BUTTON_SCAN_SW].write((val & 0x02) == 0);
1344 s->buttons[BUTTON_COPY_SW].write((val & 0x04) == 0);
1345 s->buttons[BUTTON_EMAIL_SW].write((val & 0x08) == 0);
1346 s->buttons[BUTTON_FILE_SW].write((val & 0x10) == 0);
1347 }
1348 }
1349
update_home_sensor_gpio(Genesys_Device & dev) const1350 void CommandSetGl124::update_home_sensor_gpio(Genesys_Device& dev) const
1351 {
1352 DBG_HELPER(dbg);
1353
1354 std::uint8_t val = dev.interface->read_register(REG_0x32);
1355 val &= ~REG_0x32_GPIO10;
1356 dev.interface->write_register(REG_0x32, val);
1357 }
1358
needs_home_before_init_regs_for_scan(Genesys_Device * dev) const1359 bool CommandSetGl124::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
1360 {
1361 (void) dev;
1362 return true;
1363 }
1364
send_gamma_table(Genesys_Device * dev,const Genesys_Sensor & sensor) const1365 void CommandSetGl124::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
1366 {
1367 sanei_genesys_send_gamma_table(dev, sensor);
1368 }
1369
load_document(Genesys_Device * dev) const1370 void CommandSetGl124::load_document(Genesys_Device* dev) const
1371 {
1372 (void) dev;
1373 throw SaneException("not implemented");
1374 }
1375
detect_document_end(Genesys_Device * dev) const1376 void CommandSetGl124::detect_document_end(Genesys_Device* dev) const
1377 {
1378 (void) dev;
1379 throw SaneException("not implemented");
1380 }
1381
eject_document(Genesys_Device * dev) const1382 void CommandSetGl124::eject_document(Genesys_Device* dev) const
1383 {
1384 (void) dev;
1385 throw SaneException("not implemented");
1386 }
1387
1388 } // namespace gl124
1389 } // namespace genesys
1390