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