From 233cb4bd5a5050c2867447d9c9c3e0f17c7c6eb4 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sat, 14 Mar 2020 23:19:27 +0200 Subject: [PATCH] genesys: Use single code path for gain code calculation --- backend/genesys/gl124.cpp | 17 +++++------ backend/genesys/gl841.cpp | 47 +++++++++-------------------- backend/genesys/gl846.cpp | 20 ++++++------ backend/genesys/gl847.cpp | 20 ++++++------ backend/genesys/low.cpp | 47 +++++++++++++++++++++++++---- backend/genesys/sensor.cpp | 5 +++ backend/genesys/sensor.h | 9 ++++-- backend/genesys/tables_frontend.cpp | 10 ++++++ 8 files changed, 102 insertions(+), 73 deletions(-) diff --git a/backend/genesys/gl124.cpp b/backend/genesys/gl124.cpp index acb18ec1c..13ae7bc78 100644 --- a/backend/genesys/gl124.cpp +++ b/backend/genesys/gl124.cpp @@ -1559,18 +1559,15 @@ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys total += image.get_raw_channel(x, 0, ch); } - total /= width / 2; + float target_value = sensor.gain_white_ref * coeff; + float curr_output = total / (width / 2); - gain[ch] = (static_cast(sensor.gain_white_ref) * coeff) / total; + std::uint8_t out_gain = compute_frontend_gain(curr_output, target_value, + dev->frontend.layout.type); + dev->frontend.set_gain(ch, out_gain); - /* turn logical gain value into gain code, checking for overflow */ - code = static_cast(283 - 208 / gain[ch]); - code = clamp(code, 0, 255); - dev->frontend.set_gain(ch, code); - - DBG(DBG_proc, "%s: channel %d, total=%d, gain = %f, setting:%d\n", __func__, ch, - static_cast(total), - gain[ch], dev->frontend.get_gain(ch)); + DBG(DBG_proc, "%s: channel %d, curr=%f, target=%f, out_gain:%d\n", __func__, ch, + curr_output, target_value, out_gain); } if (dev->model->is_cis) { diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp index 1e4ac36ae..b2eac699f 100644 --- a/backend/genesys/gl841.cpp +++ b/backend/genesys/gl841.cpp @@ -2950,7 +2950,6 @@ void CommandSetGl841::coarse_gain_calibration(Genesys_Device* dev, const Genesys Genesys_Register_Set& regs, int dpi) const { DBG_HELPER_ARGS(dbg, "dpi=%d", dpi); - float gain[3]; int lines=1; // feed to white strip if needed @@ -3022,45 +3021,27 @@ void CommandSetGl841::coarse_gain_calibration(Genesys_Device* dev, const Genesys } } - gain[ch] = 65535.0f / max; + float curr_output = max; + float target_value = 65535.0f; - uint8_t out_gain = 0; + std::uint8_t out_gain = compute_frontend_gain(curr_output, target_value, + dev->frontend.layout.type); - if (dev->model->adc_id == AdcId::CANON_LIDE_35 || - dev->model->adc_id == AdcId::WOLFSON_XP300 || - dev->model->adc_id == AdcId::WOLFSON_DSM600) - { - gain[ch] *= 0.69f; // seems we don't get the real maximum. empirically derived - if (283 - 208 / gain[ch] > 255) { - out_gain = 255; - } else if (283 - 208 / gain[ch] < 0) { - out_gain = 0; - } else { - out_gain = static_cast(283 - 208 / gain[ch]); - } - } else if (dev->model->adc_id == AdcId::CANON_LIDE_80) { - out_gain = static_cast(gain[ch] * 12); - } dev->frontend.set_gain(ch, out_gain); - DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, ch, max, - gain[ch], out_gain); - } + DBG(DBG_proc, "%s: channel %d, curr=%f, target=%f, out_gain:%d\n", __func__, ch, + curr_output, target_value, out_gain); - for (unsigned j = 0; j < channels; j++) { - if (gain[j] > 30) { - DBG (DBG_error0, "**********************************************\n"); - DBG (DBG_error0, "**********************************************\n"); - DBG (DBG_error0, "**** ****\n"); - DBG (DBG_error0, "**** Extremely low Brightness detected. ****\n"); - DBG (DBG_error0, "**** Check the scanning head is ****\n"); - DBG (DBG_error0, "**** unlocked and moving. ****\n"); - DBG (DBG_error0, "**** ****\n"); - DBG (DBG_error0, "**********************************************\n"); - DBG (DBG_error0, "**********************************************\n"); + if (target_value / curr_output > 30) { + DBG(DBG_error0, "****************************************\n"); + DBG(DBG_error0, "* *\n"); + DBG(DBG_error0, "* Extremely low Brightness detected. *\n"); + DBG(DBG_error0, "* Check the scanning head is *\n"); + DBG(DBG_error0, "* unlocked and moving. *\n"); + DBG(DBG_error0, "* *\n"); + DBG(DBG_error0, "****************************************\n"); throw SaneException(SANE_STATUS_JAMMED, "scanning head is locked"); } - } if (dev->model->is_cis) { diff --git a/backend/genesys/gl846.cpp b/backend/genesys/gl846.cpp index 7295ef8f9..8f80f1949 100644 --- a/backend/genesys/gl846.cpp +++ b/backend/genesys/gl846.cpp @@ -1332,8 +1332,8 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys Genesys_Register_Set& regs, int dpi) const { DBG_HELPER(dbg); - float gain[3],coeff; - int code, lines; + float coeff; + int lines; DBG(DBG_proc, "%s: dpi = %d\n", __func__, dpi); @@ -1413,17 +1413,15 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys total += image.get_raw_channel(x, 0, ch); } - total /= width / 2; + float target_value = sensor.gain_white_ref * coeff; + float curr_output = total / (width / 2); - gain[ch] = (static_cast(sensor.gain_white_ref) * coeff) / total; + std::uint8_t out_gain = compute_frontend_gain(curr_output, target_value, + dev->frontend.layout.type); + dev->frontend.set_gain(ch, out_gain); - /* turn logical gain value into gain code, checking for overflow */ - code = static_cast(283 - 208 / gain[ch]); - code = clamp(code, 0, 255); - dev->frontend.set_gain(ch, code); - - DBG(DBG_proc, "%s: channel %d, total=%d, gain = %f, setting:%d\n", __func__, ch, - static_cast(total), gain[ch], dev->frontend.get_gain(ch)); + DBG(DBG_proc, "%s: channel %d, curr=%f, target=%f, out_gain:%d\n", __func__, ch, + curr_output, target_value, out_gain); } if (dev->model->is_cis) { diff --git a/backend/genesys/gl847.cpp b/backend/genesys/gl847.cpp index b219ea423..303777e48 100644 --- a/backend/genesys/gl847.cpp +++ b/backend/genesys/gl847.cpp @@ -1373,8 +1373,8 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys Genesys_Register_Set& regs, int dpi) const { DBG_HELPER_ARGS(dbg, "dpi = %d", dpi); - float gain[3],coeff; - int code, lines; + float coeff; + int lines; // no gain nor offset for AKM AFE uint8_t reg04 = dev->interface->read_register(REG_0x04); @@ -1452,17 +1452,15 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys total += image.get_raw_channel(x, 0, ch); } - total /= width / 2; + float target_value = sensor.gain_white_ref * coeff; + float curr_output = total / (width / 2); - gain[ch] = (static_cast(sensor.gain_white_ref) * coeff) / total; + std::uint8_t out_gain = compute_frontend_gain(curr_output, target_value, + dev->frontend.layout.type); + dev->frontend.set_gain(ch, out_gain); - /* turn logical gain value into gain code, checking for overflow */ - code = static_cast(283 - 208 / gain[ch]); - code = clamp(code, 0, 255); - dev->frontend.set_gain(ch, code); - - DBG(DBG_proc, "%s: channel %d, total=%d, gain = %f, setting:%d\n", __func__, ch, - static_cast(total), gain[ch], dev->frontend.get_gain(ch)); + DBG(DBG_proc, "%s: channel %d, curr=%f, target=%f, out_gain:%d\n", __func__, ch, + curr_output, target_value, out_gain); } if (dev->model->is_cis) { diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp index b94d52883..b145de516 100644 --- a/backend/genesys/low.cpp +++ b/backend/genesys/low.cpp @@ -1335,6 +1335,32 @@ std::uint8_t compute_frontend_gain_wolfson(float value, float target_value) return clamp(code, 0, 255); } +std::uint8_t compute_frontend_gain_lide_80(float value, float target_value) +{ + int code = static_cast((target_value / value) * 12); + return clamp(code, 0, 255); +} + +std::uint8_t compute_frontend_gain_wolfson_gl841(float value, float target_value) +{ + // this code path is similar to what generic wolfson code path uses and uses similar constants, + // but is likely incorrect. + float inv_gain = target_value / value; + inv_gain *= 0.69f; + int code = static_cast(283 - 208 / inv_gain); + return clamp(code, 0, 255); +} + +std::uint8_t compute_frontend_gain_wolfson_gl846_gl847_gl124(float value, float target_value) +{ + // this code path is similar to what generic wolfson code path uses and uses similar constants, + // but is likely incorrect. + float inv_gain = target_value / value; + int code = static_cast(283 - 208 / inv_gain); + return clamp(code, 0, 255); +} + + std::uint8_t compute_frontend_gain_analog_devices(float value, float target_value) { /* The flow of data through the frontend ADC is as follows (see e.g. AD9826 datasheet) @@ -1359,13 +1385,22 @@ std::uint8_t compute_frontend_gain_analog_devices(float value, float target_valu std::uint8_t compute_frontend_gain(float value, float target_value, FrontendType frontend_type) { - if (frontend_type == FrontendType::WOLFSON) { - return compute_frontend_gain_wolfson(value, target_value); + switch (frontend_type) { + case FrontendType::WOLFSON: + return compute_frontend_gain_wolfson(value, target_value); + case FrontendType::ANALOG_DEVICES: + return compute_frontend_gain_analog_devices(value, target_value); + case FrontendType::CANON_LIDE_80: + return compute_frontend_gain_lide_80(value, target_value); + case FrontendType::WOLFSON_GL841: + return compute_frontend_gain_wolfson_gl841(value, target_value); + case FrontendType::WOLFSON_GL846: + case FrontendType::WOLFSON_GL847: + case FrontendType::WOLFSON_GL124: + return compute_frontend_gain_wolfson_gl846_gl847_gl124(value, target_value); + default: + throw SaneException("Unknown frontend to compute gain for"); } - if (frontend_type == FrontendType::ANALOG_DEVICES) { - return compute_frontend_gain_analog_devices(value, target_value); - } - throw SaneException("Unknown frontend to compute gain for"); } /** @brief initialize device diff --git a/backend/genesys/sensor.cpp b/backend/genesys/sensor.cpp index f471a7282..20823a134 100644 --- a/backend/genesys/sensor.cpp +++ b/backend/genesys/sensor.cpp @@ -64,6 +64,11 @@ std::ostream& operator<<(std::ostream& out, const FrontendType& type) case FrontendType::UNKNOWN: out << "UNKNOWN"; break; case FrontendType::WOLFSON: out << "WOLFSON"; break; case FrontendType::ANALOG_DEVICES: out << "ANALOG_DEVICES"; break; + case FrontendType::CANON_LIDE_80: out << "CANON_LIDE_80"; break; + case FrontendType::WOLFSON_GL841: out << "WOLFSON_GL841"; break; + case FrontendType::WOLFSON_GL846: out << "WOLFSON_GL846"; break; + case FrontendType::WOLFSON_GL847: out << "WOLFSON_GL847"; break; + case FrontendType::WOLFSON_GL124: out << "WOLFSON_GL124"; break; default: out << "(unknown value)"; } return out; diff --git a/backend/genesys/sensor.h b/backend/genesys/sensor.h index 46110ebfc..91ee23d12 100644 --- a/backend/genesys/sensor.h +++ b/backend/genesys/sensor.h @@ -114,9 +114,14 @@ std::ostream& operator<<(std::ostream& out, const StaggerConfig& config); enum class FrontendType : unsigned { - UNKNOWN, + UNKNOWN = 0, WOLFSON, - ANALOG_DEVICES + ANALOG_DEVICES, + CANON_LIDE_80, + WOLFSON_GL841, // old code path, likely wrong calculation + WOLFSON_GL846, // old code path, likely wrong calculation + WOLFSON_GL847, // old code path, likely wrong calculation + WOLFSON_GL124, // old code path, likely wrong calculation }; inline void serialize(std::istream& str, FrontendType& x) diff --git a/backend/genesys/tables_frontend.cpp b/backend/genesys/tables_frontend.cpp index 1edf32fd1..7754181c5 100644 --- a/backend/genesys/tables_frontend.cpp +++ b/backend/genesys/tables_frontend.cpp @@ -198,6 +198,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::CANON_LIDE_35; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL841; fe.regs = { { 0x00, 0x00 }, { 0x01, 0x3d }, @@ -242,6 +243,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::WOLFSON_XP300; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL841; fe.regs = { { 0x00, 0x00 }, { 0x01, 0x35 }, @@ -286,6 +288,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::WOLFSON_DSM600; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL841; fe.regs = { { 0x00, 0x00 }, { 0x01, 0x35 }, @@ -308,6 +311,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::CANON_LIDE_200; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL847; fe.regs = { { 0x00, 0x9d }, { 0x01, 0x91 }, @@ -330,6 +334,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::CANON_LIDE_700F; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL847; fe.regs = { { 0x00, 0x9d }, { 0x01, 0x9e }, @@ -396,6 +401,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::CANON_LIDE_110; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL124; fe.regs = { { 0x00, 0x80 }, { 0x01, 0x8a }, @@ -422,6 +428,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::CANON_LIDE_120; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL124; fe.regs = { { 0x00, 0x80 }, { 0x01, 0xa3 }, @@ -583,6 +590,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::IMG101; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL846; fe.regs = { { 0x00, 0x78 }, { 0x01, 0xf0 }, @@ -605,6 +613,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::PLUSTEK_OPTICBOOK_3800; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::WOLFSON_GL846; fe.regs = { { 0x00, 0x78 }, { 0x01, 0xf0 }, @@ -631,6 +640,7 @@ void genesys_init_frontend_tables() fe = Genesys_Frontend(); fe.id = AdcId::CANON_LIDE_80; fe.layout = wolfson_layout; + fe.layout.type = FrontendType::CANON_LIDE_80; fe.regs = { { 0x00, 0x70 }, { 0x01, 0x16 },