diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 1ee61c875..7603d58d8 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -4715,7 +4715,7 @@ static void probe_genesys_devices() of Genesys_Calibration_Cache as is. */ static const char* CALIBRATION_IDENT = "sane_genesys"; -static const int CALIBRATION_VERSION = 20; +static const int CALIBRATION_VERSION = 21; bool read_calibration(std::istream& str, Genesys_Device::Calibration& calibration, const std::string& path) diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp index cd0464966..277fdd03a 100644 --- a/backend/genesys/low.cpp +++ b/backend/genesys/low.cpp @@ -901,7 +901,7 @@ void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s, } s.pixel_startx += s.params.startx; - if (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE) { + if (sensor.stagger_config.stagger_at_resolution(s.params.xres, s.params.yres) > 0) { s.pixel_startx |= 1; } @@ -1062,37 +1062,10 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se // Note: staggering is not applied for calibration. Staggering starts at 2400 dpi s.num_staggered_lines = 0; - - if (dev->model->asic_type == AsicType::GL124 || - dev->model->asic_type == AsicType::GL841 || - dev->model->asic_type == AsicType::GL845 || - dev->model->asic_type == AsicType::GL846 || - dev->model->asic_type == AsicType::GL847) + if (!has_flag(s.params.flags, ScanFlag::IGNORE_LINE_DISTANCE)) { - if (s.ccd_size_divisor == 1 && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) { - s.num_staggered_lines = (4 * s.params.yres) / dev->motor.base_ydpi; - } - } - - if (dev->model->asic_type == AsicType::GL646) { - if (s.ccd_size_divisor == 1 && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) { - // for HP3670, stagger happens only at >=1200 dpi - if ((dev->model->motor_id != MotorId::HP3670 && - dev->model->motor_id != MotorId::HP2400) || - s.params.yres >= static_cast(sensor.optical_res)) - { - s.num_staggered_lines = (4 * s.params.yres) / dev->motor.base_ydpi; - } - } - } - - if (dev->model->asic_type == AsicType::GL843) { - if ((s.params.yres > 1200) && // FIXME: maybe ccd_size_divisor is the one that controls this? - !has_flag(s.params.flags, ScanFlag::IGNORE_LINE_DISTANCE) && - (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) - { - s.num_staggered_lines = (4 * s.params.yres) / dev->motor.base_ydpi; - } + s.num_staggered_lines = sensor.stagger_config.stagger_at_resolution(s.params.xres, + s.params.yres); } s.color_shift_lines_r = dev->model->ld_shift_r; diff --git a/backend/genesys/low.h b/backend/genesys/low.h index 1eef7c7f1..ada1643d6 100644 --- a/backend/genesys/low.h +++ b/backend/genesys/low.h @@ -122,7 +122,6 @@ #define GENESYS_FLAG_REPARK (1 << 7) /**< repark head (and check for lock) by moving without scanning */ #define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /**< do dark calibration */ -#define GENESYS_FLAG_STAGGERED_LINE (1 << 9) /**< pixel columns are shifted vertically for hi-res modes */ #define GENESYS_FLAG_MUST_WAIT (1 << 10) /**< tells wether the scanner must wait for the head when parking */ diff --git a/backend/genesys/sensor.cpp b/backend/genesys/sensor.cpp index 3fdcd836d..e54af654d 100644 --- a/backend/genesys/sensor.cpp +++ b/backend/genesys/sensor.cpp @@ -49,6 +49,15 @@ namespace genesys { +std::ostream& operator<<(std::ostream& out, const StaggerConfig& config) +{ + out << "StaggerConfig{\n" + << " min_resolution: " << config.min_resolution() << '\n' + << " lines_at_min: " << config.lines_at_min() << '\n' + << "}"; + return out; +} + std::ostream& operator<<(std::ostream& out, const FrontendType& type) { switch (type) { @@ -137,6 +146,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor) << " segment_size: " << sensor.segment_size << '\n' << " segment_order: " << format_indent_braced_list(4, format_vector_unsigned(4, sensor.segment_order)) << '\n' + << " stagger_config: " << format_indent_braced_list(4, sensor.stagger_config) << '\n' << " custom_base_regs: " << format_indent_braced_list(4, sensor.custom_base_regs) << '\n' << " custom_regs: " << format_indent_braced_list(4, sensor.custom_regs) << '\n' << " custom_fe_regs: " << format_indent_braced_list(4, sensor.custom_fe_regs) << '\n' diff --git a/backend/genesys/sensor.h b/backend/genesys/sensor.h index 5c117a549..e70728e66 100644 --- a/backend/genesys/sensor.h +++ b/backend/genesys/sensor.h @@ -67,6 +67,51 @@ struct AssignableArray : public std::array { } }; + +class StaggerConfig +{ +public: + StaggerConfig() = default; + StaggerConfig(unsigned min_resolution, unsigned lines_at_min) : + min_resolution_{min_resolution}, + lines_at_min_{lines_at_min} + { + } + + unsigned stagger_at_resolution(unsigned xresolution, unsigned yresolution) const + { + if (min_resolution_ == 0 || xresolution < min_resolution_) + return 0; + return yresolution / min_resolution_ * lines_at_min_; + } + + unsigned min_resolution() const { return min_resolution_; } + unsigned lines_at_min() const { return lines_at_min_; } + + bool operator==(const StaggerConfig& other) const + { + return min_resolution_ == other.min_resolution_ && + lines_at_min_ == other.lines_at_min_; + } + +private: + unsigned min_resolution_ = 0; + unsigned lines_at_min_ = 0; + + template + friend void serialize(Stream& str, StaggerConfig& x); +}; + +template +void serialize(Stream& str, StaggerConfig& x) +{ + serialize(str, x.min_resolution_); + serialize(str, x.lines_at_min_); +} + +std::ostream& operator<<(std::ostream& out, const StaggerConfig& config); + + enum class FrontendType : unsigned { UNKNOWN, @@ -310,6 +355,10 @@ struct Genesys_Sensor { // only on gl843 std::vector segment_order; + // some CCDs use two arrays of pixels for double resolution. On such CCDs when scanning at + // high-enough resolution, every other pixel column is shifted + StaggerConfig stagger_config; + GenesysRegisterSettingSet custom_base_regs; // gl646-specific GenesysRegisterSettingSet custom_regs; GenesysRegisterSettingSet custom_fe_regs; @@ -370,6 +419,7 @@ struct Genesys_Sensor { exposure_lperiod == other.exposure_lperiod && segment_size == other.segment_size && segment_order == other.segment_order && + stagger_config == other.stagger_config && custom_base_regs == other.custom_base_regs && custom_regs == other.custom_regs && custom_fe_regs == other.custom_fe_regs && @@ -401,6 +451,8 @@ void serialize(Stream& str, Genesys_Sensor& x) serialize_newline(str); serialize(str, x.segment_order); serialize_newline(str); + serialize(str, x.stagger_config); + serialize_newline(str); serialize(str, x.custom_base_regs); serialize_newline(str); serialize(str, x.custom_regs); diff --git a/backend/genesys/tables_model.cpp b/backend/genesys/tables_model.cpp index 311256d2b..aec20568e 100644 --- a/backend/genesys/tables_model.cpp +++ b/backend/genesys/tables_model.cpp @@ -295,7 +295,6 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::G4050; model.motor_id = MotorId::G4050; model.flags = GENESYS_FLAG_OFFSET_CALIBRATION | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA; @@ -355,7 +354,6 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::G4050; model.motor_id = MotorId::G4050; model.flags = GENESYS_FLAG_OFFSET_CALIBRATION | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA; @@ -417,7 +415,6 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::G4050; model.motor_id = MotorId::G4050; model.flags = GENESYS_FLAG_OFFSET_CALIBRATION | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA; @@ -479,7 +476,6 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::CANON_4400F; model.motor_id = MotorId::CANON_4400F; model.flags = GENESYS_FLAG_OFFSET_CALIBRATION | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_FULL_HWDPI_MODE | @@ -553,7 +549,6 @@ void genesys_init_usb_device_tables() model.flags = GENESYS_FLAG_HAS_UTA | GENESYS_FLAG_HAS_UTA_INFRARED | GENESYS_FLAG_OFFSET_CALIBRATION | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_FULL_HWDPI_MODE | @@ -627,7 +622,6 @@ void genesys_init_usb_device_tables() model.flags = GENESYS_FLAG_HAS_UTA | GENESYS_FLAG_HAS_UTA_INFRARED | GENESYS_FLAG_OFFSET_CALIBRATION | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_FULL_HWDPI_MODE | @@ -1405,7 +1399,6 @@ void genesys_init_usb_device_tables() GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_SKIP_WARMUP | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_CUSTOM_GAMMA; model.buttons = GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW; model.shading_lines = 20; @@ -1530,7 +1523,6 @@ void genesys_init_usb_device_tables() GENESYS_FLAG_XPA | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_CUSTOM_GAMMA; model.buttons = GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW; model.shading_lines = 20; @@ -1708,7 +1700,6 @@ void genesys_init_usb_device_tables() model.motor_id = MotorId::MD_5345; model.flags = GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_SEARCH_START | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_SHADING_NO_MOVE | @@ -2381,7 +2372,6 @@ void genesys_init_usb_device_tables() model.motor_id = MotorId::MD_5345; model.flags = GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_SEARCH_START | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA; @@ -2447,7 +2437,6 @@ void genesys_init_usb_device_tables() model.motor_id = MotorId::MD_5345; model.flags = GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_SEARCH_START | - GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA; diff --git a/backend/genesys/tables_sensor.cpp b/backend/genesys/tables_sensor.cpp index 8217eaffb..06779bf56 100644 --- a/backend/genesys/tables_sensor.cpp +++ b/backend/genesys/tables_sensor.cpp @@ -263,6 +263,7 @@ void genesys_init_sensor_tables() sensor.fau_gain_white_ref = 190; sensor.gain_white_ref = 190; sensor.exposure = { 0x0000, 0x0000, 0x0000 }; + sensor.stagger_config = StaggerConfig{ 1200, 4 }; // FIXME: may be incorrect sensor.custom_base_regs = { { 0x08, 0x0d }, { 0x09, 0x0f }, @@ -580,6 +581,7 @@ void genesys_init_sensor_tables() sensor.fau_gain_white_ref = 210; sensor.gain_white_ref = 200; sensor.exposure = { 0x0000, 0x0000, 0x0000 }; + sensor.stagger_config = StaggerConfig{1200, 4}; // FIXME: may be incorrect sensor.custom_base_regs = { { 0x08, 0x14 }, { 0x09, 0x15 }, @@ -1137,6 +1139,7 @@ void genesys_init_sensor_tables() sensor.fau_gain_white_ref = 210; sensor.gain_white_ref = 200; sensor.exposure = { 0, 0, 0 }; + sensor.stagger_config = StaggerConfig{1200, 4}; // FIXME: may be incorrect sensor.custom_base_regs = { { 0x08, 0x00 }, { 0x09, 0x0a }, @@ -1933,6 +1936,7 @@ void genesys_init_sensor_tables() sensor.fau_gain_white_ref = 160; sensor.gain_white_ref = 160; sensor.exposure = { 0x2c09, 0x22b8, 0x10f0 }; + sensor.stagger_config = StaggerConfig{ 2400, 4 }; // FIXME: may be incorrect sensor.custom_regs = {}; sensor.gamma = { 1.0f, 1.0f, 1.0f }; sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi; @@ -2259,6 +2263,7 @@ void genesys_init_sensor_tables() sensor.fau_gain_white_ref = 160; sensor.gain_white_ref = 160; sensor.exposure = { 0x9c40, 0x9c40, 0x9c40 }; + sensor.stagger_config = StaggerConfig{ 1600, 4 }; // FIXME: may be incorrect sensor.custom_regs = {}; sensor.gamma = { 1.0f, 1.0f, 1.0f }; sensor.get_logical_hwdpi_fun = get_sensor_optical_with_ccd_divisor; @@ -2528,6 +2533,7 @@ void genesys_init_sensor_tables() sensor.fau_gain_white_ref = 160; sensor.gain_white_ref = 160; sensor.exposure = { 0x9c40, 0x9c40, 0x9c40 }; + sensor.stagger_config = StaggerConfig{ 2400, 4 }; // FIXME: may be incorrect sensor.custom_regs = {}; sensor.gamma = { 1.0f, 1.0f, 1.0f }; sensor.get_logical_hwdpi_fun = get_sensor_optical_with_ccd_divisor;