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