kopia lustrzana https://gitlab.com/sane-project/backends
genesys: Use single code path for gain code calculation
rodzic
e0bec6723d
commit
233cb4bd5a
|
@ -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<float>(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<int>(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<unsigned>(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) {
|
||||
|
|
|
@ -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<std::uint8_t>(283 - 208 / gain[ch]);
|
||||
}
|
||||
} else if (dev->model->adc_id == AdcId::CANON_LIDE_80) {
|
||||
out_gain = static_cast<std::uint8_t>(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) {
|
||||
|
|
|
@ -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<float>(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<int>(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<unsigned>(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) {
|
||||
|
|
|
@ -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<float>(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<int>(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<unsigned>(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) {
|
||||
|
|
|
@ -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<int>((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<int>(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<int>(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,14 +1385,23 @@ 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) {
|
||||
switch (frontend_type) {
|
||||
case FrontendType::WOLFSON:
|
||||
return compute_frontend_gain_wolfson(value, target_value);
|
||||
}
|
||||
if (frontend_type == FrontendType::ANALOG_DEVICES) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief initialize device
|
||||
* Initialize backend and ASIC : registers, motor tables, and gamma tables
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 },
|
||||
|
|
Ładowanie…
Reference in New Issue