diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-08-24 18:45:55 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-08-24 18:45:55 +0200 |
commit | a77bc1fcbdf83cfdac9570c0a0ac886b5534c90f (patch) | |
tree | d839746371ecb8ed64ac81d2e37c11fcd25a00ac /backend/genesys/gl124.cpp | |
parent | 787fb1d54ec9ee5fb941ae897fb201feb9cb2fd1 (diff) | |
parent | 2b3e02411ecc09e7d41741b5587655c9b2f955b7 (diff) |
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'backend/genesys/gl124.cpp')
-rw-r--r-- | backend/genesys/gl124.cpp | 1214 |
1 files changed, 168 insertions, 1046 deletions
diff --git a/backend/genesys/gl124.cpp b/backend/genesys/gl124.cpp index 054f1ef..d3fc1bc 100644 --- a/backend/genesys/gl124.cpp +++ b/backend/genesys/gl124.cpp @@ -53,6 +53,37 @@ namespace genesys { namespace gl124 { +struct Gpio_layout +{ + std::uint8_t r31; + std::uint8_t r32; + std::uint8_t r33; + std::uint8_t r34; + std::uint8_t r35; + std::uint8_t r36; + std::uint8_t r38; +}; + +/** @brief gpio layout + * describes initial gpio settings for a given model + * registers 0x31 to 0x38 + */ +static Gpio_layout gpios[] = { + /* LiDE 110 */ + { /* 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38 */ + 0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00 + }, + /* LiDE 210 */ + { + 0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00 + }, + /* LiDE 120 */ + { + 0x9f, 0x53, 0x01, 0x80, 0x5f, 0x01, 0x00 + }, +}; + + /** @brief set all registers to default values . * This function is called only once at the beginning and * fills register startup values for registers reused across scans. @@ -336,54 +367,9 @@ gl124_init_registers (Genesys_Device * dev) // fine tune upon device description const auto& sensor = sanei_genesys_find_sensor_any(dev); - sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res); - - dev->calib_reg = dev->reg; -} - -/**@brief send slope table for motor movement - * Send slope_table in machine byte order - * @param dev device to send slope table - * @param table_nr index of the slope table in ASIC memory - * Must be in the [0-4] range. - * @param slope_table pointer to 16 bit values array of the slope table - * @param steps number of elemnts in the slope table - */ -static void gl124_send_slope_table(Genesys_Device* dev, int table_nr, - const std::vector<uint16_t>& slope_table, - int steps) -{ - DBG_HELPER_ARGS(dbg, "table_nr = %d, steps = %d", table_nr, steps); - int i; - char msg[10000]; - - /* sanity check */ - if(table_nr<0 || table_nr>4) - { - throw SaneException("invalid table number"); - } - - std::vector<uint8_t> table(steps * 2); - for (i = 0; i < steps; i++) - { - table[i * 2] = slope_table[i] & 0xff; - table[i * 2 + 1] = slope_table[i] >> 8; - } - - if (DBG_LEVEL >= DBG_io) - { - std::sprintf(msg, "write slope %d (%d)=", table_nr, steps); - for (i = 0; i < steps; i++) { - std::sprintf(msg + std::strlen(msg), ",%d", slope_table[i]); - } - DBG (DBG_io, "%s: %s\n", __func__, msg); - } - - if (dev->interface->is_mock()) { - dev->interface->record_slope_table(table_nr, slope_table); - } - // slope table addresses are fixed - dev->interface->write_ahb(0x10000000 + 0x4000 * table_nr, steps * 2, table.data()); + const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution, + 3, ScanMethod::FLATBED); + sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw); } /** @brief * Set register values of 'special' ti type frontend @@ -397,12 +383,8 @@ static void gl124_set_ti_fe(Genesys_Device* dev, uint8_t set) DBG_HELPER(dbg); int i; - if (set == AFE_INIT) - { - DBG(DBG_proc, "%s: setting DAC %u\n", __func__, - static_cast<unsigned>(dev->model->adc_id)); - - dev->frontend = dev->frontend_initial; + if (set == AFE_INIT) { + dev->frontend = dev->frontend_initial; } // start writing to DAC @@ -441,11 +423,8 @@ void CommandSetGl124::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, (void) sensor; uint8_t val; - if (set == AFE_INIT) - { - DBG(DBG_proc, "%s(): setting DAC %u\n", __func__, - static_cast<unsigned>(dev->model->adc_id)); - dev->frontend = dev->frontend_initial; + if (set == AFE_INIT) { + dev->frontend = dev->frontend_initial; } val = dev->interface->read_register(REG_0x0A); @@ -466,14 +445,14 @@ void CommandSetGl124::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, static void gl124_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor, Genesys_Register_Set* reg, - const Motor_Profile& motor_profile, + const MotorProfile& motor_profile, unsigned int scan_exposure_time, unsigned scan_yres, unsigned int scan_lines, unsigned int scan_dummy, unsigned int feed_steps, ScanColorMode scan_mode, - MotorFlag flags) + ScanFlag flags) { DBG_HELPER(dbg); int use_fast_fed; @@ -533,11 +512,8 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, linesel=0; } - DBG(DBG_io2, "%s: final yres=%d, linesel=%d\n", __func__, yres, linesel); - lincnt=scan_lines*(linesel+1); reg->set24(REG_LINCNT, lincnt); - DBG (DBG_io, "%s: lincnt=%d\n", __func__, lincnt); /* compute register 02 value */ uint8_t r02 = REG_0x02_NOTHOME; @@ -548,15 +524,15 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, r02 &= ~REG_0x02_FASTFED; } - if (has_flag(flags, MotorFlag::AUTO_GO_HOME)) { + if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) { r02 |= REG_0x02_AGOHOME; } - if (has_flag(flags, MotorFlag::DISABLE_BUFFER_FULL_MOVE) || (yres >= sensor.optical_res)) + if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) || (yres >= sensor.full_resolution)) { r02 |= REG_0x02_ACDCDIS; } - if (has_flag(flags, MotorFlag::REVERSE)) { + if (has_flag(flags, ScanFlag::REVERSE)) { r02 |= REG_0x02_MTRREV; } @@ -566,13 +542,12 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, reg->set16(REG_SCANFED, 4); /* scan and backtracking slope table */ - auto scan_table = sanei_genesys_slope_table(dev->model->asic_type, yres, scan_exposure_time, - dev->motor.base_ydpi, 1, - motor_profile); - gl124_send_slope_table(dev, SCAN_TABLE, scan_table.table, scan_table.steps_count); - gl124_send_slope_table(dev, BACKTRACK_TABLE, scan_table.table, scan_table.steps_count); + auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, yres, + scan_exposure_time, 1, motor_profile); + scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table); + scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table); - reg->set16(REG_STEPNO, scan_table.steps_count); + reg->set16(REG_STEPNO, scan_table.table.size()); /* fast table */ fast_dpi=yres; @@ -583,28 +558,26 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, fast_dpi*=3; } */ - auto fast_table = sanei_genesys_slope_table(dev->model->asic_type, fast_dpi, - scan_exposure_time, dev->motor.base_ydpi, - 1, motor_profile); - gl124_send_slope_table(dev, STOP_TABLE, fast_table.table, fast_table.steps_count); - gl124_send_slope_table(dev, FAST_TABLE, fast_table.table, fast_table.steps_count); + auto fast_table = create_slope_table(dev->model->asic_type, dev->motor, fast_dpi, + scan_exposure_time, 1, motor_profile); + scanner_send_slope_table(dev, sensor, STOP_TABLE, fast_table.table); + scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table); - reg->set16(REG_FASTNO, fast_table.steps_count); - reg->set16(REG_FSHDEC, fast_table.steps_count); - reg->set16(REG_FMOVNO, fast_table.steps_count); + reg->set16(REG_FASTNO, fast_table.table.size()); + reg->set16(REG_FSHDEC, fast_table.table.size()); + reg->set16(REG_FMOVNO, fast_table.table.size()); /* substract acceleration distance from feedl */ feedl=feed_steps; feedl <<= static_cast<unsigned>(motor_profile.step_type); - dist = scan_table.steps_count; - if (has_flag(flags, MotorFlag::FEED)) { + dist = scan_table.table.size(); + if (has_flag(flags, ScanFlag::FEEDING)) { dist *= 2; } if (use_fast_fed) { - dist += fast_table.steps_count * 2; + dist += fast_table.table.size() * 2; } - DBG (DBG_io2, "%s: acceleration distance=%d\n", __func__, dist); /* get sure we don't use insane value */ if (dist < feedl) { @@ -614,160 +587,97 @@ static void gl124_init_motor_regs_scan(Genesys_Device* dev, } reg->set24(REG_FEEDL, feedl); - DBG (DBG_io, "%s: feedl=%d\n", __func__, feedl); /* doesn't seem to matter that much */ sanei_genesys_calculate_zmod(use_fast_fed, scan_exposure_time, scan_table.table, - scan_table.steps_count, + scan_table.table.size(), feedl, - scan_table.steps_count, + scan_table.table.size(), &z1, &z2); reg->set24(REG_Z1MOD, z1); - DBG(DBG_info, "%s: z1 = %d\n", __func__, z1); - reg->set24(REG_Z2MOD, z2); - DBG(DBG_info, "%s: z2 = %d\n", __func__, z2); /* LINESEL */ reg->set8_mask(REG_0x1D, linesel, REG_0x1D_LINESEL); reg->set8(REG_0xA0, (static_cast<unsigned>(motor_profile.step_type) << REG_0xA0S_STEPSEL) | (static_cast<unsigned>(motor_profile.step_type) << REG_0xA0S_FSTPSEL)); - reg->set16(REG_FMOVDEC, fast_table.steps_count); + reg->set16(REG_FMOVDEC, fast_table.table.size()); } - -/** @brief copy sensor specific settings - * Set up register set for the given sensor resolution. Values are from the device table - * in genesys_devices.c for registers: - * [0x16 ... 0x1d] - * [0x52 ... 0x5e] - * Other come from the specific device sensor table in genesys_gl124.h: - * 0x18, 0x20, 0x61, 0x98 and - * @param dev device to set up - * @param regs register set to modify - * @param dpi resolution of the sensor during scan - * @param ccd_size_divisor flag for half ccd mode - * */ -static void gl124_setup_sensor(Genesys_Device* dev, const Genesys_Sensor& sensor, - Genesys_Register_Set* regs) -{ - DBG_HELPER(dbg); - - for (const auto& reg : sensor.custom_regs) { - regs->set8(reg.address, reg.value); - } - - regs->set24(REG_EXPR, sensor.exposure.red); - regs->set24(REG_EXPG, sensor.exposure.green); - regs->set24(REG_EXPB, sensor.exposure.blue); - - dev->segment_order = sensor.segment_order; -} - -/** @brief setup optical related registers - * start and pixels are expressed in optical sensor resolution coordinate - * space. - * @param dev scanner device to use - * @param reg registers to set up - * @param exposure_time exposure time to use - * @param used_res scanning resolution used, may differ from - * scan's one - * @param start logical start pixel coordinate - * @param pixels logical number of pixels to use - * @param channels number of color channels (currently 1 or 3) - * @param depth bit depth of the scan (1, 8 or 16) - * @param ccd_size_divisor whether sensor's timings are such that x coordinates must be halved - * @param color_filter color channel to use as gray data - * @param flags optical flags (@see ) - */ static void gl124_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor, Genesys_Register_Set* reg, unsigned int exposure_time, const ScanSession& session) { DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time); - unsigned int dpihw; - GenesysRegister *r; uint32_t expmax; - // resolution is divided according to ccd_pixels_per_system_pixel - unsigned ccd_pixels_per_system_pixel = sensor.ccd_pixels_per_system_pixel(); - DBG(DBG_io2, "%s: ccd_pixels_per_system_pixel=%d\n", __func__, ccd_pixels_per_system_pixel); - - // to manage high resolution device while keeping good low resolution scanning speed, we - // make hardware dpi vary - dpihw = sensor.get_register_hwdpi(session.output_resolution * ccd_pixels_per_system_pixel); - DBG(DBG_io2, "%s: dpihw=%d\n", __func__, dpihw); - - gl124_setup_sensor(dev, sensor, reg); + scanner_setup_sensor(*dev, sensor, *reg); dev->cmd_set->set_fe(dev, sensor, AFE_SET); /* enable shading */ regs_set_optical_off(dev->model->asic_type, *reg); - r = sanei_genesys_get_address (reg, REG_0x01); if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) || - (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) + has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION)) { - r->value &= ~REG_0x01_DVDSET; + reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET; } else { - r->value |= REG_0x01_DVDSET; + reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET; } - r = sanei_genesys_get_address(reg, REG_0x03); if ((dev->model->sensor_id != SensorId::CIS_CANON_LIDE_120) && (session.params.xres>=600)) { - r->value &= ~REG_0x03_AVEENB; - DBG (DBG_io, "%s: disabling AVEENB\n", __func__); - } - else - { - r->value |= ~REG_0x03_AVEENB; - DBG (DBG_io, "%s: enabling AVEENB\n", __func__); + reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB; + } else { + // BUG: the following is likely incorrect + reg->find_reg(REG_0x03).value |= ~REG_0x03_AVEENB; } sanei_genesys_set_lamp_power(dev, sensor, *reg, !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP)); // BW threshold - dev->interface->write_register(REG_0x114, dev->settings.threshold); - dev->interface->write_register(REG_0x115, dev->settings.threshold); + dev->interface->write_register(REG_0x114, 0x7f); + dev->interface->write_register(REG_0x115, 0x7f); /* monochrome / color scan */ - r = sanei_genesys_get_address (reg, REG_0x04); switch (session.params.depth) { case 8: - r->value &= ~(REG_0x04_LINEART | REG_0x04_BITSET); + reg->find_reg(REG_0x04).value &= ~(REG_0x04_LINEART | REG_0x04_BITSET); break; case 16: - r->value &= ~REG_0x04_LINEART; - r->value |= REG_0x04_BITSET; + reg->find_reg(REG_0x04).value &= ~REG_0x04_LINEART; + reg->find_reg(REG_0x04).value |= REG_0x04_BITSET; break; } - r->value &= ~REG_0x04_FILTER; + reg->find_reg(REG_0x04).value &= ~REG_0x04_FILTER; if (session.params.channels == 1) { switch (session.params.color_filter) { case ColorFilter::RED: - r->value |= 0x10; + reg->find_reg(REG_0x04).value |= 0x10; break; case ColorFilter::BLUE: - r->value |= 0x30; + reg->find_reg(REG_0x04).value |= 0x30; break; case ColorFilter::GREEN: - r->value |= 0x20; + reg->find_reg(REG_0x04).value |= 0x20; break; default: break; // should not happen } } - sanei_genesys_set_dpihw(*reg, sensor, dpihw); + const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution, + session.params.channels, + session.params.scan_method); + sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw); if (should_enable_gamma(session, sensor)) { reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB; @@ -775,25 +685,16 @@ static void gl124_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB; } - unsigned dpiset_reg = session.output_resolution * ccd_pixels_per_system_pixel * - session.ccd_size_divisor; - if (sensor.dpiset_override != 0) { - dpiset_reg = sensor.dpiset_override; - } - - reg->set16(REG_DPISET, dpiset_reg); - DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset_reg); + reg->set16(REG_DPISET, sensor.register_dpiset); - r = sanei_genesys_get_address(reg, REG_0x06); - r->value |= REG_0x06_GAIN4; + reg->find_reg(REG_0x06).value |= REG_0x06_GAIN4; /* CIS scanners can do true gray by setting LEDADD */ /* we set up LEDADD only when asked */ if (dev->model->is_cis) { - r = sanei_genesys_get_address (reg, REG_0x60); - r->value &= ~REG_0x60_LEDADD; + reg->find_reg(REG_0x60).value &= ~REG_0x60_LEDADD; if (session.enable_ledadd) { - r->value |= REG_0x60_LEDADD; + reg->find_reg(REG_0x60).value |= REG_0x60_LEDADD; expmax = reg->get24(REG_EXPR); expmax = std::max(expmax, reg->get24(REG_EXPG)); expmax = std::max(expmax, reg->get24(REG_EXPB)); @@ -803,31 +704,32 @@ static void gl124_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens dev->reg.set24(REG_EXPB, expmax); } /* RGB weighting, REG_TRUER,G and B are to be set */ - r = sanei_genesys_get_address (reg, 0x01); - r->value &= ~REG_0x01_TRUEGRAY; + reg->find_reg(0x01).value &= ~REG_0x01_TRUEGRAY; if (session.enable_ledadd) { - r->value |= REG_0x01_TRUEGRAY; + reg->find_reg(0x01).value |= REG_0x01_TRUEGRAY; dev->interface->write_register(REG_TRUER, 0x80); dev->interface->write_register(REG_TRUEG, 0x80); dev->interface->write_register(REG_TRUEB, 0x80); } } + std::uint32_t pixel_endx = session.pixel_endx; + if (pixel_endx == reg->get24(REG_SEGCNT)) { + pixel_endx = 0; + } reg->set24(REG_STRPIXEL, session.pixel_startx); - reg->set24(REG_ENDPIXEL, session.pixel_endx); + reg->set24(REG_ENDPIXEL, pixel_endx); dev->line_count = 0; - build_image_pipeline(dev, session); + setup_image_pipeline(*dev, session); // MAXWD is expressed in 2 words unit // BUG: we shouldn't multiply by channels here - reg->set24(REG_MAXWD, session.output_line_bytes_raw / session.ccd_size_divisor * session.params.channels); - + reg->set24(REG_MAXWD, session.output_line_bytes_raw * session.params.channels * + session.optical_resolution / session.full_resolution); reg->set24(REG_LPERIOD, exposure_time); - DBG (DBG_io2, "%s: exposure_time used=%d\n", __func__, exposure_time); - reg->set16(REG_DUMMY, sensor.dummy_pixel); } @@ -838,7 +740,6 @@ void CommandSetGl124::init_regs_for_scan_session(Genesys_Device* dev, const Gene DBG_HELPER(dbg); session.assert_computed(); - int move; int exposure_time; int dummy = 0; @@ -856,9 +757,7 @@ void CommandSetGl124::init_regs_for_scan_session(Genesys_Device* dev, const Gene } else { exposure_time = sensor.exposure_lperiod; } - const auto& motor_profile = sanei_genesys_get_motor_profile(*gl124_motor_profiles, - dev->model->motor_id, - exposure_time); + const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session); DBG(DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time); DBG(DBG_info, "%s : scan_step_type=%d\n", __func__, static_cast<unsigned>(motor_profile.step_type)); @@ -870,30 +769,13 @@ void CommandSetGl124::init_regs_for_scan_session(Genesys_Device* dev, const Gene // now _LOGICAL_ optical values used are known, setup registers gl124_init_optical_regs_scan(dev, sensor, reg, exposure_time, session); - /* add tl_y to base movement */ - move = session.params.starty; - DBG(DBG_info, "%s: move=%d steps\n", __func__, move); - - MotorFlag mflags = MotorFlag::NONE; - if (has_flag(session.params.flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE)) { - mflags |= MotorFlag::DISABLE_BUFFER_FULL_MOVE; - } - if (has_flag(session.params.flags, ScanFlag::FEEDING)) { - mflags |= MotorFlag::FEED; - } - if (has_flag(session.params.flags, ScanFlag::REVERSE)) { - mflags |= MotorFlag::REVERSE; - } gl124_init_motor_regs_scan(dev, sensor, reg, motor_profile, exposure_time, slope_dpi, - dev->model->is_cis ? session.output_line_count * session.params.channels : - session.output_line_count, - dummy, move, session.params.scan_mode, mflags); + session.optical_line_count, + dummy, session.params.starty, session.params.scan_mode, + session.params.flags); /*** prepares data reordering ***/ - dev->read_buffer.clear(); - dev->read_buffer.alloc(session.buffer_size_read); - dev->read_active = true; dev->session = session; @@ -909,21 +791,24 @@ ScanSession CommandSetGl124::calculate_scan_session(const Genesys_Device* dev, const Genesys_Sensor& sensor, const Genesys_Settings& settings) const { - int start; - DBG(DBG_info, "%s ", __func__); debug_dump(DBG_info, settings); - /* start */ - start = static_cast<int>(dev->model->x_offset); - start += static_cast<int>(settings.tl_x); - start = static_cast<int>((start * sensor.optical_res) / MM_PER_INCH); + unsigned move_dpi = dev->motor.base_ydpi / 4; + float move = dev->model->y_offset; + move += dev->settings.tl_y; + move = static_cast<float>((move * move_dpi) / MM_PER_INCH); + + float start = dev->model->x_offset; + start += settings.tl_x; + start /= sensor.full_resolution / sensor.get_optical_resolution(); + start = static_cast<float>((start * settings.xres) / MM_PER_INCH); ScanSession session; session.params.xres = settings.xres; session.params.yres = settings.yres; - session.params.startx = start; - session.params.starty = 0; // not used + session.params.startx = static_cast<unsigned>(start); + session.params.starty = static_cast<unsigned>(move); session.params.pixels = settings.pixels; session.params.requested_pixels = settings.requested_pixels; session.params.lines = settings.lines; @@ -953,17 +838,15 @@ void CommandSetGl124::save_power(Genesys_Device* dev, bool enable) const void CommandSetGl124::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const { DBG_HELPER_ARGS(dbg, "delay = %d", delay); - GenesysRegister *r; - r = sanei_genesys_get_address(&dev->reg, REG_0x03); - r->value &= ~0xf0; + dev->reg.find_reg(REG_0x03).value &= ~0xf0; if(delay<15) { - r->value |= delay; + dev->reg.find_reg(REG_0x03).value |= delay; } else { - r->value |= 0x0f; + dev->reg.find_reg(REG_0x03).value |= 0x0f; } } @@ -1031,8 +914,7 @@ void CommandSetGl124::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens // set up GPIO for scan gl124_setup_scan_gpio(dev,dev->settings.yres); - // clear scan and feed count - dev->interface->write_register(REG_0x0D, REG_0x0D_CLRLNCNT | REG_0x0D_CLRMCNT); + scanner_clear_scan_and_feed_counts(*dev); // enable scan and motor uint8_t val = dev->interface->read_register(REG_0x01); @@ -1069,177 +951,43 @@ void CommandSetGl124::move_back_home(Genesys_Device* dev, bool wait_until_home) scanner_move_back_home(*dev, wait_until_home); } -// Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi -// from very top of scanner -void CommandSetGl124::search_start_position(Genesys_Device* dev) const -{ - DBG_HELPER(dbg); - int size; - Genesys_Register_Set local_reg = dev->reg; - - int pixels = 600; - int dpi = 300; - - /* sets for a 200 lines * 600 pixels */ - /* normal scan with no shading */ - - // FIXME: the current approach of doing search only for one resolution does not work on scanners - // whith employ different sensors with potentially different settings. - const auto& sensor = sanei_genesys_find_sensor(dev, dpi, 1, ScanMethod::FLATBED); - - ScanSession session; - session.params.xres = dpi; - session.params.yres = dpi; - session.params.startx = 0; - session.params.starty = 0; /*we should give a small offset here~60 steps */ - session.params.pixels = 600; - session.params.lines = dev->model->search_lines; - session.params.depth = 8; - session.params.channels = 1; - session.params.scan_method = dev->settings.scan_method; - session.params.scan_mode = ScanColorMode::GRAY; - session.params.color_filter = ColorFilter::GREEN; - session.params.flags = ScanFlag::DISABLE_SHADING | - ScanFlag::DISABLE_GAMMA | - ScanFlag::IGNORE_LINE_DISTANCE | - ScanFlag::DISABLE_BUFFER_FULL_MOVE; - compute_session(dev, session, sensor); - - init_regs_for_scan_session(dev, sensor, &local_reg, session); - - // send to scanner - dev->interface->write_registers(local_reg); - - size = pixels * dev->model->search_lines; - - std::vector<uint8_t> data(size); - - begin_scan(dev, sensor, &local_reg, true); - - if (is_testing_mode()) { - dev->interface->test_checkpoint("search_start_position"); - end_scan(dev, &local_reg, true); - dev->reg = local_reg; - return; - } - - wait_until_buffer_non_empty(dev); - - // now we're on target, we can read data - sanei_genesys_read_data_from_scanner(dev, data.data(), size); - - if (DBG_LEVEL >= DBG_data) { - sanei_genesys_write_pnm_file("gl124_search_position.pnm", data.data(), 8, 1, pixels, - dev->model->search_lines); - } - - end_scan(dev, &local_reg, true); - - /* update regs to copy ASIC internal state */ - dev->reg = local_reg; - - for (auto& sensor_update : - sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method)) - { - sanei_genesys_search_reference_point(dev, sensor_update, data.data(), 0, dpi, pixels, - dev->model->search_lines); - } -} - -// sets up register for coarse gain calibration -// todo: check it for scanners using it -void CommandSetGl124::init_regs_for_coarse_calibration(Genesys_Device* dev, - const Genesys_Sensor& sensor, - Genesys_Register_Set& regs) const -{ - DBG_HELPER(dbg); - - ScanSession session; - session.params.xres = dev->settings.xres; - session.params.yres = dev->settings.yres; - session.params.startx = 0; - session.params.starty = 0; - session.params.pixels = sensor.optical_res / sensor.ccd_pixels_per_system_pixel(); - session.params.lines = 20; - session.params.depth = 16; - session.params.channels = dev->settings.get_channels(); - session.params.scan_method = dev->settings.scan_method; - session.params.scan_mode = dev->settings.scan_mode; - session.params.color_filter = dev->settings.color_filter; - session.params.flags = ScanFlag::DISABLE_SHADING | - ScanFlag::DISABLE_GAMMA | - ScanFlag::SINGLE_LINE | - ScanFlag::FEEDING | - ScanFlag::IGNORE_LINE_DISTANCE; - compute_session(dev, session, sensor); - - init_regs_for_scan_session(dev, sensor, ®s, session); - - sanei_genesys_set_motor_power(regs, false); - - DBG(DBG_info, "%s: optical sensor res: %d dpi, actual res: %d\n", __func__, - sensor.optical_res / sensor.ccd_pixels_per_system_pixel(), dev->settings.xres); - - dev->interface->write_registers(regs); -} - - // init registers for shading calibration shading calibration is done at dpihw void CommandSetGl124::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor, Genesys_Register_Set& regs) const { DBG_HELPER(dbg); - int move, resolution, dpihw, factor; - - /* initial calibration reg values */ - regs = dev->reg; - - dev->calib_channels = 3; - dev->calib_lines = dev->model->shading_lines; - dpihw = sensor.get_register_hwdpi(dev->settings.xres); - if(dpihw>=2400) - { - dev->calib_lines *= 2; - } - resolution=dpihw; - unsigned ccd_size_divisor = sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres); + unsigned channels = 3; + unsigned resolution = sensor.shading_resolution; - resolution /= ccd_size_divisor; - dev->calib_lines /= ccd_size_divisor; // reducing just because we reduced the resolution + unsigned calib_lines = + static_cast<unsigned>(dev->model->y_size_calib_mm * resolution / MM_PER_INCH); - const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, - dev->calib_channels, + const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels, dev->settings.scan_method); - dev->calib_resolution = resolution; - dev->calib_total_bytes_to_read = 0; - factor = calib_sensor.optical_res / resolution; - dev->calib_pixels = calib_sensor.sensor_pixels / factor; /* distance to move to reach white target at high resolution */ - move=0; + unsigned move=0; if (dev->settings.yres >= 1200) { move = static_cast<int>(dev->model->y_offset_calib_white); move = static_cast<int>((move * (dev->motor.base_ydpi/4)) / MM_PER_INCH); } - DBG (DBG_io, "%s: move=%d steps\n", __func__, move); ScanSession session; session.params.xres = resolution; session.params.yres = resolution; session.params.startx = 0; session.params.starty = move; - session.params.pixels = dev->calib_pixels; - session.params.lines = dev->calib_lines; + session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH; + session.params.lines = calib_lines; session.params.depth = 16; - session.params.channels = dev->calib_channels; + session.params.channels = channels; session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = ColorFilter::RED; session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | - ScanFlag::DISABLE_BUFFER_FULL_MOVE | - ScanFlag::IGNORE_LINE_DISTANCE; + ScanFlag::DISABLE_BUFFER_FULL_MOVE; compute_session(dev, session, calib_sensor); try { @@ -1250,7 +998,7 @@ void CommandSetGl124::init_regs_for_shading(Genesys_Device* dev, const Genesys_S } sanei_genesys_set_motor_power(regs, false); - dev->interface->write_registers(regs); + dev->calib_session = session; } void CommandSetGl124::wait_for_motor_stop(Genesys_Device* dev) const @@ -1272,56 +1020,6 @@ void CommandSetGl124::wait_for_motor_stop(Genesys_Device* dev) const dev->interface->sleep_ms(50); } -/** @brief set up registers for the actual scan - */ -void CommandSetGl124::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const -{ - DBG_HELPER(dbg); - float move; - int move_dpi; - float start; - - debug_dump(DBG_info, dev->settings); - - /* y (motor) distance to move to reach scanned area */ - move_dpi = dev->motor.base_ydpi/4; - move = static_cast<float>(dev->model->y_offset); - move += static_cast<float>(dev->settings.tl_y); - move = static_cast<float>((move * move_dpi) / MM_PER_INCH); - DBG (DBG_info, "%s: move=%f steps\n", __func__, move); - - if (dev->settings.get_channels() * dev->settings.yres >= 600 && move > 700) { - scanner_move(*dev, dev->model->default_method, static_cast<unsigned>(move - 500), - Direction::FORWARD); - move=500; - } - DBG(DBG_info, "%s: move=%f steps\n", __func__, move); - - /* start */ - start = static_cast<float>(dev->model->x_offset); - start += static_cast<float>(dev->settings.tl_x); - start /= sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres); - start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH); - - ScanSession session; - session.params.xres = dev->settings.xres; - session.params.yres = dev->settings.yres; - session.params.startx = static_cast<unsigned>(start); - session.params.starty = static_cast<unsigned>(move); - session.params.pixels = dev->settings.pixels; - session.params.requested_pixels = dev->settings.requested_pixels; - session.params.lines = dev->settings.lines; - session.params.depth = dev->settings.depth; - session.params.channels = dev->settings.get_channels(); - session.params.scan_method = dev->settings.scan_method; - session.params.scan_mode = dev->settings.scan_mode; - session.params.color_filter = dev->settings.color_filter; - session.params.flags = ScanFlag::NONE; - compute_session(dev, session, sensor); - - init_regs_for_scan_session(dev, sensor, &dev->reg, session); -} - /** * Send shading calibration data. The buffer is considered to always hold values * for all the channels. @@ -1330,8 +1028,7 @@ void CommandSetGl124::send_shading_data(Genesys_Device* dev, const Genesys_Senso std::uint8_t* data, int size) const { DBG_HELPER_ARGS(dbg, "writing %d bytes of shading data", size); - uint32_t addr, length, x, factor, segcnt, pixels, i; - uint16_t dpiset,dpihw; + std::uint32_t addr, length, segcnt, pixels, i; uint8_t *ptr, *src; /* logical size of a color as seen by generic code of the frontend */ @@ -1339,16 +1036,6 @@ void CommandSetGl124::send_shading_data(Genesys_Device* dev, const Genesys_Senso std::uint32_t strpixel = dev->session.pixel_startx; std::uint32_t endpixel = dev->session.pixel_endx; segcnt = dev->reg.get24(REG_SEGCNT); - if(endpixel==0) - { - endpixel=segcnt; - } - - /* compute deletion factor */ - dpiset = dev->reg.get16(REG_DPISET); - dpihw = sensor.get_register_hwdpi(dpiset); - factor=dpihw/dpiset; - DBG( DBG_io2, "%s: factor=%d\n",__func__,factor); /* turn pixel value into bytes 2x16 bits words */ strpixel*=2*2; /* 2 words of 2 bytes */ @@ -1359,7 +1046,7 @@ void CommandSetGl124::send_shading_data(Genesys_Device* dev, const Genesys_Senso dev->interface->record_key_value("shading_start_pixel", std::to_string(strpixel)); dev->interface->record_key_value("shading_pixels", std::to_string(pixels)); dev->interface->record_key_value("shading_length", std::to_string(length)); - dev->interface->record_key_value("shading_factor", std::to_string(factor)); + dev->interface->record_key_value("shading_factor", std::to_string(sensor.shading_factor)); dev->interface->record_key_value("shading_segcnt", std::to_string(segcnt)); dev->interface->record_key_value("shading_segment_count", std::to_string(dev->session.segment_count)); @@ -1375,47 +1062,18 @@ void CommandSetGl124::send_shading_data(Genesys_Device* dev, const Genesys_Senso ptr = buffer.data(); /* iterate on both sensor segment */ - for(x=0;x<pixels;x+=4*factor) - { + for (unsigned x = 0; x < pixels; x += 4 * sensor.shading_factor) { /* coefficient source */ src=data+x+strpixel+i*length; /* iterate over all the segments */ - switch (dev->session.segment_count) { - case 1: - ptr[0+pixels*0]=src[0+segcnt*0]; - ptr[1+pixels*0]=src[1+segcnt*0]; - ptr[2+pixels*0]=src[2+segcnt*0]; - ptr[3+pixels*0]=src[3+segcnt*0]; - break; - case 2: - ptr[0+pixels*0]=src[0+segcnt*0]; - ptr[1+pixels*0]=src[1+segcnt*0]; - ptr[2+pixels*0]=src[2+segcnt*0]; - ptr[3+pixels*0]=src[3+segcnt*0]; - ptr[0+pixels*1]=src[0+segcnt*1]; - ptr[1+pixels*1]=src[1+segcnt*1]; - ptr[2+pixels*1]=src[2+segcnt*1]; - ptr[3+pixels*1]=src[3+segcnt*1]; - break; - case 4: - ptr[0+pixels*0]=src[0+segcnt*0]; - ptr[1+pixels*0]=src[1+segcnt*0]; - ptr[2+pixels*0]=src[2+segcnt*0]; - ptr[3+pixels*0]=src[3+segcnt*0]; - ptr[0+pixels*1]=src[0+segcnt*2]; - ptr[1+pixels*1]=src[1+segcnt*2]; - ptr[2+pixels*1]=src[2+segcnt*2]; - ptr[3+pixels*1]=src[3+segcnt*2]; - ptr[0+pixels*2]=src[0+segcnt*1]; - ptr[1+pixels*2]=src[1+segcnt*1]; - ptr[2+pixels*2]=src[2+segcnt*1]; - ptr[3+pixels*2]=src[3+segcnt*1]; - ptr[0+pixels*3]=src[0+segcnt*3]; - ptr[1+pixels*3]=src[1+segcnt*3]; - ptr[2+pixels*3]=src[2+segcnt*3]; - ptr[3+pixels*3]=src[3+segcnt*3]; - break; + for (unsigned s = 0; s < dev->session.segment_count; s++) + { + unsigned segnum = dev->session.segment_count > 1 ? sensor.segment_order[s] : 0; + ptr[0+pixels*s]=src[0+segcnt*segnum]; + ptr[1+pixels*s]=src[1+segcnt*segnum]; + ptr[2+pixels*s]=src[2+segcnt*segnum]; + ptr[3+pixels*s]=src[3+segcnt*segnum]; } /* next shading coefficient */ @@ -1433,20 +1091,17 @@ void CommandSetGl124::send_shading_data(Genesys_Device* dev, const Genesys_Senso * by doing a 600 dpi scan * @param dev scanner device */ -static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& sensor, - Genesys_Register_Set& regs) +void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& sensor, + Genesys_Register_Set& regs) { (void) sensor; DBG_HELPER(dbg); - int pixels; - int size; unsigned resolution = 600; unsigned channels = 3; const auto& move_sensor = sanei_genesys_find_sensor(dev, resolution, channels, dev->settings.scan_method); - pixels = (move_sensor.sensor_pixels * 600) / move_sensor.optical_res; /* initial calibration reg values */ regs = dev->reg; @@ -1456,7 +1111,7 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& session.params.yres = resolution; session.params.startx = 0; session.params.starty = 0; - session.params.pixels = pixels; + session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH; session.params.lines = 1; session.params.depth = 8; session.params.channels = channels; @@ -1466,14 +1121,12 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA | ScanFlag::SINGLE_LINE | - ScanFlag::IGNORE_LINE_DISTANCE; + ScanFlag::IGNORE_STAGGER_OFFSET | + ScanFlag::IGNORE_COLOR_OFFSET; compute_session(dev, session, move_sensor); dev->cmd_set->init_regs_for_scan_session(dev, move_sensor, ®s, session); - size = pixels * 3; - std::vector<uint8_t> line(size); - // write registers and scan data dev->interface->write_registers(regs); @@ -1486,14 +1139,13 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& return; } - sanei_genesys_read_data_from_scanner(dev, line.data(), size); + auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes); // stop scanning scanner_stop_action(*dev); - if (DBG_LEVEL >= DBG_data) - { - sanei_genesys_write_pnm_file("gl124_movetocalarea.pnm", line.data(), 8, 3, pixels, 1); + if (dbg_log_image_data()) { + write_tiff_file("gl124_movetocalarea.tiff", image); } } @@ -1505,513 +1157,60 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor, Genesys_Register_Set& regs) const { - DBG_HELPER(dbg); - int num_pixels; - int total_size; - int resolution; - int dpihw; - int i, j; - int val; - int channels; - int avg[3]; - int turn; - uint16_t exp[3],target; - - /* move to calibration area */ - move_to_calibration_area(dev, sensor, regs); - - /* offset calibration is always done in 16 bit depth color mode */ - channels = 3; - dpihw = sensor.get_register_hwdpi(dev->settings.xres); - resolution = dpihw; - unsigned ccd_size_divisor = sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres); - resolution /= ccd_size_divisor; - - const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels, - dev->settings.scan_method); - num_pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res; - - /* initial calibration reg values */ - regs = dev->reg; - - ScanSession session; - session.params.xres = resolution; - session.params.yres = resolution; - session.params.startx = 0; - session.params.starty = 0; - session.params.pixels = num_pixels; - session.params.lines = 1; - session.params.depth = 16; - session.params.channels = channels; - session.params.scan_method = dev->settings.scan_method; - session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; - session.params.color_filter = dev->settings.color_filter; - session.params.flags = ScanFlag::DISABLE_SHADING | - ScanFlag::DISABLE_GAMMA | - ScanFlag::SINGLE_LINE | - ScanFlag::IGNORE_LINE_DISTANCE; - compute_session(dev, session, calib_sensor); - - init_regs_for_scan_session(dev, calib_sensor, ®s, session); - - total_size = num_pixels * channels * (session.params.depth / 8) * 1; - std::vector<uint8_t> line(total_size); - - // initial loop values and boundaries - exp[0] = calib_sensor.exposure.red; - exp[1] = calib_sensor.exposure.green; - exp[2] = calib_sensor.exposure.blue; - target=sensor.gain_white_ref*256; - - turn = 0; - - /* no move during led calibration */ - sanei_genesys_set_motor_power(regs, false); - bool acceptable = false; - do - { - // set up exposure - regs.set24(REG_EXPR, exp[0]); - regs.set24(REG_EXPG, exp[1]); - regs.set24(REG_EXPB, exp[2]); - - // write registers and scan data - dev->interface->write_registers(regs); - - DBG(DBG_info, "%s: starting line reading\n", __func__); - begin_scan(dev, calib_sensor, ®s, true); - - if (is_testing_mode()) { - dev->interface->test_checkpoint("led_calibration"); - scanner_stop_action(*dev); - return calib_sensor.exposure; - } - - sanei_genesys_read_data_from_scanner(dev, line.data(), total_size); - - // stop scanning - scanner_stop_action(*dev); - - if (DBG_LEVEL >= DBG_data) - { - char fn[30]; - std::snprintf(fn, 30, "gl124_led_%02d.pnm", turn); - sanei_genesys_write_pnm_file(fn, line.data(), session.params.depth, channels, num_pixels, - 1); - } - - /* compute average */ - for (j = 0; j < channels; j++) - { - avg[j] = 0; - for (i = 0; i < num_pixels; i++) - { - if (dev->model->is_cis) - val = - line[i * 2 + j * 2 * num_pixels + 1] * 256 + - line[i * 2 + j * 2 * num_pixels]; - else - val = - line[i * 2 * channels + 2 * j + 1] * 256 + - line[i * 2 * channels + 2 * j]; - avg[j] += val; - } - - avg[j] /= num_pixels; - } - - DBG(DBG_info, "%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]); - - /* check if exposure gives average within the boundaries */ - acceptable = true; - for(i=0;i<3;i++) - { - /* we accept +- 2% delta from target */ - if(abs(avg[i]-target)>target/50) - { - float prev_weight = 0.5; - exp[i] = exp[i] * prev_weight + ((exp[i] * target) / avg[i]) * (1 - prev_weight); - acceptable = false; - } - } - - turn++; - } - while (!acceptable && turn < 100); - - DBG(DBG_info, "%s: acceptable exposure: %d,%d,%d\n", __func__, exp[0], exp[1], exp[2]); - - // set these values as final ones for scan - dev->reg.set24(REG_EXPR, exp[0]); - dev->reg.set24(REG_EXPG, exp[1]); - dev->reg.set24(REG_EXPB, exp[2]); - - return { exp[0], exp[1], exp[2] }; + return scanner_led_calibration(*dev, sensor, regs); } -/** - * average dark pixels of a 8 bits scan - */ -static int -dark_average (uint8_t * data, unsigned int pixels, unsigned int lines, - unsigned int channels, unsigned int black) -{ - unsigned int i, j, k, average, count; - unsigned int avg[3]; - uint8_t val; - - /* computes average value on black margin */ - for (k = 0; k < channels; k++) - { - avg[k] = 0; - count = 0; - for (i = 0; i < lines; i++) - { - for (j = 0; j < black; j++) - { - val = data[i * channels * pixels + j + k]; - avg[k] += val; - count++; - } - } - if (count) - avg[k] /= count; - DBG(DBG_info, "%s: avg[%d] = %d\n", __func__, k, avg[k]); - } - average = 0; - for (i = 0; i < channels; i++) - average += avg[i]; - average /= channels; - DBG(DBG_info, "%s: average = %d\n", __func__, average); - return average; -} - - void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor, Genesys_Register_Set& regs) const { - DBG_HELPER(dbg); - unsigned channels; - int pass = 0, avg, total_size; - int topavg, bottomavg, lines; - int top, bottom, black_pixels, pixels; - - // no gain nor offset for TI AFE - uint8_t reg0a = dev->interface->read_register(REG_0x0A); - if (((reg0a & REG_0x0A_SIFSEL) >> REG_0x0AS_SIFSEL) == 3) { - return; - } - - /* offset calibration is always done in color mode */ - channels = 3; - dev->calib_pixels = sensor.sensor_pixels; - lines=1; - pixels = (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res; - black_pixels = (sensor.black_pixels * sensor.optical_res) / sensor.optical_res; - DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels); - - ScanSession session; - session.params.xres = sensor.optical_res; - session.params.yres = sensor.optical_res; - session.params.startx = 0; - session.params.starty = 0; - session.params.pixels = pixels; - session.params.lines = lines; - session.params.depth = 8; - session.params.channels = channels; - session.params.scan_method = dev->settings.scan_method; - session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; - session.params.color_filter = dev->settings.color_filter; - session.params.flags = ScanFlag::DISABLE_SHADING | - ScanFlag::DISABLE_GAMMA | - ScanFlag::SINGLE_LINE | - ScanFlag::IGNORE_LINE_DISTANCE; - compute_session(dev, session, sensor); - - init_regs_for_scan_session(dev, sensor, ®s, session); - - sanei_genesys_set_motor_power(regs, false); - - /* allocate memory for scans */ - total_size = pixels * channels * lines * (session.params.depth / 8); - - std::vector<uint8_t> first_line(total_size); - std::vector<uint8_t> second_line(total_size); - - /* init gain */ - dev->frontend.set_gain(0, 0); - dev->frontend.set_gain(1, 0); - dev->frontend.set_gain(2, 0); - - /* scan with no move */ - bottom = 10; - dev->frontend.set_offset(0, bottom); - dev->frontend.set_offset(1, bottom); - dev->frontend.set_offset(2, bottom); - - set_fe(dev, sensor, AFE_SET); - dev->interface->write_registers(regs); - DBG(DBG_info, "%s: starting first line reading\n", __func__); - begin_scan(dev, sensor, ®s, true); - - if (is_testing_mode()) { - dev->interface->test_checkpoint("offset_calibration"); - return; - } - - sanei_genesys_read_data_from_scanner(dev, first_line.data(), total_size); - if (DBG_LEVEL >= DBG_data) - { - char title[30]; - std::snprintf(title, 30, "gl124_offset%03d.pnm", bottom); - sanei_genesys_write_pnm_file(title, first_line.data(), session.params.depth, - channels, pixels, lines); - } - - bottomavg = dark_average(first_line.data(), pixels, lines, channels, black_pixels); - DBG(DBG_io2, "%s: bottom avg=%d\n", __func__, bottomavg); - - /* now top value */ - top = 255; - dev->frontend.set_offset(0, top); - dev->frontend.set_offset(1, top); - dev->frontend.set_offset(2, top); - set_fe(dev, sensor, AFE_SET); - dev->interface->write_registers(regs); - DBG(DBG_info, "%s: starting second line reading\n", __func__); - begin_scan(dev, sensor, ®s, true); - sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size); - - topavg = dark_average(second_line.data(), pixels, lines, channels, black_pixels); - DBG(DBG_io2, "%s: top avg=%d\n", __func__, topavg); - - /* loop until acceptable level */ - while ((pass < 32) && (top - bottom > 1)) - { - pass++; - - /* settings for new scan */ - dev->frontend.set_offset(0, (top + bottom) / 2); - dev->frontend.set_offset(1, (top + bottom) / 2); - dev->frontend.set_offset(2, (top + bottom) / 2); - - // scan with no move - set_fe(dev, sensor, AFE_SET); - dev->interface->write_registers(regs); - DBG(DBG_info, "%s: starting second line reading\n", __func__); - begin_scan(dev, sensor, ®s, true); - sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size); - - if (DBG_LEVEL >= DBG_data) - { - char title[30]; - std::snprintf(title, 30, "gl124_offset%03d.pnm", dev->frontend.get_offset(1)); - sanei_genesys_write_pnm_file(title, second_line.data(), session.params.depth, - channels, pixels, lines); - } - - avg = dark_average(second_line.data(), pixels, lines, channels, black_pixels); - DBG(DBG_info, "%s: avg=%d offset=%d\n", __func__, avg, dev->frontend.get_offset(1)); - - /* compute new boundaries */ - if (topavg == avg) - { - topavg = avg; - top = dev->frontend.get_offset(1); - } - else - { - bottomavg = avg; - bottom = dev->frontend.get_offset(1); - } - } - 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)); + scanner_offset_calibration(*dev, sensor, regs); } - -/* alternative coarse gain calibration - this on uses the settings from offset_calibration and - uses only one scanline - */ -/* - with offset and coarse calibration we only want to get our input range into - a reasonable shape. the fine calibration of the upper and lower bounds will - be done with shading. - */ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor, Genesys_Register_Set& regs, int dpi) const { - DBG_HELPER_ARGS(dbg, "dpi = %d", dpi); - int pixels; - int total_size; - int i, j, channels; - int max[3]; - float gain[3],coeff; - int val, code, lines; - - // no gain nor offset for TI AFE - uint8_t reg0a = dev->interface->read_register(REG_0x0A); - if (((reg0a & REG_0x0A_SIFSEL) >> REG_0x0AS_SIFSEL) == 3) { - return; - } - - /* coarse gain calibration is always done in color mode */ - channels = 3; - - if(dev->settings.xres<sensor.optical_res) - { - coeff = 0.9f; - } else { - coeff = 1.0f; - } - lines=10; - pixels = (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res; - - ScanSession session; - session.params.xres = sensor.optical_res; - session.params.yres = sensor.optical_res; - session.params.startx = 0; - session.params.starty = 0; - session.params.pixels = pixels; - session.params.lines = lines; - session.params.depth = 8; - session.params.channels = channels; - session.params.scan_method = dev->settings.scan_method; - session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; - session.params.color_filter = dev->settings.color_filter; - session.params.flags = ScanFlag::DISABLE_SHADING | - ScanFlag::DISABLE_GAMMA | - ScanFlag::SINGLE_LINE | - ScanFlag::IGNORE_LINE_DISTANCE; - compute_session(dev, session, sensor); - - try { - init_regs_for_scan_session(dev, sensor, ®s, session); - } catch (...) { - catch_all_exceptions(__func__, [&](){ sanei_genesys_set_motor_power(regs, false); }); - throw; - } - - sanei_genesys_set_motor_power(regs, false); - - dev->interface->write_registers(regs); - - total_size = pixels * channels * (16 / session.params.depth) * lines; - - std::vector<uint8_t> line(total_size); - - set_fe(dev, sensor, AFE_SET); - begin_scan(dev, sensor, ®s, true); - - if (is_testing_mode()) { - dev->interface->test_checkpoint("coarse_gain_calibration"); - scanner_stop_action(*dev); - move_back_home(dev, true); - return; - } - - sanei_genesys_read_data_from_scanner(dev, line.data(), total_size); - - if (DBG_LEVEL >= DBG_data) { - sanei_genesys_write_pnm_file("gl124_gain.pnm", line.data(), session.params.depth, - channels, pixels, lines); - } - - /* average value on each channel */ - for (j = 0; j < channels; j++) - { - max[j] = 0; - for (i = pixels/4; i < (pixels*3/4); i++) - { - if (dev->model->is_cis) { - val = line[i + j * pixels]; - } else { - val = line[i * channels + j]; - } - - max[j] += val; - } - max[j] = max[j] / (pixels/2); - - gain[j] = (static_cast<float>(sensor.gain_white_ref) * coeff) / max[j]; - - /* turn logical gain value into gain code, checking for overflow */ - code = static_cast<int>(283 - 208 / gain[j]); - if (code > 255) - code = 255; - else if (code < 0) - code = 0; - dev->frontend.set_gain(j, code); - - DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, max[j], - gain[j], dev->frontend.get_gain(j)); - } - - if (dev->model->is_cis) { - uint8_t gain0 = dev->frontend.get_gain(0); - if (gain0 > dev->frontend.get_gain(1)) { - gain0 = dev->frontend.get_gain(1); - } - if (gain0 > dev->frontend.get_gain(2)) { - gain0 = dev->frontend.get_gain(2); - } - dev->frontend.set_gain(0, gain0); - dev->frontend.set_gain(1, gain0); - dev->frontend.set_gain(2, gain0); - } - - if (channels == 1) { - dev->frontend.set_gain(0, dev->frontend.get_gain(1)); - dev->frontend.set_gain(2, dev->frontend.get_gain(1)); - } - - scanner_stop_action(*dev); - - move_back_home(dev, true); + scanner_coarse_gain_calibration(*dev, sensor, regs, dpi); } // wait for lamp warmup by scanning the same line until difference // between 2 scans is below a threshold void CommandSetGl124::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor, - Genesys_Register_Set* reg, int* channels, - int* total_size) const + Genesys_Register_Set* reg) const { DBG_HELPER(dbg); - int num_pixels; - - *channels=3; *reg = dev->reg; + auto flags = ScanFlag::DISABLE_SHADING | + ScanFlag::DISABLE_GAMMA | + ScanFlag::SINGLE_LINE | + ScanFlag::IGNORE_STAGGER_OFFSET | + ScanFlag::IGNORE_COLOR_OFFSET; + if (dev->settings.scan_method == ScanMethod::TRANSPARENCY || + dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) + { + flags |= ScanFlag::USE_XPA; + } + ScanSession session; - session.params.xres = sensor.optical_res; + session.params.xres = sensor.full_resolution; session.params.yres = dev->motor.base_ydpi; - session.params.startx = sensor.sensor_pixels / 4; + session.params.startx = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH / 4; session.params.starty = 0; - session.params.pixels = sensor.sensor_pixels / 2; + session.params.pixels = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH / 2; session.params.lines = 1; - session.params.depth = 8; - session.params.channels = *channels; + session.params.depth = dev->model->bpp_color_values.front(); + session.params.channels = 3; session.params.scan_method = dev->settings.scan_method; session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS; session.params.color_filter = dev->settings.color_filter; - session.params.flags = ScanFlag::DISABLE_SHADING | - ScanFlag::DISABLE_GAMMA | - ScanFlag::SINGLE_LINE | - ScanFlag::IGNORE_LINE_DISTANCE; + session.params.flags = flags; + compute_session(dev, session, sensor); init_regs_for_scan_session(dev, sensor, reg, session); - num_pixels = session.output_pixels; - - *total_size = num_pixels * 3 * 1; /* colors * bytes_per_color * scan lines */ - sanei_genesys_set_motor_power(*reg, false); - dev->interface->write_registers(*reg); } /** @brief default GPIO values @@ -2049,64 +1248,8 @@ static void gl124_init_gpio(Genesys_Device* dev) static void gl124_init_memory_layout(Genesys_Device* dev) { DBG_HELPER(dbg); - int idx = 0; - /* point to per model memory layout */ - if (dev->model->model_id == ModelId::CANON_LIDE_110 || - dev->model->model_id == ModelId::CANON_LIDE_120) - { - idx = 0; - } - else - { /* canon LiDE 210 and 220 case */ - idx = 1; - } - - /* setup base address for shading data. */ - /* values must be multiplied by 8192=0x4000 to give address on AHB */ - /* R-Channel shading bank0 address setting for CIS */ - dev->interface->write_register(0xd0, layouts[idx].rd0); - /* G-Channel shading bank0 address setting for CIS */ - dev->interface->write_register(0xd1, layouts[idx].rd1); - /* B-Channel shading bank0 address setting for CIS */ - dev->interface->write_register(0xd2, layouts[idx].rd2); - - /* setup base address for scanned data. */ - /* values must be multiplied by 1024*2=0x0800 to give address on AHB */ - /* R-Channel ODD image buffer 0x0124->0x92000 */ - /* size for each buffer is 0x16d*1k word */ - dev->interface->write_register(0xe0, layouts[idx].re0); - dev->interface->write_register(0xe1, layouts[idx].re1); - /* R-Channel ODD image buffer end-address 0x0291->0x148800 => size=0xB6800*/ - dev->interface->write_register(0xe2, layouts[idx].re2); - dev->interface->write_register(0xe3, layouts[idx].re3); - - /* R-Channel EVEN image buffer 0x0292 */ - dev->interface->write_register(0xe4, layouts[idx].re4); - dev->interface->write_register(0xe5, layouts[idx].re5); - /* R-Channel EVEN image buffer end-address 0x03ff*/ - dev->interface->write_register(0xe6, layouts[idx].re6); - dev->interface->write_register(0xe7, layouts[idx].re7); - - /* same for green, since CIS, same addresses */ - dev->interface->write_register(0xe8, layouts[idx].re0); - dev->interface->write_register(0xe9, layouts[idx].re1); - dev->interface->write_register(0xea, layouts[idx].re2); - dev->interface->write_register(0xeb, layouts[idx].re3); - dev->interface->write_register(0xec, layouts[idx].re4); - dev->interface->write_register(0xed, layouts[idx].re5); - dev->interface->write_register(0xee, layouts[idx].re6); - dev->interface->write_register(0xef, layouts[idx].re7); - -/* same for blue, since CIS, same addresses */ - dev->interface->write_register(0xf0, layouts[idx].re0); - dev->interface->write_register(0xf1, layouts[idx].re1); - dev->interface->write_register(0xf2, layouts[idx].re2); - dev->interface->write_register(0xf3, layouts[idx].re3); - dev->interface->write_register(0xf4, layouts[idx].re4); - dev->interface->write_register(0xf5, layouts[idx].re5); - dev->interface->write_register(0xf6, layouts[idx].re6); - dev->interface->write_register(0xf7, layouts[idx].re7); + apply_reg_settings_to_device_write_only(*dev, dev->memory_layout.regs); } /** @@ -2118,7 +1261,7 @@ void CommandSetGl124::init(Genesys_Device* dev) const DBG_INIT (); DBG_HELPER(dbg); - sanei_genesys_asic_init(dev, 0); + sanei_genesys_asic_init(dev); } @@ -2244,26 +1387,5 @@ void CommandSetGl124::eject_document(Genesys_Device* dev) const throw SaneException("not implemented"); } -void CommandSetGl124::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, - bool forward, bool black) const -{ - (void) dev; - (void) sensor; - (void) forward; - (void) black; - throw SaneException("not implemented"); -} - -void CommandSetGl124::move_to_ta(Genesys_Device* dev) const -{ - (void) dev; - throw SaneException("not implemented"); -} - -std::unique_ptr<CommandSet> create_gl124_cmd_set() -{ - return std::unique_ptr<CommandSet>(new CommandSetGl124{}); -} - } // namespace gl124 } // namespace genesys |