diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-09-10 19:11:27 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-09-10 19:11:27 +0200 | 
| commit | 7e9455b3b15671ff99ed168638c405e2acedb6df (patch) | |
| tree | 444e59ece236e09dc153f665e42160aeb0208c24 /backend/genesys/gl646.cpp | |
| parent | bc8a517abd2e11e1435f4ef042cfcc8648b62ef7 (diff) | |
| parent | bce41b3c37c2a68e7dab234ce0247755a61ceb40 (diff) | |
Merge branch 'release/debian/1.0.31-1_experimental1' into masterdebian/1.0.31-1_experimental1
Diffstat (limited to 'backend/genesys/gl646.cpp')
| -rw-r--r-- | backend/genesys/gl646.cpp | 1986 | 
1 files changed, 769 insertions, 1217 deletions
| diff --git a/backend/genesys/gl646.cpp b/backend/genesys/gl646.cpp index 04ee85e..61fa1e0 100644 --- a/backend/genesys/gl646.cpp +++ b/backend/genesys/gl646.cpp @@ -63,9 +63,336 @@ namespace {  constexpr unsigned CALIBRATION_LINES = 10;  } // namespace -static void gl646_send_slope_table(Genesys_Device* dev, int table_nr, -                                   const std::vector<uint16_t>& slope_table, -                                   int steps); +static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int resolution); + + +static void gl646_set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set, int dpi); + +static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor, +                        const ScanSession& session, bool move, +                        std::vector<uint8_t>& data, const char* test_identifier); +/** + * Send the stop scan command + * */ +static void end_scan_impl(Genesys_Device* dev, Genesys_Register_Set* reg, bool check_stop, +                          bool eject); + +/** + * master motor settings table entry + */ +struct Motor_Master +{ +    MotorId motor_id; +    unsigned dpi; +    unsigned channels; + +    // settings +    StepType steptype; +    bool fastmod; // fast scanning +    bool fastfed; // fast fed slope tables +    SANE_Int mtrpwm; +    MotorSlope slope1; +    MotorSlope slope2; +    SANE_Int fwdbwd; // forward/backward steps +}; + +/** + * master motor settings, for a given motor and dpi, + * it gives steps and speed informations + */ +static Motor_Master motor_master[] = { +    /* HP3670 motor settings */ +    {MotorId::HP3670, 50, 3, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(2329, 120, 229), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 75, 3, StepType::FULL, false, true, 1, +     MotorSlope::create_from_steps(3429, 305, 200), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 100, 3, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(2905, 187, 143), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 150, 3, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(3429, 305, 73), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 300, 3, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(1055, 563, 11), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 600, 3, StepType::FULL, false, true, 0, +     MotorSlope::create_from_steps(10687, 5126, 3), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670,1200, 3, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(15937, 6375, 3), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 50, 1, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(2329, 120, 229), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 75, 1, StepType::FULL, false, true, 1, +     MotorSlope::create_from_steps(3429, 305, 200), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 100, 1, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(2905, 187, 143), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 150, 1, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(3429, 305, 73), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 300, 1, StepType::HALF, false, true, 1, +     MotorSlope::create_from_steps(1055, 563, 11), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670, 600, 1, StepType::FULL, false, true, 0, +     MotorSlope::create_from_steps(10687, 5126, 3), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    {MotorId::HP3670,1200, 1, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(15937, 6375, 3), +     MotorSlope::create_from_steps(3399, 337, 192), 192}, + +    /* HP2400/G2410 motor settings base motor dpi = 600 */ +    {MotorId::HP2400, 50, 3, StepType::FULL, false, true, 63, +     MotorSlope::create_from_steps(8736, 601, 120), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 100, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(8736, 601, 120), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 150, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(15902, 902, 67), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 300, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(16703, 2188, 32), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 600, 3, StepType::FULL, false, true, 63, +     MotorSlope::create_from_steps(18761, 18761, 3), +     MotorSlope::create_from_steps(4905, 627, 192), 192}, + +    {MotorId::HP2400,1200, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(43501, 43501, 3), +     MotorSlope::create_from_steps(4905, 627, 192), 192}, + +    {MotorId::HP2400, 50, 1, StepType::FULL, false, true, 63, +     MotorSlope::create_from_steps(8736, 601, 120), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 100, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(8736, 601, 120), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 150, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(15902, 902, 67), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 300, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(16703, 2188, 32), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400, 600, 1, StepType::FULL, false, true, 63, +     MotorSlope::create_from_steps(18761, 18761, 3), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    {MotorId::HP2400,1200, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(43501, 43501, 3), +     MotorSlope::create_from_steps(4905, 337, 192), 192}, + +    /* XP 200 motor settings */ +    {MotorId::XP200, 75, 3, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(6000, 2136, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 100, 3, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(6000, 2850, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 200, 3, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(6999, 5700, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 250, 3, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(6999, 6999, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 300, 3, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(13500, 13500, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 600, 3, StepType::HALF, true, true, 0, +     MotorSlope::create_from_steps(31998, 31998, 4), +     MotorSlope::create_from_steps(12000, 1200, 2), 1}, + +    {MotorId::XP200, 75, 1, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(6000, 2000, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 100, 1, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(6000, 1300, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 200, 1, StepType::HALF, true, true, 0, +     MotorSlope::create_from_steps(6000, 3666, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 300, 1, StepType::HALF, true, false, 0, +     MotorSlope::create_from_steps(6500, 6500, 4), +     MotorSlope::create_from_steps(12000, 1200, 8), 1}, + +    {MotorId::XP200, 600, 1, StepType::HALF, true, true, 0, +     MotorSlope::create_from_steps(24000, 24000, 4), +     MotorSlope::create_from_steps(12000, 1200, 2), 1}, + +    /* HP scanjet 2300c */ +    {MotorId::HP2300, 75, 3, StepType::FULL, false, true, 63, +     MotorSlope::create_from_steps(8139, 560, 120), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 150, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(7903, 543, 67), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(2175, 1087, 3), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 600, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(8700, 4350, 3), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300,1200, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(17400, 8700, 3), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 75, 1, StepType::FULL, false, true, 63, +     MotorSlope::create_from_steps(8139, 560, 120), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 150, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(7903, 543, 67), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(2175, 1087, 3), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 600, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(8700, 4350, 3), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300,1200, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(17400, 8700, 3), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    /* non half ccd settings for 300 dpi +    {MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(5386, 2175, 44), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, + +    {MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63, +     MotorSlope::create_from_steps(5386, 2175, 44), +     MotorSlope::create_from_steps(4905, 337, 120), 16}, +    */ + +    /* MD5345/6471 motor settings */ +    /* vfinal=(exposure/(1200/dpi))/step_type */ +    {MotorId::MD_5345, 50, 3, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 250, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 75, 3, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 343, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 100, 3, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 458, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 150, 3, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 687, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 200, 3, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 916, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 300, 3, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 1375, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 400, 3, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(2000, 1833, 32), +     MotorSlope::create_from_steps(2000, 300, 255), 32}, + +    {MotorId::MD_5345, 500, 3, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(2291, 2291, 32), +     MotorSlope::create_from_steps(2000, 300, 255), 32}, + +    {MotorId::MD_5345, 600, 3, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(2750, 2750, 32), +     MotorSlope::create_from_steps(2000, 300, 255), 32}, + +    {MotorId::MD_5345, 1200, 3, StepType::QUARTER, false, true, 0, +     MotorSlope::create_from_steps(2750, 2750, 16), +     MotorSlope::create_from_steps(2000, 300, 255), 146}, + +    {MotorId::MD_5345, 2400, 3, StepType::QUARTER, false, true, 0, +     MotorSlope::create_from_steps(5500, 5500, 16), +     MotorSlope::create_from_steps(2000, 300, 255), 146}, + +    {MotorId::MD_5345, 50, 1, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 250, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 75, 1, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 343, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 100, 1, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 458, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 150, 1, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 687, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 200, 1, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 916, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 300, 1, StepType::HALF, false, true, 2, +     MotorSlope::create_from_steps(2500, 1375, 255), +     MotorSlope::create_from_steps(2000, 300, 255), 64}, + +    {MotorId::MD_5345, 400, 1, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(2000, 1833, 32), +     MotorSlope::create_from_steps(2000, 300, 255), 32}, + +    {MotorId::MD_5345, 500, 1, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(2291, 2291, 32), +     MotorSlope::create_from_steps(2000, 300, 255), 32}, + +    {MotorId::MD_5345, 600, 1, StepType::HALF, false, true, 0, +     MotorSlope::create_from_steps(2750, 2750, 32), +     MotorSlope::create_from_steps(2000, 300, 255), 32}, + +    {MotorId::MD_5345, 1200, 1, StepType::QUARTER, false, true, 0, +     MotorSlope::create_from_steps(2750, 2750, 16), +     MotorSlope::create_from_steps(2000, 300, 255), 146}, + +    {MotorId::MD_5345, 2400, 1, StepType::QUARTER, false, true, 0, +     MotorSlope::create_from_steps(5500, 5500, 16), +     MotorSlope::create_from_steps(2000, 300, 255), 146}, /* 5500 guessed */ +};  /**   * reads value from gpio endpoint @@ -105,44 +432,6 @@ static void gl646_stop_motor(Genesys_Device* dev)  }  /** - * find the closest match in mode tables for the given resolution and scan mode. - * @param sensor id of the sensor - * @param required required resolution - * @param color true is color mode - * @return the closest resolution for the sensor and mode - */ -static unsigned get_closest_resolution(SensorId sensor_id, int required, unsigned channels) -{ -    unsigned best_res = 0; -    unsigned best_diff = 9600; - -    for (const auto& sensor : *s_sensors) { -        if (sensor_id != sensor.sensor_id) -            continue; - -        // exit on perfect match -        if (sensor.resolutions.matches(required) && sensor.matches_channel_count(channels)) { -            DBG(DBG_info, "%s: match found for %d\n", __func__, required); -            return required; -        } - -        // computes distance and keep mode if it is closer than previous -        if (sensor.matches_channel_count(channels)) { -            for (auto res : sensor.resolutions.resolutions()) { -                unsigned curr_diff = std::abs(static_cast<int>(res) - static_cast<int>(required)); -                if (curr_diff < best_diff) { -                    best_res = res; -                    best_diff = curr_diff; -                } -            } -        } -    } - -    DBG(DBG_info, "%s: closest match for %d is %d\n", __func__, required, best_res); -    return best_res; -} - -/**   * Returns the cksel values used by the required scan mode.   * @param sensor id of the sensor   * @param required required resolution @@ -157,7 +446,6 @@ static int get_cksel(SensorId sensor_id, int required, unsigned channels)              sensor.matches_channel_count(channels))          {              unsigned cksel = sensor.ccd_pixels_per_system_pixel(); -            DBG(DBG_io, "%s: match found for %d (cksel=%d)\n", __func__, required, cksel);              return cksel;          }      } @@ -177,7 +465,6 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene      uint32_t move = session.params.starty; -  int i, nb;    Motor_Master *motor = nullptr;    uint32_t z1, z2;    int feedl; @@ -185,57 +472,47 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene    /* for the given resolution, search for master     * motor mode setting */ -  i = 0; -  nb = sizeof (motor_master) / sizeof (Motor_Master); -  while (i < nb) -    { -      if (dev->model->motor_id == motor_master[i].motor_id -          && motor_master[i].dpi == session.params.yres -          && motor_master[i].channels == session.params.channels) -	{ -	  motor = &motor_master[i]; -	} -      i++; +    for (unsigned i = 0; i < sizeof (motor_master) / sizeof (Motor_Master); ++i) { +        if (dev->model->motor_id == motor_master[i].motor_id && +            motor_master[i].dpi == session.params.yres && +            motor_master[i].channels == session.params.channels) +        { +            motor = &motor_master[i]; +        }      } -  if (motor == nullptr) -    { +    if (motor == nullptr) {          throw SaneException("unable to find settings for motor %d at %d dpi, color=%d",                              static_cast<unsigned>(dev->model->motor_id),                              session.params.yres, session.params.channels);      } -  /* now we can search for the specific sensor settings */ -  i = 0; - -    // now apply values from settings to registers -    regs->set16(REG_EXPR, sensor.exposure.red); -    regs->set16(REG_EXPG, sensor.exposure.green); -    regs->set16(REG_EXPB, sensor.exposure.blue); - -    for (const auto& reg : sensor.custom_regs) { -        regs->set8(reg.address, reg.value); -    } +    scanner_setup_sensor(*dev, sensor, *regs);    /* now generate slope tables : we are not using generate_slope_table3 yet */ -    auto slope_table1 = create_slope_table(motor->slope1, motor->slope1.max_speed_w, StepType::FULL, -                                           1, 4, get_slope_table_max_size(AsicType::GL646)); -    auto slope_table2 = create_slope_table(motor->slope2, motor->slope2.max_speed_w, StepType::FULL, -                                           1, 4, get_slope_table_max_size(AsicType::GL646)); +    auto slope_table1 = create_slope_table_for_speed(motor->slope1, motor->slope1.max_speed_w, +                                                     StepType::FULL, 1, 4, +                                                     get_slope_table_max_size(AsicType::GL646)); +    auto slope_table2 = create_slope_table_for_speed(motor->slope2, motor->slope2.max_speed_w, +                                                     StepType::FULL, 1, 4, +                                                     get_slope_table_max_size(AsicType::GL646));    /* R01 */    /* now setup other registers for final scan (ie with shading enabled) */    /* watch dog + shading + scan enable */ -    regs->find_reg(0x01).value |= REG_0x01_DOGENB | REG_0x01_DVDSET | REG_0x01_SCAN; +    regs->find_reg(0x01).value |= REG_0x01_DOGENB | REG_0x01_SCAN;      if (dev->model->is_cis) {          regs->find_reg(0x01).value |= REG_0x01_CISSET;      } else {          regs->find_reg(0x01).value &= ~REG_0x01_CISSET;      } -  /* if device has no calibration, don't enable shading correction */ -  if (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION) +    // if device has no calibration, don't enable shading correction +    if (has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) || +        has_flag(session.params.flags, ScanFlag::DISABLE_SHADING))      {          regs->find_reg(0x01).value &= ~REG_0x01_DVDSET; +    } else { +        regs->find_reg(0x01).value |= REG_0x01_DVDSET;      }      regs->find_reg(0x01).value &= ~REG_0x01_FASTMOD; @@ -284,7 +561,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene        break;      } -    if (dev->model->is_sheetfed) { +    if (dev->model->is_sheetfed || !has_flag(session.params.flags, ScanFlag::AUTO_GO_HOME)) {          regs->find_reg(0x02).value &= ~REG_0x02_AGOHOME;      } else {          regs->find_reg(0x02).value |= REG_0x02_AGOHOME; @@ -314,14 +591,20 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene              break;      } -    sanei_genesys_set_dpihw(*regs, sensor, sensor.optical_res); +    sanei_genesys_set_dpihw(*regs, sensor.full_resolution);    /* gamma enable for scans */ -    if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) { +    if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {          regs->find_reg(0x05).value |= REG_0x05_GMM14BIT;      } -    regs->find_reg(0x05).value &= ~REG_0x05_GMMENB; +    if (!has_flag(session.params.flags, ScanFlag::DISABLE_GAMMA) && +        session.params.depth < 16) +    { +        regs->find_reg(REG_0x05).value |= REG_0x05_GMMENB; +    } else { +        regs->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB; +    }    /* true CIS gray if needed */      if (dev->model->is_cis && session.params.channels == 1 && dev->settings.true_gray) { @@ -356,17 +639,17 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene      // the steps count must be different by at most 128, otherwise it's impossible to construct      // a proper backtracking curve. We're using slightly lower limit to allow at least a minimum      // distance between accelerations (forward_steps, backward_steps) -    if (slope_table1.steps_count > slope_table2.steps_count + 100) { -        slope_table2.steps_count += slope_table1.steps_count - 100; +    if (slope_table1.table.size() > slope_table2.table.size() + 100) { +        slope_table2.expand_table(slope_table1.table.size() - 100, 1);      } -    if (slope_table2.steps_count > slope_table1.steps_count + 100) { -        slope_table1.steps_count += slope_table2.steps_count - 100; +    if (slope_table2.table.size() > slope_table1.table.size() + 100) { +        slope_table1.expand_table(slope_table2.table.size() - 100, 1);      } -    if (slope_table1.steps_count >= slope_table2.steps_count) { -        backward_steps += (slope_table1.steps_count - slope_table2.steps_count) * 2; +    if (slope_table1.table.size() >= slope_table2.table.size()) { +        backward_steps += (slope_table1.table.size() - slope_table2.table.size()) * 2;      } else { -        forward_steps += (slope_table2.steps_count - slope_table1.steps_count) * 2; +        forward_steps += (slope_table2.table.size() - slope_table1.table.size()) * 2;      }      if (forward_steps > 255) { @@ -382,8 +665,8 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene          forward_steps -= backward_steps - 255;      } -    regs->find_reg(0x21).value = slope_table1.steps_count; -    regs->find_reg(0x24).value = slope_table2.steps_count; +    regs->find_reg(0x21).value = slope_table1.table.size(); +    regs->find_reg(0x24).value = slope_table2.table.size();      regs->find_reg(0x22).value = forward_steps;      regs->find_reg(0x23).value = backward_steps; @@ -401,8 +684,11 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene      regs->set24(REG_MAXWD, session.output_line_bytes); -    regs->set16(REG_DPISET, session.output_resolution * session.ccd_size_divisor * -                            sensor.ccd_pixels_per_system_pixel()); +    // FIXME: the incoming sensor is selected for incorrect resolution +    const auto& dpiset_sensor = sanei_genesys_find_sensor(dev, session.params.xres, +                                                          session.params.channels, +                                                          session.params.scan_method); +    regs->set16(REG_DPISET, dpiset_sensor.register_dpiset);      regs->set16(REG_LPERIOD, sensor.exposure_lperiod);    /* move distance must be adjusted to take into account the extra lines @@ -410,8 +696,8 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene    feedl = move;      if (session.num_staggered_lines + session.max_color_shift_lines > 0 && feedl != 0) { -        int feed_offset = ((session.max_color_shift_lines + session.num_staggered_lines) * dev->motor.optical_ydpi) / -                motor->dpi; +        unsigned total_lines = session.max_color_shift_lines + session.num_staggered_lines; +        int feed_offset = (total_lines * dev->motor.base_ydpi) / motor->dpi;          if (feedl > feed_offset) {              feedl = feedl - feed_offset;          } @@ -424,8 +710,6 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene    /* but head has moved due to shading calibration => dev->scanhead_position_primary */    if (feedl > 0)      { -      DBG(DBG_info, "%s: initial move=%d\n", __func__, feedl); -        /* TODO clean up this when I'll fully understand.         * for now, special casing each motor */          switch (dev->model->motor_id) { @@ -505,12 +789,12 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene  	  if (motor->fastfed)          { -                feedl = feedl - 2 * slope_table2.steps_count - -                        (slope_table1.steps_count >> step_shift); +                feedl = feedl - 2 * slope_table2.table.size() - +                        (slope_table1.table.size() >> step_shift);  	    }  	  else  	    { -                feedl = feedl - (slope_table1.steps_count >> step_shift); +                feedl = feedl - (slope_table1.table.size() >> step_shift);  	    }  	  break;          } @@ -520,7 +804,6 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene  	feedl = 0;      } -  DBG(DBG_info, "%s: final move=%d\n", __func__, feedl);      regs->set24(REG_FEEDL, feedl);    regs->find_reg(0x65).value = motor->mtrpwm; @@ -528,7 +811,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene      sanei_genesys_calculate_zmod(regs->find_reg(0x02).value & REG_0x02_FASTFED,                                   sensor.exposure_lperiod,                                   slope_table1.table, -                                 slope_table1.steps_count, +                                 slope_table1.table.size(),                                    move, motor->fwdbwd, &z1, &z2);    /* no z1/z2 for sheetfed scanners */ @@ -538,7 +821,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene      }      regs->set16(REG_Z1MOD, z1);      regs->set16(REG_Z2MOD, z2); -    regs->find_reg(0x6b).value = slope_table2.steps_count; +    regs->find_reg(0x6b).value = slope_table2.table.size();    regs->find_reg(0x6c).value =      (regs->find_reg(0x6c).value & REG_0x6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16)  								   & 0x07); @@ -548,10 +831,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene      // setup analog frontend      gl646_set_fe(dev, sensor, AFE_SET, session.output_resolution); -    dev->read_buffer.clear(); -    dev->read_buffer.alloc(session.buffer_size_read); - -    build_image_pipeline(dev, session); +    setup_image_pipeline(*dev, session);      dev->read_active = true; @@ -578,32 +858,8 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene          }      } -    gl646_send_slope_table(dev, 0, slope_table1.table, regs->get8(0x21)); -    gl646_send_slope_table(dev, 1, slope_table2.table, regs->get8(0x6b)); -} - - -/** copy sensor specific settings */ -/* *dev  : device infos -   *regs : regiters to be set -   extended : do extended set up -   ccd_size_divisor: set up for half ccd resolution -   all registers 08-0B, 10-1D, 52-5E are set up. They shouldn't -   appear anywhere else but in register init -*/ -static void -gl646_setup_sensor (Genesys_Device * dev, const Genesys_Sensor& sensor, Genesys_Register_Set * regs) -{ -    (void) dev; -    DBG(DBG_proc, "%s: start\n", __func__); - -    for (const auto& reg_setting : sensor.custom_base_regs) { -        regs->set8(reg_setting.address, reg_setting.value); -    } -    // FIXME: all other drivers don't set exposure here -    regs_set_exposure(AsicType::GL646, *regs, sensor.exposure); - -    DBG(DBG_proc, "%s: end\n", __func__); +    scanner_send_slope_table(dev, sensor, 0, slope_table1.table); +    scanner_send_slope_table(dev, sensor, 1, slope_table2.table);  }  /** @@ -632,8 +888,8 @@ gl646_init_regs (Genesys_Device * dev)      for (addr = 0x60; addr <= 0x6d; addr++)          dev->reg.init_reg(addr, 0); -  dev->reg.find_reg(0x01).value = 0x20 /*0x22 */ ;	/* enable shading, CCD, color, 1M */ -  dev->reg.find_reg(0x02).value = 0x30 /*0x38 */ ;	/* auto home, one-table-move, full step */ +    dev->reg.find_reg(0x01).value = 0x20 /*0x22 */ ;	/* enable shading, CCD, color, 1M */ +    dev->reg.find_reg(0x02).value = 0x30 /*0x38 */ ;	/* auto home, one-table-move, full step */      if (dev->model->motor_id == MotorId::MD_5345) {          dev->reg.find_reg(0x02).value |= 0x01; // half-step      } @@ -648,8 +904,8 @@ gl646_init_regs (Genesys_Device * dev)          default:        break;      } -  dev->reg.find_reg(0x03).value = 0x1f /*0x17 */ ;	/* lamp on */ -  dev->reg.find_reg(0x04).value = 0x13 /*0x03 */ ;	/* 8 bits data, 16 bits A/D, color, Wolfson fe *//* todo: according to spec, 0x0 is reserved? */ +    dev->reg.find_reg(0x03).value = 0x1f /*0x17 */ ;	/* lamp on */ +    dev->reg.find_reg(0x04).value = 0x13 /*0x03 */ ;	/* 8 bits data, 16 bits A/D, color, Wolfson fe *//* todo: according to spec, 0x0 is reserved? */    switch (dev->model->adc_id)      {      case AdcId::AD_XP200: @@ -664,9 +920,9 @@ gl646_init_regs (Genesys_Device * dev)    const auto& sensor = sanei_genesys_find_sensor_any(dev);    dev->reg.find_reg(0x05).value = 0x00;	/* 12 bits gamma, disable gamma, 24 clocks/pixel */ -    sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res); +    sanei_genesys_set_dpihw(dev->reg, sensor.full_resolution); -    if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) { +    if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {          dev->reg.find_reg(0x05).value |= REG_0x05_GMM14BIT;      }      if (dev->model->adc_id == AdcId::AD_XP200) { @@ -679,8 +935,7 @@ gl646_init_regs (Genesys_Device * dev)          dev->reg.find_reg(0x06).value = 0x18; // PWRBIT on, shading gain=8, normal AFE image capture      } - -  gl646_setup_sensor(dev, sensor, &dev->reg); +    scanner_setup_sensor(*dev, sensor, dev->reg);    dev->reg.find_reg(0x1e).value = 0xf0;	/* watch-dog time */ @@ -788,54 +1043,15 @@ gl646_init_regs (Genesys_Device * dev)    dev->reg.find_reg(0x6c).value = 0x00;	/* peroid times for LPeriod, expR,expG,expB, Z1MODE, Z2MODE (one period time) */  } - -// Send slope table for motor movement slope_table in machine byte order -static void gl646_send_slope_table(Genesys_Device* dev, int table_nr, -                                   const std::vector<uint16_t>& slope_table, -                                   int steps) -{ -    DBG_HELPER_ARGS(dbg, "table_nr = %d, steps = %d)=%d .. %d", table_nr, steps, slope_table[0], -                    slope_table[steps - 1]); -  int dpihw; -  int start_address; - -  dpihw = dev->reg.find_reg(0x05).value >> 6; - -  if (dpihw == 0)		/* 600 dpi */ -    start_address = 0x08000; -  else if (dpihw == 1)		/* 1200 dpi */ -    start_address = 0x10000; -  else if (dpihw == 2)		/* 2400 dpi */ -    start_address = 0x1f800; -    else { -        throw SaneException("Unexpected dpihw"); -    } - -  std::vector<uint8_t> table(steps * 2); -  for (int i = 0; i < steps; i++) -    { -      table[i * 2] = slope_table[i] & 0xff; -      table[i * 2 + 1] = slope_table[i] >> 8; -    } - -    if (dev->interface->is_mock()) { -        dev->interface->record_slope_table(table_nr, slope_table); -    } -    dev->interface->write_buffer(0x3c, start_address + table_nr * 0x100, table.data(), steps * 2); -} -  // Set values of Analog Device type frontend  static void gl646_set_ad_fe(Genesys_Device* dev, uint8_t set)  {      DBG_HELPER(dbg);    int i; -  if (set == AFE_INIT) -    { -        DBG(DBG_proc, "%s(): setting DAC %u\n", __func__, -            static_cast<unsigned>(dev->model->adc_id)); +    if (set == AFE_INIT) { -      dev->frontend = dev->frontend_initial; +        dev->frontend = dev->frontend_initial;          // write them to analog frontend          dev->interface->write_fe_register(0x00, dev->frontend.regs.get_value(0x00)); @@ -888,8 +1104,7 @@ static void gl646_wm_hp3670(Genesys_Device* dev, const Genesys_Sensor& sensor, u      default:			/* AFE_SET */        /* mode setup */        i = dev->frontend.regs.get_value(0x03); -      if (dpi > sensor.optical_res / 2) -	{ +            if (dpi > sensor.full_resolution / 2) {        /* fe_reg_0x03 must be 0x12 for 1200 dpi in WOLFSON_HP3670.         * WOLFSON_HP2400 in 1200 dpi mode works well with  	   * fe_reg_0x03 set to 0x32 or 0x12 but not to 0x02 */ @@ -947,11 +1162,8 @@ static void gl646_set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint      }    /* initialize analog frontend */ -  if (set == AFE_INIT) -    { -        DBG(DBG_proc, "%s(): setting DAC %u\n", __func__, -            static_cast<unsigned>(dev->model->adc_id)); -      dev->frontend = dev->frontend_initial; +    if (set == AFE_INIT) { +        dev->frontend = dev->frontend_initial;          // reset only done on init          dev->interface->write_fe_register(0x04, 0x80); @@ -1174,14 +1386,15 @@ void CommandSetGl646::load_document(Genesys_Device* dev) const    regs.init_reg(0x24, 4);    /* generate slope table 2 */ -    auto slope_table = create_slope_table(MotorSlope::create_from_steps(6000, 2400, 50), 2400, -                                          StepType::FULL, 1, 4, -                                          get_slope_table_max_size(AsicType::GL646)); +    auto slope_table = create_slope_table_for_speed(MotorSlope::create_from_steps(6000, 2400, 50), +                                                    2400, StepType::FULL, 1, 4, +                                                    get_slope_table_max_size(AsicType::GL646));      // document loading:      // send regs      // start motor      // wait e1 status to become e0 -    gl646_send_slope_table(dev, 1, slope_table.table, slope_table.steps_count); +    const auto& sensor = sanei_genesys_find_sensor_any(dev); +    scanner_send_slope_table(dev, sensor, 1, slope_table.table);      dev->interface->write_registers(regs); @@ -1292,9 +1505,8 @@ void CommandSetGl646::eject_document(Genesys_Device* dev) const      // home sensor is set when document is inserted      if (status.is_at_home) {          dev->document = false; -      DBG(DBG_info, "%s: no more document to eject\n", __func__); -      DBG(DBG_proc, "%s: end\n", __func__); -      return; +        DBG(DBG_info, "%s: no more document to eject\n", __func__); +        return;      }      // there is a document inserted, eject it @@ -1331,14 +1543,16 @@ void CommandSetGl646::eject_document(Genesys_Device* dev) const    regs.init_reg(0x24, 4);    /* generate slope table 2 */ -    auto slope_table = create_slope_table(MotorSlope::create_from_steps(10000, 1600, 60), 1600, -                                          StepType::FULL, 1, 4, -                                          get_slope_table_max_size(AsicType::GL646)); +    auto slope_table = create_slope_table_for_speed(MotorSlope::create_from_steps(10000, 1600, 60), +                                                    1600, StepType::FULL, 1, 4, +                                                    get_slope_table_max_size(AsicType::GL646));      // document eject:      // send regs      // start motor      // wait c1 status to become c8 : HOMESNR and ~MOTFLAG -    gl646_send_slope_table(dev, 1, slope_table.table, slope_table.steps_count); +    // FIXME: sensor is not used. +    const auto& sensor = sanei_genesys_find_sensor_any(dev); +    scanner_send_slope_table(dev, sensor, 1, slope_table.table);      dev->interface->write_registers(regs); @@ -1473,7 +1687,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)    if (!i)			/* the loop counted down to 0, scanner still is busy */      { -        dev->set_head_pos_unknown(); +        dev->set_head_pos_unknown(ScanHeadId::PRIMARY | ScanHeadId::SECONDARY);          throw SaneException(SANE_STATUS_DEVICE_BUSY, "motor is still on: device busy");      } @@ -1489,15 +1703,15 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)      session.params.startx = 0;      session.params.starty = 65535;      session.params.pixels = 600; -    session.params.requested_pixels = 600;      session.params.lines = 1;      session.params.depth = 8;      session.params.channels = 3;      session.params.scan_method = dev->model->default_method;      session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;      session.params.color_filter = ColorFilter::RED; -    session.params.flags = ScanFlag::USE_XCORRECTION | -                            ScanFlag::REVERSE; +    session.params.flags = ScanFlag::REVERSE | +                           ScanFlag::AUTO_GO_HOME | +                           ScanFlag::DISABLE_GAMMA;      if (dev->model->default_method == ScanMethod::TRANSPARENCY) {          session.params.flags |= ScanFlag::USE_XPA;      } @@ -1520,8 +1734,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)    /* registers are restored to an iddl state, give up if no head to park */      if (dev->model->is_sheetfed) { -      DBG(DBG_proc, "%s: end \n", __func__); -      return; +        return;      }      // starts scan @@ -1554,7 +1767,6 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)              if (status.is_at_home) {  	      DBG(DBG_info, "%s: reached home position\n", __func__); -	      DBG(DBG_proc, "%s: end\n", __func__);                  dev->interface->sleep_ms(500);                  dev->set_head_pos_zero(ScanHeadId::PRIMARY);                  return; @@ -1567,7 +1779,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)          // stop the motor          catch_all_exceptions(__func__, [&](){ gl646_stop_motor (dev); });          catch_all_exceptions(__func__, [&](){ end_scan_impl(dev, &dev->reg, true, false); }); -        dev->set_head_pos_unknown(); +        dev->set_head_pos_unknown(ScanHeadId::PRIMARY | ScanHeadId::SECONDARY);          throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");      } @@ -1576,165 +1788,60 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)  }  /** - * Automatically set top-left edge of the scan area by scanning an - * area at 300 dpi from very top of scanner - * @param dev  device stucture describing the scanner - */ -void CommandSetGl646::search_start_position(Genesys_Device* dev) const -{ -    DBG_HELPER(dbg); -  Genesys_Settings settings; -  unsigned int resolution, x, y; - -  /* we scan at 300 dpi */ -  resolution = get_closest_resolution(dev->model->sensor_id, 300, 1); - -    // FIXME: the current approach of doing search only for one resolution does not work on scanners -    // whith employ different sensors with potentially different settings. -    const auto& sensor = sanei_genesys_find_sensor(dev, resolution, 1, -                                                   dev->model->default_method); - -  /* fill settings for a gray level scan */ -  settings.scan_method = dev->model->default_method; -  settings.scan_mode = ScanColorMode::GRAY; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_x = 0; -  settings.tl_y = 0; -  settings.pixels = 600; -    settings.requested_pixels = settings.pixels; -  settings.lines = dev->model->search_lines; -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; - -  settings.disable_interpolation = 0; -  settings.threshold = 0; - -    // scan the desired area -    std::vector<uint8_t> data; -    simple_scan(dev, sensor, settings, true, true, false, data, "search_start_position"); - -    // handle stagger case : reorder gray data and thus loose some lines -    auto staggered_lines = dev->session.num_staggered_lines; -    if (staggered_lines > 0) { -        DBG(DBG_proc, "%s: 'un-staggering'\n", __func__); -        for (y = 0; y < settings.lines - staggered_lines; y++) { -            /* one point out of 2 is 'unaligned' */ -            for (x = 0; x < settings.pixels; x += 2) -        { -                data[y * settings.pixels + x] = data[(y + staggered_lines) * settings.pixels + x]; -        } -          } -        /* correct line number */ -        settings.lines -= staggered_lines; -    } - -    if (DBG_LEVEL >= DBG_data) -      { -        sanei_genesys_write_pnm_file("gl646_search_position.pnm", data.data(), settings.depth, 1, -                                     settings.pixels, settings.lines); -      } - -    // now search reference points on the data -    for (auto& sensor_update : -            sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method)) -    { -        sanei_genesys_search_reference_point(dev, sensor_update, data.data(), 0, -                                             resolution, settings.pixels, settings.lines); -    } -} - -/** - * internally overriden during effective calibration - * sets up register for coarse gain calibration - */ -void CommandSetGl646::init_regs_for_coarse_calibration(Genesys_Device* dev, -                                                       const Genesys_Sensor& sensor, -                                                       Genesys_Register_Set& regs) const -{ -    DBG_HELPER(dbg); -    (void) dev; -    (void) sensor; -    (void) regs; -} - - -/**   * init registers for shading calibration   * we assume that scanner's head is on an area suiting shading calibration.   * We scan a full scan width area by the shading line number for the device - * at either at full sensor's resolution or half depending upon ccd_size_divisor - * @param dev scanner's device   */  void CommandSetGl646::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,                                              Genesys_Register_Set& regs) const  {      DBG_HELPER(dbg);      (void) regs; -  Genesys_Settings settings; -  int cksel = 1;    /* fill settings for scan : always a color scan */    int channels = 3; +    unsigned cksel = get_cksel(dev->model->sensor_id, dev->settings.xres, channels); + +    unsigned resolution = sensor.get_optical_resolution() / cksel; +    // FIXME: we select wrong calibration sensor      const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->settings.xres, channels,                                                           dev->settings.scan_method); -    unsigned ccd_size_divisor = calib_sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres); +    auto pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH; -  settings.scan_method = dev->settings.scan_method; -  settings.scan_mode = dev->settings.scan_mode; -    if (!dev->model->is_cis) { -      // FIXME: always a color scan, but why don't we set scan_mode to COLOR_SINGLE_PASS always? -      settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; -    } -  settings.xres = sensor.optical_res / ccd_size_divisor; -  cksel = get_cksel(dev->model->sensor_id, dev->settings.xres, channels); -  settings.xres = settings.xres / cksel; -  settings.yres = settings.xres; -  settings.tl_x = 0; -  settings.tl_y = 0; -    settings.pixels = (calib_sensor.sensor_pixels * settings.xres) / calib_sensor.optical_res; -    settings.requested_pixels = settings.pixels; -  dev->calib_lines = dev->model->shading_lines; -  settings.lines = dev->calib_lines * (3 - ccd_size_divisor); -  settings.depth = 16; -  settings.color_filter = dev->settings.color_filter; - -  settings.disable_interpolation = dev->settings.disable_interpolation; -  settings.threshold = dev->settings.threshold; - -    // we don't want top offset, but we need right margin to be the same than the one for the final -    // scan -    setup_for_scan(dev, calib_sensor, &dev->reg, settings, true, false, false, false); - -  /* used when sending shading calibration data */ -  dev->calib_pixels = settings.pixels; -    dev->calib_channels = dev->session.params.channels; -    if (!dev->model->is_cis) { -      dev->calib_channels = 3; +    unsigned calib_lines = +            static_cast<unsigned>(dev->model->y_size_calib_mm * resolution / MM_PER_INCH); + +    ScanSession session; +    session.params.xres = resolution; +    session.params.yres = resolution; +    session.params.startx = 0; +    session.params.starty = 0; +    session.params.pixels = pixels; +    session.params.lines = calib_lines; +    session.params.depth = 16; +    session.params.channels = channels; +    session.params.scan_method = dev->settings.scan_method; +    session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; +    session.params.color_filter = dev->settings.color_filter; +    session.params.flags = ScanFlag::DISABLE_SHADING | +                           ScanFlag::DISABLE_GAMMA | +                           ScanFlag::IGNORE_COLOR_OFFSET | +                           ScanFlag::IGNORE_STAGGER_OFFSET; +    if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { +        session.params.flags |= ScanFlag::USE_XPA;      } +    compute_session(dev, session, calib_sensor); + +    dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session); + +    dev->calib_session = session;    /* no shading */ -    dev->reg.find_reg(0x01).value &= ~REG_0x01_DVDSET;      dev->reg.find_reg(0x02).value |= REG_0x02_ACDCDIS;	/* ease backtracking */ -    dev->reg.find_reg(0x02).value &= ~(REG_0x02_FASTFED | REG_0x02_AGOHOME); -    dev->reg.find_reg(0x05).value &= ~REG_0x05_GMMENB; +    dev->reg.find_reg(0x02).value &= ~REG_0x02_FASTFED;    sanei_genesys_set_motor_power(dev->reg, false); - -  /* TODO another flag to setup regs ? */ -  /* enforce needed LINCNT, getting rid of extra lines for color reordering */ -    if (!dev->model->is_cis) { -        dev->reg.set24(REG_LINCNT, dev->calib_lines); -    } else { -        dev->reg.set24(REG_LINCNT, dev->calib_lines * 3); -    } - -  /* copy reg to calib_reg */ -  dev->calib_reg = dev->reg; - -  DBG(DBG_info, "%s:\n\tdev->settings.xres=%d\n\tdev->settings.yres=%d\n", __func__, -      dev->settings.xres, dev->settings.yres);  }  bool CommandSetGl646::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const @@ -1745,109 +1852,6 @@ bool CommandSetGl646::needs_home_before_init_regs_for_scan(Genesys_Device* dev)  }  /** - * set up registers for the actual scan. The scan's parameters are given - * through the device settings. It allocates the scan buffers. - */ -void CommandSetGl646::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const -{ -    DBG_HELPER(dbg); - -    debug_dump(DBG_info, dev->settings); - -    ScanSession session = calculate_scan_session(dev, sensor, dev->settings); - -    init_regs_for_scan_session(dev, sensor, &dev->reg, session); - -  /* gamma is only enabled at final scan time */ -    if (dev->settings.depth < 16) { -        dev->reg.find_reg(0x05).value |= REG_0x05_GMMENB; -    } -} - -/** - * set up registers for the actual scan. The scan's parameters are given - * through the device settings. It allocates the scan buffers. - * @param dev scanner's device - * @param regs     registers to set up - * @param settings settings of scan - * @param split true if move to scan area is split from scan, false is - *              scan first moves to area - * @param xcorrection take x geometry correction into account (fixed and detected offsets) - * @param ycorrection take y geometry correction into account - */ -static void setup_for_scan(Genesys_Device* dev, -                           const Genesys_Sensor& sensor, -                           Genesys_Register_Set*regs, -                           Genesys_Settings settings, -                           bool split, -                           bool xcorrection, -                           bool ycorrection, -                           bool reverse) -{ -    DBG_HELPER(dbg); - -    debug_dump(DBG_info, dev->settings); - -    // compute distance to move -    float move = 0; -    // XXX STEF XXX MD5345 -> optical_ydpi, other base_ydpi => half/full step ? */ -    if (!split) { -        if (!dev->model->is_sheetfed) { -            if (ycorrection) { -                move = static_cast<float>(dev->model->y_offset); -            } - -            // add tl_y to base movement -        } -        move += static_cast<float>(settings.tl_y); - -        if (move < 0) { -            DBG(DBG_error, "%s: overriding negative move value %f\n", __func__, move); -            move = 0; -        } -    } -    move = static_cast<float>((move * dev->motor.optical_ydpi) / MM_PER_INCH); -    DBG(DBG_info, "%s: move=%f steps\n", __func__, move); - -    float start = static_cast<float>(settings.tl_x); -    if (xcorrection) { -        if (settings.scan_method == ScanMethod::FLATBED) { -            start += static_cast<float>(dev->model->x_offset); -        } else { -            start += static_cast<float>(dev->model->x_offset_ta); -        } -    } -    start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH); - -    ScanSession session; -    session.params.xres = settings.xres; -    session.params.yres = settings.yres; -    session.params.startx = static_cast<unsigned>(start); -    session.params.starty = static_cast<unsigned>(move); -    session.params.pixels = settings.pixels; -    session.params.requested_pixels = settings.requested_pixels; -    session.params.lines = settings.lines; -    session.params.depth = settings.depth; -    session.params.channels = settings.get_channels(); -    session.params.scan_method = dev->settings.scan_method; -    session.params.scan_mode = settings.scan_mode; -    session.params.color_filter = settings.color_filter; -    session.params.flags = ScanFlag::NONE; -    if (settings.scan_method == ScanMethod::TRANSPARENCY) { -        session.params.flags |= ScanFlag::USE_XPA; -    } -    if (xcorrection) { -        session.params.flags |= ScanFlag::USE_XCORRECTION; -    } -    if (reverse) { -        session.params.flags |= ScanFlag::REVERSE; -    } -    compute_session(dev, session, sensor); - -    dev->cmd_set->init_regs_for_scan_session(dev, sensor, regs, session); -} - -/**   * this function send gamma table to ASIC   */  void CommandSetGl646::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const @@ -1857,9 +1861,7 @@ void CommandSetGl646::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor    int address;    int bits; -  /* gamma table size */ -  if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) -    { +     if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {        size = 16384;        bits = 14;      } @@ -1903,45 +1905,42 @@ SensorExposure CommandSetGl646::led_calibration(Genesys_Device* dev, const Genes  {      DBG_HELPER(dbg);      (void) regs; -  int total_size;    unsigned int i, j;    int val;    int avg[3], avga, avge;    int turn;    uint16_t expr, expg, expb; -  Genesys_Settings settings; -  SANE_Int resolution;      unsigned channels = dev->settings.get_channels(); -  /* get led calibration resolution */ -  if (dev->settings.scan_mode == ScanColorMode::COLOR_SINGLE_PASS) -    { -      settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; -    } -  else -    { -      settings.scan_mode = ScanColorMode::GRAY; +    ScanColorMode scan_mode = ScanColorMode::COLOR_SINGLE_PASS; +    if (dev->settings.scan_mode != ScanColorMode::COLOR_SINGLE_PASS) { +        scan_mode = ScanColorMode::GRAY;      } -  resolution = get_closest_resolution(dev->model->sensor_id, sensor.optical_res, channels); -  /* offset calibration is always done in color mode */ -    settings.scan_method = dev->model->default_method; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_x = 0; -  settings.tl_y = 0; -    settings.pixels = (sensor.sensor_pixels * resolution) / sensor.optical_res; -    settings.requested_pixels = settings.pixels; -  settings.lines = 1; -  settings.depth = 16; -  settings.color_filter = ColorFilter::RED; +    // offset calibration is always done in color mode +    unsigned pixels = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH; -  settings.disable_interpolation = 0; -  settings.threshold = 0; +    ScanSession session; +    session.params.xres = sensor.full_resolution; +    session.params.yres = sensor.full_resolution; +    session.params.startx = 0; +    session.params.starty = 0; +    session.params.pixels = pixels; +    session.params.lines = 1; +    session.params.depth = 16; +    session.params.channels = channels; +    session.params.scan_method = dev->settings.scan_method; +    session.params.scan_mode = scan_mode; +    session.params.color_filter = ColorFilter::RED; +    session.params.flags = ScanFlag::DISABLE_SHADING; +    if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { +        session.params.flags |= ScanFlag::USE_XPA; +    } +    compute_session(dev, session, sensor); -  /* colors * bytes_per_color * scan lines */ -  total_size = settings.pixels * channels * 2 * 1; +    // colors * bytes_per_color * scan lines +    unsigned total_size = pixels * channels * 2 * 1;    std::vector<uint8_t> line(total_size); @@ -1968,38 +1967,34 @@ SensorExposure CommandSetGl646::led_calibration(Genesys_Device* dev, const Genes        DBG(DBG_info, "%s: starting first line reading\n", __func__); -        simple_scan(dev, calib_sensor, settings, false, true, false, line, "led_calibration"); +        dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session); +        simple_scan(dev, calib_sensor, session, false, line, "led_calibration");          if (is_testing_mode()) {              return calib_sensor.exposure;          } -      if (DBG_LEVEL >= DBG_data) -	{ -          char fn[30]; -            std::snprintf(fn, 30, "gl646_led_%02d.pnm", turn); -          sanei_genesys_write_pnm_file(fn, line.data(), 16, channels, settings.pixels, 1); -	} +        if (dbg_log_image_data()) { +            char fn[30]; +            std::snprintf(fn, 30, "gl646_led_%02d.tiff", turn); +            write_tiff_file(fn, line.data(), 16, channels, pixels, 1); +        }          acceptable = true;        for (j = 0; j < channels; j++)  	{  	  avg[j] = 0; -	  for (i = 0; i < settings.pixels; i++) -	    { -	      if (dev->model->is_cis) -		val = -		  line[i * 2 + j * 2 * settings.pixels + 1] * 256 + -		  line[i * 2 + j * 2 * settings.pixels]; -	      else -		val = -		  line[i * 2 * channels + 2 * j + 1] * 256 + -		  line[i * 2 * channels + 2 * j]; -	      avg[j] += val; +            for (i = 0; i < pixels; i++) { +                if (dev->model->is_cis) { +                    val = line[i * 2 + j * 2 * pixels + 1] * 256 + line[i * 2 + j * 2 * pixels]; +                } else { +                    val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; +                } +            avg[j] += val;  	    } -	  avg[j] /= settings.pixels; +      avg[j] /= pixels;  	}        DBG(DBG_info, "%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]); @@ -2088,31 +2083,40 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&    unsigned int channels;    int pass = 0; -  SANE_Int resolution; -  Genesys_Settings settings; -  unsigned int x, y, adr, min; +    unsigned adr, min;    unsigned int bottom, black_pixels;    channels = 3; -  resolution = get_closest_resolution(dev->model->sensor_id, sensor.optical_res, channels); -    const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3, ScanMethod::FLATBED); -    black_pixels = (calib_sensor.black_pixels * resolution) / calib_sensor.optical_res; -  DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels); - -    settings.scan_method = dev->model->default_method; -  settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_x = 0; -  settings.tl_y = 0; -    settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res; -    settings.requested_pixels = settings.pixels; -  settings.lines = CALIBRATION_LINES; -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; - -  settings.disable_interpolation = 0; -  settings.threshold = 0; + +    // FIXME: maybe reuse `sensor` +    const auto& calib_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution, 3, +                                                         ScanMethod::FLATBED); +    black_pixels = (calib_sensor.black_pixels * sensor.full_resolution) / calib_sensor.full_resolution; + +    unsigned pixels = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH; +    unsigned lines = CALIBRATION_LINES; + +    if (dev->model->is_cis) { +        lines = ((lines + 2) / 3) * 3; +    } + +    ScanSession session; +    session.params.xres = sensor.full_resolution; +    session.params.yres = sensor.full_resolution; +    session.params.startx = 0; +    session.params.starty = 0; +    session.params.pixels = pixels; +    session.params.lines = lines; +    session.params.depth = 8; +    session.params.channels = 3; +    session.params.scan_method = dev->settings.scan_method; +    session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; +    session.params.color_filter = ColorFilter::RED; +    session.params.flags = ScanFlag::DISABLE_SHADING; +    if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { +        session.params.flags |= ScanFlag::USE_XPA; +    } +    compute_session(dev, session, calib_sensor);    /* scan first line of data with no gain */    dev->frontend.set_gain(0, 0); @@ -2129,27 +2133,24 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&        dev->frontend.set_offset(0, bottom);        dev->frontend.set_offset(1, bottom);        dev->frontend.set_offset(2, bottom); -        simple_scan(dev, calib_sensor, settings, false, true, false, line, -                    "ad_fe_offset_calibration"); + +        dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session); +        simple_scan(dev, calib_sensor, session, false, line, "ad_fe_offset_calibration");          if (is_testing_mode()) {              return;          } -      if (DBG_LEVEL >= DBG_data) -	{ -          char title[30]; -          std::snprintf(title, 30, "gl646_offset%03d.pnm", static_cast<int>(bottom)); -          sanei_genesys_write_pnm_file (title, line.data(), 8, channels, -					settings.pixels, settings.lines); -	} +        if (dbg_log_image_data()) { +            char title[30]; +            std::snprintf(title, 30, "gl646_offset%03d.tiff", static_cast<int>(bottom)); +            write_tiff_file(title, line.data(), 8, channels, pixels, lines); +        }        min = 0; -      for (y = 0; y < settings.lines; y++) -	{ -	  for (x = 0; x < black_pixels; x++) -	    { -	      adr = (x + y * settings.pixels) * channels; +        for (unsigned y = 0; y < lines; y++) { +            for (unsigned x = 0; x < black_pixels; x++) { +                adr = (x + y * pixels) * channels;  	      if (line[adr] > min)  		min = line[adr];  	      if (line[adr + 1] > min) @@ -2159,7 +2160,7 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&  	    }  	} -      DBG(DBG_io2, "%s: pass=%d, min=%d\n", __func__, pass, min); +      DBG(DBG_info, "%s: pass=%d, min=%d\n", __func__, pass, min);        bottom++;      }    while (pass < 128 && min == 0); @@ -2187,9 +2188,7 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens      DBG_HELPER(dbg);      (void) regs; -  unsigned int channels;    int pass = 0, avg; -  Genesys_Settings settings;    int topavg, bottomavg;    int top, bottom, black_pixels; @@ -2198,32 +2197,38 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens          return;      } -  DBG(DBG_proc, "%s: start\n", __func__); // TODO -    /* setup for a RGB scan, one full sensor's width line */    /* resolution is the one from the final scan          */ -    channels = 3; -    int resolution = get_closest_resolution(dev->model->sensor_id, dev->settings.xres, channels); - -    const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3, ScanMethod::FLATBED); -    black_pixels = (calib_sensor.black_pixels * resolution) / calib_sensor.optical_res; +    unsigned resolution = dev->settings.xres; +    unsigned channels = 3; -  DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels); +    const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels, +                                                         ScanMethod::FLATBED); +    black_pixels = (calib_sensor.black_pixels * resolution) / calib_sensor.full_resolution; -    settings.scan_method = dev->model->default_method; -  settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_x = 0; -  settings.tl_y = 0; -    settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res; -    settings.requested_pixels = settings.pixels; -  settings.lines = CALIBRATION_LINES; -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; +    unsigned pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH; +    unsigned lines = CALIBRATION_LINES; +    if (dev->model->is_cis) { +        lines = ((lines + 2) / 3) * 3; +    } -  settings.disable_interpolation = 0; -  settings.threshold = 0; +    ScanSession session; +    session.params.xres = resolution; +    session.params.yres = resolution; +    session.params.startx = 0; +    session.params.starty = 0; +    session.params.pixels = pixels; +    session.params.lines = lines; +    session.params.depth = 8; +    session.params.channels = channels; +    session.params.scan_method = dev->settings.scan_method; +    session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; +    session.params.color_filter = ColorFilter::RED; +    session.params.flags = ScanFlag::DISABLE_SHADING; +    if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { +        session.params.flags |= ScanFlag::USE_XPA; +    } +    compute_session(dev, session, sensor);    /* scan first line of data with no gain, but with offset from     * last calibration */ @@ -2239,38 +2244,32 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens    std::vector<uint8_t> first_line, second_line; -    simple_scan(dev, calib_sensor, settings, false, true, false, first_line, -                "offset_first_line"); +    dev->cmd_set->init_regs_for_scan_session(dev, sensor, &dev->reg, session); +    simple_scan(dev, calib_sensor, session, false, first_line, "offset_first_line"); -  if (DBG_LEVEL >= DBG_data) -    { -      char title[30]; -        std::snprintf(title, 30, "gl646_offset%03d.pnm", bottom); -      sanei_genesys_write_pnm_file(title, first_line.data(), 8, channels, -                                   settings.pixels, settings.lines); +    if (dbg_log_image_data()) { +        char title[30]; +        std::snprintf(title, 30, "gl646_offset%03d.tiff", bottom); +        write_tiff_file(title, first_line.data(), 8, channels, pixels, lines);      } -  bottomavg = dark_average(first_line.data(), settings.pixels, settings.lines, channels, -                           black_pixels); -  DBG(DBG_io2, "%s: bottom avg=%d\n", __func__, bottomavg); +    bottomavg = dark_average(first_line.data(), pixels, lines, channels, black_pixels); +    DBG(DBG_info, "%s: bottom avg=%d\n", __func__, bottomavg);    /* now top value */    top = 231;    dev->frontend.set_offset(0, top);    dev->frontend.set_offset(1, top);    dev->frontend.set_offset(2, top); -    simple_scan(dev, calib_sensor, settings, false, true, false, second_line, -                "offset_second_line"); +    dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session); +    simple_scan(dev, calib_sensor, session, false, second_line, "offset_second_line"); -  if (DBG_LEVEL >= DBG_data) -    { -      char title[30]; -        std::snprintf(title, 30, "gl646_offset%03d.pnm", top); -      sanei_genesys_write_pnm_file (title, second_line.data(), 8, channels, -				    settings.pixels, settings.lines); +    if (dbg_log_image_data()) { +        char title[30]; +        std::snprintf(title, 30, "gl646_offset%03d.tiff", top); +        write_tiff_file(title, second_line.data(), 8, channels, pixels, lines);      } -  topavg = dark_average(second_line.data(), settings.pixels, settings.lines, channels, -                        black_pixels); -  DBG(DBG_io2, "%s: top avg=%d\n", __func__, topavg); +    topavg = dark_average(second_line.data(), pixels, lines, channels, black_pixels); +    DBG(DBG_info, "%s: top avg=%d\n", __func__, topavg);      if (is_testing_mode()) {          return; @@ -2287,20 +2286,17 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens        dev->frontend.set_offset(2, (top + bottom) / 2);          // scan with no move -        simple_scan(dev, calib_sensor, settings, false, true, false, second_line, +        dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session); +        simple_scan(dev, calib_sensor, session, false, second_line,                      "offset_calibration_i"); -      if (DBG_LEVEL >= DBG_data) -	{ -          char title[30]; -            std::snprintf(title, 30, "gl646_offset%03d.pnm", dev->frontend.get_offset(1)); -          sanei_genesys_write_pnm_file (title, second_line.data(), 8, channels, -					settings.pixels, settings.lines); -	} +        if (dbg_log_image_data()) { +            char title[30]; +            std::snprintf(title, 30, "gl646_offset%03d.tiff", dev->frontend.get_offset(1)); +            write_tiff_file(title, second_line.data(), 8, channels, pixels, lines); +        } -      avg = -        dark_average (second_line.data(), settings.pixels, settings.lines, channels, -		      black_pixels); +        avg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);        DBG(DBG_info, "%s: avg=%d offset=%d\n", __func__, avg, dev->frontend.get_offset(1));        /* compute new boundaries */ @@ -2322,102 +2318,6 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens        dev->frontend.get_offset(2));  } -/** @brief gain calibration for Analog Device frontends - * Alternative coarse gain calibration - */ -static void ad_fe_coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor, -                                          Genesys_Register_Set& regs, int dpi) -{ -    DBG_HELPER(dbg); -    (void) sensor; -    (void) regs; - -  unsigned int i, channels, val; -  unsigned int size, count, resolution, pass; -  float average; -  Genesys_Settings settings; -  char title[32]; - -  /* setup for a RGB scan, one full sensor's width line */ -  /* resolution is the one from the final scan          */ -  channels = 3; -  resolution = get_closest_resolution(dev->model->sensor_id, dpi, channels); - -    const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3, ScanMethod::FLATBED); - -  settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; - -    settings.scan_method = dev->model->default_method; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_x = 0; -  settings.tl_y = 0; -    settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res; -    settings.requested_pixels = settings.pixels; -  settings.lines = CALIBRATION_LINES; -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; - -  settings.disable_interpolation = 0; -  settings.threshold = 0; - -  size = channels * settings.pixels * settings.lines; - -  /* start gain value */ -  dev->frontend.set_gain(0, 1); -  dev->frontend.set_gain(1, 1); -  dev->frontend.set_gain(2, 1); - -  average = 0; -  pass = 0; - -  std::vector<uint8_t> line; - -    // loop until each channel raises to acceptable level -    while ((average < calib_sensor.gain_white_ref) && (pass < 30)) { -        // scan with no move -        simple_scan(dev, calib_sensor, settings, false, true, false, line, -                    "ad_fe_coarse_gain_calibration"); - -      /* log scanning data */ -      if (DBG_LEVEL >= DBG_data) -	{ -            std::sprintf(title, "gl646_alternative_gain%02d.pnm", pass); -          sanei_genesys_write_pnm_file(title, line.data(), 8, channels, settings.pixels, -                                       settings.lines); -	} -      pass++; - -      /* computes white average */ -      average = 0; -      count = 0; -      for (i = 0; i < size; i++) -	{ -	  val = line[i]; -	  average += val; -	  count++; -	} -      average = average / count; - -        uint8_t gain0 = dev->frontend.get_gain(0); -        // adjusts gain for the channel -        if (average < calib_sensor.gain_white_ref) { -            gain0 += 1; -        } - -        dev->frontend.set_gain(0, gain0); -        dev->frontend.set_gain(1, gain0); -        dev->frontend.set_gain(2, gain0); - -      DBG(DBG_proc, "%s: average = %.2f, gain = %d\n", __func__, average, gain0); -    } - -  DBG(DBG_info, "%s: gains=(%d,%d,%d)\n", __func__, -      dev->frontend.get_gain(0), -      dev->frontend.get_gain(1), -      dev->frontend.get_gain(2)); -} -  /**   * Alternative coarse gain calibration   * this on uses the settings from offset_calibration. First scan moves so @@ -2430,76 +2330,67 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys  {      DBG_HELPER(dbg);      (void) dpi; +    (void) sensor; +    (void) regs; -  unsigned int i, j, k, channels, val, maximum, idx; -  unsigned int count, resolution, pass;    float average[3]; -  Genesys_Settings settings;    char title[32]; -    if (dev->model->sensor_id == SensorId::CIS_XP200) { -      return ad_fe_coarse_gain_calibration(dev, sensor, regs, sensor.optical_res); -    } -    /* setup for a RGB scan, one full sensor's width line */    /* resolution is the one from the final scan          */ -  channels = 3; +    unsigned channels = 3; -  /* we are searching a sensor resolution */ -    resolution = get_closest_resolution(dev->model->sensor_id, dev->settings.xres, channels); - -    const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels, +    // BUG: the following comment is incorrect +    // we are searching a sensor resolution */ +    const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->settings.xres, channels,                                                           ScanMethod::FLATBED); -  settings.scan_method = dev->settings.scan_method; -  settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_y = 0; -  if (settings.scan_method == ScanMethod::FLATBED) -    { -      settings.tl_x = 0; -        settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res; +    unsigned pixels = 0; +    float start = 0; +    if (dev->settings.scan_method == ScanMethod::FLATBED) { +        pixels = dev->model->x_size_calib_mm * dev->settings.xres / MM_PER_INCH; +    } else { +        start = dev->model->x_offset_ta; +        pixels = static_cast<unsigned>( +                              (dev->model->x_size_ta * dev->settings.xres) / MM_PER_INCH);      } -  else -    { -        settings.tl_x = dev->model->x_offset_ta; -        settings.pixels = static_cast<unsigned>((dev->model->x_size_ta * resolution) / MM_PER_INCH); + +    unsigned lines = CALIBRATION_LINES; +    // round up to multiple of 3 in case of CIS scanner +    if (dev->model->is_cis) { +        lines = ((lines + 2) / 3) * 3;      } -    settings.requested_pixels = settings.pixels; -  settings.lines = CALIBRATION_LINES; -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; -  settings.disable_interpolation = 0; -  settings.threshold = 0; +    start = static_cast<float>((start * dev->settings.xres) / MM_PER_INCH); + +    ScanSession session; +    session.params.xres = dev->settings.xres; +    session.params.yres = dev->settings.xres; +    session.params.startx = static_cast<unsigned>(start); +    session.params.starty = 0; +    session.params.pixels = pixels; +    session.params.lines = lines; +    session.params.depth = 8; +    session.params.channels = channels; +    session.params.scan_method = dev->settings.scan_method; +    session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; +    session.params.color_filter = ColorFilter::RED; +    session.params.flags = ScanFlag::DISABLE_SHADING; +    if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { +        session.params.flags |= ScanFlag::USE_XPA; +    } +    compute_session(dev, session, calib_sensor);    /* start gain value */    dev->frontend.set_gain(0, 1);    dev->frontend.set_gain(1, 1);    dev->frontend.set_gain(2, 1); -  if (channels > 1) -    { -      average[0] = 0; -      average[1] = 0; -      average[2] = 0; -      idx = 0; -    } -  else -    { -      average[0] = 255; -      average[1] = 255; -      average[2] = 255; -        switch (dev->settings.color_filter) { -            case ColorFilter::RED: idx = 0; break; -            case ColorFilter::GREEN: idx = 1; break; -            case ColorFilter::BLUE: idx = 2; break; -            default: idx = 0; break; // should not happen -        } -      average[idx] = 0; -    } -  pass = 0; +    average[0] = 0; +    average[1] = 0; +    average[2] = 0; + +    unsigned pass = 0;    std::vector<uint8_t> line; @@ -2509,75 +2400,60 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys              (average[2] < calib_sensor.gain_white_ref)) && (pass < 30))      {          // scan with no move -        simple_scan(dev, calib_sensor, settings, false, true, false, line, -                    "coarse_gain_calibration"); +        dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session); +        simple_scan(dev, calib_sensor, session, false, line, "coarse_gain_calibration"); -      /* log scanning data */ -      if (DBG_LEVEL >= DBG_data) -	{ -          std::sprintf(title, "gl646_gain%02d.pnm", pass); -          sanei_genesys_write_pnm_file(title, line.data(), 8, channels, settings.pixels, -                                       settings.lines); -	} -      pass++; - -      /* average high level for each channel and compute gain -         to reach the target code -         we only use the central half of the CCD data         */ -      for (k = idx; k < idx + channels; k++) -	{ -	  /* we find the maximum white value, so we can deduce a threshold -	     to average white values */ -	  maximum = 0; -	  for (i = 0; i < settings.lines; i++) -	    { -	      for (j = 0; j < settings.pixels; j++) -		{ -		  val = line[i * channels * settings.pixels + j + k]; -		  if (val > maximum) -		    maximum = val; -		} -	    } +        if (dbg_log_image_data()) { +            std::sprintf(title, "gl646_gain%02d.tiff", pass); +            write_tiff_file(title, line.data(), 8, channels, pixels, lines); +        } +        pass++; + +        // average high level for each channel and compute gain to reach the target code +        // we only use the central half of the CCD data +        for (unsigned k = 0; k < channels; k++) { + +            // we find the maximum white value, so we can deduce a threshold +            // to average white values +            unsigned maximum = 0; +            for (unsigned i = 0; i < lines; i++) { +                for (unsigned j = 0; j < pixels; j++) { +                    unsigned val = line[i * channels * pixels + j + k]; +                    maximum = std::max(maximum, val); +                } +            } -	  /* threshold */              maximum = static_cast<int>(maximum * 0.9); -	  /* computes white average */ -	  average[k] = 0; -	  count = 0; -	  for (i = 0; i < settings.lines; i++) -	    { -	      for (j = 0; j < settings.pixels; j++) -		{ -		  /* averaging only white points allow us not to care about dark margins */ -		  val = line[i * channels * settings.pixels + j + k]; -		  if (val > maximum) -		    { -		      average[k] += val; -		      count++; -		    } -		} -	    } -	  average[k] = average[k] / count; - -	  /* adjusts gain for the channel */ -          if (average[k] < calib_sensor.gain_white_ref) -            dev->frontend.set_gain(k, dev->frontend.get_gain(k) + 1); +            // computes white average +            average[k] = 0; +            unsigned count = 0; +            for (unsigned i = 0; i < lines; i++) { +                for (unsigned j = 0; j < pixels; j++) { +                    // averaging only white points allow us not to care about dark margins +                    unsigned val = line[i * channels * pixels + j + k]; +                    if (val > maximum) { +                        average[k] += val; +                        count++; +                    } +                } +            } +            average[k] = average[k] / count; -	  DBG(DBG_proc, "%s: channel %d, average = %.2f, gain = %d\n", __func__, k, average[k], -              dev->frontend.get_gain(k)); -	} -    } +            // adjusts gain for the channel +            if (average[k] < calib_sensor.gain_white_ref) { +                dev->frontend.set_gain(k, dev->frontend.get_gain(k) + 1); +            } -    if (channels < 3) { -        dev->frontend.set_gain(1, dev->frontend.get_gain(0)); -        dev->frontend.set_gain(2, dev->frontend.get_gain(0)); +            DBG(DBG_info, "%s: channel %d, average = %.2f, gain = %d\n", __func__, k, average[k], +                dev->frontend.get_gain(k)); +        }      } -  DBG(DBG_info, "%s: gains=(%d,%d,%d)\n", __func__, -      dev->frontend.get_gain(0), -      dev->frontend.get_gain(1), -      dev->frontend.get_gain(2)); +    DBG(DBG_info, "%s: gains=(%d,%d,%d)\n", __func__, +        dev->frontend.get_gain(0), +        dev->frontend.get_gain(1), +        dev->frontend.get_gain(2));  }  /** @@ -2585,46 +2461,43 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys   *   */  void CommandSetGl646::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor, -                                           Genesys_Register_Set* local_reg, int* channels, -                                           int* total_size) const +                                           Genesys_Register_Set* local_reg) const  {      DBG_HELPER(dbg);      (void) sensor; -  Genesys_Settings settings; -  int resolution, lines; -    dev->frontend = dev->frontend_initial; -  resolution = get_closest_resolution(dev->model->sensor_id, 300, 1); - +    unsigned resolution = 300;      const auto& local_sensor = sanei_genesys_find_sensor(dev, resolution, 1,                                                           dev->settings.scan_method); -  /* set up for a half width 2 lines gray scan without moving */ -    settings.scan_method = dev->model->default_method; -  settings.scan_mode = ScanColorMode::GRAY; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_x = 0; -  settings.tl_y = 0; -    settings.pixels = (local_sensor.sensor_pixels * resolution) / local_sensor.optical_res; -    settings.requested_pixels = settings.pixels; -  settings.lines = 2; -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; - -  settings.disable_interpolation = 0; -  settings.threshold = 0; - -    // setup for scan -    setup_for_scan(dev, local_sensor, &dev->reg, settings, true, false, false, false); +    // set up for a full width 2 lines gray scan without moving +    unsigned pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH; -  /* we are not going to move, so clear these bits */ -    dev->reg.find_reg(0x02).value &= ~(REG_0x02_FASTFED | REG_0x02_AGOHOME); +    ScanSession session; +    session.params.xres = resolution; +    session.params.yres = resolution; +    session.params.startx = 0; +    session.params.starty = 0; +    session.params.pixels = pixels; +    session.params.lines = 2; +    session.params.depth = dev->model->bpp_gray_values.front(); +    session.params.channels = 1; +    session.params.scan_method = dev->settings.scan_method; +    session.params.scan_mode = ScanColorMode::GRAY; +    session.params.color_filter =  ColorFilter::RED; +    session.params.flags = ScanFlag::DISABLE_SHADING | +                           ScanFlag::DISABLE_GAMMA; +    if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) { +        session.params.flags |= ScanFlag::USE_XPA; +    } +    compute_session(dev, session, local_sensor); + +    dev->cmd_set->init_regs_for_scan_session(dev, local_sensor, &dev->reg, session); -  /* don't enable any correction for this scan */ -    dev->reg.find_reg(0x01).value &= ~REG_0x01_DVDSET; +  /* we are not going to move, so clear these bits */ +    dev->reg.find_reg(0x02).value &= ~REG_0x02_FASTFED;    /* copy to local_reg */    *local_reg = dev->reg; @@ -2632,66 +2505,8 @@ void CommandSetGl646::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se    /* turn off motor during this scan */    sanei_genesys_set_motor_power(*local_reg, false); -  /* returned value to higher level warmup function */ -  *channels = 1; -    lines = local_reg->get24(REG_LINCNT) + 1; -  *total_size = lines * settings.pixels; -      // now registers are ok, write them to scanner -    gl646_set_fe(dev, local_sensor, AFE_SET, settings.xres); -    dev->interface->write_registers(*local_reg); -} - - -/* - * this function moves head without scanning, forward, then backward - * so that the head goes to park position. - * as a by-product, also check for lock - */ -static void gl646_repark_head(Genesys_Device* dev) -{ -    DBG_HELPER(dbg); -  Genesys_Settings settings; -  unsigned int expected, steps; - -    settings.scan_method = dev->model->default_method; -  settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; -  settings.xres = get_closest_resolution(dev->model->sensor_id, 75, 1); -  settings.yres = settings.xres; -  settings.tl_x = 0; -  settings.tl_y = 5; -  settings.pixels = 600; -    settings.requested_pixels = settings.pixels; -  settings.lines = 4; -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; - -  settings.disable_interpolation = 0; -  settings.threshold = 0; - -    const auto& sensor = sanei_genesys_find_sensor(dev, settings.xres, 3, -                                                   dev->model->default_method); - -    setup_for_scan(dev, sensor, &dev->reg, settings, false, false, false, false); - -  /* TODO seems wrong ... no effective scan */ -    regs_set_optical_off(dev->model->asic_type, dev->reg); - -    dev->interface->write_registers(dev->reg); - -    // start scan -    dev->cmd_set->begin_scan(dev, sensor, &dev->reg, true); - -    expected = dev->reg.get24(REG_FEEDL); -  do -    { -        dev->interface->sleep_ms(100); -        sanei_genesys_read_feed_steps (dev, &steps); -    } -  while (steps < expected); - -    // toggle motor flag, put an huge step number and redo move backward -    dev->cmd_set->move_back_home(dev, 1); +    gl646_set_fe(dev, local_sensor, AFE_SET, session.params.xres);  }  /* * @@ -2731,10 +2546,11 @@ void CommandSetGl646::init(Genesys_Device* dev) const        gl646_init_regs (dev);          // Init shading data -        sanei_genesys_init_shading_data(dev, sensor, sensor.sensor_pixels); +        sanei_genesys_init_shading_data(dev, sensor, +                                        dev->model->x_size_calib_mm * sensor.full_resolution / +                                            MM_PER_INCH); -      /* initial calibration reg values */ -      dev->calib_reg = dev->reg; +        dev->initial_regs = dev->reg;      }      // execute physical unit init only if cold @@ -2787,7 +2603,7 @@ void CommandSetGl646::init(Genesys_Device* dev) const      if (dev->model->gpio_id != GpioId::HP3670 &&          dev->model->gpio_id != GpioId::HP2400)      { -      switch (sensor.optical_res) +      switch (sensor.full_resolution)  	{  	case 600:  	  addr = 0x08200; @@ -2810,9 +2626,6 @@ void CommandSetGl646::init(Genesys_Device* dev) const          } catch (...) {              dev->interface->bulk_read_data(0x45, dev->control, len);          } -        DBG(DBG_info, "%s: control read=0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", __func__, -            dev->control[0], dev->control[1], dev->control[2], dev->control[3], dev->control[4], -            dev->control[5]);        sanei_usb_set_timeout (30 * 1000);      }    else @@ -2828,104 +2641,44 @@ void CommandSetGl646::init(Genesys_Device* dev) const    /* ensure head is correctly parked, and check lock */      if (!dev->model->is_sheetfed) { -      if (dev->model->flags & GENESYS_FLAG_REPARK) -	{ -            // FIXME: if repark fails, we should print an error message that the scanner is locked and -            // the user should unlock the lock. We should also rethrow with SANE_STATUS_JAMMED -            gl646_repark_head(dev); -	} -      else -    { -            move_back_home(dev, true); -	} +        move_back_home(dev, true);      }    /* here session and device are initialized */      dev->already_initialized = true;  } -void CommandSetGl646::move_to_ta(Genesys_Device* dev) const -{ -    DBG_HELPER(dbg); - -    simple_move(dev, static_cast<int>(dev->model->y_offset_sensor_to_ta)); -} - - -/** - * Does a simple scan: ie no line reordering and avanced data buffering and - * shading correction. Memory for data is allocated in this function - * and must be freed by caller. - * @param dev device of the scanner - * @param settings parameters of the scan - * @param move true if moving during scan - * @param forward true if moving forward during scan - * @param shading true to enable shading correction - * @param data pointer for the data - */  static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor, -                        Genesys_Settings settings, bool move, bool forward, -                        bool shading, std::vector<uint8_t>& data, -                        const char* scan_identifier) +                        const ScanSession& session, bool move, +                        std::vector<uint8_t>& data, const char* scan_identifier)  { -    DBG_HELPER_ARGS(dbg, "move=%d, forward=%d, shading=%d", move, forward, shading); -  unsigned int size, lines, x, y, bpp; -    bool split; - -  /* round up to multiple of 3 in case of CIS scanner */ -    if (dev->model->is_cis) { -      settings.lines = ((settings.lines + 2) / 3) * 3; +    unsigned lines = session.output_line_count; +    if (!dev->model->is_cis) { +        lines++;      } -  /* setup for move then scan */ -    split = !(move && settings.tl_y > 0); -    setup_for_scan(dev, sensor, &dev->reg, settings, split, false, false, !forward); +    std::size_t size = lines * session.params.pixels; +    unsigned bpp = session.params.depth == 16 ? 2 : 1; -  /* allocate memory fo scan : LINCNT may have been adjusted for CCD reordering */ -    if (dev->model->is_cis) { -        lines = dev->reg.get24(REG_LINCNT) / 3; -    } else { -        lines = dev->reg.get24(REG_LINCNT) + 1; -    } -  size = lines * settings.pixels; -    if (settings.depth == 16) { -        bpp = 2; -    } else { -        bpp = 1; -    } -    size *= bpp * settings.get_channels(); +    size *= bpp * session.params.channels;    data.clear();    data.resize(size); -  DBG(DBG_io, "%s: allocated %d bytes of memory for %d lines\n", __func__, size, lines); - -  /* put back real line number in settings */ -  settings.lines = lines; -      // initialize frontend -    gl646_set_fe(dev, sensor, AFE_SET, settings.xres); - -  /* no shading correction and not watch dog for simple scan */ -    dev->reg.find_reg(0x01).value &= ~(REG_0x01_DVDSET | REG_0x01_DOGENB); -    if (shading) { -      dev->reg.find_reg(0x01).value |= REG_0x01_DVDSET; -    } +    gl646_set_fe(dev, sensor, AFE_SET, session.params.xres); -  /* enable gamma table for the scan */ -    dev->reg.find_reg(0x05).value |= REG_0x05_GMMENB; +    // no watch dog for simple scan +    dev->reg.find_reg(0x01).value &= ~REG_0x01_DOGENB;    /* one table movement for simple scan */      dev->reg.find_reg(0x02).value &= ~REG_0x02_FASTFED;      if (!move) { -      sanei_genesys_set_motor_power(dev->reg, false); - -      /* no automatic go home if no movement */ -        dev->reg.find_reg(0x02).value &= ~REG_0x02_AGOHOME; +        sanei_genesys_set_motor_power(dev->reg, false);      }    /* no automatic go home when using XPA */ -  if (settings.scan_method == ScanMethod::TRANSPARENCY) { +    if (session.params.scan_method == ScanMethod::TRANSPARENCY) {          dev->reg.find_reg(0x02).value &= ~REG_0x02_AGOHOME;      } @@ -2946,46 +2699,38 @@ static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,      sanei_genesys_read_data_from_scanner(dev, data.data(), size);    /* in case of CIS scanner, we must reorder data */ -    if (dev->model->is_cis && settings.scan_mode == ScanColorMode::COLOR_SINGLE_PASS) { -      /* alloc one line sized working buffer */ -      std::vector<uint8_t> buffer(settings.pixels * 3 * bpp); - -      /* reorder one line of data and put it back to buffer */ -      if (bpp == 1) -	{ -	  for (y = 0; y < lines; y++) -	    { -	      /* reorder line */ -	      for (x = 0; x < settings.pixels; x++) -		{ -                  buffer[x * 3] = data[y * settings.pixels * 3 + x]; -                  buffer[x * 3 + 1] = data[y * settings.pixels * 3 + settings.pixels + x]; -                  buffer[x * 3 + 2] = data[y * settings.pixels * 3 + 2 * settings.pixels + x]; -		} -	      /* copy line back */ -              memcpy (data.data() + settings.pixels * 3 * y, buffer.data(), -		      settings.pixels * 3); -	    } -	} -      else -	{ -	  for (y = 0; y < lines; y++) -	    { -	      /* reorder line */ -	      for (x = 0; x < settings.pixels; x++) -		{ -                  buffer[x * 6] = data[y * settings.pixels * 6 + x * 2]; -                  buffer[x * 6 + 1] = data[y * settings.pixels * 6 + x * 2 + 1]; -                  buffer[x * 6 + 2] = data[y * settings.pixels * 6 + 2 * settings.pixels + x * 2]; -                  buffer[x * 6 + 3] = data[y * settings.pixels * 6 + 2 * settings.pixels + x * 2 + 1]; -                  buffer[x * 6 + 4] = data[y * settings.pixels * 6 + 4 * settings.pixels + x * 2]; -                  buffer[x * 6 + 5] = data[y * settings.pixels * 6 + 4 * settings.pixels + x * 2 + 1]; -		} -	      /* copy line back */ -              memcpy (data.data() + settings.pixels * 6 * y, buffer.data(), -		      settings.pixels * 6); -	    } -	} +    if (dev->model->is_cis && session.params.scan_mode == ScanColorMode::COLOR_SINGLE_PASS) { +        auto pixels_count = session.params.pixels; + +        std::vector<uint8_t> buffer(pixels_count * 3 * bpp); + +        if (bpp == 1) { +            for (unsigned y = 0; y < lines; y++) { +                // reorder line +                for (unsigned x = 0; x < pixels_count; x++) { +                    buffer[x * 3] = data[y * pixels_count * 3 + x]; +                    buffer[x * 3 + 1] = data[y * pixels_count * 3 + pixels_count + x]; +                    buffer[x * 3 + 2] = data[y * pixels_count * 3 + 2 * pixels_count + x]; +                } +                // copy line back +                std::memcpy(data.data() + pixels_count * 3 * y, buffer.data(), pixels_count * 3); +            } +        } else { +            for (unsigned y = 0; y < lines; y++) { +                // reorder line +                auto pixels_count = session.params.pixels; +                for (unsigned x = 0; x < pixels_count; x++) { +                    buffer[x * 6] = data[y * pixels_count * 6 + x * 2]; +                    buffer[x * 6 + 1] = data[y * pixels_count * 6 + x * 2 + 1]; +                    buffer[x * 6 + 2] = data[y * pixels_count * 6 + 2 * pixels_count + x * 2]; +                    buffer[x * 6 + 3] = data[y * pixels_count * 6 + 2 * pixels_count + x * 2 + 1]; +                    buffer[x * 6 + 4] = data[y * pixels_count * 6 + 4 * pixels_count + x * 2]; +                    buffer[x * 6 + 5] = data[y * pixels_count * 6 + 4 * pixels_count + x * 2 + 1]; +                } +                // copy line back +                std::memcpy(data.data() + pixels_count * 6 * y, buffer.data(),pixels_count * 6); +            } +        }      }      // end scan , waiting the motor to stop if needed (if moving), but without ejecting doc @@ -2993,42 +2738,6 @@ static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,  }  /** - * Does a simple move of the given distance by doing a scan at lowest resolution - * shading correction. Memory for data is allocated in this function - * and must be freed by caller. - * @param dev device of the scanner - * @param distance distance to move in MM - */ -static void simple_move(Genesys_Device* dev, SANE_Int distance) -{ -    DBG_HELPER_ARGS(dbg, "%d mm", distance); -  Genesys_Settings settings; - -    unsigned resolution = sanei_genesys_get_lowest_dpi(dev); - -  const auto& sensor = sanei_genesys_find_sensor(dev, resolution, 3, dev->model->default_method); - -  /* TODO give a no AGOHOME flag */ -    settings.scan_method = dev->model->default_method; -  settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; -  settings.xres = resolution; -  settings.yres = resolution; -  settings.tl_y = 0; -  settings.tl_x = 0; -  settings.pixels = (sensor.sensor_pixels * settings.xres) / sensor.optical_res; -    settings.requested_pixels = settings.pixels; -    settings.lines = static_cast<unsigned>((distance * settings.xres) / MM_PER_INCH); -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; - -  settings.disable_interpolation = 0; -  settings.threshold = 0; - -  std::vector<uint8_t> data; -    simple_scan(dev, sensor, settings, true, true, false, data, "simple_move"); -} - -/**   * update the status of the required sensor in the scanner session   * the button fileds are used to make events 'sticky'   */ @@ -3130,22 +2839,16 @@ void CommandSetGl646::update_hardware_sensors(Genesys_Scanner* session) const      }    /* XPA detection */ -  if (dev->model->flags & GENESYS_FLAG_XPA) -    { +    if (dev->model->has_method(ScanMethod::TRANSPARENCY)) {          switch (dev->model->gpio_id) {              case GpioId::HP3670:              case GpioId::HP2400:  	  /* test if XPA is plugged-in */ -	  if ((value & 0x40) == 0) -	    { -	      DBG(DBG_io, "%s: enabling XPA\n", __func__); -	      session->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE; -	    } -	  else -	    { -	      DBG(DBG_io, "%s: disabling XPA\n", __func__); -	      session->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; -	    } +            if ((value & 0x40) == 0) { +                session->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE; +            } else { +                session->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; +            }        break;              default:                  throw SaneException(SANE_STATUS_UNSUPPORTED, "unknown gpo type"); @@ -3153,6 +2856,11 @@ void CommandSetGl646::update_hardware_sensors(Genesys_Scanner* session) const      }  } +void CommandSetGl646::update_home_sensor_gpio(Genesys_Device& dev) const +{ +    DBG_HELPER(dbg); +    (void) dev; +}  static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int resolution)  { @@ -3167,7 +2875,7 @@ static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int    /* MD6471/G2410/HP2300 and XP200 read/write data from an undocumented memory area which     * is after the second slope table */ -  switch (sensor.optical_res) +  switch (sensor.full_resolution)      {      case 600:        addr = 0x08200; @@ -3203,159 +2911,9 @@ static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int        break;      } -  DBG(DBG_info, "%s: control write=0x%02x 0x%02x 0x%02x 0x%02x\n", __func__, control[0], control[1], -      control[2], control[3]);      dev->interface->write_buffer(0x3c, addr, control, 4);  } -/** - * search for a full width black or white strip. - * @param dev scanner device - * @param forward true if searching forward, false if searching backward - * @param black true if searching for a black strip, false for a white strip - */ -void CommandSetGl646::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward, -                                   bool black) const -{ -    DBG_HELPER(dbg); -    (void) sensor; - -  Genesys_Settings settings; -  int res = get_closest_resolution(dev->model->sensor_id, 75, 1); -  unsigned int pass, count, found, x, y; -  char title[80]; - -    const auto& calib_sensor = sanei_genesys_find_sensor(dev, res, 1, ScanMethod::FLATBED); - -  /* we set up for a lowest available resolution color grey scan, full width */ -    settings.scan_method = dev->model->default_method; -  settings.scan_mode = ScanColorMode::GRAY; -  settings.xres = res; -  settings.yres = res; -  settings.tl_x = 0; -  settings.tl_y = 0; -    settings.pixels = static_cast<unsigned>((dev->model->x_size * res) / MM_PER_INCH); -    settings.pixels /= calib_sensor.get_ccd_size_divisor_for_dpi(res); -    settings.requested_pixels = settings.pixels; - -  /* 15 mm at at time */ -    settings.lines = static_cast<unsigned>((15 * settings.yres) / MM_PER_INCH); -  settings.depth = 8; -  settings.color_filter = ColorFilter::RED; - -  settings.disable_interpolation = 0; -  settings.threshold = 0; - -  /* signals if a strip of the given color has been found */ -  found = 0; - -  /* detection pass done */ -  pass = 0; - -  std::vector<uint8_t> data; - -  /* loop until strip is found or maximum pass number done */ -  while (pass < 20 && !found) -    { -        // scan a full width strip -        simple_scan(dev, calib_sensor, settings, true, forward, false, data, "search_strip"); - -        if (is_testing_mode()) { -            return; -        } - -      if (DBG_LEVEL >= DBG_data) -	{ -            std::sprintf(title, "gl646_search_strip_%s%02d.pnm", forward ? "fwd" : "bwd", pass); -          sanei_genesys_write_pnm_file (title, data.data(), settings.depth, 1, -					settings.pixels, settings.lines); -	} - -      /* search data to find black strip */ -      /* when searching forward, we only need one line of the searched color since we -       * will scan forward. But when doing backward search, we need all the area of the -       * same color */ -      if (forward) -	{ -	  for (y = 0; y < settings.lines && !found; y++) -	    { -	      count = 0; -	      /* count of white/black pixels depending on the color searched */ -	      for (x = 0; x < settings.pixels; x++) -		{ -		  /* when searching for black, detect white pixels */ -		  if (black && data[y * settings.pixels + x] > 90) -		    { -		      count++; -		    } -		  /* when searching for white, detect black pixels */ -		  if (!black && data[y * settings.pixels + x] < 60) -		    { -		      count++; -		    } -		} - -	      /* at end of line, if count >= 3%, line is not fully of the desired color -	       * so we must go to next line of the buffer */ -	      /* count*100/pixels < 3 */ -	      if ((count * 100) / settings.pixels < 3) -		{ -		  found = 1; -		  DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__, -		      pass, y); -		} -	      else -		{ -		  DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count); -		} -	    } -	} -      else			/* since calibration scans are done forward, we need the whole area -				   to be of the required color when searching backward */ -	{ -	  count = 0; -	  for (y = 0; y < settings.lines; y++) -	    { -	      /* count of white/black pixels depending on the color searched */ -	      for (x = 0; x < settings.pixels; x++) -		{ -		  /* when searching for black, detect white pixels */ -		  if (black && data[y * settings.pixels + x] > 60) -		    { -		      count++; -		    } -		  /* when searching for white, detect black pixels */ -		  if (!black && data[y * settings.pixels + x] < 60) -		    { -		      count++; -		    } -		} -	    } - -	  /* at end of area, if count >= 3%, area is not fully of the desired color -	   * so we must go to next buffer */ -	  if ((count * 100) / (settings.pixels * settings.lines) < 3) -	    { -	      found = 1; -	      DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass); -	    } -	  else -	    { -	      DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count); -	    } -	} -      pass++; -    } -  if (found) -    { -      DBG(DBG_info, "%s: strip found\n", __func__); -    } -  else -    { -        throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white"); -    } -} -  void CommandSetGl646::wait_for_motor_stop(Genesys_Device* dev) const  {      (void) dev; @@ -3377,26 +2935,25 @@ ScanSession CommandSetGl646::calculate_scan_session(const Genesys_Device* dev,  {      // compute distance to move      float move = 0; -    // XXX STEF XXX MD5345 -> optical_ydpi, other base_ydpi => half/full step ? */      if (!dev->model->is_sheetfed) { -        move = static_cast<float>(dev->model->y_offset); +        move = dev->model->y_offset;          // add tl_y to base movement      } -    move += static_cast<float>(settings.tl_y); +    move += settings.tl_y;      if (move < 0) {          DBG(DBG_error, "%s: overriding negative move value %f\n", __func__, move);          move = 0;      } -    move = static_cast<float>((move * dev->motor.optical_ydpi) / MM_PER_INCH); -    float start = static_cast<float>(settings.tl_x); +    move = static_cast<float>((move * dev->motor.base_ydpi) / MM_PER_INCH); +    float start = settings.tl_x;      if (settings.scan_method == ScanMethod::FLATBED) { -        start += static_cast<float>(dev->model->x_offset); +        start += dev->model->x_offset;      } else { -        start += static_cast<float>(dev->model->x_offset_ta); +        start += dev->model->x_offset_ta;      } -    start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH); +    start = static_cast<float>((start * settings.xres) / MM_PER_INCH);      ScanSession session;      session.params.xres = settings.xres; @@ -3411,7 +2968,7 @@ ScanSession CommandSetGl646::calculate_scan_session(const Genesys_Device* dev,      session.params.scan_method = dev->settings.scan_method;      session.params.scan_mode = settings.scan_mode;      session.params.color_filter = settings.color_filter; -    session.params.flags = ScanFlag::USE_XCORRECTION; +    session.params.flags = ScanFlag::AUTO_GO_HOME;      if (settings.scan_method == ScanMethod::TRANSPARENCY) {          session.params.flags |= ScanFlag::USE_XPA;      } @@ -3427,10 +2984,5 @@ void CommandSetGl646::asic_boot(Genesys_Device *dev, bool cold) const      throw SaneException("not implemented");  } -std::unique_ptr<CommandSet> create_gl646_cmd_set() -{ -    return std::unique_ptr<CommandSet>(new CommandSetGl646{}); -} -  } // namespace gl646  } // namespace genesys | 
