From 7cf2560dda776a806d47e747cdf9555ee5120ba7 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:20:54 +0200 Subject: [PATCH 01/25] genesys: Remove unused two-table feeding support from gl124 --- backend/genesys/gl124.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/backend/genesys/gl124.cpp b/backend/genesys/gl124.cpp index ab7f94c1d..61533dcfc 100644 --- a/backend/genesys/gl124.cpp +++ b/backend/genesys/gl124.cpp @@ -453,7 +453,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, ScanFlag flags) { DBG_HELPER(dbg); - int use_fast_fed; unsigned int lincnt, fast_dpi; unsigned int feedl,dist; std::uint32_t z1, z2; @@ -467,9 +466,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, feed_steps, static_cast(scan_mode), static_cast(flags)); - /* we never use fast fed since we do manual feed for the scans */ - use_fast_fed=0; - /* enforce motor minimal scan speed * @TODO extend motor struct for this value */ if (scan_mode == ScanColorMode::COLOR_SINGLE_PASS) @@ -516,12 +512,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, /* compute register 02 value */ std::uint8_t r02 = REG_0x02_NOTHOME; - if (use_fast_fed) { - r02 |= REG_0x02_FASTFED; - } else { - r02 &= ~REG_0x02_FASTFED; - } - if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { r02 |= REG_0x02_AGOHOME; } @@ -573,9 +563,6 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, if (has_flag(flags, ScanFlag::FEEDING)) { dist *= 2; } - if (use_fast_fed) { - dist += fast_table.table.size() * 2; - } /* get sure we don't use insane value */ if (dist < feedl) { @@ -587,7 +574,7 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, reg->set24(REG_FEEDL, feedl); /* doesn't seem to matter that much */ - sanei_genesys_calculate_zmod(use_fast_fed, + sanei_genesys_calculate_zmod(false, scan_exposure_time, scan_table.table, scan_table.table.size(), From 38eb785b42922e2c4960abc958623970187e2d7d Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:20:55 +0200 Subject: [PATCH 02/25] genesys: Remove unused two-table feeding support from gl846 --- backend/genesys/gl846.cpp | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/backend/genesys/gl846.cpp b/backend/genesys/gl846.cpp index 857dc9f8e..023e1afc0 100644 --- a/backend/genesys/gl846.cpp +++ b/backend/genesys/gl846.cpp @@ -375,25 +375,13 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev, unsigned step_multiplier = gl846_get_step_multiplier(reg); - bool use_fast_fed = false; - if (dev->settings.yres == 4444 && feed_steps > 100 && !has_flag(flags, ScanFlag::FEEDING)) { - use_fast_fed = true; - } - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } - reg->set24(REG_LINCNT, scan_lines); reg->set8(REG_0x02, 0); sanei_genesys_set_motor_power(*reg, true); std::uint8_t reg02 = reg->get8(REG_0x02); - if (use_fast_fed) { - reg02 |= REG_0x02_FASTFED; - } else { - reg02 &= ~REG_0x02_FASTFED; - } + reg02 &= ~REG_0x02_FASTFED; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME; @@ -447,18 +435,11 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev, unsigned feedl = feed_steps; unsigned dist = 0; - if (use_fast_fed) { - feedl <<= static_cast(fast_profile->step_type); - dist = (scan_table.table.size() + 2 * fast_table.table.size()); - // TODO read and decode REG_0xAB - dist += (reg->get8(0x5e) & 31); - dist += reg->get8(REG_FEDCNT); - } else { - feedl <<= static_cast(motor_profile.step_type); - dist = scan_table.table.size(); - if (has_flag(flags, ScanFlag::FEEDING)) { - dist *= 2; - } + + feedl <<= static_cast(motor_profile.step_type); + dist = scan_table.table.size(); + if (has_flag(flags, ScanFlag::FEEDING)) { + dist *= 2; } // check for overflow @@ -514,7 +495,7 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev, reg->set8(REG_BWDSTEP, min_restep); std::uint32_t z1, z2; - sanei_genesys_calculate_zmod(use_fast_fed, + sanei_genesys_calculate_zmod(false, scan_exposure_time * ccdlmt * tgtime, scan_table.table, scan_table.table.size(), From 3bb3ddb25904b716650dc946ab7985c572cb152b Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:20:56 +0200 Subject: [PATCH 03/25] genesys: Remove unused two-table feeding support from gl847 --- backend/genesys/gl847.cpp | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/backend/genesys/gl847.cpp b/backend/genesys/gl847.cpp index 19f81984d..cf18f389b 100644 --- a/backend/genesys/gl847.cpp +++ b/backend/genesys/gl847.cpp @@ -339,25 +339,13 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev, unsigned step_multiplier = gl847_get_step_multiplier (reg); - bool use_fast_fed = false; - if (dev->settings.yres == 4444 && feed_steps > 100 && !has_flag(flags, ScanFlag::FEEDING)) { - use_fast_fed = true; - } - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } - reg->set24(REG_LINCNT, scan_lines); reg->set8(REG_0x02, 0); sanei_genesys_set_motor_power(*reg, true); std::uint8_t reg02 = reg->get8(REG_0x02); - if (use_fast_fed) { - reg02 |= REG_0x02_FASTFED; - } else { - reg02 &= ~REG_0x02_FASTFED; - } + reg02 &= ~REG_0x02_FASTFED; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME; @@ -403,19 +391,11 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev, // correct move distance by acceleration and deceleration amounts unsigned feedl = feed_steps; unsigned dist = 0; - if (use_fast_fed) - { - feedl <<= static_cast(fast_step_type); - dist = (scan_table.table.size() + 2 * fast_table.table.size()); - // TODO read and decode REG_0xAB - dist += (reg->get8(0x5e) & 31); - dist += reg->get8(REG_FEDCNT); - } else { - feedl <<= static_cast(motor_profile.step_type); - dist = scan_table.table.size(); - if (has_flag(flags, ScanFlag::FEEDING)) { - dist *= 2; - } + + feedl <<= static_cast(motor_profile.step_type); + dist = scan_table.table.size(); + if (has_flag(flags, ScanFlag::FEEDING)) { + dist *= 2; } // check for overflow @@ -457,7 +437,7 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev, reg->set8(REG_BWDSTEP, min_restep); std::uint32_t z1, z2; - sanei_genesys_calculate_zmod(use_fast_fed, + sanei_genesys_calculate_zmod(false, scan_exposure_time * ccdlmt * tgtime, scan_table.table, scan_table.table.size(), From 5d93b397022ca0503765d999b92ee482fec5c99e Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:20:57 +0200 Subject: [PATCH 04/25] genesys: Remove broken two-table feeding support from gl841 At least on LiDE 50 two-table feeding caused unexplained motor spin-up failures on certain motor exposures. Various register modifications showed that there's high likelihood on device-side bug. Even the official drivers don't use proper two-table feeding. --- backend/genesys/gl841.cpp | 60 +-------------------------------------- 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index 57d4b7249..140bd9679 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -598,7 +598,6 @@ static void gl841_init_motor_regs_feed(Genesys_Device* dev, const Genesys_Sensor { DBG_HELPER_ARGS(dbg, "feed_steps=%d, flags=%x", feed_steps, static_cast(flags)); unsigned step_multiplier = 2; - int use_fast_fed = 0; unsigned int feedl; /*number of scan lines to add in a scan_lines line*/ @@ -629,10 +628,6 @@ static void gl841_init_motor_regs_feed(Genesys_Device* dev, const Genesys_Sensor // BUG: fast table is counted in base_ydpi / 4 feedl = feed_steps - fast_table.table.size() * 2; - use_fast_fed = 1; - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } reg->set8(0x3d, (feedl >> 16) & 0xf); reg->set8(0x3e, (feedl >> 8) & 0xff); @@ -647,10 +642,6 @@ static void gl841_init_motor_regs_feed(Genesys_Device* dev, const Genesys_Sensor reg->find_reg(0x02).value &= ~0x80; /*NOT_HOME OFF*/ reg->find_reg(0x02).value |= REG_0x02_MTRPWR; - - if (use_fast_fed) - reg->find_reg(0x02).value |= 0x08; - else reg->find_reg(0x02).value &= ~0x08; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { @@ -697,9 +688,6 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor unsigned step_multiplier = 2; - int use_fast_fed = 0; - unsigned int fast_time; - unsigned int slow_time; unsigned int feedl; unsigned int min_restep = 0x20; @@ -736,54 +724,11 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor fast_table.slice_steps(max_fast_slope_steps_count, step_multiplier); } - /* fast fed special cases handling */ - if (dev->model->gpio_id == GpioId::XP300 - || dev->model->gpio_id == GpioId::DP685) - { - /* quirk: looks like at least this scanner is unable to use - 2-feed mode */ - use_fast_fed = 0; - } - else if (feed_steps < fast_table.table.size() * 2 + - (slow_table.table.size() >> static_cast(motor_profile.step_type))) - { - use_fast_fed = 0; - DBG(DBG_info, "%s: feed too short, slow move forced.\n", __func__); - } else { -/* for deciding whether we should use fast mode we need to check how long we - need for (fast)accelerating, moving, decelerating, (TODO: stopping?) - (slow)accelerating again versus (slow)accelerating and moving. we need - fast and slow tables here. -*/ -/*NOTE: scan_exposure_time is per scan_yres*/ -/*NOTE: fast_exposure is per base_ydpi/4*/ -/*we use full steps as base unit here*/ - fast_time = - (fast_table.table.back() << static_cast(fast_profile->step_type)) / 4 * - (feed_steps - fast_table.table.size()*2 - - (slow_table.table.size() >> static_cast(motor_profile.step_type))) - + fast_table.pixeltime_sum() * 2 + slow_table.pixeltime_sum(); - slow_time = - (scan_exposure_time * scan_yres) / dev->motor.base_ydpi * - (feed_steps - (slow_table.table.size() >> static_cast(motor_profile.step_type))) - + slow_table.pixeltime_sum(); - - use_fast_fed = fast_time < slow_time; - } - - if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) { - use_fast_fed = false; - } - - if (use_fast_fed) { - feedl = feed_steps - fast_table.table.size() * 2 - - (slow_table.table.size() >> static_cast(motor_profile.step_type)); - } else if ((feed_steps << static_cast(motor_profile.step_type)) < slow_table.table.size()) { + if ((feed_steps << static_cast(motor_profile.step_type)) < slow_table.table.size()) { feedl = 0; } else { feedl = (feed_steps << static_cast(motor_profile.step_type)) - slow_table.table.size(); } - DBG(DBG_info, "%s: Decided to use %s mode\n", __func__, use_fast_fed?"fast feed":"slow feed"); reg->set8(0x3d, (feedl >> 16) & 0xf); reg->set8(0x3e, (feedl >> 8) & 0xff); @@ -800,9 +745,6 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor reg->find_reg(0x02).value &= ~REG_0x02_MTRREV; } - if (use_fast_fed) - reg->find_reg(0x02).value |= 0x08; - else reg->find_reg(0x02).value &= ~0x08; if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) From f439c97eaecf27703c23cfd669d49ddedd66d423 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:20:58 +0200 Subject: [PATCH 05/25] genesys: Inline gl841_get_led_exposure() --- backend/genesys/gl841.cpp | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index 140bd9679..1c261c32a 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -945,27 +945,6 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens reg->set8(0x34, sensor.dummy_pixel); } -static int -gl841_get_led_exposure(Genesys_Device * dev, const Genesys_Sensor& sensor) -{ - int d,r,g,b,m; - if (!dev->model->is_cis) - return 0; - d = dev->reg.find_reg(0x19).value; - - r = sensor.exposure.red; - g = sensor.exposure.green; - b = sensor.exposure.blue; - - m = r; - if (m < g) - m = g; - if (m < b) - m = b; - - return m + d; -} - /** @brief compute exposure time * Compute exposure time for the device and the given scan resolution */ @@ -974,9 +953,13 @@ static int gl841_exposure_time(Genesys_Device *dev, const Genesys_Sensor& sensor int start, int used_pixels) { -int led_exposure; - - led_exposure=gl841_get_led_exposure(dev, sensor); + int led_exposure = 0; + if (dev->model->is_cis) { + unsigned dummy = dev->reg.find_reg(0x19).value; + unsigned min_sensor_exposure = std::min({sensor.exposure.red, sensor.exposure.green, + sensor.exposure.blue}); + led_exposure = dummy + min_sensor_exposure; + } return sanei_genesys_exposure_time2(dev, profile, slope_dpi, start + used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ led_exposure); From 662fec6801c6058d58df0ad8c33e9692fc4080ba Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:20:59 +0200 Subject: [PATCH 06/25] genesys: Fix incorrect scan exposure setup on gl841 When sensor exposure values are significantly different from each other the total scan exposure will be too low leading to the device becoming confused and significantly --- backend/genesys/gl841.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index 1c261c32a..41a4c48b5 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -956,9 +956,9 @@ static int gl841_exposure_time(Genesys_Device *dev, const Genesys_Sensor& sensor int led_exposure = 0; if (dev->model->is_cis) { unsigned dummy = dev->reg.find_reg(0x19).value; - unsigned min_sensor_exposure = std::min({sensor.exposure.red, sensor.exposure.green, + unsigned max_sensor_exposure = std::max({sensor.exposure.red, sensor.exposure.green, sensor.exposure.blue}); - led_exposure = dummy + min_sensor_exposure; + led_exposure = dummy + max_sensor_exposure; } return sanei_genesys_exposure_time2(dev, profile, slope_dpi, start + used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ From af026e1ae618ab886dde36c935d24db8a95d546a Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:00 +0200 Subject: [PATCH 07/25] genesys: Remove true_gray variable by deriving its value directly --- backend/genesys/genesys.cpp | 6 ------ backend/genesys/gl646.cpp | 4 +++- backend/genesys/gl841.cpp | 3 ++- backend/genesys/low.cpp | 3 ++- backend/genesys/settings.h | 3 --- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 9f20e04c3..653fc0934 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -4370,12 +4370,6 @@ static Genesys_Settings calculate_scan_settings(Genesys_Scanner* s) settings.color_filter = ColorFilter::NONE; } - if (s->color_filter == "None") { - settings.true_gray = 1; - } else { - settings.true_gray = 0; - } - // brightness and contrast only for for 8 bit scans if (s->bit_depth == 8) { settings.contrast = (s->contrast * 127) / 100; diff --git a/backend/genesys/gl646.cpp b/backend/genesys/gl646.cpp index 6536fb4d3..04ddb7b4c 100644 --- a/backend/genesys/gl646.cpp +++ b/backend/genesys/gl646.cpp @@ -606,7 +606,9 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene } /* true CIS gray if needed */ - if (dev->model->is_cis && session.params.channels == 1 && dev->settings.true_gray) { + if (dev->model->is_cis && session.params.channels == 1 && + session.params.color_filter == ColorFilter::NONE) + { regs->find_reg(0x05).value |= REG_0x05_LEDADD; } else { regs->find_reg(0x05).value &= ~REG_0x05_LEDADD; diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index 41a4c48b5..eb073fa23 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -1093,7 +1093,8 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev, ScanFlag flags = ScanFlag::NONE; // true gray (led add for cis scanners) - if (dev->model->is_cis && dev->settings.true_gray && + if (dev->model->is_cis && + settings.color_filter == ColorFilter::NONE && dev->settings.scan_mode != ScanColorMode::COLOR_SINGLE_PASS && dev->model->sensor_id != SensorId::CIS_CANON_LIDE_80) { diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp index 371bebdd2..616cad5b2 100644 --- a/backend/genesys/low.cpp +++ b/backend/genesys/low.cpp @@ -1119,7 +1119,8 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se dev->model->asic_type == AsicType::GL845 || dev->model->asic_type == AsicType::GL846) { - s.enable_ledadd = (s.params.channels == 1 && dev->model->is_cis && dev->settings.true_gray); + s.enable_ledadd = (s.params.channels == 1 && dev->model->is_cis && + s.params.color_filter == ColorFilter::NONE); } s.use_host_side_calib = sensor.use_host_side_calib; diff --git a/backend/genesys/settings.h b/backend/genesys/settings.h index f95b12fe4..d2b7f1fa8 100644 --- a/backend/genesys/settings.h +++ b/backend/genesys/settings.h @@ -76,9 +76,6 @@ struct Genesys_Settings ColorFilter color_filter = ColorFilter::NONE; - // true if scan is true gray, false if monochrome scan - int true_gray = 0; - // value for contrast enhancement in the [-100..100] range int contrast = 0; From 4fa5b54b15e91fd18ced3ba9c224702a5905cd34 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:01 +0200 Subject: [PATCH 08/25] genesys: Rename ImagePipelineNodeMergeMono{Lines -> LinesToColor} --- backend/genesys/image_pipeline.cpp | 10 +++++----- backend/genesys/image_pipeline.h | 6 +++--- backend/genesys/low.cpp | 6 +++--- testsuite/backend/genesys/tests_image_pipeline.cpp | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/backend/genesys/image_pipeline.cpp b/backend/genesys/image_pipeline.cpp index f1dca36b4..c8f1558d3 100644 --- a/backend/genesys/image_pipeline.cpp +++ b/backend/genesys/image_pipeline.cpp @@ -304,8 +304,8 @@ bool ImagePipelineNodeInvert::get_next_row_data(std::uint8_t* out_data) return got_data; } -ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source, - ColorOrder color_order) : +ImagePipelineNodeMergeMonoLinesToColor::ImagePipelineNodeMergeMonoLinesToColor( + ImagePipelineNode& source, ColorOrder color_order) : source_(source), buffer_(source_.get_row_bytes()) { @@ -314,7 +314,7 @@ ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNo output_format_ = get_output_format(source_.get_format(), color_order); } -bool ImagePipelineNodeMergeMonoLines::get_next_row_data(std::uint8_t* out_data) +bool ImagePipelineNodeMergeMonoLinesToColor::get_next_row_data(std::uint8_t* out_data) { bool got_data = true; @@ -341,8 +341,8 @@ bool ImagePipelineNodeMergeMonoLines::get_next_row_data(std::uint8_t* out_data) return got_data; } -PixelFormat ImagePipelineNodeMergeMonoLines::get_output_format(PixelFormat input_format, - ColorOrder order) +PixelFormat ImagePipelineNodeMergeMonoLinesToColor::get_output_format(PixelFormat input_format, + ColorOrder order) { switch (input_format) { case PixelFormat::I1: { diff --git a/backend/genesys/image_pipeline.h b/backend/genesys/image_pipeline.h index 3632b36eb..aaf8312f2 100644 --- a/backend/genesys/image_pipeline.h +++ b/backend/genesys/image_pipeline.h @@ -295,11 +295,11 @@ private: }; // A pipeline node that merges 3 mono lines into a color channel -class ImagePipelineNodeMergeMonoLines : public ImagePipelineNode +class ImagePipelineNodeMergeMonoLinesToColor : public ImagePipelineNode { public: - ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source, - ColorOrder color_order); + ImagePipelineNodeMergeMonoLinesToColor(ImagePipelineNode& source, + ColorOrder color_order); std::size_t get_width() const override { return source_.get_width(); } std::size_t get_height() const override { return source_.get_height() / 3; } diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp index 616cad5b2..2626aecba 100644 --- a/backend/genesys/low.cpp +++ b/backend/genesys/low.cpp @@ -442,7 +442,7 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession& } if (dev->model->is_cis && session.params.channels == 3) { - pipeline.push_node(dev->model->line_mode_color_order); + pipeline.push_node(dev->model->line_mode_color_order); } if (pipeline.get_output_format() == PixelFormat::BGR888) { @@ -540,7 +540,7 @@ Image read_shuffled_image_from_scanner(Genesys_Device* dev, const ScanSession& s } if (dev->model->is_cis && session.params.channels == 3) { - pipeline.push_node(dev->model->line_mode_color_order); + pipeline.push_node(dev->model->line_mode_color_order); } if (pipeline.get_output_format() == PixelFormat::BGR888) { @@ -1218,7 +1218,7 @@ ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSes } if (dev.model->is_cis && session.params.channels == 3) { - pipeline.push_node(dev.model->line_mode_color_order); + pipeline.push_node(dev.model->line_mode_color_order); if (log_image_data) { pipeline.push_node(debug_prefix + "_4_after_merge_mono.tiff"); diff --git a/testsuite/backend/genesys/tests_image_pipeline.cpp b/testsuite/backend/genesys/tests_image_pipeline.cpp index 8edeff8ab..7baebd6e4 100644 --- a/testsuite/backend/genesys/tests_image_pipeline.cpp +++ b/testsuite/backend/genesys/tests_image_pipeline.cpp @@ -468,7 +468,7 @@ void test_node_invert_1_bits() ASSERT_EQ(out_data, expected_data); } -void test_node_merge_mono_lines() +void test_node_merge_mono_lines_to_color() { using Data = std::vector; @@ -481,7 +481,7 @@ void test_node_merge_mono_lines() ImagePipelineStack stack; stack.push_first_node(8, 3, PixelFormat::I8, std::move(in_data)); - stack.push_node(ColorOrder::RGB); + stack.push_node(ColorOrder::RGB); ASSERT_EQ(stack.get_output_width(), 8u); ASSERT_EQ(stack.get_output_height(), 1u); @@ -937,7 +937,7 @@ void test_image_pipeline() test_node_invert_16_bits(); test_node_invert_8_bits(); test_node_invert_1_bits(); - test_node_merge_mono_lines(); + test_node_merge_mono_lines_to_color(); test_node_split_mono_lines(); test_node_component_shift_lines(); test_node_pixel_shift_columns_no_switch(); From 1980b4edd2696802b7fce8260af2892f959fadb9 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:02 +0200 Subject: [PATCH 09/25] genesys: Implement image pipeline for merging color channels to gray --- backend/genesys/image_pipeline.cpp | 69 +++++++++++++++++++ backend/genesys/image_pipeline.h | 27 ++++++++ .../backend/genesys/tests_image_pipeline.cpp | 32 +++++++++ 3 files changed, 128 insertions(+) diff --git a/backend/genesys/image_pipeline.cpp b/backend/genesys/image_pipeline.cpp index c8f1558d3..60ebfd222 100644 --- a/backend/genesys/image_pipeline.cpp +++ b/backend/genesys/image_pipeline.cpp @@ -417,6 +417,75 @@ PixelFormat ImagePipelineNodeSplitMonoLines::get_output_format(PixelFormat input throw SaneException("Unsupported input format %d", static_cast(input_format)); } + +ImagePipelineNodeMergeColorToGray::ImagePipelineNodeMergeColorToGray(ImagePipelineNode& source) : + source_(source) +{ + + output_format_ = get_output_format(source_.get_format()); + float red_mult = 0.2125f; + float green_mult = 0.7154f; + float blue_mult = 0.0721f; + + switch (get_pixel_format_color_order(source_.get_format())) { + case ColorOrder::RGB: { + ch0_mult_ = red_mult; + ch1_mult_ = green_mult; + ch2_mult_ = blue_mult; + break; + } + case ColorOrder::BGR: { + ch0_mult_ = blue_mult; + ch1_mult_ = green_mult; + ch2_mult_ = red_mult; + break; + } + case ColorOrder::GBR: { + ch0_mult_ = green_mult; + ch1_mult_ = blue_mult; + ch2_mult_ = red_mult; + break; + } + default: + throw SaneException("Unknown color order"); + } + temp_buffer_.resize(source_.get_row_bytes()); +} + +bool ImagePipelineNodeMergeColorToGray::get_next_row_data(std::uint8_t* out_data) +{ + auto* src_data = temp_buffer_.data(); + + bool got_data = source_.get_next_row_data(src_data); + + auto src_format = source_.get_format(); + + for (std::size_t x = 0, width = get_width(); x < width; ++x) { + std::uint16_t ch0 = get_raw_channel_from_row(src_data, x, 0, src_format); + std::uint16_t ch1 = get_raw_channel_from_row(src_data, x, 1, src_format); + std::uint16_t ch2 = get_raw_channel_from_row(src_data, x, 2, src_format); + float mono = ch0 * ch0_mult_ + ch1 * ch1_mult_ + ch2 * ch2_mult_; + set_raw_channel_to_row(out_data, x, 0, static_cast(mono), output_format_); + } + return got_data; +} + +PixelFormat ImagePipelineNodeMergeColorToGray::get_output_format(PixelFormat input_format) +{ + switch (input_format) { + case PixelFormat::RGB111: + return PixelFormat::I1; + case PixelFormat::RGB888: + case PixelFormat::BGR888: + return PixelFormat::I8; + case PixelFormat::RGB161616: + case PixelFormat::BGR161616: + return PixelFormat::I16; + default: break; + } + throw SaneException("Unsupported format %d", static_cast(input_format)); +} + ImagePipelineNodeComponentShiftLines::ImagePipelineNodeComponentShiftLines( ImagePipelineNode& source, unsigned shift_r, unsigned shift_g, unsigned shift_b) : source_(source), diff --git a/backend/genesys/image_pipeline.h b/backend/genesys/image_pipeline.h index aaf8312f2..8e4915514 100644 --- a/backend/genesys/image_pipeline.h +++ b/backend/genesys/image_pipeline.h @@ -342,6 +342,33 @@ private: unsigned next_channel_ = 0; }; + +// A pipeline node that merges 3 mono lines into a gray channel +class ImagePipelineNodeMergeColorToGray : public ImagePipelineNode +{ +public: + ImagePipelineNodeMergeColorToGray(ImagePipelineNode& source); + + std::size_t get_width() const override { return source_.get_width(); } + std::size_t get_height() const override { return source_.get_height(); } + PixelFormat get_format() const override { return output_format_; } + + bool eof() const override { return source_.eof(); } + + bool get_next_row_data(std::uint8_t* out_data) override; + +private: + static PixelFormat get_output_format(PixelFormat input_format); + + ImagePipelineNode& source_; + PixelFormat output_format_ = PixelFormat::UNKNOWN; + float ch0_mult_ = 0; + float ch1_mult_ = 0; + float ch2_mult_ = 0; + + std::vector temp_buffer_; +}; + // A pipeline node that shifts colors across lines by the given offsets class ImagePipelineNodeComponentShiftLines : public ImagePipelineNode { diff --git a/testsuite/backend/genesys/tests_image_pipeline.cpp b/testsuite/backend/genesys/tests_image_pipeline.cpp index 7baebd6e4..8c46e8d89 100644 --- a/testsuite/backend/genesys/tests_image_pipeline.cpp +++ b/testsuite/backend/genesys/tests_image_pipeline.cpp @@ -500,6 +500,37 @@ void test_node_merge_mono_lines_to_color() ASSERT_EQ(out_data, expected_data); } +void test_node_merge_color_to_gray() +{ + using Data = std::vector; + + Data in_data = { + 0x10, 0x20, 0x30, 0x11, 0x21, 0x31, + 0x12, 0x22, 0x32, 0x13, 0x23, 0x33, + 0x14, 0x24, 0x34, 0x15, 0x25, 0x35, + 0x16, 0x26, 0x36, 0x17, 0x27, 0x37, + }; + + ImagePipelineStack stack; + stack.push_first_node(8, 1, PixelFormat::RGB888, + std::move(in_data)); + stack.push_node(); + + ASSERT_EQ(stack.get_output_width(), 8u); + ASSERT_EQ(stack.get_output_height(), 1u); + ASSERT_EQ(stack.get_output_row_bytes(), 8u); + ASSERT_EQ(stack.get_output_format(), PixelFormat::I8); + + auto out_data = stack.get_all_data(); + + Data expected_data = { + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24 + }; + + ASSERT_EQ(out_data, expected_data); +} + + void test_node_split_mono_lines() { using Data = std::vector; @@ -938,6 +969,7 @@ void test_image_pipeline() test_node_invert_8_bits(); test_node_invert_1_bits(); test_node_merge_mono_lines_to_color(); + test_node_merge_color_to_gray(); test_node_split_mono_lines(); test_node_component_shift_lines(); test_node_pixel_shift_columns_no_switch(); From d72c561ce300bcbfcad431ade35fdc7b73bba106 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:03 +0200 Subject: [PATCH 10/25] genesys: Implement host-side gray support --- backend/genesys/enums.h | 3 +++ backend/genesys/low.cpp | 20 ++++++++++++++++++++ backend/genesys/settings.cpp | 4 +++- backend/genesys/settings.h | 4 ++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/backend/genesys/enums.h b/backend/genesys/enums.h index 9d7034bcf..f506988f4 100644 --- a/backend/genesys/enums.h +++ b/backend/genesys/enums.h @@ -526,6 +526,9 @@ enum class ModelFlag : unsigned // disable fast feeding mode on this scanner DISABLE_FAST_FEEDING = 1 << 14, + // scan gray scans as color and combine on host side + HOST_SIDE_GRAY = 1 << 15, + // the scanner uses multi-segment sensors that must be handled during calibration SIS_SENSOR = 1 << 16, diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp index 2626aecba..05b7a448c 100644 --- a/backend/genesys/low.cpp +++ b/backend/genesys/low.cpp @@ -445,6 +445,10 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession& pipeline.push_node(dev->model->line_mode_color_order); } + if (session.use_host_side_gray) { + pipeline.push_node(); + } + if (pipeline.get_output_format() == PixelFormat::BGR888) { pipeline.push_node(PixelFormat::RGB888); } @@ -954,6 +958,14 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se s.output_startx = static_cast( static_cast(s.params.startx) + sensor.output_pixel_offset); + if (has_flag(dev->model->flags, ModelFlag::HOST_SIDE_GRAY) && s.params.channels == 1 && + s.params.color_filter == ColorFilter::NONE) + { + s.use_host_side_gray = true; + s.params.channels = 3; + s.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; + } + s.stagger_x = sensor.stagger_x; s.stagger_y = sensor.stagger_y; @@ -1280,6 +1292,14 @@ ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSes } } + if (session.use_host_side_gray) { + pipeline.push_node(); + + if (log_image_data) { + pipeline.push_node(debug_prefix + "_10_after_nogray.tiff"); + } + } + if (pipeline.get_output_width() != session.params.get_requested_pixels()) { pipeline.push_node(session.params.get_requested_pixels()); } diff --git a/backend/genesys/settings.cpp b/backend/genesys/settings.cpp index 66b3929f9..8eb06c819 100644 --- a/backend/genesys/settings.cpp +++ b/backend/genesys/settings.cpp @@ -129,7 +129,8 @@ bool ScanSession::operator==(const ScanSession& other) const shading_pixel_offset == other.shading_pixel_offset && buffer_size_read == other.buffer_size_read && enable_ledadd == other.enable_ledadd && - use_host_side_calib == other.use_host_side_calib; + use_host_side_calib == other.use_host_side_calib && + use_host_side_gray == other.use_host_side_gray; } std::ostream& operator<<(std::ostream& out, const ScanSession& session) @@ -166,6 +167,7 @@ std::ostream& operator<<(std::ostream& out, const ScanSession& session) << " buffer_size_read: " << session.buffer_size_read << '\n' << " enable_ledadd: " << session.enable_ledadd << '\n' << " use_host_side_calib: " << session.use_host_side_calib << '\n' + << " use_host_side_gray: " << session.use_host_side_gray << '\n' << " params: " << format_indent_braced_list(4, session.params) << '\n' << "}"; return out; diff --git a/backend/genesys/settings.h b/backend/genesys/settings.h index d2b7f1fa8..f92854442 100644 --- a/backend/genesys/settings.h +++ b/backend/genesys/settings.h @@ -324,6 +324,9 @@ struct ScanSession { // whether calibration should be performed host-side bool use_host_side_calib = false; + // whether gray scanning should be performed host-side (scan as color and merge to gray) + bool use_host_side_gray = false; + void assert_computed() const { if (!computed) { @@ -375,6 +378,7 @@ void serialize(Stream& str, ScanSession& x) serialize(str, x.buffer_size_read); serialize(str, x.enable_ledadd); serialize(str, x.use_host_side_calib); + serialize(str, x.use_host_side_gray); } std::ostream& operator<<(std::ostream& out, const SANE_Parameters& params); From 0ce9a28009db1faf69e75094ddc36d9bc9b310f5 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:04 +0200 Subject: [PATCH 11/25] genesys: Use host-side gray instead of device-side true-gray on gl841 True gray mode is not handled correctly by devices: they have bugs that lead to incorrect LED color being emitted (e.g. dark red) and thus this feature is completely unusable. At least LiDE 35/40/50, LiDE 60 and LiDE 80 are affected. Simpy disabling true-gray unfortunately leads to even worse outcome because the scanner then simply proceeds to perform a color scan. To work around these problems we do a normal color scan and then produce gray output based on the color data. This will satisfy the use cases when correct gray is needed. In cases when it is sufficient to construct gray from a single color channel, the color filter setting could be used. --- backend/genesys/gl841.cpp | 43 ++++---------------------------- backend/genesys/tables_model.cpp | 3 +++ 2 files changed, 8 insertions(+), 38 deletions(-) diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index eb073fa23..bbe190b1c 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -818,7 +818,6 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens const ScanSession& session) { DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time); - std::uint16_t expavg, expr, expb, expg; dev->cmd_set->set_fe(dev, sensor, AFE_SET); @@ -875,11 +874,7 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens /* AFEMOD should depend on FESET, and we should set these * bits separately */ reg->find_reg(0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD); - if (has_flag(session.params.flags, ScanFlag::ENABLE_LEDADD)) { - reg->find_reg(0x04).value |= 0x10; /* no filter */ - } - else if (session.params.channels == 1) - { + if (session.params.channels == 1) { switch (session.params.color_filter) { case ColorFilter::RED: @@ -909,23 +904,6 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens /* CIS scanners can do true gray by setting LEDADD */ reg->find_reg(0x87).value &= ~REG_0x87_LEDADD; - if (has_flag(session.params.flags, ScanFlag::ENABLE_LEDADD)) { - reg->find_reg(0x87).value |= REG_0x87_LEDADD; - expr = reg->get16(REG_EXPR); - expg = reg->get16(REG_EXPG); - expb = reg->get16(REG_EXPB); - - /* use minimal exposure for best image quality */ - expavg = expg; - if (expr < expg) - expavg = expr; - if (expb < expavg) - expavg = expb; - - dev->reg.set16(REG_EXPR, expavg); - dev->reg.set16(REG_EXPG, expavg); - dev->reg.set16(REG_EXPB, expavg); - } // enable gamma tables if (should_enable_gamma(session, sensor)) { @@ -1051,6 +1029,9 @@ dummy \ scanned lines dev->total_bytes_read = 0; dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines; + if (session.use_host_side_gray) { + dev->total_bytes_to_read /= 3; + } DBG(DBG_info, "%s: total bytes to send = %zu\n", __func__, dev->total_bytes_to_read); } @@ -1088,20 +1069,6 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev, start += dev->settings.tl_x; start = static_cast((start * dev->settings.xres) / MM_PER_INCH); - // we enable true gray for cis scanners only, and just when doing - // scan since color calibration is OK for this mode - ScanFlag flags = ScanFlag::NONE; - - // true gray (led add for cis scanners) - if (dev->model->is_cis && - settings.color_filter == ColorFilter::NONE && - dev->settings.scan_mode != ScanColorMode::COLOR_SINGLE_PASS && - dev->model->sensor_id != SensorId::CIS_CANON_LIDE_80) - { - // on Lide 80 the LEDADD bit results in only red LED array being lit - flags |= ScanFlag::ENABLE_LEDADD; - } - ScanSession session; session.params.xres = dev->settings.xres; session.params.yres = dev->settings.yres; @@ -1117,7 +1084,7 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev, session.params.color_filter = dev->settings.color_filter; session.params.contrast_adjustment = dev->settings.contrast; session.params.brightness_adjustment = dev->settings.brightness; - session.params.flags = flags; + session.params.flags = ScanFlag::NONE; compute_session(dev, session, sensor); return session; diff --git a/backend/genesys/tables_model.cpp b/backend/genesys/tables_model.cpp index acd933a89..7d77c6152 100644 --- a/backend/genesys/tables_model.cpp +++ b/backend/genesys/tables_model.cpp @@ -191,6 +191,7 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::CANON_LIDE_35; model.motor_id = MotorId::CANON_LIDE_35; model.flags = ModelFlag::DARK_WHITE_CALIBRATION | + ModelFlag::HOST_SIDE_GRAY | ModelFlag::CUSTOM_GAMMA; model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | @@ -1110,6 +1111,7 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::CANON_LIDE_35; model.motor_id = MotorId::CANON_LIDE_60; model.flags = ModelFlag::DARK_WHITE_CALIBRATION | + ModelFlag::HOST_SIDE_GRAY | ModelFlag::CUSTOM_GAMMA; model.buttons = GENESYS_HAS_COPY_SW | @@ -1165,6 +1167,7 @@ void genesys_init_usb_device_tables() model.gpio_id = GpioId::CANON_LIDE_80; model.motor_id = MotorId::CANON_LIDE_80; model.flags = ModelFlag::DARK_WHITE_CALIBRATION | + ModelFlag::HOST_SIDE_GRAY | ModelFlag::CUSTOM_GAMMA; model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | From 170d0a761f459efa9b768e81ab7b1c13c9c5019a Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:05 +0200 Subject: [PATCH 12/25] genesys: Remove duplicate register writes in gl841 calibration --- backend/genesys/genesys.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 653fc0934..f2aa30437 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -2101,16 +2101,6 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor for (unsigned i_test = 0; i_test < 100 && !acceptable; ++i_test) { regs_set_exposure(dev.model->asic_type, regs, { exp[0], exp[1], exp[2] }); - if (dev.model->asic_type == AsicType::GL841) { - // FIXME: remove - dev.interface->write_register(0x10, (exp[0] >> 8) & 0xff); - dev.interface->write_register(0x11, exp[0] & 0xff); - dev.interface->write_register(0x12, (exp[1] >> 8) & 0xff); - dev.interface->write_register(0x13, exp[1] & 0xff); - dev.interface->write_register(0x14, (exp[2] >> 8) & 0xff); - dev.interface->write_register(0x15, exp[2] & 0xff); - } - dev.interface->write_registers(regs); dbg.log(DBG_info, "starting line reading"); From 4bc08228879ac5b4d6c7ce57c0ce36314663aec2 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:06 +0200 Subject: [PATCH 13/25] genesys: Use more robust gain calibration on gl841 --- backend/genesys/genesys.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index f2aa30437..4963c470f 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -1884,7 +1884,8 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& float curr_output = 0; float target_value = 0; - if (dev.model->asic_type == AsicType::GL842 || + if (dev.model->asic_type == AsicType::GL841 || + dev.model->asic_type == AsicType::GL842 || dev.model->asic_type == AsicType::GL843) { std::vector values; @@ -1900,18 +1901,6 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& curr_output = static_cast(values[unsigned((values.size() - 1) * 0.95)]); target_value = calib_sensor->gain_white_ref * coeff; - } else if (dev.model->asic_type == AsicType::GL841) { - // FIXME: use the GL843 approach - unsigned max = 0; - for (std::size_t x = 0; x < image.get_width(); x++) { - auto value = image.get_raw_channel(x, 0, ch); - if (value > max) { - max = value; - } - } - - curr_output = max; - target_value = 65535.0f; } else { // FIXME: use the GL843 approach auto width = image.get_width(); From f5e110c5bd9987ec7c533b1f13ea3eaf63628426 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:07 +0200 Subject: [PATCH 14/25] genesys: Clean up exposure calibration on gl841 --- backend/genesys/genesys.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 4963c470f..1a721eb7c 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -2006,14 +2006,9 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor regs = dev.reg; // FIXME: apply this to all ASICs } - unsigned yres = resolution; - if (dev.model->asic_type == AsicType::GL841) { - yres = dev.settings.yres; // FIXME: remove this - } - ScanSession session; session.params.xres = resolution; - session.params.yres = yres; + session.params.yres = resolution; session.params.startx = 0; session.params.starty = 0; session.params.pixels = dev.model->x_size_calib_mm * resolution / MM_PER_INCH; From b019b26c1d4f05aea59a3a9d4a97c9568f53b87d Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:08 +0200 Subject: [PATCH 15/25] genesys: Remove erroneous register write on LiDE 80 --- backend/genesys/gl841.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index bbe190b1c..bef608ffb 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -330,11 +330,6 @@ gl841_init_registers (Genesys_Device * dev) dev->interface->write_0x8c(0x10, 0x94); dev->interface->write_register(0x09, 0x10); - - // FIXME: the following code originally changed 0x6b, but due to bug the 0x6c register was - // effectively changed. The current behavior matches the old code, but should probably be fixed. - dev->reg.find_reg(0x6c).value |= REG_0x6B_GPO18; - dev->reg.find_reg(0x6c).value &= ~REG_0x6B_GPO17; } } From ce506768dbbce77b26415ff3167e8a4f0fcdfd93 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:09 +0200 Subject: [PATCH 16/25] genesys: Reset registers after move during led calibration on gl841 --- backend/genesys/genesys.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 1a721eb7c..b083abe1a 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -1998,7 +1998,8 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor const auto& calib_sensor = sanei_genesys_find_sensor(&dev, resolution, channels, dev.settings.scan_method); - if (dev.model->asic_type == AsicType::GL845 || + if (dev.model->asic_type == AsicType::GL841 || + dev.model->asic_type == AsicType::GL845 || dev.model->asic_type == AsicType::GL846 || dev.model->asic_type == AsicType::GL847 || dev.model->asic_type == AsicType::GL124) From 0c29146cb4cec2608a8847a64e81186c8aa299c6 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:10 +0200 Subject: [PATCH 17/25] genesys: Remove duplicate register write during led calibration on gl841 --- backend/genesys/genesys.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index b083abe1a..50b2675d7 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -2030,10 +2030,6 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor dev.cmd_set->init_regs_for_scan_session(&dev, calib_sensor, ®s, session); - if (dev.model->asic_type == AsicType::GL841) { - dev.interface->write_registers(regs); // FIXME: remove this - } - std::uint16_t exp[3]; if (dev.model->asic_type == AsicType::GL841) { From 5c3f0332accaf30baf022c55013961ccd92ef291 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:11 +0200 Subject: [PATCH 18/25] genesys: Specify target white level for all gl841 devices --- backend/genesys/tables_sensor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/genesys/tables_sensor.cpp b/backend/genesys/tables_sensor.cpp index d79a018ac..4f1753842 100644 --- a/backend/genesys/tables_sensor.cpp +++ b/backend/genesys/tables_sensor.cpp @@ -471,8 +471,8 @@ void genesys_init_sensor_tables() sensor.register_dpihw = 1200; sensor.black_pixels = 87; sensor.dummy_pixel = 87; - sensor.fau_gain_white_ref = 0; - sensor.gain_white_ref = 0; + sensor.fau_gain_white_ref = 100; + sensor.gain_white_ref = 100; sensor.exposure = { 0x0400, 0x0400, 0x0400 }; sensor.custom_regs = { { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x00 }, { 0x19, 0x50 }, @@ -519,8 +519,8 @@ void genesys_init_sensor_tables() sensor.register_dpihw = 1200; sensor.black_pixels = 87; sensor.dummy_pixel = 87; - sensor.fau_gain_white_ref = 0; - sensor.gain_white_ref = 0; + sensor.fau_gain_white_ref = 100; + sensor.gain_white_ref = 100; sensor.exposure = { 0x0400, 0x0400, 0x0400 }; sensor.custom_regs = { { 0x16, 0x00 }, { 0x17, 0x01 }, { 0x18, 0x00 }, { 0x19, 0x50 }, From 27232565123a5d8d8694a493245195323074635c Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:12 +0200 Subject: [PATCH 19/25] genesys: Remove no longer used led calibration fallback code on gl841 This was used only on scanners which did not have calibration target intensity value. All gl841 scanners now have such setting, so the code can be removed. --- backend/genesys/genesys.cpp | 54 ++++--------------------------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 50b2675d7..eefad9221 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -2044,9 +2044,6 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor std::uint16_t target = sensor.gain_white_ref * 256; - std::uint16_t min_exposure = 500; // only gl841 - std::uint16_t max_exposure = ((exp[0] + exp[1] + exp[2]) / 3) * 2; // only gl841 - std::uint16_t top[3] = {}; std::uint16_t bottom[3] = {}; @@ -2127,52 +2124,11 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor acceptable = true; if (dev.model->asic_type == AsicType::GL841) { - if (avg[0] < avg[1] * 0.95 || avg[1] < avg[0] * 0.95 || - avg[0] < avg[2] * 0.95 || avg[2] < avg[0] * 0.95 || - avg[1] < avg[2] * 0.95 || avg[2] < avg[1] * 0.95) - { - acceptable = false; - } - - // led exposure is not acceptable if white level is too low. - // ~80 hardcoded value for white level - if (avg[0] < 20000 || avg[1] < 20000 || avg[2] < 20000) { - acceptable = false; - } - - // for scanners using target value - if (target > 0) { - acceptable = true; - for (unsigned i = 0; i < 3; i++) { - // we accept +- 2% delta from target - if (std::abs(avg[i] - target) > target / 50) { - exp[i] = (exp[i] * target) / avg[i]; - acceptable = false; - } - } - } else { - if (!acceptable) { - unsigned avga = (avg[0] + avg[1] + avg[2]) / 3; - exp[0] = (exp[0] * avga) / avg[0]; - exp[1] = (exp[1] * avga) / avg[1]; - exp[2] = (exp[2] * avga) / avg[2]; - /* Keep the resulting exposures below this value. Too long exposure drives - the ccd into saturation. We may fix this by relying on the fact that - we get a striped scan without shading, by means of statistical calculation - */ - unsigned avge = (exp[0] + exp[1] + exp[2]) / 3; - - if (avge > max_exposure) { - exp[0] = (exp[0] * max_exposure) / avge; - exp[1] = (exp[1] * max_exposure) / avge; - exp[2] = (exp[2] * max_exposure) / avge; - } - if (avge < min_exposure) { - exp[0] = (exp[0] * min_exposure) / avge; - exp[1] = (exp[1] * min_exposure) / avge; - exp[2] = (exp[2] * min_exposure) / avge; - } - + for (unsigned i = 0; i < 3; i++) { + // we accept +- 2% delta from target + if (std::abs(avg[i] - target) > target / 50) { + exp[i] = (exp[i] * target) / avg[i]; + acceptable = false; } } } else if (dev.model->asic_type == AsicType::GL845 || From d585e7a586097c247bd421c38ad55fd75c685acc Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:13 +0200 Subject: [PATCH 20/25] genesys: Reuse gl124 led calibration acceptability criteria for gl841 --- backend/genesys/genesys.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index eefad9221..f0e58f552 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -2123,16 +2123,8 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor acceptable = true; - if (dev.model->asic_type == AsicType::GL841) { - for (unsigned i = 0; i < 3; i++) { - // we accept +- 2% delta from target - if (std::abs(avg[i] - target) > target / 50) { - exp[i] = (exp[i] * target) / avg[i]; - acceptable = false; - } - } - } else if (dev.model->asic_type == AsicType::GL845 || - dev.model->asic_type == AsicType::GL846) + if (dev.model->asic_type == AsicType::GL845 || + dev.model->asic_type == AsicType::GL846) { for (unsigned i = 0; i < 3; i++) { if (avg[i] < bottom[i]) { @@ -2165,7 +2157,9 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor acceptable = false; } } - } else if (dev.model->asic_type == AsicType::GL124) { + } else if (dev.model->asic_type == AsicType::GL841 || + dev.model->asic_type == AsicType::GL124) + { for (unsigned i = 0; i < 3; i++) { // we accept +- 2% delta from target if (std::abs(avg[i] - target) > target / 50) { From 6921377fdaa7e12c7851b45c16d681504634cdd9 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:14 +0200 Subject: [PATCH 21/25] genesys: Ensure sensor exposure is up-to-date when scanning on gl841 --- backend/genesys/genesys.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index f0e58f552..bc53ffbd1 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -673,9 +673,9 @@ void scanner_setup_sensor(Genesys_Device& dev, const Genesys_Sensor& sensor, regs.set8(custom_reg.address, custom_reg.value); } - if (dev.model->asic_type != AsicType::GL841 && - dev.model->asic_type != AsicType::GL843) + if (dev.model->asic_type != AsicType::GL843) { + // FIXME: remove the above check regs_set_exposure(dev.model->asic_type, regs, sensor.exposure); } From aee8669bc0e2c8183a91462814948596618813c5 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:15 +0200 Subject: [PATCH 22/25] genesys: Fix inconsistent exposure values in led calib in testing mode --- backend/genesys/genesys.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index bc53ffbd1..3cc07ec92 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -2089,15 +2089,13 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor if (dev.model->asic_type == AsicType::GL841) { scanner_stop_action(dev); dev.cmd_set->move_back_home(&dev, true); - return { exp[0], exp[1], exp[2] }; } else if (dev.model->asic_type == AsicType::GL124) { scanner_stop_action(dev); - return calib_sensor.exposure; } else { scanner_stop_action(dev); dev.cmd_set->move_back_home(&dev, true); - return calib_sensor.exposure; } + return { exp[0], exp[1], exp[2] }; } auto image = read_unshuffled_image_from_scanner(&dev, session, session.output_line_bytes); From 12318c5c55ef7af301c2c73b37fc3dba83f13ada Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:16 +0200 Subject: [PATCH 23/25] genesys: Use consistent initial exposure for led calibration on gl841 --- backend/genesys/genesys.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp index 3cc07ec92..92a6db708 100644 --- a/backend/genesys/genesys.cpp +++ b/backend/genesys/genesys.cpp @@ -2032,15 +2032,9 @@ SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor std::uint16_t exp[3]; - if (dev.model->asic_type == AsicType::GL841) { - exp[0] = sensor.exposure.red; - exp[1] = sensor.exposure.green; - exp[2] = sensor.exposure.blue; - } else { - exp[0] = calib_sensor.exposure.red; - exp[1] = calib_sensor.exposure.green; - exp[2] = calib_sensor.exposure.blue; - } + exp[0] = calib_sensor.exposure.red; + exp[1] = calib_sensor.exposure.green; + exp[2] = calib_sensor.exposure.blue; std::uint16_t target = sensor.gain_white_ref * 256; From 9d9dc76400e494500950b06475b70fec886d8157 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:17 +0200 Subject: [PATCH 24/25] genesys: Fixed offset calibration on certain gl841 devices --- backend/genesys/gl841.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index bef608ffb..d61c0fcfc 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -1711,14 +1711,10 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor& turn++; } while ((top-bottom)>1 && turn < 100); - // FIXME: don't overwrite the calibrated values - dev->frontend.set_offset(0, 0); - dev->frontend.set_offset(1, 0); - dev->frontend.set_offset(2, 0); - DBG(DBG_info, "%s: offset=(%d,%d,%d)\n", __func__, - dev->frontend.get_offset(0), - dev->frontend.get_offset(1), - dev->frontend.get_offset(2)); + DBG(DBG_info, "%s: offset=(%d,%d,%d)\n", __func__, + dev->frontend.get_offset(0), + dev->frontend.get_offset(1), + dev->frontend.get_offset(2)); } /* this function does the offset calibration by scanning one line of the calibration From f6dbd34e23374af86110f9dee600f92aa3d5ffb6 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Mon, 27 Dec 2021 22:21:18 +0200 Subject: [PATCH 25/25] genesys: Remove unneeded per-scanner register setup These register values are overwritten later. --- backend/genesys/gl841.cpp | 48 ++++++++++----------------------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index d61c0fcfc..eb7cbc0e7 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -149,15 +149,6 @@ gl841_init_registers (Genesys_Device * dev) dev->reg.init_reg(0x13, 0x00); // SENSOR_DEF dev->reg.init_reg(0x14, 0x00); // SENSOR_DEF dev->reg.init_reg(0x15, 0x00); // SENSOR_DEF - if (dev->model->model_id == ModelId::CANON_LIDE_80) { - dev->reg.init_reg(0x10, 0x40); - dev->reg.init_reg(0x11, 0x00); - dev->reg.init_reg(0x12, 0x40); - dev->reg.init_reg(0x13, 0x00); - dev->reg.init_reg(0x14, 0x40); - dev->reg.init_reg(0x15, 0x00); - } - dev->reg.init_reg(0x16, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below dev->reg.init_reg(0x17, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below dev->reg.init_reg(0x18, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below @@ -184,36 +175,21 @@ gl841_init_registers (Genesys_Device * dev) dev->reg.init_reg(0x27, 0x00); dev->reg.init_reg(0x29, 0xff); - dev->reg.init_reg(0x2c, 0x00); - dev->reg.init_reg(0x2d, 0x00); - if (dev->model->model_id == ModelId::CANON_LIDE_80) { - dev->reg.init_reg(0x2c, sensor.full_resolution >> 8); - dev->reg.init_reg(0x2d, sensor.full_resolution & 0xff); - } + dev->reg.init_reg(0x2c, 0x02); // DPISET: overwritten during scanner setup + dev->reg.init_reg(0x2d, 0x58); // DPISET: overwritten during scanner setup dev->reg.init_reg(0x2e, 0x80); dev->reg.init_reg(0x2f, 0x80); - dev->reg.init_reg(0x30, 0x00); - dev->reg.init_reg(0x31, 0x00); - dev->reg.init_reg(0x32, 0x00); - dev->reg.init_reg(0x33, 0x00); - dev->reg.init_reg(0x34, 0x00); - dev->reg.init_reg(0x35, 0x00); - dev->reg.init_reg(0x36, 0x00); - dev->reg.init_reg(0x37, 0x00); - dev->reg.init_reg(0x38, 0x4f); - dev->reg.init_reg(0x39, 0xc1); - if (dev->model->model_id == ModelId::CANON_LIDE_80) { - dev->reg.init_reg(0x31, 0x10); - dev->reg.init_reg(0x32, 0x15); - dev->reg.init_reg(0x33, 0x0e); - dev->reg.init_reg(0x34, 0x40); - dev->reg.init_reg(0x35, 0x00); - dev->reg.init_reg(0x36, 0x2a); - dev->reg.init_reg(0x37, 0x30); - dev->reg.init_reg(0x38, 0x2a); - dev->reg.init_reg(0x39, 0xf8); - } + dev->reg.init_reg(0x30, 0x00); // STRPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x31, 0x00); // STRPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x32, 0x00); // ENDPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x33, 0x00); // ENDPIXEL: overwritten during scanner setup + dev->reg.init_reg(0x34, 0x00); // DUMMY: overwritten during scanner setup + dev->reg.init_reg(0x35, 0x00); // MAXWD: overwritten during scanner setup + dev->reg.init_reg(0x36, 0x00); // MAXWD: overwritten during scanner setup + dev->reg.init_reg(0x37, 0x00); // MAXWD: overwritten during scanner setup + dev->reg.init_reg(0x38, 0x4f); // LPERIOD: overwritten during scanner setup + dev->reg.init_reg(0x39, 0xc1); // LPERIOD: overwritten during scanner setup dev->reg.init_reg(0x3d, 0x00); dev->reg.init_reg(0x3e, 0x00);