1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2012-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 /** @file
44 *
45 * This file handles GL846 and GL845 ASICs since they are really close to each other.
46 */
47
48 #define DEBUG_DECLARE_ONLY
49
50 #include "gl846.h"
51 #include "gl846_registers.h"
52 #include "test_settings.h"
53
54 #include <vector>
55
56 namespace genesys {
57 namespace gl846 {
58
59 /**
60 * compute the step multiplier used
61 */
gl846_get_step_multiplier(Genesys_Register_Set * regs)62 static int gl846_get_step_multiplier (Genesys_Register_Set * regs)
63 {
64 unsigned value = (regs->get8(0x9d) & 0x0f) >> 1;
65 return 1 << value;
66 }
67
68 /** @brief set all registers to default values .
69 * This function is called only once at the beginning and
70 * fills register startup values for registers reused across scans.
71 * Those that are rarely modified or not modified are written
72 * individually.
73 * @param dev device structure holding register set to initialize
74 */
75 static void
gl846_init_registers(Genesys_Device * dev)76 gl846_init_registers (Genesys_Device * dev)
77 {
78 DBG_HELPER(dbg);
79
80 dev->reg.clear();
81
82 dev->reg.init_reg(0x01, 0x60);
83 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
84 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
85 {
86 dev->reg.init_reg(0x01, 0x22);
87 }
88 dev->reg.init_reg(0x02, 0x38);
89 dev->reg.init_reg(0x03, 0x03);
90 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
91 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
92 {
93 dev->reg.init_reg(0x03, 0xbf);
94 }
95 dev->reg.init_reg(0x04, 0x22);
96 dev->reg.init_reg(0x05, 0x60);
97 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
98 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
99 {
100 dev->reg.init_reg(0x05, 0x48);
101 }
102 dev->reg.init_reg(0x06, 0x10);
103 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
104 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
105 {
106 dev->reg.init_reg(0x06, 0xf0);
107 }
108 dev->reg.init_reg(0x08, 0x60);
109 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
110 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
111 {
112 dev->reg.init_reg(0x08, 0x00);
113 }
114 dev->reg.init_reg(0x09, 0x00);
115 dev->reg.init_reg(0x0a, 0x00);
116 dev->reg.init_reg(0x0b, 0x8b);
117 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
118 dev->reg.init_reg(0x0b, 0x2a);
119 }
120 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
121 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
122 {
123 dev->reg.init_reg(0x0b, 0x4a);
124 }
125 dev->reg.init_reg(0x0c, 0x00);
126 dev->reg.init_reg(0x0d, 0x00);
127 dev->reg.init_reg(0x10, 0x00); // exposure, set during sensor setup
128 dev->reg.init_reg(0x11, 0x00); // exposure, set during sensor setup
129 dev->reg.init_reg(0x12, 0x00); // exposure, set during sensor setup
130 dev->reg.init_reg(0x13, 0x00); // exposure, set during sensor setup
131 dev->reg.init_reg(0x14, 0x00); // exposure, set during sensor setup
132 dev->reg.init_reg(0x15, 0x00); // exposure, set during sensor setup
133 dev->reg.init_reg(0x16, 0xbb); // SENSOR_DEF
134 dev->reg.init_reg(0x17, 0x13); // SENSOR_DEF
135 dev->reg.init_reg(0x18, 0x10); // SENSOR_DEF
136 dev->reg.init_reg(0x19, 0x2a); // SENSOR_DEF
137 dev->reg.init_reg(0x1a, 0x34); // SENSOR_DEF
138 dev->reg.init_reg(0x1b, 0x00); // SENSOR_DEF
139 dev->reg.init_reg(0x1c, 0x20); // SENSOR_DEF
140 dev->reg.init_reg(0x1d, 0x06); // SENSOR_DEF
141 dev->reg.init_reg(0x1e, 0xf0); // WDTIME, LINESEL: set during sensor and motor setup
142
143 // SCANFED
144 dev->reg.init_reg(0x1f, 0x01);
145 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400) {
146 dev->reg.init_reg(0x1f, 0x00);
147 }
148
149 dev->reg.init_reg(0x20, 0x03);
150 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
151 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
152 {
153 dev->reg.init_reg(0x20, 0x55);
154 }
155 dev->reg.init_reg(0x21, 0x10); // STEPNO: set during motor setup
156 dev->reg.init_reg(0x22, 0x60); // FWDSTEP: set during motor setup
157 dev->reg.init_reg(0x23, 0x60); // BWDSTEP: set during motor setup
158 dev->reg.init_reg(0x24, 0x60); // FASTNO: set during motor setup
159 dev->reg.init_reg(0x25, 0x00); // LINCNT: set during motor setup
160 dev->reg.init_reg(0x26, 0x00); // LINCNT: set during motor setup
161 dev->reg.init_reg(0x27, 0x00); // LINCNT: set during motor setup
162 dev->reg.init_reg(0x2c, 0x00); // DPISET: set during sensor setup
163 dev->reg.init_reg(0x2d, 0x00); // DPISET: set during sensor setup
164 dev->reg.init_reg(0x2e, 0x80); // BWHI: set during sensor setup
165 dev->reg.init_reg(0x2f, 0x80); // BWLOW: set during sensor setup
166 dev->reg.init_reg(0x30, 0x00); // STRPIXEL: set during sensor setup
167 dev->reg.init_reg(0x31, 0x00); // STRPIXEL: set during sensor setup
168 dev->reg.init_reg(0x32, 0x00); // ENDPIXEL: set during sensor setup
169 dev->reg.init_reg(0x33, 0x00); // ENDPIXEL: set during sensor setup
170
171 // DUMMY: the number of CCD dummy pixels
172 dev->reg.init_reg(0x34, 0x1f);
173 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
174 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
175 {
176 dev->reg.init_reg(0x34, 0x14);
177 }
178
179 dev->reg.init_reg(0x35, 0x00); // MAXWD: set during scan setup
180 dev->reg.init_reg(0x36, 0x40); // MAXWD: set during scan setup
181 dev->reg.init_reg(0x37, 0x00); // MAXWD: set during scan setup
182 dev->reg.init_reg(0x38, 0x2a); // LPERIOD: set during sensor setup
183 dev->reg.init_reg(0x39, 0xf8); // LPERIOD: set during sensor setup
184 dev->reg.init_reg(0x3d, 0x00); // FEEDL: set during motor setup
185 dev->reg.init_reg(0x3e, 0x00); // FEEDL: set during motor setup
186 dev->reg.init_reg(0x3f, 0x01); // FEEDL: set during motor setup
187 dev->reg.init_reg(0x52, 0x02); // SENSOR_DEF
188 dev->reg.init_reg(0x53, 0x04); // SENSOR_DEF
189 dev->reg.init_reg(0x54, 0x06); // SENSOR_DEF
190 dev->reg.init_reg(0x55, 0x08); // SENSOR_DEF
191 dev->reg.init_reg(0x56, 0x0a); // SENSOR_DEF
192 dev->reg.init_reg(0x57, 0x00); // SENSOR_DEF
193 dev->reg.init_reg(0x58, 0x59); // SENSOR_DEF
194 dev->reg.init_reg(0x59, 0x31); // SENSOR_DEF
195 dev->reg.init_reg(0x5a, 0x40); // SENSOR_DEF
196
197 // DECSEL, STEPTIM
198 dev->reg.init_reg(0x5e, 0x1f);
199 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
200 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
201 {
202 dev->reg.init_reg(0x5e, 0x01);
203 }
204 dev->reg.init_reg(0x5f, 0x01); // FMOVDEC: overwritten during motor setup
205 dev->reg.init_reg(0x60, 0x00); // STEPSEL, Z1MOD: overwritten during motor setup
206 dev->reg.init_reg(0x61, 0x00); // Z1MOD: overwritten during motor setup
207 dev->reg.init_reg(0x62, 0x00); // Z1MOD: overwritten during motor setup
208 dev->reg.init_reg(0x63, 0x00); // FSTPSEL, Z2MOD: overwritten during motor setup
209 dev->reg.init_reg(0x64, 0x00); // Z2MOD: overwritten during motor setup
210 dev->reg.init_reg(0x65, 0x00); // Z2MOD: overwritten during motor setup
211 dev->reg.init_reg(0x67, 0x7f); // MTRPWM: overwritten during motor setup
212 dev->reg.init_reg(0x68, 0x7f); // FASTPWM: overwritten during motor setup
213 dev->reg.init_reg(0x69, 0x01); // FSHDEC: overwritten during motor setup
214 dev->reg.init_reg(0x6a, 0x01); // FMOVNO: overwritten during motor setup
215 // 0x6b, 0x6c, 0x6d, 0x6e, 0x6f - gpio
216 dev->reg.init_reg(0x70, 0x01); // SENSOR_DEF
217 dev->reg.init_reg(0x71, 0x00); // SENSOR_DEF
218 dev->reg.init_reg(0x72, 0x02); // SENSOR_DEF
219 dev->reg.init_reg(0x73, 0x01); // SENSOR_DEF
220 dev->reg.init_reg(0x74, 0x00); // SENSOR_DEF
221 dev->reg.init_reg(0x75, 0x00); // SENSOR_DEF
222 dev->reg.init_reg(0x76, 0x00); // SENSOR_DEF
223 dev->reg.init_reg(0x77, 0x00); // SENSOR_DEF
224 dev->reg.init_reg(0x78, 0x00); // SENSOR_DEF
225 dev->reg.init_reg(0x79, 0x3f); // SENSOR_DEF
226 dev->reg.init_reg(0x7a, 0x00); // SENSOR_DEF
227 dev->reg.init_reg(0x7b, 0x09); // SENSOR_DEF
228 dev->reg.init_reg(0x7c, 0x99); // SENSOR_DEF
229 dev->reg.init_reg(0x7d, 0x20); // SENSOR_DEF
230 dev->reg.init_reg(0x7f, 0x05);
231 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
232 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
233 {
234 dev->reg.init_reg(0x7f, 0x00);
235 }
236 dev->reg.init_reg(0x80, 0x4f); // overwritten during motor setup
237 dev->reg.init_reg(0x87, 0x02); // SENSOR_DEF
238
239 // MTRPLS: pulse width of ADF motor trigger signal
240 dev->reg.init_reg(0x94, 0x00);
241 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
242 dev->reg.init_reg(0x94, 0xff);
243 }
244 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
245 dev->reg.init_reg(0x98, 0x20); // ONDUR
246 dev->reg.init_reg(0x99, 0x00); // ONDUR
247 dev->reg.init_reg(0x9a, 0x90); // OFFDUR
248 dev->reg.init_reg(0x9b, 0x00); // OFFDUR
249 }
250
251 dev->reg.init_reg(0x9d, 0x00); // contains STEPTIM
252 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
253 dev->reg.init_reg(0x9d, 0x04);
254 }
255 dev->reg.init_reg(0x9e, 0x00);
256 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
257 dev->reg.init_reg(0xa1, 0xe0);
258 }
259
260 // RFHSET (SDRAM refresh time)
261 dev->reg.init_reg(0xa2, 0x1f);
262 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
263 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
264 {
265 dev->reg.init_reg(0xa2, 0x0f);
266 }
267
268 // 0xa6, 0xa7 0xa8, 0xa9 - gpio
269
270 // Various important settings: GPOM9, MULSTOP, NODECEL, TB3TB1, TB5TB2, FIX16CLK
271 dev->reg.init_reg(0xab, 0xc0);
272 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
273 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
274 {
275 dev->reg.init_reg(0xab, 0x01);
276 }
277 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
278 dev->reg.init_reg(0xbb, 0x00); // FIXME: default is the same
279 }
280 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
281 dev->reg.init_reg(0xbc, 0x0f);
282 dev->reg.init_reg(0xdb, 0xff);
283 }
284 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400) {
285 dev->reg.init_reg(0xbe, 0x07);
286 }
287
288 // 0xd0, 0xd1, 0xd2 - SH0DWN, SH1DWN, SH2DWN - shading bank[0..2] for CCD.
289 // Set during memory layout setup
290
291 // [0xe0..0xf7] - image buffer addresses. Set during memory layout setup
292 dev->reg.init_reg(0xf8, 0x05); // MAXSEL, MINSEL
293
294 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
295 dev->reg.init_reg(0xfe, 0x08); // MOTTGST, AUTO_O
296 dev->reg.init_reg(0xff, 0x02); // AUTO_S
297 }
298
299 const auto& sensor = sanei_genesys_find_sensor_any(dev);
300 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution,
301 3, dev->model->default_method);
302 sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw);
303 }
304
305 /**
306 * Set register values of Analog Device type frontend
307 * */
gl846_set_adi_fe(Genesys_Device * dev,uint8_t set)308 static void gl846_set_adi_fe(Genesys_Device* dev, uint8_t set)
309 {
310 DBG_HELPER(dbg);
311 int i;
312
313 // wait for FE to be ready
314 auto status = scanner_read_status(*dev);
315 while (status.is_front_end_busy) {
316 dev->interface->sleep_ms(10);
317 status = scanner_read_status(*dev);
318 };
319
320 if (set == AFE_INIT) {
321 dev->frontend = dev->frontend_initial;
322 }
323
324 // write them to analog frontend
325 dev->interface->write_fe_register(0x00, dev->frontend.regs.get_value(0x00));
326
327 dev->interface->write_fe_register(0x01, dev->frontend.regs.get_value(0x01));
328
329 for (i = 0; i < 3; i++) {
330 dev->interface->write_fe_register(0x02 + i, dev->frontend.get_gain(i));
331 }
332 for (i = 0; i < 3; i++) {
333 dev->interface->write_fe_register(0x05 + i, dev->frontend.get_offset(i));
334 }
335 }
336
337 // Set values of analog frontend
set_fe(Genesys_Device * dev,const Genesys_Sensor & sensor,uint8_t set) const338 void CommandSetGl846::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
339 {
340 DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
341 set == AFE_SET ? "set" :
342 set == AFE_POWER_SAVE ? "powersave" : "huh?");
343 (void) sensor;
344
345 /* route to specific analog frontend setup */
346 uint8_t frontend_type = dev->reg.find_reg(0x04).value & REG_0x04_FESET;
347 switch (frontend_type) {
348 case 0x02: /* ADI FE */
349 gl846_set_adi_fe(dev, set);
350 break;
351 default:
352 throw SaneException("unsupported frontend type %d", frontend_type);
353 }
354 }
355
356
357 // @brief set up motor related register for scan
gl846_init_motor_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,const ScanSession & session,Genesys_Register_Set * reg,const MotorProfile & motor_profile,unsigned int scan_exposure_time,unsigned scan_yres,unsigned int scan_lines,unsigned int scan_dummy,unsigned int feed_steps,ScanFlag flags)358 static void gl846_init_motor_regs_scan(Genesys_Device* dev,
359 const Genesys_Sensor& sensor,
360 const ScanSession& session,
361 Genesys_Register_Set* reg,
362 const MotorProfile& motor_profile,
363 unsigned int scan_exposure_time,
364 unsigned scan_yres,
365 unsigned int scan_lines,
366 unsigned int scan_dummy,
367 unsigned int feed_steps,
368 ScanFlag flags)
369 {
370 DBG_HELPER_ARGS(dbg, "scan_exposure_time=%d, scan_yres=%d, step_type=%d, scan_lines=%d, "
371 "scan_dummy=%d, feed_steps=%d, flags=%x",
372 scan_exposure_time, scan_yres, static_cast<unsigned>(motor_profile.step_type),
373 scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
374
375 unsigned step_multiplier = gl846_get_step_multiplier(reg);
376
377 bool use_fast_fed = false;
378 if (dev->settings.yres == 4444 && feed_steps > 100 && !has_flag(flags, ScanFlag::FEEDING)) {
379 use_fast_fed = true;
380 }
381 if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) {
382 use_fast_fed = false;
383 }
384
385 reg->set24(REG_LINCNT, scan_lines);
386
387 reg->set8(REG_0x02, 0);
388 sanei_genesys_set_motor_power(*reg, true);
389
390 std::uint8_t reg02 = reg->get8(REG_0x02);
391 if (use_fast_fed) {
392 reg02 |= REG_0x02_FASTFED;
393 } else {
394 reg02 &= ~REG_0x02_FASTFED;
395 }
396
397 if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
398 reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
399 }
400
401 if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) || (scan_yres>=sensor.full_resolution)) {
402 reg02 |= REG_0x02_ACDCDIS;
403 }
404 if (has_flag(flags, ScanFlag::REVERSE)) {
405 reg02 |= REG_0x02_MTRREV;
406 } else {
407 reg02 &= ~REG_0x02_MTRREV;
408 }
409 reg->set8(REG_0x02, reg02);
410
411 // scan and backtracking slope table
412 auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres,
413 scan_exposure_time, step_multiplier, motor_profile);
414
415 scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
416 scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
417 scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table);
418
419 reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
420 reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
421 reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
422
423 // fast table
424 const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
425 if (fast_profile == nullptr) {
426 fast_profile = &motor_profile;
427 }
428
429 auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
430 *fast_profile);
431
432 scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
433 scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
434
435 reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
436 reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
437
438 if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) {
439 std::uint8_t vref = 0;
440 vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL;
441 vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK;
442 vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST;
443 vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME;
444 reg->set8(REG_0x80, vref);
445 }
446
447 unsigned feedl = feed_steps;
448 unsigned dist = 0;
449 if (use_fast_fed) {
450 feedl <<= static_cast<unsigned>(fast_profile->step_type);
451 dist = (scan_table.table.size() + 2 * fast_table.table.size());
452 // TODO read and decode REG_0xAB
453 dist += (reg->get8(0x5e) & 31);
454 dist += reg->get8(REG_FEDCNT);
455 } else {
456 feedl <<= static_cast<unsigned>(motor_profile.step_type);
457 dist = scan_table.table.size();
458 if (has_flag(flags, ScanFlag::FEEDING)) {
459 dist *= 2;
460 }
461 }
462
463 // check for overflow
464 if (dist < feedl) {
465 feedl -= dist;
466 } else {
467 feedl = 0;
468 }
469
470 reg->set24(REG_FEEDL, feedl);
471
472 unsigned ccdlmt = (reg->get8(REG_0x0C) & REG_0x0C_CCDLMT) + 1;
473 unsigned tgtime = 1 << (reg->get8(REG_0x1C) & REG_0x1C_TGTIME);
474
475 /* hi res motor speed GPIO */
476 /*
477 uint8_t effective = dev->interface->read_register(REG_0x6C);
478 */
479
480 /* if quarter step, bipolar Vref2 */
481 /* XXX STEF XXX GPIO
482 if (motor_profile.step_type > 1)
483 {
484 if (motor_profile.step_type < 3)
485 {
486 val = effective & ~REG_0x6C_GPIO13;
487 }
488 else
489 {
490 val = effective | REG_0x6C_GPIO13;
491 }
492 }
493 else
494 {
495 val = effective;
496 }
497 dev->interface->write_register(REG_0x6C, val);
498 */
499
500 /* effective scan */
501 /*
502 effective = dev->interface->read_register(REG_0x6C);
503 val = effective | REG_0x6C_GPIO10;
504 dev->interface->write_register(REG_0x6C, val);
505 */
506
507 unsigned min_restep = (scan_table.table.size() / step_multiplier) / 2 - 1;
508 if (min_restep < 1) {
509 min_restep = 1;
510 }
511
512 reg->set8(REG_FWDSTEP, min_restep);
513 reg->set8(REG_BWDSTEP, min_restep);
514
515 std::uint32_t z1, z2;
516 sanei_genesys_calculate_zmod(use_fast_fed,
517 scan_exposure_time * ccdlmt * tgtime,
518 scan_table.table,
519 scan_table.table.size(),
520 feedl,
521 min_restep * step_multiplier,
522 &z1,
523 &z2);
524
525 reg->set24(REG_0x60, z1 | (static_cast<unsigned>(motor_profile.step_type) << (16 + REG_0x60S_STEPSEL)));
526 reg->set24(REG_0x63, z2 | (static_cast<unsigned>(motor_profile.step_type) << (16 + REG_0x63S_FSTPSEL)));
527
528 reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
529
530 reg->set8(REG_0x67, 0x7f);
531 reg->set8(REG_0x68, 0x7f);
532 }
533
534
535 /** @brief set up registers related to sensor
536 * Set up the following registers
537 0x01
538 0x03
539 0x10-0x015 R/G/B exposures
540 0x19 EXPDMY
541 0x2e BWHI
542 0x2f BWLO
543 0x04
544 0x87
545 0x05
546 0x2c,0x2d DPISET
547 0x30,0x31 STRPIXEL
548 0x32,0x33 ENDPIXEL
549 0x35,0x36,0x37 MAXWD [25:2] (>>2)
550 0x38,0x39 LPERIOD
551 0x34 DUMMY
552 */
gl846_init_optical_regs_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,unsigned int exposure_time,const ScanSession & session)553 static void gl846_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
554 Genesys_Register_Set* reg, unsigned int exposure_time,
555 const ScanSession& session)
556 {
557 DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time);
558
559 scanner_setup_sensor(*dev, sensor, *reg);
560
561 dev->cmd_set->set_fe(dev, sensor, AFE_SET);
562
563 /* enable shading */
564 regs_set_optical_off(dev->model->asic_type, *reg);
565 reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
566 if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
567 has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
568 session.use_host_side_calib)
569 {
570 reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
571 } else {
572 reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
573 }
574
575 reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
576
577 sanei_genesys_set_lamp_power(dev, sensor, *reg,
578 !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
579 reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
580
581 // BW threshold
582 reg->set8(0x2e, 0x7f);
583 reg->set8(0x2f, 0x7f);
584
585 /* monochrome / color scan */
586 switch (session.params.depth) {
587 case 8:
588 reg->find_reg(REG_0x04).value &= ~(REG_0x04_LINEART | REG_0x04_BITSET);
589 break;
590 case 16:
591 reg->find_reg(REG_0x04).value &= ~REG_0x04_LINEART;
592 reg->find_reg(REG_0x04).value |= REG_0x04_BITSET;
593 break;
594 }
595
596 reg->find_reg(REG_0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
597 if (session.params.channels == 1)
598 {
599 switch (session.params.color_filter)
600 {
601 case ColorFilter::RED:
602 reg->find_reg(REG_0x04).value |= 0x24;
603 break;
604 case ColorFilter::BLUE:
605 reg->find_reg(REG_0x04).value |= 0x2c;
606 break;
607 case ColorFilter::GREEN:
608 reg->find_reg(REG_0x04).value |= 0x28;
609 break;
610 default:
611 break; // should not happen
612 }
613 } else {
614 reg->find_reg(REG_0x04).value |= 0x20; // mono
615 }
616
617 const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution,
618 session.params.channels,
619 session.params.scan_method);
620 sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw);
621
622 if (should_enable_gamma(session, sensor)) {
623 reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB;
624 } else {
625 reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
626 }
627
628 /* CIS scanners can do true gray by setting LEDADD */
629 /* we set up LEDADD only when asked */
630 if (dev->model->is_cis) {
631 reg->find_reg(0x87).value &= ~REG_0x87_LEDADD;
632
633 if (session.enable_ledadd) {
634 reg->find_reg(0x87).value |= REG_0x87_LEDADD;
635 }
636 /* RGB weighting
637 reg->find_reg(0x01).value &= ~REG_0x01_TRUEGRAY;
638
639 if (session.enable_ledadd))
640 {
641 reg->find_reg(0x01).value |= REG_0x01_TRUEGRAY;
642 }*/
643 }
644
645 reg->set16(REG_DPISET, sensor.register_dpiset);
646 reg->set16(REG_STRPIXEL, session.pixel_startx);
647 reg->set16(REG_ENDPIXEL, session.pixel_endx);
648
649 setup_image_pipeline(*dev, session);
650
651 /* MAXWD is expressed in 4 words unit */
652 // BUG: we shouldn't multiply by channels here
653 reg->set24(REG_MAXWD, (session.output_line_bytes_raw * session.params.channels >> 2));
654 reg->set16(REG_LPERIOD, exposure_time);
655 reg->set8(0x34, sensor.dummy_pixel);
656 }
657
init_regs_for_scan_session(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,const ScanSession & session) const658 void CommandSetGl846::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
659 Genesys_Register_Set* reg,
660 const ScanSession& session) const
661 {
662 DBG_HELPER(dbg);
663 session.assert_computed();
664
665 int exposure_time;
666
667 int slope_dpi = 0;
668
669 // FIXME: on cis scanners we may want to scan at reduced resolution
670 int dummy = 0;
671
672 /* slope_dpi */
673 /* cis color scan is effectively a gray scan with 3 gray lines per color
674 line and a FILTER of 0 */
675 if (dev->model->is_cis) {
676 slope_dpi = session.params.yres * session.params.channels;
677 } else {
678 slope_dpi = session.params.yres;
679 }
680
681 slope_dpi = slope_dpi * (1 + dummy);
682
683 exposure_time = sensor.exposure_lperiod;
684 const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
685
686 /* we enable true gray for cis scanners only, and just when doing
687 * scan since color calibration is OK for this mode
688 */
689 gl846_init_optical_regs_scan(dev, sensor, reg, exposure_time, session);
690 gl846_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure_time, slope_dpi,
691 session.optical_line_count, dummy, session.params.starty,
692 session.params.flags);
693
694 /*** prepares data reordering ***/
695
696 dev->read_active = true;
697
698 dev->session = session;
699
700 dev->total_bytes_read = 0;
701 dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines;
702
703 DBG(DBG_info, "%s: total bytes to send = %zu\n", __func__, dev->total_bytes_to_read);
704 }
705
calculate_scan_session(const Genesys_Device * dev,const Genesys_Sensor & sensor,const Genesys_Settings & settings) const706 ScanSession CommandSetGl846::calculate_scan_session(const Genesys_Device* dev,
707 const Genesys_Sensor& sensor,
708 const Genesys_Settings& settings) const
709 {
710 DBG(DBG_info, "%s ", __func__);
711 debug_dump(DBG_info, settings);
712
713 ScanFlag flags = ScanFlag::NONE;
714
715 unsigned move_dpi = dev->motor.base_ydpi;
716
717 float move = dev->model->y_offset;
718 if (settings.scan_method == ScanMethod::TRANSPARENCY ||
719 settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
720 {
721 // note: scanner_move_to_ta() function has already been called and the sensor is at the
722 // transparency adapter
723 if (!dev->ignore_offsets) {
724 move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
725 }
726 flags |= ScanFlag::USE_XPA;
727 } else {
728 if (!dev->ignore_offsets) {
729 move = dev->model->y_offset;
730 }
731 }
732
733 move = move + settings.tl_y;
734 move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
735 move -= dev->head_pos(ScanHeadId::PRIMARY);
736
737 float start = dev->model->x_offset;
738 if (settings.scan_method == ScanMethod::TRANSPARENCY ||
739 settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
740 {
741 start = dev->model->x_offset_ta;
742 } else {
743 start = dev->model->x_offset;
744 }
745
746 start = start + dev->settings.tl_x;
747 start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
748
749 ScanSession session;
750 session.params.xres = settings.xres;
751 session.params.yres = settings.yres;
752 session.params.startx = static_cast<unsigned>(start);
753 session.params.starty = static_cast<unsigned>(move);
754 session.params.pixels = settings.pixels;
755 session.params.requested_pixels = settings.requested_pixels;
756 session.params.lines = settings.lines;
757 session.params.depth = settings.depth;
758 session.params.channels = settings.get_channels();
759 session.params.scan_method = settings.scan_method;
760 session.params.scan_mode = settings.scan_mode;
761 session.params.color_filter = settings.color_filter;
762 // backtracking isn't handled well, so don't enable it
763 session.params.flags = flags;
764
765 compute_session(dev, session, sensor);
766
767 return session;
768 }
769
770 // for fast power saving methods only, like disabling certain amplifiers
save_power(Genesys_Device * dev,bool enable) const771 void CommandSetGl846::save_power(Genesys_Device* dev, bool enable) const
772 {
773 (void) dev;
774 DBG_HELPER_ARGS(dbg, "enable = %d", enable);
775 }
776
set_powersaving(Genesys_Device * dev,int delay) const777 void CommandSetGl846::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const
778 {
779 (void) dev;
780 DBG_HELPER_ARGS(dbg, "delay = %d", delay);
781 }
782
783 // Send the low-level scan command
begin_scan(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * reg,bool start_motor) const784 void CommandSetGl846::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
785 Genesys_Register_Set* reg, bool start_motor) const
786 {
787 DBG_HELPER(dbg);
788 (void) sensor;
789 uint8_t val;
790
791 if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
792 dev->cmd_set->set_xpa_lamp_power(*dev, true);
793 }
794
795 scanner_clear_scan_and_feed_counts(*dev);
796
797 val = dev->interface->read_register(REG_0x01);
798 val |= REG_0x01_SCAN;
799 dev->interface->write_register(REG_0x01, val);
800 reg->set8(REG_0x01, val);
801
802 scanner_start_action(*dev, start_motor);
803
804 dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
805 }
806
807
808 // Send the stop scan command
end_scan(Genesys_Device * dev,Genesys_Register_Set * reg,bool check_stop) const809 void CommandSetGl846::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
810 bool check_stop) const
811 {
812 (void) reg;
813 DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
814
815 if (reg->state.is_xpa_on) {
816 dev->cmd_set->set_xpa_lamp_power(*dev, false);
817 }
818
819 if (!dev->model->is_sheetfed) {
820 scanner_stop_action(*dev);
821 }
822 }
823
824 // Moves the slider to the home (top) position slowly
move_back_home(Genesys_Device * dev,bool wait_until_home) const825 void CommandSetGl846::move_back_home(Genesys_Device* dev, bool wait_until_home) const
826 {
827 scanner_move_back_home(*dev, wait_until_home);
828 }
829
830 // init registers for shading calibration
init_regs_for_shading(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const831 void CommandSetGl846::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
832 Genesys_Register_Set& regs) const
833 {
834 DBG_HELPER(dbg);
835
836 unsigned move_dpi = dev->motor.base_ydpi;
837
838 float calib_size_mm = 0;
839 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
840 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
841 {
842 calib_size_mm = dev->model->y_size_calib_ta_mm;
843 } else {
844 calib_size_mm = dev->model->y_size_calib_mm;
845 }
846
847 unsigned channels = 3;
848 unsigned resolution = sensor.shading_resolution;
849
850 const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
851 dev->settings.scan_method);
852
853 float move = 0;
854 ScanFlag flags = ScanFlag::DISABLE_SHADING |
855 ScanFlag::DISABLE_GAMMA |
856 ScanFlag::DISABLE_BUFFER_FULL_MOVE;
857
858 if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
859 dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
860 {
861 // note: scanner_move_to_ta() function has already been called and the sensor is at the
862 // transparency adapter
863 move = static_cast<int>(dev->model->y_offset_calib_white_ta - dev->model->y_offset_sensor_to_ta);
864 flags |= ScanFlag::USE_XPA;
865 } else {
866 move = static_cast<int>(dev->model->y_offset_calib_white);
867 }
868
869 move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
870
871 unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
872
873 ScanSession session;
874 session.params.xres = resolution;
875 session.params.yres = resolution;
876 session.params.startx = 0;
877 session.params.starty = static_cast<unsigned>(move);
878 session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
879 session.params.lines = calib_lines;
880 session.params.depth = 16;
881 session.params.channels = channels;
882 session.params.scan_method = dev->settings.scan_method;
883 session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
884 session.params.color_filter = dev->settings.color_filter;
885 session.params.flags = flags;
886 compute_session(dev, session, calib_sensor);
887
888 init_regs_for_scan_session(dev, calib_sensor, ®s, session);
889
890 /* we use ModelFlag::SHADING_REPARK */
891 dev->set_head_pos_zero(ScanHeadId::PRIMARY);
892
893 dev->calib_session = session;
894 }
895
896 /**
897 * Send shading calibration data. The buffer is considered to always hold values
898 * for all the channels.
899 */
send_shading_data(Genesys_Device * dev,const Genesys_Sensor & sensor,uint8_t * data,int size) const900 void CommandSetGl846::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
901 uint8_t* data, int size) const
902 {
903 DBG_HELPER_ARGS(dbg, "writing %d bytes of shading data", size);
904 std::uint32_t addr, i;
905 uint8_t val,*ptr,*src;
906
907 unsigned length = static_cast<unsigned>(size / 3);
908
909 // we're using SHDAREA, thus we only need to upload part of the line
910 unsigned offset = dev->session.pixel_count_ratio.apply(
911 dev->session.params.startx * sensor.full_resolution / dev->session.params.xres);
912 unsigned pixels = dev->session.pixel_count_ratio.apply(dev->session.optical_pixels_raw);
913
914 // turn pixel value into bytes 2x16 bits words
915 offset *= 2 * 2;
916 pixels *= 2 * 2;
917
918 dev->interface->record_key_value("shading_offset", std::to_string(offset));
919 dev->interface->record_key_value("shading_pixels", std::to_string(pixels));
920 dev->interface->record_key_value("shading_length", std::to_string(length));
921 dev->interface->record_key_value("shading_factor", std::to_string(sensor.shading_factor));
922
923 std::vector<uint8_t> buffer(pixels, 0);
924
925 DBG(DBG_io2, "%s: using chunks of %d (0x%04x) bytes\n", __func__, pixels, pixels);
926
927 /* base addr of data has been written in reg D0-D4 in 4K word, so AHB address
928 * is 8192*reg value */
929
930 /* write actual color channel data */
931 for(i=0;i<3;i++)
932 {
933 /* build up actual shading data by copying the part from the full width one
934 * to the one corresponding to SHDAREA */
935 ptr = buffer.data();
936
937 /* iterate on both sensor segment */
938 for (unsigned x = 0; x < pixels; x += 4 * sensor.shading_factor) {
939 // coefficient source
940 src = (data + offset + i * length) + x;
941
942 /* coefficient copy */
943 ptr[0]=src[0];
944 ptr[1]=src[1];
945 ptr[2]=src[2];
946 ptr[3]=src[3];
947
948 /* next shading coefficient */
949 ptr+=4;
950 }
951
952 val = dev->interface->read_register(0xd0+i);
953 addr = val * 8192 + 0x10000000;
954 dev->interface->write_ahb(addr, pixels, buffer.data());
955 }
956 }
957
958 /** @brief calibrates led exposure
959 * Calibrate exposure by scanning a white area until the used exposure gives
960 * data white enough.
961 * @param dev device to calibrate
962 */
led_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const963 SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
964 Genesys_Register_Set& regs) const
965 {
966 return scanner_led_calibration(*dev, sensor, regs);
967 }
968
969 /**
970 * set up GPIO/GPOE for idle state
971 */
gl846_init_gpio(Genesys_Device * dev)972 static void gl846_init_gpio(Genesys_Device* dev)
973 {
974 DBG_HELPER(dbg);
975 apply_registers_ordered(dev->gpo.regs, { 0x6e, 0x6f }, [&](const GenesysRegisterSetting& reg)
976 {
977 dev->interface->write_register(reg.address, reg.value);
978 });
979 }
980
981 /**
982 * set memory layout by filling values in dedicated registers
983 */
gl846_init_memory_layout(Genesys_Device * dev)984 static void gl846_init_memory_layout(Genesys_Device* dev)
985 {
986 DBG_HELPER(dbg);
987
988 // prevent further writings by bulk write register
989 dev->reg.remove_reg(0x0b);
990
991 apply_reg_settings_to_device_write_only(*dev, dev->memory_layout.regs);
992 }
993
994 /* *
995 * initialize ASIC from power on condition
996 */
asic_boot(Genesys_Device * dev,bool cold) const997 void CommandSetGl846::asic_boot(Genesys_Device* dev, bool cold) const
998 {
999 DBG_HELPER(dbg);
1000 uint8_t val;
1001
1002 // reset ASIC if cold boot
1003 if (cold) {
1004 dev->interface->write_register(0x0e, 0x01);
1005 dev->interface->write_register(0x0e, 0x00);
1006 }
1007
1008 if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
1009 if (dev->usb_mode == 1) {
1010 val = 0x14;
1011 } else {
1012 val = 0x11;
1013 }
1014 dev->interface->write_0x8c(0x0f, val);
1015 }
1016
1017 // test CHKVER
1018 val = dev->interface->read_register(REG_0x40);
1019 if (val & REG_0x40_CHKVER) {
1020 val = dev->interface->read_register(0x00);
1021 DBG(DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val);
1022 }
1023
1024 gl846_init_registers (dev);
1025
1026 // Write initial registers
1027 dev->interface->write_registers(dev->reg);
1028
1029 /* CIS_LINE */
1030 if (dev->model->is_cis)
1031 {
1032 dev->reg.init_reg(0x08, REG_0x08_CIS_LINE);
1033 dev->interface->write_register(0x08, dev->reg.find_reg(0x08).value);
1034 }
1035
1036 // set up clocks
1037 if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
1038 dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
1039 {
1040 dev->interface->write_0x8c(0x10, 0x0c);
1041 dev->interface->write_0x8c(0x13, 0x0c);
1042 } else {
1043 dev->interface->write_0x8c(0x10, 0x0e);
1044 dev->interface->write_0x8c(0x13, 0x0e);
1045 }
1046
1047 // setup gpio
1048 gl846_init_gpio(dev);
1049
1050 // setup internal memory layout
1051 gl846_init_memory_layout(dev);
1052
1053 dev->reg.init_reg(0xf8, 0x05);
1054 dev->interface->write_register(0xf8, dev->reg.find_reg(0xf8).value);
1055 }
1056
1057 /**
1058 * initialize backend and ASIC : registers, motor tables, and gamma tables
1059 * then ensure scanner's head is at home
1060 */
init(Genesys_Device * dev) const1061 void CommandSetGl846::init(Genesys_Device* dev) const
1062 {
1063 DBG_INIT ();
1064 DBG_HELPER(dbg);
1065
1066 sanei_genesys_asic_init(dev);
1067 }
1068
update_hardware_sensors(Genesys_Scanner * s) const1069 void CommandSetGl846::update_hardware_sensors(Genesys_Scanner* s) const
1070 {
1071 DBG_HELPER(dbg);
1072 /* do what is needed to get a new set of events, but try to not lose
1073 any of them.
1074 */
1075 uint8_t val;
1076 uint8_t scan, file, email, copy;
1077 switch(s->dev->model->gpio_id)
1078 {
1079 default:
1080 scan=0x01;
1081 file=0x02;
1082 email=0x04;
1083 copy=0x08;
1084 }
1085 val = s->dev->interface->read_register(REG_0x6D);
1086
1087 s->buttons[BUTTON_SCAN_SW].write((val & scan) == 0);
1088 s->buttons[BUTTON_FILE_SW].write((val & file) == 0);
1089 s->buttons[BUTTON_EMAIL_SW].write((val & email) == 0);
1090 s->buttons[BUTTON_COPY_SW].write((val & copy) == 0);
1091 }
1092
1093
update_home_sensor_gpio(Genesys_Device & dev) const1094 void CommandSetGl846::update_home_sensor_gpio(Genesys_Device& dev) const
1095 {
1096 DBG_HELPER(dbg);
1097
1098 std::uint8_t val = dev.interface->read_register(REG_0x6C);
1099 val |= 0x41;
1100 dev.interface->write_register(REG_0x6C, val);
1101 }
1102
offset_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs) const1103 void CommandSetGl846::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1104 Genesys_Register_Set& regs) const
1105 {
1106 scanner_offset_calibration(*dev, sensor, regs);
1107 }
1108
coarse_gain_calibration(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set & regs,int dpi) const1109 void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
1110 Genesys_Register_Set& regs, int dpi) const
1111 {
1112 scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
1113 }
1114
needs_home_before_init_regs_for_scan(Genesys_Device * dev) const1115 bool CommandSetGl846::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
1116 {
1117 (void) dev;
1118 return false;
1119 }
1120
init_regs_for_warmup(Genesys_Device * dev,const Genesys_Sensor & sensor,Genesys_Register_Set * regs) const1121 void CommandSetGl846::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
1122 Genesys_Register_Set* regs) const
1123 {
1124 (void) dev;
1125 (void) sensor;
1126 (void) regs;
1127 throw SaneException("not implemented");
1128 }
1129
send_gamma_table(Genesys_Device * dev,const Genesys_Sensor & sensor) const1130 void CommandSetGl846::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
1131 {
1132 sanei_genesys_send_gamma_table(dev, sensor);
1133 }
1134
wait_for_motor_stop(Genesys_Device * dev) const1135 void CommandSetGl846::wait_for_motor_stop(Genesys_Device* dev) const
1136 {
1137 (void) dev;
1138 }
1139
load_document(Genesys_Device * dev) const1140 void CommandSetGl846::load_document(Genesys_Device* dev) const
1141 {
1142 (void) dev;
1143 throw SaneException("not implemented");
1144 }
1145
detect_document_end(Genesys_Device * dev) const1146 void CommandSetGl846::detect_document_end(Genesys_Device* dev) const
1147 {
1148 (void) dev;
1149 throw SaneException("not implemented");
1150 }
1151
eject_document(Genesys_Device * dev) const1152 void CommandSetGl846::eject_document(Genesys_Device* dev) const
1153 {
1154 (void) dev;
1155 throw SaneException("not implemented");
1156 }
1157
1158 } // namespace gl846
1159 } // namespace genesys
1160