1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy. 2141cc406Sopenharmony_ci 3141cc406Sopenharmony_ci Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr> 4141cc406Sopenharmony_ci Copyright (C) 2020 Povilas Kanapickas <povilas@radix.lt> 5141cc406Sopenharmony_ci 6141cc406Sopenharmony_ci This file is part of the SANE package. 7141cc406Sopenharmony_ci 8141cc406Sopenharmony_ci This program is free software; you can redistribute it and/or 9141cc406Sopenharmony_ci modify it under the terms of the GNU General Public License as 10141cc406Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 11141cc406Sopenharmony_ci License, or (at your option) any later version. 12141cc406Sopenharmony_ci 13141cc406Sopenharmony_ci This program is distributed in the hope that it will be useful, but 14141cc406Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 15141cc406Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16141cc406Sopenharmony_ci General Public License for more details. 17141cc406Sopenharmony_ci 18141cc406Sopenharmony_ci You should have received a copy of the GNU General Public License 19141cc406Sopenharmony_ci along with this program. If not, see <https://www.gnu.org/licenses/>. 20141cc406Sopenharmony_ci*/ 21141cc406Sopenharmony_ci 22141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY 23141cc406Sopenharmony_ci 24141cc406Sopenharmony_ci#include "gl842_registers.h" 25141cc406Sopenharmony_ci#include "gl842.h" 26141cc406Sopenharmony_ci#include "test_settings.h" 27141cc406Sopenharmony_ci 28141cc406Sopenharmony_ci#include <string> 29141cc406Sopenharmony_ci#include <vector> 30141cc406Sopenharmony_ci 31141cc406Sopenharmony_cinamespace genesys { 32141cc406Sopenharmony_cinamespace gl842 { 33141cc406Sopenharmony_ci 34141cc406Sopenharmony_cistatic void gl842_init_registers(Genesys_Device& dev) 35141cc406Sopenharmony_ci{ 36141cc406Sopenharmony_ci // Within this function SENSOR_DEF marker documents that a register is part 37141cc406Sopenharmony_ci // of the sensors definition and the actual value is set in 38141cc406Sopenharmony_ci // gl842_setup_sensor(). 39141cc406Sopenharmony_ci 40141cc406Sopenharmony_ci DBG_HELPER(dbg); 41141cc406Sopenharmony_ci 42141cc406Sopenharmony_ci dev.reg.clear(); 43141cc406Sopenharmony_ci 44141cc406Sopenharmony_ci if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 45141cc406Sopenharmony_ci dev.reg.init_reg(0x01, 0x00); 46141cc406Sopenharmony_ci dev.reg.init_reg(0x02, 0x78); 47141cc406Sopenharmony_ci dev.reg.init_reg(0x03, 0xbf); 48141cc406Sopenharmony_ci dev.reg.init_reg(0x04, 0x22); 49141cc406Sopenharmony_ci dev.reg.init_reg(0x05, 0x48); 50141cc406Sopenharmony_ci 51141cc406Sopenharmony_ci dev.reg.init_reg(0x06, 0xb8); 52141cc406Sopenharmony_ci 53141cc406Sopenharmony_ci dev.reg.init_reg(0x07, 0x00); 54141cc406Sopenharmony_ci dev.reg.init_reg(0x08, 0x00); 55141cc406Sopenharmony_ci dev.reg.init_reg(0x09, 0x00); 56141cc406Sopenharmony_ci dev.reg.init_reg(0x0a, 0x00); 57141cc406Sopenharmony_ci dev.reg.init_reg(0x0d, 0x01); 58141cc406Sopenharmony_ci } else if (dev.model->model_id == ModelId::CANON_LIDE_90) { 59141cc406Sopenharmony_ci dev.reg.init_reg(0x01, 0x82); 60141cc406Sopenharmony_ci dev.reg.init_reg(0x02, 0x10); 61141cc406Sopenharmony_ci dev.reg.init_reg(0x03, 0x60); 62141cc406Sopenharmony_ci dev.reg.init_reg(0x04, 0x10); 63141cc406Sopenharmony_ci dev.reg.init_reg(0x05, 0x8c); 64141cc406Sopenharmony_ci 65141cc406Sopenharmony_ci dev.reg.init_reg(0x06, 0x18); 66141cc406Sopenharmony_ci 67141cc406Sopenharmony_ci //dev.reg.init_reg(0x07, 0x00); 68141cc406Sopenharmony_ci dev.reg.init_reg(0x08, 0x00); 69141cc406Sopenharmony_ci dev.reg.init_reg(0x09, 0x21); 70141cc406Sopenharmony_ci dev.reg.init_reg(0x0a, 0x00); 71141cc406Sopenharmony_ci dev.reg.init_reg(0x0d, 0x00); 72141cc406Sopenharmony_ci } 73141cc406Sopenharmony_ci 74141cc406Sopenharmony_ci dev.reg.init_reg(0x10, 0x00); // exposure, overwritten in scanner_setup_sensor() below 75141cc406Sopenharmony_ci dev.reg.init_reg(0x11, 0x00); // exposure, overwritten in scanner_setup_sensor() below 76141cc406Sopenharmony_ci dev.reg.init_reg(0x12, 0x00); // exposure, overwritten in scanner_setup_sensor() below 77141cc406Sopenharmony_ci dev.reg.init_reg(0x13, 0x00); // exposure, overwritten in scanner_setup_sensor() below 78141cc406Sopenharmony_ci dev.reg.init_reg(0x14, 0x00); // exposure, overwritten in scanner_setup_sensor() below 79141cc406Sopenharmony_ci dev.reg.init_reg(0x15, 0x00); // exposure, overwritten in scanner_setup_sensor() below 80141cc406Sopenharmony_ci 81141cc406Sopenharmony_ci // CCD signal settings. 82141cc406Sopenharmony_ci dev.reg.init_reg(0x16, 0x00); // SENSOR_DEF 83141cc406Sopenharmony_ci dev.reg.init_reg(0x17, 0x00); // SENSOR_DEF 84141cc406Sopenharmony_ci dev.reg.init_reg(0x18, 0x00); // SENSOR_DEF 85141cc406Sopenharmony_ci 86141cc406Sopenharmony_ci // EXPDMY[0:7]: Exposure time of dummy lines. 87141cc406Sopenharmony_ci dev.reg.init_reg(0x19, 0x00); // SENSOR_DEF 88141cc406Sopenharmony_ci 89141cc406Sopenharmony_ci // Various CCD clock settings. 90141cc406Sopenharmony_ci dev.reg.init_reg(0x1a, 0x00); // SENSOR_DEF 91141cc406Sopenharmony_ci if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 92141cc406Sopenharmony_ci dev.reg.init_reg(0x1b, 0x00); // SENSOR_DEF 93141cc406Sopenharmony_ci } 94141cc406Sopenharmony_ci dev.reg.init_reg(0x1c, 0x00); // SENSOR_DEF 95141cc406Sopenharmony_ci dev.reg.init_reg(0x1d, 0x00); // SENSOR_DEF 96141cc406Sopenharmony_ci dev.reg.init_reg(0x1e, 0x10); // WDTIME, LINESEL: setup during sensor and motor setup 97141cc406Sopenharmony_ci 98141cc406Sopenharmony_ci if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 99141cc406Sopenharmony_ci dev.reg.init_reg(0x1f, 0x01); 100141cc406Sopenharmony_ci dev.reg.init_reg(0x20, 0x27); // BUFSEL: buffer full condition 101141cc406Sopenharmony_ci } else if (dev.model->model_id == ModelId::CANON_LIDE_90) { 102141cc406Sopenharmony_ci dev.reg.init_reg(0x1f, 0x02); 103141cc406Sopenharmony_ci dev.reg.init_reg(0x20, 0x02); // BUFSEL: buffer full condition 104141cc406Sopenharmony_ci } 105141cc406Sopenharmony_ci 106141cc406Sopenharmony_ci dev.reg.init_reg(0x21, 0x10); // STEPNO: set during motor setup 107141cc406Sopenharmony_ci dev.reg.init_reg(0x22, 0x10); // FWDSTEP: set during motor setup 108141cc406Sopenharmony_ci dev.reg.init_reg(0x23, 0x10); // BWDSTEP: set during motor setup 109141cc406Sopenharmony_ci dev.reg.init_reg(0x24, 0x10); // FASTNO: set during motor setup 110141cc406Sopenharmony_ci dev.reg.init_reg(0x25, 0x00); // LINCNT: set during motor setup 111141cc406Sopenharmony_ci dev.reg.init_reg(0x26, 0x00); // LINCNT: set during motor setup 112141cc406Sopenharmony_ci dev.reg.init_reg(0x27, 0x00); // LINCNT: set during motor setup 113141cc406Sopenharmony_ci 114141cc406Sopenharmony_ci dev.reg.init_reg(0x29, 0xff); // LAMPPWM 115141cc406Sopenharmony_ci 116141cc406Sopenharmony_ci dev.reg.init_reg(0x2c, 0x02); // DPISET: set during sensor setup 117141cc406Sopenharmony_ci dev.reg.init_reg(0x2d, 0x58); // DPISET: set during sensor setup 118141cc406Sopenharmony_ci 119141cc406Sopenharmony_ci dev.reg.init_reg(0x2e, 0x80); // BWHI: black/white low threshdold 120141cc406Sopenharmony_ci dev.reg.init_reg(0x2f, 0x80); // BWLOW: black/white low threshold 121141cc406Sopenharmony_ci 122141cc406Sopenharmony_ci dev.reg.init_reg(0x30, 0x00); // STRPIXEL: set during sensor setup 123141cc406Sopenharmony_ci dev.reg.init_reg(0x31, 0x49); // STRPIXEL: set during sensor setup 124141cc406Sopenharmony_ci dev.reg.init_reg(0x32, 0x53); // ENDPIXEL: set during sensor setup 125141cc406Sopenharmony_ci dev.reg.init_reg(0x33, 0xb9); // ENDPIXEL: set during sensor setup 126141cc406Sopenharmony_ci 127141cc406Sopenharmony_ci dev.reg.init_reg(0x34, 0x13); // DUMMY: SENSOR_DEF 128141cc406Sopenharmony_ci dev.reg.init_reg(0x35, 0x00); // MAXWD: set during scan setup 129141cc406Sopenharmony_ci dev.reg.init_reg(0x36, 0x40); // MAXWD: set during scan setup 130141cc406Sopenharmony_ci dev.reg.init_reg(0x37, 0x00); // MAXWD: set during scan setup 131141cc406Sopenharmony_ci dev.reg.init_reg(0x38, 0x2a); // LPERIOD: SENSOR_DEF 132141cc406Sopenharmony_ci dev.reg.init_reg(0x39, 0xf8); // LPERIOD: SENSOR_DEF 133141cc406Sopenharmony_ci dev.reg.init_reg(0x3d, 0x00); // FEEDL: set during motor setup 134141cc406Sopenharmony_ci dev.reg.init_reg(0x3e, 0x00); // FEEDL: set during motor setup 135141cc406Sopenharmony_ci dev.reg.init_reg(0x3f, 0x01); // FEEDL: set during motor setup 136141cc406Sopenharmony_ci 137141cc406Sopenharmony_ci dev.reg.init_reg(0x52, 0x00); // SENSOR_DEF 138141cc406Sopenharmony_ci dev.reg.init_reg(0x53, 0x00); // SENSOR_DEF 139141cc406Sopenharmony_ci dev.reg.init_reg(0x54, 0x00); // SENSOR_DEF 140141cc406Sopenharmony_ci dev.reg.init_reg(0x55, 0x00); // SENSOR_DEF 141141cc406Sopenharmony_ci dev.reg.init_reg(0x56, 0x00); // SENSOR_DEF 142141cc406Sopenharmony_ci dev.reg.init_reg(0x57, 0x00); // SENSOR_DEF 143141cc406Sopenharmony_ci dev.reg.init_reg(0x58, 0x00); // SENSOR_DEF 144141cc406Sopenharmony_ci dev.reg.init_reg(0x59, 0x00); // SENSOR_DEF 145141cc406Sopenharmony_ci dev.reg.init_reg(0x5a, 0x00); // SENSOR_DEF 146141cc406Sopenharmony_ci 147141cc406Sopenharmony_ci if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 148141cc406Sopenharmony_ci dev.reg.init_reg(0x5e, 0x01); // DECSEL, STOPTIM 149141cc406Sopenharmony_ci } else if (dev.model->model_id == ModelId::CANON_LIDE_90) { 150141cc406Sopenharmony_ci dev.reg.init_reg(0x5e, 0x41); // DECSEL, STOPTIM 151141cc406Sopenharmony_ci dev.reg.init_reg(0x5d, 0x20); 152141cc406Sopenharmony_ci } 153141cc406Sopenharmony_ci dev.reg.init_reg(0x5f, 0x10); // FMOVDEC: set during motor setup 154141cc406Sopenharmony_ci 155141cc406Sopenharmony_ci dev.reg.init_reg(0x60, 0x00); // Z1MOD: overwritten during motor setup 156141cc406Sopenharmony_ci dev.reg.init_reg(0x61, 0x00); // Z1MOD: overwritten during motor setup 157141cc406Sopenharmony_ci dev.reg.init_reg(0x62, 0x00); // Z1MOD: overwritten during motor setup 158141cc406Sopenharmony_ci dev.reg.init_reg(0x63, 0x00); // Z2MOD: overwritten during motor setup 159141cc406Sopenharmony_ci dev.reg.init_reg(0x64, 0x00); // Z2MOD: overwritten during motor setup 160141cc406Sopenharmony_ci dev.reg.init_reg(0x65, 0x00); // Z2MOD: overwritten during motor setup 161141cc406Sopenharmony_ci 162141cc406Sopenharmony_ci if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 163141cc406Sopenharmony_ci dev.reg.init_reg(0x67, 0x7f); // STEPSEL, MTRPWM: partially overwritten during motor setup 164141cc406Sopenharmony_ci dev.reg.init_reg(0x68, 0x7f); // FSTPSEL, FASTPWM: partially overwritten during motor setup 165141cc406Sopenharmony_ci } else if (dev.model->model_id == ModelId::CANON_LIDE_90) { 166141cc406Sopenharmony_ci dev.reg.init_reg(0x66, 0x00); // PHFREQ 167141cc406Sopenharmony_ci dev.reg.init_reg(0x67, 0x40); // STEPSEL, MTRPWM: partially overwritten during motor setup 168141cc406Sopenharmony_ci dev.reg.init_reg(0x68, 0x40); // FSTPSEL, FASTPWM: partially overwritten during motor setup 169141cc406Sopenharmony_ci } 170141cc406Sopenharmony_ci dev.reg.init_reg(0x69, 0x10); // FSHDEC: overwritten during motor setup 171141cc406Sopenharmony_ci dev.reg.init_reg(0x6a, 0x10); // FMOVNO: overwritten during motor setup 172141cc406Sopenharmony_ci 173141cc406Sopenharmony_ci // 0x6b, 0x6c, 0x6d, 0x6e, 0x6f - set according to gpio tables. See gl842_init_gpio. 174141cc406Sopenharmony_ci 175141cc406Sopenharmony_ci dev.reg.init_reg(0x70, 0x00); // SENSOR_DEF 176141cc406Sopenharmony_ci dev.reg.init_reg(0x71, 0x00); // SENSOR_DEF 177141cc406Sopenharmony_ci dev.reg.init_reg(0x72, 0x00); // SENSOR_DEF 178141cc406Sopenharmony_ci dev.reg.init_reg(0x73, 0x00); // SENSOR_DEF 179141cc406Sopenharmony_ci dev.reg.init_reg(0x74, 0x00); // SENSOR_DEF 180141cc406Sopenharmony_ci dev.reg.init_reg(0x75, 0x00); // SENSOR_DEF 181141cc406Sopenharmony_ci dev.reg.init_reg(0x76, 0x00); // SENSOR_DEF 182141cc406Sopenharmony_ci dev.reg.init_reg(0x77, 0x00); // SENSOR_DEF 183141cc406Sopenharmony_ci dev.reg.init_reg(0x78, 0x00); // SENSOR_DEF 184141cc406Sopenharmony_ci dev.reg.init_reg(0x79, 0x00); // SENSOR_DEF 185141cc406Sopenharmony_ci dev.reg.init_reg(0x7a, 0x00); // SENSOR_DEF 186141cc406Sopenharmony_ci dev.reg.init_reg(0x7b, 0x00); // SENSOR_DEF 187141cc406Sopenharmony_ci dev.reg.init_reg(0x7c, 0x00); // SENSOR_DEF 188141cc406Sopenharmony_ci dev.reg.init_reg(0x7d, 0x00); // SENSOR_DEF 189141cc406Sopenharmony_ci 190141cc406Sopenharmony_ci // 0x7e - set according to gpio tables. See gl842_init_gpio. 191141cc406Sopenharmony_ci 192141cc406Sopenharmony_ci dev.reg.init_reg(0x7f, 0x00); // SENSOR_DEF 193141cc406Sopenharmony_ci 194141cc406Sopenharmony_ci // VRHOME, VRMOVE, VRBACK, VRSCAN: Vref settings of the motor driver IC for 195141cc406Sopenharmony_ci // moving in various situations. 196141cc406Sopenharmony_ci dev.reg.init_reg(0x80, 0x00); // MOTOR_PROFILE 197141cc406Sopenharmony_ci 198141cc406Sopenharmony_ci if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 199141cc406Sopenharmony_ci dev.reg.init_reg(0x81, 0x00); 200141cc406Sopenharmony_ci dev.reg.init_reg(0x82, 0x00); 201141cc406Sopenharmony_ci dev.reg.init_reg(0x83, 0x00); 202141cc406Sopenharmony_ci dev.reg.init_reg(0x84, 0x00); 203141cc406Sopenharmony_ci dev.reg.init_reg(0x85, 0x00); 204141cc406Sopenharmony_ci dev.reg.init_reg(0x86, 0x00); 205141cc406Sopenharmony_ci dev.reg.init_reg(0x87, 0x00); 206141cc406Sopenharmony_ci } else if (dev.model->model_id == ModelId::CANON_LIDE_90) { 207141cc406Sopenharmony_ci dev.reg.init_reg(0x7e, 0x00); 208141cc406Sopenharmony_ci dev.reg.init_reg(0x81, 0x00); 209141cc406Sopenharmony_ci dev.reg.init_reg(0x82, 0x0f); 210141cc406Sopenharmony_ci dev.reg.init_reg(0x83, 0x00); 211141cc406Sopenharmony_ci dev.reg.init_reg(0x84, 0x0e); 212141cc406Sopenharmony_ci dev.reg.init_reg(0x85, 0x00); 213141cc406Sopenharmony_ci dev.reg.init_reg(0x86, 0x0d); 214141cc406Sopenharmony_ci dev.reg.init_reg(0x87, 0x00); 215141cc406Sopenharmony_ci dev.reg.init_reg(0x88, 0x00); 216141cc406Sopenharmony_ci dev.reg.init_reg(0x89, 0x00); 217141cc406Sopenharmony_ci } 218141cc406Sopenharmony_ci 219141cc406Sopenharmony_ci const auto& sensor = sanei_genesys_find_sensor_any(&dev); 220141cc406Sopenharmony_ci sanei_genesys_set_dpihw(dev.reg, sensor.register_dpihw); 221141cc406Sopenharmony_ci 222141cc406Sopenharmony_ci scanner_setup_sensor(dev, sensor, dev.reg); 223141cc406Sopenharmony_ci} 224141cc406Sopenharmony_ci 225141cc406Sopenharmony_ci// Set values of analog frontend 226141cc406Sopenharmony_civoid CommandSetGl842::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, 227141cc406Sopenharmony_ci std::uint8_t set) const 228141cc406Sopenharmony_ci{ 229141cc406Sopenharmony_ci DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" : 230141cc406Sopenharmony_ci set == AFE_SET ? "set" : 231141cc406Sopenharmony_ci set == AFE_POWER_SAVE ? "powersave" : "huh?"); 232141cc406Sopenharmony_ci (void) sensor; 233141cc406Sopenharmony_ci 234141cc406Sopenharmony_ci if (set == AFE_INIT) { 235141cc406Sopenharmony_ci dev->frontend = dev->frontend_initial; 236141cc406Sopenharmony_ci } 237141cc406Sopenharmony_ci 238141cc406Sopenharmony_ci // check analog frontend type 239141cc406Sopenharmony_ci // FIXME: looks like we write to that register with initial data 240141cc406Sopenharmony_ci std::uint8_t fe_type = dev->interface->read_register(REG_0x04) & REG_0x04_FESET; 241141cc406Sopenharmony_ci if (fe_type == 2 || dev->model->model_id == ModelId::CANON_LIDE_90) { 242141cc406Sopenharmony_ci for (const auto& reg : dev->frontend.regs) { 243141cc406Sopenharmony_ci dev->interface->write_fe_register(reg.address, reg.value); 244141cc406Sopenharmony_ci } 245141cc406Sopenharmony_ci return; 246141cc406Sopenharmony_ci } 247141cc406Sopenharmony_ci if (fe_type != 0) { 248141cc406Sopenharmony_ci throw SaneException(SANE_STATUS_UNSUPPORTED, "unsupported frontend type %d", fe_type); 249141cc406Sopenharmony_ci } 250141cc406Sopenharmony_ci 251141cc406Sopenharmony_ci for (unsigned i = 1; i <= 3; i++) { 252141cc406Sopenharmony_ci dev->interface->write_fe_register(i, dev->frontend.regs.get_value(0x00 + i)); 253141cc406Sopenharmony_ci } 254141cc406Sopenharmony_ci for (const auto& reg : sensor.custom_fe_regs) { 255141cc406Sopenharmony_ci dev->interface->write_fe_register(reg.address, reg.value); 256141cc406Sopenharmony_ci } 257141cc406Sopenharmony_ci 258141cc406Sopenharmony_ci for (unsigned i = 0; i < 3; i++) { 259141cc406Sopenharmony_ci dev->interface->write_fe_register(0x20 + i, dev->frontend.get_offset(i)); 260141cc406Sopenharmony_ci } 261141cc406Sopenharmony_ci 262141cc406Sopenharmony_ci for (unsigned i = 0; i < 3; i++) { 263141cc406Sopenharmony_ci dev->interface->write_fe_register(0x28 + i, dev->frontend.get_gain(i)); 264141cc406Sopenharmony_ci } 265141cc406Sopenharmony_ci} 266141cc406Sopenharmony_ci 267141cc406Sopenharmony_cistatic void gl842_init_motor_regs_scan(Genesys_Device* dev, 268141cc406Sopenharmony_ci const Genesys_Sensor& sensor, 269141cc406Sopenharmony_ci const ScanSession& session, 270141cc406Sopenharmony_ci Genesys_Register_Set* reg, 271141cc406Sopenharmony_ci const MotorProfile& motor_profile, 272141cc406Sopenharmony_ci unsigned int exposure, 273141cc406Sopenharmony_ci unsigned scan_yres, 274141cc406Sopenharmony_ci unsigned int scan_lines, 275141cc406Sopenharmony_ci unsigned int scan_dummy, 276141cc406Sopenharmony_ci unsigned int feed_steps, 277141cc406Sopenharmony_ci ScanFlag flags) 278141cc406Sopenharmony_ci{ 279141cc406Sopenharmony_ci DBG_HELPER_ARGS(dbg, "exposure=%d, scan_yres=%d, step_type=%d, scan_lines=%d, scan_dummy=%d, " 280141cc406Sopenharmony_ci "feed_steps=%d, flags=%x", 281141cc406Sopenharmony_ci exposure, scan_yres, static_cast<unsigned>(motor_profile.step_type), 282141cc406Sopenharmony_ci scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags)); 283141cc406Sopenharmony_ci 284141cc406Sopenharmony_ci unsigned step_multiplier = 2; 285141cc406Sopenharmony_ci bool use_fast_fed = false; 286141cc406Sopenharmony_ci 287141cc406Sopenharmony_ci if ((scan_yres >= 300 && feed_steps > 900) || (has_flag(flags, ScanFlag::FEEDING))) { 288141cc406Sopenharmony_ci use_fast_fed = true; 289141cc406Sopenharmony_ci } 290141cc406Sopenharmony_ci if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { 291141cc406Sopenharmony_ci use_fast_fed = false; 292141cc406Sopenharmony_ci } 293141cc406Sopenharmony_ci 294141cc406Sopenharmony_ci reg->set24(REG_LINCNT, scan_lines); 295141cc406Sopenharmony_ci 296141cc406Sopenharmony_ci reg->set8(REG_0x02, 0); 297141cc406Sopenharmony_ci sanei_genesys_set_motor_power(*reg, true); 298141cc406Sopenharmony_ci 299141cc406Sopenharmony_ci std::uint8_t reg02 = reg->get8(REG_0x02); 300141cc406Sopenharmony_ci if (use_fast_fed) { 301141cc406Sopenharmony_ci reg02 |= REG_0x02_FASTFED; 302141cc406Sopenharmony_ci } else { 303141cc406Sopenharmony_ci reg02 &= ~REG_0x02_FASTFED; 304141cc406Sopenharmony_ci } 305141cc406Sopenharmony_ci 306141cc406Sopenharmony_ci // in case of automatic go home, move until home sensor 307141cc406Sopenharmony_ci if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { 308141cc406Sopenharmony_ci reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME; 309141cc406Sopenharmony_ci } 310141cc406Sopenharmony_ci 311141cc406Sopenharmony_ci // disable backtracking if needed 312141cc406Sopenharmony_ci if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) || 313141cc406Sopenharmony_ci (scan_yres >= 2400) || 314141cc406Sopenharmony_ci (scan_yres >= sensor.full_resolution)) 315141cc406Sopenharmony_ci { 316141cc406Sopenharmony_ci reg02 |= REG_0x02_ACDCDIS; 317141cc406Sopenharmony_ci } 318141cc406Sopenharmony_ci 319141cc406Sopenharmony_ci if (has_flag(flags, ScanFlag::REVERSE)) { 320141cc406Sopenharmony_ci reg02 |= REG_0x02_MTRREV; 321141cc406Sopenharmony_ci } else { 322141cc406Sopenharmony_ci reg02 &= ~REG_0x02_MTRREV; 323141cc406Sopenharmony_ci } 324141cc406Sopenharmony_ci reg->set8(REG_0x02, reg02); 325141cc406Sopenharmony_ci 326141cc406Sopenharmony_ci // scan and backtracking slope table 327141cc406Sopenharmony_ci auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres, exposure, 328141cc406Sopenharmony_ci step_multiplier, motor_profile); 329141cc406Sopenharmony_ci 330141cc406Sopenharmony_ci scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table); 331141cc406Sopenharmony_ci scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table); 332141cc406Sopenharmony_ci scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table); 333141cc406Sopenharmony_ci 334141cc406Sopenharmony_ci reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier); 335141cc406Sopenharmony_ci reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier); 336141cc406Sopenharmony_ci reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier); 337141cc406Sopenharmony_ci 338141cc406Sopenharmony_ci // fast table 339141cc406Sopenharmony_ci const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session); 340141cc406Sopenharmony_ci if (fast_profile == nullptr) { 341141cc406Sopenharmony_ci fast_profile = &motor_profile; 342141cc406Sopenharmony_ci } 343141cc406Sopenharmony_ci 344141cc406Sopenharmony_ci auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier, 345141cc406Sopenharmony_ci *fast_profile); 346141cc406Sopenharmony_ci 347141cc406Sopenharmony_ci scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table); 348141cc406Sopenharmony_ci scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table); 349141cc406Sopenharmony_ci 350141cc406Sopenharmony_ci reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier); 351141cc406Sopenharmony_ci 352141cc406Sopenharmony_ci if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) { 353141cc406Sopenharmony_ci std::uint8_t vref = 0; 354141cc406Sopenharmony_ci vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL; 355141cc406Sopenharmony_ci vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK; 356141cc406Sopenharmony_ci vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST; 357141cc406Sopenharmony_ci vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME; 358141cc406Sopenharmony_ci reg->set8(REG_0x80, vref); 359141cc406Sopenharmony_ci } 360141cc406Sopenharmony_ci 361141cc406Sopenharmony_ci // subtract acceleration distance from feedl 362141cc406Sopenharmony_ci unsigned feedl = feed_steps; 363141cc406Sopenharmony_ci feedl <<= static_cast<unsigned>(motor_profile.step_type); 364141cc406Sopenharmony_ci 365141cc406Sopenharmony_ci unsigned dist = scan_table.table.size() / step_multiplier; 366141cc406Sopenharmony_ci 367141cc406Sopenharmony_ci if (use_fast_fed) { 368141cc406Sopenharmony_ci dist += (fast_table.table.size() / step_multiplier) * 2; 369141cc406Sopenharmony_ci } 370141cc406Sopenharmony_ci 371141cc406Sopenharmony_ci // make sure when don't insane value : XXX STEF XXX in this case we should 372141cc406Sopenharmony_ci // fall back to single table move 373141cc406Sopenharmony_ci if (dist < feedl) { 374141cc406Sopenharmony_ci feedl -= dist; 375141cc406Sopenharmony_ci } else { 376141cc406Sopenharmony_ci feedl = 1; 377141cc406Sopenharmony_ci } 378141cc406Sopenharmony_ci 379141cc406Sopenharmony_ci reg->set24(REG_FEEDL, feedl); 380141cc406Sopenharmony_ci 381141cc406Sopenharmony_ci // doesn't seem to matter that much 382141cc406Sopenharmony_ci std::uint32_t z1, z2; 383141cc406Sopenharmony_ci sanei_genesys_calculate_zmod(use_fast_fed, 384141cc406Sopenharmony_ci exposure, 385141cc406Sopenharmony_ci scan_table.table, 386141cc406Sopenharmony_ci scan_table.table.size() / step_multiplier, 387141cc406Sopenharmony_ci feedl, 388141cc406Sopenharmony_ci scan_table.table.size() / step_multiplier, 389141cc406Sopenharmony_ci &z1, 390141cc406Sopenharmony_ci &z2); 391141cc406Sopenharmony_ci if (scan_yres > 600) { 392141cc406Sopenharmony_ci z1 = 0; 393141cc406Sopenharmony_ci z2 = 0; 394141cc406Sopenharmony_ci } 395141cc406Sopenharmony_ci 396141cc406Sopenharmony_ci reg->set24(REG_Z1MOD, z1); 397141cc406Sopenharmony_ci reg->set24(REG_Z2MOD, z2); 398141cc406Sopenharmony_ci 399141cc406Sopenharmony_ci reg->set8_mask(REG_0x1E, scan_dummy, 0x0f); 400141cc406Sopenharmony_ci 401141cc406Sopenharmony_ci reg->set8_mask(REG_0x67, static_cast<unsigned>(motor_profile.step_type) << REG_0x67S_STEPSEL, 402141cc406Sopenharmony_ci REG_0x67_STEPSEL); 403141cc406Sopenharmony_ci reg->set8_mask(REG_0x68, static_cast<unsigned>(fast_profile->step_type) << REG_0x68S_FSTPSEL, 404141cc406Sopenharmony_ci REG_0x68_FSTPSEL); 405141cc406Sopenharmony_ci 406141cc406Sopenharmony_ci // steps for STOP table 407141cc406Sopenharmony_ci reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier); 408141cc406Sopenharmony_ci} 409141cc406Sopenharmony_ci 410141cc406Sopenharmony_cistatic void gl842_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor, 411141cc406Sopenharmony_ci Genesys_Register_Set* reg, unsigned int exposure, 412141cc406Sopenharmony_ci const ScanSession& session) 413141cc406Sopenharmony_ci{ 414141cc406Sopenharmony_ci DBG_HELPER(dbg); 415141cc406Sopenharmony_ci 416141cc406Sopenharmony_ci scanner_setup_sensor(*dev, sensor, *reg); 417141cc406Sopenharmony_ci 418141cc406Sopenharmony_ci dev->cmd_set->set_fe(dev, sensor, AFE_SET); 419141cc406Sopenharmony_ci 420141cc406Sopenharmony_ci // enable shading 421141cc406Sopenharmony_ci regs_set_optical_off(dev->model->asic_type, *reg); 422141cc406Sopenharmony_ci if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) || 423141cc406Sopenharmony_ci has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) || 424141cc406Sopenharmony_ci session.use_host_side_calib) 425141cc406Sopenharmony_ci { 426141cc406Sopenharmony_ci reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET; 427141cc406Sopenharmony_ci 428141cc406Sopenharmony_ci } else { 429141cc406Sopenharmony_ci reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET; 430141cc406Sopenharmony_ci } 431141cc406Sopenharmony_ci 432141cc406Sopenharmony_ci bool use_shdarea = true; 433141cc406Sopenharmony_ci 434141cc406Sopenharmony_ci if (use_shdarea) { 435141cc406Sopenharmony_ci reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA; 436141cc406Sopenharmony_ci } else { 437141cc406Sopenharmony_ci reg->find_reg(REG_0x01).value &= ~REG_0x01_SHDAREA; 438141cc406Sopenharmony_ci } 439141cc406Sopenharmony_ci 440141cc406Sopenharmony_ci if (dev->model->model_id == ModelId::CANON_8600F) { 441141cc406Sopenharmony_ci reg->find_reg(REG_0x03).value |= REG_0x03_AVEENB; 442141cc406Sopenharmony_ci } else { 443141cc406Sopenharmony_ci reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB; 444141cc406Sopenharmony_ci } 445141cc406Sopenharmony_ci 446141cc406Sopenharmony_ci // FIXME: we probably don't need to set exposure to registers at this point. It was this way 447141cc406Sopenharmony_ci // before a refactor. 448141cc406Sopenharmony_ci sanei_genesys_set_lamp_power(dev, sensor, *reg, 449141cc406Sopenharmony_ci !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP)); 450141cc406Sopenharmony_ci 451141cc406Sopenharmony_ci // select XPA 452141cc406Sopenharmony_ci reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL; 453141cc406Sopenharmony_ci if (has_flag(session.params.flags, ScanFlag::USE_XPA)) { 454141cc406Sopenharmony_ci reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL; 455141cc406Sopenharmony_ci } 456141cc406Sopenharmony_ci reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA); 457141cc406Sopenharmony_ci 458141cc406Sopenharmony_ci // BW threshold 459141cc406Sopenharmony_ci reg->set8(REG_0x2E, 0x7f); 460141cc406Sopenharmony_ci reg->set8(REG_0x2F, 0x7f); 461141cc406Sopenharmony_ci 462141cc406Sopenharmony_ci // monochrome / color scan parameters 463141cc406Sopenharmony_ci std::uint8_t reg04 = reg->get8(REG_0x04); 464141cc406Sopenharmony_ci reg04 = reg04 & REG_0x04_FESET; 465141cc406Sopenharmony_ci 466141cc406Sopenharmony_ci switch (session.params.depth) { 467141cc406Sopenharmony_ci case 8: 468141cc406Sopenharmony_ci break; 469141cc406Sopenharmony_ci case 16: 470141cc406Sopenharmony_ci reg04 |= REG_0x04_BITSET; 471141cc406Sopenharmony_ci break; 472141cc406Sopenharmony_ci } 473141cc406Sopenharmony_ci 474141cc406Sopenharmony_ci if (session.params.channels == 1) { 475141cc406Sopenharmony_ci switch (session.params.color_filter) { 476141cc406Sopenharmony_ci case ColorFilter::RED: reg04 |= 0x14; break; 477141cc406Sopenharmony_ci case ColorFilter::BLUE: reg04 |= 0x1c; break; 478141cc406Sopenharmony_ci case ColorFilter::GREEN: reg04 |= 0x18; break; 479141cc406Sopenharmony_ci default: 480141cc406Sopenharmony_ci break; // should not happen 481141cc406Sopenharmony_ci } 482141cc406Sopenharmony_ci } else { 483141cc406Sopenharmony_ci switch (dev->frontend.layout.type) { 484141cc406Sopenharmony_ci case FrontendType::WOLFSON: 485141cc406Sopenharmony_ci // pixel by pixel 486141cc406Sopenharmony_ci reg04 |= 0x10; 487141cc406Sopenharmony_ci break; 488141cc406Sopenharmony_ci case FrontendType::ANALOG_DEVICES: 489141cc406Sopenharmony_ci // slow color pixel by pixel 490141cc406Sopenharmony_ci reg04 |= 0x20; 491141cc406Sopenharmony_ci break; 492141cc406Sopenharmony_ci default: 493141cc406Sopenharmony_ci throw SaneException("Invalid frontend type %d", 494141cc406Sopenharmony_ci static_cast<unsigned>(dev->frontend.layout.type)); 495141cc406Sopenharmony_ci } 496141cc406Sopenharmony_ci } 497141cc406Sopenharmony_ci 498141cc406Sopenharmony_ci reg->set8(REG_0x04, reg04); 499141cc406Sopenharmony_ci 500141cc406Sopenharmony_ci const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution, 501141cc406Sopenharmony_ci session.params.channels, 502141cc406Sopenharmony_ci session.params.scan_method); 503141cc406Sopenharmony_ci sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw); 504141cc406Sopenharmony_ci 505141cc406Sopenharmony_ci if (should_enable_gamma(session, sensor)) { 506141cc406Sopenharmony_ci reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB; 507141cc406Sopenharmony_ci } else { 508141cc406Sopenharmony_ci reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB; 509141cc406Sopenharmony_ci } 510141cc406Sopenharmony_ci 511141cc406Sopenharmony_ci reg->set16(REG_DPISET, sensor.register_dpiset); 512141cc406Sopenharmony_ci 513141cc406Sopenharmony_ci reg->set16(REG_STRPIXEL, session.pixel_startx); 514141cc406Sopenharmony_ci reg->set16(REG_ENDPIXEL, session.pixel_endx); 515141cc406Sopenharmony_ci 516141cc406Sopenharmony_ci if (dev->model->is_cis) { 517141cc406Sopenharmony_ci reg->set24(REG_MAXWD, session.output_line_bytes_raw * session.params.channels); 518141cc406Sopenharmony_ci } else { 519141cc406Sopenharmony_ci reg->set24(REG_MAXWD, session.output_line_bytes_raw); 520141cc406Sopenharmony_ci } 521141cc406Sopenharmony_ci 522141cc406Sopenharmony_ci unsigned tgtime = exposure / 65536 + 1; 523141cc406Sopenharmony_ci reg->set16(REG_LPERIOD, exposure / tgtime); 524141cc406Sopenharmony_ci 525141cc406Sopenharmony_ci reg->set8(REG_DUMMY, sensor.dummy_pixel); 526141cc406Sopenharmony_ci} 527141cc406Sopenharmony_ci 528141cc406Sopenharmony_civoid CommandSetGl842::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor, 529141cc406Sopenharmony_ci Genesys_Register_Set* reg, 530141cc406Sopenharmony_ci const ScanSession& session) const 531141cc406Sopenharmony_ci{ 532141cc406Sopenharmony_ci DBG_HELPER(dbg); 533141cc406Sopenharmony_ci session.assert_computed(); 534141cc406Sopenharmony_ci 535141cc406Sopenharmony_ci // we enable true gray for cis scanners only, and just when doing scan since color calibration 536141cc406Sopenharmony_ci // is OK for this mode 537141cc406Sopenharmony_ci 538141cc406Sopenharmony_ci int dummy = 0; 539141cc406Sopenharmony_ci 540141cc406Sopenharmony_ci /* slope_dpi */ 541141cc406Sopenharmony_ci /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ 542141cc406Sopenharmony_ci int slope_dpi = 0; 543141cc406Sopenharmony_ci if (dev->model->is_cis) { 544141cc406Sopenharmony_ci slope_dpi = session.params.yres * session.params.channels; 545141cc406Sopenharmony_ci } else { 546141cc406Sopenharmony_ci slope_dpi = session.params.yres; 547141cc406Sopenharmony_ci } 548141cc406Sopenharmony_ci slope_dpi = slope_dpi * (1 + dummy); 549141cc406Sopenharmony_ci 550141cc406Sopenharmony_ci int exposure = sensor.exposure_lperiod; 551141cc406Sopenharmony_ci if (exposure < 0) { 552141cc406Sopenharmony_ci throw std::runtime_error("Exposure not defined in sensor definition"); 553141cc406Sopenharmony_ci } 554141cc406Sopenharmony_ci if (dev->model->model_id == ModelId::CANON_LIDE_90) { 555141cc406Sopenharmony_ci exposure *= 2; 556141cc406Sopenharmony_ci } 557141cc406Sopenharmony_ci const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure, session); 558141cc406Sopenharmony_ci 559141cc406Sopenharmony_ci // now _LOGICAL_ optical values used are known, setup registers 560141cc406Sopenharmony_ci gl842_init_optical_regs_scan(dev, sensor, reg, exposure, session); 561141cc406Sopenharmony_ci gl842_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure, slope_dpi, 562141cc406Sopenharmony_ci session.optical_line_count, dummy, session.params.starty, 563141cc406Sopenharmony_ci session.params.flags); 564141cc406Sopenharmony_ci 565141cc406Sopenharmony_ci setup_image_pipeline(*dev, session); 566141cc406Sopenharmony_ci 567141cc406Sopenharmony_ci dev->read_active = true; 568141cc406Sopenharmony_ci 569141cc406Sopenharmony_ci dev->session = session; 570141cc406Sopenharmony_ci 571141cc406Sopenharmony_ci dev->total_bytes_read = 0; 572141cc406Sopenharmony_ci dev->total_bytes_to_read = (size_t)session.output_line_bytes_requested * (size_t)session.params.lines; 573141cc406Sopenharmony_ci} 574141cc406Sopenharmony_ci 575141cc406Sopenharmony_ciScanSession CommandSetGl842::calculate_scan_session(const Genesys_Device* dev, 576141cc406Sopenharmony_ci const Genesys_Sensor& sensor, 577141cc406Sopenharmony_ci const Genesys_Settings& settings) const 578141cc406Sopenharmony_ci{ 579141cc406Sopenharmony_ci DBG_HELPER(dbg); 580141cc406Sopenharmony_ci debug_dump(DBG_info, settings); 581141cc406Sopenharmony_ci 582141cc406Sopenharmony_ci ScanFlag flags = ScanFlag::NONE; 583141cc406Sopenharmony_ci 584141cc406Sopenharmony_ci float move = 0.0f; 585141cc406Sopenharmony_ci if (settings.scan_method == ScanMethod::TRANSPARENCY || 586141cc406Sopenharmony_ci settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) 587141cc406Sopenharmony_ci { 588141cc406Sopenharmony_ci // note: scanner_move_to_ta() function has already been called and the sensor is at the 589141cc406Sopenharmony_ci // transparency adapter 590141cc406Sopenharmony_ci if (!dev->ignore_offsets) { 591141cc406Sopenharmony_ci move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta; 592141cc406Sopenharmony_ci } 593141cc406Sopenharmony_ci flags |= ScanFlag::USE_XPA; 594141cc406Sopenharmony_ci } else { 595141cc406Sopenharmony_ci if (!dev->ignore_offsets) { 596141cc406Sopenharmony_ci move = dev->model->y_offset; 597141cc406Sopenharmony_ci } 598141cc406Sopenharmony_ci } 599141cc406Sopenharmony_ci 600141cc406Sopenharmony_ci move += settings.tl_y; 601141cc406Sopenharmony_ci 602141cc406Sopenharmony_ci int move_dpi = dev->motor.base_ydpi; 603141cc406Sopenharmony_ci move = static_cast<float>((move * move_dpi) / MM_PER_INCH); 604141cc406Sopenharmony_ci 605141cc406Sopenharmony_ci float start = 0.0f; 606141cc406Sopenharmony_ci if (settings.scan_method==ScanMethod::TRANSPARENCY || 607141cc406Sopenharmony_ci settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) 608141cc406Sopenharmony_ci { 609141cc406Sopenharmony_ci start = dev->model->x_offset_ta; 610141cc406Sopenharmony_ci } else { 611141cc406Sopenharmony_ci start = dev->model->x_offset; 612141cc406Sopenharmony_ci } 613141cc406Sopenharmony_ci start = start + settings.tl_x; 614141cc406Sopenharmony_ci 615141cc406Sopenharmony_ci start = static_cast<float>((start * settings.xres) / MM_PER_INCH); 616141cc406Sopenharmony_ci 617141cc406Sopenharmony_ci ScanSession session; 618141cc406Sopenharmony_ci session.params.xres = settings.xres; 619141cc406Sopenharmony_ci session.params.yres = settings.yres; 620141cc406Sopenharmony_ci session.params.startx = static_cast<unsigned>(start); 621141cc406Sopenharmony_ci session.params.starty = static_cast<unsigned>(move); 622141cc406Sopenharmony_ci session.params.pixels = settings.pixels; 623141cc406Sopenharmony_ci session.params.requested_pixels = settings.requested_pixels; 624141cc406Sopenharmony_ci session.params.lines = settings.lines; 625141cc406Sopenharmony_ci session.params.depth = settings.depth; 626141cc406Sopenharmony_ci session.params.channels = settings.get_channels(); 627141cc406Sopenharmony_ci session.params.scan_method = settings.scan_method; 628141cc406Sopenharmony_ci session.params.scan_mode = settings.scan_mode; 629141cc406Sopenharmony_ci session.params.color_filter = settings.color_filter; 630141cc406Sopenharmony_ci session.params.contrast_adjustment = settings.contrast; 631141cc406Sopenharmony_ci session.params.brightness_adjustment = settings.brightness; 632141cc406Sopenharmony_ci session.params.flags = flags; 633141cc406Sopenharmony_ci compute_session(dev, session, sensor); 634141cc406Sopenharmony_ci 635141cc406Sopenharmony_ci return session; 636141cc406Sopenharmony_ci} 637141cc406Sopenharmony_ci 638141cc406Sopenharmony_civoid CommandSetGl842::save_power(Genesys_Device* dev, bool enable) const 639141cc406Sopenharmony_ci{ 640141cc406Sopenharmony_ci (void) dev; 641141cc406Sopenharmony_ci DBG_HELPER_ARGS(dbg, "enable = %d", enable); 642141cc406Sopenharmony_ci} 643141cc406Sopenharmony_ci 644141cc406Sopenharmony_civoid CommandSetGl842::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const 645141cc406Sopenharmony_ci{ 646141cc406Sopenharmony_ci (void) dev; 647141cc406Sopenharmony_ci DBG_HELPER_ARGS(dbg, "delay = %d", delay); 648141cc406Sopenharmony_ci} 649141cc406Sopenharmony_ci 650141cc406Sopenharmony_civoid CommandSetGl842::eject_document(Genesys_Device* dev) const 651141cc406Sopenharmony_ci{ 652141cc406Sopenharmony_ci (void) dev; 653141cc406Sopenharmony_ci DBG_HELPER(dbg); 654141cc406Sopenharmony_ci} 655141cc406Sopenharmony_ci 656141cc406Sopenharmony_ci 657141cc406Sopenharmony_civoid CommandSetGl842::load_document(Genesys_Device* dev) const 658141cc406Sopenharmony_ci{ 659141cc406Sopenharmony_ci DBG_HELPER(dbg); 660141cc406Sopenharmony_ci (void) dev; 661141cc406Sopenharmony_ci} 662141cc406Sopenharmony_ci 663141cc406Sopenharmony_civoid CommandSetGl842::detect_document_end(Genesys_Device* dev) const 664141cc406Sopenharmony_ci{ 665141cc406Sopenharmony_ci DBG_HELPER(dbg); 666141cc406Sopenharmony_ci (void) dev; 667141cc406Sopenharmony_ci throw SaneException(SANE_STATUS_UNSUPPORTED); 668141cc406Sopenharmony_ci} 669141cc406Sopenharmony_ci 670141cc406Sopenharmony_ci// Send the low-level scan command 671141cc406Sopenharmony_civoid CommandSetGl842::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor, 672141cc406Sopenharmony_ci Genesys_Register_Set* reg, bool start_motor) const 673141cc406Sopenharmony_ci{ 674141cc406Sopenharmony_ci DBG_HELPER(dbg); 675141cc406Sopenharmony_ci (void) sensor; 676141cc406Sopenharmony_ci 677141cc406Sopenharmony_ci if (reg->state.is_xpa_on && reg->state.is_lamp_on && 678141cc406Sopenharmony_ci !has_flag(dev->model->flags, ModelFlag::TA_NO_SECONDARY_LAMP)) 679141cc406Sopenharmony_ci { 680141cc406Sopenharmony_ci dev->cmd_set->set_xpa_lamp_power(*dev, true); 681141cc406Sopenharmony_ci } 682141cc406Sopenharmony_ci if (reg->state.is_xpa_on && !has_flag(dev->model->flags, ModelFlag::UTA_NO_SECONDARY_MOTOR)) { 683141cc406Sopenharmony_ci dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY); 684141cc406Sopenharmony_ci } 685141cc406Sopenharmony_ci 686141cc406Sopenharmony_ci if (dev->model->model_id == ModelId::CANON_LIDE_90) { 687141cc406Sopenharmony_ci if (has_flag(dev->session.params.flags, ScanFlag::REVERSE)) { 688141cc406Sopenharmony_ci dev->interface->write_register(REG_0x6B, 0x01); 689141cc406Sopenharmony_ci dev->interface->write_register(REG_0x6C, 0x02); 690141cc406Sopenharmony_ci } else { 691141cc406Sopenharmony_ci dev->interface->write_register(REG_0x6B, 0x03); 692141cc406Sopenharmony_ci switch (dev->session.params.xres) { 693141cc406Sopenharmony_ci case 150: dev->interface->write_register(REG_0x6C, 0x74); break; 694141cc406Sopenharmony_ci case 300: dev->interface->write_register(REG_0x6C, 0x38); break; 695141cc406Sopenharmony_ci case 600: dev->interface->write_register(REG_0x6C, 0x1c); break; 696141cc406Sopenharmony_ci case 1200: dev->interface->write_register(REG_0x6C, 0x2c); break; 697141cc406Sopenharmony_ci case 2400: dev->interface->write_register(REG_0x6C, 0x0c); break; 698141cc406Sopenharmony_ci default: 699141cc406Sopenharmony_ci break; 700141cc406Sopenharmony_ci } 701141cc406Sopenharmony_ci } 702141cc406Sopenharmony_ci dev->interface->sleep_ms(100); 703141cc406Sopenharmony_ci } 704141cc406Sopenharmony_ci 705141cc406Sopenharmony_ci scanner_clear_scan_and_feed_counts(*dev); 706141cc406Sopenharmony_ci 707141cc406Sopenharmony_ci // enable scan and motor 708141cc406Sopenharmony_ci std::uint8_t val = dev->interface->read_register(REG_0x01); 709141cc406Sopenharmony_ci val |= REG_0x01_SCAN; 710141cc406Sopenharmony_ci dev->interface->write_register(REG_0x01, val); 711141cc406Sopenharmony_ci 712141cc406Sopenharmony_ci scanner_start_action(*dev, start_motor); 713141cc406Sopenharmony_ci 714141cc406Sopenharmony_ci switch (reg->state.motor_mode) { 715141cc406Sopenharmony_ci case MotorMode::PRIMARY: { 716141cc406Sopenharmony_ci if (reg->state.is_motor_on) { 717141cc406Sopenharmony_ci dev->advance_head_pos_by_session(ScanHeadId::PRIMARY); 718141cc406Sopenharmony_ci } 719141cc406Sopenharmony_ci break; 720141cc406Sopenharmony_ci } 721141cc406Sopenharmony_ci case MotorMode::PRIMARY_AND_SECONDARY: { 722141cc406Sopenharmony_ci if (reg->state.is_motor_on) { 723141cc406Sopenharmony_ci dev->advance_head_pos_by_session(ScanHeadId::PRIMARY); 724141cc406Sopenharmony_ci dev->advance_head_pos_by_session(ScanHeadId::SECONDARY); 725141cc406Sopenharmony_ci } 726141cc406Sopenharmony_ci break; 727141cc406Sopenharmony_ci } 728141cc406Sopenharmony_ci case MotorMode::SECONDARY: { 729141cc406Sopenharmony_ci if (reg->state.is_motor_on) { 730141cc406Sopenharmony_ci dev->advance_head_pos_by_session(ScanHeadId::SECONDARY); 731141cc406Sopenharmony_ci } 732141cc406Sopenharmony_ci break; 733141cc406Sopenharmony_ci } 734141cc406Sopenharmony_ci } 735141cc406Sopenharmony_ci} 736141cc406Sopenharmony_ci 737141cc406Sopenharmony_civoid CommandSetGl842::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg, 738141cc406Sopenharmony_ci bool check_stop) const 739141cc406Sopenharmony_ci{ 740141cc406Sopenharmony_ci DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop); 741141cc406Sopenharmony_ci 742141cc406Sopenharmony_ci if (reg->state.is_xpa_on) { 743141cc406Sopenharmony_ci dev->cmd_set->set_xpa_lamp_power(*dev, false); 744141cc406Sopenharmony_ci } 745141cc406Sopenharmony_ci 746141cc406Sopenharmony_ci if (!dev->model->is_sheetfed) { 747141cc406Sopenharmony_ci scanner_stop_action(*dev); 748141cc406Sopenharmony_ci } 749141cc406Sopenharmony_ci} 750141cc406Sopenharmony_ci 751141cc406Sopenharmony_civoid CommandSetGl842::move_back_home(Genesys_Device* dev, bool wait_until_home) const 752141cc406Sopenharmony_ci{ 753141cc406Sopenharmony_ci scanner_move_back_home(*dev, wait_until_home); 754141cc406Sopenharmony_ci} 755141cc406Sopenharmony_ci 756141cc406Sopenharmony_civoid CommandSetGl842::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor, 757141cc406Sopenharmony_ci Genesys_Register_Set& regs) const 758141cc406Sopenharmony_ci{ 759141cc406Sopenharmony_ci DBG_HELPER(dbg); 760141cc406Sopenharmony_ci int move; 761141cc406Sopenharmony_ci 762141cc406Sopenharmony_ci float calib_size_mm = 0; 763141cc406Sopenharmony_ci if (dev->settings.scan_method == ScanMethod::TRANSPARENCY || 764141cc406Sopenharmony_ci dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) 765141cc406Sopenharmony_ci { 766141cc406Sopenharmony_ci calib_size_mm = dev->model->y_size_calib_ta_mm; 767141cc406Sopenharmony_ci } else { 768141cc406Sopenharmony_ci calib_size_mm = dev->model->y_size_calib_mm; 769141cc406Sopenharmony_ci } 770141cc406Sopenharmony_ci 771141cc406Sopenharmony_ci unsigned resolution = sensor.shading_resolution; 772141cc406Sopenharmony_ci 773141cc406Sopenharmony_ci unsigned channels = 3; 774141cc406Sopenharmony_ci const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels, 775141cc406Sopenharmony_ci dev->settings.scan_method); 776141cc406Sopenharmony_ci 777141cc406Sopenharmony_ci unsigned calib_pixels = 0; 778141cc406Sopenharmony_ci unsigned calib_pixels_offset = 0; 779141cc406Sopenharmony_ci 780141cc406Sopenharmony_ci if (should_calibrate_only_active_area(*dev, dev->settings)) { 781141cc406Sopenharmony_ci float offset = dev->model->x_offset_ta; 782141cc406Sopenharmony_ci // FIXME: we should use resolution here 783141cc406Sopenharmony_ci offset = static_cast<float>((offset * dev->settings.xres) / MM_PER_INCH); 784141cc406Sopenharmony_ci 785141cc406Sopenharmony_ci float size = dev->model->x_size_ta; 786141cc406Sopenharmony_ci size = static_cast<float>((size * dev->settings.xres) / MM_PER_INCH); 787141cc406Sopenharmony_ci 788141cc406Sopenharmony_ci calib_pixels_offset = static_cast<std::size_t>(offset); 789141cc406Sopenharmony_ci calib_pixels = static_cast<std::size_t>(size); 790141cc406Sopenharmony_ci } else { 791141cc406Sopenharmony_ci calib_pixels_offset = 0; 792141cc406Sopenharmony_ci calib_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH; 793141cc406Sopenharmony_ci } 794141cc406Sopenharmony_ci 795141cc406Sopenharmony_ci ScanFlag flags = ScanFlag::DISABLE_SHADING | 796141cc406Sopenharmony_ci ScanFlag::DISABLE_GAMMA | 797141cc406Sopenharmony_ci ScanFlag::DISABLE_BUFFER_FULL_MOVE; 798141cc406Sopenharmony_ci 799141cc406Sopenharmony_ci if (dev->settings.scan_method == ScanMethod::TRANSPARENCY || 800141cc406Sopenharmony_ci dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) 801141cc406Sopenharmony_ci { 802141cc406Sopenharmony_ci // note: scanner_move_to_ta() function has already been called and the sensor is at the 803141cc406Sopenharmony_ci // transparency adapter 804141cc406Sopenharmony_ci move = static_cast<int>(dev->model->y_offset_calib_white_ta - 805141cc406Sopenharmony_ci dev->model->y_offset_sensor_to_ta); 806141cc406Sopenharmony_ci flags |= ScanFlag::USE_XPA; 807141cc406Sopenharmony_ci } else { 808141cc406Sopenharmony_ci move = static_cast<int>(dev->model->y_offset_calib_white); 809141cc406Sopenharmony_ci } 810141cc406Sopenharmony_ci 811141cc406Sopenharmony_ci move = static_cast<int>((move * resolution) / MM_PER_INCH); 812141cc406Sopenharmony_ci unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH); 813141cc406Sopenharmony_ci 814141cc406Sopenharmony_ci ScanSession session; 815141cc406Sopenharmony_ci session.params.xres = resolution; 816141cc406Sopenharmony_ci session.params.yres = resolution; 817141cc406Sopenharmony_ci session.params.startx = calib_pixels_offset; 818141cc406Sopenharmony_ci session.params.starty = move; 819141cc406Sopenharmony_ci session.params.pixels = calib_pixels; 820141cc406Sopenharmony_ci session.params.lines = calib_lines; 821141cc406Sopenharmony_ci session.params.depth = 16; 822141cc406Sopenharmony_ci session.params.channels = channels; 823141cc406Sopenharmony_ci session.params.scan_method = dev->settings.scan_method; 824141cc406Sopenharmony_ci session.params.scan_mode = dev->settings.scan_mode; 825141cc406Sopenharmony_ci session.params.color_filter = dev->settings.color_filter; 826141cc406Sopenharmony_ci session.params.contrast_adjustment = dev->settings.contrast; 827141cc406Sopenharmony_ci session.params.brightness_adjustment = dev->settings.brightness; 828141cc406Sopenharmony_ci session.params.flags = flags; 829141cc406Sopenharmony_ci compute_session(dev, session, calib_sensor); 830141cc406Sopenharmony_ci 831141cc406Sopenharmony_ci init_regs_for_scan_session(dev, calib_sensor, ®s, session); 832141cc406Sopenharmony_ci 833141cc406Sopenharmony_ci dev->calib_session = session; 834141cc406Sopenharmony_ci} 835141cc406Sopenharmony_ci 836141cc406Sopenharmony_civoid CommandSetGl842::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const 837141cc406Sopenharmony_ci{ 838141cc406Sopenharmony_ci DBG_HELPER(dbg); 839141cc406Sopenharmony_ci 840141cc406Sopenharmony_ci if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) 841141cc406Sopenharmony_ci return; // No gamma on this model 842141cc406Sopenharmony_ci 843141cc406Sopenharmony_ci unsigned size = 256; 844141cc406Sopenharmony_ci 845141cc406Sopenharmony_ci std::vector<std::uint8_t> gamma(size * 2 * 3); 846141cc406Sopenharmony_ci 847141cc406Sopenharmony_ci std::vector<std::uint16_t> rgamma = get_gamma_table(dev, sensor, GENESYS_RED); 848141cc406Sopenharmony_ci std::vector<std::uint16_t> ggamma = get_gamma_table(dev, sensor, GENESYS_GREEN); 849141cc406Sopenharmony_ci std::vector<std::uint16_t> bgamma = get_gamma_table(dev, sensor, GENESYS_BLUE); 850141cc406Sopenharmony_ci 851141cc406Sopenharmony_ci // copy sensor specific's gamma tables 852141cc406Sopenharmony_ci for (unsigned i = 0; i < size; i++) { 853141cc406Sopenharmony_ci gamma[i * 2 + size * 0 + 0] = rgamma[i] & 0xff; 854141cc406Sopenharmony_ci gamma[i * 2 + size * 0 + 1] = (rgamma[i] >> 8) & 0xff; 855141cc406Sopenharmony_ci gamma[i * 2 + size * 2 + 0] = ggamma[i] & 0xff; 856141cc406Sopenharmony_ci gamma[i * 2 + size * 2 + 1] = (ggamma[i] >> 8) & 0xff; 857141cc406Sopenharmony_ci gamma[i * 2 + size * 4 + 0] = bgamma[i] & 0xff; 858141cc406Sopenharmony_ci gamma[i * 2 + size * 4 + 1] = (bgamma[i] >> 8) & 0xff; 859141cc406Sopenharmony_ci } 860141cc406Sopenharmony_ci 861141cc406Sopenharmony_ci dev->interface->write_gamma(0x28, 0x0000, gamma.data(), size * 2 * 3); 862141cc406Sopenharmony_ci} 863141cc406Sopenharmony_ci 864141cc406Sopenharmony_ciSensorExposure CommandSetGl842::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor, 865141cc406Sopenharmony_ci Genesys_Register_Set& regs) const 866141cc406Sopenharmony_ci{ 867141cc406Sopenharmony_ci return scanner_led_calibration(*dev, sensor, regs); 868141cc406Sopenharmony_ci} 869141cc406Sopenharmony_ci 870141cc406Sopenharmony_civoid CommandSetGl842::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor, 871141cc406Sopenharmony_ci Genesys_Register_Set& regs) const 872141cc406Sopenharmony_ci{ 873141cc406Sopenharmony_ci scanner_offset_calibration(*dev, sensor, regs); 874141cc406Sopenharmony_ci} 875141cc406Sopenharmony_ci 876141cc406Sopenharmony_civoid CommandSetGl842::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor, 877141cc406Sopenharmony_ci Genesys_Register_Set& regs, int dpi) const 878141cc406Sopenharmony_ci{ 879141cc406Sopenharmony_ci scanner_coarse_gain_calibration(*dev, sensor, regs, dpi); 880141cc406Sopenharmony_ci} 881141cc406Sopenharmony_ci 882141cc406Sopenharmony_civoid CommandSetGl842::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor, 883141cc406Sopenharmony_ci Genesys_Register_Set* reg) const 884141cc406Sopenharmony_ci{ 885141cc406Sopenharmony_ci DBG_HELPER(dbg); 886141cc406Sopenharmony_ci (void) sensor; 887141cc406Sopenharmony_ci 888141cc406Sopenharmony_ci unsigned channels = 3; 889141cc406Sopenharmony_ci unsigned resolution = dev->model->get_resolution_settings(dev->settings.scan_method) 890141cc406Sopenharmony_ci .get_nearest_resolution_x(600); 891141cc406Sopenharmony_ci 892141cc406Sopenharmony_ci const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels, 893141cc406Sopenharmony_ci dev->settings.scan_method); 894141cc406Sopenharmony_ci unsigned num_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH / 2; 895141cc406Sopenharmony_ci 896141cc406Sopenharmony_ci *reg = dev->reg; 897141cc406Sopenharmony_ci 898141cc406Sopenharmony_ci auto flags = ScanFlag::DISABLE_SHADING | 899141cc406Sopenharmony_ci ScanFlag::DISABLE_GAMMA | 900141cc406Sopenharmony_ci ScanFlag::SINGLE_LINE | 901141cc406Sopenharmony_ci ScanFlag::IGNORE_STAGGER_OFFSET | 902141cc406Sopenharmony_ci ScanFlag::IGNORE_COLOR_OFFSET; 903141cc406Sopenharmony_ci if (dev->settings.scan_method == ScanMethod::TRANSPARENCY || 904141cc406Sopenharmony_ci dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) 905141cc406Sopenharmony_ci { 906141cc406Sopenharmony_ci flags |= ScanFlag::USE_XPA; 907141cc406Sopenharmony_ci } 908141cc406Sopenharmony_ci 909141cc406Sopenharmony_ci ScanSession session; 910141cc406Sopenharmony_ci session.params.xres = resolution; 911141cc406Sopenharmony_ci session.params.yres = resolution; 912141cc406Sopenharmony_ci session.params.startx = (num_pixels / 2) * resolution / calib_sensor.full_resolution; 913141cc406Sopenharmony_ci session.params.starty = 0; 914141cc406Sopenharmony_ci session.params.pixels = num_pixels; 915141cc406Sopenharmony_ci session.params.lines = 1; 916141cc406Sopenharmony_ci session.params.depth = dev->model->bpp_color_values.front(); 917141cc406Sopenharmony_ci session.params.channels = channels; 918141cc406Sopenharmony_ci session.params.scan_method = dev->settings.scan_method; 919141cc406Sopenharmony_ci session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; 920141cc406Sopenharmony_ci session.params.color_filter = dev->settings.color_filter; 921141cc406Sopenharmony_ci session.params.contrast_adjustment = 0; 922141cc406Sopenharmony_ci session.params.brightness_adjustment = 0; 923141cc406Sopenharmony_ci session.params.flags = flags; 924141cc406Sopenharmony_ci 925141cc406Sopenharmony_ci compute_session(dev, session, calib_sensor); 926141cc406Sopenharmony_ci 927141cc406Sopenharmony_ci init_regs_for_scan_session(dev, calib_sensor, reg, session); 928141cc406Sopenharmony_ci 929141cc406Sopenharmony_ci sanei_genesys_set_motor_power(*reg, false); 930141cc406Sopenharmony_ci} 931141cc406Sopenharmony_ci 932141cc406Sopenharmony_cistatic void gl842_init_gpio(Genesys_Device* dev) 933141cc406Sopenharmony_ci{ 934141cc406Sopenharmony_ci DBG_HELPER(dbg); 935141cc406Sopenharmony_ci apply_registers_ordered(dev->gpo.regs, { 0x6e, 0x6f }, [&](const GenesysRegisterSetting& reg) 936141cc406Sopenharmony_ci { 937141cc406Sopenharmony_ci dev->interface->write_register(reg.address, reg.value); 938141cc406Sopenharmony_ci }); 939141cc406Sopenharmony_ci} 940141cc406Sopenharmony_ci 941141cc406Sopenharmony_civoid CommandSetGl842::asic_boot(Genesys_Device* dev, bool cold) const 942141cc406Sopenharmony_ci{ 943141cc406Sopenharmony_ci DBG_HELPER(dbg); 944141cc406Sopenharmony_ci 945141cc406Sopenharmony_ci if (cold) { 946141cc406Sopenharmony_ci dev->interface->write_register(0x0e, 0x01); 947141cc406Sopenharmony_ci dev->interface->write_register(0x0e, 0x00); 948141cc406Sopenharmony_ci } 949141cc406Sopenharmony_ci 950141cc406Sopenharmony_ci // setup initial register values 951141cc406Sopenharmony_ci gl842_init_registers(*dev); 952141cc406Sopenharmony_ci dev->interface->write_registers(dev->reg); 953141cc406Sopenharmony_ci 954141cc406Sopenharmony_ci if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 955141cc406Sopenharmony_ci std::uint8_t data[32] = { 956141cc406Sopenharmony_ci 0xd0, 0x38, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 957141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 958141cc406Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 959141cc406Sopenharmony_ci 0x6a, 0x73, 0x63, 0x68, 0x69, 0x65, 0x6e, 0x00, 960141cc406Sopenharmony_ci }; 961141cc406Sopenharmony_ci 962141cc406Sopenharmony_ci dev->interface->write_buffer(0x3c, 0x010a00, data, 32); 963141cc406Sopenharmony_ci } 964141cc406Sopenharmony_ci 965141cc406Sopenharmony_ci if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) { 966141cc406Sopenharmony_ci dev->interface->write_0x8c(0x10, 0x94); 967141cc406Sopenharmony_ci } 968141cc406Sopenharmony_ci if (dev->model->model_id == ModelId::CANON_LIDE_90) { 969141cc406Sopenharmony_ci dev->interface->write_0x8c(0x10, 0xd4); 970141cc406Sopenharmony_ci } 971141cc406Sopenharmony_ci 972141cc406Sopenharmony_ci // set RAM read address 973141cc406Sopenharmony_ci dev->interface->write_register(REG_0x2A, 0x00); 974141cc406Sopenharmony_ci dev->interface->write_register(REG_0x2B, 0x00); 975141cc406Sopenharmony_ci 976141cc406Sopenharmony_ci // setup gpio 977141cc406Sopenharmony_ci gl842_init_gpio(dev); 978141cc406Sopenharmony_ci dev->interface->sleep_ms(100); 979141cc406Sopenharmony_ci} 980141cc406Sopenharmony_ci 981141cc406Sopenharmony_civoid CommandSetGl842::init(Genesys_Device* dev) const 982141cc406Sopenharmony_ci{ 983141cc406Sopenharmony_ci DBG_INIT(); 984141cc406Sopenharmony_ci DBG_HELPER(dbg); 985141cc406Sopenharmony_ci 986141cc406Sopenharmony_ci sanei_genesys_asic_init(dev); 987141cc406Sopenharmony_ci} 988141cc406Sopenharmony_ci 989141cc406Sopenharmony_civoid CommandSetGl842::update_hardware_sensors(Genesys_Scanner* s) const 990141cc406Sopenharmony_ci{ 991141cc406Sopenharmony_ci DBG_HELPER(dbg); 992141cc406Sopenharmony_ci (void) s; 993141cc406Sopenharmony_ci} 994141cc406Sopenharmony_ci 995141cc406Sopenharmony_civoid CommandSetGl842::update_home_sensor_gpio(Genesys_Device& dev) const 996141cc406Sopenharmony_ci{ 997141cc406Sopenharmony_ci DBG_HELPER(dbg); 998141cc406Sopenharmony_ci if (dev.model->model_id == ModelId::CANON_LIDE_90) { 999141cc406Sopenharmony_ci std::uint8_t val = dev.interface->read_register(REG_0x6C); 1000141cc406Sopenharmony_ci val |= 0x02; 1001141cc406Sopenharmony_ci dev.interface->write_register(REG_0x6C, val); 1002141cc406Sopenharmony_ci } 1003141cc406Sopenharmony_ci} 1004141cc406Sopenharmony_ci 1005141cc406Sopenharmony_ci/** 1006141cc406Sopenharmony_ci * Send shading calibration data. The buffer is considered to always hold values 1007141cc406Sopenharmony_ci * for all the channels. 1008141cc406Sopenharmony_ci */ 1009141cc406Sopenharmony_civoid CommandSetGl842::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, 1010141cc406Sopenharmony_ci std::uint8_t* data, int size) const 1011141cc406Sopenharmony_ci{ 1012141cc406Sopenharmony_ci DBG_HELPER(dbg); 1013141cc406Sopenharmony_ci 1014141cc406Sopenharmony_ci int offset = 0; 1015141cc406Sopenharmony_ci unsigned length = size; 1016141cc406Sopenharmony_ci 1017141cc406Sopenharmony_ci if (dev->reg.get8(REG_0x01) & REG_0x01_SHDAREA) { 1018141cc406Sopenharmony_ci offset = dev->session.params.startx * sensor.shading_resolution / 1019141cc406Sopenharmony_ci dev->session.params.xres; 1020141cc406Sopenharmony_ci 1021141cc406Sopenharmony_ci length = dev->session.output_pixels * sensor.shading_resolution / 1022141cc406Sopenharmony_ci dev->session.params.xres; 1023141cc406Sopenharmony_ci 1024141cc406Sopenharmony_ci offset += sensor.shading_pixel_offset; 1025141cc406Sopenharmony_ci 1026141cc406Sopenharmony_ci // 16 bit words, 2 words per color, 3 color channels 1027141cc406Sopenharmony_ci length *= 2 * 2 * 3; 1028141cc406Sopenharmony_ci offset *= 2 * 2 * 3; 1029141cc406Sopenharmony_ci } else { 1030141cc406Sopenharmony_ci offset += sensor.shading_pixel_offset * 2 * 2 * 3; 1031141cc406Sopenharmony_ci } 1032141cc406Sopenharmony_ci 1033141cc406Sopenharmony_ci dev->interface->record_key_value("shading_offset", std::to_string(offset)); 1034141cc406Sopenharmony_ci dev->interface->record_key_value("shading_length", std::to_string(length)); 1035141cc406Sopenharmony_ci 1036141cc406Sopenharmony_ci std::vector<std::uint8_t> final_data(length, 0); 1037141cc406Sopenharmony_ci 1038141cc406Sopenharmony_ci unsigned count = 0; 1039141cc406Sopenharmony_ci if (offset < 0) { 1040141cc406Sopenharmony_ci count += (-offset); 1041141cc406Sopenharmony_ci length -= (-offset); 1042141cc406Sopenharmony_ci offset = 0; 1043141cc406Sopenharmony_ci } 1044141cc406Sopenharmony_ci if (static_cast<int>(length) + offset > static_cast<int>(size)) { 1045141cc406Sopenharmony_ci length = size - offset; 1046141cc406Sopenharmony_ci } 1047141cc406Sopenharmony_ci 1048141cc406Sopenharmony_ci for (unsigned i = 0; i < length; i++) { 1049141cc406Sopenharmony_ci final_data[count++] = data[offset + i]; 1050141cc406Sopenharmony_ci count++; 1051141cc406Sopenharmony_ci } 1052141cc406Sopenharmony_ci 1053141cc406Sopenharmony_ci dev->interface->write_buffer(0x3c, 0, final_data.data(), count); 1054141cc406Sopenharmony_ci} 1055141cc406Sopenharmony_ci 1056141cc406Sopenharmony_cibool CommandSetGl842::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const 1057141cc406Sopenharmony_ci{ 1058141cc406Sopenharmony_ci (void) dev; 1059141cc406Sopenharmony_ci return true; 1060141cc406Sopenharmony_ci} 1061141cc406Sopenharmony_ci 1062141cc406Sopenharmony_civoid CommandSetGl842::wait_for_motor_stop(Genesys_Device* dev) const 1063141cc406Sopenharmony_ci{ 1064141cc406Sopenharmony_ci (void) dev; 1065141cc406Sopenharmony_ci} 1066141cc406Sopenharmony_ci 1067141cc406Sopenharmony_ci} // namespace gl842 1068141cc406Sopenharmony_ci} // namespace genesys 1069