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, &regs, 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