summaryrefslogtreecommitdiff
path: root/backend/genesys/gl646.cpp
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2020-08-24 18:45:55 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2020-08-24 18:45:55 +0200
commita77bc1fcbdf83cfdac9570c0a0ac886b5534c90f (patch)
treed839746371ecb8ed64ac81d2e37c11fcd25a00ac /backend/genesys/gl646.cpp
parent787fb1d54ec9ee5fb941ae897fb201feb9cb2fd1 (diff)
parent2b3e02411ecc09e7d41741b5587655c9b2f955b7 (diff)
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'backend/genesys/gl646.cpp')
-rw-r--r--backend/genesys/gl646.cpp1986
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