genesys: Add support for Canon 5600F

merge-requests/244/head
Povilas Kanapickas 2020-05-26 01:51:19 +03:00
rodzic b9e4113ef0
commit 3cca2593fc
13 zmienionych plików z 704 dodań i 152 usunięć

Wyświetl plik

@ -84,6 +84,7 @@ void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
// turning off the lamp
LampSettings settings[] = {
{ ModelId::CANON_4400F, ScanMethod::TRANSPARENCY, {}, {} },
{ ModelId::CANON_5600F, ScanMethod::TRANSPARENCY, {}, {} },
{ ModelId::CANON_8400F, ScanMethod::TRANSPARENCY, {
{ 0xa6, 0x34, 0xf4 },
}, {

Wyświetl plik

@ -174,6 +174,7 @@ 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;
@ -230,6 +231,7 @@ std::ostream& operator<<(std::ostream& out, AdcId id)
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;
@ -270,6 +272,7 @@ std::ostream& operator<<(std::ostream& out, GpioId id)
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;
@ -313,6 +316,7 @@ std::ostream& operator<<(std::ostream& out, MotorId id)
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;

Wyświetl plik

@ -245,6 +245,7 @@ enum class SensorId : unsigned
UNKNOWN = 0,
CCD_5345,
CCD_CANON_4400F,
CCD_CANON_5600F,
CCD_CANON_8400F,
CCD_CANON_8600F,
CCD_DP665,
@ -312,6 +313,7 @@ enum class AdcId : unsigned
CANON_LIDE_200,
CANON_LIDE_700F,
CANON_4400F,
CANON_5600F,
CANON_8400F,
CANON_8600F,
G4050,
@ -362,6 +364,7 @@ enum class GpioId : unsigned
CANON_LIDE_210,
CANON_LIDE_700F,
CANON_4400F,
CANON_5600F,
CANON_8400F,
CANON_8600F,
DP665,
@ -404,6 +407,7 @@ enum class MotorId : unsigned
CANON_LIDE_700,
CANON_LIDE_80,
CANON_4400F,
CANON_5600F,
CANON_8400F,
CANON_8600F,
DP665,

Wyświetl plik

@ -1491,6 +1491,16 @@ void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& senso
}
}
if (dev.model->model_id == ModelId::CANON_5600F) {
// FIXME: use same approach as for GL843 scanners
lines = 8;
}
if (dev.model->asic_type == AsicType::GL847) {
calib_sensor = &sanei_genesys_find_sensor(&dev, resolution, channels,
dev.settings.scan_method);
}
ScanFlag flags = ScanFlag::DISABLE_SHADING |
ScanFlag::DISABLE_GAMMA |
ScanFlag::SINGLE_LINE |
@ -1562,6 +1572,10 @@ void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& senso
scanner_stop_action_no_move(dev, regs);
} else {
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()) {
@ -1598,6 +1612,10 @@ void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& senso
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);
}
}
for (unsigned ch = 0; ch < 3; ch++){
@ -1638,6 +1656,10 @@ void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& senso
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()) {
@ -1782,7 +1804,8 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor&
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::GL843 ||
dev.model->asic_type == AsicType::GL847)
{
calib_sensor = &sanei_genesys_find_sensor(&dev, resolution, channels,
dev.settings.scan_method);
@ -1930,6 +1953,9 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor&
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) {
@ -1942,10 +1968,8 @@ void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor&
dev.frontend.set_gain(2, min_gain);
}
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));
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);
@ -2326,10 +2350,12 @@ static void genesys_shading_calibration_impl(Genesys_Device* dev, const Genesys_
uint32_t pixels_per_line;
if (dev->model->asic_type == AsicType::GL842 ||
dev->model->asic_type == AsicType::GL843)
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;
@ -2354,7 +2380,8 @@ 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. Note the extra line when computing size.
if (dev->model->asic_type == AsicType::GL842 ||
dev->model->asic_type == AsicType::GL843)
dev->model->asic_type == AsicType::GL843 ||
dev->model->model_id == ModelId::CANON_5600F)
{
size = dev->calib_session.output_total_bytes_raw;
} else {
@ -2407,6 +2434,12 @@ 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() + start_offset * channels, 0);
@ -3489,6 +3522,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)

