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 "gl847.h"
25 #include "gl847_registers.h"
26 #include "test_settings.h"
27
28 #include <vector>
29
30 namespace genesys {
31 namespace gl847 {
32
33 /**
34 * compute the step multiplier used
35 */
gl847_get_step_multiplier(Genesys_Register_Set * regs)36 static unsigned gl847_get_step_multiplier (Genesys_Register_Set * regs)
37 {
38 unsigned value = (regs->get8(0x9d) & 0x0f) >> 1;
39 return 1 << value;
40 }
41
42 /** @brief set all registers to default values .
43 * This function is called only once at the beginning and
44 * fills register startup values for registers reused across scans.
45 * Those that are rarely modified or not modified are written
46 * individually.
47 * @param dev device structure holding register set to initialize
48 */
49 static void
gl847_init_registers(Genesys_Device * dev)50 gl847_init_registers (Genesys_Device * dev)
51 {
52 DBG_HELPER(dbg);
53 int lide700=0;
54 std::uint8_t val;
55
56 /* 700F class needs some different initial settings */
57 if (dev->model->model_id == ModelId::CANON_LIDE_700F) {
58 lide700 = 1;
59 }
60
61 dev->reg.clear();
62
63 dev->reg.init_reg(0x01, 0x82);
64 if (dev->model->model_id == ModelId::CANON_5600F) {
65 dev->reg.init_reg(0x01, 0x40);
66 }
67 dev->reg.init_reg(0x02, 0x18);
68 dev->reg.init_reg(0x03, 0x50);
69 dev->reg.init_reg(0x04, 0x12);
70 if (dev->model->model_id == ModelId::CANON_5600F) {
71 dev->reg.init_reg(0x04, 0x20);
72 }
73 dev->reg.init_reg(0x05, 0x80);
74 dev->reg.init_reg(0x06, 0x50); // FASTMODE + POWERBIT
75 if (dev->model->model_id == ModelId::CANON_5600F) {
76 dev->reg.init_reg(0x06, 0xf8);
77 }
78 dev->reg.init_reg(0x08, 0x10);
79 if (dev->model->model_id == ModelId::CANON_5600F) {
80 dev->reg.init_reg(0x08, 0x20);
81 }
82 dev->reg.init_reg(0x09, 0x01);
83 if (dev->model->model_id == ModelId::CANON_5600F) {
84 dev->reg.init_reg(0x09, 0x00);
85 }
86 dev->reg.init_reg(0x0a, 0x00);
87 dev->reg.init_reg(0x0b, 0x01);
88 if (dev->model->model_id == ModelId::CANON_5600F) {
89 dev->reg.init_reg(0x0b, 0x6b);
90 }
91 dev->reg.init_reg(0x0c, 0x02);
92 if (dev->model->model_id == ModelId::CANON_5600F) {
93 dev->reg.init_reg(0x0c, 0x00);
94 }
95
96 // LED exposures
97 dev->reg.init_reg(0x10, 0x00); // exposure, overwritten in scanner_setup_sensor() below
98 dev->reg.init_reg(0x11, 0x00); // exposure, overwritten in scanner_setup_sensor() below
99 dev->reg.init_reg(0x12, 0x00); // exposure, overwritten in scanner_setup_sensor() below
100 dev->reg.init_reg(0x13, 0x00); // exposure, overwritten in scanner_setup_sensor() below
101 dev->reg.init_reg(0x14, 0x00); // exposure, overwritten in scanner_setup_sensor() below
102 dev->reg.init_reg(0x15, 0x00); // exposure, overwritten in scanner_setup_sensor() below
103
104 dev->reg.init_reg(0x16, 0x10); // SENSOR_DEF
105 dev->reg.init_reg(0x17, 0x08); // SENSOR_DEF
106 dev->reg.init_reg(0x18, 0x00); // SENSOR_DEF
107 dev->reg.init_reg(0x19, 0x50); // SENSOR_DEF
108
109 dev->reg.init_reg(0x1a, 0x34); // SENSOR_DEF
110 dev->reg.init_reg(0x1b, 0x00); // SENSOR_DEF
111 dev->reg.init_reg(0x1c, 0x02); // SENSOR_DEF
112 dev->reg.init_reg(0x1d, 0x04); // SENSOR_DEF
113 dev->reg.init_reg(0x1e, 0x10);
114 if (dev->model->model_id == ModelId::CANON_5600F) {
115 dev->reg.init_reg(0x1e, 0xf0);
116 }
117 dev->reg.init_reg(0x1f, 0x04);
118 dev->reg.init_reg(0x20, 0x02); // BUFSEL: buffer full condition
119 dev->reg.init_reg(0x21, 0x10); // STEPNO: set during motor setup
120 dev->reg.init_reg(0x22, 0x7f); // FWDSTEP: set during motor setup
121 dev->reg.init_reg(0x23, 0x7f); // BWDSTEP: set during motor setup
122 dev->reg.init_reg(0x24, 0x10); // FASTNO: set during motor setup
123 dev->reg.init_reg(0x25, 0x00); // LINCNT: set during motor setup
124 dev->reg.init_reg(0x26, 0x00); // LINCNT: set during motor setup
125 dev->reg.init_reg(0x27, 0x00); // LINCNT: set during motor setup
126
127 dev->reg.init_reg(0x2c, 0x09); // DPISET: set during sensor setup
128 dev->reg.init_reg(0x2d, 0x60); // DPISET: set during sensor setup
129
130 dev->reg.init_reg(0x2e, 0x80); // BWHI: black/white low threshdold
131 dev->reg.init_reg(0x2f, 0x80); // BWLOW: black/white low threshold
132
133 dev->reg.init_reg(0x30, 0x00); // STRPIXEL: set during sensor setup
134 dev->reg.init_reg(0x31, 0x10); // STRPIXEL: set during sensor setup
135 dev->reg.init_reg(0x32, 0x15); // ENDPIXEL: set during sensor setup
136 dev->reg.init_reg(0x33, 0x0e); // ENDPIXEL: set during sensor setup
137
138 dev->reg.init_reg(0x34, 0x40); // DUMMY: SENSOR_DEF
139 dev->reg.init_reg(0x35, 0x00); // MAXWD: set during scan setup
140 dev->reg.init_reg(0x36, 0x2a); // MAXWD: set during scan setup
141 dev->reg.init_reg(0x37, 0x30); // MAXWD: set during scan setup
142 dev->reg.init_reg(0x38, 0x2a); // LPERIOD: SENSOR_DEF
143 dev->reg.init_reg(0x39, 0xf8); // LPERIOD: SENSOR_DEF
144 dev->reg.init_reg(0x3d, 0x00); // FEEDL: set during motor setup
145 dev->reg.init_reg(0x3e, 0x00); // FEEDL: set during motor setup
146 dev->reg.init_reg(0x3f, 0x00); // FEEDL: set during motor setup
147
148 dev->reg.init_reg(0x52, 0x03); // SENSOR_DEF
149 dev->reg.init_reg(0x53, 0x07); // SENSOR_DEF
150 dev->reg.init_reg(0x54, 0x00); // SENSOR_DEF
151 dev->reg.init_reg(0x55, 0x00); // SENSOR_DEF
152 dev->reg.init_reg(0x56, 0x00); // SENSOR_DEF
153 dev->reg.init_reg(0x57, 0x00); // SENSOR_DEF
154 dev->reg.init_reg(0x58, 0x2a); // SENSOR_DEF
155 dev->reg.init_reg(0x59, 0xe1); // SENSOR_DEF
156 dev->reg.init_reg(0x5a, 0x55); // SENSOR_DEF
157
158 dev->reg.init_reg(0x5e, 0x41); // DECSEL, STOPTIM
159 dev->reg.init_reg(0x5f, 0x40); // FMOVDEC: set during motor setup
160
161 dev->reg.init_reg(0x60, 0x00); // Z1MOD: overwritten during motor setup
162 dev->reg.init_reg(0x61, 0x21); // Z1MOD: overwritten during motor setup
163 dev->reg.init_reg(0x62, 0x40); // Z1MOD: overwritten during motor setup
164 dev->reg.init_reg(0x63, 0x00); // Z2MOD: overwritten during motor setup
165 dev->reg.init_reg(0x64, 0x21); // Z2MOD: overwritten during motor setup
166 dev->reg.init_reg(0x65, 0x40); // Z2MOD: overwritten during motor setup
167 dev->reg.init_reg(0x67, 0x80); // STEPSEL, MTRPWM: overwritten during motor setup
168 dev->reg.init_reg(0x68, 0x80); // FSTPSEL, FASTPWM: overwritten during motor setup
169 dev->reg.init_reg(0x69, 0x20); // FSHDEC: overwritten during motor setup
170 dev->reg.init_reg(0x6a, 0x20); // FMOVNO: overwritten during motor setup
171
172 dev->reg.init_reg(0x74, 0x00); // SENSOR_DEF
173 dev->reg.init_reg(0x75, 0x00); // SENSOR_DEF
174 dev->reg.init_reg(0x76, 0x3c); // SENSOR_DEF
175 dev->reg.init_reg(0x77, 0x00); // SENSOR_DEF
176 dev->reg.init_reg(0x78, 0x00); // SENSOR_DEF
177 dev->reg.init_reg(0x79, 0x9f); // SENSOR_DEF
178 dev->reg.init_reg(0x7a, 0x00); // SENSOR_DEF
179 dev->reg.init_reg(0x7b, 0x00); // SENSOR_DEF
180 dev->reg.init_reg(0x7c, 0x55); // SENSOR_DEF
181
182 dev->reg.init_reg(0x7d, 0x00);
183
184 // NOTE: autoconf is a non working option
185 dev->reg.init_reg(0x87, 0x02); // TODO: move to SENSOR_DEF
186 dev->reg.init_reg(0x9d, 0x06); // RAMDLY, MOTLAG, CMODE, STEPTIM, IFRS
187 dev->reg.init_reg(0xa2, 0x0f); // misc
188
189 if (dev->model->model_id == ModelId::CANON_5600F) {
190 dev->reg.init_reg(0xab, 0x31);
191 dev->reg.init_reg(0xbb, 0x00);
192 dev->reg.init_reg(0xbc, 0x0f);
193 }
194 dev->reg.init_reg(0xbd, 0x18); // misc
195 dev->reg.init_reg(0xfe, 0x08); // misc
196 if (dev->model->model_id == ModelId::CANON_5600F) {
197 dev->reg.init_reg(0x9e, 0x00); // sensor reg, but not in SENSOR_DEF
198 dev->reg.init_reg(0x9f, 0x00); // sensor reg, but not in SENSOR_DEF
199 dev->reg.init_reg(0xaa, 0x00); // custom data
200 dev->reg.init_reg(0xff, 0x00);
201 }
202
203 // gamma[0] and gamma[256] values
204 dev->reg.init_reg(0xbe, 0x00);
205 dev->reg.init_reg(0xc5, 0x00);
206 dev->reg.init_reg(0xc6, 0x00);
207 dev->reg.init_reg(0xc7, 0x00);
208 dev->reg.init_reg(0xc8, 0x00);
209 dev->reg.init_reg(0xc9, 0x00);
210 dev->reg.init_reg(0xca, 0x00);
211
212 /* LiDE 700 fixups */
213 if (lide700) {
214 dev->reg.init_reg(0x5f, 0x04);
215 dev->reg.init_reg(0x7d, 0x80);
216
217 /* we write to these registers only once */
218 val=0;
219 dev->interface->write_register(REG_0x7E, val);
220 dev->interface->write_register(REG_0x9E, val);
221 dev->interface->write_register(REG_0x9F, val);
222 dev->interface->write_register(REG_0xAB, val);
223 }
224
225 const auto& sensor = sanei_genesys_find_sensor_any(dev);
226 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution,
227 3, ScanMethod::FLATBED);
228 sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw);
229
230 if (dev->model->model_id == ModelId::CANON_5600F) {
231 scanner_setup_sensor(*dev, sensor, dev->reg);
232 }
233 }
234
235 // Set values of analog frontend
set_fe(Genesys_Device * dev,const Genesys_Sensor & sensor,std::uint8_t set) const236 void CommandSetGl847::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
237 std::uint8_t set) const
238 {
239 DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
240 set == AFE_SET ? "set" :
241 set == AFE_POWER_SAVE ? "powersave" : "huh?");
242
243 (void) sensor;
244
245 if (dev->model->model_id != ModelId::CANON_5600F) {
246 // FIXME: remove the following read
247 dev->interface->read_register(REG_0x04);
248 }
249
250 // wait for FE to be ready
251 auto status = scanner_read_status(*dev);
252 while (status.is_front_end_busy) {
253 dev->interface->sleep_ms(10);
254 status = scanner_read_status(*dev);
255 }
256
257 if (set == AFE_INIT) {
258 dev->frontend = dev->frontend_initial;
259 }
260
261 if (dev->model->model_id != ModelId::CANON_5600F) {
262 // reset DAC (BUG: this does completely different thing on Analog Devices ADCs)
263 dev->interface->write_fe_register(0x00, 0x80);
264 } else {
265 if (dev->frontend.layout.type == FrontendType::WOLFSON) {
266 // reset DAC
267 dev->interface->write_fe_register(0x04, 0xff);
268 }
269 }
270
271 for (const auto& reg : dev->frontend.regs) {
272 dev->interface->write_fe_register(reg.address, reg.value);
273 }
274 }
275
gl847_write_motor_phase_table(Genesys_Device & dev,unsigned ydpi)276 static void gl847_write_motor_phase_table(Genesys_Device& dev, unsigned ydpi)
277 {
278 (void) ydpi;
279 if (dev.model->model_id == ModelId::CANON_5600F) {
280 std::vector<std::uint8_t> phase_table = {
281 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00,
282 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00,
283 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00,
284 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
285 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00,
286 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00,
287 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00,
288 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00,
289 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
290 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
291 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00,
292 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
293 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00,
294 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00,
295 0x25, 0x00, 0x25, 0x00, 0x25, 0x00, 0x25, 0x00,
296 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00,
297 };
298 dev.interface->write_ahb(0x01000a00, phase_table.size(), phase_table.data());
299 }
300 }
301
302 // @brief set up motor related register for scan
gl847_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,ScanFlag flags)303 static void gl847_init_motor_regs_scan(Genesys_Device* dev,
304 const Genesys_Sensor& sensor,
305 Genesys_Register_Set* reg,
306 const MotorProfile& motor_profile,
307 unsigned int scan_exposure_time,
308 unsigned scan_yres,
309 unsigned int scan_lines,
310 unsigned int scan_dummy,
311 unsigned int feed_steps,
312 ScanFlag flags)
313 {
314 DBG_HELPER_ARGS(dbg, "scan_exposure_time=%d, can_yres=%d, step_type=%d, scan_lines=%d, "
315 "scan_dummy=%d, feed_steps=%d, flags=%x",
316 scan_exposure_time, scan_yres, static_cast<unsigned>(motor_profile.step_type),
317 scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
318
319 unsigned step_multiplier = gl847_get_step_multiplier (reg);
320
321 reg->set24(REG_LINCNT, scan_lines);
322
323 reg->set8(REG_0x02, 0);
324 sanei_genesys_set_motor_power(*reg, true);
325
326 std::uint8_t reg02 = reg->get8(REG_0x02);
327 reg02 &= ~REG_0x02_FASTFED;
328
329 if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
330 reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
331 }
332
333 if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) || (scan_yres >= sensor.full_resolution)) {
334 reg02 |= REG_0x02_ACDCDIS;
335 }
336 if (has_flag(flags, ScanFlag::REVERSE)) {
337 reg02 |= REG_0x02_MTRREV;
338 } else {
339 reg02 &= ~REG_0x02_MTRREV;
340 }
341 reg->set8(REG_0x02, reg02);
342
343 // scan and backtracking slope table
344 auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres,
345 scan_exposure_time, step_multiplier, motor_profile);
346 scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
347 scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
348
349 // fast table
350 unsigned fast_dpi = sanei_genesys_get_lowest_ydpi(dev);
351
352 // BUG: looks like for fast moves we use inconsistent step type
353 StepType fast_step_type = motor_profile.step_type;
354 if (static_cast<unsigned>(motor_profile.step_type) >= static_cast<unsigned>(StepType::QUARTER)) {
355 fast_step_type = StepType::QUARTER;
356 }
357
358 MotorProfile fast_motor_profile = motor_profile;
359 fast_motor_profile.step_type = fast_step_type;
360
361 auto fast_table = create_slope_table(dev->model->asic_type, dev->motor, fast_dpi,
362 scan_exposure_time, step_multiplier, fast_motor_profile);
363
364 scanner_send_slope_table(dev, sensor, STOP_TABLE, fast_table.table);
365 scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
366 scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
367
368 gl847_write_motor_phase_table(*dev, scan_yres);
369
370 // correct move distance by acceleration and deceleration amounts
371 unsigned feedl = feed_steps;
372 unsigned dist = 0;
373
374 feedl <<= static_cast<unsigned>(motor_profile.step_type);
375 dist = scan_table.table.size();
376 if (has_flag(flags, ScanFlag::FEEDING)) {
377 dist *= 2;
378 }
379
380 // check for overflow
381 if (dist < feedl) {
382 feedl -= dist;
383 } else {
384 feedl = 0;
385 }
386
387 reg->set24(REG_FEEDL, feedl);
388
389 unsigned ccdlmt = (reg->get8(REG_0x0C) & REG_0x0C_CCDLMT) + 1;
390 unsigned tgtime = 1 << (reg->get8(REG_0x1C) & REG_0x1C_TGTIME);
391
392 // hi res motor speed GPIO
393 std::uint8_t effective = dev->interface->read_register(REG_0x6C);
394
395 // if quarter step, bipolar Vref2
396
397 std::uint8_t val = effective;
398 if (motor_profile.step_type == StepType::QUARTER) {
399 val = effective & ~REG_0x6C_GPIO13;
400 } else if (static_cast<unsigned>(motor_profile.step_type) > static_cast<unsigned>(StepType::QUARTER)) {
401 val = effective | REG_0x6C_GPIO13;
402 }
403 dev->interface->write_register(REG_0x6C, val);
404
405 // effective scan
406 effective = dev->interface->read_register(REG_0x6C);
407 val = effective | REG_0x6C_GPIO10;
408 dev->interface->write_register(REG_0x6C, val);
409
410 unsigned min_restep = scan_table.table.size() / (2 * step_multiplier) - 1;
411 if (min_restep < 1) {
412 min_restep = 1;
413 }
414
415 reg->set8(REG_FWDSTEP, min_restep);
416 reg->set8(REG_BWDSTEP, min_restep);
417
418 std::uint32_t z1, z2;
419 sanei_genesys_calculate_zmod(false,
420 scan_exposure_time * ccdlmt * tgtime,
421 scan_table.table,
422 scan_table.table.size(),
423 feedl,
424 min_restep * step_multiplier,
425 &z1,
426 &z2);
427
428 reg->set24(REG_0x60, z1 | (static_cast<unsigned>(motor_profile.step_type) << (16+REG_0x60S_STEPSEL)));
429 reg->set24(REG_0x63, z2 | (static_cast<unsigned>(motor_profile.step_type) << (16+REG_0x63S_FSTPSEL)));
430
431 reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
432
433 reg->set8(REG_0x67, REG_0x67_MTRPWM);
434 reg->set8(REG_0x68, REG_0x68_FASTPWM);
435
436 reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
437 reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
438 reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
439 reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
440 reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
441 }
442
443
444 /** @brief set up registers related to sensor
445 * Set up the following registers
446 0x01
447 0x03
448 0x10-0x015 R/G/B exposures
449 0x19 EXPDMY
450 0x2e BWHI
451 0x2f BWLO
452 0x04
453 0x87
454 0x05
455 0x2c,0x2d DPISET
456 0x30,0x31 STRPIXEL
457 0x32,0x33 ENDPIXEL
458 0x35,0x36,0x37 MAXWD [25:2] (>>2)
459 0x38,0x39 LPERIOD
460 0x34 DUMMY
461 */
gl847_init_optical_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,unsigned int exposure_time,const ScanSession & session)462 static void gl847_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
463 Genesys_Register_Set* reg, unsigned int exposure_time,
464 const ScanSession& session)
465 {
466 DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time);
467
468 scanner_setup_sensor(*dev, sensor, *reg);
469
470 dev->cmd_set->set_fe(dev, sensor, AFE_SET);
471
472 /* enable shading */
473 regs_set_optical_off(dev->model->asic_type, *reg);
474 reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
475
476 if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
477 has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
478 session.use_host_side_calib)
479 {
480 reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
481 } else {
482 reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
483 }
484 reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
485
486 reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL;
487 if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
488 reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL;
489 }
490 sanei_genesys_set_lamp_power(dev, sensor, *reg,
491 !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
492 reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
493
494 if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
495 if (dev->model->model_id == ModelId::CANON_5600F) {
496 regs_set_exposure(dev->model->asic_type, *reg, sanei_genesys_fixup_exposure({0, 0, 0}));
497 }
498 }
499
500 // BW threshold
501 reg->set8(0x2e, 0x7f);
502 reg->set8(0x2f, 0x7f);
503
504 /* monochrome / color scan */
505 switch (session.params.depth) {
506 case 8:
507 reg->find_reg(REG_0x04).value &= ~(REG_0x04_LINEART | REG_0x04_BITSET);
508 break;
509 case 16:
510 reg->find_reg(REG_0x04).value &= ~REG_0x04_LINEART;
511 reg->find_reg(REG_0x04).value |= REG_0x04_BITSET;
512 break;
513 }
514
515 reg->find_reg(REG_0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
516 if (session.params.channels == 1)
517 {
518 switch (session.params.color_filter)
519 {
520
521 case ColorFilter::RED:
522 reg->find_reg(REG_0x04).value |= 0x14;
523 break;
524 case ColorFilter::BLUE:
525 reg->find_reg(REG_0x04).value |= 0x1c;
526 break;
527 case ColorFilter::GREEN:
528 reg->find_reg(REG_0x04).value |= 0x18;
529 break;
530 default:
531 break; // should not happen
532 }
533 } else {
534 if (dev->model->model_id == ModelId::CANON_5600F) {
535 reg->find_reg(REG_0x04).value |= 0x20;
536 } else {
537 reg->find_reg(REG_0x04).value |= 0x10; // mono
538 }
539 }
540
541 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution,
542 session.params.channels,
543 session.params.scan_method);
544 sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw);
545
546 if (should_enable_gamma(session, sensor)) {
547 reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB;
548 } else {
549 reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
550 }
551
552 /* CIS scanners can do true gray by setting LEDADD */
553 /* we set up LEDADD only when asked */
554 if (dev->model->is_cis) {
555 reg->find_reg(0x87).value &= ~REG_0x87_LEDADD;
556
557 if (session.enable_ledadd) {
558 reg->find_reg(0x87).value |= REG_0x87_LEDADD;
559 }
560 /* RGB weighting
561 reg->find_reg(0x01).value &= ~REG_0x01_TRUEGRAY;
562 if (session.enable_ledadd) {
563 reg->find_reg(0x01).value |= REG_0x01_TRUEGRAY;
564 }
565 */
566 }
567
568 reg->set16(REG_DPISET, sensor.register_dpiset);
569 reg->set16(REG_STRPIXEL, session.pixel_startx);
570 reg->set16(REG_ENDPIXEL, session.pixel_endx);
571
572 setup_image_pipeline(*dev, session);
573
574 /* MAXWD is expressed in 4 words unit */
575 // BUG: we shouldn't multiply by channels here
576 reg->set24(REG_MAXWD, (session.output_line_bytes_raw * session.params.channels >> 2));
577 reg->set16(REG_LPERIOD, exposure_time);
578 reg->set8(0x34, sensor.dummy_pixel);
579 }
580
init_regs_for_scan_session(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,const ScanSession & session) const581 void CommandSetGl847::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
582 Genesys_Register_Set* reg,
583 const ScanSession& session) const
584 {
585 DBG_HELPER(dbg);
586 session.assert_computed();
587
588 int exposure_time;
589
590 int slope_dpi = 0;
591 int dummy = 0;
592
593 if (dev->model->model_id == ModelId::CANON_LIDE_100 ||
594 dev->model->model_id == ModelId::CANON_LIDE_200 ||
595 dev->model->model_id == ModelId::CANON_LIDE_700F ||
596 dev->model->model_id == ModelId::HP_SCANJET_N6310)
597 {
598 dummy = 3 - session.params.channels;
599 }
600
601 /* slope_dpi */
602 /* cis color scan is effectively a gray scan with 3 gray lines per color
603 line and a FILTER of 0 */
604 if (dev->model->is_cis) {
605 slope_dpi = session.params.yres * session.params.channels;
606 } else {
607 slope_dpi = session.params.yres;
608 }
609
610 slope_dpi = slope_dpi * (1 + dummy);
611
612 exposure_time = sensor.exposure_lperiod;
613 const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
614
615 /* we enable true gray for cis scanners only, and just when doing
616 * scan since color calibration is OK for this mode
617 */
618 gl847_init_optical_regs_scan(dev, sensor, reg, exposure_time, session);
619 gl847_init_motor_regs_scan(dev, sensor, reg, motor_profile, exposure_time, slope_dpi,
620 session.optical_line_count, dummy, session.params.starty,
621 session.params.flags);
622
623 dev->read_active = true;
624
625 dev->session = session;
626
627 dev->total_bytes_read = 0;
628 dev->total_bytes_to_read = (size_t)session.output_line_bytes_requested * (size_t)session.params.lines;
629
630 DBG(DBG_info, "%s: total bytes to send = %zu\n", __func__, dev->total_bytes_to_read);
631 }
632
calculate_scan_session(const Genesys_Device * dev,const Genesys_Sensor & sensor,const Genesys_Settings & settings) const633 ScanSession CommandSetGl847::calculate_scan_session(const Genesys_Device* dev,
634 const Genesys_Sensor& sensor,
635 const Genesys_Settings& settings) const
636 {
637 DBG(DBG_info, "%s ", __func__);
638 debug_dump(DBG_info, settings);
639
640 // backtracking isn't handled well, so don't enable it
641 ScanFlag flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
642
643 /* Steps to move to reach scanning area:
644
645 - first we move to physical start of scanning either by a fixed steps amount from the
646 black strip or by a fixed amount from parking position, minus the steps done during
647 shading calibration.
648
649 - then we move by the needed offset whitin physical scanning area
650 */
651 unsigned move_dpi = dev->motor.base_ydpi;
652
653 float move = dev->model->y_offset;
654 if (settings.scan_method == ScanMethod::TRANSPARENCY ||
655 settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
656 {
657 // note: scanner_move_to_ta() function has already been called and the sensor is at the
658 // transparency adapter
659 if (!dev->ignore_offsets) {
660 move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
661 }
662 flags |= ScanFlag::USE_XPA;
663 } else {
664 if (!dev->ignore_offsets) {
665 move = dev->model->y_offset;
666 }
667 }
668
669 move = move + settings.tl_y;
670 move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
671 move -= dev->head_pos(ScanHeadId::PRIMARY);
672
673 float start = dev->model->x_offset;
674 if (settings.scan_method == ScanMethod::TRANSPARENCY ||
675 settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
676 {
677 start = dev->model->x_offset_ta;
678 } else {
679 start = dev->model->x_offset;
680 }
681
682 start = start + dev->settings.tl_x;
683 start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
684
685 ScanSession session;
686 session.params.xres = settings.xres;
687 session.params.yres = settings.yres;
688 session.params.startx = static_cast<unsigned>(start);
689 session.params.starty = static_cast<unsigned>(move);
690 session.params.pixels = settings.pixels;
691 session.params.requested_pixels = settings.requested_pixels;
692 session.params.lines = settings.lines;
693 session.params.depth = settings.depth;
694 session.params.channels = settings.get_channels();
695 session.params.scan_method = settings.scan_method;
696 session.params.scan_mode = settings.scan_mode;
697 session.params.color_filter = settings.color_filter;
698 session.params.contrast_adjustment = settings.contrast;
699 session.params.brightness_adjustment = settings.brightness;
700 session.params.flags = flags;
701
702 compute_session(dev, session, sensor);
703
704 return session;
705 }
706
707 // for fast power saving methods only, like disabling certain amplifiers
save_power(Genesys_Device * dev,bool enable) const708 void CommandSetGl847::save_power(Genesys_Device* dev, bool enable) const
709 {
710 DBG_HELPER_ARGS(dbg, "enable = %d", enable);
711 (void) dev;
712 }
713
set_powersaving(Genesys_Device * dev,int delay) const714 void CommandSetGl847::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const
715 {
716 (void) dev;
717 DBG_HELPER_ARGS(dbg, "delay = %d", delay);
718 }
719
720 // Send the low-level scan command
begin_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,bool start_motor) const721 void CommandSetGl847::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
722 Genesys_Register_Set* reg, bool start_motor) const
723 {
724 DBG_HELPER(dbg);
725 (void) sensor;
726 std::uint8_t val;
727
728 if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
729 dev->cmd_set->set_xpa_lamp_power(*dev, true);
730 }
731
732 if (dev->model->model_id == ModelId::HP_SCANJET_N6310 ||
733 dev->model->model_id == ModelId::CANON_LIDE_100 ||
734 dev->model->model_id == ModelId::CANON_LIDE_200)
735 {
736 val = dev->interface->read_register(REG_0x6C);
737 val &= ~REG_0x6C_GPIO10;
738 dev->interface->write_register(REG_0x6C, val);
739 }
740
741 if (dev->model->model_id == ModelId::CANON_5600F) {
742 switch (dev->session.params.xres) {
743 case 75:
744 case 150:
745 case 300:
746 scanner_register_rw_bits(*dev, REG_0xA6, 0x04, 0x1c);
747 break;
748 case 600:
749 scanner_register_rw_bits(*dev, REG_0xA6, 0x18, 0x1c);
750 break;
751 case 1200:
752 scanner_register_rw_bits(*dev, REG_0xA6, 0x08, 0x1c);
753 break;
754 case 2400:
755 scanner_register_rw_bits(*dev, REG_0xA6, 0x10, 0x1c);
756 break;
757 case 4800:
758 scanner_register_rw_bits(*dev, REG_0xA6, 0x00, 0x1c);
759 break;
760 default:
761 throw SaneException("Unexpected xres");
762 }
763 dev->interface->write_register(0x6c, 0xf0);
764 dev->interface->write_register(0x6b, 0x87);
765 dev->interface->write_register(0x6d, 0x5f);
766 }
767
768 if (dev->model->model_id == ModelId::CANON_5600F) {
769 scanner_clear_scan_and_feed_counts(*dev);
770 } else {
771 // FIXME: use scanner_clear_scan_and_feed_counts()
772 val = REG_0x0D_CLRLNCNT;
773 dev->interface->write_register(REG_0x0D, val);
774 val = REG_0x0D_CLRMCNT;
775 dev->interface->write_register(REG_0x0D, val);
776 }
777
778 val = dev->interface->read_register(REG_0x01);
779 val |= REG_0x01_SCAN;
780 dev->interface->write_register(REG_0x01, val);
781 reg->set8(REG_0x01, val);
782
783 scanner_start_action(*dev, start_motor);
784
785 dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
786 }
787
788
789 // Send the stop scan command
end_scan(Genesys_Device * dev,Genesys_Register_Set * reg,bool check_stop) const790 void CommandSetGl847::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
791 bool check_stop) const
792 {
793 (void) reg;
794 DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
795
796 if (reg->state.is_xpa_on) {
797 dev->cmd_set->set_xpa_lamp_power(*dev, false);
798 }
799
800 if (!dev->model->is_sheetfed) {
801 scanner_stop_action(*dev);
802 }
803 }
804
move_back_home(Genesys_Device * dev,bool wait_until_home) const805 void CommandSetGl847::move_back_home(Genesys_Device* dev, bool wait_until_home) const
806 {
807 scanner_move_back_home(*dev, wait_until_home);
808 }
809
810 // init registers for shading calibration
init_regs_for_shading(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const811 void CommandSetGl847::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
812 Genesys_Register_Set& regs) const
813 {
814 DBG_HELPER(dbg);
815
816 unsigned move_dpi = dev->motor.base_ydpi;
817
818 float calib_size_mm = 0;
819 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
820 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
821 {
822 calib_size_mm = dev->model->y_size_calib_ta_mm;
823 } else {
824 calib_size_mm = dev->model->y_size_calib_mm;
825 }
826
827 unsigned channels = 3;
828 unsigned resolution = sensor.shading_resolution;
829
830 const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
831 dev->settings.scan_method);
832
833 float move = 0;
834 ScanFlag flags = ScanFlag::DISABLE_SHADING |
835 ScanFlag::DISABLE_GAMMA |
836 ScanFlag::DISABLE_BUFFER_FULL_MOVE;
837
838 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
839 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
840 {
841 // note: scanner_move_to_ta() function has already been called and the sensor is at the
842 // transparency adapter
843 move = dev->model->y_offset_calib_white_ta - dev->model->y_offset_sensor_to_ta;
844 flags |= ScanFlag::USE_XPA;
845 } else {
846 move = dev->model->y_offset_calib_white;
847 }
848
849 move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
850
851 unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
852
853 ScanSession session;
854 session.params.xres = resolution;
855 session.params.yres = resolution;
856 session.params.startx = 0;
857 session.params.starty = static_cast<unsigned>(move);
858 session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
859 session.params.lines = calib_lines;
860 session.params.depth = 16;
861 session.params.channels = channels;
862 session.params.scan_method = dev->settings.scan_method;
863 session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
864 session.params.color_filter = dev->settings.color_filter;
865 session.params.contrast_adjustment = dev->settings.contrast;
866 session.params.brightness_adjustment = dev->settings.brightness;
867 session.params.flags = flags;
868 compute_session(dev, session, calib_sensor);
869
870 init_regs_for_scan_session(dev, calib_sensor, ®s, session);
871
872 /* we use ModelFlag::SHADING_REPARK */
873 dev->set_head_pos_zero(ScanHeadId::PRIMARY);
874
875 dev->calib_session = session;
876 }
877
878 /**
879 * Send shading calibration data. The buffer is considered to always hold values
880 * for all the channels.
881 */
send_shading_data(Genesys_Device * dev,const Genesys_Sensor & sensor,std::uint8_t * data,int size) const882 void CommandSetGl847::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
883 std::uint8_t* data, int size) const
884 {
885 DBG_HELPER_ARGS(dbg, "writing %d bytes of shading data", size);
886 std::uint32_t addr, i;
887
888 unsigned length = static_cast<unsigned>(size / 3);
889
890 // we're using SHDAREA, thus we only need to upload part of the line
891 unsigned offset = dev->session.pixel_count_ratio.apply(
892 dev->session.params.startx * sensor.full_resolution / dev->session.params.xres);
893 unsigned pixels = dev->session.pixel_count_ratio.apply(dev->session.optical_pixels_raw);
894
895 // turn pixel value into bytes 2x16 bits words
896 offset *= 2 * 2;
897 pixels *= 2 * 2;
898
899 dev->interface->record_key_value("shading_offset", std::to_string(offset));
900 dev->interface->record_key_value("shading_pixels", std::to_string(pixels));
901 dev->interface->record_key_value("shading_length", std::to_string(length));
902 dev->interface->record_key_value("shading_factor", std::to_string(sensor.shading_factor));
903
904 std::vector<std::uint8_t> buffer(pixels, 0);
905
906 DBG(DBG_io2, "%s: using chunks of %d (0x%04x) bytes\n", __func__, pixels, pixels);
907
908 /* base addr of data has been written in reg D0-D4 in 4K word, so AHB address
909 * is 8192*reg value */
910
911 if (dev->model->model_id == ModelId::CANON_5600F) {
912 return;
913 }
914
915 /* write actual color channel data */
916 for(i=0;i<3;i++)
917 {
918 /* build up actual shading data by copying the part from the full width one
919 * to the one corresponding to SHDAREA */
920 std::uint8_t* ptr = buffer.data();
921
922 // iterate on both sensor segment
923 for (unsigned x = 0; x < pixels; x += 4 * sensor.shading_factor) {
924 // coefficient source
925 std::uint8_t* src = (data + offset + i * length) + x;
926
927 /* coefficient copy */
928 ptr[0]=src[0];
929 ptr[1]=src[1];
930 ptr[2]=src[2];
931 ptr[3]=src[3];
932
933 /* next shading coefficient */
934 ptr+=4;
935 }
936
937 std::uint8_t val = dev->interface->read_register(0xd0+i);
938 addr = val * 8192 + 0x10000000;
939 dev->interface->write_ahb(addr, pixels, buffer.data());
940 }
941 }
942
943 /** @brief calibrates led exposure
944 * Calibrate exposure by scanning a white area until the used exposure gives
945 * data white enough.
946 * @param dev device to calibrate
947 */
led_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const948 SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
949 Genesys_Register_Set& regs) const
950 {
951 return scanner_led_calibration(*dev, sensor, regs);
952 }
953
954 /**
955 * set up GPIO/GPOE for idle state
956 */
gl847_init_gpio(Genesys_Device * dev)957 static void gl847_init_gpio(Genesys_Device* dev)
958 {
959 DBG_HELPER(dbg);
960
961 if (dev->model->model_id == ModelId::CANON_5600F) {
962 apply_registers_ordered(dev->gpo.regs, {0xa6, 0xa7, 0x6f, 0x6e},
963 [&](const GenesysRegisterSetting& reg)
964 {
965 dev->interface->write_register(reg.address, reg.value);
966 });
967 } else {
968 std::vector<std::uint16_t> order1 = { 0xa7, 0xa6, 0x6e };
969 std::vector<std::uint16_t> order2 = { 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0xa8, 0xa9 };
970
971 for (auto addr : order1) {
972 dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
973 }
974
975 dev->interface->write_register(REG_0x6C, 0x00); // FIXME: Likely not needed
976
977 for (auto addr : order2) {
978 dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
979 }
980
981 for (const auto& reg : dev->gpo.regs) {
982 if (std::find(order1.begin(), order1.end(), reg.address) != order1.end()) {
983 continue;
984 }
985 if (std::find(order2.begin(), order2.end(), reg.address) != order2.end()) {
986 continue;
987 }
988 dev->interface->write_register(reg.address, reg.value);
989 }
990 }
991 }
992
993 /**
994 * set memory layout by filling values in dedicated registers
995 */
gl847_init_memory_layout(Genesys_Device * dev)996 static void gl847_init_memory_layout(Genesys_Device* dev)
997 {
998 DBG_HELPER(dbg);
999
1000 // FIXME: move to initial register list
1001 switch (dev->model->model_id) {
1002 case ModelId::CANON_LIDE_100:
1003 case ModelId::CANON_LIDE_200:
1004 dev->interface->write_register(REG_0x0B, 0x29);
1005 break;
1006 case ModelId::CANON_LIDE_700F:
1007 dev->interface->write_register(REG_0x0B, 0x2a);
1008 break;
1009 default:
1010 break;
1011 }
1012
1013 // prevent further writings by bulk write register
1014 dev->reg.remove_reg(0x0b);
1015
1016 apply_reg_settings_to_device_write_only(*dev, dev->memory_layout.regs);
1017 }
1018
1019 /* *
1020 * initialize ASIC from power on condition
1021 */
asic_boot(Genesys_Device * dev,bool cold) const1022 void CommandSetGl847::asic_boot(Genesys_Device* dev, bool cold) const
1023 {
1024 DBG_HELPER(dbg);
1025
1026 // reset ASIC if cold boot
1027 if (cold) {
1028 dev->interface->write_register(0x0e, 0x01);
1029 dev->interface->write_register(0x0e, 0x00);
1030 }
1031
1032 // test CHKVER
1033 std::uint8_t val = dev->interface->read_register(REG_0x40);
1034 if (val & REG_0x40_CHKVER) {
1035 val = dev->interface->read_register(0x00);
1036 DBG(DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val);
1037 }
1038
1039 /* Set default values for registers */
1040 gl847_init_registers (dev);
1041
1042 // Write initial registers
1043 dev->interface->write_registers(dev->reg);
1044
1045 if (dev->model->model_id != ModelId::CANON_5600F) {
1046 // Enable DRAM by setting a rising edge on bit 3 of reg 0x0b
1047 // The initial register write also powers on SDRAM
1048 val = dev->reg.find_reg(0x0b).value & REG_0x0B_DRAMSEL;
1049 val = (val | REG_0x0B_ENBDRAM);
1050 dev->interface->write_register(REG_0x0B, val);
1051 dev->reg.find_reg(0x0b).value = val;
1052
1053 // TODO: remove this write
1054 dev->interface->write_register(0x08, dev->reg.find_reg(0x08).value);
1055 }
1056
1057 // set up end access
1058 dev->interface->write_0x8c(0x10, 0x0b);
1059 dev->interface->write_0x8c(0x13, 0x0e);
1060
1061 // setup gpio
1062 gl847_init_gpio(dev);
1063
1064 // setup internal memory layout
1065 gl847_init_memory_layout (dev);
1066
1067 if (dev->model->model_id != ModelId::CANON_5600F) {
1068 // FIXME: move to memory layout
1069 dev->reg.init_reg(0xf8, 0x01);
1070 dev->interface->write_register(0xf8, dev->reg.find_reg(0xf8).value);
1071 }
1072 }
1073
1074 /**
1075 * initialize backend and ASIC : registers, motor tables, and gamma tables
1076 * then ensure scanner's head is at home
1077 */
init(Genesys_Device * dev) const1078 void CommandSetGl847::init(Genesys_Device* dev) const
1079 {
1080 DBG_INIT ();
1081 DBG_HELPER(dbg);
1082
1083 sanei_genesys_asic_init(dev);
1084 }
1085
update_hardware_sensors(Genesys_Scanner * s) const1086 void CommandSetGl847::update_hardware_sensors(Genesys_Scanner* s) const
1087 {
1088 DBG_HELPER(dbg);
1089 /* do what is needed to get a new set of events, but try to not lose
1090 any of them.
1091 */
1092 std::uint8_t val;
1093 switch(s->dev->model->gpio_id) {
1094 case GpioId::CANON_LIDE_700F:
1095 val = s->dev->interface->read_register(REG_0x6D);
1096 DBG(DBG_io, "%s: read buttons_gpio value=0x%x\n", __func__, (int)val);
1097
1098 s->buttons[BUTTON_SCAN_SW].write((val & 0x04) == 0);
1099 s->buttons[BUTTON_FILE_SW].write((val & 0x02) == 0);
1100 s->buttons[BUTTON_EMAIL_SW].write((val & 0x01) == 0);
1101 s->buttons[BUTTON_COPY_SW].write((val & 0x08) == 0);
1102 break;
1103
1104 case GpioId::CANON_5600F:
1105 val = s->dev->interface->read_register(REG_0x6D);
1106 DBG(DBG_io, "%s: read buttons_gpio 0x6d value=0x%x\n", __func__, (int)val);
1107 s->buttons[BUTTON_SCAN_SW].write((val & 0x02) == 0);
1108 s->buttons[BUTTON_EMAIL_SW].write((val & 0x01) == 0);
1109 s->buttons[BUTTON_COPY_SW].write((val & 0x08) == 0);
1110 s->buttons[BUTTON_PDF4_SW].write((val & 0x04) == 0);
1111
1112 val = s->dev->interface->read_register(REG_0xA6);
1113 DBG(DBG_io, "%s: read buttons_gpio 0xa6 value=0x%x\n", __func__, (int)val);
1114 s->buttons[BUTTON_PDF1_SW].write((val & 0x03) == 0x01);
1115 s->buttons[BUTTON_PDF2_SW].write((val & 0x03) == 0x02);
1116
1117 val = s->dev->interface->read_register(REG_0x6C);
1118 DBG(DBG_io, "%s: read buttons_gpio 0x6c value=0x%x\n", __func__, (int)val);
1119 s->buttons[BUTTON_PDF3_SW].write((val & 0x80) == 0x00);
1120 break;
1121
1122 default:
1123 val = s->dev->interface->read_register(REG_0x6D);
1124 DBG(DBG_io, "%s: read buttons_gpio value=0x%x\n", __func__, (int)val);
1125
1126 s->buttons[BUTTON_SCAN_SW].write((val & 0x01) == 0);
1127 s->buttons[BUTTON_FILE_SW].write((val & 0x02) == 0);
1128 s->buttons[BUTTON_EMAIL_SW].write((val & 0x04) == 0);
1129 s->buttons[BUTTON_COPY_SW].write((val & 0x08) == 0);
1130 break;
1131 }
1132 }
1133
update_home_sensor_gpio(Genesys_Device & dev) const1134 void CommandSetGl847::update_home_sensor_gpio(Genesys_Device& dev) const
1135 {
1136 DBG_HELPER(dbg);
1137
1138 if (dev.model->gpio_id == GpioId::CANON_LIDE_700F) {
1139 std::uint8_t val = dev.interface->read_register(REG_0x6C);
1140 val &= ~REG_0x6C_GPIO10;
1141 dev.interface->write_register(REG_0x6C, val);
1142 } else {
1143 std::uint8_t val = dev.interface->read_register(REG_0x6C);
1144 val |= REG_0x6C_GPIO10;
1145 dev.interface->write_register(REG_0x6C, val);
1146 }
1147 }
1148
offset_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1149 void CommandSetGl847::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1150 Genesys_Register_Set& regs) const
1151 {
1152 scanner_offset_calibration(*dev, sensor, regs);
1153 }
1154
coarse_gain_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs,int dpi) const1155 void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1156 Genesys_Register_Set& regs, int dpi) const
1157 {
1158 scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
1159 }
1160
needs_home_before_init_regs_for_scan(Genesys_Device * dev) const1161 bool CommandSetGl847::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
1162 {
1163 (void) dev;
1164 return false;
1165 }
1166
init_regs_for_warmup(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * regs) const1167 void CommandSetGl847::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
1168 Genesys_Register_Set* regs) const
1169 {
1170 (void) dev;
1171 (void) sensor;
1172 (void) regs;
1173 throw SaneException("not implemented");
1174 }
1175
send_gamma_table(Genesys_Device * dev,const Genesys_Sensor & sensor) const1176 void CommandSetGl847::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
1177 {
1178 sanei_genesys_send_gamma_table(dev, sensor);
1179 }
1180
wait_for_motor_stop(Genesys_Device * dev) const1181 void CommandSetGl847::wait_for_motor_stop(Genesys_Device* dev) const
1182 {
1183 (void) dev;
1184 }
1185
load_document(Genesys_Device * dev) const1186 void CommandSetGl847::load_document(Genesys_Device* dev) const
1187 {
1188 (void) dev;
1189 throw SaneException("not implemented");
1190 }
1191
detect_document_end(Genesys_Device * dev) const1192 void CommandSetGl847::detect_document_end(Genesys_Device* dev) const
1193 {
1194 (void) dev;
1195 throw SaneException("not implemented");
1196 }
1197
eject_document(Genesys_Device * dev) const1198 void CommandSetGl847::eject_document(Genesys_Device* dev) const
1199 {
1200 (void) dev;
1201 throw SaneException("not implemented");
1202 }
1203
1204 } // namespace gl847
1205 } // namespace genesys
1206