1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr>
4 
5 
6    This file is part of the SANE package.
7 
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2 of the
11    License, or (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 
21    As a special exception, the authors of SANE give permission for
22    additional uses of the libraries contained in this release of SANE.
23 
24    The exception is that, if you link a SANE library with other files
25    to produce an executable, this does not by itself cause the
26    resulting executable to be covered by the GNU General Public
27    License.  Your use of that executable is in no way restricted on
28    account of linking the SANE library code into it.
29 
30    This exception does not, however, invalidate any other reasons why
31    the executable file might be covered by the GNU General Public
32    License.
33 
34    If you submit changes to SANE to the maintainers to be included in
35    a subsequent release, you agree by submitting the changes that
36    those changes may be distributed with this exception intact.
37 
38    If you write modifications of your own for SANE, it is your choice
39    whether to permit this exception to apply to your modifications.
40    If you do not wish that, delete this exception notice.
41 */
42 
43 #define DEBUG_DECLARE_ONLY
44 
45 #include "gl843_registers.h"
46 #include "gl843.h"
47 #include "test_settings.h"
48 
49 #include <string>
50 #include <vector>
51 
52 namespace genesys {
53 namespace gl843 {
54 
55 /**
56  * compute the step multiplier used
57  */
gl843_get_step_multiplier(Genesys_Register_Set * regs)58 static int gl843_get_step_multiplier(Genesys_Register_Set* regs)
59 {
60     switch (regs->get8(REG_0x9D) & 0x0c) {
61         case 0x04: return 2;
62         case 0x08: return 4;
63         default: return 1;
64     }
65 }
66 
67 /** @brief set all registers to default values .
68  * This function is called only once at the beginning and
69  * fills register startup values for registers reused across scans.
70  * Those that are rarely modified or not modified are written
71  * individually.
72  * @param dev device structure holding register set to initialize
73  */
74 static void
gl843_init_registers(Genesys_Device * dev)75 gl843_init_registers (Genesys_Device * dev)
76 {
77     // Within this function SENSOR_DEF marker documents that a register is part
78     // of the sensors definition and the actual value is set in
79     // scanner_setup_sensor().
80 
81     // 0x6c, 0x6d, 0x6e, 0x6f, 0xa6, 0xa7, 0xa8, 0xa9 are defined in the Gpo sensor struct
82 
83     DBG_HELPER(dbg);
84 
85     dev->reg.clear();
86 
87     dev->reg.init_reg(0x01, 0x00);
88     dev->reg.init_reg(0x02, 0x78);
89     dev->reg.init_reg(0x03, 0x1f);
90     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
91         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
92         dev->model->model_id == ModelId::HP_SCANJET_4850C)
93     {
94         dev->reg.init_reg(0x03, 0x1d);
95     }
96     if (dev->model->model_id == ModelId::CANON_8400F) {
97         dev->reg.init_reg(0x03, 0x1c);
98     }
99 
100     dev->reg.init_reg(0x04, 0x10);
101     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
102         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
103         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
104     {
105         dev->reg.init_reg(0x04, 0x22);
106     }
107 
108     // fine tune upon device description
109     dev->reg.init_reg(0x05, 0x80);
110     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
111         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
112         dev->model->model_id == ModelId::HP_SCANJET_4850C)
113     {
114       dev->reg.init_reg(0x05, 0x08);
115     }
116 
117     auto initial_scan_method = dev->model->default_method;
118     if (dev->model->model_id == ModelId::CANON_4400F ||
119         dev->model->model_id == ModelId::CANON_8600F)
120     {
121         initial_scan_method = ScanMethod::TRANSPARENCY;
122     }
123     const auto& sensor = sanei_genesys_find_sensor_any(dev);
124     const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution,
125                                                          3, initial_scan_method);
126     sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw);
127 
128     // TODO: on 8600F the windows driver turns off GAIN4 which is recommended
129     dev->reg.init_reg(0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */
130     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
131         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
132         dev->model->model_id == ModelId::HP_SCANJET_4850C)
133     {
134         dev->reg.init_reg(0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */
135     }
136     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I) {
137         dev->reg.init_reg(0x06, 0xd0);
138     }
139     if (dev->model->model_id == ModelId::CANON_4400F ||
140         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
141         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
142     {
143         dev->reg.init_reg(0x06, 0xf0); /* SCANMOD=111, PWRBIT and no GAIN4 */
144     }
145 
146   dev->reg.init_reg(0x08, 0x00);
147   dev->reg.init_reg(0x09, 0x00);
148   dev->reg.init_reg(0x0a, 0x00);
149     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
150         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
151         dev->model->model_id == ModelId::HP_SCANJET_4850C)
152     {
153         dev->reg.init_reg(0x0a, 0x18);
154     }
155     if (dev->model->model_id == ModelId::CANON_8400F) {
156         dev->reg.init_reg(0x0a, 0x10);
157     }
158 
159     // This register controls clock and RAM settings and is further modified in
160     // gl843_boot
161     dev->reg.init_reg(0x0b, 0x6a);
162 
163     if (dev->model->model_id == ModelId::CANON_4400F) {
164         dev->reg.init_reg(0x0b, 0x69); // 16M only
165     }
166     if (dev->model->model_id == ModelId::CANON_8600F) {
167         dev->reg.init_reg(0x0b, 0x89);
168     }
169     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I) {
170         dev->reg.init_reg(0x0b, 0x2a);
171     }
172     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
173         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I) {
174         dev->reg.init_reg(0x0b, 0x4a);
175     }
176     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
177         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
178         dev->model->model_id == ModelId::HP_SCANJET_4850C)
179     {
180         dev->reg.init_reg(0x0b, 0x69);
181     }
182 
183     if (dev->model->model_id != ModelId::CANON_8400F &&
184         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
185         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
186     {
187         dev->reg.init_reg(0x0c, 0x00);
188     }
189 
190     // EXPR[0:15], EXPG[0:15], EXPB[0:15]: Exposure time settings.
191     dev->reg.init_reg(0x10, 0x00); // SENSOR_DEF
192     dev->reg.init_reg(0x11, 0x00); // SENSOR_DEF
193     dev->reg.init_reg(0x12, 0x00); // SENSOR_DEF
194     dev->reg.init_reg(0x13, 0x00); // SENSOR_DEF
195     dev->reg.init_reg(0x14, 0x00); // SENSOR_DEF
196     dev->reg.init_reg(0x15, 0x00); // SENSOR_DEF
197     if (dev->model->model_id == ModelId::CANON_4400F ||
198         dev->model->model_id == ModelId::CANON_8600F)
199     {
200         dev->reg.set16(REG_EXPR, 0x9c40);
201         dev->reg.set16(REG_EXPG, 0x9c40);
202         dev->reg.set16(REG_EXPB, 0x9c40);
203     }
204     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
205         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
206         dev->model->model_id == ModelId::HP_SCANJET_4850C)
207     {
208         dev->reg.set16(REG_EXPR, 0x2c09);
209         dev->reg.set16(REG_EXPG, 0x22b8);
210         dev->reg.set16(REG_EXPB, 0x10f0);
211     }
212 
213     // CCD signal settings.
214     dev->reg.init_reg(0x16, 0x33); // SENSOR_DEF
215     dev->reg.init_reg(0x17, 0x1c); // SENSOR_DEF
216     dev->reg.init_reg(0x18, 0x10); // SENSOR_DEF
217 
218     // EXPDMY[0:7]: Exposure time of dummy lines.
219     dev->reg.init_reg(0x19, 0x2a); // SENSOR_DEF
220 
221     // Various CCD clock settings.
222     dev->reg.init_reg(0x1a, 0x04); // SENSOR_DEF
223     dev->reg.init_reg(0x1b, 0x00); // SENSOR_DEF
224     dev->reg.init_reg(0x1c, 0x20); // SENSOR_DEF
225     dev->reg.init_reg(0x1d, 0x04); // SENSOR_DEF
226 
227     dev->reg.init_reg(0x1e, 0x10);
228     if (dev->model->model_id == ModelId::CANON_4400F ||
229         dev->model->model_id == ModelId::CANON_8600F)
230     {
231         dev->reg.init_reg(0x1e, 0x20);
232     }
233     if (dev->model->model_id == ModelId::CANON_8400F) {
234         dev->reg.init_reg(0x1e, 0xa0);
235     }
236 
237     dev->reg.init_reg(0x1f, 0x01);
238     if (dev->model->model_id == ModelId::CANON_8600F) {
239       dev->reg.init_reg(0x1f, 0xff);
240     }
241 
242     dev->reg.init_reg(0x20, 0x10);
243     dev->reg.init_reg(0x21, 0x04);
244 
245     dev->reg.init_reg(0x22, 0x10);
246     dev->reg.init_reg(0x23, 0x10);
247     if (dev->model->model_id == ModelId::CANON_8600F) {
248         dev->reg.init_reg(0x22, 0xc8);
249         dev->reg.init_reg(0x23, 0xc8);
250     }
251     if (dev->model->model_id == ModelId::CANON_8400F) {
252         dev->reg.init_reg(0x22, 0x50);
253         dev->reg.init_reg(0x23, 0x50);
254     }
255 
256     dev->reg.init_reg(0x24, 0x04);
257     dev->reg.init_reg(0x25, 0x00);
258     dev->reg.init_reg(0x26, 0x00);
259     dev->reg.init_reg(0x27, 0x00);
260     dev->reg.init_reg(0x2c, 0x02);
261     dev->reg.init_reg(0x2d, 0x58);
262     // BWHI[0:7]: high level of black and white threshold
263     dev->reg.init_reg(0x2e, 0x80);
264     // BWLOW[0:7]: low level of black and white threshold
265     dev->reg.init_reg(0x2f, 0x80);
266     dev->reg.init_reg(0x30, 0x00);
267     dev->reg.init_reg(0x31, 0x14);
268     dev->reg.init_reg(0x32, 0x27);
269     dev->reg.init_reg(0x33, 0xec);
270 
271     // DUMMY: CCD dummy and optically black pixel count
272     dev->reg.init_reg(0x34, 0x24);
273     if (dev->model->model_id == ModelId::CANON_8600F) {
274         dev->reg.init_reg(0x34, 0x14);
275     }
276     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
277         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
278     {
279         dev->reg.init_reg(0x34, 0x3c);
280     }
281 
282     // MAXWD: If available buffer size is less than 2*MAXWD words, then
283     // "buffer full" state will be set.
284     dev->reg.init_reg(0x35, 0x00);
285     dev->reg.init_reg(0x36, 0xff);
286     dev->reg.init_reg(0x37, 0xff);
287 
288     // LPERIOD: Line period or exposure time for CCD or CIS.
289     dev->reg.init_reg(0x38, 0x55); // SENSOR_DEF
290     dev->reg.init_reg(0x39, 0xf0); // SENSOR_DEF
291 
292     // FEEDL[0:24]: The number of steps of motor movement.
293     dev->reg.init_reg(0x3d, 0x00);
294     dev->reg.init_reg(0x3e, 0x00);
295     dev->reg.init_reg(0x3f, 0x01);
296 
297     // Latch points for high and low bytes of R, G and B channels of AFE. If
298     // multiple clocks per pixel are consumed, then the setting defines during
299     // which clock the corresponding value will be read.
300     // RHI[0:4]: The latch point for high byte of R channel.
301     // RLOW[0:4]: The latch point for low byte of R channel.
302     // GHI[0:4]: The latch point for high byte of G channel.
303     // GLOW[0:4]: The latch point for low byte of G channel.
304     // BHI[0:4]: The latch point for high byte of B channel.
305     // BLOW[0:4]: The latch point for low byte of B channel.
306     dev->reg.init_reg(0x52, 0x01); // SENSOR_DEF
307     dev->reg.init_reg(0x53, 0x04); // SENSOR_DEF
308     dev->reg.init_reg(0x54, 0x07); // SENSOR_DEF
309     dev->reg.init_reg(0x55, 0x0a); // SENSOR_DEF
310     dev->reg.init_reg(0x56, 0x0d); // SENSOR_DEF
311     dev->reg.init_reg(0x57, 0x10); // SENSOR_DEF
312 
313     // VSMP[0:4]: The position of the image sampling pulse for AFE in cycles.
314     // VSMPW[0:2]: The length of the image sampling pulse for AFE in cycles.
315     dev->reg.init_reg(0x58, 0x1b); // SENSOR_DEF
316 
317     dev->reg.init_reg(0x59, 0x00); // SENSOR_DEF
318     dev->reg.init_reg(0x5a, 0x40); // SENSOR_DEF
319 
320     // 0x5b-0x5c: GMMADDR[0:15] address for gamma or motor tables download
321     // SENSOR_DEF
322 
323     // DECSEL[0:2]: The number of deceleration steps after touching home sensor
324     // STOPTIM[0:4]: The stop duration between change of directions in
325     // backtracking
326     dev->reg.init_reg(0x5e, 0x23);
327     if (dev->model->model_id == ModelId::CANON_4400F) {
328         dev->reg.init_reg(0x5e, 0x3f);
329     }
330     if (dev->model->model_id == ModelId::CANON_8400F) {
331         dev->reg.init_reg(0x5e, 0x85);
332     }
333     if (dev->model->model_id == ModelId::CANON_8600F) {
334         dev->reg.init_reg(0x5e, 0x1f);
335     }
336     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
337         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
338     {
339         dev->reg.init_reg(0x5e, 0x01);
340     }
341 
342     //FMOVDEC: The number of deceleration steps in table 5 for auto-go-home
343     dev->reg.init_reg(0x5f, 0x01);
344     if (dev->model->model_id == ModelId::CANON_4400F) {
345         dev->reg.init_reg(0x5f, 0xf0);
346     }
347     if (dev->model->model_id == ModelId::CANON_8600F) {
348         dev->reg.init_reg(0x5f, 0xf0);
349     }
350     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
351         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
352     {
353         dev->reg.init_reg(0x5f, 0x01);
354     }
355 
356     // Z1MOD[0:20]
357     dev->reg.init_reg(0x60, 0x00);
358     dev->reg.init_reg(0x61, 0x00);
359     dev->reg.init_reg(0x62, 0x00);
360 
361     // Z2MOD[0:20]
362     dev->reg.init_reg(0x63, 0x00);
363     dev->reg.init_reg(0x64, 0x00);
364     dev->reg.init_reg(0x65, 0x00);
365 
366     // STEPSEL[0:1]. Motor movement step mode selection for tables 1-3 in
367     // scanning mode.
368     // MTRPWM[0:5]. Motor phase PWM duty cycle setting for tables 1-3
369     dev->reg.init_reg(0x67, 0x7f); // MOTOR_PROFILE
370     // FSTPSEL[0:1]: Motor movement step mode selection for tables 4-5 in
371     // command mode.
372     // FASTPWM[5:0]: Motor phase PWM duty cycle setting for tables 4-5
373     dev->reg.init_reg(0x68, 0x7f); // MOTOR_PROFILE
374 
375     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300) {
376         dev->reg.init_reg(0x67, 0x80);
377         dev->reg.init_reg(0x68, 0x80);
378     }
379 
380     // FSHDEC[0:7]: The number of deceleration steps after scanning is finished
381     // (table 3)
382     dev->reg.init_reg(0x69, 0x01); // MOTOR_PROFILE
383 
384     // FMOVNO[0:7] The number of acceleration or deceleration steps for fast
385     // moving (table 4)
386     dev->reg.init_reg(0x6a, 0x04); // MOTOR_PROFILE
387 
388     // GPIO-related register bits
389     dev->reg.init_reg(0x6b, 0x30);
390     if (dev->model->model_id == ModelId::CANON_4400F ||
391         dev->model->model_id == ModelId::CANON_8600F)
392     {
393         dev->reg.init_reg(0x6b, 0x72);
394     }
395     if (dev->model->model_id == ModelId::CANON_8400F) {
396         dev->reg.init_reg(0x6b, 0xb1);
397     }
398     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
399         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
400         dev->model->model_id == ModelId::HP_SCANJET_4850C)
401     {
402         dev->reg.init_reg(0x6b, 0xf4);
403     }
404     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
405         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
406         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
407     {
408         dev->reg.init_reg(0x6b, 0x31);
409     }
410 
411     // 0x6c, 0x6d, 0x6e, 0x6f are set according to gpio tables. See
412     // gl843_init_gpio.
413 
414     // RSH[0:4]: The position of rising edge of CCD RS signal in cycles
415     // RSL[0:4]: The position of falling edge of CCD RS signal in cycles
416     // CPH[0:4]: The position of rising edge of CCD CP signal in cycles.
417     // CPL[0:4]: The position of falling edge of CCD CP signal in cycles
418     dev->reg.init_reg(0x70, 0x01); // SENSOR_DEF
419     dev->reg.init_reg(0x71, 0x03); // SENSOR_DEF
420     dev->reg.init_reg(0x72, 0x04); // SENSOR_DEF
421     dev->reg.init_reg(0x73, 0x05); // SENSOR_DEF
422 
423     if (dev->model->model_id == ModelId::CANON_4400F) {
424         dev->reg.init_reg(0x70, 0x01);
425         dev->reg.init_reg(0x71, 0x03);
426         dev->reg.init_reg(0x72, 0x01);
427         dev->reg.init_reg(0x73, 0x03);
428     }
429     if (dev->model->model_id == ModelId::CANON_8400F) {
430         dev->reg.init_reg(0x70, 0x01);
431         dev->reg.init_reg(0x71, 0x03);
432         dev->reg.init_reg(0x72, 0x03);
433         dev->reg.init_reg(0x73, 0x04);
434     }
435     if (dev->model->model_id == ModelId::CANON_8600F) {
436         dev->reg.init_reg(0x70, 0x00);
437         dev->reg.init_reg(0x71, 0x02);
438         dev->reg.init_reg(0x72, 0x02);
439         dev->reg.init_reg(0x73, 0x04);
440     }
441     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
442         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
443         dev->model->model_id == ModelId::HP_SCANJET_4850C)
444     {
445         dev->reg.init_reg(0x70, 0x00);
446         dev->reg.init_reg(0x71, 0x02);
447         dev->reg.init_reg(0x72, 0x00);
448         dev->reg.init_reg(0x73, 0x00);
449     }
450 
451     // CK1MAP[0:17], CK3MAP[0:17], CK4MAP[0:17]: CCD clock bit mapping setting.
452     dev->reg.init_reg(0x74, 0x00); // SENSOR_DEF
453     dev->reg.init_reg(0x75, 0x00); // SENSOR_DEF
454     dev->reg.init_reg(0x76, 0x3c); // SENSOR_DEF
455     dev->reg.init_reg(0x77, 0x00); // SENSOR_DEF
456     dev->reg.init_reg(0x78, 0x00); // SENSOR_DEF
457     dev->reg.init_reg(0x79, 0x9f); // SENSOR_DEF
458     dev->reg.init_reg(0x7a, 0x00); // SENSOR_DEF
459     dev->reg.init_reg(0x7b, 0x00); // SENSOR_DEF
460     dev->reg.init_reg(0x7c, 0x55); // SENSOR_DEF
461 
462     // various AFE settings
463     dev->reg.init_reg(0x7d, 0x00);
464     if (dev->model->model_id == ModelId::CANON_8400F) {
465         dev->reg.init_reg(0x7d, 0x20);
466     }
467 
468     // GPOLED[x]: LED vs GPIO settings
469     dev->reg.init_reg(0x7e, 0x00);
470 
471     // BSMPDLY, VSMPDLY
472     // LEDCNT[0:1]: Controls led blinking and its period
473     dev->reg.init_reg(0x7f, 0x00);
474 
475     // VRHOME, VRMOVE, VRBACK, VRSCAN: Vref settings of the motor driver IC for
476     // moving in various situations.
477     dev->reg.init_reg(0x80, 0x00); // MOTOR_PROFILE
478     if (dev->model->model_id == ModelId::CANON_4400F) {
479         dev->reg.init_reg(0x80, 0x0c);
480     }
481     if (dev->model->model_id == ModelId::CANON_8400F) {
482         dev->reg.init_reg(0x80, 0x28);
483     }
484     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
485         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
486         dev->model->model_id == ModelId::HP_SCANJET_4850C)
487     {
488         dev->reg.init_reg(0x80, 0x50);
489     }
490     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
491         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
492     {
493         dev->reg.init_reg(0x80, 0x0f);
494     }
495 
496     if (dev->model->model_id != ModelId::CANON_4400F) {
497         dev->reg.init_reg(0x81, 0x00);
498         dev->reg.init_reg(0x82, 0x00);
499         dev->reg.init_reg(0x83, 0x00);
500         dev->reg.init_reg(0x84, 0x00);
501         dev->reg.init_reg(0x85, 0x00);
502         dev->reg.init_reg(0x86, 0x00);
503     }
504 
505     dev->reg.init_reg(0x87, 0x00);
506     if (dev->model->model_id == ModelId::CANON_4400F ||
507         dev->model->model_id == ModelId::CANON_8400F ||
508         dev->model->model_id == ModelId::CANON_8600F)
509     {
510         dev->reg.init_reg(0x87, 0x02);
511     }
512 
513     // MTRPLS[0:7]: The width of the ADF motor trigger signal pulse.
514     if (dev->model->model_id != ModelId::CANON_8400F &&
515         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
516         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
517     {
518         dev->reg.init_reg(0x94, 0xff);
519     }
520 
521     // 0x95-0x97: SCANLEN[0:19]: Controls when paper jam bit is set in sheetfed
522     // scanners.
523 
524     // ONDUR[0:15]: The duration of PWM ON phase for LAMP control
525     // OFFDUR[0:15]: The duration of PWM OFF phase for LAMP control
526     // both of the above are in system clocks
527     if (dev->model->model_id == ModelId::CANON_8600F) {
528         dev->reg.init_reg(0x98, 0x00);
529         dev->reg.init_reg(0x99, 0x00);
530         dev->reg.init_reg(0x9a, 0x00);
531         dev->reg.init_reg(0x9b, 0x00);
532     }
533     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
534         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
535         dev->model->model_id == ModelId::HP_SCANJET_4850C)
536     {
537         // TODO: move to set for scan
538         dev->reg.init_reg(0x98, 0x03);
539         dev->reg.init_reg(0x99, 0x30);
540         dev->reg.init_reg(0x9a, 0x01);
541         dev->reg.init_reg(0x9b, 0x80);
542     }
543 
544     // RMADLY[0:1], MOTLAG, CMODE, STEPTIM, MULDMYLN, IFRS
545     dev->reg.init_reg(0x9d, 0x04);
546     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
547         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
548     {
549         dev->reg.init_reg(0x9d, 0x00);
550     }
551     if (dev->model->model_id == ModelId::CANON_4400F ||
552         dev->model->model_id == ModelId::CANON_8400F ||
553         dev->model->model_id == ModelId::CANON_8600F ||
554         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
555         dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
556         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
557         dev->model->model_id == ModelId::HP_SCANJET_4850C)
558     {
559         dev->reg.init_reg(0x9d, 0x08); // sets the multiplier for slope tables
560     }
561 
562 
563     // SEL3INV, TGSTIME[0:2], TGWTIME[0:2]
564     if (dev->model->model_id != ModelId::CANON_8400F &&
565         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
566         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
567     {
568       dev->reg.init_reg(0x9e, 0x00); // SENSOR_DEF
569     }
570 
571     if (dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300) {
572         dev->reg.init_reg(0xa2, 0x0f);
573     }
574 
575     // RFHSET[0:4]: Refresh time of SDRAM in units of 2us
576     if (dev->model->model_id == ModelId::CANON_4400F ||
577         dev->model->model_id == ModelId::CANON_8600F)
578     {
579         dev->reg.init_reg(0xa2, 0x1f);
580     }
581 
582     // 0xa6-0xa9: controls gpio, see gl843_gpio_init
583 
584     // not documented
585     if (dev->model->model_id != ModelId::CANON_4400F &&
586         dev->model->model_id != ModelId::CANON_8400F &&
587         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
588         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300)
589     {
590         dev->reg.init_reg(0xaa, 0x00);
591     }
592 
593     // GPOM9, MULSTOP[0-2], NODECEL, TB3TB1, TB5TB2, FIX16CLK.
594     if (dev->model->model_id != ModelId::CANON_8400F &&
595         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
596         dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300) {
597         dev->reg.init_reg(0xab, 0x50);
598     }
599     if (dev->model->model_id == ModelId::CANON_4400F) {
600         dev->reg.init_reg(0xab, 0x00);
601     }
602     if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
603         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
604         dev->model->model_id == ModelId::CANON_8600F ||
605         dev->model->model_id == ModelId::HP_SCANJET_4850C)
606     {
607         dev->reg.init_reg(0xab, 0x40);
608     }
609 
610     // VRHOME[3:2], VRMOVE[3:2], VRBACK[3:2]: Vref setting of the motor driver IC
611     // for various situations.
612     if (dev->model->model_id == ModelId::CANON_8600F ||
613         dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
614         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
615         dev->model->model_id == ModelId::HP_SCANJET_4850C)
616     {
617         dev->reg.init_reg(0xac, 0x00);
618     }
619 
620     if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I) {
621         uint8_t data[32] = {
622             0x8c, 0x8f, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00,
623             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625             0x6a, 0x73, 0x63, 0x68, 0x69, 0x65, 0x6e, 0x00,
626         };
627 
628         dev->interface->write_buffer(0x3c, 0x3ff000, data, 32);
629     }
630 }
631 
gl843_set_ad_fe(Genesys_Device * dev)632 static void gl843_set_ad_fe(Genesys_Device* dev)
633 {
634     for (const auto& reg : dev->frontend.regs) {
635         dev->interface->write_fe_register(reg.address, reg.value);
636     }
637 }
638 
639 // Set values of analog frontend
set_fe(Genesys_Device * dev,const Genesys_Sensor & sensor,uint8_t set) const640 void CommandSetGl843::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
641 {
642     DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
643                                set == AFE_SET ? "set" :
644                                set == AFE_POWER_SAVE ? "powersave" : "huh?");
645     (void) sensor;
646 
647     if (set == AFE_INIT) {
648         dev->frontend = dev->frontend_initial;
649     }
650 
651     // check analog frontend type
652     // FIXME: looks like we write to that register with initial data
653     uint8_t fe_type = dev->interface->read_register(REG_0x04) & REG_0x04_FESET;
654     if (fe_type == 2) {
655         gl843_set_ad_fe(dev);
656         return;
657     }
658     if (fe_type != 0) {
659         throw SaneException(SANE_STATUS_UNSUPPORTED, "unsupported frontend type %d", fe_type);
660     }
661 
662     for (unsigned i = 1; i <= 3; i++) {
663         dev->interface->write_fe_register(i, dev->frontend.regs.get_value(0x00 + i));
664     }
665     for (const auto& reg : sensor.custom_fe_regs) {
666         dev->interface->write_fe_register(reg.address, reg.value);
667     }
668 
669     for (unsigned i = 0; i < 3; i++) {
670         dev->interface->write_fe_register(0x20 + i, dev->frontend.get_offset(i));
671     }
672 
673     if (dev->model->sensor_id == SensorId::CCD_KVSS080) {
674         for (unsigned i = 0; i < 3; i++) {
675             dev->interface->write_fe_register(0x24 + i, dev->frontend.regs.get_value(0x24 + i));
676         }
677     }
678 
679     for (unsigned i = 0; i < 3; i++) {
680         dev->interface->write_fe_register(0x28 + i, dev->frontend.get_gain(i));
681     }
682 }
683 
gl843_init_motor_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,const ScanSession & session,Genesys_Register_Set * reg,const MotorProfile & motor_profile,unsigned int exposure,unsigned scan_yres,unsigned int scan_lines,unsigned int scan_dummy,unsigned int feed_steps,ScanFlag flags)684 static void gl843_init_motor_regs_scan(Genesys_Device* dev,
685                                        const Genesys_Sensor& sensor,
686                                        const ScanSession& session,
687                                        Genesys_Register_Set* reg,
688                                        const MotorProfile& motor_profile,
689                                        unsigned int exposure,
690                                        unsigned scan_yres,
691                                        unsigned int scan_lines,
692                                        unsigned int scan_dummy,
693                                        unsigned int feed_steps,
694                                        ScanFlag flags)
695 {
696     DBG_HELPER_ARGS(dbg, "exposure=%d, scan_yres=%d, step_type=%d, scan_lines=%d, scan_dummy=%d, "
697                          "feed_steps=%d, flags=%x",
698                     exposure, scan_yres, static_cast<unsigned>(motor_profile.step_type),
699                     scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
700 
701     unsigned feedl, dist;
702 
703   /* get step multiplier */
704     unsigned step_multiplier = gl843_get_step_multiplier (reg);
705 
706     bool use_fast_fed = false;
707 
708     if ((scan_yres >= 300 && feed_steps > 900) || (has_flag(flags, ScanFlag::FEEDING))) {
709         use_fast_fed = true;
710     }
711     if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) {
712         use_fast_fed = false;
713     }
714 
715     reg->set24(REG_LINCNT, scan_lines);
716 
717     reg->set8(REG_0x02, 0);
718     sanei_genesys_set_motor_power(*reg, true);
719 
720     std::uint8_t reg02 = reg->get8(REG_0x02);
721     if (use_fast_fed) {
722         reg02 |= REG_0x02_FASTFED;
723     } else {
724         reg02 &= ~REG_0x02_FASTFED;
725     }
726 
727     // in case of automatic go home, move until home sensor
728     if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
729         reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
730     }
731 
732   /* disable backtracking */
733     if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) ||
734         (scan_yres>=2400 && dev->model->model_id != ModelId::CANON_4400F) ||
735         (scan_yres>=sensor.full_resolution))
736     {
737         reg02 |= REG_0x02_ACDCDIS;
738     }
739 
740     if (has_flag(flags, ScanFlag::REVERSE)) {
741         reg02 |= REG_0x02_MTRREV;
742     } else {
743         reg02 &= ~REG_0x02_MTRREV;
744     }
745     reg->set8(REG_0x02, reg02);
746 
747     // scan and backtracking slope table
748     auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres, exposure,
749                                          step_multiplier, motor_profile);
750 
751     scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
752     scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
753     scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table);
754 
755     reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
756     reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
757     reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
758 
759     // fast table
760     const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
761     if (fast_profile == nullptr) {
762         fast_profile = &motor_profile;
763     }
764 
765     auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
766                                                  *fast_profile);
767 
768     scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
769     scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
770 
771     reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
772 
773     if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) {
774         std::uint8_t vref = 0;
775         vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL;
776         vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK;
777         vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST;
778         vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME;
779         reg->set8(REG_0x80, vref);
780     }
781 
782   /* subtract acceleration distance from feedl */
783   feedl=feed_steps;
784     feedl <<= static_cast<unsigned>(motor_profile.step_type);
785 
786     dist = scan_table.table.size() / step_multiplier;
787 
788     if (use_fast_fed) {
789         dist += (fast_table.table.size() / step_multiplier) * 2;
790     }
791 
792   /* get sure when don't insane value : XXX STEF XXX in this case we should
793    * fall back to single table move */
794     if (dist < feedl) {
795         feedl -= dist;
796     } else {
797         feedl = 1;
798     }
799 
800     reg->set24(REG_FEEDL, feedl);
801 
802     // doesn't seem to matter that much
803     std::uint32_t z1, z2;
804     sanei_genesys_calculate_zmod(use_fast_fed,
805                                  exposure,
806                                  scan_table.table,
807                                  scan_table.table.size() / step_multiplier,
808                                  feedl,
809                                  scan_table.table.size() / step_multiplier,
810                                   &z1,
811                                   &z2);
812   if(scan_yres>600)
813     {
814       z1=0;
815       z2=0;
816     }
817 
818     reg->set24(REG_Z1MOD, z1);
819     reg->set24(REG_Z2MOD, z2);
820 
821     reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
822 
823     reg->set8_mask(REG_0x67, static_cast<unsigned>(motor_profile.step_type) << REG_0x67S_STEPSEL, 0xc0);
824     reg->set8_mask(REG_0x68, static_cast<unsigned>(fast_profile->step_type) << REG_0x68S_FSTPSEL, 0xc0);
825 
826     // steps for STOP table
827     reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
828 
829     if (dev->model->model_id == ModelId::PANASONIC_KV_SS080 ||
830         dev->model->model_id == ModelId::HP_SCANJET_4850C ||
831         dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
832         dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
833         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
834         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
835         dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
836     {
837         // FIXME: take this information from motor struct
838         std::uint8_t reg_vref = reg->get8(0x80);
839         reg_vref = 0x50;
840         unsigned coeff = sensor.full_resolution / scan_yres;
841         if (dev->model->motor_id == MotorId::KVSS080) {
842             if (coeff >= 1) {
843                 reg_vref |= 0x05;
844             }
845         } else {
846             switch (coeff) {
847                 case 4:
848                     reg_vref |= 0x0a;
849                     break;
850                 case 2:
851                     reg_vref |= 0x0f;
852                     break;
853                 case 1:
854                     reg_vref |= 0x0f;
855                     break;
856             }
857         }
858         reg->set8(REG_0x80, reg_vref);
859     }
860 }
861 
862 
863 /** @brief setup optical related registers
864  * start and pixels are expressed in optical sensor resolution coordinate
865  * space.
866  * @param dev device to use
867  * @param reg registers to set up
868  * @param exposure exposure time to use
869  * @param used_res scanning resolution used, may differ from
870  *        scan's one
871  * @param start logical start pixel coordinate
872  * @param pixels logical number of pixels to use
873  * @param channels number of color channels used (1 or 3)
874  * @param depth bit depth of the scan (1, 8 or 16 bits)
875  * @param color_filter to choose the color channel used in gray scans
876  * @param flags to drive specific settings such no calibration, XPA use ...
877  */
gl843_init_optical_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,unsigned int exposure,const ScanSession & session)878 static void gl843_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
879                                          Genesys_Register_Set* reg, unsigned int exposure,
880                                          const ScanSession& session)
881 {
882     DBG_HELPER_ARGS(dbg, "exposure=%d", exposure);
883   unsigned int tgtime;          /**> exposure time multiplier */
884 
885   /* tgtime */
886   tgtime = exposure / 65536 + 1;
887   DBG(DBG_io2, "%s: tgtime=%d\n", __func__, tgtime);
888 
889     // sensor parameters
890     scanner_setup_sensor(*dev, sensor, *reg);
891 
892     dev->cmd_set->set_fe(dev, sensor, AFE_SET);
893 
894   /* enable shading */
895     regs_set_optical_off(dev->model->asic_type, *reg);
896     if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
897         has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
898         session.use_host_side_calib)
899     {
900         reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
901 
902     } else {
903         reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
904     }
905 
906     bool use_shdarea = false;
907     if (dev->model->model_id == ModelId::CANON_4400F) {
908         use_shdarea = session.params.xres <= 600;
909     } else if (dev->model->model_id == ModelId::CANON_8400F) {
910         use_shdarea = session.params.xres <= 400;
911     } else if (dev->model->model_id == ModelId::CANON_8600F ||
912                dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
913                dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
914                dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
915     {
916         use_shdarea = true;
917     } else {
918         use_shdarea = session.params.xres > 600;
919     }
920 
921     if (use_shdarea) {
922         reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
923     } else {
924         reg->find_reg(REG_0x01).value &= ~REG_0x01_SHDAREA;
925     }
926 
927     if (dev->model->model_id == ModelId::CANON_8600F) {
928         reg->find_reg(REG_0x03).value |= REG_0x03_AVEENB;
929     } else {
930         reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
931   }
932 
933     // FIXME: we probably don't need to set exposure to registers at this point. It was this way
934     // before a refactor.
935     sanei_genesys_set_lamp_power(dev, sensor, *reg,
936                                  !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
937 
938   /* select XPA */
939     reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL;
940     if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
941         reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL;
942     }
943     reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
944 
945     // BW threshold
946     reg->set8(REG_0x2E, 0x7f);
947     reg->set8(REG_0x2F, 0x7f);
948 
949   /* monochrome / color scan */
950     switch (session.params.depth) {
951     case 8:
952             reg->find_reg(REG_0x04).value &= ~(REG_0x04_LINEART | REG_0x04_BITSET);
953       break;
954     case 16:
955             reg->find_reg(REG_0x04).value &= ~REG_0x04_LINEART;
956             reg->find_reg(REG_0x04).value |= REG_0x04_BITSET;
957       break;
958     }
959 
960     reg->find_reg(REG_0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
961   if (session.params.channels == 1)
962     {
963       switch (session.params.color_filter)
964 	{
965             case ColorFilter::RED:
966                 reg->find_reg(REG_0x04).value |= 0x14;
967                 break;
968             case ColorFilter::BLUE:
969                 reg->find_reg(REG_0x04).value |= 0x1c;
970                 break;
971             case ColorFilter::GREEN:
972                 reg->find_reg(REG_0x04).value |= 0x18;
973                 break;
974             default:
975                 break; // should not happen
976 	}
977     } else {
978         switch (dev->frontend.layout.type) {
979             case FrontendType::WOLFSON:
980                 reg->find_reg(REG_0x04).value |= 0x10; // pixel by pixel
981                 break;
982             case FrontendType::ANALOG_DEVICES:
983                 reg->find_reg(REG_0x04).value |= 0x20; // slow color pixel by pixel
984                 break;
985             default:
986                 throw SaneException("Invalid frontend type %d",
987                                     static_cast<unsigned>(dev->frontend.layout.type));
988         }
989     }
990 
991     const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution,
992                                                          session.params.channels,
993                                                          session.params.scan_method);
994     sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw);
995 
996     if (should_enable_gamma(session, sensor)) {
997         reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB;
998     } else {
999         reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
1000     }
1001 
1002     reg->set16(REG_DPISET, sensor.register_dpiset);
1003 
1004     reg->set16(REG_STRPIXEL, session.pixel_startx);
1005     reg->set16(REG_ENDPIXEL, session.pixel_endx);
1006 
1007   /* MAXWD is expressed in 2 words unit */
1008   /* nousedspace = (mem_bank_range * 1024 / 256 -1 ) * 4; */
1009     // BUG: the division by optical and full resolution factor likely does not make sense
1010     reg->set24(REG_MAXWD, (session.output_line_bytes *
1011                            session.optical_resolution / session.full_resolution) >> 1);
1012     reg->set16(REG_LPERIOD, exposure / tgtime);
1013     reg->set8(REG_DUMMY, sensor.dummy_pixel);
1014 }
1015 
init_regs_for_scan_session(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,const ScanSession & session) const1016 void CommandSetGl843::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
1017                                                  Genesys_Register_Set* reg,
1018                                                  const ScanSession& session) const
1019 {
1020     DBG_HELPER(dbg);
1021     session.assert_computed();
1022 
1023   int exposure;
1024 
1025   int slope_dpi = 0;
1026   int dummy = 0;
1027 
1028   /* we enable true gray for cis scanners only, and just when doing
1029    * scan since color calibration is OK for this mode
1030    */
1031 
1032   dummy = 0;
1033     if (dev->model->model_id == ModelId::CANON_4400F && session.params.yres == 1200) {
1034         dummy = 1;
1035     }
1036 
1037   /* slope_dpi */
1038   /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */
1039   if (dev->model->is_cis)
1040     slope_dpi = session.params.yres * session.params.channels;
1041   else
1042     slope_dpi = session.params.yres;
1043   slope_dpi = slope_dpi * (1 + dummy);
1044 
1045   /* scan_step_type */
1046   exposure = sensor.exposure_lperiod;
1047   if (exposure < 0) {
1048       throw std::runtime_error("Exposure not defined in sensor definition");
1049   }
1050     const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure, session);
1051 
1052     // now _LOGICAL_ optical values used are known, setup registers
1053     gl843_init_optical_regs_scan(dev, sensor, reg, exposure, session);
1054     gl843_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure, slope_dpi,
1055                                session.optical_line_count, dummy, session.params.starty,
1056                                session.params.flags);
1057 
1058     setup_image_pipeline(*dev, session);
1059 
1060     dev->read_active = true;
1061 
1062     dev->session = session;
1063 
1064   dev->total_bytes_read = 0;
1065     dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines;
1066 
1067     DBG(DBG_info, "%s: total bytes to send = %zu\n", __func__, dev->total_bytes_to_read);
1068 }
1069 
calculate_scan_session(const Genesys_Device * dev,const Genesys_Sensor & sensor,const Genesys_Settings & settings) const1070 ScanSession CommandSetGl843::calculate_scan_session(const Genesys_Device* dev,
1071                                                     const Genesys_Sensor& sensor,
1072                                                     const Genesys_Settings& settings) const
1073 {
1074     DBG_HELPER(dbg);
1075     debug_dump(DBG_info, settings);
1076 
1077     ScanFlag flags = ScanFlag::NONE;
1078 
1079     float move = 0.0f;
1080     if (settings.scan_method == ScanMethod::TRANSPARENCY ||
1081         settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1082     {
1083         // note: scanner_move_to_ta() function has already been called and the sensor is at the
1084         // transparency adapter
1085         if (!dev->ignore_offsets) {
1086             move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
1087         }
1088         flags |= ScanFlag::USE_XPA;
1089     } else {
1090         if (!dev->ignore_offsets) {
1091             move = dev->model->y_offset;
1092         }
1093     }
1094 
1095     move += settings.tl_y;
1096 
1097     int move_dpi = dev->motor.base_ydpi;
1098     move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
1099 
1100     float start = 0.0f;
1101     if (settings.scan_method==ScanMethod::TRANSPARENCY ||
1102         settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1103     {
1104         start = dev->model->x_offset_ta;
1105     } else {
1106         start = dev->model->x_offset;
1107     }
1108     start = start + settings.tl_x;
1109 
1110     start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
1111 
1112     ScanSession session;
1113     session.params.xres = settings.xres;
1114     session.params.yres = settings.yres;
1115     session.params.startx = static_cast<unsigned>(start);
1116     session.params.starty = static_cast<unsigned>(move);
1117     session.params.pixels = settings.pixels;
1118     session.params.requested_pixels = settings.requested_pixels;
1119     session.params.lines = settings.lines;
1120     session.params.depth = settings.depth;
1121     session.params.channels = settings.get_channels();
1122     session.params.scan_method = settings.scan_method;
1123     session.params.scan_mode = settings.scan_mode;
1124     session.params.color_filter = settings.color_filter;
1125     session.params.flags = flags;
1126     compute_session(dev, session, sensor);
1127 
1128     return session;
1129 }
1130 
1131 /**
1132  * for fast power saving methods only, like disabling certain amplifiers
1133  * @param dev device to use
1134  * @param enable true to set inot powersaving
1135  * */
save_power(Genesys_Device * dev,bool enable) const1136 void CommandSetGl843::save_power(Genesys_Device* dev, bool enable) const
1137 {
1138     DBG_HELPER_ARGS(dbg, "enable = %d", enable);
1139 
1140     // switch KV-SS080 lamp off
1141     if (dev->model->gpio_id == GpioId::KVSS080) {
1142         uint8_t val = dev->interface->read_register(REG_0x6C);
1143         if (enable) {
1144             val &= 0xef;
1145         } else {
1146             val |= 0x10;
1147         }
1148         dev->interface->write_register(REG_0x6C, val);
1149     }
1150 }
1151 
set_powersaving(Genesys_Device * dev,int delay) const1152 void CommandSetGl843::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const
1153 {
1154     (void) dev;
1155     DBG_HELPER_ARGS(dbg, "delay = %d", delay);
1156 }
1157 
gl843_get_paper_sensor(Genesys_Device * dev)1158 static bool gl843_get_paper_sensor(Genesys_Device* dev)
1159 {
1160     DBG_HELPER(dbg);
1161 
1162     uint8_t val = dev->interface->read_register(REG_0x6D);
1163 
1164     return (val & 0x1) == 0;
1165 }
1166 
eject_document(Genesys_Device * dev) const1167 void CommandSetGl843::eject_document(Genesys_Device* dev) const
1168 {
1169     (void) dev;
1170     DBG_HELPER(dbg);
1171 }
1172 
1173 
load_document(Genesys_Device * dev) const1174 void CommandSetGl843::load_document(Genesys_Device* dev) const
1175 {
1176     DBG_HELPER(dbg);
1177     (void) dev;
1178 }
1179 
1180 /**
1181  * detects end of document and adjust current scan
1182  * to take it into account
1183  * used by sheetfed scanners
1184  */
detect_document_end(Genesys_Device * dev) const1185 void CommandSetGl843::detect_document_end(Genesys_Device* dev) const
1186 {
1187     DBG_HELPER(dbg);
1188     bool paper_loaded = gl843_get_paper_sensor(dev);
1189 
1190   /* sheetfed scanner uses home sensor as paper present */
1191     if (dev->document && !paper_loaded) {
1192       DBG(DBG_info, "%s: no more document\n", __func__);
1193         dev->document = false;
1194 
1195         unsigned scanned_lines = 0;
1196         catch_all_exceptions(__func__, [&](){ sanei_genesys_read_scancnt(dev, &scanned_lines); });
1197 
1198         std::size_t output_lines = dev->session.output_line_count;
1199 
1200         std::size_t offset_lines = static_cast<std::size_t>(
1201                 (dev->model->post_scan * dev->session.params.yres) / MM_PER_INCH);
1202 
1203         std::size_t scan_end_lines = scanned_lines + offset_lines;
1204 
1205         std::size_t remaining_lines = dev->get_pipeline_source().remaining_bytes() /
1206                 dev->session.output_line_bytes_raw;
1207 
1208         DBG(DBG_io, "%s: scanned_lines=%u\n", __func__, scanned_lines);
1209         DBG(DBG_io, "%s: scan_end_lines=%zu\n", __func__, scan_end_lines);
1210         DBG(DBG_io, "%s: output_lines=%zu\n", __func__, output_lines);
1211         DBG(DBG_io, "%s: remaining_lines=%zu\n", __func__, remaining_lines);
1212 
1213         if (scan_end_lines > output_lines) {
1214             auto skip_lines = scan_end_lines - output_lines;
1215 
1216             if (remaining_lines > skip_lines) {
1217                 remaining_lines -= skip_lines;
1218                 dev->get_pipeline_source().set_remaining_bytes(remaining_lines *
1219                                                                dev->session.output_line_bytes_raw);
1220                 dev->total_bytes_to_read -= skip_lines * dev->session.output_line_bytes_requested;
1221             }
1222         }
1223     }
1224 }
1225 
1226 // Send the low-level scan command
begin_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,bool start_motor) const1227 void CommandSetGl843::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
1228                                  Genesys_Register_Set* reg, bool start_motor) const
1229 {
1230     DBG_HELPER(dbg);
1231     (void) sensor;
1232 
1233   /* set up GPIO for scan */
1234     switch(dev->model->gpio_id) {
1235       /* KV case */
1236         case GpioId::KVSS080:
1237             dev->interface->write_register(REG_0xA9, 0x00);
1238             dev->interface->write_register(REG_0xA6, 0xf6);
1239             // blinking led
1240             dev->interface->write_register(0x7e, 0x04);
1241             break;
1242         case GpioId::G4050:
1243             dev->interface->write_register(REG_0xA7, 0xfe);
1244             dev->interface->write_register(REG_0xA8, 0x3e);
1245             dev->interface->write_register(REG_0xA9, 0x06);
1246             if ((reg->get8(0x05) & REG_0x05_DPIHW) == REG_0x05_DPIHW_600) {
1247                 dev->interface->write_register(REG_0x6C, 0x20);
1248                 dev->interface->write_register(REG_0xA6, 0x44);
1249             } else {
1250                 dev->interface->write_register(REG_0x6C, 0x60);
1251                 dev->interface->write_register(REG_0xA6, 0x46);
1252             }
1253 
1254             if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1255                 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1256             }
1257 
1258             if (reg->state.is_xpa_on) {
1259                 dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
1260             }
1261 
1262             // blinking led
1263             dev->interface->write_register(REG_0x7E, 0x01);
1264             break;
1265         case GpioId::CANON_8400F:
1266             if (dev->session.params.xres == 3200)
1267             {
1268                 GenesysRegisterSettingSet reg_settings = {
1269                     { 0x6c, 0x00, 0x02 },
1270                 };
1271                 apply_reg_settings_to_device(*dev, reg_settings);
1272             }
1273             if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1274                 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1275             }
1276             if (reg->state.is_xpa_on) {
1277                 dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
1278             }
1279             break;
1280         case GpioId::CANON_8600F:
1281             if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1282                 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1283             }
1284             if (reg->state.is_xpa_on) {
1285                 dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
1286             }
1287             break;
1288         case GpioId::PLUSTEK_OPTICFILM_7200I:
1289         case GpioId::PLUSTEK_OPTICFILM_7300:
1290         case GpioId::PLUSTEK_OPTICFILM_7500I: {
1291             if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
1292                 dev->cmd_set->set_xpa_lamp_power(*dev, true);
1293             }
1294             break;
1295         }
1296         case GpioId::CANON_4400F:
1297         default:
1298             break;
1299     }
1300 
1301     scanner_clear_scan_and_feed_counts(*dev);
1302 
1303     // enable scan and motor
1304     uint8_t val = dev->interface->read_register(REG_0x01);
1305     val |= REG_0x01_SCAN;
1306     dev->interface->write_register(REG_0x01, val);
1307 
1308     scanner_start_action(*dev, start_motor);
1309 
1310     switch (reg->state.motor_mode) {
1311         case MotorMode::PRIMARY: {
1312             if (reg->state.is_motor_on) {
1313                 dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
1314             }
1315             break;
1316         }
1317         case MotorMode::PRIMARY_AND_SECONDARY: {
1318             if (reg->state.is_motor_on) {
1319                 dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
1320                 dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
1321             }
1322             break;
1323         }
1324         case MotorMode::SECONDARY: {
1325             if (reg->state.is_motor_on) {
1326                 dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
1327             }
1328             break;
1329         }
1330     }
1331 }
1332 
1333 
1334 // Send the stop scan command
end_scan(Genesys_Device * dev,Genesys_Register_Set * reg,bool check_stop) const1335 void CommandSetGl843::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
1336                                bool check_stop) const
1337 {
1338     DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
1339 
1340     // post scan gpio
1341     dev->interface->write_register(0x7e, 0x00);
1342 
1343     if (reg->state.is_xpa_on) {
1344         dev->cmd_set->set_xpa_lamp_power(*dev, false);
1345     }
1346 
1347     if (!dev->model->is_sheetfed) {
1348         scanner_stop_action(*dev);
1349     }
1350 }
1351 
1352 /** @brief Moves the slider to the home (top) position slowly
1353  * */
move_back_home(Genesys_Device * dev,bool wait_until_home) const1354 void CommandSetGl843::move_back_home(Genesys_Device* dev, bool wait_until_home) const
1355 {
1356     scanner_move_back_home(*dev, wait_until_home);
1357 }
1358 
1359 // 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) const1360 void CommandSetGl843::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
1361                                             Genesys_Register_Set& regs) const
1362 {
1363     DBG_HELPER(dbg);
1364     int move;
1365 
1366     float calib_size_mm = 0;
1367     if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
1368         dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1369     {
1370         calib_size_mm = dev->model->y_size_calib_ta_mm;
1371     } else {
1372         calib_size_mm = dev->model->y_size_calib_mm;
1373     }
1374 
1375     unsigned resolution = sensor.shading_resolution;
1376 
1377     unsigned channels = 3;
1378   const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
1379                                                        dev->settings.scan_method);
1380 
1381     unsigned calib_pixels = 0;
1382     unsigned calib_pixels_offset = 0;
1383 
1384     if (should_calibrate_only_active_area(*dev, dev->settings)) {
1385         float offset = dev->model->x_offset_ta;
1386         // FIXME: we should use resolution here
1387         offset = static_cast<float>((offset * dev->settings.xres) / MM_PER_INCH);
1388 
1389         float size = dev->model->x_size_ta;
1390         size = static_cast<float>((size * dev->settings.xres) / MM_PER_INCH);
1391 
1392         calib_pixels_offset = static_cast<std::size_t>(offset);
1393         calib_pixels = static_cast<std::size_t>(size);
1394     } else {
1395         calib_pixels_offset = 0;
1396         calib_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
1397     }
1398 
1399     ScanFlag flags = ScanFlag::DISABLE_SHADING |
1400                      ScanFlag::DISABLE_GAMMA |
1401                      ScanFlag::DISABLE_BUFFER_FULL_MOVE;
1402 
1403     if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
1404         dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1405     {
1406         // note: scanner_move_to_ta() function has already been called and the sensor is at the
1407         // transparency adapter
1408         move = static_cast<int>(dev->model->y_offset_calib_white_ta - dev->model->y_offset_sensor_to_ta);
1409         if (dev->model->model_id == ModelId::CANON_8600F && resolution == 2400) {
1410             move /= 2;
1411         }
1412         if (dev->model->model_id == ModelId::CANON_8600F && resolution == 4800) {
1413             move /= 4;
1414         }
1415         flags |= ScanFlag::USE_XPA;
1416     } else {
1417         move = static_cast<int>(dev->model->y_offset_calib_white);
1418     }
1419 
1420     move = static_cast<int>((move * resolution) / MM_PER_INCH);
1421     unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
1422 
1423     ScanSession session;
1424     session.params.xres = resolution;
1425     session.params.yres = resolution;
1426     session.params.startx = calib_pixels_offset;
1427     session.params.starty = move;
1428     session.params.pixels = calib_pixels;
1429     session.params.lines = calib_lines;
1430     session.params.depth = 16;
1431     session.params.channels = channels;
1432     session.params.scan_method = dev->settings.scan_method;
1433     session.params.scan_mode = dev->settings.scan_mode;
1434     session.params.color_filter = dev->settings.color_filter;
1435     session.params.flags = flags;
1436     compute_session(dev, session, calib_sensor);
1437 
1438     init_regs_for_scan_session(dev, calib_sensor, &regs, session);
1439 
1440     dev->calib_session = session;
1441 }
1442 
1443 /**
1444  * This function sends gamma tables to ASIC
1445  */
send_gamma_table(Genesys_Device * dev,const Genesys_Sensor & sensor) const1446 void CommandSetGl843::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
1447 {
1448     DBG_HELPER(dbg);
1449   int size;
1450   int i;
1451 
1452   size = 256;
1453 
1454   /* allocate temporary gamma tables: 16 bits words, 3 channels */
1455   std::vector<uint8_t> gamma(size * 2 * 3);
1456 
1457     std::vector<uint16_t> rgamma = get_gamma_table(dev, sensor, GENESYS_RED);
1458     std::vector<uint16_t> ggamma = get_gamma_table(dev, sensor, GENESYS_GREEN);
1459     std::vector<uint16_t> bgamma = get_gamma_table(dev, sensor, GENESYS_BLUE);
1460 
1461     // copy sensor specific's gamma tables
1462     for (i = 0; i < size; i++) {
1463         gamma[i * 2 + size * 0 + 0] = rgamma[i] & 0xff;
1464         gamma[i * 2 + size * 0 + 1] = (rgamma[i] >> 8) & 0xff;
1465         gamma[i * 2 + size * 2 + 0] = ggamma[i] & 0xff;
1466         gamma[i * 2 + size * 2 + 1] = (ggamma[i] >> 8) & 0xff;
1467         gamma[i * 2 + size * 4 + 0] = bgamma[i] & 0xff;
1468         gamma[i * 2 + size * 4 + 1] = (bgamma[i] >> 8) & 0xff;
1469     }
1470 
1471     dev->interface->write_gamma(0x28, 0x0000, gamma.data(), size * 2 * 3);
1472 }
1473 
1474 /* this function does the led calibration by scanning one line of the calibration
1475    area below scanner's top on white strip.
1476 
1477 -needs working coarse/gain
1478 */
led_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1479 SensorExposure CommandSetGl843::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1480                                                 Genesys_Register_Set& regs) const
1481 {
1482     return scanner_led_calibration(*dev, sensor, regs);
1483 }
1484 
offset_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1485 void CommandSetGl843::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1486                                          Genesys_Register_Set& regs) const
1487 {
1488     scanner_offset_calibration(*dev, sensor, regs);
1489 }
1490 
coarse_gain_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs,int dpi) const1491 void CommandSetGl843::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1492                                               Genesys_Register_Set& regs, int dpi) const
1493 {
1494     scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
1495 }
1496 
1497 // wait for lamp warmup by scanning the same line until difference
1498 // between 2 scans is below a threshold
init_regs_for_warmup(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg) const1499 void CommandSetGl843::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
1500                                            Genesys_Register_Set* reg) const
1501 {
1502     DBG_HELPER(dbg);
1503     (void) sensor;
1504 
1505     unsigned channels = 3;
1506     unsigned resolution = dev->model->get_resolution_settings(dev->settings.scan_method)
1507                                      .get_nearest_resolution_x(600);
1508 
1509   const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
1510                                                        dev->settings.scan_method);
1511     unsigned num_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH / 2;
1512 
1513   *reg = dev->reg;
1514 
1515     auto flags = ScanFlag::DISABLE_SHADING |
1516                  ScanFlag::DISABLE_GAMMA |
1517                  ScanFlag::SINGLE_LINE |
1518                  ScanFlag::IGNORE_STAGGER_OFFSET |
1519                  ScanFlag::IGNORE_COLOR_OFFSET;
1520     if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
1521         dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
1522     {
1523         flags |= ScanFlag::USE_XPA;
1524     }
1525 
1526     ScanSession session;
1527     session.params.xres = resolution;
1528     session.params.yres = resolution;
1529     session.params.startx = (num_pixels / 2) * resolution / calib_sensor.full_resolution;
1530     session.params.starty = 0;
1531     session.params.pixels = num_pixels;
1532     session.params.lines = 1;
1533     session.params.depth = dev->model->bpp_color_values.front();
1534     session.params.channels = channels;
1535     session.params.scan_method = dev->settings.scan_method;
1536     session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
1537     session.params.color_filter = dev->settings.color_filter;
1538     session.params.flags = flags;
1539 
1540     compute_session(dev, session, calib_sensor);
1541 
1542     init_regs_for_scan_session(dev, calib_sensor, reg, session);
1543 
1544   sanei_genesys_set_motor_power(*reg, false);
1545 }
1546 
1547 /**
1548  * set up GPIO/GPOE for idle state
1549 WRITE GPIO[17-21]= GPIO19
1550 WRITE GPOE[17-21]= GPOE21 GPOE20 GPOE19 GPOE18
1551 genesys_write_register(0xa8,0x3e)
1552 GPIO(0xa8)=0x3e
1553  */
gl843_init_gpio(Genesys_Device * dev)1554 static void gl843_init_gpio(Genesys_Device* dev)
1555 {
1556     DBG_HELPER(dbg);
1557     apply_registers_ordered(dev->gpo.regs, { 0x6e, 0x6f }, [&](const GenesysRegisterSetting& reg)
1558     {
1559         dev->interface->write_register(reg.address, reg.value);
1560     });
1561 }
1562 
1563 
1564 /* *
1565  * initialize ASIC from power on condition
1566  */
asic_boot(Genesys_Device * dev,bool cold) const1567 void CommandSetGl843::asic_boot(Genesys_Device* dev, bool cold) const
1568 {
1569     DBG_HELPER(dbg);
1570   uint8_t val;
1571 
1572     if (cold) {
1573         dev->interface->write_register(0x0e, 0x01);
1574         dev->interface->write_register(0x0e, 0x00);
1575     }
1576 
1577   if(dev->usb_mode == 1)
1578     {
1579       val = 0x14;
1580     }
1581   else
1582     {
1583       val = 0x11;
1584     }
1585     dev->interface->write_0x8c(0x0f, val);
1586 
1587     // test CHKVER
1588     val = dev->interface->read_register(REG_0x40);
1589     if (val & REG_0x40_CHKVER) {
1590         val = dev->interface->read_register(0x00);
1591         DBG(DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val);
1592     }
1593 
1594   /* Set default values for registers */
1595   gl843_init_registers (dev);
1596 
1597     if (dev->model->model_id == ModelId::CANON_8600F) {
1598         // turns on vref control for maximum current of the motor driver
1599         dev->interface->write_register(REG_0x6B, 0x72);
1600     } else {
1601         dev->interface->write_register(REG_0x6B, 0x02);
1602     }
1603 
1604     // Write initial registers
1605     dev->interface->write_registers(dev->reg);
1606 
1607   // Enable DRAM by setting a rising edge on bit 3 of reg 0x0b
1608     val = dev->reg.find_reg(0x0b).value & REG_0x0B_DRAMSEL;
1609     val = (val | REG_0x0B_ENBDRAM);
1610     dev->interface->write_register(REG_0x0B, val);
1611     dev->reg.find_reg(0x0b).value = val;
1612 
1613     if (dev->model->model_id == ModelId::CANON_8400F) {
1614         dev->interface->write_0x8c(0x1e, 0x01);
1615         dev->interface->write_0x8c(0x10, 0xb4);
1616         dev->interface->write_0x8c(0x0f, 0x02);
1617     }
1618     else if (dev->model->model_id == ModelId::CANON_8600F) {
1619         dev->interface->write_0x8c(0x10, 0xc8);
1620     } else if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
1621                dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
1622     {
1623         dev->interface->write_0x8c(0x10, 0xd4);
1624     } else {
1625         dev->interface->write_0x8c(0x10, 0xb4);
1626     }
1627 
1628   /* CLKSET */
1629     int clock_freq = REG_0x0B_48MHZ;
1630     switch (dev->model->model_id) {
1631         case ModelId::CANON_8600F:
1632             clock_freq = REG_0x0B_60MHZ;
1633             break;
1634         case ModelId::PLUSTEK_OPTICFILM_7200I:
1635             clock_freq = REG_0x0B_30MHZ;
1636             break;
1637         case ModelId::PLUSTEK_OPTICFILM_7300:
1638         case ModelId::PLUSTEK_OPTICFILM_7500I:
1639             clock_freq = REG_0x0B_40MHZ;
1640             break;
1641         default:
1642             break;
1643     }
1644 
1645     val = (dev->reg.find_reg(0x0b).value & ~REG_0x0B_CLKSET) | clock_freq;
1646 
1647     dev->interface->write_register(REG_0x0B, val);
1648     dev->reg.find_reg(0x0b).value = val;
1649 
1650   /* prevent further writings by bulk write register */
1651   dev->reg.remove_reg(0x0b);
1652 
1653     // set RAM read address
1654     dev->interface->write_register(REG_0x29, 0x00);
1655     dev->interface->write_register(REG_0x2A, 0x00);
1656     dev->interface->write_register(REG_0x2B, 0x00);
1657 
1658     // setup gpio
1659     gl843_init_gpio(dev);
1660     dev->interface->sleep_ms(100);
1661 }
1662 
1663 /* *
1664  * initialize backend and ASIC : registers, motor tables, and gamma tables
1665  * then ensure scanner's head is at home
1666  */
init(Genesys_Device * dev) const1667 void CommandSetGl843::init(Genesys_Device* dev) const
1668 {
1669   DBG_INIT ();
1670     DBG_HELPER(dbg);
1671 
1672     sanei_genesys_asic_init(dev);
1673 }
1674 
update_hardware_sensors(Genesys_Scanner * s) const1675 void CommandSetGl843::update_hardware_sensors(Genesys_Scanner* s) const
1676 {
1677     DBG_HELPER(dbg);
1678   /* do what is needed to get a new set of events, but try to not lose
1679      any of them.
1680    */
1681 
1682     uint8_t val = s->dev->interface->read_register(REG_0x6D);
1683 
1684   switch (s->dev->model->gpio_id)
1685     {
1686         case GpioId::KVSS080:
1687             s->buttons[BUTTON_SCAN_SW].write((val & 0x04) == 0);
1688             break;
1689         case GpioId::G4050:
1690             s->buttons[BUTTON_SCAN_SW].write((val & 0x01) == 0);
1691             s->buttons[BUTTON_FILE_SW].write((val & 0x02) == 0);
1692             s->buttons[BUTTON_EMAIL_SW].write((val & 0x04) == 0);
1693             s->buttons[BUTTON_COPY_SW].write((val & 0x08) == 0);
1694             break;
1695         case GpioId::CANON_4400F:
1696         case GpioId::CANON_8400F:
1697         default:
1698             break;
1699     }
1700 }
1701 
update_home_sensor_gpio(Genesys_Device & dev) const1702 void CommandSetGl843::update_home_sensor_gpio(Genesys_Device& dev) const
1703 {
1704     DBG_HELPER(dbg);
1705     (void) dev;
1706 }
1707 
1708 /**
1709  * Send shading calibration data. The buffer is considered to always hold values
1710  * for all the channels.
1711  */
send_shading_data(Genesys_Device * dev,const Genesys_Sensor & sensor,uint8_t * data,int size) const1712 void CommandSetGl843::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
1713                                         uint8_t* data, int size) const
1714 {
1715     DBG_HELPER(dbg);
1716     uint32_t final_size, i;
1717   uint8_t *buffer;
1718     int count;
1719 
1720     int offset = 0;
1721     unsigned length = size;
1722 
1723     if (dev->reg.get8(REG_0x01) & REG_0x01_SHDAREA) {
1724         offset = dev->session.params.startx * sensor.shading_resolution /
1725                  dev->session.params.xres;
1726 
1727         length = dev->session.output_pixels * sensor.shading_resolution /
1728                  dev->session.params.xres;
1729 
1730         offset += sensor.shading_pixel_offset;
1731 
1732         // 16 bit words, 2 words per color, 3 color channels
1733         length *= 2 * 2 * 3;
1734         offset *= 2 * 2 * 3;
1735     } else {
1736         offset += sensor.shading_pixel_offset * 2 * 2 * 3;
1737     }
1738 
1739     dev->interface->record_key_value("shading_offset", std::to_string(offset));
1740     dev->interface->record_key_value("shading_length", std::to_string(length));
1741 
1742   /* compute and allocate size for final data */
1743   final_size = ((length+251) / 252) * 256;
1744   DBG(DBG_io, "%s: final shading size=%04x (length=%d)\n", __func__, final_size, length);
1745   std::vector<uint8_t> final_data(final_size, 0);
1746 
1747   /* copy regular shading data to the expected layout */
1748   buffer = final_data.data();
1749   count = 0;
1750     if (offset < 0) {
1751         count += (-offset);
1752         length -= (-offset);
1753         offset = 0;
1754     }
1755     if (static_cast<int>(length) + offset > static_cast<int>(size)) {
1756         length = size - offset;
1757     }
1758 
1759   /* loop over calibration data */
1760   for (i = 0; i < length; i++)
1761     {
1762       buffer[count] = data[offset+i];
1763       count++;
1764       if ((count % (256*2)) == (252*2))
1765 	{
1766 	  count += 4*2;
1767 	}
1768     }
1769 
1770     dev->interface->write_buffer(0x3c, 0, final_data.data(), count);
1771 }
1772 
needs_home_before_init_regs_for_scan(Genesys_Device * dev) const1773 bool CommandSetGl843::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
1774 {
1775     (void) dev;
1776     return true;
1777 }
1778 
wait_for_motor_stop(Genesys_Device * dev) const1779 void CommandSetGl843::wait_for_motor_stop(Genesys_Device* dev) const
1780 {
1781     (void) dev;
1782 }
1783 
1784 } // namespace gl843
1785 } // namespace genesys
1786