Wyświetl plik

@ -84,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
@ -115,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
@ -150,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
@ -181,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);
@ -213,6 +249,10 @@ gl847_init_registers (Genesys_Device * dev)
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);
if (dev->model->model_id == ModelId::CANON_5600F) {
scanner_setup_sensor(*dev, sensor, dev->reg);
}
}
// Set values of analog frontend
@ -224,11 +264,9 @@ void CommandSetGl847::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
(void) sensor;
uint8_t val = dev->interface->read_register(REG_0x04);
uint8_t frontend_type = val & REG_0x04_FESET;
if (frontend_type != 0x02) {
throw SaneException("unsupported frontend type %d", frontend_type);
if (dev->model->model_id != ModelId::CANON_5600F) {
// FIXME: remove the following read
dev->interface->read_register(REG_0x04);
}
// wait for FE to be ready
@ -242,14 +280,46 @@ void CommandSetGl847::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
dev->frontend = dev->frontend_initial;
}
// reset DAC
dev->interface->write_fe_register(0x00, 0x80);
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 (const auto& reg : dev->frontend.regs) {
dev->interface->write_fe_register(reg.address, reg.value);
}
}
static void gl847_write_motor_phase_table(Genesys_Device& dev, unsigned ydpi)
{
(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());
}
}
// @brief set up motor related register for scan
static void gl847_init_motor_regs_scan(Genesys_Device* dev,
@ -326,6 +396,8 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev,
scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
gl847_write_motor_phase_table(*dev, scan_yres);
// correct move distance by acceleration and deceleration amounts
unsigned feedl = feed_steps;
unsigned dist = 0;
@ -441,21 +513,29 @@ static void gl847_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION))
has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
session.use_host_side_calib)
{
reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
}
else
{
} else {
reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
}
reg->find_reg(REG_0x03).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
reg->set8(0x2e, 0x7f);
reg->set8(0x2f, 0x7f);
@ -490,7 +570,11 @@ static void gl847_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
break; // should not happen
}
} else {
reg->find_reg(REG_0x04).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
}
}
const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution,
@ -545,7 +629,13 @@ void CommandSetGl847::init_regs_for_scan_session(Genesys_Device* dev, const Gene
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
@ -685,11 +775,42 @@ void CommandSetGl847::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
dev->interface->write_register(REG_0x6C, val);
}
// 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);
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;
@ -823,6 +944,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++)
{
@ -869,27 +994,35 @@ static void gl847_init_gpio(Genesys_Device* dev)
{
DBG_HELPER(dbg);
std::vector<std::uint16_t> order1 = { 0xa7, 0xa6, 0x6e };
std::vector<std::uint16_t> order2 = { 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0xa8, 0xa9 };
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 };
for (auto addr : order1) {
dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
}
dev->interface->write_register(REG_0x6C, 0x00); // FIXME: Likely not needed
for (auto addr : order2) {
dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
}
for (const auto& reg : dev->gpo.regs) {
if (std::find(order1.begin(), order1.end(), reg.address) != order1.end()) {
continue;
for (auto addr : order1) {
dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
}
if (std::find(order2.begin(), order2.end(), reg.address) != order2.end()) {
continue;
dev->interface->write_register(REG_0x6C, 0x00); // FIXME: Likely not needed
for (auto addr : order2) {
dev->interface->write_register(addr, dev->gpo.regs.find_reg(addr).value);
}
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);
}
dev->interface->write_register(reg.address, reg.value);
}
}
@ -900,18 +1033,17 @@ static void gl847_init_memory_layout(Genesys_Device* dev)
{
DBG_HELPER(dbg);
// TODO: move to initial register list
// FIXME: move to initial register list
switch (dev->model->model_id) {
case ModelId::CANON_LIDE_100:
case ModelId::CANON_LIDE_200:
case ModelId::CANON_5600F:
dev->interface->write_register(REG_0x0B, 0x29);
break;
case ModelId::CANON_LIDE_700F:
dev->interface->write_register(REG_0x0B, 0x2a);
break;
default:
throw SaneException("Unknown device");
break;
}
// prevent further writings by bulk write register
@ -946,15 +1078,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);
@ -966,8 +1100,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);
}
}
/**

Wyświetl plik

@ -67,6 +67,7 @@
#include "gl646.h"
#include <cstdio>
#include <chrono>
#include <cmath>
#include <vector>
@ -409,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);
}
@ -425,19 +426,120 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession&
1, 1);
}
if (has_flag(dev->model->flags, ModelFlag::SWAP_16BIT_DATA) && session.params.depth == 16) {
pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
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>();
}
#ifdef WORDS_BIGENDIAN
if (session.params.depth == 16) {
pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
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) {
pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
@ -514,6 +616,9 @@ void sanei_genesys_set_lamp_power(Genesys_Device* dev, const Genesys_Sensor& sen
regs_set_exposure(dev->model->asic_type, regs, sanei_genesys_fixup_exposure({0, 0, 0}));
regs.set8(0x19, 0xff);
}
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;
}
@ -685,7 +790,16 @@ void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
dev->model->asic_type == AsicType::GL846 ||
dev->model->asic_type == AsicType::GL847)
{
s.pixel_startx = (s.output_startx * s.optical_resolution) / s.params.xres;
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;
}
}
s.pixel_startx = (s.output_startx * startx_xres) / s.params.xres;
s.pixel_endx = s.pixel_startx + s.optical_pixels_raw;
} else if (dev->model->asic_type == AsicType::GL124)
@ -719,6 +833,10 @@ unsigned session_adjust_output_pixels(unsigned output_pixels,
bool adjust_output_pixels)
{
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();
@ -873,6 +991,7 @@ 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;
// FIXME: Use ModelFlag::SIS_SENSOR
if ((dev->model->asic_type == AsicType::GL845 ||
dev->model->asic_type == AsicType::GL846 ||
dev->model->asic_type == AsicType::GL847) &&
@ -882,18 +1001,47 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
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.pixel_count_ratio.apply_inverse(extra_segment_scan_area);
// 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.full_resolution / 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) {
@ -927,7 +1075,11 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
dev->model->asic_type == AsicType::GL846 ||
dev->model->asic_type == AsicType::GL847)
{
s.output_segment_pixel_group_count = s.pixel_count_ratio.apply(s.optical_pixels);
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(
@ -977,7 +1129,13 @@ ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSes
auto read_data_from_usb = [&dev](std::size_t size, std::uint8_t* data)
{
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;
};

Wyświetl plik

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

Wyświetl plik

@ -583,6 +583,26 @@ void genesys_init_frontend_tables()
s_frontends->push_back(fe);
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;

Wyświetl plik

@ -392,6 +392,22 @@ void genesys_init_gpo_tables()
s_gpo->push_back(gpo);
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 = {

Wyświetl plik

@ -75,6 +75,21 @@ void genesys_init_memory_layout_tables()
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 = {
@ -90,8 +105,7 @@ void genesys_init_memory_layout_tables()
ml = MemoryLayout();
// BUG: we shouldn't use LIDE_200 data for 5600F
ml.models = { ModelId::CANON_LIDE_200, ModelId::CANON_5600F };
ml.models = { ModelId::CANON_LIDE_200 };
ml.regs = {
{ 0xd0, 0x0a }, { 0xd1, 0x1f }, { 0xd2, 0x34 },
{ 0xe0, 0x01 }, { 0xe1, 0x24 }, { 0xe2, 0x02 }, { 0xe3, 0x91 },

Wyświetl plik

@ -894,43 +894,57 @@ void genesys_init_usb_device_tables()
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_size_calib_mm = 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 = 217.4241;
model.x_size_calib_mm = 220.5;
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;
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 = ModelFlag::UNTESTED |
ModelFlag::SIS_SENSOR |
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 |

Wyświetl plik

@ -315,6 +315,34 @@ void genesys_init_motor_tables()
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;

Wyświetl plik

@ -1877,6 +1877,129 @@ void genesys_init_sensor_tables()
}
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.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);
}
}
}
sensor = Genesys_Sensor();
sensor.sensor_id = SensorId::CCD_CANON_8400F; // gl843
sensor.full_resolution = 3200;