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