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