diff --git a/backend/genesys_gl843.cc b/backend/genesys_gl843.cc index f1855ad65..09c25457a 100644 --- a/backend/genesys_gl843.cc +++ b/backend/genesys_gl843.cc @@ -3064,40 +3064,17 @@ static void gl843_coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sen // pick target value at 95th percentile of all values. There may be a lot of black values // in transparency scans for example std::sort(values.begin(), values.end()); - uint16_t target_value = values[unsigned((values.size() - 1) * 0.95)]; + uint16_t curr_output = values[unsigned((values.size() - 1) * 0.95)]; if (bpp == 16) { - target_value /= 256; + curr_output /= 256; } + float target_value = calib_sensor.gain_white_ref * coeff; - /* the flow of data through the frontend ADC is as follows (see e.g. VM8192 datasheet) - input - -> apply offset (o = i + 260mV * (DAC[7:0]-127.5)/127.5) -> - -> apply gain (o = i * 208/(283-PGA[7:0]) - -> ADC - - Here we have some input data that was acquired with zero gain (PGA==0). - We want to compute gain such that the output would approach full ADC range (controlled by - gain_white_ref). - - We want to solve the following for {PGA}: - - {input} * 208 / (283 - 0) = {output} - {input} * 208 / (283 - {PGA}) = {target output} - - The solution is the following equation: - - {PGA} = 283 * (1 - {output} / {target output}) - */ - float gain = ((float) target_value / (calib_sensor.gain_white_ref*coeff)); - int code = 283 * (1 - gain); - if (code > 255) - code = 255; - else if (code < 0) - code = 0; + int code = compute_frontend_gain(curr_output, target_value, dev->frontend.layout.type); dev->frontend.set_gain(j, code); - DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, target_value, - gain, code); + DBG(DBG_proc, "%s: channel %d, max=%d, target=%d, setting:%d\n", __func__, j, curr_output, + (int) target_value, code); } if (dev->model->is_cis) { diff --git a/backend/genesys_low.cc b/backend/genesys_low.cc index c7369ea2c..0585e2e0b 100644 --- a/backend/genesys_low.cc +++ b/backend/genesys_low.cc @@ -1379,6 +1379,41 @@ void compute_session(Genesys_Device* dev, ScanSession& s, const Genesys_Sensor& compute_session_buffer_sizes(dev->model->asic_type, s); } +std::uint8_t compute_frontend_gain_wolfson(float value, float target_value) +{ + /* the flow of data through the frontend ADC is as follows (see e.g. WM8192 datasheet) + input + -> apply offset (o = i + 260mV * (DAC[7:0]-127.5)/127.5) -> + -> apply gain (o = i * 208/(283-PGA[7:0]) + -> ADC + + Here we have some input data that was acquired with zero gain (PGA==0). + We want to compute gain such that the output would approach full ADC range (controlled by + target_value). + + We want to solve the following for {PGA}: + + {value} = {input} * 208 / (283 - 0) + {target_value} = {input} * 208 / (283 - {PGA}) + + The solution is the following equation: + + {PGA} = 283 * (1 - {value} / {target_value}) + */ + float gain = value / target_value; + int code = 283 * (1 - gain); + return clamp(code, 0, 255); +} + +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); + } + throw SaneException("Unknown frontend to compute gain for"); +} + const SensorProfile& get_sensor_profile(AsicType asic_type, const Genesys_Sensor& sensor, unsigned dpi, unsigned ccd_size_divisor) { diff --git a/backend/genesys_low.h b/backend/genesys_low.h index fdac57dcb..bfedc6ddb 100644 --- a/backend/genesys_low.h +++ b/backend/genesys_low.h @@ -640,6 +640,9 @@ void compute_session(Genesys_Device* dev, ScanSession& s, const Genesys_Sensor& void genesys_fill_segmented_buffer(Genesys_Device* dev, uint8_t* work_buffer_dst, size_t size); +std::uint8_t compute_frontend_gain(float value, float target_value, + FrontendType frontend_type); + const SensorProfile& get_sensor_profile(AsicType asic_type, const Genesys_Sensor& sensor, unsigned dpi, unsigned ccd_size_divisor);