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