summaryrefslogtreecommitdiff
path: root/backend/genesys
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2020-09-10 19:11:27 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2020-09-10 19:11:27 +0200
commit7e9455b3b15671ff99ed168638c405e2acedb6df (patch)
tree444e59ece236e09dc153f665e42160aeb0208c24 /backend/genesys
parentbc8a517abd2e11e1435f4ef042cfcc8648b62ef7 (diff)
parentbce41b3c37c2a68e7dab234ce0247755a61ceb40 (diff)
Merge branch 'release/debian/1.0.31-1_experimental1' into masterdebian/1.0.31-1_experimental1
Diffstat (limited to 'backend/genesys')
-rw-r--r--backend/genesys/buffer.cpp102
-rw-r--r--backend/genesys/buffer.h89
-rw-r--r--backend/genesys/calibration.h9
-rw-r--r--backend/genesys/command_set.h36
-rw-r--r--backend/genesys/command_set_common.cpp248
-rw-r--r--backend/genesys/command_set_common.h48
-rw-r--r--backend/genesys/conv.cpp238
-rw-r--r--backend/genesys/conv.h69
-rw-r--r--backend/genesys/device.cpp90
-rw-r--r--backend/genesys/device.h151
-rw-r--r--backend/genesys/enums.cpp242
-rw-r--r--backend/genesys/enums.h202
-rw-r--r--backend/genesys/error.cpp29
-rw-r--r--backend/genesys/error.h24
-rw-r--r--backend/genesys/fwd.h15
-rw-r--r--backend/genesys/genesys.cpp4079
-rw-r--r--backend/genesys/genesys.h20
-rw-r--r--backend/genesys/gl124.cpp1214
-rw-r--r--backend/genesys/gl124.h83
-rw-r--r--backend/genesys/gl646.cpp1986
-rw-r--r--backend/genesys/gl646.h403
-rw-r--r--backend/genesys/gl646_registers.h1
-rw-r--r--backend/genesys/gl841.cpp3123
-rw-r--r--backend/genesys/gl841.h21
-rw-r--r--backend/genesys/gl841_registers.h2
-rw-r--r--backend/genesys/gl842.cpp1066
-rw-r--r--backend/genesys/gl842.h128
-rw-r--r--backend/genesys/gl842_registers.h285
-rw-r--r--backend/genesys/gl843.cpp1955
-rw-r--r--backend/genesys/gl843.h21
-rw-r--r--backend/genesys/gl843_registers.h10
-rw-r--r--backend/genesys/gl846.cpp1763
-rw-r--r--backend/genesys/gl846.h96
-rw-r--r--backend/genesys/gl846_registers.h12
-rw-r--r--backend/genesys/gl847.cpp1883
-rw-r--r--backend/genesys/gl847.h84
-rw-r--r--backend/genesys/gl847_registers.h1
-rw-r--r--backend/genesys/image.cpp68
-rw-r--r--backend/genesys/image.h5
-rw-r--r--backend/genesys/image_buffer.cpp127
-rw-r--r--backend/genesys/image_buffer.h65
-rw-r--r--backend/genesys/image_pipeline.cpp211
-rw-r--r--backend/genesys/image_pipeline.h134
-rw-r--r--backend/genesys/image_pixel.h1
-rw-r--r--backend/genesys/low.cpp1234
-rw-r--r--backend/genesys/low.h275
-rw-r--r--backend/genesys/motor.cpp74
-rw-r--r--backend/genesys/motor.h76
-rw-r--r--backend/genesys/register.h8
-rw-r--r--backend/genesys/scanner_interface.h10
-rw-r--r--backend/genesys/scanner_interface_usb.cpp53
-rw-r--r--backend/genesys/scanner_interface_usb.h4
-rw-r--r--backend/genesys/sensor.cpp52
-rw-r--r--backend/genesys/sensor.h190
-rw-r--r--backend/genesys/settings.cpp73
-rw-r--r--backend/genesys/settings.h121
-rw-r--r--backend/genesys/tables_frontend.cpp148
-rw-r--r--backend/genesys/tables_gpo.cpp85
-rw-r--r--backend/genesys/tables_memory_layout.cpp164
-rw-r--r--backend/genesys/tables_model.cpp1391
-rw-r--r--backend/genesys/tables_motor.cpp496
-rw-r--r--backend/genesys/tables_motor_profile.cpp380
-rw-r--r--backend/genesys/tables_sensor.cpp4474
-rw-r--r--backend/genesys/test_scanner_interface.cpp12
-rw-r--r--backend/genesys/test_scanner_interface.h7
-rw-r--r--backend/genesys/test_settings.cpp10
-rw-r--r--backend/genesys/test_settings.h2
-rw-r--r--backend/genesys/test_usb_device.cpp25
-rw-r--r--backend/genesys/test_usb_device.h9
-rw-r--r--backend/genesys/usb_device.cpp24
-rw-r--r--backend/genesys/usb_device.h8
-rw-r--r--backend/genesys/utilities.h138
-rw-r--r--backend/genesys/value_filter.h140
73 files changed, 13089 insertions, 17033 deletions
diff --git a/backend/genesys/buffer.cpp b/backend/genesys/buffer.cpp
deleted file mode 100644
index f17e361..0000000
--- a/backend/genesys/buffer.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* sane - Scanner Access Now Easy.
-
- Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
-
- This file is part of the SANE package.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
-
- As a special exception, the authors of SANE give permission for
- additional uses of the libraries contained in this release of SANE.
-
- The exception is that, if you link a SANE library with other files
- to produce an executable, this does not by itself cause the
- resulting executable to be covered by the GNU General Public
- License. Your use of that executable is in no way restricted on
- account of linking the SANE library code into it.
-
- This exception does not, however, invalidate any other reasons why
- the executable file might be covered by the GNU General Public
- License.
-
- If you submit changes to SANE to the maintainers to be included in
- a subsequent release, you agree by submitting the changes that
- those changes may be distributed with this exception intact.
-
- If you write modifications of your own for SANE, it is your choice
- whether to permit this exception to apply to your modifications.
- If you do not wish that, delete this exception notice.
-*/
-
-#include "buffer.h"
-#include <cstring>
-#include <stdexcept>
-
-namespace genesys {
-
-void Genesys_Buffer::alloc(std::size_t size)
-{
- buffer_.resize(size);
- avail_ = 0;
- pos_ = 0;
-}
-
-void Genesys_Buffer::clear()
-{
- buffer_.clear();
- avail_ = 0;
- pos_ = 0;
-}
-
-void Genesys_Buffer::reset()
-{
- avail_ = 0;
- pos_ = 0;
-}
-
-std::uint8_t* Genesys_Buffer::get_write_pos(std::size_t size)
-{
- if (avail_ + size > buffer_.size())
- return nullptr;
- if (pos_ + avail_ + size > buffer_.size())
- {
- std::memmove(buffer_.data(), buffer_.data() + pos_, avail_);
- pos_ = 0;
- }
- return buffer_.data() + pos_ + avail_;
-}
-
-std::uint8_t* Genesys_Buffer::get_read_pos()
-{
- return buffer_.data() + pos_;
-}
-
-void Genesys_Buffer::produce(std::size_t size)
-{
- if (size > buffer_.size() - avail_)
- throw std::runtime_error("buffer size exceeded");
- avail_ += size;
-}
-
-void Genesys_Buffer::consume(std::size_t size)
-{
- if (size > avail_)
- throw std::runtime_error("no more data in buffer");
- avail_ -= size;
- pos_ += size;
-}
-
-} // namespace genesys
diff --git a/backend/genesys/buffer.h b/backend/genesys/buffer.h
deleted file mode 100644
index e9c889b..0000000
--- a/backend/genesys/buffer.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* sane - Scanner Access Now Easy.
-
- Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
-
- This file is part of the SANE package.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
-
- As a special exception, the authors of SANE give permission for
- additional uses of the libraries contained in this release of SANE.
-
- The exception is that, if you link a SANE library with other files
- to produce an executable, this does not by itself cause the
- resulting executable to be covered by the GNU General Public
- License. Your use of that executable is in no way restricted on
- account of linking the SANE library code into it.
-
- This exception does not, however, invalidate any other reasons why
- the executable file might be covered by the GNU General Public
- License.
-
- If you submit changes to SANE to the maintainers to be included in
- a subsequent release, you agree by submitting the changes that
- those changes may be distributed with this exception intact.
-
- If you write modifications of your own for SANE, it is your choice
- whether to permit this exception to apply to your modifications.
- If you do not wish that, delete this exception notice.
-*/
-
-#ifndef BACKEND_GENESYS_BUFFER_H
-#define BACKEND_GENESYS_BUFFER_H
-
-#include <vector>
-#include <cstddef>
-#include <cstdint>
-
-namespace genesys {
-
-/* A FIFO buffer. Note, that this is _not_ a ringbuffer.
- if we need a block which does not fit at the end of our available data,
- we move the available data to the beginning.
-*/
-struct Genesys_Buffer
-{
- Genesys_Buffer() = default;
-
- std::size_t size() const { return buffer_.size(); }
- std::size_t avail() const { return avail_; }
- std::size_t pos() const { return pos_; }
-
- // TODO: refactor code that uses this function to no longer use it
- void set_pos(std::size_t pos) { pos_ = pos; }
-
- void alloc(std::size_t size);
- void clear();
-
- void reset();
-
- std::uint8_t* get_write_pos(std::size_t size);
- std::uint8_t* get_read_pos(); // TODO: mark as const
-
- void produce(std::size_t size);
- void consume(std::size_t size);
-
-private:
- std::vector<std::uint8_t> buffer_;
- // current position in read buffer
- std::size_t pos_ = 0;
- // data bytes currently in buffer
- std::size_t avail_ = 0;
-};
-
-} // namespace genesys
-
-#endif // BACKEND_GENESYS_BUFFER_H
diff --git a/backend/genesys/calibration.h b/backend/genesys/calibration.h
index f14aaa3..81d94ea 100644
--- a/backend/genesys/calibration.h
+++ b/backend/genesys/calibration.h
@@ -63,8 +63,7 @@ struct Genesys_Calibration_Cache
Genesys_Frontend frontend;
Genesys_Sensor sensor;
- size_t calib_pixels = 0;
- size_t calib_channels = 0;
+ ScanSession session;
size_t average_size = 0;
std::vector<std::uint16_t> white_average_data;
std::vector<std::uint16_t> dark_average_data;
@@ -75,8 +74,7 @@ struct Genesys_Calibration_Cache
last_calibration == other.last_calibration &&
frontend == other.frontend &&
sensor == other.sensor &&
- calib_pixels == other.calib_pixels &&
- calib_channels == other.calib_channels &&
+ session == other.session &&
average_size == other.average_size &&
white_average_data == other.white_average_data &&
dark_average_data == other.dark_average_data;
@@ -94,8 +92,7 @@ void serialize(Stream& str, Genesys_Calibration_Cache& x)
serialize_newline(str);
serialize(str, x.sensor);
serialize_newline(str);
- serialize(str, x.calib_pixels);
- serialize(str, x.calib_channels);
+ serialize(str, x.session);
serialize(str, x.average_size);
serialize_newline(str);
serialize(str, x.white_average_data);
diff --git a/backend/genesys/command_set.h b/backend/genesys/command_set.h
index ab3a4b6..056cba8 100644
--- a/backend/genesys/command_set.h
+++ b/backend/genesys/command_set.h
@@ -67,14 +67,10 @@ public:
virtual void init(Genesys_Device* dev) const = 0;
virtual void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const = 0;
+ Genesys_Register_Set* regs) const = 0;
- virtual void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const = 0;
virtual void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const = 0;
- virtual void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const = 0;
/** Set up registers for a scan. Similar to init_regs_for_scan except that the session is
already computed from the session
@@ -98,7 +94,6 @@ public:
*/
virtual void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const = 0;
- virtual void search_start_position(Genesys_Device* dev) const = 0;
virtual void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const = 0;
virtual void coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
@@ -112,15 +107,10 @@ public:
// Updates hardware sensor information in Genesys_Scanner.val[].
virtual void update_hardware_sensors(struct Genesys_Scanner* s) const = 0;
- /** Whether the scanner needs to call update_home_sensor_gpio before reading the status of the
- home sensor. On some chipsets this is unreliable until update_home_sensor_gpio() is called.
+ /** Needed on some chipsets before reading the status of the home sensor as the sensor may be
+ controlled by additional GPIO registers.
*/
- virtual bool needs_update_home_sensor_gpio() const { return false; }
-
- /** Needed on some chipsets before reading the status of the home sensor to make this operation
- reliable.
- */
- virtual void update_home_sensor_gpio(Genesys_Device& dev) const { (void) dev; }
+ virtual void update_home_sensor_gpio(Genesys_Device& dev) const = 0;
// functions for sheetfed scanners
@@ -134,14 +124,6 @@ public:
/// eject document from scanner
virtual void eject_document(Genesys_Device* dev) const = 0;
- /**
- * search for an black or white area in forward or reverse
- * direction */
- virtual void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const = 0;
-
- /// move scanning head to transparency adapter
- virtual void move_to_ta(Genesys_Device* dev) const = 0;
/// write shading data calibration to ASIC
virtual void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
@@ -159,6 +141,16 @@ public:
/// cold boot init function
virtual void asic_boot(Genesys_Device* dev, bool cold) const = 0;
+
+ /// checks if specific scan head is at home position
+ virtual bool is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const = 0;
+
+ /// enables or disables XPA slider motor
+ virtual void set_xpa_lamp_power(Genesys_Device& dev, bool set) const = 0;
+
+ /// enables or disables XPA slider motor
+ virtual void set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
+ MotorMode mode) const = 0;
};
} // namespace genesys
diff --git a/backend/genesys/command_set_common.cpp b/backend/genesys/command_set_common.cpp
new file mode 100644
index 0000000..381404e
--- /dev/null
+++ b/backend/genesys/command_set_common.cpp
@@ -0,0 +1,248 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+*/
+
+#define DEBUG_DECLARE_ONLY
+
+#include "command_set_common.h"
+#include "low.h"
+#include "value_filter.h"
+
+namespace genesys {
+
+CommandSetCommon::~CommandSetCommon() = default;
+
+bool CommandSetCommon::is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const
+{
+ struct HeadSettings {
+ ModelId model_id;
+ ScanHeadId scan_head;
+ GenesysRegisterSettingSet regs;
+ };
+
+ HeadSettings settings[] = {
+ { ModelId::CANON_8600F,
+ ScanHeadId::PRIMARY, {
+ { 0x6c, 0x20, 0x60 },
+ { 0xa6, 0x00, 0x01 },
+ }
+ },
+ { ModelId::CANON_8600F,
+ ScanHeadId::SECONDARY, {
+ { 0x6c, 0x00, 0x60 },
+ { 0xa6, 0x01, 0x01 },
+ }
+ },
+ };
+
+ for (const auto& setting : settings) {
+ if (setting.model_id == dev.model->model_id &&
+ setting.scan_head == scan_head)
+ {
+ auto reg_backup = apply_reg_settings_to_device_with_backup(dev, setting.regs);
+ auto status = scanner_read_status(dev);
+ apply_reg_settings_to_device(dev, reg_backup);
+ return status.is_at_home;
+ }
+ }
+
+ auto status = scanner_read_status(dev);
+ return status.is_at_home;
+}
+
+void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
+
+{
+ DBG_HELPER(dbg);
+
+ struct LampSettings {
+ ModelId model_id;
+ ScanMethod scan_method;
+ GenesysRegisterSettingSet regs_on;
+ GenesysRegisterSettingSet regs_off;
+ };
+
+ // FIXME: BUG: we're not clearing the registers to the previous state when returning back when
+ // turning off the lamp
+ LampSettings settings[] = {
+ { ModelId::CANON_4400F, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::CANON_5600F, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::CANON_8400F, ScanMethod::TRANSPARENCY, {
+ { 0xa6, 0x34, 0xf4 },
+ }, {
+ { 0xa6, 0x40, 0x70 },
+ }
+ },
+ { ModelId::CANON_8400F, ScanMethod::TRANSPARENCY_INFRARED, {
+ { 0x6c, 0x40, 0x40 },
+ { 0xa6, 0x01, 0xff },
+ }, {
+ { 0x6c, 0x00, 0x40 },
+ { 0xa6, 0x00, 0xff },
+ }
+ },
+ { ModelId::CANON_8600F, ScanMethod::TRANSPARENCY, {
+ { 0xa6, 0x34, 0xf4 },
+ { 0xa7, 0xe0, 0xe0 },
+ }, {
+ { 0xa6, 0x40, 0x70 },
+ }
+ },
+ { ModelId::CANON_8600F, ScanMethod::TRANSPARENCY_INFRARED, {
+ { 0xa6, 0x00, 0xc0 },
+ { 0xa7, 0xe0, 0xe0 },
+ { 0x6c, 0x80, 0x80 },
+ }, {
+ { 0xa6, 0x00, 0xc0 },
+ { 0x6c, 0x00, 0x80 },
+ }
+ },
+ { ModelId::PLUSTEK_OPTICFILM_7200, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY_INFRARED, {
+ { 0xa8, 0x07, 0x07 },
+ }, {
+ { 0xa8, 0x00, 0x07 },
+ }
+ },
+ { ModelId::PLUSTEK_OPTICFILM_7300, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7400, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY_INFRARED, {
+ { 0xa8, 0x07, 0x07 },
+ }, {
+ { 0xa8, 0x00, 0x07 },
+ }
+ },
+ { ModelId::PLUSTEK_OPTICFILM_8200I, ScanMethod::TRANSPARENCY, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_8200I, ScanMethod::TRANSPARENCY_INFRARED, {
+ { 0xa8, 0x04, 0x04 },
+ }, {
+ { 0xa8, 0x00, 0x04 },
+ }
+ },
+ };
+
+ for (const auto& setting : settings) {
+ if (setting.model_id == dev.model->model_id &&
+ setting.scan_method == dev.settings.scan_method)
+ {
+ apply_reg_settings_to_device(dev, set ? setting.regs_on : setting.regs_off);
+ return;
+ }
+ }
+
+ throw SaneException("Could not find XPA lamp settings");
+}
+
+
+void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
+ MotorMode mode) const
+{
+ DBG_HELPER(dbg);
+
+ struct MotorSettings {
+ ModelId model_id;
+ ValueFilterAny<unsigned> resolutions;
+ GenesysRegisterSettingSet regs_primary_and_secondary;
+ GenesysRegisterSettingSet regs_primary;
+ GenesysRegisterSettingSet regs_secondary;
+ };
+
+ MotorSettings settings[] = {
+ { ModelId::CANON_8400F, { 400, 800, 1600, 3200 }, {
+ { 0x6c, 0x00, 0x90 },
+ { 0xa9, 0x04, 0x06 },
+ }, {
+ { 0x6c, 0x90, 0x90 },
+ { 0xa9, 0x02, 0x06 },
+ }, {}
+ },
+ { ModelId::CANON_8600F, { 300, 600, 1200 }, {
+ { 0x6c, 0x00, 0x60 },
+ { 0xa6, 0x01, 0x41 },
+ }, {
+ { 0x6c, 0x20, 0x62 },
+ { 0xa6, 0x00, 0x41 },
+ }, {
+ { 0x6c, 0x40, 0x62 },
+ { 0xa6, 0x01, 0x41 },
+ }
+ },
+ { ModelId::CANON_8600F, { 2400, 4800 }, {
+ { 0x6c, 0x02, 0x62 },
+ { 0xa6, 0x01, 0x41 },
+ }, {
+ { 0x6c, 0x20, 0x62 },
+ { 0xa6, 0x00, 0x41 },
+ }, {
+ { 0x6c, 0x40, 0x62 },
+ { 0xa6, 0x01, 0x41 },
+ }
+ },
+ { ModelId::HP_SCANJET_G4050, VALUE_FILTER_ANY, {
+ { 0x6b, 0x81, 0x81 }, // set MULTFILM and GPOADF
+ { 0x6c, 0x00, 0x40 }, // note that reverse change is not applied on off
+ // 0xa6 register 0x08 bit likely sets motor power. No move at all without that one
+ { 0xa6, 0x08, 0x08 }, // note that reverse change is not applied on off
+ { 0xa8, 0x00, 0x04 },
+ { 0xa9, 0x30, 0x30 },
+ }, {
+ { 0x6b, 0x00, 0x01 }, // BUG: note that only ADF is unset
+ { 0xa8, 0x04, 0x04 },
+ { 0xa9, 0x00, 0x10 }, // note that 0x20 bit is not reset
+ }, {}
+ },
+ { ModelId::PLUSTEK_OPTICFILM_7200, VALUE_FILTER_ANY, {}, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7200I, VALUE_FILTER_ANY, {}, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7300, VALUE_FILTER_ANY, {}, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7400, VALUE_FILTER_ANY, {}, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_7500I, VALUE_FILTER_ANY, {}, {}, {} },
+ { ModelId::PLUSTEK_OPTICFILM_8200I, VALUE_FILTER_ANY, {}, {}, {} },
+ };
+
+ for (const auto& setting : settings) {
+ if (setting.model_id == dev.model->model_id &&
+ setting.resolutions.matches(dev.session.output_resolution))
+ {
+ switch (mode) {
+ case MotorMode::PRIMARY: {
+ apply_reg_settings_to_device(dev, setting.regs_primary);
+ break;
+ }
+ case MotorMode::PRIMARY_AND_SECONDARY: {
+ apply_reg_settings_to_device(dev, setting.regs_primary_and_secondary);
+ break;
+ }
+ case MotorMode::SECONDARY: {
+ apply_reg_settings_to_device(dev, setting.regs_secondary);
+ break;
+ }
+ }
+ regs.state.motor_mode = mode;
+ return;
+ }
+ }
+
+ throw SaneException("Motor settings have not been found");
+}
+
+} // namespace genesys
diff --git a/backend/genesys/command_set_common.h b/backend/genesys/command_set_common.h
new file mode 100644
index 0000000..784fcd7
--- /dev/null
+++ b/backend/genesys/command_set_common.h
@@ -0,0 +1,48 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+*/
+
+#ifndef BACKEND_GENESYS_COMMAND_SET_COMMON_H
+#define BACKEND_GENESYS_COMMAND_SET_COMMON_H
+
+#include "command_set.h"
+
+namespace genesys {
+
+
+/** Common command set functionality
+ */
+class CommandSetCommon : public CommandSet
+{
+public:
+ ~CommandSetCommon() override;
+
+ bool is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const override;
+
+ void set_xpa_lamp_power(Genesys_Device& dev, bool set) const override;
+
+ void set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
+ MotorMode mode) const override;
+};
+
+} // namespace genesys
+
+#endif // BACKEND_GENESYS_COMMAND_SET_COMMON_H
diff --git a/backend/genesys/conv.cpp b/backend/genesys/conv.cpp
deleted file mode 100644
index a87c463..0000000
--- a/backend/genesys/conv.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/* sane - Scanner Access Now Easy.
-
- Copyright (C) 2005, 2006 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
- Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr>
-
- This file is part of the SANE package.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
-
- As a special exception, the authors of SANE give permission for
- additional uses of the libraries contained in this release of SANE.
-
- The exception is that, if you link a SANE library with other files
- to produce an executable, this does not by itself cause the
- resulting executable to be covered by the GNU General Public
- License. Your use of that executable is in no way restricted on
- account of linking the SANE library code into it.
-
- This exception does not, however, invalidate any other reasons why
- the executable file might be covered by the GNU General Public
- License.
-
- If you submit changes to SANE to the maintainers to be included in
- a subsequent release, you agree by submitting the changes that
- those changes may be distributed with this exception intact.
-
- If you write modifications of your own for SANE, it is your choice
- whether to permit this exception to apply to your modifications.
- If you do not wish that, delete this exception notice.
-*/
-
-#define DEBUG_DECLARE_ONLY
-
-#include "conv.h"
-#include "sane/sanei_magic.h"
-
-namespace genesys {
-
-/**
- * uses the threshold/threshold_curve to control software binarization
- * This code was taken from the epjistsu backend by m. allan noah
- * @param dev device set up for the scan
- * @param src pointer to raw data
- * @param dst pointer where to store result
- * @param width width of the processed line
- * */
-void binarize_line(Genesys_Device* dev, std::uint8_t* src, std::uint8_t* dst, int width)
-{
- DBG_HELPER(dbg);
- int j, windowX, sum = 0;
- int thresh;
- int offset, addCol, dropCol;
- unsigned char mask;
-
- int x;
- std::uint8_t min, max;
-
- /* normalize line */
- min = 255;
- max = 0;
- for (x = 0; x < width; x++)
- {
- if (src[x] > max)
- {
- max = src[x];
- }
- if (src[x] < min)
- {
- min = src[x];
- }
- }
-
- /* safeguard against dark or white areas */
- if(min>80)
- min=0;
- if(max<80)
- max=255;
- for (x = 0; x < width; x++)
- {
- src[x] = ((src[x] - min) * 255) / (max - min);
- }
-
- /* ~1mm works best, but the window needs to have odd # of pixels */
- windowX = (6 * dev->settings.xres) / 150;
- if (!(windowX % 2))
- windowX++;
-
- /* second, prefill the sliding sum */
- for (j = 0; j < windowX; j++)
- sum += src[j];
-
- /* third, walk the input buffer, update the sliding sum, */
- /* determine threshold, output bits */
- for (j = 0; j < width; j++)
- {
- /* output image location */
- offset = j % 8;
- mask = 0x80 >> offset;
- thresh = dev->settings.threshold;
-
- /* move sum/update threshold only if there is a curve */
- if (dev->settings.threshold_curve)
- {
- addCol = j + windowX / 2;
- dropCol = addCol - windowX;
-
- if (dropCol >= 0 && addCol < width)
- {
- sum -= src[dropCol];
- sum += src[addCol];
- }
- thresh = dev->lineart_lut[sum / windowX];
- }
-
- /* use average to lookup threshold */
- if (src[j] > thresh)
- *dst &= ~mask; /* white */
- else
- *dst |= mask; /* black */
-
- if (offset == 7)
- dst++;
- }
-}
-
-/**
- * software lineart using data from a 8 bit gray scan. We assume true gray
- * or monochrome scan as input.
- */
-void genesys_gray_lineart(Genesys_Device* dev,
- std::uint8_t* src_data, std::uint8_t* dst_data,
- std::size_t pixels, std::size_t lines, std::uint8_t threshold)
-{
- DBG_HELPER(dbg);
- std::size_t y;
-
- DBG(DBG_io2, "%s: converting %zu lines of %zu pixels\n", __func__, lines, pixels);
- DBG(DBG_io2, "%s: threshold=%d\n", __func__, threshold);
-
- for (y = 0; y < lines; y++)
- {
- binarize_line (dev, src_data + y * pixels, dst_data, pixels);
- dst_data += pixels / 8;
- }
-}
-
-/** Look in image for likely left/right/bottom paper edges, then crop image.
- */
-void genesys_crop(Genesys_Scanner* s)
-{
- DBG_HELPER(dbg);
- Genesys_Device *dev = s->dev;
- int top = 0;
- int bottom = 0;
- int left = 0;
- int right = 0;
-
- // first find edges if any
- TIE(sanei_magic_findEdges(&s->params, dev->img_buffer.data(),
- dev->settings.xres, dev->settings.yres,
- &top, &bottom, &left, &right));
-
- DBG (DBG_io, "%s: t:%d b:%d l:%d r:%d\n", __func__, top, bottom, left,
- right);
-
- // now crop the image
- TIE(sanei_magic_crop (&(s->params), dev->img_buffer.data(), top, bottom, left, right));
-
- /* update counters to new image size */
- dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines;
-}
-
-/** Look in image for likely upper and left paper edges, then rotate
- * image so that upper left corner of paper is upper left of image.
- */
-void genesys_deskew(Genesys_Scanner *s, const Genesys_Sensor& sensor)
-{
- DBG_HELPER(dbg);
- Genesys_Device *dev = s->dev;
-
- int x = 0, y = 0, bg;
- double slope = 0;
-
- bg=0;
- if(s->params.format==SANE_FRAME_GRAY && s->params.depth == 1)
- {
- bg=0xff;
- }
- TIE(sanei_magic_findSkew(&s->params, dev->img_buffer.data(),
- sensor.optical_res, sensor.optical_res,
- &x, &y, &slope));
-
- DBG(DBG_info, "%s: slope=%f => %f\n", __func__, slope, slope * 180 / M_PI);
-
- // rotate image slope is in [-PI/2,PI/2]. Positive values rotate trigonometric direction wise
- TIE(sanei_magic_rotate(&s->params, dev->img_buffer.data(),
- x, y, slope, bg));
-}
-
-/** remove lone dots
- */
-void genesys_despeck(Genesys_Scanner* s)
-{
- DBG_HELPER(dbg);
- TIE(sanei_magic_despeck(&s->params, s->dev->img_buffer.data(), s->despeck));
-}
-
-/** Look if image needs rotation and apply it
- * */
-void genesys_derotate(Genesys_Scanner* s)
-{
- DBG_HELPER(dbg);
- int angle = 0;
-
- TIE(sanei_magic_findTurn(&s->params, s->dev->img_buffer.data(),
- s->resolution, s->resolution, &angle));
-
- // apply rotation angle found
- TIE(sanei_magic_turn(&s->params, s->dev->img_buffer.data(), angle));
-
- // update counters to new image size
- s->dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines;
-}
-
-} // namespace genesys
diff --git a/backend/genesys/conv.h b/backend/genesys/conv.h
deleted file mode 100644
index 446a80d..0000000
--- a/backend/genesys/conv.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* sane - Scanner Access Now Easy.
-
- Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
-
- This file is part of the SANE package.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
-
- As a special exception, the authors of SANE give permission for
- additional uses of the libraries contained in this release of SANE.
-
- The exception is that, if you link a SANE library with other files
- to produce an executable, this does not by itself cause the
- resulting executable to be covered by the GNU General Public
- License. Your use of that executable is in no way restricted on
- account of linking the SANE library code into it.
-
- This exception does not, however, invalidate any other reasons why
- the executable file might be covered by the GNU General Public
- License.
-
- If you submit changes to SANE to the maintainers to be included in
- a subsequent release, you agree by submitting the changes that
- those changes may be distributed with this exception intact.
-
- If you write modifications of your own for SANE, it is your choice
- whether to permit this exception to apply to your modifications.
- If you do not wish that, delete this exception notice.
-*/
-
-#ifndef BACKEND_GENESYS_CONV_H
-#define BACKEND_GENESYS_CONV_H
-
-#include "device.h"
-#include "sensor.h"
-#include "genesys.h"
-
-namespace genesys {
-
-void binarize_line(Genesys_Device* dev, std::uint8_t* src, std::uint8_t* dst, int width);
-
-void genesys_gray_lineart(Genesys_Device* dev,
- std::uint8_t* src_data, std::uint8_t* dst_data,
- std::size_t pixels, size_t lines, std::uint8_t threshold);
-
-void genesys_crop(Genesys_Scanner* s);
-
-void genesys_deskew(Genesys_Scanner *s, const Genesys_Sensor& sensor);
-
-void genesys_despeck(Genesys_Scanner* s);
-
-void genesys_derotate(Genesys_Scanner* s);
-
-} // namespace genesys
-
-#endif // BACKEND_GENESYS_CONV_H
diff --git a/backend/genesys/device.cpp b/backend/genesys/device.cpp
index ba035fd..95bede8 100644
--- a/backend/genesys/device.cpp
+++ b/backend/genesys/device.cpp
@@ -62,15 +62,24 @@ std::vector<unsigned> MethodResolutions::get_resolutions() const
return ret;
}
-const MethodResolutions& Genesys_Model::get_resolution_settings(ScanMethod method) const
+const MethodResolutions* Genesys_Model::get_resolution_settings_ptr(ScanMethod method) const
{
for (const auto& res_for_method : resolutions) {
for (auto res_method : res_for_method.methods) {
if (res_method == method) {
- return res_for_method;
+ return &res_for_method;
}
}
}
+ return nullptr;
+
+}
+const MethodResolutions& Genesys_Model::get_resolution_settings(ScanMethod method) const
+{
+ const auto* ptr = get_resolution_settings_ptr(method);
+ if (ptr)
+ return *ptr;
+
throw SaneException("Could not find resolution settings for method %d",
static_cast<unsigned>(method));
}
@@ -80,6 +89,12 @@ std::vector<unsigned> Genesys_Model::get_resolutions(ScanMethod method) const
return get_resolution_settings(method).get_resolutions();
}
+bool Genesys_Model::has_method(ScanMethod method) const
+{
+ return get_resolution_settings_ptr(method) != nullptr;
+}
+
+
Genesys_Device::~Genesys_Device()
{
clear();
@@ -87,10 +102,6 @@ Genesys_Device::~Genesys_Device()
void Genesys_Device::clear()
{
- read_buffer.clear();
- binarize_buffer.clear();
- local_buffer.clear();
-
calib_file.clear();
calibration_cache.clear();
@@ -99,9 +110,9 @@ void Genesys_Device::clear()
dark_average_data.clear();
}
-ImagePipelineNodeBytesSource& Genesys_Device::get_pipeline_source()
+ImagePipelineNodeBufferedCallableSource& Genesys_Device::get_pipeline_source()
{
- return static_cast<ImagePipelineNodeBytesSource&>(pipeline.front());
+ return static_cast<ImagePipelineNodeBufferedCallableSource&>(pipeline.front());
}
bool Genesys_Device::is_head_pos_known(ScanHeadId scan_head) const
@@ -124,10 +135,14 @@ unsigned Genesys_Device::head_pos(ScanHeadId scan_head) const
}
}
-void Genesys_Device::set_head_pos_unknown()
+void Genesys_Device::set_head_pos_unknown(ScanHeadId scan_head)
{
- is_head_pos_primary_known_ = false;
- is_head_pos_secondary_known_ = false;
+ if ((scan_head & ScanHeadId::PRIMARY) != ScanHeadId::NONE) {
+ is_head_pos_primary_known_ = false;
+ }
+ if ((scan_head & ScanHeadId::SECONDARY) != ScanHeadId::NONE) {
+ is_head_pos_secondary_known_ = false;
+ }
}
void Genesys_Device::set_head_pos_zero(ScanHeadId scan_head)
@@ -205,12 +220,15 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
<< " ignore_offsets: " << dev.ignore_offsets << '\n'
<< " model: (not printed)\n"
<< " reg: " << format_indent_braced_list(4, dev.reg) << '\n'
- << " calib_reg: " << format_indent_braced_list(4, dev.calib_reg) << '\n'
+ << " initial_regs: " << format_indent_braced_list(4, dev.initial_regs) << '\n'
<< " settings: " << format_indent_braced_list(4, dev.settings) << '\n'
<< " frontend: " << format_indent_braced_list(4, dev.frontend) << '\n'
- << " frontend_initial: " << format_indent_braced_list(4, dev.frontend_initial) << '\n'
- << " frontend_is_init: " << dev.frontend_is_init << '\n'
- << " gpo.regs: " << format_indent_braced_list(4, dev.gpo.regs) << '\n'
+ << " frontend_initial: " << format_indent_braced_list(4, dev.frontend_initial) << '\n';
+ if (!dev.memory_layout.regs.empty()) {
+ out << " memory_layout.regs: "
+ << format_indent_braced_list(4, dev.memory_layout.regs) << '\n';
+ }
+ out << " gpo.regs: " << format_indent_braced_list(4, dev.gpo.regs) << '\n'
<< " motor: " << format_indent_braced_list(4, dev.motor) << '\n'
<< " control[0..6]: " << std::hex
<< static_cast<unsigned>(dev.control[0]) << ' '
@@ -220,13 +238,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
<< static_cast<unsigned>(dev.control[4]) << ' '
<< static_cast<unsigned>(dev.control[5]) << '\n' << std::dec
<< " average_size: " << dev.average_size << '\n'
- << " calib_pixels: " << dev.calib_pixels << '\n'
- << " calib_lines: " << dev.calib_lines << '\n'
- << " calib_channels: " << dev.calib_channels << '\n'
- << " calib_resolution: " << dev.calib_resolution << '\n'
- << " calib_total_bytes_to_read: " << dev.calib_total_bytes_to_read << '\n'
<< " calib_session: " << format_indent_braced_list(4, dev.calib_session) << '\n'
- << " calib_pixels_offset: " << dev.calib_pixels_offset << '\n'
<< " gamma_override_tables[0].size(): " << dev.gamma_override_tables[0].size() << '\n'
<< " gamma_override_tables[1].size(): " << dev.gamma_override_tables[1].size() << '\n'
<< " gamma_override_tables[2].size(): " << dev.gamma_override_tables[2].size() << '\n'
@@ -242,31 +254,47 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
<< " read_active: " << dev.read_active << '\n'
<< " parking: " << dev.parking << '\n'
<< " document: " << dev.document << '\n'
- << " read_buffer.size(): " << dev.read_buffer.size() << '\n'
- << " binarize_buffer.size(): " << dev.binarize_buffer.size() << '\n'
- << " local_buffer.size(): " << dev.local_buffer.size() << '\n'
- << " oe_buffer.size(): " << dev.oe_buffer.size() << '\n'
<< " total_bytes_read: " << dev.total_bytes_read << '\n'
<< " total_bytes_to_read: " << dev.total_bytes_to_read << '\n'
<< " session: " << format_indent_braced_list(4, dev.session) << '\n'
- << " lineart_lut: (not printed)\n"
<< " calibration_cache: (not printed)\n"
<< " line_count: " << dev.line_count << '\n'
<< " segment_order: "
<< format_indent_braced_list(4, format_vector_unsigned(4, dev.segment_order)) << '\n'
- << " buffer_image: " << dev.buffer_image << '\n'
- << " img_buffer.size(): " << dev.img_buffer.size() << '\n'
<< '}';
return out;
}
+void apply_reg_settings_to_device_write_only(Genesys_Device& dev,
+ const GenesysRegisterSettingSet& regs)
+{
+ GenesysRegisterSettingSet backup;
+ for (const auto& reg : regs) {
+ dev.interface->write_register(reg.address, reg.value);
+ }
+}
+
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs)
{
+ apply_reg_settings_to_device_with_backup(dev, regs);
+}
+
+GenesysRegisterSettingSet
+ apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
+ const GenesysRegisterSettingSet& regs)
+{
+ GenesysRegisterSettingSet backup;
for (const auto& reg : regs) {
- uint8_t val = dev.interface->read_register(reg.address);
- val = (val & ~reg.mask) | (reg.value & reg.mask);
- dev.interface->write_register(reg.address, val);
+ std::uint8_t old_val = dev.interface->read_register(reg.address);
+ std::uint8_t new_val = (old_val & ~reg.mask) | (reg.value & reg.mask);
+ dev.interface->write_register(reg.address, new_val);
+
+ using SettingType = GenesysRegisterSettingSet::SettingType;
+ backup.push_back(SettingType{reg.address,
+ static_cast<std::uint8_t>(old_val & reg.mask),
+ reg.mask});
}
+ return backup;
}
} // namespace genesys
diff --git a/backend/genesys/device.h b/backend/genesys/device.h
index 6c744c9..ded6a48 100644
--- a/backend/genesys/device.h
+++ b/backend/genesys/device.h
@@ -46,7 +46,6 @@
#include "calibration.h"
#include "command_set.h"
-#include "buffer.h"
#include "enums.h"
#include "image_pipeline.h"
#include "motor.h"
@@ -55,6 +54,7 @@
#include "register.h"
#include "usb_device.h"
#include "scanner_interface.h"
+#include "utilities.h"
#include <vector>
namespace genesys {
@@ -77,22 +77,15 @@ struct Genesys_Gpo
GenesysRegisterSettingSet regs;
};
-/// Stores a SANE_Fixed value which is automatically converted from and to floating-point values
-class FixedFloat
+struct MemoryLayout
{
-public:
- FixedFloat() = default;
- FixedFloat(const FixedFloat&) = default;
- FixedFloat(double number) : value_{SANE_FIX(number)} {}
- FixedFloat& operator=(const FixedFloat&) = default;
- FixedFloat& operator=(double number) { value_ = SANE_FIX(number); return *this; }
+ // This is used on GL845, GL846, GL847 and GL124 which have special registers to define the
+ // memory layout
+ MemoryLayout() = default;
- operator double() const { return value(); }
+ ValueFilter<ModelId> models;
- double value() const { return SANE_UNFIX(value_); }
-
-private:
- SANE_Fixed value_ = 0;
+ GenesysRegisterSettingSet regs;
};
struct MethodResolutions
@@ -106,6 +99,16 @@ struct MethodResolutions
return *std::min_element(resolutions_x.begin(), resolutions_x.end());
}
+ unsigned get_nearest_resolution_x(unsigned resolution) const
+ {
+ return *std::min_element(resolutions_x.begin(), resolutions_x.end(),
+ [&](unsigned lhs, unsigned rhs)
+ {
+ return std::abs(static_cast<int>(lhs) - static_cast<int>(resolution)) <
+ std::abs(static_cast<int>(rhs) - static_cast<int>(resolution));
+ });
+ }
+
unsigned get_min_resolution_y() const
{
return *std::min_element(resolutions_y.begin(), resolutions_y.end());
@@ -143,51 +146,67 @@ struct Genesys_Model
// All offsets below are with respect to the sensor home position
// Start of scan area in mm
- FixedFloat x_offset = 0;
+ float x_offset = 0;
// Start of scan area in mm (Amount of feeding needed to get to the medium)
- FixedFloat y_offset = 0;
+ float y_offset = 0;
// Size of scan area in mm
- FixedFloat x_size = 0;
+ float x_size = 0;
// Size of scan area in mm
- FixedFloat y_size = 0;
+ float y_size = 0;
- // Start of white strip in mm
- FixedFloat y_offset_calib_white = 0;
+ // Start of white strip in mm for scanners that use separate dark and white shading calibration.
+ float y_offset_calib_white = 0;
+
+ // The size of the scan area that is used to acquire shading data in mm
+ float y_size_calib_mm = 0;
+
+ // Start of the black/white strip in mm for scanners that use unified dark and white shading
+ // calibration.
+ float y_offset_calib_dark_white_mm = 0;
+
+ // The size of the scan area that is used to acquire dark/white shading data in mm
+ float y_size_calib_dark_white_mm = 0;
+
+ // The width of the scan area that is used to acquire shading data
+ float x_size_calib_mm = 0;
// Start of black mark in mm
- FixedFloat x_offset_calib_black = 0;
+ float x_offset_calib_black = 0;
// Start of scan area in transparency mode in mm
- FixedFloat x_offset_ta = 0;
+ float x_offset_ta = 0;
// Start of scan area in transparency mode in mm
- FixedFloat y_offset_ta = 0;
+ float y_offset_ta = 0;
// Size of scan area in transparency mode in mm
- FixedFloat x_size_ta = 0;
+ float x_size_ta = 0;
// Size of scan area in transparency mode in mm
- FixedFloat y_size_ta = 0;
+ float y_size_ta = 0;
// The position of the sensor when it's aligned with the lamp for transparency scanning
- FixedFloat y_offset_sensor_to_ta = 0;
+ float y_offset_sensor_to_ta = 0;
// Start of white strip in transparency mode in mm
- FixedFloat y_offset_calib_white_ta = 0;
+ float y_offset_calib_white_ta = 0;
// Start of black strip in transparency mode in mm
- FixedFloat y_offset_calib_black_ta = 0;
+ float y_offset_calib_black_ta = 0;
+
+ // The size of the scan area that is used to acquire shading data in transparency mode in mm
+ float y_size_calib_ta_mm = 0;
// Size of scan area after paper sensor stop sensing document in mm
- FixedFloat post_scan = 0;
+ float post_scan = 0;
// Amount of feeding needed to eject document after finishing scanning in mm
- FixedFloat eject_feed = 0;
+ float eject_feed = 0;
- // Line-distance correction (in pixel at optical_ydpi) for CCD scanners
+ // Line-distance correction (in pixel at motor base_ydpi) for CCD scanners
SANE_Int ld_shift_r = 0;
SANE_Int ld_shift_g = 0;
SANE_Int ld_shift_b = 0;
@@ -210,22 +229,24 @@ struct Genesys_Model
// stepper motor type
MotorId motor_id = MotorId::UNKNOWN;
- // Which hacks are needed for this scanner?
- SANE_Word flags = 0;
+ // Which customizations are needed for this scanner?
+ ModelFlag flags = ModelFlag::NONE;
// Button flags, described existing buttons for the model
SANE_Word buttons = 0;
- // how many lines are used for shading calibration
- SANE_Int shading_lines = 0;
- // how many lines are used for shading calibration in TA mode
- SANE_Int shading_ta_lines = 0;
// how many lines are used to search start position
SANE_Int search_lines = 0;
+ // returns nullptr if method is not supported
+ const MethodResolutions* get_resolution_settings_ptr(ScanMethod method) const;
+
+ // throws if method is not supported
const MethodResolutions& get_resolution_settings(ScanMethod method) const;
std::vector<unsigned> get_resolutions(ScanMethod method) const;
+
+ bool has_method(ScanMethod method) const;
};
/**
@@ -243,8 +264,8 @@ struct Genesys_Device
// frees commonly used data
void clear();
- SANE_Word vendorId = 0; /**< USB vendor identifier */
- SANE_Word productId = 0; /**< USB product identifier */
+ std::uint16_t vendorId = 0; // USB vendor identifier
+ std::uint16_t productId = 0; // USB product identifier
// USB mode:
// 0: not set
@@ -261,42 +282,25 @@ struct Genesys_Device
// acquiring the positions of the black and white strips and the actual scan area
bool ignore_offsets = false;
- Genesys_Model *model = nullptr;
+ const Genesys_Model* model = nullptr;
// pointers to low level functions
std::unique_ptr<CommandSet> cmd_set;
Genesys_Register_Set reg;
- Genesys_Register_Set calib_reg;
+ Genesys_Register_Set initial_regs;
Genesys_Settings settings;
Genesys_Frontend frontend, frontend_initial;
-
- // whether the frontend is initialized. This is currently used just to preserve historical
- // behavior
- bool frontend_is_init = false;
-
Genesys_Gpo gpo;
+ MemoryLayout memory_layout;
Genesys_Motor motor;
std::uint8_t control[6] = {};
size_t average_size = 0;
- // number of pixels used during shading calibration
- size_t calib_pixels = 0;
- // number of lines used during shading calibration
- size_t calib_lines = 0;
- size_t calib_channels = 0;
- size_t calib_resolution = 0;
- // bytes to read from USB when calibrating. If 0, this is not set
- size_t calib_total_bytes_to_read = 0;
// the session that was configured for calibration
ScanSession calib_session;
- // certain scanners support much higher resolution when scanning transparency, but we can't
- // read whole width of the scanner as a single line at that resolution. Thus for stuff like
- // calibration we want to read only the possible calibration area.
- size_t calib_pixels_offset = 0;
-
// gamma overrides. If a respective array is not empty then it means that the gamma for that
// color is overridden.
std::vector<std::uint16_t> gamma_override_tables[3];
@@ -313,13 +317,6 @@ struct Genesys_Device
// for sheetfed scanner's, is TRUE when there is a document in the scanner
bool document = false;
- Genesys_Buffer read_buffer;
-
- // buffer for digital lineart from gray data
- Genesys_Buffer binarize_buffer;
- // local buffer for gray data during dynamix lineart
- Genesys_Buffer local_buffer;
-
// total bytes read sent to frontend
size_t total_bytes_read = 0;
// total bytes read to be sent to frontend
@@ -328,9 +325,6 @@ struct Genesys_Device
// contains computed data for the current setup
ScanSession session;
- // look up table used in dynamic rasterization
- unsigned char lineart_lut[256] = {};
-
Calibration calibration_cache;
// number of scan lines used during scan
@@ -339,28 +333,19 @@ struct Genesys_Device
// array describing the order of the sub-segments of the sensor
std::vector<unsigned> segment_order;
- // buffer to handle even/odd data
- Genesys_Buffer oe_buffer = {};
-
// stores information about how the input image should be processed
ImagePipelineStack pipeline;
// an buffer that allows reading from `pipeline` in chunks of any size
ImageBuffer pipeline_buffer;
- // when true the scanned picture is first buffered to allow software image enhancements
- bool buffer_image = false;
-
- // image buffer where the scanned picture is stored
- std::vector<std::uint8_t> img_buffer;
-
- ImagePipelineNodeBytesSource& get_pipeline_source();
+ ImagePipelineNodeBufferedCallableSource& get_pipeline_source();
std::unique_ptr<ScannerInterface> interface;
bool is_head_pos_known(ScanHeadId scan_head) const;
unsigned head_pos(ScanHeadId scan_head) const;
- void set_head_pos_unknown();
+ void set_head_pos_unknown(ScanHeadId scan_head);
void set_head_pos_zero(ScanHeadId scan_head);
void advance_head_pos_by_session(ScanHeadId scan_head);
void advance_head_pos_by_steps(ScanHeadId scan_head, Direction direction, unsigned steps);
@@ -382,6 +367,12 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev);
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs);
+void apply_reg_settings_to_device_write_only(Genesys_Device& dev,
+ const GenesysRegisterSettingSet& regs);
+GenesysRegisterSettingSet
+ apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
+ const GenesysRegisterSettingSet& regs);
+
} // namespace genesys
#endif
diff --git a/backend/genesys/enums.cpp b/backend/genesys/enums.cpp
index f515cfd..cd4be7d 100644
--- a/backend/genesys/enums.cpp
+++ b/backend/genesys/enums.cpp
@@ -109,6 +109,248 @@ std::ostream& operator<<(std::ostream& out, ColorFilter mode)
return out;
}
+std::ostream& operator<<(std::ostream& out, ModelId id)
+{
+ switch (id) {
+ case ModelId::UNKNOWN: out << "UNKNOWN"; break;
+ case ModelId::CANON_4400F: out << "CANON_4400F"; break;
+ case ModelId::CANON_5600F: out << "CANON_5600F"; break;
+ case ModelId::CANON_8400F: out << "CANON_8400F"; break;
+ case ModelId::CANON_8600F: out << "CANON_8600F"; break;
+ case ModelId::CANON_IMAGE_FORMULA_101: out << "CANON_IMAGE_FORMULA_101"; break;
+ case ModelId::CANON_LIDE_50: out << "CANON_LIDE_50"; break;
+ case ModelId::CANON_LIDE_60: out << "CANON_LIDE_60"; break;
+ case ModelId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
+ case ModelId::CANON_LIDE_90: out << "CANON_LIDE_90"; break;
+ case ModelId::CANON_LIDE_100: out << "CANON_LIDE_100"; break;
+ case ModelId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
+ case ModelId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
+ case ModelId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
+ case ModelId::CANON_LIDE_210: out << "CANON_LIDE_210"; break;
+ case ModelId::CANON_LIDE_220: out << "CANON_LIDE_220"; break;
+ case ModelId::CANON_LIDE_700F: out << "CANON_LIDE_700F"; break;
+ case ModelId::DCT_DOCKETPORT_487: out << "DCT_DOCKETPORT_487"; break;
+ case ModelId::HP_SCANJET_2300C: out << "HP_SCANJET_2300C"; break;
+ case ModelId::HP_SCANJET_2400C: out << "HP_SCANJET_2400C"; break;
+ case ModelId::HP_SCANJET_3670: out << "HP_SCANJET_3670"; break;
+ case ModelId::HP_SCANJET_4850C: out << "HP_SCANJET_4850C"; break;
+ case ModelId::HP_SCANJET_G4010: out << "HP_SCANJET_G4010"; break;
+ case ModelId::HP_SCANJET_G4050: out << "HP_SCANJET_G4050"; break;
+ case ModelId::HP_SCANJET_N6310: out << "HP_SCANJET_N6310"; break;
+ case ModelId::MEDION_MD5345: out << "MEDION_MD5345"; break;
+ case ModelId::PANASONIC_KV_SS080: out << "PANASONIC_KV_SS080"; break;
+ case ModelId::PENTAX_DSMOBILE_600: out << "PENTAX_DSMOBILE_600"; break;
+ case ModelId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
+ case ModelId::PLUSTEK_OPTICFILM_7200: out << "PLUSTEK_OPTICFILM_7200"; break;
+ case ModelId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
+ case ModelId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
+ case ModelId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
+ case ModelId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
+ case ModelId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
+ case ModelId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
+ case ModelId::PLUSTEK_OPTICPRO_ST12: out << "PLUSTEK_OPTICPRO_ST12"; break;
+ case ModelId::PLUSTEK_OPTICPRO_ST24: out << "PLUSTEK_OPTICPRO_ST24"; break;
+ case ModelId::SYSCAN_DOCKETPORT_465: out << "SYSCAN_DOCKETPORT_465"; break;
+ case ModelId::SYSCAN_DOCKETPORT_467: out << "SYSCAN_DOCKETPORT_467"; break;
+ case ModelId::SYSCAN_DOCKETPORT_485: out << "SYSCAN_DOCKETPORT_485"; break;
+ case ModelId::SYSCAN_DOCKETPORT_665: out << "SYSCAN_DOCKETPORT_665"; break;
+ case ModelId::SYSCAN_DOCKETPORT_685: out << "SYSCAN_DOCKETPORT_685"; break;
+ case ModelId::UMAX_ASTRA_4500: out << "UMAX_ASTRA_4500"; break;
+ case ModelId::VISIONEER_7100: out << "VISIONEER_7100"; break;
+ case ModelId::VISIONEER_ROADWARRIOR: out << "VISIONEER_ROADWARRIOR"; break;
+ case ModelId::VISIONEER_STROBE_XP100_REVISION3:
+ out << "VISIONEER_STROBE_XP100_REVISION3"; break;
+ case ModelId::VISIONEER_STROBE_XP200: out << "VISIONEER_STROBE_XP200"; break;
+ case ModelId::VISIONEER_STROBE_XP300: out << "VISIONEER_STROBE_XP300"; break;
+ case ModelId::XEROX_2400: out << "XEROX_2400"; break;
+ case ModelId::XEROX_TRAVELSCANNER_100: out << "XEROX_TRAVELSCANNER_100"; break;
+ default:
+ out << static_cast<unsigned>(id); break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, SensorId id)
+{
+ switch (id) {
+ case SensorId::CCD_5345: out << "CCD_5345"; break;
+ case SensorId::CCD_CANON_4400F: out << "CCD_CANON_4400F"; break;
+ case SensorId::CCD_CANON_5600F: out << "CCD_CANON_5600F"; break;
+ case SensorId::CCD_CANON_8400F: out << "CCD_CANON_8400F"; break;
+ case SensorId::CCD_CANON_8600F: out << "CCD_CANON_8600F"; break;
+ case SensorId::CCD_DP665: out << "CCD_DP665"; break;
+ case SensorId::CCD_DP685: out << "CCD_DP685"; break;
+ case SensorId::CCD_DSMOBILE600: out << "CCD_DSMOBILE600"; break;
+ case SensorId::CCD_DOCKETPORT_487: out << "CCD_DOCKETPORT_487"; break;
+ case SensorId::CCD_G4050: out << "CCD_G4050"; break;
+ case SensorId::CCD_HP2300: out << "CCD_HP2300"; break;
+ case SensorId::CCD_HP2400: out << "CCD_HP2400"; break;
+ case SensorId::CCD_HP3670: out << "CCD_HP3670"; break;
+ case SensorId::CCD_HP_N6310: out << "CCD_HP_N6310"; break;
+ case SensorId::CCD_HP_4850C: out << "CCD_HP_4850C"; break;
+ case SensorId::CCD_IMG101: out << "CCD_IMG101"; break;
+ case SensorId::CCD_KVSS080: out << "CCD_KVSS080"; break;
+ case SensorId::CCD_PLUSTEK_OPTICBOOK_3800: out << "CCD_PLUSTEK_OPTICBOOK_3800"; break;
+ case SensorId::CCD_PLUSTEK_OPTICFILM_7200: out << "CCD_PLUSTEK_OPTICFILM_7200"; break;
+ case SensorId::CCD_PLUSTEK_OPTICFILM_7200I: out << "CCD_PLUSTEK_OPTICFILM_7200I"; break;
+ case SensorId::CCD_PLUSTEK_OPTICFILM_7300: out << "CCD_PLUSTEK_OPTICFILM_7300"; break;
+ case SensorId::CCD_PLUSTEK_OPTICFILM_7400: out << "CCD_PLUSTEK_OPTICFILM_7400"; break;
+ case SensorId::CCD_PLUSTEK_OPTICFILM_7500I: out << "CCD_PLUSTEK_OPTICFILM_7500I"; break;
+ case SensorId::CCD_PLUSTEK_OPTICFILM_8200I: out << "CCD_PLUSTEK_OPTICFILM_8200I"; break;
+ case SensorId::CCD_PLUSTEK_OPTICPRO_3600: out << "CCD_PLUSTEK_OPTICPRO_3600"; break;
+ case SensorId::CCD_ROADWARRIOR: out << "CCD_ROADWARRIOR"; break;
+ case SensorId::CCD_ST12: out << "CCD_ST12"; break;
+ case SensorId::CCD_ST24: out << "CCD_ST24"; break;
+ case SensorId::CCD_UMAX: out << "CCD_UMAX"; break;
+ case SensorId::CCD_XP300: out << "CCD_XP300"; break;
+ case SensorId::CIS_CANON_LIDE_35: out << "CIS_CANON_LIDE_35"; break;
+ case SensorId::CIS_CANON_LIDE_60: out << "CIS_CANON_LIDE_60"; break;
+ case SensorId::CIS_CANON_LIDE_80: out << "CIS_CANON_LIDE_80"; break;
+ case SensorId::CIS_CANON_LIDE_90: out << "CIS_CANON_LIDE_90"; break;
+ case SensorId::CIS_CANON_LIDE_100: out << "CIS_CANON_LIDE_100"; break;
+ case SensorId::CIS_CANON_LIDE_110: out << "CIS_CANON_LIDE_110"; break;
+ case SensorId::CIS_CANON_LIDE_120: out << "CIS_CANON_LIDE_120"; break;
+ case SensorId::CIS_CANON_LIDE_200: out << "CIS_CANON_LIDE_200"; break;
+ case SensorId::CIS_CANON_LIDE_210: out << "CIS_CANON_LIDE_210"; break;
+ case SensorId::CIS_CANON_LIDE_220: out << "CIS_CANON_LIDE_220"; break;
+ case SensorId::CIS_CANON_LIDE_700F: out << "CIS_CANON_LIDE_700F"; break;
+ case SensorId::CIS_XP200: out << "CIS_XP200"; break;
+ default:
+ out << static_cast<unsigned>(id); break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, AdcId id)
+{
+ switch (id) {
+ case AdcId::UNKNOWN: out << "UNKNOWN"; break;
+ case AdcId::AD_XP200: out << "AD_XP200"; break;
+ case AdcId::CANON_LIDE_35: out << "CANON_LIDE_35"; break;
+ case AdcId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
+ case AdcId::CANON_LIDE_90: out << "CANON_LIDE_90"; break;
+ case AdcId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
+ case AdcId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
+ case AdcId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
+ case AdcId::CANON_LIDE_700F: out << "CANON_LIDE_700F"; break;
+ case AdcId::CANON_4400F: out << "CANON_4400F"; break;
+ case AdcId::CANON_5600F: out << "CANON_5600F"; break;
+ case AdcId::CANON_8400F: out << "CANON_8400F"; break;
+ case AdcId::CANON_8600F: out << "CANON_8600F"; break;
+ case AdcId::G4050: out << "G4050"; break;
+ case AdcId::IMG101: out << "IMG101"; break;
+ case AdcId::KVSS080: out << "KVSS080"; break;
+ case AdcId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
+ case AdcId::PLUSTEK_OPTICFILM_7200: out << "PLUSTEK_OPTICFILM_7200"; break;
+ case AdcId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
+ case AdcId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
+ case AdcId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
+ case AdcId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
+ case AdcId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
+ case AdcId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
+ case AdcId::WOLFSON_5345: out << "WOLFSON_5345"; break;
+ case AdcId::WOLFSON_DSM600: out << "WOLFSON_DSM600"; break;
+ case AdcId::WOLFSON_HP2300: out << "WOLFSON_HP2300"; break;
+ case AdcId::WOLFSON_HP2400: out << "WOLFSON_HP2400"; break;
+ case AdcId::WOLFSON_HP3670: out << "WOLFSON_HP3670"; break;
+ case AdcId::WOLFSON_ST12: out << "WOLFSON_ST12"; break;
+ case AdcId::WOLFSON_ST24: out << "WOLFSON_ST24"; break;
+ case AdcId::WOLFSON_UMAX: out << "WOLFSON_UMAX"; break;
+ case AdcId::WOLFSON_XP300: out << "WOLFSON_XP300"; break;
+ default:
+ out << static_cast<unsigned>(id); break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, GpioId id)
+{
+ switch (id) {
+ case GpioId::UNKNOWN: out << "UNKNOWN"; break;
+ case GpioId::CANON_LIDE_35: out << "CANON_LIDE_35"; break;
+ case GpioId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
+ case GpioId::CANON_LIDE_90: out << "CANON_LIDE_90"; break;
+ case GpioId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
+ case GpioId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
+ case GpioId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
+ case GpioId::CANON_LIDE_210: out << "CANON_LIDE_210"; break;
+ case GpioId::CANON_LIDE_700F: out << "CANON_LIDE_700F"; break;
+ case GpioId::CANON_4400F: out << "CANON_4400F"; break;
+ case GpioId::CANON_5600F: out << "CANON_5600F"; break;
+ case GpioId::CANON_8400F: out << "CANON_8400F"; break;
+ case GpioId::CANON_8600F: out << "CANON_8600F"; break;
+ case GpioId::DP665: out << "DP665"; break;
+ case GpioId::DP685: out << "DP685"; break;
+ case GpioId::G4050: out << "G4050"; break;
+ case GpioId::HP2300: out << "HP2300"; break;
+ case GpioId::HP2400: out << "HP2400"; break;
+ case GpioId::HP3670: out << "HP3670"; break;
+ case GpioId::HP_N6310: out << "HP_N6310"; break;
+ case GpioId::IMG101: out << "IMG101"; break;
+ case GpioId::KVSS080: out << "KVSS080"; break;
+ case GpioId::MD_5345: out << "MD_5345"; break;
+ case GpioId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
+ case GpioId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
+ case GpioId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
+ case GpioId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
+ case GpioId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
+ case GpioId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
+ case GpioId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
+ case GpioId::ST12: out << "ST12"; break;
+ case GpioId::ST24: out << "ST24"; break;
+ case GpioId::UMAX: out << "UMAX"; break;
+ case GpioId::XP200: out << "XP200"; break;
+ case GpioId::XP300: out << "XP300"; break;
+ default: out << static_cast<unsigned>(id); break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, MotorId id)
+{
+ switch (id) {
+ case MotorId::UNKNOWN: out << "UNKNOWN"; break;
+ case MotorId::CANON_LIDE_90: out << "CANON_LIDE_90"; break;
+ case MotorId::CANON_LIDE_100: out << "CANON_LIDE_100"; break;
+ case MotorId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
+ case MotorId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
+ case MotorId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
+ case MotorId::CANON_LIDE_210: out << "CANON_LIDE_210"; break;
+ case MotorId::CANON_LIDE_35: out << "CANON_LIDE_35"; break;
+ case MotorId::CANON_LIDE_60: out << "CANON_LIDE_60"; break;
+ case MotorId::CANON_LIDE_700: out << "CANON_LIDE_700"; break;
+ case MotorId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
+ case MotorId::CANON_4400F: out << "CANON_4400F"; break;
+ case MotorId::CANON_5600F: out << "CANON_5600F"; break;
+ case MotorId::CANON_8400F: out << "CANON_8400F"; break;
+ case MotorId::CANON_8600F: out << "CANON_8600F"; break;
+ case MotorId::DP665: out << "DP665"; break;
+ case MotorId::DSMOBILE_600: out << "DSMOBILE_600"; break;
+ case MotorId::G4050: out << "G4050"; break;
+ case MotorId::HP2300: out << "HP2300"; break;
+ case MotorId::HP2400: out << "HP2400"; break;
+ case MotorId::HP3670: out << "HP3670"; break;
+ case MotorId::IMG101: out << "IMG101"; break;
+ case MotorId::KVSS080: out << "KVSS080"; break;
+ case MotorId::MD_5345: out << "MD_5345"; break;
+ case MotorId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
+ case MotorId::PLUSTEK_OPTICFILM_7200: out << "PLUSTEK_OPTICFILM_7200"; break;
+ case MotorId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
+ case MotorId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
+ case MotorId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
+ case MotorId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
+ case MotorId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
+ case MotorId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
+ case MotorId::ROADWARRIOR: out << "ROADWARRIOR"; break;
+ case MotorId::ST24: out << "ST24"; break;
+ case MotorId::UMAX: out << "UMAX"; break;
+ case MotorId::XP200: out << "XP200"; break;
+ case MotorId::XP300: out << "XP300"; break;
+ default: out << static_cast<unsigned>(id); break;
+ }
+ return out;
+}
+
std::ostream& operator<<(std::ostream& out, StepType type)
{
switch (type) {
diff --git a/backend/genesys/enums.h b/backend/genesys/enums.h
index 810c4ca..0e16ba4 100644
--- a/backend/genesys/enums.h
+++ b/backend/genesys/enums.h
@@ -182,6 +182,7 @@ enum class ModelId : unsigned
CANON_LIDE_50,
CANON_LIDE_60,
CANON_LIDE_80,
+ CANON_LIDE_90,
CANON_LIDE_100,
CANON_LIDE_110,
CANON_LIDE_120,
@@ -201,9 +202,12 @@ enum class ModelId : unsigned
PANASONIC_KV_SS080,
PENTAX_DSMOBILE_600,
PLUSTEK_OPTICBOOK_3800,
+ PLUSTEK_OPTICFILM_7200,
PLUSTEK_OPTICFILM_7200I,
PLUSTEK_OPTICFILM_7300,
+ PLUSTEK_OPTICFILM_7400,
PLUSTEK_OPTICFILM_7500I,
+ PLUSTEK_OPTICFILM_8200I,
PLUSTEK_OPTICPRO_3600,
PLUSTEK_OPTICPRO_ST12,
PLUSTEK_OPTICPRO_ST24,
@@ -222,16 +226,33 @@ enum class ModelId : unsigned
XEROX_TRAVELSCANNER_100,
};
+inline void serialize(std::istream& str, ModelId& x)
+{
+ unsigned value;
+ serialize(str, value);
+ x = static_cast<ModelId>(value);
+}
+
+inline void serialize(std::ostream& str, ModelId& x)
+{
+ unsigned value = static_cast<unsigned>(x);
+ serialize(str, value);
+}
+
+std::ostream& operator<<(std::ostream& out, ModelId id);
+
enum class SensorId : unsigned
{
UNKNOWN = 0,
CCD_5345,
CCD_CANON_4400F,
+ CCD_CANON_5600F,
CCD_CANON_8400F,
CCD_CANON_8600F,
CCD_DP665,
CCD_DP685,
CCD_DSMOBILE600,
+ CCD_DOCKETPORT_487,
CCD_G4050,
CCD_HP2300,
CCD_HP2400,
@@ -241,9 +262,12 @@ enum class SensorId : unsigned
CCD_IMG101,
CCD_KVSS080,
CCD_PLUSTEK_OPTICBOOK_3800,
+ CCD_PLUSTEK_OPTICFILM_7200,
CCD_PLUSTEK_OPTICFILM_7200I,
CCD_PLUSTEK_OPTICFILM_7300,
+ CCD_PLUSTEK_OPTICFILM_7400,
CCD_PLUSTEK_OPTICFILM_7500I,
+ CCD_PLUSTEK_OPTICFILM_8200I,
CCD_PLUSTEK_OPTICPRO_3600,
CCD_ROADWARRIOR,
CCD_ST12, // SONY ILX548: 5340 Pixel ???
@@ -251,7 +275,9 @@ enum class SensorId : unsigned
CCD_UMAX,
CCD_XP300,
CIS_CANON_LIDE_35,
+ CIS_CANON_LIDE_60,
CIS_CANON_LIDE_80,
+ CIS_CANON_LIDE_90,
CIS_CANON_LIDE_100,
CIS_CANON_LIDE_110,
CIS_CANON_LIDE_120,
@@ -275,6 +301,8 @@ inline void serialize(std::ostream& str, SensorId& x)
serialize(str, value);
}
+std::ostream& operator<<(std::ostream& out, SensorId id);
+
enum class AdcId : unsigned
{
@@ -282,20 +310,25 @@ enum class AdcId : unsigned
AD_XP200,
CANON_LIDE_35,
CANON_LIDE_80,
+ CANON_LIDE_90,
CANON_LIDE_110,
CANON_LIDE_120,
CANON_LIDE_200,
CANON_LIDE_700F,
CANON_4400F,
+ CANON_5600F,
CANON_8400F,
CANON_8600F,
G4050,
IMG101,
KVSS080,
PLUSTEK_OPTICBOOK_3800,
+ PLUSTEK_OPTICFILM_7200,
PLUSTEK_OPTICFILM_7200I,
PLUSTEK_OPTICFILM_7300,
+ PLUSTEK_OPTICFILM_7400,
PLUSTEK_OPTICFILM_7500I,
+ PLUSTEK_OPTICFILM_8200I,
PLUSTEK_OPTICPRO_3600,
WOLFSON_5345,
WOLFSON_DSM600,
@@ -321,17 +354,21 @@ inline void serialize(std::ostream& str, AdcId& x)
serialize(str, value);
}
+std::ostream& operator<<(std::ostream& out, AdcId id);
+
enum class GpioId : unsigned
{
UNKNOWN = 0,
CANON_LIDE_35,
CANON_LIDE_80,
+ CANON_LIDE_90,
CANON_LIDE_110,
CANON_LIDE_120,
CANON_LIDE_200,
CANON_LIDE_210,
CANON_LIDE_700F,
CANON_4400F,
+ CANON_5600F,
CANON_8400F,
CANON_8600F,
DP665,
@@ -345,9 +382,12 @@ enum class GpioId : unsigned
KVSS080,
MD_5345,
PLUSTEK_OPTICBOOK_3800,
+ PLUSTEK_OPTICFILM_7200,
PLUSTEK_OPTICFILM_7200I,
PLUSTEK_OPTICFILM_7300,
+ PLUSTEK_OPTICFILM_7400,
PLUSTEK_OPTICFILM_7500I,
+ PLUSTEK_OPTICFILM_8200I,
PLUSTEK_OPTICPRO_3600,
ST12,
ST24,
@@ -356,6 +396,8 @@ enum class GpioId : unsigned
XP300,
};
+std::ostream& operator<<(std::ostream& out, GpioId id);
+
enum class MotorId : unsigned
{
UNKNOWN = 0,
@@ -365,9 +407,12 @@ enum class MotorId : unsigned
CANON_LIDE_200,
CANON_LIDE_210,
CANON_LIDE_35,
+ CANON_LIDE_60,
CANON_LIDE_700,
CANON_LIDE_80,
+ CANON_LIDE_90,
CANON_4400F,
+ CANON_5600F,
CANON_8400F,
CANON_8600F,
DP665,
@@ -380,9 +425,12 @@ enum class MotorId : unsigned
KVSS080,
MD_5345,
PLUSTEK_OPTICBOOK_3800,
+ PLUSTEK_OPTICFILM_7200,
PLUSTEK_OPTICFILM_7200I,
PLUSTEK_OPTICFILM_7300,
+ PLUSTEK_OPTICFILM_7400,
PLUSTEK_OPTICFILM_7500I,
+ PLUSTEK_OPTICFILM_8200I,
PLUSTEK_OPTICPRO_3600,
ROADWARRIOR,
ST24,
@@ -391,6 +439,8 @@ enum class MotorId : unsigned
XP300,
};
+std::ostream& operator<<(std::ostream& out, MotorId id);
+
enum class StepType : unsigned
{
FULL = 0,
@@ -423,6 +473,7 @@ enum class AsicType : unsigned
UNKNOWN = 0,
GL646,
GL841,
+ GL842,
GL843,
GL845,
GL846,
@@ -431,6 +482,92 @@ enum class AsicType : unsigned
};
+enum class ModelFlag : unsigned
+{
+ // no flags
+ NONE = 0,
+
+ // scanner is not tested, print a warning as it's likely it won't work
+ UNTESTED = 1 << 0,
+
+ // use 14-bit gamma table instead of 12-bit
+ GAMMA_14BIT = 1 << 1,
+
+ // perform lamp warmup
+ WARMUP = 1 << 4,
+
+ // whether to disable offset and gain calibration
+ DISABLE_ADC_CALIBRATION = 1 << 5,
+
+ // whether to disable exposure calibration (this currently is only done on CIS
+ // scanners)
+ DISABLE_EXPOSURE_CALIBRATION = 1 << 6,
+
+ // whether to disable shading calibration completely
+ DISABLE_SHADING_CALIBRATION = 1 << 7,
+
+ // do dark calibration
+ DARK_CALIBRATION = 1 << 8,
+
+ // host-side calibration uses a complete scan
+ HOST_SIDE_CALIBRATION_COMPLETE_SCAN = 1 << 9,
+
+ // whether scanner must wait for the head while parking
+ MUST_WAIT = 1 << 10,
+
+ // use zeroes for dark calibration
+ USE_CONSTANT_FOR_DARK_CALIBRATION = 1 << 11,
+
+ // do dark and white calibration in one run
+ DARK_WHITE_CALIBRATION = 1 << 12,
+
+ // allow custom gamma tables
+ CUSTOM_GAMMA = 1 << 13,
+
+ // disable fast feeding mode on this scanner
+ DISABLE_FAST_FEEDING = 1 << 14,
+
+ // the scanner uses multi-segment sensors that must be handled during calibration
+ SIS_SENSOR = 1 << 16,
+
+ // the head must be reparked between shading scans
+ SHADING_REPARK = 1 << 18,
+
+ // the scanner outputs inverted pixel data
+ INVERT_PIXEL_DATA = 1 << 19,
+
+ // the scanner outputs 16-bit data that is byte-inverted
+ SWAP_16BIT_DATA = 1 << 20,
+
+ // the scanner has transparency, but it's implemented using only one motor
+ UTA_NO_SECONDARY_MOTOR = 1 << 21,
+
+ // the scanner has transparency, but it's implemented using only one lamp
+ TA_NO_SECONDARY_LAMP = 1 << 22,
+};
+
+inline ModelFlag operator|(ModelFlag left, ModelFlag right)
+{
+ return static_cast<ModelFlag>(static_cast<unsigned>(left) | static_cast<unsigned>(right));
+}
+
+inline ModelFlag& operator|=(ModelFlag& left, ModelFlag right)
+{
+ left = left | right;
+ return left;
+}
+
+inline ModelFlag operator&(ModelFlag left, ModelFlag right)
+{
+ return static_cast<ModelFlag>(static_cast<unsigned>(left) & static_cast<unsigned>(right));
+}
+
+inline bool has_flag(ModelFlag flags, ModelFlag which)
+{
+ return (flags & which) == which;
+}
+
+
enum class ScanFlag : unsigned
{
NONE = 0,
@@ -438,14 +575,24 @@ enum class ScanFlag : unsigned
DISABLE_SHADING = 1 << 1,
DISABLE_GAMMA = 1 << 2,
DISABLE_BUFFER_FULL_MOVE = 1 << 3,
- IGNORE_LINE_DISTANCE = 1 << 4,
- DISABLE_LAMP = 1 << 5,
- CALIBRATION = 1 << 6,
- FEEDING = 1 << 7,
- USE_XPA = 1 << 8,
- ENABLE_LEDADD = 1 << 9,
- USE_XCORRECTION = 1 << 10,
- REVERSE = 1 << 11,
+
+ // if this flag is set the sensor will always be handled ignoring staggering of multiple
+ // sensors to achieve high resolution.
+ IGNORE_STAGGER_OFFSET = 1 << 4,
+
+ // if this flag is set the sensor will always be handled as if the components that scan
+ // different colors are at the same position.
+ IGNORE_COLOR_OFFSET = 1 << 5,
+
+ DISABLE_LAMP = 1 << 6,
+ CALIBRATION = 1 << 7,
+ FEEDING = 1 << 8,
+ USE_XPA = 1 << 9,
+ ENABLE_LEDADD = 1 << 10,
+ REVERSE = 1 << 12,
+
+ // the scanner should return head to home position automatically after scan.
+ AUTO_GO_HOME = 1 << 13,
};
inline ScanFlag operator|(ScanFlag left, ScanFlag right)
@@ -485,45 +632,18 @@ inline void serialize(std::ostream& str, ScanFlag& x)
std::ostream& operator<<(std::ostream& out, ScanFlag flags);
-
-enum class MotorFlag : unsigned
-{
- NONE = 0,
- AUTO_GO_HOME = 1 << 0,
- DISABLE_BUFFER_FULL_MOVE = 1 << 2,
- FEED = 1 << 3,
- USE_XPA = 1 << 4,
- REVERSE = 1 << 5,
-};
-
-inline MotorFlag operator|(MotorFlag left, MotorFlag right)
-{
- return static_cast<MotorFlag>(static_cast<unsigned>(left) | static_cast<unsigned>(right));
-}
-
-inline MotorFlag& operator|=(MotorFlag& left, MotorFlag right)
-{
- left = left | right;
- return left;
-}
-
-inline MotorFlag operator&(MotorFlag left, MotorFlag right)
-{
- return static_cast<MotorFlag>(static_cast<unsigned>(left) & static_cast<unsigned>(right));
-}
-
-inline bool has_flag(MotorFlag flags, MotorFlag which)
-{
- return (flags & which) == which;
-}
-
-
enum class Direction : unsigned
{
FORWARD = 0,
BACKWARD = 1
};
+enum class MotorMode : unsigned
+{
+ PRIMARY = 0,
+ PRIMARY_AND_SECONDARY,
+ SECONDARY,
+};
} // namespace genesys
diff --git a/backend/genesys/error.cpp b/backend/genesys/error.cpp
index 6c921c1..46d79c9 100644
--- a/backend/genesys/error.cpp
+++ b/backend/genesys/error.cpp
@@ -45,6 +45,7 @@
#include "error.h"
#include <cstdarg>
+#include <cstdlib>
namespace genesys {
@@ -212,4 +213,32 @@ void DebugMessageHelper::vlog(unsigned level, const char* format, ...)
DBG(level, "%s: %s\n", func_, msg.c_str());
}
+enum class LogImageDataStatus
+{
+ NOT_SET,
+ ENABLED,
+ DISABLED
+};
+
+static LogImageDataStatus s_log_image_data_setting = LogImageDataStatus::NOT_SET;
+
+LogImageDataStatus dbg_read_log_image_data_setting()
+{
+ auto* setting = std::getenv("SANE_DEBUG_GENESYS_IMAGE");
+ if (!setting)
+ return LogImageDataStatus::DISABLED;
+ auto setting_int = std::strtol(setting, nullptr, 10);
+ if (setting_int == 0)
+ return LogImageDataStatus::DISABLED;
+ return LogImageDataStatus::ENABLED;
+}
+
+bool dbg_log_image_data()
+{
+ if (s_log_image_data_setting == LogImageDataStatus::NOT_SET) {
+ s_log_image_data_setting = dbg_read_log_image_data_setting();
+ }
+ return s_log_image_data_setting == LogImageDataStatus::ENABLED;
+}
+
} // namespace genesys
diff --git a/backend/genesys/error.h b/backend/genesys/error.h
index 5aba8cf..26235dd 100644
--- a/backend/genesys/error.h
+++ b/backend/genesys/error.h
@@ -137,7 +137,6 @@ private:
unsigned num_exceptions_on_enter_ = 0;
};
-
#if defined(__GNUC__) || defined(__clang__)
#define GENESYS_CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(__FUNCSIG__)
@@ -149,6 +148,8 @@ private:
#define DBG_HELPER(var) DebugMessageHelper var(GENESYS_CURRENT_FUNCTION)
#define DBG_HELPER_ARGS(var, ...) DebugMessageHelper var(GENESYS_CURRENT_FUNCTION, __VA_ARGS__)
+bool dbg_log_image_data();
+
template<class F>
SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function)
{
@@ -172,6 +173,27 @@ SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function)
}
template<class F>
+SANE_Status wrap_exceptions_to_status_code_return(const char* func, F&& function)
+{
+ try {
+ return function();
+ } catch (const SaneException& exc) {
+ DBG(DBG_error, "%s: got error: %s\n", func, exc.what());
+ return exc.status();
+ } catch (const std::bad_alloc& exc) {
+ (void) exc;
+ DBG(DBG_error, "%s: failed to allocate memory\n", func);
+ return SANE_STATUS_NO_MEM;
+ } catch (const std::exception& exc) {
+ DBG(DBG_error, "%s: got uncaught exception: %s\n", func, exc.what());
+ return SANE_STATUS_INVAL;
+ } catch (...) {
+ DBG(DBG_error, "%s: got unknown uncaught exception\n", func);
+ return SANE_STATUS_INVAL;
+ }
+}
+
+template<class F>
void catch_all_exceptions(const char* func, F&& function)
{
try {
diff --git a/backend/genesys/fwd.h b/backend/genesys/fwd.h
index 2d55f98..ea335f7 100644
--- a/backend/genesys/fwd.h
+++ b/backend/genesys/fwd.h
@@ -46,9 +46,6 @@
namespace genesys {
-// buffer.h
-struct Genesys_Buffer;
-
// calibration.h
struct Genesys_Calibration_Cache;
@@ -56,7 +53,6 @@ struct Genesys_Calibration_Cache;
class CommandSet;
// device.h
-class FixedFloat;
struct Genesys_Gpo;
struct MethodResolutions;
struct Genesys_Model;
@@ -75,8 +71,6 @@ class Image;
// image_buffer.h
class ImageBuffer;
-class FakeBufferModel;
-class ImageBufferGenesysUsb;
// image_pipeline.h
class ImagePipelineNode;
@@ -88,12 +82,12 @@ struct Pixel;
struct RawPixel;
// low.h
-struct Genesys_USB_Device_Entry;
-struct Motor_Profile;
+struct UsbDeviceEntry;
// motor.h
struct Genesys_Motor;
struct MotorSlope;
+struct MotorProfile;
struct MotorSlopeTable;
// register.h
@@ -113,7 +107,6 @@ class ScannerInterfaceUsb;
class TestScannerInterface;
// sensor.h
-class ResolutionFilter;
struct GenesysFrontendLayout;
struct Genesys_Frontend;
struct SensorExposure;
@@ -124,6 +117,10 @@ struct Genesys_Settings;
struct SetupParams;
struct ScanSession;
+// value_filter.h
+template<class T> class ValueFilter;
+template<class T> class ValueFilterAny;
+
// test_usb_device.h
class TestUsbDevice;
diff --git a/backend/genesys/genesys.cpp b/backend/genesys/genesys.cpp
index 7c25168..9d80cfa 100644
--- a/backend/genesys/genesys.cpp
+++ b/backend/genesys/genesys.cpp
@@ -61,9 +61,9 @@
#define DEBUG_NOT_STATIC
#include "genesys.h"
-#include "conv.h"
#include "gl124_registers.h"
#include "gl841_registers.h"
+#include "gl842_registers.h"
#include "gl843_registers.h"
#include "gl846_registers.h"
#include "gl847_registers.h"
@@ -73,7 +73,6 @@
#include "test_scanner_interface.h"
#include "test_settings.h"
#include "../include/sane/sanei_config.h"
-#include "../include/sane/sanei_magic.h"
#include <array>
#include <cmath>
@@ -111,8 +110,8 @@ namespace {
static SANE_String_Const mode_list[] = {
SANE_VALUE_SCAN_MODE_COLOR,
SANE_VALUE_SCAN_MODE_GRAY,
- /* SANE_TITLE_HALFTONE, currently unused */
- SANE_VALUE_SCAN_MODE_LINEART,
+ // SANE_TITLE_HALFTONE, not used
+ // SANE_VALUE_SCAN_MODE_LINEART, not used
nullptr
};
@@ -131,12 +130,6 @@ static SANE_String_Const cis_color_filter_list[] = {
nullptr
};
-static SANE_Range swdespeck_range = {
- 1,
- 9,
- 1
-};
-
static SANE_Range time_range = {
0, /* minimum */
60, /* maximum */
@@ -162,15 +155,9 @@ static const SANE_Range u16_range = {
};
static const SANE_Range percentage_range = {
- SANE_FIX (0), /* minimum */
- SANE_FIX (100), /* maximum */
- SANE_FIX (1) /* quantization */
-};
-
-static const SANE_Range threshold_curve_range = {
- 0, /* minimum */
- 127, /* maximum */
- 1 /* quantization */
+ float_to_fixed(0), // minimum
+ float_to_fixed(100), // maximum
+ float_to_fixed(1) // quantization
};
/**
@@ -191,7 +178,7 @@ static const SANE_Range expiration_range = {
1 /* quantization */
};
-const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev)
+const Genesys_Sensor& sanei_genesys_find_sensor_any(const Genesys_Device* dev)
{
DBG_HELPER(dbg);
for (const auto& sensor : *s_sensors) {
@@ -202,7 +189,7 @@ const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev)
throw std::runtime_error("Given device does not have sensor defined");
}
-Genesys_Sensor* find_sensor_impl(Genesys_Device* dev, unsigned dpi, unsigned channels,
+Genesys_Sensor* find_sensor_impl(const Genesys_Device* dev, unsigned dpi, unsigned channels,
ScanMethod scan_method)
{
DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels,
@@ -217,7 +204,7 @@ Genesys_Sensor* find_sensor_impl(Genesys_Device* dev, unsigned dpi, unsigned cha
return nullptr;
}
-bool sanei_genesys_has_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels,
+bool sanei_genesys_has_sensor(const Genesys_Device* dev, unsigned dpi, unsigned channels,
ScanMethod scan_method)
{
DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels,
@@ -225,8 +212,8 @@ bool sanei_genesys_has_sensor(Genesys_Device* dev, unsigned dpi, unsigned channe
return find_sensor_impl(dev, dpi, channels, scan_method) != nullptr;
}
-const Genesys_Sensor& sanei_genesys_find_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels,
- ScanMethod scan_method)
+const Genesys_Sensor& sanei_genesys_find_sensor(const Genesys_Device* dev, unsigned dpi,
+ unsigned channels, ScanMethod scan_method)
{
DBG_HELPER_ARGS(dbg, "dpi: %d, channels: %d, scan_method: %d", dpi, channels,
static_cast<unsigned>(scan_method));
@@ -250,12 +237,14 @@ Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigne
std::vector<std::reference_wrapper<const Genesys_Sensor>>
- sanei_genesys_find_sensors_all(Genesys_Device* dev, ScanMethod scan_method)
+ sanei_genesys_find_sensors_all(const Genesys_Device* dev, ScanMethod scan_method)
{
DBG_HELPER_ARGS(dbg, "scan_method: %d", static_cast<unsigned>(scan_method));
std::vector<std::reference_wrapper<const Genesys_Sensor>> ret;
- for (const Genesys_Sensor& sensor : sanei_genesys_find_sensors_all_for_write(dev, scan_method)) {
- ret.push_back(sensor);
+ for (auto& sensor : *s_sensors) {
+ if (dev->model->sensor_id == sensor.sensor_id && sensor.method == scan_method) {
+ ret.push_back(sensor);
+ }
}
return ret;
}
@@ -308,6 +297,24 @@ void sanei_genesys_init_structs (Genesys_Device * dev)
}
}
+ if (dev->model->asic_type == AsicType::GL845 ||
+ dev->model->asic_type == AsicType::GL846 ||
+ dev->model->asic_type == AsicType::GL847 ||
+ dev->model->asic_type == AsicType::GL124)
+ {
+ bool memory_layout_found = false;
+ for (const auto& memory_layout : *s_memory_layout) {
+ if (memory_layout.models.matches(dev->model->model_id)) {
+ dev->memory_layout = memory_layout;
+ memory_layout_found = true;
+ break;
+ }
+ }
+ if (!memory_layout_found) {
+ throw SaneException("Could not find memory layout");
+ }
+ }
+
if (!motor_ok || !gpo_ok || !fe_ok) {
throw SaneException("bad description(s) for fe/gpo/motor=%d/%d/%d\n",
static_cast<unsigned>(dev->model->sensor_id),
@@ -316,33 +323,6 @@ void sanei_genesys_init_structs (Genesys_Device * dev)
}
}
-/* Generate slope table for motor movement */
-/**
- * This function generates a slope table using the slope from the motor struct
- * truncated at the given exposure time or step count, whichever comes first.
- * The summed time of the acceleration steps is returned, and the
- * number of accerelation steps is put into used_steps.
- *
- * @param dev Device struct
- * @param slope_table Table to write to
- * @param step_type Generate table for this step_type. 0=>full, 1=>half,
- * 2=>quarter
- * @param exposure_time Minimum exposure time of a scan line
- * @param yres Resolution of a scan line
- * @param used_steps Final number of steps is stored here
- * @return Motor slope table
- * @note all times in pixel time
- */
-MotorSlopeTable sanei_genesys_create_slope_table3(AsicType asic_type, const Genesys_Motor& motor,
- StepType step_type, int exposure_time,
- unsigned yres)
-{
- unsigned target_speed_w = (exposure_time * yres) / motor.base_ydpi;
-
- return create_slope_table(motor.get_slope(step_type), target_speed_w, step_type, 1, 1,
- get_slope_table_max_size(asic_type));
-}
-
/** @brief computes gamma table
* Generates a gamma table of the given length within 0 and the given
* maximum value
@@ -382,7 +362,7 @@ void sanei_genesys_create_default_gamma_table(Genesys_Device* dev,
int size = 0;
int max = 0;
if (dev->model->asic_type == AsicType::GL646) {
- if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) {
+ if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {
size = 16384;
} else {
size = 4096;
@@ -411,34 +391,30 @@ void sanei_genesys_create_default_gamma_table(Genesys_Device* dev,
Note: The enhance option of the scanners does _not_ help. It only halves
the amount of pixels transfered.
*/
-SANE_Int sanei_genesys_exposure_time2(Genesys_Device * dev, float ydpi,
- StepType step_type, int endpixel, int exposure_by_led)
+SANE_Int sanei_genesys_exposure_time2(Genesys_Device * dev, const MotorProfile& profile, float ydpi,
+ int endpixel, int exposure_by_led)
{
int exposure_by_ccd = endpixel + 32;
- unsigned max_speed_motor_w = dev->motor.get_slope(step_type).max_speed_w;
+ unsigned max_speed_motor_w = profile.slope.max_speed_w;
int exposure_by_motor = static_cast<int>((max_speed_motor_w * dev->motor.base_ydpi) / ydpi);
int exposure = exposure_by_ccd;
- if (exposure < exposure_by_motor)
- exposure = exposure_by_motor;
+ if (exposure < exposure_by_motor) {
+ exposure = exposure_by_motor;
+ }
- if (exposure < exposure_by_led && dev->model->is_cis)
- exposure = exposure_by_led;
+ if (exposure < exposure_by_led && dev->model->is_cis) {
+ exposure = exposure_by_led;
+ }
- DBG(DBG_info, "%s: ydpi=%d, step=%d, endpixel=%d led=%d => exposure=%d\n", __func__,
- static_cast<int>(ydpi), static_cast<unsigned>(step_type), endpixel,
- exposure_by_led, exposure);
- return exposure;
+ return exposure;
}
/* Sends a block of shading information to the scanner.
The data is placed at address 0x0000 for color mode, gray mode and
unconditionally for the following CCD chips: HP2300, HP2400 and HP5345
- In the other cases (lineart, halftone on ccd chips not mentioned) the
- addresses are 0x2a00 for dpihw==0, 0x5500 for dpihw==1 and 0xa800 for
- dpihw==2. //Note: why this?
The data needs to be of size "size", and in little endian byte order.
*/
@@ -446,7 +422,6 @@ static void genesys_send_offset_and_shading(Genesys_Device* dev, const Genesys_S
uint8_t* data, int size)
{
DBG_HELPER_ARGS(dbg, "(size = %d)", size);
- int dpihw;
int start_address;
/* ASIC higher than gl843 doesn't have register 2A/2B, so we route to
@@ -457,84 +432,30 @@ static void genesys_send_offset_and_shading(Genesys_Device* dev, const Genesys_S
return;
}
- /* gl646, gl84[123] case */
- dpihw = dev->reg.get8(0x05) >> 6;
-
- /* TODO invert the test so only the 2 models behaving like that are
- * tested instead of adding all the others */
- /* many scanners send coefficient for lineart/gray like in color mode */
- if ((dev->settings.scan_mode == ScanColorMode::LINEART ||
- dev->settings.scan_mode == ScanColorMode::HALFTONE)
- && dev->model->sensor_id != SensorId::CCD_PLUSTEK_OPTICBOOK_3800
- && dev->model->sensor_id != SensorId::CCD_KVSS080
- && dev->model->sensor_id != SensorId::CCD_G4050
- && dev->model->sensor_id != SensorId::CCD_HP_4850C
- && dev->model->sensor_id != SensorId::CCD_CANON_4400F
- && dev->model->sensor_id != SensorId::CCD_CANON_8400F
- && dev->model->sensor_id != SensorId::CCD_CANON_8600F
- && dev->model->sensor_id != SensorId::CCD_DSMOBILE600
- && dev->model->sensor_id != SensorId::CCD_XP300
- && dev->model->sensor_id != SensorId::CCD_DP665
- && dev->model->sensor_id != SensorId::CCD_DP685
- && dev->model->sensor_id != SensorId::CIS_CANON_LIDE_80
- && dev->model->sensor_id != SensorId::CCD_ROADWARRIOR
- && dev->model->sensor_id != SensorId::CCD_HP2300
- && dev->model->sensor_id != SensorId::CCD_HP2400
- && dev->model->sensor_id != SensorId::CCD_HP3670
- && dev->model->sensor_id != SensorId::CCD_5345) /* lineart, halftone */
- {
- if (dpihw == 0) { /* 600 dpi */
- start_address = 0x02a00;
- } else if (dpihw == 1) { /* 1200 dpi */
- start_address = 0x05500;
- } else if (dpihw == 2) { /* 2400 dpi */
- start_address = 0x0a800;
- } else { /* reserved */
- throw SaneException("unknown dpihw");
- }
- }
- else { // color
- start_address = 0x00;
- }
+ start_address = 0x00;
dev->interface->write_buffer(0x3c, start_address, data, size);
}
-// ?
void sanei_genesys_init_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
int pixels_per_line)
{
DBG_HELPER_ARGS(dbg, "pixels_per_line: %d", pixels_per_line);
- if (dev->model->flags & GENESYS_FLAG_CALIBRATION_HOST_SIDE) {
- return;
- }
-
- int channels;
- int i;
-
if (dev->cmd_set->has_send_shading_data()) {
return;
}
DBG(DBG_proc, "%s (pixels_per_line = %d)\n", __func__, pixels_per_line);
- // BUG: GRAY shouldn't probably be in the if condition below. Discovered when refactoring
- if (dev->settings.scan_mode == ScanColorMode::GRAY ||
- dev->settings.scan_mode == ScanColorMode::COLOR_SINGLE_PASS)
- {
- channels = 3;
- } else {
- channels = 1;
- }
+ unsigned channels = dev->settings.get_channels();
// 16 bit black, 16 bit white
std::vector<uint8_t> shading_data(pixels_per_line * 4 * channels, 0);
uint8_t* shading_data_ptr = shading_data.data();
- for (i = 0; i < pixels_per_line * channels; i++)
- {
+ for (unsigned i = 0; i < pixels_per_line * channels; i++) {
*shading_data_ptr++ = 0x00; /* dark lo */
*shading_data_ptr++ = 0x00; /* dark hi */
*shading_data_ptr++ = 0x00; /* white lo */
@@ -545,184 +466,6 @@ void sanei_genesys_init_shading_data(Genesys_Device* dev, const Genesys_Sensor&
pixels_per_line * 4 * channels);
}
-
-// Find the position of the reference point: takes gray level 8 bits data and find
-// first CCD usable pixel and top of scanning area
-void sanei_genesys_search_reference_point(Genesys_Device* dev, Genesys_Sensor& sensor,
- const uint8_t* src_data, int start_pixel, int dpi,
- int width, int height)
-{
- DBG_HELPER(dbg);
- int x, y;
- int current, left, top = 0;
- int size, count;
- int level = 80; /* edge threshold level */
-
- // sanity check
- if ((width < 3) || (height < 3)) {
- throw SaneException("invalid width or height");
- }
-
- /* transformed image data */
- size = width * height;
- std::vector<uint8_t> image2(size, 0);
- std::vector<uint8_t> image(size, 0);
-
- /* laplace filter to denoise picture */
- std::memcpy(image2.data(), src_data, size);
- std::memcpy(image.data(), src_data, size); // to initialize unprocessed part of the image buffer
-
- for (y = 1; y < height - 1; y++) {
- for (x = 1; x < width - 1; x++) {
- image[y * width + x] =
- (image2[(y - 1) * width + x + 1] + 2 * image2[(y - 1) * width + x] +
- image2[(y - 1) * width + x - 1] + 2 * image2[y * width + x + 1] +
- 4 * image2[y * width + x] + 2 * image2[y * width + x - 1] +
- image2[(y + 1) * width + x + 1] + 2 * image2[(y + 1) * width + x] +
- image2[(y + 1) * width + x - 1]) / 16;
- }
- }
-
- image2 = image;
- if (DBG_LEVEL >= DBG_data)
- sanei_genesys_write_pnm_file("gl_laplace.pnm", image.data(), 8, 1, width, height);
-
- /* apply X direction sobel filter
- -1 0 1
- -2 0 2
- -1 0 1
- and finds threshold level
- */
- level = 0;
- for (y = 2; y < height - 2; y++) {
- for (x = 2; x < width - 2; x++) {
- current = image2[(y - 1) * width + x + 1] - image2[(y - 1) * width + x - 1] +
- 2 * image2[y * width + x + 1] - 2 * image2[y * width + x - 1] +
- image2[(y + 1) * width + x + 1] - image2[(y + 1) * width + x - 1];
- if (current < 0)
- current = -current;
- if (current > 255)
- current = 255;
- image[y * width + x] = current;
- if (current > level)
- level = current;
- }
- }
- if (DBG_LEVEL >= DBG_data)
- sanei_genesys_write_pnm_file("gl_xsobel.pnm", image.data(), 8, 1, width, height);
-
- /* set up detection level */
- level = level / 3;
-
- /* find left black margin first
- todo: search top before left
- we average the result of N searches */
- left = 0;
- count = 0;
- for (y = 2; y < 11; y++)
- {
- x = 8;
- while ((x < width / 2) && (image[y * width + x] < level))
- {
- image[y * width + x] = 255;
- x++;
- }
- count++;
- left += x;
- }
- if (DBG_LEVEL >= DBG_data)
- sanei_genesys_write_pnm_file("gl_detected-xsobel.pnm", image.data(), 8, 1, width, height);
- left = left / count;
-
- // turn it in CCD pixel at full sensor optical resolution
- sensor.ccd_start_xoffset = start_pixel + (left * sensor.optical_res) / dpi;
-
- /* find top edge by detecting black strip */
- /* apply Y direction sobel filter
- -1 -2 -1
- 0 0 0
- 1 2 1
- */
- level = 0;
- for (y = 2; y < height - 2; y++) {
- for (x = 2; x < width - 2; x++) {
- current = -image2[(y - 1) * width + x + 1] - 2 * image2[(y - 1) * width + x] -
- image2[(y - 1) * width + x - 1] + image2[(y + 1) * width + x + 1] +
- 2 * image2[(y + 1) * width + x] + image2[(y + 1) * width + x - 1];
- if (current < 0)
- current = -current;
- if (current > 255)
- current = 255;
- image[y * width + x] = current;
- if (current > level)
- level = current;
- }
- }
- if (DBG_LEVEL >= DBG_data)
- sanei_genesys_write_pnm_file("gl_ysobel.pnm", image.data(), 8, 1, width, height);
-
- /* set up detection level */
- level = level / 3;
-
- /* search top of horizontal black stripe : TODO yet another flag */
- if (dev->model->sensor_id == SensorId::CCD_5345
- && dev->model->motor_id == MotorId::MD_5345)
- {
- top = 0;
- count = 0;
- for (x = width / 2; x < width - 1; x++)
- {
- y = 2;
- while ((y < height) && (image[x + y * width] < level))
- {
- image[y * width + x] = 255;
- y++;
- }
- count++;
- top += y;
- }
- if (DBG_LEVEL >= DBG_data)
- sanei_genesys_write_pnm_file("gl_detected-ysobel.pnm", image.data(), 8, 1, width, height);
- top = top / count;
-
- /* bottom of black stripe is of fixed witdh, this hardcoded value
- * will be moved into device struct if more such values are needed */
- top += 10;
- dev->model->y_offset_calib_white = (top * MM_PER_INCH) / dpi;
- DBG(DBG_info, "%s: black stripe y_offset = %f mm \n", __func__,
- dev->model->y_offset_calib_white.value());
- }
-
- /* find white corner in dark area : TODO yet another flag */
- if ((dev->model->sensor_id == SensorId::CCD_HP2300 && dev->model->motor_id == MotorId::HP2300) ||
- (dev->model->sensor_id == SensorId::CCD_HP2400 && dev->model->motor_id == MotorId::HP2400) ||
- (dev->model->sensor_id == SensorId::CCD_HP3670 && dev->model->motor_id == MotorId::HP3670))
- {
- top = 0;
- count = 0;
- for (x = 10; x < 60; x++)
- {
- y = 2;
- while ((y < height) && (image[x + y * width] < level))
- y++;
- top += y;
- count++;
- }
- top = top / count;
- dev->model->y_offset_calib_white = (top * MM_PER_INCH) / dpi;
- DBG(DBG_info, "%s: white corner y_offset = %f mm\n", __func__,
- dev->model->y_offset_calib_white.value());
- }
-
- DBG(DBG_proc, "%s: ccd_start_xoffset = %d, left = %d, top = %d\n", __func__,
- sensor.ccd_start_xoffset, left, top);
-}
-
-namespace gl843 {
- void gl843_park_xpa_lamp(Genesys_Device* dev);
- void gl843_set_xpa_motor_power(Genesys_Device* dev, Genesys_Register_Set& regs, bool set);
-} // namespace gl843
-
namespace gl124 {
void gl124_setup_scan_gpio(Genesys_Device* dev, int resolution);
} // namespace gl124
@@ -730,6 +473,16 @@ namespace gl124 {
void scanner_clear_scan_and_feed_counts(Genesys_Device& dev)
{
switch (dev.model->asic_type) {
+ case AsicType::GL841: {
+ dev.interface->write_register(gl841::REG_0x0D,
+ gl841::REG_0x0D_CLRLNCNT);
+ break;
+ }
+ case AsicType::GL842: {
+ dev.interface->write_register(gl842::REG_0x0D,
+ gl842::REG_0x0D_CLRLNCNT);
+ break;
+ }
case AsicType::GL843: {
dev.interface->write_register(gl843::REG_0x0D,
gl843::REG_0x0D_CLRLNCNT | gl843::REG_0x0D_CLRMCNT);
@@ -756,34 +509,107 @@ void scanner_clear_scan_and_feed_counts(Genesys_Device& dev)
}
}
-void scanner_clear_scan_and_feed_counts2(Genesys_Device& dev)
+void scanner_send_slope_table(Genesys_Device* dev, const Genesys_Sensor& sensor, unsigned table_nr,
+ const std::vector<uint16_t>& slope_table)
{
- // FIXME: switch to scanner_clear_scan_and_feed_counts when updating tests
- switch (dev.model->asic_type) {
- case AsicType::GL843: {
- dev.interface->write_register(gl843::REG_0x0D, gl843::REG_0x0D_CLRLNCNT);
- dev.interface->write_register(gl843::REG_0x0D, gl843::REG_0x0D_CLRMCNT);
+ DBG_HELPER_ARGS(dbg, "table_nr = %d, steps = %zu", table_nr, slope_table.size());
+
+ unsigned max_table_nr = 0;
+ switch (dev->model->asic_type) {
+ case AsicType::GL646: {
+ max_table_nr = 2;
break;
}
+ case AsicType::GL841:
+ case AsicType::GL842:
+ case AsicType::GL843:
case AsicType::GL845:
- case AsicType::GL846: {
- dev.interface->write_register(gl846::REG_0x0D, gl846::REG_0x0D_CLRLNCNT);
- dev.interface->write_register(gl846::REG_0x0D, gl846::REG_0x0D_CLRMCNT);
+ case AsicType::GL846:
+ case AsicType::GL847:
+ case AsicType::GL124: {
+ max_table_nr = 4;
break;
}
- case AsicType::GL847: {
- dev.interface->write_register(gl847::REG_0x0D, gl847::REG_0x0D_CLRLNCNT);
- dev.interface->write_register(gl847::REG_0x0D, gl847::REG_0x0D_CLRMCNT);
+ default:
+ throw SaneException("Unsupported ASIC type");
+ }
+
+ if (table_nr > max_table_nr) {
+ throw SaneException("invalid table number %d", table_nr);
+ }
+
+ std::vector<uint8_t> table;
+ table.reserve(slope_table.size() * 2);
+ for (std::size_t i = 0; i < slope_table.size(); i++) {
+ table.push_back(slope_table[i] & 0xff);
+ table.push_back(slope_table[i] >> 8);
+ }
+ if (dev->model->asic_type == AsicType::GL841 ||
+ dev->model->model_id == ModelId::CANON_LIDE_90)
+ {
+ // BUG: do this on all gl842 scanners
+ auto max_table_size = get_slope_table_max_size(dev->model->asic_type);
+ table.reserve(max_table_size * 2);
+ while (table.size() < max_table_size * 2) {
+ table.push_back(slope_table.back() & 0xff);
+ table.push_back(slope_table.back() >> 8);
+ }
+ }
+
+ if (dev->interface->is_mock()) {
+ dev->interface->record_slope_table(table_nr, slope_table);
+ }
+
+ switch (dev->model->asic_type) {
+ case AsicType::GL646: {
+ unsigned dpihw = dev->reg.find_reg(0x05).value >> 6;
+ unsigned start_address = 0;
+ if (dpihw == 0) { // 600 dpi
+ start_address = 0x08000;
+ } else if (dpihw == 1) { // 1200 dpi
+ start_address = 0x10000;
+ } else if (dpihw == 2) { // 2400 dpi
+ start_address = 0x1f800;
+ } else {
+ throw SaneException("Unexpected dpihw");
+ }
+ dev->interface->write_buffer(0x3c, start_address + table_nr * 0x100, table.data(),
+ table.size());
break;
}
+ case AsicType::GL841:
+ case AsicType::GL842: {
+ unsigned start_address = 0;
+ switch (sensor.register_dpihw) {
+ case 600: start_address = 0x08000; break;
+ case 1200: start_address = 0x10000; break;
+ case 2400: start_address = 0x20000; break;
+ default: throw SaneException("Unexpected dpihw");
+ }
+ dev->interface->write_buffer(0x3c, start_address + table_nr * 0x200, table.data(),
+ table.size());
+ break;
+ }
+ case AsicType::GL843: {
+ // slope table addresses are fixed : 0x40000, 0x48000, 0x50000, 0x58000, 0x60000
+ // XXX STEF XXX USB 1.1 ? sanei_genesys_write_0x8c (dev, 0x0f, 0x14);
+ dev->interface->write_gamma(0x28, 0x40000 + 0x8000 * table_nr, table.data(),
+ table.size());
+ break;
+ }
+ case AsicType::GL845:
+ case AsicType::GL846:
+ case AsicType::GL847:
case AsicType::GL124: {
- dev.interface->write_register(gl124::REG_0x0D, gl124::REG_0x0D_CLRLNCNT);
- dev.interface->write_register(gl124::REG_0x0D, gl124::REG_0x0D_CLRMCNT);
+ // slope table addresses are fixed
+ dev->interface->write_ahb(0x10000000 + 0x4000 * table_nr, table.size(),
+ table.data());
break;
}
default:
- throw SaneException("Unsupported asic type");
+ throw SaneException("Unsupported ASIC type");
}
+
}
bool scanner_is_motor_stopped(Genesys_Device& dev)
@@ -794,9 +620,18 @@ bool scanner_is_motor_stopped(Genesys_Device& dev)
return !status.is_motor_enabled && status.is_feeding_finished;
}
case AsicType::GL841: {
+ auto status = scanner_read_status(dev);
auto reg = dev.interface->read_register(gl841::REG_0x40);
- return (!(reg & gl841::REG_0x40_DATAENB) && !(reg & gl841::REG_0x40_MOTMFLG));
+ return (!(reg & gl841::REG_0x40_DATAENB) && !(reg & gl841::REG_0x40_MOTMFLG) &&
+ !status.is_motor_enabled);
+ }
+ case AsicType::GL842: {
+ auto status = scanner_read_status(dev);
+ auto reg = dev.interface->read_register(gl842::REG_0x40);
+
+ return (!(reg & gl842::REG_0x40_DATAENB) && !(reg & gl842::REG_0x40_MOTMFLG) &&
+ !status.is_motor_enabled);
}
case AsicType::GL843: {
auto status = scanner_read_status(dev);
@@ -832,11 +667,31 @@ bool scanner_is_motor_stopped(Genesys_Device& dev)
}
}
+void scanner_setup_sensor(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs)
+{
+ DBG_HELPER(dbg);
+
+ for (const auto& custom_reg : sensor.custom_regs) {
+ regs.set8(custom_reg.address, custom_reg.value);
+ }
+
+ if (dev.model->asic_type != AsicType::GL841 &&
+ dev.model->asic_type != AsicType::GL843)
+ {
+ regs_set_exposure(dev.model->asic_type, regs, sensor.exposure);
+ }
+
+ dev.segment_order = sensor.segment_order;
+}
+
void scanner_stop_action(Genesys_Device& dev)
{
DBG_HELPER(dbg);
switch (dev.model->asic_type) {
+ case AsicType::GL841:
+ case AsicType::GL842:
case AsicType::GL843:
case AsicType::GL845:
case AsicType::GL846:
@@ -847,9 +702,7 @@ void scanner_stop_action(Genesys_Device& dev)
throw SaneException("Unsupported asic type");
}
- if (dev.cmd_set->needs_update_home_sensor_gpio()) {
- dev.cmd_set->update_home_sensor_gpio(dev);
- }
+ dev.cmd_set->update_home_sensor_gpio(dev);
if (scanner_is_motor_stopped(dev)) {
DBG(DBG_info, "%s: already stopped\n", __func__);
@@ -878,6 +731,7 @@ void scanner_stop_action_no_move(Genesys_Device& dev, genesys::Genesys_Register_
switch (dev.model->asic_type) {
case AsicType::GL646:
case AsicType::GL841:
+ case AsicType::GL842:
case AsicType::GL843:
case AsicType::GL845:
case AsicType::GL846:
@@ -908,7 +762,9 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
const auto& sensor = sanei_genesys_find_sensor(&dev, resolution, 3, scan_method);
bool uses_secondary_head = (scan_method == ScanMethod::TRANSPARENCY ||
- scan_method == ScanMethod::TRANSPARENCY_INFRARED);
+ scan_method == ScanMethod::TRANSPARENCY_INFRARED) &&
+ (!has_flag(dev.model->flags, ModelFlag::UTA_NO_SECONDARY_MOTOR));
+
bool uses_secondary_pos = uses_secondary_head &&
dev.model->default_method == ScanMethod::FLATBED;
@@ -934,21 +790,19 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
session.params.yres = resolution;
session.params.startx = 0;
session.params.starty = steps;
- session.params.pixels = 100;
+ session.params.pixels = 50;
session.params.lines = 3;
session.params.depth = 8;
- session.params.channels = 3;
+ session.params.channels = 1;
session.params.scan_method = scan_method;
- session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- if (dev.model->asic_type == AsicType::GL843) {
- session.params.color_filter = ColorFilter::RED;
- } else {
- session.params.color_filter = dev.settings.color_filter;
- }
+ session.params.scan_mode = ScanColorMode::GRAY;
+ session.params.color_filter = ColorFilter::GREEN;
+
session.params.flags = ScanFlag::DISABLE_SHADING |
ScanFlag::DISABLE_GAMMA |
ScanFlag::FEEDING |
- ScanFlag::IGNORE_LINE_DISTANCE;
+ ScanFlag::IGNORE_STAGGER_OFFSET |
+ ScanFlag::IGNORE_COLOR_OFFSET;
if (dev.model->asic_type == AsicType::GL124) {
session.params.flags |= ScanFlag::DISABLE_BUFFER_FULL_MOVE;
@@ -963,20 +817,21 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
dev.cmd_set->init_regs_for_scan_session(&dev, sensor, &local_reg, session);
if (dev.model->asic_type != AsicType::GL843) {
- regs_set_exposure(dev.model->asic_type, local_reg, {0, 0, 0});
+ regs_set_exposure(dev.model->asic_type, local_reg,
+ sanei_genesys_fixup_exposure({0, 0, 0}));
}
- scanner_clear_scan_and_feed_counts2(dev);
+ scanner_clear_scan_and_feed_counts(dev);
dev.interface->write_registers(local_reg);
if (uses_secondary_head) {
- gl843::gl843_set_xpa_motor_power(&dev, local_reg, true);
+ dev.cmd_set->set_motor_mode(dev, local_reg, MotorMode::PRIMARY_AND_SECONDARY);
}
try {
scanner_start_action(dev, true);
} catch (...) {
catch_all_exceptions(__func__, [&]() {
- gl843::gl843_set_xpa_motor_power(&dev, local_reg, false);
+ dev.cmd_set->set_motor_mode(dev, local_reg, MotorMode::PRIMARY);
});
catch_all_exceptions(__func__, [&]() { scanner_stop_action(dev); });
// restore original registers
@@ -992,17 +847,18 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
dev.advance_head_pos_by_steps(ScanHeadId::SECONDARY, direction, steps);
}
- // FIXME: why don't we stop the scanner like on other ASICs
- if (dev.model->asic_type != AsicType::GL843) {
- scanner_stop_action(dev);
- }
+ scanner_stop_action(dev);
if (uses_secondary_head) {
- gl843::gl843_set_xpa_motor_power(&dev, local_reg, false);
+ dev.cmd_set->set_motor_mode(dev, local_reg, MotorMode::PRIMARY);
}
return;
}
// wait until feed count reaches the required value
+ if (dev.model->model_id == ModelId::CANON_LIDE_700F) {
+ dev.cmd_set->update_home_sensor_gpio(dev);
+ }
+
// FIXME: should porbably wait for some timeout
Status status;
for (unsigned i = 0;; ++i) {
@@ -1015,12 +871,9 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
dev.interface->sleep_ms(10);
}
- // FIXME: why don't we stop the scanner like on other ASICs
- if (dev.model->asic_type != AsicType::GL843) {
- scanner_stop_action(dev);
- }
+ scanner_stop_action(dev);
if (uses_secondary_head) {
- gl843::gl843_set_xpa_motor_power(&dev, local_reg, false);
+ dev.cmd_set->set_motor_mode(dev, local_reg, MotorMode::PRIMARY);
}
dev.advance_head_pos_by_steps(ScanHeadId::PRIMARY, direction, steps);
@@ -1032,11 +885,22 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
dev.interface->sleep_ms(100);
}
+void scanner_move_to_ta(Genesys_Device& dev)
+{
+ DBG_HELPER(dbg);
+
+ unsigned feed = static_cast<unsigned>((dev.model->y_offset_sensor_to_ta * dev.motor.base_ydpi) /
+ MM_PER_INCH);
+ scanner_move(dev, dev.model->default_method, feed, Direction::FORWARD);
+}
+
void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home)
{
DBG_HELPER_ARGS(dbg, "wait_until_home = %d", wait_until_home);
switch (dev.model->asic_type) {
+ case AsicType::GL841:
+ case AsicType::GL842:
case AsicType::GL843:
case AsicType::GL845:
case AsicType::GL846:
@@ -1047,11 +911,17 @@ void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home)
throw SaneException("Unsupported asic type");
}
+ if (dev.model->is_sheetfed) {
+ dbg.vlog(DBG_proc, "sheetfed scanner, skipping going back home");
+ return;
+ }
+
// FIXME: also check whether the scanner actually has a secondary head
- if (!dev.is_head_pos_known(ScanHeadId::SECONDARY) ||
+ if ((!dev.is_head_pos_known(ScanHeadId::SECONDARY) ||
dev.head_pos(ScanHeadId::SECONDARY) > 0 ||
dev.settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev.settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ dev.settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) &&
+ (!has_flag(dev.model->flags, ModelFlag::UTA_NO_SECONDARY_MOTOR)))
{
scanner_move_back_home_ta(dev);
}
@@ -1064,9 +934,7 @@ void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home)
Direction::BACKWARD);
}
- if (dev.cmd_set->needs_update_home_sensor_gpio()) {
- dev.cmd_set->update_home_sensor_gpio(dev);
- }
+ dev.cmd_set->update_home_sensor_gpio(dev);
auto status = scanner_read_reliable_status(dev);
@@ -1076,15 +944,6 @@ void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home)
return;
}
- if (dev.model->model_id == ModelId::CANON_LIDE_210) {
- // move the head back a little first
- if (dev.is_head_pos_known(ScanHeadId::PRIMARY) &&
- dev.head_pos(ScanHeadId::PRIMARY) > 30)
- {
- scanner_move(dev, dev.model->default_method, 20, Direction::BACKWARD);
- }
- }
-
Genesys_Register_Set local_reg = dev.reg;
unsigned resolution = sanei_genesys_get_lowest_ydpi(&dev);
@@ -1093,28 +952,22 @@ void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home)
ScanSession session;
session.params.xres = resolution;
session.params.yres = resolution;
- session.params.startx = 100;
- if (dev.model->asic_type == AsicType::GL843) {
- session.params.starty = 40000;
- } else {
- session.params.starty = 30000;
- }
- session.params.pixels = 100;
- session.params.lines = 100;
+ session.params.startx = 0;
+ session.params.starty = 40000;
+ session.params.pixels = 50;
+ session.params.lines = 3;
session.params.depth = 8;
session.params.channels = 1;
session.params.scan_method = dev.settings.scan_method;
- if (dev.model->asic_type == AsicType::GL843) {
- session.params.scan_mode = ScanColorMode::LINEART;
- session.params.color_filter = dev.settings.color_filter;
- } else {
- session.params.scan_mode = ScanColorMode::GRAY;
- session.params.color_filter = ColorFilter::RED;
- }
+ 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::IGNORE_STAGGER_OFFSET |
+ ScanFlag::IGNORE_COLOR_OFFSET |
ScanFlag::REVERSE;
+
if (dev.model->asic_type == AsicType::GL843) {
session.params.flags |= ScanFlag::DISABLE_BUFFER_FULL_MOVE;
}
@@ -1143,9 +996,7 @@ void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home)
throw;
}
- if (dev.cmd_set->needs_update_home_sensor_gpio()) {
- dev.cmd_set->update_home_sensor_gpio(dev);
- }
+ dev.cmd_set->update_home_sensor_gpio(dev);
if (is_testing_mode()) {
dev.interface->test_checkpoint("move_back_home");
@@ -1174,18 +1025,49 @@ void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home)
// when we come here then the scanner needed too much time for this, so we better stop
// the motor
catch_all_exceptions(__func__, [&](){ scanner_stop_action(dev); });
- dev.set_head_pos_unknown();
+ dev.set_head_pos_unknown(ScanHeadId::PRIMARY | ScanHeadId::SECONDARY);
throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");
}
dbg.log(DBG_info, "scanhead is still moving");
}
+namespace {
+ bool should_use_secondary_motor_mode(Genesys_Device& dev)
+ {
+ bool should_use = !dev.is_head_pos_known(ScanHeadId::SECONDARY) ||
+ !dev.is_head_pos_known(ScanHeadId::PRIMARY) ||
+ dev.head_pos(ScanHeadId::SECONDARY) > dev.head_pos(ScanHeadId::PRIMARY);
+ bool supports = dev.model->model_id == ModelId::CANON_8600F;
+ return should_use && supports;
+ }
+
+ void handle_motor_position_after_move_back_home_ta(Genesys_Device& dev, MotorMode motor_mode)
+ {
+ if (motor_mode == MotorMode::SECONDARY) {
+ dev.set_head_pos_zero(ScanHeadId::SECONDARY);
+ return;
+ }
+
+ if (dev.is_head_pos_known(ScanHeadId::PRIMARY)) {
+ if (dev.head_pos(ScanHeadId::PRIMARY) > dev.head_pos(ScanHeadId::SECONDARY)) {
+ dev.advance_head_pos_by_steps(ScanHeadId::PRIMARY, Direction::BACKWARD,
+ dev.head_pos(ScanHeadId::SECONDARY));
+ } else {
+ dev.set_head_pos_zero(ScanHeadId::PRIMARY);
+ }
+ dev.set_head_pos_zero(ScanHeadId::SECONDARY);
+ }
+ }
+} // namespace
+
void scanner_move_back_home_ta(Genesys_Device& dev)
{
DBG_HELPER(dbg);
switch (dev.model->asic_type) {
+ case AsicType::GL842:
case AsicType::GL843:
+ case AsicType::GL845:
break;
default:
throw SaneException("Unsupported asic type");
@@ -1199,7 +1081,9 @@ void scanner_move_back_home_ta(Genesys_Device& dev)
const auto& sensor = sanei_genesys_find_sensor(&dev, resolution, 1, scan_method);
if (dev.is_head_pos_known(ScanHeadId::SECONDARY) &&
- dev.head_pos(ScanHeadId::SECONDARY) > 1000)
+ dev.is_head_pos_known(ScanHeadId::PRIMARY) &&
+ dev.head_pos(ScanHeadId::SECONDARY) > 1000 &&
+ dev.head_pos(ScanHeadId::SECONDARY) <= dev.head_pos(ScanHeadId::PRIMARY))
{
// leave 500 steps for regular slow back home
scanner_move(dev, scan_method, dev.head_pos(ScanHeadId::SECONDARY) - 500,
@@ -1209,18 +1093,20 @@ void scanner_move_back_home_ta(Genesys_Device& dev)
ScanSession session;
session.params.xres = resolution;
session.params.yres = resolution;
- session.params.startx = 100;
- session.params.starty = 30000;
- session.params.pixels = 100;
- session.params.lines = 100;
+ session.params.startx = 0;
+ session.params.starty = 40000;
+ session.params.pixels = 50;
+ session.params.lines = 3;
session.params.depth = 8;
session.params.channels = 1;
session.params.scan_method = scan_method;
session.params.scan_mode = ScanColorMode::GRAY;
- session.params.color_filter = ColorFilter::RED;
+ session.params.color_filter = ColorFilter::GREEN;
+
session.params.flags = ScanFlag::DISABLE_SHADING |
ScanFlag::DISABLE_GAMMA |
- ScanFlag::IGNORE_LINE_DISTANCE |
+ ScanFlag::IGNORE_STAGGER_OFFSET |
+ ScanFlag::IGNORE_COLOR_OFFSET |
ScanFlag::REVERSE;
compute_session(&dev, session, sensor);
@@ -1230,7 +1116,11 @@ void scanner_move_back_home_ta(Genesys_Device& dev)
scanner_clear_scan_and_feed_counts(dev);
dev.interface->write_registers(local_reg);
- gl843::gl843_set_xpa_motor_power(&dev, local_reg, true);
+
+ auto motor_mode = should_use_secondary_motor_mode(dev) ? MotorMode::SECONDARY
+ : MotorMode::PRIMARY_AND_SECONDARY;
+
+ dev.cmd_set->set_motor_mode(dev, local_reg, motor_mode);
try {
scanner_start_action(dev, true);
@@ -1244,18 +1134,10 @@ void scanner_move_back_home_ta(Genesys_Device& dev)
if (is_testing_mode()) {
dev.interface->test_checkpoint("move_back_home_ta");
- if (dev.is_head_pos_known(ScanHeadId::PRIMARY)) {
- if (dev.head_pos(ScanHeadId::PRIMARY) > dev.head_pos(ScanHeadId::SECONDARY)) {
- dev.advance_head_pos_by_steps(ScanHeadId::PRIMARY, Direction::BACKWARD,
- dev.head_pos(ScanHeadId::SECONDARY));
- } else {
- dev.set_head_pos_zero(ScanHeadId::PRIMARY);
- }
- dev.set_head_pos_zero(ScanHeadId::SECONDARY);
- }
+ handle_motor_position_after_move_back_home_ta(dev, motor_mode);
scanner_stop_action(dev);
- gl843::gl843_set_xpa_motor_power(&dev, local_reg, false);
+ dev.cmd_set->set_motor_mode(dev, local_reg, MotorMode::PRIMARY);
return;
}
@@ -1266,18 +1148,10 @@ void scanner_move_back_home_ta(Genesys_Device& dev)
if (status.is_at_home) {
dbg.log(DBG_info, "TA reached home position");
- if (dev.is_head_pos_known(ScanHeadId::PRIMARY)) {
- if (dev.head_pos(ScanHeadId::PRIMARY) > dev.head_pos(ScanHeadId::SECONDARY)) {
- dev.advance_head_pos_by_steps(ScanHeadId::PRIMARY, Direction::BACKWARD,
- dev.head_pos(ScanHeadId::SECONDARY));
- } else {
- dev.set_head_pos_zero(ScanHeadId::PRIMARY);
- }
- dev.set_head_pos_zero(ScanHeadId::SECONDARY);
- }
+ handle_motor_position_after_move_back_home_ta(dev, motor_mode);
scanner_stop_action(dev);
- gl843::gl843_set_xpa_motor_power(&dev, local_reg, false);
+ dev.cmd_set->set_motor_mode(dev, local_reg, MotorMode::PRIMARY);
return;
}
@@ -1287,325 +1161,1148 @@ void scanner_move_back_home_ta(Genesys_Device& dev)
throw SaneException("Timeout waiting for XPA lamp to park");
}
-void sanei_genesys_calculate_zmod(bool two_table,
- uint32_t exposure_time,
- const std::vector<uint16_t>& slope_table,
- unsigned acceleration_steps,
- unsigned move_steps,
- unsigned buffer_acceleration_steps,
- uint32_t* out_z1, uint32_t* out_z2)
+void scanner_search_strip(Genesys_Device& dev, bool forward, bool black)
{
- DBG(DBG_info, "%s: two_table=%d\n", __func__, two_table);
+ DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
- // acceleration total time
- unsigned sum = std::accumulate(slope_table.begin(), slope_table.begin() + acceleration_steps,
- 0, std::plus<unsigned>());
+ if (dev.model->asic_type == AsicType::GL841 && !black && forward) {
+ dev.frontend.set_gain(0, 0xff);
+ dev.frontend.set_gain(1, 0xff);
+ dev.frontend.set_gain(2, 0xff);
+ }
- /* Z1MOD:
- c = sum(slope_table; reg_stepno)
- d = reg_fwdstep * <cruising speed>
- Z1MOD = (c+d) % exposure_time
- */
- *out_z1 = (sum + buffer_acceleration_steps * slope_table[acceleration_steps - 1]) % exposure_time;
+ // set up for a gray scan at lowest dpi
+ const auto& resolution_settings = dev.model->get_resolution_settings(dev.settings.scan_method);
+ unsigned dpi = resolution_settings.get_min_resolution_x();
+ unsigned channels = 1;
- /* Z2MOD:
- a = sum(slope_table; reg_stepno)
- b = move_steps or 1 if 2 tables
- Z1MOD = (a+b) % exposure_time
- */
- if (!two_table) {
- sum = sum + (move_steps * slope_table[acceleration_steps - 1]);
+ auto& sensor = sanei_genesys_find_sensor(&dev, dpi, channels, dev.settings.scan_method);
+ dev.cmd_set->set_fe(&dev, sensor, AFE_SET);
+ scanner_stop_action(dev);
+
+
+ // shading calibration is done with dev.motor.base_ydpi
+ unsigned lines = static_cast<unsigned>(dev.model->y_size_calib_mm * dpi / MM_PER_INCH);
+ if (dev.model->asic_type == AsicType::GL841) {
+ lines = 10; // TODO: use dev.model->search_lines
+ lines = static_cast<unsigned>((lines * dpi) / MM_PER_INCH);
+ }
+
+ unsigned pixels = dev.model->x_size_calib_mm * dpi / MM_PER_INCH;
+
+ dev.set_head_pos_zero(ScanHeadId::PRIMARY);
+
+ unsigned length = 20;
+ if (dev.model->asic_type == AsicType::GL841) {
+ // 20 cm max length for calibration sheet
+ length = static_cast<unsigned>(((200 * dpi) / MM_PER_INCH) / lines);
+ }
+
+ auto local_reg = dev.reg;
+
+ ScanSession session;
+ session.params.xres = dpi;
+ session.params.yres = dpi;
+ 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::GRAY;
+ session.params.color_filter = ColorFilter::RED;
+ session.params.flags = ScanFlag::DISABLE_SHADING |
+ ScanFlag::DISABLE_GAMMA;
+ if (dev.model->asic_type != AsicType::GL841 && !forward) {
+ session.params.flags |= ScanFlag::REVERSE;
+ }
+ compute_session(&dev, session, sensor);
+
+ dev.cmd_set->init_regs_for_scan_session(&dev, sensor, &local_reg, session);
+
+ dev.interface->write_registers(local_reg);
+
+ dev.cmd_set->begin_scan(&dev, sensor, &local_reg, true);
+
+ if (is_testing_mode()) {
+ dev.interface->test_checkpoint("search_strip");
+ scanner_stop_action(dev);
+ return;
+ }
+
+ wait_until_buffer_non_empty(&dev);
+
+ // now we're on target, we can read data
+ auto image = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
+
+ scanner_stop_action(dev);
+
+ unsigned pass = 0;
+ if (dbg_log_image_data()) {
+ char title[80];
+ std::sprintf(title, "gl_search_strip_%s_%s%02d.tiff",
+ black ? "black" : "white", forward ? "fwd" : "bwd", pass);
+ write_tiff_file(title, image);
+ }
+
+ // loop until strip is found or maximum pass number done
+ bool found = false;
+ while (pass < length && !found) {
+ dev.interface->write_registers(local_reg);
+
+ // now start scan
+ dev.cmd_set->begin_scan(&dev, sensor, &local_reg, true);
+
+ wait_until_buffer_non_empty(&dev);
+
+ // now we're on target, we can read data
+ image = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
+
+ scanner_stop_action(dev);
+
+ if (dbg_log_image_data()) {
+ char title[80];
+ std::sprintf(title, "gl_search_strip_%s_%s%02d.tiff",
+ black ? "black" : "white",
+ forward ? "fwd" : "bwd", static_cast<int>(pass));
+ write_tiff_file(title, image);
+ }
+
+ unsigned white_level = 90;
+ unsigned black_level = 60;
+
+ std::size_t count = 0;
+ // Search data to find black strip
+ // When searching forward, we only need one line of the searched color since we
+ // will scan forward. But when doing backward search, we need all the area of the ame color
+ if (forward) {
+
+ for (std::size_t y = 0; y < image.get_height() && !found; y++) {
+ count = 0;
+
+ // count of white/black pixels depending on the color searched
+ for (std::size_t x = 0; x < image.get_width(); x++) {
+
+ // when searching for black, detect white pixels
+ if (black && image.get_raw_channel(x, y, 0) > white_level) {
+ count++;
+ }
+
+ // when searching for white, detect black pixels
+ if (!black && image.get_raw_channel(x, y, 0) < black_level) {
+ count++;
+ }
+ }
+
+ // at end of line, if count >= 3%, line is not fully of the desired color
+ // so we must go to next line of the buffer */
+ // count*100/pixels < 3
+
+ auto found_percentage = (count * 100 / image.get_width());
+ if (found_percentage < 3) {
+ found = 1;
+ DBG(DBG_data, "%s: strip found forward during pass %d at line %zu\n", __func__,
+ pass, y);
+ } else {
+ DBG(DBG_data, "%s: pixels=%zu, count=%zu (%zu%%)\n", __func__,
+ image.get_width(), count, found_percentage);
+ }
+ }
+ } else {
+ /* since calibration scans are done forward, we need the whole area
+ to be of the required color when searching backward
+ */
+ count = 0;
+ for (std::size_t y = 0; y < image.get_height(); y++) {
+ // count of white/black pixels depending on the color searched
+ for (std::size_t x = 0; x < image.get_width(); x++) {
+ // when searching for black, detect white pixels
+ if (black && image.get_raw_channel(x, y, 0) > white_level) {
+ count++;
+ }
+ // when searching for white, detect black pixels
+ if (!black && image.get_raw_channel(x, y, 0) < black_level) {
+ count++;
+ }
+ }
+ }
+
+ // at end of area, if count >= 3%, area is not fully of the desired color
+ // so we must go to next buffer
+ auto found_percentage = count * 100 / (image.get_width() * image.get_height());
+ if (found_percentage < 3) {
+ found = 1;
+ DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
+ } else {
+ DBG(DBG_data, "%s: pixels=%zu, count=%zu (%zu%%)\n", __func__, image.get_width(),
+ count, found_percentage);
+ }
+ }
+ pass++;
+ }
+
+ if (found) {
+ DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
} else {
- sum = sum + slope_table[acceleration_steps - 1];
+ throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found",
+ black ? "black" : "white");
}
- *out_z2 = sum % exposure_time;
}
-static uint8_t genesys_adjust_gain(double* applied_multi, double multi, uint8_t gain)
+static int dark_average_channel(const Image& image, unsigned black, unsigned channel)
+{
+ auto channels = get_pixel_channels(image.get_format());
+
+ unsigned avg[3];
+
+ // computes average values on black margin
+ for (unsigned ch = 0; ch < channels; ch++) {
+ avg[ch] = 0;
+ unsigned count = 0;
+ // FIXME: start with the second line because the black pixels often have noise on the first
+ // line; the cause is probably incorrectly cleaned up previous scan
+ for (std::size_t y = 1; y < image.get_height(); y++) {
+ for (unsigned j = 0; j < black; j++) {
+ avg[ch] += image.get_raw_channel(j, y, ch);
+ count++;
+ }
+ }
+ if (count > 0) {
+ avg[ch] /= count;
+ }
+ DBG(DBG_info, "%s: avg[%d] = %d\n", __func__, ch, avg[ch]);
+ }
+ DBG(DBG_info, "%s: average = %d\n", __func__, avg[channel]);
+ return avg[channel];
+}
+
+bool should_calibrate_only_active_area(const Genesys_Device& dev,
+ const Genesys_Settings& settings)
{
- double voltage, original_voltage;
- uint8_t new_gain = 0;
+ if (settings.scan_method == ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ if (dev.model->model_id == ModelId::CANON_4400F && settings.xres >= 4800) {
+ return true;
+ }
+ if (dev.model->model_id == ModelId::CANON_8600F && settings.xres == 4800) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs)
+{
+ DBG_HELPER(dbg);
+
+ if (dev.model->asic_type == AsicType::GL842 &&
+ dev.frontend.layout.type != FrontendType::WOLFSON)
+ {
+ return;
+ }
+
+ if (dev.model->asic_type == AsicType::GL843 &&
+ dev.frontend.layout.type != FrontendType::WOLFSON)
+ {
+ return;
+ }
+
+ if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846)
+ {
+ // no gain nor offset for AKM AFE
+ std::uint8_t reg04 = dev.interface->read_register(gl846::REG_0x04);
+ if ((reg04 & gl846::REG_0x04_FESET) == 0x02) {
+ return;
+ }
+ }
+ if (dev.model->asic_type == AsicType::GL847) {
+ // no gain nor offset for AKM AFE
+ std::uint8_t reg04 = dev.interface->read_register(gl847::REG_0x04);
+ if ((reg04 & gl847::REG_0x04_FESET) == 0x02) {
+ return;
+ }
+ }
- DBG(DBG_proc, "%s: multi=%f, gain=%d\n", __func__, multi, gain);
+ if (dev.model->asic_type == AsicType::GL124) {
+ std::uint8_t reg0a = dev.interface->read_register(gl124::REG_0x0A);
+ if (((reg0a & gl124::REG_0x0A_SIFSEL) >> gl124::REG_0x0AS_SIFSEL) == 3) {
+ return;
+ }
+ }
- voltage = 0.5 + gain * 0.25;
- original_voltage = voltage;
+ unsigned target_pixels = dev.model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH;
+ unsigned start_pixel = 0;
+ unsigned black_pixels = (sensor.black_pixels * sensor.full_resolution) / sensor.full_resolution;
- voltage *= multi;
+ unsigned channels = 3;
+ unsigned lines = 1;
+ unsigned resolution = sensor.full_resolution;
- new_gain = static_cast<std::uint8_t>((voltage - 0.5) * 4);
- if (new_gain > 0x0e)
- new_gain = 0x0e;
+ const Genesys_Sensor* calib_sensor = &sensor;
+ if (dev.model->asic_type == AsicType::GL843) {
+ lines = 8;
- voltage = 0.5 + (new_gain) * 0.25;
+ // compute divider factor to compute final pixels number
+ const auto& dpihw_sensor = sanei_genesys_find_sensor(&dev, dev.settings.xres, channels,
+ dev.settings.scan_method);
+ resolution = dpihw_sensor.shading_resolution;
+ unsigned factor = sensor.full_resolution / resolution;
- *applied_multi = voltage / original_voltage;
+ calib_sensor = &sanei_genesys_find_sensor(&dev, resolution, channels,
+ dev.settings.scan_method);
- DBG(DBG_proc, "%s: orig voltage=%.2f, new voltage=%.2f, *applied_multi=%f, new_gain=%d\n",
- __func__, original_voltage, voltage, *applied_multi, new_gain);
+ target_pixels = dev.model->x_size_calib_mm * resolution / MM_PER_INCH;
+ black_pixels = calib_sensor->black_pixels / factor;
- return new_gain;
-}
+ if (should_calibrate_only_active_area(dev, dev.settings)) {
+ float offset = dev.model->x_offset_ta;
+ start_pixel = static_cast<int>((offset * calib_sensor->get_optical_resolution()) / MM_PER_INCH);
+ float size = dev.model->x_size_ta;
+ target_pixels = static_cast<int>((size * calib_sensor->get_optical_resolution()) / MM_PER_INCH);
+ }
-// todo: is return status necessary (unchecked?)
-static void genesys_average_white(Genesys_Device* dev, Genesys_Sensor& sensor, int channels,
- int channel, uint8_t* data, int size, int *max_average)
-{
+ if (dev.model->model_id == ModelId::CANON_4400F &&
+ dev.settings.scan_method == ScanMethod::FLATBED)
+ {
+ return;
+ }
+ }
- DBG_HELPER_ARGS(dbg, "channels=%d, channel=%d, size=%d", channels, channel, size);
- int gain_white_ref, sum, range;
- int average;
- int i;
+ if (dev.model->model_id == ModelId::CANON_5600F) {
+ // FIXME: use same approach as for GL843 scanners
+ lines = 8;
+ }
- range = size / 50;
+ if (dev.model->asic_type == AsicType::GL847) {
+ calib_sensor = &sanei_genesys_find_sensor(&dev, resolution, channels,
+ dev.settings.scan_method);
+ }
- if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ ScanFlag 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)
{
- gain_white_ref = sensor.fau_gain_white_ref * 256;
+ flags |= ScanFlag::USE_XPA;
+ }
+
+ ScanSession session;
+ session.params.xres = resolution;
+ session.params.yres = resolution;
+ session.params.startx = start_pixel;
+ session.params.starty = 0;
+ session.params.pixels = target_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.model->asic_type == AsicType::GL843 ? ColorFilter::RED
+ : dev.settings.color_filter;
+ session.params.flags = flags;
+ compute_session(&dev, session, *calib_sensor);
+
+ dev.cmd_set->init_regs_for_scan_session(&dev, *calib_sensor, &regs, session);
+
+ unsigned output_pixels = session.output_pixels;
+
+ sanei_genesys_set_motor_power(regs, false);
+
+ int top[3], bottom[3];
+ int topavg[3], bottomavg[3], avg[3];
+
+ // init gain and offset
+ for (unsigned ch = 0; ch < 3; ch++)
+ {
+ bottom[ch] = 10;
+ dev.frontend.set_offset(ch, bottom[ch]);
+ dev.frontend.set_gain(ch, 0);
+ }
+ dev.cmd_set->set_fe(&dev, *calib_sensor, AFE_SET);
+
+ // scan with bottom AFE settings
+ dev.interface->write_registers(regs);
+ DBG(DBG_info, "%s: starting first line reading\n", __func__);
+
+ dev.cmd_set->begin_scan(&dev, *calib_sensor, &regs, true);
+
+ if (is_testing_mode()) {
+ dev.interface->test_checkpoint("offset_calibration");
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ scanner_stop_action_no_move(dev, regs);
+ }
+ return;
+ }
+
+ Image first_line;
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ first_line = read_unshuffled_image_from_scanner(&dev, session,
+ session.output_total_bytes_raw);
+ scanner_stop_action_no_move(dev, regs);
} else {
- gain_white_ref = sensor.gain_white_ref * 256;
+ first_line = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
+
+ if (dev.model->model_id == ModelId::CANON_5600F) {
+ scanner_stop_action_no_move(dev, regs);
+ }
+ }
+
+ if (dbg_log_image_data()) {
+ char fn[40];
+ std::snprintf(fn, 40, "gl843_bottom_offset_%03d_%03d_%03d.tiff",
+ bottom[0], bottom[1], bottom[2]);
+ write_tiff_file(fn, first_line);
}
- if (range < 1)
- range = 1;
+ for (unsigned ch = 0; ch < 3; ch++) {
+ bottomavg[ch] = dark_average_channel(first_line, black_pixels, ch);
+ DBG(DBG_info, "%s: bottom avg %d=%d\n", __func__, ch, bottomavg[ch]);
+ }
- size = size / (2 * range * channels);
+ // now top value
+ for (unsigned ch = 0; ch < 3; ch++) {
+ top[ch] = 255;
+ dev.frontend.set_offset(ch, top[ch]);
+ }
+ dev.cmd_set->set_fe(&dev, *calib_sensor, AFE_SET);
- data += (channel * 2);
+ // scan with top AFE values
+ dev.interface->write_registers(regs);
+ DBG(DBG_info, "%s: starting second line reading\n", __func__);
- *max_average = 0;
+ dev.cmd_set->begin_scan(&dev, *calib_sensor, &regs, true);
- while (size--)
+ Image second_line;
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
{
- sum = 0;
- for (i = 0; i < range; i++)
- {
- sum += (*data);
- sum += *(data + 1) * 256;
- data += (2 * channels); /* byte based */
- }
+ second_line = read_unshuffled_image_from_scanner(&dev, session,
+ session.output_total_bytes_raw);
+ scanner_stop_action_no_move(dev, regs);
+ } else {
+ second_line = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
- average = (sum / range);
- if (average > *max_average)
- *max_average = average;
+ if (dev.model->model_id == ModelId::CANON_5600F) {
+ scanner_stop_action_no_move(dev, regs);
+ }
}
- DBG(DBG_proc, "%s: max_average=%d, gain_white_ref = %d, finished\n", __func__, *max_average,
- gain_white_ref);
+ for (unsigned ch = 0; ch < 3; ch++){
+ topavg[ch] = dark_average_channel(second_line, black_pixels, ch);
+ DBG(DBG_info, "%s: top avg %d=%d\n", __func__, ch, topavg[ch]);
+ }
+
+ unsigned pass = 0;
+
+ std::vector<std::uint8_t> debug_image;
+ std::size_t debug_image_lines = 0;
+ std::string debug_image_info;
- if (*max_average >= gain_white_ref)
- throw SaneException(SANE_STATUS_INVAL);
+ // loop until acceptable level
+ while ((pass < 32) && ((top[0] - bottom[0] > 1) ||
+ (top[1] - bottom[1] > 1) ||
+ (top[2] - bottom[2] > 1)))
+ {
+ pass++;
+
+ for (unsigned ch = 0; ch < 3; ch++) {
+ if (top[ch] - bottom[ch] > 1) {
+ dev.frontend.set_offset(ch, (top[ch] + bottom[ch]) / 2);
+ }
+ }
+ dev.cmd_set->set_fe(&dev, *calib_sensor, AFE_SET);
+
+ // scan with no move
+ dev.interface->write_registers(regs);
+ DBG(DBG_info, "%s: starting second line reading\n", __func__);
+ dev.cmd_set->begin_scan(&dev, *calib_sensor, &regs, true);
+
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ second_line = read_unshuffled_image_from_scanner(&dev, session,
+ session.output_total_bytes_raw);
+ scanner_stop_action_no_move(dev, regs);
+ } else {
+ second_line = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
+
+ if (dev.model->model_id == ModelId::CANON_5600F) {
+ scanner_stop_action_no_move(dev, regs);
+ }
+ }
+
+ if (dbg_log_image_data()) {
+ char title[100];
+ std::snprintf(title, 100, "lines: %d pixels_per_line: %d offsets[0..2]: %d %d %d\n",
+ lines, output_pixels,
+ dev.frontend.get_offset(0),
+ dev.frontend.get_offset(1),
+ dev.frontend.get_offset(2));
+ debug_image_info += title;
+ std::copy(second_line.get_row_ptr(0),
+ second_line.get_row_ptr(0) + second_line.get_row_bytes() * second_line.get_height(),
+ std::back_inserter(debug_image));
+ debug_image_lines += lines;
+ }
+
+ for (unsigned ch = 0; ch < 3; ch++) {
+ avg[ch] = dark_average_channel(second_line, black_pixels, ch);
+ DBG(DBG_info, "%s: avg[%d]=%d offset=%d\n", __func__, ch, avg[ch],
+ dev.frontend.get_offset(ch));
+ }
+
+ // compute new boundaries
+ for (unsigned ch = 0; ch < 3; ch++) {
+ if (topavg[ch] >= avg[ch]) {
+ topavg[ch] = avg[ch];
+ top[ch] = dev.frontend.get_offset(ch);
+ } else {
+ bottomavg[ch] = avg[ch];
+ bottom[ch] = dev.frontend.get_offset(ch);
+ }
+ }
+ }
+
+ if (dbg_log_image_data()) {
+ sanei_genesys_write_file("gl_offset_all_desc.txt",
+ reinterpret_cast<const std::uint8_t*>(debug_image_info.data()),
+ debug_image_info.size());
+ write_tiff_file("gl_offset_all.tiff", debug_image.data(), session.params.depth, channels,
+ output_pixels, debug_image_lines);
+ }
+
+ 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));
}
-/* todo: understand, values are too high */
-static int
-genesys_average_black (Genesys_Device * dev, int channel,
- uint8_t * data, int pixels)
+/* 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 scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs, unsigned dpi)
{
- int i;
- int sum;
- int pixel_step;
+ DBG_HELPER_ARGS(dbg, "dpi = %d", dpi);
- DBG(DBG_proc, "%s: channel=%d, pixels=%d\n", __func__, channel, pixels);
+ if (dev.model->asic_type == AsicType::GL842 &&
+ dev.frontend.layout.type != FrontendType::WOLFSON)
+ {
+ return;
+ }
- sum = 0;
+ if (dev.model->asic_type == AsicType::GL843 &&
+ dev.frontend.layout.type != FrontendType::WOLFSON)
+ {
+ return;
+ }
- if (dev->settings.scan_mode == ScanColorMode::COLOR_SINGLE_PASS)
+ if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846)
{
- data += (channel * 2);
- pixel_step = 3 * 2;
+ // no gain nor offset for AKM AFE
+ std::uint8_t reg04 = dev.interface->read_register(gl846::REG_0x04);
+ if ((reg04 & gl846::REG_0x04_FESET) == 0x02) {
+ return;
+ }
}
- else
+
+ if (dev.model->asic_type == AsicType::GL847) {
+ // no gain nor offset for AKM AFE
+ std::uint8_t reg04 = dev.interface->read_register(gl847::REG_0x04);
+ if ((reg04 & gl847::REG_0x04_FESET) == 0x02) {
+ return;
+ }
+ }
+
+ if (dev.model->asic_type == AsicType::GL124) {
+ // no gain nor offset for TI AFE
+ std::uint8_t reg0a = dev.interface->read_register(gl124::REG_0x0A);
+ if (((reg0a & gl124::REG_0x0A_SIFSEL) >> gl124::REG_0x0AS_SIFSEL) == 3) {
+ return;
+ }
+ }
+
+ if (dev.model->asic_type == AsicType::GL841) {
+ // feed to white strip if needed
+ if (dev.model->y_offset_calib_white > 0) {
+ unsigned move = static_cast<unsigned>(
+ (dev.model->y_offset_calib_white * (dev.motor.base_ydpi)) / MM_PER_INCH);
+ scanner_move(dev, dev.model->default_method, move, Direction::FORWARD);
+ }
+ }
+
+ // coarse gain calibration is always done in color mode
+ unsigned channels = 3;
+
+ unsigned resolution = sensor.full_resolution;
+ if (dev.model->asic_type == AsicType::GL841) {
+ const auto& dpihw_sensor = sanei_genesys_find_sensor(&dev, dev.settings.xres, channels,
+ dev.settings.scan_method);
+ resolution = dpihw_sensor.shading_resolution;
+ }
+
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
{
- pixel_step = 2;
+ const auto& dpihw_sensor = sanei_genesys_find_sensor(&dev, dpi, channels,
+ dev.settings.scan_method);
+ resolution = dpihw_sensor.shading_resolution;
}
- for (i = 0; i < pixels; i++)
+ float coeff = 1;
+
+ // Follow CKSEL
+ if (dev.model->sensor_id == SensorId::CCD_KVSS080 ||
+ dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL847 ||
+ dev.model->asic_type == AsicType::GL124)
{
- sum += *data;
- sum += *(data + 1) * 256;
+ if (dev.settings.xres < sensor.full_resolution) {
+ coeff = 0.9f;
+ }
+ }
- data += pixel_step;
+ unsigned lines = 10;
+ if (dev.model->asic_type == AsicType::GL841) {
+ lines = 1;
}
- DBG(DBG_proc, "%s = %d\n", __func__, sum / pixels);
+ const Genesys_Sensor* calib_sensor = &sensor;
+ if (dev.model->asic_type == AsicType::GL841 ||
+ dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843 ||
+ dev.model->asic_type == AsicType::GL847)
+ {
+ calib_sensor = &sanei_genesys_find_sensor(&dev, resolution, channels,
+ dev.settings.scan_method);
+ }
- return sum / pixels;
+ ScanFlag 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 = resolution;
+ session.params.yres = dev.model->asic_type == AsicType::GL841 ? dev.settings.yres : resolution;
+ session.params.startx = 0;
+ session.params.starty = 0;
+ session.params.pixels = dev.model->x_size_calib_mm * resolution / MM_PER_INCH;
+ session.params.lines = lines;
+ session.params.depth = dev.model->asic_type == AsicType::GL841 ? 16 : 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 = flags;
+ compute_session(&dev, session, *calib_sensor);
+
+ std::size_t pixels = session.output_pixels;
+
+ try {
+ dev.cmd_set->init_regs_for_scan_session(&dev, *calib_sensor, &regs, session);
+ } catch (...) {
+ if (dev.model->asic_type != AsicType::GL841) {
+ catch_all_exceptions(__func__, [&](){ sanei_genesys_set_motor_power(regs, false); });
+ }
+ throw;
+ }
+
+ if (dev.model->asic_type != AsicType::GL841) {
+ sanei_genesys_set_motor_power(regs, false);
+ }
+
+ dev.interface->write_registers(regs);
+
+ if (dev.model->asic_type != AsicType::GL841) {
+ dev.cmd_set->set_fe(&dev, *calib_sensor, AFE_SET);
+ }
+ dev.cmd_set->begin_scan(&dev, *calib_sensor, &regs, true);
+
+ if (is_testing_mode()) {
+ dev.interface->test_checkpoint("coarse_gain_calibration");
+ scanner_stop_action(dev);
+ dev.cmd_set->move_back_home(&dev, true);
+ return;
+ }
+
+ Image image;
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ image = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes_raw);
+ } else if (dev.model->asic_type == AsicType::GL124) {
+ // BUG: we probably want to read whole image, not just first line
+ image = read_unshuffled_image_from_scanner(&dev, session, session.output_line_bytes);
+ } else {
+ image = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes);
+ }
+
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ scanner_stop_action_no_move(dev, regs);
+ }
+
+ if (dbg_log_image_data()) {
+ write_tiff_file("gl_coarse_gain.tiff", image);
+ }
+
+ for (unsigned ch = 0; ch < channels; ch++) {
+ float curr_output = 0;
+ float target_value = 0;
+
+ if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ std::vector<uint16_t> values;
+ // FIXME: start from the second line because the first line often has artifacts. Probably
+ // caused by unclean cleanup of previous scan
+ for (std::size_t x = pixels / 4; x < (pixels * 3 / 4); x++) {
+ values.push_back(image.get_raw_channel(x, 1, ch));
+ }
+
+ // 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());
+ curr_output = static_cast<float>(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();
+
+ std::uint64_t total = 0;
+ for (std::size_t x = width / 4; x < (width * 3 / 4); x++) {
+ total += image.get_raw_channel(x, 0, ch);
+ }
+
+ curr_output = total / (width / 2);
+ target_value = calib_sensor->gain_white_ref * coeff;
+ }
+
+ std::uint8_t out_gain = compute_frontend_gain(curr_output, target_value,
+ dev.frontend.layout.type);
+ dev.frontend.set_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);
+
+ if (dev.model->asic_type == AsicType::GL841 &&
+ 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");
+ }
+
+ dbg.vlog(DBG_info, "gain=(%d, %d, %d)", dev.frontend.get_gain(0), dev.frontend.get_gain(1),
+ dev.frontend.get_gain(2));
+ }
+
+ if (dev.model->is_cis) {
+ std::uint8_t min_gain = std::min({dev.frontend.get_gain(0),
+ dev.frontend.get_gain(1),
+ dev.frontend.get_gain(2)});
+
+ dev.frontend.set_gain(0, min_gain);
+ dev.frontend.set_gain(1, min_gain);
+ dev.frontend.set_gain(2, min_gain);
+ }
+
+ dbg.vlog(DBG_info, "final gain=(%d, %d, %d)", dev.frontend.get_gain(0),
+ dev.frontend.get_gain(1), dev.frontend.get_gain(2));
+
+ scanner_stop_action(dev);
+
+ dev.cmd_set->move_back_home(&dev, true);
}
+namespace gl124 {
+ void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
+} // namespace gl124
-// todo: check; it works but the lines 1, 2, and 3 are too dark even with the
-// same offset and gain settings?
-static void genesys_coarse_calibration(Genesys_Device* dev, Genesys_Sensor& sensor)
+SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs)
{
- DBG_HELPER_ARGS(dbg, "scan_mode = %d", static_cast<unsigned>(dev->settings.scan_mode));
- int black_pixels;
- int white_average;
- uint8_t offset[4] = { 0xa0, 0x00, 0xa0, 0x40 }; /* first value isn't used */
- uint16_t white[12], dark[12];
- int i, j;
+ DBG_HELPER(dbg);
- black_pixels = sensor.black_pixels
- * dev->settings.xres / sensor.optical_res;
+ float move = 0;
- unsigned channels = dev->settings.get_channels();
+ if (dev.model->asic_type == AsicType::GL841) {
+ if (dev.model->y_offset_calib_white > 0) {
+ move = (dev.model->y_offset_calib_white * (dev.motor.base_ydpi)) / MM_PER_INCH;
+ scanner_move(dev, dev.model->default_method, static_cast<unsigned>(move),
+ Direction::FORWARD);
+ }
+ } else if (dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ // do nothing
+ } else if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL847)
+ {
+ move = dev.model->y_offset_calib_white;
+ move = static_cast<float>((move * (dev.motor.base_ydpi / 4)) / MM_PER_INCH);
+ if (move > 20) {
+ scanner_move(dev, dev.model->default_method, static_cast<unsigned>(move),
+ Direction::FORWARD);
+ }
+ } else if (dev.model->asic_type == AsicType::GL124) {
+ gl124::move_to_calibration_area(&dev, sensor, regs);
+ }
- DBG(DBG_info, "channels %d y_size %f xres %d\n", channels, dev->model->y_size.value(),
- dev->settings.xres);
- unsigned size = static_cast<unsigned>(channels * 2 * dev->model->y_size * dev->settings.xres /
- MM_PER_INCH);
- /* 1 1 mm 1/inch inch/mm */
- std::vector<uint8_t> calibration_data(size);
- std::vector<uint8_t> all_data(size * 4, 1);
+ unsigned channels = 3;
+ unsigned resolution = sensor.shading_resolution;
+ const auto& calib_sensor = sanei_genesys_find_sensor(&dev, resolution, channels,
+ dev.settings.scan_method);
+
+ if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL847 ||
+ dev.model->asic_type == AsicType::GL124)
+ {
+ 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.startx = 0;
+ session.params.starty = 0;
+ session.params.pixels = dev.model->x_size_calib_mm * resolution / MM_PER_INCH;
+ 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_STAGGER_OFFSET |
+ ScanFlag::IGNORE_COLOR_OFFSET;
+ compute_session(&dev, session, calib_sensor);
+
+ dev.cmd_set->init_regs_for_scan_session(&dev, calib_sensor, &regs, session);
+
+ if (dev.model->asic_type == AsicType::GL841) {
+ dev.interface->write_registers(regs); // FIXME: remove this
+ }
+
+ std::uint16_t exp[3];
- dev->cmd_set->set_fe(dev, sensor, AFE_INIT);
+ 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;
+ }
+
+ std::uint16_t target = sensor.gain_white_ref * 256;
- dev->frontend.set_gain(0, 2);
- dev->frontend.set_gain(1, 2);
- dev->frontend.set_gain(2, 2); // TODO: ? was 2
- dev->frontend.set_offset(0, offset[0]);
- dev->frontend.set_offset(1, offset[0]);
- dev->frontend.set_offset(2, offset[0]);
+ std::uint16_t min_exposure = 500; // only gl841
+ std::uint16_t max_exposure = ((exp[0] + exp[1] + exp[2]) / 3) * 2; // only gl841
- for (i = 0; i < 4; i++) /* read 4 lines */
+ std::uint16_t top[3] = {};
+ std::uint16_t bottom[3] = {};
+
+ if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846)
{
- if (i < 3) /* first 3 lines */
- {
- dev->frontend.set_offset(0, offset[i]);
- dev->frontend.set_offset(1, offset[i]);
- dev->frontend.set_offset(2, offset[i]);
+ bottom[0] = 29000;
+ bottom[1] = 29000;
+ bottom[2] = 29000;
+
+ top[0] = 41000;
+ top[1] = 51000;
+ top[2] = 51000;
+ } else if (dev.model->asic_type == AsicType::GL847) {
+ bottom[0] = 28000;
+ bottom[1] = 28000;
+ bottom[2] = 28000;
+
+ top[0] = 32000;
+ top[1] = 32000;
+ top[2] = 32000;
+ }
+
+ if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL847 ||
+ dev.model->asic_type == AsicType::GL124)
+ {
+ sanei_genesys_set_motor_power(regs, false);
+ }
+
+ bool acceptable = false;
+ 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);
}
- if (i == 1) /* second line */
- {
- double applied_multi;
- double gain_white_ref;
+ dev.interface->write_registers(regs);
- if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
- {
- gain_white_ref = sensor.fau_gain_white_ref * 256;
+ dbg.log(DBG_info, "starting line reading");
+ dev.cmd_set->begin_scan(&dev, calib_sensor, &regs, true);
+
+ if (is_testing_mode()) {
+ dev.interface->test_checkpoint("led_calibration");
+ 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 {
- gain_white_ref = sensor.gain_white_ref * 256;
+ scanner_stop_action(dev);
+ dev.cmd_set->move_back_home(&dev, true);
+ return calib_sensor.exposure;
}
+ }
- // white and black are defined downwards
-
- uint8_t gain0 = genesys_adjust_gain(&applied_multi,
- gain_white_ref / (white[0] - dark[0]),
- dev->frontend.get_gain(0));
- uint8_t gain1 = genesys_adjust_gain(&applied_multi,
- gain_white_ref / (white[1] - dark[1]),
- dev->frontend.get_gain(1));
- uint8_t gain2 = genesys_adjust_gain(&applied_multi,
- gain_white_ref / (white[2] - dark[2]),
- dev->frontend.get_gain(2));
- // FIXME: looks like overwritten data. Are the above calculations doing
- // anything at all?
- dev->frontend.set_gain(0, gain0);
- dev->frontend.set_gain(1, gain1);
- dev->frontend.set_gain(2, gain2);
- dev->frontend.set_gain(0, 2);
- dev->frontend.set_gain(1, 2);
- dev->frontend.set_gain(2, 2);
-
- dev->interface->write_fe_register(0x28, dev->frontend.get_gain(0));
- dev->interface->write_fe_register(0x29, dev->frontend.get_gain(1));
- dev->interface->write_fe_register(0x2a, dev->frontend.get_gain(2));
- }
+ auto image = read_unshuffled_image_from_scanner(&dev, session, session.output_line_bytes);
- if (i == 3) /* last line */
- {
- double x, y, rate;
+ scanner_stop_action(dev);
- for (j = 0; j < 3; j++)
- {
+ if (dbg_log_image_data()) {
+ char fn[30];
+ std::snprintf(fn, 30, "gl_led_%02d.tiff", i_test);
+ write_tiff_file(fn, image);
+ }
- x = static_cast<double>(dark[(i - 2) * 3 + j] -
- dark[(i - 1) * 3 + j]) * 254 / (offset[i - 1] / 2 -
- offset[i - 2] / 2);
- y = x - x * (offset[i - 1] / 2) / 254 - dark[(i - 1) * 3 + j];
- rate = (x - DARK_VALUE - y) * 254 / x + 0.5;
+ int avg[3];
+ for (unsigned ch = 0; ch < channels; ch++) {
+ avg[ch] = 0;
+ for (std::size_t x = 0; x < image.get_width(); x++) {
+ avg[ch] += image.get_raw_channel(x, 0, ch);
+ }
+ avg[ch] /= image.get_width();
+ }
- uint8_t curr_offset = static_cast<uint8_t>(rate);
+ dbg.vlog(DBG_info, "average: %d, %d, %d", avg[0], avg[1], avg[2]);
- if (curr_offset > 0x7f) {
- curr_offset = 0x7f;
- }
- curr_offset <<= 1;
- dev->frontend.set_offset(j, curr_offset);
- }
- }
- dev->interface->write_fe_register(0x20, dev->frontend.get_offset(0));
- dev->interface->write_fe_register(0x21, dev->frontend.get_offset(1));
- dev->interface->write_fe_register(0x22, dev->frontend.get_offset(2));
+ acceptable = true;
- DBG(DBG_info,
- "%s: doing scan: gain: %d/%d/%d, offset: %d/%d/%d\n", __func__,
- dev->frontend.get_gain(0),
- dev->frontend.get_gain(1),
- dev->frontend.get_gain(2),
- dev->frontend.get_offset(0),
- dev->frontend.get_offset(1),
- dev->frontend.get_offset(2));
+ 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;
+ }
- dev->cmd_set->begin_scan(dev, sensor, &dev->calib_reg, 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;
+ }
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("coarse_calibration");
- dev->cmd_set->end_scan(dev, &dev->calib_reg, true);
- return;
+ }
+ }
+ } else 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]) {
+ if (avg[i] != 0) {
+ exp[i] = (exp[i] * bottom[i]) / avg[i];
+ } else {
+ exp[i] *= 10;
+ }
+ acceptable = false;
+ }
+ if (avg[i] > top[i]) {
+ if (avg[i] != 0) {
+ exp[i] = (exp[i] * top[i]) / avg[i];
+ } else {
+ exp[i] *= 10;
+ }
+ acceptable = false;
+ }
+ }
+ } else if (dev.model->asic_type == AsicType::GL847) {
+ for (unsigned i = 0; i < 3; i++) {
+ if (avg[i] < bottom[i] || avg[i] > top[i]) {
+ auto target = (bottom[i] + top[i]) / 2;
+ if (avg[i] != 0) {
+ exp[i] = (exp[i] * target) / avg[i];
+ } else {
+ exp[i] *= 10;
+ }
+
+ acceptable = false;
+ }
+ }
+ } else if (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) {
+ float prev_weight = 0.5;
+ if (avg[i] != 0) {
+ exp[i] = exp[i] * prev_weight + ((exp[i] * target) / avg[i]) * (1 - prev_weight);
+ } else {
+ exp[i] = exp[i] * prev_weight + (exp[i] * 10) * (1 - prev_weight);
+ }
+ acceptable = false;
+ }
+ }
}
+ }
- sanei_genesys_read_data_from_scanner(dev, calibration_data.data(), size);
- std::memcpy(all_data.data() + i * size, calibration_data.data(), size);
- if (i == 3) /* last line */
- {
- std::vector<uint8_t> all_data_8(size * 4 / 2);
- unsigned int count;
+ if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL847 ||
+ dev.model->asic_type == AsicType::GL124)
+ {
+ // set these values as final ones for scan
+ regs_set_exposure(dev.model->asic_type, dev.reg, { exp[0], exp[1], exp[2] });
+ }
- for (count = 0; count < static_cast<unsigned>(size * 4 / 2); count++) {
- all_data_8[count] = all_data[count * 2 + 1];
+ if (dev.model->asic_type == AsicType::GL841 ||
+ dev.model->asic_type == AsicType::GL842 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ dev.cmd_set->move_back_home(&dev, true);
+ }
+
+ if (dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL847)
+ {
+ if (move > 20) {
+ dev.cmd_set->move_back_home(&dev, true);
}
- sanei_genesys_write_pnm_file("gl_coarse.pnm", all_data_8.data(), 8, channels, size / 6, 4);
- }
+ }
- dev->cmd_set->end_scan(dev, &dev->calib_reg, true);
+ dbg.vlog(DBG_info,"acceptable exposure: %d, %d, %d\n", exp[0], exp[1], exp[2]);
- if (dev->settings.scan_mode == ScanColorMode::COLOR_SINGLE_PASS)
- {
- for (j = 0; j < 3; j++)
- {
- genesys_average_white(dev, sensor, 3, j, calibration_data.data(), size, &white_average);
- white[i * 3 + j] = white_average;
- dark[i * 3 + j] =
- genesys_average_black (dev, j, calibration_data.data(),
- black_pixels);
- DBG(DBG_info, "%s: white[%d]=%d, black[%d]=%d\n", __func__,
- i * 3 + j, white[i * 3 + j], i * 3 + j, dark[i * 3 + j]);
- }
- }
- else /* one color-component modes */
- {
- genesys_average_white(dev, sensor, 1, 0, calibration_data.data(), size, &white_average);
- white[i * 3 + 0] = white[i * 3 + 1] = white[i * 3 + 2] =
- white_average;
- dark[i * 3 + 0] = dark[i * 3 + 1] = dark[i * 3 + 2] =
- genesys_average_black (dev, 0, calibration_data.data(), black_pixels);
- }
- } /* for (i = 0; i < 4; i++) */
-
- DBG(DBG_info, "%s: final: gain: %d/%d/%d, offset: %d/%d/%d\n", __func__,
- dev->frontend.get_gain(0),
- dev->frontend.get_gain(1),
- dev->frontend.get_gain(2),
- dev->frontend.get_offset(0),
- dev->frontend.get_offset(1),
- dev->frontend.get_offset(2));
+ return { exp[0], exp[1], exp[2] };
+}
+
+void sanei_genesys_calculate_zmod(bool two_table,
+ uint32_t exposure_time,
+ const std::vector<uint16_t>& slope_table,
+ unsigned acceleration_steps,
+ unsigned move_steps,
+ unsigned buffer_acceleration_steps,
+ uint32_t* out_z1, uint32_t* out_z2)
+{
+ // acceleration total time
+ unsigned sum = std::accumulate(slope_table.begin(), slope_table.begin() + acceleration_steps,
+ 0, std::plus<unsigned>());
+
+ /* Z1MOD:
+ c = sum(slope_table; reg_stepno)
+ d = reg_fwdstep * <cruising speed>
+ Z1MOD = (c+d) % exposure_time
+ */
+ *out_z1 = (sum + buffer_acceleration_steps * slope_table[acceleration_steps - 1]) % exposure_time;
+
+ /* Z2MOD:
+ a = sum(slope_table; reg_stepno)
+ b = move_steps or 1 if 2 tables
+ Z1MOD = (a+b) % exposure_time
+ */
+ if (!two_table) {
+ sum = sum + (move_steps * slope_table[acceleration_steps - 1]);
+ } else {
+ sum = sum + slope_table[acceleration_steps - 1];
+ }
+ *out_z2 = sum % exposure_time;
}
/**
@@ -1614,22 +2311,41 @@ static void genesys_coarse_calibration(Genesys_Device* dev, Genesys_Sensor& sens
* @param dev scanner's device
*/
static void genesys_shading_calibration_impl(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& local_reg,
std::vector<std::uint16_t>& out_average_data,
bool is_dark, const std::string& log_filename_prefix)
{
DBG_HELPER(dbg);
+ if (dev->model->asic_type == AsicType::GL646) {
+ dev->cmd_set->init_regs_for_shading(dev, sensor, local_reg);
+ local_reg = dev->reg;
+ } else {
+ local_reg = dev->reg;
+ dev->cmd_set->init_regs_for_shading(dev, sensor, local_reg);
+ dev->interface->write_registers(local_reg);
+ }
+
debug_dump(DBG_info, dev->calib_session);
size_t size;
uint32_t pixels_per_line;
- uint8_t channels;
- /* end pixel - start pixel */
- pixels_per_line = dev->calib_pixels;
- channels = dev->calib_channels;
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843 ||
+ dev->model->model_id == ModelId::CANON_5600F)
+ {
+ pixels_per_line = dev->calib_session.output_pixels;
+ } else {
+ // BUG: this selects incorrect pixel number
+ pixels_per_line = dev->calib_session.params.pixels;
+ }
+ unsigned channels = dev->calib_session.params.channels;
- uint32_t out_pixels_per_line = pixels_per_line + dev->calib_pixels_offset;
+ // BUG: we are using wrong pixel number here
+ unsigned start_offset =
+ dev->calib_session.params.startx * sensor.full_resolution / dev->calib_session.params.xres;
+ unsigned out_pixels_per_line = pixels_per_line + start_offset;
// FIXME: we set this during both dark and white calibration. A cleaner approach should
// probably be used
@@ -1644,61 +2360,55 @@ static void genesys_shading_calibration_impl(Genesys_Device* dev, const Genesys_
}
// FIXME: the current calculation is likely incorrect on non-GL843 implementations,
- // but this needs checking
- if (dev->calib_total_bytes_to_read > 0) {
- size = dev->calib_total_bytes_to_read;
- } else if (dev->model->asic_type == AsicType::GL843) {
- size = channels * 2 * pixels_per_line * dev->calib_lines;
+ // but this needs checking. Note the extra line when computing size.
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843 ||
+ dev->model->model_id == ModelId::CANON_5600F)
+ {
+ size = dev->calib_session.output_total_bytes_raw;
} else {
- size = channels * 2 * pixels_per_line * (dev->calib_lines + 1);
+ size = channels * 2 * pixels_per_line * (dev->calib_session.params.lines + 1);
}
std::vector<uint16_t> calibration_data(size / 2);
- bool motor = true;
- if (dev->model->flags & GENESYS_FLAG_SHADING_NO_MOVE)
- {
- motor = false;
- }
-
// turn off motor and lamp power for flatbed scanners, but not for sheetfed scanners
// because they have a calibration sheet with a sufficient black strip
if (is_dark && !dev->model->is_sheetfed) {
- sanei_genesys_set_lamp_power(dev, sensor, dev->calib_reg, false);
- sanei_genesys_set_motor_power(dev->calib_reg, motor);
+ sanei_genesys_set_lamp_power(dev, sensor, local_reg, false);
} else {
- sanei_genesys_set_lamp_power(dev, sensor, dev->calib_reg, true);
- sanei_genesys_set_motor_power(dev->calib_reg, motor);
+ sanei_genesys_set_lamp_power(dev, sensor, local_reg, true);
}
+ sanei_genesys_set_motor_power(local_reg, true);
- dev->interface->write_registers(dev->calib_reg);
+ dev->interface->write_registers(local_reg);
if (is_dark) {
// wait some time to let lamp to get dark
dev->interface->sleep_ms(200);
- } else if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) {
+ } else if (has_flag(dev->model->flags, ModelFlag::DARK_CALIBRATION)) {
// make sure lamp is bright again
// FIXME: what about scanners that take a long time to warm the lamp?
dev->interface->sleep_ms(500);
}
bool start_motor = !is_dark;
- dev->cmd_set->begin_scan(dev, sensor, &dev->calib_reg, start_motor);
+ dev->cmd_set->begin_scan(dev, sensor, &local_reg, start_motor);
if (is_testing_mode()) {
dev->interface->test_checkpoint(is_dark ? "dark_shading_calibration"
: "white_shading_calibration");
- dev->cmd_set->end_scan(dev, &dev->calib_reg, true);
+ dev->cmd_set->end_scan(dev, &local_reg, true);
return;
}
sanei_genesys_read_data_from_scanner(dev, reinterpret_cast<std::uint8_t*>(calibration_data.data()),
size);
- dev->cmd_set->end_scan(dev, &dev->calib_reg, true);
+ dev->cmd_set->end_scan(dev, &local_reg, true);
- if (dev->model->flags & GENESYS_FLAG_16BIT_DATA_INVERTED) {
+ if (has_flag(dev->model->flags, ModelFlag::SWAP_16BIT_DATA)) {
for (std::size_t i = 0; i < size / 2; ++i) {
auto value = calibration_data[i];
value = ((value >> 8) & 0xff) | ((value << 8) & 0xff00);
@@ -1706,30 +2416,29 @@ static void genesys_shading_calibration_impl(Genesys_Device* dev, const Genesys_
}
}
+ if (has_flag(dev->model->flags, ModelFlag::INVERT_PIXEL_DATA)) {
+ for (std::size_t i = 0; i < size / 2; ++i) {
+ calibration_data[i] = 0xffff - calibration_data[i];
+ }
+ }
+
std::fill(out_average_data.begin(),
- out_average_data.begin() + dev->calib_pixels_offset * channels, 0);
+ out_average_data.begin() + start_offset * channels, 0);
- compute_array_percentile_approx(out_average_data.data() + dev->calib_pixels_offset * channels,
+ compute_array_percentile_approx(out_average_data.data() +
+ start_offset * channels,
calibration_data.data(),
- dev->calib_lines, pixels_per_line * channels,
+ dev->calib_session.params.lines, pixels_per_line * channels,
0.5f);
- if (DBG_LEVEL >= DBG_data) {
- sanei_genesys_write_pnm_file16((log_filename_prefix + "_shading.pnm").c_str(),
- calibration_data.data(),
- channels, pixels_per_line, dev->calib_lines);
- sanei_genesys_write_pnm_file16((log_filename_prefix + "_average.pnm").c_str(),
- out_average_data.data(),
- channels, out_pixels_per_line, 1);
+ if (dbg_log_image_data()) {
+ write_tiff_file(log_filename_prefix + "_shading.tiff", calibration_data.data(), 16,
+ channels, pixels_per_line, dev->calib_session.params.lines);
+ write_tiff_file(log_filename_prefix + "_average.tiff", out_average_data.data(), 16,
+ channels, out_pixels_per_line, 1);
}
}
-
-static void genesys_dark_shading_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor)
-{
- DBG_HELPER(dbg);
- genesys_shading_calibration_impl(dev, sensor, dev->dark_average_data, true, "gl_black_");
-}
/*
* this function builds dummy dark calibration data so that we can
* compute shading coefficient in a clean way
@@ -1737,18 +2446,28 @@ static void genesys_dark_shading_calibration(Genesys_Device* dev, const Genesys_
* can be computed from previous calibration data (when doing offset
* calibration ?)
*/
-static void genesys_dummy_dark_shading(Genesys_Device* dev, const Genesys_Sensor& sensor)
+static void genesys_dark_shading_by_dummy_pixel(Genesys_Device* dev, const Genesys_Sensor& sensor)
{
DBG_HELPER(dbg);
uint32_t pixels_per_line;
- uint8_t channels;
uint32_t skip, xend;
int dummy1, dummy2, dummy3; /* dummy black average per channel */
- pixels_per_line = dev->calib_pixels;
- channels = dev->calib_channels;
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843)
+ {
+ pixels_per_line = dev->calib_session.output_pixels;
+ } else {
+ pixels_per_line = dev->calib_session.params.pixels;
+ }
+
+ unsigned channels = dev->calib_session.params.channels;
+
+ // BUG: we are using wrong pixel number here
+ unsigned start_offset =
+ dev->calib_session.params.startx * sensor.full_resolution / dev->calib_session.params.xres;
- uint32_t out_pixels_per_line = pixels_per_line + dev->calib_pixels_offset;
+ unsigned out_pixels_per_line = pixels_per_line + start_offset;
dev->average_size = channels * out_pixels_per_line;
dev->dark_average_data.clear();
@@ -1756,8 +2475,7 @@ static void genesys_dummy_dark_shading(Genesys_Device* dev, const Genesys_Sensor
/* we average values on 'the left' where CCD pixels are under casing and
give darkest values. We then use these as dummy dark calibration */
- if (dev->settings.xres <= sensor.optical_res / 2)
- {
+ if (dev->settings.xres <= sensor.full_resolution / 2) {
skip = 4;
xend = 36;
}
@@ -1807,17 +2525,22 @@ static void genesys_dummy_dark_shading(Genesys_Device* dev, const Genesys_Sensor
}
}
+static void genesys_dark_shading_by_constant(Genesys_Device& dev)
+{
+ dev.dark_average_data.clear();
+ dev.dark_average_data.resize(dev.average_size, 0x0101);
+}
static void genesys_repark_sensor_before_shading(Genesys_Device* dev)
{
DBG_HELPER(dbg);
- if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) {
+ if (has_flag(dev->model->flags, ModelFlag::SHADING_REPARK)) {
dev->cmd_set->move_back_home(dev, true);
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- dev->cmd_set->move_to_ta(dev);
+ scanner_move_to_ta(*dev);
}
}
}
@@ -1825,34 +2548,153 @@ static void genesys_repark_sensor_before_shading(Genesys_Device* dev)
static void genesys_repark_sensor_after_white_shading(Genesys_Device* dev)
{
DBG_HELPER(dbg);
- if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) {
+ if (has_flag(dev->model->flags, ModelFlag::SHADING_REPARK)) {
dev->cmd_set->move_back_home(dev, true);
}
}
-static void genesys_white_shading_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor)
+static void genesys_host_shading_calibration_impl(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ std::vector<std::uint16_t>& out_average_data,
+ bool is_dark,
+ const std::string& log_filename_prefix)
{
DBG_HELPER(dbg);
- genesys_shading_calibration_impl(dev, sensor, dev->white_average_data, false, "gl_white_");
+
+ if (is_dark && dev.settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) {
+ // FIXME: dark shading currently not supported on infrared transparency scans
+ return;
+ }
+
+ auto local_reg = dev.reg;
+ dev.cmd_set->init_regs_for_shading(&dev, sensor, local_reg);
+
+ auto& session = dev.calib_session;
+ debug_dump(DBG_info, session);
+
+ // turn off motor and lamp power for flatbed scanners, but not for sheetfed scanners
+ // because they have a calibration sheet with a sufficient black strip
+ if (is_dark && !dev.model->is_sheetfed) {
+ sanei_genesys_set_lamp_power(&dev, sensor, local_reg, false);
+ } else {
+ sanei_genesys_set_lamp_power(&dev, sensor, local_reg, true);
+ }
+ sanei_genesys_set_motor_power(local_reg, true);
+
+ dev.interface->write_registers(local_reg);
+
+ if (is_dark) {
+ // wait some time to let lamp to get dark
+ dev.interface->sleep_ms(200);
+ } else if (has_flag(dev.model->flags, ModelFlag::DARK_CALIBRATION)) {
+ // make sure lamp is bright again
+ // FIXME: what about scanners that take a long time to warm the lamp?
+ dev.interface->sleep_ms(500);
+ }
+
+ bool start_motor = !is_dark;
+ dev.cmd_set->begin_scan(&dev, sensor, &local_reg, start_motor);
+
+ if (is_testing_mode()) {
+ dev.interface->test_checkpoint(is_dark ? "host_dark_shading_calibration"
+ : "host_white_shading_calibration");
+ dev.cmd_set->end_scan(&dev, &local_reg, true);
+ return;
+ }
+
+ Image image = read_unshuffled_image_from_scanner(&dev, session, session.output_total_bytes_raw);
+ scanner_stop_action(dev);
+
+ auto start_offset = session.params.startx;
+ auto out_pixels_per_line = start_offset + session.output_pixels;
+
+ // FIXME: we set this during both dark and white calibration. A cleaner approach should
+ // probably be used
+ dev.average_size = session.params.channels * out_pixels_per_line;
+
+ out_average_data.clear();
+ out_average_data.resize(dev.average_size);
+
+ std::fill(out_average_data.begin(),
+ out_average_data.begin() + start_offset * session.params.channels, 0);
+
+ compute_array_percentile_approx(out_average_data.data() +
+ start_offset * session.params.channels,
+ reinterpret_cast<std::uint16_t*>(image.get_row_ptr(0)),
+ session.params.lines,
+ session.output_pixels * session.params.channels,
+ 0.5f);
+
+ if (dbg_log_image_data()) {
+ write_tiff_file(log_filename_prefix + "_host_shading.tiff", image);
+ write_tiff_file(log_filename_prefix + "_host_average.tiff", out_average_data.data(), 16,
+ session.params.channels, out_pixels_per_line, 1);
+ }
+}
+
+static void genesys_dark_shading_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& local_reg)
+{
+ DBG_HELPER(dbg);
+ if (has_flag(dev->model->flags, ModelFlag::HOST_SIDE_CALIBRATION_COMPLETE_SCAN)) {
+ genesys_host_shading_calibration_impl(*dev, sensor, dev->dark_average_data, true,
+ "gl_black");
+ } else {
+ genesys_shading_calibration_impl(dev, sensor, local_reg, dev->dark_average_data, true,
+ "gl_black");
+ }
+}
+
+static void genesys_white_shading_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& local_reg)
+{
+ DBG_HELPER(dbg);
+ if (has_flag(dev->model->flags, ModelFlag::HOST_SIDE_CALIBRATION_COMPLETE_SCAN)) {
+ genesys_host_shading_calibration_impl(*dev, sensor, dev->white_average_data, false,
+ "gl_white");
+ } else {
+ genesys_shading_calibration_impl(dev, sensor, local_reg, dev->white_average_data, false,
+ "gl_white");
+ }
}
// This calibration uses a scan over the calibration target, comprising a black and a white strip.
// (So the motor must be on.)
static void genesys_dark_white_shading_calibration(Genesys_Device* dev,
- const Genesys_Sensor& sensor)
+ const Genesys_Sensor& sensor,
+ Genesys_Register_Set& local_reg)
{
- DBG_HELPER_ARGS(dbg, "lines = %zu", dev->calib_lines);
+ DBG_HELPER(dbg);
+
+ if (dev->model->asic_type == AsicType::GL646) {
+ dev->cmd_set->init_regs_for_shading(dev, sensor, local_reg);
+ local_reg = dev->reg;
+ } else {
+ local_reg = dev->reg;
+ dev->cmd_set->init_regs_for_shading(dev, sensor, local_reg);
+ dev->interface->write_registers(local_reg);
+ }
+
size_t size;
uint32_t pixels_per_line;
- uint8_t channels;
unsigned int x;
uint32_t dark, white, dark_sum, white_sum, dark_count, white_count, col,
dif;
- pixels_per_line = dev->calib_pixels;
- channels = dev->calib_channels;
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843)
+ {
+ pixels_per_line = dev->calib_session.output_pixels;
+ } else {
+ pixels_per_line = dev->calib_session.params.pixels;
+ }
- uint32_t out_pixels_per_line = pixels_per_line + dev->calib_pixels_offset;
+ unsigned channels = dev->calib_session.params.channels;
+
+ // BUG: we are using wrong pixel number here
+ unsigned start_offset =
+ dev->calib_session.params.startx * sensor.full_resolution / dev->calib_session.params.xres;
+
+ unsigned out_pixels_per_line = pixels_per_line + start_offset;
dev->average_size = channels * out_pixels_per_line;
@@ -1862,68 +2704,65 @@ static void genesys_dark_white_shading_calibration(Genesys_Device* dev,
dev->dark_average_data.clear();
dev->dark_average_data.resize(dev->average_size);
- if (dev->calib_total_bytes_to_read > 0)
- size = dev->calib_total_bytes_to_read;
- else
- size = channels * 2 * pixels_per_line * dev->calib_lines;
-
- std::vector<uint8_t> calibration_data(size);
-
- bool motor = true;
- if (dev->model->flags & GENESYS_FLAG_SHADING_NO_MOVE)
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843)
{
- motor = false;
+ size = dev->calib_session.output_total_bytes_raw;
+ } else {
+ // FIXME: on GL841 this is different than dev->calib_session.output_total_bytes_raw,
+ // needs checking
+ size = channels * 2 * pixels_per_line * dev->calib_session.params.lines;
}
+ std::vector<uint8_t> calibration_data(size);
+
// turn on motor and lamp power
- sanei_genesys_set_lamp_power(dev, sensor, dev->calib_reg, true);
- sanei_genesys_set_motor_power(dev->calib_reg, motor);
+ sanei_genesys_set_lamp_power(dev, sensor, local_reg, true);
+ sanei_genesys_set_motor_power(local_reg, true);
- dev->interface->write_registers(dev->calib_reg);
+ dev->interface->write_registers(local_reg);
- dev->cmd_set->begin_scan(dev, sensor, &dev->calib_reg, false);
+ dev->cmd_set->begin_scan(dev, sensor, &local_reg, false);
if (is_testing_mode()) {
dev->interface->test_checkpoint("dark_white_shading_calibration");
- dev->cmd_set->end_scan(dev, &dev->calib_reg, true);
+ dev->cmd_set->end_scan(dev, &local_reg, true);
return;
}
sanei_genesys_read_data_from_scanner(dev, calibration_data.data(), size);
- dev->cmd_set->end_scan(dev, &dev->calib_reg, true);
+ dev->cmd_set->end_scan(dev, &local_reg, true);
- if (DBG_LEVEL >= DBG_data)
- {
- if (dev->model->is_cis)
- {
- sanei_genesys_write_pnm_file("gl_black_white_shading.pnm", calibration_data.data(),
- 16, 1, pixels_per_line*channels,
- dev->calib_lines);
- }
- else
- {
- sanei_genesys_write_pnm_file("gl_black_white_shading.pnm", calibration_data.data(),
- 16, channels, pixels_per_line,
- dev->calib_lines);
+ if (dbg_log_image_data()) {
+ if (dev->model->is_cis) {
+ write_tiff_file("gl_black_white_shading.tiff", calibration_data.data(),
+ 16, 1, pixels_per_line*channels,
+ dev->calib_session.params.lines);
+ } else {
+ write_tiff_file("gl_black_white_shading.tiff", calibration_data.data(),
+ 16, channels, pixels_per_line,
+ dev->calib_session.params.lines);
}
}
std::fill(dev->dark_average_data.begin(),
- dev->dark_average_data.begin() + dev->calib_pixels_offset * channels, 0);
+ dev->dark_average_data.begin() + start_offset * channels, 0);
std::fill(dev->white_average_data.begin(),
- dev->white_average_data.begin() + dev->calib_pixels_offset * channels, 0);
+ dev->white_average_data.begin() + start_offset * channels, 0);
- uint16_t* average_white = dev->white_average_data.data() + dev->calib_pixels_offset * channels;
- uint16_t* average_dark = dev->dark_average_data.data() + dev->calib_pixels_offset * channels;
+ uint16_t* average_white = dev->white_average_data.data() +
+ start_offset * channels;
+ uint16_t* average_dark = dev->dark_average_data.data() +
+ start_offset * channels;
for (x = 0; x < pixels_per_line * channels; x++)
{
dark = 0xffff;
white = 0;
- for (std::size_t y = 0; y < dev->calib_lines; y++)
+ for (std::size_t y = 0; y < dev->calib_session.params.lines; y++)
{
col = calibration_data[(x + y * pixels_per_line * channels) * 2];
col |=
@@ -1947,7 +2786,7 @@ static void genesys_dark_white_shading_calibration(Genesys_Device* dev,
white_count = 0;
white_sum = 0;
- for (std::size_t y = 0; y < dev->calib_lines; y++)
+ for (std::size_t y = 0; y < dev->calib_session.params.lines; y++)
{
col = calibration_data[(x + y * pixels_per_line * channels) * 2];
col |=
@@ -1974,11 +2813,11 @@ static void genesys_dark_white_shading_calibration(Genesys_Device* dev,
*average_white++ = white_sum;
}
- if (DBG_LEVEL >= DBG_data) {
- sanei_genesys_write_pnm_file16("gl_white_average.pnm", dev->white_average_data.data(),
- channels, out_pixels_per_line, 1);
- sanei_genesys_write_pnm_file16("gl_dark_average.pnm", dev->dark_average_data.data(),
- channels, out_pixels_per_line, 1);
+ if (dbg_log_image_data()) {
+ write_tiff_file("gl_white_average.tiff", dev->white_average_data.data(), 16, channels,
+ out_pixels_per_line, 1);
+ write_tiff_file("gl_dark_average.tiff", dev->dark_average_data.data(), 16, channels,
+ out_pixels_per_line, 1);
}
}
@@ -2085,13 +2924,12 @@ compute_averaged_planar (Genesys_Device * dev, const Genesys_Sensor& sensor,
*/
res = dev->settings.xres;
- if (sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres) > 1)
- {
+ if (sensor.full_resolution > sensor.get_optical_resolution()) {
res *= 2;
}
- /* this should be evenly dividable */
- basepixels = sensor.optical_res / res;
+ // this should be evenly dividable
+ basepixels = sensor.full_resolution / res;
/* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */
if (basepixels < 1)
@@ -2376,9 +3214,10 @@ compute_shifted_coefficients (Genesys_Device * dev,
auto cmat = color_order_to_cmat(color_order);
x = dev->settings.xres;
- if (sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres) > 1)
- x *= 2; /* scanner is using half-ccd mode */
- basepixels = sensor.optical_res / x; /*this should be evenly dividable */
+ if (sensor.full_resolution > sensor.get_optical_resolution()) {
+ x *= 2; // scanner is using half-ccd mode
+ }
+ basepixels = sensor.full_resolution / x; // this should be evenly dividable
/* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */
if (basepixels < 1)
@@ -2451,19 +3290,30 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
{
DBG_HELPER(dbg);
- if (dev->model->flags & GENESYS_FLAG_CALIBRATION_HOST_SIDE) {
+ if (sensor.use_host_side_calib) {
return;
}
uint32_t pixels_per_line;
- uint8_t channels;
int o;
unsigned int length; /**> number of shading calibration data words */
unsigned int factor;
unsigned int coeff, target_code, words_per_color = 0;
- pixels_per_line = dev->calib_pixels + dev->calib_pixels_offset;
- channels = dev->calib_channels;
+
+ // BUG: we are using wrong pixel number here
+ unsigned start_offset =
+ dev->calib_session.params.startx * sensor.full_resolution / dev->calib_session.params.xres;
+
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843)
+ {
+ pixels_per_line = dev->calib_session.output_pixels + start_offset;
+ } else {
+ pixels_per_line = dev->calib_session.params.pixels + start_offset;
+ }
+
+ unsigned channels = dev->calib_session.params.channels;
/* we always build data for three channels, even for gray
* we make the shading data such that each color channel data line is contiguous
@@ -2504,25 +3354,27 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
// contains 16bit words in little endian
std::vector<uint8_t> shading_data(length, 0);
+ if (!dev->calib_session.computed) {
+ genesys_send_offset_and_shading(dev, sensor, shading_data.data(), length);
+ return;
+ }
+
/* TARGET/(Wn-Dn) = white gain -> ~1.xxx then it is multiplied by 0x2000
or 0x4000 to give an integer
Wn = white average for column n
Dn = dark average for column n
*/
- if (get_registers_gain4_bit(dev->model->asic_type, dev->calib_reg)) {
+ if (get_registers_gain4_bit(dev->model->asic_type, dev->reg)) {
coeff = 0x4000;
} else {
coeff = 0x2000;
}
/* compute avg factor */
- if(dev->settings.xres>sensor.optical_res)
- {
- factor=1;
- }
- else
- {
- factor=sensor.optical_res/dev->settings.xres;
+ if (dev->settings.xres > sensor.full_resolution) {
+ factor = 1;
+ } else {
+ factor = sensor.full_resolution / dev->settings.xres;
}
/* for GL646, shading data is planar if REG_0x01_FASTMOD is set and
@@ -2536,6 +3388,7 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
switch (dev->model->sensor_id)
{
case SensorId::CCD_XP300:
+ case SensorId::CCD_DOCKETPORT_487:
case SensorId::CCD_ROADWARRIOR:
case SensorId::CCD_DP665:
case SensorId::CCD_DP685:
@@ -2570,10 +3423,9 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
case SensorId::CCD_HP2300:
target_code = 0xdc00;
o = 2;
- if(dev->settings.xres<=sensor.optical_res/2)
- {
- o = o - sensor.dummy_pixel / 2;
- }
+ if (dev->settings.xres <= sensor.full_resolution / 2) {
+ o = o - sensor.dummy_pixel / 2;
+ }
compute_coefficients (dev,
shading_data.data(),
pixels_per_line,
@@ -2586,7 +3438,7 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
case SensorId::CCD_5345:
target_code = 0xe000;
o = 4;
- if(dev->settings.xres<=sensor.optical_res/2)
+ if(dev->settings.xres<=sensor.full_resolution/2)
{
o = o - sensor.dummy_pixel;
}
@@ -2633,9 +3485,12 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
case SensorId::CCD_CANON_4400F:
case SensorId::CCD_CANON_8400F:
case SensorId::CCD_CANON_8600F:
+ case SensorId::CCD_PLUSTEK_OPTICFILM_7200:
case SensorId::CCD_PLUSTEK_OPTICFILM_7200I:
case SensorId::CCD_PLUSTEK_OPTICFILM_7300:
+ case SensorId::CCD_PLUSTEK_OPTICFILM_7400:
case SensorId::CCD_PLUSTEK_OPTICFILM_7500I:
+ case SensorId::CCD_PLUSTEK_OPTICFILM_8200I:
target_code = 0xe000;
o = 0;
compute_coefficients (dev,
@@ -2654,6 +3509,7 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
case SensorId::CIS_CANON_LIDE_120:
case SensorId::CIS_CANON_LIDE_210:
case SensorId::CIS_CANON_LIDE_220:
+ case SensorId::CCD_CANON_5600F:
/* TODO store this in a data struct so we avoid
* growing this switch */
switch(dev->model->sensor_id)
@@ -2684,6 +3540,8 @@ static void genesys_send_shading_coefficient(Genesys_Device* dev, const Genesys_
target_code);
break;
case SensorId::CIS_CANON_LIDE_35:
+ case SensorId::CIS_CANON_LIDE_60:
+ case SensorId::CIS_CANON_LIDE_90:
compute_averaged_planar (dev, sensor,
shading_data.data(),
pixels_per_line,
@@ -2756,9 +3614,8 @@ genesys_restore_calibration(Genesys_Device * dev, Genesys_Sensor& sensor)
/* we don't restore the gamma fields */
sensor.exposure = cache.sensor.exposure;
+ dev->calib_session = cache.session;
dev->average_size = cache.average_size;
- dev->calib_pixels = cache.calib_pixels;
- dev->calib_channels = cache.calib_channels;
dev->dark_average_data = cache.dark_average_data;
dev->white_average_data = cache.white_average_data;
@@ -2812,8 +3669,7 @@ static void genesys_save_calibration(Genesys_Device* dev, const Genesys_Sensor&
found_cache_it->frontend = dev->frontend;
found_cache_it->sensor = sensor;
- found_cache_it->calib_pixels = dev->calib_pixels;
- found_cache_it->calib_channels = dev->calib_channels;
+ found_cache_it->session = dev->calib_session;
#ifdef HAVE_SYS_TIME_H
gettimeofday(&time, nullptr);
@@ -2821,20 +3677,13 @@ static void genesys_save_calibration(Genesys_Device* dev, const Genesys_Sensor&
#endif
}
-/**
- * does the calibration process for a flatbed scanner
- * - offset calibration
- * - gain calibration
- * - shading calibration
- * @param dev device to calibrate
- */
static void genesys_flatbed_calibration(Genesys_Device* dev, Genesys_Sensor& sensor)
{
DBG_HELPER(dbg);
- uint32_t pixels_per_line;
+ uint32_t pixels_per_line;
- unsigned coarse_res = sensor.optical_res;
- if (dev->settings.yres <= sensor.optical_res / 2) {
+ unsigned coarse_res = sensor.full_resolution;
+ if (dev->settings.yres <= sensor.full_resolution / 2) {
coarse_res /= 2;
}
@@ -2848,35 +3697,29 @@ static void genesys_flatbed_calibration(Genesys_Device* dev, Genesys_Sensor& sen
coarse_res = 1200;
}
- /* do offset calibration if needed */
- if (dev->model->flags & GENESYS_FLAG_OFFSET_CALIBRATION)
- {
+ auto local_reg = dev->initial_regs;
+
+ if (!has_flag(dev->model->flags, ModelFlag::DISABLE_ADC_CALIBRATION)) {
+ // do ADC calibration first.
dev->interface->record_progress_message("offset_calibration");
- dev->cmd_set->offset_calibration(dev, sensor, dev->calib_reg);
+ dev->cmd_set->offset_calibration(dev, sensor, local_reg);
- /* since all the registers are set up correctly, just use them */
dev->interface->record_progress_message("coarse_gain_calibration");
- dev->cmd_set->coarse_gain_calibration(dev, sensor, dev->calib_reg, coarse_res);
- } else {
- /* since we have 2 gain calibration proc, skip second if first one was
- used. */
- dev->interface->record_progress_message("init_regs_for_coarse_calibration");
- dev->cmd_set->init_regs_for_coarse_calibration(dev, sensor, dev->calib_reg);
-
- dev->interface->record_progress_message("genesys_coarse_calibration");
- genesys_coarse_calibration(dev, sensor);
+ dev->cmd_set->coarse_gain_calibration(dev, sensor, local_reg, coarse_res);
}
- if (dev->model->is_cis)
+ if (dev->model->is_cis &&
+ !has_flag(dev->model->flags, ModelFlag::DISABLE_EXPOSURE_CALIBRATION))
{
- /* the afe now sends valid data for doing led calibration */
+ // ADC now sends correct data, we can configure the exposure for the LEDs
dev->interface->record_progress_message("led_calibration");
switch (dev->model->asic_type) {
case AsicType::GL124:
+ case AsicType::GL841:
case AsicType::GL845:
case AsicType::GL846:
case AsicType::GL847: {
- auto calib_exposure = dev->cmd_set->led_calibration(dev, sensor, dev->calib_reg);
+ auto calib_exposure = dev->cmd_set->led_calibration(dev, sensor, local_reg);
for (auto& sensor_update :
sanei_genesys_find_sensors_all_for_write(dev, sensor.method)) {
sensor_update.get().exposure = calib_exposure;
@@ -2885,80 +3728,66 @@ static void genesys_flatbed_calibration(Genesys_Device* dev, Genesys_Sensor& sen
break;
}
default: {
- sensor.exposure = dev->cmd_set->led_calibration(dev, sensor, dev->calib_reg);
+ sensor.exposure = dev->cmd_set->led_calibration(dev, sensor, local_reg);
}
}
-
- /* calibrate afe again to match new exposure */
- if (dev->model->flags & GENESYS_FLAG_OFFSET_CALIBRATION) {
+ if (!has_flag(dev->model->flags, ModelFlag::DISABLE_ADC_CALIBRATION)) {
+ // recalibrate ADC again for the new LED exposure
dev->interface->record_progress_message("offset_calibration");
- dev->cmd_set->offset_calibration(dev, sensor, dev->calib_reg);
-
- // since all the registers are set up correctly, just use them
+ dev->cmd_set->offset_calibration(dev, sensor, local_reg);
dev->interface->record_progress_message("coarse_gain_calibration");
- dev->cmd_set->coarse_gain_calibration(dev, sensor, dev->calib_reg, coarse_res);
- } else {
- // since we have 2 gain calibration proc, skip second if first one was used
- dev->interface->record_progress_message("init_regs_for_coarse_calibration");
- dev->cmd_set->init_regs_for_coarse_calibration(dev, sensor, dev->calib_reg);
-
- dev->interface->record_progress_message("genesys_coarse_calibration");
- genesys_coarse_calibration(dev, sensor);
+ dev->cmd_set->coarse_gain_calibration(dev, sensor, local_reg, coarse_res);
}
}
/* we always use sensor pixel number when the ASIC can't handle multi-segments sensor */
- if (!(dev->model->flags & GENESYS_FLAG_SIS_SENSOR))
- {
+ if (!has_flag(dev->model->flags, ModelFlag::SIS_SENSOR)) {
pixels_per_line = static_cast<std::uint32_t>((dev->model->x_size * dev->settings.xres) /
MM_PER_INCH);
- }
- else
- {
- pixels_per_line = sensor.sensor_pixels;
+ } else {
+ pixels_per_line = static_cast<std::uint32_t>((dev->model->x_size_calib_mm * dev->settings.xres)
+ / MM_PER_INCH);
}
// send default shading data
dev->interface->record_progress_message("sanei_genesys_init_shading_data");
sanei_genesys_init_shading_data(dev, sensor, pixels_per_line);
- if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
- {
- dev->cmd_set->move_to_ta(dev);
- }
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ scanner_move_to_ta(*dev);
+ }
// shading calibration
- if (dev->model->flags & GENESYS_FLAG_DARK_WHITE_CALIBRATION) {
- dev->interface->record_progress_message("init_regs_for_shading");
- dev->cmd_set->init_regs_for_shading(dev, sensor, dev->calib_reg);
-
- dev->interface->record_progress_message("genesys_dark_white_shading_calibration");
- genesys_dark_white_shading_calibration(dev, sensor);
- } else {
- DBG(DBG_proc, "%s : genesys_dark_shading_calibration dev->calib_reg ", __func__);
- debug_dump(DBG_proc, dev->calib_reg);
-
- if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) {
- dev->interface->record_progress_message("init_regs_for_shading");
- dev->cmd_set->init_regs_for_shading(dev, sensor, dev->calib_reg);
+ if (!has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION)) {
+ if (has_flag(dev->model->flags, ModelFlag::DARK_WHITE_CALIBRATION)) {
+ dev->interface->record_progress_message("genesys_dark_white_shading_calibration");
+ genesys_dark_white_shading_calibration(dev, sensor, local_reg);
+ } else {
+ DBG(DBG_proc, "%s : genesys_dark_shading_calibration local_reg ", __func__);
+ debug_dump(DBG_proc, local_reg);
- dev->interface->record_progress_message("genesys_dark_shading_calibration");
- genesys_dark_shading_calibration(dev, sensor);
- genesys_repark_sensor_before_shading(dev);
- }
+ if (has_flag(dev->model->flags, ModelFlag::DARK_CALIBRATION)) {
+ dev->interface->record_progress_message("genesys_dark_shading_calibration");
+ genesys_dark_shading_calibration(dev, sensor, local_reg);
+ genesys_repark_sensor_before_shading(dev);
+ }
- dev->interface->record_progress_message("init_regs_for_shading2");
- dev->cmd_set->init_regs_for_shading(dev, sensor, dev->calib_reg);
+ dev->interface->record_progress_message("genesys_white_shading_calibration");
+ genesys_white_shading_calibration(dev, sensor, local_reg);
- dev->interface->record_progress_message("genesys_white_shading_calibration");
- genesys_white_shading_calibration(dev, sensor);
- genesys_repark_sensor_after_white_shading(dev);
+ genesys_repark_sensor_after_white_shading(dev);
- if (!(dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION)) {
- genesys_dummy_dark_shading(dev, sensor);
+ if (!has_flag(dev->model->flags, ModelFlag::DARK_CALIBRATION)) {
+ if (has_flag(dev->model->flags, ModelFlag::USE_CONSTANT_FOR_DARK_CALIBRATION)) {
+ genesys_dark_shading_by_constant(*dev);
+ } else {
+ genesys_dark_shading_by_dummy_pixel(dev, sensor);
+ }
+ }
}
}
@@ -2982,68 +3811,62 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
DBG_HELPER(dbg);
bool forward = true;
+ auto local_reg = dev->initial_regs;
+
// first step, load document
dev->cmd_set->load_document(dev);
- /* led, offset and gain calibration are influenced by scan
- * settings. So we set it to sensor resolution */
- dev->settings.xres = sensor.optical_res;
- /* XP200 needs to calibrate a full and half sensor's resolution */
- if (dev->model->sensor_id == SensorId::CIS_XP200 &&
- dev->settings.xres <= sensor.optical_res / 2)
- {
- dev->settings.xres /= 2;
- }
+ unsigned coarse_res = sensor.full_resolution;
/* the afe needs to sends valid data even before calibration */
/* go to a white area */
try {
- dev->cmd_set->search_strip(dev, sensor, forward, false);
+ scanner_search_strip(*dev, forward, false);
} catch (...) {
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
throw;
}
- if (dev->model->is_cis)
- {
- dev->cmd_set->led_calibration(dev, sensor, dev->calib_reg);
+ if (!has_flag(dev->model->flags, ModelFlag::DISABLE_ADC_CALIBRATION)) {
+ // do ADC calibration first.
+ dev->interface->record_progress_message("offset_calibration");
+ dev->cmd_set->offset_calibration(dev, sensor, local_reg);
+
+ dev->interface->record_progress_message("coarse_gain_calibration");
+ dev->cmd_set->coarse_gain_calibration(dev, sensor, local_reg, coarse_res);
}
- /* calibrate afe */
- if (dev->model->flags & GENESYS_FLAG_OFFSET_CALIBRATION)
+ if (dev->model->is_cis &&
+ !has_flag(dev->model->flags, ModelFlag::DISABLE_EXPOSURE_CALIBRATION))
{
- dev->cmd_set->offset_calibration(dev, sensor, dev->calib_reg);
-
- /* since all the registers are set up correctly, just use them */
+ // ADC now sends correct data, we can configure the exposure for the LEDs
+ dev->interface->record_progress_message("led_calibration");
+ dev->cmd_set->led_calibration(dev, sensor, local_reg);
- dev->cmd_set->coarse_gain_calibration(dev, sensor, dev->calib_reg, sensor.optical_res);
- }
- else
- /* since we have 2 gain calibration proc, skip second if first one was
- used. */
- {
- dev->cmd_set->init_regs_for_coarse_calibration(dev, sensor, dev->calib_reg);
+ if (!has_flag(dev->model->flags, ModelFlag::DISABLE_ADC_CALIBRATION)) {
+ // recalibrate ADC again for the new LED exposure
+ dev->interface->record_progress_message("offset_calibration");
+ dev->cmd_set->offset_calibration(dev, sensor, local_reg);
- genesys_coarse_calibration(dev, sensor);
+ dev->interface->record_progress_message("coarse_gain_calibration");
+ dev->cmd_set->coarse_gain_calibration(dev, sensor, local_reg, coarse_res);
+ }
}
/* search for a full width black strip and then do a 16 bit scan to
* gather black shading data */
- if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION)
- {
- /* seek black/white reverse/forward */
+ if (has_flag(dev->model->flags, ModelFlag::DARK_CALIBRATION)) {
+ // seek black/white reverse/forward
try {
- dev->cmd_set->search_strip(dev, sensor, forward, true);
+ scanner_search_strip(*dev, forward, true);
} catch (...) {
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
throw;
}
- dev->cmd_set->init_regs_for_shading(dev, sensor, dev->calib_reg);
-
try {
- genesys_dark_shading_calibration(dev, sensor);
+ genesys_dark_shading_calibration(dev, sensor, local_reg);
} catch (...) {
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
throw;
@@ -3054,7 +3877,7 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
/* go to a white area */
try {
- dev->cmd_set->search_strip(dev, sensor, forward, false);
+ scanner_search_strip(*dev, forward, false);
} catch (...) {
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
throw;
@@ -3062,10 +3885,8 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
genesys_repark_sensor_before_shading(dev);
- dev->cmd_set->init_regs_for_shading(dev, sensor, dev->calib_reg);
-
try {
- genesys_white_shading_calibration(dev, sensor);
+ genesys_white_shading_calibration(dev, sensor, local_reg);
genesys_repark_sensor_after_white_shading(dev);
} catch (...) {
catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
@@ -3073,17 +3894,9 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
}
// in case we haven't black shading data, build it from black pixels of white calibration
- // FIXME: shouldn't we use genesys_dummy_dark_shading() ?
- if (!(dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION)) {
- dev->dark_average_data.clear();
- dev->dark_average_data.resize(dev->average_size, 0x0f0f);
- /* XXX STEF XXX
- * with black point in white shading, build an average black
- * pixel and use it to fill the dark_average
- * dev->calib_pixels
- (sensor.sensor_pixels * dev->settings.xres) / sensor.optical_res,
- dev->calib_lines,
- */
+ // FIXME: shouldn't we use genesys_dark_shading_by_dummy_pixel() ?
+ if (!has_flag(dev->model->flags, ModelFlag::DARK_CALIBRATION)) {
+ genesys_dark_shading_by_constant(*dev);
}
/* send the shading coefficient when doing whole line shading
@@ -3099,7 +3912,7 @@ static void genesys_sheetfed_calibration(Genesys_Device* dev, Genesys_Sensor& se
dev->cmd_set->eject_document(dev);
// restore settings
- dev->settings.xres = sensor.optical_res;
+ dev->settings.xres = sensor.full_resolution;
}
/**
@@ -3129,22 +3942,23 @@ static void genesys_warmup_lamp(Genesys_Device* dev)
{
DBG_HELPER(dbg);
unsigned seconds = 0;
- int pixel;
- int channels, total_size;
- double first_average = 0;
- double second_average = 0;
- int difference = 255;
- int lines = 3;
const auto& sensor = sanei_genesys_find_sensor_any(dev);
- dev->cmd_set->init_regs_for_warmup(dev, sensor, &dev->reg, &channels, &total_size);
+ dev->cmd_set->init_regs_for_warmup(dev, sensor, &dev->reg);
+ dev->interface->write_registers(dev->reg);
+
+ auto total_pixels = dev->session.output_pixels;
+ auto total_size = dev->session.output_line_bytes;
+ auto channels = dev->session.params.channels;
+ auto lines = dev->session.output_line_count;
+
std::vector<uint8_t> first_line(total_size);
std::vector<uint8_t> second_line(total_size);
- do
- {
- DBG(DBG_info, "%s: one more loop\n", __func__);
+ do {
+ first_line = second_line;
+
dev->cmd_set->begin_scan(dev, sensor, &dev->reg, false);
if (is_testing_mode()) {
@@ -3155,72 +3969,44 @@ static void genesys_warmup_lamp(Genesys_Device* dev)
wait_until_buffer_non_empty(dev);
- try {
- sanei_genesys_read_data_from_scanner(dev, first_line.data(), total_size);
- } catch (...) {
- // FIXME: document why this retry is here
- sanei_genesys_read_data_from_scanner(dev, first_line.data(), total_size);
- }
-
+ sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
dev->cmd_set->end_scan(dev, &dev->reg, true);
- dev->interface->sleep_ms(1000);
- seconds++;
+ // compute difference between the two scans
+ double first_average = 0;
+ double second_average = 0;
+ for (unsigned pixel = 0; pixel < total_size; pixel++) {
+ // 16 bit data
+ if (dev->session.params.depth == 16) {
+ first_average += (first_line[pixel] + first_line[pixel + 1] * 256);
+ second_average += (second_line[pixel] + second_line[pixel + 1] * 256);
+ pixel++;
+ } else {
+ first_average += first_line[pixel];
+ second_average += second_line[pixel];
+ }
+ }
- dev->cmd_set->begin_scan(dev, sensor, &dev->reg, false);
+ first_average /= total_pixels;
+ second_average /= total_pixels;
- wait_until_buffer_non_empty(dev);
+ if (dbg_log_image_data()) {
+ write_tiff_file("gl_warmup1.tiff", first_line.data(), dev->session.params.depth,
+ channels, total_size / (lines * channels), lines);
+ write_tiff_file("gl_warmup2.tiff", second_line.data(), dev->session.params.depth,
+ channels, total_size / (lines * channels), lines);
+ }
- sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
- dev->cmd_set->end_scan(dev, &dev->reg, true);
+ DBG(DBG_info, "%s: average 1 = %.2f, average 2 = %.2f\n", __func__, first_average,
+ second_average);
- /* compute difference between the two scans */
- for (pixel = 0; pixel < total_size; pixel++)
- {
- // 16 bit data
- if (dev->session.params.depth == 16) {
- first_average += (first_line[pixel] + first_line[pixel + 1] * 256);
- second_average += (second_line[pixel] + second_line[pixel + 1] * 256);
- pixel++;
- }
- else
- {
- first_average += first_line[pixel];
- second_average += second_line[pixel];
- }
- }
- if (dev->session.params.depth == 16) {
- first_average /= pixel;
- second_average /= pixel;
- difference = static_cast<int>(std::fabs(first_average - second_average));
- DBG(DBG_info, "%s: average = %.2f, diff = %.3f\n", __func__,
- 100 * ((second_average) / (256 * 256)),
- 100 * (difference / second_average));
-
- if (second_average > (100 * 256)
- && (difference / second_average) < 0.002)
- break;
- }
- else
- {
- first_average /= pixel;
- second_average /= pixel;
- if (DBG_LEVEL >= DBG_data)
- {
- sanei_genesys_write_pnm_file("gl_warmup1.pnm", first_line.data(), 8, channels,
- total_size / (lines * channels), lines);
- sanei_genesys_write_pnm_file("gl_warmup2.pnm", second_line.data(), 8, channels,
- total_size / (lines * channels), lines);
- }
- DBG(DBG_info, "%s: average 1 = %.2f, average 2 = %.2f\n", __func__, first_average,
- second_average);
- /* if delta below 15/255 ~= 5.8%, lamp is considred warm enough */
- if (fabs (first_average - second_average) < 15
- && second_average > 55)
- break;
- }
+ float average_difference = std::fabs(first_average - second_average) / second_average;
+ if (second_average > 0 && average_difference < 0.005)
+ {
+ dbg.vlog(DBG_info, "difference: %f, exiting", average_difference);
+ break;
+ }
- /* sleep another second before next loop */
dev->interface->sleep_ms(1000);
seconds++;
} while (seconds < WARMUP_TIME);
@@ -3236,6 +4022,37 @@ static void genesys_warmup_lamp(Genesys_Device* dev)
}
}
+static void init_regs_for_scan(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs)
+{
+ DBG_HELPER(dbg);
+ debug_dump(DBG_info, dev.settings);
+
+ auto session = dev.cmd_set->calculate_scan_session(&dev, sensor, dev.settings);
+
+ if (dev.model->asic_type == AsicType::GL124 ||
+ dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL847)
+ {
+ /* Fast move to scan area:
+
+ We don't move fast the whole distance since it would involve computing
+ acceleration/deceleration distance for scan resolution. So leave a remainder for it so
+ scan makes the final move tuning
+ */
+
+ if (dev.settings.get_channels() * dev.settings.yres >= 600 && session.params.starty > 700) {
+ scanner_move(dev, dev.model->default_method,
+ static_cast<unsigned>(session.params.starty - 500),
+ Direction::FORWARD);
+ session.params.starty = 500;
+ }
+ compute_session(&dev, session, sensor);
+ }
+
+ dev.cmd_set->init_regs_for_scan_session(&dev, sensor, &regs, session);
+}
// High-level start of scanning
static void genesys_start_scan(Genesys_Device* dev, bool lamp_off)
@@ -3243,6 +4060,7 @@ static void genesys_start_scan(Genesys_Device* dev, bool lamp_off)
DBG_HELPER(dbg);
unsigned int steps, expected;
+
/* since not all scanners are set ot wait for head to park
* we check we are not still parking before starting a new scan */
if (dev->parking) {
@@ -3254,38 +4072,30 @@ static void genesys_start_scan(Genesys_Device* dev, bool lamp_off)
/* wait for lamp warmup : until a warmup for TRANSPARENCY is designed, skip
* it when scanning from XPA. */
- if (!(dev->model->flags & GENESYS_FLAG_SKIP_WARMUP)
- && (dev->settings.scan_method == ScanMethod::FLATBED))
+ if (has_flag(dev->model->flags, ModelFlag::WARMUP) &&
+ (dev->settings.scan_method != ScanMethod::TRANSPARENCY_INFRARED))
{
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ scanner_move_to_ta(*dev);
+ }
+
genesys_warmup_lamp(dev);
}
/* set top left x and y values by scanning the internals if flatbed scanners */
if (!dev->model->is_sheetfed) {
- /* do the geometry detection only once */
- if ((dev->model->flags & GENESYS_FLAG_SEARCH_START)
- && (dev->model->y_offset_calib_white == 0))
- {
- dev->cmd_set->search_start_position (dev);
-
- dev->parking = false;
- dev->cmd_set->move_back_home(dev, true);
- }
- else
- {
- /* Go home */
- /* TODO: check we can drop this since we cannot have the
- scanner's head wandering here */
- dev->parking = false;
- dev->cmd_set->move_back_home(dev, true);
- }
+ // TODO: check we can drop this since we cannot have the scanner's head wandering here
+ dev->parking = false;
+ dev->cmd_set->move_back_home(dev, true);
}
/* move to calibration area for transparency adapter */
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- dev->cmd_set->move_to_ta(dev);
+ scanner_move_to_ta(*dev);
}
/* load document if needed (for sheetfed scanner for instance) */
@@ -3304,22 +4114,18 @@ static void genesys_start_scan(Genesys_Device* dev, bool lamp_off)
/* try to use cached calibration first */
if (!genesys_restore_calibration (dev, sensor))
{
- /* calibration : sheetfed scanners can't calibrate before each scan */
- /* and also those who have the NO_CALIBRATION flag */
- if (!(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION) && !dev->model->is_sheetfed) {
+ // calibration : sheetfed scanners can't calibrate before each scan.
+ // also don't run calibration for those scanners where all passes are disabled
+ bool shading_disabled =
+ has_flag(dev->model->flags, ModelFlag::DISABLE_ADC_CALIBRATION) &&
+ has_flag(dev->model->flags, ModelFlag::DISABLE_EXPOSURE_CALIBRATION) &&
+ has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION);
+ if (!shading_disabled && !dev->model->is_sheetfed) {
genesys_scanner_calibration(dev, sensor);
- genesys_save_calibration (dev, sensor);
- }
- else
- {
+ genesys_save_calibration(dev, sensor);
+ } else {
DBG(DBG_warn, "%s: no calibration done\n", __func__);
- }
- }
-
- /* build look up table for dynamic lineart */
- if (dev->settings.scan_mode == ScanColorMode::LINEART) {
- sanei_genesys_load_lut(dev->lineart_lut, 8, 8, 50, 205, dev->settings.threshold_curve,
- dev->settings.threshold-127);
+ }
}
dev->cmd_set->wait_for_motor_stop(dev);
@@ -3331,10 +4137,10 @@ static void genesys_start_scan(Genesys_Device* dev, bool lamp_off)
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- dev->cmd_set->move_to_ta(dev);
+ scanner_move_to_ta(*dev);
}
- dev->cmd_set->init_regs_for_scan(dev, sensor);
+ init_regs_for_scan(*dev, sensor, dev->reg);
/* no lamp during scan */
if (lamp_off) {
@@ -3344,7 +4150,7 @@ static void genesys_start_scan(Genesys_Device* dev, bool lamp_off)
/* GL124 is using SHDAREA, so we have to wait for scan to be set up before
* sending shading data */
if (dev->cmd_set->has_send_shading_data() &&
- !(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
+ !has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION))
{
genesys_send_shading_coefficient(dev, sensor);
}
@@ -3386,33 +4192,6 @@ static void genesys_start_scan(Genesys_Device* dev, bool lamp_off)
}
}
-static void genesys_fill_read_buffer(Genesys_Device* dev)
-{
- DBG_HELPER(dbg);
-
- /* for sheetfed scanner, we must check is document is shorter than
- * the requested scan */
- if (dev->model->is_sheetfed) {
- dev->cmd_set->detect_document_end(dev);
- }
-
- std::size_t size = dev->read_buffer.size() - dev->read_buffer.avail();
-
- /* due to sensors and motors, not all data can be directly used. It
- * may have to be read from another intermediate buffer and then processed.
- * There are currently 3 intermediate stages:
- * - handling of odd/even sensors
- * - handling of line interpolation for motors that can't have low
- * enough dpi
- * - handling of multi-segments sensors
- *
- * This is also the place where full duplex data will be handled.
- */
- dev->pipeline_buffer.get_data(size, dev->read_buffer.get_write_pos(size));
-
- dev->read_buffer.produce(size);
-}
-
/* this function does the effective data read in a manner that suits
the scanner. It does data reordering and resizing if need.
It also manages EOF and I/O errors, and line distance correction.
@@ -3422,8 +4201,6 @@ static void genesys_read_ordered_data(Genesys_Device* dev, SANE_Byte* destinatio
{
DBG_HELPER(dbg);
size_t bytes = 0;
- uint8_t *work_buffer_src;
- Genesys_Buffer *src_buffer;
if (!dev->read_active) {
*len = 0;
@@ -3439,7 +4216,7 @@ static void genesys_read_ordered_data(Genesys_Device* dev, SANE_Byte* destinatio
{
/* issue park command immediatly in case scanner can handle it
* so we save time */
- if (!dev->model->is_sheetfed && !(dev->model->flags & GENESYS_FLAG_MUST_WAIT) &&
+ if (!dev->model->is_sheetfed && !has_flag(dev->model->flags, ModelFlag::MUST_WAIT) &&
!dev->parking)
{
dev->cmd_set->move_back_home(dev, false);
@@ -3448,61 +4225,22 @@ static void genesys_read_ordered_data(Genesys_Device* dev, SANE_Byte* destinatio
throw SaneException(SANE_STATUS_EOF, "nothing more to scan: EOF");
}
-/* convert data */
-/*
- 0. fill_read_buffer
--------------- read_buffer ----------------------
- 1a). (opt)uncis (assumes color components to be laid out
- planar)
- 1b). (opt)reverse_RGB (assumes pixels to be BGR or BBGGRR))
--------------- lines_buffer ----------------------
- 2a). (opt)line_distance_correction (assumes RGB or RRGGBB)
- 2b). (opt)unstagger (assumes pixels to be depth*channels/8
- bytes long, unshrinked)
-------------- shrink_buffer ---------------------
- 3. (opt)shrink_lines (assumes component separation in pixels)
--------------- out_buffer -----------------------
- 4. memcpy to destination (for lineart with bit reversal)
-*/
-/*FIXME: for lineart we need sub byte addressing in buffers, or conversion to
- bytes at 0. and back to bits at 4.
-Problems with the first approach:
- - its not clear how to check if we need to output an incomplete byte
- because it is the last one.
- */
-/*FIXME: add lineart support for gl646. in the meantime add logic to convert
- from gray to lineart at the end? would suffer the above problem,
- total_bytes_to_read and total_bytes_read help in that case.
- */
-
if (is_testing_mode()) {
if (dev->total_bytes_read + *len > dev->total_bytes_to_read) {
*len = dev->total_bytes_to_read - dev->total_bytes_read;
}
dev->total_bytes_read += *len;
} else {
- genesys_fill_read_buffer(dev);
-
- src_buffer = &(dev->read_buffer);
-
- /* move data to destination */
- bytes = std::min(src_buffer->avail(), *len);
-
- work_buffer_src = src_buffer->get_read_pos();
-
- std::memcpy(destination, work_buffer_src, bytes);
- *len = bytes;
+ if (dev->model->is_sheetfed) {
+ dev->cmd_set->detect_document_end(dev);
+ }
- /* avoid signaling some extra data because we have treated a full block
- * on the last block */
if (dev->total_bytes_read + *len > dev->total_bytes_to_read) {
*len = dev->total_bytes_to_read - dev->total_bytes_read;
}
- /* count bytes sent to frontend */
+ dev->pipeline_buffer.get_data(*len, destination);
dev->total_bytes_read += *len;
-
- src_buffer->consume(bytes);
}
/* end scan if all needed data have been read */
@@ -3576,181 +4314,113 @@ static unsigned pick_resolution(const std::vector<unsigned>& resolutions, unsign
return best_res;
}
-static void calc_parameters(Genesys_Scanner* s)
+static Genesys_Settings calculate_scan_settings(Genesys_Scanner* s)
{
DBG_HELPER(dbg);
- double tl_x = 0, tl_y = 0, br_x = 0, br_y = 0;
- tl_x = SANE_UNFIX(s->pos_top_left_x);
- tl_y = SANE_UNFIX(s->pos_top_left_y);
- br_x = SANE_UNFIX(s->pos_bottom_right_x);
- br_y = SANE_UNFIX(s->pos_bottom_right_y);
+ const auto* dev = s->dev;
+ Genesys_Settings settings;
+ settings.scan_method = s->scan_method;
+ settings.scan_mode = option_string_to_scan_color_mode(s->mode);
- s->params.last_frame = true; /* only single pass scanning supported */
+ settings.depth = s->bit_depth;
- if (s->mode == SANE_VALUE_SCAN_MODE_GRAY || s->mode == SANE_VALUE_SCAN_MODE_LINEART) {
- s->params.format = SANE_FRAME_GRAY;
- } else {
- s->params.format = SANE_FRAME_RGB;
+ if (settings.depth > 8) {
+ settings.depth = 16;
+ } else if (settings.depth < 8) {
+ settings.depth = 1;
}
- if (s->mode == SANE_VALUE_SCAN_MODE_LINEART) {
- s->params.depth = 1;
- } else {
- s->params.depth = s->bit_depth;
- }
-
- s->dev->settings.scan_method = s->scan_method;
- const auto& resolutions = s->dev->model->get_resolution_settings(s->dev->settings.scan_method);
-
- s->dev->settings.depth = s->bit_depth;
+ const auto& resolutions = dev->model->get_resolution_settings(settings.scan_method);
- /* interpolation */
- s->dev->settings.disable_interpolation = s->disable_interpolation;
+ settings.xres = pick_resolution(resolutions.resolutions_x, s->resolution, "X");
+ settings.yres = pick_resolution(resolutions.resolutions_y, s->resolution, "Y");
- // FIXME: use correct sensor
- const auto& sensor = sanei_genesys_find_sensor_any(s->dev);
-
- // hardware settings
- if (static_cast<unsigned>(s->resolution) > sensor.optical_res &&
- s->dev->settings.disable_interpolation)
- {
- s->dev->settings.xres = sensor.optical_res;
- } else {
- s->dev->settings.xres = s->resolution;
- }
- s->dev->settings.yres = s->resolution;
+ settings.tl_x = fixed_to_float(s->pos_top_left_x);
+ settings.tl_y = fixed_to_float(s->pos_top_left_y);
+ float br_x = fixed_to_float(s->pos_bottom_right_x);
+ float br_y = fixed_to_float(s->pos_bottom_right_y);
- s->dev->settings.xres = pick_resolution(resolutions.resolutions_x, s->dev->settings.xres, "X");
- s->dev->settings.yres = pick_resolution(resolutions.resolutions_y, s->dev->settings.yres, "Y");
-
- s->params.lines = static_cast<unsigned>(((br_y - tl_y) * s->dev->settings.yres) /
+ settings.lines = static_cast<unsigned>(((br_y - settings.tl_y) * settings.yres) /
MM_PER_INCH);
- unsigned pixels_per_line = static_cast<unsigned>(((br_x - tl_x) * s->dev->settings.xres) /
- MM_PER_INCH);
-
- /* we need an even pixels number
- * TODO invert test logic or generalize behaviour across all ASICs */
- if ((s->dev->model->flags & GENESYS_FLAG_SIS_SENSOR) ||
- s->dev->model->asic_type == AsicType::GL847 ||
- s->dev->model->asic_type == AsicType::GL124 ||
- s->dev->model->asic_type == AsicType::GL845 ||
- s->dev->model->asic_type == AsicType::GL846 ||
- s->dev->model->asic_type == AsicType::GL843)
- {
- if (s->dev->settings.xres <= 1200) {
- pixels_per_line = (pixels_per_line / 4) * 4;
- } else if (s->dev->settings.xres < s->dev->settings.yres) {
- // BUG: this is an artifact of the fact that the resolution was twice as large than
- // the actual resolution when scanning above the supported scanner X resolution
- pixels_per_line = (pixels_per_line / 8) * 8;
- } else {
- pixels_per_line = (pixels_per_line / 16) * 16;
- }
- }
-
- /* corner case for true lineart for sensor with several segments
- * or when xres is doubled to match yres */
- if (s->dev->settings.xres >= 1200 && (
- s->dev->model->asic_type == AsicType::GL124 ||
- s->dev->model->asic_type == AsicType::GL847 ||
- s->dev->session.params.xres < s->dev->session.params.yres))
- {
- if (s->dev->settings.xres < s->dev->settings.yres) {
- // FIXME: this is an artifact of the fact that the resolution was twice as large than
- // the actual resolution when scanning above the supported scanner X resolution
- pixels_per_line = (pixels_per_line / 8) * 8;
- } else {
- pixels_per_line = (pixels_per_line / 16) * 16;
- }
- }
-
- unsigned xres_factor = s->resolution / s->dev->settings.xres;
- unsigned bytes_per_line = 0;
-
- if (s->params.depth > 8)
- {
- s->params.depth = 16;
- bytes_per_line = 2 * pixels_per_line;
- }
- else if (s->params.depth == 1)
- {
- // round down pixel number. This will is lossy operation, at most 7 pixels will be lost
- pixels_per_line = (pixels_per_line / 8) * 8;
- bytes_per_line = pixels_per_line / 8;
- } else {
- bytes_per_line = pixels_per_line;
- }
- if (s->params.format == SANE_FRAME_RGB) {
- bytes_per_line *= 3;
- }
+ unsigned pixels_per_line = static_cast<unsigned>(((br_x - settings.tl_x) * settings.xres) /
+ MM_PER_INCH);
- s->dev->settings.scan_mode = option_string_to_scan_color_mode(s->mode);
+ const auto& sensor = sanei_genesys_find_sensor(dev, settings.xres, settings.get_channels(),
+ settings.scan_method);
- s->dev->settings.lines = s->params.lines;
- s->dev->settings.pixels = pixels_per_line;
- s->dev->settings.requested_pixels = pixels_per_line * xres_factor;
- s->params.pixels_per_line = pixels_per_line * xres_factor;
- s->params.bytes_per_line = bytes_per_line * xres_factor;
- s->dev->settings.tl_x = tl_x;
- s->dev->settings.tl_y = tl_y;
+ pixels_per_line = session_adjust_output_pixels(pixels_per_line, *dev, sensor,
+ settings.xres, settings.yres, true);
- // threshold setting
- s->dev->settings.threshold = static_cast<int>(2.55 * (SANE_UNFIX(s->threshold)));
+ unsigned xres_factor = s->resolution / settings.xres;
+ settings.pixels = pixels_per_line;
+ settings.requested_pixels = pixels_per_line * xres_factor;
- // color filter
if (s->color_filter == "Red") {
- s->dev->settings.color_filter = ColorFilter::RED;
+ settings.color_filter = ColorFilter::RED;
} else if (s->color_filter == "Green") {
- s->dev->settings.color_filter = ColorFilter::GREEN;
+ settings.color_filter = ColorFilter::GREEN;
} else if (s->color_filter == "Blue") {
- s->dev->settings.color_filter = ColorFilter::BLUE;
+ settings.color_filter = ColorFilter::BLUE;
} else {
- s->dev->settings.color_filter = ColorFilter::NONE;
+ settings.color_filter = ColorFilter::NONE;
}
- // true gray
if (s->color_filter == "None") {
- s->dev->settings.true_gray = 1;
+ settings.true_gray = 1;
} else {
- s->dev->settings.true_gray = 0;
+ settings.true_gray = 0;
}
- // threshold curve for dynamic rasterization
- s->dev->settings.threshold_curve = s->threshold_curve;
-
- /* some digital processing requires the whole picture to be buffered */
- /* no digital processing takes place when doing preview, or when bit depth is
- * higher than 8 bits */
- if ((s->swdespeck || s->swcrop || s->swdeskew || s->swderotate ||(SANE_UNFIX(s->swskip)>0))
- && (!s->preview)
- && (s->bit_depth <= 8))
- {
- s->dev->buffer_image = true;
- }
- else
- {
- s->dev->buffer_image = false;
+ // brigthness and contrast only for for 8 bit scans
+ if (s->bit_depth == 8) {
+ settings.contrast = (s->contrast * 127) / 100;
+ settings.brightness = (s->brightness * 127) / 100;
+ } else {
+ settings.contrast = 0;
+ settings.brightness = 0;
}
- /* brigthness and contrast only for for 8 bit scans */
- if(s->bit_depth <= 8)
- {
- s->dev->settings.contrast = (s->contrast * 127) / 100;
- s->dev->settings.brightness = (s->brightness * 127) / 100;
- }
- else
- {
- s->dev->settings.contrast=0;
- s->dev->settings.brightness=0;
+ settings.expiration_time = s->expiration_time;
+
+ return settings;
+}
+
+static SANE_Parameters calculate_scan_parameters(const Genesys_Device& dev,
+ const Genesys_Settings& settings)
+{
+ DBG_HELPER(dbg);
+
+ auto sensor = sanei_genesys_find_sensor(&dev, settings.xres, settings.get_channels(),
+ settings.scan_method);
+ auto session = dev.cmd_set->calculate_scan_session(&dev, sensor, settings);
+ auto pipeline = build_image_pipeline(dev, session, 0, false);
+
+ SANE_Parameters params;
+ if (settings.scan_mode == ScanColorMode::GRAY) {
+ params.format = SANE_FRAME_GRAY;
+ } else {
+ params.format = SANE_FRAME_RGB;
}
+ // only single-pass scanning supported
+ params.last_frame = true;
+ params.depth = settings.depth;
+ params.lines = pipeline.get_output_height();
+ params.pixels_per_line = pipeline.get_output_width();
+ params.bytes_per_line = pipeline.get_output_row_bytes();
- /* cache expiration time */
- s->dev->settings.expiration_time = s->expiration_time;
+ return params;
}
+static void calc_parameters(Genesys_Scanner* s)
+{
+ DBG_HELPER(dbg);
+
+ s->dev->settings = calculate_scan_settings(s);
+ s->params = calculate_scan_parameters(*s->dev, s->dev->settings);
+}
static void create_bpp_list (Genesys_Scanner * s, const std::vector<unsigned>& bpp)
{
@@ -3760,7 +4430,7 @@ static void create_bpp_list (Genesys_Scanner * s, const std::vector<unsigned>& b
/** @brief this function initialize a gamma vector based on the ASIC:
* Set up a default gamma table vector based on device description
- * gl646: 12 or 14 bits gamma table depending on GENESYS_FLAG_14BIT_GAMMA
+ * gl646: 12 or 14 bits gamma table depending on ModelFlag::GAMMA_14BIT
* gl84x: 16 bits
* gl12x: 16 bits
* @param scanner pointer to scanner session to get options
@@ -3776,8 +4446,7 @@ init_gamma_vector_option (Genesys_Scanner * scanner, int option)
scanner->opt[option].unit = SANE_UNIT_NONE;
scanner->opt[option].constraint_type = SANE_CONSTRAINT_RANGE;
if (scanner->dev->model->asic_type == AsicType::GL646) {
- if ((scanner->dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) != 0)
- {
+ if (has_flag(scanner->dev->model->flags, ModelFlag::GAMMA_14BIT)) {
scanner->opt[option].size = 16384 * sizeof (SANE_Word);
scanner->opt[option].constraint.range = &u14_range;
}
@@ -3802,9 +4471,9 @@ init_gamma_vector_option (Genesys_Scanner * scanner, int option)
static SANE_Range create_range(float size)
{
SANE_Range range;
- range.min = SANE_FIX(0.0);
- range.max = SANE_FIX(size);
- range.quant = SANE_FIX(0.0);
+ range.min = float_to_fixed(0.0);
+ range.max = float_to_fixed(size);
+ range.quant = float_to_fixed(0.0);
return range;
}
@@ -3855,7 +4524,7 @@ static std::string calibration_filename(Genesys_Device *currdev)
/* count models of the same names if several scanners attached */
if(s_devices->size() > 1) {
for (const auto& dev : *s_devices) {
- if (dev.model->model_id == currdev->model->model_id) {
+ if (dev.vendorId == currdev->vendorId && dev.productId == currdev->productId) {
count++;
}
}
@@ -3921,13 +4590,13 @@ static void set_xy_range_option_values(Genesys_Scanner& s)
{
if (s.scan_method == ScanMethod::FLATBED)
{
- s.opt_x_range = create_range(static_cast<float>(s.dev->model->x_size));
- s.opt_y_range = create_range(static_cast<float>(s.dev->model->y_size));
+ s.opt_x_range = create_range(s.dev->model->x_size);
+ s.opt_y_range = create_range(s.dev->model->y_size);
}
else
{
- s.opt_x_range = create_range(static_cast<float>(s.dev->model->x_size_ta));
- s.opt_y_range = create_range(static_cast<float>(s.dev->model->y_size_ta));
+ s.opt_x_range = create_range(s.dev->model->x_size_ta);
+ s.opt_y_range = create_range(s.dev->model->y_size_ta);
}
s.opt[OPT_TL_X].constraint.range = &s.opt_x_range;
@@ -3945,7 +4614,7 @@ static void init_options(Genesys_Scanner* s)
{
DBG_HELPER(dbg);
SANE_Int option;
- Genesys_Model *model = s->dev->model;
+ const Genesys_Model* model = s->dev->model;
memset (s->opt, 0, sizeof (s->opt));
@@ -4038,8 +4707,8 @@ static void init_options(Genesys_Scanner* s)
s->opt[OPT_GEOMETRY_GROUP].size = 0;
s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
- s->opt_x_range = create_range(static_cast<float>(model->x_size));
- s->opt_y_range = create_range(static_cast<float>(model->y_size));
+ s->opt_x_range = create_range(model->x_size);
+ s->opt_y_range = create_range(model->y_size);
// scan area
s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
@@ -4116,8 +4785,7 @@ static void init_options(Genesys_Scanner* s)
/* currently, there are only gamma table options in this group,
* so if the scanner doesn't support gamma table, disable the
* whole group */
- if (!(model->flags & GENESYS_FLAG_CUSTOM_GAMMA))
- {
+ if (!has_flag(model->flags, ModelFlag::CUSTOM_GAMMA)) {
s->opt[OPT_ENHANCEMENT_GROUP].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
DBG(DBG_info, "%s: custom gamma disabled\n", __func__);
@@ -4127,61 +4795,6 @@ static void init_options(Genesys_Scanner* s)
* memory than used by the full scanned image and may fail at high
* resolution
*/
- /* software deskew */
- s->opt[OPT_SWDESKEW].name = "swdeskew";
- s->opt[OPT_SWDESKEW].title = "Software deskew";
- s->opt[OPT_SWDESKEW].desc = "Request backend to rotate skewed pages digitally";
- s->opt[OPT_SWDESKEW].type = SANE_TYPE_BOOL;
- s->opt[OPT_SWDESKEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
- s->swdeskew = false;
-
- /* software deskew */
- s->opt[OPT_SWDESPECK].name = "swdespeck";
- s->opt[OPT_SWDESPECK].title = "Software despeck";
- s->opt[OPT_SWDESPECK].desc = "Request backend to remove lone dots digitally";
- s->opt[OPT_SWDESPECK].type = SANE_TYPE_BOOL;
- s->opt[OPT_SWDESPECK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
- s->swdespeck = false;
-
- /* software despeckle radius */
- s->opt[OPT_DESPECK].name = "despeck";
- s->opt[OPT_DESPECK].title = "Software despeckle diameter";
- s->opt[OPT_DESPECK].desc = "Maximum diameter of lone dots to remove from scan";
- s->opt[OPT_DESPECK].type = SANE_TYPE_INT;
- s->opt[OPT_DESPECK].unit = SANE_UNIT_NONE;
- s->opt[OPT_DESPECK].constraint_type = SANE_CONSTRAINT_RANGE;
- s->opt[OPT_DESPECK].constraint.range = &swdespeck_range;
- s->opt[OPT_DESPECK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_INACTIVE;
- s->despeck = 1;
-
- /* crop by software */
- s->opt[OPT_SWCROP].name = "swcrop";
- s->opt[OPT_SWCROP].title = SANE_I18N ("Software crop");
- s->opt[OPT_SWCROP].desc = SANE_I18N ("Request backend to remove border from pages digitally");
- s->opt[OPT_SWCROP].type = SANE_TYPE_BOOL;
- s->opt[OPT_SWCROP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
- s->opt[OPT_SWCROP].unit = SANE_UNIT_NONE;
- s->swcrop = false;
-
- /* Software blank page skip */
- s->opt[OPT_SWSKIP].name = "swskip";
- s->opt[OPT_SWSKIP].title = SANE_I18N ("Software blank skip percentage");
- s->opt[OPT_SWSKIP].desc = SANE_I18N("Request driver to discard pages with low numbers of dark pixels");
- s->opt[OPT_SWSKIP].type = SANE_TYPE_FIXED;
- s->opt[OPT_SWSKIP].unit = SANE_UNIT_PERCENT;
- s->opt[OPT_SWSKIP].constraint_type = SANE_CONSTRAINT_RANGE;
- s->opt[OPT_SWSKIP].constraint.range = &(percentage_range);
- s->opt[OPT_SWSKIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
- s->swskip = 0; // disable by default
-
- /* Software Derotate */
- s->opt[OPT_SWDEROTATE].name = "swderotate";
- s->opt[OPT_SWDEROTATE].title = SANE_I18N ("Software derotate");
- s->opt[OPT_SWDEROTATE].desc = SANE_I18N("Request driver to detect and correct 90 degree image rotation");
- s->opt[OPT_SWDEROTATE].type = SANE_TYPE_BOOL;
- s->opt[OPT_SWDEROTATE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
- s->opt[OPT_SWDEROTATE].unit = SANE_UNIT_NONE;
- s->swderotate = false;
/* Software brightness */
s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
@@ -4214,39 +4827,6 @@ static void init_options(Genesys_Scanner* s)
s->opt[OPT_EXTRAS_GROUP].size = 0;
s->opt[OPT_EXTRAS_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
- /* BW threshold */
- s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
- s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
- s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
- s->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
- s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
- s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
- s->opt[OPT_THRESHOLD].constraint.range = &percentage_range;
- s->threshold = SANE_FIX(50);
-
- /* BW threshold curve */
- s->opt[OPT_THRESHOLD_CURVE].name = "threshold-curve";
- s->opt[OPT_THRESHOLD_CURVE].title = SANE_I18N ("Threshold curve");
- s->opt[OPT_THRESHOLD_CURVE].desc = SANE_I18N ("Dynamic threshold curve, from light to dark, normally 50-65");
- s->opt[OPT_THRESHOLD_CURVE].type = SANE_TYPE_INT;
- s->opt[OPT_THRESHOLD_CURVE].unit = SANE_UNIT_NONE;
- s->opt[OPT_THRESHOLD_CURVE].constraint_type = SANE_CONSTRAINT_RANGE;
- s->opt[OPT_THRESHOLD_CURVE].constraint.range = &threshold_curve_range;
- s->threshold_curve = 50;
-
- /* disable_interpolation */
- s->opt[OPT_DISABLE_INTERPOLATION].name = "disable-interpolation";
- s->opt[OPT_DISABLE_INTERPOLATION].title =
- SANE_I18N ("Disable interpolation");
- s->opt[OPT_DISABLE_INTERPOLATION].desc =
- SANE_I18N
- ("When using high resolutions where the horizontal resolution is smaller "
- "than the vertical resolution this disables horizontal interpolation.");
- s->opt[OPT_DISABLE_INTERPOLATION].type = SANE_TYPE_BOOL;
- s->opt[OPT_DISABLE_INTERPOLATION].unit = SANE_UNIT_NONE;
- s->opt[OPT_DISABLE_INTERPOLATION].constraint_type = SANE_CONSTRAINT_NONE;
- s->disable_interpolation = false;
-
/* color filter */
s->opt[OPT_COLOR_FILTER].name = "color-filter";
s->opt[OPT_COLOR_FILTER].title = SANE_I18N ("Color filter");
@@ -4508,36 +5088,39 @@ check_present (SANE_String_Const devname) noexcept
return SANE_STATUS_GOOD;
}
-static Genesys_Device* attach_usb_device(const char* devname,
- std::uint16_t vendor_id, std::uint16_t product_id)
+const UsbDeviceEntry& get_matching_usb_dev(std::uint16_t vendor_id, std::uint16_t product_id,
+ std::uint16_t bcd_device)
{
- Genesys_USB_Device_Entry* found_usb_dev = nullptr;
for (auto& usb_dev : *s_usb_devices) {
- if (usb_dev.vendor == vendor_id &&
- usb_dev.product == product_id)
- {
- found_usb_dev = &usb_dev;
- break;
+ if (usb_dev.matches(vendor_id, product_id, bcd_device)) {
+ return usb_dev;
}
}
- if (found_usb_dev == nullptr) {
- throw SaneException("vendor 0x%xd product 0x%xd is not supported by this backend",
- vendor_id, product_id);
- }
+ throw SaneException("vendor 0x%x product 0x%x (bcdDevice 0x%x) "
+ "is not supported by this backend",
+ vendor_id, product_id, bcd_device);
+}
+
+static Genesys_Device* attach_usb_device(const char* devname,
+ std::uint16_t vendor_id, std::uint16_t product_id,
+ std::uint16_t bcd_device)
+{
+ const auto& usb_dev = get_matching_usb_dev(vendor_id, product_id, bcd_device);
s_devices->emplace_back();
Genesys_Device* dev = &s_devices->back();
dev->file_name = devname;
-
- dev->model = &found_usb_dev->model;
- dev->vendorId = found_usb_dev->vendor;
- dev->productId = found_usb_dev->product;
+ dev->vendorId = vendor_id;
+ dev->productId = product_id;
+ dev->model = &usb_dev.model();
dev->usb_mode = 0; // i.e. unset
dev->already_initialized = false;
return dev;
}
+static bool s_attach_device_by_name_evaluate_bcd_device = false;
+
static Genesys_Device* attach_device_by_name(SANE_String_Const devname, bool may_wait)
{
DBG_HELPER_ARGS(dbg, " devname: %s, may_wait = %d", devname, may_wait);
@@ -4560,26 +5143,31 @@ static Genesys_Device* attach_device_by_name(SANE_String_Const devname, bool may
usb_dev.open(devname);
DBG(DBG_info, "%s: device `%s' successfully opened\n", __func__, devname);
- int vendor, product;
- usb_dev.get_vendor_product(vendor, product);
+ auto vendor_id = usb_dev.get_vendor_id();
+ auto product_id = usb_dev.get_product_id();
+ auto bcd_device = UsbDeviceEntry::BCD_DEVICE_NOT_SET;
+ if (s_attach_device_by_name_evaluate_bcd_device) {
+ // when the device is already known before scanning, we don't want to call get_bcd_device()
+ // when iterating devices, as that will interfere with record/replay during testing.
+ bcd_device = usb_dev.get_bcd_device();
+ }
usb_dev.close();
/* KV-SS080 is an auxiliary device which requires a master device to be here */
- if(vendor == 0x04da && product == 0x100f)
- {
+ if (vendor_id == 0x04da && product_id == 0x100f) {
present = false;
- sanei_usb_find_devices (vendor, 0x1006, check_present);
- sanei_usb_find_devices (vendor, 0x1007, check_present);
- sanei_usb_find_devices (vendor, 0x1010, check_present);
+ sanei_usb_find_devices(vendor_id, 0x1006, check_present);
+ sanei_usb_find_devices(vendor_id, 0x1007, check_present);
+ sanei_usb_find_devices(vendor_id, 0x1010, check_present);
if (present == false) {
throw SaneException("master device not present");
}
}
- Genesys_Device* dev = attach_usb_device(devname, vendor, product);
+ Genesys_Device* dev = attach_usb_device(devname, vendor_id, product_id, bcd_device);
- DBG(DBG_info, "%s: found %s flatbed scanner %s at %s\n", __func__, dev->model->vendor,
- dev->model->model, dev->file_name.c_str());
+ DBG(DBG_info, "%s: found %u flatbed scanner %u at %s\n", __func__, vendor_id, product_id,
+ dev->file_name.c_str());
return dev;
}
@@ -4614,7 +5202,8 @@ static void probe_genesys_devices()
DBG_HELPER(dbg);
if (is_testing_mode()) {
attach_usb_device(get_testing_device_name().c_str(),
- get_testing_vendor_id(), get_testing_product_id());
+ get_testing_vendor_id(), get_testing_product_id(),
+ get_testing_bcd_device());
return;
}
@@ -4625,7 +5214,12 @@ static void probe_genesys_devices()
config.values = nullptr;
config.count = 0;
- TIE(sanei_configure_attach(GENESYS_CONFIG_FILE, &config, config_attach_genesys));
+ auto status = sanei_configure_attach(GENESYS_CONFIG_FILE, &config, config_attach_genesys);
+ if (status == SANE_STATUS_ACCESS_DENIED) {
+ dbg.vlog(DBG_error0, "Critical error: Couldn't access configuration file '%s'",
+ GENESYS_CONFIG_FILE);
+ }
+ TIE(status);
DBG(DBG_info, "%s: %zu devices currently attached\n", __func__, s_devices->size());
}
@@ -4637,7 +5231,7 @@ static void probe_genesys_devices()
of Genesys_Calibration_Cache as is.
*/
static const char* CALIBRATION_IDENT = "sane_genesys";
-static const int CALIBRATION_VERSION = 21;
+static const int CALIBRATION_VERSION = 31;
bool read_calibration(std::istream& str, Genesys_Device::Calibration& calibration,
const std::string& path)
@@ -4706,114 +5300,6 @@ static void write_calibration(Genesys_Device::Calibration& calibration, const st
write_calibration(str, calibration);
}
-/** @brief buffer scanned picture
- * In order to allow digital processing, we must be able to put all the
- * scanned picture in a buffer.
- */
-static void genesys_buffer_image(Genesys_Scanner *s)
-{
- DBG_HELPER(dbg);
- size_t maximum; /**> maximum bytes size of the scan */
- size_t len; /**> length of scanned data read */
- size_t total; /**> total of butes read */
- size_t size; /**> size of image buffer */
- size_t read_size; /**> size of reads */
- int lines; /** number of lines of the scan */
- Genesys_Device *dev = s->dev;
-
- /* compute maximum number of lines for the scan */
- if (s->params.lines > 0)
- {
- lines = s->params.lines;
- }
- else
- {
- lines = static_cast<int>((dev->model->y_size * dev->settings.yres) / MM_PER_INCH);
- }
- DBG(DBG_info, "%s: buffering %d lines of %d bytes\n", __func__, lines,
- s->params.bytes_per_line);
-
- /* maximum bytes to read */
- maximum = s->params.bytes_per_line * lines;
- if (s->dev->settings.scan_mode == ScanColorMode::LINEART) {
- maximum *= 8;
- }
-
- /* initial size of the read buffer */
- size =
- ((2048 * 2048) / s->params.bytes_per_line) * s->params.bytes_per_line;
-
- /* read size */
- read_size = size / 2;
-
- dev->img_buffer.resize(size);
-
- /* loop reading data until we reach maximum or EOF */
- total = 0;
- while (total < maximum) {
- len = size - maximum;
- if (len > read_size)
- {
- len = read_size;
- }
-
- try {
- genesys_read_ordered_data(dev, dev->img_buffer.data() + total, &len);
- } catch (const SaneException& e) {
- if (e.status() == SANE_STATUS_EOF) {
- // ideally we shouldn't end up here, but because computations are duplicated and
- // slightly different everywhere in the genesys backend, we have no other choice
- break;
- }
- throw;
- }
- total += len;
-
- // do we need to enlarge read buffer ?
- if (total + read_size > size) {
- size += read_size;
- dev->img_buffer.resize(size);
- }
- }
-
- /* since digital processing is going to take place,
- * issue head parking command so that the head move while
- * computing so we can save time
- */
- if (!dev->model->is_sheetfed && !dev->parking) {
- dev->cmd_set->move_back_home(dev, dev->model->flags & GENESYS_FLAG_MUST_WAIT);
- dev->parking = !(s->dev->model->flags & GENESYS_FLAG_MUST_WAIT);
- }
-
- /* in case of dynamic lineart, we have buffered gray data which
- * must be converted to lineart first */
- if (s->dev->settings.scan_mode == ScanColorMode::LINEART) {
- total/=8;
- std::vector<uint8_t> lineart(total);
-
- genesys_gray_lineart (dev,
- dev->img_buffer.data(),
- lineart.data(),
- dev->settings.pixels,
- (total*8)/dev->settings.pixels,
- dev->settings.threshold);
- dev->img_buffer = lineart;
- }
-
- /* update counters */
- dev->total_bytes_to_read = total;
- dev->total_bytes_read = 0;
-
- /* update params */
- s->params.lines = total / s->params.bytes_per_line;
- if (DBG_LEVEL >= DBG_io2)
- {
- sanei_genesys_write_pnm_file("gl_unprocessed.pnm", dev->img_buffer.data(), s->params.depth,
- s->params.format==SANE_FRAME_RGB ? 3 : 1,
- s->params.pixels_per_line, s->params.lines);
- }
-}
-
/* -------------------------- SANE API functions ------------------------- */
void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize)
@@ -4839,9 +5325,6 @@ void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize)
sanei_usb_init();
}
- /* init sanei_magic */
- sanei_magic_init();
-
s_scanners.init();
s_devices.init();
s_sane_devices.init();
@@ -4850,8 +5333,8 @@ void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize)
genesys_init_sensor_tables();
genesys_init_frontend_tables();
genesys_init_gpo_tables();
+ genesys_init_memory_layout_tables();
genesys_init_motor_tables();
- genesys_init_motor_profile_tables();
genesys_init_usb_device_tables();
@@ -4864,6 +5347,7 @@ void sane_init_impl(SANE_Int * version_code, SANE_Auth_Callback authorize)
);
// cold-plug case :detection of allready connected scanners
+ s_attach_device_by_name_evaluate_bcd_device = false;
probe_genesys_devices();
}
@@ -4903,6 +5387,7 @@ void sane_get_devices_impl(const SANE_Device *** device_list, SANE_Bool local_on
// hot-plug case : detection of newly connected scanners */
sanei_usb_scan_devices();
}
+ s_attach_device_by_name_evaluate_bcd_device = true;
probe_genesys_devices();
s_sane_devices->clear();
@@ -4969,7 +5454,7 @@ static void sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
}
if (dev) {
- DBG(DBG_info, "%s: found `%s' in devlist\n", __func__, dev->model->name);
+ DBG(DBG_info, "%s: found `%s' in devlist\n", __func__, dev->file_name.c_str());
} else if (is_testing_mode()) {
DBG(DBG_info, "%s: couldn't find `%s' in devlist, not attaching", __func__, devicename);
} else {
@@ -4991,37 +5476,53 @@ static void sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
throw SaneException("could not find the device to open: %s", devicename);
}
- if (dev->model->flags & GENESYS_FLAG_UNTESTED)
- {
- DBG(DBG_error0, "WARNING: Your scanner is not fully supported or at least \n");
- DBG(DBG_error0, " had only limited testing. Please be careful and \n");
- DBG(DBG_error0, " report any failure/success to \n");
- DBG(DBG_error0, " sane-devel@alioth-lists.debian.net. Please provide as many\n");
- DBG(DBG_error0, " details as possible, e.g. the exact name of your\n");
- DBG(DBG_error0, " scanner and what does (not) work.\n");
- }
+ if (is_testing_mode()) {
+ // during testing we need to initialize dev->model before test scanner interface is created
+ // as that it needs to know what type of chip it needs to mimic.
+ auto vendor_id = get_testing_vendor_id();
+ auto product_id = get_testing_product_id();
+ auto bcd_device = get_testing_bcd_device();
- dbg.vstatus("open device '%s'", dev->file_name.c_str());
+ dev->model = &get_matching_usb_dev(vendor_id, product_id, bcd_device).model();
- if (is_testing_mode()) {
- auto interface = std::unique_ptr<TestScannerInterface>{new TestScannerInterface{dev}};
+ auto interface = std::unique_ptr<TestScannerInterface>{
+ new TestScannerInterface{dev, vendor_id, product_id, bcd_device}};
interface->set_checkpoint_callback(get_testing_checkpoint_callback());
dev->interface = std::move(interface);
+
+ dev->interface->get_usb_device().open(dev->file_name.c_str());
} else {
dev->interface = std::unique_ptr<ScannerInterfaceUsb>{new ScannerInterfaceUsb{dev}};
+
+ dbg.vstatus("open device '%s'", dev->file_name.c_str());
+ dev->interface->get_usb_device().open(dev->file_name.c_str());
+ dbg.clear();
+
+ auto bcd_device = dev->interface->get_usb_device().get_bcd_device();
+
+ dev->model = &get_matching_usb_dev(dev->vendorId, dev->productId, bcd_device).model();
+ }
+
+ dbg.vlog(DBG_info, "Opened device %s", dev->model->name);
+
+ if (has_flag(dev->model->flags, ModelFlag::UNTESTED)) {
+ DBG(DBG_error0, "WARNING: Your scanner is not fully supported or at least \n");
+ DBG(DBG_error0, " had only limited testing. Please be careful and \n");
+ DBG(DBG_error0, " report any failure/success to \n");
+ DBG(DBG_error0, " sane-devel@alioth-lists.debian.net. Please provide as many\n");
+ DBG(DBG_error0, " details as possible, e.g. the exact name of your\n");
+ DBG(DBG_error0, " scanner and what does (not) work.\n");
}
- dev->interface->get_usb_device().open(dev->file_name.c_str());
- dbg.clear();
s_scanners->push_back(Genesys_Scanner());
auto* s = &s_scanners->back();
- s->dev = dev;
+ s->dev = dev;
s->scanning = false;
- s->dev->parking = false;
- s->dev->read_active = false;
- s->dev->force_calibration = 0;
- s->dev->line_count = 0;
+ dev->parking = false;
+ dev->read_active = false;
+ dev->force_calibration = 0;
+ dev->line_count = 0;
*handle = s;
@@ -5029,31 +5530,18 @@ static void sane_open_impl(SANE_String_Const devicename, SANE_Handle * handle)
sanei_genesys_init_structs (dev);
}
+ dev->cmd_set = create_cmd_set(dev->model->asic_type);
+
init_options(s);
- sanei_genesys_init_cmd_set(s->dev);
+ DBG_INIT();
// FIXME: we create sensor tables for the sensor, this should happen when we know which sensor
// we will select
dev->cmd_set->init(dev);
// some hardware capabilities are detected through sensors
- s->dev->cmd_set->update_hardware_sensors (s);
-
- /* here is the place to fetch a stored calibration cache */
- if (s->dev->force_calibration == 0)
- {
- auto path = calibration_filename(s->dev);
- s->calibration_file = path;
- s->dev->calib_file = path;
- DBG(DBG_info, "%s: Calibration filename set to:\n", __func__);
- DBG(DBG_info, "%s: >%s<\n", __func__, s->dev->calib_file.c_str());
-
- catch_all_exceptions(__func__, [&]()
- {
- sanei_genesys_read_calibration(s->dev->calibration_cache, s->dev->calib_file);
- });
- }
+ dev->cmd_set->update_hardware_sensors (s);
}
SANE_GENESYS_API_LINKAGE
@@ -5085,46 +5573,42 @@ sane_close_impl(SANE_Handle handle)
return; /* oops, not a handle we know about */
}
- Genesys_Scanner* s = &*it;
+ auto* dev = it->dev;
- /* eject document for sheetfed scanners */
- if (s->dev->model->is_sheetfed) {
- catch_all_exceptions(__func__, [&](){ s->dev->cmd_set->eject_document(s->dev); });
- }
- else
- {
- /* in case scanner is parking, wait for the head
- * to reach home position */
- if (s->dev->parking) {
- sanei_genesys_wait_for_home(s->dev);
+ // eject document for sheetfed scanners
+ if (dev->model->is_sheetfed) {
+ catch_all_exceptions(__func__, [&](){ dev->cmd_set->eject_document(dev); });
+ } else {
+ // in case scanner is parking, wait for the head to reach home position
+ if (dev->parking) {
+ sanei_genesys_wait_for_home(dev);
}
}
// enable power saving before leaving
- s->dev->cmd_set->save_power(s->dev, true);
+ dev->cmd_set->save_power(dev, true);
// here is the place to store calibration cache
- if (s->dev->force_calibration == 0 && !is_testing_mode()) {
- catch_all_exceptions(__func__, [&](){ write_calibration(s->dev->calibration_cache,
- s->dev->calib_file); });
+ if (dev->force_calibration == 0 && !is_testing_mode()) {
+ catch_all_exceptions(__func__, [&](){ write_calibration(dev->calibration_cache,
+ dev->calib_file); });
}
- s->dev->already_initialized = false;
-
- s->dev->clear();
+ dev->already_initialized = false;
+ dev->clear();
// LAMP OFF : same register across all the ASICs */
- s->dev->interface->write_register(0x03, 0x00);
+ dev->interface->write_register(0x03, 0x00);
- catch_all_exceptions(__func__, [&](){ s->dev->interface->get_usb_device().clear_halt(); });
+ catch_all_exceptions(__func__, [&](){ dev->interface->get_usb_device().clear_halt(); });
// we need this to avoid these ASIC getting stuck in bulk writes
- catch_all_exceptions(__func__, [&](){ s->dev->interface->get_usb_device().reset(); });
+ catch_all_exceptions(__func__, [&](){ dev->interface->get_usb_device().reset(); });
- // not freeing s->dev because it's in the dev list
- catch_all_exceptions(__func__, [&](){ s->dev->interface->get_usb_device().close(); });
+ // not freeing dev because it's in the dev list
+ catch_all_exceptions(__func__, [&](){ dev->interface->get_usb_device().close(); });
- s_scanners->erase(it);
+ s_scanners->erase(it);
}
SANE_GENESYS_API_LINKAGE
@@ -5174,7 +5658,7 @@ static void print_option(DebugMessageHelper& dbg, const Genesys_Scanner& s, int
return;
}
case SANE_TYPE_FIXED: {
- dbg.vlog(DBG_proc, "value: %f", SANE_UNFIX(*reinterpret_cast<SANE_Word*>(val)));
+ dbg.vlog(DBG_proc, "value: %f", fixed_to_float(*reinterpret_cast<SANE_Word*>(val)));
return;
}
case SANE_TYPE_STRING: {
@@ -5189,18 +5673,19 @@ static void print_option(DebugMessageHelper& dbg, const Genesys_Scanner& s, int
static void get_option_value(Genesys_Scanner* s, int option, void* val)
{
DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option);
+ auto* dev = s->dev;
unsigned int i;
SANE_Word* table = nullptr;
std::vector<uint16_t> gamma_table;
unsigned option_size = 0;
const Genesys_Sensor* sensor = nullptr;
- if (sanei_genesys_has_sensor(s->dev, s->dev->settings.xres, s->dev->settings.get_channels(),
- s->dev->settings.scan_method))
+ if (sanei_genesys_has_sensor(dev, dev->settings.xres, dev->settings.get_channels(),
+ dev->settings.scan_method))
{
- sensor = &sanei_genesys_find_sensor(s->dev, s->dev->settings.xres,
- s->dev->settings.get_channels(),
- s->dev->settings.scan_method);
+ sensor = &sanei_genesys_find_sensor(dev, dev->settings.xres,
+ dev->settings.get_channels(),
+ dev->settings.scan_method);
}
switch (option)
@@ -5231,39 +5716,12 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
case OPT_PREVIEW:
*reinterpret_cast<SANE_Word*>(val) = s->preview;
break;
- case OPT_THRESHOLD:
- *reinterpret_cast<SANE_Word*>(val) = s->threshold;
- break;
- case OPT_THRESHOLD_CURVE:
- *reinterpret_cast<SANE_Word*>(val) = s->threshold_curve;
- break;
- case OPT_DISABLE_INTERPOLATION:
- *reinterpret_cast<SANE_Word*>(val) = s->disable_interpolation;
- break;
case OPT_LAMP_OFF:
*reinterpret_cast<SANE_Word*>(val) = s->lamp_off;
break;
case OPT_LAMP_OFF_TIME:
*reinterpret_cast<SANE_Word*>(val) = s->lamp_off_time;
break;
- case OPT_SWDESKEW:
- *reinterpret_cast<SANE_Word*>(val) = s->swdeskew;
- break;
- case OPT_SWCROP:
- *reinterpret_cast<SANE_Word*>(val) = s->swcrop;
- break;
- case OPT_SWDESPECK:
- *reinterpret_cast<SANE_Word*>(val) = s->swdespeck;
- break;
- case OPT_SWDEROTATE:
- *reinterpret_cast<SANE_Word*>(val) = s->swderotate;
- break;
- case OPT_SWSKIP:
- *reinterpret_cast<SANE_Word*>(val) = s->swskip;
- break;
- case OPT_DESPECK:
- *reinterpret_cast<SANE_Word*>(val) = s->despeck;
- break;
case OPT_CONTRAST:
*reinterpret_cast<SANE_Word*>(val) = s->contrast;
break;
@@ -5297,13 +5755,13 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val);
- if (s->color_filter == "Red") {
- gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_RED);
- } else if (s->color_filter == "Blue") {
- gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_BLUE);
- } else {
- gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_GREEN);
- }
+ if (s->color_filter == "Red") {
+ gamma_table = get_gamma_table(dev, *sensor, GENESYS_RED);
+ } else if (s->color_filter == "Blue") {
+ gamma_table = get_gamma_table(dev, *sensor, GENESYS_BLUE);
+ } else {
+ gamma_table = get_gamma_table(dev, *sensor, GENESYS_GREEN);
+ }
option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match");
@@ -5317,7 +5775,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val);
- gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_RED);
+ gamma_table = get_gamma_table(dev, *sensor, GENESYS_RED);
option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match");
@@ -5331,7 +5789,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val);
- gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_GREEN);
+ gamma_table = get_gamma_table(dev, *sensor, GENESYS_GREEN);
option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match");
@@ -5345,7 +5803,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
throw SaneException("Unsupported scanner mode selected");
table = reinterpret_cast<SANE_Word*>(val);
- gamma_table = get_gamma_table(s->dev, *sensor, GENESYS_BLUE);
+ gamma_table = get_gamma_table(dev, *sensor, GENESYS_BLUE);
option_size = s->opt[option].size / sizeof (SANE_Word);
if (gamma_table.size() != option_size) {
throw std::runtime_error("The size of the gamma tables does not match");
@@ -5377,11 +5835,10 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
bool result = true;
- auto session = s->dev->cmd_set->calculate_scan_session(s->dev, *sensor,
- s->dev->settings);
+ auto session = dev->cmd_set->calculate_scan_session(dev, *sensor, dev->settings);
- for (auto& cache : s->dev->calibration_cache) {
- if (sanei_genesys_is_compatible_calibration(s->dev, session, &cache, false)) {
+ for (auto& cache : dev->calibration_cache) {
+ if (sanei_genesys_is_compatible_calibration(dev, session, &cache, false)) {
*reinterpret_cast<SANE_Bool*>(val) = SANE_FALSE;
}
}
@@ -5400,6 +5857,7 @@ static void get_option_value(Genesys_Scanner* s, int option, void* val)
static void set_calibration_value(Genesys_Scanner* s, const char* val)
{
DBG_HELPER(dbg);
+ auto dev = s->dev;
std::string new_calib_path = val;
Genesys_Device::Calibration new_calibration;
@@ -5414,8 +5872,8 @@ static void set_calibration_value(Genesys_Scanner* s, const char* val)
return;
}
- s->dev->calibration_cache = std::move(new_calibration);
- s->dev->calib_file = new_calib_path;
+ dev->calibration_cache = std::move(new_calibration);
+ dev->calib_file = new_calib_path;
s->calibration_file = new_calib_path;
DBG(DBG_info, "%s: Calibration filename set to '%s':\n", __func__, new_calib_path.c_str());
}
@@ -5426,12 +5884,13 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
DBG_HELPER_ARGS(dbg, "option: %s (%d)", s->opt[option].name, option);
print_option(dbg, *s, option, val);
+ auto* dev = s->dev;
+
SANE_Word *table;
unsigned int i;
unsigned option_size = 0;
- switch (option)
- {
+ switch (option) {
case OPT_TL_X:
s->pos_top_left_x = *reinterpret_cast<SANE_Word*>(val);
calc_parameters(s);
@@ -5457,46 +5916,6 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
calc_parameters(s);
*myinfo |= SANE_INFO_RELOAD_PARAMS;
break;
- case OPT_THRESHOLD:
- s->threshold = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
- case OPT_THRESHOLD_CURVE:
- s->threshold_curve = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
- case OPT_SWCROP:
- s->swcrop = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
- case OPT_SWDESKEW:
- s->swdeskew = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
- case OPT_DESPECK:
- s->despeck = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
- case OPT_SWDEROTATE:
- s->swderotate = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
- case OPT_SWSKIP:
- s->swskip = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
- case OPT_DISABLE_INTERPOLATION:
- s->disable_interpolation = *reinterpret_cast<SANE_Word*>(val);
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS;
- break;
case OPT_LAMP_OFF:
s->lamp_off = *reinterpret_cast<SANE_Word*>(val);
calc_parameters(s);
@@ -5517,38 +5936,14 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
calc_parameters(s);
*myinfo |= SANE_INFO_RELOAD_PARAMS;
break;
- case OPT_SWDESPECK:
- s->swdespeck = *reinterpret_cast<SANE_Word*>(val);
- if (s->swdespeck) {
- ENABLE(OPT_DESPECK);
- } else {
- DISABLE(OPT_DESPECK);
- }
- calc_parameters(s);
- *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
- break;
/* software enhancement functions only apply to 8 or 1 bits data */
case OPT_BIT_DEPTH:
s->bit_depth = *reinterpret_cast<SANE_Word*>(val);
if(s->bit_depth>8)
{
- DISABLE(OPT_SWDESKEW);
- DISABLE(OPT_SWDESPECK);
- DISABLE(OPT_SWCROP);
- DISABLE(OPT_DESPECK);
- DISABLE(OPT_SWDEROTATE);
- DISABLE(OPT_SWSKIP);
DISABLE(OPT_CONTRAST);
DISABLE(OPT_BRIGHTNESS);
- }
- else
- {
- ENABLE(OPT_SWDESKEW);
- ENABLE(OPT_SWDESPECK);
- ENABLE(OPT_SWCROP);
- ENABLE(OPT_DESPECK);
- ENABLE(OPT_SWDEROTATE);
- ENABLE(OPT_SWSKIP);
+ } else {
ENABLE(OPT_CONTRAST);
ENABLE(OPT_BRIGHTNESS);
}
@@ -5567,38 +5962,22 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
}
break;
}
- case OPT_MODE:
- s->mode = reinterpret_cast<const char*>(val);
+ case OPT_MODE: {
+ s->mode = reinterpret_cast<const char*>(val);
- if (s->mode == SANE_VALUE_SCAN_MODE_LINEART)
- {
- ENABLE (OPT_THRESHOLD);
- ENABLE (OPT_THRESHOLD_CURVE);
- DISABLE (OPT_BIT_DEPTH);
- if (s->dev->model->asic_type != AsicType::GL646 || !s->dev->model->is_cis) {
+ if (s->mode == SANE_VALUE_SCAN_MODE_GRAY) {
+ if (dev->model->asic_type != AsicType::GL646 || !dev->model->is_cis) {
ENABLE(OPT_COLOR_FILTER);
}
- }
- else
- {
- DISABLE (OPT_THRESHOLD);
- DISABLE (OPT_THRESHOLD_CURVE);
- if (s->mode == SANE_VALUE_SCAN_MODE_GRAY)
- {
- if (s->dev->model->asic_type != AsicType::GL646 || !s->dev->model->is_cis) {
- ENABLE(OPT_COLOR_FILTER);
- }
- create_bpp_list (s, s->dev->model->bpp_gray_values);
- s->bit_depth = s->dev->model->bpp_gray_values[0];
- }
- else
- {
- DISABLE (OPT_COLOR_FILTER);
- create_bpp_list (s, s->dev->model->bpp_color_values);
- s->bit_depth = s->dev->model->bpp_color_values[0];
- }
- }
- calc_parameters(s);
+ create_bpp_list(s, dev->model->bpp_gray_values);
+ s->bit_depth = dev->model->bpp_gray_values[0];
+ } else {
+ DISABLE(OPT_COLOR_FILTER);
+ create_bpp_list(s, dev->model->bpp_color_values);
+ s->bit_depth = dev->model->bpp_color_values[0];
+ }
+
+ calc_parameters(s);
/* if custom gamma, toggle gamma table options according to the mode */
if (s->custom_gamma)
@@ -5621,30 +6000,31 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
+ }
case OPT_COLOR_FILTER:
s->color_filter = reinterpret_cast<const char*>(val);
calc_parameters(s);
break;
- case OPT_CALIBRATION_FILE:
- if (s->dev->force_calibration == 0) {
+ case OPT_CALIBRATION_FILE: {
+ if (dev->force_calibration == 0) {
set_calibration_value(s, reinterpret_cast<const char*>(val));
}
break;
- case OPT_LAMP_OFF_TIME:
- if (*reinterpret_cast<SANE_Word*>(val) != s->lamp_off_time) {
- s->lamp_off_time = *reinterpret_cast<SANE_Word*>(val);
- s->dev->cmd_set->set_powersaving(s->dev, s->lamp_off_time);
}
- break;
- case OPT_EXPIRATION_TIME:
- if (*reinterpret_cast<SANE_Word*>(val) != s->expiration_time) {
- s->expiration_time = *reinterpret_cast<SANE_Word*>(val);
- // BUG: this is most likely not intended behavior, found out during refactor
- s->dev->cmd_set->set_powersaving(s->dev, s->expiration_time);
- }
- break;
-
- case OPT_CUSTOM_GAMMA:
+ case OPT_LAMP_OFF_TIME: {
+ if (*reinterpret_cast<SANE_Word*>(val) != s->lamp_off_time) {
+ s->lamp_off_time = *reinterpret_cast<SANE_Word*>(val);
+ dev->cmd_set->set_powersaving(dev, s->lamp_off_time);
+ }
+ break;
+ }
+ case OPT_EXPIRATION_TIME: {
+ if (*reinterpret_cast<SANE_Word*>(val) != s->expiration_time) {
+ s->expiration_time = *reinterpret_cast<SANE_Word*>(val);
+ }
+ break;
+ }
+ case OPT_CUSTOM_GAMMA: {
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
s->custom_gamma = *reinterpret_cast<SANE_Bool*>(val);
@@ -5670,88 +6050,96 @@ static void set_option_value(Genesys_Scanner* s, int option, void *val, SANE_Int
DISABLE (OPT_GAMMA_VECTOR_R);
DISABLE (OPT_GAMMA_VECTOR_G);
DISABLE (OPT_GAMMA_VECTOR_B);
- for (auto& table : s->dev->gamma_override_tables) {
- table.clear();
+ for (auto& table : dev->gamma_override_tables) {
+ table.clear();
+ }
}
- }
- break;
-
- case OPT_GAMMA_VECTOR:
- table = reinterpret_cast<SANE_Word*>(val);
- option_size = s->opt[option].size / sizeof (SANE_Word);
+ break;
+ }
- s->dev->gamma_override_tables[GENESYS_RED].resize(option_size);
- s->dev->gamma_override_tables[GENESYS_GREEN].resize(option_size);
- s->dev->gamma_override_tables[GENESYS_BLUE].resize(option_size);
- for (i = 0; i < option_size; i++) {
- s->dev->gamma_override_tables[GENESYS_RED][i] = table[i];
- s->dev->gamma_override_tables[GENESYS_GREEN][i] = table[i];
- s->dev->gamma_override_tables[GENESYS_BLUE][i] = table[i];
+ case OPT_GAMMA_VECTOR: {
+ table = reinterpret_cast<SANE_Word*>(val);
+ option_size = s->opt[option].size / sizeof (SANE_Word);
+
+ dev->gamma_override_tables[GENESYS_RED].resize(option_size);
+ dev->gamma_override_tables[GENESYS_GREEN].resize(option_size);
+ dev->gamma_override_tables[GENESYS_BLUE].resize(option_size);
+ for (i = 0; i < option_size; i++) {
+ dev->gamma_override_tables[GENESYS_RED][i] = table[i];
+ dev->gamma_override_tables[GENESYS_GREEN][i] = table[i];
+ dev->gamma_override_tables[GENESYS_BLUE][i] = table[i];
+ }
+ break;
}
- break;
- case OPT_GAMMA_VECTOR_R:
- table = reinterpret_cast<SANE_Word*>(val);
- option_size = s->opt[option].size / sizeof (SANE_Word);
- s->dev->gamma_override_tables[GENESYS_RED].resize(option_size);
- for (i = 0; i < option_size; i++) {
- s->dev->gamma_override_tables[GENESYS_RED][i] = table[i];
+ case OPT_GAMMA_VECTOR_R: {
+ table = reinterpret_cast<SANE_Word*>(val);
+ option_size = s->opt[option].size / sizeof (SANE_Word);
+ dev->gamma_override_tables[GENESYS_RED].resize(option_size);
+ for (i = 0; i < option_size; i++) {
+ dev->gamma_override_tables[GENESYS_RED][i] = table[i];
+ }
+ break;
}
- break;
- case OPT_GAMMA_VECTOR_G:
- table = reinterpret_cast<SANE_Word*>(val);
- option_size = s->opt[option].size / sizeof (SANE_Word);
- s->dev->gamma_override_tables[GENESYS_GREEN].resize(option_size);
- for (i = 0; i < option_size; i++) {
- s->dev->gamma_override_tables[GENESYS_GREEN][i] = table[i];
+ case OPT_GAMMA_VECTOR_G: {
+ table = reinterpret_cast<SANE_Word*>(val);
+ option_size = s->opt[option].size / sizeof (SANE_Word);
+ dev->gamma_override_tables[GENESYS_GREEN].resize(option_size);
+ for (i = 0; i < option_size; i++) {
+ dev->gamma_override_tables[GENESYS_GREEN][i] = table[i];
+ }
+ break;
}
- break;
- case OPT_GAMMA_VECTOR_B:
- table = reinterpret_cast<SANE_Word*>(val);
- option_size = s->opt[option].size / sizeof (SANE_Word);
- s->dev->gamma_override_tables[GENESYS_BLUE].resize(option_size);
- for (i = 0; i < option_size; i++) {
- s->dev->gamma_override_tables[GENESYS_BLUE][i] = table[i];
+ case OPT_GAMMA_VECTOR_B: {
+ table = reinterpret_cast<SANE_Word*>(val);
+ option_size = s->opt[option].size / sizeof (SANE_Word);
+ dev->gamma_override_tables[GENESYS_BLUE].resize(option_size);
+ for (i = 0; i < option_size; i++) {
+ dev->gamma_override_tables[GENESYS_BLUE][i] = table[i];
+ }
+ break;
}
- break;
case OPT_CALIBRATE: {
- auto& sensor = sanei_genesys_find_sensor_for_write(s->dev, s->dev->settings.xres,
- s->dev->settings.get_channels(),
- s->dev->settings.scan_method);
+ auto& sensor = sanei_genesys_find_sensor_for_write(dev, dev->settings.xres,
+ dev->settings.get_channels(),
+ dev->settings.scan_method);
catch_all_exceptions(__func__, [&]()
{
- s->dev->cmd_set->save_power(s->dev, false);
- genesys_scanner_calibration(s->dev, sensor);
+ dev->cmd_set->save_power(dev, false);
+ genesys_scanner_calibration(dev, sensor);
});
catch_all_exceptions(__func__, [&]()
{
- s->dev->cmd_set->save_power(s->dev, true);
+ dev->cmd_set->save_power(dev, true);
});
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
}
- case OPT_CLEAR_CALIBRATION:
- s->dev->calibration_cache.clear();
+ case OPT_CLEAR_CALIBRATION: {
+ dev->calibration_cache.clear();
- /* remove file */
- unlink(s->dev->calib_file.c_str());
- /* signals that sensors will have to be read again */
- *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
- break;
- case OPT_FORCE_CALIBRATION:
- s->dev->force_calibration = 1;
- s->dev->calibration_cache.clear();
- s->dev->calib_file.clear();
+ // remove file
+ unlink(dev->calib_file.c_str());
+ // signals that sensors will have to be read again
+ *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
+ break;
+ }
+ case OPT_FORCE_CALIBRATION: {
+ dev->force_calibration = 1;
+ dev->calibration_cache.clear();
+ dev->calib_file.clear();
- /* signals that sensors will have to be read again */
- *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
- break;
+ // signals that sensors will have to be read again
+ *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
+ break;
+ }
case OPT_IGNORE_OFFSETS: {
- s->dev->ignore_offsets = true;
+ dev->ignore_offsets = true;
break;
}
- default:
- DBG(DBG_warn, "%s: can't set unknown option %d\n", __func__, option);
+ default: {
+ DBG(DBG_warn, "%s: can't set unknown option %d\n", __func__, option);
+ }
}
}
@@ -5829,13 +6217,13 @@ void sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params)
{
DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
+ auto* dev = s->dev;
/* don't recompute parameters once data reading is active, ie during scan */
- if (!s->dev->read_active) {
+ if (!dev->read_active) {
calc_parameters(s);
}
- if (params)
- {
+ if (params) {
*params = s->params;
/* in the case of a sheetfed scanner, when full height is specified
@@ -5843,11 +6231,11 @@ void sane_get_parameters_impl(SANE_Handle handle, SANE_Parameters* params)
* don't know the real document height.
* We don't do that doing buffering image for digital processing
*/
- if (s->dev->model->is_sheetfed && !s->dev->buffer_image &&
+ if (dev->model->is_sheetfed &&
s->pos_bottom_right_y == s->opt[OPT_BR_Y].constraint.range->max)
{
- params->lines = -1;
- }
+ params->lines = -1;
+ }
}
debug_dump(DBG_proc, *params);
}
@@ -5865,6 +6253,7 @@ void sane_start_impl(SANE_Handle handle)
{
DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
+ auto* dev = s->dev;
if (s->pos_top_left_x >= s->pos_bottom_right_x) {
throw SaneException("top left x >= bottom right x");
@@ -5873,67 +6262,27 @@ void sane_start_impl(SANE_Handle handle)
throw SaneException("top left y >= bottom right y");
}
- /* First make sure we have a current parameter set. Some of the
- parameters will be overwritten below, but that's OK. */
-
- calc_parameters(s);
- genesys_start_scan(s->dev, s->lamp_off);
-
- s->scanning = true;
+ // fetch stored calibration
+ if (dev->force_calibration == 0) {
+ auto path = calibration_filename(dev);
+ s->calibration_file = path;
+ dev->calib_file = path;
+ DBG(DBG_info, "%s: Calibration filename set to:\n", __func__);
+ DBG(DBG_info, "%s: >%s<\n", __func__, dev->calib_file.c_str());
- /* allocate intermediate buffer when doing dynamic lineart */
- if (s->dev->settings.scan_mode == ScanColorMode::LINEART) {
- s->dev->binarize_buffer.clear();
- s->dev->binarize_buffer.alloc(s->dev->settings.pixels);
- s->dev->local_buffer.clear();
- s->dev->local_buffer.alloc(s->dev->binarize_buffer.size() * 8);
+ catch_all_exceptions(__func__, [&]()
+ {
+ sanei_genesys_read_calibration(dev->calibration_cache, dev->calib_file);
+ });
}
- /* if one of the software enhancement option is selected,
- * we do the scan internally, process picture then put it an internal
- * buffer. Since cropping may change scan parameters, we recompute them
- * at the end */
- if (s->dev->buffer_image)
- {
- genesys_buffer_image(s);
-
- /* check if we need to skip this page, sheetfed scanners
- * can go to next doc while flatbed ones can't */
- if (s->swskip > 0 && IS_ACTIVE(OPT_SWSKIP)) {
- auto status = sanei_magic_isBlank(&s->params,
- s->dev->img_buffer.data(),
- SANE_UNFIX(s->swskip));
-
- if (status == SANE_STATUS_NO_DOCS && s->dev->model->is_sheetfed) {
- DBG(DBG_info, "%s: blank page, recurse\n", __func__);
- sane_start(handle);
- return;
- }
+ // First make sure we have a current parameter set. Some of the
+ // parameters will be overwritten below, but that's OK.
- if (status != SANE_STATUS_GOOD) {
- throw SaneException(status);
- }
- }
-
- if (s->swdeskew) {
- const auto& sensor = sanei_genesys_find_sensor(s->dev, s->dev->settings.xres,
- s->dev->settings.get_channels(),
- s->dev->settings.scan_method);
- catch_all_exceptions(__func__, [&](){ genesys_deskew(s, sensor); });
- }
-
- if (s->swdespeck) {
- catch_all_exceptions(__func__, [&](){ genesys_despeck(s); });
- }
-
- if(s->swcrop) {
- catch_all_exceptions(__func__, [&](){ genesys_crop(s); });
- }
+ calc_parameters(s);
+ genesys_start_scan(dev, s->lamp_off);
- if(s->swderotate) {
- catch_all_exceptions(__func__, [&](){ genesys_derotate(s); });
- }
- }
+ s->scanning = true;
}
SANE_GENESYS_API_LINKAGE
@@ -5945,18 +6294,18 @@ SANE_Status sane_start(SANE_Handle handle)
});
}
-void sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len)
+// returns SANE_STATUS_GOOD if there are more data, SANE_STATUS_EOF otherwise
+SANE_Status sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len)
{
DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
- Genesys_Device *dev;
size_t local_len;
if (!s) {
throw SaneException("handle is nullptr");
}
- dev=s->dev;
+ auto* dev = s->dev;
if (!dev) {
throw SaneException("dev is nullptr");
}
@@ -5986,86 +6335,33 @@ void sane_read_impl(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_
/* issue park command immediatly in case scanner can handle it
* so we save time */
- if (!dev->model->is_sheetfed && !(dev->model->flags & GENESYS_FLAG_MUST_WAIT) &&
+ if (!dev->model->is_sheetfed && !has_flag(dev->model->flags, ModelFlag::MUST_WAIT) &&
!dev->parking)
{
dev->cmd_set->move_back_home(dev, false);
dev->parking = true;
}
- throw SaneException(SANE_STATUS_EOF);
+ return SANE_STATUS_EOF;
}
local_len = max_len;
- /* in case of image processing, all data has been stored in
- * buffer_image. So read data from it if it exists, else from scanner */
- if(!dev->buffer_image)
- {
- /* dynamic lineart is another kind of digital processing that needs
- * another layer of buffering on top of genesys_read_ordered_data */
- if (dev->settings.scan_mode == ScanColorMode::LINEART) {
- /* if buffer is empty, fill it with genesys_read_ordered_data */
- if(dev->binarize_buffer.avail() == 0)
- {
- /* store gray data */
- local_len=dev->local_buffer.size();
- dev->local_buffer.reset();
- genesys_read_ordered_data(dev, dev->local_buffer.get_write_pos(local_len),
- &local_len);
- dev->local_buffer.produce(local_len);
-
- dev->binarize_buffer.reset();
- if (!is_testing_mode()) {
- genesys_gray_lineart(dev, dev->local_buffer.get_read_pos(),
- dev->binarize_buffer.get_write_pos(local_len / 8),
- dev->settings.pixels,
- local_len / dev->settings.pixels,
- dev->settings.threshold);
- }
- dev->binarize_buffer.produce(local_len / 8);
- }
-
- /* return data from lineart buffer if any, up to the available amount */
- local_len = max_len;
- if (static_cast<std::size_t>(max_len) > dev->binarize_buffer.avail())
- {
- local_len=dev->binarize_buffer.avail();
- }
- if(local_len)
- {
- memcpy(buf, dev->binarize_buffer.get_read_pos(), local_len);
- dev->binarize_buffer.consume(local_len);
- }
- }
- else
- {
- // most usual case, direct read of data from scanner */
- genesys_read_ordered_data(dev, buf, &local_len);
- }
- }
- else /* read data from buffer */
- {
- if(dev->total_bytes_read+local_len>dev->total_bytes_to_read)
- {
- local_len=dev->total_bytes_to_read-dev->total_bytes_read;
- }
- memcpy(buf, dev->img_buffer.data() + dev->total_bytes_read, local_len);
- dev->total_bytes_read+=local_len;
- }
+ genesys_read_ordered_data(dev, buf, &local_len);
*len = local_len;
if (local_len > static_cast<std::size_t>(max_len)) {
- fprintf (stderr, "[genesys] sane_read: returning incorrect length!!\n");
+ dbg.log(DBG_error, "error: returning incorrect length");
}
DBG(DBG_proc, "%s: %d bytes returned\n", __func__, *len);
+ return SANE_STATUS_GOOD;
}
SANE_GENESYS_API_LINKAGE
SANE_Status sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int* len)
{
- return wrap_exceptions_to_status_code(__func__, [=]()
+ return wrap_exceptions_to_status_code_return(__func__, [=]()
{
- sane_read_impl(handle, buf, max_len, len);
+ return sane_read_impl(handle, buf, max_len, len);
});
}
@@ -6073,36 +6369,31 @@ void sane_cancel_impl(SANE_Handle handle)
{
DBG_HELPER(dbg);
Genesys_Scanner* s = reinterpret_cast<Genesys_Scanner*>(handle);
+ auto* dev = s->dev;
s->scanning = false;
- s->dev->read_active = false;
- s->dev->img_buffer.clear();
+ dev->read_active = false;
- /* no need to end scan if we are parking the head */
- if (!s->dev->parking) {
- s->dev->cmd_set->end_scan(s->dev, &s->dev->reg, true);
+ // no need to end scan if we are parking the head
+ if (!dev->parking) {
+ dev->cmd_set->end_scan(dev, &dev->reg, true);
}
- /* park head if flatbed scanner */
- if (!s->dev->model->is_sheetfed) {
- if (!s->dev->parking) {
- s->dev->cmd_set->move_back_home (s->dev, s->dev->model->flags &
- GENESYS_FLAG_MUST_WAIT);
-
- s->dev->parking = !(s->dev->model->flags & GENESYS_FLAG_MUST_WAIT);
+ // park head if flatbed scanner
+ if (!dev->model->is_sheetfed) {
+ if (!dev->parking) {
+ dev->cmd_set->move_back_home(dev, has_flag(dev->model->flags, ModelFlag::MUST_WAIT));
+ dev->parking = !has_flag(dev->model->flags, ModelFlag::MUST_WAIT);
}
- }
- else
- { /* in case of sheetfed scanners, we have to eject the document if still present */
- s->dev->cmd_set->eject_document(s->dev);
+ } else {
+ // in case of sheetfed scanners, we have to eject the document if still present
+ dev->cmd_set->eject_document(dev);
}
- /* enable power saving mode unless we are parking .... */
- if (!s->dev->parking) {
- s->dev->cmd_set->save_power(s->dev, true);
+ // enable power saving mode unless we are parking ....
+ if (!dev->parking) {
+ dev->cmd_set->save_power(dev, true);
}
-
- return;
}
SANE_GENESYS_API_LINKAGE
diff --git a/backend/genesys/genesys.h b/backend/genesys/genesys.h
index 255bf76..9b1a087 100644
--- a/backend/genesys/genesys.h
+++ b/backend/genesys/genesys.h
@@ -107,21 +107,12 @@ enum Genesys_Option
OPT_GAMMA_VECTOR_R,
OPT_GAMMA_VECTOR_G,
OPT_GAMMA_VECTOR_B,
- OPT_SWDESKEW,
- OPT_SWCROP,
- OPT_SWDESPECK,
- OPT_DESPECK,
- OPT_SWSKIP,
- OPT_SWDEROTATE,
OPT_BRIGHTNESS,
OPT_CONTRAST,
OPT_EXTRAS_GROUP,
OPT_LAMP_OFF_TIME,
OPT_LAMP_OFF,
- OPT_THRESHOLD,
- OPT_THRESHOLD_CURVE,
- OPT_DISABLE_INTERPOLATION,
OPT_COLOR_FILTER,
OPT_CALIBRATION_FILE,
OPT_EXPIRATION_TIME,
@@ -213,18 +204,9 @@ struct Genesys_Scanner
// Option values
SANE_Word bit_depth = 0;
SANE_Word resolution = 0;
- bool preview = false;
- SANE_Word threshold = 0;
- SANE_Word threshold_curve = 0;
- bool disable_interpolation = false;
+ bool preview = false; // TODO: currently not used
bool lamp_off = false;
SANE_Word lamp_off_time = 0;
- bool swdeskew = false;
- bool swcrop = false;
- bool swdespeck = false;
- bool swderotate = false;
- SANE_Word swskip = 0;
- SANE_Word despeck = 0;
SANE_Word contrast = 0;
SANE_Word brightness = 0;
SANE_Word expiration_time = 0;
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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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
diff --git a/backend/genesys/gl124.h b/backend/genesys/gl124.h
index cdf8faf..ea7041e 100644
--- a/backend/genesys/gl124.h
+++ b/backend/genesys/gl124.h
@@ -45,74 +45,12 @@
#define BACKEND_GENESYS_GL124_H
#include "genesys.h"
-#include "command_set.h"
+#include "command_set_common.h"
namespace genesys {
namespace gl124 {
-typedef struct
-{
- uint8_t r31;
- uint8_t r32;
- uint8_t r33;
- uint8_t r34;
- uint8_t r35;
- uint8_t r36;
- uint8_t r38;
-} Gpio_layout;
-
-/** @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
- },
-};
-
-typedef struct
-{
- uint8_t rd0;
- uint8_t rd1;
- uint8_t rd2;
- uint8_t re0;
- uint8_t re1;
- uint8_t re2;
- uint8_t re3;
- uint8_t re4;
- uint8_t re5;
- uint8_t re6;
- uint8_t re7;
-} Memory_layout;
-
-static Memory_layout layouts[]={
- /* LIDE 110, 120 */
- { /* 0xd0 0xd1 0xd2 */
- 0x0a, 0x15, 0x20,
- /* 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 */
- 0x00, 0xac, 0x08, 0x55, 0x08, 0x56, 0x0f, 0xff
- },
- /* LIDE 210, 220 */
- {
- 0x0a, 0x1f, 0x34,
- 0x01, 0x24, 0x08, 0x91, 0x08, 0x92, 0x0f, 0xff
- }
-};
-
-static void gl124_send_slope_table(Genesys_Device* dev, int table_nr,
- const std::vector<uint16_t>& slope_table, int steps);
-
-class CommandSetGl124 : public CommandSet
+class CommandSetGl124 : public CommandSetCommon
{
public:
~CommandSetGl124() override = default;
@@ -122,17 +60,11 @@ public:
void init(Genesys_Device* dev) const override;
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const override;
-
- void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const override;
+ Genesys_Register_Set* regs) const override;
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
- void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
-
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set* reg,
const ScanSession& session) const override;
@@ -148,8 +80,6 @@ public:
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
- void search_start_position(Genesys_Device* dev) const override;
-
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
@@ -165,8 +95,6 @@ public:
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
- bool needs_update_home_sensor_gpio() const override { return true; }
-
void update_home_sensor_gpio(Genesys_Device& dev) const override;
void load_document(Genesys_Device* dev) const override;
@@ -175,11 +103,6 @@ public:
void eject_document(Genesys_Device* dev) const override;
- void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const override;
-
- void move_to_ta(Genesys_Device* dev) const override;
-
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
int size) const override;
diff --git a/backend/genesys/gl646.cpp b/backend/genesys/gl646.cpp
index 04ee85e..61fa1e0 100644
--- a/backend/genesys/gl646.cpp
+++ b/backend/genesys/gl646.cpp
@@ -63,9 +63,336 @@ namespace {
constexpr unsigned CALIBRATION_LINES = 10;
} // namespace
-static void gl646_send_slope_table(Genesys_Device* dev, int table_nr,
- const std::vector<uint16_t>& slope_table,
- int steps);
+static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int resolution);
+
+
+static void gl646_set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set, int dpi);
+
+static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ const ScanSession& session, bool move,
+ std::vector<uint8_t>& data, const char* test_identifier);
+/**
+ * Send the stop scan command
+ * */
+static void end_scan_impl(Genesys_Device* dev, Genesys_Register_Set* reg, bool check_stop,
+ bool eject);
+
+/**
+ * master motor settings table entry
+ */
+struct Motor_Master
+{
+ MotorId motor_id;
+ unsigned dpi;
+ unsigned channels;
+
+ // settings
+ StepType steptype;
+ bool fastmod; // fast scanning
+ bool fastfed; // fast fed slope tables
+ SANE_Int mtrpwm;
+ MotorSlope slope1;
+ MotorSlope slope2;
+ SANE_Int fwdbwd; // forward/backward steps
+};
+
+/**
+ * master motor settings, for a given motor and dpi,
+ * it gives steps and speed informations
+ */
+static Motor_Master motor_master[] = {
+ /* HP3670 motor settings */
+ {MotorId::HP3670, 50, 3, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(2329, 120, 229),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 75, 3, StepType::FULL, false, true, 1,
+ MotorSlope::create_from_steps(3429, 305, 200),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 100, 3, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(2905, 187, 143),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 150, 3, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(3429, 305, 73),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 300, 3, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(1055, 563, 11),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 600, 3, StepType::FULL, false, true, 0,
+ MotorSlope::create_from_steps(10687, 5126, 3),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670,1200, 3, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(15937, 6375, 3),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 50, 1, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(2329, 120, 229),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 75, 1, StepType::FULL, false, true, 1,
+ MotorSlope::create_from_steps(3429, 305, 200),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 100, 1, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(2905, 187, 143),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 150, 1, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(3429, 305, 73),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 300, 1, StepType::HALF, false, true, 1,
+ MotorSlope::create_from_steps(1055, 563, 11),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670, 600, 1, StepType::FULL, false, true, 0,
+ MotorSlope::create_from_steps(10687, 5126, 3),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ {MotorId::HP3670,1200, 1, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(15937, 6375, 3),
+ MotorSlope::create_from_steps(3399, 337, 192), 192},
+
+ /* HP2400/G2410 motor settings base motor dpi = 600 */
+ {MotorId::HP2400, 50, 3, StepType::FULL, false, true, 63,
+ MotorSlope::create_from_steps(8736, 601, 120),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 100, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(8736, 601, 120),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 150, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(15902, 902, 67),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 300, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(16703, 2188, 32),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 600, 3, StepType::FULL, false, true, 63,
+ MotorSlope::create_from_steps(18761, 18761, 3),
+ MotorSlope::create_from_steps(4905, 627, 192), 192},
+
+ {MotorId::HP2400,1200, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(43501, 43501, 3),
+ MotorSlope::create_from_steps(4905, 627, 192), 192},
+
+ {MotorId::HP2400, 50, 1, StepType::FULL, false, true, 63,
+ MotorSlope::create_from_steps(8736, 601, 120),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 100, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(8736, 601, 120),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 150, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(15902, 902, 67),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 300, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(16703, 2188, 32),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400, 600, 1, StepType::FULL, false, true, 63,
+ MotorSlope::create_from_steps(18761, 18761, 3),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ {MotorId::HP2400,1200, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(43501, 43501, 3),
+ MotorSlope::create_from_steps(4905, 337, 192), 192},
+
+ /* XP 200 motor settings */
+ {MotorId::XP200, 75, 3, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(6000, 2136, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 100, 3, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(6000, 2850, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 200, 3, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(6999, 5700, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 250, 3, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(6999, 6999, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 300, 3, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(13500, 13500, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 600, 3, StepType::HALF, true, true, 0,
+ MotorSlope::create_from_steps(31998, 31998, 4),
+ MotorSlope::create_from_steps(12000, 1200, 2), 1},
+
+ {MotorId::XP200, 75, 1, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(6000, 2000, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 100, 1, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(6000, 1300, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 200, 1, StepType::HALF, true, true, 0,
+ MotorSlope::create_from_steps(6000, 3666, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 300, 1, StepType::HALF, true, false, 0,
+ MotorSlope::create_from_steps(6500, 6500, 4),
+ MotorSlope::create_from_steps(12000, 1200, 8), 1},
+
+ {MotorId::XP200, 600, 1, StepType::HALF, true, true, 0,
+ MotorSlope::create_from_steps(24000, 24000, 4),
+ MotorSlope::create_from_steps(12000, 1200, 2), 1},
+
+ /* HP scanjet 2300c */
+ {MotorId::HP2300, 75, 3, StepType::FULL, false, true, 63,
+ MotorSlope::create_from_steps(8139, 560, 120),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 150, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(7903, 543, 67),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(2175, 1087, 3),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 600, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(8700, 4350, 3),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300,1200, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(17400, 8700, 3),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 75, 1, StepType::FULL, false, true, 63,
+ MotorSlope::create_from_steps(8139, 560, 120),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 150, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(7903, 543, 67),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(2175, 1087, 3),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 600, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(8700, 4350, 3),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300,1200, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(17400, 8700, 3),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ /* non half ccd settings for 300 dpi
+ {MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(5386, 2175, 44),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+
+ {MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63,
+ MotorSlope::create_from_steps(5386, 2175, 44),
+ MotorSlope::create_from_steps(4905, 337, 120), 16},
+ */
+
+ /* MD5345/6471 motor settings */
+ /* vfinal=(exposure/(1200/dpi))/step_type */
+ {MotorId::MD_5345, 50, 3, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 250, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 75, 3, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 343, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 100, 3, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 458, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 150, 3, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 687, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 200, 3, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 916, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 300, 3, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 1375, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 400, 3, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(2000, 1833, 32),
+ MotorSlope::create_from_steps(2000, 300, 255), 32},
+
+ {MotorId::MD_5345, 500, 3, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(2291, 2291, 32),
+ MotorSlope::create_from_steps(2000, 300, 255), 32},
+
+ {MotorId::MD_5345, 600, 3, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(2750, 2750, 32),
+ MotorSlope::create_from_steps(2000, 300, 255), 32},
+
+ {MotorId::MD_5345, 1200, 3, StepType::QUARTER, false, true, 0,
+ MotorSlope::create_from_steps(2750, 2750, 16),
+ MotorSlope::create_from_steps(2000, 300, 255), 146},
+
+ {MotorId::MD_5345, 2400, 3, StepType::QUARTER, false, true, 0,
+ MotorSlope::create_from_steps(5500, 5500, 16),
+ MotorSlope::create_from_steps(2000, 300, 255), 146},
+
+ {MotorId::MD_5345, 50, 1, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 250, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 75, 1, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 343, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 100, 1, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 458, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 150, 1, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 687, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 200, 1, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 916, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 300, 1, StepType::HALF, false, true, 2,
+ MotorSlope::create_from_steps(2500, 1375, 255),
+ MotorSlope::create_from_steps(2000, 300, 255), 64},
+
+ {MotorId::MD_5345, 400, 1, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(2000, 1833, 32),
+ MotorSlope::create_from_steps(2000, 300, 255), 32},
+
+ {MotorId::MD_5345, 500, 1, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(2291, 2291, 32),
+ MotorSlope::create_from_steps(2000, 300, 255), 32},
+
+ {MotorId::MD_5345, 600, 1, StepType::HALF, false, true, 0,
+ MotorSlope::create_from_steps(2750, 2750, 32),
+ MotorSlope::create_from_steps(2000, 300, 255), 32},
+
+ {MotorId::MD_5345, 1200, 1, StepType::QUARTER, false, true, 0,
+ MotorSlope::create_from_steps(2750, 2750, 16),
+ MotorSlope::create_from_steps(2000, 300, 255), 146},
+
+ {MotorId::MD_5345, 2400, 1, StepType::QUARTER, false, true, 0,
+ MotorSlope::create_from_steps(5500, 5500, 16),
+ MotorSlope::create_from_steps(2000, 300, 255), 146}, /* 5500 guessed */
+};
/**
* reads value from gpio endpoint
@@ -105,44 +432,6 @@ static void gl646_stop_motor(Genesys_Device* dev)
}
/**
- * find the closest match in mode tables for the given resolution and scan mode.
- * @param sensor id of the sensor
- * @param required required resolution
- * @param color true is color mode
- * @return the closest resolution for the sensor and mode
- */
-static unsigned get_closest_resolution(SensorId sensor_id, int required, unsigned channels)
-{
- unsigned best_res = 0;
- unsigned best_diff = 9600;
-
- for (const auto& sensor : *s_sensors) {
- if (sensor_id != sensor.sensor_id)
- continue;
-
- // exit on perfect match
- if (sensor.resolutions.matches(required) && sensor.matches_channel_count(channels)) {
- DBG(DBG_info, "%s: match found for %d\n", __func__, required);
- return required;
- }
-
- // computes distance and keep mode if it is closer than previous
- if (sensor.matches_channel_count(channels)) {
- for (auto res : sensor.resolutions.resolutions()) {
- unsigned curr_diff = std::abs(static_cast<int>(res) - static_cast<int>(required));
- if (curr_diff < best_diff) {
- best_res = res;
- best_diff = curr_diff;
- }
- }
- }
- }
-
- DBG(DBG_info, "%s: closest match for %d is %d\n", __func__, required, best_res);
- return best_res;
-}
-
-/**
* Returns the cksel values used by the required scan mode.
* @param sensor id of the sensor
* @param required required resolution
@@ -157,7 +446,6 @@ static int get_cksel(SensorId sensor_id, int required, unsigned channels)
sensor.matches_channel_count(channels))
{
unsigned cksel = sensor.ccd_pixels_per_system_pixel();
- DBG(DBG_io, "%s: match found for %d (cksel=%d)\n", __func__, required, cksel);
return cksel;
}
}
@@ -177,7 +465,6 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
uint32_t move = session.params.starty;
- int i, nb;
Motor_Master *motor = nullptr;
uint32_t z1, z2;
int feedl;
@@ -185,57 +472,47 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
/* for the given resolution, search for master
* motor mode setting */
- i = 0;
- nb = sizeof (motor_master) / sizeof (Motor_Master);
- while (i < nb)
- {
- if (dev->model->motor_id == motor_master[i].motor_id
- && motor_master[i].dpi == session.params.yres
- && motor_master[i].channels == session.params.channels)
- {
- motor = &motor_master[i];
- }
- i++;
+ for (unsigned i = 0; i < sizeof (motor_master) / sizeof (Motor_Master); ++i) {
+ if (dev->model->motor_id == motor_master[i].motor_id &&
+ motor_master[i].dpi == session.params.yres &&
+ motor_master[i].channels == session.params.channels)
+ {
+ motor = &motor_master[i];
+ }
}
- if (motor == nullptr)
- {
+ if (motor == nullptr) {
throw SaneException("unable to find settings for motor %d at %d dpi, color=%d",
static_cast<unsigned>(dev->model->motor_id),
session.params.yres, session.params.channels);
}
- /* now we can search for the specific sensor settings */
- i = 0;
-
- // now apply values from settings to registers
- regs->set16(REG_EXPR, sensor.exposure.red);
- regs->set16(REG_EXPG, sensor.exposure.green);
- regs->set16(REG_EXPB, sensor.exposure.blue);
-
- for (const auto& reg : sensor.custom_regs) {
- regs->set8(reg.address, reg.value);
- }
+ scanner_setup_sensor(*dev, sensor, *regs);
/* now generate slope tables : we are not using generate_slope_table3 yet */
- auto slope_table1 = create_slope_table(motor->slope1, motor->slope1.max_speed_w, StepType::FULL,
- 1, 4, get_slope_table_max_size(AsicType::GL646));
- auto slope_table2 = create_slope_table(motor->slope2, motor->slope2.max_speed_w, StepType::FULL,
- 1, 4, get_slope_table_max_size(AsicType::GL646));
+ auto slope_table1 = create_slope_table_for_speed(motor->slope1, motor->slope1.max_speed_w,
+ StepType::FULL, 1, 4,
+ get_slope_table_max_size(AsicType::GL646));
+ auto slope_table2 = create_slope_table_for_speed(motor->slope2, motor->slope2.max_speed_w,
+ StepType::FULL, 1, 4,
+ get_slope_table_max_size(AsicType::GL646));
/* R01 */
/* now setup other registers for final scan (ie with shading enabled) */
/* watch dog + shading + scan enable */
- regs->find_reg(0x01).value |= REG_0x01_DOGENB | REG_0x01_DVDSET | REG_0x01_SCAN;
+ regs->find_reg(0x01).value |= REG_0x01_DOGENB | REG_0x01_SCAN;
if (dev->model->is_cis) {
regs->find_reg(0x01).value |= REG_0x01_CISSET;
} else {
regs->find_reg(0x01).value &= ~REG_0x01_CISSET;
}
- /* if device has no calibration, don't enable shading correction */
- if (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)
+ // if device has no calibration, don't enable shading correction
+ if (has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
+ has_flag(session.params.flags, ScanFlag::DISABLE_SHADING))
{
regs->find_reg(0x01).value &= ~REG_0x01_DVDSET;
+ } else {
+ regs->find_reg(0x01).value |= REG_0x01_DVDSET;
}
regs->find_reg(0x01).value &= ~REG_0x01_FASTMOD;
@@ -284,7 +561,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
break;
}
- if (dev->model->is_sheetfed) {
+ if (dev->model->is_sheetfed || !has_flag(session.params.flags, ScanFlag::AUTO_GO_HOME)) {
regs->find_reg(0x02).value &= ~REG_0x02_AGOHOME;
} else {
regs->find_reg(0x02).value |= REG_0x02_AGOHOME;
@@ -314,14 +591,20 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
break;
}
- sanei_genesys_set_dpihw(*regs, sensor, sensor.optical_res);
+ sanei_genesys_set_dpihw(*regs, sensor.full_resolution);
/* gamma enable for scans */
- if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) {
+ if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {
regs->find_reg(0x05).value |= REG_0x05_GMM14BIT;
}
- regs->find_reg(0x05).value &= ~REG_0x05_GMMENB;
+ if (!has_flag(session.params.flags, ScanFlag::DISABLE_GAMMA) &&
+ session.params.depth < 16)
+ {
+ regs->find_reg(REG_0x05).value |= REG_0x05_GMMENB;
+ } else {
+ regs->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
+ }
/* true CIS gray if needed */
if (dev->model->is_cis && session.params.channels == 1 && dev->settings.true_gray) {
@@ -356,17 +639,17 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
// the steps count must be different by at most 128, otherwise it's impossible to construct
// a proper backtracking curve. We're using slightly lower limit to allow at least a minimum
// distance between accelerations (forward_steps, backward_steps)
- if (slope_table1.steps_count > slope_table2.steps_count + 100) {
- slope_table2.steps_count += slope_table1.steps_count - 100;
+ if (slope_table1.table.size() > slope_table2.table.size() + 100) {
+ slope_table2.expand_table(slope_table1.table.size() - 100, 1);
}
- if (slope_table2.steps_count > slope_table1.steps_count + 100) {
- slope_table1.steps_count += slope_table2.steps_count - 100;
+ if (slope_table2.table.size() > slope_table1.table.size() + 100) {
+ slope_table1.expand_table(slope_table2.table.size() - 100, 1);
}
- if (slope_table1.steps_count >= slope_table2.steps_count) {
- backward_steps += (slope_table1.steps_count - slope_table2.steps_count) * 2;
+ if (slope_table1.table.size() >= slope_table2.table.size()) {
+ backward_steps += (slope_table1.table.size() - slope_table2.table.size()) * 2;
} else {
- forward_steps += (slope_table2.steps_count - slope_table1.steps_count) * 2;
+ forward_steps += (slope_table2.table.size() - slope_table1.table.size()) * 2;
}
if (forward_steps > 255) {
@@ -382,8 +665,8 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
forward_steps -= backward_steps - 255;
}
- regs->find_reg(0x21).value = slope_table1.steps_count;
- regs->find_reg(0x24).value = slope_table2.steps_count;
+ regs->find_reg(0x21).value = slope_table1.table.size();
+ regs->find_reg(0x24).value = slope_table2.table.size();
regs->find_reg(0x22).value = forward_steps;
regs->find_reg(0x23).value = backward_steps;
@@ -401,8 +684,11 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
regs->set24(REG_MAXWD, session.output_line_bytes);
- regs->set16(REG_DPISET, session.output_resolution * session.ccd_size_divisor *
- sensor.ccd_pixels_per_system_pixel());
+ // FIXME: the incoming sensor is selected for incorrect resolution
+ const auto& dpiset_sensor = sanei_genesys_find_sensor(dev, session.params.xres,
+ session.params.channels,
+ session.params.scan_method);
+ regs->set16(REG_DPISET, dpiset_sensor.register_dpiset);
regs->set16(REG_LPERIOD, sensor.exposure_lperiod);
/* move distance must be adjusted to take into account the extra lines
@@ -410,8 +696,8 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
feedl = move;
if (session.num_staggered_lines + session.max_color_shift_lines > 0 && feedl != 0) {
- int feed_offset = ((session.max_color_shift_lines + session.num_staggered_lines) * dev->motor.optical_ydpi) /
- motor->dpi;
+ unsigned total_lines = session.max_color_shift_lines + session.num_staggered_lines;
+ int feed_offset = (total_lines * dev->motor.base_ydpi) / motor->dpi;
if (feedl > feed_offset) {
feedl = feedl - feed_offset;
}
@@ -424,8 +710,6 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
/* but head has moved due to shading calibration => dev->scanhead_position_primary */
if (feedl > 0)
{
- DBG(DBG_info, "%s: initial move=%d\n", __func__, feedl);
-
/* TODO clean up this when I'll fully understand.
* for now, special casing each motor */
switch (dev->model->motor_id) {
@@ -505,12 +789,12 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
if (motor->fastfed)
{
- feedl = feedl - 2 * slope_table2.steps_count -
- (slope_table1.steps_count >> step_shift);
+ feedl = feedl - 2 * slope_table2.table.size() -
+ (slope_table1.table.size() >> step_shift);
}
else
{
- feedl = feedl - (slope_table1.steps_count >> step_shift);
+ feedl = feedl - (slope_table1.table.size() >> step_shift);
}
break;
}
@@ -520,7 +804,6 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
feedl = 0;
}
- DBG(DBG_info, "%s: final move=%d\n", __func__, feedl);
regs->set24(REG_FEEDL, feedl);
regs->find_reg(0x65).value = motor->mtrpwm;
@@ -528,7 +811,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
sanei_genesys_calculate_zmod(regs->find_reg(0x02).value & REG_0x02_FASTFED,
sensor.exposure_lperiod,
slope_table1.table,
- slope_table1.steps_count,
+ slope_table1.table.size(),
move, motor->fwdbwd, &z1, &z2);
/* no z1/z2 for sheetfed scanners */
@@ -538,7 +821,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
}
regs->set16(REG_Z1MOD, z1);
regs->set16(REG_Z2MOD, z2);
- regs->find_reg(0x6b).value = slope_table2.steps_count;
+ regs->find_reg(0x6b).value = slope_table2.table.size();
regs->find_reg(0x6c).value =
(regs->find_reg(0x6c).value & REG_0x6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16)
& 0x07);
@@ -548,10 +831,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
// setup analog frontend
gl646_set_fe(dev, sensor, AFE_SET, session.output_resolution);
- dev->read_buffer.clear();
- dev->read_buffer.alloc(session.buffer_size_read);
-
- build_image_pipeline(dev, session);
+ setup_image_pipeline(*dev, session);
dev->read_active = true;
@@ -578,32 +858,8 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
}
}
- gl646_send_slope_table(dev, 0, slope_table1.table, regs->get8(0x21));
- gl646_send_slope_table(dev, 1, slope_table2.table, regs->get8(0x6b));
-}
-
-
-/** copy sensor specific settings */
-/* *dev : device infos
- *regs : regiters to be set
- extended : do extended set up
- ccd_size_divisor: set up for half ccd resolution
- all registers 08-0B, 10-1D, 52-5E are set up. They shouldn't
- appear anywhere else but in register init
-*/
-static void
-gl646_setup_sensor (Genesys_Device * dev, const Genesys_Sensor& sensor, Genesys_Register_Set * regs)
-{
- (void) dev;
- DBG(DBG_proc, "%s: start\n", __func__);
-
- for (const auto& reg_setting : sensor.custom_base_regs) {
- regs->set8(reg_setting.address, reg_setting.value);
- }
- // FIXME: all other drivers don't set exposure here
- regs_set_exposure(AsicType::GL646, *regs, sensor.exposure);
-
- DBG(DBG_proc, "%s: end\n", __func__);
+ scanner_send_slope_table(dev, sensor, 0, slope_table1.table);
+ scanner_send_slope_table(dev, sensor, 1, slope_table2.table);
}
/**
@@ -632,8 +888,8 @@ gl646_init_regs (Genesys_Device * dev)
for (addr = 0x60; addr <= 0x6d; addr++)
dev->reg.init_reg(addr, 0);
- dev->reg.find_reg(0x01).value = 0x20 /*0x22 */ ; /* enable shading, CCD, color, 1M */
- dev->reg.find_reg(0x02).value = 0x30 /*0x38 */ ; /* auto home, one-table-move, full step */
+ dev->reg.find_reg(0x01).value = 0x20 /*0x22 */ ; /* enable shading, CCD, color, 1M */
+ dev->reg.find_reg(0x02).value = 0x30 /*0x38 */ ; /* auto home, one-table-move, full step */
if (dev->model->motor_id == MotorId::MD_5345) {
dev->reg.find_reg(0x02).value |= 0x01; // half-step
}
@@ -648,8 +904,8 @@ gl646_init_regs (Genesys_Device * dev)
default:
break;
}
- dev->reg.find_reg(0x03).value = 0x1f /*0x17 */ ; /* lamp on */
- dev->reg.find_reg(0x04).value = 0x13 /*0x03 */ ; /* 8 bits data, 16 bits A/D, color, Wolfson fe *//* todo: according to spec, 0x0 is reserved? */
+ dev->reg.find_reg(0x03).value = 0x1f /*0x17 */ ; /* lamp on */
+ dev->reg.find_reg(0x04).value = 0x13 /*0x03 */ ; /* 8 bits data, 16 bits A/D, color, Wolfson fe *//* todo: according to spec, 0x0 is reserved? */
switch (dev->model->adc_id)
{
case AdcId::AD_XP200:
@@ -664,9 +920,9 @@ gl646_init_regs (Genesys_Device * dev)
const auto& sensor = sanei_genesys_find_sensor_any(dev);
dev->reg.find_reg(0x05).value = 0x00; /* 12 bits gamma, disable gamma, 24 clocks/pixel */
- sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
+ sanei_genesys_set_dpihw(dev->reg, sensor.full_resolution);
- if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) {
+ if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {
dev->reg.find_reg(0x05).value |= REG_0x05_GMM14BIT;
}
if (dev->model->adc_id == AdcId::AD_XP200) {
@@ -679,8 +935,7 @@ gl646_init_regs (Genesys_Device * dev)
dev->reg.find_reg(0x06).value = 0x18; // PWRBIT on, shading gain=8, normal AFE image capture
}
-
- gl646_setup_sensor(dev, sensor, &dev->reg);
+ scanner_setup_sensor(*dev, sensor, dev->reg);
dev->reg.find_reg(0x1e).value = 0xf0; /* watch-dog time */
@@ -788,54 +1043,15 @@ gl646_init_regs (Genesys_Device * dev)
dev->reg.find_reg(0x6c).value = 0x00; /* peroid times for LPeriod, expR,expG,expB, Z1MODE, Z2MODE (one period time) */
}
-
-// Send slope table for motor movement slope_table in machine byte order
-static void gl646_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)=%d .. %d", table_nr, steps, slope_table[0],
- slope_table[steps - 1]);
- int dpihw;
- int start_address;
-
- dpihw = dev->reg.find_reg(0x05).value >> 6;
-
- if (dpihw == 0) /* 600 dpi */
- start_address = 0x08000;
- else if (dpihw == 1) /* 1200 dpi */
- start_address = 0x10000;
- else if (dpihw == 2) /* 2400 dpi */
- start_address = 0x1f800;
- else {
- throw SaneException("Unexpected dpihw");
- }
-
- std::vector<uint8_t> table(steps * 2);
- for (int i = 0; i < steps; i++)
- {
- table[i * 2] = slope_table[i] & 0xff;
- table[i * 2 + 1] = slope_table[i] >> 8;
- }
-
- if (dev->interface->is_mock()) {
- dev->interface->record_slope_table(table_nr, slope_table);
- }
- dev->interface->write_buffer(0x3c, start_address + table_nr * 0x100, table.data(), steps * 2);
-}
-
// Set values of Analog Device type frontend
static void gl646_set_ad_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));
+ if (set == AFE_INIT) {
- dev->frontend = dev->frontend_initial;
+ dev->frontend = dev->frontend_initial;
// write them to analog frontend
dev->interface->write_fe_register(0x00, dev->frontend.regs.get_value(0x00));
@@ -888,8 +1104,7 @@ static void gl646_wm_hp3670(Genesys_Device* dev, const Genesys_Sensor& sensor, u
default: /* AFE_SET */
/* mode setup */
i = dev->frontend.regs.get_value(0x03);
- if (dpi > sensor.optical_res / 2)
- {
+ if (dpi > sensor.full_resolution / 2) {
/* fe_reg_0x03 must be 0x12 for 1200 dpi in WOLFSON_HP3670.
* WOLFSON_HP2400 in 1200 dpi mode works well with
* fe_reg_0x03 set to 0x32 or 0x12 but not to 0x02 */
@@ -947,11 +1162,8 @@ static void gl646_set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint
}
/* initialize analog frontend */
- 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;
// reset only done on init
dev->interface->write_fe_register(0x04, 0x80);
@@ -1174,14 +1386,15 @@ void CommandSetGl646::load_document(Genesys_Device* dev) const
regs.init_reg(0x24, 4);
/* generate slope table 2 */
- auto slope_table = create_slope_table(MotorSlope::create_from_steps(6000, 2400, 50), 2400,
- StepType::FULL, 1, 4,
- get_slope_table_max_size(AsicType::GL646));
+ auto slope_table = create_slope_table_for_speed(MotorSlope::create_from_steps(6000, 2400, 50),
+ 2400, StepType::FULL, 1, 4,
+ get_slope_table_max_size(AsicType::GL646));
// document loading:
// send regs
// start motor
// wait e1 status to become e0
- gl646_send_slope_table(dev, 1, slope_table.table, slope_table.steps_count);
+ const auto& sensor = sanei_genesys_find_sensor_any(dev);
+ scanner_send_slope_table(dev, sensor, 1, slope_table.table);
dev->interface->write_registers(regs);
@@ -1292,9 +1505,8 @@ void CommandSetGl646::eject_document(Genesys_Device* dev) const
// home sensor is set when document is inserted
if (status.is_at_home) {
dev->document = false;
- DBG(DBG_info, "%s: no more document to eject\n", __func__);
- DBG(DBG_proc, "%s: end\n", __func__);
- return;
+ DBG(DBG_info, "%s: no more document to eject\n", __func__);
+ return;
}
// there is a document inserted, eject it
@@ -1331,14 +1543,16 @@ void CommandSetGl646::eject_document(Genesys_Device* dev) const
regs.init_reg(0x24, 4);
/* generate slope table 2 */
- auto slope_table = create_slope_table(MotorSlope::create_from_steps(10000, 1600, 60), 1600,
- StepType::FULL, 1, 4,
- get_slope_table_max_size(AsicType::GL646));
+ auto slope_table = create_slope_table_for_speed(MotorSlope::create_from_steps(10000, 1600, 60),
+ 1600, StepType::FULL, 1, 4,
+ get_slope_table_max_size(AsicType::GL646));
// document eject:
// send regs
// start motor
// wait c1 status to become c8 : HOMESNR and ~MOTFLAG
- gl646_send_slope_table(dev, 1, slope_table.table, slope_table.steps_count);
+ // FIXME: sensor is not used.
+ const auto& sensor = sanei_genesys_find_sensor_any(dev);
+ scanner_send_slope_table(dev, sensor, 1, slope_table.table);
dev->interface->write_registers(regs);
@@ -1473,7 +1687,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
if (!i) /* the loop counted down to 0, scanner still is busy */
{
- dev->set_head_pos_unknown();
+ dev->set_head_pos_unknown(ScanHeadId::PRIMARY | ScanHeadId::SECONDARY);
throw SaneException(SANE_STATUS_DEVICE_BUSY, "motor is still on: device busy");
}
@@ -1489,15 +1703,15 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
session.params.startx = 0;
session.params.starty = 65535;
session.params.pixels = 600;
- session.params.requested_pixels = 600;
session.params.lines = 1;
session.params.depth = 8;
session.params.channels = 3;
session.params.scan_method = dev->model->default_method;
session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
session.params.color_filter = ColorFilter::RED;
- session.params.flags = ScanFlag::USE_XCORRECTION |
- ScanFlag::REVERSE;
+ session.params.flags = ScanFlag::REVERSE |
+ ScanFlag::AUTO_GO_HOME |
+ ScanFlag::DISABLE_GAMMA;
if (dev->model->default_method == ScanMethod::TRANSPARENCY) {
session.params.flags |= ScanFlag::USE_XPA;
}
@@ -1520,8 +1734,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
/* registers are restored to an iddl state, give up if no head to park */
if (dev->model->is_sheetfed) {
- DBG(DBG_proc, "%s: end \n", __func__);
- return;
+ return;
}
// starts scan
@@ -1554,7 +1767,6 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
if (status.is_at_home) {
DBG(DBG_info, "%s: reached home position\n", __func__);
- DBG(DBG_proc, "%s: end\n", __func__);
dev->interface->sleep_ms(500);
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
return;
@@ -1567,7 +1779,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
// stop the motor
catch_all_exceptions(__func__, [&](){ gl646_stop_motor (dev); });
catch_all_exceptions(__func__, [&](){ end_scan_impl(dev, &dev->reg, true, false); });
- dev->set_head_pos_unknown();
+ dev->set_head_pos_unknown(ScanHeadId::PRIMARY | ScanHeadId::SECONDARY);
throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");
}
@@ -1576,165 +1788,60 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
}
/**
- * Automatically set top-left edge of the scan area by scanning an
- * area at 300 dpi from very top of scanner
- * @param dev device stucture describing the scanner
- */
-void CommandSetGl646::search_start_position(Genesys_Device* dev) const
-{
- DBG_HELPER(dbg);
- Genesys_Settings settings;
- unsigned int resolution, x, y;
-
- /* we scan at 300 dpi */
- resolution = get_closest_resolution(dev->model->sensor_id, 300, 1);
-
- // 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, resolution, 1,
- dev->model->default_method);
-
- /* fill settings for a gray level scan */
- settings.scan_method = dev->model->default_method;
- settings.scan_mode = ScanColorMode::GRAY;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = 600;
- settings.requested_pixels = settings.pixels;
- settings.lines = dev->model->search_lines;
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
-
- settings.disable_interpolation = 0;
- settings.threshold = 0;
-
- // scan the desired area
- std::vector<uint8_t> data;
- simple_scan(dev, sensor, settings, true, true, false, data, "search_start_position");
-
- // handle stagger case : reorder gray data and thus loose some lines
- auto staggered_lines = dev->session.num_staggered_lines;
- if (staggered_lines > 0) {
- DBG(DBG_proc, "%s: 'un-staggering'\n", __func__);
- for (y = 0; y < settings.lines - staggered_lines; y++) {
- /* one point out of 2 is 'unaligned' */
- for (x = 0; x < settings.pixels; x += 2)
- {
- data[y * settings.pixels + x] = data[(y + staggered_lines) * settings.pixels + x];
- }
- }
- /* correct line number */
- settings.lines -= staggered_lines;
- }
-
- if (DBG_LEVEL >= DBG_data)
- {
- sanei_genesys_write_pnm_file("gl646_search_position.pnm", data.data(), settings.depth, 1,
- settings.pixels, settings.lines);
- }
-
- // now search reference points on the data
- 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,
- resolution, settings.pixels, settings.lines);
- }
-}
-
-/**
- * internally overriden during effective calibration
- * sets up register for coarse gain calibration
- */
-void CommandSetGl646::init_regs_for_coarse_calibration(Genesys_Device* dev,
- const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const
-{
- DBG_HELPER(dbg);
- (void) dev;
- (void) sensor;
- (void) regs;
-}
-
-
-/**
* init registers for shading calibration
* we assume that scanner's head is on an area suiting shading calibration.
* We scan a full scan width area by the shading line number for the device
- * at either at full sensor's resolution or half depending upon ccd_size_divisor
- * @param dev scanner's device
*/
void CommandSetGl646::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
DBG_HELPER(dbg);
(void) regs;
- Genesys_Settings settings;
- int cksel = 1;
/* fill settings for scan : always a color scan */
int channels = 3;
+ unsigned cksel = get_cksel(dev->model->sensor_id, dev->settings.xres, channels);
+
+ unsigned resolution = sensor.get_optical_resolution() / cksel;
+ // FIXME: we select wrong calibration sensor
const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->settings.xres, channels,
dev->settings.scan_method);
- unsigned ccd_size_divisor = calib_sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres);
+ auto pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
- settings.scan_method = dev->settings.scan_method;
- settings.scan_mode = dev->settings.scan_mode;
- if (!dev->model->is_cis) {
- // FIXME: always a color scan, but why don't we set scan_mode to COLOR_SINGLE_PASS always?
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- }
- settings.xres = sensor.optical_res / ccd_size_divisor;
- cksel = get_cksel(dev->model->sensor_id, dev->settings.xres, channels);
- settings.xres = settings.xres / cksel;
- settings.yres = settings.xres;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = (calib_sensor.sensor_pixels * settings.xres) / calib_sensor.optical_res;
- settings.requested_pixels = settings.pixels;
- dev->calib_lines = dev->model->shading_lines;
- settings.lines = dev->calib_lines * (3 - ccd_size_divisor);
- settings.depth = 16;
- settings.color_filter = dev->settings.color_filter;
-
- settings.disable_interpolation = dev->settings.disable_interpolation;
- settings.threshold = dev->settings.threshold;
-
- // we don't want top offset, but we need right margin to be the same than the one for the final
- // scan
- setup_for_scan(dev, calib_sensor, &dev->reg, settings, true, false, false, false);
-
- /* used when sending shading calibration data */
- dev->calib_pixels = settings.pixels;
- dev->calib_channels = dev->session.params.channels;
- if (!dev->model->is_cis) {
- dev->calib_channels = 3;
+ unsigned calib_lines =
+ static_cast<unsigned>(dev->model->y_size_calib_mm * resolution / MM_PER_INCH);
+
+ ScanSession session;
+ session.params.xres = resolution;
+ session.params.yres = resolution;
+ session.params.startx = 0;
+ session.params.starty = 0;
+ session.params.pixels = pixels;
+ session.params.lines = calib_lines;
+ 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::IGNORE_COLOR_OFFSET |
+ ScanFlag::IGNORE_STAGGER_OFFSET;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) {
+ session.params.flags |= ScanFlag::USE_XPA;
}
+ compute_session(dev, session, calib_sensor);
+
+ dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session);
+
+ dev->calib_session = session;
/* no shading */
- dev->reg.find_reg(0x01).value &= ~REG_0x01_DVDSET;
dev->reg.find_reg(0x02).value |= REG_0x02_ACDCDIS; /* ease backtracking */
- dev->reg.find_reg(0x02).value &= ~(REG_0x02_FASTFED | REG_0x02_AGOHOME);
- dev->reg.find_reg(0x05).value &= ~REG_0x05_GMMENB;
+ dev->reg.find_reg(0x02).value &= ~REG_0x02_FASTFED;
sanei_genesys_set_motor_power(dev->reg, false);
-
- /* TODO another flag to setup regs ? */
- /* enforce needed LINCNT, getting rid of extra lines for color reordering */
- if (!dev->model->is_cis) {
- dev->reg.set24(REG_LINCNT, dev->calib_lines);
- } else {
- dev->reg.set24(REG_LINCNT, dev->calib_lines * 3);
- }
-
- /* copy reg to calib_reg */
- dev->calib_reg = dev->reg;
-
- DBG(DBG_info, "%s:\n\tdev->settings.xres=%d\n\tdev->settings.yres=%d\n", __func__,
- dev->settings.xres, dev->settings.yres);
}
bool CommandSetGl646::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
@@ -1745,109 +1852,6 @@ bool CommandSetGl646::needs_home_before_init_regs_for_scan(Genesys_Device* dev)
}
/**
- * set up registers for the actual scan. The scan's parameters are given
- * through the device settings. It allocates the scan buffers.
- */
-void CommandSetGl646::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const
-{
- DBG_HELPER(dbg);
-
- debug_dump(DBG_info, dev->settings);
-
- ScanSession session = calculate_scan_session(dev, sensor, dev->settings);
-
- init_regs_for_scan_session(dev, sensor, &dev->reg, session);
-
- /* gamma is only enabled at final scan time */
- if (dev->settings.depth < 16) {
- dev->reg.find_reg(0x05).value |= REG_0x05_GMMENB;
- }
-}
-
-/**
- * set up registers for the actual scan. The scan's parameters are given
- * through the device settings. It allocates the scan buffers.
- * @param dev scanner's device
- * @param regs registers to set up
- * @param settings settings of scan
- * @param split true if move to scan area is split from scan, false is
- * scan first moves to area
- * @param xcorrection take x geometry correction into account (fixed and detected offsets)
- * @param ycorrection take y geometry correction into account
- */
-static void setup_for_scan(Genesys_Device* dev,
- const Genesys_Sensor& sensor,
- Genesys_Register_Set*regs,
- Genesys_Settings settings,
- bool split,
- bool xcorrection,
- bool ycorrection,
- bool reverse)
-{
- DBG_HELPER(dbg);
-
- debug_dump(DBG_info, dev->settings);
-
- // compute distance to move
- float move = 0;
- // XXX STEF XXX MD5345 -> optical_ydpi, other base_ydpi => half/full step ? */
- if (!split) {
- if (!dev->model->is_sheetfed) {
- if (ycorrection) {
- move = static_cast<float>(dev->model->y_offset);
- }
-
- // add tl_y to base movement
- }
- move += static_cast<float>(settings.tl_y);
-
- if (move < 0) {
- DBG(DBG_error, "%s: overriding negative move value %f\n", __func__, move);
- move = 0;
- }
- }
- move = static_cast<float>((move * dev->motor.optical_ydpi) / MM_PER_INCH);
- DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
-
- float start = static_cast<float>(settings.tl_x);
- if (xcorrection) {
- if (settings.scan_method == ScanMethod::FLATBED) {
- start += static_cast<float>(dev->model->x_offset);
- } else {
- start += static_cast<float>(dev->model->x_offset_ta);
- }
- }
- start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH);
-
- ScanSession session;
- session.params.xres = settings.xres;
- session.params.yres = settings.yres;
- 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;
- session.params.depth = settings.depth;
- session.params.channels = settings.get_channels();
- session.params.scan_method = dev->settings.scan_method;
- session.params.scan_mode = settings.scan_mode;
- session.params.color_filter = settings.color_filter;
- session.params.flags = ScanFlag::NONE;
- if (settings.scan_method == ScanMethod::TRANSPARENCY) {
- session.params.flags |= ScanFlag::USE_XPA;
- }
- if (xcorrection) {
- session.params.flags |= ScanFlag::USE_XCORRECTION;
- }
- if (reverse) {
- session.params.flags |= ScanFlag::REVERSE;
- }
- compute_session(dev, session, sensor);
-
- dev->cmd_set->init_regs_for_scan_session(dev, sensor, regs, session);
-}
-
-/**
* this function send gamma table to ASIC
*/
void CommandSetGl646::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
@@ -1857,9 +1861,7 @@ void CommandSetGl646::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor
int address;
int bits;
- /* gamma table size */
- if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA)
- {
+ if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {
size = 16384;
bits = 14;
}
@@ -1903,45 +1905,42 @@ SensorExposure CommandSetGl646::led_calibration(Genesys_Device* dev, const Genes
{
DBG_HELPER(dbg);
(void) regs;
- int total_size;
unsigned int i, j;
int val;
int avg[3], avga, avge;
int turn;
uint16_t expr, expg, expb;
- Genesys_Settings settings;
- SANE_Int resolution;
unsigned channels = dev->settings.get_channels();
- /* get led calibration resolution */
- if (dev->settings.scan_mode == ScanColorMode::COLOR_SINGLE_PASS)
- {
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- }
- else
- {
- settings.scan_mode = ScanColorMode::GRAY;
+ ScanColorMode scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
+ if (dev->settings.scan_mode != ScanColorMode::COLOR_SINGLE_PASS) {
+ scan_mode = ScanColorMode::GRAY;
}
- resolution = get_closest_resolution(dev->model->sensor_id, sensor.optical_res, channels);
- /* offset calibration is always done in color mode */
- settings.scan_method = dev->model->default_method;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = (sensor.sensor_pixels * resolution) / sensor.optical_res;
- settings.requested_pixels = settings.pixels;
- settings.lines = 1;
- settings.depth = 16;
- settings.color_filter = ColorFilter::RED;
+ // offset calibration is always done in color mode
+ unsigned pixels = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH;
- settings.disable_interpolation = 0;
- settings.threshold = 0;
+ ScanSession session;
+ session.params.xres = sensor.full_resolution;
+ session.params.yres = sensor.full_resolution;
+ session.params.startx = 0;
+ session.params.starty = 0;
+ session.params.pixels = 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 = scan_mode;
+ session.params.color_filter = ColorFilter::RED;
+ session.params.flags = ScanFlag::DISABLE_SHADING;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) {
+ session.params.flags |= ScanFlag::USE_XPA;
+ }
+ compute_session(dev, session, sensor);
- /* colors * bytes_per_color * scan lines */
- total_size = settings.pixels * channels * 2 * 1;
+ // colors * bytes_per_color * scan lines
+ unsigned total_size = pixels * channels * 2 * 1;
std::vector<uint8_t> line(total_size);
@@ -1968,38 +1967,34 @@ SensorExposure CommandSetGl646::led_calibration(Genesys_Device* dev, const Genes
DBG(DBG_info, "%s: starting first line reading\n", __func__);
- simple_scan(dev, calib_sensor, settings, false, true, false, line, "led_calibration");
+ dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session);
+ simple_scan(dev, calib_sensor, session, false, line, "led_calibration");
if (is_testing_mode()) {
return calib_sensor.exposure;
}
- if (DBG_LEVEL >= DBG_data)
- {
- char fn[30];
- std::snprintf(fn, 30, "gl646_led_%02d.pnm", turn);
- sanei_genesys_write_pnm_file(fn, line.data(), 16, channels, settings.pixels, 1);
- }
+ if (dbg_log_image_data()) {
+ char fn[30];
+ std::snprintf(fn, 30, "gl646_led_%02d.tiff", turn);
+ write_tiff_file(fn, line.data(), 16, channels, pixels, 1);
+ }
acceptable = true;
for (j = 0; j < channels; j++)
{
avg[j] = 0;
- for (i = 0; i < settings.pixels; i++)
- {
- if (dev->model->is_cis)
- val =
- line[i * 2 + j * 2 * settings.pixels + 1] * 256 +
- line[i * 2 + j * 2 * settings.pixels];
- else
- val =
- line[i * 2 * channels + 2 * j + 1] * 256 +
- line[i * 2 * channels + 2 * j];
- avg[j] += val;
+ for (i = 0; i < pixels; i++) {
+ if (dev->model->is_cis) {
+ val = line[i * 2 + j * 2 * pixels + 1] * 256 + line[i * 2 + j * 2 * pixels];
+ } else {
+ val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j];
+ }
+ avg[j] += val;
}
- avg[j] /= settings.pixels;
+ avg[j] /= pixels;
}
DBG(DBG_info, "%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]);
@@ -2088,31 +2083,40 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
unsigned int channels;
int pass = 0;
- SANE_Int resolution;
- Genesys_Settings settings;
- unsigned int x, y, adr, min;
+ unsigned adr, min;
unsigned int bottom, black_pixels;
channels = 3;
- resolution = get_closest_resolution(dev->model->sensor_id, sensor.optical_res, channels);
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3, ScanMethod::FLATBED);
- black_pixels = (calib_sensor.black_pixels * resolution) / calib_sensor.optical_res;
- DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels);
-
- settings.scan_method = dev->model->default_method;
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
- settings.requested_pixels = settings.pixels;
- settings.lines = CALIBRATION_LINES;
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
-
- settings.disable_interpolation = 0;
- settings.threshold = 0;
+
+ // FIXME: maybe reuse `sensor`
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution, 3,
+ ScanMethod::FLATBED);
+ black_pixels = (calib_sensor.black_pixels * sensor.full_resolution) / calib_sensor.full_resolution;
+
+ unsigned pixels = dev->model->x_size_calib_mm * sensor.full_resolution / MM_PER_INCH;
+ unsigned lines = CALIBRATION_LINES;
+
+ if (dev->model->is_cis) {
+ lines = ((lines + 2) / 3) * 3;
+ }
+
+ ScanSession session;
+ session.params.xres = sensor.full_resolution;
+ session.params.yres = sensor.full_resolution;
+ session.params.startx = 0;
+ session.params.starty = 0;
+ session.params.pixels = pixels;
+ session.params.lines = lines;
+ session.params.depth = 8;
+ session.params.channels = 3;
+ 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;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) {
+ session.params.flags |= ScanFlag::USE_XPA;
+ }
+ compute_session(dev, session, calib_sensor);
/* scan first line of data with no gain */
dev->frontend.set_gain(0, 0);
@@ -2129,27 +2133,24 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
dev->frontend.set_offset(0, bottom);
dev->frontend.set_offset(1, bottom);
dev->frontend.set_offset(2, bottom);
- simple_scan(dev, calib_sensor, settings, false, true, false, line,
- "ad_fe_offset_calibration");
+
+ dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session);
+ simple_scan(dev, calib_sensor, session, false, line, "ad_fe_offset_calibration");
if (is_testing_mode()) {
return;
}
- if (DBG_LEVEL >= DBG_data)
- {
- char title[30];
- std::snprintf(title, 30, "gl646_offset%03d.pnm", static_cast<int>(bottom));
- sanei_genesys_write_pnm_file (title, line.data(), 8, channels,
- settings.pixels, settings.lines);
- }
+ if (dbg_log_image_data()) {
+ char title[30];
+ std::snprintf(title, 30, "gl646_offset%03d.tiff", static_cast<int>(bottom));
+ write_tiff_file(title, line.data(), 8, channels, pixels, lines);
+ }
min = 0;
- for (y = 0; y < settings.lines; y++)
- {
- for (x = 0; x < black_pixels; x++)
- {
- adr = (x + y * settings.pixels) * channels;
+ for (unsigned y = 0; y < lines; y++) {
+ for (unsigned x = 0; x < black_pixels; x++) {
+ adr = (x + y * pixels) * channels;
if (line[adr] > min)
min = line[adr];
if (line[adr + 1] > min)
@@ -2159,7 +2160,7 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
}
}
- DBG(DBG_io2, "%s: pass=%d, min=%d\n", __func__, pass, min);
+ DBG(DBG_info, "%s: pass=%d, min=%d\n", __func__, pass, min);
bottom++;
}
while (pass < 128 && min == 0);
@@ -2187,9 +2188,7 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens
DBG_HELPER(dbg);
(void) regs;
- unsigned int channels;
int pass = 0, avg;
- Genesys_Settings settings;
int topavg, bottomavg;
int top, bottom, black_pixels;
@@ -2198,32 +2197,38 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens
return;
}
- DBG(DBG_proc, "%s: start\n", __func__); // TODO
-
/* setup for a RGB scan, one full sensor's width line */
/* resolution is the one from the final scan */
- channels = 3;
- int resolution = get_closest_resolution(dev->model->sensor_id, dev->settings.xres, channels);
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3, ScanMethod::FLATBED);
- black_pixels = (calib_sensor.black_pixels * resolution) / calib_sensor.optical_res;
+ unsigned resolution = dev->settings.xres;
+ unsigned channels = 3;
- DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels);
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
+ ScanMethod::FLATBED);
+ black_pixels = (calib_sensor.black_pixels * resolution) / calib_sensor.full_resolution;
- settings.scan_method = dev->model->default_method;
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
- settings.requested_pixels = settings.pixels;
- settings.lines = CALIBRATION_LINES;
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
+ unsigned pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
+ unsigned lines = CALIBRATION_LINES;
+ if (dev->model->is_cis) {
+ lines = ((lines + 2) / 3) * 3;
+ }
- settings.disable_interpolation = 0;
- settings.threshold = 0;
+ ScanSession session;
+ session.params.xres = resolution;
+ session.params.yres = resolution;
+ 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 = ColorFilter::RED;
+ session.params.flags = ScanFlag::DISABLE_SHADING;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) {
+ session.params.flags |= ScanFlag::USE_XPA;
+ }
+ compute_session(dev, session, sensor);
/* scan first line of data with no gain, but with offset from
* last calibration */
@@ -2239,38 +2244,32 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens
std::vector<uint8_t> first_line, second_line;
- simple_scan(dev, calib_sensor, settings, false, true, false, first_line,
- "offset_first_line");
+ dev->cmd_set->init_regs_for_scan_session(dev, sensor, &dev->reg, session);
+ simple_scan(dev, calib_sensor, session, false, first_line, "offset_first_line");
- if (DBG_LEVEL >= DBG_data)
- {
- char title[30];
- std::snprintf(title, 30, "gl646_offset%03d.pnm", bottom);
- sanei_genesys_write_pnm_file(title, first_line.data(), 8, channels,
- settings.pixels, settings.lines);
+ if (dbg_log_image_data()) {
+ char title[30];
+ std::snprintf(title, 30, "gl646_offset%03d.tiff", bottom);
+ write_tiff_file(title, first_line.data(), 8, channels, pixels, lines);
}
- bottomavg = dark_average(first_line.data(), settings.pixels, settings.lines, channels,
- black_pixels);
- DBG(DBG_io2, "%s: bottom avg=%d\n", __func__, bottomavg);
+ bottomavg = dark_average(first_line.data(), pixels, lines, channels, black_pixels);
+ DBG(DBG_info, "%s: bottom avg=%d\n", __func__, bottomavg);
/* now top value */
top = 231;
dev->frontend.set_offset(0, top);
dev->frontend.set_offset(1, top);
dev->frontend.set_offset(2, top);
- simple_scan(dev, calib_sensor, settings, false, true, false, second_line,
- "offset_second_line");
+ dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session);
+ simple_scan(dev, calib_sensor, session, false, second_line, "offset_second_line");
- if (DBG_LEVEL >= DBG_data)
- {
- char title[30];
- std::snprintf(title, 30, "gl646_offset%03d.pnm", top);
- sanei_genesys_write_pnm_file (title, second_line.data(), 8, channels,
- settings.pixels, settings.lines);
+ if (dbg_log_image_data()) {
+ char title[30];
+ std::snprintf(title, 30, "gl646_offset%03d.tiff", top);
+ write_tiff_file(title, second_line.data(), 8, channels, pixels, lines);
}
- topavg = dark_average(second_line.data(), settings.pixels, settings.lines, channels,
- black_pixels);
- DBG(DBG_io2, "%s: top avg=%d\n", __func__, topavg);
+ topavg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);
+ DBG(DBG_info, "%s: top avg=%d\n", __func__, topavg);
if (is_testing_mode()) {
return;
@@ -2287,20 +2286,17 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens
dev->frontend.set_offset(2, (top + bottom) / 2);
// scan with no move
- simple_scan(dev, calib_sensor, settings, false, true, false, second_line,
+ dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session);
+ simple_scan(dev, calib_sensor, session, false, second_line,
"offset_calibration_i");
- if (DBG_LEVEL >= DBG_data)
- {
- char title[30];
- std::snprintf(title, 30, "gl646_offset%03d.pnm", dev->frontend.get_offset(1));
- sanei_genesys_write_pnm_file (title, second_line.data(), 8, channels,
- settings.pixels, settings.lines);
- }
+ if (dbg_log_image_data()) {
+ char title[30];
+ std::snprintf(title, 30, "gl646_offset%03d.tiff", dev->frontend.get_offset(1));
+ write_tiff_file(title, second_line.data(), 8, channels, pixels, lines);
+ }
- avg =
- dark_average (second_line.data(), settings.pixels, settings.lines, channels,
- black_pixels);
+ 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 */
@@ -2322,102 +2318,6 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens
dev->frontend.get_offset(2));
}
-/** @brief gain calibration for Analog Device frontends
- * Alternative coarse gain calibration
- */
-static void ad_fe_coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs, int dpi)
-{
- DBG_HELPER(dbg);
- (void) sensor;
- (void) regs;
-
- unsigned int i, channels, val;
- unsigned int size, count, resolution, pass;
- float average;
- Genesys_Settings settings;
- char title[32];
-
- /* setup for a RGB scan, one full sensor's width line */
- /* resolution is the one from the final scan */
- channels = 3;
- resolution = get_closest_resolution(dev->model->sensor_id, dpi, channels);
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3, ScanMethod::FLATBED);
-
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
-
- settings.scan_method = dev->model->default_method;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
- settings.requested_pixels = settings.pixels;
- settings.lines = CALIBRATION_LINES;
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
-
- settings.disable_interpolation = 0;
- settings.threshold = 0;
-
- size = channels * settings.pixels * settings.lines;
-
- /* start gain value */
- dev->frontend.set_gain(0, 1);
- dev->frontend.set_gain(1, 1);
- dev->frontend.set_gain(2, 1);
-
- average = 0;
- pass = 0;
-
- std::vector<uint8_t> line;
-
- // loop until each channel raises to acceptable level
- while ((average < calib_sensor.gain_white_ref) && (pass < 30)) {
- // scan with no move
- simple_scan(dev, calib_sensor, settings, false, true, false, line,
- "ad_fe_coarse_gain_calibration");
-
- /* log scanning data */
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl646_alternative_gain%02d.pnm", pass);
- sanei_genesys_write_pnm_file(title, line.data(), 8, channels, settings.pixels,
- settings.lines);
- }
- pass++;
-
- /* computes white average */
- average = 0;
- count = 0;
- for (i = 0; i < size; i++)
- {
- val = line[i];
- average += val;
- count++;
- }
- average = average / count;
-
- uint8_t gain0 = dev->frontend.get_gain(0);
- // adjusts gain for the channel
- if (average < calib_sensor.gain_white_ref) {
- gain0 += 1;
- }
-
- dev->frontend.set_gain(0, gain0);
- dev->frontend.set_gain(1, gain0);
- dev->frontend.set_gain(2, gain0);
-
- DBG(DBG_proc, "%s: average = %.2f, gain = %d\n", __func__, average, gain0);
- }
-
- DBG(DBG_info, "%s: gains=(%d,%d,%d)\n", __func__,
- dev->frontend.get_gain(0),
- dev->frontend.get_gain(1),
- dev->frontend.get_gain(2));
-}
-
/**
* Alternative coarse gain calibration
* this on uses the settings from offset_calibration. First scan moves so
@@ -2430,76 +2330,67 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys
{
DBG_HELPER(dbg);
(void) dpi;
+ (void) sensor;
+ (void) regs;
- unsigned int i, j, k, channels, val, maximum, idx;
- unsigned int count, resolution, pass;
float average[3];
- Genesys_Settings settings;
char title[32];
- if (dev->model->sensor_id == SensorId::CIS_XP200) {
- return ad_fe_coarse_gain_calibration(dev, sensor, regs, sensor.optical_res);
- }
-
/* setup for a RGB scan, one full sensor's width line */
/* resolution is the one from the final scan */
- channels = 3;
+ unsigned channels = 3;
- /* we are searching a sensor resolution */
- resolution = get_closest_resolution(dev->model->sensor_id, dev->settings.xres, channels);
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
+ // BUG: the following comment is incorrect
+ // we are searching a sensor resolution */
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->settings.xres, channels,
ScanMethod::FLATBED);
- settings.scan_method = dev->settings.scan_method;
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_y = 0;
- if (settings.scan_method == ScanMethod::FLATBED)
- {
- settings.tl_x = 0;
- settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
+ unsigned pixels = 0;
+ float start = 0;
+ if (dev->settings.scan_method == ScanMethod::FLATBED) {
+ pixels = dev->model->x_size_calib_mm * dev->settings.xres / MM_PER_INCH;
+ } else {
+ start = dev->model->x_offset_ta;
+ pixels = static_cast<unsigned>(
+ (dev->model->x_size_ta * dev->settings.xres) / MM_PER_INCH);
}
- else
- {
- settings.tl_x = dev->model->x_offset_ta;
- settings.pixels = static_cast<unsigned>((dev->model->x_size_ta * resolution) / MM_PER_INCH);
+
+ unsigned lines = CALIBRATION_LINES;
+ // round up to multiple of 3 in case of CIS scanner
+ if (dev->model->is_cis) {
+ lines = ((lines + 2) / 3) * 3;
}
- settings.requested_pixels = settings.pixels;
- settings.lines = CALIBRATION_LINES;
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
- settings.disable_interpolation = 0;
- settings.threshold = 0;
+ start = static_cast<float>((start * dev->settings.xres) / MM_PER_INCH);
+
+ ScanSession session;
+ session.params.xres = dev->settings.xres;
+ session.params.yres = dev->settings.xres;
+ session.params.startx = static_cast<unsigned>(start);
+ 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 = ColorFilter::RED;
+ session.params.flags = ScanFlag::DISABLE_SHADING;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) {
+ session.params.flags |= ScanFlag::USE_XPA;
+ }
+ compute_session(dev, session, calib_sensor);
/* start gain value */
dev->frontend.set_gain(0, 1);
dev->frontend.set_gain(1, 1);
dev->frontend.set_gain(2, 1);
- if (channels > 1)
- {
- average[0] = 0;
- average[1] = 0;
- average[2] = 0;
- idx = 0;
- }
- else
- {
- average[0] = 255;
- average[1] = 255;
- average[2] = 255;
- switch (dev->settings.color_filter) {
- case ColorFilter::RED: idx = 0; break;
- case ColorFilter::GREEN: idx = 1; break;
- case ColorFilter::BLUE: idx = 2; break;
- default: idx = 0; break; // should not happen
- }
- average[idx] = 0;
- }
- pass = 0;
+ average[0] = 0;
+ average[1] = 0;
+ average[2] = 0;
+
+ unsigned pass = 0;
std::vector<uint8_t> line;
@@ -2509,75 +2400,60 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys
(average[2] < calib_sensor.gain_white_ref)) && (pass < 30))
{
// scan with no move
- simple_scan(dev, calib_sensor, settings, false, true, false, line,
- "coarse_gain_calibration");
+ dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &dev->reg, session);
+ simple_scan(dev, calib_sensor, session, false, line, "coarse_gain_calibration");
- /* log scanning data */
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl646_gain%02d.pnm", pass);
- sanei_genesys_write_pnm_file(title, line.data(), 8, channels, settings.pixels,
- settings.lines);
- }
- pass++;
-
- /* average high level for each channel and compute gain
- to reach the target code
- we only use the central half of the CCD data */
- for (k = idx; k < idx + channels; k++)
- {
- /* we find the maximum white value, so we can deduce a threshold
- to average white values */
- maximum = 0;
- for (i = 0; i < settings.lines; i++)
- {
- for (j = 0; j < settings.pixels; j++)
- {
- val = line[i * channels * settings.pixels + j + k];
- if (val > maximum)
- maximum = val;
- }
- }
+ if (dbg_log_image_data()) {
+ std::sprintf(title, "gl646_gain%02d.tiff", pass);
+ write_tiff_file(title, line.data(), 8, channels, pixels, lines);
+ }
+ pass++;
+
+ // average high level for each channel and compute gain to reach the target code
+ // we only use the central half of the CCD data
+ for (unsigned k = 0; k < channels; k++) {
+
+ // we find the maximum white value, so we can deduce a threshold
+ // to average white values
+ unsigned maximum = 0;
+ for (unsigned i = 0; i < lines; i++) {
+ for (unsigned j = 0; j < pixels; j++) {
+ unsigned val = line[i * channels * pixels + j + k];
+ maximum = std::max(maximum, val);
+ }
+ }
- /* threshold */
maximum = static_cast<int>(maximum * 0.9);
- /* computes white average */
- average[k] = 0;
- count = 0;
- for (i = 0; i < settings.lines; i++)
- {
- for (j = 0; j < settings.pixels; j++)
- {
- /* averaging only white points allow us not to care about dark margins */
- val = line[i * channels * settings.pixels + j + k];
- if (val > maximum)
- {
- average[k] += val;
- count++;
- }
- }
- }
- average[k] = average[k] / count;
-
- /* adjusts gain for the channel */
- if (average[k] < calib_sensor.gain_white_ref)
- dev->frontend.set_gain(k, dev->frontend.get_gain(k) + 1);
+ // computes white average
+ average[k] = 0;
+ unsigned count = 0;
+ for (unsigned i = 0; i < lines; i++) {
+ for (unsigned j = 0; j < pixels; j++) {
+ // averaging only white points allow us not to care about dark margins
+ unsigned val = line[i * channels * pixels + j + k];
+ if (val > maximum) {
+ average[k] += val;
+ count++;
+ }
+ }
+ }
+ average[k] = average[k] / count;
- DBG(DBG_proc, "%s: channel %d, average = %.2f, gain = %d\n", __func__, k, average[k],
- dev->frontend.get_gain(k));
- }
- }
+ // adjusts gain for the channel
+ if (average[k] < calib_sensor.gain_white_ref) {
+ dev->frontend.set_gain(k, dev->frontend.get_gain(k) + 1);
+ }
- if (channels < 3) {
- dev->frontend.set_gain(1, dev->frontend.get_gain(0));
- dev->frontend.set_gain(2, dev->frontend.get_gain(0));
+ DBG(DBG_info, "%s: channel %d, average = %.2f, gain = %d\n", __func__, k, average[k],
+ dev->frontend.get_gain(k));
+ }
}
- DBG(DBG_info, "%s: gains=(%d,%d,%d)\n", __func__,
- dev->frontend.get_gain(0),
- dev->frontend.get_gain(1),
- dev->frontend.get_gain(2));
+ DBG(DBG_info, "%s: gains=(%d,%d,%d)\n", __func__,
+ dev->frontend.get_gain(0),
+ dev->frontend.get_gain(1),
+ dev->frontend.get_gain(2));
}
/**
@@ -2585,46 +2461,43 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys
*
*/
void CommandSetGl646::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* local_reg, int* channels,
- int* total_size) const
+ Genesys_Register_Set* local_reg) const
{
DBG_HELPER(dbg);
(void) sensor;
- Genesys_Settings settings;
- int resolution, lines;
-
dev->frontend = dev->frontend_initial;
- resolution = get_closest_resolution(dev->model->sensor_id, 300, 1);
-
+ unsigned resolution = 300;
const auto& local_sensor = sanei_genesys_find_sensor(dev, resolution, 1,
dev->settings.scan_method);
- /* set up for a half width 2 lines gray scan without moving */
- settings.scan_method = dev->model->default_method;
- settings.scan_mode = ScanColorMode::GRAY;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = (local_sensor.sensor_pixels * resolution) / local_sensor.optical_res;
- settings.requested_pixels = settings.pixels;
- settings.lines = 2;
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
-
- settings.disable_interpolation = 0;
- settings.threshold = 0;
-
- // setup for scan
- setup_for_scan(dev, local_sensor, &dev->reg, settings, true, false, false, false);
+ // set up for a full width 2 lines gray scan without moving
+ unsigned pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
- /* we are not going to move, so clear these bits */
- dev->reg.find_reg(0x02).value &= ~(REG_0x02_FASTFED | REG_0x02_AGOHOME);
+ ScanSession session;
+ session.params.xres = resolution;
+ session.params.yres = resolution;
+ session.params.startx = 0;
+ session.params.starty = 0;
+ session.params.pixels = pixels;
+ session.params.lines = 2;
+ session.params.depth = dev->model->bpp_gray_values.front();
+ session.params.channels = 1;
+ session.params.scan_method = dev->settings.scan_method;
+ session.params.scan_mode = ScanColorMode::GRAY;
+ session.params.color_filter = ColorFilter::RED;
+ session.params.flags = ScanFlag::DISABLE_SHADING |
+ ScanFlag::DISABLE_GAMMA;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY) {
+ session.params.flags |= ScanFlag::USE_XPA;
+ }
+ compute_session(dev, session, local_sensor);
+
+ dev->cmd_set->init_regs_for_scan_session(dev, local_sensor, &dev->reg, session);
- /* don't enable any correction for this scan */
- dev->reg.find_reg(0x01).value &= ~REG_0x01_DVDSET;
+ /* we are not going to move, so clear these bits */
+ dev->reg.find_reg(0x02).value &= ~REG_0x02_FASTFED;
/* copy to local_reg */
*local_reg = dev->reg;
@@ -2632,66 +2505,8 @@ void CommandSetGl646::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se
/* turn off motor during this scan */
sanei_genesys_set_motor_power(*local_reg, false);
- /* returned value to higher level warmup function */
- *channels = 1;
- lines = local_reg->get24(REG_LINCNT) + 1;
- *total_size = lines * settings.pixels;
-
// now registers are ok, write them to scanner
- gl646_set_fe(dev, local_sensor, AFE_SET, settings.xres);
- dev->interface->write_registers(*local_reg);
-}
-
-
-/*
- * this function moves head without scanning, forward, then backward
- * so that the head goes to park position.
- * as a by-product, also check for lock
- */
-static void gl646_repark_head(Genesys_Device* dev)
-{
- DBG_HELPER(dbg);
- Genesys_Settings settings;
- unsigned int expected, steps;
-
- settings.scan_method = dev->model->default_method;
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- settings.xres = get_closest_resolution(dev->model->sensor_id, 75, 1);
- settings.yres = settings.xres;
- settings.tl_x = 0;
- settings.tl_y = 5;
- settings.pixels = 600;
- settings.requested_pixels = settings.pixels;
- settings.lines = 4;
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
-
- settings.disable_interpolation = 0;
- settings.threshold = 0;
-
- const auto& sensor = sanei_genesys_find_sensor(dev, settings.xres, 3,
- dev->model->default_method);
-
- setup_for_scan(dev, sensor, &dev->reg, settings, false, false, false, false);
-
- /* TODO seems wrong ... no effective scan */
- regs_set_optical_off(dev->model->asic_type, dev->reg);
-
- dev->interface->write_registers(dev->reg);
-
- // start scan
- dev->cmd_set->begin_scan(dev, sensor, &dev->reg, true);
-
- expected = dev->reg.get24(REG_FEEDL);
- do
- {
- dev->interface->sleep_ms(100);
- sanei_genesys_read_feed_steps (dev, &steps);
- }
- while (steps < expected);
-
- // toggle motor flag, put an huge step number and redo move backward
- dev->cmd_set->move_back_home(dev, 1);
+ gl646_set_fe(dev, local_sensor, AFE_SET, session.params.xres);
}
/* *
@@ -2731,10 +2546,11 @@ void CommandSetGl646::init(Genesys_Device* dev) const
gl646_init_regs (dev);
// Init shading data
- sanei_genesys_init_shading_data(dev, sensor, sensor.sensor_pixels);
+ sanei_genesys_init_shading_data(dev, sensor,
+ dev->model->x_size_calib_mm * sensor.full_resolution /
+ MM_PER_INCH);
- /* initial calibration reg values */
- dev->calib_reg = dev->reg;
+ dev->initial_regs = dev->reg;
}
// execute physical unit init only if cold
@@ -2787,7 +2603,7 @@ void CommandSetGl646::init(Genesys_Device* dev) const
if (dev->model->gpio_id != GpioId::HP3670 &&
dev->model->gpio_id != GpioId::HP2400)
{
- switch (sensor.optical_res)
+ switch (sensor.full_resolution)
{
case 600:
addr = 0x08200;
@@ -2810,9 +2626,6 @@ void CommandSetGl646::init(Genesys_Device* dev) const
} catch (...) {
dev->interface->bulk_read_data(0x45, dev->control, len);
}
- DBG(DBG_info, "%s: control read=0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", __func__,
- dev->control[0], dev->control[1], dev->control[2], dev->control[3], dev->control[4],
- dev->control[5]);
sanei_usb_set_timeout (30 * 1000);
}
else
@@ -2828,104 +2641,44 @@ void CommandSetGl646::init(Genesys_Device* dev) const
/* ensure head is correctly parked, and check lock */
if (!dev->model->is_sheetfed) {
- if (dev->model->flags & GENESYS_FLAG_REPARK)
- {
- // FIXME: if repark fails, we should print an error message that the scanner is locked and
- // the user should unlock the lock. We should also rethrow with SANE_STATUS_JAMMED
- gl646_repark_head(dev);
- }
- else
- {
- move_back_home(dev, true);
- }
+ move_back_home(dev, true);
}
/* here session and device are initialized */
dev->already_initialized = true;
}
-void CommandSetGl646::move_to_ta(Genesys_Device* dev) const
-{
- DBG_HELPER(dbg);
-
- simple_move(dev, static_cast<int>(dev->model->y_offset_sensor_to_ta));
-}
-
-
-/**
- * Does a simple scan: ie no line reordering and avanced data buffering and
- * shading correction. Memory for data is allocated in this function
- * and must be freed by caller.
- * @param dev device of the scanner
- * @param settings parameters of the scan
- * @param move true if moving during scan
- * @param forward true if moving forward during scan
- * @param shading true to enable shading correction
- * @param data pointer for the data
- */
static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Settings settings, bool move, bool forward,
- bool shading, std::vector<uint8_t>& data,
- const char* scan_identifier)
+ const ScanSession& session, bool move,
+ std::vector<uint8_t>& data, const char* scan_identifier)
{
- DBG_HELPER_ARGS(dbg, "move=%d, forward=%d, shading=%d", move, forward, shading);
- unsigned int size, lines, x, y, bpp;
- bool split;
-
- /* round up to multiple of 3 in case of CIS scanner */
- if (dev->model->is_cis) {
- settings.lines = ((settings.lines + 2) / 3) * 3;
+ unsigned lines = session.output_line_count;
+ if (!dev->model->is_cis) {
+ lines++;
}
- /* setup for move then scan */
- split = !(move && settings.tl_y > 0);
- setup_for_scan(dev, sensor, &dev->reg, settings, split, false, false, !forward);
+ std::size_t size = lines * session.params.pixels;
+ unsigned bpp = session.params.depth == 16 ? 2 : 1;
- /* allocate memory fo scan : LINCNT may have been adjusted for CCD reordering */
- if (dev->model->is_cis) {
- lines = dev->reg.get24(REG_LINCNT) / 3;
- } else {
- lines = dev->reg.get24(REG_LINCNT) + 1;
- }
- size = lines * settings.pixels;
- if (settings.depth == 16) {
- bpp = 2;
- } else {
- bpp = 1;
- }
- size *= bpp * settings.get_channels();
+ size *= bpp * session.params.channels;
data.clear();
data.resize(size);
- DBG(DBG_io, "%s: allocated %d bytes of memory for %d lines\n", __func__, size, lines);
-
- /* put back real line number in settings */
- settings.lines = lines;
-
// initialize frontend
- gl646_set_fe(dev, sensor, AFE_SET, settings.xres);
-
- /* no shading correction and not watch dog for simple scan */
- dev->reg.find_reg(0x01).value &= ~(REG_0x01_DVDSET | REG_0x01_DOGENB);
- if (shading) {
- dev->reg.find_reg(0x01).value |= REG_0x01_DVDSET;
- }
+ gl646_set_fe(dev, sensor, AFE_SET, session.params.xres);
- /* enable gamma table for the scan */
- dev->reg.find_reg(0x05).value |= REG_0x05_GMMENB;
+ // no watch dog for simple scan
+ dev->reg.find_reg(0x01).value &= ~REG_0x01_DOGENB;
/* one table movement for simple scan */
dev->reg.find_reg(0x02).value &= ~REG_0x02_FASTFED;
if (!move) {
- sanei_genesys_set_motor_power(dev->reg, false);
-
- /* no automatic go home if no movement */
- dev->reg.find_reg(0x02).value &= ~REG_0x02_AGOHOME;
+ sanei_genesys_set_motor_power(dev->reg, false);
}
/* no automatic go home when using XPA */
- if (settings.scan_method == ScanMethod::TRANSPARENCY) {
+ if (session.params.scan_method == ScanMethod::TRANSPARENCY) {
dev->reg.find_reg(0x02).value &= ~REG_0x02_AGOHOME;
}
@@ -2946,46 +2699,38 @@ static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
/* in case of CIS scanner, we must reorder data */
- if (dev->model->is_cis && settings.scan_mode == ScanColorMode::COLOR_SINGLE_PASS) {
- /* alloc one line sized working buffer */
- std::vector<uint8_t> buffer(settings.pixels * 3 * bpp);
-
- /* reorder one line of data and put it back to buffer */
- if (bpp == 1)
- {
- for (y = 0; y < lines; y++)
- {
- /* reorder line */
- for (x = 0; x < settings.pixels; x++)
- {
- buffer[x * 3] = data[y * settings.pixels * 3 + x];
- buffer[x * 3 + 1] = data[y * settings.pixels * 3 + settings.pixels + x];
- buffer[x * 3 + 2] = data[y * settings.pixels * 3 + 2 * settings.pixels + x];
- }
- /* copy line back */
- memcpy (data.data() + settings.pixels * 3 * y, buffer.data(),
- settings.pixels * 3);
- }
- }
- else
- {
- for (y = 0; y < lines; y++)
- {
- /* reorder line */
- for (x = 0; x < settings.pixels; x++)
- {
- buffer[x * 6] = data[y * settings.pixels * 6 + x * 2];
- buffer[x * 6 + 1] = data[y * settings.pixels * 6 + x * 2 + 1];
- buffer[x * 6 + 2] = data[y * settings.pixels * 6 + 2 * settings.pixels + x * 2];
- buffer[x * 6 + 3] = data[y * settings.pixels * 6 + 2 * settings.pixels + x * 2 + 1];
- buffer[x * 6 + 4] = data[y * settings.pixels * 6 + 4 * settings.pixels + x * 2];
- buffer[x * 6 + 5] = data[y * settings.pixels * 6 + 4 * settings.pixels + x * 2 + 1];
- }
- /* copy line back */
- memcpy (data.data() + settings.pixels * 6 * y, buffer.data(),
- settings.pixels * 6);
- }
- }
+ if (dev->model->is_cis && session.params.scan_mode == ScanColorMode::COLOR_SINGLE_PASS) {
+ auto pixels_count = session.params.pixels;
+
+ std::vector<uint8_t> buffer(pixels_count * 3 * bpp);
+
+ if (bpp == 1) {
+ for (unsigned y = 0; y < lines; y++) {
+ // reorder line
+ for (unsigned x = 0; x < pixels_count; x++) {
+ buffer[x * 3] = data[y * pixels_count * 3 + x];
+ buffer[x * 3 + 1] = data[y * pixels_count * 3 + pixels_count + x];
+ buffer[x * 3 + 2] = data[y * pixels_count * 3 + 2 * pixels_count + x];
+ }
+ // copy line back
+ std::memcpy(data.data() + pixels_count * 3 * y, buffer.data(), pixels_count * 3);
+ }
+ } else {
+ for (unsigned y = 0; y < lines; y++) {
+ // reorder line
+ auto pixels_count = session.params.pixels;
+ for (unsigned x = 0; x < pixels_count; x++) {
+ buffer[x * 6] = data[y * pixels_count * 6 + x * 2];
+ buffer[x * 6 + 1] = data[y * pixels_count * 6 + x * 2 + 1];
+ buffer[x * 6 + 2] = data[y * pixels_count * 6 + 2 * pixels_count + x * 2];
+ buffer[x * 6 + 3] = data[y * pixels_count * 6 + 2 * pixels_count + x * 2 + 1];
+ buffer[x * 6 + 4] = data[y * pixels_count * 6 + 4 * pixels_count + x * 2];
+ buffer[x * 6 + 5] = data[y * pixels_count * 6 + 4 * pixels_count + x * 2 + 1];
+ }
+ // copy line back
+ std::memcpy(data.data() + pixels_count * 6 * y, buffer.data(),pixels_count * 6);
+ }
+ }
}
// end scan , waiting the motor to stop if needed (if moving), but without ejecting doc
@@ -2993,42 +2738,6 @@ static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
}
/**
- * Does a simple move of the given distance by doing a scan at lowest resolution
- * shading correction. Memory for data is allocated in this function
- * and must be freed by caller.
- * @param dev device of the scanner
- * @param distance distance to move in MM
- */
-static void simple_move(Genesys_Device* dev, SANE_Int distance)
-{
- DBG_HELPER_ARGS(dbg, "%d mm", distance);
- Genesys_Settings settings;
-
- unsigned resolution = sanei_genesys_get_lowest_dpi(dev);
-
- const auto& sensor = sanei_genesys_find_sensor(dev, resolution, 3, dev->model->default_method);
-
- /* TODO give a no AGOHOME flag */
- settings.scan_method = dev->model->default_method;
- settings.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- settings.xres = resolution;
- settings.yres = resolution;
- settings.tl_y = 0;
- settings.tl_x = 0;
- settings.pixels = (sensor.sensor_pixels * settings.xres) / sensor.optical_res;
- settings.requested_pixels = settings.pixels;
- settings.lines = static_cast<unsigned>((distance * settings.xres) / MM_PER_INCH);
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
-
- settings.disable_interpolation = 0;
- settings.threshold = 0;
-
- std::vector<uint8_t> data;
- simple_scan(dev, sensor, settings, true, true, false, data, "simple_move");
-}
-
-/**
* update the status of the required sensor in the scanner session
* the button fileds are used to make events 'sticky'
*/
@@ -3130,22 +2839,16 @@ void CommandSetGl646::update_hardware_sensors(Genesys_Scanner* session) const
}
/* XPA detection */
- if (dev->model->flags & GENESYS_FLAG_XPA)
- {
+ if (dev->model->has_method(ScanMethod::TRANSPARENCY)) {
switch (dev->model->gpio_id) {
case GpioId::HP3670:
case GpioId::HP2400:
/* test if XPA is plugged-in */
- if ((value & 0x40) == 0)
- {
- DBG(DBG_io, "%s: enabling XPA\n", __func__);
- session->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE;
- }
- else
- {
- DBG(DBG_io, "%s: disabling XPA\n", __func__);
- session->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE;
- }
+ if ((value & 0x40) == 0) {
+ session->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE;
+ } else {
+ session->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE;
+ }
break;
default:
throw SaneException(SANE_STATUS_UNSUPPORTED, "unknown gpo type");
@@ -3153,6 +2856,11 @@ void CommandSetGl646::update_hardware_sensors(Genesys_Scanner* session) const
}
}
+void CommandSetGl646::update_home_sensor_gpio(Genesys_Device& dev) const
+{
+ DBG_HELPER(dbg);
+ (void) dev;
+}
static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int resolution)
{
@@ -3167,7 +2875,7 @@ static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int
/* MD6471/G2410/HP2300 and XP200 read/write data from an undocumented memory area which
* is after the second slope table */
- switch (sensor.optical_res)
+ switch (sensor.full_resolution)
{
case 600:
addr = 0x08200;
@@ -3203,159 +2911,9 @@ static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int
break;
}
- DBG(DBG_info, "%s: control write=0x%02x 0x%02x 0x%02x 0x%02x\n", __func__, control[0], control[1],
- control[2], control[3]);
dev->interface->write_buffer(0x3c, addr, control, 4);
}
-/**
- * search for a full width black or white strip.
- * @param dev scanner device
- * @param forward true if searching forward, false if searching backward
- * @param black true if searching for a black strip, false for a white strip
- */
-void CommandSetGl646::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
- bool black) const
-{
- DBG_HELPER(dbg);
- (void) sensor;
-
- Genesys_Settings settings;
- int res = get_closest_resolution(dev->model->sensor_id, 75, 1);
- unsigned int pass, count, found, x, y;
- char title[80];
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, res, 1, ScanMethod::FLATBED);
-
- /* we set up for a lowest available resolution color grey scan, full width */
- settings.scan_method = dev->model->default_method;
- settings.scan_mode = ScanColorMode::GRAY;
- settings.xres = res;
- settings.yres = res;
- settings.tl_x = 0;
- settings.tl_y = 0;
- settings.pixels = static_cast<unsigned>((dev->model->x_size * res) / MM_PER_INCH);
- settings.pixels /= calib_sensor.get_ccd_size_divisor_for_dpi(res);
- settings.requested_pixels = settings.pixels;
-
- /* 15 mm at at time */
- settings.lines = static_cast<unsigned>((15 * settings.yres) / MM_PER_INCH);
- settings.depth = 8;
- settings.color_filter = ColorFilter::RED;
-
- settings.disable_interpolation = 0;
- settings.threshold = 0;
-
- /* signals if a strip of the given color has been found */
- found = 0;
-
- /* detection pass done */
- pass = 0;
-
- std::vector<uint8_t> data;
-
- /* loop until strip is found or maximum pass number done */
- while (pass < 20 && !found)
- {
- // scan a full width strip
- simple_scan(dev, calib_sensor, settings, true, forward, false, data, "search_strip");
-
- if (is_testing_mode()) {
- return;
- }
-
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl646_search_strip_%s%02d.pnm", forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file (title, data.data(), settings.depth, 1,
- settings.pixels, settings.lines);
- }
-
- /* search data to find black strip */
- /* when searching forward, we only need one line of the searched color since we
- * will scan forward. But when doing backward search, we need all the area of the
- * same color */
- if (forward)
- {
- for (y = 0; y < settings.lines && !found; y++)
- {
- count = 0;
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < settings.pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * settings.pixels + x] > 90)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * settings.pixels + x] < 60)
- {
- count++;
- }
- }
-
- /* at end of line, if count >= 3%, line is not fully of the desired color
- * so we must go to next line of the buffer */
- /* count*100/pixels < 3 */
- if ((count * 100) / settings.pixels < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
- pass, y);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count);
- }
- }
- }
- else /* since calibration scans are done forward, we need the whole area
- to be of the required color when searching backward */
- {
- count = 0;
- for (y = 0; y < settings.lines; y++)
- {
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < settings.pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * settings.pixels + x] > 60)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * settings.pixels + x] < 60)
- {
- count++;
- }
- }
- }
-
- /* at end of area, if count >= 3%, area is not fully of the desired color
- * so we must go to next buffer */
- if ((count * 100) / (settings.pixels * settings.lines) < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count);
- }
- }
- pass++;
- }
- if (found)
- {
- DBG(DBG_info, "%s: strip found\n", __func__);
- }
- else
- {
- throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
- }
-}
-
void CommandSetGl646::wait_for_motor_stop(Genesys_Device* dev) const
{
(void) dev;
@@ -3377,26 +2935,25 @@ ScanSession CommandSetGl646::calculate_scan_session(const Genesys_Device* dev,
{
// compute distance to move
float move = 0;
- // XXX STEF XXX MD5345 -> optical_ydpi, other base_ydpi => half/full step ? */
if (!dev->model->is_sheetfed) {
- move = static_cast<float>(dev->model->y_offset);
+ move = dev->model->y_offset;
// add tl_y to base movement
}
- move += static_cast<float>(settings.tl_y);
+ move += settings.tl_y;
if (move < 0) {
DBG(DBG_error, "%s: overriding negative move value %f\n", __func__, move);
move = 0;
}
- move = static_cast<float>((move * dev->motor.optical_ydpi) / MM_PER_INCH);
- float start = static_cast<float>(settings.tl_x);
+ move = static_cast<float>((move * dev->motor.base_ydpi) / MM_PER_INCH);
+ float start = settings.tl_x;
if (settings.scan_method == ScanMethod::FLATBED) {
- start += static_cast<float>(dev->model->x_offset);
+ start += dev->model->x_offset;
} else {
- start += static_cast<float>(dev->model->x_offset_ta);
+ start += dev->model->x_offset_ta;
}
- start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH);
+ start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
ScanSession session;
session.params.xres = settings.xres;
@@ -3411,7 +2968,7 @@ ScanSession CommandSetGl646::calculate_scan_session(const Genesys_Device* dev,
session.params.scan_method = dev->settings.scan_method;
session.params.scan_mode = settings.scan_mode;
session.params.color_filter = settings.color_filter;
- session.params.flags = ScanFlag::USE_XCORRECTION;
+ session.params.flags = ScanFlag::AUTO_GO_HOME;
if (settings.scan_method == ScanMethod::TRANSPARENCY) {
session.params.flags |= ScanFlag::USE_XPA;
}
@@ -3427,10 +2984,5 @@ void CommandSetGl646::asic_boot(Genesys_Device *dev, bool cold) const
throw SaneException("not implemented");
}
-std::unique_ptr<CommandSet> create_gl646_cmd_set()
-{
- return std::unique_ptr<CommandSet>(new CommandSetGl646{});
-}
-
} // namespace gl646
} // namespace genesys
diff --git a/backend/genesys/gl646.h b/backend/genesys/gl646.h
index afcfa05..8ab2c96 100644
--- a/backend/genesys/gl646.h
+++ b/backend/genesys/gl646.h
@@ -48,395 +48,13 @@
#define BACKEND_GENESYS_GL646_H
#include "genesys.h"
-#include "command_set.h"
+#include "command_set_common.h"
#include "motor.h"
namespace genesys {
namespace gl646 {
-static void gl646_set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set, int dpi);
-
-/**
- * sets up the scanner for a scan, registers, gamma tables, shading tables
- * and slope tables, based on the parameter struct.
- * @param dev device to set up
- * @param regs registers to set up
- * @param settings settings of the scan
- * @param split true if move before scan has to be done
- * @param xcorrection true if scanner's X geometry must be taken into account to
- * compute X, ie add left margins
- * @param ycorrection true if scanner's Y geometry must be taken into account to
- * compute Y, ie add top margins
- */
-static void setup_for_scan(Genesys_Device* device,
- const Genesys_Sensor& sensor,
- Genesys_Register_Set*regs,
- Genesys_Settings settings,
- bool split,
- bool xcorrection,
- bool ycorrection,
- bool reverse);
-
-/**
- * Does a simple move of the given distance by doing a scan at lowest resolution
- * shading correction. Memory for data is allocated in this function
- * and must be freed by caller.
- * @param dev device of the scanner
- * @param distance distance to move in MM
- */
-static void simple_move(Genesys_Device* dev, SANE_Int distance);
-
-/**
- * Does a simple scan of the area given by the settings. Scanned data
- * it put in an allocated area which must be freed by the caller.
- * and slope tables, based on the parameter struct. There is no shading
- * correction while gamma correction is active.
- * @param dev device to set up
- * @param settings settings of the scan
- * @param move flag to enable scanhead to move
- * @param forward flag to tell movement direction
- * @param shading flag to tell if shading correction should be done
- * @param data pointer that will point to the scanned data
- */
-static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Settings settings, bool move, bool forward,
- bool shading, std::vector<uint8_t>& data, const char* test_identifier);
-
-/**
- * Send the stop scan command
- * */
-static void end_scan_impl(Genesys_Device* dev, Genesys_Register_Set* reg, bool check_stop,
- bool eject);
-/**
- * writes control data to an area behind the last motor table.
- */
-static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int resolution);
-
-
-/**
- * initialize scanner's registers at SANE init time
- */
-static void gl646_init_regs (Genesys_Device * dev);
-
-/**
- * master motor settings table entry
- */
-typedef struct
-{
- /* key */
- MotorId motor_id;
- unsigned dpi;
- unsigned channels;
-
- /* settings */
- StepType steptype;
- bool fastmod; // fast scanning
- bool fastfed; // fast fed slope tables
- SANE_Int mtrpwm;
- MotorSlope slope1;
- MotorSlope slope2;
- SANE_Int fwdbwd; /* forward/backward steps */
-} Motor_Master;
-
-/**
- * master motor settings, for a given motor and dpi,
- * it gives steps and speed informations
- */
-static Motor_Master motor_master[] = {
- /* HP3670 motor settings */
- {MotorId::HP3670, 50, 3, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(2329, 120, 229),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 75, 3, StepType::FULL, false, true, 1,
- MotorSlope::create_from_steps(3429, 305, 200),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 100, 3, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(2905, 187, 143),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 150, 3, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(3429, 305, 73),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 300, 3, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(1055, 563, 11),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 600, 3, StepType::FULL, false, true, 0,
- MotorSlope::create_from_steps(10687, 5126, 3),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670,1200, 3, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(15937, 6375, 3),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 50, 1, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(2329, 120, 229),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 75, 1, StepType::FULL, false, true, 1,
- MotorSlope::create_from_steps(3429, 305, 200),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 100, 1, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(2905, 187, 143),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 150, 1, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(3429, 305, 73),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 300, 1, StepType::HALF, false, true, 1,
- MotorSlope::create_from_steps(1055, 563, 11),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670, 600, 1, StepType::FULL, false, true, 0,
- MotorSlope::create_from_steps(10687, 5126, 3),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- {MotorId::HP3670,1200, 1, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(15937, 6375, 3),
- MotorSlope::create_from_steps(3399, 337, 192), 192},
-
- /* HP2400/G2410 motor settings base motor dpi = 600 */
- {MotorId::HP2400, 50, 3, StepType::FULL, false, true, 63,
- MotorSlope::create_from_steps(8736, 601, 120),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 100, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(8736, 601, 120),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 150, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(15902, 902, 67),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 300, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(16703, 2188, 32),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 600, 3, StepType::FULL, false, true, 63,
- MotorSlope::create_from_steps(18761, 18761, 3),
- MotorSlope::create_from_steps(4905, 627, 192), 192},
-
- {MotorId::HP2400,1200, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(43501, 43501, 3),
- MotorSlope::create_from_steps(4905, 627, 192), 192},
-
- {MotorId::HP2400, 50, 1, StepType::FULL, false, true, 63,
- MotorSlope::create_from_steps(8736, 601, 120),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 100, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(8736, 601, 120),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 150, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(15902, 902, 67),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 300, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(16703, 2188, 32),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400, 600, 1, StepType::FULL, false, true, 63,
- MotorSlope::create_from_steps(18761, 18761, 3),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- {MotorId::HP2400,1200, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(43501, 43501, 3),
- MotorSlope::create_from_steps(4905, 337, 192), 192},
-
- /* XP 200 motor settings */
- {MotorId::XP200, 75, 3, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(6000, 2136, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 100, 3, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(6000, 2850, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 200, 3, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(6999, 5700, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 250, 3, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(6999, 6999, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 300, 3, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(13500, 13500, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 600, 3, StepType::HALF, true, true, 0,
- MotorSlope::create_from_steps(31998, 31998, 4),
- MotorSlope::create_from_steps(12000, 1200, 2), 1},
-
- {MotorId::XP200, 75, 1, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(6000, 2000, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 100, 1, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(6000, 1300, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 200, 1, StepType::HALF, true, true, 0,
- MotorSlope::create_from_steps(6000, 3666, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 300, 1, StepType::HALF, true, false, 0,
- MotorSlope::create_from_steps(6500, 6500, 4),
- MotorSlope::create_from_steps(12000, 1200, 8), 1},
-
- {MotorId::XP200, 600, 1, StepType::HALF, true, true, 0,
- MotorSlope::create_from_steps(24000, 24000, 4),
- MotorSlope::create_from_steps(12000, 1200, 2), 1},
-
- /* HP scanjet 2300c */
- {MotorId::HP2300, 75, 3, StepType::FULL, false, true, 63,
- MotorSlope::create_from_steps(8139, 560, 120),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 150, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(7903, 543, 67),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(2175, 1087, 3),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 600, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(8700, 4350, 3),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300,1200, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(17400, 8700, 3),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 75, 1, StepType::FULL, false, true, 63,
- MotorSlope::create_from_steps(8139, 560, 120),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 150, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(7903, 543, 67),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(2175, 1087, 3),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 600, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(8700, 4350, 3),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300,1200, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(17400, 8700, 3),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- /* non half ccd settings for 300 dpi
- {MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(5386, 2175, 44),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
-
- {MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63,
- MotorSlope::create_from_steps(5386, 2175, 44),
- MotorSlope::create_from_steps(4905, 337, 120), 16},
- */
-
- /* MD5345/6471 motor settings */
- /* vfinal=(exposure/(1200/dpi))/step_type */
- {MotorId::MD_5345, 50, 3, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 250, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 75, 3, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 343, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 100, 3, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 458, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 150, 3, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 687, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 200, 3, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 916, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 300, 3, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 1375, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 400, 3, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(2000, 1833, 32),
- MotorSlope::create_from_steps(2000, 300, 255), 32},
-
- {MotorId::MD_5345, 500, 3, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(2291, 2291, 32),
- MotorSlope::create_from_steps(2000, 300, 255), 32},
-
- {MotorId::MD_5345, 600, 3, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(2750, 2750, 32),
- MotorSlope::create_from_steps(2000, 300, 255), 32},
-
- {MotorId::MD_5345, 1200, 3, StepType::QUARTER, false, true, 0,
- MotorSlope::create_from_steps(2750, 2750, 16),
- MotorSlope::create_from_steps(2000, 300, 255), 146},
-
- {MotorId::MD_5345, 2400, 3, StepType::QUARTER, false, true, 0,
- MotorSlope::create_from_steps(5500, 5500, 16),
- MotorSlope::create_from_steps(2000, 300, 255), 146},
-
- {MotorId::MD_5345, 50, 1, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 250, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 75, 1, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 343, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 100, 1, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 458, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 150, 1, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 687, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 200, 1, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 916, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 300, 1, StepType::HALF, false, true, 2,
- MotorSlope::create_from_steps(2500, 1375, 255),
- MotorSlope::create_from_steps(2000, 300, 255), 64},
-
- {MotorId::MD_5345, 400, 1, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(2000, 1833, 32),
- MotorSlope::create_from_steps(2000, 300, 255), 32},
-
- {MotorId::MD_5345, 500, 1, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(2291, 2291, 32),
- MotorSlope::create_from_steps(2000, 300, 255), 32},
-
- {MotorId::MD_5345, 600, 1, StepType::HALF, false, true, 0,
- MotorSlope::create_from_steps(2750, 2750, 32),
- MotorSlope::create_from_steps(2000, 300, 255), 32},
-
- {MotorId::MD_5345, 1200, 1, StepType::QUARTER, false, true, 0,
- MotorSlope::create_from_steps(2750, 2750, 16),
- MotorSlope::create_from_steps(2000, 300, 255), 146},
-
- {MotorId::MD_5345, 2400, 1, StepType::QUARTER, false, true, 0,
- MotorSlope::create_from_steps(5500, 5500, 16),
- MotorSlope::create_from_steps(2000, 300, 255), 146}, /* 5500 guessed */
-};
-
-class CommandSetGl646 : public CommandSet
+class CommandSetGl646 : public CommandSetCommon
{
public:
~CommandSetGl646() override = default;
@@ -446,17 +64,11 @@ public:
void init(Genesys_Device* dev) const override;
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const override;
-
- void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const override;
+ Genesys_Register_Set* regs) const override;
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
- void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
-
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set* reg,
const ScanSession& session) const override;
@@ -472,8 +84,6 @@ public:
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
- void search_start_position(Genesys_Device* dev) const override;
-
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
@@ -489,17 +99,14 @@ public:
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
+ void update_home_sensor_gpio(Genesys_Device& dev) const override;
+
void load_document(Genesys_Device* dev) const override;
void detect_document_end(Genesys_Device* dev) const override;
void eject_document(Genesys_Device* dev) const override;
- void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const override;
-
- void move_to_ta(Genesys_Device* dev) const override;
-
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
int size) const override;
diff --git a/backend/genesys/gl646_registers.h b/backend/genesys/gl646_registers.h
index 2fe8f19..6ee9549 100644
--- a/backend/genesys/gl646_registers.h
+++ b/backend/genesys/gl646_registers.h
@@ -88,6 +88,7 @@ static constexpr RegMask REG_0x04_ADTYPE = 0x30;
static constexpr RegMask REG_0x04_FILTER = 0x0c;
static constexpr RegMask REG_0x04_FESET = 0x03;
+static constexpr RegAddr REG_0x05 = 0x05;
static constexpr RegMask REG_0x05_DPIHW = 0xc0;
static constexpr RegMask REG_0x05_DPIHW_600 = 0x00;
static constexpr RegMask REG_0x05_DPIHW_1200 = 0x40;
diff --git a/backend/genesys/gl841.cpp b/backend/genesys/gl841.cpp
index 470f9ba..731354f 100644
--- a/backend/genesys/gl841.cpp
+++ b/backend/genesys/gl841.cpp
@@ -63,315 +63,11 @@ namespace gl841 {
static int gl841_exposure_time(Genesys_Device *dev, const Genesys_Sensor& sensor,
+ const MotorProfile& profile,
float slope_dpi,
- StepType scan_step_type,
int start,
int used_pixels);
-/** copy sensor specific settings */
-/* *dev : device infos
- *regs : registers to be set
- extended : do extended set up
- ccd_size_divisor: set up for half ccd resolution
- all registers 08-0B, 10-1D, 52-59 are set up. They shouldn't
- appear anywhere else but in register_ini
-
-Responsible for signals to CCD/CIS:
- CCD_CK1X (CK1INV(0x16),CKDIS(0x16),CKTOGGLE(0x18),CKDELAY(0x18),MANUAL1(0x1A),CK1MTGL(0x1C),CK1LOW(0x1D),CK1MAP(0x74,0x75,0x76),CK1NEG(0x7D))
- CCD_CK2X (CK2INV(0x16),CKDIS(0x16),CKTOGGLE(0x18),CKDELAY(0x18),MANUAL1(0x1A),CK1LOW(0x1D),CK1NEG(0x7D))
- CCD_CK3X (MANUAL3(0x1A),CK3INV(0x1A),CK3MTGL(0x1C),CK3LOW(0x1D),CK3MAP(0x77,0x78,0x79),CK3NEG(0x7D))
- CCD_CK4X (MANUAL3(0x1A),CK4INV(0x1A),CK4MTGL(0x1C),CK4LOW(0x1D),CK4MAP(0x7A,0x7B,0x7C),CK4NEG(0x7D))
- CCD_CPX (CTRLHI(0x16),CTRLINV(0x16),CTRLDIS(0x16),CPH(0x72),CPL(0x73),CPNEG(0x7D))
- CCD_RSX (CTRLHI(0x16),CTRLINV(0x16),CTRLDIS(0x16),RSH(0x70),RSL(0x71),RSNEG(0x7D))
- CCD_TGX (TGINV(0x16),TGMODE(0x17),TGW(0x17),EXPR(0x10,0x11),TGSHLD(0x1D))
- CCD_TGG (TGINV(0x16),TGMODE(0x17),TGW(0x17),EXPG(0x12,0x13),TGSHLD(0x1D))
- CCD_TGB (TGINV(0x16),TGMODE(0x17),TGW(0x17),EXPB(0x14,0x15),TGSHLD(0x1D))
- LAMP_SW (EXPR(0x10,0x11),XPA_SEL(0x03),LAMP_PWR(0x03),LAMPTIM(0x03),MTLLAMP(0x04),LAMPPWM(0x29))
- XPA_SW (EXPG(0x12,0x13),XPA_SEL(0x03),LAMP_PWR(0x03),LAMPTIM(0x03),MTLLAMP(0x04),LAMPPWM(0x29))
- LAMP_B (EXPB(0x14,0x15),LAMP_PWR(0x03))
-
-other registers:
- CISSET(0x01),CNSET(0x18),DCKSEL(0x18),SCANMOD(0x18),EXPDMY(0x19),LINECLP(0x1A),CKAREA(0x1C),TGTIME(0x1C),LINESEL(0x1E),DUMMY(0x34)
-
-Responsible for signals to AFE:
- VSMP (VSMP(0x58),VSMPW(0x58))
- BSMP (BSMP(0x59),BSMPW(0x59))
-
-other register settings depending on this:
- RHI(0x52),RLOW(0x53),GHI(0x54),GLOW(0x55),BHI(0x56),BLOW(0x57),
-
-*/
-static void sanei_gl841_setup_sensor(Genesys_Device * dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set * regs,
- bool extended, unsigned ccd_size_divisor)
-{
- DBG(DBG_proc, "%s\n", __func__);
-
- // that one is tricky at least
- for (uint16_t addr = 0x08; addr <= 0x0b; ++addr) {
- regs->set8(0x70 + addr - 0x08, sensor.custom_regs.get_value(addr));
- }
-
- // ignore registers in range [0x10..0x16)
- for (uint16_t addr = 0x16; addr < 0x1e; ++addr) {
- regs->set8(addr, sensor.custom_regs.get_value(addr));
- }
-
- // ignore registers in range [0x5b..0x5e]
- for (uint16_t addr = 0x52; addr < 0x52 + 9; ++addr) {
- regs->set8(addr, sensor.custom_regs.get_value(addr));
- }
-
- /* don't go any further if no extended setup */
- if (!extended)
- return;
-
- /* todo : add more CCD types if needed */
- /* we might want to expand the Sensor struct to have these
- 2 kind of settings */
- if (dev->model->sensor_id == SensorId::CCD_5345) {
- if (ccd_size_divisor > 1) {
- GenesysRegister* r;
- /* settings for CCD used at half is max resolution */
- r = sanei_genesys_get_address (regs, 0x70);
- r->value = 0x00;
- r = sanei_genesys_get_address (regs, 0x71);
- r->value = 0x05;
- r = sanei_genesys_get_address (regs, 0x72);
- r->value = 0x06;
- r = sanei_genesys_get_address (regs, 0x73);
- r->value = 0x08;
- r = sanei_genesys_get_address (regs, 0x18);
- r->value = 0x28;
- r = sanei_genesys_get_address (regs, 0x58);
- r->value = 0x80 | (r->value & 0x03); /* VSMP=16 */
- }
- else
- {
- GenesysRegister* r;
- /* swap latch times */
- r = sanei_genesys_get_address (regs, 0x18);
- r->value = 0x30;
- regs->set8(0x52, sensor.custom_regs.get_value(0x55));
- regs->set8(0x53, sensor.custom_regs.get_value(0x56));
- regs->set8(0x54, sensor.custom_regs.get_value(0x57));
- regs->set8(0x55, sensor.custom_regs.get_value(0x52));
- regs->set8(0x56, sensor.custom_regs.get_value(0x53));
- regs->set8(0x57, sensor.custom_regs.get_value(0x54));
- r = sanei_genesys_get_address (regs, 0x58);
- r->value = 0x20 | (r->value & 0x03); /* VSMP=4 */
- }
- return;
- }
-
- if (dev->model->sensor_id == SensorId::CCD_HP2300) {
- /* settings for CCD used at half is max resolution */
- GenesysRegister* r;
- if (ccd_size_divisor > 1) {
- r = sanei_genesys_get_address (regs, 0x70);
- r->value = 0x16;
- r = sanei_genesys_get_address (regs, 0x71);
- r->value = 0x00;
- r = sanei_genesys_get_address (regs, 0x72);
- r->value = 0x01;
- r = sanei_genesys_get_address (regs, 0x73);
- r->value = 0x03;
- /* manual clock programming */
- r = sanei_genesys_get_address (regs, 0x1d);
- r->value |= 0x80;
- }
- else
- {
- r = sanei_genesys_get_address (regs, 0x70);
- r->value = 1;
- r = sanei_genesys_get_address (regs, 0x71);
- r->value = 3;
- r = sanei_genesys_get_address (regs, 0x72);
- r->value = 4;
- r = sanei_genesys_get_address (regs, 0x73);
- r->value = 6;
- }
- r = sanei_genesys_get_address (regs, 0x58);
- r->value = 0x80 | (r->value & 0x03); /* VSMP=16 */
- return;
- }
-}
-
-/*
- * Set all registers LiDE 80 to default values
- * (function called only once at the beginning)
- * we are doing a special case to ease development
- */
-static void
-gl841_init_lide80 (Genesys_Device * dev)
-{
- dev->reg.init_reg(0x01, 0x82); // 0x02 = SHDAREA and no CISSET !
- dev->reg.init_reg(0x02, 0x10);
- dev->reg.init_reg(0x03, 0x50);
- dev->reg.init_reg(0x04, 0x02);
- dev->reg.init_reg(0x05, 0x4c); // 1200 DPI
- dev->reg.init_reg(0x06, 0x38); // 0x38 scanmod=1, pwrbit, GAIN4
- dev->reg.init_reg(0x07, 0x00);
- dev->reg.init_reg(0x08, 0x00);
- dev->reg.init_reg(0x09, 0x11);
- dev->reg.init_reg(0x0a, 0x00);
-
- 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);
- dev->reg.init_reg(0x17, 0x01);
- dev->reg.init_reg(0x18, 0x00);
- dev->reg.init_reg(0x19, 0x06);
- dev->reg.init_reg(0x1a, 0x00);
- dev->reg.init_reg(0x1b, 0x00);
- dev->reg.init_reg(0x1c, 0x00);
- dev->reg.init_reg(0x1d, 0x04);
- dev->reg.init_reg(0x1e, 0x10);
- dev->reg.init_reg(0x1f, 0x04);
- dev->reg.init_reg(0x20, 0x02);
- dev->reg.init_reg(0x21, 0x10);
- dev->reg.init_reg(0x22, 0x20);
- dev->reg.init_reg(0x23, 0x20);
- dev->reg.init_reg(0x24, 0x10);
- dev->reg.init_reg(0x25, 0x00);
- dev->reg.init_reg(0x26, 0x00);
- dev->reg.init_reg(0x27, 0x00);
-
- dev->reg.init_reg(0x29, 0xff);
-
- const auto& sensor = sanei_genesys_find_sensor_any(dev);
- dev->reg.init_reg(0x2c, sensor.optical_res>>8);
- dev->reg.init_reg(0x2d, sensor.optical_res & 0xff);
- dev->reg.init_reg(0x2e, 0x80);
- dev->reg.init_reg(0x2f, 0x80);
- dev->reg.init_reg(0x30, 0x00);
- 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(0x3d, 0x00);
- dev->reg.init_reg(0x3e, 0x00);
- dev->reg.init_reg(0x3f, 0x00);
-
- dev->reg.init_reg(0x52, 0x03);
- dev->reg.init_reg(0x53, 0x07);
- dev->reg.init_reg(0x54, 0x00);
- dev->reg.init_reg(0x55, 0x00);
- dev->reg.init_reg(0x56, 0x00);
- dev->reg.init_reg(0x57, 0x00);
- dev->reg.init_reg(0x58, 0x29);
- dev->reg.init_reg(0x59, 0x69);
- dev->reg.init_reg(0x5a, 0x55);
-
- dev->reg.init_reg(0x5d, 0x20);
- dev->reg.init_reg(0x5e, 0x41);
- dev->reg.init_reg(0x5f, 0x40);
- dev->reg.init_reg(0x60, 0x00);
- dev->reg.init_reg(0x61, 0x00);
- dev->reg.init_reg(0x62, 0x00);
- dev->reg.init_reg(0x63, 0x00);
- dev->reg.init_reg(0x64, 0x00);
- dev->reg.init_reg(0x65, 0x00);
- dev->reg.init_reg(0x66, 0x00);
- dev->reg.init_reg(0x67, 0x40);
- dev->reg.init_reg(0x68, 0x40);
- dev->reg.init_reg(0x69, 0x20);
- dev->reg.init_reg(0x6a, 0x20);
- dev->reg.init_reg(0x6c, 0x00);
- dev->reg.init_reg(0x6d, 0x00);
- dev->reg.init_reg(0x6e, 0x00);
- dev->reg.init_reg(0x6f, 0x00);
- dev->reg.init_reg(0x70, 0x00);
- dev->reg.init_reg(0x71, 0x05);
- dev->reg.init_reg(0x72, 0x07);
- dev->reg.init_reg(0x73, 0x09);
- dev->reg.init_reg(0x74, 0x00);
- dev->reg.init_reg(0x75, 0x01);
- dev->reg.init_reg(0x76, 0xff);
- dev->reg.init_reg(0x77, 0x00);
- dev->reg.init_reg(0x78, 0x0f);
- dev->reg.init_reg(0x79, 0xf0);
- dev->reg.init_reg(0x7a, 0xf0);
- dev->reg.init_reg(0x7b, 0x00);
- dev->reg.init_reg(0x7c, 0x1e);
- dev->reg.init_reg(0x7d, 0x11);
- dev->reg.init_reg(0x7e, 0x00);
- dev->reg.init_reg(0x7f, 0x50);
- dev->reg.init_reg(0x80, 0x00);
- dev->reg.init_reg(0x81, 0x00);
- dev->reg.init_reg(0x82, 0x0f);
- dev->reg.init_reg(0x83, 0x00);
- dev->reg.init_reg(0x84, 0x0e);
- dev->reg.init_reg(0x85, 0x00);
- dev->reg.init_reg(0x86, 0x0d);
- dev->reg.init_reg(0x87, 0x02);
- dev->reg.init_reg(0x88, 0x00);
- dev->reg.init_reg(0x89, 0x00);
-
- for (const auto& reg : dev->gpo.regs) {
- dev->reg.set8(reg.address, reg.value);
- }
-
- // specific scanner settings, clock and gpio first
- // FIXME: remove the dummy reads as we don't use the values
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6B);
- }
- dev->interface->write_register(REG_0x6B, 0x0c);
- dev->interface->write_register(0x06, 0x10);
- dev->interface->write_register(REG_0x6E, 0x6d);
- dev->interface->write_register(REG_0x6F, 0x80);
- dev->interface->write_register(REG_0x6B, 0x0e);
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6C);
- }
- dev->interface->write_register(REG_0x6C, 0x00);
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6D);
- }
- dev->interface->write_register(REG_0x6D, 0x8f);
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6B);
- }
- dev->interface->write_register(REG_0x6B, 0x0e);
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6B);
- }
- dev->interface->write_register(REG_0x6B, 0x0e);
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6B);
- }
- dev->interface->write_register(REG_0x6B, 0x0a);
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6B);
- }
- dev->interface->write_register(REG_0x6B, 0x02);
- if (!is_testing_mode()) {
- dev->interface->read_register(REG_0x6B);
- }
- dev->interface->write_register(REG_0x6B, 0x06);
-
- 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;
-
- sanei_gl841_setup_sensor(dev, sensor, &dev->reg, 0, 1);
-}
-
/*
* Set all registers to default values
* (function called only once at the beginning)
@@ -379,139 +75,232 @@ gl841_init_lide80 (Genesys_Device * dev)
static void
gl841_init_registers (Genesys_Device * dev)
{
- int addr;
-
- DBG(DBG_proc, "%s\n", __func__);
-
- dev->reg.clear();
- if (dev->model->model_id == ModelId::CANON_LIDE_80) {
- gl841_init_lide80(dev);
- return ;
- }
-
- for (addr = 1; addr <= 0x0a; addr++) {
- dev->reg.init_reg(addr, 0);
- }
- for (addr = 0x10; addr <= 0x27; addr++) {
- dev->reg.init_reg(addr, 0);
- }
- dev->reg.init_reg(0x29, 0);
- for (addr = 0x2c; addr <= 0x39; addr++)
- dev->reg.init_reg(addr, 0);
- for (addr = 0x3d; addr <= 0x3f; addr++)
- dev->reg.init_reg(addr, 0);
- for (addr = 0x52; addr <= 0x5a; addr++)
- dev->reg.init_reg(addr, 0);
- for (addr = 0x5d; addr <= 0x87; addr++)
- dev->reg.init_reg(addr, 0);
-
+ DBG_HELPER(dbg);
- dev->reg.find_reg(0x01).value = 0x20; /* (enable shading), CCD, color, 1M */
+ dev->reg.init_reg(0x01, 0x20);
if (dev->model->is_cis) {
dev->reg.find_reg(0x01).value |= REG_0x01_CISSET;
} else {
dev->reg.find_reg(0x01).value &= ~REG_0x01_CISSET;
}
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x01, 0x82);
+ }
- dev->reg.find_reg(0x02).value = 0x30 /*0x38 */ ; /* auto home, one-table-move, full step */
- dev->reg.find_reg(0x02).value |= REG_0x02_AGOHOME;
- sanei_genesys_set_motor_power(dev->reg, true);
- dev->reg.find_reg(0x02).value |= REG_0x02_FASTFED;
-
- dev->reg.find_reg(0x03).value = 0x1f /*0x17 */ ; /* lamp on */
- dev->reg.find_reg(0x03).value |= REG_0x03_AVEENB;
+ dev->reg.init_reg(0x02, 0x38);
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x02, 0x10);
+ }
- if (dev->model->sensor_id == SensorId::CCD_PLUSTEK_OPTICPRO_3600) {
- // AD front end
- dev->reg.find_reg(0x04).value = (2 << REG_0x04S_AFEMOD) | 0x02;
+ dev->reg.init_reg(0x03, 0x5f);
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x03, 0x50);
}
- else /* Wolfson front end */
- {
- dev->reg.find_reg(0x04).value |= 1 << REG_0x04S_AFEMOD;
+
+ dev->reg.init_reg(0x04, 0x10);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICPRO_3600) {
+ dev->reg.init_reg(0x04, 0x22);
+ } else if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x04, 0x02);
}
- const auto& sensor = sanei_genesys_find_sensor_any(dev);
+ const auto& sensor = sanei_genesys_find_sensor_any(dev);
- dev->reg.find_reg(0x05).value = 0x00; /* disable gamma, 24 clocks/pixel */
+ dev->reg.init_reg(0x05, 0x00); // disable gamma, 24 clocks/pixel
- unsigned dpihw = 0;
- if (sensor.sensor_pixels < 0x1500) {
- dpihw = 600;
- } else if (sensor.sensor_pixels < 0x2a80) {
- dpihw = 1200;
- } else if (sensor.sensor_pixels < 0x5400) {
- dpihw = 2400;
- } else {
- throw SaneException("Cannot handle sensor pixel count %d", sensor.sensor_pixels);
- }
- sanei_genesys_set_dpihw(dev->reg, sensor, dpihw);
+ sanei_genesys_set_dpihw(dev->reg, sensor.register_dpihw);
- dev->reg.find_reg(0x06).value |= REG_0x06_PWRBIT;
- dev->reg.find_reg(0x06).value |= REG_0x06_GAIN4;
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x05, 0x4c);
+ }
- /* XP300 CCD needs different clock and clock/pixels values */
- if (dev->model->sensor_id != SensorId::CCD_XP300 &&
- dev->model->sensor_id != SensorId::CCD_DP685 &&
- dev->model->sensor_id != SensorId::CCD_PLUSTEK_OPTICPRO_3600)
- {
- dev->reg.find_reg(0x06).value |= 0 << REG_0x06S_SCANMOD;
- dev->reg.find_reg(0x09).value |= 1 << REG_0x09S_CLKSET;
+ dev->reg.init_reg(0x06, 0x18);
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x06, 0x38);
}
- else
+ if (dev->model->model_id == ModelId::VISIONEER_STROBE_XP300 ||
+ dev->model->model_id == ModelId::SYSCAN_DOCKETPORT_485 ||
+ dev->model->model_id == ModelId::DCT_DOCKETPORT_487 ||
+ dev->model->model_id == ModelId::SYSCAN_DOCKETPORT_685 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICPRO_3600)
{
- dev->reg.find_reg(0x06).value |= 0x05 << REG_0x06S_SCANMOD; /* 15 clocks/pixel */
- dev->reg.find_reg(0x09).value = 0; /* 24 MHz CLKSET */
+ dev->reg.init_reg(0x06, 0xb8);
}
- dev->reg.find_reg(0x1e).value = 0xf0; /* watch-dog time */
-
- dev->reg.find_reg(0x17).value |= 1 << REG_0x17S_TGW;
-
- dev->reg.find_reg(0x19).value = 0x50;
-
- dev->reg.find_reg(0x1d).value |= 1 << REG_0x1DS_TGSHLD;
-
- dev->reg.find_reg(0x1e).value |= 1 << REG_0x1ES_WDTIME;
-
-/*SCANFED*/
- dev->reg.find_reg(0x1f).value = 0x01;
+ dev->reg.init_reg(0x07, 0x00);
+ dev->reg.init_reg(0x08, 0x00);
-/*BUFSEL*/
- dev->reg.find_reg(0x20).value = 0x20;
+ dev->reg.init_reg(0x09, 0x10);
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x09, 0x11);
+ }
+ if (dev->model->model_id == ModelId::VISIONEER_STROBE_XP300 ||
+ dev->model->model_id == ModelId::SYSCAN_DOCKETPORT_485 ||
+ dev->model->model_id == ModelId::DCT_DOCKETPORT_487 ||
+ dev->model->model_id == ModelId::SYSCAN_DOCKETPORT_685 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICPRO_3600)
+ {
+ dev->reg.init_reg(0x09, 0x00);
+ }
+ dev->reg.init_reg(0x0a, 0x00);
-/*LAMPPWM*/
- dev->reg.find_reg(0x29).value = 0xff;
+ // EXPR[0:15], EXPG[0:15], EXPB[0:15]: Exposure time settings
+ dev->reg.init_reg(0x10, 0x00); // SENSOR_DEF
+ dev->reg.init_reg(0x11, 0x00); // SENSOR_DEF
+ dev->reg.init_reg(0x12, 0x00); // SENSOR_DEF
+ 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
+ dev->reg.init_reg(0x19, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x1a, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x1b, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x1c, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x1d, 0x01); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x1e, 0xf0);
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x1e, 0x10);
+ }
+ dev->reg.init_reg(0x1f, 0x01);
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x1f, 0x04);
+ }
+ dev->reg.init_reg(0x20, 0x20);
+ dev->reg.init_reg(0x21, 0x01);
+ dev->reg.init_reg(0x22, 0x01);
+ dev->reg.init_reg(0x23, 0x01);
+ dev->reg.init_reg(0x24, 0x01);
+ dev->reg.init_reg(0x25, 0x00);
+ dev->reg.init_reg(0x26, 0x00);
+ dev->reg.init_reg(0x27, 0x00);
+ dev->reg.init_reg(0x29, 0xff);
-/*BWHI*/
- dev->reg.find_reg(0x2e).value = 0x80;
+ 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(0x2e, 0x80);
+ dev->reg.init_reg(0x2f, 0x80);
-/*BWLOW*/
- dev->reg.find_reg(0x2f).value = 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);
+ }
-/*LPERIOD*/
- dev->reg.find_reg(0x38).value = 0x4f;
- dev->reg.find_reg(0x39).value = 0xc1;
+ dev->reg.init_reg(0x3d, 0x00);
+ dev->reg.init_reg(0x3e, 0x00);
+ dev->reg.init_reg(0x3f, 0x00);
-/*VSMPW*/
- dev->reg.find_reg(0x58).value |= 3 << REG_0x58S_VSMPW;
+ dev->reg.init_reg(0x52, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x53, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x54, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x55, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x56, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x57, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x58, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x59, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x5a, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
-/*BSMPW*/
- dev->reg.find_reg(0x59).value |= 3 << REG_0x59S_BSMPW;
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x5d, 0x20);
+ dev->reg.init_reg(0x5e, 0x41);
+ dev->reg.init_reg(0x5f, 0x40);
+ dev->reg.init_reg(0x60, 0x00);
+ dev->reg.init_reg(0x61, 0x00);
+ dev->reg.init_reg(0x62, 0x00);
+ dev->reg.init_reg(0x63, 0x00);
+ dev->reg.init_reg(0x64, 0x00);
+ dev->reg.init_reg(0x65, 0x00);
+ dev->reg.init_reg(0x66, 0x00);
+ dev->reg.init_reg(0x67, 0x40);
+ dev->reg.init_reg(0x68, 0x40);
+ dev->reg.init_reg(0x69, 0x20);
+ dev->reg.init_reg(0x6a, 0x20);
+ dev->reg.init_reg(0x6c, 0x00);
+ dev->reg.init_reg(0x6d, 0x00);
+ dev->reg.init_reg(0x6e, 0x00);
+ dev->reg.init_reg(0x6f, 0x00);
+ } else {
+ for (unsigned addr = 0x5d; addr <= 0x6f; addr++) {
+ dev->reg.init_reg(addr, 0);
+ }
+ dev->reg.init_reg(0x5e, 0x02);
+ if (dev->model->model_id == ModelId::CANON_LIDE_60) {
+ dev->reg.init_reg(0x66, 0xff);
+ }
+ }
-/*RLCSEL*/
- dev->reg.find_reg(0x5a).value |= REG_0x5A_RLCSEL;
+ dev->reg.init_reg(0x70, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x71, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x72, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x73, 0x00); // SENSOR_DEF, overwritten in scanner_setup_sensor() below
-/*STOPTIM*/
- dev->reg.find_reg(0x5e).value |= 0x2 << REG_0x5ES_STOPTIM;
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ dev->reg.init_reg(0x74, 0x00);
+ dev->reg.init_reg(0x75, 0x01);
+ dev->reg.init_reg(0x76, 0xff);
+ dev->reg.init_reg(0x77, 0x00);
+ dev->reg.init_reg(0x78, 0x0f);
+ dev->reg.init_reg(0x79, 0xf0);
+ dev->reg.init_reg(0x7a, 0xf0);
+ dev->reg.init_reg(0x7b, 0x00);
+ dev->reg.init_reg(0x7c, 0x1e);
+ dev->reg.init_reg(0x7d, 0x11);
+ dev->reg.init_reg(0x7e, 0x00);
+ dev->reg.init_reg(0x7f, 0x50);
+ dev->reg.init_reg(0x80, 0x00);
+ dev->reg.init_reg(0x81, 0x00);
+ dev->reg.init_reg(0x82, 0x0f);
+ dev->reg.init_reg(0x83, 0x00);
+ dev->reg.init_reg(0x84, 0x0e);
+ dev->reg.init_reg(0x85, 0x00);
+ dev->reg.init_reg(0x86, 0x0d);
+ dev->reg.init_reg(0x87, 0x02);
+ dev->reg.init_reg(0x88, 0x00);
+ dev->reg.init_reg(0x89, 0x00);
+ } else {
+ for (unsigned addr = 0x74; addr <= 0x87; addr++) {
+ dev->reg.init_reg(addr, 0);
+ }
+ }
- sanei_gl841_setup_sensor(dev, sensor, &dev->reg, 0, 1);
+ scanner_setup_sensor(*dev, sensor, dev->reg);
// set up GPIO
for (const auto& reg : dev->gpo.regs) {
dev->reg.set8(reg.address, reg.value);
}
- /* TODO there is a switch calling to be written here */
if (dev->model->gpio_id == GpioId::CANON_LIDE_35) {
dev->reg.find_reg(0x6b).value |= REG_0x6B_GPO18;
dev->reg.find_reg(0x6b).value &= ~REG_0x6B_GPO17;
@@ -523,70 +312,43 @@ gl841_init_registers (Genesys_Device * dev)
if (dev->model->gpio_id == GpioId::DP685) {
/* REG_0x6B_GPO18 lights on green led */
- dev->reg.find_reg(0x6b).value |= REG_0x6B_GPO17|REG_0x6B_GPO18;
+ dev->reg.find_reg(0x6b).value |= REG_0x6B_GPO17 | REG_0x6B_GPO18;
}
- DBG(DBG_proc, "%s complete\n", __func__);
-}
-
-// Send slope table for motor movement slope_table in machine byte order
-static void gl841_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 dpihw;
- int start_address;
- char msg[4000];
-/*#ifdef WORDS_BIGENDIAN*/
- int i;
-/*#endif*/
-
- dpihw = dev->reg.find_reg(0x05).value >> 6;
-
- if (dpihw == 0) /* 600 dpi */
- start_address = 0x08000;
- else if (dpihw == 1) /* 1200 dpi */
- start_address = 0x10000;
- else if (dpihw == 2) /* 2400 dpi */
- start_address = 0x20000;
- else {
- throw SaneException("Unexpected dpihw");
- }
-
- 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+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);
+ if (dev->model->model_id == ModelId::CANON_LIDE_80) {
+ // specific scanner settings, clock and gpio first
+ dev->interface->write_register(REG_0x6B, 0x0c);
+ dev->interface->write_register(0x06, 0x10);
+ dev->interface->write_register(REG_0x6E, 0x6d);
+ dev->interface->write_register(REG_0x6F, 0x80);
+ dev->interface->write_register(REG_0x6B, 0x0e);
+ dev->interface->write_register(REG_0x6C, 0x00);
+ dev->interface->write_register(REG_0x6D, 0x8f);
+ dev->interface->write_register(REG_0x6B, 0x0e);
+ dev->interface->write_register(REG_0x6B, 0x0e);
+ dev->interface->write_register(REG_0x6B, 0x0a);
+ dev->interface->write_register(REG_0x6B, 0x02);
+ dev->interface->write_register(REG_0x6B, 0x06);
+
+ 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;
}
- dev->interface->write_buffer(0x3c, start_address + table_nr * 0x200, table.data(), steps * 2);
}
static void gl841_set_lide80_fe(Genesys_Device* dev, uint8_t set)
{
DBG_HELPER(dbg);
- 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;
- // write them to analog frontend
+ // BUG: the following code does not make sense. The addresses are different than AFE_SET
+ // case
dev->interface->write_fe_register(0x00, dev->frontend.regs.get_value(0x00));
dev->interface->write_fe_register(0x03, dev->frontend.regs.get_value(0x01));
dev->interface->write_fe_register(0x06, dev->frontend.regs.get_value(0x02));
@@ -611,11 +373,7 @@ static void gl841_set_ad_fe(Genesys_Device* dev, uint8_t set)
return;
}
- if (set == AFE_INIT)
- {
- DBG(DBG_proc, "%s(): setting DAC %u\n", __func__,
- static_cast<unsigned>(dev->model->adc_id));
-
+ if (set == AFE_INIT) {
dev->frontend = dev->frontend_initial;
// write them to analog frontend
@@ -674,15 +432,11 @@ void CommandSetGl841::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
throw SaneException("unsupported frontend type %d", frontend_type);
}
- 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;
// reset only done on init
dev->interface->write_fe_register(0x04, 0x80);
- DBG(DBG_proc, "%s(): frontend reset complete\n", __func__);
}
@@ -712,71 +466,34 @@ void CommandSetGl841::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
}
}
-enum MotorAction {
- MOTOR_ACTION_FEED = 1,
- MOTOR_ACTION_GO_HOME = 2,
- MOTOR_ACTION_HOME_FREE = 3
-};
-
// @brief turn off motor
static void gl841_init_motor_regs_off(Genesys_Register_Set* reg, unsigned int scan_lines)
{
DBG_HELPER_ARGS(dbg, "scan_lines=%d", scan_lines);
unsigned int feedl;
- GenesysRegister* r;
feedl = 2;
- r = sanei_genesys_get_address (reg, 0x3d);
- r->value = (feedl >> 16) & 0xf;
- r = sanei_genesys_get_address (reg, 0x3e);
- r->value = (feedl >> 8) & 0xff;
- r = sanei_genesys_get_address (reg, 0x3f);
- r->value = feedl & 0xff;
- r = sanei_genesys_get_address (reg, 0x5e);
- r->value &= ~0xe0;
-
- r = sanei_genesys_get_address (reg, 0x25);
- r->value = (scan_lines >> 16) & 0xf;
- r = sanei_genesys_get_address (reg, 0x26);
- r->value = (scan_lines >> 8) & 0xff;
- r = sanei_genesys_get_address (reg, 0x27);
- r->value = scan_lines & 0xff;
-
- r = sanei_genesys_get_address (reg, 0x02);
- r->value &= ~0x01; /*LONGCURV OFF*/
- r->value &= ~0x80; /*NOT_HOME OFF*/
-
- r->value &= ~0x10;
-
- r->value &= ~0x06;
-
- r->value &= ~0x08;
+ reg->set8(0x3d, (feedl >> 16) & 0xf);
+ reg->set8(0x3e, (feedl >> 8) & 0xff);
+ reg->set8(0x3f, feedl & 0xff);
+ reg->find_reg(0x5e).value &= ~0xe0;
- r->value &= ~0x20;
+ reg->set8(0x25, (scan_lines >> 16) & 0xf);
+ reg->set8(0x26, (scan_lines >> 8) & 0xff);
+ reg->set8(0x27, scan_lines & 0xff);
- r->value &= ~0x40;
+ reg->set8(0x02, 0x00);
- r = sanei_genesys_get_address (reg, 0x67);
- r->value = 0x3f;
+ reg->set8(0x67, 0x3f);
+ reg->set8(0x68, 0x3f);
- r = sanei_genesys_get_address (reg, 0x68);
- r->value = 0x3f;
+ reg->set8(REG_STEPNO, 1);
+ reg->set8(REG_FASTNO, 1);
- r = sanei_genesys_get_address(reg, REG_STEPNO);
- r->value = 0;
-
- r = sanei_genesys_get_address(reg, REG_FASTNO);
- r->value = 0;
-
- r = sanei_genesys_get_address (reg, 0x69);
- r->value = 0;
-
- r = sanei_genesys_get_address (reg, 0x6a);
- r->value = 0;
-
- r = sanei_genesys_get_address (reg, 0x5f);
- r->value = 0;
+ reg->set8(0x69, 1);
+ reg->set8(0x6a, 1);
+ reg->set8(0x5f, 1);
}
/** @brief write motor table frequency
@@ -814,207 +531,122 @@ uint8_t *table;
table=tdefault;
}
dev->interface->write_register(0x66, 0x00);
- dev->interface->write_gamma(0x28, 0xc000, table, 128,
- ScannerInterface::FLAG_SWAP_REGISTERS);
+ dev->interface->write_gamma(0x28, 0xc000, table, 128);
dev->interface->write_register(0x5b, 0x00);
dev->interface->write_register(0x5c, 0x00);
}
}
-
-static void gl841_init_motor_regs(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* reg, unsigned int feed_steps,/*1/base_ydpi*/
- /*maybe float for half/quarter step resolution?*/
- unsigned int action, MotorFlag flags)
+static void gl841_init_motor_regs_feed(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* reg, unsigned int feed_steps,/*1/base_ydpi*/
+ ScanFlag flags)
{
- DBG_HELPER_ARGS(dbg, "feed_steps=%d, action=%d, flags=%x", feed_steps, action,
- static_cast<unsigned>(flags));
- unsigned int fast_exposure = 0;
+ DBG_HELPER_ARGS(dbg, "feed_steps=%d, flags=%x", feed_steps, static_cast<unsigned>(flags));
+ unsigned step_multiplier = 2;
int use_fast_fed = 0;
unsigned int feedl;
- GenesysRegister* r;
/*number of scan lines to add in a scan_lines line*/
{
std::vector<uint16_t> table;
table.resize(256, 0xffff);
- gl841_send_slope_table(dev, 0, table, 256);
- gl841_send_slope_table(dev, 1, table, 256);
- gl841_send_slope_table(dev, 2, table, 256);
- gl841_send_slope_table(dev, 3, table, 256);
- gl841_send_slope_table(dev, 4, table, 256);
+ scanner_send_slope_table(dev, sensor, 0, table);
+ scanner_send_slope_table(dev, sensor, 1, table);
+ scanner_send_slope_table(dev, sensor, 2, table);
+ scanner_send_slope_table(dev, sensor, 3, table);
+ scanner_send_slope_table(dev, sensor, 4, table);
}
gl841_write_freq(dev, dev->motor.base_ydpi / 4);
- if (action == MOTOR_ACTION_FEED || action == MOTOR_ACTION_GO_HOME) {
- /* FEED and GO_HOME can use fastest slopes available */
- fast_exposure = gl841_exposure_time(dev, sensor,
- dev->motor.base_ydpi / 4,
- StepType::FULL,
- 0,
- 0);
- DBG(DBG_info, "%s : fast_exposure=%d pixels\n", __func__, fast_exposure);
- }
+ // FIXME: use proper scan session
+ ScanSession session;
+ session.params.yres = dev->motor.base_ydpi;
+ session.params.scan_method = dev->model->default_method;
- if (action == MOTOR_ACTION_HOME_FREE) {
-/* HOME_FREE must be able to stop in one step, so do not try to get faster */
- fast_exposure = dev->motor.get_slope(StepType::FULL).max_speed_w;
+ const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
+ if (fast_profile == nullptr) {
+ fast_profile = get_motor_profile_ptr(dev->motor.profiles, 0, session);
}
+ auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
+ *fast_profile);
- auto fast_table = sanei_genesys_create_slope_table3(dev->model->asic_type, dev->motor,
- StepType::FULL, fast_exposure,
- dev->motor.base_ydpi / 4);
-
- feedl = feed_steps - fast_table.steps_count * 2;
+ // 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;
+ }
-/* all needed slopes available. we did even decide which mode to use.
- what next?
- - transfer slopes
-SCAN:
-flags \ use_fast_fed ! 0 1
-------------------------\--------------------
- 0 ! 0,1,2 0,1,2,3
-MotorFlag::AUTO_GO_HOME ! 0,1,2,4 0,1,2,3,4
-OFF: none
-FEED: 3
-GO_HOME: 3
-HOME_FREE: 3
- - setup registers
- * slope specific registers (already done)
- * DECSEL for HOME_FREE/GO_HOME/SCAN
- * FEEDL
- * MTRREV
- * MTRPWR
- * FASTFED
- * STEPSEL
- * MTRPWM
- * FSTPSEL
- * FASTPWM
- * HOMENEG
- * BWDSTEP
- * FWDSTEP
- * Z1
- * Z2
- */
+ reg->set8(0x3d, (feedl >> 16) & 0xf);
+ reg->set8(0x3e, (feedl >> 8) & 0xff);
+ reg->set8(0x3f, feedl & 0xff);
+ reg->find_reg(0x5e).value &= ~0xe0;
- r = sanei_genesys_get_address(reg, 0x3d);
- r->value = (feedl >> 16) & 0xf;
- r = sanei_genesys_get_address(reg, 0x3e);
- r->value = (feedl >> 8) & 0xff;
- r = sanei_genesys_get_address(reg, 0x3f);
- r->value = feedl & 0xff;
- r = sanei_genesys_get_address(reg, 0x5e);
- r->value &= ~0xe0;
-
- r = sanei_genesys_get_address(reg, 0x25);
- r->value = 0;
- r = sanei_genesys_get_address(reg, 0x26);
- r->value = 0;
- r = sanei_genesys_get_address(reg, 0x27);
- r->value = 0;
-
- r = sanei_genesys_get_address(reg, 0x02);
- r->value &= ~0x01; /*LONGCURV OFF*/
- r->value &= ~0x80; /*NOT_HOME OFF*/
-
- r->value |= 0x10;
-
- if (action == MOTOR_ACTION_GO_HOME)
- r->value |= 0x06;
- else
- r->value &= ~0x06;
+ reg->set8(0x25, 0);
+ reg->set8(0x26, 0);
+ reg->set8(0x27, 0);
+
+ reg->find_reg(0x02).value &= ~0x01; /*LONGCURV OFF*/
+ reg->find_reg(0x02).value &= ~0x80; /*NOT_HOME OFF*/
+
+ reg->find_reg(0x02).value |= REG_0x02_MTRPWR;
if (use_fast_fed)
- r->value |= 0x08;
+ reg->find_reg(0x02).value |= 0x08;
else
- r->value &= ~0x08;
+ reg->find_reg(0x02).value &= ~0x08;
- if (has_flag(flags, MotorFlag::AUTO_GO_HOME)) {
- r->value |= 0x20;
+ if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
+ reg->find_reg(0x02).value |= 0x20;
} else {
- r->value &= ~0x20;
+ reg->find_reg(0x02).value &= ~0x20;
}
- r->value &= ~0x40;
+ reg->find_reg(0x02).value &= ~0x40;
- if (has_flag(flags, MotorFlag::REVERSE)) {
- r->value |= REG_0x02_MTRREV;
+ if (has_flag(flags, ScanFlag::REVERSE)) {
+ reg->find_reg(0x02).value |= REG_0x02_MTRREV;
+ } else {
+ reg->find_reg(0x02).value &= ~REG_0x02_MTRREV;
}
- gl841_send_slope_table(dev, 3, fast_table.table, 256);
+ scanner_send_slope_table(dev, sensor, 3, fast_table.table);
- r = sanei_genesys_get_address(reg, 0x67);
- r->value = 0x3f;
-
- r = sanei_genesys_get_address(reg, 0x68);
- r->value = 0x3f;
-
- r = sanei_genesys_get_address(reg, REG_STEPNO);
- r->value = 0;
-
- r = sanei_genesys_get_address(reg, REG_FASTNO);
- r->value = 0;
-
- r = sanei_genesys_get_address(reg, 0x69);
- r->value = 0;
-
- r = sanei_genesys_get_address(reg, 0x6a);
- r->value = (fast_table.steps_count >> 1) + (fast_table.steps_count & 1);
-
- r = sanei_genesys_get_address(reg, 0x5f);
- r->value = (fast_table.steps_count >> 1) + (fast_table.steps_count & 1);
+ reg->set8(0x67, 0x3f);
+ reg->set8(0x68, 0x3f);
+ reg->set8(REG_STEPNO, 1);
+ reg->set8(REG_FASTNO, 1);
+ reg->set8(0x69, 1);
+ reg->set8(0x6a, fast_table.table.size() / step_multiplier);
+ reg->set8(0x5f, 1);
}
static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* reg,
+ const ScanSession& session,
+ Genesys_Register_Set* reg, const MotorProfile& motor_profile,
unsigned int scan_exposure_time,/*pixel*/
unsigned scan_yres, // dpi, motor resolution
- StepType scan_step_type,
unsigned int scan_lines,/*lines, scan resolution*/
unsigned int scan_dummy,
// number of scan lines to add in a scan_lines line
unsigned int feed_steps,/*1/base_ydpi*/
// maybe float for half/quarter step resolution?
- MotorFlag flags)
+ ScanFlag flags)
{
DBG_HELPER_ARGS(dbg, "scan_exposure_time=%d, scan_yres=%d, scan_step_type=%d, scan_lines=%d,"
" scan_dummy=%d, feed_steps=%d, flags=%x",
- scan_exposure_time, scan_yres, static_cast<unsigned>(scan_step_type),
+ scan_exposure_time, scan_yres, static_cast<unsigned>(motor_profile.step_type),
scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
- unsigned int fast_exposure;
+
+ unsigned step_multiplier = 2;
+
int use_fast_fed = 0;
unsigned int fast_time;
unsigned int slow_time;
unsigned int feedl;
- GenesysRegister* r;
unsigned int min_restep = 0x20;
- uint32_t z1, z2;
-
- fast_exposure = gl841_exposure_time(dev, sensor,
- dev->motor.base_ydpi / 4,
- StepType::FULL,
- 0,
- 0);
-
- DBG(DBG_info, "%s : fast_exposure=%d pixels\n", __func__, fast_exposure);
-
- {
- std::vector<uint16_t> table;
- table.resize(256, 0xffff);
-
- gl841_send_slope_table(dev, 0, table, 256);
- gl841_send_slope_table(dev, 1, table, 256);
- gl841_send_slope_table(dev, 2, table, 256);
- gl841_send_slope_table(dev, 3, table, 256);
- gl841_send_slope_table(dev, 4, table, 256);
- }
-
-
- /* motor frequency table */
- gl841_write_freq(dev, scan_yres);
/*
we calculate both tables for SCAN. the fast slope step count depends on
@@ -1022,30 +654,31 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor
allowed to use.
*/
- auto slow_table = sanei_genesys_create_slope_table3(dev->model->asic_type, dev->motor,
- scan_step_type, scan_exposure_time,
- scan_yres);
+ // At least in LiDE 50, 60 the fast movement table is counted in full steps.
+ const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
+ if (fast_profile == nullptr) {
+ fast_profile = &motor_profile;
+ }
- auto back_table = sanei_genesys_create_slope_table3(dev->model->asic_type, dev->motor,
- scan_step_type, 0, scan_yres);
+ auto slow_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres,
+ scan_exposure_time, step_multiplier, motor_profile);
- if (feed_steps < (slow_table.steps_count >> static_cast<unsigned>(scan_step_type))) {
+ if (feed_steps < (slow_table.table.size() >> static_cast<unsigned>(motor_profile.step_type))) {
/*TODO: what should we do here?? go back to exposure calculation?*/
- feed_steps = slow_table.steps_count >> static_cast<unsigned>(scan_step_type);
+ feed_steps = slow_table.table.size() >> static_cast<unsigned>(motor_profile.step_type);
}
- auto fast_table = sanei_genesys_create_slope_table3(dev->model->asic_type, dev->motor,
- StepType::FULL, fast_exposure,
- dev->motor.base_ydpi / 4);
+ auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
+ *fast_profile);
- unsigned max_fast_slope_steps_count = 1;
- if (feed_steps > (slow_table.steps_count >> static_cast<unsigned>(scan_step_type)) + 2) {
+ unsigned max_fast_slope_steps_count = step_multiplier;
+ if (feed_steps > (slow_table.table.size() >> static_cast<unsigned>(motor_profile.step_type)) + 2) {
max_fast_slope_steps_count = (feed_steps -
- (slow_table.steps_count >> static_cast<unsigned>(scan_step_type))) / 2;
+ (slow_table.table.size() >> static_cast<unsigned>(motor_profile.step_type))) / 2;
}
- if (fast_table.steps_count > max_fast_slope_steps_count) {
- fast_table.slice_steps(max_fast_slope_steps_count);
+ if (fast_table.table.size() > max_fast_slope_steps_count) {
+ fast_table.slice_steps(max_fast_slope_steps_count, step_multiplier);
}
/* fast fed special cases handling */
@@ -1056,8 +689,8 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor
2-feed mode */
use_fast_fed = 0;
}
- else if (feed_steps < fast_table.steps_count * 2 +
- (slow_table.steps_count >> static_cast<unsigned>(scan_step_type)))
+ else if (feed_steps < fast_table.table.size() * 2 +
+ (slow_table.table.size() >> static_cast<unsigned>(motor_profile.step_type)))
{
use_fast_fed = 0;
DBG(DBG_info, "%s: feed too short, slow move forced.\n", __func__);
@@ -1071,113 +704,70 @@ static void gl841_init_motor_regs_scan(Genesys_Device* dev, const Genesys_Sensor
/*NOTE: fast_exposure is per base_ydpi/4*/
/*we use full steps as base unit here*/
fast_time =
- fast_exposure / 4 *
- (feed_steps - fast_table.steps_count*2 -
- (slow_table.steps_count >> static_cast<unsigned>(scan_step_type)))
- + fast_table.pixeltime_sum*2 + slow_table.pixeltime_sum;
+ (fast_table.table.back() << static_cast<unsigned>(fast_profile->step_type)) / 4 *
+ (feed_steps - fast_table.table.size()*2 -
+ (slow_table.table.size() >> static_cast<unsigned>(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.steps_count >> static_cast<unsigned>(scan_step_type)))
- + slow_table.pixeltime_sum;
+ (feed_steps - (slow_table.table.size() >> static_cast<unsigned>(motor_profile.step_type)))
+ + slow_table.pixeltime_sum();
- DBG(DBG_info, "%s: Time for slow move: %d\n", __func__, slow_time);
- DBG(DBG_info, "%s: Time for fast move: %d\n", __func__, fast_time);
+ use_fast_fed = fast_time < slow_time;
+ }
- 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.steps_count * 2 -
- (slow_table.steps_count >> static_cast<unsigned>(scan_step_type));
- } else if ((feed_steps << static_cast<unsigned>(scan_step_type)) < slow_table.steps_count) {
+ feedl = feed_steps - fast_table.table.size() * 2 -
+ (slow_table.table.size() >> static_cast<unsigned>(motor_profile.step_type));
+ } else if ((feed_steps << static_cast<unsigned>(motor_profile.step_type)) < slow_table.table.size()) {
feedl = 0;
} else {
- feedl = (feed_steps << static_cast<unsigned>(scan_step_type)) - slow_table.steps_count;
+ feedl = (feed_steps << static_cast<unsigned>(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");
-/* all needed slopes available. we did even decide which mode to use.
- what next?
- - transfer slopes
-SCAN:
-flags \ use_fast_fed ! 0 1
-------------------------\--------------------
- 0 ! 0,1,2 0,1,2,3
-MotorFlag::AUTO_GO_HOME ! 0,1,2,4 0,1,2,3,4
-OFF: none
-FEED: 3
-GO_HOME: 3
-HOME_FREE: 3
- - setup registers
- * slope specific registers (already done)
- * DECSEL for HOME_FREE/GO_HOME/SCAN
- * FEEDL
- * MTRREV
- * MTRPWR
- * FASTFED
- * STEPSEL
- * MTRPWM
- * FSTPSEL
- * FASTPWM
- * HOMENEG
- * BWDSTEP
- * FWDSTEP
- * Z1
- * Z2
- */
-
- r = sanei_genesys_get_address (reg, 0x3d);
- r->value = (feedl >> 16) & 0xf;
- r = sanei_genesys_get_address (reg, 0x3e);
- r->value = (feedl >> 8) & 0xff;
- r = sanei_genesys_get_address (reg, 0x3f);
- r->value = feedl & 0xff;
- r = sanei_genesys_get_address (reg, 0x5e);
- r->value &= ~0xe0;
-
- r = sanei_genesys_get_address (reg, 0x25);
- r->value = (scan_lines >> 16) & 0xf;
- r = sanei_genesys_get_address (reg, 0x26);
- r->value = (scan_lines >> 8) & 0xff;
- r = sanei_genesys_get_address (reg, 0x27);
- r->value = scan_lines & 0xff;
-
- r = sanei_genesys_get_address (reg, 0x02);
- r->value &= ~0x01; /*LONGCURV OFF*/
- r->value &= ~0x80; /*NOT_HOME OFF*/
- r->value |= 0x10;
-
- r->value &= ~0x06;
+ reg->set8(0x3d, (feedl >> 16) & 0xf);
+ reg->set8(0x3e, (feedl >> 8) & 0xff);
+ reg->set8(0x3f, feedl & 0xff);
+ reg->find_reg(0x5e).value &= ~0xe0;
+ reg->set8(0x25, (scan_lines >> 16) & 0xf);
+ reg->set8(0x26, (scan_lines >> 8) & 0xff);
+ reg->set8(0x27, scan_lines & 0xff);
+ reg->find_reg(0x02).value = REG_0x02_MTRPWR;
+
+ if (has_flag(flags, ScanFlag::REVERSE)) {
+ reg->find_reg(0x02).value |= REG_0x02_MTRREV;
+ } else {
+ reg->find_reg(0x02).value &= ~REG_0x02_MTRREV;
+ }
if (use_fast_fed)
- r->value |= 0x08;
+ reg->find_reg(0x02).value |= 0x08;
else
- r->value &= ~0x08;
+ reg->find_reg(0x02).value &= ~0x08;
- if (has_flag(flags, MotorFlag::AUTO_GO_HOME))
- r->value |= 0x20;
+ if (has_flag(flags, ScanFlag::AUTO_GO_HOME))
+ reg->find_reg(0x02).value |= 0x20;
else
- r->value &= ~0x20;
+ reg->find_reg(0x02).value &= ~0x20;
- if (has_flag(flags, MotorFlag::DISABLE_BUFFER_FULL_MOVE)) {
- r->value |= 0x40;
+ if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE)) {
+ reg->find_reg(0x02).value |= 0x40;
} else {
- r->value &= ~0x40;
+ reg->find_reg(0x02).value &= ~0x40;
}
- gl841_send_slope_table(dev, 0, slow_table.table, 256);
-
- gl841_send_slope_table(dev, 1, back_table.table, 256);
+ scanner_send_slope_table(dev, sensor, 0, slow_table.table);
+ scanner_send_slope_table(dev, sensor, 1, slow_table.table);
+ scanner_send_slope_table(dev, sensor, 2, slow_table.table);
+ scanner_send_slope_table(dev, sensor, 3, fast_table.table);
+ scanner_send_slope_table(dev, sensor, 4, fast_table.table);
- gl841_send_slope_table(dev, 2, slow_table.table, 256);
-
- if (use_fast_fed) {
- gl841_send_slope_table(dev, 3, fast_table.table, 256);
- }
-
- if (has_flag(flags, MotorFlag::AUTO_GO_HOME)) {
- gl841_send_slope_table(dev, 4, fast_table.table, 256);
- }
+ gl841_write_freq(dev, scan_yres);
/* now reg 0x21 and 0x24 are available, we can calculate reg 0x22 and 0x23,
reg 0x60-0x62 and reg 0x63-0x65
@@ -1185,19 +775,18 @@ HOME_FREE: 3
2*STEPNO+FWDSTEP=2*FASTNO+BWDSTEP
*/
/* steps of table 0*/
- if (min_restep < slow_table.steps_count * 2 + 2) {
- min_restep = slow_table.steps_count * 2 + 2;
+ if (min_restep < slow_table.table.size() * 2 + 2) {
+ min_restep = slow_table.table.size() * 2 + 2;
}
/* steps of table 1*/
- if (min_restep < back_table.steps_count * 2 + 2) {
- min_restep = back_table.steps_count * 2 + 2;
+ if (min_restep < slow_table.table.size() * 2 + 2) {
+ min_restep = slow_table.table.size() * 2 + 2;
}
/* steps of table 0*/
- r = sanei_genesys_get_address(reg, REG_FWDSTEP);
- r->value = min_restep - slow_table.steps_count*2;
+ reg->set8(REG_FWDSTEP, min_restep - slow_table.table.size()*2);
+
/* steps of table 1*/
- r = sanei_genesys_get_address(reg, REG_BWDSTEP);
- r->value = min_restep - back_table.steps_count*2;
+ reg->set8(REG_BWDSTEP, min_restep - slow_table.table.size()*2);
/*
for z1/z2:
@@ -1214,64 +803,17 @@ HOME_FREE: 3
z1 = (slope_0_time-1) % exposure_time;
z2 = (slope_0_time-1) % exposure_time;
*/
- z1 = z2 = 0;
-
- DBG(DBG_info, "%s: z1 = %d\n", __func__, z1);
- DBG(DBG_info, "%s: z2 = %d\n", __func__, z2);
- r = sanei_genesys_get_address (reg, 0x60);
- r->value = ((z1 >> 16) & 0xff);
- r = sanei_genesys_get_address (reg, 0x61);
- r->value = ((z1 >> 8) & 0xff);
- r = sanei_genesys_get_address (reg, 0x62);
- r->value = (z1 & 0xff);
- r = sanei_genesys_get_address (reg, 0x63);
- r->value = ((z2 >> 16) & 0xff);
- r = sanei_genesys_get_address (reg, 0x64);
- r->value = ((z2 >> 8) & 0xff);
- r = sanei_genesys_get_address (reg, 0x65);
- r->value = (z2 & 0xff);
-
- r = sanei_genesys_get_address(reg, REG_0x1E);
- r->value &= REG_0x1E_WDTIME;
- r->value |= scan_dummy;
-
- r = sanei_genesys_get_address (reg, 0x67);
- r->value = 0x3f | (static_cast<unsigned>(scan_step_type) << 6);
-
- r = sanei_genesys_get_address (reg, 0x68);
- r->value = 0x3f;
-
- r = sanei_genesys_get_address(reg, REG_STEPNO);
- r->value = (slow_table.steps_count >> 1) + (slow_table.steps_count & 1);
-
- r = sanei_genesys_get_address(reg, REG_FASTNO);
- r->value = (back_table.steps_count >> 1) + (back_table.steps_count & 1);
-
- r = sanei_genesys_get_address (reg, 0x69);
- r->value = (slow_table.steps_count >> 1) + (slow_table.steps_count & 1);
-
- r = sanei_genesys_get_address (reg, 0x6a);
- r->value = (fast_table.steps_count >> 1) + (fast_table.steps_count & 1);
-
- r = sanei_genesys_get_address (reg, 0x5f);
- r->value = (fast_table.steps_count >> 1) + (fast_table.steps_count & 1);
-}
-
-static int
-gl841_get_dpihw(Genesys_Device * dev)
-{
- GenesysRegister* r;
- r = sanei_genesys_get_address(&dev->reg, 0x05);
- if ((r->value & REG_0x05_DPIHW) == REG_0x05_DPIHW_600) {
- return 600;
- }
- if ((r->value & REG_0x05_DPIHW) == REG_0x05_DPIHW_1200) {
- return 1200;
- }
- if ((r->value & REG_0x05_DPIHW) == REG_0x05_DPIHW_2400) {
- return 2400;
- }
- return 0;
+ reg->set24(REG_0x60, 0);
+ reg->set24(REG_0x63, 0);
+ reg->find_reg(REG_0x1E).value &= REG_0x1E_WDTIME;
+ reg->find_reg(REG_0x1E).value |= scan_dummy;
+ reg->set8(0x67, 0x3f | (static_cast<unsigned>(motor_profile.step_type) << 6));
+ reg->set8(0x68, 0x3f | (static_cast<unsigned>(fast_profile->step_type) << 6));
+ reg->set8(REG_STEPNO, slow_table.table.size() / step_multiplier);
+ reg->set8(REG_FASTNO, slow_table.table.size() / step_multiplier);
+ reg->set8(0x69, slow_table.table.size() / step_multiplier);
+ reg->set8(0x6a, fast_table.table.size() / step_multiplier);
+ reg->set8(0x5f, fast_table.table.size() / step_multiplier);
}
static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
@@ -1279,108 +821,99 @@ 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);
- GenesysRegister* r;
uint16_t expavg, expr, expb, expg;
dev->cmd_set->set_fe(dev, sensor, AFE_SET);
/* gpio part.*/
if (dev->model->gpio_id == GpioId::CANON_LIDE_35) {
- r = sanei_genesys_get_address(reg, REG_0x6C);
- if (session.ccd_size_divisor > 1) {
- r->value &= ~0x80;
+ if (session.params.xres <= 600) {
+ reg->find_reg(REG_0x6C).value &= ~0x80;
} else {
- r->value |= 0x80;
+ reg->find_reg(REG_0x6C).value |= 0x80;
}
}
if (dev->model->gpio_id == GpioId::CANON_LIDE_80) {
- r = sanei_genesys_get_address(reg, REG_0x6C);
- if (session.ccd_size_divisor > 1) {
- r->value &= ~0x40;
- r->value |= 0x20;
+ if (session.params.xres <= 600) {
+ reg->find_reg(REG_0x6C).value &= ~0x40;
+ reg->find_reg(REG_0x6C).value |= 0x20;
} else {
- r->value &= ~0x20;
- r->value |= 0x40;
+ reg->find_reg(REG_0x6C).value &= ~0x20;
+ reg->find_reg(REG_0x6C).value |= 0x40;
}
- }
+ }
/* enable shading */
- r = sanei_genesys_get_address (reg, 0x01);
- r->value |= REG_0x01_SCAN;
+ reg->find_reg(0x01).value |= REG_0x01_SCAN;
if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
- (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) {
- r->value &= ~REG_0x01_DVDSET;
+ has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION)) {
+ reg->find_reg(0x01).value &= ~REG_0x01_DVDSET;
} else {
- r->value |= REG_0x01_DVDSET;
+ reg->find_reg(0x01).value |= REG_0x01_DVDSET;
}
/* average looks better than deletion, and we are already set up to
use one of the average enabled resolutions
*/
- r = sanei_genesys_get_address (reg, 0x03);
- r->value |= REG_0x03_AVEENB;
+ reg->find_reg(0x03).value |= REG_0x03_AVEENB;
sanei_genesys_set_lamp_power(dev, sensor, *reg,
!has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
/* BW threshold */
- r = sanei_genesys_get_address (reg, 0x2e);
- r->value = dev->settings.threshold;
- r = sanei_genesys_get_address (reg, 0x2f);
- r->value = dev->settings.threshold;
+ reg->set8(0x2e, 0x7f);
+ reg->set8(0x2f, 0x7f);
/* monochrome / color scan */
- r = sanei_genesys_get_address (reg, 0x04);
switch (session.params.depth) {
case 8:
- r->value &= ~(REG_0x04_LINEART | REG_0x04_BITSET);
+ reg->find_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(0x04).value &= ~REG_0x04_LINEART;
+ reg->find_reg(0x04).value |= REG_0x04_BITSET;
break;
}
/* AFEMOD should depend on FESET, and we should set these
* bits separately */
- r->value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
+ reg->find_reg(0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
if (has_flag(session.params.flags, ScanFlag::ENABLE_LEDADD)) {
- r->value |= 0x10; /* no filter */
+ reg->find_reg(0x04).value |= 0x10; /* no filter */
}
else if (session.params.channels == 1)
{
switch (session.params.color_filter)
{
case ColorFilter::RED:
- r->value |= 0x14;
+ reg->find_reg(0x04).value |= 0x14;
break;
case ColorFilter::GREEN:
- r->value |= 0x18;
+ reg->find_reg(0x04).value |= 0x18;
break;
case ColorFilter::BLUE:
- r->value |= 0x1c;
+ reg->find_reg(0x04).value |= 0x1c;
break;
default:
- r->value |= 0x10;
+ reg->find_reg(0x04).value |= 0x10;
break;
}
}
else
{
if (dev->model->sensor_id == SensorId::CCD_PLUSTEK_OPTICPRO_3600) {
- r->value |= 0x22; /* slow color pixel by pixel */
+ reg->find_reg(0x04).value |= 0x22; /* slow color pixel by pixel */
}
else
{
- r->value |= 0x10; /* color pixel by pixel */
+ reg->find_reg(0x04).value |= 0x10; /* color pixel by pixel */
}
}
/* CIS scanners can do true gray by setting LEDADD */
- r = sanei_genesys_get_address (reg, 0x87);
- r->value &= ~REG_0x87_LEDADD;
+ reg->find_reg(0x87).value &= ~REG_0x87_LEDADD;
if (has_flag(session.params.flags, ScanFlag::ENABLE_LEDADD)) {
- r->value |= REG_0x87_LEDADD;
+ reg->find_reg(0x87).value |= REG_0x87_LEDADD;
expr = reg->get16(REG_EXPR);
expg = reg->get16(REG_EXPG);
expb = reg->get16(REG_EXPB);
@@ -1405,21 +938,14 @@ static void gl841_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
}
/* sensor parameters */
- sanei_gl841_setup_sensor(dev, sensor, &dev->reg, 1, session.ccd_size_divisor);
-
- r = sanei_genesys_get_address (reg, 0x29);
- r->value = 255; /*<<<"magic" number, only suitable for cis*/
-
- reg->set16(REG_DPISET, gl841_get_dpihw(dev) * session.output_resolution / session.optical_resolution);
+ scanner_setup_sensor(*dev, sensor, dev->reg);
+ reg->set8(0x29, 255); /*<<<"magic" number, only suitable for cis*/
+ reg->set16(REG_DPISET, sensor.register_dpiset);
reg->set16(REG_STRPIXEL, session.pixel_startx);
reg->set16(REG_ENDPIXEL, session.pixel_endx);
-
reg->set24(REG_MAXWD, session.output_line_bytes);
-
reg->set16(REG_LPERIOD, exposure_time);
-
- r = sanei_genesys_get_address (reg, 0x34);
- r->value = sensor.dummy_pixel;
+ reg->set8(0x34, sensor.dummy_pixel);
}
static int
@@ -1446,56 +972,17 @@ gl841_get_led_exposure(Genesys_Device * dev, const Genesys_Sensor& sensor)
/** @brief compute exposure time
* Compute exposure time for the device and the given scan resolution
*/
-static int
-gl841_exposure_time(Genesys_Device *dev, const Genesys_Sensor& sensor,
- float slope_dpi,
- StepType scan_step_type,
- int start,
- int used_pixels)
+static int gl841_exposure_time(Genesys_Device *dev, const Genesys_Sensor& sensor,
+ const MotorProfile& profile, float slope_dpi,
+ int start,
+ int used_pixels)
{
-int exposure_time = 0;
int led_exposure;
led_exposure=gl841_get_led_exposure(dev, sensor);
- exposure_time = sanei_genesys_exposure_time2(
- dev,
- slope_dpi,
- scan_step_type,
- start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/
- led_exposure);
-
- return exposure_time;
-}
-
-/**@brief compute scan_step_type
- * Try to do at least 4 steps per line. if that is impossible we will have to
- * live with that.
- * @param dev device
- * @param yres motor resolution
- */
-static StepType gl841_scan_step_type(Genesys_Device *dev, int yres)
-{
- StepType type = StepType::FULL;
-
- /* TODO : check if there is a bug around the use of max_step_type */
- /* should be <=1, need to chek all devices entry in genesys_devices */
- if (yres * 4 < dev->motor.base_ydpi || dev->motor.max_step_type() == StepType::FULL) {
- type = StepType::FULL;
- } else if (yres * 4 < dev->motor.base_ydpi * 2 ||
- dev->motor.max_step_type() <= StepType::HALF)
- {
- type = StepType::HALF;
- } else {
- type = StepType::QUARTER;
- }
-
- /* this motor behaves differently */
- if (dev->model->motor_id==MotorId::CANON_LIDE_80) {
- // driven by 'frequency' tables ?
- type = StepType::FULL;
- }
-
- return type;
+ 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);
}
void CommandSetGl841::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
@@ -1511,34 +998,6 @@ void CommandSetGl841::init_regs_for_scan_session(Genesys_Device* dev, const Gene
int slope_dpi = 0;
int dummy = 0;
-/*
-results:
-
-for scanner:
-start
-end
-dpiset
-exposure_time
-dummy
-z1
-z2
-
-for ordered_read:
- dev->words_per_line
- dev->read_factor
- dev->requested_buffer_size
- dev->read_buffer_size
- dev->read_pos
- dev->read_bytes_in_buffer
- dev->read_bytes_left
- dev->max_shift
- dev->stagger
-
-independent of our calculated values:
- dev->total_bytes_read
- dev->bytes_to_read
- */
-
/* dummy */
/* dummy lines: may not be usefull, for instance 250 dpi works with 0 or 1
dummy line. Maybe the dummy line adds correctness since the motor runs
@@ -1577,48 +1036,34 @@ dummy \ scanned lines
slope_dpi = slope_dpi * (1 + dummy);
- StepType scan_step_type = gl841_scan_step_type(dev, session.params.yres);
- exposure_time = gl841_exposure_time(dev, sensor,
- slope_dpi,
- scan_step_type,
- session.pixel_startx,
- session.optical_pixels);
- DBG(DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time);
+ const auto& motor_profile = get_motor_profile(dev->motor.profiles, 0, session);
+
+ exposure_time = gl841_exposure_time(dev, sensor, motor_profile, slope_dpi,
+ session.pixel_startx, session.optical_pixels);
gl841_init_optical_regs_scan(dev, sensor, reg, exposure_time, session);
move = session.params.starty;
- DBG(DBG_info, "%s: move=%d steps\n", __func__, move);
/* subtract current head position */
move -= (dev->head_pos(ScanHeadId::PRIMARY) * session.params.yres) / dev->motor.base_ydpi;
- DBG(DBG_info, "%s: move=%d steps\n", __func__, move);
if (move < 0)
move = 0;
/* round it */
/* the move is not affected by dummy -- pierre */
-/* move = ((move + dummy) / (dummy + 1)) * (dummy + 1);
- DBG(DBG_info, "%s: move=%d steps\n", __func__, move);*/
+/* move = ((move + dummy) / (dummy + 1)) * (dummy + 1);*/
if (has_flag(session.params.flags, ScanFlag::SINGLE_LINE)) {
- gl841_init_motor_regs_off(reg, dev->model->is_cis ? session.output_line_count * session.params.channels
- : session.output_line_count);
+ gl841_init_motor_regs_off(reg, session.optical_line_count);
} else {
- auto motor_flag = has_flag(session.params.flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) ?
- MotorFlag::DISABLE_BUFFER_FULL_MOVE : MotorFlag::NONE;
-
- gl841_init_motor_regs_scan(dev, sensor, reg, exposure_time, slope_dpi, scan_step_type,
- dev->model->is_cis ? session.output_line_count * session.params.channels
- : session.output_line_count,
- dummy, move, motor_flag);
+ gl841_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure_time,
+ slope_dpi, session.optical_line_count, dummy, move,
+ session.params.flags);
}
- dev->read_buffer.clear();
- dev->read_buffer.alloc(session.buffer_size_read);
-
- build_image_pipeline(dev, session);
+ setup_image_pipeline(*dev, session);
dev->read_active = true;
@@ -1634,32 +1079,62 @@ ScanSession CommandSetGl841::calculate_scan_session(const Genesys_Device* dev,
const Genesys_Sensor& sensor,
const Genesys_Settings& settings) const
{
- int start;
-
- DBG(DBG_info, "%s ", __func__);
+ DBG_HELPER(dbg);
debug_dump(DBG_info, settings);
-/* start */
- start = static_cast<int>(dev->model->x_offset);
- start += static_cast<int>(settings.tl_x);
+ /* steps to move to reach scanning area:
+ - first we move to physical start of scanning
+ either by a fixed steps amount from the black strip
+ or by a fixed amount from parking position,
+ minus the steps done during shading calibration
+ - then we move by the needed offset whitin physical
+ scanning area
+
+ assumption: steps are expressed at maximum motor resolution
+
+ we need:
+ float y_offset;
+ float y_size;
+ float y_offset_calib;
+ mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH
+ */
+ float move = dev->model->y_offset;
+ move += dev->settings.tl_y;
- start = static_cast<int>((start * sensor.optical_res) / MM_PER_INCH);
+ int move_dpi = dev->motor.base_ydpi;
+ move = static_cast<float>((move * move_dpi) / 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.pixels = settings.pixels;
- session.params.requested_pixels = settings.requested_pixels;
- session.params.lines = settings.lines;
- session.params.depth = settings.depth;
- session.params.channels = settings.get_channels();
- session.params.scan_method = settings.scan_method;
- session.params.scan_mode = settings.scan_mode;
- session.params.color_filter = settings.color_filter;
- session.params.flags = ScanFlag::NONE;
+ float start = dev->model->x_offset;
+ start += dev->settings.tl_x;
+ start = static_cast<float>((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 && dev->settings.true_gray &&
+ 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;
+ 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 = flags;
compute_session(dev, session, sensor);
return session;
@@ -1709,7 +1184,7 @@ void CommandSetGl841::save_power(Genesys_Device* dev, bool enable) const
uint8_t val = dev->interface->read_register(REG_0x6B);
dev->interface->write_register(REG_0x6B, val & ~REG_0x6B_GPO17);
dev->reg.find_reg(0x6b).value &= ~REG_0x6B_GPO17;
- dev->calib_reg.find_reg(0x6b).value &= ~REG_0x6B_GPO17;
+ dev->initial_regs.find_reg(0x6b).value &= ~REG_0x6B_GPO17;
}
set_fe(dev, sensor, AFE_POWER_SAVE);
@@ -1741,13 +1216,13 @@ void CommandSetGl841::save_power(Genesys_Device* dev, bool enable) const
val = dev->interface->read_register(REG_0x6B);
dev->interface->write_register(REG_0x6B, val | REG_0x6B_GPO17);
dev->reg.find_reg(0x6b).value |= REG_0x6B_GPO17;
- dev->calib_reg.find_reg(0x6b).value |= REG_0x6B_GPO17;
+ dev->initial_regs.find_reg(0x6b).value |= REG_0x6B_GPO17;
/*enable GPO18*/
val = dev->interface->read_register(REG_0x6B);
dev->interface->write_register(REG_0x6B, val | REG_0x6B_GPO18);
dev->reg.find_reg(0x6b).value |= REG_0x6B_GPO18;
- dev->calib_reg.find_reg(0x6b).value |= REG_0x6B_GPO18;
+ dev->initial_regs.find_reg(0x6b).value |= REG_0x6B_GPO18;
}
if (dev->model->gpio_id == GpioId::DP665
@@ -1756,7 +1231,7 @@ void CommandSetGl841::save_power(Genesys_Device* dev, bool enable) const
uint8_t val = dev->interface->read_register(REG_0x6B);
dev->interface->write_register(REG_0x6B, val | REG_0x6B_GPO17);
dev->reg.find_reg(0x6b).value |= REG_0x6B_GPO17;
- dev->calib_reg.find_reg(0x6b).value |= REG_0x6B_GPO17;
+ dev->initial_regs.find_reg(0x6b).value |= REG_0x6B_GPO17;
}
}
@@ -1826,47 +1301,6 @@ void CommandSetGl841::set_powersaving(Genesys_Device* dev, int delay /* in minut
dev->interface->write_registers(local_reg);
}
-static void gl841_stop_action(Genesys_Device* dev)
-{
- DBG_HELPER(dbg);
- Genesys_Register_Set local_reg;
- unsigned int loop;
-
- scanner_read_print_status(*dev);
-
- if (scanner_is_motor_stopped(*dev)) {
- DBG(DBG_info, "%s: already stopped\n", __func__);
- return;
- }
-
- local_reg = dev->reg;
-
- regs_set_optical_off(dev->model->asic_type, local_reg);
-
- gl841_init_motor_regs_off(&local_reg,0);
- dev->interface->write_registers(local_reg);
-
- if (is_testing_mode()) {
- return;
- }
-
- /* looks like writing the right registers to zero is enough to get the chip
- out of scan mode into command mode, actually triggering(writing to
- register 0x0f) seems to be unnecessary */
-
- loop = 10;
- while (loop > 0) {
- if (scanner_is_motor_stopped(*dev)) {
- return;
- }
-
- dev->interface->sleep_ms(100);
- loop--;
- }
-
- throw SaneException(SANE_STATUS_IO_ERROR, "could not stop motor");
-}
-
static bool gl841_get_paper_sensor(Genesys_Device* dev)
{
DBG_HELPER(dbg);
@@ -1886,7 +1320,6 @@ void CommandSetGl841::eject_document(Genesys_Device* dev) const
if (!dev->model->is_sheetfed) {
DBG(DBG_proc, "%s: there is no \"eject sheet\"-concept for non sheet fed\n", __func__);
- DBG(DBG_proc, "%s: finished\n", __func__);
return;
}
@@ -1895,22 +1328,21 @@ void CommandSetGl841::eject_document(Genesys_Device* dev) const
// FIXME: unused result
scanner_read_status(*dev);
-
- gl841_stop_action(dev);
+ scanner_stop_action(*dev);
local_reg = dev->reg;
regs_set_optical_off(dev->model->asic_type, local_reg);
const auto& sensor = sanei_genesys_find_sensor_any(dev);
- gl841_init_motor_regs(dev, sensor, &local_reg, 65536, MOTOR_ACTION_FEED, MotorFlag::NONE);
+ gl841_init_motor_regs_feed(dev, sensor, &local_reg, 65536, ScanFlag::NONE);
dev->interface->write_registers(local_reg);
try {
scanner_start_action(*dev, true);
} catch (...) {
- catch_all_exceptions(__func__, [&]() { gl841_stop_action(dev); });
+ catch_all_exceptions(__func__, [&]() { scanner_stop_action(*dev); });
// restore original registers
catch_all_exceptions(__func__, [&]()
{
@@ -1921,7 +1353,7 @@ void CommandSetGl841::eject_document(Genesys_Device* dev) const
if (is_testing_mode()) {
dev->interface->test_checkpoint("eject_document");
- gl841_stop_action(dev);
+ scanner_stop_action(*dev);
return;
}
@@ -1936,10 +1368,9 @@ void CommandSetGl841::eject_document(Genesys_Device* dev) const
{
if (!gl841_get_paper_sensor(dev)) {
- DBG(DBG_info, "%s: reached home position\n", __func__);
- DBG(DBG_proc, "%s: finished\n", __func__);
- break;
- }
+ DBG(DBG_info, "%s: reached home position\n", __func__);
+ break;
+ }
dev->interface->sleep_ms(100);
--loop;
}
@@ -1948,16 +1379,15 @@ void CommandSetGl841::eject_document(Genesys_Device* dev) const
{
// when we come here then the scanner needed too much time for this, so we better stop
// the motor
- catch_all_exceptions(__func__, [&](){ gl841_stop_action(dev); });
+ catch_all_exceptions(__func__, [&](){ scanner_stop_action(*dev); });
throw SaneException(SANE_STATUS_IO_ERROR,
"timeout while waiting for scanhead to go home");
}
}
- feed_mm = static_cast<float>(dev->model->eject_feed);
- if (dev->document)
- {
- feed_mm += static_cast<float>(dev->model->post_scan);
+ feed_mm = dev->model->eject_feed;
+ if (dev->document) {
+ feed_mm += dev->model->post_scan;
}
sanei_genesys_read_feed_steps(dev, &init_steps);
@@ -1981,11 +1411,22 @@ void CommandSetGl841::eject_document(Genesys_Device* dev) const
++loop;
}
- gl841_stop_action(dev);
+ scanner_stop_action(*dev);
dev->document = false;
}
+void CommandSetGl841::update_home_sensor_gpio(Genesys_Device& dev) const
+{
+ if (dev.model->gpio_id == GpioId::CANON_LIDE_35) {
+ dev.interface->read_register(REG_0x6C);
+ dev.interface->write_register(REG_0x6C, dev.gpo.regs.get_value(0x6c));
+ }
+ if (dev.model->gpio_id == GpioId::CANON_LIDE_80) {
+ dev.interface->read_register(REG_0x6B);
+ dev.interface->write_register(REG_0x6B, REG_0x6B_GPO18 | REG_0x6B_GPO17);
+ }
+}
void CommandSetGl841::load_document(Genesys_Device* dev) const
{
@@ -2064,8 +1505,6 @@ void CommandSetGl841::detect_document_end(Genesys_Device* dev) const
auto skip_lines = scan_end_lines - output_lines;
if (remaining_lines > skip_lines) {
- DBG(DBG_io, "%s: skip_lines=%zu\n", __func__, skip_lines);
-
remaining_lines -= skip_lines;
dev->get_pipeline_source().set_remaining_bytes(remaining_lines *
dev->session.output_line_bytes_raw);
@@ -2092,6 +1531,21 @@ void CommandSetGl841::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
dev->interface->write_register(REG_0x6B, val);
}
+ if (dev->model->model_id == ModelId::CANON_LIDE_50 ||
+ dev->model->model_id == ModelId::CANON_LIDE_60)
+ {
+ if (dev->session.params.yres >= 1200) {
+ dev->interface->write_register(REG_0x6C, 0x82);
+ } else {
+ dev->interface->write_register(REG_0x6C, 0x02);
+ }
+ if (dev->session.params.yres >= 600) {
+ dev->interface->write_register(REG_0x6B, 0x01);
+ } else {
+ dev->interface->write_register(REG_0x6B, 0x03);
+ }
+ }
+
if (dev->model->sensor_id != SensorId::CCD_PLUSTEK_OPTICPRO_3600) {
local_reg.init_reg(0x03, reg->get8(0x03) | REG_0x03_LAMPPWR);
} else {
@@ -2123,439 +1577,53 @@ void CommandSetGl841::end_scan(Genesys_Device* dev, Genesys_Register_Set __sane_
DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
if (!dev->model->is_sheetfed) {
- gl841_stop_action(dev);
+ scanner_stop_action(*dev);
}
}
-// Moves the slider to steps
-static void gl841_feed(Genesys_Device* dev, int steps)
-{
- DBG_HELPER_ARGS(dbg, "steps = %d", steps);
- Genesys_Register_Set local_reg;
- int loop;
-
- gl841_stop_action(dev);
-
- // FIXME: we should pick sensor according to the resolution scanner is currently operating on
- const auto& sensor = sanei_genesys_find_sensor_any(dev);
-
- local_reg = dev->reg;
-
- regs_set_optical_off(dev->model->asic_type, local_reg);
-
- gl841_init_motor_regs(dev, sensor, &local_reg, steps, MOTOR_ACTION_FEED, MotorFlag::NONE);
-
- dev->interface->write_registers(local_reg);
-
- try {
- scanner_start_action(*dev, true);
- } catch (...) {
- catch_all_exceptions(__func__, [&]() { gl841_stop_action (dev); });
- // restore original registers
- catch_all_exceptions(__func__, [&]()
- {
- dev->interface->write_registers(dev->reg);
- });
- throw;
- }
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("feed");
- dev->advance_head_pos_by_steps(ScanHeadId::PRIMARY, Direction::FORWARD, steps);
- gl841_stop_action(dev);
- return;
- }
-
- loop = 0;
- while (loop < 300) /* do not wait longer then 30 seconds */
- {
- auto status = scanner_read_status(*dev);
-
- if (!status.is_motor_enabled) {
- DBG(DBG_proc, "%s: finished\n", __func__);
- dev->advance_head_pos_by_steps(ScanHeadId::PRIMARY, Direction::FORWARD, steps);
- return;
- }
- dev->interface->sleep_ms(100);
- ++loop;
- }
-
- /* when we come here then the scanner needed too much time for this, so we better stop the motor */
- gl841_stop_action (dev);
-
- dev->set_head_pos_unknown();
-
- throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");
-}
-
// Moves the slider to the home (top) position slowly
void CommandSetGl841::move_back_home(Genesys_Device* dev, bool wait_until_home) const
{
- DBG_HELPER_ARGS(dbg, "wait_until_home = %d", wait_until_home);
- Genesys_Register_Set local_reg;
- int loop = 0;
-
- if (dev->model->is_sheetfed) {
- DBG(DBG_proc, "%s: there is no \"home\"-concept for sheet fed\n", __func__);
- DBG(DBG_proc, "%s: finished\n", __func__);
- return;
- }
-
- // reset gpio pin
- uint8_t val;
- if (dev->model->gpio_id == GpioId::CANON_LIDE_35) {
- val = dev->interface->read_register(REG_0x6C);
- val = dev->gpo.regs.get_value(0x6c);
- dev->interface->write_register(REG_0x6C, val);
- }
- if (dev->model->gpio_id == GpioId::CANON_LIDE_80) {
- val = dev->interface->read_register(REG_0x6B);
- val = REG_0x6B_GPO18 | REG_0x6B_GPO17;
- dev->interface->write_register(REG_0x6B, val);
- }
- dev->cmd_set->save_power(dev, false);
-
- // first read gives HOME_SENSOR true
- auto status = scanner_read_reliable_status(*dev);
-
-
- if (status.is_at_home) {
- DBG(DBG_info, "%s: already at home, completed\n", __func__);
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
- return;
- }
-
- scanner_stop_action_no_move(*dev, dev->reg);
-
- /* if motor is on, stop current action */
- if (status.is_motor_enabled) {
- gl841_stop_action(dev);
- }
-
- local_reg = dev->reg;
-
- const auto& sensor = sanei_genesys_find_sensor_any(dev);
-
- gl841_init_motor_regs(dev, sensor, &local_reg, 65536, MOTOR_ACTION_GO_HOME, MotorFlag::REVERSE);
-
- // set up for no scan
- regs_set_optical_off(dev->model->asic_type, local_reg);
-
- dev->interface->write_registers(local_reg);
-
- try {
- scanner_start_action(*dev, true);
- } catch (...) {
- catch_all_exceptions(__func__, [&]() { gl841_stop_action(dev); });
- // restore original registers
- catch_all_exceptions(__func__, [&]()
- {
- dev->interface->write_registers(dev->reg);
- });
- throw;
- }
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("move_back_home");
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
- return;
- }
-
- if (wait_until_home)
- {
- while (loop < 300) /* do not wait longer then 30 seconds */
- {
- auto status = scanner_read_status(*dev);
- if (status.is_at_home) {
- DBG(DBG_info, "%s: reached home position\n", __func__);
- DBG(DBG_proc, "%s: finished\n", __func__);
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
- return;
- }
- dev->interface->sleep_ms(100);
- ++loop;
- }
-
- // when we come here then the scanner needed too much time for this, so we better stop
- // the motor
- catch_all_exceptions(__func__, [&](){ gl841_stop_action(dev); });
- dev->set_head_pos_unknown();
- throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");
- }
-
- DBG(DBG_info, "%s: scanhead is still moving\n", __func__);
-}
-
-// Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi
-// from very top of scanner
-void CommandSetGl841::search_start_position(Genesys_Device* dev) const
-{
- DBG_HELPER(dbg);
- int size;
- Genesys_Register_Set local_reg;
-
- int pixels = 600;
- int dpi = 300;
-
- local_reg = dev->reg;
-
- /* 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, dev->model->default_method);
-
- 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);
-
- dev->cmd_set->begin_scan(dev, sensor, &local_reg, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("search_start_position");
- dev->cmd_set->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("gl841_search_position.pnm", data.data(), 8, 1, pixels,
- dev->model->search_lines);
- }
-
- dev->cmd_set->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);
- }
+ scanner_move_back_home(*dev, wait_until_home);
}
-// sets up register for coarse gain calibration
-// todo: check it for scanners using it
-void CommandSetGl841::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::IGNORE_LINE_DISTANCE;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &regs, session);
-
- 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);
-
-/* if (DBG_LEVEL >= DBG_info)
- sanei_gl841_print_registers (regs);*/
-}
-
-
// init registers for shading calibration
void CommandSetGl841::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
- DBG_HELPER_ARGS(dbg, "lines = %zu", dev->calib_lines);
- SANE_Int ydpi;
- unsigned starty = 0;
-
- /* initial calibration reg values */
- regs = dev->reg;
-
- ydpi = dev->motor.base_ydpi;
- if (dev->model->motor_id == MotorId::PLUSTEK_OPTICPRO_3600) /* TODO PLUSTEK_3600: 1200dpi not yet working, produces dark bar */
- {
- ydpi = 600;
- }
- if (dev->model->motor_id == MotorId::CANON_LIDE_80) {
- ydpi = gl841_get_dpihw(dev);
- /* get over extra dark area for this model.
- It looks like different devices have dark areas of different width
- due to manufacturing variability. The initial value of starty was 140,
- but it moves the sensor almost past the dark area completely in places
- on certain devices.
-
- On a particular device the black area starts at roughly position
- 160 to 230 depending on location (the dark area is not completely
- parallel to the frame).
- */
- starty = 70;
- }
-
- dev->calib_channels = 3;
- dev->calib_lines = dev->model->shading_lines;
+ DBG_HELPER(dbg);
- unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
- unsigned factor = sensor.optical_res / resolution;
+ unsigned channels = 3;
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, dev->calib_channels,
+ unsigned resolution = sensor.shading_resolution;
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
dev->settings.scan_method);
- dev->calib_pixels = calib_sensor.sensor_pixels / factor;
-
+ unsigned calib_lines =
+ static_cast<unsigned>(dev->model->y_size_calib_dark_white_mm * resolution / MM_PER_INCH);
+ unsigned starty =
+ static_cast<unsigned>(dev->model->y_offset_calib_dark_white_mm * dev->motor.base_ydpi / MM_PER_INCH);
ScanSession session;
session.params.xres = resolution;
- session.params.yres = ydpi;
+ session.params.yres = resolution;
session.params.startx = 0;
session.params.starty = starty;
- 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 = dev->settings.color_filter;
session.params.flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA |
- /*ScanFlag::DISABLE_BUFFER_FULL_MOVE |*/
- ScanFlag::IGNORE_LINE_DISTANCE;
+ ScanFlag::DISABLE_GAMMA;
compute_session(dev, session, calib_sensor);
init_regs_for_scan_session(dev, calib_sensor, &regs, session);
- dev->interface->write_registers(regs);
+ dev->calib_session = session;
}
-// set up registers for the actual scan
-void CommandSetGl841::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);
-
- /* steps to move to reach scanning area:
- - first we move to physical start of scanning
- either by a fixed steps amount from the black strip
- or by a fixed amount from parking position,
- minus the steps done during shading calibration
- - then we move by the needed offset whitin physical
- scanning area
-
- assumption: steps are expressed at maximum motor resolution
-
- we need:
- float y_offset;
- float y_size;
- float y_offset_calib;
- mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
-
- /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
- relative from origin, else, it is from parking position */
-
- move_dpi = dev->motor.base_ydpi;
-
- move = 0;
- if (dev->model->flags & GENESYS_FLAG_SEARCH_START) {
- move += static_cast<float>(dev->model->y_offset_calib_white);
- }
-
- DBG(DBG_info, "%s move=%f steps\n", __func__, move);
-
- move += static_cast<float>(dev->model->y_offset);
- DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
-
- move += static_cast<float>(dev->settings.tl_y);
- DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
-
- move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
-
-/* start */
- start = static_cast<float>(dev->model->x_offset);
-
- start += static_cast<float>(dev->settings.tl_x);
-
- start = static_cast<float>((start * sensor.optical_res) / 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 && dev->settings.true_gray
- && 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
- DBG(DBG_io, "%s: activating LEDADD\n", __func__);
- flags |= ScanFlag::ENABLE_LEDADD;
- }
-
- 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 = flags;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &dev->reg, session);
-}
-
-
// this function sends generic gamma table (ie linear ones) or the Sensor specific one if provided
void CommandSetGl841::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
{
@@ -2581,216 +1649,7 @@ void CommandSetGl841::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor
SensorExposure CommandSetGl841::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
- DBG_HELPER(dbg);
- int num_pixels;
- int total_size;
- int i, j;
- int val;
- int channels;
- int avg[3], avga, avge;
- int turn;
- uint16_t exp[3], target;
- int move;
-
- /* these 2 boundaries should be per sensor */
- uint16_t min_exposure=500;
- uint16_t max_exposure;
-
- /* feed to white strip if needed */
- if (dev->model->y_offset_calib_white > 0) {
- move = static_cast<int>(dev->model->y_offset_calib_white);
- move = static_cast<int>((move * (dev->motor.base_ydpi)) / MM_PER_INCH);
- DBG(DBG_io, "%s: move=%d lines\n", __func__, move);
- gl841_feed(dev, move);
- }
-
- /* offset calibration is always done in color mode */
- channels = 3;
-
- unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
- unsigned factor = sensor.optical_res / resolution;
-
- const auto& calib_sensor_base = sanei_genesys_find_sensor(dev, resolution, channels,
- dev->settings.scan_method);
-
- num_pixels = calib_sensor_base.sensor_pixels / factor;
-
- ScanSession session;
- session.params.xres = resolution;
- session.params.yres = dev->settings.yres;
- 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_base);
-
- init_regs_for_scan_session(dev, calib_sensor_base, &regs, session);
-
- dev->interface->write_registers(regs);
-
-
- total_size = num_pixels * channels * 2 * 1; /* colors * bytes_per_color * scan lines */
-
- std::vector<uint8_t> line(total_size);
-
-/*
- we try to get equal bright leds here:
-
- loop:
- average per color
- adjust exposure times
- */
-
- exp[0] = sensor.exposure.red;
- exp[1] = sensor.exposure.green;
- exp[2] = sensor.exposure.blue;
-
- turn = 0;
- /* max exposure is set to ~2 time initial average
- * exposure, or 2 time last calibration exposure */
- max_exposure=((exp[0]+exp[1]+exp[2])/3)*2;
- target=sensor.gain_white_ref*256;
-
- auto calib_sensor = calib_sensor_base;
-
- bool acceptable = false;
- do {
- calib_sensor.exposure.red = exp[0];
- calib_sensor.exposure.green = exp[1];
- calib_sensor.exposure.blue = exp[2];
-
- regs_set_exposure(dev->model->asic_type, regs, calib_sensor.exposure);
- dev->interface->write_register(0x10, (calib_sensor.exposure.red >> 8) & 0xff);
- dev->interface->write_register(0x11, calib_sensor.exposure.red & 0xff);
- dev->interface->write_register(0x12, (calib_sensor.exposure.green >> 8) & 0xff);
- dev->interface->write_register(0x13, calib_sensor.exposure.green & 0xff);
- dev->interface->write_register(0x14, (calib_sensor.exposure.blue >> 8) & 0xff);
- dev->interface->write_register(0x15, calib_sensor.exposure.blue & 0xff);
-
- dev->interface->write_registers(regs);
-
- DBG(DBG_info, "%s: starting line reading\n", __func__);
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("led_calibration");
- move_back_home(dev, true);
- return calib_sensor.exposure;
- }
-
- sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
-
- if (DBG_LEVEL >= DBG_data) {
- char fn[30];
- std::snprintf(fn, 30, "gl841_led_%d.pnm", turn);
- sanei_genesys_write_pnm_file(fn, line.data(), 16, 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]);
-
- acceptable = true;
-
- /* exposure is acceptable if each color is in the %5 range
- * of other color channels */
- 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(i=0;i<3;i++)
- {
- /* we accept +- 2% delta from target */
- if(abs(avg[i]-target)>target/50)
- {
- exp[i]=(exp[i]*target)/avg[i];
- acceptable = false;
- }
- }
- }
- else
- {
- if (!acceptable)
- {
- 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
- */
- 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;
- }
-
- }
- }
-
- gl841_stop_action(dev);
-
- turn++;
-
- } while (!acceptable && turn < 100);
-
- DBG(DBG_info,"%s: acceptable exposure: %d,%d,%d\n", __func__, exp[0], exp[1], exp[2]);
-
- dev->cmd_set->move_back_home(dev, true);
-
- return calib_sensor.exposure;
+ return scanner_led_calibration(*dev, sensor, regs);
}
/** @brief calibration for AD frontend devices
@@ -2804,9 +1663,6 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
Genesys_Register_Set& regs)
{
DBG_HELPER(dbg);
- int num_pixels;
- int total_size;
- int i;
int average;
int turn;
int top;
@@ -2818,14 +1674,12 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
return;
}
- unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
- unsigned factor = sensor.optical_res / resolution;
+ unsigned resolution = sensor.shading_resolution;
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3,
dev->settings.scan_method);
- num_pixels = calib_sensor.sensor_pixels / factor;
-
+ unsigned num_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
ScanSession session;
session.params.xres = resolution;
session.params.yres = dev->settings.yres;
@@ -2841,14 +1695,15 @@ static void ad_fe_offset_calibration(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, calib_sensor);
dev->cmd_set->init_regs_for_scan_session(dev, calib_sensor, &regs, session);
- total_size = num_pixels * 3 * 2 * 1;
-
- std::vector<uint8_t> line(total_size);
+ // FIXME: we're reading twice as much data for no reason
+ std::size_t total_size = session.output_line_bytes * 2;
+ std::vector<uint8_t> line(total_size);
dev->frontend.set_gain(0, 0);
dev->frontend.set_gain(1, 0);
@@ -2873,23 +1728,23 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
if (is_testing_mode()) {
dev->interface->test_checkpoint("ad_fe_offset_calibration");
- gl841_stop_action(dev);
+ scanner_stop_action(*dev);
return;
}
sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
- gl841_stop_action (dev);
- if (DBG_LEVEL >= DBG_data) {
+ scanner_stop_action(*dev);
+ if (dbg_log_image_data()) {
char fn[30];
- std::snprintf(fn, 30, "gl841_offset_%02d.pnm", turn);
- sanei_genesys_write_pnm_file(fn, line.data(), 8, 3, num_pixels, 1);
+ std::snprintf(fn, 30, "gl841_offset_%02d.tiff", turn);
+ write_tiff_file(fn, line.data(), 8, 3, num_pixels, 1);
}
/* search for minimal value */
average=0;
- for(i=0;i<total_size;i++)
+ for (std::size_t i = 0; i < total_size; i++)
{
- average+=line[i];
+ average += line[i];
}
average/=total_size;
DBG(DBG_data, "%s: average=%d\n", __func__, average);
@@ -2919,8 +1774,6 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
/* this function does the offset calibration by scanning one line of the calibration
area below scanner's top. There is a black margin and the remaining is white.
- sanei_genesys_search_start() must have been called so that the offsets and margins
- are allready known.
this function expects the slider to be where?
*/
@@ -2928,39 +1781,32 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
Genesys_Register_Set& regs) const
{
DBG_HELPER(dbg);
- int num_pixels;
- int total_size;
- int i, j;
- int val;
- int channels;
int off[3],offh[3],offl[3],off1[3],off2[3];
int min1[3],min2[3];
- int cmin[3],cmax[3];
+ unsigned cmin[3],cmax[3];
int turn;
int mintgt = 0x400;
/* Analog Device fronted have a different calibration */
if ((dev->reg.find_reg(0x04).value & REG_0x04_FESET) == 0x02) {
- return ad_fe_offset_calibration(dev, sensor, regs);
+ ad_fe_offset_calibration(dev, sensor, regs);
+ return;
}
/* offset calibration is always done in color mode */
- channels = 3;
+ unsigned channels = 3;
- unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
- unsigned factor = sensor.optical_res / resolution;
+ unsigned resolution = sensor.shading_resolution;
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
dev->settings.scan_method);
- num_pixels = calib_sensor.sensor_pixels / factor;
-
ScanSession session;
session.params.xres = resolution;
session.params.yres = dev->settings.yres;
session.params.startx = 0;
session.params.starty = 0;
- session.params.pixels = num_pixels;
+ session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
session.params.lines = 1;
session.params.depth = 16;
session.params.channels = channels;
@@ -2970,17 +1816,13 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
session.params.flags = ScanFlag::DISABLE_SHADING |
ScanFlag::DISABLE_GAMMA |
ScanFlag::SINGLE_LINE |
- ScanFlag::IGNORE_LINE_DISTANCE |
+ ScanFlag::IGNORE_STAGGER_OFFSET |
+ ScanFlag::IGNORE_COLOR_OFFSET |
ScanFlag::DISABLE_LAMP;
compute_session(dev, session, calib_sensor);
init_regs_for_scan_session(dev, calib_sensor, &regs, session);
- total_size = num_pixels * channels * 2 * 1; /* colors * bytes_per_color * scan lines */
-
- std::vector<uint8_t> first_line(total_size);
- std::vector<uint8_t> second_line(total_size);
-
/* scan first line of data with no offset nor gain */
/*WM8199: gain=0.73; offset=-260mV*/
/*okay. the sensor black level is now at -260mV. we only get 0 from AFE...*/
@@ -3011,12 +1853,14 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
offl[2] = 0x00;
turn = 0;
+ Image first_line;
+
bool acceptable = false;
do {
dev->interface->write_registers(regs);
- for (j=0; j < channels; j++) {
+ for (unsigned j = 0; j < channels; j++) {
off[j] = (offh[j]+offl[j])/2;
dev->frontend.set_offset(j, off[j]);
}
@@ -3031,57 +1875,51 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
return;
}
- sanei_genesys_read_data_from_scanner(dev, first_line.data(), total_size);
+ first_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
- if (DBG_LEVEL >= DBG_data) {
- char fn[30];
- std::snprintf(fn, 30, "gl841_offset1_%02d.pnm", turn);
- sanei_genesys_write_pnm_file(fn, first_line.data(), 16, channels, num_pixels, 1);
- }
+ if (dbg_log_image_data()) {
+ char fn[30];
+ std::snprintf(fn, 30, "gl841_offset1_%02d.tiff", turn);
+ write_tiff_file(fn, first_line);
+ }
acceptable = true;
- for (j = 0; j < channels; j++)
- {
- cmin[j] = 0;
- cmax[j] = 0;
+ for (unsigned ch = 0; ch < channels; ch++) {
+ cmin[ch] = 0;
+ cmax[ch] = 0;
- for (i = 0; i < num_pixels; i++)
- {
- if (dev->model->is_cis)
- val =
- first_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
- first_line[i * 2 + j * 2 * num_pixels];
- else
- val =
- first_line[i * 2 * channels + 2 * j + 1] * 256 +
- first_line[i * 2 * channels + 2 * j];
- if (val < 10)
- cmin[j]++;
- if (val > 65525)
- cmax[j]++;
- }
+ for (std::size_t x = 0; x < first_line.get_width(); x++) {
+ auto value = first_line.get_raw_channel(x, 0, ch);
+ if (value < 10) {
+ cmin[ch]++;
+ }
+ if (value > 65525) {
+ cmax[ch]++;
+ }
+ }
/* TODO the DP685 has a black strip in the middle of the sensor
* should be handled in a more elegant way , could be a bug */
- if (dev->model->sensor_id == SensorId::CCD_DP685)
- cmin[j] -= 20;
+ if (dev->model->sensor_id == SensorId::CCD_DP685) {
+ cmin[ch] -= 20;
+ }
- if (cmin[j] > num_pixels/100) {
+ if (cmin[ch] > first_line.get_width() / 100) {
acceptable = false;
if (dev->model->is_cis)
offl[0] = off[0];
else
- offl[j] = off[j];
- }
- if (cmax[j] > num_pixels/100) {
+ offl[ch] = off[ch];
+ }
+ if (cmax[ch] > first_line.get_width() / 100) {
acceptable = false;
if (dev->model->is_cis)
offh[0] = off[0];
else
- offh[j] = off[j];
- }
- }
+ offh[ch] = off[ch];
+ }
+ }
DBG(DBG_info,"%s: black/white pixels: %d/%d,%d/%d,%d/%d\n", __func__, cmin[0], cmax[0],
cmin[1], cmax[1], cmin[2], cmax[2]);
@@ -3091,7 +1929,7 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
offl[2] = offl[1] = offl[0];
}
- gl841_stop_action(dev);
+ scanner_stop_action(*dev);
turn++;
} while (!acceptable && turn < 100);
@@ -3099,26 +1937,19 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
DBG(DBG_info,"%s: acceptable offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
- for (j = 0; j < channels; j++)
- {
- off1[j] = off[j];
+ for (unsigned ch = 0; ch < channels; ch++) {
+ off1[ch] = off[ch];
- min1[j] = 65536;
+ min1[ch] = 65536;
- for (i = 0; i < num_pixels; i++)
- {
- if (dev->model->is_cis)
- val =
- first_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
- first_line[i * 2 + j * 2 * num_pixels];
- else
- val =
- first_line[i * 2 * channels + 2 * j + 1] * 256 +
- first_line[i * 2 * channels + 2 * j];
- if (min1[j] > val && val >= 10)
- min1[j] = val;
- }
- }
+ for (std::size_t x = 0; x < first_line.get_width(); x++) {
+ auto value = first_line.get_raw_channel(x, 0, ch);
+
+ if (min1[ch] > value && value >= 10) {
+ min1[ch] = value;
+ }
+ }
+ }
offl[0] = off[0];
@@ -3126,64 +1957,59 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
offl[2] = off[0];
turn = 0;
+ Image second_line;
do {
- for (j=0; j < channels; j++) {
+ for (unsigned j=0; j < channels; j++) {
off[j] = (offh[j]+offl[j])/2;
dev->frontend.set_offset(j, off[j]);
- }
+ }
dev->cmd_set->set_fe(dev, calib_sensor, AFE_SET);
DBG(DBG_info, "%s: starting second line reading\n", __func__);
dev->interface->write_registers(regs);
dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
- sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
+ second_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
- if (DBG_LEVEL >= DBG_data) {
- char fn[30];
- std::snprintf(fn, 30, "gl841_offset2_%02d.pnm", turn);
- sanei_genesys_write_pnm_file(fn, second_line.data(), 16, channels, num_pixels, 1);
- }
+ if (dbg_log_image_data()) {
+ char fn[30];
+ std::snprintf(fn, 30, "gl841_offset2_%02d.tiff", turn);
+ write_tiff_file(fn, second_line);
+ }
acceptable = true;
- for (j = 0; j < channels; j++)
- {
- cmin[j] = 0;
- cmax[j] = 0;
+ for (unsigned ch = 0; ch < channels; ch++) {
+ cmin[ch] = 0;
+ cmax[ch] = 0;
- for (i = 0; i < num_pixels; i++)
- {
- if (dev->model->is_cis)
- val =
- second_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
- second_line[i * 2 + j * 2 * num_pixels];
- else
- val =
- second_line[i * 2 * channels + 2 * j + 1] * 256 +
- second_line[i * 2 * channels + 2 * j];
- if (val < 10)
- cmin[j]++;
- if (val > 65525)
- cmax[j]++;
- }
+ for (std::size_t x = 0; x < second_line.get_width(); x++) {
+ auto value = second_line.get_raw_channel(x, 0, ch);
- if (cmin[j] > num_pixels/100) {
+ if (value < 10) {
+ cmin[ch]++;
+ }
+ if (value > 65525) {
+ cmax[ch]++;
+ }
+ }
+
+ if (cmin[ch] > second_line.get_width() / 100) {
acceptable = false;
if (dev->model->is_cis)
offl[0] = off[0];
else
- offl[j] = off[j];
- }
- if (cmax[j] > num_pixels/100) {
+ offl[ch] = off[ch];
+ }
+ if (cmax[ch] > second_line.get_width() / 100) {
acceptable = false;
if (dev->model->is_cis)
offh[0] = off[0];
else
- offh[j] = off[j];
- }
- }
+ offh[ch] = off[ch];
+ }
+ }
DBG(DBG_info, "%s: black/white pixels: %d/%d,%d/%d,%d/%d\n", __func__, cmin[0], cmax[0],
cmin[1], cmax[1], cmin[2], cmax[2]);
@@ -3193,7 +2019,7 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
offl[2] = offl[1] = offl[0];
}
- gl841_stop_action(dev);
+ scanner_stop_action(*dev);
turn++;
@@ -3202,26 +2028,19 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
DBG(DBG_info, "%s: acceptable offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
- for (j = 0; j < channels; j++)
- {
- off2[j] = off[j];
+ for (unsigned ch = 0; ch < channels; ch++) {
+ off2[ch] = off[ch];
- min2[j] = 65536;
+ min2[ch] = 65536;
- for (i = 0; i < num_pixels; i++)
- {
- if (dev->model->is_cis)
- val =
- second_line[i * 2 + j * 2 * num_pixels + 1] * 256 +
- second_line[i * 2 + j * 2 * num_pixels];
- else
- val =
- second_line[i * 2 * channels + 2 * j + 1] * 256 +
- second_line[i * 2 * channels + 2 * j];
- if (min2[j] > val && val != 0)
- min2[j] = val;
- }
- }
+ for (std::size_t x = 0; x < second_line.get_width(); x++) {
+ auto value = second_line.get_raw_channel(x, 0, ch);
+
+ if (min2[ch] > value && value != 0) {
+ min2[ch] = value;
+ }
+ }
+ }
DBG(DBG_info, "%s: first set: %d/%d,%d/%d,%d/%d\n", __func__, off1[0], min1[0], off1[1], min1[1],
off1[2], min1[2]);
@@ -3247,22 +2066,25 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
off=(min*(off1-off2)+min1*off2-off1*min2)/(min1-min2)
*/
- for (j = 0; j < channels; j++)
- {
- if (min2[j]-min1[j] == 0) {
+ for (unsigned ch = 0; ch < channels; ch++) {
+ if (min2[ch] - min1[ch] == 0) {
/*TODO: try to avoid this*/
DBG(DBG_warn, "%s: difference too small\n", __func__);
- if (mintgt * (off1[j] - off2[j]) + min1[j] * off2[j] - min2[j] * off1[j] >= 0)
- off[j] = 0x0000;
- else
- off[j] = 0xffff;
- } else
- off[j] = (mintgt * (off1[j] - off2[j]) + min1[j] * off2[j] - min2[j] * off1[j])/(min1[j]-min2[j]);
- if (off[j] > 255)
- off[j] = 255;
- if (off[j] < 0)
- off[j] = 0;
- dev->frontend.set_offset(j, off[j]);
+ if (mintgt * (off1[ch] - off2[ch]) + min1[ch] * off2[ch] - min2[ch] * off1[ch] >= 0) {
+ off[ch] = 0x0000;
+ } else {
+ off[ch] = 0xffff;
+ }
+ } else {
+ off[ch] = (mintgt * (off1[ch] - off2[ch]) + min1[ch] * off2[ch] - min2[ch] * off1[ch])/(min1[ch]-min2[ch]);
+ }
+ if (off[ch] > 255) {
+ off[ch] = 255;
+ }
+ if (off[ch] < 0) {
+ off[ch] = 0;
+ }
+ dev->frontend.set_offset(ch, off[ch]);
}
DBG(DBG_info, "%s: final offsets: %d,%d,%d\n", __func__, off[0], off[1], off[2]);
@@ -3297,171 +2119,13 @@ void CommandSetGl841::offset_calibration(Genesys_Device* dev, const Genesys_Sens
void CommandSetGl841::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 num_pixels;
- int total_size;
- int i, j, channels;
- int max[3];
- float gain[3];
- int val;
- int lines=1;
- int move;
-
- // feed to white strip if needed
- if (dev->model->y_offset_calib_white > 0) {
- move = static_cast<int>(dev->model->y_offset_calib_white);
- move = static_cast<int>((move * (dev->motor.base_ydpi)) / MM_PER_INCH);
- DBG(DBG_io, "%s: move=%d lines\n", __func__, move);
- gl841_feed(dev, move);
- }
-
- /* coarse gain calibration is allways done in color mode */
- channels = 3;
-
- unsigned resolution = sensor.get_logical_hwdpi(dev->settings.xres);
- unsigned factor = sensor.optical_res / resolution;
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
- dev->settings.scan_method);
-
- num_pixels = calib_sensor.sensor_pixels / factor;
-
- ScanSession session;
- session.params.xres = resolution;
- session.params.yres = dev->settings.yres;
- session.params.startx = 0;
- session.params.starty = 0;
- session.params.pixels = num_pixels;
- session.params.lines = lines;
- 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, &regs, session);
-
- dev->interface->write_registers(regs);
-
- total_size = num_pixels * channels * 2 * lines; /* colors * bytes_per_color * scan lines */
-
- std::vector<uint8_t> line(total_size);
-
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("coarse_gain_calibration");
- gl841_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("gl841_gain.pnm", line.data(), 16, channels, num_pixels, lines);
-
- /* average high level for each channel and compute gain
- to reach the target code
- we only use the central half of the CCD data */
- for (j = 0; j < channels; j++)
- {
- max[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];
-
- if (val > max[j])
- max[j] = val;
- }
-
- gain[j] = 65535.0f / max[j];
-
- uint8_t out_gain = 0;
-
- if (dev->model->adc_id == AdcId::CANON_LIDE_35 ||
- dev->model->adc_id == AdcId::WOLFSON_XP300 ||
- dev->model->adc_id == AdcId::WOLFSON_DSM600)
- {
- gain[j] *= 0.69f; // seems we don't get the real maximum. empirically derived
- if (283 - 208/gain[j] > 255)
- out_gain = 255;
- else if (283 - 208/gain[j] < 0)
- out_gain = 0;
- else
- out_gain = static_cast<std::uint8_t>(283 - 208 / gain[j]);
- } else if (dev->model->adc_id == AdcId::CANON_LIDE_80) {
- out_gain = static_cast<std::uint8_t>(gain[j] * 12);
- }
- dev->frontend.set_gain(j, out_gain);
-
- DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, max[j], gain[j],
- out_gain);
- }
-
- for (j = 0; j < channels; j++)
- {
- if(gain[j] > 10)
- {
- 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");
- throw SaneException(SANE_STATUS_JAMMED, "scanning head is locked");
- }
-
- }
-
- 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));
- }
-
- DBG(DBG_info, "%s: gain=(%d,%d,%d)\n", __func__,
- dev->frontend.get_gain(0),
- dev->frontend.get_gain(1),
- dev->frontend.get_gain(2));
-
- gl841_stop_action(dev);
-
- dev->cmd_set->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 CommandSetGl841::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* local_reg, int* channels,
- int* total_size) const
+ Genesys_Register_Set* local_reg) const
{
DBG_HELPER(dbg);
int num_pixels = 4 * 300;
@@ -3475,51 +2139,34 @@ void CommandSetGl841::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se
dev->frontend.set_offset(1, 0x80);
dev->frontend.set_offset(2, 0x80);
+ 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->settings.yres;
session.params.startx = sensor.dummy_pixel;
session.params.starty = 0;
session.params.pixels = num_pixels;
session.params.lines = 1;
- session.params.depth = 16;
- 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;
- if (*channels == 3) {
- session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
- } else {
- session.params.scan_mode = ScanColorMode::GRAY;
- }
+ 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, local_reg, session);
-
- num_pixels = session.output_pixels;
-
- *total_size = num_pixels * 3 * 2 * 1; /* colors * bytes_per_color * scan lines */
-
- dev->interface->write_registers(*local_reg);
-}
-
-
-/*
- * this function moves head without scanning, forward, then backward
- * so that the head goes to park position.
- * as a by-product, also check for lock
- */
-static void sanei_gl841_repark_head(Genesys_Device* dev)
-{
- DBG_HELPER(dbg);
-
- gl841_feed(dev,232);
-
- // toggle motor flag, put an huge step number and redo move backward
- dev->cmd_set->move_back_home(dev, true);
}
/*
@@ -3528,123 +2175,9 @@ static void sanei_gl841_repark_head(Genesys_Device* dev)
*/
void CommandSetGl841::init(Genesys_Device* dev) const
{
- size_t size;
-
- DBG_INIT ();
+ DBG_INIT();
DBG_HELPER(dbg);
-
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
-
- /* Check if the device has already been initialized and powered up */
- if (dev->already_initialized)
- {
- auto status = scanner_read_status(*dev);
- if (!status.is_replugged) {
- DBG(DBG_info, "%s: already initialized\n", __func__);
- return;
- }
- }
-
- dev->dark_average_data.clear();
- dev->white_average_data.clear();
-
- dev->settings.color_filter = ColorFilter::RED;
-
- // ASIC reset
- dev->interface->write_register(0x0e, 0x01);
- dev->interface->write_register(0x0e, 0x00);
-
- /* Set default values for registers */
- gl841_init_registers (dev);
-
- // Write initial registers
- dev->interface->write_registers(dev->reg);
-
- const auto& sensor = sanei_genesys_find_sensor_any(dev);
-
- // Set analog frontend
- dev->cmd_set->set_fe(dev, sensor, AFE_INIT);
-
- // FIXME: move_back_home modifies dev->calib_reg and requires it to be filled
- dev->calib_reg = dev->reg;
-
- // Move home
- dev->cmd_set->move_back_home(dev, true);
-
- // Init shading data
- sanei_genesys_init_shading_data(dev, sensor, sensor.sensor_pixels);
-
- /* ensure head is correctly parked, and check lock */
- if (dev->model->flags & GENESYS_FLAG_REPARK)
- {
- // FIXME: if repark fails, we should print an error message that the scanner is locked and
- // the user should unlock the lock. We should also rethrow with SANE_STATUS_JAMMED
- sanei_gl841_repark_head(dev);
- }
-
- // send gamma tables
- dev->cmd_set->send_gamma_table(dev, sensor);
-
- /* initial calibration reg values */
- Genesys_Register_Set& regs = dev->calib_reg;
- regs = dev->reg;
-
- unsigned resolution = sensor.get_logical_hwdpi(300);
- unsigned factor = sensor.optical_res / resolution;
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, 3,
- dev->settings.scan_method);
-
- unsigned num_pixels = 16 / factor;
-
- ScanSession session;
- session.params.xres = resolution;
- session.params.yres = 300;
- session.params.startx = 0;
- session.params.starty = 0;
- session.params.pixels = num_pixels;
- session.params.lines = 1;
- session.params.depth = 16;
- session.params.channels = 3;
- 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::SINGLE_LINE |
- ScanFlag::IGNORE_LINE_DISTANCE;
- compute_session(dev, session, calib_sensor);
-
- init_regs_for_scan_session(dev, calib_sensor, &regs, session);
-
- dev->interface->write_registers(regs);
-
- size = num_pixels * 3 * 2 * 1; // colors * bytes_per_color * scan lines
-
- std::vector<uint8_t> line(size);
-
- DBG(DBG_info, "%s: starting dummy data reading\n", __func__);
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
-
- sanei_usb_set_timeout(1000);/* 1 second*/
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("init");
- } else {
- // ignore errors. next read will succeed
- catch_all_exceptions(__func__,
- [&](){ sanei_genesys_read_data_from_scanner(dev, line.data(), size); });
- }
-
- sanei_usb_set_timeout(30 * 1000);/* 30 seconds*/
-
- end_scan(dev, &regs, true);
-
- regs = dev->reg;
-
- // Set powersaving(default = 15 minutes)
- set_powersaving(dev, 15);
- dev->already_initialized = true;
+ sanei_genesys_asic_init(dev);
}
void CommandSetGl841::update_hardware_sensors(Genesys_Scanner* s) const
@@ -3676,225 +2209,6 @@ void CommandSetGl841::update_hardware_sensors(Genesys_Scanner* s) const
}
}
-/** @brief search for a full width black or white strip.
- * This function searches for a black or white stripe across the scanning area.
- * When searching backward, the searched area must completely be of the desired
- * color since this area will be used for calibration which scans forward.
- * @param dev scanner device
- * @param forward true if searching forward, false if searching backward
- * @param black true if searching for a black strip, false for a white strip
- */
-void CommandSetGl841::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
- bool black) const
-{
- DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
- unsigned int pixels, lines, channels;
- Genesys_Register_Set local_reg;
- size_t size;
- unsigned int pass, count, found, x, y, length;
- char title[80];
- GenesysRegister *r;
- uint8_t white_level=90; /**< default white level to detect white dots */
- uint8_t black_level=60; /**< default black level to detect black dots */
-
- /* use maximum gain when doing forward white strip detection
- * since we don't have calibrated the sensor yet */
- if(!black && forward)
- {
- dev->frontend.set_gain(0, 0xff);
- dev->frontend.set_gain(1, 0xff);
- dev->frontend.set_gain(2, 0xff);
- }
-
- dev->cmd_set->set_fe(dev, sensor, AFE_SET);
- gl841_stop_action(dev);
-
- // set up for a gray scan at lowest dpi
- const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
- unsigned dpi = resolution_settings.get_min_resolution_x();
- channels = 1;
-
- /* shading calibation is done with dev->motor.base_ydpi */
- /* lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi; */
- lines = static_cast<unsigned>((10 * dpi) / MM_PER_INCH);
-
- pixels = (sensor.sensor_pixels * dpi) / sensor.optical_res;
-
- /* 20 cm max length for calibration sheet */
- length = static_cast<unsigned>(((200 * dpi) / MM_PER_INCH) / lines);
-
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
-
- local_reg = dev->reg;
-
- ScanSession session;
- session.params.xres = dpi;
- session.params.yres = dpi;
- 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::GRAY;
- session.params.color_filter = ColorFilter::RED;
- session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_GAMMA;
- compute_session(dev, session, sensor);
-
- size = pixels * channels * lines * (session.params.depth / 8);
- std::vector<uint8_t> data(size);
-
- init_regs_for_scan_session(dev, sensor, &local_reg, session);
-
- /* set up for reverse or forward */
- r = sanei_genesys_get_address(&local_reg, 0x02);
- if (forward) {
- r->value &= ~4;
- } else {
- r->value |= 4;
- }
-
- dev->interface->write_registers(local_reg);
-
- dev->cmd_set->begin_scan(dev, sensor, &local_reg, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("search_strip");
- gl841_stop_action(dev);
- return;
- }
-
- // waits for valid data
- 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);
-
- gl841_stop_action(dev);
-
- pass = 0;
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm", black ? "black" : "white",
- forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
- channels, pixels, lines);
- }
-
- /* loop until strip is found or maximum pass number done */
- found = 0;
- while (pass < length && !found)
- {
- dev->interface->write_registers(local_reg);
-
- //now start scan
- dev->cmd_set->begin_scan(dev, sensor, &local_reg, true);
-
- // waits for valid data
- 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);
-
- gl841_stop_action (dev);
-
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl841_search_strip_%s_%s%02u.pnm",
- black ? "black" : "white", forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
- channels, pixels, lines);
- }
-
- /* search data to find black strip */
- /* when searching forward, we only need one line of the searched color since we
- * will scan forward. But when doing backward search, we need all the area of the
- * same color */
- if (forward)
- {
- for (y = 0; y < lines && !found; y++)
- {
- count = 0;
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * pixels + x] > white_level)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * pixels + x] < black_level)
- {
- count++;
- }
- }
-
- /* at end of line, if count >= 3%, line is not fully of the desired color
- * so we must go to next line of the buffer */
- /* count*100/pixels < 3 */
- if ((count * 100) / pixels < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
- pass, y);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- }
- else /* since calibration scans are done forward, we need the whole area
- to be of the required color when searching backward */
- {
- count = 0;
- for (y = 0; y < lines; y++)
- {
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * pixels + x] > white_level)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * pixels + x] < black_level)
- {
- count++;
- }
- }
- }
-
- /* at end of area, if count >= 3%, area is not fully of the desired color
- * so we must go to next buffer */
- if ((count * 100) / (pixels * lines) < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- pass++;
- }
-
- if (found)
- {
- DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
- }
- else
- {
- throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
- }
-}
-
/**
* Send shading calibration data. The buffer is considered to always hold values
* for all the channels.
@@ -3903,42 +2217,30 @@ void CommandSetGl841::send_shading_data(Genesys_Device* dev, const Genesys_Senso
uint8_t* data, int size) const
{
DBG_HELPER_ARGS(dbg, "writing %d bytes of shading data", size);
- uint32_t length, x, factor, pixels, i;
- uint16_t dpiset, dpihw, beginpixel;
+ uint32_t length, x, pixels, i;
uint8_t *ptr,*src;
/* old method if no SHDAREA */
if ((dev->reg.find_reg(0x01).value & REG_0x01_SHDAREA) == 0) {
+ // Note that this requires the sensor pixel offset to be exactly the same as to start
+ // reading from dummy_pixel + 1 position.
dev->interface->write_buffer(0x3c, 0x0000, data, size);
return;
}
/* data is whole line, we extract only the part for the scanned area */
length = static_cast<std::uint32_t>(size / 3);
- unsigned strpixel = dev->session.pixel_startx;
- unsigned endpixel = dev->session.pixel_endx;
-
- /* compute deletion/average factor */
- dpiset = dev->reg.get16(REG_DPISET);
- dpihw = gl841_get_dpihw(dev);
- unsigned ccd_size_divisor = dev->session.ccd_size_divisor;
- factor=dpihw/dpiset;
- DBG(DBG_io2, "%s: dpihw=%d, dpiset=%d, ccd_size_divisor=%d, factor=%d\n", __func__, dpihw, dpiset,
- ccd_size_divisor, factor);
-
- /* turn pixel value into bytes 2x16 bits words */
- strpixel*=2*2; /* 2 words of 2 bytes */
- endpixel*=2*2;
- pixels=endpixel-strpixel;
-
- /* shading pixel begin is start pixel minus start pixel during shading
- * calibration. Currently only cases handled are full and half ccd resolution.
- */
- beginpixel = sensor.ccd_start_xoffset / ccd_size_divisor;
- beginpixel += sensor.dummy_pixel + 1;
- DBG(DBG_io2, "%s: ORIGIN PIXEL=%d\n", __func__, beginpixel);
- beginpixel = (strpixel-beginpixel*2*2)/factor;
- DBG(DBG_io2, "%s: BEGIN PIXEL=%d\n", __func__, beginpixel/4);
+
+ // turn pixel value into bytes 2x16 bits words
+ pixels = dev->session.pixel_endx - dev->session.pixel_startx;
+ pixels *= 4;
+
+ // shading pixel begin is start pixel minus start pixel during shading
+ // calibration. Currently only cases handled are full and half ccd resolution.
+ unsigned beginpixel = dev->session.params.startx * dev->session.optical_resolution /
+ dev->session.params.xres;
+ beginpixel *= 4;
+ beginpixel /= sensor.shading_factor;
dev->interface->record_key_value("shading_offset", std::to_string(beginpixel));
dev->interface->record_key_value("shading_pixels", std::to_string(pixels));
@@ -3962,7 +2264,7 @@ void CommandSetGl841::send_shading_data(Genesys_Device* dev, const Genesys_Senso
for(x=0;x<pixels;x+=4)
{
/* coefficient source */
- src=data+x+beginpixel+i*length;
+ src = data + x + beginpixel + i * length;
ptr[0]=src[0];
ptr[1]=src[1];
ptr[2]=src[2];
@@ -3988,22 +2290,29 @@ void CommandSetGl841::wait_for_motor_stop(Genesys_Device* dev) const
(void) dev;
}
-void CommandSetGl841::move_to_ta(Genesys_Device* dev) const
-{
- (void) dev;
- throw SaneException("not implemented");
-}
-
void CommandSetGl841::asic_boot(Genesys_Device *dev, bool cold) const
{
- (void) dev;
- (void) cold;
- throw SaneException("not implemented");
-}
+ // reset ASIC in case of cold boot
+ if (cold) {
+ dev->interface->write_register(0x0e, 0x01);
+ dev->interface->write_register(0x0e, 0x00);
+ }
-std::unique_ptr<CommandSet> create_gl841_cmd_set()
-{
- return std::unique_ptr<CommandSet>(new CommandSetGl841{});
+ gl841_init_registers(dev);
+
+ // Write initial registers
+ dev->interface->write_registers(dev->reg);
+
+ // FIXME: 0x0b is not set, but on all other backends we do set it
+ // dev->reg.remove_reg(0x0b);
+
+ if (dev->model->model_id == ModelId::CANON_LIDE_60) {
+ dev->interface->write_0x8c(0x10, 0xa4);
+ }
+
+ // FIXME: we probably don't need this
+ const auto& sensor = sanei_genesys_find_sensor_any(dev);
+ dev->cmd_set->set_fe(dev, sensor, AFE_INIT);
}
} // namespace gl841
diff --git a/backend/genesys/gl841.h b/backend/genesys/gl841.h
index 5e24249..c9f15ee 100644
--- a/backend/genesys/gl841.h
+++ b/backend/genesys/gl841.h
@@ -42,7 +42,7 @@
*/
#include "genesys.h"
-#include "command_set.h"
+#include "command_set_common.h"
#ifndef BACKEND_GENESYS_GL841_H
#define BACKEND_GENESYS_GL841_H
@@ -50,7 +50,7 @@
namespace genesys {
namespace gl841 {
-class CommandSetGl841 : public CommandSet
+class CommandSetGl841 : public CommandSetCommon
{
public:
~CommandSetGl841() override = default;
@@ -60,17 +60,11 @@ public:
void init(Genesys_Device* dev) const override;
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const override;
-
- void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const override;
+ Genesys_Register_Set* regs) const override;
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
- void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
-
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set* reg,
const ScanSession& session) const override;
@@ -86,8 +80,6 @@ public:
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
- void search_start_position(Genesys_Device* dev) const override;
-
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
@@ -103,17 +95,14 @@ public:
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
+ void update_home_sensor_gpio(Genesys_Device& dev) const override;
+
void load_document(Genesys_Device* dev) const override;
void detect_document_end(Genesys_Device* dev) const override;
void eject_document(Genesys_Device* dev) const override;
- void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const override;
-
- void move_to_ta(Genesys_Device* dev) const override;
-
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
int size) const override;
diff --git a/backend/genesys/gl841_registers.h b/backend/genesys/gl841_registers.h
index 8e0c204..2fac278 100644
--- a/backend/genesys/gl841_registers.h
+++ b/backend/genesys/gl841_registers.h
@@ -224,10 +224,12 @@ static constexpr RegShift REG_0x5ES_DECSEL = 5;
static constexpr RegMask REG_0x5E_STOPTIM = 0x1f;
static constexpr RegShift REG_0x5ES_STOPTIM = 0;
+static constexpr RegAddr REG_0x60 = 0x60;
static constexpr RegMask REG_0x60_ZIMOD = 0x1f;
static constexpr RegMask REG_0x61_Z1MOD = 0xff;
static constexpr RegMask REG_0x62_Z1MOD = 0xff;
+static constexpr RegAddr REG_0x63 = 0x63;
static constexpr RegMask REG_0x63_Z2MOD = 0x1f;
static constexpr RegMask REG_0x64_Z2MOD = 0xff;
static constexpr RegMask REG_0x65_Z2MOD = 0xff;
diff --git a/backend/genesys/gl842.cpp b/backend/genesys/gl842.cpp
new file mode 100644
index 0000000..d5bebe5
--- /dev/null
+++ b/backend/genesys/gl842.cpp
@@ -0,0 +1,1066 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr>
+ Copyright (C) 2020 Povilas Kanapickas <povilas@radix.lt>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+*/
+
+#define DEBUG_DECLARE_ONLY
+
+#include "gl842_registers.h"
+#include "gl842.h"
+#include "test_settings.h"
+
+#include <string>
+#include <vector>
+
+namespace genesys {
+namespace gl842 {
+
+static void gl842_init_registers(Genesys_Device& dev)
+{
+ // Within this function SENSOR_DEF marker documents that a register is part
+ // of the sensors definition and the actual value is set in
+ // gl842_setup_sensor().
+
+ DBG_HELPER(dbg);
+
+ dev.reg.clear();
+
+ if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ dev.reg.init_reg(0x01, 0x00);
+ dev.reg.init_reg(0x02, 0x78);
+ dev.reg.init_reg(0x03, 0xbf);
+ dev.reg.init_reg(0x04, 0x22);
+ dev.reg.init_reg(0x05, 0x48);
+
+ dev.reg.init_reg(0x06, 0xb8);
+
+ dev.reg.init_reg(0x07, 0x00);
+ dev.reg.init_reg(0x08, 0x00);
+ dev.reg.init_reg(0x09, 0x00);
+ dev.reg.init_reg(0x0a, 0x00);
+ dev.reg.init_reg(0x0d, 0x01);
+ } else if (dev.model->model_id == ModelId::CANON_LIDE_90) {
+ dev.reg.init_reg(0x01, 0x82);
+ dev.reg.init_reg(0x02, 0x10);
+ dev.reg.init_reg(0x03, 0x60);
+ dev.reg.init_reg(0x04, 0x10);
+ dev.reg.init_reg(0x05, 0x8c);
+
+ dev.reg.init_reg(0x06, 0x18);
+
+ //dev.reg.init_reg(0x07, 0x00);
+ dev.reg.init_reg(0x08, 0x00);
+ dev.reg.init_reg(0x09, 0x21);
+ dev.reg.init_reg(0x0a, 0x00);
+ dev.reg.init_reg(0x0d, 0x00);
+ }
+
+ dev.reg.init_reg(0x10, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev.reg.init_reg(0x11, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev.reg.init_reg(0x12, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev.reg.init_reg(0x13, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev.reg.init_reg(0x14, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev.reg.init_reg(0x15, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+
+ // CCD signal settings.
+ dev.reg.init_reg(0x16, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x17, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x18, 0x00); // SENSOR_DEF
+
+ // EXPDMY[0:7]: Exposure time of dummy lines.
+ dev.reg.init_reg(0x19, 0x00); // SENSOR_DEF
+
+ // Various CCD clock settings.
+ dev.reg.init_reg(0x1a, 0x00); // SENSOR_DEF
+ if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ dev.reg.init_reg(0x1b, 0x00); // SENSOR_DEF
+ }
+ dev.reg.init_reg(0x1c, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x1d, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x1e, 0x10); // WDTIME, LINESEL: setup during sensor and motor setup
+
+ if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ dev.reg.init_reg(0x1f, 0x01);
+ dev.reg.init_reg(0x20, 0x27); // BUFSEL: buffer full condition
+ } else if (dev.model->model_id == ModelId::CANON_LIDE_90) {
+ dev.reg.init_reg(0x1f, 0x02);
+ dev.reg.init_reg(0x20, 0x02); // BUFSEL: buffer full condition
+ }
+
+ dev.reg.init_reg(0x21, 0x10); // STEPNO: set during motor setup
+ dev.reg.init_reg(0x22, 0x10); // FWDSTEP: set during motor setup
+ dev.reg.init_reg(0x23, 0x10); // BWDSTEP: set during motor setup
+ dev.reg.init_reg(0x24, 0x10); // FASTNO: set during motor setup
+ dev.reg.init_reg(0x25, 0x00); // LINCNT: set during motor setup
+ dev.reg.init_reg(0x26, 0x00); // LINCNT: set during motor setup
+ dev.reg.init_reg(0x27, 0x00); // LINCNT: set during motor setup
+
+ dev.reg.init_reg(0x29, 0xff); // LAMPPWM
+
+ dev.reg.init_reg(0x2c, 0x02); // DPISET: set during sensor setup
+ dev.reg.init_reg(0x2d, 0x58); // DPISET: set during sensor setup
+
+ dev.reg.init_reg(0x2e, 0x80); // BWHI: black/white low threshdold
+ dev.reg.init_reg(0x2f, 0x80); // BWLOW: black/white low threshold
+
+ dev.reg.init_reg(0x30, 0x00); // STRPIXEL: set during sensor setup
+ dev.reg.init_reg(0x31, 0x49); // STRPIXEL: set during sensor setup
+ dev.reg.init_reg(0x32, 0x53); // ENDPIXEL: set during sensor setup
+ dev.reg.init_reg(0x33, 0xb9); // ENDPIXEL: set during sensor setup
+
+ dev.reg.init_reg(0x34, 0x13); // DUMMY: SENSOR_DEF
+ dev.reg.init_reg(0x35, 0x00); // MAXWD: set during scan setup
+ dev.reg.init_reg(0x36, 0x40); // MAXWD: set during scan setup
+ dev.reg.init_reg(0x37, 0x00); // MAXWD: set during scan setup
+ dev.reg.init_reg(0x38, 0x2a); // LPERIOD: SENSOR_DEF
+ dev.reg.init_reg(0x39, 0xf8); // LPERIOD: SENSOR_DEF
+ dev.reg.init_reg(0x3d, 0x00); // FEEDL: set during motor setup
+ dev.reg.init_reg(0x3e, 0x00); // FEEDL: set during motor setup
+ dev.reg.init_reg(0x3f, 0x01); // FEEDL: set during motor setup
+
+ dev.reg.init_reg(0x52, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x53, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x54, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x55, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x56, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x57, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x58, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x59, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x5a, 0x00); // SENSOR_DEF
+
+ if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ dev.reg.init_reg(0x5e, 0x01); // DECSEL, STOPTIM
+ } else if (dev.model->model_id == ModelId::CANON_LIDE_90) {
+ dev.reg.init_reg(0x5e, 0x41); // DECSEL, STOPTIM
+ dev.reg.init_reg(0x5d, 0x20);
+ }
+ dev.reg.init_reg(0x5f, 0x10); // FMOVDEC: set during motor setup
+
+ dev.reg.init_reg(0x60, 0x00); // Z1MOD: overwritten during motor setup
+ dev.reg.init_reg(0x61, 0x00); // Z1MOD: overwritten during motor setup
+ dev.reg.init_reg(0x62, 0x00); // Z1MOD: overwritten during motor setup
+ dev.reg.init_reg(0x63, 0x00); // Z2MOD: overwritten during motor setup
+ dev.reg.init_reg(0x64, 0x00); // Z2MOD: overwritten during motor setup
+ dev.reg.init_reg(0x65, 0x00); // Z2MOD: overwritten during motor setup
+
+ if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ dev.reg.init_reg(0x67, 0x7f); // STEPSEL, MTRPWM: partially overwritten during motor setup
+ dev.reg.init_reg(0x68, 0x7f); // FSTPSEL, FASTPWM: partially overwritten during motor setup
+ } else if (dev.model->model_id == ModelId::CANON_LIDE_90) {
+ dev.reg.init_reg(0x66, 0x00); // PHFREQ
+ dev.reg.init_reg(0x67, 0x40); // STEPSEL, MTRPWM: partially overwritten during motor setup
+ dev.reg.init_reg(0x68, 0x40); // FSTPSEL, FASTPWM: partially overwritten during motor setup
+ }
+ dev.reg.init_reg(0x69, 0x10); // FSHDEC: overwritten during motor setup
+ dev.reg.init_reg(0x6a, 0x10); // FMOVNO: overwritten during motor setup
+
+ // 0x6b, 0x6c, 0x6d, 0x6e, 0x6f - set according to gpio tables. See gl842_init_gpio.
+
+ dev.reg.init_reg(0x70, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x71, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x72, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x73, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x74, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x75, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x76, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x77, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x78, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x79, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x7a, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x7b, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x7c, 0x00); // SENSOR_DEF
+ dev.reg.init_reg(0x7d, 0x00); // SENSOR_DEF
+
+ // 0x7e - set according to gpio tables. See gl842_init_gpio.
+
+ dev.reg.init_reg(0x7f, 0x00); // SENSOR_DEF
+
+ // VRHOME, VRMOVE, VRBACK, VRSCAN: Vref settings of the motor driver IC for
+ // moving in various situations.
+ dev.reg.init_reg(0x80, 0x00); // MOTOR_PROFILE
+
+ if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ dev.reg.init_reg(0x81, 0x00);
+ dev.reg.init_reg(0x82, 0x00);
+ dev.reg.init_reg(0x83, 0x00);
+ dev.reg.init_reg(0x84, 0x00);
+ dev.reg.init_reg(0x85, 0x00);
+ dev.reg.init_reg(0x86, 0x00);
+ dev.reg.init_reg(0x87, 0x00);
+ } else if (dev.model->model_id == ModelId::CANON_LIDE_90) {
+ dev.reg.init_reg(0x7e, 0x00);
+ dev.reg.init_reg(0x81, 0x00);
+ dev.reg.init_reg(0x82, 0x0f);
+ dev.reg.init_reg(0x83, 0x00);
+ dev.reg.init_reg(0x84, 0x0e);
+ dev.reg.init_reg(0x85, 0x00);
+ dev.reg.init_reg(0x86, 0x0d);
+ dev.reg.init_reg(0x87, 0x00);
+ dev.reg.init_reg(0x88, 0x00);
+ dev.reg.init_reg(0x89, 0x00);
+ }
+
+ const auto& sensor = sanei_genesys_find_sensor_any(&dev);
+ sanei_genesys_set_dpihw(dev.reg, sensor.register_dpihw);
+
+ scanner_setup_sensor(dev, sensor, dev.reg);
+}
+
+// Set values of analog frontend
+void CommandSetGl842::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
+{
+ DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
+ set == AFE_SET ? "set" :
+ set == AFE_POWER_SAVE ? "powersave" : "huh?");
+ (void) sensor;
+
+ if (set == AFE_INIT) {
+ dev->frontend = dev->frontend_initial;
+ }
+
+ // check analog frontend type
+ // FIXME: looks like we write to that register with initial data
+ uint8_t fe_type = dev->interface->read_register(REG_0x04) & REG_0x04_FESET;
+ if (fe_type == 2 || dev->model->model_id == ModelId::CANON_LIDE_90) {
+ for (const auto& reg : dev->frontend.regs) {
+ dev->interface->write_fe_register(reg.address, reg.value);
+ }
+ return;
+ }
+ if (fe_type != 0) {
+ throw SaneException(SANE_STATUS_UNSUPPORTED, "unsupported frontend type %d", fe_type);
+ }
+
+ for (unsigned i = 1; i <= 3; i++) {
+ dev->interface->write_fe_register(i, dev->frontend.regs.get_value(0x00 + i));
+ }
+ for (const auto& reg : sensor.custom_fe_regs) {
+ dev->interface->write_fe_register(reg.address, reg.value);
+ }
+
+ for (unsigned i = 0; i < 3; i++) {
+ dev->interface->write_fe_register(0x20 + i, dev->frontend.get_offset(i));
+ }
+
+ for (unsigned i = 0; i < 3; i++) {
+ dev->interface->write_fe_register(0x28 + i, dev->frontend.get_gain(i));
+ }
+}
+
+static void gl842_init_motor_regs_scan(Genesys_Device* dev,
+ const Genesys_Sensor& sensor,
+ const ScanSession& session,
+ Genesys_Register_Set* reg,
+ const MotorProfile& motor_profile,
+ unsigned int exposure,
+ unsigned scan_yres,
+ unsigned int scan_lines,
+ unsigned int scan_dummy,
+ unsigned int feed_steps,
+ ScanFlag flags)
+{
+ DBG_HELPER_ARGS(dbg, "exposure=%d, scan_yres=%d, step_type=%d, scan_lines=%d, scan_dummy=%d, "
+ "feed_steps=%d, flags=%x",
+ exposure, scan_yres, static_cast<unsigned>(motor_profile.step_type),
+ scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
+
+ unsigned step_multiplier = 2;
+ bool use_fast_fed = false;
+
+ if ((scan_yres >= 300 && feed_steps > 900) || (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;
+ }
+
+ // in case of automatic go home, move until home sensor
+ if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
+ reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
+ }
+
+ // disable backtracking if needed
+ if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) ||
+ (scan_yres >= 2400) ||
+ (scan_yres >= sensor.full_resolution))
+ {
+ reg02 |= REG_0x02_ACDCDIS;
+ }
+
+ if (has_flag(flags, ScanFlag::REVERSE)) {
+ reg02 |= REG_0x02_MTRREV;
+ } else {
+ reg02 &= ~REG_0x02_MTRREV;
+ }
+ reg->set8(REG_0x02, reg02);
+
+ // scan and backtracking slope table
+ auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres, exposure,
+ step_multiplier, motor_profile);
+
+ scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
+ scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
+ scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table);
+
+ reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
+
+ // fast table
+ const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
+ if (fast_profile == nullptr) {
+ fast_profile = &motor_profile;
+ }
+
+ auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
+ *fast_profile);
+
+ scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
+ scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
+
+ reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
+
+ if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) {
+ std::uint8_t vref = 0;
+ vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL;
+ vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK;
+ vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST;
+ vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME;
+ reg->set8(REG_0x80, vref);
+ }
+
+ // substract acceleration distance from feedl
+ unsigned feedl = feed_steps;
+ feedl <<= static_cast<unsigned>(motor_profile.step_type);
+
+ unsigned dist = scan_table.table.size() / step_multiplier;
+
+ if (use_fast_fed) {
+ dist += (fast_table.table.size() / step_multiplier) * 2;
+ }
+
+ // make sure when don't insane value : XXX STEF XXX in this case we should
+ // fall back to single table move
+ if (dist < feedl) {
+ feedl -= dist;
+ } else {
+ feedl = 1;
+ }
+
+ reg->set24(REG_FEEDL, feedl);
+
+ // doesn't seem to matter that much
+ std::uint32_t z1, z2;
+ sanei_genesys_calculate_zmod(use_fast_fed,
+ exposure,
+ scan_table.table,
+ scan_table.table.size() / step_multiplier,
+ feedl,
+ scan_table.table.size() / step_multiplier,
+ &z1,
+ &z2);
+ if (scan_yres > 600) {
+ z1 = 0;
+ z2 = 0;
+ }
+
+ reg->set24(REG_Z1MOD, z1);
+ reg->set24(REG_Z2MOD, z2);
+
+ reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
+
+ reg->set8_mask(REG_0x67, static_cast<unsigned>(motor_profile.step_type) << REG_0x67S_STEPSEL,
+ REG_0x67_STEPSEL);
+ reg->set8_mask(REG_0x68, static_cast<unsigned>(fast_profile->step_type) << REG_0x68S_FSTPSEL,
+ REG_0x68_FSTPSEL);
+
+ // steps for STOP table
+ reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
+}
+
+static void gl842_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* reg, unsigned int exposure,
+ const ScanSession& session)
+{
+ DBG_HELPER(dbg);
+
+ 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);
+ if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
+ has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
+ session.use_host_side_calib)
+ {
+ reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
+
+ } else {
+ reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
+ }
+
+ bool use_shdarea = true;
+
+ if (use_shdarea) {
+ reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
+ } else {
+ reg->find_reg(REG_0x01).value &= ~REG_0x01_SHDAREA;
+ }
+
+ if (dev->model->model_id == ModelId::CANON_8600F) {
+ reg->find_reg(REG_0x03).value |= REG_0x03_AVEENB;
+ } else {
+ reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
+ }
+
+ // FIXME: we probably don't need to set exposure to registers at this point. It was this way
+ // before a refactor.
+ sanei_genesys_set_lamp_power(dev, sensor, *reg,
+ !has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
+
+ // select XPA
+ reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL;
+ if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
+ reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL;
+ }
+ reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
+
+ // BW threshold
+ reg->set8(REG_0x2E, 0x7f);
+ reg->set8(REG_0x2F, 0x7f);
+
+ // monochrome / color scan parameters
+ std::uint8_t reg04 = reg->get8(REG_0x04);
+ reg04 = reg04 & REG_0x04_FESET;
+
+ switch (session.params.depth) {
+ case 8:
+ break;
+ case 16:
+ reg04 |= REG_0x04_BITSET;
+ break;
+ }
+
+ if (session.params.channels == 1) {
+ switch (session.params.color_filter) {
+ case ColorFilter::RED: reg04 |= 0x14; break;
+ case ColorFilter::BLUE: reg04 |= 0x1c; break;
+ case ColorFilter::GREEN: reg04 |= 0x18; break;
+ default:
+ break; // should not happen
+ }
+ } else {
+ switch (dev->frontend.layout.type) {
+ case FrontendType::WOLFSON:
+ // pixel by pixel
+ reg04 |= 0x10;
+ break;
+ case FrontendType::ANALOG_DEVICES:
+ // slow color pixel by pixel
+ reg04 |= 0x20;
+ break;
+ default:
+ throw SaneException("Invalid frontend type %d",
+ static_cast<unsigned>(dev->frontend.layout.type));
+ }
+ }
+
+ reg->set8(REG_0x04, reg04);
+
+ 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;
+ } else {
+ reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
+ }
+
+ reg->set16(REG_DPISET, sensor.register_dpiset);
+
+ reg->set16(REG_STRPIXEL, session.pixel_startx);
+ reg->set16(REG_ENDPIXEL, session.pixel_endx);
+
+ if (dev->model->is_cis) {
+ reg->set24(REG_MAXWD, session.output_line_bytes_raw * session.params.channels);
+ } else {
+ reg->set24(REG_MAXWD, session.output_line_bytes_raw);
+ }
+
+ unsigned tgtime = exposure / 65536 + 1;
+ reg->set16(REG_LPERIOD, exposure / tgtime);
+
+ reg->set8(REG_DUMMY, sensor.dummy_pixel);
+}
+
+void CommandSetGl842::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* reg,
+ const ScanSession& session) const
+{
+ DBG_HELPER(dbg);
+ session.assert_computed();
+
+ // we enable true gray for cis scanners only, and just when doing scan since color calibration
+ // is OK for this mode
+
+ int dummy = 0;
+
+ /* slope_dpi */
+ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */
+ int slope_dpi = 0;
+ if (dev->model->is_cis) {
+ slope_dpi = session.params.yres * session.params.channels;
+ } else {
+ slope_dpi = session.params.yres;
+ }
+ slope_dpi = slope_dpi * (1 + dummy);
+
+ int exposure = sensor.exposure_lperiod;
+ if (exposure < 0) {
+ throw std::runtime_error("Exposure not defined in sensor definition");
+ }
+ if (dev->model->model_id == ModelId::CANON_LIDE_90) {
+ exposure *= 2;
+ }
+ const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure, session);
+
+ // now _LOGICAL_ optical values used are known, setup registers
+ gl842_init_optical_regs_scan(dev, sensor, reg, exposure, session);
+ gl842_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure, slope_dpi,
+ session.optical_line_count, dummy, session.params.starty,
+ session.params.flags);
+
+ setup_image_pipeline(*dev, session);
+
+ dev->read_active = true;
+
+ dev->session = session;
+
+ dev->total_bytes_read = 0;
+ dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines;
+}
+
+ScanSession CommandSetGl842::calculate_scan_session(const Genesys_Device* dev,
+ const Genesys_Sensor& sensor,
+ const Genesys_Settings& settings) const
+{
+ DBG_HELPER(dbg);
+ debug_dump(DBG_info, settings);
+
+ ScanFlag flags = ScanFlag::NONE;
+
+ float move = 0.0f;
+ if (settings.scan_method == ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
+ // transparency adapter
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
+ }
+ flags |= ScanFlag::USE_XPA;
+ } else {
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset;
+ }
+ }
+
+ move += settings.tl_y;
+
+ int move_dpi = dev->motor.base_ydpi;
+ move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
+
+ float start = 0.0f;
+ if (settings.scan_method==ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ start = dev->model->x_offset_ta;
+ } else {
+ start = dev->model->x_offset;
+ }
+ start = start + settings.tl_x;
+
+ 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 = 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;
+ session.params.depth = settings.depth;
+ session.params.channels = settings.get_channels();
+ session.params.scan_method = settings.scan_method;
+ session.params.scan_mode = settings.scan_mode;
+ session.params.color_filter = settings.color_filter;
+ session.params.flags = flags;
+ compute_session(dev, session, sensor);
+
+ return session;
+}
+
+void CommandSetGl842::save_power(Genesys_Device* dev, bool enable) const
+{
+ (void) dev;
+ DBG_HELPER_ARGS(dbg, "enable = %d", enable);
+}
+
+void CommandSetGl842::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const
+{
+ (void) dev;
+ DBG_HELPER_ARGS(dbg, "delay = %d", delay);
+}
+
+void CommandSetGl842::eject_document(Genesys_Device* dev) const
+{
+ (void) dev;
+ DBG_HELPER(dbg);
+}
+
+
+void CommandSetGl842::load_document(Genesys_Device* dev) const
+{
+ DBG_HELPER(dbg);
+ (void) dev;
+}
+
+void CommandSetGl842::detect_document_end(Genesys_Device* dev) const
+{
+ DBG_HELPER(dbg);
+ (void) dev;
+ throw SaneException(SANE_STATUS_UNSUPPORTED);
+}
+
+// Send the low-level scan command
+void CommandSetGl842::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* reg, bool start_motor) const
+{
+ DBG_HELPER(dbg);
+ (void) sensor;
+
+ if (reg->state.is_xpa_on && reg->state.is_lamp_on &&
+ !has_flag(dev->model->flags, ModelFlag::TA_NO_SECONDARY_LAMP))
+ {
+ dev->cmd_set->set_xpa_lamp_power(*dev, true);
+ }
+ if (reg->state.is_xpa_on && !has_flag(dev->model->flags, ModelFlag::UTA_NO_SECONDARY_MOTOR)) {
+ dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
+ }
+
+ if (dev->model->model_id == ModelId::CANON_LIDE_90) {
+ if (has_flag(dev->session.params.flags, ScanFlag::REVERSE)) {
+ dev->interface->write_register(REG_0x6B, 0x01);
+ dev->interface->write_register(REG_0x6C, 0x02);
+ } else {
+ dev->interface->write_register(REG_0x6B, 0x03);
+ switch (dev->session.params.xres) {
+ case 150: dev->interface->write_register(REG_0x6C, 0x74); break;
+ case 300: dev->interface->write_register(REG_0x6C, 0x38); break;
+ case 600: dev->interface->write_register(REG_0x6C, 0x1c); break;
+ case 1200: dev->interface->write_register(REG_0x6C, 0x2c); break;
+ case 2400: dev->interface->write_register(REG_0x6C, 0x0c); break;
+ default:
+ break;
+ }
+ }
+ dev->interface->sleep_ms(100);
+ }
+
+ scanner_clear_scan_and_feed_counts(*dev);
+
+ // enable scan and motor
+ std::uint8_t val = dev->interface->read_register(REG_0x01);
+ val |= REG_0x01_SCAN;
+ dev->interface->write_register(REG_0x01, val);
+
+ scanner_start_action(*dev, start_motor);
+
+ switch (reg->state.motor_mode) {
+ case MotorMode::PRIMARY: {
+ if (reg->state.is_motor_on) {
+ dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
+ }
+ break;
+ }
+ case MotorMode::PRIMARY_AND_SECONDARY: {
+ if (reg->state.is_motor_on) {
+ dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
+ dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
+ }
+ break;
+ }
+ case MotorMode::SECONDARY: {
+ if (reg->state.is_motor_on) {
+ dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
+ }
+ break;
+ }
+ }
+}
+
+void CommandSetGl842::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
+ bool check_stop) const
+{
+ DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
+
+ if (reg->state.is_xpa_on) {
+ dev->cmd_set->set_xpa_lamp_power(*dev, false);
+ }
+
+ if (!dev->model->is_sheetfed) {
+ scanner_stop_action(*dev);
+ }
+}
+
+void CommandSetGl842::move_back_home(Genesys_Device* dev, bool wait_until_home) const
+{
+ scanner_move_back_home(*dev, wait_until_home);
+}
+
+void CommandSetGl842::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs) const
+{
+ DBG_HELPER(dbg);
+ int move;
+
+ float calib_size_mm = 0;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ calib_size_mm = dev->model->y_size_calib_ta_mm;
+ } else {
+ calib_size_mm = dev->model->y_size_calib_mm;
+ }
+
+ unsigned resolution = sensor.shading_resolution;
+
+ unsigned channels = 3;
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
+ dev->settings.scan_method);
+
+ unsigned calib_pixels = 0;
+ unsigned calib_pixels_offset = 0;
+
+ if (should_calibrate_only_active_area(*dev, dev->settings)) {
+ float offset = dev->model->x_offset_ta;
+ // FIXME: we should use resolution here
+ offset = static_cast<float>((offset * dev->settings.xres) / MM_PER_INCH);
+
+ float size = dev->model->x_size_ta;
+ size = static_cast<float>((size * dev->settings.xres) / MM_PER_INCH);
+
+ calib_pixels_offset = static_cast<std::size_t>(offset);
+ calib_pixels = static_cast<std::size_t>(size);
+ } else {
+ calib_pixels_offset = 0;
+ calib_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
+ }
+
+ ScanFlag flags = ScanFlag::DISABLE_SHADING |
+ ScanFlag::DISABLE_GAMMA |
+ ScanFlag::DISABLE_BUFFER_FULL_MOVE;
+
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
+ // transparency adapter
+ move = static_cast<int>(dev->model->y_offset_calib_white_ta -
+ dev->model->y_offset_sensor_to_ta);
+ flags |= ScanFlag::USE_XPA;
+ } else {
+ move = static_cast<int>(dev->model->y_offset_calib_white);
+ }
+
+ move = static_cast<int>((move * resolution) / MM_PER_INCH);
+ unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
+
+ ScanSession session;
+ session.params.xres = resolution;
+ session.params.yres = resolution;
+ session.params.startx = calib_pixels_offset;
+ session.params.starty = move;
+ session.params.pixels = calib_pixels;
+ session.params.lines = calib_lines;
+ session.params.depth = 16;
+ session.params.channels = 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 = flags;
+ compute_session(dev, session, calib_sensor);
+
+ init_regs_for_scan_session(dev, calib_sensor, &regs, session);
+
+ dev->calib_session = session;
+}
+
+void CommandSetGl842::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
+{
+ DBG_HELPER(dbg);
+
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200)
+ return; // No gamma on this model
+
+ unsigned size = 256;
+
+ std::vector<uint8_t> gamma(size * 2 * 3);
+
+ std::vector<uint16_t> rgamma = get_gamma_table(dev, sensor, GENESYS_RED);
+ std::vector<uint16_t> ggamma = get_gamma_table(dev, sensor, GENESYS_GREEN);
+ std::vector<uint16_t> bgamma = get_gamma_table(dev, sensor, GENESYS_BLUE);
+
+ // copy sensor specific's gamma tables
+ for (unsigned i = 0; i < size; i++) {
+ gamma[i * 2 + size * 0 + 0] = rgamma[i] & 0xff;
+ gamma[i * 2 + size * 0 + 1] = (rgamma[i] >> 8) & 0xff;
+ gamma[i * 2 + size * 2 + 0] = ggamma[i] & 0xff;
+ gamma[i * 2 + size * 2 + 1] = (ggamma[i] >> 8) & 0xff;
+ gamma[i * 2 + size * 4 + 0] = bgamma[i] & 0xff;
+ gamma[i * 2 + size * 4 + 1] = (bgamma[i] >> 8) & 0xff;
+ }
+
+ dev->interface->write_gamma(0x28, 0x0000, gamma.data(), size * 2 * 3);
+}
+
+SensorExposure CommandSetGl842::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs) const
+{
+ return scanner_led_calibration(*dev, sensor, regs);
+}
+
+void CommandSetGl842::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs) const
+{
+ scanner_offset_calibration(*dev, sensor, regs);
+}
+
+void CommandSetGl842::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs, int dpi) const
+{
+ scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
+}
+
+void CommandSetGl842::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* reg) const
+{
+ DBG_HELPER(dbg);
+ (void) sensor;
+
+ unsigned channels = 3;
+ unsigned resolution = dev->model->get_resolution_settings(dev->settings.scan_method)
+ .get_nearest_resolution_x(600);
+
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
+ dev->settings.scan_method);
+ unsigned num_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH / 2;
+
+ *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 = resolution;
+ session.params.yres = resolution;
+ session.params.startx = (num_pixels / 2) * resolution / calib_sensor.full_resolution;
+ session.params.starty = 0;
+ session.params.pixels = num_pixels;
+ session.params.lines = 1;
+ session.params.depth = dev->model->bpp_color_values.front();
+ 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 = flags;
+
+ compute_session(dev, session, calib_sensor);
+
+ init_regs_for_scan_session(dev, calib_sensor, reg, session);
+
+ sanei_genesys_set_motor_power(*reg, false);
+}
+
+static void gl842_init_gpio(Genesys_Device* dev)
+{
+ DBG_HELPER(dbg);
+ apply_registers_ordered(dev->gpo.regs, { 0x6e, 0x6f }, [&](const GenesysRegisterSetting& reg)
+ {
+ dev->interface->write_register(reg.address, reg.value);
+ });
+}
+
+void CommandSetGl842::asic_boot(Genesys_Device* dev, bool cold) const
+{
+ DBG_HELPER(dbg);
+
+ if (cold) {
+ dev->interface->write_register(0x0e, 0x01);
+ dev->interface->write_register(0x0e, 0x00);
+ }
+
+ // setup initial register values
+ gl842_init_registers(*dev);
+ dev->interface->write_registers(dev->reg);
+
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ uint8_t data[32] = {
+ 0xd0, 0x38, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6a, 0x73, 0x63, 0x68, 0x69, 0x65, 0x6e, 0x00,
+ };
+
+ dev->interface->write_buffer(0x3c, 0x010a00, data, 32);
+ }
+
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
+ dev->interface->write_0x8c(0x10, 0x94);
+ }
+ if (dev->model->model_id == ModelId::CANON_LIDE_90) {
+ dev->interface->write_0x8c(0x10, 0xd4);
+ }
+
+ // set RAM read address
+ dev->interface->write_register(REG_0x2A, 0x00);
+ dev->interface->write_register(REG_0x2B, 0x00);
+
+ // setup gpio
+ gl842_init_gpio(dev);
+ dev->interface->sleep_ms(100);
+}
+
+void CommandSetGl842::init(Genesys_Device* dev) const
+{
+ DBG_INIT();
+ DBG_HELPER(dbg);
+
+ sanei_genesys_asic_init(dev);
+}
+
+void CommandSetGl842::update_hardware_sensors(Genesys_Scanner* s) const
+{
+ DBG_HELPER(dbg);
+ (void) s;
+}
+
+void CommandSetGl842::update_home_sensor_gpio(Genesys_Device& dev) const
+{
+ DBG_HELPER(dbg);
+ if (dev.model->model_id == ModelId::CANON_LIDE_90) {
+ std::uint8_t val = dev.interface->read_register(REG_0x6C);
+ val |= 0x02;
+ dev.interface->write_register(REG_0x6C, val);
+ }
+}
+
+/**
+ * Send shading calibration data. The buffer is considered to always hold values
+ * for all the channels.
+ */
+void CommandSetGl842::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ uint8_t* data, int size) const
+{
+ DBG_HELPER(dbg);
+
+ int offset = 0;
+ unsigned length = size;
+
+ if (dev->reg.get8(REG_0x01) & REG_0x01_SHDAREA) {
+ offset = dev->session.params.startx * sensor.shading_resolution /
+ dev->session.params.xres;
+
+ length = dev->session.output_pixels * sensor.shading_resolution /
+ dev->session.params.xres;
+
+ offset += sensor.shading_pixel_offset;
+
+ // 16 bit words, 2 words per color, 3 color channels
+ length *= 2 * 2 * 3;
+ offset *= 2 * 2 * 3;
+ } else {
+ offset += sensor.shading_pixel_offset * 2 * 2 * 3;
+ }
+
+ dev->interface->record_key_value("shading_offset", std::to_string(offset));
+ dev->interface->record_key_value("shading_length", std::to_string(length));
+
+ std::vector<uint8_t> final_data(length, 0);
+
+ unsigned count = 0;
+ if (offset < 0) {
+ count += (-offset);
+ length -= (-offset);
+ offset = 0;
+ }
+ if (static_cast<int>(length) + offset > static_cast<int>(size)) {
+ length = size - offset;
+ }
+
+ for (unsigned i = 0; i < length; i++) {
+ final_data[count++] = data[offset + i];
+ count++;
+ }
+
+ dev->interface->write_buffer(0x3c, 0, final_data.data(), count);
+}
+
+bool CommandSetGl842::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
+{
+ (void) dev;
+ return true;
+}
+
+void CommandSetGl842::wait_for_motor_stop(Genesys_Device* dev) const
+{
+ (void) dev;
+}
+
+} // namespace gl842
+} // namespace genesys
diff --git a/backend/genesys/gl842.h b/backend/genesys/gl842.h
new file mode 100644
index 0000000..288d29c
--- /dev/null
+++ b/backend/genesys/gl842.h
@@ -0,0 +1,128 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice.
+*/
+
+#include "genesys.h"
+#include "command_set_common.h"
+
+#ifndef BACKEND_GENESYS_GL842_H
+#define BACKEND_GENESYS_GL842_H
+
+namespace genesys {
+namespace gl842 {
+
+class CommandSetGl842 : public CommandSetCommon
+{
+public:
+ ~CommandSetGl842() override = default;
+
+ bool needs_home_before_init_regs_for_scan(Genesys_Device* dev) const override;
+
+ void init(Genesys_Device* dev) const override;
+
+ void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* regs) const override;
+
+ void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs) const override;
+
+ void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* reg,
+ const ScanSession& session) const override;
+
+ void set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const override;
+ void set_powersaving(Genesys_Device* dev, int delay) const override;
+ void save_power(Genesys_Device* dev, bool enable) const override;
+
+ void begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* regs, bool start_motor) const override;
+
+ void end_scan(Genesys_Device* dev, Genesys_Register_Set* regs, bool check_stop) const override;
+
+ void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
+
+ void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs) const override;
+
+ void coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs, int dpi) const override;
+
+ SensorExposure led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs) const override;
+
+ void wait_for_motor_stop(Genesys_Device* dev) const override;
+
+ void move_back_home(Genesys_Device* dev, bool wait_until_home) const override;
+
+ void update_hardware_sensors(struct Genesys_Scanner* s) const override;
+
+ void update_home_sensor_gpio(Genesys_Device& dev) const override;
+
+ void load_document(Genesys_Device* dev) const override;
+
+ void detect_document_end(Genesys_Device* dev) const override;
+
+ void eject_document(Genesys_Device* dev) const override;
+
+ void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
+ int size) const override;
+
+ ScanSession calculate_scan_session(const Genesys_Device* dev,
+ const Genesys_Sensor& sensor,
+ const Genesys_Settings& settings) const override;
+
+ void asic_boot(Genesys_Device* dev, bool cold) const override;
+};
+
+enum SlopeTable
+{
+ SCAN_TABLE = 0, // table 1 at 0x4000
+ BACKTRACK_TABLE = 1, // table 2 at 0x4800
+ STOP_TABLE = 2, // table 3 at 0x5000
+ FAST_TABLE = 3, // table 4 at 0x5800
+ HOME_TABLE = 4, // table 5 at 0x6000
+};
+
+} // namespace gl842
+} // namespace genesys
+
+#endif // BACKEND_GENESYS_GL842_H
diff --git a/backend/genesys/gl842_registers.h b/backend/genesys/gl842_registers.h
new file mode 100644
index 0000000..b6934ce
--- /dev/null
+++ b/backend/genesys/gl842_registers.h
@@ -0,0 +1,285 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice.
+*/
+
+#ifndef BACKEND_GENESYS_gl842_REGISTERS_H
+#define BACKEND_GENESYS_gl842_REGISTERS_H
+
+#include <cstdint>
+
+namespace genesys {
+namespace gl842 {
+
+using RegAddr = std::uint16_t;
+using RegMask = std::uint8_t;
+using RegShift = unsigned;
+
+static constexpr RegAddr REG_0x01 = 0x01;
+static constexpr RegMask REG_0x01_CISSET = 0x80;
+static constexpr RegMask REG_0x01_DOGENB = 0x40;
+static constexpr RegMask REG_0x01_DVDSET = 0x20;
+static constexpr RegMask REG_0x01_M15DRAM = 0x08;
+static constexpr RegMask REG_0x01_DRAMSEL = 0x04;
+static constexpr RegMask REG_0x01_SHDAREA = 0x02;
+static constexpr RegMask REG_0x01_SCAN = 0x01;
+
+static constexpr RegAddr REG_0x02 = 0x02;
+static constexpr RegMask REG_0x02_NOTHOME = 0x80;
+static constexpr RegMask REG_0x02_ACDCDIS = 0x40;
+static constexpr RegMask REG_0x02_AGOHOME = 0x20;
+static constexpr RegMask REG_0x02_MTRPWR = 0x10;
+static constexpr RegMask REG_0x02_FASTFED = 0x08;
+static constexpr RegMask REG_0x02_MTRREV = 0x04;
+static constexpr RegMask REG_0x02_HOMENEG = 0x02;
+static constexpr RegMask REG_0x02_LONGCURV = 0x01;
+
+static constexpr RegAddr REG_0x03 = 0x03;
+static constexpr RegMask REG_0x03_LAMPDOG = 0x80;
+static constexpr RegMask REG_0x03_AVEENB = 0x40;
+static constexpr RegMask REG_0x03_XPASEL = 0x20;
+static constexpr RegMask REG_0x03_LAMPPWR = 0x10;
+static constexpr RegMask REG_0x03_LAMPTIM = 0x0f;
+
+static constexpr RegAddr REG_0x04 = 0x04;
+static constexpr RegMask REG_0x04_LINEART = 0x80;
+static constexpr RegMask REG_0x04_BITSET = 0x40;
+static constexpr RegMask REG_0x04_AFEMOD = 0x30;
+static constexpr RegMask REG_0x04_FILTER = 0x0c;
+static constexpr RegMask REG_0x04_FESET = 0x03;
+
+static constexpr RegShift REG_0x04S_AFEMOD = 4;
+
+static constexpr RegAddr REG_0x05 = 0x05;
+static constexpr RegMask REG_0x05_DPIHW = 0xc0;
+static constexpr RegMask REG_0x05_DPIHW_600 = 0x00;
+static constexpr RegMask REG_0x05_DPIHW_1200 = 0x40;
+static constexpr RegMask REG_0x05_DPIHW_2400 = 0x80;
+static constexpr RegMask REG_0x05_DPIHW_4800 = 0xc0;
+static constexpr RegMask REG_0x05_MTLLAMP = 0x30;
+static constexpr RegMask REG_0x05_GMMENB = 0x08;
+static constexpr RegMask REG_0x05_MTLBASE = 0x03;
+
+static constexpr RegAddr REG_0x06 = 0x06;
+static constexpr RegMask REG_0x06_SCANMOD = 0xe0;
+static constexpr RegShift REG_0x06S_SCANMOD = 5;
+static constexpr RegMask REG_0x06_PWRBIT = 0x10;
+static constexpr RegMask REG_0x06_GAIN4 = 0x08;
+static constexpr RegMask REG_0x06_OPTEST = 0x07;
+
+static constexpr RegMask REG_0x08_DECFLAG = 0x40;
+static constexpr RegMask REG_0x08_GMMFFR = 0x20;
+static constexpr RegMask REG_0x08_GMMFFG = 0x10;
+static constexpr RegMask REG_0x08_GMMFFB = 0x08;
+static constexpr RegMask REG_0x08_GMMZR = 0x04;
+static constexpr RegMask REG_0x08_GMMZG = 0x02;
+static constexpr RegMask REG_0x08_GMMZB = 0x01;
+
+static constexpr RegMask REG_0x09_MCNTSET = 0xc0;
+static constexpr RegMask REG_0x09_CLKSET = 0x30;
+static constexpr RegMask REG_0x09_BACKSCAN = 0x08;
+static constexpr RegMask REG_0x09_ENHANCE = 0x04;
+static constexpr RegMask REG_0x09_SHORTTG = 0x02;
+static constexpr RegMask REG_0x09_NWAIT = 0x01;
+
+static constexpr RegAddr REG_0x0D = 0x0d;
+static constexpr RegMask REG_0x0D_CLRLNCNT = 0x01;
+
+static constexpr RegAddr REG_0x0F = 0x0f;
+
+static constexpr RegAddr REG_EXPR = 0x10;
+static constexpr RegAddr REG_EXPG = 0x12;
+static constexpr RegAddr REG_EXPB = 0x14;
+
+static constexpr RegMask REG_0x16_CTRLHI = 0x80;
+static constexpr RegMask REG_0x16_TOSHIBA = 0x40;
+static constexpr RegMask REG_0x16_TGINV = 0x20;
+static constexpr RegMask REG_0x16_CK1INV = 0x10;
+static constexpr RegMask REG_0x16_CK2INV = 0x08;
+static constexpr RegMask REG_0x16_CTRLINV = 0x04;
+static constexpr RegMask REG_0x16_CKDIS = 0x02;
+static constexpr RegMask REG_0x16_CTRLDIS = 0x01;
+
+static constexpr RegMask REG_0x17_TGMODE = 0xc0;
+static constexpr RegMask REG_0x17_TGMODE_NO_DUMMY = 0x00;
+static constexpr RegMask REG_0x17_TGMODE_REF = 0x40;
+static constexpr RegMask REG_0x17_TGMODE_XPA = 0x80;
+static constexpr RegMask REG_0x17_TGW = 0x3f;
+
+static constexpr RegAddr REG_0x18 = 0x18;
+static constexpr RegMask REG_0x18_CNSET = 0x80;
+static constexpr RegMask REG_0x18_DCKSEL = 0x60;
+static constexpr RegMask REG_0x18_CKTOGGLE = 0x10;
+static constexpr RegMask REG_0x18_CKDELAY = 0x0c;
+static constexpr RegMask REG_0x18_CKSEL = 0x03;
+
+static constexpr RegAddr REG_EXPDMY = 0x19;
+
+static constexpr RegAddr REG_0x1A = 0x1a;
+static constexpr RegMask REG_0x1A_MANUAL3 = 0x02;
+static constexpr RegMask REG_0x1A_MANUAL1 = 0x01;
+static constexpr RegMask REG_0x1A_CK4INV = 0x08;
+static constexpr RegMask REG_0x1A_CK3INV = 0x04;
+static constexpr RegMask REG_0x1A_LINECLP = 0x02;
+
+static constexpr RegAddr REG_0x1C = 0x1c;
+static constexpr RegMask REG_0x1C_TGTIME = 0x07;
+
+static constexpr RegMask REG_0x1D_CK4LOW = 0x80;
+static constexpr RegMask REG_0x1D_CK3LOW = 0x40;
+static constexpr RegMask REG_0x1D_CK1LOW = 0x20;
+static constexpr RegMask REG_0x1D_TGSHLD = 0x1f;
+
+static constexpr RegAddr REG_0x1E = 0x1e;
+static constexpr RegMask REG_0x1E_WDTIME = 0xf0;
+static constexpr RegShift REG_0x1ES_WDTIME = 4;
+static constexpr RegMask REG_0x1E_LINESEL = 0x0f;
+static constexpr RegShift REG_0x1ES_LINESEL = 0;
+
+static constexpr RegAddr REG_0x21 = 0x21;
+static constexpr RegAddr REG_STEPNO = 0x21;
+static constexpr RegAddr REG_FWDSTEP = 0x22;
+static constexpr RegAddr REG_BWDSTEP = 0x23;
+static constexpr RegAddr REG_FASTNO = 0x24;
+static constexpr RegAddr REG_LINCNT = 0x25;
+
+static constexpr RegAddr REG_0x29 = 0x29;
+static constexpr RegAddr REG_0x2A = 0x2a;
+static constexpr RegAddr REG_0x2B = 0x2b;
+static constexpr RegAddr REG_DPISET = 0x2c;
+static constexpr RegAddr REG_0x2E = 0x2e;
+static constexpr RegAddr REG_0x2F = 0x2f;
+
+static constexpr RegAddr REG_STRPIXEL = 0x30;
+static constexpr RegAddr REG_ENDPIXEL = 0x32;
+static constexpr RegAddr REG_DUMMY = 0x34;
+static constexpr RegAddr REG_MAXWD = 0x35;
+static constexpr RegAddr REG_LPERIOD = 0x38;
+static constexpr RegAddr REG_FEEDL = 0x3d;
+
+static constexpr RegAddr REG_0x40 = 0x40;
+static constexpr RegMask REG_0x40_HISPDFLG = 0x04;
+static constexpr RegMask REG_0x40_MOTMFLG = 0x02;
+static constexpr RegMask REG_0x40_DATAENB = 0x01;
+
+static constexpr RegMask REG_0x41_PWRBIT = 0x80;
+static constexpr RegMask REG_0x41_BUFEMPTY = 0x40;
+static constexpr RegMask REG_0x41_FEEDFSH = 0x20;
+static constexpr RegMask REG_0x41_SCANFSH = 0x10;
+static constexpr RegMask REG_0x41_HOMESNR = 0x08;
+static constexpr RegMask REG_0x41_LAMPSTS = 0x04;
+static constexpr RegMask REG_0x41_FEBUSY = 0x02;
+static constexpr RegMask REG_0x41_MOTORENB = 0x01;
+
+static constexpr RegMask REG_0x5A_ADCLKINV = 0x80;
+static constexpr RegMask REG_0x5A_RLCSEL = 0x40;
+static constexpr RegMask REG_0x5A_CDSREF = 0x30;
+static constexpr RegShift REG_0x5AS_CDSREF = 4;
+static constexpr RegMask REG_0x5A_RLC = 0x0f;
+static constexpr RegShift REG_0x5AS_RLC = 0;
+
+static constexpr RegAddr REG_0x5E = 0x5e;
+static constexpr RegMask REG_0x5E_DECSEL = 0xe0;
+static constexpr RegShift REG_0x5ES_DECSEL = 5;
+static constexpr RegMask REG_0x5E_STOPTIM = 0x1f;
+static constexpr RegShift REG_0x5ES_STOPTIM = 0;
+
+static constexpr RegAddr REG_FMOVDEC = 0x5f;
+
+static constexpr RegAddr REG_0x60 = 0x60;
+static constexpr RegMask REG_0x60_Z1MOD = 0x1f;
+static constexpr RegAddr REG_0x61 = 0x61;
+static constexpr RegMask REG_0x61_Z1MOD = 0xff;
+static constexpr RegAddr REG_0x62 = 0x62;
+static constexpr RegMask REG_0x62_Z1MOD = 0xff;
+
+static constexpr RegAddr REG_0x63 = 0x63;
+static constexpr RegMask REG_0x63_Z2MOD = 0x1f;
+static constexpr RegAddr REG_0x64 = 0x64;
+static constexpr RegMask REG_0x64_Z2MOD = 0xff;
+static constexpr RegAddr REG_0x65 = 0x65;
+static constexpr RegMask REG_0x65_Z2MOD = 0xff;
+
+static constexpr RegAddr REG_0x67 = 0x67;
+static constexpr RegAddr REG_0x68 = 0x68;
+
+static constexpr RegShift REG_0x67S_STEPSEL = 6;
+static constexpr RegMask REG_0x67_STEPSEL = 0xc0;
+
+static constexpr RegShift REG_0x68S_FSTPSEL = 6;
+static constexpr RegMask REG_0x68_FSTPSEL = 0xc0;
+
+static constexpr RegAddr REG_FSHDEC = 0x69;
+static constexpr RegAddr REG_FMOVNO = 0x6a;
+
+static constexpr RegAddr REG_0x6B = 0x6b;
+static constexpr RegMask REG_0x6B_MULTFILM = 0x80;
+
+static constexpr RegAddr REG_Z1MOD = 0x60;
+static constexpr RegAddr REG_Z2MOD = 0x63;
+
+static constexpr RegAddr REG_0x6C = 0x6c;
+static constexpr RegAddr REG_0x6D = 0x6d;
+static constexpr RegAddr REG_0x6E = 0x6e;
+static constexpr RegAddr REG_0x6F = 0x6f;
+
+static constexpr RegAddr REG_CK1MAP = 0x74;
+static constexpr RegAddr REG_CK3MAP = 0x77;
+static constexpr RegAddr REG_CK4MAP = 0x7a;
+
+static constexpr RegAddr REG_0x7E = 0x7e;
+
+static constexpr RegAddr REG_0x80 = 0x80;
+static constexpr RegMask REG_0x80_TABLE1_NORMAL = 0x03;
+static constexpr RegShift REG_0x80S_TABLE1_NORMAL = 0;
+static constexpr RegMask REG_0x80_TABLE2_BACK = 0x0c;
+static constexpr RegShift REG_0x80S_TABLE2_BACK = 2;
+static constexpr RegMask REG_0x80_TABLE4_FAST = 0x30;
+static constexpr RegShift REG_0x80S_TABLE4_FAST = 4;
+static constexpr RegMask REG_0x80_TABLE5_GO_HOME = 0xc0;
+static constexpr RegShift REG_0x80S_TABLE5_GO_HOME = 6;
+
+static constexpr RegMask REG_0x87_LEDADD = 0x04;
+
+} // namespace gl842
+} // namespace genesys
+
+#endif // BACKEND_GENESYS_gl842_REGISTERS_H
diff --git a/backend/genesys/gl843.cpp b/backend/genesys/gl843.cpp
index f83ac8d..8233bde 100644
--- a/backend/genesys/gl843.cpp
+++ b/backend/genesys/gl843.cpp
@@ -54,60 +54,18 @@
namespace genesys {
namespace gl843 {
-// Set address for writing data
-static void gl843_set_buffer_address(Genesys_Device* dev, uint32_t addr)
-{
- DBG_HELPER_ARGS(dbg, "setting address to 0x%05x", addr & 0xffff);
-
- dev->interface->write_register(0x5b, ((addr >> 8) & 0xff));
- dev->interface->write_register(0x5c, (addr & 0xff));
-}
-
/**
* compute the step multiplier used
*/
static int gl843_get_step_multiplier(Genesys_Register_Set* regs)
{
- GenesysRegister *r = sanei_genesys_get_address(regs, REG_0x9D);
- int value = 1;
- if (r != nullptr)
- {
- switch (r->value & 0x0c)
- {
- case 0x04:
- value = 2;
- break;
- case 0x08:
- value = 4;
- break;
- default:
- value = 1;
- }
- }
- DBG(DBG_io, "%s: step multiplier is %d\n", __func__, value);
- return value;
-}
-
-/** copy sensor specific settings */
-static void gl843_setup_sensor(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs)
-{
- DBG_HELPER(dbg);
- for (const auto& custom_reg : sensor.custom_regs) {
- regs->set8(custom_reg.address, custom_reg.value);
+ switch (regs->get8(REG_0x9D) & 0x0c) {
+ case 0x04: return 2;
+ case 0x08: return 4;
+ default: return 1;
}
- if (!(dev->model->flags & GENESYS_FLAG_FULL_HWDPI_MODE) &&
- dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
- dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300 &&
- dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7500I)
- {
- regs->set8(0x7d, 0x90);
- }
-
- dev->segment_order = sensor.segment_order;
}
-
/** @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.
@@ -118,9 +76,9 @@ static void gl843_setup_sensor(Genesys_Device* dev, const Genesys_Sensor& sensor
static void
gl843_init_registers (Genesys_Device * dev)
{
- // Within this function SENSOR_DEF marker documents that a register is part
- // of the sensors definition and the actual value is set in
- // gl843_setup_sensor().
+ // Within this function SENSOR_DEF marker documents that a register is part
+ // of the sensors definition and the actual value is set in
+ // scanner_setup_sensor().
// 0x6c, 0x6d, 0x6e, 0x6f, 0xa6, 0xa7, 0xa8, 0xa9 are defined in the Gpo sensor struct
@@ -158,8 +116,16 @@ gl843_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0x05, 0x08);
}
+ auto initial_scan_method = dev->model->default_method;
+ if (dev->model->model_id == ModelId::CANON_4400F ||
+ dev->model->model_id == ModelId::CANON_8600F)
+ {
+ initial_scan_method = ScanMethod::TRANSPARENCY;
+ }
const auto& sensor = sanei_genesys_find_sensor_any(dev);
- sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
+ const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution,
+ 3, initial_scan_method);
+ sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw);
// TODO: on 8600F the windows driver turns off GAIN4 which is recommended
dev->reg.init_reg(0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */
@@ -402,11 +368,11 @@ gl843_init_registers (Genesys_Device * dev)
// STEPSEL[0:1]. Motor movement step mode selection for tables 1-3 in
// scanning mode.
// MTRPWM[0:5]. Motor phase PWM duty cycle setting for tables 1-3
- dev->reg.init_reg(0x67, 0x7f);
+ dev->reg.init_reg(0x67, 0x7f); // MOTOR_PROFILE
// FSTPSEL[0:1]: Motor movement step mode selection for tables 4-5 in
// command mode.
// FASTPWM[5:0]: Motor phase PWM duty cycle setting for tables 4-5
- dev->reg.init_reg(0x68, 0x7f);
+ dev->reg.init_reg(0x68, 0x7f); // MOTOR_PROFILE
if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300) {
dev->reg.init_reg(0x67, 0x80);
@@ -415,17 +381,11 @@ gl843_init_registers (Genesys_Device * dev)
// FSHDEC[0:7]: The number of deceleration steps after scanning is finished
// (table 3)
- dev->reg.init_reg(0x69, 0x01);
- if (dev->model->model_id == ModelId::CANON_8600F) {
- dev->reg.init_reg(0x69, 64);
- }
+ dev->reg.init_reg(0x69, 0x01); // MOTOR_PROFILE
// FMOVNO[0:7] The number of acceleration or deceleration steps for fast
// moving (table 4)
- dev->reg.init_reg(0x6a, 0x04);
- if (dev->model->model_id == ModelId::CANON_8600F) {
- dev->reg.init_reg(0x69, 64);
- }
+ dev->reg.init_reg(0x6a, 0x04); // MOTOR_PROFILE
// GPIO-related register bits
dev->reg.init_reg(0x6b, 0x30);
@@ -516,7 +476,7 @@ gl843_init_registers (Genesys_Device * dev)
// VRHOME, VRMOVE, VRBACK, VRSCAN: Vref settings of the motor driver IC for
// moving in various situations.
- dev->reg.init_reg(0x80, 0x00);
+ dev->reg.init_reg(0x80, 0x00); // MOTOR_PROFILE
if (dev->model->model_id == ModelId::CANON_4400F) {
dev->reg.init_reg(0x80, 0x0c);
}
@@ -632,7 +592,7 @@ gl843_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0xaa, 0x00);
}
- // GPOM9, MULSTOP[0-2], NODECEL, TB3TB1, TB5TB2, FIX16CLK. Not documented
+ // GPOM9, MULSTOP[0-2], NODECEL, TB3TB1, TB5TB2, FIX16CLK.
if (dev->model->model_id != ModelId::CANON_8400F &&
dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7200I &&
dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7300) {
@@ -643,10 +603,9 @@ gl843_init_registers (Genesys_Device * dev)
}
if (dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
+ dev->model->model_id == ModelId::CANON_8600F ||
dev->model->model_id == ModelId::HP_SCANJET_4850C)
{
- // BUG: this should apply to ModelId::CANON_CANOSCAN_8600F too, but due to previous bug
- // the 8400F case overwrote it
dev->reg.init_reg(0xab, 0x40);
}
@@ -660,8 +619,6 @@ gl843_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0xac, 0x00);
}
- dev->calib_reg = dev->reg;
-
if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I) {
uint8_t data[32] = {
0x8c, 0x8f, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00,
@@ -670,48 +627,8 @@ gl843_init_registers (Genesys_Device * dev)
0x6a, 0x73, 0x63, 0x68, 0x69, 0x65, 0x6e, 0x00,
};
- dev->interface->write_buffer(0x3c, 0x3ff000, data, 32,
- ScannerInterface::FLAG_SWAP_REGISTERS);
- }
-}
-
-// Send slope table for motor movement slope_table in machine byte order
-static void gl843_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];
-
- 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+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);
+ dev->interface->write_buffer(0x3c, 0x3ff000, data, 32);
}
-
- // slope table addresses are fixed : 0x40000, 0x48000, 0x50000, 0x58000, 0x60000
- // XXX STEF XXX USB 1.1 ? sanei_genesys_write_0x8c (dev, 0x0f, 0x14);
- dev->interface->write_gamma(0x28, 0x40000 + 0x8000 * table_nr, table.data(), steps * 2,
- ScannerInterface::FLAG_SWAP_REGISTERS);
-
- // FIXME: remove this when updating tests
- gl843_set_buffer_address(dev, 0);
}
static void gl843_set_ad_fe(Genesys_Device* dev)
@@ -728,14 +645,9 @@ void CommandSetGl843::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
set == AFE_SET ? "set" :
set == AFE_POWER_SAVE ? "powersave" : "huh?");
(void) sensor;
- 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;
- dev->frontend_is_init = true;
+ if (set == AFE_INIT) {
+ dev->frontend = dev->frontend_initial;
}
// check analog frontend type
@@ -749,153 +661,135 @@ void CommandSetGl843::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
throw SaneException(SANE_STATUS_UNSUPPORTED, "unsupported frontend type %d", fe_type);
}
- DBG(DBG_proc, "%s(): frontend reset complete\n", __func__);
-
- for (i = 1; i <= 3; i++)
- {
- // FIXME: the check below is just historical artifact, we can remove it when convenient
- if (!dev->frontend_is_init) {
- dev->interface->write_fe_register(i, 0x00);
- } else {
- dev->interface->write_fe_register(i, dev->frontend.regs.get_value(0x00 + i));
- }
+ for (unsigned i = 1; i <= 3; i++) {
+ dev->interface->write_fe_register(i, dev->frontend.regs.get_value(0x00 + i));
}
for (const auto& reg : sensor.custom_fe_regs) {
dev->interface->write_fe_register(reg.address, reg.value);
}
- for (i = 0; i < 3; i++)
- {
- // FIXME: the check below is just historical artifact, we can remove it when convenient
- if (!dev->frontend_is_init) {
- dev->interface->write_fe_register(0x20 + i, 0x00);
- } else {
- dev->interface->write_fe_register(0x20 + i, dev->frontend.get_offset(i));
- }
+ for (unsigned i = 0; i < 3; i++) {
+ dev->interface->write_fe_register(0x20 + i, dev->frontend.get_offset(i));
}
if (dev->model->sensor_id == SensorId::CCD_KVSS080) {
- for (i = 0; i < 3; i++)
- {
- // FIXME: the check below is just historical artifact, we can remove it when convenient
- if (!dev->frontend_is_init) {
- dev->interface->write_fe_register(0x24 + i, 0x00);
- } else {
- dev->interface->write_fe_register(0x24 + i, dev->frontend.regs.get_value(0x24 + i));
- }
- }
+ for (unsigned i = 0; i < 3; i++) {
+ dev->interface->write_fe_register(0x24 + i, dev->frontend.regs.get_value(0x24 + i));
+ }
}
- for (i = 0; i < 3; i++)
- {
- // FIXME: the check below is just historical artifact, we can remove it when convenient
- if (!dev->frontend_is_init) {
- dev->interface->write_fe_register(0x28 + i, 0x00);
- } else {
- dev->interface->write_fe_register(0x28 + i, dev->frontend.get_gain(i));
- }
+ for (unsigned i = 0; i < 3; i++) {
+ dev->interface->write_fe_register(0x28 + i, dev->frontend.get_gain(i));
}
}
-
static void gl843_init_motor_regs_scan(Genesys_Device* dev,
const Genesys_Sensor& sensor,
+ const ScanSession& session,
Genesys_Register_Set* reg,
- const Motor_Profile& motor_profile,
+ const MotorProfile& motor_profile,
unsigned int exposure,
unsigned scan_yres,
unsigned int scan_lines,
unsigned int scan_dummy,
unsigned int feed_steps,
- MotorFlag flags)
+ ScanFlag flags)
{
DBG_HELPER_ARGS(dbg, "exposure=%d, scan_yres=%d, step_type=%d, scan_lines=%d, scan_dummy=%d, "
"feed_steps=%d, flags=%x",
exposure, scan_yres, static_cast<unsigned>(motor_profile.step_type),
scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
- int use_fast_fed, coeff;
- unsigned int lincnt;
unsigned feedl, dist;
- GenesysRegister *r;
- uint32_t z1, z2;
/* get step multiplier */
unsigned step_multiplier = gl843_get_step_multiplier (reg);
- use_fast_fed = 0;
+ bool use_fast_fed = false;
- if ((scan_yres >= 300 && feed_steps > 900) || (has_flag(flags, MotorFlag::FEED))) {
- use_fast_fed = 1;
+ if ((scan_yres >= 300 && feed_steps > 900) || (has_flag(flags, ScanFlag::FEEDING))) {
+ use_fast_fed = true;
+ }
+ if (has_flag(dev->model->flags, ModelFlag::DISABLE_FAST_FEEDING)) {
+ use_fast_fed = false;
}
- lincnt=scan_lines;
- reg->set24(REG_LINCNT, lincnt);
- DBG(DBG_io, "%s: lincnt=%d\n", __func__, lincnt);
+ reg->set24(REG_LINCNT, scan_lines);
- /* compute register 02 value */
- r = sanei_genesys_get_address(reg, REG_0x02);
- r->value = 0x00;
- sanei_genesys_set_motor_power(*reg, true);
+ reg->set8(REG_0x02, 0);
+ sanei_genesys_set_motor_power(*reg, true);
+ std::uint8_t reg02 = reg->get8(REG_0x02);
if (use_fast_fed) {
- r->value |= REG_0x02_FASTFED;
+ reg02 |= REG_0x02_FASTFED;
} else {
- r->value &= ~REG_0x02_FASTFED;
+ reg02 &= ~REG_0x02_FASTFED;
}
- /* in case of automatic go home, move until home sensor */
- if (has_flag(flags, MotorFlag::AUTO_GO_HOME)) {
- r->value |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
+ // in case of automatic go home, move until home sensor
+ if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
+ reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
}
/* disable backtracking */
- if (has_flag(flags, MotorFlag::DISABLE_BUFFER_FULL_MOVE)
- ||(scan_yres>=2400 && dev->model->model_id != ModelId::CANON_4400F)
- ||(scan_yres>=sensor.optical_res))
+ if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) ||
+ (scan_yres>=2400 && dev->model->model_id != ModelId::CANON_4400F) ||
+ (scan_yres>=sensor.full_resolution))
{
- r->value |= REG_0x02_ACDCDIS;
+ reg02 |= REG_0x02_ACDCDIS;
}
- if (has_flag(flags, MotorFlag::REVERSE)) {
- r->value |= REG_0x02_MTRREV;
+ if (has_flag(flags, ScanFlag::REVERSE)) {
+ reg02 |= REG_0x02_MTRREV;
} else {
- r->value &= ~REG_0x02_MTRREV;
+ reg02 &= ~REG_0x02_MTRREV;
}
+ reg->set8(REG_0x02, reg02);
- /* scan and backtracking slope table */
- auto scan_table = sanei_genesys_slope_table(dev->model->asic_type, scan_yres, exposure,
- dev->motor.base_ydpi, step_multiplier,
- motor_profile);
+ // scan and backtracking slope table
+ auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres, exposure,
+ step_multiplier, motor_profile);
- gl843_send_slope_table(dev, SCAN_TABLE, scan_table.table, scan_table.steps_count);
- gl843_send_slope_table(dev, BACKTRACK_TABLE, scan_table.table, scan_table.steps_count);
+ scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
+ scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
+ scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table);
- reg->set8(REG_STEPNO, scan_table.steps_count / step_multiplier);
- reg->set8(REG_FASTNO, scan_table.steps_count / step_multiplier);
+ reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
// fast table
- unsigned fast_yres = sanei_genesys_get_lowest_ydpi(dev);
- auto fast_table = sanei_genesys_slope_table(dev->model->asic_type, fast_yres, exposure,
- dev->motor.base_ydpi, step_multiplier,
- motor_profile);
- gl843_send_slope_table(dev, STOP_TABLE, fast_table.table, fast_table.steps_count);
- gl843_send_slope_table(dev, FAST_TABLE, fast_table.table, fast_table.steps_count);
- gl843_send_slope_table(dev, HOME_TABLE, fast_table.table, fast_table.steps_count);
+ const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
+ if (fast_profile == nullptr) {
+ fast_profile = &motor_profile;
+ }
- reg->set8(REG_FSHDEC, fast_table.steps_count / step_multiplier);
- reg->set8(REG_FMOVNO, fast_table.steps_count / step_multiplier);
+ auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
+ *fast_profile);
+
+ scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
+ scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
+
+ reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
+
+ if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) {
+ std::uint8_t vref = 0;
+ vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL;
+ vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK;
+ vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST;
+ vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME;
+ reg->set8(REG_0x80, vref);
+ }
/* substract acceleration distance from feedl */
feedl=feed_steps;
feedl <<= static_cast<unsigned>(motor_profile.step_type);
- dist = scan_table.steps_count / step_multiplier;
- if (use_fast_fed)
- {
- dist += (fast_table.steps_count / step_multiplier) * 2;
+ dist = scan_table.table.size() / step_multiplier;
+
+ if (use_fast_fed) {
+ dist += (fast_table.table.size() / step_multiplier) * 2;
}
- DBG(DBG_io2, "%s: acceleration distance=%d\n", __func__, dist);
/* get sure when don't insane value : XXX STEF XXX in this case we should
* fall back to single table move */
@@ -906,15 +800,15 @@ static void gl843_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 */
+ // doesn't seem to matter that much
+ std::uint32_t z1, z2;
sanei_genesys_calculate_zmod(use_fast_fed,
- exposure,
+ exposure,
scan_table.table,
- scan_table.steps_count / step_multiplier,
- feedl,
- scan_table.steps_count / step_multiplier,
+ scan_table.table.size() / step_multiplier,
+ feedl,
+ scan_table.table.size() / step_multiplier,
&z1,
&z2);
if(scan_yres>600)
@@ -924,47 +818,46 @@ static void gl843_init_motor_regs_scan(Genesys_Device* dev,
}
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);
- r = sanei_genesys_get_address(reg, REG_0x1E);
- r->value &= 0xf0; /* 0 dummy lines */
- r->value |= scan_dummy; /* dummy lines */
+ reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
reg->set8_mask(REG_0x67, static_cast<unsigned>(motor_profile.step_type) << REG_0x67S_STEPSEL, 0xc0);
- reg->set8_mask(REG_0x68, static_cast<unsigned>(motor_profile.step_type) << REG_0x68S_FSTPSEL, 0xc0);
+ reg->set8_mask(REG_0x68, static_cast<unsigned>(fast_profile->step_type) << REG_0x68S_FSTPSEL, 0xc0);
// steps for STOP table
- reg->set8(REG_FMOVDEC, fast_table.steps_count / step_multiplier);
+ reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
- /* Vref XXX STEF XXX : optical divider or step type ? */
- r = sanei_genesys_get_address (reg, 0x80);
- if (!(dev->model->flags & GENESYS_FLAG_FULL_HWDPI_MODE))
+ if (dev->model->model_id == ModelId::PANASONIC_KV_SS080 ||
+ dev->model->model_id == ModelId::HP_SCANJET_4850C ||
+ dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
+ dev->model->model_id == ModelId::HP_SCANJET_G4050 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
{
- r->value = 0x50;
- coeff = sensor.get_hwdpi_divisor_for_dpi(scan_yres);
+ // FIXME: take this information from motor struct
+ std::uint8_t reg_vref = reg->get8(0x80);
+ reg_vref = 0x50;
+ unsigned coeff = sensor.full_resolution / scan_yres;
if (dev->model->motor_id == MotorId::KVSS080) {
- if(coeff>=1)
- {
- r->value |= 0x05;
+ if (coeff >= 1) {
+ reg_vref |= 0x05;
+ }
+ } else {
+ switch (coeff) {
+ case 4:
+ reg_vref |= 0x0a;
+ break;
+ case 2:
+ reg_vref |= 0x0f;
+ break;
+ case 1:
+ reg_vref |= 0x0f;
+ break;
}
}
- else {
- switch(coeff)
- {
- case 4:
- r->value |= 0x0a;
- break;
- case 2:
- r->value |= 0x0f;
- break;
- case 1:
- r->value |= 0x0f;
- break;
- }
- }
+ reg->set8(REG_0x80, reg_vref);
}
}
@@ -981,7 +874,6 @@ static void gl843_init_motor_regs_scan(Genesys_Device* dev,
* @param pixels logical number of pixels to use
* @param channels number of color channles used (1 or 3)
* @param depth bit depth of the scan (1, 8 or 16 bits)
- * @param ccd_size_divisor true specifies how much x coordinates must be shrunk
* @param color_filter to choose the color channel used in gray scans
* @param flags to drive specific settings such no calibration, XPA use ...
*/
@@ -990,57 +882,54 @@ static void gl843_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
const ScanSession& session)
{
DBG_HELPER_ARGS(dbg, "exposure=%d", exposure);
- unsigned int dpihw;
unsigned int tgtime; /**> exposure time multiplier */
- GenesysRegister *r;
/* tgtime */
tgtime = exposure / 65536 + 1;
DBG(DBG_io2, "%s: tgtime=%d\n", __func__, tgtime);
- // 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);
- DBG(DBG_io2, "%s: dpihw=%d\n", __func__, dpihw);
-
- /* sensor parameters */
- gl843_setup_sensor(dev, sensor, reg);
-
- // resolution is divided according to CKSEL
- 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);
+ // sensor parameters
+ 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 ||
- (dev->model->flags & GENESYS_FLAG_CALIBRATION_HOST_SIDE)))
+ has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
+ session.use_host_side_calib)
{
- 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;
}
- bool use_shdarea = dpihw > 600;
+ bool use_shdarea = false;
if (dev->model->model_id == ModelId::CANON_4400F) {
use_shdarea = session.params.xres <= 600;
} else if (dev->model->model_id == ModelId::CANON_8400F) {
use_shdarea = session.params.xres <= 400;
+ } else if (dev->model->model_id == ModelId::CANON_8600F ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
+ {
+ use_shdarea = true;
+ } else {
+ use_shdarea = session.params.xres > 600;
}
+
if (use_shdarea) {
- r->value |= REG_0x01_SHDAREA;
+ reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
} else {
- r->value &= ~REG_0x01_SHDAREA;
+ reg->find_reg(REG_0x01).value &= ~REG_0x01_SHDAREA;
}
- r = sanei_genesys_get_address (reg, REG_0x03);
if (dev->model->model_id == ModelId::CANON_8600F) {
- r->value |= REG_0x03_AVEENB;
+ reg->find_reg(REG_0x03).value |= REG_0x03_AVEENB;
} else {
- r->value &= ~REG_0x03_AVEENB;
+ reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
}
// FIXME: we probably don't need to set exposure to registers at this point. It was this way
@@ -1049,43 +938,40 @@ static void gl843_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
!has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
/* select XPA */
- r->value &= ~REG_0x03_XPASEL;
+ reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL;
if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
- r->value |= REG_0x03_XPASEL;
+ reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL;
}
reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
- /* BW threshold */
- r = sanei_genesys_get_address(reg, REG_0x2E);
- r->value = dev->settings.threshold;
- r = sanei_genesys_get_address(reg, REG_0x2F);
- r->value = dev->settings.threshold;
+ // BW threshold
+ reg->set8(REG_0x2E, 0x7f);
+ reg->set8(REG_0x2F, 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_0x04_AFEMOD);
+ reg->find_reg(REG_0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
if (session.params.channels == 1)
{
switch (session.params.color_filter)
{
case ColorFilter::RED:
- r->value |= 0x14;
+ reg->find_reg(REG_0x04).value |= 0x14;
break;
case ColorFilter::BLUE:
- r->value |= 0x1c;
+ reg->find_reg(REG_0x04).value |= 0x1c;
break;
case ColorFilter::GREEN:
- r->value |= 0x18;
+ reg->find_reg(REG_0x04).value |= 0x18;
break;
default:
break; // should not happen
@@ -1093,10 +979,10 @@ static void gl843_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
} else {
switch (dev->frontend.layout.type) {
case FrontendType::WOLFSON:
- r->value |= 0x10; // pixel by pixel
+ reg->find_reg(REG_0x04).value |= 0x10; // pixel by pixel
break;
case FrontendType::ANALOG_DEVICES:
- r->value |= 0x20; // slow color pixel by pixel
+ reg->find_reg(REG_0x04).value |= 0x20; // slow color pixel by pixel
break;
default:
throw SaneException("Invalid frontend type %d",
@@ -1104,7 +990,10 @@ static void gl843_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
}
}
- 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;
@@ -1112,28 +1001,18 @@ static void gl843_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
}
- unsigned dpiset = session.output_resolution * session.ccd_size_divisor *
- ccd_pixels_per_system_pixel;
-
- if (sensor.dpiset_override != 0) {
- dpiset = sensor.dpiset_override;
- }
- reg->set16(REG_DPISET, dpiset);
- DBG(DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset);
+ reg->set16(REG_DPISET, sensor.register_dpiset);
reg->set16(REG_STRPIXEL, session.pixel_startx);
reg->set16(REG_ENDPIXEL, session.pixel_endx);
/* MAXWD is expressed in 2 words unit */
/* nousedspace = (mem_bank_range * 1024 / 256 -1 ) * 4; */
- // BUG: the division by ccd_size_divisor likely does not make sense
- reg->set24(REG_MAXWD, (session.output_line_bytes / session.ccd_size_divisor) >> 1);
-
+ // BUG: the division by optical and full resolution factor likely does not make sense
+ reg->set24(REG_MAXWD, (session.output_line_bytes *
+ session.optical_resolution / session.full_resolution) >> 1);
reg->set16(REG_LPERIOD, exposure / tgtime);
- DBG(DBG_io2, "%s: exposure used=%d\n", __func__, exposure/tgtime);
-
- r = sanei_genesys_get_address (reg, REG_DUMMY);
- r->value = sensor.dummy_pixel;
+ reg->set8(REG_DUMMY, sensor.dummy_pixel);
}
void CommandSetGl843::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
@@ -1170,42 +1049,15 @@ void CommandSetGl843::init_regs_for_scan_session(Genesys_Device* dev, const Gene
if (exposure < 0) {
throw std::runtime_error("Exposure not defined in sensor definition");
}
- const auto& motor_profile = sanei_genesys_get_motor_profile(*gl843_motor_profiles,
- dev->model->motor_id,
- exposure);
-
- DBG(DBG_info, "%s : exposure=%d pixels\n", __func__, exposure);
- DBG(DBG_info, "%s : scan_step_type=%d\n", __func__,
- static_cast<unsigned>(motor_profile.step_type));
+ const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure, session);
// now _LOGICAL_ optical values used are known, setup registers
gl843_init_optical_regs_scan(dev, sensor, reg, exposure, session);
+ gl843_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure, slope_dpi,
+ session.optical_line_count, dummy, session.params.starty,
+ session.params.flags);
- /*** motor parameters ***/
- 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::USE_XPA)) {
- mflags |= MotorFlag::USE_XPA;
- }
- if (has_flag(session.params.flags, ScanFlag::REVERSE)) {
- mflags |= MotorFlag::REVERSE;
- }
-
- unsigned scan_lines = dev->model->is_cis ? session.output_line_count * session.params.channels
- : session.output_line_count;
-
- gl843_init_motor_regs_scan(dev, sensor, reg, motor_profile, exposure, slope_dpi,
- scan_lines, dummy, session.params.starty, mflags);
-
- dev->read_buffer.clear();
- dev->read_buffer.alloc(session.buffer_size_read);
-
- build_image_pipeline(dev, session);
+ setup_image_pipeline(*dev, session);
dev->read_active = true;
@@ -1224,33 +1076,46 @@ ScanSession CommandSetGl843::calculate_scan_session(const Genesys_Device* dev,
DBG_HELPER(dbg);
debug_dump(DBG_info, settings);
- int start;
-
- /* we have 2 domains for ccd: xres below or above half ccd max dpi */
- unsigned ccd_size_divisor = sensor.get_ccd_size_divisor_for_dpi(settings.xres);
+ ScanFlag flags = ScanFlag::NONE;
+ float move = 0.0f;
if (settings.scan_method == ScanMethod::TRANSPARENCY ||
settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- start = static_cast<int>(dev->model->x_offset_ta);
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
+ // transparency adapter
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
+ }
+ flags |= ScanFlag::USE_XPA;
} else {
- start = static_cast<int>(dev->model->x_offset);
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset;
+ }
}
- if (dev->model->model_id == ModelId::CANON_8600F)
+ move += settings.tl_y;
+
+ int move_dpi = dev->motor.base_ydpi;
+ move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
+
+ float start = 0.0f;
+ if (settings.scan_method==ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- // FIXME: this is probably just an artifact of a bug elsewhere
- start /= ccd_size_divisor;
+ start = dev->model->x_offset_ta;
+ } else {
+ start = dev->model->x_offset;
}
+ start = start + settings.tl_x;
- start += static_cast<int>(settings.tl_x);
- start = static_cast<int>((start * sensor.optical_res) / MM_PER_INCH);
+ 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; // not used
- 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;
@@ -1259,8 +1124,7 @@ ScanSession CommandSetGl843::calculate_scan_session(const Genesys_Device* dev,
session.params.scan_method = settings.scan_method;
session.params.scan_mode = settings.scan_mode;
session.params.color_filter = settings.color_filter;
- session.params.flags = ScanFlag::NONE;
-
+ session.params.flags = flags;
compute_session(dev, session, sensor);
return session;
@@ -1352,8 +1216,6 @@ void CommandSetGl843::detect_document_end(Genesys_Device* dev) const
auto skip_lines = scan_end_lines - output_lines;
if (remaining_lines > skip_lines) {
- DBG(DBG_io, "%s: skip_lines=%zu\n", __func__, skip_lines);
-
remaining_lines -= skip_lines;
dev->get_pipeline_source().set_remaining_bytes(remaining_lines *
dev->session.output_line_bytes_raw);
@@ -1363,194 +1225,6 @@ void CommandSetGl843::detect_document_end(Genesys_Device* dev) const
}
}
-// enables or disables XPA slider motor
-void gl843_set_xpa_motor_power(Genesys_Device* dev, Genesys_Register_Set& regs, bool set)
-{
- DBG_HELPER(dbg);
- uint8_t val;
-
- if (dev->model->model_id == ModelId::CANON_8400F) {
-
- if (set) {
- val = dev->interface->read_register(0x6c);
- val &= ~(REG_0x6C_GPIO16 | REG_0x6C_GPIO13);
- if (dev->session.output_resolution >= 2400) {
- val &= ~REG_0x6C_GPIO10;
- }
- dev->interface->write_register(0x6c, val);
-
- val = dev->interface->read_register(0xa9);
- val |= REG_0xA9_GPO30;
- val &= ~REG_0xA9_GPO29;
- dev->interface->write_register(0xa9, val);
- } else {
- val = dev->interface->read_register(0x6c);
- val |= REG_0x6C_GPIO16 | REG_0x6C_GPIO13;
- dev->interface->write_register(0x6c, val);
-
- val = dev->interface->read_register(0xa9);
- val &= ~REG_0xA9_GPO30;
- val |= REG_0xA9_GPO29;
- dev->interface->write_register(0xa9, val);
- }
- } else if (dev->model->model_id == ModelId::CANON_8600F) {
- if (set) {
- val = dev->interface->read_register(REG_0x6C);
- val &= ~REG_0x6C_GPIO14;
- if (dev->session.output_resolution >= 2400) {
- val |= REG_0x6C_GPIO10;
- }
- dev->interface->write_register(REG_0x6C, val);
-
- val = dev->interface->read_register(REG_0xA6);
- val |= REG_0xA6_GPIO17;
- val &= ~REG_0xA6_GPIO23;
- dev->interface->write_register(REG_0xA6, val);
- } else {
- val = dev->interface->read_register(REG_0x6C);
- val |= REG_0x6C_GPIO14;
- val &= ~REG_0x6C_GPIO10;
- dev->interface->write_register(REG_0x6C, val);
-
- val = dev->interface->read_register(REG_0xA6);
- val &= ~REG_0xA6_GPIO17;
- val &= ~REG_0xA6_GPIO23;
- dev->interface->write_register(REG_0xA6, val);
- }
- } else if (dev->model->model_id == ModelId::HP_SCANJET_G4050) {
- if (set) {
- // set MULTFILM et GPOADF
- val = dev->interface->read_register(REG_0x6B);
- val |=REG_0x6B_MULTFILM|REG_0x6B_GPOADF;
- dev->interface->write_register(REG_0x6B, val);
-
- val = dev->interface->read_register(REG_0x6C);
- val &= ~REG_0x6C_GPIO15;
- dev->interface->write_register(REG_0x6C, val);
-
- /* Motor power ? No move at all without this one */
- val = dev->interface->read_register(REG_0xA6);
- val |= REG_0xA6_GPIO20;
- dev->interface->write_register(REG_0xA6, val);
-
- val = dev->interface->read_register(REG_0xA8);
- val &= ~REG_0xA8_GPO27;
- dev->interface->write_register(REG_0xA8, val);
-
- val = dev->interface->read_register(REG_0xA9);
- val |= REG_0xA9_GPO32|REG_0xA9_GPO31;
- dev->interface->write_register(REG_0xA9, val);
- } else {
- // unset GPOADF
- val = dev->interface->read_register(REG_0x6B);
- val &= ~REG_0x6B_GPOADF;
- dev->interface->write_register(REG_0x6B, val);
-
- val = dev->interface->read_register(REG_0xA8);
- val |= REG_0xA8_GPO27;
- dev->interface->write_register(REG_0xA8, val);
-
- val = dev->interface->read_register(REG_0xA9);
- val &= ~REG_0xA9_GPO31;
- dev->interface->write_register(REG_0xA9, val);
- }
- }
- regs.state.is_xpa_motor_on = set;
-}
-
-
-/** @brief light XPA lamp
- * toggle gpios to switch off regular lamp and light on the
- * XPA light
- * @param dev device to set up
- */
-static void gl843_set_xpa_lamp_power(Genesys_Device* dev, bool set)
-{
- DBG_HELPER(dbg);
-
- struct LampSettings {
- ModelId model_id;
- ScanMethod scan_method;
- GenesysRegisterSettingSet regs_on;
- GenesysRegisterSettingSet regs_off;
- };
-
- // FIXME: BUG: we're not clearing the registers to the previous state when returning back when
- // turning off the lamp
- LampSettings settings[] = {
- { ModelId::CANON_8400F, ScanMethod::TRANSPARENCY, {
- { 0xa6, 0x34, 0xf4 },
- }, {
- { 0xa6, 0x40, 0x70 },
- }
- },
- { ModelId::CANON_8400F, ScanMethod::TRANSPARENCY_INFRARED, {
- { 0x6c, 0x40, 0x40 },
- { 0xa6, 0x01, 0xff },
- }, {
- { 0x6c, 0x00, 0x40 },
- { 0xa6, 0x00, 0xff },
- }
- },
- { ModelId::CANON_8600F, ScanMethod::TRANSPARENCY, {
- { 0xa6, 0x34, 0xf4 },
- { 0xa7, 0xe0, 0xe0 },
- }, {
- { 0xa6, 0x40, 0x70 },
- }
- },
- { ModelId::CANON_8600F, ScanMethod::TRANSPARENCY_INFRARED, {
- { 0xa6, 0x00, 0xc0 },
- { 0xa7, 0xe0, 0xe0 },
- { 0x6c, 0x80, 0x80 },
- }, {
- { 0xa6, 0x00, 0xc0 },
- { 0x6c, 0x00, 0x80 },
- }
- },
- { ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY, {
- }, {
- { 0xa6, 0x40, 0x70 }, // BUG: remove this cleanup write, it was enabled by accident
- }
- },
- { ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY_INFRARED, {
- { 0xa8, 0x07, 0x07 },
- }, {
- { 0xa8, 0x00, 0x07 },
- }
- },
- { ModelId::PLUSTEK_OPTICFILM_7300, ScanMethod::TRANSPARENCY, {}, {} },
- { ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY, {}, {} },
- { ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY_INFRARED, {
- { 0xa8, 0x07, 0x07 },
- }, {
- { 0xa8, 0x00, 0x07 },
- }
- },
- };
-
- for (const auto& setting : settings) {
- if (setting.model_id == dev->model->model_id &&
- setting.scan_method == dev->settings.scan_method)
- {
- apply_reg_settings_to_device(*dev, set ? setting.regs_on : setting.regs_off);
- return;
- }
- }
-
- // BUG: we're currently calling the function in shut down path of regular lamp
- if (set) {
- throw SaneException("Unexpected code path entered");
- }
-
- GenesysRegisterSettingSet regs = {
- { 0xa6, 0x40, 0x70 },
- };
- apply_reg_settings_to_device(*dev, regs);
- // TODO: throw exception when we're only calling this function in error return path
- // throw SaneException("Could not find XPA lamp settings");
-}
-
// Send the low-level scan command
void CommandSetGl843::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set* reg, bool start_motor) const
@@ -1580,30 +1254,44 @@ void CommandSetGl843::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
}
if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
- gl843_set_xpa_lamp_power(dev, true);
+ dev->cmd_set->set_xpa_lamp_power(*dev, true);
}
if (reg->state.is_xpa_on) {
- gl843_set_xpa_motor_power(dev, *reg, true);
+ dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
}
// blinking led
dev->interface->write_register(REG_0x7E, 0x01);
break;
case GpioId::CANON_8400F:
+ if (dev->session.params.xres == 3200)
+ {
+ GenesysRegisterSettingSet reg_settings = {
+ { 0x6c, 0x00, 0x02 },
+ };
+ apply_reg_settings_to_device(*dev, reg_settings);
+ }
+ if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
+ dev->cmd_set->set_xpa_lamp_power(*dev, true);
+ }
+ if (reg->state.is_xpa_on) {
+ dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
+ }
+ break;
case GpioId::CANON_8600F:
if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
- gl843_set_xpa_lamp_power(dev, true);
+ dev->cmd_set->set_xpa_lamp_power(*dev, true);
}
if (reg->state.is_xpa_on) {
- gl843_set_xpa_motor_power(dev, *reg, true);
+ dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
}
break;
case GpioId::PLUSTEK_OPTICFILM_7200I:
case GpioId::PLUSTEK_OPTICFILM_7300:
case GpioId::PLUSTEK_OPTICFILM_7500I: {
if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
- gl843_set_xpa_lamp_power(dev, true);
+ dev->cmd_set->set_xpa_lamp_power(*dev, true);
}
break;
}
@@ -1612,8 +1300,7 @@ void CommandSetGl843::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
break;
}
- // 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);
@@ -1622,11 +1309,26 @@ void CommandSetGl843::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
scanner_start_action(*dev, start_motor);
- if (reg->state.is_motor_on) {
- dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
- }
- if (reg->state.is_xpa_motor_on) {
- dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
+ switch (reg->state.motor_mode) {
+ case MotorMode::PRIMARY: {
+ if (reg->state.is_motor_on) {
+ dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
+ }
+ break;
+ }
+ case MotorMode::PRIMARY_AND_SECONDARY: {
+ if (reg->state.is_motor_on) {
+ dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
+ dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
+ }
+ break;
+ }
+ case MotorMode::SECONDARY: {
+ if (reg->state.is_motor_on) {
+ dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
+ }
+ break;
+ }
}
}
@@ -1640,10 +1342,8 @@ void CommandSetGl843::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
// post scan gpio
dev->interface->write_register(0x7e, 0x00);
- // turn off XPA lamp if needed
- // BUG: the if condition below probably shouldn't be enabled when XPA is off
- if (reg->state.is_xpa_on || reg->state.is_lamp_on) {
- gl843_set_xpa_lamp_power(dev, false);
+ if (reg->state.is_xpa_on) {
+ dev->cmd_set->set_xpa_lamp_power(*dev, false);
}
if (!dev->model->is_sheetfed) {
@@ -1658,202 +1358,79 @@ void CommandSetGl843::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 CommandSetGl843::search_start_position(Genesys_Device* dev) const
-{
- DBG_HELPER(dbg);
- Genesys_Register_Set local_reg;
-
- int pixels = 600;
- int dpi = 300;
-
- local_reg = dev->reg;
-
- /* 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, dev->model->default_method);
-
- 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);
-
- dev->cmd_set->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
- Image image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes_raw);
-
- scanner_stop_action_no_move(*dev, local_reg);
-
- if (DBG_LEVEL >= DBG_data) {
- sanei_genesys_write_pnm_file("gl843_search_position.pnm", image);
- }
-
- dev->cmd_set->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, image.get_row_ptr(0), 0, dpi,
- pixels, dev->model->search_lines);
- }
-}
-
-// sets up register for coarse gain calibration
-// todo: check it for scanners using it
-void CommandSetGl843::init_regs_for_coarse_calibration(Genesys_Device* dev,
- const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const
-{
- DBG_HELPER(dbg);
-
- ScanFlag flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA |
- ScanFlag::SINGLE_LINE |
- ScanFlag::IGNORE_LINE_DISTANCE;
-
- if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) {
- flags |= ScanFlag::USE_XPA;
- }
-
- 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 = flags;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &regs, 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 CommandSetGl843::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;
+ int move;
+ float calib_size_mm = 0;
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- dev->calib_lines = dev->model->shading_ta_lines;
+ calib_size_mm = dev->model->y_size_calib_ta_mm;
} else {
- dev->calib_lines = dev->model->shading_lines;
+ calib_size_mm = dev->model->y_size_calib_mm;
}
- dpihw = sensor.get_logical_hwdpi(dev->settings.xres);
- factor=sensor.optical_res/dpihw;
- resolution=dpihw;
+ unsigned resolution = sensor.shading_resolution;
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, dev->calib_channels,
+ unsigned channels = 3;
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
dev->settings.scan_method);
- if ((dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) &&
- dev->model->model_id == ModelId::CANON_8600F &&
- dev->settings.xres == 4800)
- {
- float offset = static_cast<float>(dev->model->x_offset_ta);
- offset /= calib_sensor.get_ccd_size_divisor_for_dpi(resolution);
- offset = static_cast<float>((offset * calib_sensor.optical_res) / MM_PER_INCH);
+ unsigned calib_pixels = 0;
+ unsigned calib_pixels_offset = 0;
- float size = static_cast<float>(dev->model->x_size_ta);
- size /= calib_sensor.get_ccd_size_divisor_for_dpi(resolution);
- size = static_cast<float>((size * calib_sensor.optical_res) / MM_PER_INCH);
+ if (should_calibrate_only_active_area(*dev, dev->settings)) {
+ float offset = dev->model->x_offset_ta;
+ // FIXME: we should use resolution here
+ offset = static_cast<float>((offset * dev->settings.xres) / MM_PER_INCH);
- dev->calib_pixels_offset = static_cast<std::size_t>(offset);
- dev->calib_pixels = static_cast<std::size_t>(size);
- }
- else
- {
- dev->calib_pixels_offset = 0;
- dev->calib_pixels = calib_sensor.sensor_pixels / factor;
- }
+ float size = dev->model->x_size_ta;
+ size = static_cast<float>((size * dev->settings.xres) / MM_PER_INCH);
- dev->calib_resolution = resolution;
+ calib_pixels_offset = static_cast<std::size_t>(offset);
+ calib_pixels = static_cast<std::size_t>(size);
+ } else {
+ calib_pixels_offset = 0;
+ calib_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
+ }
ScanFlag flags = ScanFlag::DISABLE_SHADING |
ScanFlag::DISABLE_GAMMA |
- ScanFlag::DISABLE_BUFFER_FULL_MOVE |
- ScanFlag::IGNORE_LINE_DISTANCE;
+ ScanFlag::DISABLE_BUFFER_FULL_MOVE;
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- // note: move_to_ta() function has already been called and the sensor is at the
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
// transparency adapter
move = static_cast<int>(dev->model->y_offset_calib_white_ta - dev->model->y_offset_sensor_to_ta);
+ if (dev->model->model_id == ModelId::CANON_8600F && resolution == 2400) {
+ move /= 2;
+ }
+ if (dev->model->model_id == ModelId::CANON_8600F && resolution == 4800) {
+ move /= 4;
+ }
flags |= ScanFlag::USE_XPA;
} else {
move = static_cast<int>(dev->model->y_offset_calib_white);
}
move = static_cast<int>((move * resolution) / MM_PER_INCH);
+ unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
ScanSession session;
session.params.xres = resolution;
session.params.yres = resolution;
- session.params.startx = dev->calib_pixels_offset;
+ session.params.startx = calib_pixels_offset;
session.params.starty = move;
- session.params.pixels = dev->calib_pixels;
- session.params.lines = dev->calib_lines;
+ session.params.pixels = calib_pixels;
+ 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 = dev->settings.scan_mode;
session.params.color_filter = dev->settings.color_filter;
@@ -1862,89 +1439,7 @@ void CommandSetGl843::init_regs_for_shading(Genesys_Device* dev, const Genesys_S
init_regs_for_scan_session(dev, calib_sensor, &regs, session);
- // the pixel number may be updated to conform to scanner constraints
- dev->calib_pixels = session.output_pixels;
-
dev->calib_session = session;
- dev->calib_total_bytes_to_read = session.output_total_bytes_raw;
-
- dev->interface->write_registers(regs);
-}
-
-/** @brief set up registers for the actual scan
- */
-void CommandSetGl843::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);
-
- move_dpi = dev->motor.base_ydpi;
-
- ScanFlag flags = ScanFlag::NONE;
-
- if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
- {
- // note: move_to_ta() function has already been called and the sensor is at the
- // transparency adapter
- if (dev->ignore_offsets) {
- move = 0;
- } else {
- move = static_cast<float>(dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta);
- }
- flags |= ScanFlag::USE_XPA;
- } else {
- if (dev->ignore_offsets) {
- move = 0;
- } else {
- 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);
-
- /* start */
- if (dev->settings.scan_method==ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
- {
- start = static_cast<float>(dev->model->x_offset_ta);
- } else {
- start = static_cast<float>(dev->model->x_offset);
- }
-
- if (dev->model->model_id == ModelId::CANON_8400F ||
- dev->model->model_id == ModelId::CANON_8600F)
- {
- // FIXME: this is probably just an artifact of a bug elsewhere
- start /= sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres);
- }
-
- start = static_cast<float>(start + dev->settings.tl_x);
- 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 = flags;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &dev->reg, session);
}
/**
@@ -1975,8 +1470,7 @@ void CommandSetGl843::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor
gamma[i * 2 + size * 4 + 1] = (bgamma[i] >> 8) & 0xff;
}
- dev->interface->write_gamma(0x28, 0x0000, gamma.data(), size * 2 * 3,
- ScannerInterface::FLAG_SWAP_REGISTERS);
+ dev->interface->write_gamma(0x28, 0x0000, gamma.data(), size * 2 * 3);
}
/* this function does the led calibration by scanning one line of the calibration
@@ -1987,607 +1481,69 @@ void CommandSetGl843::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor
SensorExposure CommandSetGl843::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
- DBG_HELPER(dbg);
- int num_pixels;
- int avg[3], avga, avge;
- int turn;
- uint16_t expr, expg, expb;
-
- // offset calibration is always done in color mode
- unsigned channels = 3;
-
- // take a copy, as we're going to modify exposure
- auto calib_sensor = sanei_genesys_find_sensor(dev, sensor.optical_res, channels,
- dev->settings.scan_method);
-
- num_pixels = (calib_sensor.sensor_pixels * calib_sensor.optical_res) / calib_sensor.optical_res;
-
- /* initial calibration reg values */
- regs = dev->reg;
-
- ScanSession session;
- session.params.xres = calib_sensor.sensor_pixels;
- session.params.yres = dev->motor.base_ydpi;
- 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, &regs, session);
-
- dev->interface->write_registers(regs);
-
-/*
- we try to get equal bright leds here:
-
- loop:
- average per color
- adjust exposure times
- */
-
- expr = calib_sensor.exposure.red;
- expg = calib_sensor.exposure.green;
- expb = calib_sensor.exposure.blue;
-
- turn = 0;
-
- bool acceptable = false;
- do
- {
-
- calib_sensor.exposure.red = expr;
- calib_sensor.exposure.green = expg;
- calib_sensor.exposure.blue = expb;
-
- regs_set_exposure(dev->model->asic_type, regs, calib_sensor.exposure);
-
- dev->interface->write_registers(regs);
-
- DBG(DBG_info, "%s: starting first line reading\n", __func__);
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("led_calibration");
- move_back_home(dev, true);
- return calib_sensor.exposure;
- }
-
- auto image = read_unshuffled_image_from_scanner(dev, session,
- session.output_total_bytes_raw);
- scanner_stop_action_no_move(*dev, regs);
-
- if (DBG_LEVEL >= DBG_data)
- {
- char fn[30];
- std::snprintf(fn, 30, "gl843_led_%02d.pnm", turn);
- sanei_genesys_write_pnm_file(fn, image);
- }
-
- acceptable = true;
-
- for (unsigned ch = 0; ch < channels; ch++) {
- avg[ch] = 0;
- for (std::size_t x = 0; x < image.get_width(); x++) {
- avg[ch] += image.get_raw_channel(x, 0, ch);
- }
- avg[ch] /= image.get_width();
- }
-
- DBG(DBG_info, "%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]);
-
- acceptable = true;
-
- 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;
-
- if (!acceptable)
- {
- avga = (avg[0] + avg[1] + avg[2]) / 3;
- expr = (expr * avga) / avg[0];
- expg = (expg * avga) / avg[1];
- expb = (expb * 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
-*/
- avge = (expr + expg + expb) / 3;
-
- /* don't overflow max exposure */
- if (avge > 3000)
- {
- expr = (expr * 2000) / avge;
- expg = (expg * 2000) / avge;
- expb = (expb * 2000) / avge;
- }
- if (avge < 50)
- {
- expr = (expr * 50) / avge;
- expg = (expg * 50) / avge;
- expb = (expb * 50) / avge;
- }
-
- }
- scanner_stop_action(*dev);
-
- turn++;
-
- }
- while (!acceptable && turn < 100);
-
- DBG(DBG_info, "%s: acceptable exposure: %d,%d,%d\n", __func__, expr, expg, expb);
-
- move_back_home(dev, true);
-
- return calib_sensor.exposure;
-}
-
-
-
-/**
- * average dark pixels of a 8 bits scan of a given channel
- */
-static int dark_average_channel(const Image& image, unsigned black, unsigned channel)
-{
- auto channels = get_pixel_channels(image.get_format());
-
- unsigned avg[3];
-
- // computes average values on black margin
- for (unsigned ch = 0; ch < channels; ch++) {
- avg[ch] = 0;
- unsigned count = 0;
- // FIXME: start with the second line because the black pixels often have noise on the first
- // line; the cause is probably incorrectly cleaned up previous scan
- for (std::size_t y = 1; y < image.get_height(); y++) {
- for (unsigned j = 0; j < black; j++) {
- avg[ch] += image.get_raw_channel(j, y, ch);
- count++;
- }
- }
- if (count > 0) {
- avg[ch] /= count;
- }
- DBG(DBG_info, "%s: avg[%d] = %d\n", __func__, ch, avg[ch]);
- }
- DBG(DBG_info, "%s: average = %d\n", __func__, avg[channel]);
- return avg[channel];
+ return scanner_led_calibration(*dev, sensor, regs);
}
-/** @brief calibrate AFE offset
- * Iterate doing scans at target dpi until AFE offset if correct. One
- * color line is scanned at a time. Scanning head doesn't move.
- * @param dev device to calibrate
- */
void CommandSetGl843::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
- DBG_HELPER(dbg);
-
- if (dev->frontend.layout.type != FrontendType::WOLFSON)
- return;
-
- unsigned channels;
- int pass, resolution, lines;
- int topavg[3], bottomavg[3], avg[3];
- int top[3], bottom[3], black_pixels, pixels, factor, dpihw;
-
- /* offset calibration is always done in color mode */
- channels = 3;
- lines = 8;
-
- // compute divider factor to compute final pixels number
- dpihw = sensor.get_logical_hwdpi(dev->settings.xres);
- factor = sensor.optical_res / dpihw;
- resolution = dpihw;
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
- dev->settings.scan_method);
-
- int target_pixels = calib_sensor.sensor_pixels / factor;
- int start_pixel = 0;
- black_pixels = calib_sensor.black_pixels / factor;
-
- if ((dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED) &&
- dev->model->model_id == ModelId::CANON_8600F &&
- dev->settings.xres == 4800)
- {
- start_pixel = static_cast<int>(dev->model->x_offset_ta);
- start_pixel /= calib_sensor.get_ccd_size_divisor_for_dpi(resolution);
- start_pixel = static_cast<int>((start_pixel * calib_sensor.optical_res) / MM_PER_INCH);
-
- target_pixels = static_cast<int>(dev->model->x_size_ta);
- target_pixels /= calib_sensor.get_ccd_size_divisor_for_dpi(resolution);
- target_pixels = static_cast<int>((target_pixels * calib_sensor.optical_res) / MM_PER_INCH);
- }
-
- ScanFlag flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA |
- ScanFlag::SINGLE_LINE |
- ScanFlag::IGNORE_LINE_DISTANCE;
-
- if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
- {
- flags |= ScanFlag::USE_XPA;
- }
-
- ScanSession session;
- session.params.xres = resolution;
- session.params.yres = resolution;
- session.params.startx = start_pixel;
- session.params.starty = 0;
- session.params.pixels = target_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 = ColorFilter::RED;
- session.params.flags = flags;
- compute_session(dev, session, calib_sensor);
- pixels = session.output_pixels;
-
- DBG(DBG_io, "%s: dpihw =%d\n", __func__, dpihw);
- DBG(DBG_io, "%s: factor =%d\n", __func__, factor);
- DBG(DBG_io, "%s: resolution =%d\n", __func__, resolution);
- DBG(DBG_io, "%s: pixels =%d\n", __func__, pixels);
- DBG(DBG_io, "%s: black_pixels=%d\n", __func__, black_pixels);
- init_regs_for_scan_session(dev, calib_sensor, &regs, session);
-
- sanei_genesys_set_motor_power(regs, false);
-
- // init gain and offset
- for (unsigned ch = 0; ch < 3; ch++)
- {
- bottom[ch] = 10;
- dev->frontend.set_offset(ch, bottom[ch]);
- dev->frontend.set_gain(ch, 0);
- }
- dev->cmd_set->set_fe(dev, calib_sensor, AFE_SET);
-
- // scan with bottom AFE settings
- dev->interface->write_registers(regs);
- DBG(DBG_info, "%s: starting first line reading\n", __func__);
-
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("offset_calibration");
- scanner_stop_action_no_move(*dev, regs);
- return;
- }
-
- auto first_line = read_unshuffled_image_from_scanner(dev, session,
- session.output_total_bytes_raw);
- scanner_stop_action_no_move(*dev, regs);
-
- if (DBG_LEVEL >= DBG_data)
- {
- char fn[40];
- std::snprintf(fn, 40, "gl843_bottom_offset_%03d_%03d_%03d.pnm",
- bottom[0], bottom[1], bottom[2]);
- sanei_genesys_write_pnm_file(fn, first_line);
- }
-
- for (unsigned ch = 0; ch < 3; ch++) {
- bottomavg[ch] = dark_average_channel(first_line, black_pixels, ch);
- DBG(DBG_io2, "%s: bottom avg %d=%d\n", __func__, ch, bottomavg[ch]);
- }
-
- // now top value
- for (unsigned ch = 0; ch < 3; ch++) {
- top[ch] = 255;
- dev->frontend.set_offset(ch, top[ch]);
- }
- dev->cmd_set->set_fe(dev, calib_sensor, AFE_SET);
-
- // scan with top AFE values
- dev->interface->write_registers(regs);
- DBG(DBG_info, "%s: starting second line reading\n", __func__);
-
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
- auto second_line = read_unshuffled_image_from_scanner(dev, session,
- session.output_total_bytes_raw);
- scanner_stop_action_no_move(*dev, regs);
-
- for (unsigned ch = 0; ch < 3; ch++){
- topavg[ch] = dark_average_channel(second_line, black_pixels, ch);
- DBG(DBG_io2, "%s: top avg %d=%d\n", __func__, ch, topavg[ch]);
- }
-
- pass = 0;
-
- std::vector<uint8_t> debug_image;
- size_t debug_image_lines = 0;
- std::string debug_image_info;
-
- /* loop until acceptable level */
- while ((pass < 32)
- && ((top[0] - bottom[0] > 1)
- || (top[1] - bottom[1] > 1) || (top[2] - bottom[2] > 1)))
- {
- pass++;
-
- // settings for new scan
- for (unsigned ch = 0; ch < 3; ch++) {
- if (top[ch] - bottom[ch] > 1) {
- dev->frontend.set_offset(ch, (top[ch] + bottom[ch]) / 2);
- }
- }
- dev->cmd_set->set_fe(dev, calib_sensor, AFE_SET);
-
- // scan with no move
- dev->interface->write_registers(regs);
- DBG(DBG_info, "%s: starting second line reading\n", __func__);
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
- second_line = read_unshuffled_image_from_scanner(dev, session,
- session.output_total_bytes_raw);
- scanner_stop_action_no_move(*dev, regs);
-
- if (DBG_LEVEL >= DBG_data)
- {
- char title[100];
- std::snprintf(title, 100, "lines: %d pixels_per_line: %d offsets[0..2]: %d %d %d\n",
- lines, pixels,
- dev->frontend.get_offset(0),
- dev->frontend.get_offset(1),
- dev->frontend.get_offset(2));
- debug_image_info += title;
- std::copy(second_line.get_row_ptr(0),
- second_line.get_row_ptr(0) + second_line.get_row_bytes() * second_line.get_height(),
- std::back_inserter(debug_image));
- debug_image_lines += lines;
- }
-
- for (unsigned ch = 0; ch < 3; ch++) {
- avg[ch] = dark_average_channel(second_line, black_pixels, ch);
- DBG(DBG_info, "%s: avg[%d]=%d offset=%d\n", __func__, ch, avg[ch],
- dev->frontend.get_offset(ch));
- }
-
- // compute new boundaries
- for (unsigned ch = 0; ch < 3; ch++) {
- if (topavg[ch] >= avg[ch]) {
- topavg[ch] = avg[ch];
- top[ch] = dev->frontend.get_offset(ch);
- } else {
- bottomavg[ch] = avg[ch];
- bottom[ch] = dev->frontend.get_offset(ch);
- }
- }
- }
-
- if (DBG_LEVEL >= DBG_data)
- {
- sanei_genesys_write_file("gl843_offset_all_desc.txt",
- reinterpret_cast<const std::uint8_t*>(debug_image_info.data()),
- debug_image_info.size());
- sanei_genesys_write_pnm_file("gl843_offset_all.pnm",
- debug_image.data(), session.params.depth, channels, pixels,
- debug_image_lines);
- }
-
- 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 CommandSetGl843::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 factor, dpihw;
- float coeff;
- int lines;
- int resolution;
-
- if (dev->frontend.layout.type != FrontendType::WOLFSON)
- return;
+ scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
+}
- dpihw = sensor.get_logical_hwdpi(dpi);
- factor=sensor.optical_res/dpihw;
+// wait for lamp warmup by scanning the same line until difference
+// between 2 scans is below a threshold
+void CommandSetGl843::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set* reg) const
+{
+ DBG_HELPER(dbg);
+ (void) sensor;
- // coarse gain calibration is always done in color mode
unsigned channels = 3;
+ unsigned resolution = dev->model->get_resolution_settings(dev->settings.scan_method)
+ .get_nearest_resolution_x(600);
- /* follow CKSEL */
- if (dev->model->sensor_id == SensorId::CCD_KVSS080) {
- if(dev->settings.xres<sensor.optical_res)
- {
- coeff = 0.9f;
- }
- else
- {
- coeff=1.0;
- }
- }
- else
- {
- coeff=1.0;
- }
- resolution=dpihw;
- lines=10;
- int target_pixels = sensor.sensor_pixels / factor;
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
+ dev->settings.scan_method);
+ unsigned num_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH / 2;
- ScanFlag flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA |
- ScanFlag::SINGLE_LINE |
- ScanFlag::IGNORE_LINE_DISTANCE;
+ *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;
}
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
- dev->settings.scan_method);
-
ScanSession session;
session.params.xres = resolution;
session.params.yres = resolution;
- session.params.startx = 0;
+ session.params.startx = (num_pixels / 2) * resolution / calib_sensor.full_resolution;
session.params.starty = 0;
- session.params.pixels = target_pixels;
- session.params.lines = lines;
- session.params.depth = 8;
+ session.params.pixels = num_pixels;
+ session.params.lines = 1;
+ session.params.depth = dev->model->bpp_color_values.front();
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 = flags;
- compute_session(dev, session, calib_sensor);
- std::size_t pixels = session.output_pixels;
-
- try {
- init_regs_for_scan_session(dev, calib_sensor, &regs, 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);
-
- dev->cmd_set->set_fe(dev, calib_sensor, AFE_SET);
- dev->cmd_set->begin_scan(dev, calib_sensor, &regs, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("coarse_gain_calibration");
- scanner_stop_action(*dev);
- move_back_home(dev, true);
- return;
- }
-
- auto line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes_raw);
- scanner_stop_action_no_move(*dev, regs);
-
- if (DBG_LEVEL >= DBG_data) {
- sanei_genesys_write_pnm_file("gl843_gain.pnm", line);
- }
-
- // average value on each channel
- for (unsigned ch = 0; ch < channels; ch++) {
-
- std::vector<uint16_t> values;
- // FIXME: start from the second line because the first line often has artifacts. Probably
- // caused by unclean cleanup of previous scan
- for (std::size_t x = pixels / 4; x < (pixels * 3 / 4); x++) {
- values.push_back(line.get_raw_channel(x, 1, ch));
- }
- // 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 curr_output = values[unsigned((values.size() - 1) * 0.95)];
- float target_value = calib_sensor.gain_white_ref * coeff;
-
- int code = compute_frontend_gain(curr_output, target_value, dev->frontend.layout.type);
- dev->frontend.set_gain(ch, code);
-
- DBG(DBG_proc, "%s: channel %d, max=%d, target=%d, setting:%d\n", __func__, ch, curr_output,
- static_cast<int>(target_value), code);
- }
-
- 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);
-}
-
-// wait for lamp warmup by scanning the same line until difference
-// between 2 scans is below a threshold
-void CommandSetGl843::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* reg, int* channels,
- int* total_size) const
-{
- DBG_HELPER(dbg);
- int num_pixels;
- int dpihw;
- int resolution;
- int factor;
-
- /* setup scan */
- *channels=3;
- resolution=600;
- dpihw = sensor.get_logical_hwdpi(resolution);
- resolution=dpihw;
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, *channels,
- dev->settings.scan_method);
- factor = calib_sensor.optical_res/dpihw;
- num_pixels = calib_sensor.sensor_pixels/(factor*2);
- *total_size = num_pixels * 3 * 1;
-
- *reg = dev->reg;
-
- ScanSession session;
- session.params.xres = resolution;
- session.params.yres = resolution;
- session.params.startx = num_pixels/2;
- session.params.starty = 0;
- session.params.pixels = num_pixels;
- session.params.lines = 1;
- 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, calib_sensor);
init_regs_for_scan_session(dev, calib_sensor, reg, session);
sanei_genesys_set_motor_power(*reg, false);
- dev->interface->write_registers(*reg);
}
/**
@@ -2654,7 +1610,7 @@ void CommandSetGl843::asic_boot(Genesys_Device* dev, bool cold) const
val = dev->reg.find_reg(0x0b).value & REG_0x0B_DRAMSEL;
val = (val | REG_0x0B_ENBDRAM);
dev->interface->write_register(REG_0x0B, val);
- dev->reg.find_reg(0x0b).value = val;
+ dev->reg.find_reg(0x0b).value = val;
if (dev->model->model_id == ModelId::CANON_8400F) {
dev->interface->write_0x8c(0x1e, 0x01);
@@ -2691,18 +1647,11 @@ void CommandSetGl843::asic_boot(Genesys_Device* dev, bool cold) const
val = (dev->reg.find_reg(0x0b).value & ~REG_0x0B_CLKSET) | clock_freq;
dev->interface->write_register(REG_0x0B, val);
- dev->reg.find_reg(0x0b).value = val;
+ dev->reg.find_reg(0x0b).value = val;
/* prevent further writings by bulk write register */
dev->reg.remove_reg(0x0b);
- if (dev->model->model_id != ModelId::CANON_8600F) {
- // set up end access
- // FIXME: this is overwritten in gl843_init_gpio
- dev->interface->write_register(REG_0xA7, 0x04);
- dev->interface->write_register(REG_0xA9, 0x00);
- }
-
// set RAM read address
dev->interface->write_register(REG_0x29, 0x00);
dev->interface->write_register(REG_0x2A, 0x00);
@@ -2710,8 +1659,6 @@ void CommandSetGl843::asic_boot(Genesys_Device* dev, bool cold) const
// setup gpio
gl843_init_gpio(dev);
-
- scanner_move(*dev, dev->model->default_method, 300, Direction::FORWARD);
dev->interface->sleep_ms(100);
}
@@ -2724,7 +1671,7 @@ void CommandSetGl843::init(Genesys_Device* dev) const
DBG_INIT ();
DBG_HELPER(dbg);
- sanei_genesys_asic_init(dev, 0);
+ sanei_genesys_asic_init(dev);
}
void CommandSetGl843::update_hardware_sensors(Genesys_Scanner* s) const
@@ -2754,216 +1701,10 @@ void CommandSetGl843::update_hardware_sensors(Genesys_Scanner* s) const
}
}
-/** @brief move sensor to transparency adaptor
- * Move sensor to the calibration of the transparency adapator (XPA).
- * @param dev device to use
- */
-void CommandSetGl843::move_to_ta(Genesys_Device* dev) const
+void CommandSetGl843::update_home_sensor_gpio(Genesys_Device& dev) const
{
DBG_HELPER(dbg);
-
- const auto& resolution_settings = dev->model->get_resolution_settings(dev->model->default_method);
- float resolution = resolution_settings.get_min_resolution_y();
-
- unsigned multiplier = 16;
- if (dev->model->model_id == ModelId::CANON_8400F) {
- multiplier = 4;
- }
- unsigned feed = static_cast<unsigned>(multiplier * (dev->model->y_offset_sensor_to_ta * resolution) /
- MM_PER_INCH);
- scanner_move(*dev, dev->model->default_method, feed, Direction::FORWARD);
-}
-
-
-/** @brief search for a full width black or white strip.
- * This function searches for a black or white stripe across the scanning area.
- * When searching backward, the searched area must completely be of the desired
- * color since this area will be used for calibration which scans forward.
- * @param dev scanner device
- * @param forward true if searching forward, false if searching backward
- * @param black true if searching for a black strip, false for a white strip
- */
-void CommandSetGl843::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const
-{
- DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
- unsigned int pixels, lines, channels;
- Genesys_Register_Set local_reg;
- int dpi;
- unsigned int pass, count, found, x, y;
-
- dev->cmd_set->set_fe(dev, sensor, AFE_SET);
- scanner_stop_action(*dev);
-
- /* set up for a gray scan at lowest dpi */
- dpi = sanei_genesys_get_lowest_dpi(dev);
- channels = 1;
-
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, dpi, channels,
- dev->settings.scan_method);
-
- /* 10 MM */
- /* lines = (10 * dpi) / MM_PER_INCH; */
- /* shading calibation is done with dev->motor.base_ydpi */
- lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
- pixels = (calib_sensor.sensor_pixels * dpi) / calib_sensor.optical_res;
-
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
-
- local_reg = dev->reg;
-
- ScanSession session;
- session.params.xres = dpi;
- session.params.yres = dpi;
- 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::GRAY;
- session.params.color_filter = ColorFilter::RED;
- session.params.flags = ScanFlag::DISABLE_SHADING | ScanFlag::DISABLE_SHADING;
- if (!forward) {
- session.params.flags = ScanFlag::REVERSE;
- }
- compute_session(dev, session, calib_sensor);
-
- init_regs_for_scan_session(dev, calib_sensor, &local_reg, session);
-
- dev->interface->write_registers(local_reg);
-
- dev->cmd_set->begin_scan(dev, calib_sensor, &local_reg, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("search_strip");
- scanner_stop_action(*dev);
- return;
- }
-
- wait_until_buffer_non_empty(dev);
-
- // now we're on target, we can read data
- auto data = read_unshuffled_image_from_scanner(dev, session,
- session.output_total_bytes_raw);
-
- scanner_stop_action(*dev);
-
- pass = 0;
- if (DBG_LEVEL >= DBG_data)
- {
- char fn[40];
- std::snprintf(fn, 40, "gl843_search_strip_%s_%s%02d.pnm",
- black ? "black" : "white", forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file(fn, data);
- }
-
- /* loop until strip is found or maximum pass number done */
- found = 0;
- while (pass < 20 && !found)
- {
- dev->interface->write_registers(local_reg);
-
- // now start scan
- dev->cmd_set->begin_scan(dev, calib_sensor, &local_reg, true);
-
- wait_until_buffer_non_empty(dev);
-
- // now we're on target, we can read data
- data = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes_raw);
-
- scanner_stop_action(*dev);
-
- if (DBG_LEVEL >= DBG_data)
- {
- char fn[40];
- std::snprintf(fn, 40, "gl843_search_strip_%s_%s%02d.pnm",
- black ? "black" : "white", forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file(fn, data);
- }
-
- /* search data to find black strip */
- /* when searching forward, we only need one line of the searched color since we
- * will scan forward. But when doing backward search, we need all the area of the
- * same color */
- if (forward)
- {
- for (y = 0; y < lines && !found; y++)
- {
- count = 0;
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data.get_raw_channel(x, y, 0) > 90) {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data.get_raw_channel(x, y, 0) < 60) {
- count++;
- }
- }
-
- /* at end of line, if count >= 3%, line is not fully of the desired color
- * so we must go to next line of the buffer */
- /* count*100/pixels < 3 */
- if ((count * 100) / pixels < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
- pass, y);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- }
- else /* since calibration scans are done forward, we need the whole area
- to be of the required color when searching backward */
- {
- count = 0;
- for (y = 0; y < lines; y++)
- {
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- // when searching for black, detect white pixels
- if (black && data.get_raw_channel(x, y, 0) > 90) {
- count++;
- }
- // when searching for white, detect black pixels
- if (!black && data.get_raw_channel(x, y, 0) < 60) {
- count++;
- }
- }
- }
-
- /* at end of area, if count >= 3%, area is not fully of the desired color
- * so we must go to next buffer */
- if ((count * 100) / (pixels * lines) < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- pass++;
- }
- if (found)
- {
- DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
- }
- else
- {
- throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
- }
+ (void) dev;
}
/**
@@ -2974,43 +1715,27 @@ void CommandSetGl843::send_shading_data(Genesys_Device* dev, const Genesys_Senso
uint8_t* data, int size) const
{
DBG_HELPER(dbg);
- uint32_t final_size, length, i;
+ uint32_t final_size, i;
uint8_t *buffer;
- int count,offset;
- GenesysRegister *r;
- uint16_t strpixel, endpixel, startx;
-
- offset=0;
- length=size;
- r = sanei_genesys_get_address(&dev->reg, REG_0x01);
- if (r->value & REG_0x01_SHDAREA)
- {
- /* recompute STRPIXEL used shading calibration so we can
- * compute offset within data for SHDAREA case */
-
- // FIXME: the following is likely incorrect
- // start coordinate in optical dpi coordinates
- startx = (sensor.dummy_pixel / sensor.ccd_pixels_per_system_pixel()) / dev->session.hwdpi_divisor;
- startx *= dev->session.pixel_count_multiplier;
-
- /* current scan coordinates */
- strpixel = dev->session.pixel_startx;
- endpixel = dev->session.pixel_endx;
-
- if (dev->model->model_id == ModelId::CANON_4400F ||
- dev->model->model_id == ModelId::CANON_8600F)
- {
- int half_ccd_factor = dev->session.optical_resolution /
- sensor.get_logical_hwdpi(dev->session.output_resolution);
- strpixel /= half_ccd_factor * sensor.ccd_pixels_per_system_pixel();
- endpixel /= half_ccd_factor * sensor.ccd_pixels_per_system_pixel();
- }
+ int count;
+
+ int offset = 0;
+ unsigned length = size;
+
+ if (dev->reg.get8(REG_0x01) & REG_0x01_SHDAREA) {
+ offset = dev->session.params.startx * sensor.shading_resolution /
+ dev->session.params.xres;
- /* 16 bit words, 2 words per color, 3 color channels */
- offset=(strpixel-startx)*2*2*3;
- length=(endpixel-strpixel)*2*2*3;
- DBG(DBG_info, "%s: STRPIXEL=%d, ENDPIXEL=%d, startx=%d\n", __func__, strpixel, endpixel,
- startx);
+ length = dev->session.output_pixels * sensor.shading_resolution /
+ dev->session.params.xres;
+
+ offset += sensor.shading_pixel_offset;
+
+ // 16 bit words, 2 words per color, 3 color channels
+ length *= 2 * 2 * 3;
+ offset *= 2 * 2 * 3;
+ } else {
+ offset += sensor.shading_pixel_offset * 2 * 2 * 3;
}
dev->interface->record_key_value("shading_offset", std::to_string(offset));
@@ -3024,6 +1749,14 @@ void CommandSetGl843::send_shading_data(Genesys_Device* dev, const Genesys_Senso
/* copy regular shading data to the expected layout */
buffer = final_data.data();
count = 0;
+ if (offset < 0) {
+ count += (-offset);
+ length -= (-offset);
+ offset = 0;
+ }
+ if (static_cast<int>(length) + offset > static_cast<int>(size)) {
+ length = size - offset;
+ }
/* loop over calibration data */
for (i = 0; i < length; i++)
@@ -3036,8 +1769,7 @@ void CommandSetGl843::send_shading_data(Genesys_Device* dev, const Genesys_Senso
}
}
- dev->interface->write_buffer(0x3c, 0, final_data.data(), count,
- ScannerInterface::FLAG_SMALL_ADDRESS);
+ dev->interface->write_buffer(0x3c, 0, final_data.data(), count);
}
bool CommandSetGl843::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
@@ -3051,10 +1783,5 @@ void CommandSetGl843::wait_for_motor_stop(Genesys_Device* dev) const
(void) dev;
}
-std::unique_ptr<CommandSet> create_gl843_cmd_set()
-{
- return std::unique_ptr<CommandSet>(new CommandSetGl843{});
-}
-
} // namespace gl843
} // namespace genesys
diff --git a/backend/genesys/gl843.h b/backend/genesys/gl843.h
index 9f0a9e9..5326a2d 100644
--- a/backend/genesys/gl843.h
+++ b/backend/genesys/gl843.h
@@ -42,7 +42,7 @@
*/
#include "genesys.h"
-#include "command_set.h"
+#include "command_set_common.h"
#ifndef BACKEND_GENESYS_GL843_H
#define BACKEND_GENESYS_GL843_H
@@ -50,7 +50,7 @@
namespace genesys {
namespace gl843 {
-class CommandSetGl843 : public CommandSet
+class CommandSetGl843 : public CommandSetCommon
{
public:
~CommandSetGl843() override = default;
@@ -60,17 +60,11 @@ public:
void init(Genesys_Device* dev) const override;
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const override;
-
- void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const override;
+ Genesys_Register_Set* regs) const override;
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
- void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
-
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set* reg,
const ScanSession& session) const override;
@@ -86,8 +80,6 @@ public:
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
- void search_start_position(Genesys_Device* dev) const override;
-
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
@@ -103,17 +95,14 @@ public:
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
+ void update_home_sensor_gpio(Genesys_Device& dev) const override;
+
void load_document(Genesys_Device* dev) const override;
void detect_document_end(Genesys_Device* dev) const override;
void eject_document(Genesys_Device* dev) const override;
- void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const override;
-
- void move_to_ta(Genesys_Device* dev) const override;
-
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
int size) const override;
diff --git a/backend/genesys/gl843_registers.h b/backend/genesys/gl843_registers.h
index 8ecb0fc..cbc38c0 100644
--- a/backend/genesys/gl843_registers.h
+++ b/backend/genesys/gl843_registers.h
@@ -338,6 +338,16 @@ static constexpr RegAddr REG_CK4MAP = 0x7a;
static constexpr RegAddr REG_0x7E = 0x7e;
+static constexpr RegAddr REG_0x80 = 0x80;
+static constexpr RegMask REG_0x80_TABLE1_NORMAL = 0x03;
+static constexpr RegShift REG_0x80S_TABLE1_NORMAL = 0;
+static constexpr RegMask REG_0x80_TABLE2_BACK = 0x0c;
+static constexpr RegShift REG_0x80S_TABLE2_BACK = 2;
+static constexpr RegMask REG_0x80_TABLE4_FAST = 0x30;
+static constexpr RegShift REG_0x80S_TABLE4_FAST = 4;
+static constexpr RegMask REG_0x80_TABLE5_GO_HOME = 0xc0;
+static constexpr RegShift REG_0x80S_TABLE5_GO_HOME = 6;
+
static constexpr RegAddr REG_0x9D = 0x9d;
static constexpr RegShift REG_0x9DS_STEPTIM = 2;
diff --git a/backend/genesys/gl846.cpp b/backend/genesys/gl846.cpp
index d309d29..cae7414 100644
--- a/backend/genesys/gl846.cpp
+++ b/backend/genesys/gl846.cpp
@@ -61,38 +61,12 @@ namespace gl846 {
/**
* compute the step multiplier used
*/
-static int
-gl846_get_step_multiplier (Genesys_Register_Set * regs)
+static int gl846_get_step_multiplier (Genesys_Register_Set * regs)
{
- GenesysRegister *r = sanei_genesys_get_address(regs, 0x9d);
- int value = 1;
- if (r != nullptr) {
- value = (r->value & 0x0f)>>1;
- value = 1 << value;
- }
- DBG (DBG_io, "%s: step multiplier is %d\n", __func__, value);
- return value;
-}
-
-/** @brief sensor specific settings
-*/
-static void gl846_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->set16(REG_EXPR, sensor.exposure.red);
- regs->set16(REG_EXPG, sensor.exposure.green);
- regs->set16(REG_EXPB, sensor.exposure.blue);
-
- dev->segment_order = sensor.segment_order;
+ unsigned value = (regs->get8(0x9d) & 0x0f) >> 1;
+ return 1 << value;
}
-
/** @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.
@@ -108,23 +82,56 @@ gl846_init_registers (Genesys_Device * dev)
dev->reg.clear();
dev->reg.init_reg(0x01, 0x60);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x01, 0x22);
+ }
dev->reg.init_reg(0x02, 0x38);
dev->reg.init_reg(0x03, 0x03);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x03, 0xbf);
+ }
dev->reg.init_reg(0x04, 0x22);
dev->reg.init_reg(0x05, 0x60);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x05, 0x48);
+ }
dev->reg.init_reg(0x06, 0x10);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x06, 0xf0);
+ }
dev->reg.init_reg(0x08, 0x60);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x08, 0x00);
+ }
dev->reg.init_reg(0x09, 0x00);
dev->reg.init_reg(0x0a, 0x00);
dev->reg.init_reg(0x0b, 0x8b);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0x0b, 0x2a);
+ }
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x0b, 0x4a);
+ }
dev->reg.init_reg(0x0c, 0x00);
dev->reg.init_reg(0x0d, 0x00);
- dev->reg.init_reg(0x10, 0x00);
- dev->reg.init_reg(0x11, 0x00);
- dev->reg.init_reg(0x12, 0x00);
- dev->reg.init_reg(0x13, 0x00);
- dev->reg.init_reg(0x14, 0x00);
- dev->reg.init_reg(0x15, 0x00);
+ dev->reg.init_reg(0x10, 0x00); // exposure, set during sensor setup
+ dev->reg.init_reg(0x11, 0x00); // exposure, set during sensor setup
+ dev->reg.init_reg(0x12, 0x00); // exposure, set during sensor setup
+ dev->reg.init_reg(0x13, 0x00); // exposure, set during sensor setup
+ dev->reg.init_reg(0x14, 0x00); // exposure, set during sensor setup
+ dev->reg.init_reg(0x15, 0x00); // exposure, set during sensor setup
dev->reg.init_reg(0x16, 0xbb); // SENSOR_DEF
dev->reg.init_reg(0x17, 0x13); // SENSOR_DEF
dev->reg.init_reg(0x18, 0x10); // SENSOR_DEF
@@ -133,33 +140,52 @@ gl846_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0x1b, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x1c, 0x20); // SENSOR_DEF
dev->reg.init_reg(0x1d, 0x06); // SENSOR_DEF
- dev->reg.init_reg(0x1e, 0xf0);
+ dev->reg.init_reg(0x1e, 0xf0); // WDTIME, LINESEL: set during sensor and motor setup
+
+ // SCANFED
dev->reg.init_reg(0x1f, 0x01);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400) {
+ dev->reg.init_reg(0x1f, 0x00);
+ }
+
dev->reg.init_reg(0x20, 0x03);
- dev->reg.init_reg(0x21, 0x10);
- dev->reg.init_reg(0x22, 0x60);
- dev->reg.init_reg(0x23, 0x60);
- dev->reg.init_reg(0x24, 0x60);
- dev->reg.init_reg(0x25, 0x00);
- dev->reg.init_reg(0x26, 0x00);
- dev->reg.init_reg(0x27, 0x00);
- dev->reg.init_reg(0x2c, 0x00);
- dev->reg.init_reg(0x2d, 0x00);
- 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);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x20, 0x55);
+ }
+ dev->reg.init_reg(0x21, 0x10); // STEPNO: set during motor setup
+ dev->reg.init_reg(0x22, 0x60); // FWDSTEP: set during motor setup
+ dev->reg.init_reg(0x23, 0x60); // BWDSTEP: set during motor setup
+ dev->reg.init_reg(0x24, 0x60); // FASTNO: set during motor setup
+ dev->reg.init_reg(0x25, 0x00); // LINCNT: set during motor setup
+ dev->reg.init_reg(0x26, 0x00); // LINCNT: set during motor setup
+ dev->reg.init_reg(0x27, 0x00); // LINCNT: set during motor setup
+ dev->reg.init_reg(0x2c, 0x00); // DPISET: set during sensor setup
+ dev->reg.init_reg(0x2d, 0x00); // DPISET: set during sensor setup
+ dev->reg.init_reg(0x2e, 0x80); // BWHI: set during sensor setup
+ dev->reg.init_reg(0x2f, 0x80); // BWLOW: set during sensor setup
+ dev->reg.init_reg(0x30, 0x00); // STRPIXEL: set during sensor setup
+ dev->reg.init_reg(0x31, 0x00); // STRPIXEL: set during sensor setup
+ dev->reg.init_reg(0x32, 0x00); // ENDPIXEL: set during sensor setup
+ dev->reg.init_reg(0x33, 0x00); // ENDPIXEL: set during sensor setup
+
+ // DUMMY: the number of CCD dummy pixels
dev->reg.init_reg(0x34, 0x1f);
- dev->reg.init_reg(0x35, 0x00);
- dev->reg.init_reg(0x36, 0x40);
- dev->reg.init_reg(0x37, 0x00);
- dev->reg.init_reg(0x38, 0x2a);
- dev->reg.init_reg(0x39, 0xf8);
- dev->reg.init_reg(0x3d, 0x00);
- dev->reg.init_reg(0x3e, 0x00);
- dev->reg.init_reg(0x3f, 0x01);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x34, 0x14);
+ }
+
+ dev->reg.init_reg(0x35, 0x00); // MAXWD: set during scan setup
+ dev->reg.init_reg(0x36, 0x40); // MAXWD: set during scan setup
+ dev->reg.init_reg(0x37, 0x00); // MAXWD: set during scan setup
+ dev->reg.init_reg(0x38, 0x2a); // LPERIOD: set during sensor setup
+ dev->reg.init_reg(0x39, 0xf8); // LPERIOD: set during sensor setup
+ dev->reg.init_reg(0x3d, 0x00); // FEEDL: set during motor setup
+ dev->reg.init_reg(0x3e, 0x00); // FEEDL: set during motor setup
+ dev->reg.init_reg(0x3f, 0x01); // FEEDL: set during motor setup
dev->reg.init_reg(0x52, 0x02); // SENSOR_DEF
dev->reg.init_reg(0x53, 0x04); // SENSOR_DEF
dev->reg.init_reg(0x54, 0x06); // SENSOR_DEF
@@ -169,22 +195,30 @@ gl846_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0x58, 0x59); // SENSOR_DEF
dev->reg.init_reg(0x59, 0x31); // SENSOR_DEF
dev->reg.init_reg(0x5a, 0x40); // SENSOR_DEF
+
+ // DECSEL, STEPTIM
dev->reg.init_reg(0x5e, 0x1f);
- dev->reg.init_reg(0x5f, 0x01);
- dev->reg.init_reg(0x60, 0x00);
- dev->reg.init_reg(0x61, 0x00);
- dev->reg.init_reg(0x62, 0x00);
- dev->reg.init_reg(0x63, 0x00);
- dev->reg.init_reg(0x64, 0x00);
- dev->reg.init_reg(0x65, 0x00);
- dev->reg.init_reg(0x67, 0x7f);
- dev->reg.init_reg(0x68, 0x7f);
- dev->reg.init_reg(0x69, 0x01);
- dev->reg.init_reg(0x6a, 0x01);
- dev->reg.init_reg(0x70, 0x01);
- dev->reg.init_reg(0x71, 0x00);
- dev->reg.init_reg(0x72, 0x02);
- dev->reg.init_reg(0x73, 0x01);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x5e, 0x01);
+ }
+ dev->reg.init_reg(0x5f, 0x01); // FMOVDEC: overwritten during motor setup
+ dev->reg.init_reg(0x60, 0x00); // STEPSEL, Z1MOD: overwritten during motor setup
+ dev->reg.init_reg(0x61, 0x00); // Z1MOD: overwritten during motor setup
+ dev->reg.init_reg(0x62, 0x00); // Z1MOD: overwritten during motor setup
+ dev->reg.init_reg(0x63, 0x00); // FSTPSEL, Z2MOD: overwritten during motor setup
+ dev->reg.init_reg(0x64, 0x00); // Z2MOD: overwritten during motor setup
+ dev->reg.init_reg(0x65, 0x00); // Z2MOD: overwritten during motor setup
+ dev->reg.init_reg(0x67, 0x7f); // MTRPWM: overwritten during motor setup
+ dev->reg.init_reg(0x68, 0x7f); // FASTPWM: overwritten during motor setup
+ dev->reg.init_reg(0x69, 0x01); // FSHDEC: overwritten during motor setup
+ dev->reg.init_reg(0x6a, 0x01); // FMOVNO: overwritten during motor setup
+ // 0x6b, 0x6c, 0x6d, 0x6e, 0x6f - gpio
+ dev->reg.init_reg(0x70, 0x01); // SENSOR_DEF
+ dev->reg.init_reg(0x71, 0x00); // SENSOR_DEF
+ dev->reg.init_reg(0x72, 0x02); // SENSOR_DEF
+ dev->reg.init_reg(0x73, 0x01); // SENSOR_DEF
dev->reg.init_reg(0x74, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x75, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x76, 0x00); // SENSOR_DEF
@@ -194,78 +228,80 @@ gl846_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0x7a, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x7b, 0x09); // SENSOR_DEF
dev->reg.init_reg(0x7c, 0x99); // SENSOR_DEF
- dev->reg.init_reg(0x7d, 0x20);
+ dev->reg.init_reg(0x7d, 0x20); // SENSOR_DEF
dev->reg.init_reg(0x7f, 0x05);
- dev->reg.init_reg(0x80, 0x4f);
- dev->reg.init_reg(0x87, 0x02);
- dev->reg.init_reg(0x94, 0xff);
- dev->reg.init_reg(0x9d, 0x04);
- dev->reg.init_reg(0x9e, 0x00);
- dev->reg.init_reg(0xa1, 0xe0);
- dev->reg.init_reg(0xa2, 0x1f);
- dev->reg.init_reg(0xab, 0xc0);
- dev->reg.init_reg(0xbb, 0x00);
- dev->reg.init_reg(0xbc, 0x0f);
- dev->reg.init_reg(0xdb, 0xff);
- dev->reg.init_reg(0xfe, 0x08);
- dev->reg.init_reg(0xff, 0x02);
- dev->reg.init_reg(0x98, 0x20);
- dev->reg.init_reg(0x99, 0x00);
- dev->reg.init_reg(0x9a, 0x90);
- dev->reg.init_reg(0x9b, 0x00);
- dev->reg.init_reg(0xf8, 0x05);
-
- const auto& sensor = sanei_genesys_find_sensor_any(dev);
- sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
-
- /* initalize calibration reg */
- dev->calib_reg = dev->reg;
-}
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->reg.init_reg(0x7f, 0x00);
+ }
+ dev->reg.init_reg(0x80, 0x4f); // overwritten during motor setup
+ dev->reg.init_reg(0x87, 0x02); // SENSOR_DEF
-/**@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 elements in the slope table
- */
-static void gl846_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];
+ // MTRPLS: pulse width of ADF motor trigger signal
+ dev->reg.init_reg(0x94, 0x00);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0x94, 0xff);
+ }
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0x98, 0x20); // ONDUR
+ dev->reg.init_reg(0x99, 0x00); // ONDUR
+ dev->reg.init_reg(0x9a, 0x90); // OFFDUR
+ dev->reg.init_reg(0x9b, 0x00); // OFFDUR
+ }
- /* sanity check */
- if(table_nr<0 || table_nr>4)
- {
- throw SaneException("invalid table number %d", table_nr);
+ dev->reg.init_reg(0x9d, 0x00); // contains STEPTIM
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0x9d, 0x04);
+ }
+ dev->reg.init_reg(0x9e, 0x00);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0xa1, 0xe0);
}
- std::vector<uint8_t> table(steps * 2);
- for (i = 0; i < steps; i++)
+ // RFHSET (SDRAM refresh time)
+ dev->reg.init_reg(0xa2, 0x1f);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
{
- table[i * 2] = slope_table[i] & 0xff;
- table[i * 2 + 1] = slope_table[i] >> 8;
+ dev->reg.init_reg(0xa2, 0x0f);
}
- if (DBG_LEVEL >= DBG_io)
+ // 0xa6, 0xa7 0xa8, 0xa9 - gpio
+
+ // Various important settings: GPOM9, MULSTOP, NODECEL, TB3TB1, TB5TB2, FIX16CLK
+ dev->reg.init_reg(0xab, 0xc0);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
{
- std::sprintf(msg, "write slope %d (%d)=", table_nr, steps);
- for (i = 0; i < steps; i++)
- {
- std::sprintf(msg+strlen(msg), "%d", slope_table[i]);
- }
- DBG (DBG_io, "%s: %s\n", __func__, msg);
+ dev->reg.init_reg(0xab, 0x01);
+ }
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0xbb, 0x00); // FIXME: default is the same
+ }
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0xbc, 0x0f);
+ dev->reg.init_reg(0xdb, 0xff);
+ }
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400) {
+ dev->reg.init_reg(0xbe, 0x07);
}
- if (dev->interface->is_mock()) {
- dev->interface->record_slope_table(table_nr, slope_table);
+ // 0xd0, 0xd1, 0xd2 - SH0DWN, SH1DWN, SH2DWN - shading bank[0..2] for CCD.
+ // Set during memory layout setup
+
+ // [0xe0..0xf7] - image buffer addresses. Set during memory layout setup
+ dev->reg.init_reg(0xf8, 0x05); // MAXSEL, MINSEL
+
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ dev->reg.init_reg(0xfe, 0x08); // MOTTGST, AUTO_O
+ dev->reg.init_reg(0xff, 0x02); // AUTO_S
}
- // slope table addresses are fixed
- dev->interface->write_ahb(0x10000000 + 0x4000 * table_nr, steps * 2, table.data());
+
+ const auto& sensor = sanei_genesys_find_sensor_any(dev);
+ const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, sensor.full_resolution,
+ 3, dev->model->default_method);
+ sanei_genesys_set_dpihw(dev->reg, dpihw_sensor.register_dpihw);
}
/**
@@ -283,11 +319,8 @@ static void gl846_set_adi_fe(Genesys_Device* dev, uint8_t set)
status = scanner_read_status(*dev);
};
- 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;
}
// write them to analog frontend
@@ -326,115 +359,110 @@ void CommandSetGl846::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
// @brief set up motor related register for scan
static void gl846_init_motor_regs_scan(Genesys_Device* dev,
const Genesys_Sensor& sensor,
+ const ScanSession& session,
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,
- MotorFlag flags)
+ ScanFlag flags)
{
DBG_HELPER_ARGS(dbg, "scan_exposure_time=%d, scan_yres=%d, step_type=%d, scan_lines=%d, "
"scan_dummy=%d, feed_steps=%d, flags=%x",
scan_exposure_time, scan_yres, static_cast<unsigned>(motor_profile.step_type),
scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
- int use_fast_fed;
- unsigned int fast_dpi;
- unsigned int feedl, dist;
- GenesysRegister *r;
- uint32_t z1, z2;
- unsigned int min_restep = 0x20;
- uint8_t val;
- unsigned int ccdlmt,tgtime;
unsigned step_multiplier = gl846_get_step_multiplier(reg);
- use_fast_fed=0;
- /* no fast fed since feed works well */
- if (dev->settings.yres == 4444 && feed_steps > 100 && !has_flag(flags, MotorFlag::FEED)) {
- use_fast_fed = 1;
+ 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;
}
- DBG (DBG_io, "%s: use_fast_fed=%d\n", __func__, use_fast_fed);
reg->set24(REG_LINCNT, scan_lines);
- DBG (DBG_io, "%s: lincnt=%d\n", __func__, scan_lines);
- /* compute register 02 value */
- r = sanei_genesys_get_address(reg, REG_0x02);
- r->value = 0x00;
- sanei_genesys_set_motor_power(*reg, true);
+ reg->set8(REG_0x02, 0);
+ sanei_genesys_set_motor_power(*reg, true);
- if (use_fast_fed)
- r->value |= REG_0x02_FASTFED;
- else
- r->value &= ~REG_0x02_FASTFED;
+ std::uint8_t reg02 = reg->get8(REG_0x02);
+ if (use_fast_fed) {
+ reg02 |= REG_0x02_FASTFED;
+ } else {
+ reg02 &= ~REG_0x02_FASTFED;
+ }
- if (has_flag(flags, MotorFlag::AUTO_GO_HOME)) {
- r->value |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
+ if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
+ reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
}
- if (has_flag(flags, MotorFlag::DISABLE_BUFFER_FULL_MOVE) ||(scan_yres>=sensor.optical_res)) {
- r->value |= REG_0x02_ACDCDIS;
+ if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) || (scan_yres>=sensor.full_resolution)) {
+ reg02 |= REG_0x02_ACDCDIS;
}
- if (has_flag(flags, MotorFlag::REVERSE)) {
- r->value |= REG_0x02_MTRREV;
+ if (has_flag(flags, ScanFlag::REVERSE)) {
+ reg02 |= REG_0x02_MTRREV;
} else {
- r->value &= ~REG_0x02_MTRREV;
+ reg02 &= ~REG_0x02_MTRREV;
}
+ reg->set8(REG_0x02, reg02);
- /* scan and backtracking slope table */
- auto scan_table = sanei_genesys_slope_table(dev->model->asic_type, scan_yres,
- scan_exposure_time, dev->motor.base_ydpi,
- step_multiplier, motor_profile);
+ // scan and backtracking slope table
+ auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres,
+ scan_exposure_time, step_multiplier, motor_profile);
- gl846_send_slope_table(dev, SCAN_TABLE, scan_table.table, scan_table.steps_count);
- gl846_send_slope_table(dev, BACKTRACK_TABLE, scan_table.table, scan_table.steps_count);
+ scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
+ scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
+ scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table);
- /* fast table */
- fast_dpi=sanei_genesys_get_lowest_ydpi(dev);
+ reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
- // BUG: looks like for fast moves we use inconsistent step type
- StepType fast_step_type = motor_profile.step_type;
- if (static_cast<unsigned>(motor_profile.step_type) >= static_cast<unsigned>(StepType::QUARTER)) {
- fast_step_type = StepType::QUARTER;
+ // fast table
+ const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
+ if (fast_profile == nullptr) {
+ fast_profile = &motor_profile;
}
- Motor_Profile fast_motor_profile = motor_profile;
- fast_motor_profile.step_type = fast_step_type;
+ auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
+ *fast_profile);
- auto fast_table = sanei_genesys_slope_table(dev->model->asic_type, fast_dpi,
- scan_exposure_time, dev->motor.base_ydpi,
- step_multiplier, fast_motor_profile);
+ scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
+ scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
- gl846_send_slope_table(dev, STOP_TABLE, fast_table.table, fast_table.steps_count);
- gl846_send_slope_table(dev, FAST_TABLE, fast_table.table, fast_table.steps_count);
- gl846_send_slope_table(dev, HOME_TABLE, fast_table.table, fast_table.steps_count);
+ reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
+ reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
- /* correct move distance by acceleration and deceleration amounts */
- feedl=feed_steps;
- if (use_fast_fed)
- {
- feedl <<= static_cast<unsigned>(fast_step_type);
- dist = (scan_table.steps_count + 2 * fast_table.steps_count);
- /* TODO read and decode REG_0xAB */
- r = sanei_genesys_get_address (reg, 0x5e);
- dist += (r->value & 31);
- /* FEDCNT */
- r = sanei_genesys_get_address(reg, REG_FEDCNT);
- dist += r->value;
+ if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) {
+ std::uint8_t vref = 0;
+ vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL;
+ vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK;
+ vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST;
+ vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME;
+ reg->set8(REG_0x80, vref);
}
- else
- {
+
+ unsigned feedl = feed_steps;
+ unsigned dist = 0;
+ if (use_fast_fed) {
+ feedl <<= static_cast<unsigned>(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<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;
}
}
- DBG (DBG_io2, "%s: acceleration distance=%d\n", __func__, dist);
- /* check for overflow */
+ // check for overflow
if (dist < feedl) {
feedl -= dist;
} else {
@@ -442,13 +470,9 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev,
}
reg->set24(REG_FEEDL, feedl);
- DBG (DBG_io ,"%s: feedl=%d\n",__func__,feedl);
-
- r = sanei_genesys_get_address(reg, REG_0x0C);
- ccdlmt = (r->value & REG_0x0C_CCDLMT) + 1;
- r = sanei_genesys_get_address(reg, REG_0x1C);
- tgtime = 1 << (r->value & REG_0x1C_TGTIME);
+ unsigned ccdlmt = (reg->get8(REG_0x0C) & REG_0x0C_CCDLMT) + 1;
+ unsigned tgtime = 1 << (reg->get8(REG_0x1C) & REG_0x1C_TGTIME);
/* hi res motor speed GPIO */
/*
@@ -482,56 +506,31 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev,
dev->interface->write_register(REG_0x6C, val);
*/
- if(dev->model->gpio_id == GpioId::IMG101) {
- if (scan_yres == sensor.get_register_hwdpi(scan_yres)) {
- val=1;
- }
- else
- {
- val=0;
- }
- dev->interface->write_register(REG_0x7E, val);
- }
-
- min_restep = (scan_table.steps_count / step_multiplier) / 2 - 1;
+ unsigned min_restep = (scan_table.table.size() / step_multiplier) / 2 - 1;
if (min_restep < 1) {
min_restep = 1;
}
- r = sanei_genesys_get_address(reg, REG_FWDSTEP);
- r->value = min_restep;
- r = sanei_genesys_get_address(reg, REG_BWDSTEP);
- r->value = min_restep;
+ reg->set8(REG_FWDSTEP, min_restep);
+ reg->set8(REG_BWDSTEP, min_restep);
+
+ std::uint32_t z1, z2;
sanei_genesys_calculate_zmod(use_fast_fed,
- scan_exposure_time*ccdlmt*tgtime,
+ scan_exposure_time * ccdlmt * tgtime,
scan_table.table,
- scan_table.steps_count,
+ scan_table.table.size(),
feedl,
min_restep * step_multiplier,
&z1,
&z2);
- DBG(DBG_info, "%s: z1 = %d\n", __func__, z1);
reg->set24(REG_0x60, z1 | (static_cast<unsigned>(motor_profile.step_type) << (16 + REG_0x60S_STEPSEL)));
-
- DBG(DBG_info, "%s: z2 = %d\n", __func__, z2);
reg->set24(REG_0x63, z2 | (static_cast<unsigned>(motor_profile.step_type) << (16 + REG_0x63S_FSTPSEL)));
- r = sanei_genesys_get_address (reg, 0x1e);
- r->value &= 0xf0; /* 0 dummy lines */
- r->value |= scan_dummy; /* dummy lines */
-
- r = sanei_genesys_get_address(reg, REG_0x67);
- r->value = 0x7f;
+ reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
- r = sanei_genesys_get_address(reg, REG_0x68);
- r->value = 0x7f;
-
- reg->set8(REG_STEPNO, scan_table.steps_count / step_multiplier);
- reg->set8(REG_FASTNO, scan_table.steps_count / step_multiplier);
- reg->set8(REG_FSHDEC, scan_table.steps_count / step_multiplier);
- reg->set8(REG_FMOVNO, fast_table.steps_count / step_multiplier);
- reg->set8(REG_FMOVDEC, fast_table.steps_count / step_multiplier);
+ reg->set8(REG_0x67, 0x7f);
+ reg->set8(REG_0x68, 0x7f);
}
@@ -558,82 +557,69 @@ static void gl846_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
const ScanSession& session)
{
DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time);
- unsigned int dpihw;
- GenesysRegister *r;
-
- // 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.params.xres * ccd_pixels_per_system_pixel);
- DBG(DBG_io2, "%s: dpihw=%d\n", __func__, dpihw);
-
- gl846_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);
- r->value |= REG_0x01_SHDAREA;
+ reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
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) ||
+ session.use_host_side_calib)
{
- r->value &= ~REG_0x01_DVDSET;
- }
- else
- {
- r->value |= REG_0x01_DVDSET;
+ reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
+ } else {
+ reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
}
- r = sanei_genesys_get_address(reg, REG_0x03);
- r->value &= ~REG_0x03_AVEENB;
+ 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));
+ reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
- /* BW threshold */
- r = sanei_genesys_get_address (reg, 0x2e);
- r->value = dev->settings.threshold;
- r = sanei_genesys_get_address (reg, 0x2f);
- r->value = dev->settings.threshold;
+ // BW threshold
+ reg->set8(0x2e, 0x7f);
+ reg->set8(0x2f, 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_0x04_AFEMOD);
+ reg->find_reg(REG_0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
if (session.params.channels == 1)
{
switch (session.params.color_filter)
{
case ColorFilter::RED:
- r->value |= 0x24;
+ reg->find_reg(REG_0x04).value |= 0x24;
break;
case ColorFilter::BLUE:
- r->value |= 0x2c;
+ reg->find_reg(REG_0x04).value |= 0x2c;
break;
case ColorFilter::GREEN:
- r->value |= 0x28;
+ reg->find_reg(REG_0x04).value |= 0x28;
break;
default:
break; // should not happen
}
} else {
- r->value |= 0x20; // mono
+ reg->find_reg(REG_0x04).value |= 0x20; // mono
}
- 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;
@@ -644,38 +630,31 @@ static void gl846_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
/* 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, 0x87);
- r->value &= ~REG_0x87_LEDADD;
+ reg->find_reg(0x87).value &= ~REG_0x87_LEDADD;
+
if (session.enable_ledadd) {
- r->value |= REG_0x87_LEDADD;
+ reg->find_reg(0x87).value |= REG_0x87_LEDADD;
}
/* RGB weighting
- 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;
}*/
}
- unsigned dpiset = session.params.xres * ccd_pixels_per_system_pixel;
- reg->set16(REG_DPISET, dpiset);
- DBG(DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset);
-
+ reg->set16(REG_DPISET, sensor.register_dpiset);
reg->set16(REG_STRPIXEL, session.pixel_startx);
reg->set16(REG_ENDPIXEL, session.pixel_endx);
- build_image_pipeline(dev, session);
+ setup_image_pipeline(*dev, session);
/* MAXWD is expressed in 4 words unit */
// BUG: we shouldn't multiply by channels here
reg->set24(REG_MAXWD, (session.output_line_bytes_raw * session.params.channels >> 2));
-
reg->set16(REG_LPERIOD, exposure_time);
- DBG (DBG_io2, "%s: exposure_time used=%d\n", __func__, exposure_time);
-
- r = sanei_genesys_get_address (reg, 0x34);
- r->value = sensor.dummy_pixel;
+ reg->set8(0x34, sensor.dummy_pixel);
}
void CommandSetGl846::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
@@ -685,13 +664,12 @@ void CommandSetGl846::init_regs_for_scan_session(Genesys_Device* dev, const Gene
DBG_HELPER(dbg);
session.assert_computed();
- int move;
int exposure_time;
int slope_dpi = 0;
- int dummy = 0;
- dummy = 3-session.params.channels;
+ // FIXME: on cis scanners we may want to scan at reduced resolution
+ int dummy = 0;
/* slope_dpi */
/* cis color scan is effectively a gray scan with 3 gray lines per color
@@ -705,46 +683,18 @@ void CommandSetGl846::init_regs_for_scan_session(Genesys_Device* dev, const Gene
slope_dpi = slope_dpi * (1 + dummy);
exposure_time = sensor.exposure_lperiod;
- const auto& motor_profile = sanei_genesys_get_motor_profile(*gl846_motor_profiles,
- dev->model->motor_id,
- exposure_time);
-
- 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));
+ const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
/* we enable true gray for cis scanners only, and just when doing
* scan since color calibration is OK for this mode
*/
gl846_init_optical_regs_scan(dev, sensor, reg, exposure_time, session);
-
-/*** motor parameters ***/
-
- /* 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;
- }
-
- gl846_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, mflags);
+ gl846_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure_time, slope_dpi,
+ session.optical_line_count, dummy, session.params.starty,
+ 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;
@@ -759,21 +709,50 @@ ScanSession CommandSetGl846::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);
+ ScanFlag flags = ScanFlag::NONE;
+
+ unsigned move_dpi = dev->motor.base_ydpi;
+
+ float move = dev->model->y_offset;
+ if (settings.scan_method == ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
+ // transparency adapter
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
+ }
+ flags |= ScanFlag::USE_XPA;
+ } else {
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset;
+ }
+ }
+
+ move = move + settings.tl_y;
+ move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
+ move -= dev->head_pos(ScanHeadId::PRIMARY);
+
+ float start = dev->model->x_offset;
+ if (settings.scan_method == ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ start = dev->model->x_offset_ta;
+ } else {
+ start = dev->model->x_offset;
+ }
+
+ start = start + dev->settings.tl_x;
+ 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; // not used
- 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;
@@ -782,7 +761,8 @@ ScanSession CommandSetGl846::calculate_scan_session(const Genesys_Device* dev,
session.params.scan_method = settings.scan_method;
session.params.scan_mode = settings.scan_mode;
session.params.color_filter = settings.color_filter;
- session.params.flags = ScanFlag::NONE;
+ // backtracking isn't handled well, so don't enable it
+ session.params.flags = flags;
compute_session(dev, session, sensor);
@@ -809,24 +789,17 @@ void CommandSetGl846::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
DBG_HELPER(dbg);
(void) sensor;
uint8_t val;
- GenesysRegister *r;
- /* XXX STEF XXX SCAN GPIO */
- /*
- val = dev->interface->read_register(REG_0x6C);
- dev->interface->write_register(REG_0x6C, val);
- */
+ if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
+ dev->cmd_set->set_xpa_lamp_power(*dev, true);
+ }
- val = REG_0x0D_CLRLNCNT;
- dev->interface->write_register(REG_0x0D, val);
- val = REG_0x0D_CLRMCNT;
- dev->interface->write_register(REG_0x0D, val);
+ scanner_clear_scan_and_feed_counts(*dev);
val = dev->interface->read_register(REG_0x01);
val |= REG_0x01_SCAN;
dev->interface->write_register(REG_0x01, val);
- r = sanei_genesys_get_address (reg, REG_0x01);
- r->value = val;
+ reg->set8(REG_0x01, val);
scanner_start_action(*dev, start_motor);
@@ -841,6 +814,10 @@ void CommandSetGl846::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
(void) reg;
DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
+ if (reg->state.is_xpa_on) {
+ dev->cmd_set->set_xpa_lamp_power(*dev, false);
+ }
+
if (!dev->model->is_sheetfed) {
scanner_stop_action(*dev);
}
@@ -852,260 +829,72 @@ void CommandSetGl846::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 CommandSetGl846::search_start_position(Genesys_Device* dev) const
-{
- DBG_HELPER(dbg);
- int size;
- Genesys_Register_Set local_reg;
-
- int pixels = 600;
- int dpi = 300;
-
- local_reg = dev->reg;
-
- /* 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, dev->model->default_method);
-
- 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;
- 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("gl846_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;
-
- // TODO: find out where sanei_genesys_search_reference_point stores information,
- // and use that correctly
- 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 CommandSetGl846::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::IGNORE_LINE_DISTANCE;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &regs, session);
-
- 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
void CommandSetGl846::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
DBG_HELPER(dbg);
- float move;
- dev->calib_channels = 3;
+ unsigned move_dpi = dev->motor.base_ydpi;
- /* initial calibration reg values */
- regs = dev->reg;
+ float calib_size_mm = 0;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ calib_size_mm = dev->model->y_size_calib_ta_mm;
+ } else {
+ calib_size_mm = dev->model->y_size_calib_mm;
+ }
- dev->calib_resolution = sensor.get_register_hwdpi(dev->settings.xres);
+ unsigned channels = 3;
+ unsigned resolution = sensor.shading_resolution;
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->calib_resolution,
- dev->calib_channels,
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
dev->settings.scan_method);
- dev->calib_total_bytes_to_read = 0;
- dev->calib_lines = dev->model->shading_lines;
- if (dev->calib_resolution==4800) {
- dev->calib_lines *= 2;
- }
- dev->calib_pixels = (calib_sensor.sensor_pixels * dev->calib_resolution) /
- calib_sensor.optical_res;
- DBG(DBG_io, "%s: calib_lines = %zu\n", __func__, dev->calib_lines);
- DBG(DBG_io, "%s: calib_pixels = %zu\n", __func__, dev->calib_pixels);
+ float move = 0;
+ ScanFlag flags = ScanFlag::DISABLE_SHADING |
+ ScanFlag::DISABLE_GAMMA |
+ ScanFlag::DISABLE_BUFFER_FULL_MOVE;
- /* this is aworkaround insufficent distance for slope
- * motor acceleration TODO special motor slope for shading */
- move=1;
- if(dev->calib_resolution<1200)
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
{
- move=40;
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
+ // transparency adapter
+ move = static_cast<int>(dev->model->y_offset_calib_white_ta - dev->model->y_offset_sensor_to_ta);
+ flags |= ScanFlag::USE_XPA;
+ } else {
+ move = static_cast<int>(dev->model->y_offset_calib_white);
}
+ move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
+
+ unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
+
ScanSession session;
- session.params.xres = dev->calib_resolution;
- session.params.yres = dev->calib_resolution;
+ session.params.xres = resolution;
+ session.params.yres = resolution;
session.params.startx = 0;
session.params.starty = static_cast<unsigned>(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 = dev->settings.color_filter;
- session.params.flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA |
- ScanFlag::DISABLE_BUFFER_FULL_MOVE |
- ScanFlag::IGNORE_LINE_DISTANCE;
+ session.params.flags = flags;
compute_session(dev, session, calib_sensor);
init_regs_for_scan_session(dev, calib_sensor, &regs, session);
- dev->interface->write_registers(regs);
-
- /* we use GENESYS_FLAG_SHADING_REPARK */
+ /* we use ModelFlag::SHADING_REPARK */
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
-}
-
-/** @brief set up registers for the actual scan
- */
-void CommandSetGl846::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);
- /* steps to move to reach scanning area:
- - first we move to physical start of scanning
- either by a fixed steps amount from the black strip
- or by a fixed amount from parking position,
- minus the steps done during shading calibration
- - then we move by the needed offset whitin physical
- scanning area
-
- assumption: steps are expressed at maximum motor resolution
-
- we need:
- float y_offset;
- float y_size;
- float y_offset_calib;
- mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
-
- /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
- relative from origin, else, it is from parking position */
-
- move_dpi = dev->motor.base_ydpi;
-
- move = static_cast<float>(dev->model->y_offset);
- move = static_cast<float>(move + dev->settings.tl_y);
- move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
- move -= dev->head_pos(ScanHeadId::PRIMARY);
- DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
-
- /* fast move to scan area */
- /* we don't move fast the whole distance since it would involve
- * computing acceleration/deceleration distance for scan
- * resolution. So leave a remainder for it so scan makes the final
- * move tuning */
- 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);
- DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
-
- /* start */
- start = static_cast<float>(dev->model->x_offset);
- start = static_cast<float>(start + dev->settings.tl_x);
- 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;
- // backtracking isn't handled well, so don't enable it
- session.params.flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &dev->reg, session);
+ dev->calib_session = session;
}
-
/**
* Send shading calibration data. The buffer is considered to always hold values
* for all the channels.
@@ -1114,39 +903,24 @@ void CommandSetGl846::send_shading_data(Genesys_Device* dev, const Genesys_Senso
uint8_t* data, int size) const
{
DBG_HELPER_ARGS(dbg, "writing %d bytes of shading data", size);
- uint32_t addr, length, i, x, factor, pixels;
- uint32_t dpiset, dpihw;
+ std::uint32_t addr, i;
uint8_t val,*ptr,*src;
- /* shading data is plit in 3 (up to 5 with IR) areas
- write(0x10014000,0x00000dd8)
- URB 23429 bulk_out len 3544 wrote 0x33 0x10 0x....
- write(0x1003e000,0x00000dd8)
- write(0x10068000,0x00000dd8)
- */
- length = static_cast<uint32_t>(size / 3);
- unsigned strpixel = dev->session.pixel_startx;
- unsigned endpixel = dev->session.pixel_endx;
-
- /* 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);
-
- pixels=endpixel-strpixel;
+ unsigned length = static_cast<unsigned>(size / 3);
- /* since we're using SHDAREA, substract startx coordinate from shading */
- strpixel -= (sensor.ccd_start_xoffset * 600) / sensor.optical_res;
+ // we're using SHDAREA, thus we only need to upload part of the line
+ unsigned offset = dev->session.pixel_count_ratio.apply(
+ dev->session.params.startx * sensor.full_resolution / dev->session.params.xres);
+ unsigned pixels = dev->session.pixel_count_ratio.apply(dev->session.optical_pixels_raw);
- /* turn pixel value into bytes 2x16 bits words */
- strpixel*=2*2;
- pixels*=2*2;
+ // turn pixel value into bytes 2x16 bits words
+ offset *= 2 * 2;
+ pixels *= 2 * 2;
- dev->interface->record_key_value("shading_offset", std::to_string(strpixel));
+ dev->interface->record_key_value("shading_offset", std::to_string(offset));
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));
std::vector<uint8_t> buffer(pixels, 0);
@@ -1163,10 +937,9 @@ void CommandSetGl846::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)
- {
- /* coefficient source */
- src=(data+strpixel+i*length)+x;
+ for (unsigned x = 0; x < pixels; x += 4 * sensor.shading_factor) {
+ // coefficient source
+ src = (data + offset + i * length) + x;
/* coefficient copy */
ptr[0]=src[0];
@@ -1192,166 +965,7 @@ void CommandSetGl846::send_shading_data(Genesys_Device* dev, const Genesys_Senso
SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
- DBG_HELPER(dbg);
- int num_pixels;
- int total_size;
- int used_res;
- int i, j;
- int val;
- int channels;
- int avg[3], top[3], bottom[3];
- int turn;
- uint16_t exp[3];
-
- float move = static_cast<float>(dev->model->y_offset_calib_white);
- move = static_cast<float>((move * (dev->motor.base_ydpi / 4)) / MM_PER_INCH);
- if(move>20)
- {
- scanner_move(*dev, dev->model->default_method, static_cast<unsigned>(move),
- Direction::FORWARD);
- }
- DBG(DBG_io, "%s: move=%f steps\n", __func__, move);
-
- /* offset calibration is always done in color mode */
- channels = 3;
- used_res = sensor.get_register_hwdpi(dev->settings.xres);
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, used_res, channels,
- dev->settings.scan_method);
- num_pixels = (calib_sensor.sensor_pixels * used_res) / calib_sensor.optical_res;
-
- /* initial calibration reg values */
- regs = dev->reg;
-
- ScanSession session;
- session.params.xres = used_res;
- session.params.yres = used_res;
- 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, &regs, 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;
-
- bottom[0]=29000;
- bottom[1]=29000;
- bottom[2]=29000;
-
- top[0]=41000;
- top[1]=51000;
- top[2]=51000;
-
- turn = 0;
-
- /* no move during led calibration */
- sanei_genesys_set_motor_power(regs, false);
- bool acceptable = false;
- do
- {
- // set up exposure
- regs.set16(REG_EXPR, exp[0]);
- regs.set16(REG_EXPG, exp[1]);
- regs.set16(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, &regs, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("led_calibration");
- scanner_stop_action(*dev);
- move_back_home(dev, true);
- 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, "gl846_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++)
- {
- if(avg[i]<bottom[i])
- {
- exp[i]=(exp[i]*bottom[i])/avg[i];
- acceptable = false;
- }
- if(avg[i]>top[i])
- {
- exp[i]=(exp[i]*top[i])/avg[i];
- 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.set16(REG_EXPR, exp[0]);
- dev->reg.set16(REG_EXPG, exp[1]);
- dev->reg.set16(REG_EXPB, exp[2]);
-
- /* go back home */
- if(move>20)
- {
- move_back_home(dev, true);
- }
-
- return { exp[0], exp[1], exp[2] };
+ return scanner_led_calibration(*dev, sensor, regs);
}
/**
@@ -1360,29 +974,10 @@ SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genes
static void gl846_init_gpio(Genesys_Device* dev)
{
DBG_HELPER(dbg);
- int idx=0;
-
- /* search GPIO profile */
- while (gpios[idx].gpio_id != GpioId::UNKNOWN && dev->model->gpio_id != gpios[idx].gpio_id) {
- idx++;
- }
- if (gpios[idx].gpio_id == GpioId::UNKNOWN)
+ apply_registers_ordered(dev->gpo.regs, { 0x6e, 0x6f }, [&](const GenesysRegisterSetting& reg)
{
- throw SaneException("failed to find GPIO profile for sensor_id=%d",
- static_cast<unsigned>(dev->model->sensor_id));
- }
-
- dev->interface->write_register(REG_0xA7, gpios[idx].ra7);
- dev->interface->write_register(REG_0xA6, gpios[idx].ra6);
-
- dev->interface->write_register(REG_0x6B, gpios[idx].r6b);
- dev->interface->write_register(REG_0x6C, gpios[idx].r6c);
- dev->interface->write_register(REG_0x6D, gpios[idx].r6d);
- dev->interface->write_register(REG_0x6E, gpios[idx].r6e);
- dev->interface->write_register(REG_0x6F, gpios[idx].r6f);
-
- dev->interface->write_register(REG_0xA8, gpios[idx].ra8);
- dev->interface->write_register(REG_0xA9, gpios[idx].ra9);
+ dev->interface->write_register(reg.address, reg.value);
+ });
}
/**
@@ -1391,32 +986,11 @@ static void gl846_init_gpio(Genesys_Device* dev)
static void gl846_init_memory_layout(Genesys_Device* dev)
{
DBG_HELPER(dbg);
- int idx = 0, i;
- uint8_t val;
-
- /* point to per model memory layout */
- idx = 0;
- while (layouts[idx].model != nullptr && strcmp(dev->model->name,layouts[idx].model)!=0) {
- if(strcmp(dev->model->name,layouts[idx].model)!=0)
- idx++;
- }
- if (layouts[idx].model == nullptr) {
- throw SaneException("failed to find memory layout for model %s", dev->model->name);
- }
- /* CLKSET and DRAMSEL */
- val = layouts[idx].dramsel;
- dev->interface->write_register(REG_0x0B, val);
- dev->reg.find_reg(0x0b).value = val;
+ // prevent further writings by bulk write register
+ dev->reg.remove_reg(0x0b);
- /* prevent further writings by bulk write register */
- dev->reg.remove_reg(0x0b);
-
- /* setup base address for shading and scanned data. */
- for(i=0;i<10;i++)
- {
- dev->interface->write_register(0xe0+i, layouts[idx].rx[i]);
- }
+ apply_reg_settings_to_device_write_only(*dev, dev->memory_layout.regs);
}
/* *
@@ -1433,15 +1007,14 @@ void CommandSetGl846::asic_boot(Genesys_Device* dev, bool cold) const
dev->interface->write_register(0x0e, 0x00);
}
- if(dev->usb_mode == 1)
- {
- val = 0x14;
- }
- else
- {
- val = 0x11;
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICBOOK_3800) {
+ if (dev->usb_mode == 1) {
+ val = 0x14;
+ } else {
+ val = 0x11;
+ }
+ dev->interface->write_0x8c(0x0f, val);
}
- dev->interface->write_0x8c(0x0f, val);
// test CHKVER
val = dev->interface->read_register(REG_0x40);
@@ -1450,18 +1023,11 @@ void CommandSetGl846::asic_boot(Genesys_Device* dev, bool cold) const
DBG(DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val);
}
- /* Set default values for registers */
- gl846_init_registers (dev);
+ gl846_init_registers (dev);
// Write initial registers
dev->interface->write_registers(dev->reg);
- /* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */
- val = dev->reg.find_reg(0x0b).value & REG_0x0B_DRAMSEL;
- val = (val | REG_0x0B_ENBDRAM);
- dev->interface->write_register(REG_0x0B, val);
- dev->reg.find_reg(0x0b).value = val;
-
/* CIS_LINE */
if (dev->model->is_cis)
{
@@ -1470,8 +1036,15 @@ void CommandSetGl846::asic_boot(Genesys_Device* dev, bool cold) const
}
// set up clocks
- dev->interface->write_0x8c(0x10, 0x0e);
- dev->interface->write_0x8c(0x13, 0x0e);
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ dev->interface->write_0x8c(0x10, 0x0c);
+ dev->interface->write_0x8c(0x13, 0x0c);
+ } else {
+ dev->interface->write_0x8c(0x10, 0x0e);
+ dev->interface->write_0x8c(0x13, 0x0e);
+ }
// setup gpio
gl846_init_gpio(dev);
@@ -1492,7 +1065,7 @@ void CommandSetGl846::init(Genesys_Device* dev) const
DBG_INIT ();
DBG_HELPER(dbg);
- sanei_genesys_asic_init(dev, 0);
+ sanei_genesys_asic_init(dev);
}
void CommandSetGl846::update_hardware_sensors(Genesys_Scanner* s) const
@@ -1529,512 +1102,16 @@ void CommandSetGl846::update_home_sensor_gpio(Genesys_Device& dev) const
dev.interface->write_register(REG_0x6C, val);
}
-/** @brief search for a full width black or white strip.
- * This function searches for a black or white stripe across the scanning area.
- * When searching backward, the searched area must completely be of the desired
- * color since this area will be used for calibration which scans forward.
- * @param dev scanner device
- * @param forward true if searching forward, false if searching backward
- * @param black true if searching for a black strip, false for a white strip
- */
-void CommandSetGl846::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
- bool black) const
-{
- DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
- unsigned int pixels, lines, channels;
- Genesys_Register_Set local_reg;
- size_t size;
- unsigned int pass, count, found, x, y;
- char title[80];
-
- set_fe(dev, sensor, AFE_SET);
-
- scanner_stop_action(*dev);
-
- // set up for a gray scan at lowest dpi
- const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
- unsigned dpi = resolution_settings.get_min_resolution_x();
- channels = 1;
- /* 10 MM */
- /* lines = (10 * dpi) / MM_PER_INCH; */
- /* shading calibation is done with dev->motor.base_ydpi */
- lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
- pixels = (sensor.sensor_pixels * dpi) / sensor.optical_res;
-
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
-
- local_reg = dev->reg;
-
- ScanSession session;
- session.params.xres = dpi;
- session.params.yres = dpi;
- 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_mode = ScanColorMode::GRAY;
- session.params.color_filter = ColorFilter::RED;
- session.params.flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA;
- if (!forward) {
- session.params.flags |= ScanFlag::REVERSE;
- }
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &local_reg, session);
-
- size = pixels * channels * lines * (session.params.depth / 8);
- std::vector<uint8_t> data(size);
-
- dev->interface->write_registers(local_reg);
-
- begin_scan(dev, sensor, &local_reg, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("search_strip");
- scanner_stop_action(*dev);
- 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);
-
- scanner_stop_action(*dev);
-
- pass = 0;
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl846_search_strip_%s_%s%02d.pnm",
- black ? "black" : "white", forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
- channels, pixels, lines);
- }
-
- /* loop until strip is found or maximum pass number done */
- found = 0;
- while (pass < 20 && !found)
- {
- dev->interface->write_registers(local_reg);
-
- // now start scan
- begin_scan(dev, sensor, &local_reg, true);
-
- 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);
-
- scanner_stop_action(*dev);
-
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl846_search_strip_%s_%s%02d.pnm",
- black ? "black" : "white", forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
- channels, pixels, lines);
- }
-
- /* search data to find black strip */
- /* when searching forward, we only need one line of the searched color since we
- * will scan forward. But when doing backward search, we need all the area of the
- * same color */
- if (forward)
- {
- for (y = 0; y < lines && !found; y++)
- {
- count = 0;
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * pixels + x] > 90)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * pixels + x] < 60)
- {
- count++;
- }
- }
-
- /* at end of line, if count >= 3%, line is not fully of the desired color
- * so we must go to next line of the buffer */
- /* count*100/pixels < 3 */
- if ((count * 100) / pixels < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
- pass, y);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- }
- else /* since calibration scans are done forward, we need the whole area
- to be of the required color when searching backward */
- {
- count = 0;
- for (y = 0; y < lines; y++)
- {
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * pixels + x] > 90)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * pixels + x] < 60)
- {
- count++;
- }
- }
- }
-
- /* at end of area, if count >= 3%, area is not fully of the desired color
- * so we must go to next buffer */
- if ((count * 100) / (pixels * lines) < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- pass++;
- }
-
- if (found)
- {
- DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
- }
- else
- {
- throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
- }
-}
-
-/**
- * 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 CommandSetGl846::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 AKM AFE
- uint8_t reg04 = dev->interface->read_register(REG_0x04);
- if ((reg04 & REG_0x04_FESET) == 0x02) {
- 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, &regs, session);
-
- sanei_genesys_set_motor_power(regs, false);
-
- 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, &regs, 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 fn[30];
- std::snprintf(fn, 30, "gl846_offset%03d.pnm", bottom);
- sanei_genesys_write_pnm_file(fn, 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, &regs, 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, &regs, true);
- sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
-
- if (DBG_LEVEL >= DBG_data)
- {
- char fn[30];
- std::snprintf(fn, 30, "gl846_offset%03d.pnm", dev->frontend.get_offset(1));
- sanei_genesys_write_pnm_file(fn, 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);
}
void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs, int dpi) const
{
- DBG_HELPER(dbg);
- int pixels;
- int total_size;
- int i, j, channels;
- int max[3];
- float gain[3],coeff;
- int val, code, lines;
-
- DBG(DBG_proc, "%s: dpi = %d\n", __func__, dpi);
-
- // no gain nor offset for AKM AFE
- uint8_t reg04 = dev->interface->read_register(REG_0x04);
- if ((reg04 & REG_0x04_FESET) == 0x02) {
- return;
- }
-
- /* coarse gain calibration is always done in color mode */
- channels = 3;
-
- /* follow CKSEL */
- if(dev->settings.xres<sensor.optical_res)
- {
- coeff = 0.9f;
- }
- else
- {
- coeff=1.0;
- }
- 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, &regs, 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, &regs, 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("gl846_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);
- }
-
- scanner_stop_action(*dev);
-
- move_back_home(dev, true);
+ scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
}
bool CommandSetGl846::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
@@ -2044,14 +1121,11 @@ bool CommandSetGl846::needs_home_before_init_regs_for_scan(Genesys_Device* dev)
}
void CommandSetGl846::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const
+ Genesys_Register_Set* regs) const
{
(void) dev;
(void) sensor;
(void) regs;
- (void) channels;
- (void) total_size;
throw SaneException("not implemented");
}
@@ -2083,16 +1157,5 @@ void CommandSetGl846::eject_document(Genesys_Device* dev) const
throw SaneException("not implemented");
}
-void CommandSetGl846::move_to_ta(Genesys_Device* dev) const
-{
- (void) dev;
- throw SaneException("not implemented");
-}
-
-std::unique_ptr<CommandSet> create_gl846_cmd_set()
-{
- return std::unique_ptr<CommandSet>(new CommandSetGl846{});
-}
-
} // namespace gl846
} // namespace genesys
diff --git a/backend/genesys/gl846.h b/backend/genesys/gl846.h
index 258015a..f794a01 100644
--- a/backend/genesys/gl846.h
+++ b/backend/genesys/gl846.h
@@ -42,7 +42,7 @@
*/
#include "genesys.h"
-#include "command_set.h"
+#include "command_set_common.h"
#ifndef BACKEND_GENESYS_GL846_H
#define BACKEND_GENESYS_GL846_H
@@ -50,82 +50,7 @@
namespace genesys {
namespace gl846 {
-typedef struct
-{
- GpioId gpio_id;
- uint8_t r6b;
- uint8_t r6c;
- uint8_t r6d;
- uint8_t r6e;
- uint8_t r6f;
- uint8_t ra6;
- uint8_t ra7;
- uint8_t ra8;
- uint8_t ra9;
-} Gpio_Profile;
-
-static Gpio_Profile gpios[]={
- { GpioId::IMG101, 0x72, 0x1f, 0xa4, 0x13, 0xa7, 0x11, 0xff, 0x19, 0x05},
- { GpioId::PLUSTEK_OPTICBOOK_3800, 0x30, 0x01, 0x80, 0x2d, 0x80, 0x0c, 0x8f, 0x08, 0x04},
- { GpioId::UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-
-typedef struct
-{
- const char *model;
- uint8_t dramsel;
- /* shading data address */
- uint8_t rd0;
- uint8_t rd1;
- uint8_t rd2;
- /* scanned data address */
- uint8_t rx[24];
-} Memory_layout;
-
-static Memory_layout layouts[]={
- /* Image formula 101 */
- {
- "canon-image-formula-101",
- 0x8b,
- 0x0a, 0x1b, 0x00,
- { /* RED ODD START / RED ODD END */
- 0x00, 0xb0, 0x05, 0xe7, /* [0x00b0, 0x05e7] 1336*4000w */
- /* RED EVEN START / RED EVEN END */
- 0x05, 0xe8, 0x0b, 0x1f, /* [0x05e8, 0x0b1f] */
- /* GREEN ODD START / GREEN ODD END */
- 0x0b, 0x20, 0x10, 0x57, /* [0x0b20, 0x1057] */
- /* GREEN EVEN START / GREEN EVEN END */
- 0x10, 0x58, 0x15, 0x8f, /* [0x1058, 0x158f] */
- /* BLUE ODD START / BLUE ODD END */
- 0x15, 0x90, 0x1a, 0xc7, /* [0x1590,0x1ac7] */
- /* BLUE EVEN START / BLUE EVEN END */
- 0x1a, 0xc8, 0x1f, 0xff /* [0x1ac8,0x1fff] */
- }
- },
- /* OpticBook 3800 */
- {
- "plustek-opticbook-3800",
- 0x2a,
- 0x0a, 0x0a, 0x0a,
- { /* RED ODD START / RED ODD END */
- 0x00, 0x68, 0x03, 0x00,
- /* RED EVEN START / RED EVEN END */
- 0x03, 0x01, 0x05, 0x99,
- /* GREEN ODD START / GREEN ODD END */
- 0x05, 0x9a, 0x08, 0x32,
- /* GREEN EVEN START / GREEN EVEN END */
- 0x08, 0x33, 0x0a, 0xcb,
- /* BLUE ODD START / BLUE ODD END */
- 0x0a, 0xcc, 0x0d, 0x64,
- /* BLUE EVEN START / BLUE EVEN END */
- 0x0d, 0x65, 0x0f, 0xfd
- }
- },
- /* list terminating entry */
- { nullptr, 0, 0, 0, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }
-};
-
-class CommandSetGl846 : public CommandSet
+class CommandSetGl846 : public CommandSetCommon
{
public:
~CommandSetGl846() override = default;
@@ -135,17 +60,11 @@ public:
void init(Genesys_Device* dev) const override;
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const override;
-
- void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const override;
+ Genesys_Register_Set* regs) const override;
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
- void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
-
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set* reg,
const ScanSession& session) const override;
@@ -161,8 +80,6 @@ public:
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
- void search_start_position(Genesys_Device* dev) const override;
-
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
@@ -178,8 +95,6 @@ public:
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
- bool needs_update_home_sensor_gpio() const override { return true; }
-
void update_home_sensor_gpio(Genesys_Device& dev) const override;
void load_document(Genesys_Device* dev) const override;
@@ -188,11 +103,6 @@ public:
void eject_document(Genesys_Device* dev) const override;
- void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const override;
-
- void move_to_ta(Genesys_Device* dev) const override;
-
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
int size) const override;
diff --git a/backend/genesys/gl846_registers.h b/backend/genesys/gl846_registers.h
index 39b3029..e4a8ac5 100644
--- a/backend/genesys/gl846_registers.h
+++ b/backend/genesys/gl846_registers.h
@@ -194,7 +194,7 @@ static constexpr RegMask REG_0x1D_CK1LOW = 0x20;
static constexpr RegMask REG_0x1D_TGSHLD = 0x1f;
static constexpr RegShift REG_0x1DS_TGSHLD = 0;
-
+static constexpr RegAddr REG_0x1E = 0x1e;
static constexpr RegMask REG_0x1E_WDTIME = 0xf0;
static constexpr RegShift REG_0x1ES_WDTIME = 4;
static constexpr RegMask REG_0x1E_LINESEL = 0x0f;
@@ -303,6 +303,16 @@ static constexpr RegAddr REG_0x6E = 0x6e;
static constexpr RegAddr REG_0x6F = 0x6f;
static constexpr RegAddr REG_0x7E = 0x7e;
+static constexpr RegAddr REG_0x80 = 0x80;
+static constexpr RegMask REG_0x80_TABLE1_NORMAL = 0x03;
+static constexpr RegShift REG_0x80S_TABLE1_NORMAL = 0;
+static constexpr RegMask REG_0x80_TABLE2_BACK = 0x0c;
+static constexpr RegShift REG_0x80S_TABLE2_BACK = 2;
+static constexpr RegMask REG_0x80_TABLE4_FAST = 0x30;
+static constexpr RegShift REG_0x80S_TABLE4_FAST = 4;
+static constexpr RegMask REG_0x80_TABLE5_GO_HOME = 0xc0;
+static constexpr RegShift REG_0x80S_TABLE5_GO_HOME = 6;
+
static constexpr RegMask REG_0x87_ACYCNRLC = 0x10;
static constexpr RegMask REG_0x87_ENOFFSET = 0x08;
static constexpr RegMask REG_0x87_LEDADD = 0x04;
diff --git a/backend/genesys/gl847.cpp b/backend/genesys/gl847.cpp
index cb0b527..f8f6b1c 100644
--- a/backend/genesys/gl847.cpp
+++ b/backend/genesys/gl847.cpp
@@ -56,39 +56,12 @@ namespace gl847 {
/**
* compute the step multiplier used
*/
-static int
-gl847_get_step_multiplier (Genesys_Register_Set * regs)
+static unsigned gl847_get_step_multiplier (Genesys_Register_Set * regs)
{
- GenesysRegister *r = sanei_genesys_get_address(regs, 0x9d);
- int value = 1;
- if (r != nullptr)
- {
- value = (r->value & 0x0f)>>1;
- value = 1 << value;
- }
- DBG (DBG_io, "%s: step multiplier is %d\n", __func__, value);
- return value;
+ unsigned value = (regs->get8(0x9d) & 0x0f) >> 1;
+ return 1 << value;
}
-/** @brief sensor specific settings
-*/
-static void gl847_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->set16(REG_EXPR, sensor.exposure.red);
- regs->set16(REG_EXPG, sensor.exposure.green);
- regs->set16(REG_EXPB, sensor.exposure.blue);
-
- dev->segment_order = sensor.segment_order;
-}
-
-
/** @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.
@@ -111,30 +84,49 @@ gl847_init_registers (Genesys_Device * dev)
dev->reg.clear();
dev->reg.init_reg(0x01, 0x82);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x01, 0x40);
+ }
dev->reg.init_reg(0x02, 0x18);
dev->reg.init_reg(0x03, 0x50);
dev->reg.init_reg(0x04, 0x12);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x04, 0x20);
+ }
dev->reg.init_reg(0x05, 0x80);
dev->reg.init_reg(0x06, 0x50); // FASTMODE + POWERBIT
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x06, 0xf8);
+ }
dev->reg.init_reg(0x08, 0x10);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x08, 0x20);
+ }
dev->reg.init_reg(0x09, 0x01);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x09, 0x00);
+ }
dev->reg.init_reg(0x0a, 0x00);
dev->reg.init_reg(0x0b, 0x01);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x0b, 0x6b);
+ }
dev->reg.init_reg(0x0c, 0x02);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x0c, 0x00);
+ }
// LED exposures
- dev->reg.init_reg(0x10, 0x00);
- dev->reg.init_reg(0x11, 0x00);
- dev->reg.init_reg(0x12, 0x00);
- dev->reg.init_reg(0x13, 0x00);
- dev->reg.init_reg(0x14, 0x00);
- dev->reg.init_reg(0x15, 0x00);
+ dev->reg.init_reg(0x10, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x11, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x12, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x13, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x14, 0x00); // exposure, overwritten in scanner_setup_sensor() below
+ dev->reg.init_reg(0x15, 0x00); // exposure, overwritten in scanner_setup_sensor() below
dev->reg.init_reg(0x16, 0x10); // SENSOR_DEF
dev->reg.init_reg(0x17, 0x08); // SENSOR_DEF
dev->reg.init_reg(0x18, 0x00); // SENSOR_DEF
-
- // EXPDMY
dev->reg.init_reg(0x19, 0x50); // SENSOR_DEF
dev->reg.init_reg(0x1a, 0x34); // SENSOR_DEF
@@ -142,32 +134,40 @@ gl847_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0x1c, 0x02); // SENSOR_DEF
dev->reg.init_reg(0x1d, 0x04); // SENSOR_DEF
dev->reg.init_reg(0x1e, 0x10);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x1e, 0xf0);
+ }
dev->reg.init_reg(0x1f, 0x04);
- dev->reg.init_reg(0x20, 0x02);
- dev->reg.init_reg(0x21, 0x10);
- dev->reg.init_reg(0x22, 0x7f);
- dev->reg.init_reg(0x23, 0x7f);
- dev->reg.init_reg(0x24, 0x10);
- dev->reg.init_reg(0x25, 0x00);
- dev->reg.init_reg(0x26, 0x00);
- dev->reg.init_reg(0x27, 0x00);
- dev->reg.init_reg(0x2c, 0x09);
- dev->reg.init_reg(0x2d, 0x60);
- dev->reg.init_reg(0x2e, 0x80);
- dev->reg.init_reg(0x2f, 0x80);
- dev->reg.init_reg(0x30, 0x00);
- 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(0x3d, 0x00);
- dev->reg.init_reg(0x3e, 0x00);
- dev->reg.init_reg(0x3f, 0x00);
+ dev->reg.init_reg(0x20, 0x02); // BUFSEL: buffer full condition
+ dev->reg.init_reg(0x21, 0x10); // STEPNO: set during motor setup
+ dev->reg.init_reg(0x22, 0x7f); // FWDSTEP: set during motor setup
+ dev->reg.init_reg(0x23, 0x7f); // BWDSTEP: set during motor setup
+ dev->reg.init_reg(0x24, 0x10); // FASTNO: set during motor setup
+ dev->reg.init_reg(0x25, 0x00); // LINCNT: set during motor setup
+ dev->reg.init_reg(0x26, 0x00); // LINCNT: set during motor setup
+ dev->reg.init_reg(0x27, 0x00); // LINCNT: set during motor setup
+
+ dev->reg.init_reg(0x2c, 0x09); // DPISET: set during sensor setup
+ dev->reg.init_reg(0x2d, 0x60); // DPISET: set during sensor setup
+
+ dev->reg.init_reg(0x2e, 0x80); // BWHI: black/white low threshdold
+ dev->reg.init_reg(0x2f, 0x80); // BWLOW: black/white low threshold
+
+ dev->reg.init_reg(0x30, 0x00); // STRPIXEL: set during sensor setup
+ dev->reg.init_reg(0x31, 0x10); // STRPIXEL: set during sensor setup
+ dev->reg.init_reg(0x32, 0x15); // ENDPIXEL: set during sensor setup
+ dev->reg.init_reg(0x33, 0x0e); // ENDPIXEL: set during sensor setup
+
+ dev->reg.init_reg(0x34, 0x40); // DUMMY: SENSOR_DEF
+ dev->reg.init_reg(0x35, 0x00); // MAXWD: set during scan setup
+ dev->reg.init_reg(0x36, 0x2a); // MAXWD: set during scan setup
+ dev->reg.init_reg(0x37, 0x30); // MAXWD: set during scan setup
+ dev->reg.init_reg(0x38, 0x2a); // LPERIOD: SENSOR_DEF
+ dev->reg.init_reg(0x39, 0xf8); // LPERIOD: SENSOR_DEF
+ dev->reg.init_reg(0x3d, 0x00); // FEEDL: set during motor setup
+ dev->reg.init_reg(0x3e, 0x00); // FEEDL: set during motor setup
+ dev->reg.init_reg(0x3f, 0x00); // FEEDL: set during motor setup
+
dev->reg.init_reg(0x52, 0x03); // SENSOR_DEF
dev->reg.init_reg(0x53, 0x07); // SENSOR_DEF
dev->reg.init_reg(0x54, 0x00); // SENSOR_DEF
@@ -177,30 +177,27 @@ gl847_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0x58, 0x2a); // SENSOR_DEF
dev->reg.init_reg(0x59, 0xe1); // SENSOR_DEF
dev->reg.init_reg(0x5a, 0x55); // SENSOR_DEF
- dev->reg.init_reg(0x5e, 0x41);
- dev->reg.init_reg(0x5f, 0x40);
- dev->reg.init_reg(0x60, 0x00);
- dev->reg.init_reg(0x61, 0x21);
- dev->reg.init_reg(0x62, 0x40);
- dev->reg.init_reg(0x63, 0x00);
- dev->reg.init_reg(0x64, 0x21);
- dev->reg.init_reg(0x65, 0x40);
- dev->reg.init_reg(0x67, 0x80);
- dev->reg.init_reg(0x68, 0x80);
- dev->reg.init_reg(0x69, 0x20);
- dev->reg.init_reg(0x6a, 0x20);
-
- // CK1MAP
+
+ dev->reg.init_reg(0x5e, 0x41); // DECSEL, STOPTIM
+ dev->reg.init_reg(0x5f, 0x40); // FMOVDEC: set during motor setup
+
+ dev->reg.init_reg(0x60, 0x00); // Z1MOD: overwritten during motor setup
+ dev->reg.init_reg(0x61, 0x21); // Z1MOD: overwritten during motor setup
+ dev->reg.init_reg(0x62, 0x40); // Z1MOD: overwritten during motor setup
+ dev->reg.init_reg(0x63, 0x00); // Z2MOD: overwritten during motor setup
+ dev->reg.init_reg(0x64, 0x21); // Z2MOD: overwritten during motor setup
+ dev->reg.init_reg(0x65, 0x40); // Z2MOD: overwritten during motor setup
+ dev->reg.init_reg(0x67, 0x80); // STEPSEL, MTRPWM: overwritten during motor setup
+ dev->reg.init_reg(0x68, 0x80); // FSTPSEL, FASTPWM: overwritten during motor setup
+ dev->reg.init_reg(0x69, 0x20); // FSHDEC: overwritten during motor setup
+ dev->reg.init_reg(0x6a, 0x20); // FMOVNO: overwritten during motor setup
+
dev->reg.init_reg(0x74, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x75, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x76, 0x3c); // SENSOR_DEF
-
- // CK3MAP
dev->reg.init_reg(0x77, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x78, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x79, 0x9f); // SENSOR_DEF
-
- // CK4MAP
dev->reg.init_reg(0x7a, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x7b, 0x00); // SENSOR_DEF
dev->reg.init_reg(0x7c, 0x55); // SENSOR_DEF
@@ -208,11 +205,23 @@ gl847_init_registers (Genesys_Device * dev)
dev->reg.init_reg(0x7d, 0x00);
// NOTE: autoconf is a non working option
- dev->reg.init_reg(0x87, 0x02);
- dev->reg.init_reg(0x9d, 0x06);
- dev->reg.init_reg(0xa2, 0x0f);
- dev->reg.init_reg(0xbd, 0x18);
- dev->reg.init_reg(0xfe, 0x08);
+ dev->reg.init_reg(0x87, 0x02); // TODO: move to SENSOR_DEF
+ dev->reg.init_reg(0x9d, 0x06); // RAMDLY, MOTLAG, CMODE, STEPTIM, IFRS
+ dev->reg.init_reg(0xa2, 0x0f); // misc
+
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0xab, 0x31);
+ dev->reg.init_reg(0xbb, 0x00);
+ dev->reg.init_reg(0xbc, 0x0f);
+ }
+ dev->reg.init_reg(0xbd, 0x18); // misc
+ dev->reg.init_reg(0xfe, 0x08); // misc
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ dev->reg.init_reg(0x9e, 0x00); // sensor reg, but not in SENSOR_DEF
+ dev->reg.init_reg(0x9f, 0x00); // sensor reg, but not in SENSOR_DEF
+ dev->reg.init_reg(0xaa, 0x00); // custom data
+ dev->reg.init_reg(0xff, 0x00);
+ }
// gamma[0] and gamma[256] values
dev->reg.init_reg(0xbe, 0x00);
@@ -237,233 +246,180 @@ gl847_init_registers (Genesys_Device * dev)
}
const auto& sensor = sanei_genesys_find_sensor_any(dev);
- sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
+ 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);
- /* initalize calibration reg */
- dev->calib_reg = dev->reg;
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ scanner_setup_sensor(*dev, sensor, 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 elements in the slope table
- */
-static void gl847_send_slope_table(Genesys_Device* dev, int table_nr,
- const std::vector<uint16_t>& slope_table,
- int steps)
+// Set values of analog frontend
+void CommandSetGl847::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
{
- 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 %d", table_nr);
- }
-
- 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;
- }
+ DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
+ set == AFE_SET ? "set" :
+ set == AFE_POWER_SAVE ? "powersave" : "huh?");
- 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);
- }
+ (void) sensor;
- if (dev->interface->is_mock()) {
- dev->interface->record_slope_table(table_nr, slope_table);
+ if (dev->model->model_id != ModelId::CANON_5600F) {
+ // FIXME: remove the following read
+ dev->interface->read_register(REG_0x04);
}
- // slope table addresses are fixed
- dev->interface->write_ahb(0x10000000 + 0x4000 * table_nr, steps * 2, table.data());
-}
-
-/**
- * Set register values of Analog Device type frontend
- * */
-static void gl847_set_ad_fe(Genesys_Device* dev, uint8_t set)
-{
- DBG_HELPER(dbg);
- int i;
// wait for FE to be ready
auto status = scanner_read_status(*dev);
while (status.is_front_end_busy) {
dev->interface->sleep_ms(10);
status = scanner_read_status(*dev);
- };
-
- 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;
}
- // reset DAC
- dev->interface->write_fe_register(0x00, 0x80);
-
- // write them to analog frontend
- dev->interface->write_fe_register(0x00, dev->frontend.regs.get_value(0x00));
-
- dev->interface->write_fe_register(0x01, dev->frontend.regs.get_value(0x01));
+ if (set == AFE_INIT) {
+ dev->frontend = dev->frontend_initial;
+ }
- for (i = 0; i < 3; i++) {
- dev->interface->write_fe_register(0x02 + i, dev->frontend.get_gain(i));
+ if (dev->model->model_id != ModelId::CANON_5600F) {
+ // reset DAC (BUG: this does completely different thing on Analog Devices ADCs)
+ dev->interface->write_fe_register(0x00, 0x80);
+ } else {
+ if (dev->frontend.layout.type == FrontendType::WOLFSON) {
+ // reset DAC
+ dev->interface->write_fe_register(0x04, 0xff);
+ }
}
- for (i = 0; i < 3; i++) {
- dev->interface->write_fe_register(0x05 + i, dev->frontend.get_offset(i));
+
+ for (const auto& reg : dev->frontend.regs) {
+ dev->interface->write_fe_register(reg.address, reg.value);
}
}
-// Set values of analog frontend
-void CommandSetGl847::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
+static void gl847_write_motor_phase_table(Genesys_Device& dev, unsigned ydpi)
{
- DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
- set == AFE_SET ? "set" :
- set == AFE_POWER_SAVE ? "powersave" : "huh?");
-
- (void) sensor;
-
- uint8_t val = dev->interface->read_register(REG_0x04);
- uint8_t frontend_type = val & REG_0x04_FESET;
-
- // route to AD devices
- if (frontend_type == 0x02) {
- gl847_set_ad_fe(dev, set);
- return;
+ (void) ydpi;
+ if (dev.model->model_id == ModelId::CANON_5600F) {
+ std::vector<std::uint8_t> phase_table = {
+ 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00,
+ 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00,
+ 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00,
+ 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
+ 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00,
+ 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00,
+ 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00,
+ 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00,
+ 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
+ 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00,
+ 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00,
+ 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00,
+ 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00,
+ 0x25, 0x00, 0x25, 0x00, 0x25, 0x00, 0x25, 0x00,
+ 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00,
+ };
+ dev.interface->write_ahb(0x01000a00, phase_table.size(), phase_table.data());
}
-
- throw SaneException("unsupported frontend type %d", frontend_type);
}
-
// @brief set up motor related register for scan
static void gl847_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,
- MotorFlag flags)
+ ScanFlag flags)
{
DBG_HELPER_ARGS(dbg, "scan_exposure_time=%d, can_yres=%d, step_type=%d, scan_lines=%d, "
"scan_dummy=%d, feed_steps=%d, flags=%x",
scan_exposure_time, scan_yres, static_cast<unsigned>(motor_profile.step_type),
scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
- int use_fast_fed;
- unsigned int fast_dpi;
- unsigned int feedl, dist;
- GenesysRegister *r;
- uint32_t z1, z2;
- unsigned int min_restep = 0x20;
- uint8_t val;
- unsigned int ccdlmt,tgtime;
unsigned step_multiplier = gl847_get_step_multiplier (reg);
- use_fast_fed=0;
- /* no fast fed since feed works well */
- if (dev->settings.yres==4444 && feed_steps > 100 && (!has_flag(flags, MotorFlag::FEED)))
- {
- use_fast_fed=1;
+ 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;
}
- DBG(DBG_io, "%s: use_fast_fed=%d\n", __func__, use_fast_fed);
reg->set24(REG_LINCNT, scan_lines);
- DBG(DBG_io, "%s: lincnt=%d\n", __func__, scan_lines);
- /* compute register 02 value */
- r = sanei_genesys_get_address(reg, REG_0x02);
- r->value = 0x00;
- sanei_genesys_set_motor_power(*reg, true);
+ reg->set8(REG_0x02, 0);
+ sanei_genesys_set_motor_power(*reg, true);
+ std::uint8_t reg02 = reg->get8(REG_0x02);
if (use_fast_fed) {
- r->value |= REG_0x02_FASTFED;
+ reg02 |= REG_0x02_FASTFED;
} else {
- r->value &= ~REG_0x02_FASTFED;
+ reg02 &= ~REG_0x02_FASTFED;
}
- if (has_flag(flags, MotorFlag::AUTO_GO_HOME)) {
- r->value |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
+ if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
+ reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
}
- if (has_flag(flags, MotorFlag::DISABLE_BUFFER_FULL_MOVE)
- ||(scan_yres>=sensor.optical_res))
- {
- r->value |= REG_0x02_ACDCDIS;
+ if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) || (scan_yres >= sensor.full_resolution)) {
+ reg02 |= REG_0x02_ACDCDIS;
}
-
- if (has_flag(flags, MotorFlag::REVERSE)) {
- r->value |= REG_0x02_MTRREV;
+ if (has_flag(flags, ScanFlag::REVERSE)) {
+ reg02 |= REG_0x02_MTRREV;
} else {
- r->value &= ~REG_0x02_MTRREV;
+ reg02 &= ~REG_0x02_MTRREV;
}
+ reg->set8(REG_0x02, reg02);
- /* scan and backtracking slope table */
- auto scan_table = sanei_genesys_slope_table(dev->model->asic_type, scan_yres,
- scan_exposure_time, dev->motor.base_ydpi,
- step_multiplier, motor_profile);
- gl847_send_slope_table(dev, SCAN_TABLE, scan_table.table, scan_table.steps_count);
- gl847_send_slope_table(dev, BACKTRACK_TABLE, scan_table.table, scan_table.steps_count);
+ // scan and backtracking slope table
+ auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres,
+ scan_exposure_time, step_multiplier, motor_profile);
+ scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
+ scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
- /* fast table */
- fast_dpi=sanei_genesys_get_lowest_ydpi(dev);
+ // fast table
+ unsigned fast_dpi = sanei_genesys_get_lowest_ydpi(dev);
+
+ // BUG: looks like for fast moves we use inconsistent step type
StepType fast_step_type = motor_profile.step_type;
if (static_cast<unsigned>(motor_profile.step_type) >= static_cast<unsigned>(StepType::QUARTER)) {
fast_step_type = StepType::QUARTER;
}
- Motor_Profile fast_motor_profile = motor_profile;
+ MotorProfile fast_motor_profile = motor_profile;
fast_motor_profile.step_type = fast_step_type;
- auto fast_table = sanei_genesys_slope_table(dev->model->asic_type, fast_dpi,
- scan_exposure_time, dev->motor.base_ydpi,
- step_multiplier, fast_motor_profile);
+ auto fast_table = create_slope_table(dev->model->asic_type, dev->motor, fast_dpi,
+ scan_exposure_time, step_multiplier, fast_motor_profile);
+
+ scanner_send_slope_table(dev, sensor, STOP_TABLE, fast_table.table);
+ scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
+ scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
- gl847_send_slope_table(dev, STOP_TABLE, fast_table.table, fast_table.steps_count);
- gl847_send_slope_table(dev, FAST_TABLE, fast_table.table, fast_table.steps_count);
- gl847_send_slope_table(dev, HOME_TABLE, fast_table.table, fast_table.steps_count);
+ gl847_write_motor_phase_table(*dev, scan_yres);
- /* correct move distance by acceleration and deceleration amounts */
- feedl=feed_steps;
- if (use_fast_fed)
+ // correct move distance by acceleration and deceleration amounts
+ unsigned feedl = feed_steps;
+ unsigned dist = 0;
+ if (use_fast_fed)
{
feedl <<= static_cast<unsigned>(fast_step_type);
- dist = (scan_table.steps_count + 2 * fast_table.steps_count);
- /* TODO read and decode REG_0xAB */
- r = sanei_genesys_get_address (reg, 0x5e);
- dist += (r->value & 31);
- /* FEDCNT */
- r = sanei_genesys_get_address (reg, REG_FEDCNT);
- dist += r->value;
- }
- else
- {
+ 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<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;
}
}
- DBG(DBG_io2, "%s: acceleration distance=%d\n", __func__, dist);
- /* check for overflow */
+ // check for overflow
if (dist < feedl) {
feedl -= dist;
} else {
@@ -471,25 +427,20 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev,
}
reg->set24(REG_FEEDL, feedl);
- DBG(DBG_io ,"%s: feedl=%d\n", __func__, feedl);
- r = sanei_genesys_get_address(reg, REG_0x0C);
- ccdlmt = (r->value & REG_0x0C_CCDLMT) + 1;
-
- r = sanei_genesys_get_address(reg, REG_0x1C);
- tgtime = 1<<(r->value & REG_0x1C_TGTIME);
+ unsigned ccdlmt = (reg->get8(REG_0x0C) & REG_0x0C_CCDLMT) + 1;
+ unsigned tgtime = 1 << (reg->get8(REG_0x1C) & REG_0x1C_TGTIME);
// hi res motor speed GPIO
uint8_t effective = dev->interface->read_register(REG_0x6C);
// if quarter step, bipolar Vref2
+ std::uint8_t val = effective;
if (motor_profile.step_type == StepType::QUARTER) {
val = effective & ~REG_0x6C_GPIO13;
} else if (static_cast<unsigned>(motor_profile.step_type) > static_cast<unsigned>(StepType::QUARTER)) {
val = effective | REG_0x6C_GPIO13;
- } else {
- val = effective;
}
dev->interface->write_register(REG_0x6C, val);
@@ -498,45 +449,37 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev,
val = effective | REG_0x6C_GPIO10;
dev->interface->write_register(REG_0x6C, val);
- min_restep = scan_table.steps_count / (2 * step_multiplier) - 1;
+ unsigned min_restep = scan_table.table.size() / (2 * step_multiplier) - 1;
if (min_restep < 1) {
min_restep = 1;
}
- r = sanei_genesys_get_address(reg, REG_FWDSTEP);
- r->value = min_restep;
- r = sanei_genesys_get_address(reg, REG_BWDSTEP);
- r->value = min_restep;
+ reg->set8(REG_FWDSTEP, min_restep);
+ reg->set8(REG_BWDSTEP, min_restep);
+
+ std::uint32_t z1, z2;
sanei_genesys_calculate_zmod(use_fast_fed,
- scan_exposure_time*ccdlmt*tgtime,
+ scan_exposure_time * ccdlmt * tgtime,
scan_table.table,
- scan_table.steps_count,
- feedl,
+ scan_table.table.size(),
+ feedl,
min_restep * step_multiplier,
&z1,
&z2);
- DBG(DBG_info, "%s: z1 = %d\n", __func__, z1);
reg->set24(REG_0x60, z1 | (static_cast<unsigned>(motor_profile.step_type) << (16+REG_0x60S_STEPSEL)));
-
- DBG(DBG_info, "%s: z2 = %d\n", __func__, z2);
reg->set24(REG_0x63, z2 | (static_cast<unsigned>(motor_profile.step_type) << (16+REG_0x63S_FSTPSEL)));
- r = sanei_genesys_get_address (reg, 0x1e);
- r->value &= 0xf0; /* 0 dummy lines */
- r->value |= scan_dummy; /* dummy lines */
+ reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
- r = sanei_genesys_get_address(reg, REG_0x67);
- r->value = REG_0x67_MTRPWM;
+ reg->set8(REG_0x67, REG_0x67_MTRPWM);
+ reg->set8(REG_0x68, REG_0x68_FASTPWM);
- r = sanei_genesys_get_address(reg, REG_0x68);
- r->value = REG_0x68_FASTPWM;
-
- reg->set8(REG_STEPNO, scan_table.steps_count / step_multiplier);
- reg->set8(REG_FASTNO, scan_table.steps_count / step_multiplier);
- reg->set8(REG_FSHDEC, scan_table.steps_count / step_multiplier);
- reg->set8(REG_FMOVNO, fast_table.steps_count / step_multiplier);
- reg->set8(REG_FMOVDEC, fast_table.steps_count / step_multiplier);
+ reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
+ reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
+ reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
}
@@ -563,84 +506,84 @@ static void gl847_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
const ScanSession& session)
{
DBG_HELPER_ARGS(dbg, "exposure_time=%d", exposure_time);
- unsigned dpihw;
- GenesysRegister *r;
-
- // 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.params.xres * ccd_pixels_per_system_pixel);
- DBG(DBG_io2, "%s: dpihw=%d\n", __func__, dpihw);
- gl847_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);
- r->value |= REG_0x01_SHDAREA;
+ reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
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) ||
+ session.use_host_side_calib)
{
- r->value &= ~REG_0x01_DVDSET;
- }
- else
- {
- r->value |= REG_0x01_DVDSET;
+ reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
+ } else {
+ reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
}
+ reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
- r = sanei_genesys_get_address (reg, REG_0x03);
- r->value &= ~REG_0x03_AVEENB;
-
+ reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL;
+ if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
+ reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL;
+ }
sanei_genesys_set_lamp_power(dev, sensor, *reg,
!has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
+ reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
+
+ if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ regs_set_exposure(dev->model->asic_type, *reg, sanei_genesys_fixup_exposure({0, 0, 0}));
+ }
+ }
- /* BW threshold */
- r = sanei_genesys_get_address (reg, 0x2e);
- r->value = dev->settings.threshold;
- r = sanei_genesys_get_address (reg, 0x2f);
- r->value = dev->settings.threshold;
+ // BW threshold
+ reg->set8(0x2e, 0x7f);
+ reg->set8(0x2f, 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_0x04_AFEMOD);
+ reg->find_reg(REG_0x04).value &= ~(REG_0x04_FILTER | REG_0x04_AFEMOD);
if (session.params.channels == 1)
{
switch (session.params.color_filter)
{
case ColorFilter::RED:
- r->value |= 0x14;
+ reg->find_reg(REG_0x04).value |= 0x14;
break;
case ColorFilter::BLUE:
- r->value |= 0x1c;
+ reg->find_reg(REG_0x04).value |= 0x1c;
break;
case ColorFilter::GREEN:
- r->value |= 0x18;
+ reg->find_reg(REG_0x04).value |= 0x18;
break;
default:
break; // should not happen
}
} else {
- r->value |= 0x10; // mono
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ reg->find_reg(REG_0x04).value |= 0x20;
+ } else {
+ reg->find_reg(REG_0x04).value |= 0x10; // mono
+ }
}
- 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;
@@ -651,38 +594,30 @@ static void gl847_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
/* 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, 0x87);
- r->value &= ~REG_0x87_LEDADD;
+ reg->find_reg(0x87).value &= ~REG_0x87_LEDADD;
+
if (session.enable_ledadd) {
- r->value |= REG_0x87_LEDADD;
+ reg->find_reg(0x87).value |= REG_0x87_LEDADD;
}
/* RGB weighting
- 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;
}
*/
}
- unsigned dpiset = session.params.xres * ccd_pixels_per_system_pixel;
- reg->set16(REG_DPISET, dpiset);
- DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset);
-
+ reg->set16(REG_DPISET, sensor.register_dpiset);
reg->set16(REG_STRPIXEL, session.pixel_startx);
reg->set16(REG_ENDPIXEL, session.pixel_endx);
- build_image_pipeline(dev, session);
+ setup_image_pipeline(*dev, session);
/* MAXWD is expressed in 4 words unit */
// BUG: we shouldn't multiply by channels here
reg->set24(REG_MAXWD, (session.output_line_bytes_raw * session.params.channels >> 2));
-
reg->set16(REG_LPERIOD, exposure_time);
- DBG(DBG_io2, "%s: exposure_time used=%d\n", __func__, exposure_time);
-
- r = sanei_genesys_get_address (reg, 0x34);
- r->value = sensor.dummy_pixel;
+ reg->set8(0x34, sensor.dummy_pixel);
}
void CommandSetGl847::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
@@ -692,13 +627,18 @@ void CommandSetGl847::init_regs_for_scan_session(Genesys_Device* dev, const Gene
DBG_HELPER(dbg);
session.assert_computed();
- int move;
int exposure_time;
int slope_dpi = 0;
int dummy = 0;
- dummy = 3 - session.params.channels;
+ if (dev->model->model_id == ModelId::CANON_LIDE_100 ||
+ dev->model->model_id == ModelId::CANON_LIDE_200 ||
+ dev->model->model_id == ModelId::CANON_LIDE_700F ||
+ dev->model->model_id == ModelId::HP_SCANJET_N6310)
+ {
+ dummy = 3 - session.params.channels;
+ }
/* slope_dpi */
/* cis color scan is effectively a gray scan with 3 gray lines per color
@@ -712,40 +652,15 @@ void CommandSetGl847::init_regs_for_scan_session(Genesys_Device* dev, const Gene
slope_dpi = slope_dpi * (1 + dummy);
exposure_time = sensor.exposure_lperiod;
- const auto& motor_profile = sanei_genesys_get_motor_profile(*gl847_motor_profiles,
- dev->model->motor_id,
- exposure_time);
-
- 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));
+ const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
/* we enable true gray for cis scanners only, and just when doing
* scan since color calibration is OK for this mode
*/
gl847_init_optical_regs_scan(dev, sensor, reg, exposure_time, session);
-
- 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;
- }
-
gl847_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, mflags);
-
- dev->read_buffer.clear();
- dev->read_buffer.alloc(session.buffer_size_read);
+ session.optical_line_count, dummy, session.params.starty,
+ session.params.flags);
dev->read_active = true;
@@ -761,21 +676,59 @@ ScanSession CommandSetGl847::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>(start + settings.tl_x);
- start = static_cast<int>((start * sensor.optical_res) / MM_PER_INCH);
+ // backtracking isn't handled well, so don't enable it
+ ScanFlag flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
+
+ /* Steps to move to reach scanning area:
+
+ - first we move to physical start of scanning either by a fixed steps amount from the
+ black strip or by a fixed amount from parking position, minus the steps done during
+ shading calibration.
+
+ - then we move by the needed offset whitin physical scanning area
+ */
+ unsigned move_dpi = dev->motor.base_ydpi;
+
+ float move = dev->model->y_offset;
+ if (settings.scan_method == ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
+ // transparency adapter
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
+ }
+ flags |= ScanFlag::USE_XPA;
+ } else {
+ if (!dev->ignore_offsets) {
+ move = dev->model->y_offset;
+ }
+ }
+
+ move = move + settings.tl_y;
+ move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
+ move -= dev->head_pos(ScanHeadId::PRIMARY);
+
+ float start = dev->model->x_offset;
+ if (settings.scan_method == ScanMethod::TRANSPARENCY ||
+ settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ start = dev->model->x_offset_ta;
+ } else {
+ start = dev->model->x_offset;
+ }
+
+ start = start + dev->settings.tl_x;
+ 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; // not used
- 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;
@@ -784,7 +737,7 @@ ScanSession CommandSetGl847::calculate_scan_session(const Genesys_Device* dev,
session.params.scan_method = settings.scan_method;
session.params.scan_mode = settings.scan_mode;
session.params.color_filter = settings.color_filter;
- session.params.flags = ScanFlag::NONE;
+ session.params.flags = flags;
compute_session(dev, session, sensor);
@@ -811,25 +764,61 @@ void CommandSetGl847::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
DBG_HELPER(dbg);
(void) sensor;
uint8_t val;
- GenesysRegister *r;
- // clear GPIO 10
- if (dev->model->gpio_id != GpioId::CANON_LIDE_700F) {
+ if (reg->state.is_xpa_on && reg->state.is_lamp_on) {
+ dev->cmd_set->set_xpa_lamp_power(*dev, true);
+ }
+
+ if (dev->model->model_id == ModelId::HP_SCANJET_N6310 ||
+ dev->model->model_id == ModelId::CANON_LIDE_100 ||
+ dev->model->model_id == ModelId::CANON_LIDE_200)
+ {
val = dev->interface->read_register(REG_0x6C);
val &= ~REG_0x6C_GPIO10;
dev->interface->write_register(REG_0x6C, val);
}
- val = REG_0x0D_CLRLNCNT;
- dev->interface->write_register(REG_0x0D, val);
- val = REG_0x0D_CLRMCNT;
- dev->interface->write_register(REG_0x0D, val);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ switch (dev->session.params.xres) {
+ case 75:
+ case 150:
+ case 300:
+ scanner_register_rw_bits(*dev, REG_0xA6, 0x04, 0x1c);
+ break;
+ case 600:
+ scanner_register_rw_bits(*dev, REG_0xA6, 0x18, 0x1c);
+ break;
+ case 1200:
+ scanner_register_rw_bits(*dev, REG_0xA6, 0x08, 0x1c);
+ break;
+ case 2400:
+ scanner_register_rw_bits(*dev, REG_0xA6, 0x10, 0x1c);
+ break;
+ case 4800:
+ scanner_register_rw_bits(*dev, REG_0xA6, 0x00, 0x1c);
+ break;
+ default:
+ throw SaneException("Unexpected xres");
+ }
+ dev->interface->write_register(0x6c, 0xf0);
+ dev->interface->write_register(0x6b, 0x87);
+ dev->interface->write_register(0x6d, 0x5f);
+ }
+
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ scanner_clear_scan_and_feed_counts(*dev);
+ } else {
+ // FIXME: use scanner_clear_scan_and_feed_counts()
+ val = REG_0x0D_CLRLNCNT;
+ dev->interface->write_register(REG_0x0D, val);
+ val = REG_0x0D_CLRMCNT;
+ dev->interface->write_register(REG_0x0D, val);
+ }
val = dev->interface->read_register(REG_0x01);
val |= REG_0x01_SCAN;
dev->interface->write_register(REG_0x01, val);
- r = sanei_genesys_get_address (reg, REG_0x01);
- r->value = val;
+ reg->set8(REG_0x01, val);
scanner_start_action(*dev, start_motor);
@@ -844,268 +833,86 @@ void CommandSetGl847::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
(void) reg;
DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
+ if (reg->state.is_xpa_on) {
+ dev->cmd_set->set_xpa_lamp_power(*dev, false);
+ }
+
if (!dev->model->is_sheetfed) {
scanner_stop_action(*dev);
}
}
-/** Park head
- * Moves the slider to the home (top) position slowly
- * @param dev device to park
- * @param wait_until_home true to make the function waiting for head
- * to be home before returning, if fals returne immediately
-*/
void CommandSetGl847::move_back_home(Genesys_Device* dev, bool wait_until_home) const
{
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 CommandSetGl847::search_start_position(Genesys_Device* dev) const
-{
- DBG_HELPER(dbg);
- int size;
- Genesys_Register_Set local_reg;
-
- int pixels = 600;
- int dpi = 300;
-
- local_reg = dev->reg;
-
- /* 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, dev->model->default_method);
-
- 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;
- 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("gl847_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;
-
- // TODO: find out where sanei_genesys_search_reference_point stores information,
- // and use that correctly
- 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 CommandSetGl847::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::IGNORE_LINE_DISTANCE;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &regs, session);
-
- 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
void CommandSetGl847::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
DBG_HELPER(dbg);
- dev->calib_channels = 3;
+ unsigned move_dpi = dev->motor.base_ydpi;
- /* initial calibration reg values */
- regs = dev->reg;
+ float calib_size_mm = 0;
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ calib_size_mm = dev->model->y_size_calib_ta_mm;
+ } else {
+ calib_size_mm = dev->model->y_size_calib_mm;
+ }
- dev->calib_resolution = sensor.get_register_hwdpi(dev->settings.xres);
+ unsigned channels = 3;
+ unsigned resolution = sensor.shading_resolution;
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->calib_resolution,
- dev->calib_channels,
+ const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
dev->settings.scan_method);
- dev->calib_total_bytes_to_read = 0;
- dev->calib_lines = dev->model->shading_lines;
- if (dev->calib_resolution == 4800) {
- dev->calib_lines *= 2;
+ float move = 0;
+ ScanFlag flags = ScanFlag::DISABLE_SHADING |
+ ScanFlag::DISABLE_GAMMA |
+ ScanFlag::DISABLE_BUFFER_FULL_MOVE;
+
+ if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ // note: scanner_move_to_ta() function has already been called and the sensor is at the
+ // transparency adapter
+ move = dev->model->y_offset_calib_white_ta - dev->model->y_offset_sensor_to_ta;
+ flags |= ScanFlag::USE_XPA;
+ } else {
+ move = dev->model->y_offset_calib_white;
}
- dev->calib_pixels = (calib_sensor.sensor_pixels * dev->calib_resolution) /
- calib_sensor.optical_res;
- DBG(DBG_io, "%s: calib_lines = %zu\n", __func__, dev->calib_lines);
- DBG(DBG_io, "%s: calib_pixels = %zu\n", __func__, dev->calib_pixels);
+ move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
+
+ unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
ScanSession session;
- session.params.xres = dev->calib_resolution;
- session.params.yres = dev->motor.base_ydpi;
+ session.params.xres = resolution;
+ session.params.yres = resolution;
session.params.startx = 0;
- session.params.starty = 20;
- session.params.pixels = dev->calib_pixels;
- session.params.lines = dev->calib_lines;
+ session.params.starty = static_cast<unsigned>(move);
+ 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 = dev->settings.color_filter;
- session.params.flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA |
- ScanFlag::DISABLE_BUFFER_FULL_MOVE |
- ScanFlag::IGNORE_LINE_DISTANCE;
+ session.params.flags = flags;
compute_session(dev, session, calib_sensor);
init_regs_for_scan_session(dev, calib_sensor, &regs, session);
- dev->interface->write_registers(regs);
-
- /* we use GENESYS_FLAG_SHADING_REPARK */
+ /* we use ModelFlag::SHADING_REPARK */
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
-}
-
-/** @brief set up registers for the actual scan
- */
-void CommandSetGl847::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);
-
- /* steps to move to reach scanning area:
- - first we move to physical start of scanning
- either by a fixed steps amount from the black strip
- or by a fixed amount from parking position,
- minus the steps done during shading calibration
- - then we move by the needed offset whitin physical
- scanning area
-
- assumption: steps are expressed at maximum motor resolution
-
- we need:
- float y_offset;
- float y_size;
- float y_offset_calib;
- mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
-
- /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
- relative from origin, else, it is from parking position */
-
- move_dpi = dev->motor.base_ydpi;
-
- move = static_cast<float>(dev->model->y_offset);
- move = static_cast<float>(move + dev->settings.tl_y);
- move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
- move -= dev->head_pos(ScanHeadId::PRIMARY);
- DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
-
- /* fast move to scan area */
- /* we don't move fast the whole distance since it would involve
- * computing acceleration/deceleration distance for scan
- * resolution. So leave a remainder for it so scan makes the final
- * move tuning */
- 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);
- DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
-
- /* start */
- start = static_cast<float>(dev->model->x_offset);
- start = static_cast<float>(start + dev->settings.tl_x);
- 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;
- // backtracking isn't handled well, so don't enable it
- session.params.flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
- compute_session(dev, session, sensor);
-
- init_regs_for_scan_session(dev, sensor, &dev->reg, session);
+ dev->calib_session = session;
}
-
/**
* Send shading calibration data. The buffer is considered to always hold values
* for all the channels.
@@ -1114,39 +921,24 @@ void CommandSetGl847::send_shading_data(Genesys_Device* dev, const Genesys_Senso
uint8_t* data, int size) const
{
DBG_HELPER_ARGS(dbg, "writing %d bytes of shading data", size);
- uint32_t addr, length, i, x, factor, pixels;
- uint32_t dpiset, dpihw;
+ std::uint32_t addr, i;
uint8_t val,*ptr,*src;
- /* shading data is plit in 3 (up to 5 with IR) areas
- write(0x10014000,0x00000dd8)
- URB 23429 bulk_out len 3544 wrote 0x33 0x10 0x....
- write(0x1003e000,0x00000dd8)
- write(0x10068000,0x00000dd8)
- */
- length = static_cast<std::uint32_t>(size / 3);
- std::uint32_t strpixel = dev->session.pixel_startx;
- std::uint32_t endpixel = dev->session.pixel_endx;
+ unsigned length = static_cast<unsigned>(size / 3);
- /* 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);
+ // we're using SHDAREA, thus we only need to upload part of the line
+ unsigned offset = dev->session.pixel_count_ratio.apply(
+ dev->session.params.startx * sensor.full_resolution / dev->session.params.xres);
+ unsigned pixels = dev->session.pixel_count_ratio.apply(dev->session.optical_pixels_raw);
- pixels=endpixel-strpixel;
+ // turn pixel value into bytes 2x16 bits words
+ offset *= 2 * 2;
+ pixels *= 2 * 2;
- /* since we're using SHDAREA, substract startx coordinate from shading */
- strpixel -= (sensor.ccd_start_xoffset * 600) / sensor.optical_res;
-
- /* turn pixel value into bytes 2x16 bits words */
- strpixel*=2*2;
- pixels*=2*2;
-
- dev->interface->record_key_value("shading_offset", std::to_string(strpixel));
+ dev->interface->record_key_value("shading_offset", std::to_string(offset));
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));
std::vector<uint8_t> buffer(pixels, 0);
@@ -1155,6 +947,10 @@ void CommandSetGl847::send_shading_data(Genesys_Device* dev, const Genesys_Senso
/* base addr of data has been written in reg D0-D4 in 4K word, so AHB address
* is 8192*reg value */
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ return;
+ }
+
/* write actual color channel data */
for(i=0;i<3;i++)
{
@@ -1162,11 +958,10 @@ void CommandSetGl847::send_shading_data(Genesys_Device* dev, const Genesys_Senso
* to the one corresponding to SHDAREA */
ptr = buffer.data();
- /* iterate on both sensor segment */
- for(x=0;x<pixels;x+=4*factor)
- {
+ // iterate on both sensor segment
+ for (unsigned x = 0; x < pixels; x += 4 * sensor.shading_factor) {
/* coefficient source */
- src=(data+strpixel+i*length)+x;
+ src = (data + offset + i * length) + x;
/* coefficient copy */
ptr[0]=src[0];
@@ -1192,160 +987,7 @@ void CommandSetGl847::send_shading_data(Genesys_Device* dev, const Genesys_Senso
SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const
{
- DBG_HELPER(dbg);
- int num_pixels;
- int total_size;
- int used_res;
- int i, j;
- int val;
- int channels;
- int avg[3], top[3], bottom[3];
- int turn;
- uint16_t exp[3];
- float move;
-
- move = static_cast<float>(dev->model->y_offset_calib_white);
- move = static_cast<float>((move * (dev->motor.base_ydpi / 4)) / MM_PER_INCH);
- if (move > 20) {
- scanner_move(*dev, dev->model->default_method, static_cast<unsigned>(move),
- Direction::FORWARD);
- }
- DBG(DBG_io, "%s: move=%f steps\n", __func__, move);
-
- /* offset calibration is always done in color mode */
- channels = 3;
- used_res = sensor.get_register_hwdpi(dev->settings.xres);
- const auto& calib_sensor = sanei_genesys_find_sensor(dev, used_res, channels,
- dev->settings.scan_method);
- num_pixels = (calib_sensor.sensor_pixels * used_res) / calib_sensor.optical_res;
-
- /* initial calibration reg values */
- regs = dev->reg;
-
- ScanSession session;
- session.params.xres = used_res;
- session.params.yres = used_res;
- 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, &regs, 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;
-
- bottom[0] = 28000;
- bottom[1] = 28000;
- bottom[2] = 28000;
-
- top[0] = 32000;
- top[1] = 32000;
- top[2] = 32000;
-
- turn = 0;
-
- /* no move during led calibration */
- bool acceptable = false;
- sanei_genesys_set_motor_power(regs, false);
- do
- {
- // set up exposure
- regs.set16(REG_EXPR,exp[0]);
- regs.set16(REG_EXPG,exp[1]);
- regs.set16(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, &regs, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("led_calibration");
- scanner_stop_action(*dev);
- move_back_home(dev, true);
- 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, "gl847_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++)
- {
- if (avg[i] < bottom[i] || avg[i] > top[i]) {
- auto target = (bottom[i] + top[i]) / 2;
- exp[i] = (exp[i] * target) / avg[i];
- 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.set16(REG_EXPR, exp[0]);
- dev->reg.set16(REG_EXPG, exp[1]);
- dev->reg.set16(REG_EXPB, exp[2]);
-
- // go back home
- if (move>20) {
- move_back_home(dev, true);
- }
-
- return { exp[0], exp[1], exp[2] };
+ return scanner_led_calibration(*dev, sensor, regs);
}
/**
@@ -1354,31 +996,37 @@ SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genes
static void gl847_init_gpio(Genesys_Device* dev)
{
DBG_HELPER(dbg);
- int idx=0;
- /* search GPIO profile */
- while(gpios[idx].gpio_id != GpioId::UNKNOWN && dev->model->gpio_id != gpios[idx].gpio_id) {
- idx++;
- }
- if (gpios[idx].gpio_id == GpioId::UNKNOWN) {
- throw SaneException("failed to find GPIO profile for sensor_id=%d",
- static_cast<unsigned>(dev->model->sensor_id));
- }
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ apply_registers_ordered(dev->gpo.regs, {0xa6, 0xa7, 0x6f, 0x6e},
+ [&](const GenesysRegisterSetting& reg)
+ {
+ dev->interface->write_register(reg.address, reg.value);
+ });
+ } else {
+ std::vector<std::uint16_t> order1 = { 0xa7, 0xa6, 0x6e };
+ std::vector<std::uint16_t> order2 = { 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0xa8, 0xa9 };
- dev->interface->write_register(REG_0xA7, gpios[idx].ra7);
- dev->interface->write_register(REG_0xA6, gpios[idx].ra6);
+ for (auto addr : order1) {
+ dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
+ }
- dev->interface->write_register(REG_0x6E, gpios[idx].r6e);
- dev->interface->write_register(REG_0x6C, 0x00);
+ dev->interface->write_register(REG_0x6C, 0x00); // FIXME: Likely not needed
- dev->interface->write_register(REG_0x6B, gpios[idx].r6b);
- dev->interface->write_register(REG_0x6C, gpios[idx].r6c);
- dev->interface->write_register(REG_0x6D, gpios[idx].r6d);
- dev->interface->write_register(REG_0x6E, gpios[idx].r6e);
- dev->interface->write_register(REG_0x6F, gpios[idx].r6f);
+ for (auto addr : order2) {
+ dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
+ }
- dev->interface->write_register(REG_0xA8, gpios[idx].ra8);
- dev->interface->write_register(REG_0xA9, gpios[idx].ra9);
+ for (const auto& reg : dev->gpo.regs) {
+ if (std::find(order1.begin(), order1.end(), reg.address) != order1.end()) {
+ continue;
+ }
+ if (std::find(order2.begin(), order2.end(), reg.address) != order2.end()) {
+ continue;
+ }
+ dev->interface->write_register(reg.address, reg.value);
+ }
+ }
}
/**
@@ -1387,77 +1035,24 @@ static void gl847_init_gpio(Genesys_Device* dev)
static void gl847_init_memory_layout(Genesys_Device* dev)
{
DBG_HELPER(dbg);
- int idx = 0;
- uint8_t val;
- /* point to per model memory layout */
- idx = 0;
- if (dev->model->model_id == ModelId::CANON_LIDE_100) {
- idx = 0;
- }
- if (dev->model->model_id == ModelId::CANON_LIDE_200) {
- idx = 1;
- }
- if (dev->model->model_id == ModelId::CANON_5600F) {
- idx = 2;
- }
- if (dev->model->model_id == ModelId::CANON_LIDE_700F) {
- idx = 3;
+ // FIXME: move to initial register list
+ switch (dev->model->model_id) {
+ case ModelId::CANON_LIDE_100:
+ case ModelId::CANON_LIDE_200:
+ dev->interface->write_register(REG_0x0B, 0x29);
+ break;
+ case ModelId::CANON_LIDE_700F:
+ dev->interface->write_register(REG_0x0B, 0x2a);
+ break;
+ default:
+ break;
}
- /* CLKSET nd DRAMSEL */
- val = layouts[idx].dramsel;
- dev->interface->write_register(REG_0x0B, val);
- dev->reg.find_reg(0x0b).value = val;
-
- /* prevent further writings by bulk write register */
- dev->reg.remove_reg(0x0b);
-
- /* 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);
+ // prevent further writings by bulk write register
+ dev->reg.remove_reg(0x0b);
+
+ apply_reg_settings_to_device_write_only(*dev, dev->memory_layout.regs);
}
/* *
@@ -1486,15 +1081,17 @@ void CommandSetGl847::asic_boot(Genesys_Device* dev, bool cold) const
// Write initial registers
dev->interface->write_registers(dev->reg);
- /* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */
- val = dev->reg.find_reg(0x0b).value & REG_0x0B_DRAMSEL;
- val = (val | REG_0x0B_ENBDRAM);
- dev->interface->write_register(REG_0x0B, val);
- dev->reg.find_reg(0x0b).value = val;
+ if (dev->model->model_id != ModelId::CANON_5600F) {
+ // Enable DRAM by setting a rising edge on bit 3 of reg 0x0b
+ // The initial register write also powers on SDRAM
+ val = dev->reg.find_reg(0x0b).value & REG_0x0B_DRAMSEL;
+ val = (val | REG_0x0B_ENBDRAM);
+ dev->interface->write_register(REG_0x0B, val);
+ dev->reg.find_reg(0x0b).value = val;
- /* CIS_LINE */
- dev->reg.init_reg(0x08, REG_0x08_CIS_LINE);
- dev->interface->write_register(0x08, dev->reg.find_reg(0x08).value);
+ // TODO: remove this write
+ dev->interface->write_register(0x08, dev->reg.find_reg(0x08).value);
+ }
// set up end access
dev->interface->write_0x8c(0x10, 0x0b);
@@ -1506,8 +1103,11 @@ void CommandSetGl847::asic_boot(Genesys_Device* dev, bool cold) const
// setup internal memory layout
gl847_init_memory_layout (dev);
- dev->reg.init_reg(0xf8, 0x01);
- dev->interface->write_register(0xf8, dev->reg.find_reg(0xf8).value);
+ if (dev->model->model_id != ModelId::CANON_5600F) {
+ // FIXME: move to memory layout
+ dev->reg.init_reg(0xf8, 0x01);
+ dev->interface->write_register(0xf8, dev->reg.find_reg(0xf8).value);
+ }
}
/**
@@ -1519,7 +1119,7 @@ void CommandSetGl847::init(Genesys_Device* dev) const
DBG_INIT ();
DBG_HELPER(dbg);
- sanei_genesys_asic_init(dev, 0);
+ sanei_genesys_asic_init(dev);
}
void CommandSetGl847::update_hardware_sensors(Genesys_Scanner* s) const
@@ -1566,517 +1166,16 @@ void CommandSetGl847::update_home_sensor_gpio(Genesys_Device& dev) const
}
}
-/** @brief search for a full width black or white strip.
- * This function searches for a black or white stripe across the scanning area.
- * When searching backward, the searched area must completely be of the desired
- * color since this area will be used for calibration which scans forward.
- * @param dev scanner device
- * @param forward true if searching forward, false if searching backward
- * @param black true if searching for a black strip, false for a white strip
- */
-void CommandSetGl847::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
- bool black) const
-{
- DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
- unsigned int pixels, lines, channels;
- Genesys_Register_Set local_reg;
- size_t size;
- unsigned int pass, count, found, x, y;
- char title[80];
-
- set_fe(dev, sensor, AFE_SET);
- scanner_stop_action(*dev);
-
- // set up for a gray scan at lowest dpi
- const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
- unsigned dpi = resolution_settings.get_min_resolution_x();
- channels = 1;
- /* 10 MM */
- /* lines = (10 * dpi) / MM_PER_INCH; */
- /* shading calibation is done with dev->motor.base_ydpi */
- lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
- pixels = (sensor.sensor_pixels * dpi) / sensor.optical_res;
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
-
- local_reg = dev->reg;
-
- ScanSession session;
- session.params.xres = dpi;
- session.params.yres = dpi;
- 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::GRAY;
- session.params.color_filter = ColorFilter::RED;
- session.params.flags = ScanFlag::DISABLE_SHADING |
- ScanFlag::DISABLE_GAMMA;
- if (!forward) {
- session.params.flags |= ScanFlag::REVERSE;
- }
- compute_session(dev, session, sensor);
-
- size = pixels * channels * lines * (session.params.depth / 8);
- std::vector<uint8_t> data(size);
-
- init_regs_for_scan_session(dev, sensor, &local_reg, session);
-
- dev->interface->write_registers(local_reg);
-
- begin_scan(dev, sensor, &local_reg, true);
-
- if (is_testing_mode()) {
- dev->interface->test_checkpoint("search_strip");
- scanner_stop_action(*dev);
- 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);
-
- scanner_stop_action(*dev);
-
- pass = 0;
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl847_search_strip_%s_%s%02d.pnm",
- black ? "black" : "white", forward ? "fwd" : "bwd", pass);
- sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
- channels, pixels, lines);
- }
-
- /* loop until strip is found or maximum pass number done */
- found = 0;
- while (pass < 20 && !found)
- {
- dev->interface->write_registers(local_reg);
-
- // now start scan
- begin_scan(dev, sensor, &local_reg, true);
-
- 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);
-
- scanner_stop_action(*dev);
-
- if (DBG_LEVEL >= DBG_data)
- {
- std::sprintf(title, "gl847_search_strip_%s_%s%02d.pnm",
- black ? "black" : "white",
- forward ? "fwd" : "bwd", static_cast<int>(pass));
- sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
- channels, pixels, lines);
- }
-
- /* search data to find black strip */
- /* when searching forward, we only need one line of the searched color since we
- * will scan forward. But when doing backward search, we need all the area of the
- * same color */
- if (forward)
- {
- for (y = 0; y < lines && !found; y++)
- {
- count = 0;
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * pixels + x] > 90)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * pixels + x] < 60)
- {
- count++;
- }
- }
-
- /* at end of line, if count >= 3%, line is not fully of the desired color
- * so we must go to next line of the buffer */
- /* count*100/pixels < 3 */
- if ((count * 100) / pixels < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
- pass, y);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- }
- else /* since calibration scans are done forward, we need the whole area
- to be of the required color when searching backward */
- {
- count = 0;
- for (y = 0; y < lines; y++)
- {
- /* count of white/black pixels depending on the color searched */
- for (x = 0; x < pixels; x++)
- {
- /* when searching for black, detect white pixels */
- if (black && data[y * pixels + x] > 90)
- {
- count++;
- }
- /* when searching for white, detect black pixels */
- if (!black && data[y * pixels + x] < 60)
- {
- count++;
- }
- }
- }
-
- /* at end of area, if count >= 3%, area is not fully of the desired color
- * so we must go to next buffer */
- if ((count * 100) / (pixels * lines) < 3)
- {
- found = 1;
- DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
- }
- else
- {
- DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
- (100 * count) / pixels);
- }
- }
- pass++;
- }
-
- if (found)
- {
- DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
- }
- else
- {
- throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
- }
-}
-
-/**
- * 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 CommandSetGl847::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 AKM AFE
- uint8_t reg04 = dev->interface->read_register(REG_0x04);
- if ((reg04 & REG_0x04_FESET) == 0x02) {
- 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, &regs, session);
-
- sanei_genesys_set_motor_power(regs, false);
-
- /* allocate memory for scans */
- total_size = pixels * channels * lines * (session.params.depth / 8); /* colors * bytes_per_color * scan lines */
-
- 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, &regs, 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 fn[30];
- std::snprintf(fn, 30, "gl847_offset%03d.pnm", bottom);
- sanei_genesys_write_pnm_file(fn, 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, &regs, 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, &regs, true);
- sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
-
- if (DBG_LEVEL >= DBG_data)
- {
- char fn[30];
- std::snprintf(fn, 30, "gl847_offset%03d.pnm", dev->frontend.get_offset(1));
- sanei_genesys_write_pnm_file(fn, 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);
}
void CommandSetGl847::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 AKM AFE
- uint8_t reg04 = dev->interface->read_register(REG_0x04);
- if ((reg04 & REG_0x04_FESET) == 0x02) {
- return;
- }
-
- /* coarse gain calibration is always done in color mode */
- channels = 3;
-
- /* follow CKSEL */
- if(dev->settings.xres<sensor.optical_res)
- {
- coeff = 0.9f;
- }
- else
- {
- coeff=1.0;
- }
- 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, &regs, 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, &regs, 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("gl847_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);
}
bool CommandSetGl847::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
@@ -2086,14 +1185,11 @@ bool CommandSetGl847::needs_home_before_init_regs_for_scan(Genesys_Device* dev)
}
void CommandSetGl847::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const
+ Genesys_Register_Set* regs) const
{
(void) dev;
(void) sensor;
(void) regs;
- (void) channels;
- (void) total_size;
throw SaneException("not implemented");
}
@@ -2125,16 +1221,5 @@ void CommandSetGl847::eject_document(Genesys_Device* dev) const
throw SaneException("not implemented");
}
-void CommandSetGl847::move_to_ta(Genesys_Device* dev) const
-{
- (void) dev;
- throw SaneException("not implemented");
-}
-
-std::unique_ptr<CommandSet> create_gl847_cmd_set()
-{
- return std::unique_ptr<CommandSet>(new CommandSetGl847{});
-}
-
} // namespace gl847
} // namespace genesys
diff --git a/backend/genesys/gl847.h b/backend/genesys/gl847.h
index a51c293..aa4fb85 100644
--- a/backend/genesys/gl847.h
+++ b/backend/genesys/gl847.h
@@ -45,75 +45,12 @@
#define BACKEND_GENESYS_GL847_H
#include "genesys.h"
-#include "command_set.h"
+#include "command_set_common.h"
namespace genesys {
namespace gl847 {
-typedef struct
-{
- GpioId gpio_id;
- uint8_t r6b;
- uint8_t r6c;
- uint8_t r6d;
- uint8_t r6e;
- uint8_t r6f;
- uint8_t ra6;
- uint8_t ra7;
- uint8_t ra8;
- uint8_t ra9;
-} Gpio_Profile;
-
-static Gpio_Profile gpios[]={
- { GpioId::CANON_LIDE_200, 0x02, 0xf9, 0x20, 0xff, 0x00, 0x04, 0x04, 0x00, 0x00},
- { GpioId::CANON_LIDE_700F, 0x06, 0xdb, 0xff, 0xff, 0x80, 0x15, 0x07, 0x20, 0x10},
- { GpioId::UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-
-typedef struct
-{
- uint8_t dramsel;
- uint8_t rd0;
- uint8_t rd1;
- uint8_t rd2;
- uint8_t re0;
- uint8_t re1;
- uint8_t re2;
- uint8_t re3;
- uint8_t re4;
- uint8_t re5;
- uint8_t re6;
- uint8_t re7;
-} Memory_layout;
-
-static Memory_layout layouts[]={
- /* LIDE 100 */
- {
- 0x29,
- 0x0a, 0x15, 0x20,
- 0x00, 0xac, 0x02, 0x55, 0x02, 0x56, 0x03, 0xff
- },
- /* LIDE 200 */
- {
- 0x29,
- 0x0a, 0x1f, 0x34,
- 0x01, 0x24, 0x02, 0x91, 0x02, 0x92, 0x03, 0xff
- },
- /* 5600F */
- {
- 0x29,
- 0x0a, 0x1f, 0x34,
- 0x01, 0x24, 0x02, 0x91, 0x02, 0x92, 0x03, 0xff
- },
- /* LIDE 700F */
- {
- 0x2a,
- 0x0a, 0x33, 0x5c,
- 0x02, 0x14, 0x09, 0x09, 0x09, 0x0a, 0x0f, 0xff
- }
-};
-
-class CommandSetGl847 : public CommandSet
+class CommandSetGl847 : public CommandSetCommon
{
public:
~CommandSetGl847() override = default;
@@ -123,17 +60,11 @@ public:
void init(Genesys_Device* dev) const override;
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set* regs, int* channels,
- int* total_size) const override;
-
- void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
- Genesys_Register_Set& regs) const override;
+ Genesys_Register_Set* regs) const override;
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
- void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
-
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set* reg,
const ScanSession& session) const override;
@@ -149,8 +80,6 @@ public:
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
- void search_start_position(Genesys_Device* dev) const override;
-
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
Genesys_Register_Set& regs) const override;
@@ -166,8 +95,6 @@ public:
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
- bool needs_update_home_sensor_gpio() const override { return true; }
-
void update_home_sensor_gpio(Genesys_Device& dev) const override;
void load_document(Genesys_Device* dev) const override;
@@ -176,11 +103,6 @@ public:
void eject_document(Genesys_Device* dev) const override;
- void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
- bool forward, bool black) const override;
-
- void move_to_ta(Genesys_Device* dev) const override;
-
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
int size) const override;
diff --git a/backend/genesys/gl847_registers.h b/backend/genesys/gl847_registers.h
index 0603a6a..aa3d43b 100644
--- a/backend/genesys/gl847_registers.h
+++ b/backend/genesys/gl847_registers.h
@@ -190,6 +190,7 @@ static constexpr RegMask REG_0x1D_CK1LOW = 0x20;
static constexpr RegMask REG_0x1D_TGSHLD = 0x1f;
static constexpr RegMask REG_0x1DS_TGSHLD = 0;
+static constexpr RegAddr REG_0x1E = 0x1e;
static constexpr RegMask REG_0x1E_WDTIME = 0xf0;
static constexpr RegMask REG_0x1ES_WDTIME = 4;
static constexpr RegMask REG_0x1E_LINESEL = 0x0f;
diff --git a/backend/genesys/image.cpp b/backend/genesys/image.cpp
index 7d386c6..793a209 100644
--- a/backend/genesys/image.cpp
+++ b/backend/genesys/image.cpp
@@ -45,6 +45,10 @@
#include "image.h"
+#if defined(HAVE_TIFFIO_H)
+#include <tiffio.h>
+#endif
+
#include <array>
namespace genesys {
@@ -201,4 +205,68 @@ void convert_pixel_row_format(const std::uint8_t* in_data, PixelFormat in_format
}
}
+void write_tiff_file(const std::string& filename, const void* data, int depth, int channels,
+ int pixels_per_line, int lines)
+{
+ DBG_HELPER_ARGS(dbg, "depth=%d, channels=%d, ppl=%d, lines=%d", depth, channels,
+ pixels_per_line, lines);
+#if defined(HAVE_TIFFIO_H)
+ auto image = TIFFOpen(filename.c_str(), "w");
+ if (!image) {
+ dbg.log(DBG_error, "Could not save debug image");
+ return;
+ }
+ TIFFSetField(image, TIFFTAG_IMAGEWIDTH, pixels_per_line);
+ TIFFSetField(image, TIFFTAG_IMAGELENGTH, lines);
+ TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, depth);
+ TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, channels);
+ if (channels > 1) {
+ TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
+ } else {
+ TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
+ }
+ TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+ TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
+
+ std::size_t bytes_per_line = (pixels_per_line * channels * depth + 7) / 8;
+ const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(data);
+
+ // we don't need to handle endian because libtiff will handle that
+ for (int iline = 0; iline < lines; ++iline) {
+ const auto* line_data = data_ptr + bytes_per_line * iline;
+ TIFFWriteScanline(image, const_cast<std::uint8_t*>(line_data), iline, 0);
+ }
+ TIFFClose(image);
+
+#else
+ dbg.log(DBG_error, "Backend has been built without TIFF library support. "
+ "Debug images will not be saved");
+#endif
+}
+
+bool is_supported_write_tiff_file_image_format(PixelFormat format)
+{
+ switch (format) {
+ case PixelFormat::I1:
+ case PixelFormat::RGB111:
+ case PixelFormat::I8:
+ case PixelFormat::RGB888:
+ case PixelFormat::I16:
+ case PixelFormat::RGB161616:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void write_tiff_file(const std::string& filename, const Image& image)
+{
+ if (!is_supported_write_tiff_file_image_format(image.get_format())) {
+ throw SaneException("Unsupported format %d", static_cast<unsigned>(image.get_format()));
+ }
+
+ write_tiff_file(filename, image.get_row_ptr(0), get_pixel_format_depth(image.get_format()),
+ get_pixel_channels(image.get_format()), image.get_width(), image.get_height());
+}
+
} // namespace genesys
diff --git a/backend/genesys/image.h b/backend/genesys/image.h
index c96b1bb..798594e 100644
--- a/backend/genesys/image.h
+++ b/backend/genesys/image.h
@@ -82,6 +82,11 @@ private:
void convert_pixel_row_format(const std::uint8_t* in_data, PixelFormat in_format,
std::uint8_t* out_data, PixelFormat out_format, std::size_t count);
+void write_tiff_file(const std::string& filename, const void* data, int depth,
+ int channels, int pixels_per_line, int lines);
+
+void write_tiff_file(const std::string& filename, const Image& image);
+
} // namespace genesys
#endif // ifndef BACKEND_GENESYS_IMAGE_H
diff --git a/backend/genesys/image_buffer.cpp b/backend/genesys/image_buffer.cpp
index 07c6987..c4f8019 100644
--- a/backend/genesys/image_buffer.cpp
+++ b/backend/genesys/image_buffer.cpp
@@ -45,13 +45,13 @@
#include "image_buffer.h"
#include "image.h"
+#include "utilities.h"
namespace genesys {
ImageBuffer::ImageBuffer(std::size_t size, ProducerCallback producer) :
producer_{producer},
- size_{size},
- buffer_offset_{size}
+ size_{size}
{
buffer_.resize(size_);
}
@@ -81,123 +81,30 @@ bool ImageBuffer::get_data(std::size_t size, std::uint8_t* out_data)
bool got_data = true;
do {
buffer_offset_ = 0;
- got_data &= producer_(size_, buffer_.data());
- copy_buffer();
- } while(out_data < out_data_end && got_data);
-
- return got_data;
-}
-
-void FakeBufferModel::push_step(std::size_t buffer_size, std::size_t row_bytes)
-{
- sizes_.push_back(buffer_size);
- available_sizes_.push_back(0);
- row_bytes_.push_back(row_bytes);
-}
-
-std::size_t FakeBufferModel::available_space() const
-{
- if (sizes_.empty())
- throw SaneException("Model has not been setup");
- return sizes_.front() - available_sizes_.front();
-}
-
-void FakeBufferModel::simulate_read(std::size_t size)
-{
- if (sizes_.empty()) {
- throw SaneException("Model has not been setup");
- }
- if (available_space() < size) {
- throw SaneException("Attempted to simulate read of too much memory");
- }
-
- available_sizes_.front() += size;
-
- for (unsigned i = 1; i < sizes_.size(); ++i) {
- auto avail_src = available_sizes_[i - 1];
- auto avail_dst = sizes_[i] - available_sizes_[i];
-
- auto avail = (std::min(avail_src, avail_dst) / row_bytes_[i]) * row_bytes_[i];
- available_sizes_[i - 1] -= avail;
- available_sizes_[i] += avail;
- }
- available_sizes_.back() = 0;
-}
-
-ImageBufferGenesysUsb::ImageBufferGenesysUsb(std::size_t total_size,
- const FakeBufferModel& buffer_model,
- ProducerCallback producer) :
- remaining_size_{total_size},
- buffer_model_{buffer_model},
- producer_{producer}
-{}
+ std::size_t size_to_read = size_;
+ if (remaining_size_ != BUFFER_SIZE_UNSET) {
+ size_to_read = std::min<std::uint64_t>(size_to_read, remaining_size_);
+ remaining_size_ -= size_to_read;
+ }
-bool ImageBufferGenesysUsb::get_data(std::size_t size, std::uint8_t* out_data)
-{
- const std::uint8_t* out_data_end = out_data + size;
+ std::size_t aligned_size_to_read = size_to_read;
+ if (remaining_size_ == 0 && last_read_multiple_ != BUFFER_SIZE_UNSET) {
+ aligned_size_to_read = align_multiple_ceil(size_to_read, last_read_multiple_);
+ }
- auto copy_buffer = [&]()
- {
- std::size_t bytes_copy = std::min<std::size_t>(out_data_end - out_data, available());
- std::memcpy(out_data, buffer_.data() + buffer_offset_, bytes_copy);
- out_data += bytes_copy;
- buffer_offset_ += bytes_copy;
- };
+ got_data &= producer_(aligned_size_to_read, buffer_.data());
+ curr_size_ = size_to_read;
- // first, read remaining data from buffer
- if (available() > 0) {
copy_buffer();
- }
-
- if (out_data == out_data_end) {
- return true;
- }
-
- // now the buffer is empty and there's more data to be read
- do {
- if (remaining_size_ == 0)
- return false;
- auto bytes_to_read = get_read_size();
- buffer_offset_ = 0;
- buffer_end_ = bytes_to_read;
- buffer_.resize(bytes_to_read);
-
- producer_(bytes_to_read, buffer_.data());
-
- if (remaining_size_ < bytes_to_read) {
- remaining_size_ = 0;
- } else {
- remaining_size_ -= bytes_to_read;
+ if (remaining_size_ == 0 && out_data < out_data_end) {
+ got_data = false;
}
- copy_buffer();
- } while(out_data < out_data_end);
- return true;
-}
-
-std::size_t ImageBufferGenesysUsb::get_read_size()
-{
- std::size_t size = buffer_model_.available_space();
+ } while (out_data < out_data_end && got_data);
- // never read an odd number. exception: last read
- // the chip internal counter does not count half words.
- size &= ~1;
-
- // Some setups need the reads to be multiples of 256 bytes
- size &= ~0xff;
-
- if (remaining_size_ < size) {
- size = remaining_size_;
- /*round up to a multiple of 256 bytes */
- size += (size & 0xff) ? 0x100 : 0x00;
- size &= ~0xff;
- }
-
- buffer_model_.simulate_read(size);
-
- return size;
+ return got_data;
}
} // namespace genesys
diff --git a/backend/genesys/image_buffer.h b/backend/genesys/image_buffer.h
index 43c3eb7..1910244 100644
--- a/backend/genesys/image_buffer.h
+++ b/backend/genesys/image_buffer.h
@@ -56,72 +56,33 @@ class ImageBuffer
{
public:
using ProducerCallback = std::function<bool(std::size_t size, std::uint8_t* out_data)>;
+ static constexpr std::uint64_t BUFFER_SIZE_UNSET = std::numeric_limits<std::uint64_t>::max();
ImageBuffer() {}
ImageBuffer(std::size_t size, ProducerCallback producer);
- std::size_t size() const { return size_; }
- std::size_t available() const { return size_ - buffer_offset_; }
+ std::size_t available() const { return curr_size_ - buffer_offset_; }
- bool get_data(std::size_t size, std::uint8_t* out_data);
-
-private:
- ProducerCallback producer_;
- std::size_t size_ = 0;
-
- std::size_t buffer_offset_ = 0;
- std::vector<std::uint8_t> buffer_;
-};
-
-class FakeBufferModel
-{
-public:
- FakeBufferModel() {}
-
- void push_step(std::size_t buffer_size, std::size_t row_bytes);
-
- std::size_t available_space() const;
-
- void simulate_read(std::size_t size);
+ // allows adjusting the amount of data left so that we don't do a full size read from the
+ // producer on the last iteration. Set to BUFFER_SIZE_UNSET to ignore buffer size.
+ std::uint64_t remaining_size() const { return remaining_size_; }
+ void set_remaining_size(std::uint64_t bytes) { remaining_size_ = bytes; }
-private:
- std::vector<std::size_t> sizes_;
- std::vector<std::size_t> available_sizes_;
- std::vector<std::size_t> row_bytes_;
-};
-
-// This class is similar to ImageBuffer, but preserves historical peculiarities of buffer handling
-// in the backend to preserve exact behavior
-class ImageBufferGenesysUsb
-{
-public:
- using ProducerCallback = std::function<void(std::size_t size, std::uint8_t* out_data)>;
-
- ImageBufferGenesysUsb() {}
- ImageBufferGenesysUsb(std::size_t total_size, const FakeBufferModel& buffer_model,
- ProducerCallback producer);
-
- std::size_t remaining_size() const { return remaining_size_; }
-
- void set_remaining_size(std::size_t bytes) { remaining_size_ = bytes; }
-
- std::size_t available() const { return buffer_end_ - buffer_offset_; }
+ // May be used to force the last read to be rounded up of a certain number of bytes
+ void set_last_read_multiple(std::uint64_t bytes) { last_read_multiple_ = bytes; }
bool get_data(std::size_t size, std::uint8_t* out_data);
private:
+ ProducerCallback producer_;
+ std::size_t size_ = 0;
+ std::size_t curr_size_ = 0;
- std::size_t get_read_size();
-
- std::size_t remaining_size_ = 0;
+ std::uint64_t remaining_size_ = BUFFER_SIZE_UNSET;
+ std::uint64_t last_read_multiple_ = BUFFER_SIZE_UNSET;
std::size_t buffer_offset_ = 0;
- std::size_t buffer_end_ = 0;
std::vector<std::uint8_t> buffer_;
-
- FakeBufferModel buffer_model_;
-
- ProducerCallback producer_;
};
} // namespace genesys
diff --git a/backend/genesys/image_pipeline.cpp b/backend/genesys/image_pipeline.cpp
index c01b7f4..8d67be9 100644
--- a/backend/genesys/image_pipeline.cpp
+++ b/backend/genesys/image_pipeline.cpp
@@ -53,15 +53,6 @@ namespace genesys {
ImagePipelineNode::~ImagePipelineNode() {}
-std::size_t ImagePipelineNodeBytesSource::consume_remaining_bytes(std::size_t bytes)
-{
- if (bytes > remaining_bytes_) {
- bytes = remaining_bytes_;
- }
- remaining_bytes_ -= bytes;
- return bytes;
-}
-
bool ImagePipelineNodeCallableSource::get_next_row_data(std::uint8_t* out_data)
{
bool got_data = producer_(get_row_bytes(), out_data);
@@ -78,7 +69,7 @@ ImagePipelineNodeBufferedCallableSource::ImagePipelineNodeBufferedCallableSource
format_{format},
buffer_{input_batch_size, producer}
{
- set_remaining_bytes(height_ * get_row_bytes());
+ buffer_.set_remaining_size(height_ * get_row_bytes());
}
bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* out_data)
@@ -92,13 +83,7 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou
bool got_data = true;
- auto row_bytes = get_row_bytes();
- auto bytes_to_ask = consume_remaining_bytes(row_bytes);
- if (bytes_to_ask < row_bytes) {
- got_data = false;
- }
-
- got_data &= buffer_.get_data(bytes_to_ask, out_data);
+ got_data &= buffer_.get_data(get_row_bytes(), out_data);
curr_row_++;
if (!got_data) {
eof_ = true;
@@ -106,37 +91,6 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou
return got_data;
}
-
-ImagePipelineNodeBufferedGenesysUsb::ImagePipelineNodeBufferedGenesysUsb(
- std::size_t width, std::size_t height, PixelFormat format, std::size_t total_size,
- const FakeBufferModel& buffer_model, ProducerCallback producer) :
- width_{width},
- height_{height},
- format_{format},
- buffer_{total_size, buffer_model, producer}
-{
- set_remaining_bytes(total_size);
-}
-
-bool ImagePipelineNodeBufferedGenesysUsb::get_next_row_data(std::uint8_t* out_data)
-{
- if (remaining_bytes() != buffer_.remaining_size() + buffer_.available()) {
- buffer_.set_remaining_size(remaining_bytes() - buffer_.available());
- }
- bool got_data = true;
-
- std::size_t row_bytes = get_row_bytes();
- std::size_t ask_bytes = consume_remaining_bytes(row_bytes);
- if (ask_bytes < row_bytes) {
- got_data = false;
- }
- got_data &= buffer_.get_data(ask_bytes, out_data);
- if (!got_data) {
- eof_ = true;
- }
- return got_data;
-}
-
ImagePipelineNodeArraySource::ImagePipelineNodeArraySource(std::size_t width, std::size_t height,
PixelFormat format,
std::vector<std::uint8_t> data) :
@@ -151,7 +105,6 @@ ImagePipelineNodeArraySource::ImagePipelineNodeArraySource(std::size_t width, st
throw SaneException("The given array is too small (%zu bytes). Need at least %zu",
data_.size(), size);
}
- set_remaining_bytes(size);
}
bool ImagePipelineNodeArraySource::get_next_row_data(std::uint8_t* out_data)
@@ -161,21 +114,11 @@ bool ImagePipelineNodeArraySource::get_next_row_data(std::uint8_t* out_data)
return false;
}
- bool got_data = true;
-
auto row_bytes = get_row_bytes();
- auto bytes_to_ask = consume_remaining_bytes(row_bytes);
- if (bytes_to_ask < row_bytes) {
- got_data = false;
- }
-
- std::memcpy(out_data, data_.data() + get_row_bytes() * next_row_, bytes_to_ask);
+ std::memcpy(out_data, data_.data() + row_bytes * next_row_, row_bytes);
next_row_++;
- if (!got_data) {
- eof_ = true;
- }
- return got_data;
+ return true;
}
@@ -319,6 +262,50 @@ bool ImagePipelineNodeSwap16BitEndian::get_next_row_data(std::uint8_t* out_data)
return got_data;
}
+ImagePipelineNodeInvert::ImagePipelineNodeInvert(ImagePipelineNode& source) :
+ source_(source)
+{
+}
+
+bool ImagePipelineNodeInvert::get_next_row_data(std::uint8_t* out_data)
+{
+ bool got_data = source_.get_next_row_data(out_data);
+ auto num_values = get_width() * get_pixel_channels(source_.get_format());
+ auto depth = get_pixel_format_depth(source_.get_format());
+
+ switch (depth) {
+ case 16: {
+ auto* data = reinterpret_cast<std::uint16_t*>(out_data);
+ for (std::size_t i = 0; i < num_values; ++i) {
+ *data = 0xffff - *data;
+ data++;
+ }
+ break;
+ }
+ case 8: {
+ auto* data = out_data;
+ for (std::size_t i = 0; i < num_values; ++i) {
+ *data = 0xff - *data;
+ data++;
+ }
+ break;
+ }
+ case 1: {
+ auto* data = out_data;
+ auto num_bytes = (num_values + 7) / 8;
+ for (std::size_t i = 0; i < num_bytes; ++i) {
+ *data = ~*data;
+ data++;
+ }
+ break;
+ }
+ default:
+ throw SaneException("Unsupported pixel depth");
+ }
+
+ return got_data;
+}
+
ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source,
ColorOrder color_order) :
source_(source),
@@ -456,6 +443,12 @@ ImagePipelineNodeComponentShiftLines::ImagePipelineNodeComponentShiftLines(
static_cast<unsigned>(source.get_format()));
}
extra_height_ = *std::max_element(channel_shifts_.begin(), channel_shifts_.end());
+ height_ = source_.get_height();
+ if (extra_height_ > height_) {
+ height_ = 0;
+ } else {
+ height_ -= extra_height_;
+ }
}
bool ImagePipelineNodeComponentShiftLines::get_next_row_data(std::uint8_t* out_data)
@@ -492,18 +485,13 @@ ImagePipelineNodePixelShiftLines::ImagePipelineNodePixelShiftLines(
pixel_shifts_{shifts},
buffer_{get_row_bytes()}
{
- DBG_HELPER(dbg);
- DBG(DBG_proc, "%s: shifts={", __func__);
- for (auto el : pixel_shifts_) {
- DBG(DBG_proc, " %zu", el);
- }
- DBG(DBG_proc, " }\n");
-
- if (pixel_shifts_.size() > MAX_SHIFTS) {
- throw SaneException("Unsupported number of shift configurations %zu", pixel_shifts_.size());
- }
-
extra_height_ = *std::max_element(pixel_shifts_.begin(), pixel_shifts_.end());
+ height_ = source_.get_height();
+ if (extra_height_ > height_) {
+ height_ = 0;
+ } else {
+ height_ -= extra_height_;
+ }
}
bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)
@@ -521,7 +509,8 @@ bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)
auto format = get_format();
auto shift_count = pixel_shifts_.size();
- std::array<std::uint8_t*, MAX_SHIFTS> rows;
+ std::vector<std::uint8_t*> rows;
+ rows.resize(shift_count, nullptr);
for (std::size_t irow = 0; irow < shift_count; ++irow) {
rows[irow] = buffer_.get_row_ptr(pixel_shifts_[irow]);
@@ -536,6 +525,63 @@ bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)
return got_data;
}
+ImagePipelineNodePixelShiftColumns::ImagePipelineNodePixelShiftColumns(
+ ImagePipelineNode& source, const std::vector<std::size_t>& shifts) :
+ source_(source),
+ pixel_shifts_{shifts}
+{
+ width_ = source_.get_width();
+ extra_width_ = compute_pixel_shift_extra_width(width_, pixel_shifts_);
+ if (extra_width_ > width_) {
+ width_ = 0;
+ } else {
+ width_ -= extra_width_;
+ }
+ temp_buffer_.resize(source_.get_row_bytes());
+}
+
+bool ImagePipelineNodePixelShiftColumns::get_next_row_data(std::uint8_t* out_data)
+{
+ if (width_ == 0) {
+ throw SaneException("Attempt to read zero-width line");
+ }
+ bool got_data = source_.get_next_row_data(temp_buffer_.data());
+
+ auto format = get_format();
+ auto shift_count = pixel_shifts_.size();
+
+ for (std::size_t x = 0, width = get_width(); x < width; x += shift_count) {
+ for (std::size_t ishift = 0; ishift < shift_count && x + ishift < width; ishift++) {
+ RawPixel pixel = get_raw_pixel_from_row(temp_buffer_.data(), x + pixel_shifts_[ishift],
+ format);
+ set_raw_pixel_to_row(out_data, x + ishift, pixel, format);
+ }
+ }
+ return got_data;
+}
+
+
+std::size_t compute_pixel_shift_extra_width(std::size_t source_width,
+ const std::vector<std::size_t>& shifts)
+{
+ // we iterate across pixel shifts and find the pixel that needs the maximum shift according to
+ // source_width.
+ int group_size = shifts.size();
+ int non_filled_group = source_width % shifts.size();
+ int extra_width = 0;
+
+ for (int i = 0; i < group_size; ++i) {
+ int shift_groups = shifts[i] / group_size;
+ int shift_rem = shifts[i] % group_size;
+
+ if (shift_rem < non_filled_group) {
+ shift_groups--;
+ }
+ extra_width = std::max(extra_width, shift_groups * group_size + non_filled_group - i);
+ }
+ return extra_width;
+}
+
ImagePipelineNodeExtract::ImagePipelineNodeExtract(ImagePipelineNode& source,
std::size_t offset_x, std::size_t offset_y,
std::size_t width, std::size_t height) :
@@ -666,16 +712,21 @@ bool ImagePipelineNodeExtract::get_next_row_data(std::uint8_t* out_data)
ImagePipelineNodeCalibrate::ImagePipelineNodeCalibrate(ImagePipelineNode& source,
const std::vector<std::uint16_t>& bottom,
- const std::vector<std::uint16_t>& top) :
+ const std::vector<std::uint16_t>& top,
+ std::size_t x_start) :
source_{source}
{
- auto size = std::min(bottom.size(), top.size());
+ std::size_t size = 0;
+ if (bottom.size() >= x_start && top.size() >= x_start) {
+ size = std::min(bottom.size() - x_start, top.size() - x_start);
+ }
+
offset_.reserve(size);
multiplier_.reserve(size);
for (std::size_t i = 0; i < size; ++i) {
- offset_.push_back(bottom[i] / 65535.0f);
- multiplier_.push_back(65535.0f / (top[i] - bottom[i]));
+ offset_.push_back(bottom[i + x_start] / 65535.0f);
+ multiplier_.push_back(65535.0f / (top[i + x_start] - bottom[i + x_start]));
}
}
@@ -729,10 +780,8 @@ ImagePipelineNodeDebug::~ImagePipelineNodeDebug()
auto format = get_format();
buffer_.linearize();
- sanei_genesys_write_pnm_file(path_.c_str(), buffer_.get_front_row_ptr(),
- get_pixel_format_depth(format),
- get_pixel_channels(format),
- get_width(), buffer_.height());
+ write_tiff_file(path_, buffer_.get_front_row_ptr(), get_pixel_format_depth(format),
+ get_pixel_channels(format), get_width(), buffer_.height());
});
}
diff --git a/backend/genesys/image_pipeline.h b/backend/genesys/image_pipeline.h
index 2986837..d4aef49 100644
--- a/backend/genesys/image_pipeline.h
+++ b/backend/genesys/image_pipeline.h
@@ -75,18 +75,6 @@ public:
virtual bool get_next_row_data(std::uint8_t* out_data) = 0;
};
-class ImagePipelineNodeBytesSource : public ImagePipelineNode
-{
-public:
- std::size_t remaining_bytes() const { return remaining_bytes_; }
- void set_remaining_bytes(std::size_t bytes) { remaining_bytes_ = bytes; }
-
- std::size_t consume_remaining_bytes(std::size_t bytes);
-
-private:
- std::size_t remaining_bytes_ = 0;
-};
-
// A pipeline node that produces data from a callable
class ImagePipelineNodeCallableSource : public ImagePipelineNode
{
@@ -118,7 +106,7 @@ private:
};
// A pipeline node that produces data from a callable requesting fixed-size chunks.
-class ImagePipelineNodeBufferedCallableSource : public ImagePipelineNodeBytesSource
+class ImagePipelineNodeBufferedCallableSource : public ImagePipelineNode
{
public:
using ProducerCallback = std::function<bool(std::size_t size, std::uint8_t* out_data)>;
@@ -135,8 +123,9 @@ public:
bool get_next_row_data(std::uint8_t* out_data) override;
- std::size_t buffer_size() const { return buffer_.size(); }
- std::size_t buffer_available() const { return buffer_.available(); }
+ std::size_t remaining_bytes() const { return buffer_.remaining_size(); }
+ void set_remaining_bytes(std::size_t bytes) { buffer_.set_remaining_size(bytes); }
+ void set_last_read_multiple(std::size_t bytes) { buffer_.set_last_read_multiple(bytes); }
private:
ProducerCallback producer_;
@@ -150,39 +139,8 @@ private:
ImageBuffer buffer_;
};
-class ImagePipelineNodeBufferedGenesysUsb : public ImagePipelineNodeBytesSource
-{
-public:
- using ProducerCallback = std::function<void(std::size_t size, std::uint8_t* out_data)>;
-
- ImagePipelineNodeBufferedGenesysUsb(std::size_t width, std::size_t height,
- PixelFormat format, std::size_t total_size,
- const FakeBufferModel& buffer_model,
- ProducerCallback producer);
-
- std::size_t get_width() const override { return width_; }
- std::size_t get_height() const override { return height_; }
- PixelFormat get_format() const override { return format_; }
-
- bool eof() const override { return eof_; }
-
- bool get_next_row_data(std::uint8_t* out_data) override;
-
- std::size_t buffer_available() const { return buffer_.available(); }
-
-private:
- ProducerCallback producer_;
- std::size_t width_ = 0;
- std::size_t height_ = 0;
- PixelFormat format_ = PixelFormat::UNKNOWN;
-
- bool eof_ = false;
-
- ImageBufferGenesysUsb buffer_;
-};
-
// A pipeline node that produces data from the given array.
-class ImagePipelineNodeArraySource : public ImagePipelineNodeBytesSource
+class ImagePipelineNodeArraySource : public ImagePipelineNode
{
public:
ImagePipelineNodeArraySource(std::size_t width, std::size_t height, PixelFormat format,
@@ -302,7 +260,7 @@ public:
std::size_t pixels_per_chunk);
};
-// A pipeline that swaps bytes in 16-bit components on big-endian systems
+// A pipeline that swaps bytes in 16-bit components and does nothing otherwise.
class ImagePipelineNodeSwap16BitEndian : public ImagePipelineNode
{
public:
@@ -321,6 +279,23 @@ private:
bool needs_swapping_ = false;
};
+class ImagePipelineNodeInvert : public ImagePipelineNode
+{
+public:
+ ImagePipelineNodeInvert(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 source_.get_format(); }
+
+ bool eof() const override { return source_.eof(); }
+
+ bool get_next_row_data(std::uint8_t* out_data) override;
+
+private:
+ ImagePipelineNode& source_;
+};
+
// A pipeline node that merges 3 mono lines into a color channel
class ImagePipelineNodeMergeMonoLines : public ImagePipelineNode
{
@@ -377,7 +352,7 @@ public:
unsigned shift_r, unsigned shift_g, unsigned shift_b);
std::size_t get_width() const override { return source_.get_width(); }
- std::size_t get_height() const override { return source_.get_height() - extra_height_; }
+ std::size_t get_height() const override { return height_; }
PixelFormat get_format() const override { return source_.get_format(); }
bool eof() const override { return source_.eof(); }
@@ -387,23 +362,23 @@ public:
private:
ImagePipelineNode& source_;
std::size_t extra_height_ = 0;
+ std::size_t height_ = 0;
std::array<unsigned, 3> channel_shifts_;
RowBuffer buffer_;
};
-// A pipeline node that shifts pixels across lines by the given offsets (performs unstaggering)
+// A pipeline node that shifts pixels across lines by the given offsets (performs vertical
+// unstaggering)
class ImagePipelineNodePixelShiftLines : public ImagePipelineNode
{
public:
- constexpr static std::size_t MAX_SHIFTS = 2;
-
ImagePipelineNodePixelShiftLines(ImagePipelineNode& source,
const std::vector<std::size_t>& shifts);
std::size_t get_width() const override { return source_.get_width(); }
- std::size_t get_height() const override { return source_.get_height() - extra_height_; }
+ std::size_t get_height() const override { return height_; }
PixelFormat get_format() const override { return source_.get_format(); }
bool eof() const override { return source_.eof(); }
@@ -413,12 +388,44 @@ public:
private:
ImagePipelineNode& source_;
std::size_t extra_height_ = 0;
+ std::size_t height_ = 0;
std::vector<std::size_t> pixel_shifts_;
RowBuffer buffer_;
};
+// A pipeline node that shifts pixels across columns by the given offsets. Each row is divided
+// into pixel groups of shifts.size() pixels. For each output group starting at position xgroup,
+// the i-th pixel will be set to the input pixel at position xgroup + shifts[i].
+class ImagePipelineNodePixelShiftColumns : public ImagePipelineNode
+{
+public:
+ ImagePipelineNodePixelShiftColumns(ImagePipelineNode& source,
+ const std::vector<std::size_t>& shifts);
+
+ std::size_t get_width() const override { return width_; }
+ std::size_t get_height() const override { return source_.get_height(); }
+ PixelFormat get_format() const override { return source_.get_format(); }
+
+ bool eof() const override { return source_.eof(); }
+
+ bool get_next_row_data(std::uint8_t* out_data) override;
+
+private:
+ ImagePipelineNode& source_;
+ std::size_t width_ = 0;
+ std::size_t extra_width_ = 0;
+
+ std::vector<std::size_t> pixel_shifts_;
+
+ std::vector<std::uint8_t> temp_buffer_;
+};
+
+// exposed for tests
+std::size_t compute_pixel_shift_extra_width(std::size_t source_width,
+ const std::vector<std::size_t>& shifts);
+
// A pipeline node that extracts a sub-image from the image. Padding and cropping is done as needed.
// The class can't pad to the left of the image currently, as only positive offsets are accepted.
class ImagePipelineNodeExtract : public ImagePipelineNode
@@ -476,7 +483,7 @@ class ImagePipelineNodeCalibrate : public ImagePipelineNode
public:
ImagePipelineNodeCalibrate(ImagePipelineNode& source, const std::vector<std::uint16_t>& bottom,
- const std::vector<std::uint16_t>& top);
+ const std::vector<std::uint16_t>& top, std::size_t x_start);
std::size_t get_width() const override { return source_.get_width(); }
std::size_t get_height() const override { return source_.get_height(); }
@@ -517,6 +524,19 @@ class ImagePipelineStack
{
public:
ImagePipelineStack() {}
+ ImagePipelineStack(ImagePipelineStack&& other)
+ {
+ clear();
+ nodes_ = std::move(other.nodes_);
+ }
+
+ ImagePipelineStack& operator=(ImagePipelineStack&& other)
+ {
+ clear();
+ nodes_ = std::move(other.nodes_);
+ return *this;
+ }
+
~ImagePipelineStack() { clear(); }
std::size_t get_input_width() const;
@@ -536,20 +556,22 @@ public:
void clear();
template<class Node, class... Args>
- void push_first_node(Args&&... args)
+ Node& push_first_node(Args&&... args)
{
if (!nodes_.empty()) {
throw SaneException("Trying to append first node when there are existing nodes");
}
nodes_.emplace_back(std::unique_ptr<Node>(new Node(std::forward<Args>(args)...)));
+ return static_cast<Node&>(*nodes_.back());
}
template<class Node, class... Args>
- void push_node(Args&&... args)
+ Node& push_node(Args&&... args)
{
ensure_node_exists();
nodes_.emplace_back(std::unique_ptr<Node>(new Node(*nodes_.back(),
std::forward<Args>(args)...)));
+ return static_cast<Node&>(*nodes_.back());
}
bool get_next_row_data(std::uint8_t* out_data)
diff --git a/backend/genesys/image_pixel.h b/backend/genesys/image_pixel.h
index 2dda271..aa9980e 100644
--- a/backend/genesys/image_pixel.h
+++ b/backend/genesys/image_pixel.h
@@ -51,6 +51,7 @@
namespace genesys {
+// 16-bit values are in host endian
enum class PixelFormat
{
UNKNOWN,
diff --git a/backend/genesys/low.cpp b/backend/genesys/low.cpp
index 7937fcc..05ef46b 100644
--- a/backend/genesys/low.cpp
+++ b/backend/genesys/low.cpp
@@ -51,12 +51,23 @@
#include "gl124_registers.h"
#include "gl646_registers.h"
#include "gl841_registers.h"
+#include "gl842_registers.h"
#include "gl843_registers.h"
#include "gl846_registers.h"
#include "gl847_registers.h"
#include "gl646_registers.h"
+#include "gl124.h"
+#include "gl646.h"
+#include "gl841.h"
+#include "gl842.h"
+#include "gl843.h"
+#include "gl846.h"
+#include "gl847.h"
+#include "gl646.h"
+
#include <cstdio>
+#include <chrono>
#include <cmath>
#include <vector>
@@ -66,29 +77,17 @@
namespace genesys {
-/**
- * setup the hardware dependent functions
- */
-
-namespace gl124 { std::unique_ptr<CommandSet> create_gl124_cmd_set(); }
-namespace gl646 { std::unique_ptr<CommandSet> create_gl646_cmd_set(); }
-namespace gl841 { std::unique_ptr<CommandSet> create_gl841_cmd_set(); }
-namespace gl843 { std::unique_ptr<CommandSet> create_gl843_cmd_set(); }
-namespace gl846 { std::unique_ptr<CommandSet> create_gl846_cmd_set(); }
-namespace gl847 { std::unique_ptr<CommandSet> create_gl847_cmd_set(); }
-
-void sanei_genesys_init_cmd_set(Genesys_Device* dev)
+std::unique_ptr<CommandSet> create_cmd_set(AsicType asic_type)
{
- DBG_INIT ();
- DBG_HELPER(dbg);
- switch (dev->model->asic_type) {
- case AsicType::GL646: dev->cmd_set = gl646::create_gl646_cmd_set(); break;
- case AsicType::GL841: dev->cmd_set = gl841::create_gl841_cmd_set(); break;
- case AsicType::GL843: dev->cmd_set = gl843::create_gl843_cmd_set(); break;
+ switch (asic_type) {
+ case AsicType::GL646: return std::unique_ptr<CommandSet>(new gl646::CommandSetGl646{});
+ case AsicType::GL841: return std::unique_ptr<CommandSet>(new gl841::CommandSetGl841{});
+ case AsicType::GL842: return std::unique_ptr<CommandSet>(new gl842::CommandSetGl842{});
+ case AsicType::GL843: return std::unique_ptr<CommandSet>(new gl843::CommandSetGl843{});
case AsicType::GL845: // since only a few reg bits differs we handle both together
- case AsicType::GL846: dev->cmd_set = gl846::create_gl846_cmd_set(); break;
- case AsicType::GL847: dev->cmd_set = gl847::create_gl847_cmd_set(); break;
- case AsicType::GL124: dev->cmd_set = gl124::create_gl124_cmd_set(); break;
+ case AsicType::GL846: return std::unique_ptr<CommandSet>(new gl846::CommandSetGl846{});
+ case AsicType::GL847: return std::unique_ptr<CommandSet>(new gl847::CommandSetGl847{});
+ case AsicType::GL124: return std::unique_ptr<CommandSet>(new gl124::CommandSetGl124{});
default: throw SaneException(SANE_STATUS_INVAL, "unknown ASIC type");
}
}
@@ -108,116 +107,6 @@ void sanei_genesys_write_file(const char* filename, const std::uint8_t* data, st
std::fclose(out);
}
-// Write data to a pnm file (e.g. calibration). For debugging only
-// data is RGB or grey, with little endian byte order
-void sanei_genesys_write_pnm_file(const char* filename, const std::uint8_t* data, int depth,
- int channels, int pixels_per_line, int lines)
-{
- DBG_HELPER_ARGS(dbg, "depth=%d, channels=%d, ppl=%d, lines=%d", depth, channels,
- pixels_per_line, lines);
- int count;
-
- std::FILE* out = std::fopen(filename, "w");
- if (!out)
- {
- throw SaneException("could not open %s for writing: %s\n", filename, strerror(errno));
- }
- if(depth==1)
- {
- fprintf (out, "P4\n%d\n%d\n", pixels_per_line, lines);
- }
- else
- {
- std::fprintf(out, "P%c\n%d\n%d\n%d\n", channels == 1 ? '5' : '6', pixels_per_line, lines,
- static_cast<int>(std::pow(static_cast<double>(2),
- static_cast<double>(depth - 1))));
- }
- if (channels == 3)
- {
- for (count = 0; count < (pixels_per_line * lines * 3); count++)
- {
- if (depth == 16)
- fputc (*(data + 1), out);
- fputc (*(data++), out);
- if (depth == 16)
- data++;
- }
- }
- else
- {
- if (depth==1)
- {
- pixels_per_line/=8;
- }
- for (count = 0; count < (pixels_per_line * lines); count++)
- {
- switch (depth)
- {
- case 8:
- fputc (*(data + count), out);
- break;
- case 16:
- fputc (*(data + 1), out);
- fputc (*(data), out);
- data += 2;
- break;
- default:
- fputc(data[count], out);
- break;
- }
- }
- }
- std::fclose(out);
-}
-
-void sanei_genesys_write_pnm_file16(const char* filename, const uint16_t* data, unsigned channels,
- unsigned pixels_per_line, unsigned lines)
-{
- DBG_HELPER_ARGS(dbg, "channels=%d, ppl=%d, lines=%d", channels,
- pixels_per_line, lines);
-
- std::FILE* out = std::fopen(filename, "w");
- if (!out) {
- throw SaneException("could not open %s for writing: %s\n", filename, strerror(errno));
- }
- std::fprintf(out, "P%c\n%d\n%d\n%d\n", channels == 1 ? '5' : '6',
- pixels_per_line, lines, 256 * 256 - 1);
-
- for (unsigned count = 0; count < (pixels_per_line * lines * channels); count++) {
- fputc(*data >> 8, out);
- fputc(*data & 0xff, out);
- data++;
- }
- std::fclose(out);
-}
-
-bool is_supported_write_pnm_file_image_format(PixelFormat format)
-{
- switch (format) {
- case PixelFormat::I1:
- case PixelFormat::RGB111:
- case PixelFormat::I8:
- case PixelFormat::RGB888:
- case PixelFormat::I16:
- case PixelFormat::RGB161616:
- return true;
- default:
- return false;
- }
-}
-
-void sanei_genesys_write_pnm_file(const char* filename, const Image& image)
-{
- if (!is_supported_write_pnm_file_image_format(image.get_format())) {
- throw SaneException("Unsupported format %d", static_cast<unsigned>(image.get_format()));
- }
-
- sanei_genesys_write_pnm_file(filename, image.get_row_ptr(0),
- get_pixel_format_depth(image.get_format()),
- get_pixel_channels(image.get_format()),
- image.get_width(), image.get_height());
-}
-
/* ------------------------------------------------------------------------ */
/* Read and write RAM, registers and AFE */
/* ------------------------------------------------------------------------ */
@@ -276,6 +165,7 @@ Status scanner_read_status(Genesys_Device& dev)
case AsicType::GL124: address = 0x101; break;
case AsicType::GL646:
case AsicType::GL841:
+ case AsicType::GL842:
case AsicType::GL843:
case AsicType::GL845:
case AsicType::GL846:
@@ -336,28 +226,23 @@ void debug_print_status(DebugMessageHelper& dbg, Status val)
dbg.vlog(DBG_info, "status=%s\n", str.str().c_str());
}
-#if 0
-/* returns pixels per line from register set */
-/*candidate for moving into chip specific files?*/
-static int
-genesys_pixels_per_line (Genesys_Register_Set * reg)
+void scanner_register_rw_clear_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask)
{
- int pixels_per_line;
-
- pixels_per_line = reg->get8(0x32) * 256 + reg->get8(0x33);
- pixels_per_line -= (reg->get8(0x30) * 256 + reg->get8(0x31));
+ scanner_register_rw_bits(dev, address, 0x00, mask);
+}
- return pixels_per_line;
+void scanner_register_rw_set_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask)
+{
+ scanner_register_rw_bits(dev, address, mask, mask);
}
-/* returns dpiset from register set */
-/*candidate for moving into chip specific files?*/
-static int
-genesys_dpiset (Genesys_Register_Set * reg)
+void scanner_register_rw_bits(Genesys_Device& dev, std::uint16_t address,
+ std::uint8_t value, std::uint8_t mask)
{
- return reg->get8(0x2c) * 256 + reg->get8(0x2d);
+ auto reg_value = dev.interface->read_register(address);
+ reg_value = (reg_value & ~mask) | (value & mask);
+ dev.interface->write_register(address, reg_value);
}
-#endif
/** read the number of valid words in scanner's RAM
* ie registers 42-43-44
@@ -481,7 +366,7 @@ void wait_until_has_valid_words(Genesys_Device* dev)
unsigned words = 0;
unsigned sleep_time_ms = 10;
- for (unsigned wait_ms = 0; wait_ms < 50000; wait_ms += sleep_time_ms) {
+ for (unsigned wait_ms = 0; wait_ms < 70000; wait_ms += sleep_time_ms) {
sanei_genesys_read_valid_words(dev, &words);
if (words != 0)
break;
@@ -516,7 +401,7 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession&
dev->model->line_mode_color_order);
auto width = get_pixels_from_row_bytes(format, session.output_line_bytes_raw);
- auto height = session.output_line_count * (dev->model->is_cis ? session.params.channels : 1);
+ auto height = session.optical_line_count;
Image image(width, height, format);
@@ -525,7 +410,7 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession&
throw SaneException("Trying to read too much data %zu (max %zu)", total_bytes, max_bytes);
}
if (total_bytes != max_bytes) {
- DBG(DBG_info, "WARNING %s: trying to read not enough data (%zu, full fill %zu\n", __func__,
+ DBG(DBG_info, "WARNING %s: trying to read not enough data (%zu, full fill %zu)\n", __func__,
total_bytes, max_bytes);
}
@@ -534,26 +419,138 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession&
ImagePipelineStack pipeline;
pipeline.push_first_node<ImagePipelineNodeImageSource>(image);
- if ((dev->model->flags & GENESYS_FLAG_16BIT_DATA_INVERTED) && session.params.depth == 16) {
- dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
+ if (session.segment_count > 1) {
+ auto output_width = session.output_segment_pixel_group_count * session.segment_count;
+ pipeline.push_node<ImagePipelineNodeDesegment>(output_width, dev->segment_order,
+ session.conseq_pixel_dist,
+ 1, 1);
}
+ if (session.params.depth == 16) {
+ unsigned num_swaps = 0;
+ if (has_flag(dev->model->flags, ModelFlag::SWAP_16BIT_DATA)) {
+ num_swaps++;
+ }
#ifdef WORDS_BIGENDIAN
- if (depth == 16) {
- dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
+ num_swaps++;
+#endif
+ if (num_swaps % 2 != 0) {
+ dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
+ }
}
+
+ if (has_flag(dev->model->flags, ModelFlag::INVERT_PIXEL_DATA)) {
+ pipeline.push_node<ImagePipelineNodeInvert>();
+ }
+
+ if (dev->model->is_cis && session.params.channels == 3) {
+ pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
+ }
+
+ if (pipeline.get_output_format() == PixelFormat::BGR888) {
+ pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB888);
+ }
+
+ if (pipeline.get_output_format() == PixelFormat::BGR161616) {
+ pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
+ }
+
+ return pipeline.get_image();
+}
+
+
+Image read_shuffled_image_from_scanner(Genesys_Device* dev, const ScanSession& session)
+{
+ DBG_HELPER(dbg);
+
+ std::size_t total_bytes = 0;
+ std::size_t pixels_per_line = 0;
+
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843 ||
+ dev->model->model_id == ModelId::CANON_5600F)
+ {
+ pixels_per_line = session.output_pixels;
+ } else {
+ // BUG: this selects incorrect pixel number
+ pixels_per_line = session.params.pixels;
+ }
+
+ // FIXME: the current calculation is likely incorrect on non-GL843 implementations,
+ // but this needs checking. Note the extra line when computing size.
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843 ||
+ dev->model->model_id == ModelId::CANON_5600F)
+ {
+ total_bytes = session.output_total_bytes_raw;
+ } else {
+ total_bytes = session.params.channels * 2 * pixels_per_line * (session.params.lines + 1);
+ }
+
+ auto format = create_pixel_format(session.params.depth,
+ dev->model->is_cis ? 1 : session.params.channels,
+ dev->model->line_mode_color_order);
+
+ // auto width = get_pixels_from_row_bytes(format, session.output_line_bytes_raw);
+ auto width = pixels_per_line;
+ auto height = session.params.lines + 1; // BUG: incorrect
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843 ||
+ dev->model->model_id == ModelId::CANON_5600F)
+ {
+ height = session.optical_line_count;
+ }
+
+ Image image(width, height, format);
+
+ auto max_bytes = image.get_row_bytes() * height;
+ if (total_bytes > max_bytes) {
+ throw SaneException("Trying to read too much data %zu (max %zu)", total_bytes, max_bytes);
+ }
+ if (total_bytes != max_bytes) {
+ DBG(DBG_info, "WARNING %s: trying to read not enough data (%zu, full fill %zu)\n", __func__,
+ total_bytes, max_bytes);
+ }
+
+ sanei_genesys_read_data_from_scanner(dev, image.get_row_ptr(0), total_bytes);
+
+ ImagePipelineStack pipeline;
+ pipeline.push_first_node<ImagePipelineNodeImageSource>(image);
+
+ if (session.segment_count > 1) {
+ auto output_width = session.output_segment_pixel_group_count * session.segment_count;
+ pipeline.push_node<ImagePipelineNodeDesegment>(output_width, dev->segment_order,
+ session.conseq_pixel_dist,
+ 1, 1);
+ }
+
+ if (session.params.depth == 16) {
+ unsigned num_swaps = 0;
+ if (has_flag(dev->model->flags, ModelFlag::SWAP_16BIT_DATA)) {
+ num_swaps++;
+ }
+#ifdef WORDS_BIGENDIAN
+ num_swaps++;
#endif
+ if (num_swaps % 2 != 0) {
+ dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
+ }
+ }
+
+ if (has_flag(dev->model->flags, ModelFlag::INVERT_PIXEL_DATA)) {
+ pipeline.push_node<ImagePipelineNodeInvert>();
+ }
if (dev->model->is_cis && session.params.channels == 3) {
- dev->pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
+ pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
}
- if (dev->pipeline.get_output_format() == PixelFormat::BGR888) {
- dev->pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB888);
+ if (pipeline.get_output_format() == PixelFormat::BGR888) {
+ pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB888);
}
- if (dev->pipeline.get_output_format() == PixelFormat::BGR161616) {
- dev->pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
+ if (pipeline.get_output_format() == PixelFormat::BGR161616) {
+ pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
}
return pipeline.get_image();
@@ -600,34 +597,27 @@ void sanei_genesys_set_lamp_power(Genesys_Device* dev, const Genesys_Sensor& sen
if (dev->model->asic_type == AsicType::GL843) {
regs_set_exposure(dev->model->asic_type, regs, sensor.exposure);
+ }
- // we don't actually turn on lamp on infrared scan
- if ((dev->model->model_id == ModelId::CANON_8400F ||
- dev->model->model_id == ModelId::CANON_8600F ||
- dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
- dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I) &&
- dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
- {
- regs.find_reg(0x03).value &= ~REG_0x03_LAMPPWR;
- }
+ // we don't actually turn on lamp on infrared scan
+ if ((dev->model->model_id == ModelId::CANON_8400F ||
+ dev->model->model_id == ModelId::CANON_8600F ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I) &&
+ dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
+ {
+ regs.find_reg(0x03).value &= ~REG_0x03_LAMPPWR;
}
} else {
regs.find_reg(0x03).value &= ~REG_0x03_LAMPPWR;
if (dev->model->asic_type == AsicType::GL841) {
- regs_set_exposure(dev->model->asic_type, regs, {0x0101, 0x0101, 0x0101});
+ regs_set_exposure(dev->model->asic_type, regs, sanei_genesys_fixup_exposure({0, 0, 0}));
regs.set8(0x19, 0xff);
}
-
- if (dev->model->asic_type == AsicType::GL843) {
- if (dev->model->model_id == ModelId::PANASONIC_KV_SS080 ||
- dev->model->model_id == ModelId::HP_SCANJET_4850C ||
- dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
- dev->model->model_id == ModelId::HP_SCANJET_G4050)
- {
- // BUG: datasheet says we shouldn't set exposure to zero
- regs_set_exposure(dev->model->asic_type, regs, {0, 0, 0});
- }
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ regs_set_exposure(dev->model->asic_type, regs, sanei_genesys_fixup_exposure({0, 0, 0}));
}
}
regs.state.is_lamp_on = set;
@@ -786,218 +776,144 @@ void sanei_genesys_send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& s
}
}
-static unsigned align_int_up(unsigned num, unsigned alignment)
-{
- unsigned mask = alignment - 1;
- if (num & mask)
- num = (num & ~mask) + alignment;
- return num;
-}
-
-void compute_session_buffer_sizes(AsicType asic, ScanSession& s)
+void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
+ const Genesys_Sensor& sensor)
{
- size_t line_bytes = s.output_line_bytes;
- size_t line_bytes_stagger = s.output_line_bytes;
-
- if (asic != AsicType::GL646) {
- // BUG: this is historical artifact and should be removed. Note that buffer sizes affect
- // how often we request the scanner for data and thus change the USB traffic.
- line_bytes_stagger =
- multiply_by_depth_ceil(s.optical_pixels, s.params.depth) * s.params.channels;
- }
-
- struct BufferConfig {
- size_t* result_size = nullptr;
- size_t lines = 0;
- size_t lines_mult = 0;
- size_t max_size = 0; // does not apply if 0
- size_t stagger_lines = 0;
-
- BufferConfig() = default;
- BufferConfig(std::size_t* rs, std::size_t l, std::size_t lm, std::size_t ms,
- std::size_t sl) :
- result_size{rs},
- lines{l},
- lines_mult{lm},
- max_size{ms},
- stagger_lines{sl}
- {}
- };
+ if (dev->model->asic_type == AsicType::GL646) {
+ s.pixel_startx += s.output_startx * sensor.full_resolution / s.params.xres;
+ s.pixel_endx = s.pixel_startx + s.optical_pixels * s.full_resolution / s.optical_resolution;
- std::array<BufferConfig, 4> configs;
- if (asic == AsicType::GL124 || asic == AsicType::GL843) {
- configs = { {
- { &s.buffer_size_read, 32, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
- { &s.buffer_size_lines, 32, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
- { &s.buffer_size_shrink, 16, 1, 0, 0 },
- { &s.buffer_size_out, 8, 1, 0, 0 },
- } };
- } else if (asic == AsicType::GL841) {
- size_t max_buf = sanei_genesys_get_bulk_max_size(asic);
- configs = { {
- { &s.buffer_size_read, 8, 2, max_buf, s.max_color_shift_lines + s.num_staggered_lines },
- { &s.buffer_size_lines, 8, 2, max_buf, s.max_color_shift_lines + s.num_staggered_lines },
- { &s.buffer_size_shrink, 8, 1, max_buf, 0 },
- { &s.buffer_size_out, 8, 1, 0, 0 },
- } };
- } else {
- configs = { {
- { &s.buffer_size_read, 16, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
- { &s.buffer_size_lines, 16, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
- { &s.buffer_size_shrink, 8, 1, 0, 0 },
- { &s.buffer_size_out, 8, 1, 0, 0 },
- } };
- }
-
- for (BufferConfig& config : configs) {
- size_t buf_size = line_bytes * config.lines;
- if (config.max_size > 0 && buf_size > config.max_size) {
- buf_size = (config.max_size / line_bytes) * line_bytes;
+ } else if (dev->model->asic_type == AsicType::GL841 ||
+ dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843 ||
+ dev->model->asic_type == AsicType::GL845 ||
+ dev->model->asic_type == AsicType::GL846 ||
+ dev->model->asic_type == AsicType::GL847)
+ {
+ unsigned startx_xres = s.optical_resolution;
+ if (dev->model->model_id == ModelId::CANON_5600F ||
+ dev->model->model_id == ModelId::CANON_LIDE_90)
+ {
+ if (s.output_resolution == 1200) {
+ startx_xres /= 2;
+ }
+ if (s.output_resolution >= 2400) {
+ startx_xres /= 4;
+ }
}
- buf_size *= config.lines_mult;
- buf_size += line_bytes_stagger * config.stagger_lines;
- *config.result_size = buf_size;
- }
-}
-
-void compute_session_pipeline(const Genesys_Device* dev, ScanSession& s)
-{
- auto channels = s.params.channels;
- auto depth = s.params.depth;
+ s.pixel_startx = (s.output_startx * startx_xres) / s.params.xres;
+ s.pixel_endx = s.pixel_startx + s.optical_pixels_raw;
- s.pipeline_needs_reorder = true;
- if (channels != 3 && depth != 16) {
- s.pipeline_needs_reorder = false;
- }
-#ifndef WORDS_BIGENDIAN
- if (channels != 3 && depth == 16) {
- s.pipeline_needs_reorder = false;
- }
- if (channels == 3 && depth == 16 && !dev->model->is_cis &&
- dev->model->line_mode_color_order == ColorOrder::RGB)
+ } else if (dev->model->asic_type == AsicType::GL124)
{
- s.pipeline_needs_reorder = false;
+ s.pixel_startx = s.output_startx * sensor.full_resolution / s.params.xres;
+ s.pixel_endx = s.pixel_startx + s.optical_pixels_raw;
}
-#endif
- if (channels == 3 && depth == 8 && !dev->model->is_cis &&
- dev->model->line_mode_color_order == ColorOrder::RGB)
+
+ // align pixels to correct boundary for unstaggering
+ unsigned needed_x_alignment = std::max(s.stagger_x.size(), s.stagger_y.size());
+ unsigned aligned_pixel_startx = align_multiple_floor(s.pixel_startx, needed_x_alignment);
+ s.pixel_endx -= s.pixel_startx - aligned_pixel_startx;
+ s.pixel_startx = aligned_pixel_startx;
+
+ s.pixel_startx = sensor.pixel_count_ratio.apply(s.pixel_startx);
+ s.pixel_endx = sensor.pixel_count_ratio.apply(s.pixel_endx);
+
+ if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
+ dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
{
- s.pipeline_needs_reorder = false;
+ s.pixel_startx = align_multiple_floor(s.pixel_startx, sensor.pixel_count_ratio.divisor());
+ s.pixel_endx = align_multiple_floor(s.pixel_endx, sensor.pixel_count_ratio.divisor());
}
- s.pipeline_needs_ccd = s.max_color_shift_lines + s.num_staggered_lines > 0;
- s.pipeline_needs_shrink = dev->settings.requested_pixels != s.output_pixels;
}
-void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
- const Genesys_Sensor& sensor)
+unsigned session_adjust_output_pixels(unsigned output_pixels,
+ const Genesys_Device& dev, const Genesys_Sensor& sensor,
+ unsigned output_xresolution, unsigned output_yresolution,
+ bool adjust_output_pixels)
{
- unsigned ccd_pixels_per_system_pixel = sensor.ccd_pixels_per_system_pixel();
-
- if (dev->model->asic_type == AsicType::GL646) {
-
- // startx cannot be below dummy pixel value
- s.pixel_startx = sensor.dummy_pixel;
- if (has_flag(s.params.flags, ScanFlag::USE_XCORRECTION) && sensor.ccd_start_xoffset > 0) {
- s.pixel_startx = sensor.ccd_start_xoffset;
- }
- s.pixel_startx += s.params.startx;
-
- if (sensor.stagger_config.stagger_at_resolution(s.params.xres, s.params.yres) > 0) {
- s.pixel_startx |= 1;
- }
-
- s.pixel_endx = s.pixel_startx + s.optical_pixels;
-
- s.pixel_startx /= sensor.ccd_pixels_per_system_pixel() * s.ccd_size_divisor;
- s.pixel_endx /= sensor.ccd_pixels_per_system_pixel() * s.ccd_size_divisor;
-
- } else if (dev->model->asic_type == AsicType::GL841) {
- s.pixel_startx = ((sensor.ccd_start_xoffset + s.params.startx) * s.optical_resolution)
- / sensor.optical_res;
+ bool adjust_optical_pixels = !adjust_output_pixels;
+ if (dev.model->model_id == ModelId::CANON_5600F) {
+ adjust_optical_pixels = true;
+ adjust_output_pixels = true;
+ }
+ if (adjust_optical_pixels) {
+ auto optical_resolution = sensor.get_optical_resolution();
- s.pixel_startx += sensor.dummy_pixel + 1;
+ // FIXME: better way would be to compute and return the required multiplier
+ unsigned optical_pixels = (output_pixels * optical_resolution) / output_xresolution;
- if (s.num_staggered_lines > 0 && (s.pixel_startx & 1) == 0) {
- s.pixel_startx++;
+ if (dev.model->asic_type == AsicType::GL841 ||
+ dev.model->asic_type == AsicType::GL842)
+ {
+ optical_pixels = align_multiple_ceil(optical_pixels, 2);
}
- /* In case of SHDAREA, we need to align start on pixel average factor, startx is
- different than 0 only when calling for function to setup for scan, where shading data
- needs to be align.
-
- NOTE: we can check the value of the register here, because we don't set this bit
- anywhere except in initialization.
- */
- const uint8_t REG_0x01_SHDAREA = 0x02;
- if ((dev->reg.find_reg(0x01).value & REG_0x01_SHDAREA) != 0) {
- unsigned average_factor = s.optical_resolution / s.params.xres;
- s.pixel_startx = align_multiple_floor(s.pixel_startx, average_factor);
+ if (dev.model->asic_type == AsicType::GL646 && output_xresolution == 400) {
+ optical_pixels = align_multiple_floor(optical_pixels, 6);
}
- s.pixel_endx = s.pixel_startx + s.optical_pixels;
-
- } else if (dev->model->asic_type == AsicType::GL843) {
-
- s.pixel_startx = (s.params.startx + sensor.dummy_pixel) / ccd_pixels_per_system_pixel;
- s.pixel_endx = s.pixel_startx + s.optical_pixels / ccd_pixels_per_system_pixel;
-
- s.pixel_startx /= s.hwdpi_divisor;
- s.pixel_endx /= s.hwdpi_divisor;
-
- // in case of stagger we have to start at an odd coordinate
- bool stagger_starts_even = dev->model->model_id == ModelId::CANON_8400F;
- if (s.num_staggered_lines > 0) {
- if (!stagger_starts_even && (s.pixel_startx & 1) == 0) {
- s.pixel_startx++;
- s.pixel_endx++;
- } else if (stagger_starts_even && (s.pixel_startx & 1) != 0) {
- s.pixel_startx++;
- s.pixel_endx++;
+ if (dev.model->asic_type == AsicType::GL843) {
+ // ensure the number of optical pixels is divisible by 2.
+ // In quarter-CCD mode optical_pixels is 4x larger than the actual physical number
+ optical_pixels = align_multiple_ceil(optical_pixels,
+ 2 * sensor.full_resolution / optical_resolution);
+ if (dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200 ||
+ dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
+ dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
+ dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7400 ||
+ dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I ||
+ dev.model->model_id == ModelId::PLUSTEK_OPTICFILM_8200I)
+ {
+ optical_pixels = align_multiple_ceil(optical_pixels, 16);
}
}
+ output_pixels = (optical_pixels * output_xresolution) / optical_resolution;
+ }
- } else if (dev->model->asic_type == AsicType::GL845 ||
- dev->model->asic_type == AsicType::GL846 ||
- dev->model->asic_type == AsicType::GL847)
- {
- s.pixel_startx = s.params.startx;
-
- if (s.num_staggered_lines > 0) {
- s.pixel_startx |= 1;
- }
-
- s.pixel_startx += sensor.ccd_start_xoffset * ccd_pixels_per_system_pixel;
- s.pixel_endx = s.pixel_startx + s.optical_pixels_raw;
-
- s.pixel_startx /= s.hwdpi_divisor * s.segment_count * ccd_pixels_per_system_pixel;
- s.pixel_endx /= s.hwdpi_divisor * s.segment_count * ccd_pixels_per_system_pixel;
-
- } else if (dev->model->asic_type == AsicType::GL124) {
- s.pixel_startx = s.params.startx;
+ if (adjust_output_pixels) {
+ // TODO: the following may no longer be needed but were applied historically.
- if (s.num_staggered_lines > 0) {
- s.pixel_startx |= 1;
+ // we need an even pixels number
+ // TODO invert test logic or generalize behaviour across all ASICs
+ if (has_flag(dev.model->flags, ModelFlag::SIS_SENSOR) ||
+ dev.model->asic_type == AsicType::GL847 ||
+ dev.model->asic_type == AsicType::GL124 ||
+ dev.model->asic_type == AsicType::GL845 ||
+ dev.model->asic_type == AsicType::GL846 ||
+ dev.model->asic_type == AsicType::GL843)
+ {
+ if (output_xresolution <= 1200) {
+ output_pixels = align_multiple_floor(output_pixels, 4);
+ } else if (output_xresolution < output_yresolution) {
+ // BUG: this is an artifact of the fact that the resolution was twice as large than
+ // the actual resolution when scanning above the supported scanner X resolution
+ output_pixels = align_multiple_floor(output_pixels, 8);
+ } else {
+ output_pixels = align_multiple_floor(output_pixels, 16);
+ }
}
- s.pixel_startx /= ccd_pixels_per_system_pixel;
- // FIXME: should we add sensor.dummy_pxel to pixel_startx at this point?
- s.pixel_endx = s.pixel_startx + s.optical_pixels / ccd_pixels_per_system_pixel;
-
- s.pixel_startx /= s.hwdpi_divisor * s.segment_count;
- s.pixel_endx /= s.hwdpi_divisor * s.segment_count;
-
- std::uint32_t segcnt = (sensor.custom_regs.get_value(gl124::REG_SEGCNT) << 16) +
- (sensor.custom_regs.get_value(gl124::REG_SEGCNT + 1) << 8) +
- sensor.custom_regs.get_value(gl124::REG_SEGCNT + 2);
- if (s.pixel_endx == segcnt) {
- s.pixel_endx = 0;
+ // corner case for true lineart for sensor with several segments or when xres is doubled
+ // to match yres */
+ if (output_xresolution >= 1200 && (
+ dev.model->asic_type == AsicType::GL124 ||
+ dev.model->asic_type == AsicType::GL847 ||
+ dev.session.params.xres < dev.session.params.yres))
+ {
+ if (output_xresolution < output_yresolution) {
+ // FIXME: this is an artifact of the fact that the resolution was twice as large than
+ // the actual resolution when scanning above the supported scanner X resolution
+ output_pixels = align_multiple_floor(output_pixels, 8);
+ } else {
+ output_pixels = align_multiple_floor(output_pixels, 16);
+ }
}
}
- s.pixel_count_multiplier = sensor.pixel_count_multiplier;
-
- s.pixel_startx *= sensor.pixel_count_multiplier;
- s.pixel_endx *= sensor.pixel_count_multiplier;
+ return output_pixels;
}
void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Sensor& sensor)
@@ -1011,68 +927,36 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
throw SaneException("Unsupported depth setting %d", s.params.depth);
}
- unsigned ccd_pixels_per_system_pixel = sensor.ccd_pixels_per_system_pixel();
-
// compute optical and output resolutions
-
- if (dev->model->asic_type == AsicType::GL843) {
- // FIXME: this may be incorrect, but need more scanners to test
- s.hwdpi_divisor = sensor.get_hwdpi_divisor_for_dpi(s.params.xres);
- } else {
- s.hwdpi_divisor = sensor.get_hwdpi_divisor_for_dpi(s.params.xres * ccd_pixels_per_system_pixel);
- }
-
- s.ccd_size_divisor = sensor.get_ccd_size_divisor_for_dpi(s.params.xres);
-
- if (dev->model->asic_type == AsicType::GL646) {
- s.optical_resolution = sensor.optical_res;
- } else {
- s.optical_resolution = sensor.optical_res / s.ccd_size_divisor;
- }
+ s.full_resolution = sensor.full_resolution;
+ s.optical_resolution = sensor.get_optical_resolution();
s.output_resolution = s.params.xres;
+ s.pixel_count_ratio = sensor.pixel_count_ratio;
+
if (s.output_resolution > s.optical_resolution) {
throw std::runtime_error("output resolution higher than optical resolution");
}
- // compute the number of optical pixels that will be acquired by the chip
- s.optical_pixels = (s.params.pixels * s.optical_resolution) / s.output_resolution;
- if (s.optical_pixels * s.output_resolution < s.params.pixels * s.optical_resolution) {
- s.optical_pixels++;
- }
-
- if (dev->model->asic_type == AsicType::GL841) {
- if (s.optical_pixels & 1)
- s.optical_pixels++;
- }
-
- if (dev->model->asic_type == AsicType::GL646 && s.params.xres == 400) {
- s.optical_pixels = (s.optical_pixels / 6) * 6;
- }
+ s.output_pixels = session_adjust_output_pixels(s.params.pixels, *dev, sensor,
+ s.params.xres, s.params.yres, false);
- if (dev->model->asic_type == AsicType::GL843) {
- // ensure the number of optical pixels is divisible by 2.
- // In quarter-CCD mode optical_pixels is 4x larger than the actual physical number
- s.optical_pixels = align_int_up(s.optical_pixels, 2 * s.ccd_size_divisor);
+ // Compute the number of optical pixels that will be acquired by the chip.
+ // The necessary alignment requirements have already been computed by
+ // get_session_output_pixels_multiplier
+ s.optical_pixels = (s.output_pixels * s.optical_resolution) / s.output_resolution;
- if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200I ||
- dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7300 ||
- dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7500I)
- {
- s.optical_pixels = align_int_up(s.optical_pixels, 16);
- }
- }
+ if (static_cast<int>(s.params.startx) + sensor.output_pixel_offset < 0)
+ throw SaneException("Invalid sensor.output_pixel_offset");
+ s.output_startx = static_cast<unsigned>(
+ static_cast<int>(s.params.startx) + sensor.output_pixel_offset);
- // after all adjustments on the optical pixels have been made, compute the number of pixels
- // to retrieve from the chip
- s.output_pixels = (s.optical_pixels * s.output_resolution) / s.optical_resolution;
+ s.stagger_x = sensor.stagger_x;
+ s.stagger_y = sensor.stagger_y;
- // Note: staggering is not applied for calibration. Staggering starts at 2400 dpi
s.num_staggered_lines = 0;
- if (!has_flag(s.params.flags, ScanFlag::IGNORE_LINE_DISTANCE))
- {
- s.num_staggered_lines = sensor.stagger_config.stagger_at_resolution(s.params.xres,
- s.params.yres);
+ if (!has_flag(s.params.flags, ScanFlag::IGNORE_STAGGER_OFFSET)) {
+ s.num_staggered_lines = s.stagger_y.max_shift() * s.params.yres / s.params.xres;
}
s.color_shift_lines_r = dev->model->ld_shift_r;
@@ -1091,12 +975,14 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
s.color_shift_lines_b = (s.color_shift_lines_b * s.params.yres) / dev->motor.base_ydpi;
s.max_color_shift_lines = 0;
- if (s.params.channels > 1 && !has_flag(s.params.flags, ScanFlag::IGNORE_LINE_DISTANCE)) {
+ if (s.params.channels > 1 && !has_flag(s.params.flags, ScanFlag::IGNORE_COLOR_OFFSET)) {
s.max_color_shift_lines = std::max(s.color_shift_lines_r, std::max(s.color_shift_lines_g,
s.color_shift_lines_b));
}
s.output_line_count = s.params.lines + s.max_color_shift_lines + s.num_staggered_lines;
+ s.optical_line_count = dev->model->is_cis ? s.output_line_count * s.params.channels
+ : s.output_line_count;
s.output_channel_bytes = multiply_by_depth_ceil(s.output_pixels, s.params.depth);
s.output_line_bytes = s.output_channel_bytes * s.params.channels;
@@ -1107,29 +993,62 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
s.output_line_bytes_raw = s.output_line_bytes;
s.conseq_pixel_dist = 0;
- if (dev->model->asic_type == AsicType::GL845 ||
- dev->model->asic_type == AsicType::GL846 ||
- dev->model->asic_type == AsicType::GL847)
+ // FIXME: Use ModelFlag::SIS_SENSOR
+ if ((dev->model->asic_type == AsicType::GL845 ||
+ dev->model->asic_type == AsicType::GL846 ||
+ dev->model->asic_type == AsicType::GL847) &&
+ dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_7400 &&
+ dev->model->model_id != ModelId::PLUSTEK_OPTICFILM_8200I)
{
if (s.segment_count > 1) {
s.conseq_pixel_dist = sensor.segment_size;
- // in case of multi-segments sensor, we have to add the width of the sensor crossed by
- // the scan area
- unsigned extra_segment_scan_area = align_multiple_ceil(s.conseq_pixel_dist, 2);
- extra_segment_scan_area *= s.segment_count - 1;
- extra_segment_scan_area *= s.hwdpi_divisor * s.segment_count;
- extra_segment_scan_area *= ccd_pixels_per_system_pixel;
+ // in case of multi-segments sensor, we have expand the scan area to sensor boundary
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ unsigned startx_xres = s.optical_resolution;
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ if (s.output_resolution == 1200) {
+ startx_xres /= 2;
+ }
+ if (s.output_resolution >= 2400) {
+ startx_xres /= 4;
+ }
+ }
+ unsigned optical_startx = s.output_startx * startx_xres / s.params.xres;
+ unsigned optical_endx = optical_startx + s.optical_pixels;
- s.optical_pixels_raw += extra_segment_scan_area;
+ unsigned multi_segment_size_output = s.segment_count * s.conseq_pixel_dist;
+ unsigned multi_segment_size_optical =
+ (multi_segment_size_output * s.optical_resolution) / s.output_resolution;
+
+ optical_endx = align_multiple_ceil(optical_endx, multi_segment_size_optical);
+ s.optical_pixels_raw = optical_endx - optical_startx;
+ s.optical_pixels_raw = align_multiple_floor(s.optical_pixels_raw,
+ 4 * s.optical_resolution / s.output_resolution);
+ } else {
+ // BUG: the following code will likely scan too much. Use the CANON_5600F approach
+ unsigned extra_segment_scan_area = align_multiple_ceil(s.conseq_pixel_dist, 2);
+ extra_segment_scan_area *= s.segment_count - 1;
+ extra_segment_scan_area = s.pixel_count_ratio.apply_inverse(extra_segment_scan_area);
+
+ s.optical_pixels_raw += extra_segment_scan_area;
+ }
}
- s.output_line_bytes_raw = multiply_by_depth_ceil(
- (s.optical_pixels_raw * s.output_resolution) / sensor.optical_res / s.segment_count,
- s.params.depth);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ auto output_pixels_raw = (s.optical_pixels_raw * s.output_resolution) / s.optical_resolution;
+ auto output_channel_bytes_raw = multiply_by_depth_ceil(output_pixels_raw, s.params.depth);
+ s.output_line_bytes_raw = output_channel_bytes_raw * s.params.channels;
+ } else {
+ s.output_line_bytes_raw = multiply_by_depth_ceil(
+ (s.optical_pixels_raw * s.output_resolution) / sensor.full_resolution / s.segment_count,
+ s.params.depth);
+ }
}
- if (dev->model->asic_type == AsicType::GL841) {
+ if (dev->model->asic_type == AsicType::GL841 ||
+ dev->model->asic_type == AsicType::GL842)
+ {
if (dev->model->is_cis) {
s.output_line_bytes_raw = s.output_channel_bytes;
}
@@ -1139,27 +1058,43 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
if (dev->model->is_cis) {
s.output_line_bytes_raw = s.output_channel_bytes;
}
- s.conseq_pixel_dist = s.output_pixels / s.ccd_size_divisor / s.segment_count;
+ s.conseq_pixel_dist = s.output_pixels / (s.full_resolution / s.optical_resolution) / s.segment_count;
}
- if (dev->model->asic_type == AsicType::GL843) {
- s.conseq_pixel_dist = s.output_pixels / s.segment_count;
+ if (dev->model->asic_type == AsicType::GL842 ||
+ dev->model->asic_type == AsicType::GL843)
+ {
+ if (dev->model->is_cis) {
+ if (s.segment_count > 1) {
+ s.conseq_pixel_dist = sensor.segment_size;
+ }
+ } else {
+ s.conseq_pixel_dist = s.output_pixels / s.segment_count;
+ }
}
s.output_segment_pixel_group_count = 0;
if (dev->model->asic_type == AsicType::GL124 ||
+ dev->model->asic_type == AsicType::GL842 ||
dev->model->asic_type == AsicType::GL843)
{
- s.output_segment_pixel_group_count = multiply_by_depth_ceil(
- s.output_pixels / s.ccd_size_divisor / s.segment_count, s.params.depth);
+ s.output_segment_pixel_group_count = s.output_pixels /
+ (s.full_resolution / s.optical_resolution * s.segment_count);
}
+
+ if (dev->model->model_id == ModelId::CANON_LIDE_90) {
+ s.output_segment_pixel_group_count = s.output_pixels / s.segment_count;
+ }
+
if (dev->model->asic_type == AsicType::GL845 ||
dev->model->asic_type == AsicType::GL846 ||
dev->model->asic_type == AsicType::GL847)
{
- s.output_segment_pixel_group_count = multiply_by_depth_ceil(
- s.optical_pixels / (s.hwdpi_divisor * s.segment_count * ccd_pixels_per_system_pixel),
- s.params.depth);
+ if (dev->model->model_id == ModelId::CANON_5600F) {
+ s.output_segment_pixel_group_count = s.output_pixels / s.segment_count;
+ } else {
+ s.output_segment_pixel_group_count = s.pixel_count_ratio.apply(s.optical_pixels);
+ }
}
s.output_line_bytes_requested = multiply_by_depth_ceil(
@@ -1167,11 +1102,16 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
s.output_total_bytes_raw = s.output_line_bytes_raw * s.output_line_count;
s.output_total_bytes = s.output_line_bytes * s.output_line_count;
+ if (dev->model->model_id == ModelId::CANON_LIDE_90) {
+ s.output_total_bytes_raw *= s.params.channels;
+ s.output_total_bytes *= s.params.channels;
+ }
- compute_session_buffer_sizes(dev->model->asic_type, s);
- compute_session_pipeline(dev, s);
+ s.buffer_size_read = s.output_line_bytes_raw * 64;
compute_session_pixel_offsets(dev, s, sensor);
+ s.shading_pixel_offset = sensor.shading_pixel_offset;
+
if (dev->model->asic_type == AsicType::GL124 ||
dev->model->asic_type == AsicType::GL845 ||
dev->model->asic_type == AsicType::GL846)
@@ -1179,7 +1119,10 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
s.enable_ledadd = (s.params.channels == 1 && dev->model->is_cis && dev->settings.true_gray);
}
+ s.use_host_side_calib = sensor.use_host_side_calib;
+
if (dev->model->asic_type == AsicType::GL841 ||
+ dev->model->asic_type == AsicType::GL842 ||
dev->model->asic_type == AsicType::GL843)
{
// no 16 bit gamma for this ASIC
@@ -1194,177 +1137,166 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
debug_dump(DBG_info, s);
}
-static std::size_t get_usb_buffer_read_size(AsicType asic, const ScanSession& session)
+ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSession& session,
+ unsigned pipeline_index, bool log_image_data)
{
- switch (asic) {
- case AsicType::GL646:
- // buffer not used on this chip set
- return 1;
-
- case AsicType::GL124:
- // BUG: we shouldn't multiply by channels here nor divide by ccd_size_divisor
- return session.output_line_bytes_raw / session.ccd_size_divisor * session.params.channels;
-
- case AsicType::GL845:
- case AsicType::GL846:
- case AsicType::GL847:
- // BUG: we shouldn't multiply by channels here
- return session.output_line_bytes_raw * session.params.channels;
-
- case AsicType::GL843:
- return session.output_line_bytes_raw * 2;
-
- default:
- throw SaneException("Unknown asic type");
- }
-}
-
-static FakeBufferModel get_fake_usb_buffer_model(const ScanSession& session)
-{
- FakeBufferModel model;
- model.push_step(session.buffer_size_read, 1);
-
- if (session.pipeline_needs_reorder) {
- model.push_step(session.buffer_size_lines, session.output_line_bytes);
- }
- if (session.pipeline_needs_ccd) {
- model.push_step(session.buffer_size_shrink, session.output_line_bytes);
- }
- if (session.pipeline_needs_shrink) {
- model.push_step(session.buffer_size_out, session.output_line_bytes);
- }
-
- return model;
-}
-
-void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
-{
- static unsigned s_pipeline_index = 0;
-
- s_pipeline_index++;
-
auto format = create_pixel_format(session.params.depth,
- dev->model->is_cis ? 1 : session.params.channels,
- dev->model->line_mode_color_order);
+ dev.model->is_cis ? 1 : session.params.channels,
+ dev.model->line_mode_color_order);
auto depth = get_pixel_format_depth(format);
auto width = get_pixels_from_row_bytes(format, session.output_line_bytes_raw);
- auto read_data_from_usb = [dev](std::size_t size, std::uint8_t* data)
+ auto read_data_from_usb = [&dev](std::size_t size, std::uint8_t* data)
{
- dev->interface->bulk_read_data(0x45, data, size);
+ DBG(DBG_info, "read_data_from_usb: reading %zu bytes\n", size);
+ auto begin = std::chrono::high_resolution_clock::now();
+ dev.interface->bulk_read_data(0x45, data, size);
+ auto end = std::chrono::high_resolution_clock::now();
+ float us = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
+ float speed = size / us; // bytes/us == MB/s
+ DBG(DBG_info, "read_data_from_usb: reading %zu bytes finished %f MB/s\n", size, speed);
return true;
};
- auto lines = session.output_line_count * (dev->model->is_cis ? session.params.channels : 1);
+ auto debug_prefix = "gl_pipeline_" + std::to_string(pipeline_index);
- dev->pipeline.clear();
+ ImagePipelineStack pipeline;
- // FIXME: here we are complicating things for the time being to preserve the existing behaviour
- // This allows to be sure that the changes to the image pipeline have not introduced
- // regressions.
+ auto lines = session.optical_line_count;
+ auto buffer_size = session.buffer_size_read;
- if (session.segment_count > 1) {
- // BUG: we're reading one line too much
- dev->pipeline.push_first_node<ImagePipelineNodeBufferedCallableSource>(
- width, lines + 1, format,
- get_usb_buffer_read_size(dev->model->asic_type, session), read_data_from_usb);
+ // At least GL841 requires reads to be aligned to 2 bytes and will fail on some devices on
+ // certain circumstances.
+ buffer_size = align_multiple_ceil(buffer_size, 2);
+
+ auto& src_node = pipeline.push_first_node<ImagePipelineNodeBufferedCallableSource>(
+ width, lines, format, buffer_size, read_data_from_usb);
+ src_node.set_last_read_multiple(2);
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_0_from_usb.tiff");
+ }
+
+ if (session.segment_count > 1) {
auto output_width = session.output_segment_pixel_group_count * session.segment_count;
- dev->pipeline.push_node<ImagePipelineNodeDesegment>(output_width, dev->segment_order,
+ pipeline.push_node<ImagePipelineNodeDesegment>(output_width, dev.segment_order,
session.conseq_pixel_dist,
1, 1);
- } else {
- auto read_bytes_left_after_deseg = session.output_line_bytes * session.output_line_count;
- if (dev->model->asic_type == AsicType::GL646) {
- read_bytes_left_after_deseg *= dev->model->is_cis ? session.params.channels : 1;
- }
- dev->pipeline.push_first_node<ImagePipelineNodeBufferedGenesysUsb>(
- width, lines, format, read_bytes_left_after_deseg,
- get_fake_usb_buffer_model(session), read_data_from_usb);
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_1_after_desegment.tiff");
+ }
}
- if (DBG_LEVEL >= DBG_io2) {
- dev->pipeline.push_node<ImagePipelineNodeDebug>("gl_pipeline_" +
- std::to_string(s_pipeline_index) +
- "_0_before_swap.pnm");
- }
+ if (depth == 16) {
+ unsigned num_swaps = 0;
+ if (has_flag(dev.model->flags, ModelFlag::SWAP_16BIT_DATA)) {
+ num_swaps++;
+ }
+#ifdef WORDS_BIGENDIAN
+ num_swaps++;
+#endif
+ if (num_swaps % 2 != 0) {
+ pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
- if ((dev->model->flags & GENESYS_FLAG_16BIT_DATA_INVERTED) && depth == 16) {
- dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_2_after_swap.tiff");
+ }
+ }
}
-#ifdef WORDS_BIGENDIAN
- if (depth == 16) {
- dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
+ if (has_flag(dev.model->flags, ModelFlag::INVERT_PIXEL_DATA)) {
+ pipeline.push_node<ImagePipelineNodeInvert>();
+
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_3_after_invert.tiff");
+ }
}
-#endif
- if (DBG_LEVEL >= DBG_io2) {
- dev->pipeline.push_node<ImagePipelineNodeDebug>("gl_pipeline_" +
- std::to_string(s_pipeline_index) +
- "_1_after_swap.pnm");
+ if (dev.model->is_cis && session.params.channels == 3) {
+ pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev.model->line_mode_color_order);
+
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_4_after_merge_mono.tiff");
+ }
}
- if (dev->model->is_cis && session.params.channels == 3) {
- dev->pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
+ if (pipeline.get_output_format() == PixelFormat::BGR888) {
+ pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB888);
}
- if (dev->pipeline.get_output_format() == PixelFormat::BGR888) {
- dev->pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB888);
+ if (pipeline.get_output_format() == PixelFormat::BGR161616) {
+ pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
}
- if (dev->pipeline.get_output_format() == PixelFormat::BGR161616) {
- dev->pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_5_after_format.tiff");
}
if (session.max_color_shift_lines > 0 && session.params.channels == 3) {
- dev->pipeline.push_node<ImagePipelineNodeComponentShiftLines>(
+ pipeline.push_node<ImagePipelineNodeComponentShiftLines>(
session.color_shift_lines_r,
session.color_shift_lines_g,
session.color_shift_lines_b);
+
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_6_after_color_unshift.tiff");
+ }
}
- if (DBG_LEVEL >= DBG_io2) {
- dev->pipeline.push_node<ImagePipelineNodeDebug>("gl_pipeline_" +
- std::to_string(s_pipeline_index) +
- "_2_after_shift.pnm");
+ if (!session.stagger_x.empty()) {
+ // FIXME: the image will be scaled to requested pixel count without regard to the reduction
+ // of image size in this step.
+ pipeline.push_node<ImagePipelineNodePixelShiftColumns>(session.stagger_x.shifts());
+
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_7_after_x_unstagger.tiff");
+ }
}
if (session.num_staggered_lines > 0) {
- std::vector<std::size_t> shifts{0, session.num_staggered_lines};
- dev->pipeline.push_node<ImagePipelineNodePixelShiftLines>(shifts);
- }
+ pipeline.push_node<ImagePipelineNodePixelShiftLines>(session.stagger_y.shifts());
- if (DBG_LEVEL >= DBG_io2) {
- dev->pipeline.push_node<ImagePipelineNodeDebug>("gl_pipeline_" +
- std::to_string(s_pipeline_index) +
- "_3_after_stagger.pnm");
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_8_after_y_unstagger.tiff");
+ }
}
- if ((dev->model->flags & GENESYS_FLAG_CALIBRATION_HOST_SIDE) &&
- !(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
+ if (session.use_host_side_calib &&
+ !has_flag(dev.model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) &&
+ !has_flag(session.params.flags, ScanFlag::DISABLE_SHADING))
{
- dev->pipeline.push_node<ImagePipelineNodeCalibrate>(dev->dark_average_data,
- dev->white_average_data);
+ unsigned offset_pixels = session.params.startx + dev.calib_session.shading_pixel_offset;
+ unsigned offset_bytes = offset_pixels * dev.calib_session.params.channels;
+ pipeline.push_node<ImagePipelineNodeCalibrate>(dev.dark_average_data,
+ dev.white_average_data, offset_bytes);
- if (DBG_LEVEL >= DBG_io2) {
- dev->pipeline.push_node<ImagePipelineNodeDebug>("gl_pipeline_" +
- std::to_string(s_pipeline_index) +
- "_4_after_calibrate.pnm");
+ if (log_image_data) {
+ pipeline.push_node<ImagePipelineNodeDebug>(debug_prefix + "_9_after_calibrate.tiff");
}
}
- if (session.output_pixels != session.params.get_requested_pixels()) {
- dev->pipeline.push_node<ImagePipelineNodeScaleRows>(session.params.get_requested_pixels());
+ if (pipeline.get_output_width() != session.params.get_requested_pixels()) {
+ pipeline.push_node<ImagePipelineNodeScaleRows>(session.params.get_requested_pixels());
}
- auto read_from_pipeline = [dev](std::size_t size, std::uint8_t* out_data)
+ return pipeline;
+}
+
+void setup_image_pipeline(Genesys_Device& dev, const ScanSession& session)
+{
+ static unsigned s_pipeline_index = 0;
+
+ s_pipeline_index++;
+
+ dev.pipeline = build_image_pipeline(dev, session, s_pipeline_index, dbg_log_image_data());
+
+ auto read_from_pipeline = [&dev](std::size_t size, std::uint8_t* out_data)
{
- (void) size; // will be always equal to dev->pipeline.get_output_row_bytes()
- return dev->pipeline.get_next_row_data(out_data);
+ (void) size; // will be always equal to dev.pipeline.get_output_row_bytes()
+ return dev.pipeline.get_next_row_data(out_data);
};
- dev->pipeline_buffer = ImageBuffer{dev->pipeline.get_output_row_bytes(),
+ dev.pipeline_buffer = ImageBuffer{dev.pipeline.get_output_row_bytes(),
read_from_pipeline};
}
@@ -1394,6 +1326,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)
@@ -1418,13 +1376,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);
- }
- if (frontend_type == FrontendType::ANALOG_DEVICES) {
- return compute_frontend_gain_analog_devices(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::ANALOG_DEVICES_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");
}
- throw SaneException("Unknown frontend to compute gain for");
}
/** @brief initialize device
@@ -1436,7 +1403,7 @@ std::uint8_t compute_frontend_gain(float value, float target_value,
* @param dev device to initialize
* @param max_regs umber of maximum used registers
*/
-void sanei_genesys_asic_init(Genesys_Device* dev, bool /*max_regs*/)
+void sanei_genesys_asic_init(Genesys_Device* dev)
{
DBG_HELPER(dbg);
@@ -1486,8 +1453,7 @@ void sanei_genesys_asic_init(Genesys_Device* dev, bool /*max_regs*/)
dev->settings.color_filter = ColorFilter::RED;
- /* duplicate initial values into calibration registers */
- dev->calib_reg = dev->reg;
+ dev->initial_regs = dev->reg;
const auto& sensor = sanei_genesys_find_sensor_any(dev);
@@ -1497,8 +1463,15 @@ void sanei_genesys_asic_init(Genesys_Device* dev, bool /*max_regs*/)
dev->already_initialized = true;
// Move to home if needed
+ if (dev->model->model_id == ModelId::CANON_8600F) {
+ if (!dev->cmd_set->is_head_home(*dev, ScanHeadId::SECONDARY)) {
+ dev->set_head_pos_unknown(ScanHeadId::SECONDARY);
+ }
+ if (!dev->cmd_set->is_head_home(*dev, ScanHeadId::PRIMARY)) {
+ dev->set_head_pos_unknown(ScanHeadId::SECONDARY);
+ }
+ }
dev->cmd_set->move_back_home(dev, true);
- dev->set_head_pos_zero(ScanHeadId::PRIMARY);
// Set powersaving (default = 15 minutes)
dev->cmd_set->set_powersaving(dev, 15);
@@ -1510,6 +1483,7 @@ void scanner_start_action(Genesys_Device& dev, bool start_motor)
switch (dev.model->asic_type) {
case AsicType::GL646:
case AsicType::GL841:
+ case AsicType::GL842:
case AsicType::GL843:
case AsicType::GL845:
case AsicType::GL846:
@@ -1527,8 +1501,7 @@ void scanner_start_action(Genesys_Device& dev, bool start_motor)
}
}
-void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, const Genesys_Sensor& sensor,
- unsigned dpihw)
+void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, unsigned dpihw)
{
// same across GL646, GL841, GL843, GL846, GL847, GL124
const uint8_t REG_0x05_DPIHW_MASK = 0xc0;
@@ -1537,10 +1510,6 @@ void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, const Genesys_Sensor& s
const uint8_t REG_0x05_DPIHW_2400 = 0x80;
const uint8_t REG_0x05_DPIHW_4800 = 0xc0;
- if (sensor.register_dpihw_override != 0) {
- dpihw = sensor.register_dpihw_override;
- }
-
uint8_t dpihw_setting;
switch (dpihw) {
case 600:
@@ -1583,6 +1552,12 @@ void regs_set_exposure(AsicType asic_type, Genesys_Register_Set& regs,
regs.set16(gl841::REG_EXPB, exposure.blue);
break;
}
+ case AsicType::GL842: {
+ regs.set16(gl842::REG_EXPR, exposure.red);
+ regs.set16(gl842::REG_EXPG, exposure.green);
+ regs.set16(gl842::REG_EXPB, exposure.blue);
+ break;
+ }
case AsicType::GL843: {
regs.set16(gl843::REG_EXPR, exposure.red);
regs.set16(gl843::REG_EXPG, exposure.green);
@@ -1619,6 +1594,10 @@ void regs_set_optical_off(AsicType asic_type, Genesys_Register_Set& regs)
regs.find_reg(gl841::REG_0x01).value &= ~gl841::REG_0x01_SCAN;
break;
}
+ case AsicType::GL842: {
+ regs.find_reg(gl842::REG_0x01).value &= ~gl842::REG_0x01_SCAN;
+ break;
+ }
case AsicType::GL843: {
regs.find_reg(gl843::REG_0x01).value &= ~gl843::REG_0x01_SCAN;
break;
@@ -1648,6 +1627,8 @@ bool get_registers_gain4_bit(AsicType asic_type, const Genesys_Register_Set& reg
return static_cast<bool>(regs.get8(gl646::REG_0x06) & gl646::REG_0x06_GAIN4);
case AsicType::GL841:
return static_cast<bool>(regs.get8(gl841::REG_0x06) & gl841::REG_0x06_GAIN4);
+ case AsicType::GL842:
+ return static_cast<bool>(regs.get8(gl842::REG_0x06) & gl842::REG_0x06_GAIN4);
case AsicType::GL843:
return static_cast<bool>(regs.get8(gl843::REG_0x06) & gl843::REG_0x06_GAIN4);
case AsicType::GL845:
@@ -1706,79 +1687,78 @@ void sanei_genesys_wait_for_home(Genesys_Device* dev)
}
}
-/** @brief motor profile
- * search for the database of motor profiles and get the best one. Each
- * profile is at full step and at a reference exposure. Use first entry
- * by default.
- * @param motors motor profile database
- * @param motor_type motor id
- * @param exposure exposure time
- * @return a pointer to a Motor_Profile struct
- */
-const Motor_Profile& sanei_genesys_get_motor_profile(const std::vector<Motor_Profile>& motors,
- MotorId motor_id, int exposure)
+const MotorProfile* get_motor_profile_ptr(const std::vector<MotorProfile>& profiles,
+ unsigned exposure,
+ const ScanSession& session)
{
- int idx;
+ int best_i = -1;
+
+ for (unsigned i = 0; i < profiles.size(); ++i) {
+ const auto& profile = profiles[i];
- idx=-1;
- for (std::size_t i = 0; i < motors.size(); ++i) {
- // exact match
- if (motors[i].motor_id == motor_id && motors[i].exposure==exposure) {
- return motors[i];
+ if (!profile.resolutions.matches(session.params.yres)) {
+ continue;
+ }
+ if (!profile.scan_methods.matches(session.params.scan_method)) {
+ continue;
}
- // closest match
- if (motors[i].motor_id == motor_id) {
- /* if profile exposure is higher than the required one,
- * the entry is a candidate for the closest match */
- if (motors[i].exposure == 0 || motors[i].exposure >= exposure)
- {
- if(idx<0)
- {
- /* no match found yet */
- idx=i;
- }
- else
- {
- /* test for better match */
- if(motors[i].exposure<motors[idx].exposure)
- {
- idx=i;
- }
+ if (profile.max_exposure == exposure) {
+ return &profile;
+ }
+
+ if (profile.max_exposure == 0 || profile.max_exposure >= exposure) {
+ if (best_i < 0) {
+ // no match found yet
+ best_i = i;
+ } else {
+ // test for better match
+ if (profiles[i].max_exposure < profiles[best_i].max_exposure) {
+ best_i = i;
}
}
}
}
- /* default fallback */
- if(idx<0)
- {
- DBG (DBG_warn,"%s: using default motor profile\n",__func__);
- idx=0;
+ if (best_i < 0) {
+ return nullptr;
+ }
+
+ return &profiles[best_i];
+}
+
+const MotorProfile& get_motor_profile(const std::vector<MotorProfile>& profiles,
+ unsigned exposure,
+ const ScanSession& session)
+{
+ const auto* profile = get_motor_profile_ptr(profiles, exposure, session);
+ if (profile == nullptr) {
+ throw SaneException("Motor slope is not configured");
}
- return motors[idx];
+ return *profile;
}
-MotorSlopeTable sanei_genesys_slope_table(AsicType asic_type, int dpi, int exposure, int base_dpi,
- unsigned step_multiplier,
- const Motor_Profile& motor_profile)
+MotorSlopeTable create_slope_table(AsicType asic_type, const Genesys_Motor& motor, unsigned ydpi,
+ unsigned exposure, unsigned step_multiplier,
+ const MotorProfile& motor_profile)
{
- unsigned target_speed_w = ((exposure * dpi) / base_dpi);
+ unsigned target_speed_w = ((exposure * ydpi) / motor.base_ydpi);
- auto table = create_slope_table(motor_profile.slope, target_speed_w, motor_profile.step_type,
- step_multiplier, 2 * step_multiplier,
- get_slope_table_max_size(asic_type));
+ auto table = create_slope_table_for_speed(motor_profile.slope, target_speed_w,
+ motor_profile.step_type,
+ step_multiplier, 2 * step_multiplier,
+ get_slope_table_max_size(asic_type));
return table;
}
MotorSlopeTable create_slope_table_fastest(AsicType asic_type, unsigned step_multiplier,
- const Motor_Profile& motor_profile)
+ const MotorProfile& motor_profile)
{
- return create_slope_table(motor_profile.slope, motor_profile.slope.max_speed_w,
- motor_profile.step_type,
- step_multiplier, 2 * step_multiplier,
- get_slope_table_max_size(asic_type));
+ return create_slope_table_for_speed(motor_profile.slope, motor_profile.slope.max_speed_w,
+ motor_profile.step_type,
+ step_multiplier, 2 * step_multiplier,
+ get_slope_table_max_size(asic_type));
}
/** @brief returns the lowest possible ydpi for the device
diff --git a/backend/genesys/low.h b/backend/genesys/low.h
index d7f5dd2..d67b427 100644
--- a/backend/genesys/low.h
+++ b/backend/genesys/low.h
@@ -108,39 +108,6 @@
#define GENESYS_GREEN 1
#define GENESYS_BLUE 2
-/* Flags */
-#define GENESYS_FLAG_UNTESTED (1 << 0) /**< Print a warning for these scanners */
-#define GENESYS_FLAG_14BIT_GAMMA (1 << 1) /**< use 14bit Gamma table instead of 12 */
-#define GENESYS_FLAG_XPA (1 << 3)
-#define GENESYS_FLAG_SKIP_WARMUP (1 << 4) /**< skip genesys_warmup() */
-/** @brief offset calibration flag
- * signals that the scanner does offset calibration. In this case off_calibration() and
- * coarse_gain_calibration() functions must be implemented
- */
-#define GENESYS_FLAG_OFFSET_CALIBRATION (1 << 5)
-#define GENESYS_FLAG_SEARCH_START (1 << 6) /**< do start search before scanning */
-#define GENESYS_FLAG_REPARK (1 << 7) /**< repark head (and check for lock) by
- moving without scanning */
-#define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /**< do dark calibration */
-
-#define GENESYS_FLAG_MUST_WAIT (1 << 10) /**< tells wether the scanner must wait for the head when parking */
-
-
-#define GENESYS_FLAG_HAS_UTA (1 << 11) /**< scanner has a transparency adapter */
-
-#define GENESYS_FLAG_DARK_WHITE_CALIBRATION (1 << 12) /**< yet another calibration method. does white and dark shading in one run, depending on a black and a white strip*/
-#define GENESYS_FLAG_CUSTOM_GAMMA (1 << 13) /**< allow custom gamma tables */
-#define GENESYS_FLAG_NO_CALIBRATION (1 << 14) /**< allow scanners to use skip the calibration, needed for sheetfed scanners */
-#define GENESYS_FLAG_SIS_SENSOR (1 << 16) /**< handling of multi-segments sensors in software */
-#define GENESYS_FLAG_SHADING_NO_MOVE (1 << 17) /**< scanner doesn't move sensor during shading calibration */
-#define GENESYS_FLAG_SHADING_REPARK (1 << 18) /**< repark head between shading scans */
-#define GENESYS_FLAG_FULL_HWDPI_MODE (1 << 19) /**< scanner always use maximum hw dpi to setup the sensor */
-// scanner has infrared transparency scanning capability
-#define GENESYS_FLAG_HAS_UTA_INFRARED (1 << 20)
-// scanner calibration is handled on the host side
-#define GENESYS_FLAG_CALIBRATION_HOST_SIDE (1 << 21)
-#define GENESYS_FLAG_16BIT_DATA_INVERTED (1 << 22)
-
#define GENESYS_HAS_NO_BUTTONS 0 /**< scanner has no supported button */
#define GENESYS_HAS_SCAN_SW (1 << 0) /**< scanner has SCAN button */
#define GENESYS_HAS_FILE_SW (1 << 1) /**< scanner has FILE button */
@@ -186,66 +153,60 @@
#define AFE_SET 2
#define AFE_POWER_SAVE 4
-#define LOWORD(x) ((uint16_t)((x) & 0xffff))
-#define HIWORD(x) ((uint16_t)((x) >> 16))
-#define LOBYTE(x) ((uint8_t)((x) & 0xFF))
-#define HIBYTE(x) ((uint8_t)((x) >> 8))
-
-/* Global constants */
-/* TODO: emove this leftover of early backend days */
-#define MOTOR_SPEED_MAX 350
-#define DARK_VALUE 0
-
-#define MAX_RESOLUTIONS 13
-#define MAX_DPI 4
-
namespace genesys {
-struct Genesys_USB_Device_Entry {
+class UsbDeviceEntry {
+public:
+ static constexpr std::uint16_t BCD_DEVICE_NOT_SET = 0xffff;
+
+ UsbDeviceEntry(std::uint16_t vendor_id, std::uint16_t product_id,
+ const Genesys_Model& model) :
+ vendor_{vendor_id}, product_{product_id},
+ bcd_device_{BCD_DEVICE_NOT_SET}, model_{model}
+ {}
- Genesys_USB_Device_Entry(unsigned v, unsigned p, const Genesys_Model& m) :
- vendor(v), product(p), model(m)
+ UsbDeviceEntry(std::uint16_t vendor_id, std::uint16_t product_id, std::uint16_t bcd_device,
+ const Genesys_Model& model) :
+ vendor_{vendor_id}, product_{product_id},
+ bcd_device_{bcd_device}, model_{model}
{}
+ std::uint16_t vendor_id() const { return vendor_; }
+ std::uint16_t product_id() const { return product_; }
+ std::uint16_t bcd_device() const { return bcd_device_; }
+
+ const Genesys_Model& model() const { return model_; }
+
+ bool matches(std::uint16_t vendor_id, std::uint16_t product_id, std::uint16_t bcd_device)
+ {
+ if (vendor_ != vendor_id)
+ return false;
+ if (product_ != product_id)
+ return false;
+ if (bcd_device_ != BCD_DEVICE_NOT_SET && bcd_device != BCD_DEVICE_NOT_SET &&
+ bcd_device_ != bcd_device)
+ {
+ return false;
+ }
+ return true;
+ }
+
+private:
// USB vendor identifier
- std::uint16_t vendor;
+ std::uint16_t vendor_;
// USB product identifier
- std::uint16_t product;
+ std::uint16_t product_;
+ // USB bcdProduct identifier
+ std::uint16_t bcd_device_;
// Scanner model information
- Genesys_Model model;
+ Genesys_Model model_;
};
-/**
- * structure for motor database
- */
-struct Motor_Profile
-{
- MotorId motor_id;
- int exposure; // used only to select the wanted motor
- StepType step_type; // default step type for given exposure
- MotorSlope slope;
-};
-
-extern StaticInit<std::vector<Motor_Profile>> gl843_motor_profiles;
-extern StaticInit<std::vector<Motor_Profile>> gl846_motor_profiles;
-extern StaticInit<std::vector<Motor_Profile>> gl847_motor_profiles;
-extern StaticInit<std::vector<Motor_Profile>> gl124_motor_profiles;
-
/*--------------------------------------------------------------------------*/
/* common functions needed by low level specific functions */
/*--------------------------------------------------------------------------*/
-inline GenesysRegister* sanei_genesys_get_address(Genesys_Register_Set* regs, uint16_t addr)
-{
- auto* ret = regs->find_reg_address(addr);
- if (ret == nullptr) {
- DBG(DBG_error, "%s: failed to find address for register 0x%02x, crash expected !\n",
- __func__, addr);
- }
- return ret;
-}
-
-extern void sanei_genesys_init_cmd_set(Genesys_Device* dev);
+std::unique_ptr<CommandSet> create_cmd_set(AsicType asic_type);
// reads the status of the scanner
Status scanner_read_status(Genesys_Device& dev);
@@ -259,21 +220,26 @@ void scanner_read_print_status(Genesys_Device& dev);
void debug_print_status(DebugMessageHelper& dbg, Status status);
+void scanner_register_rw_clear_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask);
+void scanner_register_rw_set_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask);
+void scanner_register_rw_bits(Genesys_Device& dev, std::uint16_t address,
+ std::uint8_t value, std::uint8_t mask);
+
extern void sanei_genesys_write_ahb(Genesys_Device* dev, uint32_t addr, uint32_t size,
uint8_t* data);
extern void sanei_genesys_init_structs (Genesys_Device * dev);
-const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev);
-const Genesys_Sensor& sanei_genesys_find_sensor(Genesys_Device* dev, unsigned dpi,
+const Genesys_Sensor& sanei_genesys_find_sensor_any(const Genesys_Device* dev);
+const Genesys_Sensor& sanei_genesys_find_sensor(const Genesys_Device* dev, unsigned dpi,
unsigned channels, ScanMethod scan_method);
-bool sanei_genesys_has_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels,
+bool sanei_genesys_has_sensor(const Genesys_Device* dev, unsigned dpi, unsigned channels,
ScanMethod scan_method);
Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigned dpi,
unsigned channels, ScanMethod scan_method);
std::vector<std::reference_wrapper<const Genesys_Sensor>>
- sanei_genesys_find_sensors_all(Genesys_Device* dev, ScanMethod scan_method);
+ sanei_genesys_find_sensors_all(const Genesys_Device* dev, ScanMethod scan_method);
std::vector<std::reference_wrapper<Genesys_Sensor>>
sanei_genesys_find_sensors_all_for_write(Genesys_Device* dev, ScanMethod scan_method);
@@ -318,13 +284,9 @@ extern void sanei_genesys_set_buffer_address(Genesys_Device* dev, uint32_t addr)
unsigned sanei_genesys_get_bulk_max_size(AsicType asic_type);
-SANE_Int sanei_genesys_exposure_time2(Genesys_Device * dev, float ydpi, StepType step_type,
+SANE_Int sanei_genesys_exposure_time2(Genesys_Device* dev, const MotorProfile& profile, float ydpi,
int endpixel, int led_exposure);
-MotorSlopeTable sanei_genesys_create_slope_table3(AsicType asic_type, const Genesys_Motor& motor,
- StepType step_type, int exposure_time,
- unsigned yres);
-
void sanei_genesys_create_default_gamma_table(Genesys_Device* dev,
std::vector<uint16_t>& gamma_table, float gamma);
@@ -335,28 +297,42 @@ void sanei_genesys_send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& s
extern void sanei_genesys_stop_motor(Genesys_Device* dev);
-extern void sanei_genesys_search_reference_point(Genesys_Device* dev, Genesys_Sensor& sensor,
- const uint8_t* src_data, int start_pixel, int dpi,
- int width, int height);
-
// moves the scan head by the specified steps at the motor base dpi
void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, Direction direction);
void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home);
void scanner_move_back_home_ta(Genesys_Device& dev);
-void scanner_clear_scan_and_feed_counts(Genesys_Device& dev);
+/** Search for a full width black or white strip.
+ This function searches for a black or white stripe across the scanning area.
+ When searching backward, the searched area must completely be of the desired
+ color since this area will be used for calibration which scans forward.
-extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
- std::size_t length);
+ @param dev scanner device
+ @param forward true if searching forward, false if searching backward
+ @param black true if searching for a black strip, false for a white strip
+ */
+void scanner_search_strip(Genesys_Device& dev, bool forward, bool black);
+
+bool should_calibrate_only_active_area(const Genesys_Device& dev,
+ const Genesys_Settings& settings);
+
+void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
-extern void sanei_genesys_write_pnm_file(const char* filename, const std::uint8_t* data, int depth,
- int channels, int pixels_per_line, int lines);
+void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs, unsigned dpi);
+
+SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
+
+void scanner_clear_scan_and_feed_counts(Genesys_Device& dev);
-void sanei_genesys_write_pnm_file(const char* filename, const Image& image);
+void scanner_send_slope_table(Genesys_Device* dev, const Genesys_Sensor& sensor, unsigned table_nr,
+ const std::vector<uint16_t>& slope_table);
-extern void sanei_genesys_write_pnm_file16(const char* filename, const uint16_t *data, unsigned channels,
- unsigned pixels_per_line, unsigned lines);
+extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
+ std::size_t length);
void wait_until_buffer_non_empty(Genesys_Device* dev, bool check_status_twice = false);
@@ -370,25 +346,13 @@ void regs_set_exposure(AsicType asic_type, Genesys_Register_Set& regs,
void regs_set_optical_off(AsicType asic_type, Genesys_Register_Set& regs);
-void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, const Genesys_Sensor& sensor,
- unsigned dpihw);
-
-inline uint16_t sanei_genesys_fixup_exposure_value(uint16_t value)
-{
- if ((value & 0xff00) == 0) {
- value |= 0x100;
- }
- if ((value & 0x00ff) == 0) {
- value |= 0x1;
- }
- return value;
-}
+void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, unsigned dpihw);
inline SensorExposure sanei_genesys_fixup_exposure(SensorExposure exposure)
{
- exposure.red = sanei_genesys_fixup_exposure_value(exposure.red);
- exposure.green = sanei_genesys_fixup_exposure_value(exposure.green);
- exposure.blue = sanei_genesys_fixup_exposure_value(exposure.blue);
+ exposure.red = std::max<std::uint16_t>(1, exposure.red);
+ exposure.green = std::max<std::uint16_t>(1, exposure.green);
+ exposure.blue = std::max<std::uint16_t>(1, exposure.blue);
return exposure;
}
@@ -396,7 +360,7 @@ bool get_registers_gain4_bit(AsicType asic_type, const Genesys_Register_Set& reg
extern void sanei_genesys_wait_for_home(Genesys_Device* dev);
-extern void sanei_genesys_asic_init(Genesys_Device* dev, bool cold);
+extern void sanei_genesys_asic_init(Genesys_Device* dev);
void scanner_start_action(Genesys_Device& dev, bool start_motor);
void scanner_stop_action(Genesys_Device& dev);
@@ -404,15 +368,23 @@ void scanner_stop_action_no_move(Genesys_Device& dev, Genesys_Register_Set& regs
bool scanner_is_motor_stopped(Genesys_Device& dev);
-const Motor_Profile& sanei_genesys_get_motor_profile(const std::vector<Motor_Profile>& motors,
- MotorId motor_id, int exposure);
+void scanner_setup_sensor(Genesys_Device& dev, const Genesys_Sensor& sensor,
+ Genesys_Register_Set& regs);
+
+const MotorProfile* get_motor_profile_ptr(const std::vector<MotorProfile>& profiles,
+ unsigned exposure,
+ const ScanSession& session);
-MotorSlopeTable sanei_genesys_slope_table(AsicType asic_type, int dpi, int exposure, int base_dpi,
- unsigned step_multiplier,
- const Motor_Profile& motor_profile);
+const MotorProfile& get_motor_profile(const std::vector<MotorProfile>& profiles,
+ unsigned exposure,
+ const ScanSession& session);
+
+MotorSlopeTable create_slope_table(AsicType asic_type, const Genesys_Motor& motor, unsigned ydpi,
+ unsigned exposure, unsigned step_multiplier,
+ const MotorProfile& motor_profile);
MotorSlopeTable create_slope_table_fastest(AsicType asic_type, unsigned step_multiplier,
- const Motor_Profile& motor_profile);
+ const MotorProfile& motor_profile);
/** @brief find lowest motor resolution for the device.
* Parses the resolution list for motor and
@@ -449,52 +421,22 @@ extern void sanei_genesys_generate_gamma_buffer(Genesys_Device* dev,
int size,
uint8_t* gamma);
+unsigned session_adjust_output_pixels(unsigned output_pixels,
+ const Genesys_Device& dev, const Genesys_Sensor& sensor,
+ unsigned output_xresolution, unsigned output_yresolution,
+ bool adjust_output_pixels);
+
void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Sensor& sensor);
-void build_image_pipeline(Genesys_Device* dev, const ScanSession& session);
+ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSession& session,
+ unsigned pipeline_index, bool log_image_data);
+
+// sets up a image pipeline for device `dev`
+void setup_image_pipeline(Genesys_Device& dev, const ScanSession& session);
std::uint8_t compute_frontend_gain(float value, float target_value,
FrontendType frontend_type);
-template<class T>
-inline T abs_diff(T a, T b)
-{
- if (a < b) {
- return b - a;
- } else {
- return a - b;
- }
-}
-
-inline uint64_t align_multiple_floor(uint64_t x, uint64_t multiple)
-{
- return (x / multiple) * multiple;
-}
-
-inline uint64_t align_multiple_ceil(uint64_t x, uint64_t multiple)
-{
- return ((x + multiple - 1) / multiple) * multiple;
-}
-
-inline uint64_t multiply_by_depth_ceil(uint64_t pixels, uint64_t depth)
-{
- if (depth == 1) {
- return (pixels / 8) + ((pixels % 8) ? 1 : 0);
- } else {
- return pixels * (depth / 8);
- }
-}
-
-template<class T>
-inline T clamp(const T& value, const T& lo, const T& hi)
-{
- if (value < lo)
- return lo;
- if (value > hi)
- return hi;
- return value;
-}
-
/*---------------------------------------------------------------------------*/
/* ASIC specific functions declarations */
/*---------------------------------------------------------------------------*/
@@ -502,15 +444,18 @@ inline T clamp(const T& value, const T& lo, const T& hi)
extern StaticInit<std::vector<Genesys_Sensor>> s_sensors;
extern StaticInit<std::vector<Genesys_Frontend>> s_frontends;
extern StaticInit<std::vector<Genesys_Gpo>> s_gpo;
+extern StaticInit<std::vector<MemoryLayout>> s_memory_layout;
extern StaticInit<std::vector<Genesys_Motor>> s_motors;
-extern StaticInit<std::vector<Genesys_USB_Device_Entry>> s_usb_devices;
+extern StaticInit<std::vector<UsbDeviceEntry>> s_usb_devices;
void genesys_init_sensor_tables();
void genesys_init_frontend_tables();
void genesys_init_gpo_tables();
+void genesys_init_memory_layout_tables();
void genesys_init_motor_tables();
-void genesys_init_motor_profile_tables();
void genesys_init_usb_device_tables();
+void verify_sensor_tables();
+void verify_usb_device_tables();
template<class T>
void debug_dump(unsigned level, const T& value)
diff --git a/backend/genesys/motor.cpp b/backend/genesys/motor.cpp
index 910266a..a18d6e1 100644
--- a/backend/genesys/motor.cpp
+++ b/backend/genesys/motor.cpp
@@ -43,9 +43,11 @@
#define DEBUG_DECLARE_ONLY
+#include "low.h"
#include "motor.h"
#include "utilities.h"
#include <cmath>
+#include <numeric>
namespace genesys {
@@ -80,19 +82,38 @@ MotorSlope MotorSlope::create_from_steps(unsigned initial_w, unsigned max_w,
return slope;
}
-void MotorSlopeTable::slice_steps(unsigned count)
+void MotorSlopeTable::slice_steps(unsigned count, unsigned step_multiplier)
{
- if (count >= table.size() || count > steps_count) {
- throw SaneException("Excepssive steps count");
+ if (count > table.size() || count < step_multiplier) {
+ throw SaneException("Invalid steps count");
}
- steps_count = count;
+ count = align_multiple_floor(count, step_multiplier);
+ table.resize(count);
+ generate_pixeltime_sum();
+}
+
+void MotorSlopeTable::expand_table(unsigned count, unsigned step_multiplier)
+{
+ if (table.empty()) {
+ throw SaneException("Can't expand empty table");
+ }
+ count = align_multiple_ceil(count, step_multiplier);
+ table.resize(table.size() + count, table.back());
+ generate_pixeltime_sum();
+}
+
+void MotorSlopeTable::generate_pixeltime_sum()
+{
+ pixeltime_sum_ = std::accumulate(table.begin(), table.end(),
+ std::size_t{0}, std::plus<std::size_t>());
}
unsigned get_slope_table_max_size(AsicType asic_type)
{
switch (asic_type) {
case AsicType::GL646:
- case AsicType::GL841: return 255;
+ case AsicType::GL841:
+ case AsicType::GL842: return 255;
case AsicType::GL843:
case AsicType::GL845:
case AsicType::GL846:
@@ -103,9 +124,9 @@ unsigned get_slope_table_max_size(AsicType asic_type)
}
}
-MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_speed_w,
- StepType step_type, unsigned steps_alignment,
- unsigned min_size, unsigned max_size)
+MotorSlopeTable create_slope_table_for_speed(const MotorSlope& slope, unsigned target_speed_w,
+ StepType step_type, unsigned steps_alignment,
+ unsigned min_size, unsigned max_size)
{
DBG_HELPER_ARGS(dbg, "target_speed_w: %d, step_type: %d, steps_alignment: %d, min_size: %d",
target_speed_w, static_cast<unsigned>(step_type), steps_alignment, min_size);
@@ -120,6 +141,10 @@ MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_spee
dbg.log(DBG_warn, "failed to reach target speed");
}
+ if (target_speed_shifted_w >= std::numeric_limits<std::uint16_t>::max()) {
+ throw SaneException("Target motor speed is too low");
+ }
+
unsigned final_speed = std::max(target_speed_shifted_w, max_speed_shifted_w);
table.table.reserve(max_size);
@@ -130,26 +155,20 @@ MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_spee
break;
}
table.table.push_back(current);
- table.pixeltime_sum += current;
}
// make sure the target speed (or the max speed if target speed is too high) is present in
// the table
table.table.push_back(final_speed);
- table.pixeltime_sum += table.table.back();
// fill the table up to the specified size
while (table.table.size() < max_size - 1 &&
(table.table.size() % steps_alignment != 0 || table.table.size() < min_size))
{
table.table.push_back(table.table.back());
- table.pixeltime_sum += table.table.back();
}
- table.steps_count = table.table.size();
-
- // fill the rest of the table with the final speed
- table.table.resize(max_size, final_speed);
+ table.generate_pixeltime_sum();
return table;
}
@@ -164,15 +183,30 @@ std::ostream& operator<<(std::ostream& out, const MotorSlope& slope)
return out;
}
+std::ostream& operator<<(std::ostream& out, const MotorProfile& profile)
+{
+ out << "MotorProfile{\n"
+ << " max_exposure: " << profile.max_exposure << '\n'
+ << " step_type: " << profile.step_type << '\n'
+ << " motor_vref: " << profile.motor_vref << '\n'
+ << " resolutions: " << format_indent_braced_list(4, profile.resolutions) << '\n'
+ << " scan_methods: " << format_indent_braced_list(4, profile.scan_methods) << '\n'
+ << " slope: " << format_indent_braced_list(4, profile.slope) << '\n'
+ << '}';
+ return out;
+}
+
std::ostream& operator<<(std::ostream& out, const Genesys_Motor& motor)
{
out << "Genesys_Motor{\n"
- << " id: " << static_cast<unsigned>(motor.id) << '\n'
+ << " id: " << motor.id << '\n'
<< " base_ydpi: " << motor.base_ydpi << '\n'
- << " optical_ydpi: " << motor.optical_ydpi << '\n'
- << " slopes: "
- << format_indent_braced_list(4, format_vector_indent_braced(4, "MotorSlope",
- motor.slopes))
+ << " profiles: "
+ << format_indent_braced_list(4, format_vector_indent_braced(4, "MotorProfile",
+ motor.profiles)) << '\n'
+ << " fast_profiles: "
+ << format_indent_braced_list(4, format_vector_indent_braced(4, "MotorProfile",
+ motor.fast_profiles)) << '\n'
<< '}';
return out;
}
diff --git a/backend/genesys/motor.h b/backend/genesys/motor.h
index d80da6d..c433c0e 100644
--- a/backend/genesys/motor.h
+++ b/backend/genesys/motor.h
@@ -44,9 +44,12 @@
#ifndef BACKEND_GENESYS_MOTOR_H
#define BACKEND_GENESYS_MOTOR_H
+#include <algorithm>
#include <cstdint>
#include <vector>
#include "enums.h"
+#include "sensor.h"
+#include "value_filter.h"
namespace genesys {
@@ -123,20 +126,47 @@ struct MotorSlope
struct MotorSlopeTable
{
std::vector<std::uint16_t> table;
- unsigned steps_count = 0;
- unsigned pixeltime_sum = 0;
- void slice_steps(unsigned count);
+ void slice_steps(unsigned count, unsigned step_multiplier);
+
+ // expands the table by the given number of steps
+ void expand_table(unsigned count, unsigned step_multiplier);
+
+ std::uint64_t pixeltime_sum() const { return pixeltime_sum_; }
+
+ void generate_pixeltime_sum();
+private:
+ std::uint64_t pixeltime_sum_ = 0;
};
unsigned get_slope_table_max_size(AsicType asic_type);
-MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_speed_w,
- StepType step_type, unsigned steps_alignment,
- unsigned min_size, unsigned max_size);
+MotorSlopeTable create_slope_table_for_speed(const MotorSlope& slope, unsigned target_speed_w,
+ StepType step_type, unsigned steps_alignment,
+ unsigned min_size, unsigned max_size);
std::ostream& operator<<(std::ostream& out, const MotorSlope& slope);
+struct MotorProfile
+{
+ MotorProfile() = default;
+ MotorProfile(const MotorSlope& a_slope, StepType a_step_type, unsigned a_max_exposure) :
+ slope{a_slope}, step_type{a_step_type}, max_exposure{a_max_exposure}
+ {}
+
+ MotorSlope slope;
+ StepType step_type = StepType::FULL;
+ int motor_vref = -1;
+
+ // the resolutions this profile is good for
+ ValueFilterAny<unsigned> resolutions = VALUE_FILTER_ANY;
+ // the scan method this profile is good for. If the list is empty, good for any method.
+ ValueFilterAny<ScanMethod> scan_methods = VALUE_FILTER_ANY;
+
+ unsigned max_exposure = 0; // 0 - any exposure
+};
+
+std::ostream& operator<<(std::ostream& out, const MotorProfile& profile);
struct Genesys_Motor
{
@@ -146,27 +176,41 @@ struct Genesys_Motor
MotorId id = MotorId::UNKNOWN;
// motor base steps. Unit: 1/inch
int base_ydpi = 0;
- // maximum resolution in y-direction. Unit: 1/inch
- int optical_ydpi = 0;
// slopes to derive individual slopes from
- std::vector<MotorSlope> slopes;
+ std::vector<MotorProfile> profiles;
+ // slopes to derive individual slopes from for fast moving
+ std::vector<MotorProfile> fast_profiles;
- MotorSlope& get_slope(StepType step_type)
+ MotorSlope& get_slope_with_step_type(StepType step_type)
{
- return slopes[static_cast<unsigned>(step_type)];
+ for (auto& p : profiles) {
+ if (p.step_type == step_type)
+ return p.slope;
+ }
+ throw SaneException("No motor profile with step type");
}
- const MotorSlope& get_slope(StepType step_type) const
+ const MotorSlope& get_slope_with_step_type(StepType step_type) const
{
- return slopes[static_cast<unsigned>(step_type)];
+ for (const auto& p : profiles) {
+ if (p.step_type == step_type)
+ return p.slope;
+ }
+ throw SaneException("No motor profile with step type");
}
StepType max_step_type() const
{
- if (slopes.empty()) {
- throw std::runtime_error("Slopes table is empty");
+ if (profiles.empty()) {
+ throw std::runtime_error("Profiles table is empty");
+ }
+ StepType step_type = StepType::FULL;
+ for (const auto& p : profiles) {
+ step_type = static_cast<StepType>(
+ std::max(static_cast<unsigned>(step_type),
+ static_cast<unsigned>(p.step_type)));
}
- return static_cast<StepType>(slopes.size() - 1);
+ return step_type;
}
};
diff --git a/backend/genesys/register.h b/backend/genesys/register.h
index bbc7ec8..51aab90 100644
--- a/backend/genesys/register.h
+++ b/backend/genesys/register.h
@@ -44,6 +44,7 @@
#ifndef BACKEND_GENESYS_REGISTER_H
#define BACKEND_GENESYS_REGISTER_H
+#include "enums.h"
#include "utilities.h"
#include <algorithm>
@@ -76,7 +77,7 @@ struct GenesysRegisterSetState
bool is_lamp_on = false;
bool is_xpa_on = false;
bool is_motor_on = false;
- bool is_xpa_motor_on = false;
+ MotorMode motor_mode = MotorMode::PRIMARY;
};
template<class Value>
@@ -414,6 +415,11 @@ public:
}
}
+ bool has_reg(AddressType address) const
+ {
+ return find_reg_index(address) != -1;
+ }
+
SettingType& find_reg(AddressType address)
{
int i = find_reg_index(address);
diff --git a/backend/genesys/scanner_interface.h b/backend/genesys/scanner_interface.h
index 03c7132..70413d1 100644
--- a/backend/genesys/scanner_interface.h
+++ b/backend/genesys/scanner_interface.h
@@ -56,11 +56,6 @@ namespace genesys {
class ScannerInterface
{
public:
- enum Flags {
- FLAG_NONE = 0,
- FLAG_SWAP_REGISTERS = 1 << 0,
- FLAG_SMALL_ADDRESS = 1 << 1
- };
virtual ~ScannerInterface();
@@ -75,12 +70,11 @@ public:
virtual void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) = 0;
// GL646, GL841, GL843 have different ways to write to RAM and to gamma tables
- // FIXME: remove flags when updating tests
virtual void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags = FLAG_NONE) = 0;
+ std::size_t size) = 0;
virtual void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags = FLAG_NONE) = 0;
+ std::size_t size) = 0;
// GL845, GL846, GL847 and GL124 have a uniform way to write to RAM tables
virtual void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) = 0;
diff --git a/backend/genesys/scanner_interface_usb.cpp b/backend/genesys/scanner_interface_usb.cpp
index d4d83dd..d405ede 100644
--- a/backend/genesys/scanner_interface_usb.cpp
+++ b/backend/genesys/scanner_interface_usb.cpp
@@ -101,8 +101,6 @@ std::uint8_t ScannerInterfaceUsb::read_register(std::uint16_t address)
usb_dev_.control_msg(REQUEST_TYPE_IN, REQUEST_REGISTER, VALUE_READ_REGISTER, INDEX,
1, &value);
}
-
- DBG(DBG_proc, "%s (0x%02x, 0x%02x) completed\n", __func__, address, value);
return value;
}
@@ -213,6 +211,7 @@ static void bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, s
uint8_t outdata[8];
if (asic_type == AsicType::GL124 ||
+ asic_type == AsicType::GL845 ||
asic_type == AsicType::GL846 ||
asic_type == AsicType::GL847)
{
@@ -222,7 +221,9 @@ static void bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, s
outdata[2] = 0;
outdata[3] = 0x10;
} else if (asic_type == AsicType::GL841 ||
- asic_type == AsicType::GL843) {
+ asic_type == AsicType::GL842 ||
+ asic_type == AsicType::GL843)
+ {
outdata[0] = BULK_IN;
outdata[1] = BULK_RAM;
outdata[2] = 0x82; //
@@ -246,12 +247,13 @@ static void bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, s
void ScannerInterfaceUsb::bulk_read_data(std::uint8_t addr, std::uint8_t* data, std::size_t size)
{
- // currently supported: GL646, GL841, GL843, GL846, GL847, GL124
+ // currently supported: GL646, GL841, GL843, GL845, GL846, GL847, GL124
DBG_HELPER(dbg);
unsigned is_addr_used = 1;
unsigned has_header_before_each_chunk = 0;
if (dev_->model->asic_type == AsicType::GL124 ||
+ dev_->model->asic_type == AsicType::GL845 ||
dev_->model->asic_type == AsicType::GL846 ||
dev_->model->asic_type == AsicType::GL847)
{
@@ -351,30 +353,21 @@ void ScannerInterfaceUsb::bulk_write_data(std::uint8_t addr, std::uint8_t* data,
}
void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags)
+ std::size_t size)
{
DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
if (dev_->model->asic_type != AsicType::GL646 &&
dev_->model->asic_type != AsicType::GL841 &&
+ dev_->model->asic_type != AsicType::GL842 &&
dev_->model->asic_type != AsicType::GL843)
{
throw SaneException("Unsupported transfer mode");
}
if (dev_->model->asic_type == AsicType::GL843) {
- if (flags & FLAG_SWAP_REGISTERS) {
- if (!(flags & FLAG_SMALL_ADDRESS)) {
- write_register(0x29, ((addr >> 20) & 0xff));
- }
- write_register(0x2a, ((addr >> 12) & 0xff));
- write_register(0x2b, ((addr >> 4) & 0xff));
- } else {
- write_register(0x2b, ((addr >> 4) & 0xff));
- write_register(0x2a, ((addr >> 12) & 0xff));
- if (!(flags & FLAG_SMALL_ADDRESS)) {
- write_register(0x29, ((addr >> 20) & 0xff));
- }
- }
+ write_register(0x2b, ((addr >> 4) & 0xff));
+ write_register(0x2a, ((addr >> 12) & 0xff));
+ write_register(0x29, ((addr >> 20) & 0xff));
} else {
write_register(0x2b, ((addr >> 4) & 0xff));
write_register(0x2a, ((addr >> 12) & 0xff));
@@ -383,24 +376,28 @@ void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, st
}
void ScannerInterfaceUsb::write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags)
+ std::size_t size)
{
DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
- if (dev_->model->asic_type != AsicType::GL646 &&
- dev_->model->asic_type != AsicType::GL841 &&
+ if (dev_->model->asic_type != AsicType::GL841 &&
+ dev_->model->asic_type != AsicType::GL842 &&
dev_->model->asic_type != AsicType::GL843)
{
throw SaneException("Unsupported transfer mode");
}
- if (flags & FLAG_SWAP_REGISTERS) {
- write_register(0x5b, ((addr >> 12) & 0xff));
- write_register(0x5c, ((addr >> 4) & 0xff));
- } else {
- write_register(0x5c, ((addr >> 4) & 0xff));
- write_register(0x5b, ((addr >> 12) & 0xff));
- }
+ write_register(0x5b, ((addr >> 12) & 0xff));
+ write_register(0x5c, ((addr >> 4) & 0xff));
bulk_write_data(type, data, size);
+
+ if (dev_->model->asic_type == AsicType::GL842 ||
+ dev_->model->asic_type == AsicType::GL843)
+ {
+ // it looks like we need to reset the address so that subsequent buffer operations work.
+ // Most likely the MTRTBL register is to blame.
+ write_register(0x5b, 0);
+ write_register(0x5c, 0);
+ }
}
void ScannerInterfaceUsb::write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)
diff --git a/backend/genesys/scanner_interface_usb.h b/backend/genesys/scanner_interface_usb.h
index 06b51ff..33fb8fe 100644
--- a/backend/genesys/scanner_interface_usb.h
+++ b/backend/genesys/scanner_interface_usb.h
@@ -67,9 +67,9 @@ public:
void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) override;
void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags) override;
+ std::size_t size) override;
void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags) override;
+ std::size_t size) override;
void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) override;
diff --git a/backend/genesys/sensor.cpp b/backend/genesys/sensor.cpp
index e54af65..ce51403 100644
--- a/backend/genesys/sensor.cpp
+++ b/backend/genesys/sensor.cpp
@@ -51,10 +51,16 @@ namespace genesys {
std::ostream& operator<<(std::ostream& out, const StaggerConfig& config)
{
- out << "StaggerConfig{\n"
- << " min_resolution: " << config.min_resolution() << '\n'
- << " lines_at_min: " << config.lines_at_min() << '\n'
- << "}";
+ if (config.shifts().empty()) {
+ out << "StaggerConfig{}";
+ return out;
+ }
+
+ out << "StaggerConfig{ " << config.shifts().front();
+ for (auto it = std::next(config.shifts().begin()); it != config.shifts().end(); ++it) {
+ out << ", " << *it;
+ }
+ out << " }";
return out;
}
@@ -64,6 +70,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::ANALOG_DEVICES_GL847: out << "ANALOG_DEVICES_GL847"; break;
+ case FrontendType::WOLFSON_GL124: out << "WOLFSON_GL124"; break;
default: out << "(unknown value)";
}
return out;
@@ -91,7 +102,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Frontend& frontend)
StreamStateSaver state_saver{out};
out << "Genesys_Frontend{\n"
- << " id: " << static_cast<unsigned>(frontend.id) << '\n'
+ << " id: " << frontend.id << '\n'
<< " regs: " << format_indent_braced_list(4, frontend.regs) << '\n'
<< std::hex
<< " reg2[0]: " << frontend.reg2[0] << '\n'
@@ -112,33 +123,23 @@ std::ostream& operator<<(std::ostream& out, const SensorExposure& exposure)
return out;
}
-std::ostream& operator<<(std::ostream& out, const ResolutionFilter& resolutions)
-{
- if (resolutions.matches_any()) {
- out << "ANY";
- return out;
- }
- out << format_vector_unsigned(4, resolutions.resolutions());
- return out;
-}
-
std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor)
{
out << "Genesys_Sensor{\n"
<< " sensor_id: " << static_cast<unsigned>(sensor.sensor_id) << '\n'
- << " optical_res: " << sensor.optical_res << '\n'
+ << " full_resolution: " << sensor.full_resolution << '\n'
+ << " optical_resolution: " << sensor.get_optical_resolution() << '\n'
<< " resolutions: " << format_indent_braced_list(4, sensor.resolutions) << '\n'
<< " channels: " << format_vector_unsigned(4, sensor.channels) << '\n'
<< " method: " << sensor.method << '\n'
- << " register_dpihw_override: " << sensor.register_dpihw_override << '\n'
- << " logical_dpihw_override: " << sensor.logical_dpihw_override << '\n'
- << " dpiset_override: " << sensor.dpiset_override << '\n'
- << " ccd_size_divisor: " << sensor.ccd_size_divisor << '\n'
- << " pixel_count_multiplier: " << sensor.pixel_count_multiplier << '\n'
+ << " register_dpihw: " << sensor.register_dpihw << '\n'
+ << " register_dpiset: " << sensor.register_dpiset << '\n'
+ << " shading_factor: " << sensor.shading_factor << '\n'
+ << " shading_pixel_offset: " << sensor.shading_pixel_offset << '\n'
+ << " pixel_count_ratio: " << sensor.pixel_count_ratio << '\n'
+ << " output_pixel_offset: " << sensor.output_pixel_offset << '\n'
<< " black_pixels: " << sensor.black_pixels << '\n'
<< " dummy_pixel: " << sensor.dummy_pixel << '\n'
- << " ccd_start_xoffset: " << sensor.ccd_start_xoffset << '\n'
- << " sensor_pixels: " << sensor.sensor_pixels << '\n'
<< " fau_gain_white_ref: " << sensor.fau_gain_white_ref << '\n'
<< " gain_white_ref: " << sensor.gain_white_ref << '\n'
<< " exposure: " << format_indent_braced_list(4, sensor.exposure) << '\n'
@@ -146,8 +147,9 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor)
<< " segment_size: " << sensor.segment_size << '\n'
<< " segment_order: "
<< format_indent_braced_list(4, format_vector_unsigned(4, sensor.segment_order)) << '\n'
- << " stagger_config: " << format_indent_braced_list(4, sensor.stagger_config) << '\n'
- << " custom_base_regs: " << format_indent_braced_list(4, sensor.custom_base_regs) << '\n'
+ << " stagger_x: " << sensor.stagger_x << '\n'
+ << " stagger_y: " << sensor.stagger_y << '\n'
+ << " use_host_side_calib: " << sensor.use_host_side_calib << '\n'
<< " custom_regs: " << format_indent_braced_list(4, sensor.custom_regs) << '\n'
<< " custom_fe_regs: " << format_indent_braced_list(4, sensor.custom_fe_regs) << '\n'
<< " gamma.red: " << sensor.gamma[0] << '\n'
diff --git a/backend/genesys/sensor.h b/backend/genesys/sensor.h
index e70728e..ca6fef7 100644
--- a/backend/genesys/sensor.h
+++ b/backend/genesys/sensor.h
@@ -47,6 +47,7 @@
#include "enums.h"
#include "register.h"
#include "serialize.h"
+#include "value_filter.h"
#include <array>
#include <functional>
@@ -72,31 +73,30 @@ class StaggerConfig
{
public:
StaggerConfig() = default;
- StaggerConfig(unsigned min_resolution, unsigned lines_at_min) :
- min_resolution_{min_resolution},
- lines_at_min_{lines_at_min}
+ explicit StaggerConfig(std::initializer_list<std::size_t> shifts) :
+ shifts_{shifts}
{
}
- unsigned stagger_at_resolution(unsigned xresolution, unsigned yresolution) const
+ std::size_t max_shift() const
{
- if (min_resolution_ == 0 || xresolution < min_resolution_)
+ if (shifts_.empty()) {
return 0;
- return yresolution / min_resolution_ * lines_at_min_;
+ }
+ return *std::max_element(shifts_.begin(), shifts_.end());
}
- unsigned min_resolution() const { return min_resolution_; }
- unsigned lines_at_min() const { return lines_at_min_; }
+ bool empty() const { return shifts_.empty(); }
+ std::size_t size() const { return shifts_.size(); }
+ const std::vector<std::size_t>& shifts() const { return shifts_; }
bool operator==(const StaggerConfig& other) const
{
- return min_resolution_ == other.min_resolution_ &&
- lines_at_min_ == other.lines_at_min_;
+ return shifts_ == other.shifts_;
}
private:
- unsigned min_resolution_ = 0;
- unsigned lines_at_min_ = 0;
+ std::vector<std::size_t> shifts_;
template<class Stream>
friend void serialize(Stream& str, StaggerConfig& x);
@@ -105,8 +105,7 @@ private:
template<class Stream>
void serialize(Stream& str, StaggerConfig& x)
{
- serialize(str, x.min_resolution_);
- serialize(str, x.lines_at_min_);
+ serialize(str, x.shifts_);
}
std::ostream& operator<<(std::ostream& out, const StaggerConfig& config);
@@ -114,9 +113,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
+ ANALOG_DEVICES_GL847, // old code path, likely wrong calculation
+ WOLFSON_GL124, // old code path, likely wrong calculation
};
inline void serialize(std::istream& str, FrontendType& x)
@@ -242,54 +246,6 @@ struct SensorExposure {
std::ostream& operator<<(std::ostream& out, const SensorExposure& exposure);
-class ResolutionFilter
-{
-public:
- struct Any {};
- static constexpr Any ANY{};
-
- ResolutionFilter() : matches_any_{false} {}
- ResolutionFilter(Any) : matches_any_{true} {}
- ResolutionFilter(std::initializer_list<unsigned> resolutions) :
- matches_any_{false},
- resolutions_{resolutions}
- {}
-
- bool matches(unsigned resolution) const
- {
- if (matches_any_)
- return true;
- auto it = std::find(resolutions_.begin(), resolutions_.end(), resolution);
- return it != resolutions_.end();
- }
-
- bool operator==(const ResolutionFilter& other) const
- {
- return matches_any_ == other.matches_any_ && resolutions_ == other.resolutions_;
- }
-
- bool matches_any() const { return matches_any_; }
- const std::vector<unsigned>& resolutions() const { return resolutions_; }
-
-private:
- bool matches_any_ = false;
- std::vector<unsigned> resolutions_;
-
- template<class Stream>
- friend void serialize(Stream& str, ResolutionFilter& x);
-};
-
-std::ostream& operator<<(std::ostream& out, const ResolutionFilter& resolutions);
-
-template<class Stream>
-void serialize(Stream& str, ResolutionFilter& x)
-{
- serialize(str, x.matches_any_);
- serialize_newline(str);
- serialize(str, x.resolutions_);
-}
-
-
struct Genesys_Sensor {
Genesys_Sensor() = default;
@@ -300,10 +256,15 @@ struct Genesys_Sensor {
// sensor resolution in CCD pixels. Note that we may read more than one CCD pixel per logical
// pixel, see ccd_pixels_per_system_pixel()
- unsigned optical_res = 0;
+ unsigned full_resolution = 0;
+
+ // sensor resolution in pixel values that are read by the chip. Many scanners make low
+ // resolutions faster by configuring the timings in such a way that 1/2 or 1/4 of pixel values
+ // that are read. If zero, then it is equal to `full_resolution`.
+ unsigned optical_resolution = 0;
// the resolution list that the sensor is usable at.
- ResolutionFilter resolutions = ResolutionFilter::ANY;
+ ValueFilterAny<unsigned> resolutions = VALUE_FILTER_ANY;
// the channel list that the sensor is usable at
std::vector<unsigned> channels = { 1, 3 };
@@ -313,29 +274,32 @@ struct Genesys_Sensor {
// The scanner may be setup to use a custom dpihw that does not correspond to any actual
// resolution. The value zero does not set the override.
- unsigned register_dpihw_override = 0;
-
- // The scanner may be setup to use a custom logical dpihw that does not correspond to any actual
- // resolution. The value zero does not set the override.
- unsigned logical_dpihw_override = 0;
+ unsigned register_dpihw = 0;
// The scanner may be setup to use a custom dpiset value that does not correspond to any actual
// resolution. The value zero does not set the override.
- unsigned dpiset_override = 0;
+ unsigned register_dpiset = 0;
+
+ // The resolution to use for shading calibration
+ unsigned shading_resolution = 0;
- // CCD may present itself as half or quarter-size CCD on certain resolutions
- int ccd_size_divisor = 1;
+ // How many real pixels correspond to one shading pixel that is sent to the scanner
+ unsigned shading_factor = 1;
- // Some scanners need an additional multiplier over the scan coordinates
- int pixel_count_multiplier = 1;
+ // How many pixels the shading data is offset to the right from the acquired data. Calculated
+ // in shading resolution.
+ int shading_pixel_offset = 0;
+
+ // This defines the ratio between logical pixel coordinates and the pixel coordinates sent to
+ // the scanner.
+ Ratio pixel_count_ratio = Ratio{1, 1};
+
+ // The offset in pixels in terms of scan resolution that needs to be applied to scan position.
+ int output_pixel_offset = 0;
int black_pixels = 0;
// value of the dummy register
int dummy_pixel = 0;
- // last pixel of CCD margin at optical resolution
- int ccd_start_xoffset = 0;
- // total pixels used by the sensor
- int sensor_pixels = 0;
// TA CCD target code (reference gain)
int fau_gain_white_ref = 0;
// CCD target code (reference gain)
@@ -346,8 +310,7 @@ struct Genesys_Sensor {
int exposure_lperiod = -1;
- // the number of pixels in a single segment.
- // only on gl843
+ // the number of pixels in a single segment. This is counted in output resolution.
unsigned segment_size = 0;
// the order of the segments, if any, for the sensor. If the sensor is not segmented or uses
@@ -355,31 +318,28 @@ struct Genesys_Sensor {
// only on gl843
std::vector<unsigned> segment_order;
- // some CCDs use two arrays of pixels for double resolution. On such CCDs when scanning at
- // high-enough resolution, every other pixel column is shifted
- StaggerConfig stagger_config;
+ // some CCDs use multiple arrays of pixels for double or quadruple resolution. This can result
+ // in the following effects on the output:
+ // - every n-th column may be shifted in a vertical direction.
+ // - the columns themselves may be reordered in arbitrary order and may require shifting
+ // in X direction.
+ StaggerConfig stagger_x;
+ StaggerConfig stagger_y;
+
+ // True if calibration should be performed on host-side
+ bool use_host_side_calib = false;
- GenesysRegisterSettingSet custom_base_regs; // gl646-specific
GenesysRegisterSettingSet custom_regs;
GenesysRegisterSettingSet custom_fe_regs;
// red, green and blue gamma coefficient for default gamma tables
AssignableArray<float, 3> gamma;
- std::function<unsigned(const Genesys_Sensor&, unsigned)> get_logical_hwdpi_fun;
- std::function<unsigned(const Genesys_Sensor&, unsigned)> get_register_hwdpi_fun;
- std::function<unsigned(const Genesys_Sensor&, unsigned)> get_ccd_size_divisor_fun;
- std::function<unsigned(const Genesys_Sensor&, unsigned)> get_hwdpi_divisor_fun;
-
- unsigned get_logical_hwdpi(unsigned xres) const { return get_logical_hwdpi_fun(*this, xres); }
- unsigned get_register_hwdpi(unsigned xres) const { return get_register_hwdpi_fun(*this, xres); }
- unsigned get_ccd_size_divisor_for_dpi(unsigned xres) const
- {
- return get_ccd_size_divisor_fun(*this, xres);
- }
- unsigned get_hwdpi_divisor_for_dpi(unsigned xres) const
+ unsigned get_optical_resolution() const
{
- return get_hwdpi_divisor_fun(*this, xres);
+ if (optical_resolution != 0)
+ return optical_resolution;
+ return full_resolution;
}
// how many CCD pixels are processed per system pixel time. This corresponds to CKSEL + 1
@@ -405,22 +365,26 @@ struct Genesys_Sensor {
bool operator==(const Genesys_Sensor& other) const
{
return sensor_id == other.sensor_id &&
- optical_res == other.optical_res &&
+ full_resolution == other.full_resolution &&
+ optical_resolution == other.optical_resolution &&
resolutions == other.resolutions &&
method == other.method &&
- ccd_size_divisor == other.ccd_size_divisor &&
+ shading_resolution == other.shading_resolution &&
+ shading_factor == other.shading_factor &&
+ shading_pixel_offset == other.shading_pixel_offset &&
+ pixel_count_ratio == other.pixel_count_ratio &&
+ output_pixel_offset == other.output_pixel_offset &&
black_pixels == other.black_pixels &&
dummy_pixel == other.dummy_pixel &&
- ccd_start_xoffset == other.ccd_start_xoffset &&
- sensor_pixels == other.sensor_pixels &&
fau_gain_white_ref == other.fau_gain_white_ref &&
gain_white_ref == other.gain_white_ref &&
exposure == other.exposure &&
exposure_lperiod == other.exposure_lperiod &&
segment_size == other.segment_size &&
segment_order == other.segment_order &&
- stagger_config == other.stagger_config &&
- custom_base_regs == other.custom_base_regs &&
+ stagger_x == other.stagger_x &&
+ stagger_y == other.stagger_y &&
+ use_host_side_calib == other.use_host_side_calib &&
custom_regs == other.custom_regs &&
custom_fe_regs == other.custom_fe_regs &&
gamma == other.gamma;
@@ -431,14 +395,16 @@ template<class Stream>
void serialize(Stream& str, Genesys_Sensor& x)
{
serialize(str, x.sensor_id);
- serialize(str, x.optical_res);
+ serialize(str, x.full_resolution);
serialize(str, x.resolutions);
serialize(str, x.method);
- serialize(str, x.ccd_size_divisor);
+ serialize(str, x.shading_resolution);
+ serialize(str, x.shading_factor);
+ serialize(str, x.shading_pixel_offset);
+ serialize(str, x.output_pixel_offset);
+ serialize(str, x.pixel_count_ratio);
serialize(str, x.black_pixels);
serialize(str, x.dummy_pixel);
- serialize(str, x.ccd_start_xoffset);
- serialize(str, x.sensor_pixels);
serialize(str, x.fau_gain_white_ref);
serialize(str, x.gain_white_ref);
serialize_newline(str);
@@ -451,9 +417,11 @@ void serialize(Stream& str, Genesys_Sensor& x)
serialize_newline(str);
serialize(str, x.segment_order);
serialize_newline(str);
- serialize(str, x.stagger_config);
+ serialize(str, x.stagger_x);
+ serialize_newline(str);
+ serialize(str, x.stagger_y);
serialize_newline(str);
- serialize(str, x.custom_base_regs);
+ serialize(str, x.use_host_side_calib);
serialize_newline(str);
serialize(str, x.custom_regs);
serialize_newline(str);
diff --git a/backend/genesys/settings.cpp b/backend/genesys/settings.cpp
index 41c66de..c2b54dc 100644
--- a/backend/genesys/settings.cpp
+++ b/backend/genesys/settings.cpp
@@ -72,14 +72,20 @@ std::ostream& operator<<(std::ostream& out, const SetupParams& params)
{
StreamStateSaver state_saver{out};
+ bool reverse = has_flag(params.flags, ScanFlag::REVERSE);
+
out << "SetupParams{\n"
- << " xres: " << params.xres << " yres: " << params.yres << '\n'
- << " lines: " << params.lines << '\n'
- << " pixels per line (actual): " << params.pixels << '\n'
- << " pixels per line (requested): " << params.requested_pixels << '\n'
+ << " xres: " << params.xres
+ << " startx: " << params.startx
+ << " pixels per line (actual): " << params.pixels
+ << " pixels per line (requested): " << params.requested_pixels << '\n'
+
+ << " yres: " << params.yres
+ << " lines: " << params.lines
+ << " starty: " << params.starty << (reverse ? " (reverse)" : "") << '\n'
+
<< " depth: " << params.depth << '\n'
<< " channels: " << params.channels << '\n'
- << " startx: " << params.startx << " starty: " << params.starty << '\n'
<< " scan_mode: " << params.scan_mode << '\n'
<< " color_filter: " << params.color_filter << '\n'
<< " flags: " << params.flags << '\n'
@@ -87,16 +93,56 @@ std::ostream& operator<<(std::ostream& out, const SetupParams& params)
return out;
}
+bool ScanSession::operator==(const ScanSession& other) const
+{
+ return params == other.params &&
+ computed == other.computed &&
+ full_resolution == other.full_resolution &&
+ optical_resolution == other.optical_resolution &&
+ optical_pixels == other.optical_pixels &&
+ optical_pixels_raw == other.optical_pixels_raw &&
+ optical_line_count == other.optical_line_count &&
+ output_resolution == other.output_resolution &&
+ output_startx == other.output_startx &&
+ output_pixels == other.output_pixels &&
+ output_channel_bytes == other.output_channel_bytes &&
+ output_line_bytes == other.output_line_bytes &&
+ output_line_bytes_raw == other.output_line_bytes_raw &&
+ output_line_bytes_requested == other.output_line_bytes_requested &&
+ output_line_count == other.output_line_count &&
+ output_total_bytes_raw == other.output_total_bytes_raw &&
+ output_total_bytes == other.output_total_bytes &&
+ num_staggered_lines == other.num_staggered_lines &&
+ max_color_shift_lines == other.max_color_shift_lines &&
+ color_shift_lines_r == other.color_shift_lines_r &&
+ color_shift_lines_g == other.color_shift_lines_g &&
+ color_shift_lines_b == other.color_shift_lines_b &&
+ stagger_x == other.stagger_x &&
+ stagger_y == other.stagger_y &&
+ segment_count == other.segment_count &&
+ pixel_startx == other.pixel_startx &&
+ pixel_endx == other.pixel_endx &&
+ pixel_count_ratio == other.pixel_count_ratio &&
+ conseq_pixel_dist == other.conseq_pixel_dist &&
+ output_segment_pixel_group_count == other.output_segment_pixel_group_count &&
+ output_segment_start_offset == other.output_segment_start_offset &&
+ 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;
+}
+
std::ostream& operator<<(std::ostream& out, const ScanSession& session)
{
out << "ScanSession{\n"
<< " computed: " << session.computed << '\n'
- << " hwdpi_divisor: " << session.hwdpi_divisor << '\n'
- << " ccd_size_divisor: " << session.ccd_size_divisor << '\n'
+ << " full_resolution: " << session.full_resolution << '\n'
<< " optical_resolution: " << session.optical_resolution << '\n'
<< " optical_pixels: " << session.optical_pixels << '\n'
<< " optical_pixels_raw: " << session.optical_pixels_raw << '\n'
+ << " optical_line_count: " << session.optical_line_count << '\n'
<< " output_resolution: " << session.output_resolution << '\n'
+ << " output_startx: " << session.output_startx << '\n'
<< " output_pixels: " << session.output_pixels << '\n'
<< " output_line_bytes: " << session.output_line_bytes << '\n'
<< " output_line_bytes_raw: " << session.output_line_bytes_raw << '\n'
@@ -107,20 +153,19 @@ std::ostream& operator<<(std::ostream& out, const ScanSession& session)
<< " color_shift_lines_b: " << session.color_shift_lines_b << '\n'
<< " max_color_shift_lines: " << session.max_color_shift_lines << '\n'
<< " enable_ledadd: " << session.enable_ledadd << '\n'
+ << " stagger_x: " << session.stagger_x << '\n'
+ << " stagger_y: " << session.stagger_y << '\n'
<< " segment_count: " << session.segment_count << '\n'
<< " pixel_startx: " << session.pixel_startx << '\n'
<< " pixel_endx: " << session.pixel_endx << '\n'
+ << " pixel_count_ratio: " << session.pixel_count_ratio << '\n'
<< " conseq_pixel_dist: " << session.conseq_pixel_dist << '\n'
<< " output_segment_pixel_group_count: "
<< session.output_segment_pixel_group_count << '\n'
+ << " shading_pixel_offset: " << session.shading_pixel_offset << '\n'
<< " buffer_size_read: " << session.buffer_size_read << '\n'
- << " buffer_size_read: " << session.buffer_size_lines << '\n'
- << " buffer_size_shrink: " << session.buffer_size_shrink << '\n'
- << " buffer_size_out: " << session.buffer_size_out << '\n'
- << " filters: "
- << (session.pipeline_needs_reorder ? " reorder": "")
- << (session.pipeline_needs_ccd ? " ccd": "")
- << (session.pipeline_needs_shrink ? " shrink": "") << '\n'
+ << " enable_ledadd: " << session.enable_ledadd << '\n'
+ << " use_host_side_calib: " << session.use_host_side_calib << '\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 a697e60..f78845b 100644
--- a/backend/genesys/settings.h
+++ b/backend/genesys/settings.h
@@ -46,6 +46,8 @@
#include "enums.h"
#include "serialize.h"
+#include "utilities.h"
+#include "sensor.h"
namespace genesys {
@@ -60,9 +62,9 @@ struct Genesys_Settings
unsigned yres = 0;
//x start on scan table in mm
- double tl_x = 0;
+ float tl_x = 0;
// y start on scan table in mm
- double tl_y = 0;
+ float tl_y = 0;
// number of lines at scan resolution
unsigned int lines = 0;
@@ -79,15 +81,6 @@ struct Genesys_Settings
// true if scan is true gray, false if monochrome scan
int true_gray = 0;
- // lineart threshold
- int threshold = 0;
-
- // lineart threshold curve for dynamic rasterization
- int threshold_curve = 0;
-
- // Disable interpolation for xres<yres
- int disable_interpolation = 0;
-
// value for contrast enhancement in the [-100..100] range
int contrast = 0;
@@ -116,12 +109,13 @@ struct SetupParams {
unsigned xres = NOT_SET;
// resolution in y direction
unsigned yres = NOT_SET;
- // start pixel in X direction, from dummy_pixel + 1
+ // start pixel in X direction, from dummy_pixel + 1. Counted in terms of xres.
unsigned startx = NOT_SET;
// start pixel in Y direction, counted according to base_ydpi
unsigned starty = NOT_SET;
- // the number of pixels in X direction. Note that each logical pixel may correspond to more
- // than one CCD pixel, see CKSEL and GenesysSensor::ccd_pixels_per_system_pixel()
+ // the number of pixels in X direction. Counted in terms of xres.
+ // Note that each logical pixel may correspond to more than one CCD pixel, see CKSEL and
+ // GenesysSensor::ccd_pixels_per_system_pixel()
unsigned pixels = NOT_SET;
// the number of pixels in the X direction as requested by the frontend. This will be different
@@ -144,7 +138,7 @@ struct SetupParams {
ColorFilter color_filter = static_cast<ColorFilter>(NOT_SET);
- ScanFlag flags;
+ ScanFlag flags = ScanFlag::NONE;
unsigned get_requested_pixels() const
{
@@ -210,15 +204,10 @@ struct ScanSession {
// whether the session setup has been computed via compute_session()
bool computed = false;
- // specifies the reduction (if any) of hardware dpi on the Genesys chip side.
- // except gl646
- unsigned hwdpi_divisor = 1;
-
- // specifies the reduction (if any) of CCD effective dpi which is performed by latching the
- // data coming from CCD in such a way that 1/2 or 3/4 of pixel data is ignored.
- unsigned ccd_size_divisor = 1;
+ // specifies the full resolution of the sensor that is being used.
+ unsigned full_resolution = 0;
- // the optical resolution of the scanner.
+ // the optical resolution of the sensor that is being used.
unsigned optical_resolution = 0;
// the number of pixels at the optical resolution, not including segmentation overhead.
@@ -228,10 +217,15 @@ struct ScanSession {
// only on gl846, g847
unsigned optical_pixels_raw = 0;
+ // the number of optical scan lines. Equal to output_line_count on CCD scanners.
+ unsigned optical_line_count = 0;
+
// the resolution of the output data.
- // gl843-only
unsigned output_resolution = 0;
+ // the offset in pixels from the beginning of output data
+ unsigned output_startx = 0;
+
// the number of pixels in output data (after desegmentation)
unsigned output_pixels = 0;
@@ -259,7 +253,7 @@ struct ScanSession {
unsigned output_total_bytes = 0;
// the number of staggered lines (i.e. lines that overlap during scanning due to line being
- // thinner than the CCD element)
+ // thinner than the CCD element). Computed according to stagger_y.
unsigned num_staggered_lines = 0;
// the number of lines that color channels shift due to different physical positions of
@@ -273,6 +267,11 @@ struct ScanSession {
// actual line shift of the blue color
unsigned color_shift_lines_b = 0;
+ // The shifts that need to be applied to the output pixels in x direction.
+ StaggerConfig stagger_x;
+ // The shifts that need to be applied to the output pixels in y direction.
+ StaggerConfig stagger_y;
+
// the number of scanner segments used in the current scan
unsigned segment_count = 1;
@@ -280,8 +279,18 @@ struct ScanSession {
unsigned pixel_startx = 0;
unsigned pixel_endx = 0;
- // certain scanners require the logical pixel count to be multiplied on certain resolutions
- unsigned pixel_count_multiplier = 1;
+ /* The following defines the ratio between logical pixel count and pixel count setting sent to
+ the scanner. The ratio is affected by the following:
+
+ - Certain scanners just like to multiply the pixel number by a multiplier that depends on
+ the resolution.
+
+ - The sensor may be configured to output one value per multiple physical pixels
+
+ - The scanner will automatically average the pixels that come from the sensor using a
+ certain ratio.
+ */
+ Ratio pixel_count_ratio = Ratio{1, 1};
// Distance in pixels between consecutive pixels, e.g. between odd and even pixels. Note that
// the number of segments can be large.
@@ -297,19 +306,18 @@ struct ScanSession {
// Currently it's always zero.
unsigned output_segment_start_offset = 0;
- // the sizes of the corresponding buffers
+ // How many pixels the shading data is offset to the right from the acquired data. Calculated
+ // in shading resolution.
+ int shading_pixel_offset = 0;
+
+ // the size of the read buffer.
size_t buffer_size_read = 0;
- size_t buffer_size_lines = 0;
- size_t buffer_size_shrink = 0;
- size_t buffer_size_out = 0;
// whether to enable ledadd functionality
bool enable_ledadd = false;
- // what pipeline modifications are needed
- bool pipeline_needs_reorder = false;
- bool pipeline_needs_ccd = false;
- bool pipeline_needs_shrink = false;
+ // whether calibration should be performed host-side
+ bool use_host_side_calib = false;
void assert_computed() const
{
@@ -317,10 +325,53 @@ struct ScanSession {
throw std::runtime_error("ScanSession is not computed");
}
}
+
+ bool operator==(const ScanSession& other) const;
};
std::ostream& operator<<(std::ostream& out, const ScanSession& session);
+template<class Stream>
+void serialize(Stream& str, ScanSession& x)
+{
+ serialize(str, x.params);
+ serialize_newline(str);
+ serialize(str, x.computed);
+ serialize(str, x.full_resolution);
+ serialize(str, x.optical_resolution);
+ serialize(str, x.optical_pixels);
+ serialize(str, x.optical_pixels_raw);
+ serialize(str, x.optical_line_count);
+ serialize(str, x.output_resolution);
+ serialize(str, x.output_startx);
+ serialize(str, x.output_pixels);
+ serialize(str, x.output_channel_bytes);
+ serialize(str, x.output_line_bytes);
+ serialize(str, x.output_line_bytes_raw);
+ serialize(str, x.output_line_bytes_requested);
+ serialize(str, x.output_line_count);
+ serialize(str, x.output_total_bytes_raw);
+ serialize(str, x.output_total_bytes);
+ serialize(str, x.num_staggered_lines);
+ serialize(str, x.max_color_shift_lines);
+ serialize(str, x.color_shift_lines_r);
+ serialize(str, x.color_shift_lines_g);
+ serialize(str, x.color_shift_lines_b);
+ serialize(str, x.stagger_x);
+ serialize(str, x.stagger_y);
+ serialize(str, x.segment_count);
+ serialize(str, x.pixel_startx);
+ serialize(str, x.pixel_endx);
+ serialize(str, x.pixel_count_ratio);
+ serialize(str, x.conseq_pixel_dist);
+ serialize(str, x.output_segment_pixel_group_count);
+ serialize(str, x.output_segment_start_offset);
+ serialize(str, x.shading_pixel_offset);
+ serialize(str, x.buffer_size_read);
+ serialize(str, x.enable_ledadd);
+ serialize(str, x.use_host_side_calib);
+}
+
std::ostream& operator<<(std::ostream& out, const SANE_Parameters& params);
} // namespace genesys
diff --git a/backend/genesys/tables_frontend.cpp b/backend/genesys/tables_frontend.cpp
index 1edf32f..5eb6e3c 100644
--- a/backend/genesys/tables_frontend.cpp
+++ b/backend/genesys/tables_frontend.cpp
@@ -60,7 +60,8 @@ void genesys_init_frontend_tables()
GenesysFrontendLayout analog_devices;
analog_devices.type = FrontendType::ANALOG_DEVICES;
-
+ analog_devices.offset_addr = { 0x05, 0x06, 0x07 };
+ analog_devices.gain_addr = { 0x02, 0x03, 0x04 };
Genesys_Frontend fe;
fe.id = AdcId::WOLFSON_UMAX;
@@ -198,6 +199,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 },
@@ -218,6 +220,30 @@ void genesys_init_frontend_tables()
fe = Genesys_Frontend();
+ fe.id = AdcId::CANON_LIDE_90;
+ fe.layout = wolfson_layout;
+ fe.layout.type = FrontendType::WOLFSON;
+ fe.regs = {
+ { 0x01, 0x23 },
+ { 0x02, 0x07 },
+ { 0x03, 0x29 },
+ { 0x06, 0x0d },
+ { 0x08, 0x00 },
+ { 0x09, 0x16 },
+ { 0x20, 0x4d },
+ { 0x21, 0x4d },
+ { 0x22, 0x4d },
+ { 0x23, 0x4d },
+ { 0x28, 0x14 },
+ { 0x29, 0x14 },
+ { 0x2a, 0x14 },
+ { 0x2b, 0x14 },
+ };
+ fe.reg2 = {0x00, 0x00, 0x00};
+ s_frontends->push_back(fe);
+
+
+ fe = Genesys_Frontend();
fe.id = AdcId::AD_XP200;
fe.layout = wolfson_layout;
fe.regs = {
@@ -242,6 +268,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 +313,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 },
@@ -307,45 +335,35 @@ void genesys_init_frontend_tables()
fe = Genesys_Frontend();
fe.id = AdcId::CANON_LIDE_200;
- fe.layout = wolfson_layout;
+ fe.layout = analog_devices;
+ fe.layout.type = FrontendType::ANALOG_DEVICES_GL847;
fe.regs = {
{ 0x00, 0x9d },
{ 0x01, 0x91 },
- { 0x02, 0x00 },
- { 0x03, 0x00 },
- { 0x20, 0x00 },
- { 0x21, 0x3f },
- { 0x22, 0x00 },
- { 0x24, 0x00 },
- { 0x25, 0x00 },
- { 0x26, 0x00 },
- { 0x28, 0x32 },
- { 0x29, 0x04 },
- { 0x2a, 0x00 },
+ { 0x02, 0x32 },
+ { 0x03, 0x04 },
+ { 0x04, 0x00 },
+ { 0x05, 0x00 },
+ { 0x06, 0x3f },
+ { 0x07, 0x00 },
};
- fe.reg2 = {0x00, 0x00, 0x00};
s_frontends->push_back(fe);
fe = Genesys_Frontend();
fe.id = AdcId::CANON_LIDE_700F;
- fe.layout = wolfson_layout;
+ fe.layout = analog_devices;
+ fe.layout.type = FrontendType::ANALOG_DEVICES_GL847;
fe.regs = {
{ 0x00, 0x9d },
{ 0x01, 0x9e },
- { 0x02, 0x00 },
- { 0x03, 0x00 },
- { 0x20, 0x00 },
- { 0x21, 0x3f },
- { 0x22, 0x00 },
- { 0x24, 0x00 },
- { 0x25, 0x00 },
- { 0x26, 0x00 },
- { 0x28, 0x2f },
- { 0x29, 0x04 },
- { 0x2a, 0x00 },
+ { 0x02, 0x2f },
+ { 0x03, 0x04 },
+ { 0x04, 0x00 },
+ { 0x05, 0x00 },
+ { 0x06, 0x3f },
+ { 0x07, 0x00 },
};
- fe.reg2 = {0x00, 0x00, 0x00};
s_frontends->push_back(fe);
@@ -396,6 +414,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 +441,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 },
@@ -464,6 +484,23 @@ void genesys_init_frontend_tables()
fe = Genesys_Frontend();
+ fe.id = AdcId::PLUSTEK_OPTICFILM_7200;
+ fe.layout = analog_devices;
+ fe.regs = {
+ { 0x00, 0xf8 },
+ { 0x01, 0x80 },
+ { 0x02, 0x2e },
+ { 0x03, 0x17 },
+ { 0x04, 0x20 },
+ { 0x05, 0x0109 },
+ { 0x06, 0x01 },
+ { 0x07, 0x0104 },
+ };
+ fe.reg2 = {0x00, 0x00, 0x00};
+ s_frontends->push_back(fe);
+
+
+ fe = Genesys_Frontend();
fe.id = AdcId::PLUSTEK_OPTICFILM_7200I;
fe.layout = analog_devices;
fe.regs = {
@@ -498,6 +535,23 @@ void genesys_init_frontend_tables()
fe = Genesys_Frontend();
+ fe.id = AdcId::PLUSTEK_OPTICFILM_7400;
+ fe.layout = analog_devices;
+ fe.regs = {
+ { 0x00, 0xf8 },
+ { 0x01, 0x80 },
+ { 0x02, 0x1f },
+ { 0x03, 0x14 },
+ { 0x04, 0x19 },
+ { 0x05, 0x1b },
+ { 0x06, 0x1e },
+ { 0x07, 0x0e },
+ };
+ fe.reg2 = {0x00, 0x00, 0x00};
+ s_frontends->push_back(fe);
+
+
+ fe = Genesys_Frontend();
fe.id = AdcId::PLUSTEK_OPTICFILM_7500I;
fe.layout = analog_devices;
fe.regs = {
@@ -515,6 +569,23 @@ void genesys_init_frontend_tables()
fe = Genesys_Frontend();
+ fe.id = AdcId::PLUSTEK_OPTICFILM_8200I;
+ fe.layout = analog_devices;
+ fe.regs = {
+ { 0x00, 0xf8 },
+ { 0x01, 0x80 },
+ { 0x02, 0x28 },
+ { 0x03, 0x20 },
+ { 0x04, 0x28 },
+ { 0x05, 0x2f },
+ { 0x06, 0x2d },
+ { 0x07, 0x23 },
+ };
+ fe.reg2 = {0x00, 0x00, 0x00};
+ s_frontends->push_back(fe);
+
+
+ fe = Genesys_Frontend();
fe.id = AdcId::CANON_4400F;
fe.layout = wolfson_layout;
fe.regs = {
@@ -537,6 +608,26 @@ void genesys_init_frontend_tables()
fe = Genesys_Frontend();
+ fe.id = AdcId::CANON_5600F;
+ fe.layout = wolfson_layout;
+ fe.regs = {
+ { 0x01, 0x23 },
+ { 0x02, 0x24 },
+ { 0x03, 0x2f },
+ { 0x06, 0x00 },
+ { 0x08, 0x00 },
+ { 0x09, 0x00 },
+ { 0x20, 0x60 },
+ { 0x21, 0x60 },
+ { 0x22, 0x60 },
+ { 0x28, 0x77 },
+ { 0x29, 0x77 },
+ { 0x2a, 0x77 },
+ };
+ s_frontends->push_back(fe);
+
+
+ fe = Genesys_Frontend();
fe.id = AdcId::CANON_8400F;
fe.layout = wolfson_layout;
fe.regs = {
@@ -583,6 +674,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 +697,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 +724,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 },
diff --git a/backend/genesys/tables_gpo.cpp b/backend/genesys/tables_gpo.cpp
index 2c9ad5e..5c1c54f 100644
--- a/backend/genesys/tables_gpo.cpp
+++ b/backend/genesys/tables_gpo.cpp
@@ -131,6 +131,18 @@ void genesys_init_gpo_tables()
gpo = Genesys_Gpo();
+ gpo.id = GpioId::CANON_LIDE_90;
+ gpo.regs = {
+ { 0x6b, 0x03 },
+ { 0x6c, 0x74 },
+ { 0x6d, 0x80 },
+ { 0x6e, 0x7f },
+ { 0x6f, 0xe0 },
+ };
+ s_gpo->push_back(gpo);
+
+
+ gpo = Genesys_Gpo();
gpo.id = GpioId::XP200;
gpo.regs = {
{ 0x66, 0x30 },
@@ -188,10 +200,15 @@ void genesys_init_gpo_tables()
gpo = Genesys_Gpo();
gpo.id = GpioId::CANON_LIDE_200;
gpo.regs = {
- { 0x6c, 0xfb }, // 0xfb when idle , 0xf9/0xe9 (1200) when scanning
+ { 0x6b, 0x02 },
+ { 0x6c, 0xf9 }, // 0xfb when idle , 0xf9/0xe9 (1200) when scanning
{ 0x6d, 0x20 },
{ 0x6e, 0xff },
{ 0x6f, 0x00 },
+ { 0xa6, 0x04 },
+ { 0xa7, 0x04 },
+ { 0xa8, 0x00 },
+ { 0xa9, 0x00 },
};
s_gpo->push_back(gpo);
@@ -199,10 +216,15 @@ void genesys_init_gpo_tables()
gpo = Genesys_Gpo();
gpo.id = GpioId::CANON_LIDE_700F;
gpo.regs = {
+ { 0x6b, 0x06 },
{ 0x6c, 0xdb },
{ 0x6d, 0xff },
{ 0x6e, 0xff },
{ 0x6f, 0x80 },
+ { 0xa6, 0x15 },
+ { 0xa7, 0x07 },
+ { 0xa8, 0x20 },
+ { 0xa9, 0x10 },
};
s_gpo->push_back(gpo);
@@ -293,6 +315,19 @@ void genesys_init_gpo_tables()
gpo = Genesys_Gpo();
+ gpo.id = GpioId::PLUSTEK_OPTICFILM_7200;
+ gpo.regs = {
+ { 0x6b, 0x33 },
+ { 0x6c, 0x00 },
+ { 0x6d, 0x80 },
+ { 0x6e, 0x0c },
+ { 0x6f, 0x80 },
+ { 0x7e, 0x00 }
+ };
+ s_gpo->push_back(gpo);
+
+
+ gpo = Genesys_Gpo();
gpo.id = GpioId::PLUSTEK_OPTICFILM_7200I;
gpo.regs = {
{ 0x6c, 0x4c },
@@ -320,6 +355,16 @@ void genesys_init_gpo_tables()
};
s_gpo->push_back(gpo);
+
+ gpo = Genesys_Gpo();
+ gpo.id = GpioId::PLUSTEK_OPTICFILM_7400;
+ gpo.regs = {
+ { 0x6b, 0x30 }, { 0x6c, 0x4c }, { 0x6d, 0x80 }, { 0x6e, 0x4c }, { 0x6f, 0x80 },
+ { 0xa6, 0x00 }, { 0xa7, 0x07 }, { 0xa8, 0x20 }, { 0xa9, 0x01 },
+ };
+ s_gpo->push_back(gpo);
+
+
gpo = Genesys_Gpo();
gpo.id = GpioId::PLUSTEK_OPTICFILM_7500I;
gpo.regs = {
@@ -334,6 +379,16 @@ void genesys_init_gpo_tables()
};
s_gpo->push_back(gpo);
+
+ gpo = Genesys_Gpo();
+ gpo.id = GpioId::PLUSTEK_OPTICFILM_8200I;
+ gpo.regs = {
+ { 0x6b, 0x30 }, { 0x6c, 0x4c }, { 0x6d, 0x80 }, { 0x6e, 0x4c }, { 0x6f, 0x80 },
+ { 0xa6, 0x00 }, { 0xa7, 0x07 }, { 0xa8, 0x20 }, { 0xa9, 0x01 },
+ };
+ s_gpo->push_back(gpo);
+
+
gpo = Genesys_Gpo();
gpo.id = GpioId::CANON_4400F;
gpo.regs = {
@@ -350,6 +405,22 @@ void genesys_init_gpo_tables()
gpo = Genesys_Gpo();
+ gpo.id = GpioId::CANON_5600F;
+ gpo.regs = {
+ { 0x6b, 0x87 },
+ { 0x6c, 0xf0 },
+ { 0x6d, 0x5f },
+ { 0x6e, 0x7f },
+ { 0x6f, 0xa0 },
+ { 0xa6, 0x07 },
+ { 0xa7, 0x1c },
+ { 0xa8, 0x00 },
+ { 0xa9, 0x04 },
+ };
+ s_gpo->push_back(gpo);
+
+
+ gpo = Genesys_Gpo();
gpo.id = GpioId::CANON_8400F;
gpo.regs = {
{ 0x6c, 0x9a },
@@ -382,10 +453,8 @@ void genesys_init_gpo_tables()
gpo = Genesys_Gpo();
gpo.id = GpioId::IMG101;
gpo.regs = {
- { 0x6c, 0x41 },
- { 0x6d, 0xa4 },
- { 0x6e, 0x13 },
- { 0x6f, 0xa7 },
+ { 0x6b, 0x72 }, { 0x6c, 0x1f }, { 0x6d, 0xa4 }, { 0x6e, 0x13 }, { 0x6f, 0xa7 },
+ { 0xa6, 0x11 }, { 0xa7, 0xff }, { 0xa8, 0x19 }, { 0xa9, 0x05 },
};
s_gpo->push_back(gpo);
@@ -393,10 +462,8 @@ void genesys_init_gpo_tables()
gpo = Genesys_Gpo();
gpo.id = GpioId::PLUSTEK_OPTICBOOK_3800;
gpo.regs = {
- { 0x6c, 0x41 },
- { 0x6d, 0xa4 },
- { 0x6e, 0x13 },
- { 0x6f, 0xa7 },
+ { 0x6b, 0x30 }, { 0x6c, 0x01 }, { 0x6d, 0x80 }, { 0x6e, 0x2d }, { 0x6f, 0x80 },
+ { 0xa6, 0x0c }, { 0xa7, 0x8f }, { 0xa8, 0x08 }, { 0xa9, 0x04 },
};
s_gpo->push_back(gpo);
diff --git a/backend/genesys/tables_memory_layout.cpp b/backend/genesys/tables_memory_layout.cpp
new file mode 100644
index 0000000..3eaedd4
--- /dev/null
+++ b/backend/genesys/tables_memory_layout.cpp
@@ -0,0 +1,164 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2020 Povilas Kanapickas <povilas@radix.lt>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+*/
+
+#define DEBUG_DECLARE_ONLY
+
+#include "low.h"
+
+namespace genesys {
+
+StaticInit<std::vector<MemoryLayout>> s_memory_layout;
+
+void genesys_init_memory_layout_tables()
+{
+ s_memory_layout.init();
+
+ MemoryLayout ml;
+ ml.models = { ModelId::CANON_IMAGE_FORMULA_101 };
+ // FIXME: this scanner does not set all required registers
+ ml.regs = {
+ { 0xe0, 0x00 }, { 0xe1, 0xb0 }, { 0xe2, 0x05 }, { 0xe3, 0xe7 },
+ { 0xe4, 0x05 }, { 0xe5, 0xe8 }, { 0xe6, 0x0b }, { 0xe7, 0x1f },
+ { 0xe8, 0x0b }, { 0xe9, 0x20 },
+ };
+ s_memory_layout->push_back(ml);
+
+
+ ml = MemoryLayout();
+ ml.models = { ModelId::PLUSTEK_OPTICBOOK_3800 };
+ // FIXME: this scanner does not set all required registers
+ ml.regs = {
+ { 0xe0, 0x00 }, { 0xe1, 0x68 }, { 0xe2, 0x03 }, { 0xe3, 0x00 },
+ { 0xe4, 0x03 }, { 0xe5, 0x01 }, { 0xe6, 0x05 }, { 0xe7, 0x99 },
+ { 0xe8, 0x05 }, { 0xe9, 0x9a },
+ };
+ s_memory_layout->push_back(ml);
+
+ ml = MemoryLayout();
+ ml.models = { ModelId::PLUSTEK_OPTICFILM_7400, ModelId::PLUSTEK_OPTICFILM_8200I };
+ ml.regs = {
+ { 0x81, 0x6d }, { 0x82, 0x00 }, { 0x83, 0x00 }, { 0x84, 0x00 },
+ { 0x85, 0x00 }, { 0x86, 0x00 },
+ { 0xd0, 0x0a }, { 0xd1, 0x0a }, { 0xd2, 0x0a },
+ { 0xe0, 0x00 }, { 0xe1, 0x68 }, { 0xe2, 0x03 }, { 0xe3, 0x00 },
+ { 0xe4, 0x03 }, { 0xe5, 0x01 }, { 0xe6, 0x05 }, { 0xe7, 0x99 },
+ { 0xe8, 0x05 }, { 0xe9, 0x9a }, { 0xea, 0x08 }, { 0xeb, 0x32 },
+ { 0xec, 0x08 }, { 0xed, 0x33 }, { 0xee, 0x0a }, { 0xef, 0xcb },
+ { 0xf0, 0x0a }, { 0xf1, 0xcc }, { 0xf2, 0x0d }, { 0xf3, 0x64 },
+ { 0xf4, 0x0d }, { 0xf5, 0x65 }, { 0xf6, 0x0f }, { 0xf7, 0xfd },
+ };
+ s_memory_layout->push_back(ml);
+
+
+ /* On GL847 and GL124, the values of the base address for shading data must be multiplied by
+ 8192=0x4000 to give address on AHB
+
+ On GL847 and GL124, the values of the base address for scanned data must be multiplied by
+ 1024*2=0x0800 to give address on AHB
+ */
+ ml = MemoryLayout();
+ ml.models = { ModelId::CANON_5600F };
+ ml.regs = {
+ { 0xd0, 0x0a },
+ { 0xe0, 0x01 }, { 0xe1, 0x2c }, { 0xe2, 0x06 }, { 0xe3, 0x4e },
+ { 0xe4, 0x06 }, { 0xe5, 0x4f }, { 0xe6, 0x0b }, { 0xe7, 0x71 },
+ { 0xe8, 0x0b }, { 0xe9, 0x72 }, { 0xea, 0x10 }, { 0xeb, 0x94 },
+ { 0xec, 0x10 }, { 0xed, 0x95 }, { 0xee, 0x15 }, { 0xef, 0xb7 },
+ { 0xf0, 0x15 }, { 0xf1, 0xb8 }, { 0xf2, 0x1a }, { 0xf3, 0xda },
+ { 0xf4, 0x1a }, { 0xf5, 0xdb }, { 0xf6, 0x1f }, { 0xf7, 0xfd },
+ { 0xf8, 0x05 }
+ };
+ s_memory_layout->push_back(ml);
+
+
+ ml = MemoryLayout();
+ ml.models = { ModelId::CANON_LIDE_100 };
+ ml.regs = {
+ { 0xd0, 0x0a }, { 0xd1, 0x15 }, { 0xd2, 0x20 },
+ { 0xe0, 0x00 }, { 0xe1, 0xac }, { 0xe2, 0x02 }, { 0xe3, 0x55 },
+ { 0xe4, 0x02 }, { 0xe5, 0x56 }, { 0xe6, 0x03 }, { 0xe7, 0xff },
+ { 0xe8, 0x00 }, { 0xe9, 0xac }, { 0xea, 0x02 }, { 0xeb, 0x55 },
+ { 0xec, 0x02 }, { 0xed, 0x56 }, { 0xee, 0x03 }, { 0xef, 0xff },
+ { 0xf0, 0x00 }, { 0xf1, 0xac }, { 0xf2, 0x02 }, { 0xf3, 0x55 },
+ { 0xf4, 0x02 }, { 0xf5, 0x56 }, { 0xf6, 0x03 }, { 0xf7, 0xff },
+ };
+ s_memory_layout->push_back(ml);
+
+
+ ml = MemoryLayout();
+ ml.models = { ModelId::CANON_LIDE_200 };
+ ml.regs = {
+ { 0xd0, 0x0a }, { 0xd1, 0x1f }, { 0xd2, 0x34 },
+ { 0xe0, 0x01 }, { 0xe1, 0x24 }, { 0xe2, 0x02 }, { 0xe3, 0x91 },
+ { 0xe4, 0x02 }, { 0xe5, 0x92 }, { 0xe6, 0x03 }, { 0xe7, 0xff },
+ { 0xe8, 0x01 }, { 0xe9, 0x24 }, { 0xea, 0x02 }, { 0xeb, 0x91 },
+ { 0xec, 0x02 }, { 0xed, 0x92 }, { 0xee, 0x03 }, { 0xef, 0xff },
+ { 0xf0, 0x01 }, { 0xf1, 0x24 }, { 0xf2, 0x02 }, { 0xf3, 0x91 },
+ { 0xf4, 0x02 }, { 0xf5, 0x92 }, { 0xf6, 0x03 }, { 0xf7, 0xff },
+ };
+ s_memory_layout->push_back(ml);
+
+
+ ml = MemoryLayout();
+ ml.models = { ModelId::CANON_LIDE_700F };
+ ml.regs = {
+ { 0xd0, 0x0a }, { 0xd1, 0x33 }, { 0xd2, 0x5c },
+ { 0xe0, 0x02 }, { 0xe1, 0x14 }, { 0xe2, 0x09 }, { 0xe3, 0x09 },
+ { 0xe4, 0x09 }, { 0xe5, 0x0a }, { 0xe6, 0x0f }, { 0xe7, 0xff },
+ { 0xe8, 0x02 }, { 0xe9, 0x14 }, { 0xea, 0x09 }, { 0xeb, 0x09 },
+ { 0xec, 0x09 }, { 0xed, 0x0a }, { 0xee, 0x0f }, { 0xef, 0xff },
+ { 0xf0, 0x02 }, { 0xf1, 0x14 }, { 0xf2, 0x09 }, { 0xf3, 0x09 },
+ { 0xf4, 0x09 }, { 0xf5, 0x0a }, { 0xf6, 0x0f }, { 0xf7, 0xff },
+ };
+ s_memory_layout->push_back(ml);
+
+
+ ml = MemoryLayout();
+ ml.models = { ModelId::CANON_LIDE_110, ModelId::CANON_LIDE_120 };
+ ml.regs = {
+ { 0xd0, 0x0a }, { 0xd1, 0x15 }, { 0xd2, 0x20 },
+ { 0xe0, 0x00 }, { 0xe1, 0xac }, { 0xe2, 0x08 }, { 0xe3, 0x55 },
+ { 0xe4, 0x08 }, { 0xe5, 0x56 }, { 0xe6, 0x0f }, { 0xe7, 0xff },
+ { 0xe8, 0x00 }, { 0xe9, 0xac }, { 0xea, 0x08 }, { 0xeb, 0x55 },
+ { 0xec, 0x08 }, { 0xed, 0x56 }, { 0xee, 0x0f }, { 0xef, 0xff },
+ { 0xf0, 0x00 }, { 0xf1, 0xac }, { 0xf2, 0x08 }, { 0xf3, 0x55 },
+ { 0xf4, 0x08 }, { 0xf5, 0x56 }, { 0xf6, 0x0f }, { 0xf7, 0xff },
+
+ };
+ s_memory_layout->push_back(ml);
+
+
+ ml = MemoryLayout();
+ ml.models = { ModelId::CANON_LIDE_210, ModelId::CANON_LIDE_220 };
+ ml.regs = {
+ { 0xd0, 0x0a }, { 0xd1, 0x1f }, { 0xd2, 0x34 },
+ { 0xe0, 0x01 }, { 0xe1, 0x24 }, { 0xe2, 0x08 }, { 0xe3, 0x91 },
+ { 0xe4, 0x08 }, { 0xe5, 0x92 }, { 0xe6, 0x0f }, { 0xe7, 0xff },
+ { 0xe8, 0x01 }, { 0xe9, 0x24 }, { 0xea, 0x08 }, { 0xeb, 0x91 },
+ { 0xec, 0x08 }, { 0xed, 0x92 }, { 0xee, 0x0f }, { 0xef, 0xff },
+ { 0xf0, 0x01 }, { 0xf1, 0x24 }, { 0xf2, 0x08 }, { 0xf3, 0x91 },
+ { 0xf4, 0x08 }, { 0xf5, 0x92 }, { 0xf6, 0x0f }, { 0xf7, 0xff },
+ };
+ s_memory_layout->push_back(ml);
+}
+
+} // namespace genesys
diff --git a/backend/genesys/tables_model.cpp b/backend/genesys/tables_model.cpp
index 0b3a0af..2c5e6a3 100644
--- a/backend/genesys/tables_model.cpp
+++ b/backend/genesys/tables_model.cpp
@@ -58,10 +58,44 @@
namespace genesys {
-StaticInit<std::vector<Genesys_USB_Device_Entry>> s_usb_devices;
+StaticInit<std::vector<UsbDeviceEntry>> s_usb_devices;
void genesys_init_usb_device_tables()
{
+ /* Guidelines on calibration area sizes
+ ------------------------------------
+
+ on many scanners scanning a single line takes aroung 10ms. In order not to take excessive
+ amount of time, the sizes of the calibration area are limited as follows:
+ 2400 dpi or less: 4mm (would take ~4 seconds on 2400 dpi)
+ 4800 dpi or less: 3mm (would take ~6 seconds on 4800 dpi)
+ anything more: 2mm (would take ~7 seconds on 9600 dpi)
+
+ Optional properties
+ -------------------
+
+ All fields of the Genesys_Model class are defined even if they use default value, with
+ the following exceptions:
+
+ If the scanner does not have ScanMethod::TRANSPARENCY or ScanMethod::TRANSPARENCY_INFRARED,
+ the following properties are optional:
+
+ model.x_offset_ta = 0.0;
+ model.y_offset_ta = 0.0;
+ model.x_size_ta = 0.0;
+ model.y_size_ta = 0.0;
+
+ model.y_offset_sensor_to_ta = 0.0;
+ model.y_offset_calib_white_ta = 0.0;
+ model.y_size_calib_ta_mm = 0.0;
+
+ If the scanner does not have ModelFlag::DARK_WHITE_CALIBRATION, then the following
+ properties are optional:
+
+ model.y_offset_calib_dark_white_mm = 0.0;
+ model.y_size_calib_dark_white_mm = 0.0;
+ */
+
s_usb_devices.init();
Genesys_Model model;
@@ -87,15 +121,9 @@ void genesys_init_usb_device_tables()
model.y_size = 299.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 1.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 228.6;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -112,10 +140,8 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_UMAX;
model.gpio_id = GpioId::UMAX;
model.motor_id = MotorId::UMAX;
- model.flags = GENESYS_FLAG_UNTESTED;
+ model.flags = ModelFlag::UNTESTED;
model.buttons = GENESYS_HAS_NO_BUTTONS;
- model.shading_lines = 20;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x0638, 0x0a10, model);
@@ -144,17 +170,13 @@ void genesys_init_usb_device_tables()
model.x_size = 218.0;
model.y_size = 299.0;
- model.y_offset_calib_white = 6.0;
+ model.y_offset_calib_white = 3.0;
+ model.y_size_calib_mm = 3.0;
+ model.y_offset_calib_dark_white_mm = 1.0;
+ model.y_size_calib_dark_white_mm = 6.0;
+ model.x_size_calib_mm = 220.13334;
model.x_offset_calib_black = 0.0;
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
-
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -170,16 +192,12 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_35;
model.gpio_id = GpioId::CANON_LIDE_35;
model.motor_id = MotorId::CANON_LIDE_35;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_WHITE_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_WHITE_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_FILE_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_COPY_SW;
- model.shading_lines = 280;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x2213, model);
@@ -209,15 +227,9 @@ void genesys_init_usb_device_tables()
model.y_size = 300.0;
model.y_offset_calib_white = 9.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 0.0;
- model.y_size_ta = 0.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 227.584;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -234,12 +246,8 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::KVSS080;
model.gpio_id = GpioId::KVSS080;
model.motor_id = MotorId::KVSS080;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x04da, 0x100f, model);
@@ -269,15 +277,9 @@ void genesys_init_usb_device_tables()
model.y_size = 314.5;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 226.9067;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -294,13 +296,10 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::G4050;
model.gpio_id = GpioId::G4050;
model.motor_id = MotorId::G4050;
- model.flags = GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x03f0, 0x1b05, model);
@@ -329,15 +328,9 @@ void genesys_init_usb_device_tables()
model.y_size = 315.0;
model.y_offset_calib_white = 3.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 226.9067;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -353,13 +346,10 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::G4050;
model.gpio_id = GpioId::G4050;
model.motor_id = MotorId::G4050;
- model.flags = GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x03f0, 0x4505, model);
@@ -389,15 +379,9 @@ void genesys_init_usb_device_tables()
model.y_size = 315.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 8.0;
- model.y_offset_ta = 13.00;
- model.x_size_ta = 217.9;
- model.y_size_ta = 250.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 40.0;
+ model.x_size_calib_mm = 226.9067;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -414,13 +398,10 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::G4050;
model.gpio_id = GpioId::G4050;
model.motor_id = MotorId::G4050;
- model.flags = GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x03f0, 0x4605, model);
@@ -438,6 +419,10 @@ void genesys_init_usb_device_tables()
{ ScanMethod::FLATBED },
{ 1200, 600, 300 },
{ 1200, 600, 300 },
+ }, {
+ { ScanMethod::TRANSPARENCY },
+ { 4800, 2400, 1200 },
+ { 9600, 4800, 2400, 1200 },
}
};
@@ -445,20 +430,23 @@ void genesys_init_usb_device_tables()
model.bpp_color_values = { 8, 16 };
model.x_offset = 6.0;
- model.y_offset = 12.00;
+ model.y_offset = 10.00;
model.x_size = 215.9;
model.y_size = 297.0;
- model.y_offset_calib_white = 0.0;
+ model.y_offset_calib_white = 2.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
+ model.x_size_calib_mm = 241.3;
- model.x_offset_ta = 8.0;
- model.y_offset_ta = 13.00;
- model.x_size_ta = 217.9;
- model.y_size_ta = 250.0;
+ model.x_offset_ta = 115.0;
+ model.y_offset_ta = 37.0;
+ model.x_size_ta = 35.0;
+ model.y_size_ta = 230.0;
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 40.0;
+ model.y_offset_sensor_to_ta = 23.0;
+ model.y_offset_calib_white_ta = 24.0;
+ model.y_size_calib_ta_mm = 2.0;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -475,15 +463,13 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_4400F;
model.gpio_id = GpioId::CANON_4400F;
model.motor_id = MotorId::CANON_4400F;
- model.flags = GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_FULL_HWDPI_MODE |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SHADING_REPARK;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::UTA_NO_SECONDARY_MOTOR;
+
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x04a9, 0x2228, model);
@@ -515,13 +501,15 @@ void genesys_init_usb_device_tables()
model.bpp_gray_values = { 8, 16 };
model.bpp_color_values = { 8, 16 };
- model.x_offset = 3.5;
+ model.x_offset = 5.5;
model.y_offset = 17.00;
model.x_size = 219.9;
model.y_size = 300.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 10.0;
+ model.x_size_calib_mm = 225.425;
model.x_offset_ta = 75.0;
model.y_offset_ta = 45.00;
@@ -530,6 +518,7 @@ void genesys_init_usb_device_tables()
model.y_offset_sensor_to_ta = 22.0;
model.y_offset_calib_white_ta = 25.0;
+ model.y_size_calib_ta_mm = 3.0;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -546,17 +535,11 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_8400F;
model.gpio_id = GpioId::CANON_8400F;
model.motor_id = MotorId::CANON_8400F;
- model.flags = GENESYS_FLAG_HAS_UTA |
- GENESYS_FLAG_HAS_UTA_INFRARED |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_FULL_HWDPI_MODE |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SHADING_REPARK;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::SHADING_REPARK;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
- model.shading_lines = 100;
- model.shading_ta_lines = 50;
model.search_lines = 100;
s_usb_devices->emplace_back(0x04a9, 0x221e, model);
@@ -590,15 +573,18 @@ void genesys_init_usb_device_tables()
model.y_size = 297.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 8.0;
+ model.x_size_calib_mm = 240.70734;
- model.x_offset_ta = 85.0;
- model.y_offset_ta = 26.0;
+ model.x_offset_ta = 97.0;
+ model.y_offset_ta = 38.5;
model.x_size_ta = 70.0;
model.y_size_ta = 230.0;
- model.y_offset_sensor_to_ta = 11.5;
- model.y_offset_calib_white_ta = 14.0;
+ model.y_offset_sensor_to_ta = 23.0;
+ model.y_offset_calib_white_ta = 25.5;
+ model.y_size_calib_ta_mm = 3.0;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -615,17 +601,11 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_8600F;
model.gpio_id = GpioId::CANON_8600F;
model.motor_id = MotorId::CANON_8600F;
- model.flags = GENESYS_FLAG_HAS_UTA |
- GENESYS_FLAG_HAS_UTA_INFRARED |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_FULL_HWDPI_MODE |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SHADING_REPARK;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::SHADING_REPARK;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
- model.shading_lines = 50;
- model.shading_ta_lines = 50;
model.search_lines = 100;
s_usb_devices->emplace_back(0x04a9, 0x2229, model);
@@ -654,16 +634,10 @@ void genesys_init_usb_device_tables()
model.x_size = 216.07;
model.y_size = 299.0;
- model.y_offset_calib_white = 1.0;
+ model.y_offset_calib_white = 0.4233334;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 217.4241;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -680,18 +654,14 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_200;
model.gpio_id = GpioId::CANON_LIDE_200;
model.motor_id = MotorId::CANON_LIDE_100;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_SIS_SENSOR |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::SIS_SENSOR |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW;
- model.shading_lines = 50;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x1904, model);
@@ -721,15 +691,9 @@ void genesys_init_usb_device_tables()
model.y_size = 300.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 218.7787;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -745,17 +709,13 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_110;
model.gpio_id = GpioId::CANON_LIDE_110;
model.motor_id = MotorId::CANON_LIDE_110;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW;
- model.shading_lines = 25;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x1909, model);
@@ -785,15 +745,9 @@ void genesys_init_usb_device_tables()
model.y_size = 300.0;
model.y_offset_calib_white = 1.0;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 216.0694;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -808,17 +762,13 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_120;
model.gpio_id = GpioId::CANON_LIDE_120;
model.motor_id = MotorId::CANON_LIDE_120;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW;
- model.shading_lines = 50;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x190e, model);
@@ -834,30 +784,23 @@ void genesys_init_usb_device_tables()
model.resolutions = {
{
{ ScanMethod::FLATBED },
- // BUG: 4800 resolution crashes
- { /*4800,*/ 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
- { /*4800,*/ 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
+ { 4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
+ { 4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
}
};
model.bpp_gray_values = { 8, 16 };
model.bpp_color_values = { 8, 16 };
- model.x_offset = 2.2;
+ model.x_offset = 2.1;
model.y_offset = 8.7;
model.x_size = 216.70;
model.y_size = 297.5;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 218.7787;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -874,18 +817,14 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_110;
model.gpio_id = GpioId::CANON_LIDE_210;
model.motor_id = MotorId::CANON_LIDE_210;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW |
GENESYS_HAS_EXTRA_SW;
- model.shading_lines = 60;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x190a, model);
@@ -901,30 +840,23 @@ void genesys_init_usb_device_tables()
model.resolutions = {
{
{ ScanMethod::FLATBED },
- // BUG: 4800 resolution crashes
- { /*4800,*/ 2400, 1200, 600, 300, 150, 100, 75 },
- { /*4800,*/ 2400, 1200, 600, 300, 150, 100, 75 },
+ { 4800, 2400, 1200, 600, 300, 150, 100, 75 },
+ { 4800, 2400, 1200, 600, 300, 150, 100, 75 },
}
};
model.bpp_gray_values = { 8, 16 };
model.bpp_color_values = { 8, 16 };
- model.x_offset = 2.2;
+ model.x_offset = 2.1;
model.y_offset = 8.7;
model.x_size = 216.70;
model.y_size = 297.5;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 218.7787;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -940,84 +872,84 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_110;
model.gpio_id = GpioId::CANON_LIDE_210;
model.motor_id = MotorId::CANON_LIDE_210;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW |
GENESYS_HAS_EXTRA_SW;
- model.shading_lines = 60;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x190f, model);
model = Genesys_Model();
- model.name = "canon-5600f";
+ model.name = "canon-canoscan-5600f";
model.vendor = "Canon";
- model.model = "5600F";
+ model.model = "CanoScan 5600F";
model.model_id = ModelId::CANON_5600F;
model.asic_type = AsicType::GL847;
model.resolutions = {
{
- { ScanMethod::FLATBED },
- { 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 75 },
- { 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 75 },
+ { ScanMethod::FLATBED, ScanMethod::TRANSPARENCY },
+ { 4800, 2400, 1200, 600, 300, /*150*/ },
+ { 4800, 2400, 1200, 600, 300, /*150*/ },
}
};
model.bpp_gray_values = { 8, 16 };
model.bpp_color_values = { 8, 16 };
- model.x_offset = 1.1;
- model.y_offset = 8.3;
- model.x_size = 216.07;
- model.y_size = 299.0;
+ model.x_offset = 1.5;
+ model.y_offset = 10.4;
+ model.x_size = 219.00;
+ model.y_size = 305.0;
- model.y_offset_calib_white = 3.0;
+ model.y_offset_calib_white = 2.0;
+ model.y_size_calib_mm = 2.0;
model.x_offset_calib_black = 0.0;
+ model.x_size_calib_mm = 220.5;
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
+ model.x_offset_ta = 93.0;
+ model.y_offset_ta = 42.4;
+ model.x_size_ta = 35.0;
+ model.y_size_ta = 230.0;
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.y_offset_sensor_to_ta = 0;
+ model.y_offset_calib_white_ta = 21.4;
+ model.y_size_calib_ta_mm = 1.0;
model.post_scan = 0.0;
model.eject_feed = 0.0;
model.ld_shift_r = 0;
- model.ld_shift_g = 0;
- model.ld_shift_b = 0;
+ model.ld_shift_g = 32;
+ model.ld_shift_b = 64;
model.line_mode_color_order = ColorOrder::RGB;
- model.is_cis = true;
+ model.is_cis = false;
model.is_sheetfed = false;
- model.sensor_id = SensorId::CIS_CANON_LIDE_200;
- model.adc_id = AdcId::CANON_LIDE_200;
- model.gpio_id = GpioId::CANON_LIDE_200;
- model.motor_id = MotorId::CANON_LIDE_200;
- model.flags = GENESYS_FLAG_UNTESTED |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_SIS_SENSOR |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.sensor_id = SensorId::CCD_CANON_5600F;
+ model.adc_id = AdcId::CANON_5600F;
+ model.gpio_id = GpioId::CANON_5600F;
+ model.motor_id = MotorId::CANON_5600F;
+ model.flags = ModelFlag::SIS_SENSOR |
+ ModelFlag::INVERT_PIXEL_DATA |
+ ModelFlag::DISABLE_ADC_CALIBRATION |
+ ModelFlag::DISABLE_EXPOSURE_CALIBRATION |
+ ModelFlag::HOST_SIDE_CALIBRATION_COMPLETE_SCAN |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::UTA_NO_SECONDARY_MOTOR |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW;
- model.shading_lines = 50;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x1906, model);
@@ -1032,9 +964,10 @@ void genesys_init_usb_device_tables()
model.resolutions = {
{
+ // FIXME: support 2400 ad 4800 dpi
{ ScanMethod::FLATBED },
- { 4800, 2400, 1200, 600, 300, 200, 150, 100, 75 },
- { 4800, 2400, 1200, 600, 300, 200, 150, 100, 75 },
+ { 1200, 600, 300, 200, 150, 100, 75 },
+ { 1200, 600, 300, 200, 150, 100, 75 },
}
};
@@ -1046,16 +979,11 @@ void genesys_init_usb_device_tables()
model.x_size = 216.07;
model.y_size = 297.0;
- model.y_offset_calib_white = 1.0;
+ model.y_offset_calib_white = 0.4233334;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 0.0;
+ model.x_size_calib_mm = 219.6254;
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1071,18 +999,14 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_700F;
model.gpio_id = GpioId::CANON_LIDE_700F;
model.motor_id = MotorId::CANON_LIDE_700;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_SIS_SENSOR |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::SIS_SENSOR |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW;
- model.shading_lines = 70;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x1907, model);
@@ -1111,16 +1035,10 @@ void genesys_init_usb_device_tables()
model.x_size = 216.07;
model.y_size = 299.0;
- model.y_offset_calib_white = 0.0;
+ model.y_offset_calib_white = 0.4233334;
+ model.y_size_calib_mm = 3.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 217.4241;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1136,18 +1054,14 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_200;
model.gpio_id = GpioId::CANON_LIDE_200;
model.motor_id = MotorId::CANON_LIDE_200;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_SIS_SENSOR |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::SIS_SENSOR |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_FILE_SW;
- model.shading_lines = 50;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x1905, model);
@@ -1176,16 +1090,12 @@ void genesys_init_usb_device_tables()
model.x_size = 218.0;
model.y_size = 299.0;
- model.y_offset_calib_white = 6.0;
+ model.y_offset_calib_white = 3.0;
+ model.y_size_calib_mm = 3.0;
+ model.y_offset_calib_dark_white_mm = 1.0;
+ model.y_size_calib_dark_white_mm = 6.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.13334;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1197,23 +1107,18 @@ void genesys_init_usb_device_tables()
model.is_cis = true;
model.is_sheetfed = false;
- model.sensor_id = SensorId::CIS_CANON_LIDE_35;
+ model.sensor_id = SensorId::CIS_CANON_LIDE_60;
model.adc_id = AdcId::CANON_LIDE_35;
model.gpio_id = GpioId::CANON_LIDE_35;
- model.motor_id = MotorId::CANON_LIDE_35;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_WHITE_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.motor_id = MotorId::CANON_LIDE_60;
+ model.flags = ModelFlag::DARK_WHITE_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_COPY_SW |
GENESYS_HAS_SCAN_SW |
GENESYS_HAS_FILE_SW |
GENESYS_HAS_EMAIL_SW;
- model.shading_lines = 300;
- model.shading_ta_lines = 0;
model.search_lines = 400;
- // this is completely untested
s_usb_devices->emplace_back(0x04a9, 0x221c, model);
@@ -1240,15 +1145,11 @@ void genesys_init_usb_device_tables()
model.y_size = 299.0;
model.y_offset_calib_white = 4.5;
+ model.y_size_calib_mm = 3.0;
+ model.y_offset_calib_dark_white_mm = 1.0;
+ model.y_size_calib_dark_white_mm = 6.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 216.7467;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1265,22 +1166,77 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_80;
model.gpio_id = GpioId::CANON_LIDE_80;
model.motor_id = MotorId::CANON_LIDE_80;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_WHITE_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_WHITE_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW |
GENESYS_HAS_FILE_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_COPY_SW;
- model.shading_lines = 160;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a9, 0x2214, model);
model = Genesys_Model();
+ model.name = "canon-lide-90";
+ model.vendor = "Canon";
+ model.model = "LiDE 90";
+ model.model_id = ModelId::CANON_LIDE_90;
+ model.asic_type = AsicType::GL842;
+
+ model.resolutions = {
+ {
+ { ScanMethod::FLATBED },
+ { 2400, 1200, 600, 300 },
+ { 2400, 1200, 600, 300 },
+ }
+ };
+
+ model.bpp_gray_values = { 8, 16 };
+ model.bpp_color_values = { 8, 16 };
+ model.x_offset = 3.50;
+ model.y_offset = 9.0;
+ model.x_size = 219.0;
+ model.y_size = 299.0;
+
+ model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 2.0;
+ model.y_offset_calib_dark_white_mm = 0.0;
+ model.y_size_calib_dark_white_mm = 0.0;
+ model.x_offset_calib_black = 0.0;
+ model.x_size_calib_mm = 221.5;
+
+ model.post_scan = 0.0;
+ model.eject_feed = 0.0;
+
+ model.ld_shift_r = 0;
+ model.ld_shift_g = 0;
+ model.ld_shift_b = 0;
+
+ model.line_mode_color_order = ColorOrder::RGB;
+
+ model.is_cis = true;
+ model.is_sheetfed = false;
+ model.sensor_id = SensorId::CIS_CANON_LIDE_90;
+ model.adc_id = AdcId::CANON_LIDE_90;
+ model.gpio_id = GpioId::CANON_LIDE_90;
+ model.motor_id = MotorId::CANON_LIDE_90;
+ model.flags = ModelFlag::DISABLE_ADC_CALIBRATION |
+ ModelFlag::HOST_SIDE_CALIBRATION_COMPLETE_SCAN |
+ ModelFlag::USE_CONSTANT_FOR_DARK_CALIBRATION |
+ ModelFlag::DISABLE_FAST_FEEDING |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::CUSTOM_GAMMA;
+ model.buttons = GENESYS_HAS_SCAN_SW |
+ GENESYS_HAS_FILE_SW |
+ GENESYS_HAS_EMAIL_SW |
+ GENESYS_HAS_COPY_SW;
+ model.search_lines = 400;
+
+ s_usb_devices->emplace_back(0x04a9, 0x1900, model);
+
+
+ model = Genesys_Model();
model.name = "hewlett-packard-scanjet-2300c";
model.vendor = "Hewlett Packard";
model.model = "ScanJet 2300c";
@@ -1298,27 +1254,21 @@ void genesys_init_usb_device_tables()
model.bpp_gray_values = { 8, 16 };
model.bpp_color_values = { 8, 16 };
- model.x_offset = 2.0;
- model.y_offset = 7.5;
+ model.x_offset = 6.5;
+ model.y_offset = 8;
model.x_size = 215.9;
model.y_size = 295.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 1.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 227.2454;
model.post_scan = 0.0;
model.eject_feed = 0.0;
- model.ld_shift_r = 16;
- model.ld_shift_g = 8;
+ model.ld_shift_r = 32;
+ model.ld_shift_g = 16;
model.ld_shift_b = 0;
model.line_mode_color_order = ColorOrder::RGB;
@@ -1328,15 +1278,10 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_HP2300;
model.gpio_id = GpioId::HP2300;
model.motor_id = MotorId::HP2300;
- model.flags = GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_SEARCH_START |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::GAMMA_14BIT |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW;
- model.shading_lines = 40;
- model.shading_ta_lines = 0;
model.search_lines = 132;
s_usb_devices->emplace_back(0x03f0, 0x0901, model);
@@ -1366,15 +1311,9 @@ void genesys_init_usb_device_tables()
model.y_size = 297.2;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 2.0; // FIXME: check if white area is really so small
model.x_offset_calib_black = 1.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 230.1241;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1391,14 +1330,10 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_HP2400;
model.gpio_id = GpioId::HP2400;
model.motor_id = MotorId::HP2400;
- model.flags = GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::GAMMA_14BIT |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW;
- model.shading_lines = 20;
- model.shading_ta_lines = 0;
model.search_lines = 132;
s_usb_devices->emplace_back(0x03f0, 0x0a01, model);
@@ -1428,15 +1363,9 @@ void genesys_init_usb_device_tables()
model.y_size = 297.2;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.1334;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1453,14 +1382,10 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::AD_XP200;
model.gpio_id = GpioId::XP200;
model.motor_id = MotorId::XP200;
- model.flags = GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION;
+ model.flags = ModelFlag::GAMMA_14BIT |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 120;
- model.shading_ta_lines = 0;
model.search_lines = 132;
s_usb_devices->emplace_back(0x04a7, 0x0426, model);
@@ -1490,15 +1415,9 @@ void genesys_init_usb_device_tables()
model.y_size = 300.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 1.0;
-
- model.x_offset_ta = 104.0;
- model.y_offset_ta = 55.6;
- model.x_size_ta = 25.6;
- model.y_size_ta = 78.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 76.0;
+ model.x_size_calib_mm = 230.1241;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1515,14 +1434,11 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_HP3670;
model.gpio_id = GpioId::HP3670;
model.motor_id = MotorId::HP3670;
- model.flags = GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_XPA |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::GAMMA_14BIT |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW;
- model.shading_lines = 20;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x03f0, 0x1405, model);
@@ -1552,15 +1468,9 @@ void genesys_init_usb_device_tables()
model.y_size = 299.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 1.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 229.2774;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1577,10 +1487,8 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_ST12;
model.gpio_id = GpioId::ST12;
model.motor_id = MotorId::UMAX;
- model.flags = GENESYS_FLAG_UNTESTED | GENESYS_FLAG_14BIT_GAMMA;
+ model.flags = ModelFlag::UNTESTED | ModelFlag::GAMMA_14BIT;
model.buttons = GENESYS_HAS_NO_BUTTONS;
- model.shading_lines = 20;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x07b3, 0x0600, model);
@@ -1604,20 +1512,14 @@ void genesys_init_usb_device_tables()
model.bpp_color_values = { 8, 16 };
model.x_offset = 3.5;
- model.y_offset = 7.5;
+ model.y_offset = 7.5; // FIXME: incorrect, needs updating
model.x_size = 218.0;
model.y_size = 299.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 1.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 228.6;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -1634,14 +1536,10 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_ST24;
model.gpio_id = GpioId::ST24;
model.motor_id = MotorId::ST24;
- model.flags = GENESYS_FLAG_UNTESTED |
- GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SEARCH_START |
- GENESYS_FLAG_OFFSET_CALIBRATION;
+ model.flags = ModelFlag::UNTESTED |
+ ModelFlag::GAMMA_14BIT |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_NO_BUTTONS;
- model.shading_lines = 20;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x07b3, 0x0601, model);
@@ -1665,26 +1563,20 @@ void genesys_init_usb_device_tables()
model.bpp_color_values = { 8, 16 };
model.x_offset = 0.30;
- model.y_offset = 0.80;
+ model.y_offset = 4.0; // FIXME: incorrect, needs updating
model.x_size = 220.0;
model.y_size = 296.4;
model.y_offset_calib_white = 0.00;
+ model.y_size_calib_mm = 2.0;
model.x_offset_calib_black = 0.00;
-
- model.x_offset_ta = 0.00;
- model.y_offset_ta = 0.00;
- model.x_size_ta = 0.00;
- model.y_size_ta = 0.00;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.00;
+ model.x_size_calib_mm = 230.1241;
model.post_scan = 0.0;
model.eject_feed = 0.0;
- model.ld_shift_r = 48;
- model.ld_shift_g = 24;
+ model.ld_shift_r = 96;
+ model.ld_shift_g = 48;
model.ld_shift_b = 0;
model.line_mode_color_order = ColorOrder::RGB;
@@ -1694,19 +1586,15 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_5345;
model.gpio_id = GpioId::MD_5345;
model.motor_id = MotorId::MD_5345;
- model.flags = GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_SEARCH_START |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_SHADING_NO_MOVE |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::GAMMA_14BIT |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_POWER_SW |
GENESYS_HAS_OCR_SW |
GENESYS_HAS_SCAN_SW;
- model.shading_lines = 40;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x0461, 0x0377, model);
@@ -1735,15 +1623,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 433.4934;
model.post_scan = 26.5;
// this is larger than needed -- accounts for second sensor head, which is a calibration item
@@ -1760,13 +1642,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::XP300;
model.motor_id = MotorId::XP300;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a7, 0x0474, model);
@@ -1795,15 +1673,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 105.664;
model.post_scan = 17.5;
model.eject_feed = 0.0;
@@ -1820,13 +1692,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::DP665;
model.motor_id = MotorId::DP665;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x0a82, 0x4803, model);
@@ -1855,15 +1723,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.1334;
model.post_scan = 16.0;
model.eject_feed = 0.0;
@@ -1880,13 +1742,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::DP665;
model.motor_id = MotorId::ROADWARRIOR;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a7, 0x0494, model);
@@ -1915,15 +1773,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.1334;
model.post_scan = 16.0;
model.eject_feed = 0.0;
@@ -1940,13 +1792,12 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::DP665;
model.motor_id = MotorId::ROADWARRIOR;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_NO_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_UNTESTED;
+ model.flags = ModelFlag::DISABLE_ADC_CALIBRATION |
+ ModelFlag::DISABLE_EXPOSURE_CALIBRATION |
+ ModelFlag::DISABLE_SHADING_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::UNTESTED;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW;
- model.shading_lines = 300;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x0a82, 0x4802, model);
@@ -1976,15 +1827,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.1334;
model.post_scan = 16.0;
model.eject_feed = 0.0;
@@ -2001,13 +1846,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::DP665;
model.motor_id = MotorId::ROADWARRIOR;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a7, 0x049b, model);
@@ -2036,15 +1877,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.1334;
model.post_scan = 16.0;
model.eject_feed = 0.0;
@@ -2061,13 +1896,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_DSM600;
model.gpio_id = GpioId::DP665;
model.motor_id = MotorId::DSMOBILE_600;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x0a17, 0x3210, model);
@@ -2098,15 +1929,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.1334;
model.post_scan = 16.0;
model.eject_feed = 0.0;
@@ -2122,13 +1947,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_DSM600;
model.gpio_id = GpioId::DP665;
model.motor_id = MotorId::DSMOBILE_600;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x1dcc, 0x4812, model);
@@ -2157,15 +1978,9 @@ void genesys_init_usb_device_tables()
model.y_size = 500;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 212.5134;
model.post_scan = 26.5;
// this is larger than needed -- accounts for second sensor head, which is a calibration item
@@ -2182,13 +1997,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_DSM600;
model.gpio_id = GpioId::DP685;
model.motor_id = MotorId::XP300;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
@@ -2219,15 +2030,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 433.4934;
model.post_scan = 26.5;
// this is larger than needed -- accounts for second sensor head, which is a calibration item
@@ -2244,13 +2049,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::XP300;
model.motor_id = MotorId::XP300;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x0a82, 0x4800, model);
@@ -2280,19 +2081,14 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 433.4934;
model.post_scan = 26.5;
// this is larger than needed -- accounts for second sensor head, which is a calibration item
model.eject_feed = 0.0;
+
model.ld_shift_r = 0;
model.ld_shift_g = 0;
model.ld_shift_b = 0;
@@ -2301,18 +2097,14 @@ void genesys_init_usb_device_tables()
model.is_cis = true;
model.is_sheetfed = true;
- model.sensor_id = SensorId::CCD_XP300;
+ model.sensor_id = SensorId::CCD_DOCKETPORT_487;
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::XP300;
model.motor_id = MotorId::XP300;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_UNTESTED;
+ model.flags = ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::UNTESTED;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x1dcc, 0x4810, model);
@@ -2337,26 +2129,20 @@ void genesys_init_usb_device_tables()
model.bpp_color_values = { 8, 16 };
model.x_offset = 4.00;
- model.y_offset = 0.80;
+ model.y_offset = 5.0; // FIXME: incorrect, needs updating
model.x_size = 215.9;
model.y_size = 296.4;
model.y_offset_calib_white = 0.00;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.00;
-
- model.x_offset_ta = 0.00;
- model.y_offset_ta = 0.00;
- model.x_size_ta = 0.00;
- model.y_size_ta = 0.00;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.00;
+ model.x_size_calib_mm = 230.1241;
model.post_scan = 0.0;
model.eject_feed = 0.0;
- model.ld_shift_r = 48;
- model.ld_shift_g = 24;
+ model.ld_shift_r = 96;
+ model.ld_shift_g = 48;
model.ld_shift_b = 0;
model.line_mode_color_order = ColorOrder::RGB;
@@ -2366,18 +2152,15 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_5345;
model.gpio_id = GpioId::MD_5345;
model.motor_id = MotorId::MD_5345;
- model.flags = GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_SEARCH_START |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::GAMMA_14BIT |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_POWER_SW |
GENESYS_HAS_OCR_SW |
GENESYS_HAS_SCAN_SW;
- model.shading_lines = 40;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x04a7, 0x0229, model);
@@ -2402,26 +2185,20 @@ void genesys_init_usb_device_tables()
model.bpp_color_values = { 8, 16 };
model.x_offset = 4.00;
- model.y_offset = 0.80;
+ model.y_offset = 5.0; // FIXME: incorrect, needs updating
model.x_size = 215.9;
model.y_size = 296.4;
model.y_offset_calib_white = 0.00;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.00;
-
- model.x_offset_ta = 0.00;
- model.y_offset_ta = 0.00;
- model.x_size_ta = 0.00;
- model.y_size_ta = 0.00;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.00;
+ model.x_size_calib_mm = 230.1241;
model.post_scan = 0.0;
model.eject_feed = 0.0;
- model.ld_shift_r = 48;
- model.ld_shift_g = 24;
+ model.ld_shift_r = 96;
+ model.ld_shift_g = 48;
model.ld_shift_b = 0;
model.line_mode_color_order = ColorOrder::RGB;
@@ -2431,18 +2208,15 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_5345;
model.gpio_id = GpioId::MD_5345;
model.motor_id = MotorId::MD_5345;
- model.flags = GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_SEARCH_START |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::GAMMA_14BIT |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_COPY_SW |
GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_POWER_SW |
GENESYS_HAS_OCR_SW |
GENESYS_HAS_SCAN_SW;
- model.shading_lines = 40;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x0461, 0x038b, model);
@@ -2472,15 +2246,9 @@ void genesys_init_usb_device_tables()
model.y_size = 511;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 220.1334;
model.post_scan = 16.0;
model.eject_feed = 0.0;
@@ -2497,13 +2265,9 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::WOLFSON_XP300;
model.gpio_id = GpioId::DP665;
model.motor_id = MotorId::ROADWARRIOR;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 400;
s_usb_devices->emplace_back(0x04a7, 0x04ac, model);
@@ -2533,15 +2297,9 @@ void genesys_init_usb_device_tables()
model.y_size = 297.0;
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 0.0;
- model.y_size_ta = 0.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 213.7834;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -2558,19 +2316,81 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::PLUSTEK_OPTICPRO_3600;
model.gpio_id = GpioId::PLUSTEK_OPTICPRO_3600;
model.motor_id = MotorId::PLUSTEK_OPTICPRO_3600;
- model.flags = GENESYS_FLAG_UNTESTED | // not fully working yet
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION;
+ model.flags = ModelFlag::UNTESTED | // not fully working yet
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION;
model.buttons = GENESYS_HAS_NO_BUTTONS;
- model.shading_lines = 7;
- model.shading_ta_lines = 0;
model.search_lines = 200;
s_usb_devices->emplace_back(0x07b3, 0x0900, model);
+
+ model = Genesys_Model();
+ model.name = "plustek-opticfilm-7200";
+ model.vendor = "PLUSTEK";
+ model.model = "OpticFilm 7200";
+ model.model_id = ModelId::PLUSTEK_OPTICFILM_7200;
+ model.asic_type = AsicType::GL842;
+
+ model.resolutions = {
+ {
+ { ScanMethod::TRANSPARENCY },
+ { 7200, 3600, 1800, 900 },
+ { 7200, 3600, 1800, 900 },
+ }
+ };
+
+ model.bpp_gray_values = { 16 };
+ model.bpp_color_values = { 16 };
+ model.default_method = ScanMethod::TRANSPARENCY;
+
+ model.x_offset = 0.0;
+ model.y_offset = 0.0;
+ model.x_size = 36.0;
+ model.y_size = 44.0;
+
+ model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 0.0;
+ model.x_offset_calib_black = 6.5;
+ model.x_size_calib_mm = 35.9834;
+
+ model.x_offset_ta = 0.7f;
+ model.y_offset_ta = 28.0;
+ model.x_size_ta = 36.0;
+ model.y_size_ta = 25.0;
+
+ model.y_offset_sensor_to_ta = 0.0;
+ model.y_offset_calib_black_ta = 6.5;
+ model.y_offset_calib_white_ta = 0.0;
+ model.y_size_calib_ta_mm = 2.0;
+
+ model.post_scan = 0.0;
+ model.eject_feed = 0.0;
+
+ model.ld_shift_r = 0;
+ model.ld_shift_g = 12;
+ model.ld_shift_b = 24;
+
+ model.line_mode_color_order = ColorOrder::RGB;
+
+ model.is_cis = false;
+ model.is_sheetfed = false;
+
+ model.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7200;
+ model.adc_id = AdcId::PLUSTEK_OPTICFILM_7200;
+ model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7200;
+ model.motor_id = MotorId::PLUSTEK_OPTICFILM_7200;
+
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK;
+
+ model.search_lines = 200;
+ s_usb_devices->emplace_back(0x07b3, 0x0807, model);
+
+
model = Genesys_Model();
model.name = "plustek-opticfilm-7200i";
model.vendor = "PLUSTEK";
@@ -2594,16 +2414,22 @@ void genesys_init_usb_device_tables()
model.y_offset = 0.0;
model.x_size = 36.0;
model.y_size = 44.0;
+
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 0.0;
model.x_offset_calib_black = 6.5;
+ model.x_size_calib_mm = 35.9834;
model.x_offset_ta = 0.0;
model.y_offset_ta = 29.0;
model.x_size_ta = 36.0;
model.y_size_ta = 24.0;
+
model.y_offset_sensor_to_ta = 0.0;
model.y_offset_calib_black_ta = 6.5;
model.y_offset_calib_white_ta = 0.0;
+ model.y_size_calib_ta_mm = 2.0;
+
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -2621,23 +2447,29 @@ void genesys_init_usb_device_tables()
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7200I;
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7200I;
- model.flags = GENESYS_FLAG_HAS_UTA |
- GENESYS_FLAG_HAS_UTA_INFRARED |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_HAS_NO_BUTTONS |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CALIBRATION_HOST_SIDE |
- GENESYS_FLAG_16BIT_DATA_INVERTED;
-
- model.shading_lines = 7;
- model.shading_ta_lines = 50;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK |
+ ModelFlag::SWAP_16BIT_DATA;
+
model.search_lines = 200;
s_usb_devices->emplace_back(0x07b3, 0x0c04, model);
+ // same as 7200i, just without the infrared channel
+ model.name = "plustek-opticfilm-7200-v2";
+ model.model = "OpticFilm 7200 v2";
+ model.resolutions = {
+ {
+ { ScanMethod::TRANSPARENCY },
+ { 7200, 3600, 1800, 900 },
+ { 7200, 3600, 1800, 900 },
+ }
+ };
+ s_usb_devices->emplace_back(0x07b3, 0x0c07, model);
+
+
model = Genesys_Model();
model.name = "plustek-opticfilm-7300";
model.vendor = "PLUSTEK";
@@ -2661,16 +2493,22 @@ void genesys_init_usb_device_tables()
model.y_offset = 0.0;
model.x_size = 36.0;
model.y_size = 44.0;
+
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 0.0;
model.x_offset_calib_black = 6.5;
+ model.x_size_calib_mm = 35.9834;
model.x_offset_ta = 0.0;
model.y_offset_ta = 29.0;
model.x_size_ta = 36.0;
model.y_size_ta = 24.0;
+
model.y_offset_sensor_to_ta = 0.0;
model.y_offset_calib_black_ta = 6.5;
model.y_offset_calib_white_ta = 0.0;
+ model.y_size_calib_ta_mm = 2.0;
+
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -2688,21 +2526,91 @@ void genesys_init_usb_device_tables()
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7300;
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7300;
- model.flags = GENESYS_FLAG_HAS_UTA |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_HAS_NO_BUTTONS |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CALIBRATION_HOST_SIDE;
-
- model.shading_lines = 7;
- model.shading_ta_lines = 50;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK;
+
model.search_lines = 200;
s_usb_devices->emplace_back(0x07b3, 0x0c12, model);
+ // same as 7300, same USB ID as 7400-v2
+ model.name = "plustek-opticfilm-7400-v1";
+ model.model = "OpticFilm 7400 (v1)";
+ s_usb_devices->emplace_back(0x07b3, 0x0c3a, 0x0400, model);
+
+
+ model = Genesys_Model();
+ model.name = "plustek-opticfilm-7400-v2";
+ model.vendor = "PLUSTEK";
+ model.model = "OpticFilm 7400 (v2)";
+ model.model_id = ModelId::PLUSTEK_OPTICFILM_7400;
+ model.asic_type = AsicType::GL845;
+
+ model.resolutions = {
+ {
+ { ScanMethod::TRANSPARENCY },
+ { 7200, 3600, 2400, 1200, 600 },
+ { 7200, 3600, 2400, 1200, 600 },
+ }
+ };
+
+ model.bpp_gray_values = { 16 };
+ model.bpp_color_values = { 16 };
+ model.default_method = ScanMethod::TRANSPARENCY;
+
+ model.x_offset = 0.0;
+ model.y_offset = 0.0;
+ model.x_size = 36.0;
+ model.y_size = 44.0;
+
+ model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 0.0;
+ model.x_offset_calib_black = 6.5;
+ model.x_size_calib_mm = 36.83;
+
+ model.x_offset_ta = 0.5;
+ model.y_offset_ta = 29.0;
+ model.x_size_ta = 36.33;
+ model.y_size_ta = 25.0;
+
+ model.y_offset_sensor_to_ta = 0.0;
+ model.y_offset_calib_black_ta = 6.5;
+ model.y_offset_calib_white_ta = 0.0;
+ model.y_size_calib_ta_mm = 2.0;
+
+ model.post_scan = 0.0;
+ model.eject_feed = 0.0;
+
+ model.ld_shift_r = 0;
+ model.ld_shift_g = 12;
+ model.ld_shift_b = 24;
+
+ model.line_mode_color_order = ColorOrder::RGB;
+
+ model.is_cis = false;
+ model.is_sheetfed = false;
+
+ model.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7400;
+ model.adc_id = AdcId::PLUSTEK_OPTICFILM_7400;
+ model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7400;
+ model.motor_id = MotorId::PLUSTEK_OPTICFILM_7400;
+
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK;
+
+ model.search_lines = 200;
+ s_usb_devices->emplace_back(0x07b3, 0x0c3a, 0x0605, model);
+
+
+ // same as 7400-v2
+ model.name = "plustek-opticfilm-8100";
+ model.model = "OpticFilm 8100";
+ s_usb_devices->emplace_back(0x07b3, 0x130c, model);
+
+
model = Genesys_Model();
model.name = "plustek-opticfilm-7500i";
model.vendor = "PLUSTEK";
@@ -2726,16 +2634,22 @@ void genesys_init_usb_device_tables()
model.y_offset = 0.0;
model.x_size = 36.0;
model.y_size = 44.0;
+
model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 0.0;
model.x_offset_calib_black = 6.5;
model.x_offset_ta = 0.0;
model.y_offset_ta = 29.0;
model.x_size_ta = 36.0;
model.y_size_ta = 24.0;
+ model.x_size_calib_mm = 35.9834;
+
model.y_offset_sensor_to_ta = 0.0;
model.y_offset_calib_black_ta = 6.5;
model.y_offset_calib_white_ta = 0.0;
+ model.y_size_calib_ta_mm = 2.0;
+
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -2753,22 +2667,91 @@ void genesys_init_usb_device_tables()
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7500I;
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7500I;
- model.flags = GENESYS_FLAG_HAS_UTA |
- GENESYS_FLAG_HAS_UTA_INFRARED |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_HAS_NO_BUTTONS |
- GENESYS_FLAG_SHADING_REPARK |
- GENESYS_FLAG_CALIBRATION_HOST_SIDE;
-
- model.shading_lines = 7;
- model.shading_ta_lines = 50;
+ model.flags = ModelFlag::WARMUP |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK;
+
model.search_lines = 200;
s_usb_devices->emplace_back(0x07b3, 0x0c13, model);
+ // same as 7500i
+ model.name = "plustek-opticfilm-7600i-v1";
+ model.model = "OpticFilm 7600i (v1)";
+ s_usb_devices->emplace_back(0x07b3, 0x0c3b, 0x0400, model);
+
+
+ model = Genesys_Model();
+ model.name = "plustek-opticfilm-8200i";
+ model.vendor = "PLUSTEK";
+ model.model = "OpticFilm 8200i";
+ model.model_id = ModelId::PLUSTEK_OPTICFILM_8200I;
+ model.asic_type = AsicType::GL845;
+
+ model.resolutions = {
+ {
+ { ScanMethod::TRANSPARENCY, ScanMethod::TRANSPARENCY_INFRARED },
+ { 7200, 3600, 1800, 900 },
+ { 7200, 3600, 1800, 900 },
+ }
+ };
+
+ model.bpp_gray_values = { 16 };
+ model.bpp_color_values = { 16 };
+ model.default_method = ScanMethod::TRANSPARENCY;
+
+ model.x_offset = 0.0;
+ model.y_offset = 0.0;
+ model.x_size = 36.0;
+ model.y_size = 44.0;
+
+ model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 0.0;
+ model.x_offset_calib_black = 6.5;
+ model.x_size_calib_mm = 36.83;
+
+ model.x_offset_ta = 0.5;
+ model.y_offset_ta = 28.5;
+ model.x_size_ta = 36.33;
+ model.y_size_ta = 25.0;
+
+ model.y_offset_sensor_to_ta = 0.0;
+ model.y_offset_calib_black_ta = 6.5;
+ model.y_offset_calib_white_ta = 0.0;
+ model.y_size_calib_ta_mm = 2.0;
+
+ model.post_scan = 0.0;
+ model.eject_feed = 0.0;
+
+ model.ld_shift_r = 0;
+ model.ld_shift_g = 12;
+ model.ld_shift_b = 24;
+
+ model.line_mode_color_order = ColorOrder::RGB;
+
+ model.is_cis = false;
+ model.is_sheetfed = false;
+
+ model.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_8200I;
+ model.adc_id = AdcId::PLUSTEK_OPTICFILM_8200I;
+ model.gpio_id = GpioId::PLUSTEK_OPTICFILM_8200I;
+ model.motor_id = MotorId::PLUSTEK_OPTICFILM_8200I;
+
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::SHADING_REPARK;
+
+ model.search_lines = 200;
+ s_usb_devices->emplace_back(0x07b3, 0x130d, model);
+
+
+ // same as 8200i
+ model.name = "plustek-opticfilm-7600i-v2";
+ model.model = "OpticFilm 7600i (v2)";
+ s_usb_devices->emplace_back(0x07b3, 0x0c3b, 0x0605, model);
+
+
model = Genesys_Model();
model.name = "hewlett-packard-scanjet-N6310";
model.vendor = "Hewlett Packard";
@@ -2792,16 +2775,10 @@ void genesys_init_usb_device_tables()
model.x_size = 216;
model.y_size = 511;
- model.y_offset_calib_white = 3.0;
+ model.y_offset_calib_white = 0.0;
+ model.y_size_calib_mm = 4.0; // FIXME: y_offset is liely incorrect
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 100.0;
- model.y_size_ta = 100.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0;
+ model.x_size_calib_mm = 452.12;
model.post_scan = 0;
model.eject_feed = 0;
@@ -2818,17 +2795,15 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::CANON_LIDE_200; // Not defined yet for N6310
model.gpio_id = GpioId::HP_N6310;
model.motor_id = MotorId::CANON_LIDE_200; // Not defined yet for N6310
- model.flags = GENESYS_FLAG_UNTESTED |
- GENESYS_FLAG_14BIT_GAMMA |
- GENESYS_FLAG_DARK_CALIBRATION |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_NO_CALIBRATION;
+ model.flags = ModelFlag::UNTESTED |
+ ModelFlag::GAMMA_14BIT |
+ ModelFlag::DARK_CALIBRATION |
+ ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::DISABLE_ADC_CALIBRATION |
+ ModelFlag::DISABLE_EXPOSURE_CALIBRATION |
+ ModelFlag::DISABLE_SHADING_CALIBRATION;
model.buttons = GENESYS_HAS_NO_BUTTONS;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x03f0, 0x4705, model);
@@ -2858,15 +2833,9 @@ void genesys_init_usb_device_tables()
model.y_size = 300.0;
model.y_offset_calib_white = 9.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 0.0;
- model.y_size_ta = 0.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 215.9;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -2883,12 +2852,8 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::PLUSTEK_OPTICBOOK_3800;
model.gpio_id = GpioId::PLUSTEK_OPTICBOOK_3800;
model.motor_id = MotorId::PLUSTEK_OPTICBOOK_3800;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA;
+ model.flags = ModelFlag::CUSTOM_GAMMA;
model.buttons = GENESYS_HAS_NO_BUTTONS; // TODO there are 4 buttons to support
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x07b3, 0x1300, model);
@@ -2918,15 +2883,9 @@ void genesys_init_usb_device_tables()
model.y_size = 300.0;
model.y_offset_calib_white = 9.0;
+ model.y_size_calib_mm = 4.0;
model.x_offset_calib_black = 0.0;
-
- model.x_offset_ta = 0.0;
- model.y_offset_ta = 0.0;
- model.x_size_ta = 0.0;
- model.y_size_ta = 0.0;
-
- model.y_offset_sensor_to_ta = 0.0;
- model.y_offset_calib_white_ta = 0.0;
+ model.x_size_calib_mm = 228.6;
model.post_scan = 0.0;
model.eject_feed = 0.0;
@@ -2943,16 +2902,36 @@ void genesys_init_usb_device_tables()
model.adc_id = AdcId::IMG101;
model.gpio_id = GpioId::IMG101;
model.motor_id = MotorId::IMG101;
- model.flags = GENESYS_FLAG_SKIP_WARMUP |
- GENESYS_FLAG_OFFSET_CALIBRATION |
- GENESYS_FLAG_CUSTOM_GAMMA |
- GENESYS_FLAG_UNTESTED;
+ model.flags = ModelFlag::CUSTOM_GAMMA |
+ ModelFlag::UNTESTED;
model.buttons = GENESYS_HAS_NO_BUTTONS ;
- model.shading_lines = 100;
- model.shading_ta_lines = 0;
model.search_lines = 100;
s_usb_devices->emplace_back(0x1083, 0x162e, model);
- }
+}
+
+void verify_usb_device_tables()
+{
+ for (const auto& device : *s_usb_devices) {
+ const auto& model = device.model();
+
+ if (model.x_size_calib_mm == 0.0f) {
+ throw SaneException("Calibration width can't be zero");
+ }
+
+ if (model.has_method(ScanMethod::FLATBED)) {
+ if (model.y_size_calib_mm == 0.0f) {
+ throw SaneException("Calibration size can't be zero");
+ }
+ }
+ if (model.has_method(ScanMethod::TRANSPARENCY) ||
+ model.has_method(ScanMethod::TRANSPARENCY_INFRARED))
+ {
+ if (model.y_size_calib_ta_mm == 0.0f) {
+ throw SaneException("Calibration size can't be zero");
+ }
+ }
+ }
+}
} // namespace genesys
diff --git a/backend/genesys/tables_motor.cpp b/backend/genesys/tables_motor.cpp
index 2484d2d..a452fe5 100644
--- a/backend/genesys/tables_motor.cpp
+++ b/backend/genesys/tables_motor.cpp
@@ -53,272 +53,586 @@ void genesys_init_motor_tables()
{
s_motors.init();
+ MotorProfile profile;
+
Genesys_Motor motor;
motor.id = MotorId::UMAX;
- motor.base_ydpi = 1200;
- motor.optical_ydpi = 2400;
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
+ motor.base_ydpi = 2400;
+ motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::FULL, 0});
+ motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::HALF, 0});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::MD_5345; // MD5345/6228/6471
- motor.base_ydpi = 1200;
- motor.optical_ydpi = 2400;
- motor.slopes.push_back(MotorSlope::create_from_steps(2000, 1375, 128));
- motor.slopes.push_back(MotorSlope::create_from_steps(2000, 1375, 128));
+ motor.base_ydpi = 2400;
+ motor.profiles.push_back({MotorSlope::create_from_steps(2000, 1375, 128), StepType::FULL, 0});
+ motor.profiles.push_back({MotorSlope::create_from_steps(2000, 1375, 128), StepType::HALF, 0});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::ST24;
motor.base_ydpi = 2400;
- motor.optical_ydpi = 2400;
- motor.slopes.push_back(MotorSlope::create_from_steps(2289, 2100, 128));
- motor.slopes.push_back(MotorSlope::create_from_steps(2289, 2100, 128));
+ motor.profiles.push_back({MotorSlope::create_from_steps(2289, 2100, 128), StepType::FULL, 0});
+ motor.profiles.push_back({MotorSlope::create_from_steps(2289, 2100, 128), StepType::HALF, 0});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::HP3670;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 1200;
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
+ motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::FULL, 0});
+ motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::HALF, 0});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::HP2400;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 1200;
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
+ motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::FULL, 0});
+ motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::HALF, 0});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::HP2300;
- motor.base_ydpi = 600;
- motor.optical_ydpi = 1200;
- motor.slopes.push_back(MotorSlope::create_from_steps(3200, 1200, 128));
- motor.slopes.push_back(MotorSlope::create_from_steps(3200, 1200, 128));
+ motor.base_ydpi = 1200;
+ motor.profiles.push_back({MotorSlope::create_from_steps(3200, 1200, 128), StepType::FULL, 0});
+ motor.profiles.push_back({MotorSlope::create_from_steps(3200, 1200, 128), StepType::HALF, 0});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_35;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 2400;
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1400, 60));
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 150), StepType::HALF, 0};
+ profile.resolutions = { 75, 150, 200, 300, 600 };
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 150), StepType::QUARTER, 0};
+ profile.resolutions = { 1200, 2400 };
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 1400, 150), StepType::FULL, 0};
+ profile.resolutions = { 75, 150, 200, 300 };
+ motor.fast_profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(6000, 3000, 100), StepType::FULL, 0};
+ profile.resolutions = { 600, 1200, 2400 };
+ motor.fast_profiles.push_back(profile);
+
+ s_motors->push_back(std::move(motor));
+
+
+ motor = Genesys_Motor();
+ motor.id = MotorId::CANON_LIDE_60;
+ motor.base_ydpi = 1200;
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 1400, 150), StepType::HALF, 0};
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 1400, 150), StepType::FULL, 0};
+ profile.resolutions = { 75, 150, 300 };
+ motor.fast_profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(6000, 3000, 100), StepType::FULL, 0};
+ profile.resolutions = { 600, 1200, 2400 };
+ motor.fast_profiles.push_back(profile);
+
+ s_motors->push_back(std::move(motor));
+
+
+ motor = Genesys_Motor();
+ motor.id = MotorId::CANON_LIDE_90;
+ motor.base_ydpi = 1200;
+ profile = {MotorSlope::create_from_steps(8000, 3000, 200), StepType::FULL, 0};
+ profile.resolutions = { 150, 300 };
+ motor.profiles.push_back(profile);
+
+ profile = {MotorSlope::create_from_steps(7000, 3000, 200), StepType::HALF, 0};
+ profile.resolutions = { 600, 1200 };
+ motor.profiles.push_back(profile);
+
+ profile = {MotorSlope::create_from_steps(7000, 3000, 200), StepType::QUARTER, 0};
+ profile.resolutions = { 2400 };
+ motor.profiles.push_back(profile);
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::XP200;
motor.base_ydpi = 600;
- motor.optical_ydpi = 600;
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
+ motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0});
+ motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::HALF, 0});
+ motor.fast_profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::XP300;
motor.base_ydpi = 300;
- motor.optical_ydpi = 600;
// works best with GPIO10, GPIO14 off
- motor.slopes.push_back(MotorSlope::create_from_steps(3700, 3700, 2));
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
+ profile = MotorProfile{MotorSlope::create_from_steps(3700, 3700, 2), StepType::FULL, 0};
+ profile.resolutions = {}; // used during fast moves
+ motor.profiles.push_back(profile);
+
+ // FIXME: this motor profile is useless
+ profile = MotorProfile{MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0};
+ profile.resolutions = {75, 150, 300, 600};
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3700, 3700, 2), StepType::FULL, 0};
+ motor.fast_profiles.push_back(profile);
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::DP665;
motor.base_ydpi = 750;
- motor.optical_ydpi = 1500;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 2500, 10));
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3000, 2500, 10), StepType::FULL, 0};
+ profile.resolutions = {75, 150};
+ motor.profiles.push_back(profile);
+
+ // FIXME: this motor profile is useless
+ profile = MotorProfile{MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0};
+ profile.resolutions = {300, 600, 1200};
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3000, 2500, 10), StepType::FULL, 0};
+ motor.fast_profiles.push_back(profile);
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::ROADWARRIOR;
motor.base_ydpi = 750;
- motor.optical_ydpi = 1500;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 2600, 10));
- motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3000, 2600, 10), StepType::FULL, 0};
+ profile.resolutions = {75, 150};
+ motor.profiles.push_back(profile);
+
+ // FIXME: this motor profile is useless
+ profile = MotorProfile{MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0};
+ profile.resolutions = {300, 600, 1200};
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3000, 2600, 10), StepType::FULL, 0};
+ motor.fast_profiles.push_back(profile);
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::DSMOBILE_600;
motor.base_ydpi = 750;
- motor.optical_ydpi = 1500;
- motor.slopes.push_back(MotorSlope::create_from_steps(6666, 3700, 8));
- motor.slopes.push_back(MotorSlope::create_from_steps(6666, 3700, 8));
+
+ profile = MotorProfile{MotorSlope::create_from_steps(6666, 3700, 8), StepType::FULL, 0};
+ profile.resolutions = {75, 150};
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(6666, 3700, 8), StepType::HALF, 0};
+ profile.resolutions = {300, 600, 1200};
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(6666, 3700, 8), StepType::FULL, 0};
+ motor.fast_profiles.push_back(profile);
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_100;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 6400;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
- motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 255),
+ StepType::HALF, 1432});
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 279),
+ StepType::QUARTER, 2712});
+ motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
+ StepType::EIGHTH, 5280});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_200;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 6400;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
- motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 255),
+ StepType::HALF, 1432});
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 279),
+ StepType::QUARTER, 2712});
+ motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
+ StepType::EIGHTH, 5280});
+ motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
+ StepType::EIGHTH, 10416});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_700;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 6400;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
- motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
+ StepType::HALF, 1424});
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
+ StepType::HALF, 1504});
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 2022, 127),
+ StepType::HALF, 2696});
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
+ StepType::HALF, 2848});
+ motor.profiles.push_back({MotorSlope::create_from_steps(46876, 15864, 2),
+ StepType::EIGHTH, 10576});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::KVSS080;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 1200;
- motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
+ motor.profiles.push_back({MotorSlope::create_from_steps(44444, 500, 489),
+ StepType::HALF, 8000});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::G4050;
motor.base_ydpi = 2400;
- motor.optical_ydpi = 9600;
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
+ motor.profiles.push_back({MotorSlope::create_from_steps(7842, 320, 602),
+ StepType::HALF, 8016});
+ motor.profiles.push_back({MotorSlope::create_from_steps(9422, 254, 1004),
+ StepType::HALF, 15624});
+ motor.profiles.push_back({MotorSlope::create_from_steps(28032, 2238, 604),
+ StepType::HALF, 56064});
+ motor.profiles.push_back({MotorSlope::create_from_steps(42752, 1706, 610),
+ StepType::QUARTER, 42752});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_4400F;
motor.base_ydpi = 2400;
- motor.optical_ydpi = 9600;
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(28597 * 2, 727 * 2, 200);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 1;
+ profile.resolutions = { 300, 600 };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(28597 * 2, 727 * 2, 200);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ profile.resolutions = { 1200, 2400, 4800, 9600 };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(28597 * 2, 279 * 2, 1000);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ motor.fast_profiles.push_back(std::move(profile));
+
+ s_motors->push_back(std::move(motor));
+
+
+ motor = Genesys_Motor();
+ motor.id = MotorId::CANON_5600F;
+ motor.base_ydpi = 2400;
+
+ // FIXME: real limit is 134, but for some reason the motor can't acquire that speed.
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(2500 * 2, 134 * 2, 1000);
+ profile.step_type = StepType::HALF;
+ profile.motor_vref = 0;
+ profile.resolutions = { 75, 150 };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(2500 * 2, 200 * 2, 1000);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ profile.resolutions = { 300, 600, 1200, 2400, 4800 };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(2500 * 2, 200 * 2, 1000);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ motor.fast_profiles.push_back(std::move(profile));
+
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_8400F;
motor.base_ydpi = 1600;
- motor.optical_ydpi = 6400;
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(20202 * 4, 333 * 4, 100);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ profile.resolutions = VALUE_FILTER_ANY;
+ profile.scan_methods = { ScanMethod::FLATBED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 100);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 2;
+ profile.resolutions = VALUE_FILTER_ANY;
+ profile.scan_methods = { ScanMethod::TRANSPARENCY, ScanMethod::TRANSPARENCY_INFRARED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 200);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 2;
+ profile.resolutions = VALUE_FILTER_ANY;
+ profile.scan_methods = VALUE_FILTER_ANY;
+ motor.fast_profiles.push_back(std::move(profile));
+
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_8600F;
motor.base_ydpi = 2400;
- motor.optical_ydpi = 9600;
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
- motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 3;
+ profile.resolutions = { 300, 600 };
+ profile.scan_methods = { ScanMethod::FLATBED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 2;
+ profile.resolutions = { 1200, 2400 };
+ profile.scan_methods = { ScanMethod::FLATBED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 2;
+ profile.resolutions = { 4800 };
+ profile.scan_methods = { ScanMethod::FLATBED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 2;
+ profile.resolutions = { 300, 600 };
+ profile.scan_methods = { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 1;
+ profile.resolutions = { 1200, 2400 };
+ profile.scan_methods = { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ profile.resolutions = { 4800 };
+ profile.scan_methods = { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED };
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(59240, 582, 1020);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 2;
+ motor.fast_profiles.push_back(std::move(profile));
+
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_110;
motor.base_ydpi = 4800;
- motor.optical_ydpi = 9600;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 255),
+ StepType::FULL, 2768});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 469),
+ StepType::HALF, 5360});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2632, 3),
+ StepType::HALF, 10528});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 3),
+ StepType::QUARTER, 20864});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_120;
motor.base_ydpi = 4800;
- motor.optical_ydpi = 9600;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 864, 127),
+ StepType::FULL, 4608});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2010, 63),
+ StepType::HALF, 5360});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62464, 2632, 3),
+ StepType::QUARTER, 10528});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62592, 10432, 5),
+ StepType::QUARTER, 20864});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_210;
motor.base_ydpi = 4800;
- motor.optical_ydpi = 9600;
- motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 255),
+ StepType::FULL, 2768});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 469),
+ StepType::HALF, 5360});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2632, 3),
+ StepType::HALF, 10528});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 4),
+ StepType::QUARTER, 20864});
+ motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 4),
+ StepType::EIGHTH, 41536});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::PLUSTEK_OPTICPRO_3600;
motor.base_ydpi = 1200;
- motor.optical_ydpi = 2400;
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0};
+ profile.resolutions = {75, 100, 150, 200};
+ motor.profiles.push_back(profile);
+
+ // FIXME: this motor profile is almost useless
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 3250, 60), StepType::HALF, 0};
+ profile.resolutions = {300, 400, 600, 1200};
+ motor.profiles.push_back(profile);
+
+ profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0};
+ motor.fast_profiles.push_back(profile);
+ s_motors->push_back(std::move(motor));
+
+
+ motor = Genesys_Motor();
+ motor.id = MotorId::PLUSTEK_OPTICFILM_7200;
+ motor.base_ydpi = 3600;
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(20000 * 2, 600 * 2, 200);
+ profile.step_type = StepType::HALF;
+ profile.motor_vref = 0;
+ motor.profiles.push_back(std::move(profile));
+
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::PLUSTEK_OPTICFILM_7200I;
motor.base_ydpi = 3600;
- motor.optical_ydpi = 3600;
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(34722 * 2, 454 * 2, 40);
+ profile.step_type = StepType::HALF;
+ profile.motor_vref = 3;
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(34722 * 2, 454 * 2, 40);
+ profile.step_type = StepType::HALF;
+ profile.motor_vref = 0;
+ motor.fast_profiles.push_back(std::move(profile));
+
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::PLUSTEK_OPTICFILM_7300;
motor.base_ydpi = 3600;
- motor.optical_ydpi = 3600;
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 3;
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ motor.fast_profiles.push_back(std::move(profile));
+
+ s_motors->push_back(std::move(motor));
+
+
+ motor = Genesys_Motor();
+ motor.id = MotorId::PLUSTEK_OPTICFILM_7400;
+ motor.base_ydpi = 3600;
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(64102 * 4, 400 * 4, 30);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 3;
+ motor.profiles.push_back(profile);
+ motor.fast_profiles.push_back(profile);
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::PLUSTEK_OPTICFILM_7500I;
motor.base_ydpi = 3600;
- motor.optical_ydpi = 3600;
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 3;
+ motor.profiles.push_back(std::move(profile));
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 0;
+ motor.fast_profiles.push_back(std::move(profile));
+
+ s_motors->push_back(std::move(motor));
+
+
+ motor = Genesys_Motor();
+ motor.id = MotorId::PLUSTEK_OPTICFILM_8200I;
+ motor.base_ydpi = 3600;
+
+ profile = MotorProfile();
+ profile.slope = MotorSlope::create_from_steps(64102 * 4, 400 * 4, 100);
+ profile.step_type = StepType::QUARTER;
+ profile.motor_vref = 3;
+ motor.profiles.push_back(profile);
+ motor.fast_profiles.push_back(profile);
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::IMG101;
motor.base_ydpi = 600;
- motor.optical_ydpi = 1200;
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
+ motor.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
+ StepType::HALF, 11000});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::PLUSTEK_OPTICBOOK_3800;
motor.base_ydpi = 600;
- motor.optical_ydpi = 1200;
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
- motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
+ motor.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
+ StepType::HALF, 11000});
s_motors->push_back(std::move(motor));
motor = Genesys_Motor();
motor.id = MotorId::CANON_LIDE_80;
motor.base_ydpi = 2400;
- motor.optical_ydpi = 4800; // 9600
- motor.slopes.push_back(MotorSlope::create_from_steps(9560, 1912, 31));
+ motor.profiles.push_back({MotorSlope::create_from_steps(9560, 1912, 31), StepType::FULL, 0});
s_motors->push_back(std::move(motor));
}
diff --git a/backend/genesys/tables_motor_profile.cpp b/backend/genesys/tables_motor_profile.cpp
deleted file mode 100644
index 18f7271..0000000
--- a/backend/genesys/tables_motor_profile.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-/* sane - Scanner Access Now Easy.
-
- Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
-
- This file is part of the SANE package.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
-
- As a special exception, the authors of SANE give permission for
- additional uses of the libraries contained in this release of SANE.
-
- The exception is that, if you link a SANE library with other files
- to produce an executable, this does not by itself cause the
- resulting executable to be covered by the GNU General Public
- License. Your use of that executable is in no way restricted on
- account of linking the SANE library code into it.
-
- This exception does not, however, invalidate any other reasons why
- the executable file might be covered by the GNU General Public
- License.
-
- If you submit changes to SANE to the maintainers to be included in
- a subsequent release, you agree by submitting the changes that
- those changes may be distributed with this exception intact.
-
- If you write modifications of your own for SANE, it is your choice
- whether to permit this exception to apply to your modifications.
- If you do not wish that, delete this exception notice.
-*/
-
-#define DEBUG_DECLARE_ONLY
-
-#include "low.h"
-
-namespace genesys {
-
-StaticInit<std::vector<Motor_Profile>> gl843_motor_profiles;
-
-void genesys_init_motor_profile_tables_gl843()
-{
- gl843_motor_profiles.init();
-
- auto profile = Motor_Profile();
- profile.motor_id = MotorId::KVSS080;
- profile.exposure = 8000;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(44444, 500, 489);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::G4050;
- profile.exposure = 8016;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(7842, 320, 602);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::G4050;
- profile.exposure = 15624;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(9422, 254, 1004);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::G4050;
- profile.exposure = 42752;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(42752, 1706, 610);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::G4050;
- profile.exposure = 56064;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(28032, 2238, 604);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_4400F;
- profile.exposure = 11640;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(49152, 484, 1014);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_8400F;
- profile.exposure = 50000;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(8743, 300, 794);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_8600F;
- profile.exposure = 0x59d8;
- profile.step_type = StepType::QUARTER;
- // FIXME: if the exposure is lower then we'll select another motor
- profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7200I;
- profile.exposure = 0;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(39682, 1191, 15);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7300;
- profile.exposure = 0x2f44;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(31250, 1512, 6);
- gl843_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7500I;
- profile.exposure = 0;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(31250, 1375, 7);
- gl843_motor_profiles->push_back(profile);
-}
-
-StaticInit<std::vector<Motor_Profile>> gl846_motor_profiles;
-
-void genesys_init_motor_profile_tables_gl846()
-{
- gl846_motor_profiles.init();
-
- auto profile = Motor_Profile();
- profile.motor_id = MotorId::IMG101;
- profile.exposure = 11000;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(22000, 1000, 1017);
-
- gl846_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::PLUSTEK_OPTICBOOK_3800;
- profile.exposure = 11000;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(22000, 1000, 1017);
- gl846_motor_profiles->push_back(profile);
-}
-
-/**
- * database of motor profiles
- */
-
-StaticInit<std::vector<Motor_Profile>> gl847_motor_profiles;
-
-void genesys_init_motor_profile_tables_gl847()
-{
- gl847_motor_profiles.init();
-
- auto profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_100;
- profile.exposure = 2848;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_100;
- profile.exposure = 1424;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_100;
- profile.exposure = 1432;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_100;
- profile.exposure = 2712;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 279);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_100;
- profile.exposure = 5280;
- profile.step_type = StepType::EIGHTH;
- profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_200;
- profile.exposure = 2848;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_200;
- profile.exposure = 1424;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_200;
- profile.exposure = 1432;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_200;
- profile.exposure = 2712;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 279);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_200;
- profile.exposure = 5280;
- profile.step_type = StepType::EIGHTH;
- profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_200;
- profile.exposure = 10416;
- profile.step_type = StepType::EIGHTH;
- profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_700;
- profile.exposure = 2848;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_700;
- profile.exposure = 1424;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_700;
- profile.exposure = 1504;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_700;
- profile.exposure = 2696;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(46876, 2022, 127);
- gl847_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_700;
- profile.exposure = 10576;
- profile.step_type = StepType::EIGHTH;
- profile.slope = MotorSlope::create_from_steps(46876, 15864, 2);
- gl847_motor_profiles->push_back(profile);
-}
-
-StaticInit<std::vector<Motor_Profile>> gl124_motor_profiles;
-
-void genesys_init_motor_profile_tables_gl124()
-{
- gl124_motor_profiles.init();
-
- // NEXT LPERIOD=PREVIOUS*2-192
- Motor_Profile profile;
- profile.motor_id = MotorId::CANON_LIDE_110;
- profile.exposure = 2768;
- profile.step_type = StepType::FULL;
- profile.slope = MotorSlope::create_from_steps(62496, 335, 255);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_110;
- profile.exposure = 5360;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(62496, 335, 469);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_110;
- profile.exposure = 10528;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(62496, 2632, 3);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_110;
- profile.exposure = 20864;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(62496, 10432, 3);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_120;
- profile.exposure = 4608;
- profile.step_type = StepType::FULL;
- profile.slope = MotorSlope::create_from_steps(62496, 864, 127);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_120;
- profile.exposure = 5360;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(62496, 2010, 63);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_120;
- profile.exposure = 10528;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(62464, 2632, 3);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_120;
- profile.exposure = 20864;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(62592, 10432, 5);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_210;
- profile.exposure = 2768;
- profile.step_type = StepType::FULL;
- profile.slope = MotorSlope::create_from_steps(62496, 335, 255);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_210;
- profile.exposure = 5360;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(62496, 335, 469);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_210;
- profile.exposure = 10528;
- profile.step_type = StepType::HALF;
- profile.slope = MotorSlope::create_from_steps(62496, 2632, 3);
- gl124_motor_profiles->push_back(profile);
-
- profile = Motor_Profile();
- profile.motor_id = MotorId::CANON_LIDE_210;
- profile.exposure = 20864;
- profile.step_type = StepType::QUARTER;
- profile.slope = MotorSlope::create_from_steps(62496, 10432, 4);
- gl124_motor_profiles->push_back(profile);
-}
-
-void genesys_init_motor_profile_tables()
-{
- genesys_init_motor_profile_tables_gl843();
- genesys_init_motor_profile_tables_gl846();
- genesys_init_motor_profile_tables_gl847();
- genesys_init_motor_profile_tables_gl124();
-}
-
-} // namespace genesys
diff --git a/backend/genesys/tables_sensor.cpp b/backend/genesys/tables_sensor.cpp
index bbbe441..b90355c 100644
--- a/backend/genesys/tables_sensor.cpp
+++ b/backend/genesys/tables_sensor.cpp
@@ -44,71 +44,10 @@
#define DEBUG_DECLARE_ONLY
#include "low.h"
+#include <map>
namespace genesys {
-inline unsigned default_get_logical_hwdpi(const Genesys_Sensor& sensor, unsigned xres)
-{
- if (sensor.logical_dpihw_override)
- return sensor.logical_dpihw_override;
-
- // can't be below 600 dpi
- if (xres <= 600) {
- return 600;
- }
- if (xres <= static_cast<unsigned>(sensor.optical_res) / 4) {
- return sensor.optical_res / 4;
- }
- if (xres <= static_cast<unsigned>(sensor.optical_res) / 2) {
- return sensor.optical_res / 2;
- }
- return sensor.optical_res;
-}
-
-inline unsigned get_sensor_optical_with_ccd_divisor(const Genesys_Sensor& sensor, unsigned xres)
-{
- unsigned hwres = sensor.optical_res / sensor.get_ccd_size_divisor_for_dpi(xres);
-
- if (xres <= hwres / 4) {
- return hwres / 4;
- }
- if (xres <= hwres / 2) {
- return hwres / 2;
- }
- return hwres;
-}
-
-inline unsigned default_get_ccd_size_divisor_for_dpi(const Genesys_Sensor& sensor, unsigned xres)
-{
- if (sensor.ccd_size_divisor >= 4 && xres * 4 <= static_cast<unsigned>(sensor.optical_res)) {
- return 4;
- }
- if (sensor.ccd_size_divisor >= 2 && xres * 2 <= static_cast<unsigned>(sensor.optical_res)) {
- return 2;
- }
- return 1;
-}
-
-inline unsigned get_ccd_size_divisor_exact(const Genesys_Sensor& sensor, unsigned xres)
-{
- (void) xres;
- return sensor.ccd_size_divisor;
-}
-
-inline unsigned get_ccd_size_divisor_gl124(const Genesys_Sensor& sensor, unsigned xres)
-{
- // we have 2 domains for ccd: xres below or above half ccd max dpi
- if (xres <= 300 && sensor.ccd_size_divisor > 1) {
- return 2;
- }
- return 1;
-}
-
-inline unsigned default_get_hwdpi_divisor_for_dpi(const Genesys_Sensor& sensor, unsigned xres)
-{
- return sensor.optical_res / default_get_logical_hwdpi(sensor, xres);
-}
-
StaticInit<std::vector<Genesys_Sensor>> s_sensors;
void genesys_init_sensor_tables()
@@ -118,444 +57,231 @@ void genesys_init_sensor_tables()
Genesys_Sensor sensor;
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_UMAX;
- sensor.optical_res = 1200;
+ sensor.sensor_id = SensorId::CCD_UMAX; // gl646
+ sensor.full_resolution = 1200;
sensor.black_pixels = 48;
sensor.dummy_pixel = 64;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10800;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.custom_regs = {
- { 0x08, 0x01 },
- { 0x09, 0x03 },
- { 0x0a, 0x05 },
- { 0x0b, 0x07 },
- { 0x16, 0x33 },
- { 0x17, 0x05 },
- { 0x18, 0x31 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x13 },
- { 0x53, 0x17 },
- { 0x54, 0x03 },
- { 0x55, 0x07 },
- { 0x56, 0x0b },
- { 0x57, 0x0f },
- { 0x58, 0x23 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 },
+ { 0x08, 0x01 }, { 0x09, 0x03 }, { 0x0a, 0x05 }, { 0x0b, 0x07 },
+ { 0x16, 0x33 }, { 0x17, 0x05 }, { 0x18, 0x31 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x13 }, { 0x53, 0x17 }, { 0x54, 0x03 }, { 0x55, 0x07 },
+ { 0x56, 0x0b }, { 0x57, 0x0f }, { 0x58, 0x23 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 150, 4 },
+ { { 150 }, 300, 8 },
+ { { 300 }, 600, 16 },
+ { { 600 }, 1200, 32 },
+ { { 1200 }, 2400, 64 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_ST12;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CCD_ST12; // gl646
+ sensor.full_resolution = 600;
sensor.black_pixels = 48;
sensor.dummy_pixel = 85;
- sensor.ccd_start_xoffset = 152;
- sensor.sensor_pixels = 5416;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.custom_regs = {
- { 0x08, 0x02 },
- { 0x09, 0x00 },
- { 0x0a, 0x06 },
- { 0x0b, 0x04 },
- { 0x16, 0x2b },
- { 0x17, 0x08 },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x0c },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 },
+ { 0x08, 0x02 }, { 0x09, 0x00 }, { 0x0a, 0x06 }, { 0x0b, 0x04 },
+ { 0x16, 0x2b }, { 0x17, 0x08 }, { 0x18, 0x20 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x0c }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 10 },
+ { { 150 }, 21 },
+ { { 300 }, 42 },
+ { { 600 }, 85 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.resolutions.values()[0];
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_ST24;
- sensor.optical_res = 1200;
+ sensor.sensor_id = SensorId::CCD_ST24; // gl646
+ sensor.full_resolution = 1200;
sensor.black_pixels = 48;
sensor.dummy_pixel = 64;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10800;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.custom_regs = {
- { 0x08, 0x0e },
- { 0x09, 0x0c },
- { 0x0a, 0x00 },
- { 0x0b, 0x0c },
- { 0x16, 0x33 },
- { 0x17, 0x08 },
- { 0x18, 0x31 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x17 },
- { 0x53, 0x03 },
- { 0x54, 0x07 },
- { 0x55, 0x0b },
- { 0x56, 0x0f },
- { 0x57, 0x13 },
- { 0x58, 0x03 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 },
+ { 0x08, 0x0e }, { 0x09, 0x0c }, { 0x0a, 0x00 }, { 0x0b, 0x0c },
+ { 0x16, 0x33 }, { 0x17, 0x08 }, { 0x18, 0x31 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x17 }, { 0x53, 0x03 }, { 0x54, 0x07 }, { 0x55, 0x0b },
+ { 0x56, 0x0f }, { 0x57, 0x13 }, { 0x58, 0x03 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 150, 4 },
+ { { 150 }, 300, 8 },
+ { { 300 }, 600, 16 },
+ { { 600 }, 1200, 32 },
+ { { 1200 }, 2400, 64 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_5345;
- sensor.optical_res = 1200;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CCD_5345; // gl646
+ sensor.full_resolution = 1200;
sensor.black_pixels = 48;
sensor.dummy_pixel = 16;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10872;
sensor.fau_gain_white_ref = 190;
sensor.gain_white_ref = 190;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
- sensor.stagger_config = StaggerConfig{ 1200, 4 }; // FIXME: may be incorrect
- sensor.custom_base_regs = {
- { 0x08, 0x0d },
- { 0x09, 0x0f },
- { 0x0a, 0x11 },
- { 0x0b, 0x13 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x30 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x23 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 },
- };
sensor.gamma = { 2.38f, 2.35f, 2.34f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpiset;
unsigned exposure_lperiod;
- unsigned ccd_size_divisor;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ StaggerConfig stagger_y; // FIXME: may be incorrect
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 50 }, 12000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 75 }, 11000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 100 }, 11000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 150 }, 11000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 200 }, 11000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 300 }, 11000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 400 }, 11000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 600 }, 11000, 2, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x28 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 1200 }, 11000, 1, {
- { 0x08, 0x0d },
- { 0x09, 0x0f },
- { 0x0a, 0x11 },
- { 0x0b, 0x13 },
- { 0x16, 0x0b },
- { 0x17, 0x0a },
- { 0x18, 0x30 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x03 },
- { 0x52, 0x03 },
- { 0x53, 0x07 },
- { 0x54, 0x0b },
- { 0x55, 0x0f },
- { 0x56, 0x13 },
- { 0x57, 0x17 },
- { 0x58, 0x23 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
+ { { 50 }, 600, 100, 12000, Ratio{1, 2}, 0, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 75 }, 600, 150, 11000, Ratio{1, 2}, 1, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 100 }, 600, 200, 11000, Ratio{1, 2}, 1, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 150 }, 600, 300, 11000, Ratio{1, 2}, 2, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 200 }, 600, 400, 11000, Ratio{1, 2}, 2, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 300 }, 600, 600, 11000, Ratio{1, 2}, 4, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 400 }, 600, 800, 11000, Ratio{1, 2}, 5, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 600 }, 600, 1200, 11000, Ratio{1, 2}, 8, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x28 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 1200 }, 1200, 1200, 11000, Ratio{1, 1}, 16, StaggerConfig{4, 0}, {
+ { 0x08, 0x0d }, { 0x09, 0x0f }, { 0x0a, 0x11 }, { 0x0b, 0x13 },
+ { 0x16, 0x0b }, { 0x17, 0x0a }, { 0x18, 0x30 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x03 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x0b }, { 0x55, 0x0f },
+ { 0x56, 0x13 }, { 0x57, 0x17 }, { 0x58, 0x23 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
}
},
};
@@ -563,8 +289,12 @@ void genesys_init_sensor_tables()
for (const CustomSensorSettings& setting : custom_settings)
{
sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpiset = setting.register_dpiset;
sensor.exposure_lperiod = setting.exposure_lperiod;
- sensor.ccd_size_divisor = setting.ccd_size_divisor;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.stagger_y = setting.stagger_y;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
}
@@ -572,223 +302,79 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_HP2400;
- sensor.optical_res = 1200;
+ sensor.sensor_id = SensorId::CCD_HP2400; // gl646
+ sensor.full_resolution = 1200;
sensor.black_pixels = 48;
sensor.dummy_pixel = 15;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10872;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
- sensor.stagger_config = StaggerConfig{1200, 4}; // FIXME: may be incorrect
- sensor.custom_base_regs = {
- { 0x08, 0x14 },
- { 0x09, 0x15 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0xbf },
- { 0x17, 0x08 },
- { 0x18, 0x3f },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x0b },
- { 0x53, 0x0f },
- { 0x54, 0x13 },
- { 0x55, 0x17 },
- { 0x56, 0x03 },
- { 0x57, 0x07 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x0e },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 },
- };
sensor.gamma = { 2.1f, 2.1f, 2.1f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
unsigned exposure_lperiod;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ StaggerConfig stagger_y;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 50 }, 7211, {
- { 0x08, 0x14 },
- { 0x09, 0x15 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0xbf },
- { 0x17, 0x08 },
- { 0x18, 0x3f },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x0b },
- { 0x53, 0x0f },
- { 0x54, 0x13 },
- { 0x55, 0x17 },
- { 0x56, 0x03 },
- { 0x57, 0x07 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 100 }, 7211, {
- { 0x08, 0x14 },
- { 0x09, 0x15 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0xbf },
- { 0x17, 0x08 },
- { 0x18, 0x3f },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x0b },
- { 0x53, 0x0f },
- { 0x54, 0x13 },
- { 0x55, 0x17 },
- { 0x56, 0x03 },
- { 0x57, 0x07 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 150 }, 7211, {
- { 0x08, 0x14 },
- { 0x09, 0x15 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0xbf },
- { 0x17, 0x08 },
- { 0x18, 0x3f },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x0b },
- { 0x53, 0x0f },
- { 0x54, 0x13 },
- { 0x55, 0x17 },
- { 0x56, 0x03 },
- { 0x57, 0x07 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 300 }, 8751, {
- { 0x08, 0x14 },
- { 0x09, 0x15 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0xbf },
- { 0x17, 0x08 },
- { 0x18, 0x3f },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x0b },
- { 0x53, 0x0f },
- { 0x54, 0x13 },
- { 0x55, 0x17 },
- { 0x56, 0x03 },
- { 0x57, 0x07 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 600 }, 18760, {
- { 0x08, 0x0e },
- { 0x09, 0x0f },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0xbf },
- { 0x17, 0x08 },
- { 0x18, 0x31 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x03 },
- { 0x53, 0x07 },
- { 0x54, 0x0b },
- { 0x55, 0x0f },
- { 0x56, 0x13 },
- { 0x57, 0x17 },
- { 0x58, 0x23 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 1200 }, 21749, {
- { 0x08, 0x02 },
- { 0x09, 0x04 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0xbf },
- { 0x17, 0x08 },
- { 0x18, 0x30 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x42 },
- { 0x52, 0x0b },
- { 0x53, 0x0f },
- { 0x54, 0x13 },
- { 0x55, 0x17 },
- { 0x56, 0x03 },
- { 0x57, 0x07 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x0e },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
+ { { 50 }, 200, 7211, Ratio{1, 4}, 0, StaggerConfig{}, {
+ { 0x08, 0x14 }, { 0x09, 0x15 }, { 0x0a, 0x00 }, { 0x0b, 0x00 },
+ { 0x16, 0xbf }, { 0x17, 0x08 }, { 0x18, 0x3f }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x0b }, { 0x53, 0x0f }, { 0x54, 0x13 }, { 0x55, 0x17 },
+ { 0x56, 0x03 }, { 0x57, 0x07 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 100 }, 400, 7211, Ratio{1, 4}, 1, StaggerConfig{}, {
+ { 0x08, 0x14 }, { 0x09, 0x15 }, { 0x0a, 0x00 }, { 0x0b, 0x00 },
+ { 0x16, 0xbf }, { 0x17, 0x08 }, { 0x18, 0x3f }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x0b }, { 0x53, 0x0f }, { 0x54, 0x13 }, { 0x55, 0x17 },
+ { 0x56, 0x03 }, { 0x57, 0x07 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 150 }, 600, 7211, Ratio{1, 4}, 1, StaggerConfig{}, {
+ { 0x08, 0x14 }, { 0x09, 0x15 }, { 0x0a, 0x00 }, { 0x0b, 0x00 },
+ { 0x16, 0xbf }, { 0x17, 0x08 }, { 0x18, 0x3f }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x0b }, { 0x53, 0x0f }, { 0x54, 0x13 }, { 0x55, 0x17 },
+ { 0x56, 0x03 }, { 0x57, 0x07 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 300 }, 1200, 8751, Ratio{1, 4}, 3, StaggerConfig{}, {
+ { 0x08, 0x14 }, { 0x09, 0x15 }, { 0x0a, 0x00 }, { 0x0b, 0x00 },
+ { 0x16, 0xbf }, { 0x17, 0x08 }, { 0x18, 0x3f }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x0b }, { 0x53, 0x0f }, { 0x54, 0x13 }, { 0x55, 0x17 },
+ { 0x56, 0x03 }, { 0x57, 0x07 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 600 }, 1200, 18760, Ratio{1, 2}, 7, StaggerConfig{}, {
+ { 0x08, 0x0e }, { 0x09, 0x0f }, { 0x0a, 0x00 }, { 0x0b, 0x00 },
+ { 0x16, 0xbf }, { 0x17, 0x08 }, { 0x18, 0x31 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x0b }, { 0x55, 0x0f },
+ { 0x56, 0x13 }, { 0x57, 0x17 }, { 0x58, 0x23 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 1200 }, 1200, 21749, Ratio{1, 1}, 15, StaggerConfig{4, 0}, {
+ { 0x08, 0x02 }, { 0x09, 0x04 }, { 0x0a, 0x00 }, { 0x0b, 0x00 },
+ { 0x16, 0xbf }, { 0x17, 0x08 }, { 0x18, 0x30 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0xc0 }, { 0x1d, 0x42 },
+ { 0x52, 0x0b }, { 0x53, 0x0f }, { 0x54, 0x13 }, { 0x55, 0x17 },
+ { 0x56, 0x03 }, { 0x57, 0x07 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x0e }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
}
},
};
@@ -796,7 +382,11 @@ void genesys_init_sensor_tables()
for (const CustomSensorSettings& setting : custom_settings)
{
sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
sensor.exposure_lperiod = setting.exposure_lperiod;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.stagger_y = setting.stagger_y;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
}
@@ -804,168 +394,61 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_HP2300;
- sensor.optical_res = 600;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CCD_HP2300; // gl646
+ sensor.full_resolution = 600;
sensor.black_pixels = 48;
sensor.dummy_pixel = 20;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 5368;
sensor.fau_gain_white_ref = 180;
sensor.gain_white_ref = 180;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
- sensor.custom_base_regs = {
- { 0x08, 0x16 },
- { 0x09, 0x00 },
- { 0x0a, 0x01 },
- { 0x0b, 0x03 },
- { 0x16, 0xb7 },
- { 0x17, 0x0a },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x6a },
- { 0x1b, 0x8a },
- { 0x1c, 0x00 },
- { 0x1d, 0x05 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x06 },
- { 0x5c, 0x0b },
- { 0x5d, 0x10 },
- { 0x5e, 0x16 },
- };
sensor.gamma = { 2.1f, 2.1f, 2.1f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpiset;
unsigned exposure_lperiod;
- unsigned ccd_size_divisor;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 75 }, 4480, 2, {
- { 0x08, 0x16 },
- { 0x09, 0x00 },
- { 0x0a, 0x01 },
- { 0x0b, 0x03 },
- { 0x16, 0xb7 },
- { 0x17, 0x0a },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x6a },
- { 0x1b, 0x8a },
- { 0x1c, 0x00 },
- { 0x1d, 0x85 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x06 },
- { 0x5c, 0x0b },
- { 0x5d, 0x10 },
- { 0x5e, 0x16 }
- }
- },
- { { 150 }, 4350, 2, {
- { 0x08, 0x16 },
- { 0x09, 0x00 },
- { 0x0a, 0x01 },
- { 0x0b, 0x03 },
- { 0x16, 0xb7 },
- { 0x17, 0x0a },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x6a },
- { 0x1b, 0x8a },
- { 0x1c, 0x00 },
- { 0x1d, 0x85 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x06 },
- { 0x5c, 0x0b },
- { 0x5d, 0x10 },
- { 0x5e, 0x16 }
- }
- },
- { { 300 }, 4350, 2, {
- { 0x08, 0x16 },
- { 0x09, 0x00 },
- { 0x0a, 0x01 },
- { 0x0b, 0x03 },
- { 0x16, 0xb7 },
- { 0x17, 0x0a },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x6a },
- { 0x1b, 0x8a },
- { 0x1c, 0x00 },
- { 0x1d, 0x85 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x06 },
- { 0x5c, 0x0b },
- { 0x5d, 0x10 },
- { 0x5e, 0x16 }
- }
- },
- { { 600 }, 8700, 1, {
- { 0x08, 0x01 },
- { 0x09, 0x03 },
- { 0x0a, 0x04 },
- { 0x0b, 0x06 },
- { 0x16, 0xb7 },
- { 0x17, 0x0a },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x6a },
- { 0x1b, 0x8a },
- { 0x1c, 0x00 },
- { 0x1d, 0x05 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x06 },
- { 0x5c, 0x0b },
- { 0x5d, 0x10 },
- { 0x5e, 0x16 }
+ { { 75 }, 300, 150, 4480, Ratio{1, 2}, 2, {
+ { 0x08, 0x16 }, { 0x09, 0x00 }, { 0x0a, 0x01 }, { 0x0b, 0x03 },
+ { 0x16, 0xb7 }, { 0x17, 0x0a }, { 0x18, 0x20 }, { 0x19, 0x2a },
+ { 0x1a, 0x6a }, { 0x1b, 0x8a }, { 0x1c, 0x00 }, { 0x1d, 0x85 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x06 }, { 0x5c, 0x0b }, { 0x5d, 0x10 }, { 0x5e, 0x16 }
+ }
+ },
+ { { 150 }, 300, 300, 4350, Ratio{1, 2}, 5, {
+ { 0x08, 0x16 }, { 0x09, 0x00 }, { 0x0a, 0x01 }, { 0x0b, 0x03 },
+ { 0x16, 0xb7 }, { 0x17, 0x0a }, { 0x18, 0x20 }, { 0x19, 0x2a },
+ { 0x1a, 0x6a }, { 0x1b, 0x8a }, { 0x1c, 0x00 }, { 0x1d, 0x85 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x06 }, { 0x5c, 0x0b }, { 0x5d, 0x10 }, { 0x5e, 0x16 }
+ }
+ },
+ { { 300 }, 300, 600, 4350, Ratio{1, 2}, 10, {
+ { 0x08, 0x16 }, { 0x09, 0x00 }, { 0x0a, 0x01 }, { 0x0b, 0x03 },
+ { 0x16, 0xb7 }, { 0x17, 0x0a }, { 0x18, 0x20 }, { 0x19, 0x2a },
+ { 0x1a, 0x6a }, { 0x1b, 0x8a }, { 0x1c, 0x00 }, { 0x1d, 0x85 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x06 }, { 0x5c, 0x0b }, { 0x5d, 0x10 }, { 0x5e, 0x16 }
+ }
+ },
+ { { 600 }, 600, 600, 8700, Ratio{1, 1}, 20, {
+ { 0x08, 0x01 }, { 0x09, 0x03 }, { 0x0a, 0x04 }, { 0x0b, 0x06 },
+ { 0x16, 0xb7 }, { 0x17, 0x0a }, { 0x18, 0x20 }, { 0x19, 0x2a },
+ { 0x1a, 0x6a }, { 0x1b, 0x8a }, { 0x1c, 0x00 }, { 0x1d, 0x05 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x06 }, { 0x5c, 0x0b }, { 0x5d, 0x10 }, { 0x5e, 0x16 }
}
},
};
@@ -973,8 +456,11 @@ void genesys_init_sensor_tables()
for (const CustomSensorSettings& setting : custom_settings)
{
sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpiset = setting.register_dpiset;
sensor.exposure_lperiod = setting.exposure_lperiod;
- sensor.ccd_size_divisor = setting.ccd_size_divisor;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
}
@@ -982,399 +468,300 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_35;
- sensor.optical_res = 1200;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_35; // gl841
+ sensor.full_resolution = 1200;
+ sensor.register_dpihw = 1200;
sensor.black_pixels = 87;
sensor.dummy_pixel = 87;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10400;
sensor.fau_gain_white_ref = 0;
sensor.gain_white_ref = 0;
sensor.exposure = { 0x0400, 0x0400, 0x0400 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x00 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0x00 },
- { 0x17, 0x02 },
- { 0x18, 0x00 },
- { 0x19, 0x50 },
- { 0x1a, 0x00 }, // TODO: 1a-1d: these do no harm, but may be neccessery for CCD
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x02 },
- { 0x52, 0x05 }, // [GB](HI|LOW) not needed for cis
- { 0x53, 0x07 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x3a },
- { 0x59, 0x03 },
- { 0x5a, 0x40 },
- { 0x5b, 0x00 }, // TODO: 5b-5e
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 },
+ { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x00 }, { 0x19, 0x50 },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x05 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x3a }, { 0x59, 0x03 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 600, 150, 600, 11 },
+ { { 100 }, 600, 200, 600, 14 },
+ { { 150 }, 600, 300, 600, 22 },
+ { { 200 }, 600, 400, 600, 29 },
+ { { 300 }, 600, 600, 600, 44 },
+ { { 600 }, 600, 1200, 600, 88 },
+ { { 1200 }, 1200, 1200, 1200, 88 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_XP200;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_60; // gl841
+ sensor.full_resolution = 1200;
+ sensor.register_dpihw = 1200;
+ sensor.black_pixels = 87;
+ sensor.dummy_pixel = 87;
+ sensor.fau_gain_white_ref = 0;
+ sensor.gain_white_ref = 0;
+ sensor.exposure = { 0x0400, 0x0400, 0x0400 };
+ sensor.custom_regs = {
+ { 0x16, 0x00 }, { 0x17, 0x01 }, { 0x18, 0x00 }, { 0x19, 0x50 },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x02 },
+ { 0x52, 0x05 }, { 0x53, 0x07 }, { 0x54, 0x03 }, { 0x55, 0x05 },
+ { 0x56, 0x02 }, { 0x57, 0x05 }, { 0x58, 0x3a }, { 0x59, 0x03 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
+ };
+ sensor.gamma = { 1.0f, 1.0f, 1.0f };
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 600, 150, 600, 11 },
+ { { 100 }, 600, 200, 600, 14 },
+ { { 150 }, 600, 300, 600, 22 },
+ { { 200 }, 600, 400, 600, 29 },
+ { { 300 }, 600, 600, 600, 44 },
+ { { 600 }, 600, 1200, 600, 88 },
+ { { 1200 }, 1200, 1200, 1200, 88 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
+
+
+ sensor = Genesys_Sensor();
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_90; // gl842
+ sensor.full_resolution = 2400;
+ sensor.black_pixels = 20;
+ sensor.dummy_pixel = 253;
+ sensor.fau_gain_white_ref = 150;
+ sensor.gain_white_ref = 150;
+ sensor.use_host_side_calib = true;
+ sensor.custom_regs = {
+ { 0x16, 0x20 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x24 }, { 0x1c, 0x00 }, { 0x1d, 0x04 },
+ { 0x52, 0x02 }, { 0x53, 0x04 }, { 0x54, 0x02 }, { 0x55, 0x04 },
+ { 0x56, 0x02 }, { 0x57, 0x04 }, { 0x58, 0x0a }, { 0x59, 0x71 }, { 0x5a, 0x55 },
+ { 0x70, 0x00 }, { 0x71, 0x05 }, { 0x72, 0x07 }, { 0x73, 0x09 },
+ { 0x74, 0x00 }, { 0x75, 0x01 }, { 0x76, 0xff },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x3f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x1e }, { 0x7d, 0x11 }, { 0x7f, 0x50 }
+ };
+ sensor.gamma = { 1.0f, 1.0f, 1.0f };
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
+ unsigned shading_factor;
+ int output_pixel_offset;
+ SensorExposure exposure;
+ unsigned exposure_lperiod;
+ unsigned segment_size;
+ std::vector<unsigned> segment_order;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 300 }, 300, 600, 600, 300, 2, 280, { 955, 1235, 675 }, 6500, 5152,
+ std::vector<unsigned>{} },
+ { { 600 }, 600, 600, 600, 600, 1, 250, { 1655, 2075, 1095 }, 6536, 5152,
+ std::vector<unsigned>{} },
+ { { 1200 }, 1200, 1200, 1200, 1200, 1, 500, { 3055, 4175, 1935 }, 12688, 5152,
+ {0, 1} },
+ { { 2400 }, 2400, 2400, 2400, 2400, 1, 1000, { 5855, 7535, 3615 }, 21500, 5152,
+ {0, 1, 2, 3} },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
+ sensor.shading_factor = setting.shading_factor;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.exposure = setting.exposure;
+ sensor.exposure_lperiod = setting.exposure_lperiod;
+ sensor.segment_size = setting.segment_size;
+ sensor.segment_order = setting.segment_order;
+ s_sensors->push_back(sensor);
+ }
+ }
+
+
+ sensor = Genesys_Sensor();
+ sensor.sensor_id = SensorId::CIS_XP200; // gl646
+ sensor.full_resolution = 600;
sensor.black_pixels = 5;
sensor.dummy_pixel = 38;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 5200;
sensor.fau_gain_white_ref = 200;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x1450, 0x0c80, 0x0a28 };
- sensor.custom_base_regs = {
- { 0x08, 0x16 },
- { 0x09, 0x00 },
- { 0x0a, 0x01 },
- { 0x0b, 0x03 },
- { 0x16, 0xb7 },
- { 0x17, 0x0a },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x6a },
- { 0x1b, 0x8a },
- { 0x1c, 0x00 },
- { 0x1d, 0x05 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x06 },
- { 0x5c, 0x0b },
- { 0x5d, 0x10 },
- { 0x5e, 0x16 },
- };
sensor.custom_regs = {
- { 0x08, 0x06 },
- { 0x09, 0x07 },
- { 0x0a, 0x0a },
- { 0x0b, 0x04 },
- { 0x16, 0x24 },
- { 0x17, 0x04 },
- { 0x18, 0x00 },
- { 0x19, 0x2a },
- { 0x1a, 0x0a },
- { 0x1b, 0x0a },
- { 0x1c, 0x00 },
- { 0x1d, 0x11 },
- { 0x52, 0x08 },
- { 0x53, 0x02 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x1a },
- { 0x59, 0x51 },
- { 0x5a, 0x00 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
+ { 0x08, 0x06 }, { 0x09, 0x07 }, { 0x0a, 0x0a }, { 0x0b, 0x04 },
+ { 0x16, 0x24 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x0a }, { 0x1b, 0x0a }, { 0x1c, 0x00 }, { 0x1d, 0x11 },
+ { 0x52, 0x08 }, { 0x53, 0x02 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x1a }, { 0x59, 0x51 }, { 0x5a, 0x00 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
};
sensor.gamma = { 2.1f, 2.1f, 2.1f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
std::vector<unsigned> channels;
unsigned exposure_lperiod;
SensorExposure exposure;
+ int output_pixel_offset;
};
CustomSensorSettings custom_settings[] = {
- { { 75 }, { 3 }, 5700, { 0x1644, 0x0c80, 0x092e } },
- { { 100 }, { 3 }, 5700, { 0x1644, 0x0c80, 0x092e } },
- { { 200 }, { 3 }, 5700, { 0x1644, 0x0c80, 0x092e } },
- { { 300 }, { 3 }, 9000, { 0x1644, 0x0c80, 0x092e } },
- { { 600 }, { 3 }, 16000, { 0x1644, 0x0c80, 0x092e } },
- { { 75 }, { 1 }, 16000, { 0x050a, 0x0fa0, 0x1010 } },
- { { 100 }, { 1 }, 7800, { 0x050a, 0x0fa0, 0x1010 } },
- { { 200 }, { 1 }, 11000, { 0x050a, 0x0fa0, 0x1010 } },
- { { 300 }, { 1 }, 13000, { 0x050a, 0x0fa0, 0x1010 } },
- { { 600 }, { 1 }, 24000, { 0x050a, 0x0fa0, 0x1010 } },
+ { { 75 }, { 3 }, 5700, { 0x1644, 0x0c80, 0x092e }, 4 },
+ { { 100 }, { 3 }, 5700, { 0x1644, 0x0c80, 0x092e }, 6 },
+ { { 200 }, { 3 }, 5700, { 0x1644, 0x0c80, 0x092e }, 12 },
+ { { 300 }, { 3 }, 9000, { 0x1644, 0x0c80, 0x092e }, 19 },
+ { { 600 }, { 3 }, 16000, { 0x1644, 0x0c80, 0x092e }, 38 },
+ { { 75 }, { 1 }, 16000, { 0x050a, 0x0fa0, 0x1010 }, 4 },
+ { { 100 }, { 1 }, 7800, { 0x050a, 0x0fa0, 0x1010 }, 6 },
+ { { 200 }, { 1 }, 11000, { 0x050a, 0x0fa0, 0x1010 }, 12 },
+ { { 300 }, { 1 }, 13000, { 0x050a, 0x0fa0, 0x1010 }, 19 },
+ { { 600 }, { 1 }, 24000, { 0x050a, 0x0fa0, 0x1010 }, 38 },
};
for (const CustomSensorSettings& setting : custom_settings)
{
sensor.resolutions = setting.resolutions;
sensor.channels = setting.channels;
+ sensor.register_dpiset = setting.resolutions.values()[0];
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
s_sensors->push_back(sensor);
}
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_HP3670;
- sensor.optical_res = 1200;
+ sensor.sensor_id = SensorId::CCD_HP3670; // gl646
+ sensor.full_resolution = 1200;
sensor.black_pixels = 48;
sensor.dummy_pixel = 16;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10872;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0, 0, 0 };
- sensor.stagger_config = StaggerConfig{1200, 4}; // FIXME: may be incorrect
- sensor.custom_base_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x0a },
- { 0x0a, 0x0b },
- { 0x0b, 0x0d },
- { 0x16, 0x33 },
- { 0x17, 0x07 },
- { 0x18, 0x20 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x00 },
- { 0x5a, 0x15 },
- { 0x5b, 0x05 },
- { 0x5c, 0x0a },
- { 0x5d, 0x0f },
- { 0x5e, 0x00 },
- };
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
unsigned exposure_lperiod;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ StaggerConfig stagger_y;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 50 }, 5758, {
- { 0x08, 0x00 },
- { 0x09, 0x0a },
- { 0x0a, 0x0b },
- { 0x0b, 0x0d },
- { 0x16, 0x33 },
- { 0x17, 0x07 },
- { 0x18, 0x33 },
- { 0x19, 0x2a },
- { 0x1a, 0x02 },
- { 0x1b, 0x13 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x15 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x05 },
- { 0x5c, 0x0a },
- { 0x5d, 0x0f },
- { 0x5e, 0x00 }
- }
- },
- { { 75 }, 4879, {
- { 0x08, 0x00 },
- { 0x09, 0x0a },
- { 0x0a, 0x0b },
- { 0x0b, 0x0d },
- { 0x16, 0x33 },
- { 0x17, 0x07 },
- { 0x18, 0x33 },
- { 0x19, 0x2a },
- { 0x1a, 0x02 },
- { 0x1b, 0x13 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x15 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x05 },
- { 0x5c, 0x0a },
- { 0x5d, 0x0f },
- { 0x5e, 0x00 }
- }
- },
- { { 100 }, 4487, {
- { 0x08, 0x00 },
- { 0x09, 0x0a },
- { 0x0a, 0x0b },
- { 0x0b, 0x0d },
- { 0x16, 0x33 },
- { 0x17, 0x07 },
- { 0x18, 0x33 },
- { 0x19, 0x2a },
- { 0x1a, 0x02 },
- { 0x1b, 0x13 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x15 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x05 },
- { 0x5c, 0x0a },
- { 0x5d, 0x0f },
- { 0x5e, 0x00 }
- }
- },
- { { 150 }, 4879, {
- { 0x08, 0x00 },
- { 0x09, 0x0a },
- { 0x0a, 0x0b },
- { 0x0b, 0x0d },
- { 0x16, 0x33 },
- { 0x17, 0x07 },
- { 0x18, 0x33 },
- { 0x19, 0x2a },
- { 0x1a, 0x02 },
- { 0x1b, 0x13 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x15 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x05 },
- { 0x5c, 0x0a },
- { 0x5d, 0x0f },
- { 0x5e, 0x00 }
- }
- },
- { { 300 }, 4503, {
- { 0x08, 0x00 },
- { 0x09, 0x0a },
- { 0x0a, 0x0b },
- { 0x0b, 0x0d },
- { 0x16, 0x33 },
- { 0x17, 0x07 },
- { 0x18, 0x33 },
- { 0x19, 0x2a },
- { 0x1a, 0x02 },
- { 0x1b, 0x13 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x0f },
- { 0x53, 0x13 },
- { 0x54, 0x17 },
- { 0x55, 0x03 },
- { 0x56, 0x07 },
- { 0x57, 0x0b },
- { 0x58, 0x83 },
- { 0x59, 0x15 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x05 },
- { 0x5c, 0x0a },
- { 0x5d, 0x0f },
- { 0x5e, 0x00 }
- }
- },
- { { 600 }, 10251, {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x06 },
- { 0x0b, 0x08 },
- { 0x16, 0x33 },
- { 0x17, 0x07 },
- { 0x18, 0x31 },
- { 0x19, 0x2a },
- { 0x1a, 0x02 },
- { 0x1b, 0x0e },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x0b },
- { 0x53, 0x0f },
- { 0x54, 0x13 },
- { 0x55, 0x17 },
- { 0x56, 0x03 },
- { 0x57, 0x07 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x02 },
- { 0x5c, 0x0e },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
- }
- },
- { { 1200 }, 12750, {
- { 0x08, 0x0d },
- { 0x09, 0x0f },
- { 0x0a, 0x11 },
- { 0x0b, 0x13 },
- { 0x16, 0x2b },
- { 0x17, 0x07 },
- { 0x18, 0x30 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x43 },
- { 0x52, 0x03 },
- { 0x53, 0x07 },
- { 0x54, 0x0b },
- { 0x55, 0x0f },
- { 0x56, 0x13 },
- { 0x57, 0x17 },
- { 0x58, 0x23 },
- { 0x59, 0x00 },
- { 0x5a, 0xc1 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x00 }
+ { { 50 }, 200, 5758, Ratio{1, 4}, 0, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x0a }, { 0x0a, 0x0b }, { 0x0b, 0x0d },
+ { 0x16, 0x33 }, { 0x17, 0x07 }, { 0x18, 0x33 }, { 0x19, 0x2a },
+ { 0x1a, 0x02 }, { 0x1b, 0x13 }, { 0x1c, 0xc0 }, { 0x1d, 0x43 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x15 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x05 }, { 0x5c, 0x0a }, { 0x5d, 0x0f }, { 0x5e, 0x00 }
+ }
+ },
+ { { 75 }, 300, 4879, Ratio{1, 4}, 1, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x0a }, { 0x0a, 0x0b }, { 0x0b, 0x0d },
+ { 0x16, 0x33 }, { 0x17, 0x07 }, { 0x18, 0x33 }, { 0x19, 0x2a },
+ { 0x1a, 0x02 }, { 0x1b, 0x13 }, { 0x1c, 0xc0 }, { 0x1d, 0x43 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x15 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x05 }, { 0x5c, 0x0a }, { 0x5d, 0x0f }, { 0x5e, 0x00 }
+ }
+ },
+ { { 100 }, 400, 4487, Ratio{1, 4}, 1, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x0a }, { 0x0a, 0x0b }, { 0x0b, 0x0d },
+ { 0x16, 0x33 }, { 0x17, 0x07 }, { 0x18, 0x33 }, { 0x19, 0x2a },
+ { 0x1a, 0x02 }, { 0x1b, 0x13 }, { 0x1c, 0xc0 }, { 0x1d, 0x43 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x15 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x05 }, { 0x5c, 0x0a }, { 0x5d, 0x0f }, { 0x5e, 0x00 }
+ }
+ },
+ { { 150 }, 600, 4879, Ratio{1, 4}, 2, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x0a }, { 0x0a, 0x0b }, { 0x0b, 0x0d },
+ { 0x16, 0x33 }, { 0x17, 0x07 }, { 0x18, 0x33 }, { 0x19, 0x2a },
+ { 0x1a, 0x02 }, { 0x1b, 0x13 }, { 0x1c, 0xc0 }, { 0x1d, 0x43 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x15 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x05 }, { 0x5c, 0x0a }, { 0x5d, 0x0f }, { 0x5e, 0x00 }
+ }
+ },
+ { { 300 }, 1200, 4503, Ratio{1, 4}, 4, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x0a }, { 0x0a, 0x0b }, { 0x0b, 0x0d },
+ { 0x16, 0x33 }, { 0x17, 0x07 }, { 0x18, 0x33 }, { 0x19, 0x2a },
+ { 0x1a, 0x02 }, { 0x1b, 0x13 }, { 0x1c, 0xc0 }, { 0x1d, 0x43 },
+ { 0x52, 0x0f }, { 0x53, 0x13 }, { 0x54, 0x17 }, { 0x55, 0x03 },
+ { 0x56, 0x07 }, { 0x57, 0x0b }, { 0x58, 0x83 }, { 0x59, 0x15 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x05 }, { 0x5c, 0x0a }, { 0x5d, 0x0f }, { 0x5e, 0x00 }
+ }
+ },
+ { { 600 }, 1200, 10251, Ratio{1, 2}, 8, StaggerConfig{}, {
+ { 0x08, 0x00 }, { 0x09, 0x05 }, { 0x0a, 0x06 }, { 0x0b, 0x08 },
+ { 0x16, 0x33 }, { 0x17, 0x07 }, { 0x18, 0x31 }, { 0x19, 0x2a },
+ { 0x1a, 0x02 }, { 0x1b, 0x0e }, { 0x1c, 0xc0 }, { 0x1d, 0x43 },
+ { 0x52, 0x0b }, { 0x53, 0x0f }, { 0x54, 0x13 }, { 0x55, 0x17 },
+ { 0x56, 0x03 }, { 0x57, 0x07 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x02 }, { 0x5c, 0x0e }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
+ }
+ },
+ { { 1200 }, 1200, 12750, Ratio{1, 1}, 16, StaggerConfig{4, 0}, {
+ { 0x08, 0x0d }, { 0x09, 0x0f }, { 0x0a, 0x11 }, { 0x0b, 0x13 },
+ { 0x16, 0x2b }, { 0x17, 0x07 }, { 0x18, 0x30 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0xc0 }, { 0x1d, 0x43 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x0b }, { 0x55, 0x0f },
+ { 0x56, 0x13 }, { 0x57, 0x17 }, { 0x58, 0x23 }, { 0x59, 0x00 }, { 0x5a, 0xc1 },
+ { 0x5b, 0x00 }, { 0x5c, 0x00 }, { 0x5d, 0x00 }, { 0x5e, 0x00 }
}
},
};
@@ -1382,7 +769,11 @@ void genesys_init_sensor_tables()
for (const CustomSensorSettings& setting : custom_settings)
{
sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
sensor.exposure_lperiod = setting.exposure_lperiod;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.stagger_y = setting.stagger_y;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
}
@@ -1390,251 +781,278 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_DP665;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CCD_DP665; // gl841
+ sensor.full_resolution = 600;
+ sensor.register_dpihw = 600;
+ sensor.shading_resolution = 600;
sensor.black_pixels = 27;
sensor.dummy_pixel = 27;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 2496;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x1100, 0x1100, 0x1100 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x00 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0x00 },
- { 0x17, 0x02 },
- { 0x18, 0x04 },
- { 0x19, 0x50 },
- { 0x1a, 0x10 },
- { 0x1b, 0x00 },
- { 0x1c, 0x20 },
- { 0x1d, 0x02 },
- { 0x52, 0x04 }, // [GB](HI|LOW) not needed for cis
- { 0x53, 0x05 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x54 },
- { 0x59, 0x03 },
- { 0x5a, 0x00 },
- { 0x5b, 0x00 }, // TODO: 5b-5e
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x01 },
+ { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x04 }, { 0x19, 0x50 },
+ { 0x1a, 0x10 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x05 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x54 }, { 0x59, 0x03 }, { 0x5a, 0x00 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 75, 1 },
+ { { 150 }, 150, 3 },
+ { { 300 }, 300, 7 },
+ { { 600 }, 600, 14 },
+ { { 1200 }, 1200, 28 },
+ };
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_ROADWARRIOR;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CCD_ROADWARRIOR; // gl841
+ sensor.full_resolution = 600;
+ sensor.register_dpihw = 600;
+ sensor.shading_resolution = 600;
sensor.black_pixels = 27;
sensor.dummy_pixel = 27;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 5200;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x1100, 0x1100, 0x1100 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x00 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0x00 },
- { 0x17, 0x02 },
- { 0x18, 0x04 },
- { 0x19, 0x50 },
- { 0x1a, 0x10 },
- { 0x1b, 0x00 },
- { 0x1c, 0x20 },
- { 0x1d, 0x02 },
- { 0x52, 0x04 }, // [GB](HI|LOW) not needed for cis
- { 0x53, 0x05 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x54 },
- { 0x59, 0x03 },
- { 0x5a, 0x00 },
- { 0x5b, 0x00 }, // TODO: 5b-5e
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x01 },
+ { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x04 }, { 0x19, 0x50 },
+ { 0x1a, 0x10 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x05 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x54 }, { 0x59, 0x03 }, { 0x5a, 0x00 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 75, 1 },
+ { { 150 }, 150, 3 },
+ { { 300 }, 300, 7 },
+ { { 600 }, 600, 14 },
+ { { 1200 }, 1200, 28 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_DSMOBILE600;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CCD_DSMOBILE600; // gl841
+ sensor.full_resolution = 600;
+ sensor.register_dpihw = 600;
+ sensor.shading_resolution = 600;
sensor.black_pixels = 28;
sensor.dummy_pixel = 28;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 5200;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x1544, 0x1544, 0x1544 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x00 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0x00 },
- { 0x17, 0x02 },
- { 0x18, 0x04 },
- { 0x19, 0x50 },
- { 0x1a, 0x10 },
- { 0x1b, 0x00 },
- { 0x1c, 0x20 },
- { 0x1d, 0x02 },
- { 0x52, 0x04 }, // [GB](HI|LOW) not needed for cis
- { 0x53, 0x05 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x54 },
- { 0x59, 0x03 },
- { 0x5a, 0x00 },
- { 0x5b, 0x00 }, // TODO: 5b-5e
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x01 },
+ { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x04 }, { 0x19, 0x50 },
+ { 0x1a, 0x10 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x05 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x54 }, { 0x59, 0x03 }, { 0x5a, 0x00 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
+ };
+ sensor.gamma = { 1.0f, 1.0f, 1.0f };
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 75, 3 },
+ { { 150 }, 150, 7 },
+ { { 300 }, 300, 14 },
+ { { 600 }, 600, 29 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
+
+
+ sensor = Genesys_Sensor();
+ sensor.sensor_id = SensorId::CCD_XP300; // gl841
+ sensor.full_resolution = 600;
+ sensor.register_dpihw = 1200; // FIXME: could be incorrect, but previous code used this value
+ sensor.shading_resolution = 600;
+ sensor.black_pixels = 27;
+ sensor.dummy_pixel = 27;
+ sensor.fau_gain_white_ref = 210;
+ sensor.gain_white_ref = 200;
+ sensor.exposure = { 0x1100, 0x1100, 0x1100 };
+ sensor.custom_regs = {
+ { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x04 }, { 0x19, 0x50 },
+ { 0x1a, 0x10 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x05 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x54 }, { 0x59, 0x03 }, { 0x5a, 0x00 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 150, 3 },
+ { { 150 }, 300, 7 },
+ { { 300 }, 600, 14 },
+ { { 600 }, 1200, 28 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_XP300;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CCD_DOCKETPORT_487; // gl841
+ sensor.full_resolution = 600;
+ sensor.register_dpihw = 600;
+ sensor.shading_resolution = 600;
sensor.black_pixels = 27;
sensor.dummy_pixel = 27;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10240;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x1100, 0x1100, 0x1100 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x00 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0x00 },
- { 0x17, 0x02 },
- { 0x18, 0x04 },
- { 0x19, 0x50 },
- { 0x1a, 0x10 },
- { 0x1b, 0x00 },
- { 0x1c, 0x20 },
- { 0x1d, 0x02 },
- { 0x52, 0x04 }, // [GB](HI|LOW) not needed for cis
- { 0x53, 0x05 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x54 },
- { 0x59, 0x03 },
- { 0x5a, 0x00 },
- { 0x5b, 0x00 }, // TODO: 5b-5e
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x01 },
+ { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x04 }, { 0x19, 0x50 },
+ { 0x1a, 0x10 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x05 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x54 }, { 0x59, 0x03 }, { 0x5a, 0x00 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 150, 3 },
+ { { 150 }, 300, 7 },
+ { { 300 }, 600, 14 },
+ { { 600 }, 600, 28 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_DP685;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CCD_DP685; // gl841
+ sensor.full_resolution = 600;
+ sensor.register_dpihw = 600;
+ sensor.shading_resolution = 600;
+ sensor.full_resolution = 600;
sensor.black_pixels = 27;
sensor.dummy_pixel = 27;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 5020;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x1100, 0x1100, 0x1100 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x00 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0x00 },
- { 0x17, 0x02 },
- { 0x18, 0x04 },
- { 0x19, 0x50 },
- { 0x1a, 0x10 },
- { 0x1b, 0x00 },
- { 0x1c, 0x20 },
- { 0x1d, 0x02 },
- { 0x52, 0x04 }, // [GB](HI|LOW) not needed for cis
- { 0x53, 0x05 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x54 },
- { 0x59, 0x03 },
- { 0x5a, 0x00 },
- { 0x5b, 0x00 }, // TODO: 5b-5e
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x01 },
+ { 0x16, 0x00 }, { 0x17, 0x02 }, { 0x18, 0x04 }, { 0x19, 0x50 },
+ { 0x1a, 0x10 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x05 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x54 }, { 0x59, 0x03 }, { 0x5a, 0x00 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 75, 3 },
+ { { 150 }, 150, 6 },
+ { { 300 }, 300, 13 },
+ { { 600 }, 600, 27 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_200;
- sensor.optical_res = 4800;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_200; // gl847
+ sensor.full_resolution = 4800;
sensor.black_pixels = 87*4;
sensor.dummy_pixel = 16*4;
- sensor.ccd_start_xoffset = 320*8;
- sensor.sensor_pixels = 5136*8;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.gamma = { 2.2f, 2.2f, 2.2f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
int exposure_lperiod;
SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
+ int output_pixel_offset;
unsigned segment_size;
std::vector<unsigned> segment_order;
GenesysRegisterSettingSet custom_regs;
@@ -1642,7 +1060,44 @@ void genesys_init_sensor_tables()
CustomSensorSettings custom_settings[] = {
// Note: Windows driver uses 1424 lperiod and enables dummy line (0x17)
- { { 75, 100, 150, 200 }, 2848, { 304, 203, 180 }, 5136, std::vector<unsigned>{}, {
+ { { 75 }, 600, 2848, { 304, 203, 180 }, Ratio{1, 8}, 8, 40, 5136,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ // Note: Windows driver uses 1424 lperiod and enables dummy line (0x17)
+ { { 100 }, 600, 2848, { 304, 203, 180 }, Ratio{1, 8}, 6, 53, 5136,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ // Note: Windows driver uses 1424 lperiod and enables dummy line (0x17)
+ { { 150 }, 600, 2848, { 304, 203, 180 }, Ratio{1, 8}, 4, 80, 5136,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ // Note: Windows driver uses 1424 lperiod and enables dummy line (0x17)
+ { { 200 }, 600, 2848, { 304, 203, 180 }, Ratio{1, 8}, 3, 106, 5136,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1653,7 +1108,8 @@ void genesys_init_sensor_tables()
}
},
// Note: Windows driver uses 788 lperiod and enables dummy line (0x17)
- { { 300, 400 }, 1424, { 304, 203, 180 }, 5136, std::vector<unsigned>{}, {
+ { { 300 }, 600, 1424, { 304, 203, 180 }, Ratio{1, 8}, 2, 160, 5136,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1663,7 +1119,9 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 600 }, 1432, { 492, 326, 296 }, 5136, std::vector<unsigned>{}, {
+ // Note: Windows driver uses 788 lperiod and enables dummy line (0x17)
+ { { 400 }, 600, 1424, { 304, 203, 180 }, Ratio{1, 8}, 1, 213, 5136,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1673,7 +1131,19 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 1200 }, 2712, { 935, 592, 538 }, 5136, { 0, 1 }, {
+ { { 600 }, 600, 1432, { 492, 326, 296 }, Ratio{1, 8}, 1, 320, 5136,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ { { 1200 }, 1200, 2712, { 935, 592, 538 }, Ratio{1, 8}, 1, 640, 5136,
+ { 0, 1 }, {
{ 0x16, 0x10 }, { 0x17, 0x08 }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1683,7 +1153,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 2400 }, 5280, { 1777, 1125, 979 }, 5136, { 0, 2, 1, 3 }, {
+ { { 2400 }, 2400, 5280, { 1777, 1125, 979 }, Ratio{1, 8}, 1, 1280, 5136,
+ { 0, 2, 1, 3 }, {
{ 0x16, 0x10 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1693,7 +1164,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 4800 }, 10416, { 3377, 2138, 1780 }, 5136, { 0, 2, 4, 6, 1, 3, 5, 7 }, {
+ { { 4800 }, 4800, 10416, { 3377, 2138, 1780 }, Ratio{1, 8}, 1, 2560, 5136,
+ { 0, 2, 4, 6, 1, 3, 5, 7 }, {
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1707,8 +1179,14 @@ void genesys_init_sensor_tables()
for (const auto& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.resolutions.values()[0];
+ sensor.shading_resolution = setting.register_dpihw;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
sensor.segment_size = setting.segment_size;
sensor.segment_order = setting.segment_order;
sensor.custom_regs = setting.custom_regs;
@@ -1718,34 +1196,64 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_700F;
- sensor.optical_res = 4800;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_700F; // gl847
+ sensor.full_resolution = 4800;
sensor.black_pixels = 73*8; // black pixels 73 at 600 dpi
sensor.dummy_pixel = 16*8;
- // 384 at 600 dpi
- sensor.ccd_start_xoffset = 384*8;
- // 8x5570 segments, 5187+1 for rounding
- sensor.sensor_pixels = 5188*8;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
int exposure_lperiod;
SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
+ int output_pixel_offset;
unsigned segment_size;
std::vector<unsigned> segment_order;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 75, 100, 150, 200 }, 2848, { 465, 310, 239 }, 5187, std::vector<unsigned>{}, {
+ { { 75 }, 600, 2848, { 465, 310, 239 }, Ratio{1, 8}, 8, 48, 5187,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x87 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0xf9 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ { { 100 }, 600, 2848, { 465, 310, 239 }, Ratio{1, 8}, 6, 64, 5187,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x87 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0xf9 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ { { 150 }, 600, 2848, { 465, 310, 239 }, Ratio{1, 8}, 4, 96, 5187,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x87 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0xf9 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ { { 200 }, 600, 2848, { 465, 310, 239 }, Ratio{1, 8}, 3, 128, 5187,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1755,7 +1263,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 300 }, 1424, { 465, 310, 239 }, 5187, std::vector<unsigned>{}, {
+ { { 300 }, 600, 1424, { 465, 310, 239 }, Ratio{1, 8}, 2, 192, 5187,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1765,7 +1274,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 600 }, 1504, { 465, 310, 239 }, 5187, std::vector<unsigned>{}, {
+ { { 600 }, 600, 1504, { 465, 310, 239 }, Ratio{1, 8}, 1, 384, 5187,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1775,7 +1285,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 1200 }, 2696, { 1464, 844, 555 }, 5187, { 0, 1 }, {
+ { { 1200 }, 1200, 2696, { 1464, 844, 555 }, Ratio{1, 8}, 1, 768, 5187,
+ { 0, 1 }, {
{ 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1785,7 +1296,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 2400 }, 10576, { 2798, 1558, 972 }, 5187, { 0, 1, 2, 3 }, {
+ { { 2400 }, 2400, 10576, { 2798, 1558, 972 }, Ratio{1, 8}, 1, 1536, 5187,
+ { 0, 1, 2, 3 }, {
{ 0x16, 0x10 }, { 0x17, 0x08 }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1795,7 +1307,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 4800 }, 10576, { 2798, 1558, 972 }, 5187, { 0, 1, 4, 5, 2, 3, 6, 7 }, {
+ { { 4800 }, 4800, 10576, { 2798, 1558, 972 }, Ratio{1, 8}, 1, 3072, 5187,
+ { 0, 1, 4, 5, 2, 3, 6, 7 }, {
{ 0x16, 0x10 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x07 }, { 0x53, 0x03 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1809,8 +1322,14 @@ void genesys_init_sensor_tables()
for (const auto& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.resolutions.values()[0];
+ sensor.shading_resolution = setting.register_dpihw;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
sensor.segment_size = setting.segment_size;
sensor.segment_order = setting.segment_order;
sensor.custom_regs = setting.custom_regs;
@@ -1820,33 +1339,32 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_100;
- sensor.optical_res = 2400;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_100; // gl847
+ sensor.full_resolution = 2400;
sensor.black_pixels = 87*4;
sensor.dummy_pixel = 16*4;
- sensor.ccd_start_xoffset = 320*4;
- sensor.sensor_pixels = 5136*4;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x01c1, 0x0126, 0x00e5 };
sensor.gamma = { 2.2f, 2.2f, 2.2f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
int exposure_lperiod;
SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
+ int output_pixel_offset;
unsigned segment_size;
std::vector<unsigned> segment_order;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 75, 100, 150, 200 }, 2304, { 423, 294, 242 }, 5136, std::vector<unsigned>{}, {
+ { { 75 }, 600, 2304, { 423, 294, 242 }, Ratio{1, 4}, 8, 40, 5136,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1856,7 +1374,8 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 300 }, 1728, { 423, 294, 242 }, 5136, std::vector<unsigned>{}, {
+ { { 100 }, 600, 2304, { 423, 294, 242 }, Ratio{1, 4}, 6, 53, 5136,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1866,7 +1385,41 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 600 }, 1432, { 423, 294, 242 }, 5136, std::vector<unsigned>{}, {
+ { { 150 }, 600, 2304, { 423, 294, 242 }, Ratio{1, 4}, 4, 80, 5136,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ { { 200 }, 600, 2304, { 423, 294, 242 }, Ratio{1, 4}, 3, 106, 5136,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ { { 300 }, 600, 1728, { 423, 294, 242 }, Ratio{1, 4}, 2, 160, 5136,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
+ { 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x2a }, { 0x59, 0xe1 }, { 0x5a, 0x55 },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ }
+ },
+ { { 600 }, 600, 1432, { 423, 294, 242 }, Ratio{1, 4}, 1, 320, 5136,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x0a }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1876,7 +1429,7 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
},
},
- { { 1200 }, 2712, { 791, 542, 403 }, 5136, {0, 1}, {
+ { { 1200 }, 1200, 2712, { 791, 542, 403 }, Ratio{1, 4}, 1, 640, 5136, {0, 1}, {
{ 0x16, 0x10 }, { 0x17, 0x08 }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1886,7 +1439,7 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
}
},
- { { 2400 }, 5280, { 1504, 1030, 766 }, 5136, {0, 2, 1, 3}, {
+ { { 2400 }, 2400, 5280, { 1504, 1030, 766 }, Ratio{1, 4}, 1, 1280, 5136, {0, 2, 1, 3}, {
{ 0x16, 0x10 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0xff },
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x04 },
{ 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
@@ -1900,8 +1453,14 @@ void genesys_init_sensor_tables()
for (const auto& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.resolutions.values()[0];
+ sensor.shading_resolution = setting.register_dpihw;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
sensor.segment_size = setting.segment_size;
sensor.segment_order = setting.segment_order;
sensor.custom_regs = setting.custom_regs;
@@ -1910,12 +1469,12 @@ void genesys_init_sensor_tables()
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_KVSS080;
- sensor.optical_res = 600;
+ sensor.sensor_id = SensorId::CCD_KVSS080; // gl843
+ sensor.full_resolution = 600;
+ sensor.register_dpihw = 600;
+ sensor.shading_resolution = 600;
sensor.black_pixels = 38;
sensor.dummy_pixel = 38;
- sensor.ccd_start_xoffset = 152;
- sensor.sensor_pixels = 5376;
sensor.fau_gain_white_ref = 160;
sensor.gain_white_ref = 160;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
@@ -1946,191 +1505,170 @@ void genesys_init_sensor_tables()
{ 0x58, 0x6b },
{ 0x59, 0x00 },
{ 0x5a, 0xc0 },
+ { 0x7d, 0x90 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ };
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 75, Ratio{1, 1}, 4 },
+ { { 100 }, 100, Ratio{1, 1}, 6 },
+ { { 150 }, 150, Ratio{1, 1}, 9 },
+ { { 200 }, 200, Ratio{1, 1}, 12 },
+ { { 300 }, 300, Ratio{1, 1}, 19 },
+ { { 600 }, 600, Ratio{1, 1}, 38 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_G4050;
- sensor.optical_res = 4800;
+ sensor.sensor_id = SensorId::CCD_G4050; // gl843
+ sensor.full_resolution = 4800;
sensor.black_pixels = 50*8;
// 31 at 600 dpi dummy_pixels 58 at 1200
sensor.dummy_pixel = 58;
- sensor.ccd_start_xoffset = 152;
- sensor.sensor_pixels = 5360*8;
sensor.fau_gain_white_ref = 160;
sensor.gain_white_ref = 160;
sensor.exposure = { 0x2c09, 0x22b8, 0x10f0 };
- sensor.stagger_config = StaggerConfig{ 2400, 4 }; // FIXME: may be incorrect
sensor.custom_regs = {};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
int exposure_lperiod;
ScanMethod method;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ StaggerConfig stagger_y; // FIXME: may be incorrect
GenesysRegisterSettingSet extra_custom_regs;
};
+ GenesysRegisterSettingSet regs_100_to_600 = {
+ { 0x0c, 0x00 },
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
+ { 0x52, 0x0b }, { 0x53, 0x0e }, { 0x54, 0x11 }, { 0x55, 0x02 }, { 0x56, 0x05 },
+ { 0x57, 0x08 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x02 },
+ { 0x74, 0x00 }, { 0x75, 0x01 }, { 0x76, 0xff },
+ { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
+ { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff }, { 0x7d, 0x90 },
+ { 0x9e, 0x00 },
+ { 0xaa, 0x00 },
+ };
+
+ GenesysRegisterSettingSet regs_1200 = {
+ { 0x0c, 0x20 },
+ { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b }, { 0x56, 0x0e },
+ { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x08 }, { 0x71, 0x0c },
+ { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
+ { 0x77, 0x00 }, { 0x78, 0x01 }, { 0x79, 0xff },
+ { 0x7a, 0x00 }, { 0x7b, 0x01 }, { 0x7c, 0xff }, { 0x7d, 0x90 },
+ { 0x9e, 0xc0 },
+ { 0xaa, 0x05 },
+ };
+
+ GenesysRegisterSettingSet regs_2400 = {
+ { 0x0c, 0x20 },
+ { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0xc0 }, { 0x1d, 0x08 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b }, { 0x56, 0x0e },
+ { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x08 }, { 0x71, 0x0a },
+ { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x90 },
+ { 0x9e, 0xc0 },
+ { 0xaa, 0x05 },
+ };
+
+ GenesysRegisterSettingSet regs_4800 = {
+ { 0x0c, 0x21 },
+ { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0xc1 }, { 0x1d, 0x08 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b }, { 0x56, 0x0e },
+ { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x08 }, { 0x71, 0x0a },
+ { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x90 },
+ { 0x9e, 0xc0 },
+ { 0xaa, 0x07 },
+ };
+
+ GenesysRegisterSettingSet regs_ta_any = {
+ { 0x0c, 0x00 },
+ { 0x16, 0x33 }, { 0x17, 0x4c }, { 0x18, 0x01 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
+ { 0x52, 0x0e }, { 0x53, 0x11 }, { 0x54, 0x02 }, { 0x55, 0x05 }, { 0x56, 0x08 },
+ { 0x57, 0x0b }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0xc0 },
+ { 0x70, 0x00 }, { 0x71, 0x02 },
+ { 0x74, 0x00 }, { 0x75, 0x1c }, { 0x76, 0x7f },
+ { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
+ { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff }, { 0x7d, 0x90 },
+ { 0x9e, 0x00 },
+ { 0xaa, 0x00 },
+ };
+
CustomSensorSettings custom_settings[] = {
- { { 100, 150, 200, 300, 400, 600 }, 8016, ScanMethod::FLATBED, {
- { 0x74, 0x00 }, { 0x75, 0x01 }, { 0x76, 0xff },
- { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
- { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff },
- { 0x0c, 0x00 },
- { 0x70, 0x00 },
- { 0x71, 0x02 },
- { 0x9e, 0x00 },
- { 0xaa, 0x00 },
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x00 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x08 },
- { 0x52, 0x0b },
- { 0x53, 0x0e },
- { 0x54, 0x11 },
- { 0x55, 0x02 },
- { 0x56, 0x05 },
- { 0x57, 0x08 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
- }
- },
- { { 1200 }, 56064, ScanMethod::FLATBED, {
- { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
- { 0x77, 0x00 }, { 0x78, 0x01 }, { 0x79, 0xff },
- { 0x7a, 0x00 }, { 0x7b, 0x01 }, { 0x7c, 0xff },
- { 0x0c, 0x20 },
- { 0x70, 0x08 },
- { 0x71, 0x0c },
- { 0x9e, 0xc0 },
- { 0xaa, 0x05 },
- { 0x16, 0x3b },
- { 0x17, 0x0c },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x38 },
- { 0x1b, 0x10 },
- { 0x1c, 0x00 },
- { 0x1d, 0x08 },
- { 0x52, 0x02 },
- { 0x53, 0x05 },
- { 0x54, 0x08 },
- { 0x55, 0x0b },
- { 0x56, 0x0e },
- { 0x57, 0x11 },
- { 0x58, 0x1b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
- }
- },
- { { 2400 }, 56064, ScanMethod::FLATBED, {
- { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
- { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
- { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 },
- { 0x0c, 0x20 },
- { 0x70, 0x08 },
- { 0x71, 0x0a },
- { 0x9e, 0xc0 },
- { 0xaa, 0x05 },
- { 0x16, 0x3b },
- { 0x17, 0x0c },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x38 },
- { 0x1b, 0x10 },
- { 0x1c, 0xc0 },
- { 0x1d, 0x08 },
- { 0x52, 0x02 },
- { 0x53, 0x05 },
- { 0x54, 0x08 },
- { 0x55, 0x0b },
- { 0x56, 0x0e },
- { 0x57, 0x11 },
- { 0x58, 0x1b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
- }
- },
- { { 4800 }, 42752, ScanMethod::FLATBED, {
- { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
- { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
- { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 },
- { 0x0c, 0x21 },
- { 0x70, 0x08 },
- { 0x71, 0x0a },
- { 0x9e, 0xc0 },
- { 0xaa, 0x07 },
- { 0x16, 0x3b },
- { 0x17, 0x0c },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x38 },
- { 0x1b, 0x10 },
- { 0x1c, 0xc1 },
- { 0x1d, 0x08 },
- { 0x52, 0x02 },
- { 0x53, 0x05 },
- { 0x54, 0x08 },
- { 0x55, 0x0b },
- { 0x56, 0x0e },
- { 0x57, 0x11 },
- { 0x58, 0x1b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
- }
- },
- { ResolutionFilter::ANY, 15624, ScanMethod::TRANSPARENCY, {
- { 0x74, 0x00 }, { 0x75, 0x1c }, { 0x76, 0x7f },
- { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
- { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff },
- { 0x0c, 0x00 },
- { 0x70, 0x00 },
- { 0x71, 0x02 },
- { 0x9e, 0x00 },
- { 0xaa, 0x00 },
- { 0x16, 0x33 },
- { 0x17, 0x4c },
- { 0x18, 0x01 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x08 },
- { 0x52, 0x0e },
- { 0x53, 0x11 },
- { 0x54, 0x02 },
- { 0x55, 0x05 },
- { 0x56, 0x08 },
- { 0x57, 0x0b },
- { 0x58, 0x6b },
- { 0x59, 0x00 },
- { 0x5a, 0xc0 },
- }
- }
+ { { 100 }, 600, 100, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 1,
+ StaggerConfig{}, regs_100_to_600 },
+ { { 150 }, 600, 150, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 1,
+ StaggerConfig{}, regs_100_to_600 },
+ { { 200 }, 600, 200, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 2,
+ StaggerConfig{}, regs_100_to_600 },
+ { { 300 }, 600, 300, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 3,
+ StaggerConfig{}, regs_100_to_600 },
+ { { 400 }, 600, 400, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 4,
+ StaggerConfig{}, regs_100_to_600 },
+ { { 600 }, 600, 600, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 7,
+ StaggerConfig{}, regs_100_to_600 },
+ { { 1200 }, 1200, 1200, 56064, ScanMethod::FLATBED, Ratio{1, 4}, 14,
+ StaggerConfig{}, regs_1200 },
+ { { 2400 }, 2400, 2400, 56064, ScanMethod::FLATBED, Ratio{1, 2}, 29,
+ StaggerConfig{4, 0}, regs_2400 },
+ { { 4800 }, 4800, 4800, 42752, ScanMethod::FLATBED, Ratio{1, 1}, 58,
+ StaggerConfig{8, 0}, regs_4800 },
+ { { 100, 150, 200, 300, 400, 600, 1200 }, 600, 600, 15624, ScanMethod::TRANSPARENCY,
+ Ratio{1, 1}, 58, StaggerConfig{}, regs_ta_any }, // FIXME: may be incorrect
+ { { 2400 }, 600, 600, 15624, ScanMethod::TRANSPARENCY,
+ Ratio{1, 1}, 58, StaggerConfig{4, 0}, regs_ta_any }, // FIXME: may be incorrect
+ { { 4800 }, 600, 600, 15624, ScanMethod::TRANSPARENCY,
+ Ratio{1, 1}, 58, StaggerConfig{8, 0}, regs_ta_any }, // FIXME: may be incorrect
};
auto base_custom_regs = sensor.custom_regs;
for (const CustomSensorSettings& setting : custom_settings)
{
sensor.resolutions = setting.resolutions;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.register_dpihw;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.method = setting.method;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.stagger_y = setting.stagger_y;
sensor.custom_regs = base_custom_regs;
sensor.custom_regs.merge(setting.extra_custom_regs);
s_sensors->push_back(sensor);
@@ -2138,110 +1676,136 @@ void genesys_init_sensor_tables()
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_HP_4850C;
- sensor.optical_res = 4800;
+ sensor.sensor_id = SensorId::CCD_HP_4850C; // gl843
+ sensor.full_resolution = 4800;
sensor.black_pixels = 100;
sensor.dummy_pixel = 58;
- sensor.ccd_start_xoffset = 152;
- sensor.sensor_pixels = 5360*8;
sensor.fau_gain_white_ref = 160;
sensor.gain_white_ref = 160;
sensor.exposure = { 0x2c09, 0x22b8, 0x10f0 };
- sensor.stagger_config = StaggerConfig{ 2400, 4 }; // FIXME: may be incorrect
sensor.custom_regs = {};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
int exposure_lperiod;
ScanMethod method;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ int shading_pixel_offset;
+ StaggerConfig stagger_y; // FIXME: review, may be incorrect
GenesysRegisterSettingSet extra_custom_regs;
};
+ GenesysRegisterSettingSet regs_100_to_600 = {
+ { 0x0c, 0x00 },
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
+ { 0x52, 0x0b }, { 0x53, 0x0e }, { 0x54, 0x11 }, { 0x55, 0x02 },
+ { 0x56, 0x05 }, { 0x57, 0x08 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x02 },
+ { 0x74, 0x00 }, { 0x75, 0x01 }, { 0x76, 0xff },
+ { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
+ { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff }, { 0x7d, 0x90 },
+ { 0x9e, 0x00 },
+ { 0xaa, 0x00 },
+ };
+ GenesysRegisterSettingSet regs_1200 = {
+ { 0x0c, 0x20 },
+ { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
+ { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x08 }, { 0x71, 0x0c },
+ { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
+ { 0x77, 0x00 }, { 0x78, 0x01 }, { 0x79, 0xff },
+ { 0x7a, 0x00 }, { 0x7b, 0x01 }, { 0x7c, 0xff }, { 0x7d, 0x90 },
+ { 0x9e, 0xc0 },
+ { 0xaa, 0x05 },
+ };
+ GenesysRegisterSettingSet regs_2400 = {
+ { 0x0c, 0x20 },
+ { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0xc0 }, { 0x1d, 0x08 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
+ { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x08 }, { 0x71, 0x0a },
+ { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x90 },
+ { 0x9e, 0xc0 },
+ { 0xaa, 0x05 },
+ };
+ GenesysRegisterSettingSet regs_4800 = {
+ { 0x0c, 0x21 },
+ { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0xc1 }, { 0x1d, 0x08 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
+ { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x08 }, { 0x71, 0x0a },
+ { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x90 },
+ { 0x9e, 0xc0 },
+ { 0xaa, 0x07 },
+ };
+ GenesysRegisterSettingSet regs_ta_any = {
+ { 0x0c, 0x00 },
+ { 0x16, 0x33 }, { 0x17, 0x4c }, { 0x18, 0x01 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
+ { 0x52, 0x0e }, { 0x53, 0x11 }, { 0x54, 0x02 }, { 0x55, 0x05 },
+ { 0x56, 0x08 }, { 0x57, 0x0b }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0xc0 },
+ { 0x70, 0x00 }, { 0x71, 0x02 },
+ { 0x74, 0x00 }, { 0x75, 0x1c }, { 0x76, 0x7f },
+ { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
+ { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff }, { 0x7d, 0x90 },
+ { 0x9e, 0x00 },
+ { 0xaa, 0x00 },
+ };
+
CustomSensorSettings custom_settings[] = {
- { { 100, 150, 200, 300, 400, 600 }, 8016, ScanMethod::FLATBED, {
- { 0x0c, 0x00 },
- { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x00 }, { 0x19, 0x2a },
- { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
- { 0x52, 0x0b }, { 0x53, 0x0e }, { 0x54, 0x11 }, { 0x55, 0x02 },
- { 0x56, 0x05 }, { 0x57, 0x08 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0x40 },
- { 0x70, 0x00 }, { 0x71, 0x02 },
- { 0x74, 0x00 }, { 0x75, 0x01 }, { 0x76, 0xff },
- { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
- { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff },
- { 0x9e, 0x00 },
- { 0xaa, 0x00 },
- }
- },
- { { 1200 }, 56064, ScanMethod::FLATBED, {
- { 0x0c, 0x20 },
- { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
- { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
- { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
- { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
- { 0x70, 0x08 }, { 0x71, 0x0c },
- { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
- { 0x77, 0x00 }, { 0x78, 0x01 }, { 0x79, 0xff },
- { 0x7a, 0x00 }, { 0x7b, 0x01 }, { 0x7c, 0xff },
- { 0x9e, 0xc0 },
- { 0xaa, 0x05 },
- }
- },
- { { 2400 }, 56064, ScanMethod::FLATBED, {
- { 0x0c, 0x20 },
- { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
- { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0xc0 }, { 0x1d, 0x08 },
- { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
- { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
- { 0x70, 0x08 }, { 0x71, 0x0a },
- { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
- { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
- { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 },
- { 0x9e, 0xc0 },
- { 0xaa, 0x05 },
- }
- },
- { { 4800 }, 42752, ScanMethod::FLATBED, {
- { 0x0c, 0x21 },
- { 0x16, 0x3b }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
- { 0x1a, 0x38 }, { 0x1b, 0x10 }, { 0x1c, 0xc1 }, { 0x1d, 0x08 },
- { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
- { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
- { 0x70, 0x08 }, { 0x71, 0x0a },
- { 0x74, 0x0f }, { 0x75, 0xff }, { 0x76, 0xff },
- { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
- { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 },
- { 0x9e, 0xc0 },
- { 0xaa, 0x07 },
- }
- },
- { ResolutionFilter::ANY, 15624, ScanMethod::TRANSPARENCY, {
- { 0x0c, 0x00 },
- { 0x16, 0x33 }, { 0x17, 0x4c }, { 0x18, 0x01 }, { 0x19, 0x2a },
- { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x08 },
- { 0x52, 0x0e }, { 0x53, 0x11 }, { 0x54, 0x02 }, { 0x55, 0x05 },
- { 0x56, 0x08 }, { 0x57, 0x0b }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0xc0 },
- { 0x70, 0x00 }, { 0x71, 0x02 },
- { 0x74, 0x00 }, { 0x75, 0x1c }, { 0x76, 0x7f },
- { 0x77, 0x03 }, { 0x78, 0xff }, { 0x79, 0xff },
- { 0x7a, 0x03 }, { 0x7b, 0xff }, { 0x7c, 0xff },
- { 0x9e, 0x00 },
- { 0xaa, 0x00 },
- }
- }
+ { { 100 }, 600, 100, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 1, 50, StaggerConfig{},
+ regs_100_to_600 },
+ { { 150 }, 600, 150, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 1, 50, StaggerConfig{},
+ regs_100_to_600 },
+ { { 200 }, 600, 200, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 2, 50, StaggerConfig{},
+ regs_100_to_600 },
+ { { 300 }, 600, 300, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 3, 50, StaggerConfig{},
+ regs_100_to_600 },
+ { { 400 }, 600, 400, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 4, 50, StaggerConfig{},
+ regs_100_to_600 },
+ { { 600 }, 600, 600, 8016, ScanMethod::FLATBED, Ratio{1, 8}, 7, 50, StaggerConfig{},
+ regs_100_to_600 },
+ { { 1200 }, 1200, 1200, 56064, ScanMethod::FLATBED, Ratio{1, 4}, 14, 0,
+ StaggerConfig{}, regs_1200 },
+ { { 2400 }, 2400, 2400, 56064, ScanMethod::FLATBED, Ratio{1, 2}, 29, 0,
+ StaggerConfig{0, 4}, regs_2400 },
+ { { 4800 }, 4800, 4800, 42752, ScanMethod::FLATBED, Ratio{1, 1}, 58, 0,
+ StaggerConfig{0, 8}, regs_4800 },
+ { { 100, 150, 200, 300, 400, 600, 1200}, 600, 600, 15624, ScanMethod::TRANSPARENCY,
+ Ratio{1, 1}, 58, 0, StaggerConfig{}, regs_ta_any }, // FIXME: review
+ { { 2400 }, 600, 600, 15624, ScanMethod::TRANSPARENCY,
+ Ratio{1, 1}, 58, 0, StaggerConfig{0, 4}, regs_ta_any }, // FIXME: review
+ { { 4800 }, 600, 600, 15624, ScanMethod::TRANSPARENCY,
+ Ratio{1, 1}, 58, 0, StaggerConfig{0, 8}, regs_ta_any }, // FIXME: review
};
auto base_custom_regs = sensor.custom_regs;
for (const CustomSensorSettings& setting : custom_settings)
{
sensor.resolutions = setting.resolutions;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.register_dpihw;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.method = setting.method;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.shading_pixel_offset = setting.shading_pixel_offset;
+ sensor.stagger_y = setting.stagger_y;
sensor.custom_regs = base_custom_regs;
sensor.custom_regs.merge(setting.extra_custom_regs);
s_sensors->push_back(sensor);
@@ -2249,142 +1813,250 @@ void genesys_init_sensor_tables()
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_CANON_4400F;
- sensor.optical_res = 4800;
- sensor.ccd_size_divisor = 4;
+ sensor.sensor_id = SensorId::CCD_CANON_4400F; // gl843
+ sensor.full_resolution = 4800;
+ sensor.register_dpihw = 4800;
sensor.black_pixels = 50*8;
// 31 at 600 dpi, 58 at 1200 dpi
sensor.dummy_pixel = 20;
- sensor.ccd_start_xoffset = 152;
- // 5360 max at 600 dpi
- sensor.sensor_pixels = 5700 * 8;
sensor.fau_gain_white_ref = 160;
sensor.gain_white_ref = 160;
sensor.exposure = { 0x9c40, 0x9c40, 0x9c40 };
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = get_sensor_optical_with_ccd_divisor;
- sensor.get_register_hwdpi_fun = [](const Genesys_Sensor&, unsigned) { return 4800; };
- sensor.get_hwdpi_divisor_fun = [](const Genesys_Sensor&, unsigned) { return 1; };
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpiset;
int exposure_lperiod;
+ bool use_host_side_calib;
+ int output_pixel_offset;
std::vector<ScanMethod> methods;
+ StaggerConfig stagger_y;
GenesysRegisterSettingSet extra_custom_regs;
+ GenesysRegisterSettingSet extra_custom_fe_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 300, 600, 1200 }, 11640, { ScanMethod::FLATBED }, {
- { 0x16, 0x13 },
- { 0x17, 0x0a },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x6b },
- { 0x52, 0x0a },
- { 0x53, 0x0d },
- { 0x54, 0x00 },
- { 0x55, 0x03 },
- { 0x56, 0x06 },
- { 0x57, 0x08 },
- { 0x58, 0x5b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 300 }, 1200, 1200, 11640, false, 197, { ScanMethod::FLATBED }, StaggerConfig{}, {
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0a }, { 0x53, 0x0d }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x56, 0x06 }, { 0x57, 0x08 }, { 0x58, 0x5b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x01 }, { 0x73, 0x03 },
{ 0x74, 0x00 }, { 0x75, 0xf8 }, { 0x76, 0x38 },
{ 0x77, 0x00 }, { 0x78, 0xfc }, { 0x79, 0x00 },
{ 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0xa4 },
{ 0x9e, 0x2d },
- }
+ }, {}
+ },
+ { { 600 }, 1200, 2400, 11640, false, 392, { ScanMethod::FLATBED }, StaggerConfig{}, {
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0a }, { 0x53, 0x0d }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x56, 0x06 }, { 0x57, 0x08 }, { 0x58, 0x5b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x01 }, { 0x73, 0x03 },
+ { 0x74, 0x00 }, { 0x75, 0xf8 }, { 0x76, 0x38 },
+ { 0x77, 0x00 }, { 0x78, 0xfc }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0xa4 },
+ { 0x9e, 0x2d },
+ }, {}
+ },
+ { { 1200 }, 1200, 4800, 11640, false, 794, { ScanMethod::FLATBED }, StaggerConfig{}, {
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0a }, { 0x53, 0x0d }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x56, 0x06 }, { 0x57, 0x08 }, { 0x58, 0x5b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x01 }, { 0x73, 0x03 },
+ { 0x74, 0x00 }, { 0x75, 0xf8 }, { 0x76, 0x38 },
+ { 0x77, 0x00 }, { 0x78, 0xfc }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0xa4 },
+ { 0x9e, 0x2d },
+ }, {}
},
- { { 300, 600, 1200 }, 33300, { ScanMethod::TRANSPARENCY }, {
- { 0x16, 0x13 },
- { 0x17, 0x0a },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x6b },
- { 0x52, 0x0a },
- { 0x53, 0x0d },
- { 0x54, 0x00 },
- { 0x55, 0x03 },
- { 0x56, 0x06 },
- { 0x57, 0x08 },
- { 0x58, 0x5b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 1200 }, 1200, 4800, 33300, true, 5, { ScanMethod::TRANSPARENCY },
+ StaggerConfig{}, {
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0a }, { 0x53, 0x0d }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x56, 0x06 }, { 0x57, 0x08 }, { 0x58, 0x5b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x00 }, { 0x73, 0x02 },
{ 0x74, 0x00 }, { 0x75, 0xf8 }, { 0x76, 0x38 },
{ 0x77, 0x00 }, { 0x78, 0xfc }, { 0x79, 0x00 },
{ 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0xa4 },
{ 0x9e, 0x2d },
- }
+ }, {}
},
- { { 2400 }, 33300, { ScanMethod::TRANSPARENCY }, {
- { 0x16, 0x13 },
- { 0x17, 0x0a },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x01 },
- { 0x1d, 0x75 },
- { 0x52, 0x0b },
- { 0x53, 0x0d },
- { 0x54, 0x00 },
- { 0x55, 0x03 },
- { 0x56, 0x06 },
- { 0x57, 0x09 },
- { 0x58, 0x53 },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 2400 }, 2400, 4800, 33300, true, 10, { ScanMethod::TRANSPARENCY },
+ StaggerConfig{}, {
+ { 0x16, 0x13 }, { 0x17, 0x15 }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x01 }, { 0x1d, 0x75 },
+ { 0x52, 0x0b }, { 0x53, 0x0d }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x56, 0x06 }, { 0x57, 0x09 }, { 0x58, 0x53 }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x02 }, { 0x73, 0x04 },
{ 0x74, 0x00 }, { 0x75, 0xff }, { 0x76, 0x00 },
{ 0x77, 0x00 }, { 0x78, 0xff }, { 0x79, 0x00 },
{ 0x7a, 0x00 }, { 0x7b, 0x54 }, { 0x7c, 0x92 },
{ 0x9e, 0x2d },
+ }, {
+ { 0x03, 0x1f },
}
},
- { { 4800 }, 33300, { ScanMethod::TRANSPARENCY }, {
- { 0x16, 0x13 },
- { 0x17, 0x0a },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x61 },
- { 0x1d, 0x75 },
- { 0x52, 0x02 },
- { 0x53, 0x05 },
- { 0x54, 0x08 },
- { 0x55, 0x0b },
- { 0x56, 0x0d },
- { 0x57, 0x0f },
- { 0x58, 0x1b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 4800 }, 4800, 4800, 33300, true, -2063, { ScanMethod::TRANSPARENCY },
+ StaggerConfig{0, 8}, {
+ { 0x16, 0x13 }, { 0x17, 0x15 }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x61 }, { 0x1d, 0x75 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
+ { 0x56, 0x0d }, { 0x57, 0x0f }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x08 }, { 0x71, 0x0a }, { 0x72, 0x0a }, { 0x73, 0x0c },
{ 0x74, 0x00 }, { 0x75, 0xff }, { 0x76, 0xff },
{ 0x77, 0x00 }, { 0x78, 0xff }, { 0x79, 0xff },
{ 0x7a, 0x00 }, { 0x7b, 0x54 }, { 0x7c, 0x92 },
{ 0x9e, 0x2d },
- }
+ }, {}
}
};
for (const CustomSensorSettings& setting : custom_settings)
{
for (auto method : setting.methods) {
+ for (auto resolution : setting.resolutions.values()) {
+ sensor.resolutions = { resolution };
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = resolution;
+ sensor.exposure_lperiod = setting.exposure_lperiod;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.use_host_side_calib = setting.use_host_side_calib;
+ sensor.method = method;
+ sensor.stagger_y = setting.stagger_y;
+ sensor.custom_regs = setting.extra_custom_regs;
+ sensor.custom_fe_regs = setting.extra_custom_fe_regs;
+ s_sensors->push_back(sensor);
+ }
+ }
+ }
+ }
+
+
+ sensor = Genesys_Sensor();
+ sensor.sensor_id = SensorId::CCD_CANON_5600F; // gl847
+ sensor.full_resolution = 4800;
+ sensor.register_dpihw = 4800;
+ sensor.black_pixels = 50*8;
+ sensor.dummy_pixel = 10;
+ sensor.fau_gain_white_ref = 160;
+ sensor.gain_white_ref = 160;
+ sensor.exposure = { 0x9c40, 0x9c40, 0x9c40 };
+ sensor.gamma = { 1.0f, 1.0f, 1.0f };
+ sensor.use_host_side_calib = true;
+ {
+ struct CustomSensorSettings {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
+ int exposure_lperiod;
+ SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ unsigned segment_size;
+ std::vector<unsigned> segment_order;
+ StaggerConfig stagger_x;
+ StaggerConfig stagger_y;
+ GenesysRegisterSettingSet custom_regs;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 150 }, 2400, 600, 300, 4288, { 3983/2, 3983/2, 3983/2 }, Ratio{1, 8}, 10,
+ 5418, std::vector<unsigned>{}, StaggerConfig{}, StaggerConfig{}, {
+ { 0x16, 0x00 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x10 }, { 0x1c, 0x08 }, { 0x1d, 0x02 },
+ { 0x52, 0x0e }, { 0x53, 0x00 }, { 0x54, 0x02 }, { 0x55, 0x04 },
+ { 0x56, 0x06 }, { 0x57, 0x08 }, { 0x58, 0x52 }, { 0x59, 0x3a }, { 0x5a, 0x40 },
+ { 0x74, 0x00 }, { 0x75, 0x33 }, { 0x76, 0x33 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 }, { 0x87, 0x00 },
+ }
+ },
+ { { 300 }, 2400, 600, 600, 5472, { 4558/2, 4558/2, 4558/2 }, Ratio{1, 8}, 110,
+ 5418, std::vector<unsigned>{}, StaggerConfig{}, StaggerConfig{}, {
+ { 0x16, 0x00 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x10 }, { 0x1c, 0x08 }, { 0x1d, 0x02 },
+ { 0x52, 0x0e }, { 0x53, 0x00 }, { 0x54, 0x02 }, { 0x55, 0x04 },
+ { 0x56, 0x06 }, { 0x57, 0x08 }, { 0x58, 0x52 }, { 0x59, 0x3a }, { 0x5a, 0x40 },
+ { 0x74, 0x00 }, { 0x75, 0x33 }, { 0x76, 0x33 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 }, { 0x87, 0x00 },
+ }
+ },
+ { { 600 }, 2400, 600, 600, 10944, { 8701/2, 8701/2, 8701/2 }, Ratio{1, 4}, 155,
+ 5418, std::vector<unsigned>{}, StaggerConfig{}, StaggerConfig{}, {
+ { 0x16, 0x00 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x10 }, { 0x1c, 0x08 }, { 0x1d, 0x02 },
+ { 0x52, 0x02 }, { 0x53, 0x04 }, { 0x54, 0x06 }, { 0x55, 0x08 },
+ { 0x56, 0x0a }, { 0x57, 0x0c }, { 0x58, 0x72 }, { 0x59, 0x5a }, { 0x5a, 0x40 },
+ { 0x74, 0x00 }, { 0x75, 0x33 }, { 0x76, 0x33 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 }, { 0x87, 0x00 },
+ }
+ },
+ { { 1200 }, 2400, 1200, 1200, 29120, { 17120/2, 17120/2, 17120/2 }, Ratio{1, 2}, 295,
+ 5418, { 1, 0 }, StaggerConfig{}, StaggerConfig{}, {
+ { 0x16, 0x00 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x10 }, { 0x1c, 0x08 }, { 0x1d, 0x02 },
+ { 0x52, 0x02 }, { 0x53, 0x04 }, { 0x54, 0x06 }, { 0x55, 0x08 },
+ { 0x56, 0x0a }, { 0x57, 0x0c }, { 0x58, 0x72 }, { 0x59, 0x5a }, { 0x5a, 0x40 },
+ { 0x74, 0x00 }, { 0x75, 0x33 }, { 0x76, 0x33 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 }, { 0x87, 0x00 },
+ }
+ },
+ { { 2400 }, 2400, 2400, 2400, 43776, { 36725/2, 36725/2, 36725/2 }, Ratio{1, 1}, 600,
+ 5418, { 0, 1, 2, 3 },
+ StaggerConfig{10, 15, 4, 9, 14, 19, 8, 13}, StaggerConfig{}, {
+ { 0x16, 0x00 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x10 }, { 0x1c, 0x08 }, { 0x1d, 0x02 },
+ { 0x52, 0x02 }, { 0x53, 0x04 }, { 0x54, 0x06 }, { 0x55, 0x08 },
+ { 0x56, 0x0a }, { 0x57, 0x0c }, { 0x58, 0x72 }, { 0x59, 0x5a }, { 0x5a, 0x40 },
+ { 0x74, 0x00 }, { 0x75, 0x33 }, { 0x76, 0x33 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 }, { 0x87, 0x00 },
+ }
+ },
+ { { 4800 }, 4800, 4800, 4800, 43776, { 36725/2, 36725/2, 36725/2 }, Ratio{1, 1}, 1000,
+ 10784, { 0, 1, 2, 3 },
+ StaggerConfig{5, 9, 6, 10, 3, 7, 16, 20, 13, 17, 14, 18, 11, 15, 24, 28},
+ StaggerConfig{6, 0}, {
+ { 0x16, 0x00 }, { 0x17, 0x06 }, { 0x18, 0x00 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x10 }, { 0x1c, 0x08 }, { 0x1d, 0x02 },
+ { 0x52, 0x0a }, { 0x53, 0x0c }, { 0x54, 0x0e }, { 0x55, 0x00 },
+ { 0x56, 0x02 }, { 0x57, 0x04 }, { 0x58, 0x32 }, { 0x59, 0x1a }, { 0x5a, 0x40 },
+ { 0x74, 0x00 }, { 0x75, 0x33 }, { 0x76, 0x33 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 }, { 0x87, 0x00 },
+ }
+ }
+ };
+
+ for (const auto& setting : custom_settings) {
+ for (auto method : { ScanMethod::FLATBED, ScanMethod::TRANSPARENCY }) {
+ sensor.method = method;
sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.resolutions.values().front();
sensor.exposure_lperiod = setting.exposure_lperiod;
- sensor.method = method;
- sensor.custom_regs = setting.extra_custom_regs;
+ sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.segment_size = setting.segment_size;
+ sensor.segment_order = setting.segment_order;
+ sensor.stagger_x = setting.stagger_x;
+ sensor.stagger_y = setting.stagger_y;
+ sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
}
}
@@ -2392,57 +2064,39 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_CANON_8400F;
- sensor.optical_res = 3200;
- sensor.register_dpihw_override = 4800;
- sensor.ccd_size_divisor = 1;
+ sensor.sensor_id = SensorId::CCD_CANON_8400F; // gl843
+ sensor.full_resolution = 3200;
+ sensor.register_dpihw = 4800;
sensor.black_pixels = 50*8;
// 31 at 600 dpi, 58 at 1200 dpi
sensor.dummy_pixel = 20;
- sensor.ccd_start_xoffset = 152;
- sensor.sensor_pixels = 27200;
sensor.fau_gain_white_ref = 160;
sensor.gain_white_ref = 160;
sensor.exposure = { 0x9c40, 0x9c40, 0x9c40 };
- sensor.stagger_config = StaggerConfig{ 3200, 6 };
sensor.custom_regs = {};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = get_sensor_optical_with_ccd_divisor;
- sensor.get_register_hwdpi_fun = [](const Genesys_Sensor&, unsigned) { return 4800; };
- sensor.get_hwdpi_divisor_fun = [](const Genesys_Sensor&, unsigned) { return 1; };
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
- unsigned dpiset_override;
- unsigned pixel_count_multiplier;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ Ratio pixel_count_ratio;
int exposure_lperiod;
+ int output_pixel_offset;
+ int shading_pixel_offset;
std::vector<ScanMethod> methods;
+ StaggerConfig stagger_y;
GenesysRegisterSettingSet extra_custom_regs;
GenesysRegisterSettingSet custom_fe_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 400 }, 2400, 1, 7200, { ScanMethod::FLATBED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x13 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa0 },
- { 0x52, 0x0d },
- { 0x53, 0x10 },
- { 0x54, 0x01 },
- { 0x55, 0x04 },
- { 0x56, 0x07 },
- { 0x57, 0x0a },
- { 0x58, 0x6b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 400 }, 2400, Ratio{1, 4}, 7200, 2, 0, { ScanMethod::FLATBED },
+ StaggerConfig{}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x13 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x84 }, { 0x1e, 0xa0 },
+ { 0x52, 0x0d }, { 0x53, 0x10 }, { 0x54, 0x01 }, { 0x55, 0x04 },
+ { 0x56, 0x07 }, { 0x57, 0x0a }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x01 }, { 0x71, 0x02 }, { 0x72, 0x03 }, { 0x73, 0x04 },
{ 0x74, 0x00 }, { 0x75, 0x0e }, { 0x76, 0x3f },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
@@ -2450,25 +2104,12 @@ void genesys_init_sensor_tables()
{ 0x80, 0x2a },
}, {}
},
- { { 800 }, 4800, 1, 7200, { ScanMethod::FLATBED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x13 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa0 },
- { 0x52, 0x0d },
- { 0x53, 0x10 },
- { 0x54, 0x01 },
- { 0x55, 0x04 },
- { 0x56, 0x07 },
- { 0x57, 0x0a },
- { 0x58, 0x6b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 800 }, 4800, Ratio{1, 4}, 7200, 5, 13, { ScanMethod::FLATBED },
+ StaggerConfig{}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x13 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x84 }, { 0x1e, 0xa0 },
+ { 0x52, 0x0d }, { 0x53, 0x10 }, { 0x54, 0x01 }, { 0x55, 0x04 },
+ { 0x56, 0x07 }, { 0x57, 0x0a }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x01 }, { 0x71, 0x02 }, { 0x72, 0x03 }, { 0x73, 0x04 },
{ 0x74, 0x00 }, { 0x75, 0x0e }, { 0x76, 0x3f },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
@@ -2476,26 +2117,13 @@ void genesys_init_sensor_tables()
{ 0x80, 0x20 },
}, {}
},
- { { 1600 }, 4800, 1, 14400, { ScanMethod::FLATBED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x11 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa1 },
- { 0x52, 0x0b },
- { 0x53, 0x0e },
- { 0x54, 0x11 },
- { 0x55, 0x02 },
- { 0x56, 0x05 },
- { 0x57, 0x08 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
- { 0x70, 0x01 }, { 0x71, 0x02 }, { 0x72, 0x02 }, { 0x73, 0x03 },
+ { { 1600 }, 4800, Ratio{1, 2}, 14400, 10, 8, { ScanMethod::FLATBED },
+ StaggerConfig{}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x11 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x84 }, { 0x1e, 0xa1 },
+ { 0x52, 0x0b }, { 0x53, 0x0e }, { 0x54, 0x11 }, { 0x55, 0x02 },
+ { 0x56, 0x05 }, { 0x57, 0x08 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x01 }, { 0x72, 0x02 }, { 0x73, 0x03 },
{ 0x74, 0x00 }, { 0x75, 0x01 }, { 0x76, 0xff },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
{ 0x7a, 0x02 }, { 0x7b, 0x49 }, { 0x7c, 0x24 },
@@ -2504,25 +2132,12 @@ void genesys_init_sensor_tables()
{ 0x03, 0x1f },
}
},
- { { 3200 }, 4800, 1, 28800, { ScanMethod::FLATBED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x20 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa1 },
- { 0x52, 0x02 },
- { 0x53, 0x05 },
- { 0x54, 0x08 },
- { 0x55, 0x0b },
- { 0x56, 0x0e },
- { 0x57, 0x11 },
- { 0x58, 0x1b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 3200 }, 4800, Ratio{1, 1}, 28800, 20, -2, { ScanMethod::FLATBED },
+ StaggerConfig{0, 6}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x84 }, { 0x1e, 0xa1 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
+ { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x09 }, { 0x71, 0x0a }, { 0x72, 0x0b }, { 0x73, 0x0c },
{ 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x00 },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
@@ -2532,26 +2147,13 @@ void genesys_init_sensor_tables()
{ 0x03, 0x1f },
},
},
- { { 400 }, 2400, 1, 14400, { ScanMethod::TRANSPARENCY,
- ScanMethod::TRANSPARENCY_INFRARED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x13 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa0 },
- { 0x52, 0x0d },
- { 0x53, 0x10 },
- { 0x54, 0x01 },
- { 0x55, 0x04 },
- { 0x56, 0x07 },
- { 0x57, 0x0a },
- { 0x58, 0x6b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 400 }, 2400, Ratio{1, 4}, 14400, 2, 0, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x13 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x84 }, { 0x1e, 0xa0 },
+ { 0x52, 0x0d }, { 0x53, 0x10 }, { 0x54, 0x01 }, { 0x55, 0x04 },
+ { 0x56, 0x07 }, { 0x57, 0x0a }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x01 }, { 0x71, 0x02 }, { 0x72, 0x03 }, { 0x73, 0x04 },
{ 0x74, 0x00 }, { 0x75, 0x0e }, { 0x76, 0x3f },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
@@ -2559,53 +2161,27 @@ void genesys_init_sensor_tables()
{ 0x80, 0x20 },
}, {}
},
- { { 800 }, 4800, 1, 14400, { ScanMethod::TRANSPARENCY,
- ScanMethod::TRANSPARENCY_INFRARED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x13 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa0 },
- { 0x52, 0x0d },
- { 0x53, 0x10 },
- { 0x54, 0x01 },
- { 0x55, 0x04 },
- { 0x56, 0x07 },
- { 0x57, 0x0a },
- { 0x58, 0x6b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
- { 0x70, 0x01 }, { 0x71, 0x02 }, { 0x72, 0x03 }, { 0x73, 0x04 },
+ { { 800 }, 4800, Ratio{1, 4}, 14400, 5, 13, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x13 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x84 }, { 0x1e, 0xa0 },
+ { 0x52, 0x0d }, { 0x53, 0x10 }, { 0x54, 0x01 }, { 0x55, 0x04 },
+ { 0x56, 0x07 }, { 0x57, 0x0a }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x01 }, { 0x72, 0x02 }, { 0x73, 0x03 },
{ 0x74, 0x00 }, { 0x75, 0x0e }, { 0x76, 0x3f },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
{ 0x7a, 0x01 }, { 0x7b, 0xb6 }, { 0x7c, 0xdb },
{ 0x80, 0x20 },
}, {}
},
- { { 1600 }, 4800, 1, 28800, { ScanMethod::TRANSPARENCY,
- ScanMethod::TRANSPARENCY_INFRARED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x11 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa0 },
- { 0x52, 0x0b },
- { 0x53, 0x0e },
- { 0x54, 0x11 },
- { 0x55, 0x02 },
- { 0x56, 0x05 },
- { 0x57, 0x08 },
- { 0x58, 0x63 },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 1600 }, 4800, Ratio{1, 2}, 28800, 10, 8, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x11 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x84 }, { 0x1e, 0xa0 },
+ { 0x52, 0x0b }, { 0x53, 0x0e }, { 0x54, 0x11 }, { 0x55, 0x02 },
+ { 0x56, 0x05 }, { 0x57, 0x08 }, { 0x58, 0x63 }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x00 }, { 0x71, 0x01 }, { 0x72, 0x02 }, { 0x73, 0x03 },
{ 0x74, 0x00 }, { 0x75, 0x01 }, { 0x76, 0xff },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
@@ -2615,26 +2191,13 @@ void genesys_init_sensor_tables()
{ 0x03, 0x1f },
},
},
- { { 3200 }, 4800, 1, 28800, { ScanMethod::TRANSPARENCY,
- ScanMethod::TRANSPARENCY_INFRARED }, {
- { 0x16, 0x33 },
- { 0x17, 0x0c },
- { 0x18, 0x10 },
- { 0x19, 0x2a },
- { 0x1a, 0x30 },
- { 0x1b, 0x00 },
- { 0x1c, 0x20 },
- { 0x1d, 0x84 },
- { 0x1e, 0xa0 },
- { 0x52, 0x02 },
- { 0x53, 0x05 },
- { 0x54, 0x08 },
- { 0x55, 0x0b },
- { 0x56, 0x0e },
- { 0x57, 0x11 },
- { 0x58, 0x1b },
- { 0x59, 0x00 },
- { 0x5a, 0x40 },
+ { { 3200 }, 4800, Ratio{1, 1}, 28800, 20, 10, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{0, 6}, {
+ { 0x16, 0x33 }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x84 }, { 0x1e, 0xa0 },
+ { 0x52, 0x02 }, { 0x53, 0x05 }, { 0x54, 0x08 }, { 0x55, 0x0b },
+ { 0x56, 0x0e }, { 0x57, 0x11 }, { 0x58, 0x1b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
{ 0x70, 0x09 }, { 0x71, 0x0a }, { 0x72, 0x0b }, { 0x73, 0x0c },
{ 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x00 },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
@@ -2648,51 +2211,68 @@ void genesys_init_sensor_tables()
for (const CustomSensorSettings& setting : custom_settings)
{
- for (auto method : setting.methods) {
- sensor.resolutions = setting.resolutions;
- sensor.dpiset_override = setting.dpiset_override;
- sensor.pixel_count_multiplier = setting.pixel_count_multiplier;
- sensor.exposure_lperiod = setting.exposure_lperiod;
- sensor.method = method;
- sensor.custom_regs = setting.extra_custom_regs;
- sensor.custom_fe_regs = setting.custom_fe_regs;
- s_sensors->push_back(sensor);
+ for (auto method : setting.methods)
+ {for (auto resolution : setting.resolutions.values()) {
+ sensor.resolutions = { resolution };
+ sensor.shading_resolution = resolution;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.exposure_lperiod = setting.exposure_lperiod;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.shading_pixel_offset = setting.shading_pixel_offset;
+ sensor.method = method;
+ sensor.stagger_y = setting.stagger_y;
+ sensor.custom_regs = setting.extra_custom_regs;
+ sensor.custom_fe_regs = setting.custom_fe_regs;
+ s_sensors->push_back(sensor);
+ }
}
}
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_CANON_8600F;
- sensor.optical_res = 4800;
- sensor.ccd_size_divisor = 4;
+ sensor.sensor_id = SensorId::CCD_CANON_8600F; // gl843
+ sensor.full_resolution = 4800;
+ sensor.register_dpihw = 4800;
sensor.black_pixels = 31;
sensor.dummy_pixel = 20;
- sensor.ccd_start_xoffset = 0; // not used at the moment
- // 11372 pixels at 1200 dpi
- sensor.sensor_pixels = 11372*4;
sensor.fau_gain_white_ref = 160;
sensor.gain_white_ref = 160;
sensor.exposure = { 0x9c40, 0x9c40, 0x9c40 };
- sensor.stagger_config = StaggerConfig{4800, 8};
sensor.custom_regs = {};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = get_sensor_optical_with_ccd_divisor;
- sensor.get_register_hwdpi_fun = [](const Genesys_Sensor&, unsigned) { return 4800; };
- sensor.get_hwdpi_divisor_fun = [](const Genesys_Sensor&, unsigned) { return 1; };
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpiset;
int exposure_lperiod;
+ int output_pixel_offset;
std::vector<ScanMethod> methods;
+ StaggerConfig stagger_y;
GenesysRegisterSettingSet extra_custom_regs;
GenesysRegisterSettingSet custom_fe_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 300, 600, 1200 }, 24000, { ScanMethod::FLATBED }, {
+ { { 300 }, 1200, 1200, 24000, 1, { ScanMethod::FLATBED }, StaggerConfig{}, {
+ { 0x0c, 0x00 },
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0c }, { 0x53, 0x0f }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x02 }, { 0x73, 0x04 },
+ { 0x56, 0x06 }, { 0x57, 0x09 }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x74, 0x03 }, { 0x75, 0xf0 }, { 0x76, 0xf0 },
+ { 0x77, 0x03 }, { 0x78, 0xfe }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0x49 },
+ { 0x9e, 0x2d },
+ { 0xaa, 0x00 },
+ },
+ {},
+ },
+ { { 600 }, 1200, 2400, 24000, 2, { ScanMethod::FLATBED }, StaggerConfig{}, {
{ 0x0c, 0x00 },
{ 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
@@ -2707,8 +2287,24 @@ void genesys_init_sensor_tables()
},
{},
},
- { { 300, 600, 1200 }, 45000, { ScanMethod::TRANSPARENCY,
- ScanMethod::TRANSPARENCY_INFRARED }, {
+ { { 1200 }, 1200, 4800, 24000, 5, { ScanMethod::FLATBED }, StaggerConfig{}, {
+ { 0x0c, 0x00 },
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0c }, { 0x53, 0x0f }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x02 }, { 0x73, 0x04 },
+ { 0x56, 0x06 }, { 0x57, 0x09 }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x74, 0x03 }, { 0x75, 0xf0 }, { 0x76, 0xf0 },
+ { 0x77, 0x03 }, { 0x78, 0xfe }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0x49 },
+ { 0x9e, 0x2d },
+ { 0xaa, 0x00 },
+ },
+ {},
+ },
+ { { 300 }, 1200, 1200, 45000, 6, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{}, {
{ 0x0c, 0x00 },
{ 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
@@ -2723,8 +2319,43 @@ void genesys_init_sensor_tables()
},
{},
},
- { { 2400 }, 45000, { ScanMethod::TRANSPARENCY,
- ScanMethod::TRANSPARENCY_INFRARED }, {
+ { { 600 }, 1200, 2400, 45000, 11, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{}, {
+ { 0x0c, 0x00 },
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0c }, { 0x53, 0x0f }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x56, 0x06 }, { 0x57, 0x09 }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x02 }, { 0x73, 0x04 },
+ { 0x74, 0x03 }, { 0x75, 0xf0 }, { 0x76, 0xf0 },
+ { 0x77, 0x03 }, { 0x78, 0xfe }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0x49 },
+ { 0x9e, 0x2d },
+ { 0xaa, 0x00 },
+ },
+ {},
+ },
+ { { 1200 }, 1200, 4800, 45000, 23, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{}, {
+ { 0x0c, 0x00 },
+ { 0x16, 0x13 }, { 0x17, 0x0a }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x6b },
+ { 0x52, 0x0c }, { 0x53, 0x0f }, { 0x54, 0x00 }, { 0x55, 0x03 },
+ { 0x56, 0x06 }, { 0x57, 0x09 }, { 0x58, 0x6b }, { 0x59, 0x00 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x02 }, { 0x72, 0x02 }, { 0x73, 0x04 },
+ { 0x74, 0x03 }, { 0x75, 0xf0 }, { 0x76, 0xf0 },
+ { 0x77, 0x03 }, { 0x78, 0xfe }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x92 }, { 0x7c, 0x49 },
+ { 0x9e, 0x2d },
+ { 0xaa, 0x00 },
+ },
+ {},
+ },
+ { { 2400 }, 2400, 4800, 45000, 10, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{}, {
{ 0x0c, 0x00 },
{ 0x16, 0x13 }, { 0x17, 0x15 }, { 0x18, 0x10 }, { 0x19, 0x2a },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x01 }, { 0x1d, 0x75 },
@@ -2739,8 +2370,9 @@ void genesys_init_sensor_tables()
},
{},
},
- { { 4800 }, 45000, { ScanMethod::TRANSPARENCY,
- ScanMethod::TRANSPARENCY_INFRARED }, {
+ { { 4800 }, 4800, 4800, 45000, -1982, { ScanMethod::TRANSPARENCY,
+ ScanMethod::TRANSPARENCY_INFRARED },
+ StaggerConfig{8, 0}, {
{ 0x0c, 0x00 },
{ 0x16, 0x13 }, { 0x17, 0x15 }, { 0x18, 0x10 }, { 0x19, 0x2a },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x61 }, { 0x1d, 0x75 },
@@ -2760,25 +2392,30 @@ void genesys_init_sensor_tables()
for (const CustomSensorSettings& setting : custom_settings) {
for (auto method : setting.methods) {
- sensor.resolutions = setting.resolutions;
- sensor.method = method;
- sensor.exposure_lperiod = setting.exposure_lperiod;
- sensor.custom_regs = setting.extra_custom_regs;
- sensor.custom_fe_regs = setting.custom_fe_regs;
- s_sensors->push_back(sensor);
+ for (auto resolution : setting.resolutions.values()) {
+ sensor.resolutions = { resolution };
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = resolution;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.method = method;
+ sensor.exposure_lperiod = setting.exposure_lperiod;
+ sensor.stagger_y = setting.stagger_y;
+ sensor.custom_regs = setting.extra_custom_regs;
+ sensor.custom_fe_regs = setting.custom_fe_regs;
+ s_sensors->push_back(sensor);
+ }
}
}
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_HP_N6310;
- sensor.optical_res = 2400;
- // sensor.ccd_size_divisor = 2; Possibly half CCD, needs checking
+ sensor.sensor_id = SensorId::CCD_HP_N6310; // gl847
+ sensor.full_resolution = 2400;
sensor.black_pixels = 96;
sensor.dummy_pixel = 26;
- sensor.ccd_start_xoffset = 128;
- sensor.sensor_pixels = 42720;
+ sensor.pixel_count_ratio = Ratio{1, 4};
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
@@ -2802,41 +2439,102 @@ void genesys_init_sensor_tables()
{ 0x5a, 0x40 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
+ unsigned shading_factor;
+ int output_pixel_offset;
+ };
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 600, 8, 4 },
+ { { 100 }, 600, 6, 5 },
+ { { 150 }, 600, 4, 8 },
+ { { 200 }, 600, 3, 10 },
+ { { 300 }, 600, 2, 16 },
+ { { 600 }, 600, 1, 32 },
+ { { 1200 }, 1200, 1, 64 },
+ { { 2400 }, 2400, 1, 128 },
+ };
+
+ auto base_custom_regs = sensor.custom_regs;
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpiset = setting.resolutions.values()[0];
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.shading_resolution = setting.register_dpihw;
+ sensor.shading_factor = setting.shading_factor;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_110;
- sensor.optical_res = 2400;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_110; // gl124
+ sensor.full_resolution = 2400;
sensor.black_pixels = 87;
sensor.dummy_pixel = 16;
- sensor.ccd_start_xoffset = 303;
- sensor.sensor_pixels = 5168*4;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.gamma = { 2.2f, 2.2f, 2.2f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_gl124;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
int exposure_lperiod;
SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
std::vector<unsigned> segment_order;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 75, 100, 150 }, 4608, { 462, 609, 453 }, std::vector<unsigned>{}, {
+ { { 75 }, 1200, 600, 150, 300, 4608, { 462, 609, 453 }, Ratio{1, 4}, 4,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ { 0x70, 0x06 }, { 0x71, 0x08 }, { 0x72, 0x08 }, { 0x73, 0x0a },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x1e },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 100 }, 1200, 600, 200, 300, 4608, { 462, 609, 453 }, Ratio{1, 4}, 3,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ { 0x70, 0x06 }, { 0x71, 0x08 }, { 0x72, 0x08 }, { 0x73, 0x0a },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x1e },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 150 }, 1200, 600, 300, 300, 4608, { 462, 609, 453 }, Ratio{1, 4}, 2,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
{ 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
@@ -2853,7 +2551,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
}
},
- { { 300 }, 4608, { 462, 609, 453 }, std::vector<unsigned>{}, {
+ { { 300 }, 1200, 600, 600, 300, 4608, { 462, 609, 453 }, Ratio{1, 4}, 1,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x0c },
{ 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
@@ -2870,7 +2569,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
}
},
- { { 600 }, 5360, { 823, 1117, 805 }, std::vector<unsigned>{}, {
+ { { 600 }, 2400, 600, 600, 600, 5360, { 823, 1117, 805 }, Ratio{1, 4}, 1,
+ std::vector<unsigned>{}, {
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x0a },
{ 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
@@ -2887,7 +2587,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
},
},
- { { 1200 }, 10528, { 6071, 6670, 6042 }, { 0, 1 }, {
+ { { 1200 }, 2400, 1200, 1200, 1200, 10528, { 6071, 6670, 6042 }, Ratio{1, 4}, 1,
+ { 0, 1 }, {
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 },{ 0x20, 0x08 },
{ 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
@@ -2904,7 +2605,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x22 },
}
},
- { { 2400 }, 20864, { 7451, 8661, 7405 }, { 0, 2, 1, 3 }, {
+ { { 2400 }, 2400, 2400, 2400, 2400, 20864, { 7451, 8661, 7405 }, Ratio{1, 4}, 1,
+ { 0, 2, 1, 3 }, {
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x06 },
{ 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
@@ -2925,8 +2627,14 @@ void genesys_init_sensor_tables()
for (const auto& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
sensor.segment_order = setting.segment_order;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
@@ -2934,34 +2642,69 @@ void genesys_init_sensor_tables()
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_120;
- sensor.optical_res = 2400;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_120; // gl124
+ sensor.full_resolution = 2400;
sensor.black_pixels = 87;
sensor.dummy_pixel = 16;
- sensor.ccd_start_xoffset = 303;
- // SEGCNT at 600 DPI by number of segments
- sensor.sensor_pixels = 5104*4;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.gamma = { 2.2f, 2.2f, 2.2f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_gl124;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
int exposure_lperiod;
SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
std::vector<unsigned> segment_order;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 75, 100, 150, 300 }, 4608, { 1244, 1294, 1144 }, std::vector<unsigned>{}, {
+ { { 75 }, 1200, 600, 150, 300, 4608, { 1244, 1294, 1144 }, Ratio{1, 4}, 4,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x15 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x06 }, { 0x54, 0x00 }, { 0x55, 0x02 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x3a }, { 0x5b, 0x00 }, { 0x5c, 0x00 },
+ { 0x61, 0x20 },
+ { 0x70, 0x00 }, { 0x71, 0x1f }, { 0x72, 0x08 }, { 0x73, 0x0a },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x0f },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x5e },
+ { 0x93, 0x00 }, { 0x94, 0x09 }, { 0x95, 0xf8 },
+ { 0x96, 0x00 }, { 0x97, 0x70 },
+ { 0x98, 0x21 },
+ },
+ },
+ { { 100 }, 1200, 600, 200, 300, 4608, { 1244, 1294, 1144 }, Ratio{1, 4}, 3,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x15 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x06 }, { 0x54, 0x00 }, { 0x55, 0x02 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x3a }, { 0x5b, 0x00 }, { 0x5c, 0x00 },
+ { 0x61, 0x20 },
+ { 0x70, 0x00 }, { 0x71, 0x1f }, { 0x72, 0x08 }, { 0x73, 0x0a },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x0f },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x5e },
+ { 0x93, 0x00 }, { 0x94, 0x09 }, { 0x95, 0xf8 },
+ { 0x96, 0x00 }, { 0x97, 0x70 },
+ { 0x98, 0x21 },
+ },
+ },
+ { { 150 }, 1200, 600, 300, 300, 4608, { 1244, 1294, 1144 }, Ratio{1, 4}, 2,
+ std::vector<unsigned>{}, {
{ 0x16, 0x15 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x02 },
{ 0x52, 0x04 }, { 0x53, 0x06 }, { 0x54, 0x00 }, { 0x55, 0x02 },
@@ -2978,7 +2721,26 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
},
},
- { { 600 }, 5360, { 2394, 2444, 2144 }, std::vector<unsigned>{}, {
+ { { 300 }, 1200, 600, 600, 300, 4608, { 1244, 1294, 1144 }, Ratio{1, 4}, 1,
+ std::vector<unsigned>{}, {
+ { 0x16, 0x15 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x02 },
+ { 0x52, 0x04 }, { 0x53, 0x06 }, { 0x54, 0x00 }, { 0x55, 0x02 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x3a }, { 0x5b, 0x00 }, { 0x5c, 0x00 },
+ { 0x61, 0x20 },
+ { 0x70, 0x00 }, { 0x71, 0x1f }, { 0x72, 0x08 }, { 0x73, 0x0a },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x0f },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x5e },
+ { 0x93, 0x00 }, { 0x94, 0x09 }, { 0x95, 0xf8 },
+ { 0x96, 0x00 }, { 0x97, 0x70 },
+ { 0x98, 0x21 },
+ },
+ },
+ { { 600 }, 2400, 600, 600, 600, 5360, { 2394, 2444, 2144 }, Ratio{1, 4}, 1,
+ std::vector<unsigned>{}, {
{ 0x16, 0x11 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x02 },
{ 0x52, 0x04 }, { 0x53, 0x06 }, { 0x54, 0x00 }, { 0x55, 0x02 },
@@ -2995,7 +2757,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
},
},
- { { 1200 }, 10528, { 4694, 4644, 4094 }, std::vector<unsigned>{}, {
+ { { 1200 }, 2400, 1200, 1200, 1200, 10528, { 4694, 4644, 4094 }, Ratio{1, 2}, 1,
+ std::vector<unsigned>{}, {
{ 0x16, 0x15 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x02 },
{ 0x52, 0x04 }, { 0x53, 0x06 }, { 0x54, 0x00 }, { 0x55, 0x02 },
@@ -3012,7 +2775,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
},
},
- { { 2400 }, 20864, { 8944, 8144, 7994 }, std::vector<unsigned>{}, {
+ { { 2400 }, 2400, 2400, 2400, 2400, 20864, { 8944, 8144, 7994 }, Ratio{1, 1}, 1,
+ std::vector<unsigned>{}, {
{ 0x16, 0x11 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x00 }, { 0x20, 0x02 },
{ 0x52, 0x04 }, { 0x53, 0x06 }, { 0x54, 0x00 }, { 0x55, 0x02 },
@@ -3033,8 +2797,14 @@ void genesys_init_sensor_tables()
for (const auto& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
sensor.segment_order = setting.segment_order;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
@@ -3042,33 +2812,71 @@ void genesys_init_sensor_tables()
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_210;
- sensor.optical_res = 2400;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_210; // gl124
+ sensor.full_resolution = 4800;
sensor.black_pixels = 87;
sensor.dummy_pixel = 16;
- sensor.ccd_start_xoffset = 303;
- sensor.sensor_pixels = 5168*4;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.gamma = { 2.2f, 2.2f, 2.2f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_gl124;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
int exposure_lperiod;
SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
std::vector<unsigned> segment_order;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 75, 100, 150, 300 }, 2768, { 388, 574, 393 }, std::vector<unsigned>{}, {
+ { { 75 }, 2400, 600, 150, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 4,
+ std::vector<unsigned>{}, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x1e },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 100 }, 2400, 600, 200, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 3,
+ std::vector<unsigned>{}, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x1e },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 150 }, 2400, 600, 300, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 2,
+ std::vector<unsigned>{}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
@@ -3086,7 +2894,27 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
}
},
- { { 600 }, 5360, { 388, 574, 393 }, std::vector<unsigned>{}, {
+ { { 300 }, 2400, 600, 600, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 1,
+ std::vector<unsigned>{}, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x1e },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 600 }, 4800, 600, 600, 600, 5360, { 388, 574, 393 }, Ratio{1, 8}, 1,
+ std::vector<unsigned>{}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0a },
@@ -3104,7 +2932,7 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
}
},
- { { 1200 }, 10528, { 388, 574, 393 }, {0, 1}, {
+ { { 1200 }, 4800, 1200, 1200, 1200, 10528, { 388, 574, 393 }, Ratio{1, 8}, 1, {0, 1}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x08 },
@@ -3122,7 +2950,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x22 },
},
},
- { { 2400 }, 20864, { 6839, 8401, 6859 }, {0, 2, 1, 3}, {
+ { { 2400 }, 4800, 2400, 2400, 2400, 20864, { 6839, 8401, 6859 }, Ratio{1, 8}, 1,
+ {0, 2, 1, 3}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x06 },
@@ -3139,13 +2968,38 @@ void genesys_init_sensor_tables()
{ 0x96, 0x00 }, { 0x97, 0xa3 },
{ 0x98, 0x24 },
},
+ },
+ { { 4800 }, 4800, 4800, 4800, 4800, 41536, { 9735, 14661, 11345 }, Ratio{1, 8}, 1,
+ { 0, 2, 4, 6, 1, 3, 5, 7 }, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x04 },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x1e },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x12 }, { 0x89, 0x47 },
+ { 0x93, 0x00 }, { 0x94, 0x14 }, { 0x95, 0x30 },
+ { 0x96, 0x00 }, { 0x97, 0xa5 },
+ { 0x98, 0x28 },
+ },
}
};
for (const auto& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
sensor.segment_order = setting.segment_order;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
@@ -3153,33 +3007,33 @@ void genesys_init_sensor_tables()
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_220;
- sensor.optical_res = 2400;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_220; // gl124
+ sensor.full_resolution = 4800;
sensor.black_pixels = 87;
sensor.dummy_pixel = 16;
- sensor.ccd_start_xoffset = 303;
- sensor.sensor_pixels = 5168*4;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.gamma = { 2.2f, 2.2f, 2.2f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_gl124;
{
struct CustomSensorSettings {
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
int exposure_lperiod;
SensorExposure exposure;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
std::vector<unsigned> segment_order;
GenesysRegisterSettingSet custom_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 75, 100, 150, 300 }, 2768, { 388, 574, 393 }, std::vector<unsigned>{}, {
+ { { 75 }, 2400, 600, 150, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 4,
+ std::vector<unsigned>{}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
@@ -3197,7 +3051,65 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
}
},
- { { 600 }, 5360, { 388, 574, 393 }, std::vector<unsigned>{}, {
+ { { 100 }, 2400, 600, 200, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 3,
+ std::vector<unsigned>{}, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x0f },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 150 }, 2400, 600, 300, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 2,
+ std::vector<unsigned>{}, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x0f },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 300 }, 2400, 600, 600, 300, 2768, { 388, 574, 393 }, Ratio{1, 8}, 1,
+ std::vector<unsigned>{}, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0c },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x0f },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x00 }, { 0x89, 0x65 },
+ { 0x93, 0x00 }, { 0x94, 0x0a }, { 0x95, 0x18 },
+ { 0x96, 0x00 }, { 0x97, 0x9a },
+ { 0x98, 0x21 },
+ }
+ },
+ { { 600 }, 4800, 600, 600, 600, 5360, { 388, 574, 393 }, Ratio{1, 8}, 1,
+ std::vector<unsigned>{}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x0a },
@@ -3215,7 +3127,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x21 },
}
},
- { { 1200 }, 10528, { 388, 574, 393 }, {0, 1}, {
+ { { 1200 }, 4800, 1200, 1200, 1200, 10528, { 388, 574, 393 }, Ratio{1, 8}, 1,
+ {0, 1}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x08 },
@@ -3233,7 +3146,8 @@ void genesys_init_sensor_tables()
{ 0x98, 0x22 },
}
},
- { { 2400 }, 20864, { 6839, 8401, 6859 }, {0, 2, 1, 3}, {
+ { { 2400 }, 4800, 2400, 2400, 2400, 20864, { 6839, 8401, 6859 }, Ratio{1, 8}, 1,
+ {0, 2, 1, 3}, {
// { 0x16, 0x00 }, // FIXME: check if default value is different
{ 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
{ 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x06 },
@@ -3250,13 +3164,38 @@ void genesys_init_sensor_tables()
{ 0x96, 0x00 }, { 0x97, 0xa3 },
{ 0x98, 0x24 },
},
+ },
+ { { 4800 }, 4800, 4800, 4800, 4800, 41536, { 9735, 14661, 11345 }, Ratio{1, 8}, 1,
+ { 0, 2, 4, 6, 1, 3, 5, 7 }, {
+ // { 0x16, 0x00 }, // FIXME: check if default value is different
+ { 0x16, 0x10 }, { 0x17, 0x04 }, { 0x18, 0x00 }, { 0x19, 0x01 },
+ { 0x1a, 0x30 }, { 0x1b, 0x00 }, { 0x1c, 0x02 }, { 0x1d, 0x01 }, { 0x20, 0x04 },
+ { 0x52, 0x00 }, { 0x53, 0x02 }, { 0x54, 0x04 }, { 0x55, 0x06 },
+ { 0x56, 0x04 }, { 0x57, 0x04 }, { 0x58, 0x04 }, { 0x59, 0x04 },
+ { 0x5a, 0x1a }, { 0x5b, 0x00 }, { 0x5c, 0xc0 },
+ { 0x61, 0x20 },
+ // { 0x70, 0x00 }, // FIXME: check if default value is different
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x0f },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x88, 0x12 }, { 0x89, 0x47 },
+ { 0x93, 0x00 }, { 0x94, 0x14 }, { 0x95, 0x30 },
+ { 0x96, 0x00 }, { 0x97, 0xa5 },
+ { 0x98, 0x28 },
+ },
}
};
for (const auto& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
sensor.exposure_lperiod = setting.exposure_lperiod;
sensor.exposure = setting.exposure;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
sensor.segment_order = setting.segment_order;
sensor.custom_regs = setting.custom_regs;
s_sensors->push_back(sensor);
@@ -3264,63 +3203,116 @@ void genesys_init_sensor_tables()
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICPRO_3600;
- sensor.optical_res = 1200;
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICPRO_3600; // gl841
+ sensor.full_resolution = 1200;
sensor.black_pixels = 87;
sensor.dummy_pixel = 87;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10100;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x00 },
- { 0x0a, 0x00 },
- { 0x0b, 0x00 },
- { 0x16, 0x33 },
- { 0x17, 0x0b },
- { 0x18, 0x11 },
- { 0x19, 0x2a },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0xc4 },
- { 0x52, 0x07 }, // [GB](HI|LOW) not needed for cis
- { 0x53, 0x0a },
- { 0x54, 0x0c },
- { 0x55, 0x00 },
- { 0x56, 0x02 },
- { 0x57, 0x06 },
- { 0x58, 0x22 },
- { 0x59, 0x69 },
- { 0x5a, 0x40 },
- { 0x5b, 0x00 }, // TODO: 5b-5e
- { 0x5c, 0x00 },
- { 0x5d, 0x00 },
- { 0x5e, 0x02 },
+ { 0x16, 0x33 }, { 0x17, 0x0b }, { 0x18, 0x11 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0xc4 },
+ { 0x52, 0x07 }, { 0x53, 0x0a }, { 0x54, 0x0c }, { 0x55, 0x00 },
+ { 0x56, 0x02 }, { 0x57, 0x06 }, { 0x58, 0x22 }, { 0x59, 0x69 }, { 0x5a, 0x40 },
+ { 0x70, 0x00 }, { 0x71, 0x00 }, { 0x72, 0x00 }, { 0x73, 0x00 },
+ };
+ sensor.gamma = { 1.0f, 1.0f, 1.0f };
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpihw;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 600, 600, 150, 11 },
+ { { 100 }, 600, 600, 200, 14 },
+ { { 150 }, 600, 600, 300, 22 },
+ { { 200 }, 600, 600, 400, 29 },
+ { { 300 }, 600, 600, 600, 44 },
+ { { 600 }, 600, 600, 1200, 88 },
+ { { 1200 }, 1200, 1200, 1200, 88 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.register_dpihw;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
+
+
+ sensor = Genesys_Sensor();
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7200; // gl842
+ sensor.full_resolution = 7200;
+ sensor.register_dpihw = 1200;
+ sensor.black_pixels = 88; // TODO
+ sensor.dummy_pixel = 19;
+ sensor.fau_gain_white_ref = 210;
+ sensor.gain_white_ref = 230;
+ sensor.exposure = { 0x2b00, 0x2b00, 0x2b00 };
+ sensor.exposure_lperiod = 0x694e;
+ sensor.use_host_side_calib = true;
+ sensor.custom_regs = {
+ { 0x16, 0x3b }, { 0x17, 0x4b }, { 0x18, 0x10 }, { 0x19, 0x00 },
+ { 0x1a, 0x24 }, { 0x1b, 0x00 }, { 0x1c, 0x40 }, { 0x1d, 0x84 },
+ { 0x52, 0x09 }, { 0x53, 0x0c }, { 0x54, 0x0e }, { 0x55, 0x02 },
+ { 0x56, 0x04 }, { 0x57, 0x07 }, { 0x58, 0x22 }, { 0x59, 0x69 }, { 0x5a, 0xc0 },
+ { 0x70, 0x08 }, { 0x71, 0x09 }, { 0x72, 0x0b }, { 0x73, 0x0c },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x00 },
+ { 0x77, 0x00 }, { 0x78, 0x7f }, { 0x79, 0xff },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x00 }, { 0x7f, 0x01 }
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ ScanMethod method;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ unsigned register_dpiset;
+ StaggerConfig stagger_y;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 900 }, ScanMethod::TRANSPARENCY, Ratio{8, 8}, 2, 150, StaggerConfig{} },
+ { { 1800 }, ScanMethod::TRANSPARENCY, Ratio{4, 4}, 10, 300, StaggerConfig{} },
+ { { 3600 }, ScanMethod::TRANSPARENCY, Ratio{2, 2}, 10, 600, StaggerConfig{} },
+ { { 7200 }, ScanMethod::TRANSPARENCY, Ratio{1, 1}, 20, 1200, StaggerConfig{0, 4} },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.method = setting.method;
+ sensor.shading_resolution = setting.resolutions.values().front();
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.stagger_y = setting.stagger_y;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7200I;
- sensor.optical_res = 7200;
- sensor.register_dpihw_override = 1200;
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7200I; // gl843
+ sensor.full_resolution = 7200;
+ sensor.register_dpihw = 1200;
sensor.black_pixels = 88; // TODO
sensor.dummy_pixel = 20;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10200; // TODO
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
- sensor.stagger_config = StaggerConfig{7200, 4};
+ sensor.use_host_side_calib = true;
sensor.custom_regs = {
{ 0x08, 0x00 },
{ 0x09, 0x00 },
@@ -3351,47 +3343,53 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings
{
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
ScanMethod method;
- unsigned ccd_size_divisor;
- unsigned logical_dpihw_override;
- unsigned pixel_count_multiplier;
+ unsigned shading_resolution;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
unsigned exposure_lperiod;
- unsigned dpiset_override;
+ unsigned register_dpiset;
+ StaggerConfig stagger_y;
GenesysRegisterSettingSet custom_fe_regs;
};
CustomSensorSettings custom_settings[] = {
- { { 900 }, ScanMethod::TRANSPARENCY, 1, 900, 8, 0x2538, 150, {} },
- { { 1800 }, ScanMethod::TRANSPARENCY, 1, 1800, 4, 0x2538, 300, {} },
- { { 3600 }, ScanMethod::TRANSPARENCY, 1, 3600, 2, 0x2538, 600, {} },
- { { 7200 }, ScanMethod::TRANSPARENCY, 1, 7200, 1, 0x19c8, 1200, {
+ { { 900 }, ScanMethod::TRANSPARENCY, 900, Ratio{8, 8}, 2, 0x2538, 150,
+ StaggerConfig{}, {} },
+ { { 1800 }, ScanMethod::TRANSPARENCY, 1800, Ratio{4, 4}, 5, 0x2538, 300,
+ StaggerConfig{}, {} },
+ { { 3600 }, ScanMethod::TRANSPARENCY, 3600, Ratio{2, 2}, 10, 0x2538, 600,
+ StaggerConfig{}, {} },
+ { { 7200 }, ScanMethod::TRANSPARENCY, 7200, Ratio{1, 1}, 20, 0x19c8, 1200,
+ StaggerConfig{4, 0}, {
{ 0x02, 0x1b },
{ 0x03, 0x14 },
{ 0x04, 0x20 },
}
},
- { { 900 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 900, 8, 0x1f54, 150, {} },
- { { 1800 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 1800, 4, 0x1f54, 300, {} },
- { { 3600 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 3600, 2, 0x1f54, 600, {} },
- { { 7200 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 7200, 1, 0x1f54, 1200, {} },
+ { { 900 }, ScanMethod::TRANSPARENCY_INFRARED, 900, Ratio{8, 8}, 2, 0x1f54, 150,
+ StaggerConfig{}, {} },
+ { { 1800 }, ScanMethod::TRANSPARENCY_INFRARED, 1800, Ratio{4, 4}, 5, 0x1f54, 300,
+ StaggerConfig{}, {} },
+ { { 3600 }, ScanMethod::TRANSPARENCY_INFRARED, 3600, Ratio{2, 2}, 10, 0x1f54, 600,
+ StaggerConfig{}, {}},
+ { { 7200 }, ScanMethod::TRANSPARENCY_INFRARED, 7200, Ratio{1, 1}, 20, 0x1f54, 1200,
+ StaggerConfig{4, 0}, {} },
};
for (const CustomSensorSettings& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
sensor.method = setting.method;
- sensor.ccd_size_divisor = setting.ccd_size_divisor;
- sensor.logical_dpihw_override = setting.logical_dpihw_override;
- sensor.pixel_count_multiplier = setting.pixel_count_multiplier;
+ sensor.shading_resolution = setting.shading_resolution;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
sensor.exposure_lperiod = setting.exposure_lperiod;
- sensor.dpiset_override = setting.dpiset_override;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.stagger_y = setting.stagger_y;
sensor.custom_fe_regs = setting.custom_fe_regs;
s_sensors->push_back(sensor);
}
@@ -3399,19 +3397,17 @@ void genesys_init_sensor_tables()
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7300;
- sensor.optical_res = 7200;
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7300; // gl843
+ sensor.full_resolution = 7200;
sensor.method = ScanMethod::TRANSPARENCY;
- sensor.register_dpihw_override = 1200;
+ sensor.register_dpihw = 1200;
sensor.black_pixels = 88; // TODO
sensor.dummy_pixel = 20;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10200; // TODO
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
sensor.exposure_lperiod = 0x2f44;
- sensor.stagger_config = StaggerConfig{7200, 4};
+ sensor.use_host_side_calib = true;
sensor.custom_regs = {
{ 0x08, 0x00 },
{ 0x09, 0x00 },
@@ -3442,50 +3438,98 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings
{
- ResolutionFilter resolutions;
- unsigned ccd_size_divisor;
- unsigned logical_dpihw_override;
- unsigned pixel_count_multiplier;
- unsigned dpiset_override;
+ ValueFilterAny<unsigned> resolutions;
+ unsigned shading_resolution;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
+ unsigned register_dpiset;
+ StaggerConfig stagger_y;
};
CustomSensorSettings custom_settings[] = {
- { { 900 }, 1, 900, 8, 150 },
- { { 1800 }, 1, 1800, 4, 300 },
- { { 3600 }, 1, 3600, 2, 600 },
- { { 7200 }, 1, 7200, 1, 1200 },
+ { { 900 }, 900, Ratio{8, 8}, 2, 150, StaggerConfig{} },
+ { { 1800 }, 1800, Ratio{4, 4}, 5, 300, StaggerConfig{} },
+ { { 3600 }, 3600, Ratio{2, 2}, 10, 600, StaggerConfig{} },
+ { { 7200 }, 7200, Ratio{1, 1}, 20, 1200, StaggerConfig{4, 0} },
};
for (const CustomSensorSettings& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
- sensor.ccd_size_divisor = setting.ccd_size_divisor;
- sensor.logical_dpihw_override = setting.logical_dpihw_override;
- sensor.pixel_count_multiplier = setting.pixel_count_multiplier;
- sensor.dpiset_override = setting.dpiset_override;
+ sensor.shading_resolution = setting.shading_resolution;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.stagger_y = setting.stagger_y;
s_sensors->push_back(sensor);
}
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7500I;
- sensor.optical_res = 7200;
- sensor.register_dpihw_override = 1200;
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7400; // gl845
+ sensor.full_resolution = 7200;
+ sensor.method = ScanMethod::TRANSPARENCY;
+ sensor.register_dpihw = 1200;
sensor.black_pixels = 88; // TODO
sensor.dummy_pixel = 20;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10200; // TODO
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 230;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
- sensor.stagger_config = StaggerConfig{7200, 4};
+ sensor.exposure_lperiod = 14000;
+ sensor.use_host_side_calib = true;
+ sensor.custom_regs = {
+ { 0x08, 0x00 }, { 0x09, 0x00 }, { 0x0a, 0x00 },
+ { 0x16, 0x27 }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x84 },
+ { 0x52, 0x09 }, { 0x53, 0x0d }, { 0x54, 0x0f }, { 0x55, 0x01 },
+ { 0x56, 0x04 }, { 0x57, 0x07 }, { 0x58, 0x31 }, { 0x59, 0x79 }, { 0x5a, 0xc0 },
+ { 0x70, 0x0a }, { 0x71, 0x0b }, { 0x72, 0x0c }, { 0x73, 0x0d },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x00 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x00 },
+ { 0x87, 0x00 },
+ };
+ sensor.gamma = { 1.0f, 1.0f, 1.0f };
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ StaggerConfig stagger_y;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 600 }, 100, 10, StaggerConfig{} },
+ { { 1200 }, 200, 20, StaggerConfig{} },
+ { { 2400 }, 400, 40, StaggerConfig{} },
+ { { 3600 }, 600, 60, StaggerConfig{} },
+ { { 7200 }, 1200, 120, StaggerConfig{4, 0} },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.shading_resolution = setting.resolutions.values()[0];
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.stagger_y = setting.stagger_y;
+ s_sensors->push_back(sensor);
+ }
+ }
+
+ sensor = Genesys_Sensor();
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7500I; // gl843
+ sensor.full_resolution = 7200;
+ sensor.register_dpihw = 1200;
+ sensor.black_pixels = 88; // TODO
+ sensor.dummy_pixel = 20;
+ sensor.fau_gain_white_ref = 210;
+ sensor.gain_white_ref = 230;
+ sensor.exposure = { 0x0000, 0x0000, 0x0000 };
+ sensor.use_host_side_calib = true;
sensor.custom_regs = {
{ 0x08, 0x00 },
{ 0x09, 0x00 },
@@ -3516,57 +3560,119 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = get_ccd_size_divisor_exact;
{
struct CustomSensorSettings
{
- ResolutionFilter resolutions;
+ ValueFilterAny<unsigned> resolutions;
ScanMethod method;
- unsigned ccd_size_divisor;
- unsigned logical_dpihw_override;
- unsigned pixel_count_multiplier;
+ unsigned shading_resolution;
+ Ratio pixel_count_ratio;
+ int output_pixel_offset;
unsigned exposure_lperiod;
- unsigned dpiset_override;
+ unsigned register_dpiset;
+ StaggerConfig stagger_y;
};
CustomSensorSettings custom_settings[] = {
- { { 900 }, ScanMethod::TRANSPARENCY, 1, 900, 8, 0x2f44, 150 },
- { { 1800 }, ScanMethod::TRANSPARENCY, 1, 1800, 4, 0x2f44, 300 },
- { { 3600 }, ScanMethod::TRANSPARENCY, 1, 3600, 2, 0x2f44, 600 },
- { { 7200 }, ScanMethod::TRANSPARENCY, 1, 7200, 1, 0x2f44, 1200 },
- { { 900 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 900, 8, 0x2af8, 150 },
- { { 1800 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 1800, 4, 0x2af8, 300 },
- { { 3600 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 3600, 2, 0x2af8, 600 },
- { { 7200 }, ScanMethod::TRANSPARENCY_INFRARED, 1, 7200, 1, 0x2af8, 1200 },
+ { { 900 }, ScanMethod::TRANSPARENCY, 900, Ratio{8, 8}, 2, 0x2f44, 150,
+ StaggerConfig{} },
+ { { 1800 }, ScanMethod::TRANSPARENCY, 1800, Ratio{4, 4}, 5, 0x2f44, 300,
+ StaggerConfig{} },
+ { { 3600 }, ScanMethod::TRANSPARENCY, 3600, Ratio{2, 2}, 10, 0x2f44, 600,
+ StaggerConfig{} },
+ { { 7200 }, ScanMethod::TRANSPARENCY, 7200, Ratio{1, 1}, 20, 0x2f44, 1200,
+ StaggerConfig{4, 0} },
+ { { 900 }, ScanMethod::TRANSPARENCY_INFRARED, 900, Ratio{8, 8}, 2, 0x2af8, 150,
+ StaggerConfig{} },
+ { { 1800 }, ScanMethod::TRANSPARENCY_INFRARED, 1800, Ratio{4, 4}, 5, 0x2af8, 300,
+ StaggerConfig{} },
+ { { 3600 }, ScanMethod::TRANSPARENCY_INFRARED, 3600, Ratio{2, 2}, 10, 0x2af8, 600,
+ StaggerConfig{} },
+ { { 7200 }, ScanMethod::TRANSPARENCY_INFRARED, 7200, Ratio{1, 1}, 20, 0x2af8, 1200,
+ StaggerConfig{4, 0} },
};
for (const CustomSensorSettings& setting : custom_settings) {
sensor.resolutions = setting.resolutions;
sensor.method = setting.method;
- sensor.ccd_size_divisor = setting.ccd_size_divisor;
- sensor.logical_dpihw_override = setting.logical_dpihw_override;
- sensor.pixel_count_multiplier = setting.pixel_count_multiplier;
+ sensor.shading_resolution = setting.shading_resolution;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
sensor.exposure_lperiod = setting.exposure_lperiod;
- sensor.dpiset_override = setting.dpiset_override;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.stagger_y = setting.stagger_y;
s_sensors->push_back(sensor);
}
}
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_IMG101;
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_8200I; // gl845
+ sensor.full_resolution = 7200;
+ sensor.method = ScanMethod::TRANSPARENCY;
+ sensor.register_dpihw = 1200;
+ sensor.black_pixels = 88; // TODO
+ sensor.dummy_pixel = 20;
+ sensor.fau_gain_white_ref = 210;
+ sensor.gain_white_ref = 230;
+ sensor.exposure = { 0x0000, 0x0000, 0x0000 };
+ sensor.exposure_lperiod = 14000;
+ sensor.use_host_side_calib = true;
+ sensor.custom_regs = {
+ { 0x08, 0x00 }, { 0x09, 0x00 }, { 0x0a, 0x00 },
+ { 0x16, 0x27 }, { 0x17, 0x0c }, { 0x18, 0x10 }, { 0x19, 0x2a },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x84 },
+ { 0x52, 0x09 }, { 0x53, 0x0d }, { 0x54, 0x0f }, { 0x55, 0x01 },
+ { 0x56, 0x04 }, { 0x57, 0x07 }, { 0x58, 0x31 }, { 0x59, 0x79 }, { 0x5a, 0xc0 },
+ { 0x70, 0x0a }, { 0x71, 0x0b }, { 0x72, 0x0c }, { 0x73, 0x0d },
+ { 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x00 },
+ { 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x00 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x00 },
+ { 0x87, 0x00 },
+ };
+ sensor.gamma = { 1.0f, 1.0f, 1.0f };
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ ScanMethod method;
+ unsigned register_dpiset;
+ int output_pixel_offset;
+ StaggerConfig stagger_y;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 900 }, ScanMethod::TRANSPARENCY, 150, 15, StaggerConfig{} },
+ { { 1800 }, ScanMethod::TRANSPARENCY, 300, 30, StaggerConfig{} },
+ { { 3600 }, ScanMethod::TRANSPARENCY, 600, 60, StaggerConfig{} },
+ { { 7200 }, ScanMethod::TRANSPARENCY, 1200, 120, StaggerConfig{4, 0} },
+ { { 900 }, ScanMethod::TRANSPARENCY_INFRARED, 150, 15, StaggerConfig{} },
+ { { 1800 }, ScanMethod::TRANSPARENCY_INFRARED, 300, 30, StaggerConfig{} },
+ { { 3600 }, ScanMethod::TRANSPARENCY_INFRARED, 600, 60, StaggerConfig{} },
+ { { 7200 }, ScanMethod::TRANSPARENCY_INFRARED, 1200, 120, StaggerConfig{4, 0} },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.method = setting.method;
+ sensor.shading_resolution = setting.resolutions.values()[0];
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ sensor.stagger_y = setting.stagger_y;
+ s_sensors->push_back(sensor);
+ }
+ }
+
+
+ sensor = Genesys_Sensor();
+ sensor.sensor_id = SensorId::CCD_IMG101; // gl846
sensor.resolutions = { 75, 100, 150, 300, 600, 1200 };
sensor.exposure_lperiod = 11000;
sensor.segment_size = 5136;
sensor.segment_order = {0, 1};
- sensor.optical_res = 1200;
+ sensor.full_resolution = 1200;
sensor.black_pixels = 31;
sensor.dummy_pixel = 31;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10800;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0x0000, 0x0000, 0x0000 };
@@ -3580,21 +3686,47 @@ void genesys_init_sensor_tables()
{ 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
};
sensor.gamma = { 1.7f, 1.7f, 1.7f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
+ GenesysRegisterSettingSet extra_custom_regs;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 600, Ratio{1, 4}, 8, { { 0x7e, 0x00 } } },
+ { { 100 }, 600, Ratio{1, 4}, 6, { { 0x7e, 0x00 } } },
+ { { 150 }, 600, Ratio{1, 4}, 4, { { 0x7e, 0x00 } } },
+ { { 300 }, 600, Ratio{1, 4}, 2, { { 0x7e, 0x00 } } },
+ { { 600 }, 600, Ratio{1, 4}, 1, { { 0x7e, 0x01 } } },
+ { { 1200 }, 1200, Ratio{1, 2}, 1, { { 0x7e, 0x01 } } },
+ };
+
+ auto base_custom_regs = sensor.custom_regs;
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.resolutions.values()[0];
+ sensor.shading_resolution = setting.register_dpihw;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
+ sensor.custom_regs = base_custom_regs;
+ sensor.custom_regs.merge(setting.extra_custom_regs);
+ s_sensors->push_back(sensor);
+ }
+ }
+
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICBOOK_3800;
+ sensor.sensor_id = SensorId::CCD_PLUSTEK_OPTICBOOK_3800; // gl845
sensor.resolutions = { 75, 100, 150, 300, 600, 1200 };
sensor.exposure_lperiod = 11000;
- sensor.optical_res = 1200;
+ sensor.full_resolution = 1200;
sensor.black_pixels = 31;
sensor.dummy_pixel = 31;
- sensor.ccd_start_xoffset = 0;
- sensor.sensor_pixels = 10200;
sensor.fau_gain_white_ref = 210;
sensor.gain_white_ref = 200;
sensor.exposure = { 0, 0, 0 };
@@ -3603,66 +3735,150 @@ void genesys_init_sensor_tables()
{ 0x1a, 0x34 }, { 0x1b, 0x00 }, { 0x1c, 0x20 }, { 0x1d, 0x06 },
{ 0x52, 0x02 }, { 0x53, 0x04 }, { 0x54, 0x06 }, { 0x55, 0x08 },
{ 0x56, 0x0a }, { 0x57, 0x00 }, { 0x58, 0x59 }, { 0x59, 0x31 }, { 0x5a, 0x40 },
+ { 0x70, 0x01 }, { 0x71, 0x00 }, { 0x72, 0x02 }, { 0x73, 0x01 },
{ 0x74, 0x00 }, { 0x75, 0x00 }, { 0x76, 0x3c },
{ 0x77, 0x00 }, { 0x78, 0x00 }, { 0x79, 0x9f },
- { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 },
+ { 0x7a, 0x00 }, { 0x7b, 0x00 }, { 0x7c, 0x55 }, { 0x7d, 0x20 },
+ { 0x87, 0x02 },
};
sensor.gamma = { 1.7f, 1.7f, 1.7f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned register_dpihw;
+ Ratio pixel_count_ratio;
+ unsigned shading_factor;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 600, Ratio{1, 2}, 8 },
+ { { 100 }, 600, Ratio{1, 2}, 6 },
+ { { 150 }, 600, Ratio{1, 2}, 4 },
+ { { 300 }, 600, Ratio{1, 2}, 2 },
+ { { 600 }, 600, Ratio{1, 2}, 1 },
+ { { 1200 }, 1200, Ratio{1, 1}, 1 },
+ };
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.register_dpihw = setting.register_dpihw;
+ sensor.register_dpiset = setting.resolutions.values()[0];
+ sensor.shading_resolution = setting.register_dpihw;
+ sensor.pixel_count_ratio = setting.pixel_count_ratio;
+ sensor.shading_factor = setting.shading_factor;
+ s_sensors->push_back(sensor);
+ }
+ }
sensor = Genesys_Sensor();
- sensor.sensor_id = SensorId::CIS_CANON_LIDE_80;
- sensor.optical_res = 1200; // real hardware limit is 2400
- sensor.ccd_size_divisor = 2;
+ sensor.sensor_id = SensorId::CIS_CANON_LIDE_80; // gl841
+ sensor.full_resolution = 1200; // real hardware limit is 2400
+ sensor.register_dpihw = 1200;
sensor.black_pixels = 20;
sensor.dummy_pixel = 6;
- // tuned to give 3*8 multiple startx coordinate during shading calibration
- sensor.ccd_start_xoffset = 34; // 14=>3, 20=>2
- // 10400, too wide=>10288 in shading data 10240~
- // 10208 too short for shading, max shading data = 10240 pixels, endpix-startpix=10208
- sensor.sensor_pixels = 10240;
sensor.fau_gain_white_ref = 150;
sensor.gain_white_ref = 150;
// maps to 0x70-0x73 for GL841
sensor.exposure = { 0x1000, 0x1000, 0x0500 };
sensor.custom_regs = {
- { 0x08, 0x00 },
- { 0x09, 0x05 },
- { 0x0a, 0x07 },
- { 0x0b, 0x09 },
- { 0x16, 0x00 },
- { 0x17, 0x01 },
- { 0x18, 0x00 },
- { 0x19, 0x06 },
- { 0x1a, 0x00 },
- { 0x1b, 0x00 },
- { 0x1c, 0x00 },
- { 0x1d, 0x04 },
- { 0x52, 0x03 },
- { 0x53, 0x07 },
- { 0x54, 0x00 },
- { 0x55, 0x00 },
- { 0x56, 0x00 },
- { 0x57, 0x00 },
- { 0x58, 0x29 },
- { 0x59, 0x69 },
- { 0x5a, 0x55 },
- { 0x5b, 0x00 },
- { 0x5c, 0x00 },
- { 0x5d, 0x20 },
- { 0x5e, 0x41 },
+ { 0x16, 0x00 }, { 0x17, 0x01 }, { 0x18, 0x00 }, { 0x19, 0x06 },
+ { 0x1a, 0x00 }, { 0x1b, 0x00 }, { 0x1c, 0x00 }, { 0x1d, 0x04 },
+ { 0x52, 0x03 }, { 0x53, 0x07 }, { 0x54, 0x00 }, { 0x55, 0x00 },
+ { 0x56, 0x00 }, { 0x57, 0x00 }, { 0x58, 0x29 }, { 0x59, 0x69 }, { 0x5a, 0x55 },
+ { 0x70, 0x00 }, { 0x71, 0x05 }, { 0x72, 0x07 }, { 0x73, 0x09 },
};
sensor.gamma = { 1.0f, 1.0f, 1.0f };
- sensor.get_logical_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_register_hwdpi_fun = default_get_logical_hwdpi;
- sensor.get_hwdpi_divisor_fun = default_get_hwdpi_divisor_for_dpi;
- sensor.get_ccd_size_divisor_fun = default_get_ccd_size_divisor_for_dpi;
- s_sensors->push_back(sensor);
+ {
+ struct CustomSensorSettings
+ {
+ ValueFilterAny<unsigned> resolutions;
+ unsigned optical_resolution;
+ unsigned register_dpiset;
+ unsigned shading_resolution;
+ unsigned shading_factor;
+ int output_pixel_offset;
+ };
+
+ CustomSensorSettings custom_settings[] = {
+ { { 75 }, 600, 150, 600, 8, 2 },
+ { { 100 }, 600, 200, 600, 6, 3 },
+ { { 150 }, 600, 300, 600, 4, 4 },
+ { { 200 }, 600, 400, 600, 3, 6 },
+ { { 300 }, 600, 600, 600, 2, 9 },
+ { { 600 }, 600, 1200, 600, 1, 17 },
+ { { 1200 }, 1200, 1200, 1200, 1, 35 },
+ };
+
+ for (const CustomSensorSettings& setting : custom_settings) {
+ sensor.resolutions = setting.resolutions;
+ sensor.optical_resolution = setting.optical_resolution;
+ sensor.register_dpiset = setting.register_dpiset;
+ sensor.shading_resolution = setting.shading_resolution;
+ sensor.shading_factor = setting.shading_factor;
+ sensor.output_pixel_offset = setting.output_pixel_offset;
+ s_sensors->push_back(sensor);
+ }
+ }
+}
+
+void verify_sensor_tables()
+{
+ std::map<SensorId, AsicType> sensor_to_asic;
+ for (const auto& device : *s_usb_devices) {
+ sensor_to_asic[device.model().sensor_id] = device.model().asic_type;
+ }
+ for (const auto& sensor : *s_sensors) {
+ if (sensor_to_asic.count(sensor.sensor_id) == 0) {
+ throw SaneException("Unknown asic for sensor");
+ }
+ auto asic_type = sensor_to_asic[sensor.sensor_id];
+
+ if (sensor.full_resolution == 0) {
+ throw SaneException("full_resolution is not defined");
+ }
+
+ if (sensor.register_dpiset == 0) {
+ throw SaneException("register_dpiset is not defined");
+ }
+
+ if (asic_type != AsicType::GL646) {
+ if (sensor.register_dpihw == 0) {
+ throw SaneException("register_dpihw is not defined");
+ }
+ if (sensor.shading_resolution == 0) {
+ throw SaneException("shading_resolution is not defined");
+ }
+ }
+
+ if (asic_type == AsicType::GL841) {
+ auto required_registers = {
+ 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
+ 0x70, 0x71, 0x72, 0x73,
+ };
+ for (auto address : required_registers) {
+ if (!sensor.custom_regs.has_reg(address)) {
+ throw SaneException("Required register is not present");
+ }
+ }
+ }
+
+ if (asic_type == AsicType::GL842) {
+ auto required_registers = {
+ 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1c, 0x1d,
+ 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d,
+ 0x7f
+ };
+ for (auto address : required_registers) {
+ if (!sensor.custom_regs.has_reg(address)) {
+ throw SaneException("Required register is not present");
+ }
+ }
+ }
+ }
}
+
} // namespace genesys
diff --git a/backend/genesys/test_scanner_interface.cpp b/backend/genesys/test_scanner_interface.cpp
index 12f726f..e8af494 100644
--- a/backend/genesys/test_scanner_interface.cpp
+++ b/backend/genesys/test_scanner_interface.cpp
@@ -49,7 +49,10 @@
namespace genesys {
-TestScannerInterface::TestScannerInterface(Genesys_Device* dev) : dev_{dev}
+TestScannerInterface::TestScannerInterface(Genesys_Device* dev, uint16_t vendor_id,
+ uint16_t product_id, uint16_t bcd_device) :
+ dev_{dev},
+ usb_dev_{vendor_id, product_id, bcd_device}
{
// initialize status registers
if (dev_->model->asic_type == AsicType::GL124) {
@@ -58,6 +61,7 @@ TestScannerInterface::TestScannerInterface(Genesys_Device* dev) : dev_{dev}
write_register(0x41, 0x00);
}
if (dev_->model->asic_type == AsicType::GL841 ||
+ dev_->model->asic_type == AsicType::GL842 ||
dev_->model->asic_type == AsicType::GL843 ||
dev_->model->asic_type == AsicType::GL845 ||
dev_->model->asic_type == AsicType::GL846 ||
@@ -137,23 +141,21 @@ void TestScannerInterface::bulk_write_data(std::uint8_t addr, std::uint8_t* data
}
void TestScannerInterface::write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags)
+ std::size_t size)
{
(void) type;
(void) addr;
(void) data;
(void) size;
- (void) flags;
}
void TestScannerInterface::write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags)
+ std::size_t size)
{
(void) type;
(void) addr;
(void) data;
(void) size;
- (void) flags;
}
void TestScannerInterface::write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)
diff --git a/backend/genesys/test_scanner_interface.h b/backend/genesys/test_scanner_interface.h
index acf0f6d..fc8128c 100644
--- a/backend/genesys/test_scanner_interface.h
+++ b/backend/genesys/test_scanner_interface.h
@@ -56,7 +56,8 @@ namespace genesys {
class TestScannerInterface : public ScannerInterface
{
public:
- TestScannerInterface(Genesys_Device* dev);
+ TestScannerInterface(Genesys_Device* dev, std::uint16_t vendor_id, std::uint16_t product_id,
+ std::uint16_t bcd_device);
~TestScannerInterface() override;
@@ -74,9 +75,9 @@ public:
void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) override;
void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags) override;
+ std::size_t size) override;
void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
- std::size_t size, Flags flags) override;
+ std::size_t size) override;
void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) override;
std::uint16_t read_fe_register(std::uint8_t address) override;
diff --git a/backend/genesys/test_settings.cpp b/backend/genesys/test_settings.cpp
index 425f09c..f328709 100644
--- a/backend/genesys/test_settings.cpp
+++ b/backend/genesys/test_settings.cpp
@@ -52,6 +52,7 @@ namespace {
bool s_testing_mode = false;
std::uint16_t s_vendor_id = 0;
std::uint16_t s_product_id = 0;
+std::uint16_t s_bcd_device = 0;
TestCheckpointCallback s_checkpoint_callback;
} // namespace
@@ -66,15 +67,17 @@ void disable_testing_mode()
s_testing_mode = false;
s_vendor_id = 0;
s_product_id = 0;
-
+ s_bcd_device = 0;
}
void enable_testing_mode(std::uint16_t vendor_id, std::uint16_t product_id,
+ std::uint16_t bcd_device,
TestCheckpointCallback checkpoint_callback)
{
s_testing_mode = true;
s_vendor_id = vendor_id;
s_product_id = product_id;
+ s_bcd_device = bcd_device;
s_checkpoint_callback = checkpoint_callback;
}
@@ -88,6 +91,11 @@ std::uint16_t get_testing_product_id()
return s_product_id;
}
+std::uint16_t get_testing_bcd_device()
+{
+ return s_bcd_device;
+}
+
std::string get_testing_device_name()
{
std::string name;
diff --git a/backend/genesys/test_settings.h b/backend/genesys/test_settings.h
index 8ac03e0..38cc3b3 100644
--- a/backend/genesys/test_settings.h
+++ b/backend/genesys/test_settings.h
@@ -58,9 +58,11 @@ using TestCheckpointCallback = std::function<void(const Genesys_Device&,
bool is_testing_mode();
void disable_testing_mode();
void enable_testing_mode(std::uint16_t vendor_id, std::uint16_t product_id,
+ std::uint16_t bcd_device,
TestCheckpointCallback checkpoint_callback);
std::uint16_t get_testing_vendor_id();
std::uint16_t get_testing_product_id();
+std::uint16_t get_testing_bcd_device();
std::string get_testing_device_name();
TestCheckpointCallback get_testing_checkpoint_callback();
diff --git a/backend/genesys/test_usb_device.cpp b/backend/genesys/test_usb_device.cpp
index de2399e..1612eae 100644
--- a/backend/genesys/test_usb_device.cpp
+++ b/backend/genesys/test_usb_device.cpp
@@ -48,9 +48,11 @@
namespace genesys {
-TestUsbDevice::TestUsbDevice(std::uint16_t vendor, std::uint16_t product) :
+TestUsbDevice::TestUsbDevice(std::uint16_t vendor, std::uint16_t product,
+ std::uint16_t bcd_device) :
vendor_{vendor},
- product_{product}
+ product_{product},
+ bcd_device_{bcd_device}
{
}
@@ -94,12 +96,25 @@ void TestUsbDevice::close()
name_ = "";
}
-void TestUsbDevice::get_vendor_product(int& vendor, int& product)
+std::uint16_t TestUsbDevice::get_vendor_id()
{
DBG_HELPER(dbg);
assert_is_open();
- vendor = vendor_;
- product = product_;
+ return vendor_;
+}
+
+std::uint16_t TestUsbDevice::get_product_id()
+{
+ DBG_HELPER(dbg);
+ assert_is_open();
+ return product_;
+}
+
+std::uint16_t TestUsbDevice::get_bcd_device()
+{
+ DBG_HELPER(dbg);
+ assert_is_open();
+ return bcd_device_;
}
void TestUsbDevice::control_msg(int rtype, int reg, int value, int index, int length,
diff --git a/backend/genesys/test_usb_device.h b/backend/genesys/test_usb_device.h
index abbd78a..03b49cc 100644
--- a/backend/genesys/test_usb_device.h
+++ b/backend/genesys/test_usb_device.h
@@ -50,9 +50,7 @@ namespace genesys {
class TestUsbDevice : public IUsbDevice {
public:
- TestUsbDevice(std::uint16_t vendor, std::uint16_t product);
- TestUsbDevice() = default;
-
+ TestUsbDevice(std::uint16_t vendor, std::uint16_t product, std::uint16_t bcd_device);
~TestUsbDevice() override;
bool is_open() const override { return is_open_; }
@@ -65,7 +63,9 @@ public:
void reset() override;
void close() override;
- void get_vendor_product(int& vendor, int& product) override;
+ std::uint16_t get_vendor_id() override;
+ std::uint16_t get_product_id() override;
+ std::uint16_t get_bcd_device() override;
void control_msg(int rtype, int reg, int value, int index, int length,
std::uint8_t* data) override;
@@ -78,6 +78,7 @@ private:
bool is_open_ = false;
std::uint16_t vendor_ = 0;
std::uint16_t product_ = 0;
+ std::uint16_t bcd_device_ = 0;
};
} // namespace genesys
diff --git a/backend/genesys/usb_device.cpp b/backend/genesys/usb_device.cpp
index 2d02219..d6cbaed 100644
--- a/backend/genesys/usb_device.cpp
+++ b/backend/genesys/usb_device.cpp
@@ -101,11 +101,33 @@ void UsbDevice::close()
sanei_usb_close(device_num);
}
-void UsbDevice::get_vendor_product(int& vendor, int& product)
+std::uint16_t UsbDevice::get_vendor_id()
{
DBG_HELPER(dbg);
assert_is_open();
+ int vendor = 0;
+ int product = 0;
TIE(sanei_usb_get_vendor_product(device_num_, &vendor, &product));
+ return static_cast<std::uint16_t>(vendor);
+}
+
+std::uint16_t UsbDevice::get_product_id()
+{
+ DBG_HELPER(dbg);
+ assert_is_open();
+ int vendor = 0;
+ int product = 0;
+ TIE(sanei_usb_get_vendor_product(device_num_, &vendor, &product));
+ return static_cast<std::uint16_t>(product);
+}
+
+std::uint16_t UsbDevice::get_bcd_device()
+{
+ DBG_HELPER(dbg);
+ assert_is_open();
+ sanei_usb_dev_descriptor desc;
+ TIE(sanei_usb_get_descriptor(device_num_, &desc));
+ return desc.bcd_dev;
}
void UsbDevice::control_msg(int rtype, int reg, int value, int index, int length,
diff --git a/backend/genesys/usb_device.h b/backend/genesys/usb_device.h
index 265c57c..aa8b89a 100644
--- a/backend/genesys/usb_device.h
+++ b/backend/genesys/usb_device.h
@@ -71,7 +71,9 @@ public:
virtual void reset() = 0;
virtual void close() = 0;
- virtual void get_vendor_product(int& vendor, int& product) = 0;
+ virtual std::uint16_t get_vendor_id() = 0;
+ virtual std::uint16_t get_product_id() = 0;
+ virtual std::uint16_t get_bcd_device() = 0;
virtual void control_msg(int rtype, int reg, int value, int index, int length,
std::uint8_t* data) = 0;
@@ -96,7 +98,9 @@ public:
void reset() override;
void close() override;
- void get_vendor_product(int& vendor, int& product) override;
+ std::uint16_t get_vendor_id() override;
+ std::uint16_t get_product_id() override;
+ std::uint16_t get_bcd_device() override;
void control_msg(int rtype, int reg, int value, int index, int length,
std::uint8_t* data) override;
diff --git a/backend/genesys/utilities.h b/backend/genesys/utilities.h
index 1e268b5..fdab770 100644
--- a/backend/genesys/utilities.h
+++ b/backend/genesys/utilities.h
@@ -46,12 +46,81 @@
#include "error.h"
#include <algorithm>
+#include <cstdint>
#include <iostream>
#include <sstream>
#include <vector>
+
namespace genesys {
+// just like SANE_FIX and SANE_UNFIX except that the conversion is done by a function and argument
+// precision is handled correctly
+inline SANE_Word double_to_fixed(double v)
+{
+ return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
+}
+
+inline SANE_Word float_to_fixed(float v)
+{
+ return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
+}
+
+inline float fixed_to_float(SANE_Word v)
+{
+ return static_cast<float>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
+}
+
+inline double fixed_to_double(SANE_Word v)
+{
+ return static_cast<double>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
+}
+
+template<class T>
+inline T abs_diff(T a, T b)
+{
+ if (a < b) {
+ return b - a;
+ } else {
+ return a - b;
+ }
+}
+
+inline std::uint64_t align_multiple_floor(std::uint64_t x, std::uint64_t multiple)
+{
+ if (multiple == 0) {
+ return x;
+ }
+ return (x / multiple) * multiple;
+}
+
+inline std::uint64_t align_multiple_ceil(std::uint64_t x, std::uint64_t multiple)
+{
+ if (multiple == 0) {
+ return x;
+ }
+ return ((x + multiple - 1) / multiple) * multiple;
+}
+
+inline std::uint64_t multiply_by_depth_ceil(std::uint64_t pixels, std::uint64_t depth)
+{
+ if (depth == 1) {
+ return (pixels / 8) + ((pixels % 8) ? 1 : 0);
+ } else {
+ return pixels * (depth / 8);
+ }
+}
+
+template<class T>
+inline T clamp(const T& value, const T& lo, const T& hi)
+{
+ if (value < lo)
+ return lo;
+ if (value > hi)
+ return hi;
+ return value;
+}
+
template<class T>
void compute_array_percentile_approx(T* result, const T* data,
std::size_t line_count, std::size_t elements_per_line,
@@ -85,6 +154,75 @@ void compute_array_percentile_approx(T* result, const T* data,
}
}
+class Ratio
+{
+public:
+ Ratio() : multiplier_{1}, divisor_{1}
+ {
+ }
+
+ Ratio(unsigned multiplier, unsigned divisor) : multiplier_{multiplier}, divisor_{divisor}
+ {
+ }
+
+ unsigned multiplier() const { return multiplier_; }
+ unsigned divisor() const { return divisor_; }
+
+ unsigned apply(unsigned arg) const
+ {
+ return static_cast<std::uint64_t>(arg) * multiplier_ / divisor_;
+ }
+
+ int apply(int arg) const
+ {
+ return static_cast<std::int64_t>(arg) * multiplier_ / divisor_;
+ }
+
+ float apply(float arg) const
+ {
+ return arg * multiplier_ / divisor_;
+ }
+
+ unsigned apply_inverse(unsigned arg) const
+ {
+ return static_cast<std::uint64_t>(arg) * divisor_ / multiplier_;
+ }
+
+ int apply_inverse(int arg) const
+ {
+ return static_cast<std::int64_t>(arg) * divisor_ / multiplier_;
+ }
+
+ float apply_inverse(float arg) const
+ {
+ return arg * divisor_ / multiplier_;
+ }
+
+ bool operator==(const Ratio& other) const
+ {
+ return multiplier_ == other.multiplier_ && divisor_ == other.divisor_;
+ }
+private:
+ unsigned multiplier_;
+ unsigned divisor_;
+
+ template<class Stream>
+ friend void serialize(Stream& str, Ratio& x);
+};
+
+template<class Stream>
+void serialize(Stream& str, Ratio& x)
+{
+ serialize(str, x.multiplier_);
+ serialize(str, x.divisor_);
+}
+
+inline std::ostream& operator<<(std::ostream& out, const Ratio& ratio)
+{
+ out << ratio.multiplier() << "/" << ratio.divisor();
+ return out;
+}
+
template<class Char, class Traits>
class BasicStreamStateSaver
{
diff --git a/backend/genesys/value_filter.h b/backend/genesys/value_filter.h
new file mode 100644
index 0000000..ba55567
--- /dev/null
+++ b/backend/genesys/value_filter.h
@@ -0,0 +1,140 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2020 Povilas Kanapickas <povilas@radix.lt>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+*/
+
+#ifndef BACKEND_GENESYS_VALUE_FILTER_H
+#define BACKEND_GENESYS_VALUE_FILTER_H
+
+#include <algorithm>
+#include <initializer_list>
+#include <iostream>
+#include <vector>
+
+namespace genesys {
+
+struct AnyTag {};
+constexpr AnyTag VALUE_FILTER_ANY{};
+
+template<class T>
+class ValueFilterAny
+{
+public:
+ ValueFilterAny() : matches_any_{false} {}
+ ValueFilterAny(AnyTag) : matches_any_{true} {}
+ ValueFilterAny(std::initializer_list<T> values) :
+ matches_any_{false},
+ values_{values}
+ {}
+
+ bool matches(T value) const
+ {
+ if (matches_any_)
+ return true;
+ auto it = std::find(values_.begin(), values_.end(), value);
+ return it != values_.end();
+ }
+
+ bool operator==(const ValueFilterAny& other) const
+ {
+ return matches_any_ == other.matches_any_ && values_ == other.values_;
+ }
+
+ bool matches_any() const { return matches_any_; }
+ const std::vector<T>& values() const { return values_; }
+
+private:
+ bool matches_any_ = false;
+ std::vector<T> values_;
+
+ template<class Stream, class U>
+ friend void serialize(Stream& str, ValueFilterAny<U>& x);
+};
+
+template<class T>
+std::ostream& operator<<(std::ostream& out, const ValueFilterAny<T>& values)
+{
+ if (values.matches_any()) {
+ out << "ANY";
+ return out;
+ }
+ out << format_vector_indent_braced(4, "", values.values());
+ return out;
+}
+
+template<class Stream, class T>
+void serialize(Stream& str, ValueFilterAny<T>& x)
+{
+ serialize(str, x.matches_any_);
+ serialize_newline(str);
+ serialize(str, x.values_);
+}
+
+
+template<class T>
+class ValueFilter
+{
+public:
+ ValueFilter() = default;
+ ValueFilter(std::initializer_list<T> values) :
+ values_{values}
+ {}
+
+ bool matches(T value) const
+ {
+ auto it = std::find(values_.begin(), values_.end(), value);
+ return it != values_.end();
+ }
+
+ bool operator==(const ValueFilter& other) const
+ {
+ return values_ == other.values_;
+ }
+
+ const std::vector<T>& values() const { return values_; }
+
+private:
+ std::vector<T> values_;
+
+ template<class Stream, class U>
+ friend void serialize(Stream& str, ValueFilter<U>& x);
+};
+
+template<class T>
+std::ostream& operator<<(std::ostream& out, const ValueFilter<T>& values)
+{
+ if (values.values().empty()) {
+ out << "(none)";
+ return out;
+ }
+ out << format_vector_indent_braced(4, "", values.values());
+ return out;
+}
+
+template<class Stream, class T>
+void serialize(Stream& str, ValueFilter<T>& x)
+{
+ serialize_newline(str);
+ serialize(str, x.values_);
+}
+
+} // namespace genesys
+
+#endif // BACKEND_GENESYS_VALUE_FILTER_H