Merge branch 'genesys-refactor-motor-handling' into 'master'

genesys: Refactor motor handling

See merge request sane-project/backends!308
merge-requests/317/merge
Povilas Kanapickas 2020-01-12 19:26:35 +00:00
commit 8d07515bea
19 zmienionych plików z 357 dodań i 255 usunięć

Wyświetl plik

@ -504,6 +504,7 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \
genesys/buffer.h genesys/buffer.cpp \
genesys/calibration.h \
genesys/command_set.h \
genesys/command_set_common.h genesys/command_set_common.cpp \
genesys/conv.h genesys/conv.cpp \
genesys/device.h genesys/device.cpp \
genesys/enums.h genesys/enums.cpp \

Wyświetl plik

@ -159,6 +159,13 @@ public:
/// cold boot init function
virtual void asic_boot(Genesys_Device* dev, bool cold) 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

Wyświetl plik

@ -0,0 +1,205 @@
/* 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"
namespace genesys {
CommandSetCommon::~CommandSetCommon() = default;
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_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");
}
void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
MotorMode mode) const
{
DBG_HELPER(dbg);
struct MotorSettings {
ModelId model_id;
ResolutionFilter resolutions;
GenesysRegisterSettingSet regs_primary_and_secondary;
GenesysRegisterSettingSet regs_primary;
};
MotorSettings settings[] = {
{ ModelId::CANON_8400F, { 400, 800, 1600 }, {
{ 0x6c, 0x00, 0x90 },
{ 0xa9, 0x04, 0x06 },
}, {
{ 0x6c, 0x90, 0x90 },
{ 0xa9, 0x02, 0x06 },
}
},
{ ModelId::CANON_8400F, { 3200 }, {
{ 0x6c, 0x00, 0x92 },
{ 0xa9, 0x04, 0x06 },
}, {
{ 0x6c, 0x90, 0x90 },
{ 0xa9, 0x02, 0x06 },
}
},
{ ModelId::CANON_8600F, { 300, 600, 1200 }, {
{ 0x6c, 0x00, 0x20 },
{ 0xa6, 0x01, 0x41 },
}, {
{ 0x6c, 0x20, 0x22 },
{ 0xa6, 0x00, 0x41 },
}
},
{ ModelId::CANON_8600F, { 2400, 4800 }, {
{ 0x6c, 0x02, 0x22 },
{ 0xa6, 0x01, 0x41 },
}, {
{ 0x6c, 0x20, 0x22 },
{ 0xa6, 0x00, 0x41 },
}
},
{ ModelId::HP_SCANJET_G4050, ResolutionFilter::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_7200I, ResolutionFilter::ANY, {}, {} },
{ ModelId::PLUSTEK_OPTICFILM_7300, ResolutionFilter::ANY, {}, {} },
{ ModelId::PLUSTEK_OPTICFILM_7500I, ResolutionFilter::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;
}
}
regs.state.motor_mode = mode;
return;
}
}
throw SaneException("Motor settings have not been found");
}
} // namespace genesys

Wyświetl plik

@ -0,0 +1,46 @@
/* 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;
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

Wyświetl plik

@ -124,10 +124,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)
@ -262,11 +266,25 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
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

Wyświetl plik

@ -360,7 +360,7 @@ struct Genesys_Device
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 +382,10 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev);
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs);
GenesysRegisterSettingSet
apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
const GenesysRegisterSettingSet& regs);
} // namespace genesys
#endif

Wyświetl plik

@ -524,6 +524,11 @@ enum class Direction : unsigned
BACKWARD = 1
};
enum class MotorMode : unsigned
{
PRIMARY = 0,
PRIMARY_AND_SECONDARY,
};
} // namespace genesys

Wyświetl plik

@ -718,11 +718,6 @@ void sanei_genesys_search_reference_point(Genesys_Device* dev, Genesys_Sensor& s
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
@ -969,14 +964,14 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
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
@ -997,7 +992,7 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
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;
}
@ -1020,7 +1015,7 @@ void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, D
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);
@ -1174,12 +1169,27 @@ 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 {
void handle_motor_position_after_move_back_home_ta(Genesys_Device& dev)
{
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);
@ -1230,7 +1240,7 @@ 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);
dev.cmd_set->set_motor_mode(dev, local_reg, MotorMode::PRIMARY_AND_SECONDARY);
try {
scanner_start_action(dev, true);
@ -1244,18 +1254,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);
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 +1268,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);
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;
}

Wyświetl plik

@ -45,7 +45,7 @@
#define BACKEND_GENESYS_GL124_H
#include "genesys.h"
#include "command_set.h"
#include "command_set_common.h"
namespace genesys {
namespace gl124 {
@ -112,7 +112,7 @@ static Memory_layout layouts[]={
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;

Wyświetl plik

@ -1473,7 +1473,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");
}
@ -1567,7 +1567,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");
}

Wyświetl plik

@ -48,7 +48,7 @@
#define BACKEND_GENESYS_GL646_H
#include "genesys.h"
#include "command_set.h"
#include "command_set_common.h"
#include "motor.h"
namespace genesys {
@ -436,7 +436,7 @@ static Motor_Master motor_master[] = {
MotorSlope::create_from_steps(2000, 300, 255), 146}, /* 5500 guessed */
};
class CommandSetGl646 : public CommandSet
class CommandSetGl646 : public CommandSetCommon
{
public:
~CommandSetGl646() override = default;

Wyświetl plik

@ -2180,7 +2180,7 @@ static void gl841_feed(Genesys_Device* dev, int steps)
/* 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();
dev->set_head_pos_unknown(ScanHeadId::PRIMARY);
throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");
}
@ -2276,7 +2276,7 @@ void CommandSetGl841::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__, [&](){ gl841_stop_action(dev); });
dev->set_head_pos_unknown();
dev->set_head_pos_unknown(ScanHeadId::PRIMARY);
throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -1360,194 +1360,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
@ -1577,11 +1389,11 @@ 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
@ -1590,17 +1402,17 @@ void CommandSetGl843::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
case GpioId::CANON_8400F:
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;
}
@ -1619,11 +1431,21 @@ 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);
}
// BUG: we should advance secondary head only if motor was on
dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
break;
}
}
}
@ -1640,7 +1462,7 @@ void CommandSetGl843::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
// 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);
dev->cmd_set->set_xpa_lamp_power(*dev, false);
}
if (!dev->model->is_sheetfed) {

Wyświetl plik

@ -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;

Wyświetl plik

@ -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
@ -125,7 +125,7 @@ static Memory_layout layouts[]={
{ 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;

Wyświetl plik

@ -45,7 +45,7 @@
#define BACKEND_GENESYS_GL847_H
#include "genesys.h"
#include "command_set.h"
#include "command_set_common.h"
namespace genesys {
namespace gl847 {
@ -113,7 +113,7 @@ static Memory_layout layouts[]={
}
};
class CommandSetGl847 : public CommandSet
class CommandSetGl847 : public CommandSetCommon
{
public:
~CommandSetGl847() override = default;

Wyświetl plik

@ -1505,7 +1505,6 @@ void sanei_genesys_asic_init(Genesys_Device* dev, bool /*max_regs*/)
// Move to home if needed
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);

Wyświetl plik

@ -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>