diff --git a/backend/genesys.c b/backend/genesys.c index 37e17345f..a63c573ce 100644 --- a/backend/genesys.c +++ b/backend/genesys.c @@ -2,7 +2,7 @@ Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004, 2005 Gerhard Jaeger - Copyright (C) 2004, 2008 Stéphane Voltz + Copyright (C) 2004-2009 Stéphane Voltz Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2006 Laurent Charpentier Copyright (C) 2007 Luke @@ -60,8 +60,6 @@ #include #include -#include "_stdint.h" - #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" @@ -71,6 +69,7 @@ #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" +#include "_stdint.h" #include "genesys.h" #include "genesys_devices.c" @@ -394,25 +393,63 @@ sanei_genesys_set_buffer_address (Genesys_Device * dev, uint32_t addr) void sanei_genesys_init_structs (Genesys_Device * dev) { + unsigned int i, sensor_ok = 0, gpo_ok = 0, motor_ok = 0; /* initialize the sensor data stuff */ - memcpy (&dev->sensor, &Sensor[dev->model->ccd_type], - sizeof (Genesys_Sensor)); + for (i = 0; i < sizeof (Sensor) / sizeof (Genesys_Sensor); i++) + { + if (dev->model->ccd_type == Sensor[i].sensor_id) + { + memcpy (&dev->sensor, &Sensor[i], sizeof (Genesys_Sensor)); + sensor_ok = 1; + } + } /* initialize the GPO data stuff */ - memcpy (&dev->gpo, &Gpo[dev->model->gpo_type], sizeof (Genesys_Gpo)); + for (i = 0; i < sizeof (Gpo) / sizeof (Genesys_Gpo); i++) + { + if (dev->model->gpo_type == Gpo[i].gpo_id) + { + memcpy (&dev->gpo, &Gpo[i], sizeof (Genesys_Gpo)); + gpo_ok = 1; + } + } /* initialize the motor data stuff */ - memcpy (&dev->motor, &Motor[dev->model->motor_type], - sizeof (Genesys_Motor)); + for (i = 0; i < sizeof (Motor) / sizeof (Genesys_Motor); i++) + { + if (dev->model->motor_type == Motor[i].motor_id) + { + memcpy (&dev->motor, &Motor[i], sizeof (Genesys_Motor)); + motor_ok = 1; + } + } + + if (sensor_ok == 0 || motor_ok == 0 || gpo_ok == 0) + { + DBG (DBG_error0, + "sanei_genesys_init_structs: bad description(s) for ccd/gpo/motor=%d/%d/%d\n", + dev->model->ccd_type, dev->model->gpo_type, dev->model->motor_type); + } } void sanei_genesys_init_fe (Genesys_Device * dev) { + unsigned int i; - memcpy (&dev->frontend, &Wolfson[dev->model->dac_type], - sizeof (Genesys_Frontend)); + for (i = 0; i < sizeof (Wolfson) / sizeof (Genesys_Frontend); i++) + { + if (dev->model->dac_type == Wolfson[i].fe_id) + { + memcpy (&dev->frontend, &Wolfson[i], sizeof (Genesys_Frontend)); + return; + } + } + DBG (DBG_error0, + "sanei_genesys_init_fe: failed to find description for dac_type %d\n", + dev->model->dac_type); + DBG (DBG_info, "sanei_genesys_init_fe: dac_type %d set up\n", dev->model->dac_type); } /* Write data for analog frontend */ @@ -1693,13 +1730,13 @@ sanei_genesys_calculate_zmode2 (SANE_Bool two_table, /* huh? */ /* todo: double check */ /* Z1 and Z2 seem to be a time to synchronize with clock or a phase correction */ -/* steps_sum is the result of create_slope_table */ -/* last_speed is the last entry of the slope_table */ -/* feedl is registers 3d,3e,3f */ -/* fastfed is register 02 bit 3 */ -/* scanfed is register 1f */ -/* fwdstep is register 22 */ -/* tgtime is register 6c bit 6+7 >> 6 */ +/* steps_sum is the result of create_slope_table */ +/* last_speed is the last entry of the slope_table */ +/* feedl is registers 3d,3e,3f */ +/* fastfed is register 02 bit 3 */ +/* scanfed is register 1f */ +/* fwdstep is register 22 */ +/* tgtime is register 6c bit 6+7 >> 6 */ void sanei_genesys_calculate_zmode (Genesys_Device * dev, uint32_t exposure_time, @@ -1833,7 +1870,7 @@ genesys_average_black (Genesys_Device * dev, int channel, sum = 0; - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { data += (channel * 2); pixel_step = 3 * 2; @@ -1878,7 +1915,7 @@ genesys_coarse_calibration (Genesys_Device * dev) black_pixels = dev->sensor.black_pixels * dev->settings.xres / dev->sensor.optical_res; - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; @@ -2085,7 +2122,7 @@ genesys_coarse_calibration (Genesys_Device * dev) sane_strstatus (status)); return status; } - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { for (j = 0; j < 3; j++) { @@ -2112,7 +2149,7 @@ genesys_coarse_calibration (Genesys_Device * dev) if (i == 3) { - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { /* todo: huh? */ dev->dark[0] = @@ -2205,7 +2242,7 @@ genesys_dark_shading_calibration (Genesys_Device * dev) (genesys_pixels_per_line (dev->calib_reg) * genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res; - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; @@ -2336,7 +2373,7 @@ genesys_dummy_dark_shading (Genesys_Device * dev) (genesys_pixels_per_line (dev->calib_reg) * genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res; - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; @@ -2431,7 +2468,7 @@ genesys_white_shading_calibration (Genesys_Device * dev) (genesys_pixels_per_line (dev->calib_reg) * genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res; - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; @@ -2447,7 +2484,7 @@ genesys_white_shading_calibration (Genesys_Device * dev) return SANE_STATUS_NO_MEM; } - size = channels * 2 * pixels_per_line * dev->model->shading_lines; + size = channels * 2 * pixels_per_line * (dev->model->shading_lines + 1); calibration_data = malloc (size); if (!calibration_data) @@ -2477,7 +2514,7 @@ genesys_white_shading_calibration (Genesys_Device * dev) if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) usleep (500 * 1000); /* wait 500ms to make sure lamp is bright again */ - status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_FALSE); + status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (calibration_data); @@ -2562,7 +2599,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) (genesys_pixels_per_line (dev->calib_reg) * genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res; - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; @@ -2752,7 +2789,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev) (genesys_pixels_per_line (dev->calib_reg) * genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res; - if (dev->settings.scan_mode == 4) /* single pass color */ + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; @@ -3264,7 +3301,6 @@ genesys_flatbed_calibration (Genesys_Device * dev) } /* since all the registers are set up correctly, just use them */ - status = dev->model->cmd_set->coarse_gain_calibration (dev, yres); if (status != SANE_STATUS_GOOD) { @@ -3292,7 +3328,7 @@ genesys_flatbed_calibration (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "genesys_flatbed_calibration: failed to do static calibration: %s\n", + "genesys_flatbed_calibration: failed to do coarse gain calibration: %s\n", sane_strstatus (status)); return status; } @@ -3491,7 +3527,6 @@ genesys_wait_not_moving (Genesys_Device * dev, int mseconds) static SANE_Status genesys_warmup_lamp (Genesys_Device * dev) { - Genesys_Register_Set local_reg[GENESYS_MAX_REGS]; uint8_t *first_line, *second_line; int seconds = 0; int pixel; @@ -3499,12 +3534,12 @@ genesys_warmup_lamp (Genesys_Device * dev) double first_average = 0; double second_average = 0; int difference = 255; - int empty; + int empty, lines = 3; SANE_Status status = SANE_STATUS_IO_ERROR; DBG (DBG_proc, "genesys_warmup_lamp: start\n"); - dev->model->cmd_set->init_regs_for_warmup (dev, local_reg, &channels, + dev->model->cmd_set->init_regs_for_warmup (dev, dev->reg, &channels, &total_size); first_line = malloc (total_size); if (!first_line) @@ -3518,19 +3553,13 @@ genesys_warmup_lamp (Genesys_Device * dev) { DBG (DBG_info, "genesys_warmup_lamp: one more loop\n"); - RIE (dev->model->cmd_set->begin_scan (dev, local_reg, SANE_TRUE)); + RIE (dev->model->cmd_set->begin_scan (dev, dev->reg, SANE_FALSE)); do { sanei_genesys_test_buffer_empty (dev, &empty); } while (empty); - /* STEF: workaround 'hang' problem with gl646 : data reading hangs - depending on the amount of data read by the last scan done - before scanner reset. So we allow for one read failure, which - fixes the communication with scanner . Put usb timeout to a friendly - value first, so that 'recovery' doesn't take too long */ - sanei_usb_set_timeout (2 * 1000); status = sanei_genesys_read_data_from_scanner (dev, first_line, total_size); if (status != SANE_STATUS_GOOD) @@ -3538,14 +3567,13 @@ genesys_warmup_lamp (Genesys_Device * dev) RIE (sanei_genesys_read_data_from_scanner (dev, first_line, total_size)); } - /* back to normal time out */ - sanei_usb_set_timeout (30 * 1000); - RIE (dev->model->cmd_set->end_scan (dev, local_reg, SANE_FALSE)); + + RIE (dev->model->cmd_set->end_scan (dev, dev->reg, SANE_TRUE)); sleep (1); /* sleep 1 s */ seconds++; - RIE (dev->model->cmd_set->begin_scan (dev, local_reg, SANE_FALSE)); + RIE (dev->model->cmd_set->begin_scan (dev, dev->reg, SANE_FALSE)); do { sanei_genesys_test_buffer_empty (dev, &empty); @@ -3553,14 +3581,12 @@ genesys_warmup_lamp (Genesys_Device * dev) while (empty); RIE (sanei_genesys_read_data_from_scanner (dev, second_line, total_size)); - RIE (dev->model->cmd_set->end_scan (dev, local_reg, SANE_FALSE)); - - sleep (1); /* sleep 1 s */ - seconds++; + RIE (dev->model->cmd_set->end_scan (dev, dev->reg, SANE_TRUE)); + /* compute difference between the two scans */ for (pixel = 0; pixel < total_size; pixel++) { - if (dev->model->cmd_set->get_bitset_bit (local_reg)) + if (dev->model->cmd_set->get_bitset_bit (dev->reg)) { first_average += (first_line[pixel] + first_line[pixel + 1] * 256); @@ -3574,10 +3600,10 @@ genesys_warmup_lamp (Genesys_Device * dev) second_average += second_line[pixel]; } } - if (dev->model->cmd_set->get_bitset_bit (local_reg)) + if (dev->model->cmd_set->get_bitset_bit (dev->reg)) { DBG (DBG_info, - "genesys_warmup_lamp: average = %.2f %%, diff = %.3f %%\n", + "genesys_warmup_lamp: average = %.2f, diff = %.3f\n", 100 * ((second_average) / (256 * 256)), 100 * (difference / second_average)); first_average /= pixel; @@ -3595,9 +3621,13 @@ genesys_warmup_lamp (Genesys_Device * dev) if (DBG_LEVEL >= DBG_data) { sanei_genesys_write_pnm_file ("warmup1.pnm", first_line, 8, - channels, total_size / 2, 2); + channels, + total_size / (lines * channels), + lines); sanei_genesys_write_pnm_file ("warmup2.pnm", second_line, 8, - channels, total_size / 2, 2); + channels, + total_size / (lines * channels), + lines); } DBG (DBG_info, "genesys_warmup_lamp: average 1 = %.2f %%, average 2 = %.2f %%\n", @@ -3606,6 +3636,10 @@ genesys_warmup_lamp (Genesys_Device * dev) && second_average > 120) break; } + + /* sleep another second before next loop */ + sleep (1); + seconds++; } while (seconds < WARMUP_TIME); @@ -3914,6 +3948,7 @@ sanei_genesys_buffer_consume (Genesys_Buffer * buf, size_t size) #include "genesys_conv.c" /*#undef SANE_DEBUG_LOG_RAW_DATA*/ +#define SANE_DEBUG_LOG_RAW_DATA 1 #ifdef SANE_DEBUG_LOG_RAW_DATA static FILE *rawfile = NULL; @@ -4620,19 +4655,19 @@ calc_parameters (Genesys_Scanner * s) s->params.bytes_per_line *= 3; if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) - s->dev->settings.scan_mode = 4; + s->dev->settings.scan_mode = SCAN_MODE_COLOR; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) - s->dev->settings.scan_mode = 2; + s->dev->settings.scan_mode = SCAN_MODE_GRAY; else if (strcmp (mode, SANE_TITLE_HALFTONE) == 0) - s->dev->settings.scan_mode = 1; + s->dev->settings.scan_mode = SCAN_MODE_HALFTONE; else /* Lineart */ - s->dev->settings.scan_mode = 0; + s->dev->settings.scan_mode = SCAN_MODE_LINEART; /* todo: change and check */ if (strcmp (source, "Flatbed") == 0) - s->dev->settings.scan_method = 0; + s->dev->settings.scan_method = SCAN_METHOD_FLATBED; else /* transparency */ - s->dev->settings.scan_method = 2; + s->dev->settings.scan_method = SCAN_METHOD_TRANSPARENCY; s->dev->settings.lines = s->params.lines; s->dev->settings.pixels = s->params.pixels_per_line; @@ -4987,7 +5022,8 @@ init_options (Genesys_Scanner * s) s->opt[OPT_FILE_SW].type = SANE_TYPE_BOOL; s->opt[OPT_FILE_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_FILE_SW) - s->opt[OPT_FILE_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + s->opt[OPT_FILE_SW].cap = + SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_FILE_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_FILE_SW].b = 0; @@ -4998,8 +5034,9 @@ init_options (Genesys_Scanner * s) s->opt[OPT_EMAIL_SW].desc = SANE_DESC_EMAIL; s->opt[OPT_EMAIL_SW].type = SANE_TYPE_BOOL; s->opt[OPT_EMAIL_SW].unit = SANE_UNIT_NONE; - if (model->buttons & GENESYS_HAS_EMAIL_SW) - s->opt[OPT_EMAIL_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if (model->buttons & GENESYS_HAS_EMAIL_SW) + s->opt[OPT_EMAIL_SW].cap = + SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_EMAIL_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_EMAIL_SW].b = 0; @@ -5010,8 +5047,9 @@ init_options (Genesys_Scanner * s) s->opt[OPT_COPY_SW].desc = SANE_DESC_COPY; s->opt[OPT_COPY_SW].type = SANE_TYPE_BOOL; s->opt[OPT_COPY_SW].unit = SANE_UNIT_NONE; - if (model->buttons & GENESYS_HAS_COPY_SW) - s->opt[OPT_COPY_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if (model->buttons & GENESYS_HAS_COPY_SW) + s->opt[OPT_COPY_SW].cap = + SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_COPY_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_COPY_SW].b = 0; @@ -5022,8 +5060,9 @@ init_options (Genesys_Scanner * s) s->opt[OPT_PAGE_LOADED_SW].desc = SANE_DESC_PAGE_LOADED; s->opt[OPT_PAGE_LOADED_SW].type = SANE_TYPE_BOOL; s->opt[OPT_PAGE_LOADED_SW].unit = SANE_UNIT_NONE; - if (model->buttons & GENESYS_HAS_PAGE_LOADED_SW) - s->opt[OPT_PAGE_LOADED_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if (model->buttons & GENESYS_HAS_PAGE_LOADED_SW) + s->opt[OPT_PAGE_LOADED_SW].cap = + SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_PAGE_LOADED_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_PAGE_LOADED_SW].b = 0; @@ -5035,8 +5074,9 @@ init_options (Genesys_Scanner * s) s->opt[OPT_OCR_SW].desc = "OCR button"; s->opt[OPT_OCR_SW].type = SANE_TYPE_BOOL; s->opt[OPT_OCR_SW].unit = SANE_UNIT_NONE; - if (model->buttons & GENESYS_HAS_OCR_SW) - s->opt[OPT_OCR_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if (model->buttons & GENESYS_HAS_OCR_SW) + s->opt[OPT_OCR_SW].cap = + SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_OCR_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_OCR_SW].b = 0; @@ -5048,13 +5088,28 @@ init_options (Genesys_Scanner * s) s->opt[OPT_POWER_SW].desc = "Power button"; s->opt[OPT_POWER_SW].type = SANE_TYPE_BOOL; s->opt[OPT_POWER_SW].unit = SANE_UNIT_NONE; - if (model->buttons & GENESYS_HAS_POWER_SW) - s->opt[OPT_POWER_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; + if (model->buttons & GENESYS_HAS_POWER_SW) + s->opt[OPT_POWER_SW].cap = + SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_POWER_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_POWER_SW].b = 0; s->last_val[OPT_POWER_SW].b = 0; + /* calibrate button */ + s->opt[OPT_CALIBRATE].name = "calibrate"; + s->opt[OPT_CALIBRATE].title = "Calibrate button"; + s->opt[OPT_CALIBRATE].desc = "Start calibration using special sheet"; + s->opt[OPT_CALIBRATE].type = SANE_TYPE_BOOL; + s->opt[OPT_CALIBRATE].unit = SANE_UNIT_NONE; + if (model->buttons & GENESYS_HAS_CALIBRATE) + s->opt[OPT_CALIBRATE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT + | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; + else + s->opt[OPT_CALIBRATE].cap = SANE_CAP_INACTIVE; + s->val[OPT_CALIBRATE].b = 0; + s->last_val[OPT_CALIBRATE].b = 0; + RIE (calc_parameters (s)); DBG (DBG_proc, "init_options: exit\n"); @@ -5589,7 +5644,7 @@ get_option_value (Genesys_Scanner * s, int option, void *val) case OPT_PAGE_LOADED_SW: case OPT_OCR_SW: case OPT_POWER_SW: - RIE(s->dev->model->cmd_set->update_hardware_sensors(s)); + RIE (s->dev->model->cmd_set->update_hardware_sensors (s)); *(SANE_Bool *) val = s->val[option].b; s->last_val[option].b = *(SANE_Bool *) val; break; diff --git a/backend/genesys.conf.in b/backend/genesys.conf.in index 04ac41e10..2520f6e58 100644 --- a/backend/genesys.conf.in +++ b/backend/genesys.conf.in @@ -9,10 +9,10 @@ #usb 0x0638 0x0a10 # Hewlett Packard ScanJet 2400c -#usb 0x03f0 0x0a01 +usb 0x03f0 0x0a01 # Hewlett Packard ScanJet 3670c -#usb 0x03f0 0x1405 +usb 0x03f0 0x1405 # Plustek OpticPro ST24 #usb 0x07b3 0x0601 diff --git a/backend/genesys.h b/backend/genesys.h index f02a513ee..497d49b24 100644 --- a/backend/genesys.h +++ b/backend/genesys.h @@ -103,13 +103,14 @@ enum Genesys_Option OPT_PAGE_LOADED_SW, OPT_OCR_SW, OPT_POWER_SW, + OPT_CALIBRATE, /* must come last: */ NUM_OPTIONS }; -/** Scanner object. +/** Scanner object. Should have better be called Session than Scanner */ typedef struct Genesys_Scanner { diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c index f232641c4..625ea1a96 100644 --- a/backend/genesys_devices.c +++ b/backend/genesys_devices.c @@ -3,7 +3,7 @@ Copyright (C) 2003 Oliver Rauch Copyright (C) 2003-2005 Henning Meier-Geinitz Copyright (C) 2004, 2005 Gerhard Jaeger - Copyright (C) 2004-2007 Stephane Voltz + Copyright (C) 2004-2009 Stéphane Voltz Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2007 Luke @@ -53,69 +53,77 @@ /** Setup table for various scanners using a Wolfson DAC */ static Genesys_Frontend Wolfson[] = { - {{0x00, 0x03, 0x05, 0x11} + { DAC_WOLFSON_UMAX, {0x00, 0x03, 0x05, 0x11} , {0x00, 0x00, 0x00} , {0x80, 0x80, 0x80} , {0x02, 0x02, 0x02} , {0x00, 0x00, 0x00} } , /* 0: UMAX */ - {{0x00, 0x03, 0x05, 0x03} + {DAC_WOLFSON_ST12, {0x00, 0x03, 0x05, 0x03} , {0x00, 0x00, 0x00} , {0xc8, 0xc8, 0xc8} , {0x04, 0x04, 0x04} , {0x00, 0x00, 0x00} } , /* 1: ST12 */ - {{0x00, 0x03, 0x05, 0x21} + {DAC_WOLFSON_ST24,{0x00, 0x03, 0x05, 0x21} , {0x00, 0x00, 0x00} , {0xc8, 0xc8, 0xc8} , {0x06, 0x06, 0x06} , {0x00, 0x00, 0x00} } , /* 2: ST24 */ - {{0x00, 0x03, 0x05, 0x12} + {DAC_WOLFSON_5345,{0x00, 0x03, 0x05, 0x12} , {0x00, 0x00, 0x00} - , {0xc8, 0xc8, 0xc8} + , {0xb8, 0xb8, 0xb8} , {0x04, 0x04, 0x04} , {0x00, 0x00, 0x00} } , /* 3: MD6228/MD6471 */ - {{0x00, 0x03, 0x05, 0x02} + {DAC_WOLFSON_HP2400,{0x00, 0x03, 0x05, 0x02} , {0x00, 0x00, 0x00} , {0xc0, 0xc0, 0xc0} , {0x07, 0x07, 0x07} , {0x00, 0x00, 0x00} } , /* 4: HP2400c */ - {{0x00, 0x03, 0x04, 0x02} + {DAC_WOLFSON_HP2300,{0x00, 0x03, 0x04, 0x02} , {0x00, 0x00, 0x00} - , {0xb0, 0xb0, 0xb0} + , {0xbe, 0xbe, 0xbe} , {0x04, 0x04, 0x04} , {0x00, 0x00, 0x00} } , /* 5: HP2300c */ - {{0x00, 0x3d, 0x08, 0x00} + {DAC_CANONLIDE35,{0x00, 0x3d, 0x08, 0x00} , {0x00, 0x00, 0x00} , {0xe1, 0xe1, 0xe1} , {0x93, 0x93, 0x93} , {0x00, 0x19, 0x06} } , /* 6: CANONLIDE35 */ - {{0x58, 0x00, 0x00, 0x00} /* TODO create an AnalogDevice struct */ + {DAC_AD_XP200,{0x58, 0x00, 0x00, 0x00} /* TODO create an AnalogDevice struct */ , {0x00, 0x00, 0x00} , {0x06, 0x00, 0x00} , {0x0c, 0x00, 0x00} , {0x00, 0x00, 0x00} } - , /* 7: XP200 */ - {{0x00, 0x35, 0x20, 0x14} + , + {DAC_WOLFSON_XP300,{0x00, 0x35, 0x20, 0x14} /* 7: XP300 */ , {0x00, 0x00, 0x00} , {0xe1, 0xe1, 0xe1} , {0x93, 0x93, 0x93} , {0x07, 0x00, 0x00} } , /* 8: XP300 */ + {DAC_WOLFSON_HP3670, /* uses one write for offset or gain like hp2300/2400 */ + {0x00, 0x03, 0x04, 0x02} + , {0x00, 0x00, 0x00} + , {0xb4, 0xb4, 0xb4} + , {0x08, 0x08, 0x08} + , {0x00, 0x00, 0x00} + } + , }; @@ -126,7 +134,7 @@ static Genesys_Frontend Wolfson[] = { */ static Genesys_Sensor Sensor[] = { /* 0: UMAX */ - {1200, 48, 64, 0, 10800, 210, 230, + {CCD_UMAX,1200, 48, 64, 0, 10800, 210, 230, {0x01, 0x03, 0x05, 0x07} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x05, 0x31, 0x2a, 0x00, 0x00, @@ -139,7 +147,7 @@ static Genesys_Sensor Sensor[] = { NULL, NULL, NULL} , /* 1: Plustek OpticPro S12/ST12 */ - {600, 48, 85, 152, 5416, 210, 230, + {CCD_ST12,600, 48, 85, 152, 5416, 210, 230, {0x02, 0x00, 0x06, 0x04} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x08, 0x20, 0x2a, 0x00, 0x00, @@ -152,7 +160,7 @@ static Genesys_Sensor Sensor[] = { NULL, NULL, NULL} , /* 2: Plustek OpticPro S24/ST24 */ - {1200, 48, 64, 0, 10800, 210, 230, + {CCD_ST24,1200, 48, 64, 0, 10800, 210, 230, {0x0e, 0x0c, 0x00, 0x0c} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x08, 0x31, 0x2a, 0x00, 0x00, @@ -165,10 +173,10 @@ static Genesys_Sensor Sensor[] = { NULL, NULL, NULL} , /* 3: MD6471 */ - {1200, + {CCD_5345,1200, 48, 16, 0, 10872, - 210, 200, + 210, 240, {0x0d, 0x0f, 0x11, 0x13} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x30, 0x2a, 0x00, 0x00, @@ -181,7 +189,7 @@ static Genesys_Sensor Sensor[] = { NULL, NULL, NULL} , /* 4: HP2400c */ - {1200, + {CCD_HP2400,1200, 48, 15, 0, 10872, 210, 200, {0x14, 0x15, 0x00, 0x00} /* registers 0x08-0x0b */ @@ -196,9 +204,9 @@ static Genesys_Sensor Sensor[] = { NULL, NULL, NULL} , /* 5: HP2300c */ - {600, + {CCD_HP2300,600, 48, - 20, 0, 5454, 210, 200, + 20, 0, 5454, 210, 240, {0x16, 0x00, 0x01, 0x03} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a, @@ -211,7 +219,7 @@ static Genesys_Sensor Sensor[] = { NULL, NULL, NULL} , /* CANOLIDE35 */ - {1200, + {CCD_CANONLIDE35, 1200, /*TODO: find a good reason for keeping all three following variables*/ 87, /*(black) */ 87, /* (dummy) */ @@ -234,7 +242,7 @@ static Genesys_Sensor Sensor[] = { NULL, NULL, NULL} , /* 7: Strobe XP200 */ - {600, + {CIS_XP200, 600, 48, 38, 0, 5454, 210, 200, {0x16, 0x00, 0x01, 0x03} @@ -246,10 +254,20 @@ static Genesys_Sensor Sensor[] = { 0x16} , 2.1, 2.1, 2.1, + NULL, NULL, NULL}, + /* HP3670 */ + {CCD_HP3670,1200, + 48, + 16, 0, 10872, + 210, 200, + {0x00, 0x0a, 0x0b, 0x0d} , + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x07, 0x20, 0x2a, 0x00, 0x00, 0xc0, 0x43} , + {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0x15, 0x05, 0x0a, 0x0f, 0x00}, + 2.38, 2.35, 2.34, NULL, NULL, NULL} , /* 8: Strobe XP300 */ - {600, + {CCD_XP300, 600, /*TODO: find a good reason for keeping all three following variables*/ 87, /*(black) */ 87, /* (dummy) */ @@ -279,7 +297,7 @@ static Genesys_Sensor Sensor[] = { */ static Genesys_Gpo Gpo[] = { /* UMAX */ - { + {GPO_UMAX, {0x11, 0x00} , {0x51, 0x20} @@ -287,7 +305,7 @@ static Genesys_Gpo Gpo[] = { } , /* Plustek OpticPro S12/ST12 */ - { + {GPO_ST12, {0x11, 0x00} , {0x51, 0x20} @@ -295,7 +313,7 @@ static Genesys_Gpo Gpo[] = { } , /* Plustek OpticPro S24/ST24 */ - { + {GPO_ST24, {0x00, 0x00} , {0x51, 0x20} @@ -303,7 +321,7 @@ static Genesys_Gpo Gpo[] = { } , /* MD5345/MD6471 */ - { + {GPO_5345, {0x30, 0x18} , /* bits 11-12 are for bipolar V-ref input voltage */ {0xa0, 0x18} @@ -311,7 +329,7 @@ static Genesys_Gpo Gpo[] = { } , /* HP2400C */ - { + {GPO_HP2400, {0x30, 0x00} , {0x31, 0x00} @@ -319,7 +337,7 @@ static Genesys_Gpo Gpo[] = { } , /* HP2300C */ - { + {GPO_HP2300, {0x00, 0x00} , {0x00, 0x00} @@ -327,7 +345,7 @@ static Genesys_Gpo Gpo[] = { } , /* CANONLIDE35 */ - { + {GPO_CANONLIDE35, {0x81, 0x80} , {0xef, 0x80} @@ -335,24 +353,29 @@ static Genesys_Gpo Gpo[] = { } , /* 7: XP200 */ - { + {GPO_XP200, {0x30, 0x00} , {0xb0, 0x00} , - } + }, + /* HP2400C */ + {GPO_HP3670, + {0x20, 0x00} + , + {0x70, 0x00} + } , /* 8: XP300 */ - { + {GPO_XP300, {0x09, 0xc6}, {0xbb, 0x00}, - } + } }; -#define MOTOR_ST24 2 static Genesys_Motor Motor[] = { - /* 0: UMAX */ - { + /* UMAX */ + {MOTOR_UMAX, 1200, /* motor base steps */ 2400, /* maximum motor resolution */ 1, /* maximum step mode */ @@ -370,7 +393,7 @@ static Genesys_Motor Motor[] = { 1.0, },},}, }, - { /* 1: MD5345/6228/6471 */ + {MOTOR_5345, /* MD5345/6228/6471 */ 1200, 2400, 1, @@ -388,7 +411,7 @@ static Genesys_Motor Motor[] = { 0.5, },},}, }, - { /* 2: ST24 */ + {MOTOR_ST24, /* ST24 */ 2400, 2400, 1, @@ -406,7 +429,7 @@ static Genesys_Motor Motor[] = { 0.3, },},}, }, - { /* 3: HP 2400c */ + {MOTOR_HP3670, /* HP 3670 */ 1200, 2400, 1, @@ -424,7 +447,25 @@ static Genesys_Motor Motor[] = { 0.5, },},}, }, - { /* 4: HP 2300c */ + {MOTOR_HP2400, /* HP 2400c */ + 1200, + 2400, + 1, + 1, + {{{ + 11000, /* start speed */ + 3000, /* max speed */ + 128, /* min steps */ + 0.25, + }, + { + 11000, + 3000, + 128, + 0.5, + },},}, + }, + {MOTOR_HP2300, /* HP 2300c */ 600, 1200, 1, @@ -442,7 +483,7 @@ static Genesys_Motor Motor[] = { 0.5, },},}, }, - { /* 5: Canon LiDE 35 */ + {MOTOR_CANONLIDE35, /* Canon LiDE 35 */ 1200, 2400, 1, @@ -460,7 +501,7 @@ static Genesys_Motor Motor[] = { 0.8, },},}, }, - { /* 6: Strobe XP200 */ + {MOTOR_XP200, /* Strobe XP200 */ 600, 600, 1, @@ -478,7 +519,7 @@ static Genesys_Motor Motor[] = { 0.5, },},}, }, - { /* 7: Visioneer Strobe XP300 */ + {MOTOR_XP300, /* 7: Visioneer Strobe XP300 */ 300, 600, 1, @@ -669,8 +710,8 @@ static Genesys_Model hp2300c_model = { {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ - SANE_FIX (-2.0), /* Start of scan area in mm (x_offset) */ - SANE_FIX (0.0), /* Start of scan area in mm (y_offset) */ + SANE_FIX (2.0), /* Start of scan area in mm (x_offset) */ + SANE_FIX (7.5), /* Start of scan area in mm (y_offset) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (295.0), /* Size of scan area in mm (y) */ @@ -699,12 +740,12 @@ static Genesys_Model hp2300c_model = { DAC_WOLFSON_HP2300, GPO_HP2300, MOTOR_HP2300, - GENESYS_FLAG_REPARK - | GENESYS_FLAG_14BIT_GAMMA + GENESYS_FLAG_14BIT_GAMMA + /* | GENESYS_FLAG_NO_CALIBRATION */ | GENESYS_FLAG_SEARCH_START - | GENESYS_FLAG_MUST_WAIT | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION + | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW, 9, @@ -755,9 +796,7 @@ Genesys_Model hp2400c_model = { GPO_HP2400, MOTOR_HP2400, GENESYS_FLAG_UNTESTED /* not fully working yet */ - | GENESYS_FLAG_REPARK | GENESYS_FLAG_14BIT_GAMMA - | GENESYS_FLAG_MUST_WAIT | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA @@ -811,8 +850,7 @@ Genesys_Model visioneer_xp200_model = { DAC_AD_XP200, /* Analog Device frontend */ GPO_XP200, MOTOR_XP200, - GENESYS_FLAG_UNTESTED /* not fully working yet */ - | GENESYS_FLAG_14BIT_GAMMA + GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_NO_CALIBRATION, @@ -828,8 +866,8 @@ static Genesys_Model hp3670c_model = { GENESYS_GL646, NULL, - {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ - {2400, 1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ + {1200, 600, 300, 150, 100, 50, 0}, /* possible x-resolutions */ + {1200, 600, 300, 150, 100, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ @@ -859,12 +897,15 @@ static Genesys_Model hp3670c_model = { SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ - CCD_UMAX, - DAC_WOLFSON_UMAX, - GPO_UMAX, - MOTOR_UMAX, - GENESYS_FLAG_UNTESTED, /* Which flags are needed for this scanner? */ - /* untested, values set by mike p. according to vendor's datasheet. */ + CCD_HP3670, + DAC_WOLFSON_HP3670, + GPO_HP3670, + MOTOR_HP3670, + GENESYS_FLAG_14BIT_GAMMA + | GENESYS_FLAG_SEARCH_START + | GENESYS_FLAG_DARK_CALIBRATION + | GENESYS_FLAG_OFFSET_CALIBRATION + | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ 20, 200 @@ -964,7 +1005,6 @@ static Genesys_Model plustek_st24_model = { | GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_USE_PARK - | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_SEARCH_START | GENESYS_FLAG_OFFSET_CALIBRATION, GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ 20, @@ -978,13 +1018,13 @@ static Genesys_Model medion_md5345_model = { GENESYS_GL646, NULL, - {1200, 600, 300, 200, 150, 100, 75, 50, 0}, /* possible x-resolutions */ - {2400, 1200, 600, 500, 400, 300, 250, 200, 150, 100, 50, 0}, /* possible y-resolutions */ + {1200, 600, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible x-resolutions */ + {2400, 1200, 600, 500, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ - SANE_FIX (1.00), /* Start of scan area in mm (x) */ - SANE_FIX (5.00), /* 2.79 < Start of scan area in mm (y) */ + SANE_FIX ( 0.00), /* Start of scan area in mm (x) */ + SANE_FIX ( 0.00), /* 2.79 < Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (296.4), /* Size of scan area in mm (y) */ @@ -1016,11 +1056,11 @@ static Genesys_Model medion_md5345_model = { GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_USE_PARK - | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_SEARCH_START - | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE + | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION + | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_POWER_SW | GENESYS_HAS_OCR_SW | GENESYS_HAS_SCAN_SW, 32, diff --git a/backend/genesys_gl646.c b/backend/genesys_gl646.c index a04d75e4b..10b118080 100644 --- a/backend/genesys_gl646.c +++ b/backend/genesys_gl646.c @@ -3,8 +3,8 @@ Copyright (C) 2003 Oliver Rauch Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004 Gerhard Jaeger - Copyright (C) 2004 - 2008 Stéphane Voltz - Copyright (C) 2005 - 2009 Pierre Willenbrock + Copyright (C) 2004-2009 Stéphane Voltz + Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2007 Luke This file is part of the SANE package. @@ -57,8 +57,6 @@ #include #endif -#include "_stdint.h" - #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" @@ -70,6 +68,7 @@ #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_usb.h" +#include "_stdint.h" #include "genesys.h" /* Individual bits */ @@ -168,6 +167,7 @@ #define REG6C_Z1MOD 0x38 #define REG6C_Z2MOD 0x07 +#define REG_SCANFED 0x1f #define REG_LINCNT 0x25 #define REG_DPISET 0x2c #define REG_STRPIXEL 0x30 @@ -175,6 +175,9 @@ #define REG_MAXWD 0x35 #define REG_LPERIOD 0x38 #define REG_FEEDL 0x3d +#define REG_VALIDWORD 0x42 +#define REG_FEDCNT 0x48 +#define REG_SCANCNT 0x4b #define REG_Z1MOD 0x60 #define REG_Z2MOD 0x62 @@ -269,9 +272,32 @@ enum static SANE_Status gl646_set_fe (Genesys_Device * dev, uint8_t set); -static SANE_Status + +/** + * sets up the scanner for a scan, registers, gamma tables, shading tables + * and slope tables, based on the parameter struct. + * @param device device 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 SANE_Status +setup_for_scan (Genesys_Device * device, Genesys_Settings settings, + SANE_Bool split, SANE_Bool xcorrection, + SANE_Bool ycorrection); + +/** + * sets up the registers for a scan corresponding to the settings. + * Builds motor slope tables. Computes buffer sizes and data amount to + * transfer. It also sets up analog frontend. + * */ +static SANE_Status gl646_setup_registers (Genesys_Device * dev, Genesys_Register_Set * regs, + Genesys_Settings scan_settings, uint16_t * slope_table1, uint16_t * slope_table2, SANE_Int resolution, @@ -279,7 +305,85 @@ gl646_setup_registers (Genesys_Device * dev, uint32_t linecnt, uint16_t startx, uint16_t endx, SANE_Bool color, SANE_Int depth); -static void gl646_init_regs (Genesys_Device * dev); +/** + * 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 SANE_Status gl646_repark_head (Genesys_Device * dev); + +/** + * 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 device device to set up + * @param settings settings of the scan + * @param move flag to enable scanhead to move + * @param data pointer that will point to the scanned data + */ +static SANE_Status +simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, + unsigned char **data); + +/** + * Send the stop scan command + * */ +static SANE_Status +end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, + SANE_Bool check_stop, SANE_Bool eject); +/** + * writes control data to an area behind the last motor table. + */ +static SANE_Status write_control (Genesys_Device * dev, int resolution); + + +/** + * initialize scanner's registers at SANE init time + */ +static void gl646_init_regs (Genesys_Device * dev); + +/** + * returns the value hold by a 3 word register + * @param regs register set from which reading the value + * @param regnum number of the register to read + * @return 24 bit value of the register + */ +static uint32_t +gl646_get_triple_reg (Genesys_Register_Set * regs, int regnum) +{ + Genesys_Register_Set *r = NULL; + uint32_t ret = 0; + + r = sanei_genesys_get_address (regs, regnum); + ret = r->value; + r = sanei_genesys_get_address (regs, regnum + 1); + ret = (ret << 8) + r->value; + r = sanei_genesys_get_address (regs, regnum + 2); + ret = (ret << 8) + r->value; + + return ret; +} + +/** + * returns the value hold by a 2 word register + * @param regs register set from which reading the value + * @param regnum number of the register to read + * @return 16 bit value of the register + */ +static uint32_t +gl646_get_double_reg (Genesys_Register_Set * regs, int regnum) +{ + Genesys_Register_Set *r = NULL; + uint32_t ret = 0; + + r = sanei_genesys_get_address (regs, regnum); + ret = r->value; + r = sanei_genesys_get_address (regs, regnum + 1); + ret = (ret << 8) + r->value; + + return ret; +} /* Write to many registers */ static SANE_Status @@ -339,8 +443,31 @@ gl646_bulk_write_register (Genesys_Device * dev, return status; } - for (i = 0; i < size; i += 2) - DBG (DBG_io2, "reg[0x%02x] = 0x%02x\n", buffer[i], buffer[i + 1]); + if (DBG_LEVEL >= DBG_io2) + { + for (i = 0; i < size; i += 2) + { + DBG (DBG_io2, "reg[0x%02x] = 0x%02x\n", buffer[i], buffer[i + 1]); + } + /* when full size, decode regfister content */ + if (elems > 60) + { + DBG (DBG_io2, "DPISET =%d\n", + gl646_get_double_reg (reg, REG_DPISET)); + DBG (DBG_io2, "STRPIXEL =%d\n", + gl646_get_double_reg (reg, REG_STRPIXEL)); + DBG (DBG_io2, "ENDPIXEL =%d\n", + gl646_get_double_reg (reg, REG_ENDPIXEL)); + DBG (DBG_io2, "LINCNT =%d\n", + gl646_get_triple_reg (reg, REG_LINCNT)); + DBG (DBG_io2, "MAXWD =%d\n", + gl646_get_triple_reg (reg, REG_MAXWD)); + DBG (DBG_io2, "LPERIOD =%d\n", + gl646_get_double_reg (reg, REG_LPERIOD)); + DBG (DBG_io2, "FEEDL =%d\n", + gl646_get_triple_reg (reg, REG_FEEDL)); + } + } DBG (DBG_io, "gl646_bulk_write_register: wrote %lu bytes, %lu registers\n", (u_long) size, (u_long) elems); @@ -414,7 +541,7 @@ gl646_bulk_write_data (Genesys_Device * dev, uint8_t addr, data += size; } - DBG (DBG_io, "gl646_bulk_write_data: completed\n"); + DBG (DBG_io, "gl646_bulk_write_data: end\n"); return status; } @@ -463,8 +590,6 @@ gl646_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t outdata[8]; DBG (DBG_io, "gl646_bulk_read_data: requesting %lu bytes\n", (u_long) len); - DBG (DBG_io, "gl646_bulk_read_data: read bytes left %lu \n", - (u_long) dev->read_bytes_left); /* write requested size */ status = @@ -525,11 +650,33 @@ gl646_bulk_read_data (Genesys_Device * dev, uint8_t addr, data += size; } - DBG (DBG_io, "gl646_bulk_read_data: completed\n"); + DBG (DBG_io, "gl646_bulk_read_data: end\n"); return status; } +static SANE_Status +read_triple_reg (Genesys_Device * dev, int index, unsigned int *words) +{ + SANE_Status status; + uint8_t value; + + DBG (DBG_proc, "read_triple_reg\n"); + + RIE (sanei_genesys_read_register (dev, index + 2, &value)); + *words = value; + RIE (sanei_genesys_read_register (dev, index + 1, &value)); + *words += (value * 256); + RIE (sanei_genesys_read_register (dev, index, &value)); + if (dev->model->asic_type == GENESYS_GL646) + *words += ((value & 0x03) * 256 * 256); + else + *words += ((value & 0x0f) * 256 * 256); + + DBG (DBG_proc, "read_triple_reg: value=%d\n", *words); + return status; +} + static SANE_Bool gl646_get_fast_feed_bit (Genesys_Register_Set * regs) { @@ -627,130 +774,55 @@ gl646_set_double_reg (Genesys_Register_Set * regs, int regnum, r->value = LOBYTE (LOWORD (value)); } -/* - * sets r21 to r23 registers, ie number of steps for motor - * todo : some hardcoded values will be put in Motor_Struct +/** + * decodes and prints content of status (0x41) register + * @param val value read from reg41 */ static void -gl646_setup_steps (Genesys_Device * dev, Genesys_Register_Set * regs, int dpi) +print_status (uint8_t val) { - Genesys_Register_Set *r; - int fw, bw; + char msg[80]; - if (regs[reg_0x04].value & REG04_FILTER) - { - /* monochrome */ - switch (dev->model->motor_type) - { - case MOTOR_HP2300: - if (dpi <= 75) - fw = 120; - else if (dpi <= 150) - fw = 67; - else if (dpi <= 300) - fw = 44; - else - fw = 3; - bw = 16; - break; - case MOTOR_HP2400: - if (dpi <= 75) - fw = 120; - else if (dpi <= 150) - fw = 67; - else if (dpi <= 300) - fw = 44; - else - fw = 3; - bw = 16; - break; - case MOTOR_5345: - default: - if (dpi <= 600) - fw = 255; - else - fw = 32; - bw = 64; - break; - } - } - else - { - switch (dev->model->motor_type) - { - case MOTOR_HP2300: - if (dpi <= 75) - fw = 120; - else if (dpi <= 150) - fw = 67; - else if (dpi <= 300) - fw = 44; - else - fw = 3; - bw = 16; - break; - case MOTOR_HP2400: - if (dpi <= 75) - { - fw = 120; - bw = 64; - } - else if (dpi <= 150) - { - fw = 32; - bw = 64; - } - else if (dpi <= 300) - { - fw = 32; - bw = 64; - } - else /* >300 dpi */ - { - fw = 32; - bw = 64; - } - break; - - case MOTOR_5345: - default: - if (dpi < 200) - { - fw = 255; - bw = 64; - } - else if (dpi < 400) - { - fw = 64; - bw = 32; - } - else if (dpi <= 600) - { - fw = 32; - bw = 32; - } - else - { - fw = 16; - bw = 146; - } - } - } - - r = sanei_genesys_get_address (regs, 0x21); - r->value = fw; - r = sanei_genesys_get_address (regs, 0x22); - r->value = bw; - r = sanei_genesys_get_address (regs, 0x23); - r->value = bw; - r = sanei_genesys_get_address (regs, 0x24); - r->value = fw; + sprintf (msg, "%s%s%s%s%s%s%s%s", + val & REG41_PWRBIT ? "PWRBIT " : "", + val & REG41_BUFEMPTY ? "BUFEMPTY " : "", + val & REG41_FEEDFSH ? "FEEDFSH " : "", + val & REG41_SCANFSH ? "SCANFSH " : "", + val & REG41_HOMESNR ? "HOMESNR " : "", + val & REG41_LAMPSTS ? "LAMPSTS " : "", + val & REG41_FEBUSY ? "FEBUSY " : "", + val & REG41_MOTMFLG ? "MOTMFLG" : ""); + DBG (DBG_info, "status=%s\n", msg); } +/** + * start scanner's motor + * @param dev scanner's device + */ +static SANE_Status +gl646_start_motor (Genesys_Device * dev) +{ + return sanei_genesys_write_register (dev, 0x0f, 0x01); +} + + +/** + * stop scanner's motor + * @param dev scanner's device + */ +static SANE_Status +gl646_stop_motor (Genesys_Device * dev) +{ + return sanei_genesys_write_register (dev, 0x0f, 0x00); +} + + #define FULL_STEP 0 #define HALF_STEP 1 #define QUATER_STEP 2 +#define CALIBRATION_LINES 10 + /** * master motor settings table entry */ @@ -763,7 +835,7 @@ typedef struct /* settings */ SANE_Int ydpi; /* real motor dpi, may be different from the resolution */ - SANE_Int steptype; /* 0=full, 1=half, 2=quater */ + SANE_Int steptype; /* 0=full, 1=half, 2=quarter */ SANE_Bool fastmod; /* fast scanning 0/1 */ SANE_Bool fastfed; /* fast fed slope tables */ SANE_Int mtrpwm; @@ -792,14 +864,17 @@ typedef struct SANE_Int xdpi; /**< real sensor dpi, may be different from the required resolution */ SANE_Int exposure; /**< exposure time */ SANE_Int dpiset; /**< set sensor dpi */ - SANE_Int cksel; /**< dpiset 'divisor' */ + SANE_Int cksel; /**< dpiset 'divisor', part of reg 18h */ SANE_Int dummy; /**< dummy exposure time */ uint8_t regs_0x10_0x15[6]; /**< per color exposure time for CIS scanners */ - SANE_Bool half_ccd; /**> true if manual CCD/2 clock programming */ + SANE_Bool half_ccd; /**> true if manual CCD/2 clock programming or real dpi is half dpiset */ + uint8_t reg_0x18; /**> content of register 18h */ + uint8_t reg_0x1d; /**> content of register 1dh */ } Sensor_Master; /** * settings for a given resolution and DPISET + * TODO clean up this when all scanners will have been added */ typedef struct { @@ -809,40 +884,84 @@ typedef struct /* values */ uint8_t regs_0x08_0x0b[4]; /**< settings for normal CCD clock */ - uint8_t manual_0x08_0x0b[4]; /**< settings for manual CCD/2 clock */ + uint8_t manual_0x08_0x0b[4]; /**< settings for CCD/2 clock */ uint8_t regs_0x16_0x1d[8]; uint8_t regs_0x52_0x5e[13]; + uint8_t manual_0x52_0x58[7]; } Sensor_Settings; - /** * master sensor settings, for a given sensor and dpi, * it gives exposure and CCD time */ +/* *INDENT-OFF* */ static Sensor_Master sensor_master[] = { + /* HP3670 master settings */ + {CCD_HP3670, 50, SANE_TRUE , 50, 5758, 200, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 100, SANE_TRUE , 100, 4487, 400, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 150, SANE_TRUE , 150, 4879, 600, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 300, SANE_TRUE , 300, 4503, 1200, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 600, SANE_TRUE , 600, 10251, 1200, 2, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x31, 0x43}, + {CCD_HP3670,1200, SANE_TRUE , 1200, 12750, 1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x30, 0x43}, + {CCD_HP3670, 50, SANE_FALSE, 50, 5758, 200, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 100, SANE_FALSE, 100, 4487, 400, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 150, SANE_FALSE, 150, 4879, 600, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 300, SANE_FALSE, 300, 4503, 1200, 4, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x33, 0x43}, + {CCD_HP3670, 600, SANE_FALSE, 600, 10251, 1200, 2, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x31, 0x43}, + {CCD_HP3670,1200, SANE_FALSE, 1200, 12750, 1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x30, 0x43}, + /* HP 2400 master settings */ - {CCD_HP2400, 50, SANE_TRUE, 600, 675, 200, 4, 42, {0, 0, 0, 0, 0, 0}, SANE_FALSE}, - {CCD_HP2400, 600, SANE_TRUE, 1200, 18760, 1200, 2, 42, {0, 0, 0, 0, 0, 0}, SANE_FALSE}, + {CCD_HP2400, 50, SANE_TRUE, 50, 675, 200, 4, 42, {0, 0, 0, 0, 0, 0}, SANE_FALSE, 0x3f, 0x02}, + {CCD_HP2400, 300, SANE_TRUE, 300, 8751, 1200, 4, 42, {0, 0, 0, 0, 0, 0}, SANE_FALSE, 0x3f, 0x02}, + {CCD_HP2400, 600, SANE_TRUE, 1200, 18760, 1200, 2, 42, {0, 0, 0, 0, 0, 0}, SANE_FALSE, 0x3f, 0x02}, /* XP 200 master settings */ - {CIS_XP200, 75, SANE_TRUE, 75, 5700, 75, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE}, - {CIS_XP200, 100, SANE_TRUE, 100, 5700, 100, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE}, - {CIS_XP200, 200, SANE_TRUE, 200, 5700, 200, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE}, - {CIS_XP200, 300, SANE_TRUE, 300, 9000, 300, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE}, - {CIS_XP200, 600, SANE_TRUE, 600, 16000, 600, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE}, + {CIS_XP200 , 75, SANE_TRUE , 75, 5700, 75, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 100, SANE_TRUE , 100, 5700, 100, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 200, SANE_TRUE , 200, 5700, 200, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 300, SANE_TRUE , 300, 9000, 300, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 600, SANE_TRUE , 600, 16000, 600, 1, 42, {0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}, SANE_FALSE, 0x00, 0x11}, - {CIS_XP200, 75, SANE_FALSE, 75, 16000, 75, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE}, - {CIS_XP200, 100, SANE_FALSE, 100, 7800, 100, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE}, - {CIS_XP200, 200, SANE_FALSE, 200, 11000, 200, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE}, - {CIS_XP200, 300, SANE_FALSE, 300, 13000, 300, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE}, - {CIS_XP200, 600, SANE_FALSE, 600, 24000, 600, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE}, + {CIS_XP200 , 75, SANE_FALSE, 75, 16000, 75, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 100, SANE_FALSE, 100, 7800, 100, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 200, SANE_FALSE, 200, 11000, 200, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 300, SANE_FALSE, 300, 13000, 300, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE, 0x00, 0x11}, + {CIS_XP200 , 600, SANE_FALSE, 600, 24000, 600, 1, 42, {0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}, SANE_FALSE, 0x00, 0x11}, /* HP 2300 master settings */ - {CCD_HP2300, 75, SANE_TRUE, 75, 4480, 150, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, SANE_TRUE}, - {CCD_HP2300, 150, SANE_TRUE, 150, 4350, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, SANE_TRUE}, - {CCD_HP2300, 300, SANE_TRUE, 300, 8700, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, SANE_FALSE}, - {CCD_HP2300, 600, SANE_TRUE, 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, SANE_FALSE}, - {CCD_HP2300,1200, SANE_TRUE, 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, SANE_FALSE}, + {CCD_HP2300, 75, SANE_TRUE , 75, 4480, 150, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, + {CCD_HP2300, 150, SANE_TRUE , 150, 4350, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, + {CCD_HP2300, 300, SANE_TRUE , 300, 8700, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300, 600, SANE_TRUE , 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300,1200, SANE_TRUE , 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300, 75, SANE_FALSE, 75, 4480, 150, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, + {CCD_HP2300, 150, SANE_FALSE, 150, 4350, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, + {CCD_HP2300, 300, SANE_FALSE, 300, 8700, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300, 600, SANE_FALSE, 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300,1200, SANE_FALSE, 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + + /* MD5345/6471 master settings */ + {CCD_5345 , 50, SANE_TRUE , 50, 12000, 100, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 75, SANE_TRUE , 75, 11000, 150, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 100, SANE_TRUE , 100, 11000, 200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 150, SANE_TRUE , 150, 11000, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 200, SANE_TRUE , 200, 11000, 400, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 300, SANE_TRUE, 300, 11000, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 400, SANE_TRUE, 400, 11000, 800, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 600, SANE_TRUE, 600, 11000,1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 ,1200, SANE_TRUE ,1200, 11000,1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x30, 0x03}, + {CCD_5345 ,2400, SANE_TRUE ,1200, 11000,1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x30, 0x03}, + {CCD_5345 , 50, SANE_FALSE, 50, 12000, 100, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 75, SANE_FALSE, 75, 11000, 150, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 100, SANE_FALSE, 100, 11000, 200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 150, SANE_FALSE, 150, 11000, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 200, SANE_FALSE, 200, 11000, 400, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 300, SANE_FALSE, 300, 11000, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 400, SANE_FALSE, 400, 11000, 800, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 , 600, SANE_FALSE, 600, 11000,1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, + {CCD_5345 ,1200, SANE_FALSE,1200, 11000,1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x30, 0x03}, + {CCD_5345 ,2400, SANE_FALSE,1200, 11000,1200, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x30, 0x03}, + }; /** @@ -850,74 +969,200 @@ static Sensor_Master sensor_master[] = { * it gives steps and speed informations */ static Motor_Master motor_master[] = { + /* HP3670 motor settings */ + {MOTOR_HP3670, 50, SANE_TRUE , 50, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 229, 2329, 120, 200, 3399, 337, 0.3, 0.4, 192}, + {MOTOR_HP3670, 100, SANE_TRUE , 100, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 143, 2905, 187, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670, 150, SANE_TRUE , 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 73, 3429, 305, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670, 300, SANE_TRUE , 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 11, 1055, 563, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670, 600, SANE_TRUE , 600, FULL_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 10687, 5126, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670,1200, SANE_TRUE ,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 12751,12751, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670, 50, SANE_FALSE, 50, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 229, 2329, 120, 200, 3399, 337, 0.3, 0.4, 192}, + {MOTOR_HP3670, 100, SANE_FALSE, 100, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 143, 2905, 187, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670, 150, SANE_FALSE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 73, 3429, 305, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 11, 1055, 563, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670, 600, SANE_FALSE, 600, FULL_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 10687, 5126, 200, 3399, 337, 0.3, 0.4, 96}, + {MOTOR_HP3670,1200, SANE_FALSE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 12751,12751, 200, 3399, 337, 0.3, 0.4, 96}, + /* HP2400/G2410 motor settings */ - {MOTOR_HP2400, 50, SANE_TRUE, 50, HALF_STEP, SANE_FALSE, SANE_FALSE, 63, 4, 1382, 800, 2, 5400, 5400, 0.25, 0.5, 16}, - {MOTOR_HP2400, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE, 63, 32, 16703, 2188, 64, 4905, 419, 0.25, 0.5, 16}, - {MOTOR_HP2400, 600, SANE_TRUE, 600, FULL_STEP, SANE_FALSE, SANE_TRUE, 63, 3, 18761, 18761, 16, 4905, 627, 0.25, 0.5, 16}, + {MOTOR_HP2400, 50, SANE_TRUE, 50, HALF_STEP, SANE_FALSE, SANE_FALSE, 63, 4, 1382, 800, 2, 5400, 5400, 0.25, 0.5, 16}, + {MOTOR_HP2400, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 32, 16703, 2188, 120, 4905, 337, 0.25, 0.5, 16}, + {MOTOR_HP2400, 600, SANE_TRUE, 600, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 18761, 18761, 16, 4905, 627, 0.25, 0.5, 16}, /* XP 200 motor settings */ - {MOTOR_XP200, 75, SANE_TRUE, 75, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 6000, 2136, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 100, SANE_TRUE, 100, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 6000, 2850, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 200, SANE_TRUE, 200, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 6999, 5700, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 250, SANE_TRUE, 250, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 6999, 6999, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 300, SANE_TRUE, 300, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 13500, 13500, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 600, SANE_TRUE, 600, HALF_STEP, SANE_TRUE, SANE_TRUE, 0, 4, 31998, 31998, 2, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 75, SANE_FALSE, 75, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 6000, 2000, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 100, SANE_FALSE, 100, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 6000, 1300, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 200, SANE_FALSE, 200, HALF_STEP, SANE_TRUE, SANE_TRUE, 0, 4, 6000, 3666, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 300, SANE_FALSE, 300, HALF_STEP, SANE_TRUE, SANE_FALSE, 0, 4, 6500, 6500, 8, 12000, 1200, 0.3, 0.5, 1}, - {MOTOR_XP200, 600, SANE_FALSE, 600, HALF_STEP, SANE_TRUE, SANE_TRUE, 0, 4, 24000, 24000, 2, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 75, SANE_TRUE, 75, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 2136, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 100, SANE_TRUE, 100, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 2850, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 200, SANE_TRUE, 200, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6999, 5700, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 250, SANE_TRUE, 250, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6999, 6999, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 300, SANE_TRUE, 300, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 13500, 13500, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 600, SANE_TRUE, 600, HALF_STEP, SANE_TRUE , SANE_TRUE, 0, 4, 31998, 31998, 2, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 75, SANE_FALSE, 75, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 2000, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 100, SANE_FALSE, 100, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 1300, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 200, SANE_FALSE, 200, HALF_STEP, SANE_TRUE , SANE_TRUE, 0, 4, 6000, 3666, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 300, SANE_FALSE, 300, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6500, 6500, 8, 12000, 1200, 0.3, 0.5, 1}, + {MOTOR_XP200, 600, SANE_FALSE, 600, HALF_STEP, SANE_TRUE , SANE_TRUE, 0, 4, 24000, 24000, 2, 12000, 1200, 0.3, 0.5, 1}, - /* hp scanjet 2300c */ - {MOTOR_HP2300, 75, SANE_TRUE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE, 63, 120, 8139, 560, 120, 4905, 337, 0.3, 0.4, 16}, - {MOTOR_HP2300, 150, SANE_TRUE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE, 63, 67, 7903, 543, 120, 4905, 337, 0.3, 0.4, 16}, - {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE, 63, 44, 5386, 2175, 16, 4905, 1200, 0.5, 0.5, 16}, - {MOTOR_HP2300, 600, SANE_TRUE, 600, HALF_STEP, SANE_FALSE, SANE_FALSE, 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, - {MOTOR_HP2300,1200, SANE_TRUE,1200, HALF_STEP, SANE_FALSE, SANE_FALSE, 63, 3, 26100, 17400, 120, 4905, 337, 0.3, 0.4, 16}, + /* HP scanjet 2300c */ + {MOTOR_HP2300, 75, SANE_TRUE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8139, 560, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 150, SANE_TRUE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 7903, 543, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 600, SANE_TRUE, 600, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300,1200, SANE_TRUE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 26100, 17400, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 75, SANE_FALSE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8139, 560, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 150, SANE_FALSE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 7903, 543, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 600, SANE_FALSE, 600, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300,1200, SANE_FALSE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 26100, 17400, 120, 4905, 337, 0.3, 0.4, 16}, + + /* MD5345/6471 motor settings */ + {MOTOR_5345, 50, SANE_TRUE , 50, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 250, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 75, SANE_TRUE , 75, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 343, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 100, SANE_TRUE , 100, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 458, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 150, SANE_TRUE , 150, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 687, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 200, SANE_TRUE , 200, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 916, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 300, SANE_TRUE, 300, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 1375, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 400, SANE_TRUE, 400, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2000, 1833, 255, 2000, 300, 0.3, 0.4, 32}, + {MOTOR_5345, 500, SANE_TRUE, 500, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2291, 2291, 255, 2000, 300, 0.3, 0.4, 32}, + {MOTOR_5345, 600, SANE_TRUE, 600, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 32}, + {MOTOR_5345, 1200, SANE_TRUE ,1200, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 32, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 2400, SANE_TRUE ,2400, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 32, 2750, 5500, 255, 2000, 300, 0.3, 0.4, 64}, /* 5500 guessed */ + {MOTOR_5345, 50, SANE_FALSE, 50, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 250, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 75, SANE_FALSE, 75, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 343, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 100, SANE_FALSE, 100, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 458, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 150, SANE_FALSE, 150, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 687, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 200, SANE_FALSE, 200, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 916, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 300, SANE_FALSE, 300, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 1375, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 400, SANE_FALSE, 400, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2000, 1833, 255, 2000, 300, 0.3, 0.4, 32}, + {MOTOR_5345, 500, SANE_FALSE, 500, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2291, 2291, 255, 2000, 300, 0.3, 0.4, 32}, + {MOTOR_5345, 600, SANE_FALSE, 600, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 32}, + {MOTOR_5345, 1200, SANE_FALSE,1200, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 32, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 64}, + {MOTOR_5345, 2400, SANE_FALSE,2400, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 32, 2750, 5500, 255, 2000, 300, 0.3, 0.4, 64}, /* 5500 guessed */ }; /** * sensor settings for a given sensor and timing method */ static Sensor_Settings sensor_settings[] = { + /* HP 3670 */ + {CCD_HP3670, 1, + {0x0d, 0x0f, 0x11, 0x13}, + {0x00, 0x00, 0x00, 0x00}, + {0x2b, 0x07, 0x30, 0x2a, 0x00, 0x00, 0xc0, 0x43}, + {0x03, 0x07, 0x0b, 0x0f, 0x13, 0x17, 0x23, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, }, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + }, + {CCD_HP3670, 2, + {0x00, 0x05, 0x06, 0x08}, + {0x00, 0x00, 0x00, 0x00}, + {0x33, 0x07, 0x31, 0x2a, 0x02, 0x0e, 0xc0, 0x43}, + {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63, 0x00, 0xc1, 0x02, 0x0e, 0x00, 0x00, }, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + }, + {CCD_HP3670, 4, + {0x00, 0x0a, 0x0b, 0x0d}, + {0x00, 0x00, 0x00, 0x00}, + {0x33, 0x07, 0x33, 0x2a, 0x02, 0x13, 0xc0, 0x43}, + {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x15, 0xc1, 0x05, 0x0a, 0x0f, 0x00, }, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + }, + /* HP 2400 */ {CCD_HP2400, 4, - {20, 21, 0, 0}, - {20, 21, 0, 0}, - {0xbf, 0x08, 0x3f, 0x2a, 0, 0, 0, 0x02}, - {11, 15, 19, 23, 3, 7, 0x63, 0, 0xc1, 0, 0, 0, 0} + {0x14, 0x15, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00}, + {0xbf, 0x08, 0x3f, 0x2a, 0x00, 0x00, 0x00, 0x02}, + {11, 15, 19, 23, 3, 7, 0x63, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00}, + {11, 15, 19, 23, 3, 7, 0x63} }, {CCD_HP2400, 2, {14, 15, 0, 0}, {14, 15, 0, 0}, {0xbf, 0x08, 0x3f, 0x2a, 0, 0, 0, 0x02}, - {3, 7, 11, 15, 19, 23, 0x23, 0, 0xc1, 0, 0, 0, 0} + {3, 7, 11, 15, 19, 23, 0x23, 0, 0xc1, 0, 0, 0, 0}, + {3, 7, 11, 15, 19, 23, 0x23} }, {CCD_HP2400, 1, {0x02, 0x04, 0x00, 0x00}, {0x02, 0x04, 0x00, 0x00}, {0xbf, 0x08, 0x30, 0x2a, 0x00, 0x00, 0xc0, 0x42}, - {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63, 0x00, 0xc1, 0x00, 0x0e, 0x00, - 0x00} + {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63, 0x00, 0xc1, 0x00, 0x0e, 0x00, 0x00}, + {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63} }, {CIS_XP200, 1, {6, 7, 10, 4}, {6, 7, 10, 4}, {0x24, 0x04, 0x00, 0x2a, 0x0a, 0x0a, 0, 0x11}, - {8, 2, 0, 0, 0, 0, 0x1a, 0x51, 0, 0, 0, 0, 0} + {8, 2, 0, 0, 0, 0, 0x1a, 0x51, 0, 0, 0, 0, 0}, + {8, 2, 0, 0, 0, 0, 0x1a} }, {CCD_HP2300, 1, {0x01, 0x03, 0x04, 0x06}, {0x16, 0x00, 0x01, 0x03}, - {0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a, 0x00, 0x05,}, - {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0xc1, 0x06, 0x0b, 0x10, 0x16,} + {0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a, 0x00, 0x05}, + {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0xc1, 0x06, 0x0b, 0x10, 0x16}, + {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83} }, + {CCD_5345, 1, + {0x0d, 0x0f, 0x11, 0x13}, + {0x00, 0x05, 0x06, 0x08}, /* manual clock 1/2 settings or half ccd */ + {0x0b, 0x0a, 0x30, 0x2a, 0x00, 0x00, 0x00, 0x03, }, + {0x03, 0x07, 0x0b, 0x0f, 0x13, 0x17, 0x23, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00}, + {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83} /* half ccd settings */ + }, }; +/* *INDENT-ON* */ + + +/** + * 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 int +get_closest_resolution (int sensor, int required, SANE_Bool color) +{ + int i, nb; + int dist, dpi; + + i = 0; + dpi = 0; + dist = 9600; + nb = sizeof (sensor_master) / sizeof (Sensor_Master); + while (sensor_master[i].sensor != -1 && i < nb) + { + /* exit on perfect match */ + if (sensor == sensor_master[i].sensor + && sensor_master[i].dpi == required + && sensor_master[i].color == color) + { + DBG (DBG_info, "get_closest_resolution: match found for %d\n", + required); + return required; + } + /* computes distance and kepm ode is closest than previous */ + if (sensor == sensor_master[i].sensor + && sensor_master[i].color == color) + { + if (abs (sensor_master[i].dpi - required) < dist) + { + dpi = sensor_master[i].dpi; + dist = abs (sensor_master[i].dpi - required); + } + } + i++; + } + DBG (DBG_info, "get_closest_resolution: closest match for %d is %d\n", + required, dpi); + return dpi; +} /** * Setup register and motor tables for a scan at the - * given resolution and color mode. + * given resolution and color mode. TODO try to not use any filed from + * the device. * @param dev pointer to a struct describing the device * @param regs register set to fill + * @param scan_settings scan's settings * @param slope_table1 first motor table to fill * @param slope_table2 second motor table to fill * @param resolution dpi of the scan @@ -933,9 +1178,10 @@ static Sensor_Settings sensor_settings[] = { * registers are set from settings tables and flags related * to the hardware capabilities. * */ -static SANE_Status +static SANE_Status gl646_setup_registers (Genesys_Device * dev, Genesys_Register_Set * regs, + Genesys_Settings scan_settings, uint16_t * slope_table1, uint16_t * slope_table2, SANE_Int resolution, @@ -950,17 +1196,28 @@ gl646_setup_registers (Genesys_Device * dev, Motor_Master *motor = NULL; Sensor_Settings *settings = NULL; Genesys_Register_Set *r; - unsigned int used, vfinal; - uint32_t z1, z2, addr = 0xdead; - int dummy, channels = 1, stagger, wpl, max_shift; + unsigned int used1, used2, vfinal; + uint32_t z1, z2; + int channels = 1, stagger, wpl, max_shift; size_t requested_buffer_size; size_t read_buffer_size; - uint8_t control[4]; + SANE_Bool half_ccd = SANE_FALSE; + SANE_Int xresolution; DBG (DBG_proc, "gl646_setup_registers: start\n"); DBG (DBG_info, "gl646_setup_registers: startx=%d, endx=%d, linecnt=%d\n", startx, endx, linecnt); + /* x resolution is capped by sensor's capability */ + if (resolution > dev->sensor.optical_res) + { + xresolution = dev->sensor.optical_res; + } + else + { + xresolution = resolution; + } + /* for the given resolution, search for master * sensor mode setting */ i = 0; @@ -968,7 +1225,7 @@ gl646_setup_registers (Genesys_Device * dev, while (sensor_master[i].sensor != -1 && i < nb) { if (dev->model->ccd_type == sensor_master[i].sensor - && sensor_master[i].dpi == resolution + && sensor_master[i].dpi == xresolution && sensor_master[i].color == color) { sensor = &sensor_master[i]; @@ -979,7 +1236,7 @@ gl646_setup_registers (Genesys_Device * dev, { DBG (DBG_error, "gl646_setup_registers: unable to find settings for sensor %d at %d dpi color=%d\n", - dev->model->ccd_type, resolution, color); + dev->model->ccd_type, xresolution, color); return SANE_STATUS_INVAL; } @@ -1025,6 +1282,9 @@ gl646_setup_registers (Genesys_Device * dev, return SANE_STATUS_INVAL; } + /* half_ccd if manual clock programming or dpi is half dpiset */ + half_ccd = sensor->half_ccd; + /* now apply values from settings to registers */ for (i = 0; i < 6; i++) { @@ -1035,7 +1295,7 @@ gl646_setup_registers (Genesys_Device * dev, for (i = 0; i < 4; i++) { r = sanei_genesys_get_address (regs, 0x08 + i); - if(sensor->half_ccd==SANE_TRUE) + if (half_ccd == SANE_TRUE) r->value = settings->manual_0x08_0x0b[i]; else r->value = settings->regs_0x08_0x0b[i]; @@ -1052,17 +1312,25 @@ gl646_setup_registers (Genesys_Device * dev, r = sanei_genesys_get_address (regs, 0x52 + i); r->value = settings->regs_0x52_0x5e[i]; } + if (half_ccd == SANE_TRUE) + { + for (i = 0; i < 7; i++) + { + r = sanei_genesys_get_address (regs, 0x52 + i); + r->value = settings->manual_0x52_0x58[i]; + } + } /* now generate slope tables : we are not using generate_slope_table3 yet */ sanei_genesys_generate_slope_table (slope_table1, motor->steps1, motor->steps1 + 1, motor->vend1, motor->vstart1, motor->vend1, - motor->steps1, motor->g1, &used, + motor->steps1, motor->g1, &used1, &vfinal); sanei_genesys_generate_slope_table (slope_table2, motor->steps2, motor->steps2 + 1, motor->vend2, motor->vstart2, motor->vend2, - motor->steps2, motor->g2, &used, + motor->steps2, motor->g2, &used2, &vfinal); if (color == SANE_TRUE) @@ -1083,6 +1351,12 @@ gl646_setup_registers (Genesys_Device * dev, else regs[reg_0x01].value &= ~REG01_FASTMOD; + /* allow moving when buffer full by default */ + dev->reg[reg_0x02].value &= ~REG02_ACDCDIS; + + /* setup motor power */ + regs[reg_0x02].value |= REG02_MTRPWR; + /* fastfed enabled (2 motor slope tables) */ if (motor->fastfed) regs[reg_0x02].value |= REG02_FASTFED; @@ -1111,33 +1385,20 @@ gl646_setup_registers (Genesys_Device * dev, { regs[reg_0x02].value &= ~REG02_AGOHOME; } - - /* R04 building */ - regs[reg_0x04].value &= ~(REG04_FILTER | REG04_BITSET); - if (channels == 1) + else { - switch (dev->settings.color_filter) - { - /* red */ - case 0: - regs[reg_0x04].value |= 0x04; - break; - /* green */ - case 1: - regs[reg_0x04].value |= 0x08; - break; - /* blue */ - case 2: - regs[reg_0x04].value |= 0x0c; - break; - default: - return SANE_STATUS_INVAL; - } + regs[reg_0x02].value |= REG02_AGOHOME; } + + /* R04 */ if (depth > 8) { regs[reg_0x04].value |= REG04_BITSET; } + else + { + regs[reg_0x04].value &= ~REG04_BITSET; + } /* R05 */ regs[reg_0x05].value &= ~REG05_DPIHW; @@ -1159,18 +1420,20 @@ gl646_setup_registers (Genesys_Device * dev, /* gamma enable for scans */ if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) regs[reg_0x05].value |= REG05_GMM14BIT; - regs[reg_0x05].value |= REG05_GMMENB; - + if (depth < 16) + regs[reg_0x05].value |= REG05_GMMENB; + else + regs[reg_0x05].value &= ~REG05_GMMENB; /* true CIS gray */ if (dev->model->is_cis == SANE_TRUE && color == SANE_FALSE) regs[reg_0x05].value |= REG05_LEDADD; - /* manual CCD/2 clock programming => half_ccd */ - if (sensor->half_ccd==SANE_TRUE) - regs[reg_0x1d].value |= 0x80; - else - regs[reg_0x1d].value &= 0x7f; + /* cktoggle, ckdelay and cksel at once, cktdelay=2 => half_ccd for md5345 */ + regs[reg_0x18].value = sensor->reg_0x18; + + /* manual CCD/2 clock programming => half_ccd for hp2300 */ + regs[reg_0x1d].value = sensor->reg_0x1d; /* motor steps used */ regs[reg_0x21].value = motor->steps1; @@ -1179,7 +1442,7 @@ gl646_setup_registers (Genesys_Device * dev, regs[reg_0x24].value = motor->steps1; /* we adjust linecnt according to real motor dpi */ - linecnt = (linecnt * motor->ydpi) / dev->settings.yres; + linecnt = (linecnt * motor->ydpi) / scan_settings.yres; /* scanned area must be enlarged by max color shift needed */ /* all values are assumed >= 0 */ @@ -1190,7 +1453,7 @@ gl646_setup_registers (Genesys_Device * dev, max_shift = dev->model->ld_shift_b; if (dev->model->ld_shift_g > max_shift) max_shift = dev->model->ld_shift_g; - max_shift = (max_shift * dev->settings.yres) / dev->motor.base_ydpi; + max_shift = (max_shift * scan_settings.yres) / dev->motor.base_ydpi; linecnt += max_shift; } @@ -1199,6 +1462,14 @@ gl646_setup_registers (Genesys_Device * dev, max_shift = 0; } + /* at QUATER_STEP lines are 'staggered' and need correction */ + if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) + stagger = (4 * scan_settings.yres) / dev->motor.base_ydpi; + else + stagger = 0; + DBG (DBG_info, "gl646_setup_registers : max_shift=%d, stagger=%d lines\n", + max_shift, stagger); + /* CIS scanners read one line per color channel */ if (dev->model->is_cis == SANE_TRUE) { @@ -1211,17 +1482,21 @@ gl646_setup_registers (Genesys_Device * dev, /* scanner's x coordinates are expressed in physical DPI but they must be divided by cksel */ startx = startx / sensor->cksel; endx = endx / sensor->cksel; - DBG (DBG_info, "gl646_setup_registers: startx=%d, endx=%d, half_ccd=%d\n", - startx, endx, sensor->half_ccd); - if (sensor->half_ccd==SANE_TRUE) + if (half_ccd == SANE_TRUE) { - gl646_set_double_reg (regs, REG_STRPIXEL, startx/2); - gl646_set_double_reg (regs, REG_ENDPIXEL, endx/2); + gl646_set_double_reg (regs, REG_STRPIXEL, startx / 2); + gl646_set_double_reg (regs, REG_ENDPIXEL, endx / 2); + DBG (DBG_info, + "gl646_setup_registers: startx=%d, endx=%d, half_ccd=%d\n", + startx / 2, endx / 2, half_ccd); } else { gl646_set_double_reg (regs, REG_STRPIXEL, startx); gl646_set_double_reg (regs, REG_ENDPIXEL, endx); + DBG (DBG_info, + "gl646_setup_registers: startx=%d, endx=%d, half_ccd=%d\n", startx, + endx, half_ccd); } /* wpl must be computed according to the scan's resolution */ @@ -1239,12 +1514,32 @@ gl646_setup_registers (Genesys_Device * dev, gl646_set_double_reg (regs, REG_DPISET, sensor->dpiset); gl646_set_double_reg (regs, REG_LPERIOD, sensor->exposure); - /* round move distance according to dummy lines */ - if (dev->model->is_cis == SANE_FALSE) + /* move distance must be adjusted to take into account the extra lines + * read to reorder data */ + if (stagger + max_shift > 0 && move > 0) { - dummy = regs[reg_0x1e].value & 0x0f; - move = ((move + dummy) / (dummy + 1)) * (dummy + 1); + if (move > + ((max_shift + stagger) * dev->motor.optical_ydpi) / motor->ydpi) + move = + move - + ((max_shift + stagger) * dev->motor.optical_ydpi) / motor->ydpi; } + + /* we assume all scans are done with 2 tables */ + if (move > 0) + { + move = move - motor->steps1; + if (move < 0) + move = 0; + } + + /* round move distance according to dummy lines */ + /* XXX STEF XXX if (dev->model->is_cis == SANE_FALSE) + * it is for backtracking + { + dummy = regs[reg_0x1e].value & 0x0f; + move = ((move + dummy) / (dummy + 1)) * (dummy + 1); + } */ gl646_set_triple_reg (regs, REG_FEEDL, move); regs[reg_0x65].value = motor->mtrpwm; @@ -1252,11 +1547,11 @@ gl646_setup_registers (Genesys_Device * dev, sanei_genesys_calculate_zmode2 (regs[reg_0x02].value & REG02_FASTFED, sensor->exposure, slope_table1, - regs[reg_0x21].value, - move, regs[reg_0x22].value, &z1, &z2); + motor->steps1, + move, motor->fwdbwd, &z1, &z2); /* no z1/z2 for sheetfed scanners */ - if (dev->model->is_sheetfed == SANE_FALSE) + if (dev->model->is_sheetfed == SANE_TRUE) { z1 = 0; z2 = 0; @@ -1268,62 +1563,13 @@ gl646_setup_registers (Genesys_Device * dev, (regs[reg_0x6c]. value & REG6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16) & 0x07); - /* MD6471/G2410 and XP200 read/write data from an undocumented memory area which - * is after the second slope table */ - switch (dev->sensor.optical_res) - { - case 600: - addr = 0x08200; - break; - case 1200: - addr = 0x10200; - break; - case 2400: - addr = 0x1fa00; - break; - } - - /* XP200 sets dpi, what other scanner put is unknown yet */ - if (dev->model->motor_type == MOTOR_XP200) - { - /* we put scan's dpi, not motor one */ - control[0] = LOBYTE (dev->settings.yres); - control[1] = HIBYTE (dev->settings.yres); - control[2] = dev->control[4]; - control[3] = dev->control[5]; - } - else - { - control[0] = dev->control[2]; - control[1] = dev->control[3]; - control[2] = dev->control[4]; - control[3] = dev->control[5]; - } - - - DBG (DBG_info, - "gl646_setup_registers: control write=0x%02x 0x%02x 0x%02x 0x%02x\n", - control[0], control[1], control[2], control[3]); - status = sanei_genesys_set_buffer_address (dev, addr); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_setup_registers: failed to set up control address\n"); - return SANE_STATUS_INVAL; - } - status = gl646_bulk_write_data (dev, 0x3c, control, 4); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, "gl646_setup_registers: failed to set up control\n"); - return SANE_STATUS_INVAL; - } + RIE (write_control (dev, xresolution)); /* setup analog frontend */ - status = gl646_set_fe (dev, AFE_SET); + RIE (gl646_set_fe (dev, AFE_SET)); /* now we're done with registers setup values used by data transfer */ /* we setup values needed for the data transfer */ - stagger = 0; /* not implemented yet for this function */ /* we must use a round number of words_per_line */ /* CCD scanners have different requirements than CIS, and sheetfed ones @@ -1334,7 +1580,7 @@ gl646_setup_registers (Genesys_Device * dev, /* TODO seems CIS scanners should be treated differently */ read_buffer_size = 2 * requested_buffer_size + - ((max_shift + stagger) * dev->settings.pixels * channels * depth) / 8; + ((max_shift + stagger) * scan_settings.pixels * channels * depth) / 8; } else { @@ -1354,7 +1600,7 @@ gl646_setup_registers (Genesys_Device * dev, RIE (sanei_genesys_buffer_free (&(dev->out_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer), - (8 * dev->settings.pixels * channels * + (8 * scan_settings.pixels * channels * depth) / 8)); /* scan bytes to read */ @@ -1373,7 +1619,7 @@ gl646_setup_registers (Genesys_Device * dev, dev->current_setup.exposure_time = sensor->exposure; dev->current_setup.xres = sensor->xdpi; dev->current_setup.yres = motor->ydpi; - dev->current_setup.half_ccd = sensor->half_ccd; + dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; @@ -1382,17 +1628,17 @@ gl646_setup_registers (Genesys_Device * dev, * read_bytes_left is the number of bytes to read from the scanner */ dev->total_bytes_read = 0; - if (depth == 1 || dev->settings.scan_mode == 0) + if (depth == 1 || scan_settings.scan_mode == SCAN_MODE_LINEART) dev->total_bytes_to_read = - ((dev->settings.pixels * dev->settings.lines) / 8 + - (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) * + ((scan_settings.pixels * scan_settings.lines) / 8 + + (((scan_settings.pixels * scan_settings.lines) % 8) ? 1 : 0)) * channels; else dev->total_bytes_to_read = - dev->settings.pixels * dev->settings.lines * channels * (depth / 8); + scan_settings.pixels * scan_settings.lines * channels * (depth / 8); DBG (DBG_proc, "gl646_setup_registers: end\n"); - return status; + return SANE_STATUS_GOOD; } @@ -1405,13 +1651,12 @@ gl646_setup_registers (Genesys_Device * dev, appear anywhere else but in register init */ static void -gl646_setup_sensor (Genesys_Device * dev, - Genesys_Register_Set * regs, - SANE_Bool extended, SANE_Bool half_ccd) +gl646_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs) { Genesys_Register_Set *r; int i; + DBG (DBG_proc, "gl646_setup_sensor: start\n"); for (i = 0; i < 4; i++) { r = sanei_genesys_get_address (regs, 0x08 + i); @@ -1429,80 +1674,8 @@ gl646_setup_sensor (Genesys_Device * dev, r = sanei_genesys_get_address (regs, 0x52 + i); r->value = dev->sensor.regs_0x52_0x5e[i]; } + DBG (DBG_proc, "gl646_setup_sensor: end\n"); - /* don't go nay 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->ccd_type == CCD_5345) - { - if (half_ccd) - { - /* settings for CCD used at half is max resolution */ - r = sanei_genesys_get_address (regs, 0x08); - r->value = 0x00; - r = sanei_genesys_get_address (regs, 0x09); - r->value = 0x05; - r = sanei_genesys_get_address (regs, 0x0a); - r->value = 0x06; - r = sanei_genesys_get_address (regs, 0x0b); - 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 - { - /* swap latch times */ - r = sanei_genesys_get_address (regs, 0x18); - r->value = 0x30; - for (i = 0; i < 6; i++, r++) - { - r = sanei_genesys_get_address (regs, 0x52 + i); - r->value = dev->sensor.regs_0x52_0x5e[(i + 3) % 6]; - } - r = sanei_genesys_get_address (regs, 0x58); - r->value = 0x20 | (r->value & 0x03); /* VSMP=4 */ - } - return; - } - - if (dev->model->ccd_type == CCD_HP2300) - { - /* settings for CCD used at half is max resolution */ - if (half_ccd) - { - r = sanei_genesys_get_address (regs, 0x08); - r->value = 0x16; - r = sanei_genesys_get_address (regs, 0x09); - r->value = 0x00; - r = sanei_genesys_get_address (regs, 0x0a); - r->value = 0x01; - r = sanei_genesys_get_address (regs, 0x0b); - r->value = 0x03; - /* manual clock programming */ - r = sanei_genesys_get_address (regs, 0x1d); - r->value |= 0x80; - } - else - { - r = sanei_genesys_get_address (regs, 0x08); - r->value = 1; - r = sanei_genesys_get_address (regs, 0x09); - r->value = 3; - r = sanei_genesys_get_address (regs, 0x0a); - r->value = 4; - r = sanei_genesys_get_address (regs, 0x0b); - r->value = 6; - } - r = sanei_genesys_get_address (regs, 0x58); - r->value = 0x80 | (r->value & 0x03); /* VSMP=16 */ - return; - } } /** Test if the ASIC works @@ -1517,7 +1690,7 @@ gl646_asic_test (Genesys_Device * dev) size_t size, verify_size; unsigned int i; - DBG (DBG_proc, "gl646_asic_test\n"); + DBG (DBG_proc, "gl646_asic_test: start\n"); /* set and read exposure time, compare if it's the same */ status = sanei_genesys_write_register (dev, 0x38, 0xde); @@ -1647,7 +1820,7 @@ gl646_asic_test (Genesys_Device * dev) free (data); free (verify_data); - DBG (DBG_info, "gl646_asic_test: completed\n"); + DBG (DBG_info, "gl646_asic_test: end\n"); return SANE_STATUS_GOOD; } @@ -1659,10 +1832,11 @@ gl646_bulk_full_size (void) return GENESYS_GL646_MAX_REGS; } -/* - * Set all registers to default values +/** + * Set all registers to default values after init + * @param dev scannerr's device to set */ -static void +static void gl646_init_regs (Genesys_Device * dev) { int nr, addr; @@ -1685,8 +1859,6 @@ gl646_init_regs (Genesys_Device * dev) for (addr = 0x60; addr <= 0x6d; addr++) dev->reg[nr++].address = addr; -/* ST12: 0x01 0x20 0x02 0x30 0x03 0x1f 0x04 0x13 0x05 0x10 */ -/* ST24: 0x01 0x20 0x02 0x30 0x03 0x1f 0x04 0x13 0x05 0x50 */ dev->reg[reg_0x01].value = 0x20 /*0x22 */ ; /* enable shading, CCD, color, 1M */ dev->reg[reg_0x02].value = 0x30 /*0x38 */ ; /* auto home, one-table-move, full step */ if (dev->model->motor_type == MOTOR_5345) @@ -1743,12 +1915,10 @@ gl646_init_regs (Genesys_Device * dev) dev->reg[reg_0x06].value = 0x18; /* PWRBIT on, shading gain=8, normal AFE image capture */ - gl646_setup_sensor (dev, dev->reg, 0, 0); + gl646_setup_sensor (dev, dev->reg); dev->reg[reg_0x1e].value = 0xf0; /* watch-dog time */ -/* ST12: 0x20 0x10 0x21 0x08 0x22 0x10 0x23 0x10 0x24 0x08 0x25 0x00 0x26 0x00 0x27 0xd4 0x28 0x01 0x29 0xff */ -/* ST24: 0x20 0x10 0x21 0x08 0x22 0x10 0x23 0x10 0x24 0x08 0x25 0x00 0x26 0x00 0x27 0xd4 0x28 0x01 0x29 0xff */ switch (dev->model->ccd_type) { case CCD_HP2300: @@ -1765,13 +1935,16 @@ gl646_init_regs (Genesys_Device * dev) case CIS_XP200: dev->reg[reg_0x1e].value = 0x10; dev->reg[reg_0x1f].value = 0x01; - dev->reg[reg_0x20].value = 0x50; /* n * 2k, below this condition, motor move forward *//* todo: huh, 2k is pretty low? */ + dev->reg[reg_0x20].value = 0x50; break; default: dev->reg[reg_0x1f].value = 0x01; - dev->reg[reg_0x20].value = 0x10; /* n * 2k, below this condition, motor move forward *//* todo: huh, 2k is pretty low? */ + dev->reg[reg_0x20].value = 0x10; break; } + dev->reg[reg_0x1f].value = 0x01; /* XXX STEF XXX */ + dev->reg[reg_0x20].value = 0x50; /* XXX STEF XXX */ + dev->reg[reg_0x21].value = 0x08 /*0x20 */ ; /* table one steps number for forward slope curve of the acc/dec */ dev->reg[reg_0x22].value = 0x10 /*0x08 */ ; /* steps number of the forward steps for start/stop */ dev->reg[reg_0x23].value = 0x10 /*0x08 */ ; /* steps number of the backward steps for start/stop */ @@ -1782,16 +1955,11 @@ gl646_init_regs (Genesys_Device * dev) dev->reg[reg_0x28].value = 0x01; /* PWM duty for lamp control */ dev->reg[reg_0x29].value = 0xff; -/* ST12: 0x2c 0x02 0x2d 0x58 0x2e 0x6e 0x2f 0x80 */ -/* ST24: 0x2c 0x02 0x2d 0x58 0x2e 0x6e 0x2f 0x80 */ - dev->reg[reg_0x2c].value = 0x02; /* set resolution (600 DPI) */ dev->reg[reg_0x2d].value = 0x58; dev->reg[reg_0x2e].value = 0x78; /* set black&white threshold high level */ dev->reg[reg_0x2f].value = 0x7f; /* set black&white threshold low level */ -/* ST12: 0x30 0x00 0x31 0x0e 0x32 0x17 0x33 0x70 0x34 0x0c 0x35 0x01 0x36 0x00 0x37 0x00 0x38 0x17 0x39 0x70 */ -/* ST24: 0x30 0x00 0x31 0x0c 0x32 0x2a 0x33 0xf8 0x34 0x0c 0x35 0x01 0x36 0x00 0x37 0x00 0x38 0x2a 0x39 0xf8 */ dev->reg[reg_0x30].value = 0x00; /* begin pixel positon (16) */ dev->reg[reg_0x31].value = dev->sensor.dummy_pixel /*0x10 */ ; /* TGW + 2*TG_SHLD + x */ dev->reg[reg_0x32].value = 0x2a /*0x15 */ ; /* end pixel position (5390) */ @@ -1802,46 +1970,10 @@ gl646_init_regs (Genesys_Device * dev) dev->reg[reg_0x37].value = 0x00 /*0x30 */ ; dev->reg[reg_0x38].value = HIBYTE (dev->settings.exposure_time) /*0x2a */ ; /* line period (exposure time = 11000 pixels) */ dev->reg[reg_0x39].value = LOBYTE (dev->settings.exposure_time) /*0xf8 */ ; - -/* ST12: 0x3d 0x00 0x3e 0x00 0x3f 0x01 */ -/* ST24: 0x3d 0x00 0x3e 0x00 0x3f 0x01 */ dev->reg[reg_0x3d].value = 0x00; /* set feed steps number of motor move */ dev->reg[reg_0x3e].value = 0x00; dev->reg[reg_0x3f].value = 0x01 /*0x00 */ ; -#if 0 -/* ST12: 0x52 0x0f 0x53 0x13 0x54 0x17 0x55 0x03 0x56 0x07 0x57 0x0b 0x58 0x83 0x59 0x00 */ -/* ST24: 0x52 0x0f 0x53 0x13 0x54 0x17 0x55 0x03 0x56 0x07 0x57 0x0b 0x58 0x83 0x59 0x00 */ - dev->reg[reg_0x52].value = 0x0f /*0x13 */ ; /* R position */ - dev->reg[reg_0x53].value = 0x13 /*0x17 */ ; - dev->reg[reg_0x54].value = 0x17 /*0x03 */ ; /* G position */ - dev->reg[reg_0x55].value = 0x03 /*0x07 */ ; - dev->reg[reg_0x56].value = 0x07 /*0x0b */ ; /* B position on AFE signal */ - dev->reg[reg_0x57].value = 0x0b /*0x0f */ ; - dev->reg[reg_0x58].value = 0x83 /*0x23 */ ; /* set rising edge and width of image sample for AFE */ - dev->reg[reg_0x59].value = 0x00; /* set rising edge and width of dark voltage position */ -#endif - -#if 0 /* done in setup_sensor */ - for (i = 0; i < 6; i++, r++) - { - r = sanei_genesys_get_address (dev->reg, 0x52 + i); - r->value = dev->sensor.regs_0x52_0x5e[i]; - } -#endif - -/* ST12: 0x5a 0xc1 0x5b 0x00 0x5c 0x00 0x5d 0x00 0x5e 0x00 */ -/* ST24: 0x5a 0xc1 0x5b 0x00 0x5c 0x00 0x5d 0x00 0x5e 0x00 */ -#if 0 /* buggy code kept for reference ... */ - dev->reg[reg_0x5a].value = 0xc1; /* Wolfson AFE, reset level clamp on pixel, RLC of AFE for line rate scanning type */ - dev->reg[reg_0x5b].value = 0x00; /* First point of rising edge */ - dev->reg[reg_0x5c].value = 0x00; /* First point of falling edge */ - dev->reg[reg_0x5d].value = 0x00; /* Second point of rising edge */ - dev->reg[reg_0x5e].value = 0x00; /* Second point of falling edge */ -#endif - -/* ST12: 0x60 0x00 0x61 0x00 0x62 0x00 0x63 0x00 0x64 0x00 0x65 0x00 0x66 0x00 0x67 0x00 0x68 0x51 0x69 0x20 */ -/* ST24: 0x60 0x00 0x61 0x00 0x62 0x00 0x63 0x00 0x64 0x00 0x65 0x00 0x66 0x00 0x67 0x00 0x68 0x51 0x69 0x20 */ dev->reg[reg_0x60].value = 0x00; /* Z1MOD, 60h:61h:(6D b5:b3), remainder for start/stop */ dev->reg[reg_0x61].value = 0x00; /* (21h+22h)/LPeriod */ dev->reg[reg_0x62].value = 0x00; /* Z2MODE, 62h:63h:(6D b2:b0), remainder for start scan */ @@ -1951,7 +2083,7 @@ gl646_send_slope_table (Genesys_Device * dev, int table_nr, #ifdef WORDS_BIGENDIAN free (table); #endif - DBG (DBG_proc, "gl646_send_slope_table: completed\n"); + DBG (DBG_proc, "gl646_send_slope_table: end\n"); return status; } @@ -1966,7 +2098,11 @@ gl646_set_ad_fe (Genesys_Device * dev, uint8_t set) { DBG (DBG_proc, "gl646_set_ad_fe(): setting DAC %u\n", dev->model->dac_type); + + /* sets to default values */ sanei_genesys_init_fe (dev); + + /* write them to analog frontend */ status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); } if (set == AFE_SET) @@ -2004,9 +2140,7 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set) return SANE_STATUS_UNSUPPORTED; } - status = sanei_genesys_read_register (dev, 0x70, &val); - DBG (DBG_proc, "gl646_set_fe: R70=0x%02d\n", val); - + /* initialize analog frontend */ if (set == AFE_INIT) { DBG (DBG_proc, "gl646_set_fe(): setting DAC %u\n", @@ -2017,28 +2151,30 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set) status = sanei_genesys_fe_write_data (dev, 0x04, 0x80); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, "gl646_set_fe: reset fe failed: %s\n", + DBG (DBG_error, "gl646_set_fe: init fe failed: %s\n", sane_strstatus (status)); return status; - if (dev->model->ccd_type == CCD_HP2300 - || dev->model->ccd_type == CCD_HP2400) + } + + /* enable GPIO for some models */ + if (dev->model->ccd_type == CCD_HP2300 + || dev->model->ccd_type == CCD_HP2400 + || dev->model->ccd_type == CCD_HP3670) + { + val = 0x07; + status = gl646_gpio_output_enable (dev->dn, val); + if (status != SANE_STATUS_GOOD) { - val = 0x07; - status = - sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, - REQUEST_REGISTER, GPIO_OUTPUT_ENABLE, - INDEX, 1, &val); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_set_fe failed resetting frontend: %s\n", - sane_strstatus (status)); - return status; - } + DBG (DBG_error, + "gl646_set_fe: failed to enable GPIO: %s\n", + sane_strstatus (status)); + return status; } } + return status; } + /* set fontend to power saving mode */ if (set == AFE_POWER_SAVE) { status = sanei_genesys_fe_write_data (dev, 0x01, 0x02); @@ -2048,11 +2184,9 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set) return status; } - status = sanei_genesys_read_register (dev, 0x70, &val); - DBG (DBG_proc, "gl646_set_fe: R70=0x%02d\n", val); - /* TODO : base this test on cfg reg3 or a CCD family flag to be created */ - /*if (dev->model->ccd_type!=CCD_HP2300 && dev->model->ccd_type!=CCD_HP2400) */ + /*if (dev->model->ccd_type != CCD_HP2300 + && dev->model->ccd_type != CCD_HP2400) */ { status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); if (status != SANE_STATUS_GOOD) @@ -2070,14 +2204,7 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set) } } - status = sanei_genesys_fe_write_data (dev, 0x01, dev->frontend.reg[1]); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, "gl646_set_fe: writing reg1 failed: %s\n", - sane_strstatus (status)); - return status; - } - + /* start with reg3 */ status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.reg[3]); if (status != SANE_STATUS_GOOD) { @@ -2086,38 +2213,76 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set) return status; } - for (i = 0; i < 3; i++) + switch (dev->model->ccd_type) { - status = - sanei_genesys_fe_write_data (dev, 0x24 + i, dev->frontend.sign[i]); - if (status != SANE_STATUS_GOOD) + default: + for (i = 0; i < 3; i++) { - DBG (DBG_error, "gl646_set_fe: writing sign[%d] failed: %s\n", - i, sane_strstatus (status)); - return status; - } + status = + sanei_genesys_fe_write_data (dev, 0x24 + i, + dev->frontend.sign[i]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "gl646_set_fe: writing sign[%d] failed: %s\n", + i, sane_strstatus (status)); + return status; + } - status = - sanei_genesys_fe_write_data (dev, 0x28 + i, dev->frontend.gain[i]); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, "gl646_set_fe: writing gain[%d] failed: %s\n", - i, sane_strstatus (status)); - return status; - } + status = + sanei_genesys_fe_write_data (dev, 0x28 + i, + dev->frontend.gain[i]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "gl646_set_fe: writing gain[%d] failed: %s\n", + i, sane_strstatus (status)); + return status; + } - status = - sanei_genesys_fe_write_data (dev, 0x20 + i, dev->frontend.offset[i]); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_set_fe: writing offset[%d] failed: %s\n", i, - sane_strstatus (status)); - return status; + status = + sanei_genesys_fe_write_data (dev, 0x20 + i, + dev->frontend.offset[i]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl646_set_fe: writing offset[%d] failed: %s\n", i, + sane_strstatus (status)); + return status; + } } + break; + /* STEF just can't have it to work, seems polarity is inversed + case CCD_HP2300: + status = sanei_genesys_fe_write_data (dev, 0x28, dev->frontend.gain[1]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "gl646_set_fe: writing gain[1] failed: %s\n", + sane_strstatus (status)); + return status; + } + + status = + sanei_genesys_fe_write_data (dev, 0x23, dev->frontend.offset[1]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl646_set_fe: writing offset[1] failed: %s\n", + sane_strstatus (status)); + return status; + } + break; */ } - DBG (DBG_proc, "gl646_set_fe: completed\n"); + /* end with reg1 */ + status = sanei_genesys_fe_write_data (dev, 0x01, dev->frontend.reg[1]); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "gl646_set_fe: writing reg1 failed: %s\n", + sane_strstatus (status)); + return status; + } + + + DBG (DBG_proc, "gl646_set_fe: end\n"); return SANE_STATUS_GOOD; } @@ -2145,27 +2310,35 @@ static void gl646_set_lamp_power (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool set) { - if (set) + if (dev) { - sanei_genesys_set_reg_from_set (regs, 0x03, - sanei_genesys_read_reg_from_set (regs, - 0x03) | - REG03_LAMPPWR); - } - else - { - sanei_genesys_set_reg_from_set (regs, 0x03, - sanei_genesys_read_reg_from_set (regs, - 0x03) & - ~REG03_LAMPPWR); + if (set) + { + sanei_genesys_set_reg_from_set (regs, 0x03, + sanei_genesys_read_reg_from_set + (regs, 0x03) | REG03_LAMPPWR); + } + else + { + sanei_genesys_set_reg_from_set (regs, 0x03, + sanei_genesys_read_reg_from_set + (regs, 0x03) & ~REG03_LAMPPWR); + } } } +/** + * enters or leaves power saving mode + * @param dev scanner's device + * @param SANE_TRUE to enable power saving, SANE_FALSE to leave it + * @return allways SANE_STATUS_GOOD + */ static SANE_Status gl646_save_power (Genesys_Device * dev, SANE_Bool enable) { - DBG (DBG_proc, "gl646_save_power: enable = %d\n", enable); + DBG (DBG_proc, "gl646_save_power: start\n"); + DBG (DBG_info, "gl646_save_power: enable = %d\n", enable); if (enable) { @@ -2173,9 +2346,10 @@ gl646_save_power (Genesys_Device * dev, SANE_Bool enable) } else { - gl646_set_fe (dev, AFE_INIT); + /* gl646_set_fe (dev, AFE_INIT); */ } + DBG (DBG_proc, "gl646_save_power: end\n"); return SANE_STATUS_GOOD; } @@ -2258,21 +2432,10 @@ gl646_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ ) "gl646_set_powersaving: Failed to bulk write registers: %s\n", sane_strstatus (status)); - DBG (DBG_proc, "gl646_set_powersaving: completed\n"); + DBG (DBG_proc, "gl646_set_powersaving: end\n"); return status; } -static SANE_Status -gl646_start_motor (Genesys_Device * dev) -{ - return sanei_genesys_write_register (dev, 0x0f, 0x01); -} - -static SANE_Status -gl646_stop_motor (Genesys_Device * dev) -{ - return sanei_genesys_write_register (dev, 0x0f, 0x00); -} /** * loads document into scanner @@ -2461,7 +2624,7 @@ gl646_detect_document_end (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t val; - int bytes_to_flush, lines; + unsigned int bytes_to_flush, lines; uint32_t flines, bpl, channels, depth; DBG (DBG_proc, "gl646_detect_document_end: start\n"); @@ -2485,7 +2648,8 @@ gl646_detect_document_end (Genesys_Device * dev) lines = (SANE_UNFIX (dev->model->y_offset) * dev->current_setup.yres) / MM_PER_INCH; - DBG (DBG_io, "gl646_detect_document_end: adding %d line to flush\n", lines); + DBG (DBG_io, "gl646_detect_document_end: adding %d line to flush\n", + lines); if (dev->model->is_cis == SANE_TRUE) lines *= channels; @@ -2686,7 +2850,6 @@ gl646_eject_document (Genesys_Device * dev) } /* Send the low-level scan command */ -/* todo : is this that useful ? */ static SANE_Status gl646_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor) @@ -2720,7 +2883,7 @@ gl646_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, return status; } - DBG (DBG_proc, "gl646_begin_scan: completed\n"); + DBG (DBG_proc, "gl646_begin_scan: end\n"); return status; } @@ -2728,34 +2891,47 @@ gl646_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, /* Send the stop scan command */ static SANE_Status -gl646_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, - SANE_Bool check_stop) +end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, + SANE_Bool check_stop, SANE_Bool eject) { - SANE_Status status; + SANE_Status status = SANE_STATUS_GOOD; int i = 0; uint8_t val; + unsigned int value; - DBG (DBG_proc, "gl646_end_scan (check_stop = %d)\n", check_stop); + DBG (DBG_proc, "end_scan (check_stop = %d, eject = %d)\n", check_stop, + eject); + + status = sanei_genesys_get_status (dev, &val); + DBG (DBG_info, "end_scan: current status =0x%02x\n", val); + if (DBG_LEVEL > DBG_io) + { + print_status (val); + read_triple_reg (dev, REG_SCANCNT, &value); + } /* for sheetfed scanners, we have to eject document and read * left data in buffers */ if (dev->model->is_sheetfed == SANE_TRUE && dev->document == SANE_TRUE) { - status = gl646_eject_document (dev); - if (status != SANE_STATUS_GOOD) + if (eject == SANE_TRUE) { - DBG (DBG_error, "gl646_end_scan: failed to eject document\n"); - return status; + status = gl646_eject_document (dev); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "end_scan: failed to eject document\n"); + return status; + } } } else /* flat bed scanners */ { - - status = sanei_genesys_write_register (dev, 0x01, sanei_genesys_read_reg_from_set (reg, 0x01) & ~REG01_SCAN); /* disable scan */ + /* ends scan */ + status = sanei_genesys_write_register (dev, 0x01, 0x00); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_end_scan: failed to write register 01: %s\n", + "end_scan: failed to write register 01: %s\n", sane_strstatus (status)); return status; } @@ -2765,58 +2941,70 @@ gl646_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, for (i = 0; i < 300; i++) /* do not wait longer than wait 30 seconds */ { status = sanei_genesys_get_status (dev, &val); + if (DBG_LEVEL > DBG_io) + { + print_status (val); + } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_end_scan: failed to read register: %s\n", + "end_scan: failed to read register: %s\n", sane_strstatus (status)); return status; } - if ((!(val & REG41_MOTMFLG)) && (val & REG41_FEEDFSH)) + if (!(val & REG41_MOTMFLG) && (val & REG41_FEEDFSH) + && (val & REG41_SCANFSH)) { - DBG (DBG_proc, "gl646_end_scan: scanfeed finished\n"); + DBG (DBG_proc, "end_scan: scanfeed finished\n"); break; /* leave while loop */ } if ((!(val & REG41_MOTMFLG)) && (val & REG41_HOMESNR)) { - DBG (DBG_proc, "gl646_end_scan: head at home\n"); + DBG (DBG_proc, "end_scan: head at home\n"); break; /* leave while loop */ } - usleep (10000UL); /* sleep 100 ms */ + /* XXX STEF XXX usleep (10000UL); sleep 100 ms */ } } } - DBG (DBG_proc, "gl646_end_scan: completed (i=%u)\n", i); + DBG (DBG_proc, "end_scan: end (i=%u)\n", i); return status; } -/* Moves the slider to the home (top) postion slowly */ +/* Send the stop scan command */ +static SANE_Status +gl646_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, + SANE_Bool check_stop) +{ + return end_scan (dev, reg, check_stop, SANE_TRUE); +} + +/** + * parks head + * @param dev scanner's device + * @param wait_until_home true if the function waits until head parked + */ static SANE_Status gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { - Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS + 1]; SANE_Status status; - uint8_t val = 0; - uint8_t prepare_steps; - uint32_t steps; - uint16_t slope_table0[256]; - uint16_t exposure_time; - int i, dpi; + Genesys_Settings settings; + uint8_t val; + int i; - DBG (DBG_proc, "gl646_slow_back_home (wait_until_home = %d)\n", + DBG (DBG_proc, "gl646_slow_back_home: start , wait_until_home = %d\n", wait_until_home); - memset (local_reg, 0, sizeof (local_reg)); status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_slow_back_home: Failed to read home sensor: %s\n", + "gl646_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } @@ -2825,8 +3013,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) if (val & REG41_HOMESNR) /* is sensor at home? */ { - DBG (DBG_info, "gl646_slow_back_home: already at home, completed\n"); - dev->scanhead_position_in_steps = 0; + DBG (DBG_info, "gl646_slow_back_home: end since already at home\n"); return SANE_STATUS_GOOD; } @@ -2844,67 +3031,10 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) usleep (200000UL); } - memcpy (local_reg, dev->reg, - (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); - - prepare_steps = 4; - exposure_time = 6 * MOTOR_SPEED_MAX; - steps = 14700 - 2 * prepare_steps; - if (dev->model->motor_type == MOTOR_HP2300 - || dev->model->motor_type == MOTOR_HP2400) - { - steps = 65535; /* enough to get back home ... */ - dpi = dev->motor.base_ydpi / 4; - local_reg[reg_0x04].value &= ~REG04_FILTER; - exposure_time = sanei_genesys_exposure_time (dev, local_reg, dpi); - } - else - dpi = dev->motor.base_ydpi; - - local_reg[reg_0x01].value = - local_reg[reg_0x01].value & ~REG01_FASTMOD & ~REG01_SCAN; - local_reg[reg_0x02].value = (local_reg[reg_0x02].value & ~REG02_FASTFED & ~REG02_STEPSEL) | REG02_MTRPWR | REG02_MTRREV; /* Motor on, direction = reverse */ - if (dev->model->motor_type == MOTOR_HP2300 - || dev->model->motor_type == MOTOR_HP2400) - local_reg[reg_0x02].value = - (local_reg[reg_0x02].value & ~REG02_STEPSEL) | REG02_HALFSTEP; - - local_reg[reg_0x21].value = prepare_steps; - local_reg[reg_0x24].value = prepare_steps; - - local_reg[reg_0x38].value = HIBYTE (exposure_time); - local_reg[reg_0x39].value = LOBYTE (exposure_time); - - local_reg[reg_0x3d].value = LOBYTE (HIWORD (steps)); - local_reg[reg_0x3e].value = HIBYTE (LOWORD (steps)); - local_reg[reg_0x3f].value = LOBYTE (LOWORD (steps)); - - local_reg[reg_0x6c].value = 0x00; /* one time period (only one speed) */ - if (dev->model->motor_type != MOTOR_HP2300 - && dev->model->motor_type != MOTOR_HP2400) - { - local_reg[reg_0x66].value = local_reg[reg_0x66].value | REG66_LOW_CURRENT; /* gpio7-12: reset GPIO11 (low current) */ - local_reg[reg_0x6d].value = 0x54; - } - - if (dev->model->motor_type != MOTOR_UMAX) - { - sanei_genesys_create_slope_table (dev, - slope_table0, - local_reg[reg_0x21].value, - local_reg[reg_0x02]. - value & REG02_STEPSEL, - exposure_time, 0, dpi, 0); - } - else - { - sanei_genesys_create_slope_table (dev, slope_table0, prepare_steps, 0, exposure_time, 0, dev->motor.base_ydpi, /*MOTOR_GEAR */ - 0); - } - /* when scanhead is moving then wait until scanhead stops or timeout */ DBG (DBG_info, "gl646_slow_back_home: ensuring that motor is off\n"); - for (i = 400; i > 0; i--) /* do not wait longer than 40 seconds, count down to get i = 0 when busy */ + val = REG41_MOTMFLG; + for (i = 400; i > 0 && (val & REG41_MOTMFLG); i--) /* do not wait longer than 40 seconds, count down to get i = 0 when busy */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) @@ -2917,18 +3047,9 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) if (((val & (REG41_MOTMFLG | REG41_HOMESNR)) == REG41_HOMESNR)) /* at home and motor is off */ { DBG (DBG_info, - "gl646_slow_back_home: already at home and nor moving\n"); - dev->scanhead_position_in_steps = 0; + "gl646_slow_back_home: already at home and not moving\n"); return SANE_STATUS_GOOD; } - - if (!(val & REG41_MOTMFLG)) /* motor is off (todo: was this really wrong?) */ - { - DBG (DBG_info, - "gl646_slow_back_home: motor is off but scanhead is not home\n"); - break; /* motor is off and scanhead is not at home: continue */ - } - usleep (100 * 1000); /* sleep 100 ms (todo: fixed to really sleep 100 ms) */ } @@ -2939,37 +3060,57 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) return SANE_STATUS_DEVICE_BUSY; } - status = - gl646_send_slope_table (dev, 0, slope_table0, local_reg[reg_0x21].value); + /* setup for a backward scan of 65535 steps, with no actual data reading */ + settings.scan_method = SCAN_METHOD_FLATBED; + settings.scan_mode = SCAN_MODE_COLOR; + settings.xres = 75; + settings.yres = 75; + settings.tl_x = 0; + settings.tl_y = 0; + settings.pixels = 600; + settings.lines = 1; + settings.depth = 8; + settings.color_filter = 0; + + settings.disable_interpolation = 0; + settings.threshold = 0; + settings.exposure_time = 0; + + status = setup_for_scan (dev, settings, SANE_TRUE, SANE_TRUE, SANE_TRUE); + + /* backward , no actual data scanned TODO more setup flags to avoid this register manipulations ? */ + dev->reg[reg_0x02].value |= REG02_MTRREV; + dev->reg[reg_0x01].value &= ~REG01_SCAN; + gl646_set_triple_reg (dev->reg, REG_FEEDL, 65535); + + /* sets frontend */ + status = gl646_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_slow_back_home: Failed to send slope table 0: %s\n", + "gl646_slow_back_home: failed to set frontend: %s\n", sane_strstatus (status)); return status; } - status = gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS); + /* write scan registers */ + status = gl646_bulk_write_register (dev, dev->reg, + sizeof (dev->reg) / + sizeof (dev->reg[0])); + if (status != SANE_STATUS_GOOD) + DBG (DBG_error, + "gl646_slow_back_home: failed to bulk write registers: %s\n", + sane_strstatus (status)); + + /* starts scan */ + status = gl646_begin_scan (dev, dev->reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, - "gl646_slow_back_home: Failed to bulk write registers: %s\n", - sane_strstatus (status)); - return status; - } - - status = gl646_start_motor (dev); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_slow_back_home: Failed to start motor: %s\n", - sane_strstatus (status)); - gl646_stop_motor (dev); - /* send original registers */ - gl646_bulk_write_register (dev, dev->reg, GENESYS_GL646_MAX_REGS); + DBG (DBG_error, "gl646_slow_back_home: failed to begin scan: \n"); return status; } + /* loop until head parked */ if (wait_until_home) { int loop = 0; @@ -2988,7 +3129,8 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) if (val & 0x08) /* home sensor */ { DBG (DBG_info, "gl646_slow_back_home: reached home position\n"); - DBG (DBG_proc, "gl646_slow_back_home: finished\n"); + DBG (DBG_proc, "gl646_slow_back_home: end\n"); + usleep (500000); /* sleep 500 ms before returning */ return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ @@ -3002,463 +3144,95 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) } DBG (DBG_info, "gl646_slow_back_home: scanhead is still moving\n"); - DBG (DBG_proc, "gl646_slow_back_home: finished\n"); + DBG (DBG_proc, "gl646_slow_back_home: end\n"); return SANE_STATUS_GOOD; } -/* Moves the slider to the home (top) postion */ -/* relies on the settings given for scan, - but disables scan, puts motor in reverse and - steps to go before area to 65535 so head will - go home */ static SANE_Status gl646_park_head (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool wait_until_home) { - Genesys_Register_Set local_reg[9]; - SANE_Status status; - uint8_t val = 0; - int loop = 0; - int i; - int exposure_time; - - DBG (DBG_proc, "gl646_park_head (wait_until_home = %d)\n", wait_until_home); - memset (local_reg, 0, sizeof (local_reg)); - - /* read status */ - status = sanei_genesys_get_status (dev, &val); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_park_head: failed to read home sensor: %s\n", - sane_strstatus (status)); - return status; - } - - /* no need to park if allready at home */ - if (val & REG41_HOMESNR) - { - dev->scanhead_position_in_steps = 0; - return status; - } - - /* stop motor if needed */ - if (val & REG41_MOTMFLG) - { - status = gl646_stop_motor (dev); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_search_par_head: failed to stop motor: %s\n", - sane_strstatus (status)); - return SANE_STATUS_IO_ERROR; - } - usleep (200 * 1000); - } - - /* toggle values to get backward move */ - i = 0; - /* disable scan */ - local_reg[i].address = 0x01; - local_reg[i++].value = reg[reg_0x01].value & ~REG01_SCAN; - - /* motor reverse */ - local_reg[i].address = 0x02; - local_reg[i].value = reg[reg_0x02].value | REG02_MTRREV; - - switch (dev->model->motor_type) - { - case MOTOR_HP2300: - exposure_time = 2000; - local_reg[i++].value &= ~REG02_FASTFED; - break; - case MOTOR_HP2400: - exposure_time = 675; - local_reg[i++].value &= ~REG02_FASTFED; - break; - case MOTOR_5345: - exposure_time = 3600; - local_reg[i++].value |= REG02_FASTFED; - break; - default: - exposure_time = 3600; - local_reg[i++].value &= ~REG02_FASTFED; - break; - } - - /* enough steps (65535) to get home */ - local_reg[i].address = 0x3d; - local_reg[i++].value = 0x00; - local_reg[i].address = 0x3e; - local_reg[i++].value = HIBYTE (65535); - local_reg[i].address = 0x3f; - local_reg[i++].value = LOBYTE (65535); - - /* set line period */ - local_reg[i].address = 0x38; - local_reg[i++].value = HIBYTE (exposure_time); - local_reg[i].address = 0x39; - local_reg[i++].value = LOBYTE (exposure_time); - - /* writes register */ - status = gl646_bulk_write_register (dev, local_reg, i); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_park_head: failed to bulk write registers: %s\n", - sane_strstatus (status)); - return status; - } - - /* sends slope table 1 (move before scan area) */ - status = gl646_send_slope_table (dev, 1, dev->slope_table1, - reg[reg_0x6b].value); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_park_head: failed to send slope table 1: %s\n", - sane_strstatus (status)); - return status; - } - - /* start motor */ - status = gl646_start_motor (dev); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, "gl646_park_head: failed to start motor: %s\n", - sane_strstatus (status)); - gl646_stop_motor (dev); - /* restore original registers */ - gl646_bulk_write_register (dev, reg, GENESYS_GL646_MAX_REGS); - return status; - } - - /* wait for head to park if needed */ - if (wait_until_home) - { - /* no more than 300 loops of 100 ms each -> 30 second time out */ - while (loop < 300) - { - status = sanei_genesys_get_status (dev, &val); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_park_head: failed to read home sensor: %s\n", - sane_strstatus (status)); - return status; - } - - /* test home sensor */ - if (val & REG41_HOMESNR) - { - DBG (DBG_info, "gl646_park_head: reached home position\n"); - DBG (DBG_proc, "gl646_park_head: finished\n"); - dev->scanhead_position_in_steps = 0; - return SANE_STATUS_GOOD; - } - /* hack around a bug ? */ - if (!(val & REG41_MOTMFLG)) - { - DBG (DBG_info, "gl646_park_head: restarting motor\n"); - status = gl646_start_motor (dev); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_park_head: failed to restart motor: %s\n", - sane_strstatus (status)); - } - } - usleep (100000); - } - } - - /* when we come here then the scanner needed too much time for this, - so we better stop the motor */ - gl646_start_motor (dev); - DBG (DBG_error, - "gl646_park_head: timeout while waiting for scanhead to go home\n"); - return SANE_STATUS_IO_ERROR; + return gl646_slow_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 */ +/** + * 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 + * @return SANE_STATUS_GOOD in cas of success, else failure code + */ static SANE_Status gl646_search_start_position (Genesys_Device * dev) { - int size; SANE_Status status; - uint8_t *data; - uint16_t slope_table0[256]; - Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS + 1]; - int i, steps; - int exposure_time, half_ccd = 0; - struct timeval tv; + unsigned char *data = NULL; + Genesys_Settings settings; + unsigned int resolution, x, y; - int pixels = 600, depth, words; - int dpi = 300; - int start_pixel, end_pixel; + DBG (DBG_proc, "gl646_search_start_position: start\n"); - DBG (DBG_proc, "gl646_search_start_position\n"); - memset (local_reg, 0, sizeof (local_reg)); - memcpy (local_reg, dev->reg, - (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); + /* we scan at 300 dpi */ + resolution = get_closest_resolution (dev->model->ccd_type, 300, SANE_FALSE); - gettimeofday (&tv, NULL); - /* is scanner warm enough ? */ - /* we have 2 options there, either wait, or return SANE_STATUS_DEVICE_BUSY */ - /* we'd rather wait ... */ - if ((dev->model->flags & GENESYS_FLAG_MUST_WAIT) - && (tv.tv_sec - dev->init_date < 60)) - { - DBG (DBG_proc, - "gl646_search_start_position: waiting for scanner to be ready\n"); - usleep (1000 * 1000 * (tv.tv_sec - dev->init_date)); - } - - /* sets for a 200 lines * 600 pixels */ - /* normal scan with no shading */ - local_reg[reg_0x01].value = - (local_reg[reg_0x01]. - value & (REG01_CISSET | REG01_DRAMSEL | REG01_DOGENB)) | - (REG01_SCAN | REG01_DOGENB); - if (dev->model->ccd_type == CCD_HP2300 - || dev->model->ccd_type == CCD_HP2400) - { - local_reg[reg_0x02].value = 0x30; - half_ccd = 0; - } - else - { - local_reg[reg_0x02].value = 0xd0; /* auto-go-home disabled, disable moving when buffer full, auto-go-home after scan disabled, turn on MOTOR power and phase, one table motor moving, motor forward */ - half_ccd = 1; - } - local_reg[reg_0x02].value = - (local_reg[reg_0x02].value | REG02_HALFSTEP) & ~REG02_AGOHOME; - - /* we are doing a monochrome scan */ - local_reg[reg_0x04].value = 0x57; /* color lineart, 16 bits data, frontend type 16 bits, scan color type R, frontend B */ - gl646_setup_sensor (dev, local_reg, 1, half_ccd); - - if (dev->model->ccd_type == CCD_HP2300 - || dev->model->ccd_type == CCD_HP2400) - { - local_reg[reg_0x04].value &= ~(REG04_BITSET | REG04_FILTER); - local_reg[reg_0x04].value |= 0x08; /* green filter */ - local_reg[reg_0x05].value |= REG05_GMMENB; - depth = 8; - steps = 18; - } - else - { - local_reg[reg_0x05].value &= ~REG05_GMMENB; - depth = 16; - /*local_reg[reg_0x1f].value = 0x01; */ - steps = 1; - } - - /* no dummy lines */ - local_reg[reg_0x1e].value &= 0xf0; - if (dev->model->ccd_type == CCD_HP2300 - || dev->model->ccd_type == CCD_HP2400) - local_reg[reg_0x1e].value = 0x40; - - /* step move */ - local_reg[reg_0x3d].value = LOBYTE (HIWORD (steps)); - local_reg[reg_0x3e].value = HIBYTE (LOWORD (steps)); - local_reg[reg_0x3f].value = LOBYTE (LOWORD (steps)); - - /* reset GPO */ - local_reg[reg_0x66].value = dev->gpo.value[0]; - local_reg[reg_0x67].value = dev->gpo.value[1]; - local_reg[reg_0x68].value = dev->gpo.enable[0]; - local_reg[reg_0x69].value = dev->gpo.enable[1]; - - exposure_time = sanei_genesys_exposure_time (dev, local_reg, dpi); - if (dev->model->motor_type == MOTOR_5345) - gl646_setup_steps (dev, local_reg, dpi); - else - { - local_reg[reg_0x21].value = 3; - local_reg[reg_0x22].value = 16; - local_reg[reg_0x23].value = 16; - local_reg[reg_0x24].value = 3; - } - - /* number of scan lines */ - local_reg[reg_0x25].value = LOBYTE (HIWORD (dev->model->search_lines)); - local_reg[reg_0x26].value = HIBYTE (LOWORD (dev->model->search_lines)); - local_reg[reg_0x27].value = LOBYTE (LOWORD (dev->model->search_lines)); - - /* DPISET is at CCD max, word count gives the ratio, and the real dpi */ - local_reg[reg_0x2c].value = HIBYTE (dev->sensor.optical_res); - local_reg[reg_0x2d].value = LOBYTE (dev->sensor.optical_res); - - /* start pixel */ - start_pixel = dev->sensor.dummy_pixel; - if (dev->model->ccd_type == CCD_HP2300) - start_pixel += 64; - local_reg[reg_0x30].value = HIBYTE (start_pixel); - local_reg[reg_0x31].value = LOBYTE (start_pixel); - - - /* end CCD pixel */ - end_pixel = start_pixel + pixels; - local_reg[reg_0x32].value = HIBYTE (end_pixel); - local_reg[reg_0x33].value = LOBYTE (end_pixel); - - words = (pixels * depth) / 8; - local_reg[reg_0x35].value = LOBYTE (HIWORD (words)); - local_reg[reg_0x36].value = HIBYTE (LOWORD (words)); /* */ - local_reg[reg_0x37].value = LOBYTE (LOWORD (words)); /* maximum word size per line=1200 */ - - local_reg[reg_0x38].value = HIBYTE (exposure_time); /* half default period of 11000 */ - local_reg[reg_0x39].value = LOBYTE (exposure_time); /* CCD line period set to 5500 */ - - /* Z1MOD = Z2MOD = 0 */ - local_reg[reg_0x60].value = LOBYTE (0); - local_reg[reg_0x61].value = HIBYTE (0); - local_reg[reg_0x62].value = LOBYTE (0); - local_reg[reg_0x63].value = HIBYTE (0); - - if (dev->model->motor_type != MOTOR_HP2300 - && dev->model->motor_type != MOTOR_HP2400) - local_reg[reg_0x65].value = 0x00; /* PWM duty cycle for table one motor phase (63 = max) */ - else - { - local_reg[reg_0x65].value = 0x3f; - local_reg[reg_0x6a].value = 0x7f; /* table two fast moving step type, PWM duty for table two */ - local_reg[reg_0x6d].value = 0x7f; /* select deceleration steps whenever go home (0), accel/decel stop time (31 * LPeriod) */ - } - - /* send to scanner */ - status = gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_search_start_position: failed to bulk write registers: %s\n", - sane_strstatus (status)); - return status; - } - - /* create local slope tables */ - if (dev->model->motor_type == MOTOR_5345) - sanei_genesys_create_slope_table (dev, - slope_table0, - local_reg[reg_0x21].value, - local_reg[reg_0x02]. - value & REG02_STEPSEL, - exposure_time, 0, dpi, 0); - else - sanei_genesys_create_slope_table (dev, - slope_table0, - local_reg[reg_0x21].value, - local_reg[reg_0x02]. - value & REG02_STEPSEL, - exposure_time, 0, - dev->motor.base_ydpi, 0); - - status = - gl646_send_slope_table (dev, 0, slope_table0, local_reg[reg_0x21].value); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_search_start_position: failed to send slope table 0: %s\n", - sane_strstatus (status)); - return status; - } - - size = words * (dev->model->search_lines + 1); - - data = malloc (size); - if (!data) - { - DBG (DBG_error, - "gl646_search_start_position: failed to allocate memory\n"); - return SANE_STATUS_NO_MEM; - } - - status = gl646_set_fe (dev, AFE_INIT); - if (status != SANE_STATUS_GOOD) - { - free (data); - DBG (DBG_error, - "gl646_search_start_position: failed to set frontend: %s\n", - sane_strstatus (status)); - return status; - } - - status = gl646_begin_scan (dev, local_reg, SANE_TRUE); - if (status != SANE_STATUS_GOOD) - { - free (data); - DBG (DBG_error, - "gl646_search_start_position: failed to begin scan: %s\n", - sane_strstatus (status)); - return status; - } - - /* waits for valid data */ - do - sanei_genesys_test_buffer_empty (dev, &steps); - while (steps); - - /* now we're on target, we can read data */ - status = sanei_genesys_read_data_from_scanner (dev, data, size); - if (status != SANE_STATUS_GOOD) - { - free (data); - DBG (DBG_error, - "gl646_search_start_position: failed to read data: %s\n", - sane_strstatus (status)); - return status; - } - - /* start position search is done on 8 bit data */ - if (depth == 16) + /* fill settings for a gray level scan */ + settings.scan_method = SCAN_METHOD_FLATBED; + settings.scan_mode = SCAN_MODE_GRAY; + settings.xres = resolution; + settings.yres = resolution; + settings.tl_x = 0; + settings.tl_y = 0; + settings.pixels = 600; + settings.lines = dev->model->search_lines; + settings.depth = 8; + settings.color_filter = 0; + + settings.disable_interpolation = 0; + settings.threshold = 0; + settings.exposure_time = 0; + + /* scan the desired area */ + status = simple_scan (dev, settings, SANE_TRUE, &data); + + /* process data if scan is OK */ + if (status == SANE_STATUS_GOOD) { + /* handle stagger case : reorder gray data and thus loose some lines */ + if (dev->current_setup.stagger > 0) + { + DBG (DBG_proc, "gl646_search_start_position: 'un-staggering'\n"); + for (y = 0; y < settings.lines - dev->current_setup.stagger; y++) + { + /* one point out of 2 is 'unaligned' */ + for (x = 0; x < settings.pixels; x += 2) + { + data[y * settings.pixels + x] = + data[(y + dev->current_setup.stagger) * settings.pixels + + x]; + } + } + /* correct line number */ + settings.lines -= dev->current_setup.stagger; + } if (DBG_LEVEL >= DBG_data) - sanei_genesys_write_pnm_file ("search_position16.pnm", data, - depth, 1, pixels, - dev->model->search_lines); - size /= 2; - for (i = 0; i < size; i++) - data[i] = data[i * 2 + 1]; + { + sanei_genesys_write_pnm_file ("search_position.pnm", + data, + settings.depth, + 1, settings.pixels, settings.lines); + } } - - /* x resolution may be the double of y resolution */ - /* after that we have a 300 dpi gray level picture */ - if (dev->sensor.optical_res > 2 * dpi) - { - size /= 2; - for (i = 0; i < size; i++) - data[i] = (data[i * 2] + data[i * 2 + 1]) / 2; - pixels /= 2; - } - - if (DBG_LEVEL >= DBG_data) - sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, - pixels, dev->model->search_lines); - - status = gl646_end_scan (dev, local_reg, SANE_FALSE); - if (status != SANE_STATUS_GOOD) + else { + DBG (DBG_error, "gl646_search_start_position: simple_scan failed\n"); free (data); - DBG (DBG_error, - "gl646_search_start_position: failed to end scan: %s\n", - sane_strstatus (status)); - return status; } - /* update regs to copy ASIC internal state */ - dev->reg[reg_0x01].value = local_reg[reg_0x01].value; - dev->reg[reg_0x02].value = local_reg[reg_0x02].value; - memcpy (dev->reg, local_reg, - (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); - + /* now search reference points on the data */ status = - sanei_genesys_search_reference_point (dev, data, start_pixel, dpi, - pixels, dev->model->search_lines); + sanei_genesys_search_reference_point (dev, data, + dev->sensor.CCD_start_xoffset, + resolution, settings.pixels, + settings.lines); if (status != SANE_STATUS_GOOD) { free (data); @@ -3469,7 +3243,8 @@ gl646_search_start_position (Genesys_Device * dev) } free (data); - return SANE_STATUS_GOOD; + DBG (DBG_proc, "gl646_search_start_position: end\n"); + return status; } /* @@ -3478,1074 +3253,117 @@ gl646_search_start_position (Genesys_Device * dev) static SANE_Status gl646_init_regs_for_coarse_calibration (Genesys_Device * dev) { - SANE_Status status; - uint32_t bytes_per_line; - uint32_t words_per_line; - uint32_t steps_sum; - uint32_t z1, z2; - uint16_t slope_table[256]; - uint16_t strpixel; - uint16_t endpixel; - uint8_t channels; - uint8_t cksel; - DBG (DBG_proc, "gl646_init_regs_for_coarse_calibration\n"); - -/* ST12: - 0x01 0x00 0x02 0x71 0x03 0x1f 0x04 0x57 0x05 0x10 0x06 0x18 0x08 0x02 0x09 0x00 - 0x0a 0x06 0x0b 0x04 - 0x10 0x00 0x11 0x00 0x12 0x00 0x13 0x00 0x14 0x00 0x15 0x00 0x16 0x2b 0x17 0x08 0x18 0x20 0x19 0x2a - 0x1c 0xc0 0x1d 0x03 */ - - /* shading off, compression off */ - dev->calib_reg[reg_0x01].value = REG01_SCAN; - /* disable forward/backward+autogohome+fastfed+motor */ - dev->calib_reg[reg_0x02].value = - (dev->calib_reg[reg_0x02]. - value & ~REG02_MTRPWR & ~REG02_AGOHOME & ~REG02_FASTFED & - ~REG02_STEPSEL) | REG02_ACDCDIS; - if (dev->model->motor_type == MOTOR_5345) - dev->calib_reg[reg_0x02].value |= REG02_QUATERSTEP; - - /* disable lineart, enable 16bit */ - dev->calib_reg[reg_0x04].value = - (dev->calib_reg[reg_0x04].value & ~REG04_LINEART) | REG04_BITSET; - dev->calib_reg[reg_0x05].value = (dev->calib_reg[reg_0x05].value & ~REG05_GMMENB); /* disable gamma */ - -/* ST12: - 0x21 0x20 0x22 0x10 0x23 0x10 0x24 0x20 0x25 0x00 0x26 0x00 0x27 0x64 - 0x32 0x02 0x33 0x66 0x35 0x00 0x36 0x04 0x37 0xb0 0x38 0x27 0x39 0x10 - 0x52 0x0f 0x53 0x13 0x54 0x17 0x55 0x03 0x56 0x07 0x57 0x0b 0x58 0x83 - 0x65 0x3f 0x6b 0xff */ - - dev->calib_reg[reg_0x21].value = 0x20 /*0x01 */ ; - dev->calib_reg[reg_0x22].value = 0x10 /*0x00 */ ; - dev->calib_reg[reg_0x23].value = 0x10 /*0x01 */ ; - dev->calib_reg[reg_0x24].value = 0x20 /*0x00 */ ; - dev->calib_reg[reg_0x25].value = 0x00; - dev->calib_reg[reg_0x26].value = 0x00; - dev->calib_reg[reg_0x27].value = 0x64 /*0x01 */ ; - dev->calib_reg[reg_0x3d].value = 0x00; - dev->calib_reg[reg_0x3e].value = 0x00; - dev->calib_reg[reg_0x3f].value = 0x00; - /* dev->calib_reg[reg_0x6b].value = 0xff; done in init *//*0x01 */ - - cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */ - - /* start position */ - strpixel = dev->sensor.dummy_pixel; - dev->calib_reg[reg_0x30].value = HIBYTE (strpixel); - dev->calib_reg[reg_0x31].value = LOBYTE (strpixel); - - /* set right position todo: optical resolution, not real x resolution? */ - endpixel = strpixel + (dev->sensor.optical_res / cksel); - - dev->calib_reg[reg_0x32].value = HIBYTE (endpixel); - dev->calib_reg[reg_0x33].value = LOBYTE (endpixel); - DBG (DBG_info, - "gl646_init_register_for_coarse_calibration: left pos: %d CCD pixels, right pos: %d CCD pixels\n", - strpixel, endpixel); - - /* set dummy pixels */ - /* todo: dummy pixels + tgw + 2* tgs according spec? */ - dev->calib_reg[reg_0x34].value = dev->sensor.dummy_pixel; - DBG (DBG_info, - "gl646_init_register_for_coarse_calibration: dummy pixels: %d CCD pixels\n", - dev->sensor.dummy_pixel); - - DBG (DBG_info, - "gl646_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n", - dev->sensor.optical_res / cksel, dev->settings.xres); - - /* set line size */ - if (dev->settings.scan_mode == 4) /* single pass color */ - channels = 3; - else - channels = 1; - - bytes_per_line = channels * 2 * (endpixel - strpixel); - - words_per_line = (bytes_per_line + 1) / 2 + 1; - - dev->calib_reg[reg_0x35].value = LOBYTE (HIWORD (words_per_line)); - dev->calib_reg[reg_0x36].value = HIBYTE (LOWORD (words_per_line)); - dev->calib_reg[reg_0x37].value = LOBYTE (LOWORD (words_per_line)); - - DBG (DBG_info, - "gl646_init_register_for_coarse_calibration: bytes_per_line=%d, words_per_line=%d\n", - bytes_per_line, words_per_line); - - /* TODO: only 2 steps? */ - - steps_sum = sanei_genesys_create_slope_table (dev, slope_table, dev->calib_reg[reg_0x21].value, dev->calib_reg[reg_0x02].value & REG02_STEPSEL, dev->settings.exposure_time, 0, dev->motor.base_ydpi, /*MOTOR_GEAR */ - 0); - - /* TODO: z1 = z2 = 0? */ - sanei_genesys_calculate_zmode (dev, - dev->settings.exposure_time, - steps_sum, - slope_table[dev->calib_reg[reg_0x21]. - value - 1], - dev->calib_reg[reg_0x3d].value * - 65536 + - dev->calib_reg[reg_0x3e].value * 256 + - dev->calib_reg[reg_0x3f].value, - dev->calib_reg[reg_0x02]. - value & REG02_FASTFED, - dev->calib_reg[reg_0x1f].value, - dev->calib_reg[reg_0x22].value, - (dev->calib_reg[reg_0x6c]. - value & REG6C_TGTIME) >> 6, &z1, &z2); - DBG (DBG_info, - "gl646_init_register_for_coarse_calibration: z1 = %d\n", z1); - DBG (DBG_info, - "gl646_init_register_for_coarse_calibration: z2 = %d\n", z2); - dev->calib_reg[reg_0x60].value = HIBYTE (z1); - dev->calib_reg[reg_0x61].value = LOBYTE (z1); - dev->calib_reg[reg_0x62].value = HIBYTE (z2); - dev->calib_reg[reg_0x63].value = LOBYTE (z2); - dev->calib_reg[reg_0x6c].value = (dev->calib_reg[reg_0x6c].value & REG6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16) & 0x07); /* todo: double check */ - - status = - gl646_send_slope_table (dev, 0, slope_table, - dev->calib_reg[reg_0x21].value); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_init_register_for_coarse_calibration: Failed to send slope table: %s\n", - sane_strstatus (status)); - return status; - } - - status = - gl646_bulk_write_register (dev, dev->calib_reg, GENESYS_GL646_MAX_REGS); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_init_register_for_coarse_calibration: Failed to bulk write registers: %s\n", - sane_strstatus (status)); - return status; - } - - DBG (DBG_proc, "gl646_init_register_for_coarse_calibration: completed\n"); + DBG (DBG_proc, "gl646_init_register_for_coarse_calibration: end\n"); return SANE_STATUS_GOOD; } -/* init registers for shading calibration */ +/** + * 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 eihter at full sensor's resolution or half depending upon half_ccd + * @param dev scanner's device + * @return SANE_STATUS_GOOD if success, else error code + */ static SANE_Status gl646_init_regs_for_shading (Genesys_Device * dev) { - SANE_Status status; - uint32_t bytes_per_line; - uint32_t num_pixels; - uint32_t steps_sum; - int move = 0; - int exposure_time; - uint32_t z1, z2; - uint16_t slope_table[256]; - uint16_t steps; - uint8_t step_parts; - uint8_t channels; - uint8_t dummy_lines = 3; - int dpiset; - SANE_Bool half_ccd; - int workaround; + SANE_Status status = SANE_STATUS_GOOD; + Genesys_Settings settings; + /* 1: no half_ccd, 2: use half number of pixels */ + int half_ccd = 1; - DBG (DBG_proc, "gl646_init_register_for_shading: lines = %d\n", - dev->model->shading_lines); + DBG (DBG_proc, "gl646_init_register_for_shading: start\n"); - if (dev->settings.scan_mode == 4) /* single pass color */ - channels = 3; - else - channels = 1; - - /* monochrome / color scan */ - dev->calib_reg[reg_0x04].value &= ~REG04_FILTER; - if (channels == 1) + /* when shading all line, we must adapt to half_ccd case */ + if ((dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE) + && (dev->settings.xres <= dev->sensor.optical_res / 2)) { - switch (dev->settings.color_filter) - { - /* red */ - case 0: - dev->calib_reg[reg_0x04].value |= 0x04; - break; - /* green */ - case 1: - dev->calib_reg[reg_0x04].value |= 0x08; - break; - /* blue */ - case 2: - dev->calib_reg[reg_0x04].value |= 0x0c; - break; - default: - return SANE_STATUS_INVAL; - } + /* we are going to use half the pixel number */ + half_ccd = 2; } - /* disable forward/backward+motor, stepsel = 1 */ - dev->calib_reg[reg_0x02].value = - (dev->calib_reg[reg_0x02]. - value & ~REG02_MTRPWR & ~REG02_STEPSEL & ~REG02_AGOHOME) | - REG02_ACDCDIS | 0x01; + /* fill settings for scan */ + settings.scan_method = SCAN_METHOD_FLATBED; + settings.scan_mode = dev->settings.scan_mode; + settings.xres = dev->sensor.optical_res / half_ccd; + settings.yres = dev->sensor.optical_res / half_ccd; + settings.tl_x = 0; + settings.tl_y = 0; + settings.pixels = dev->sensor.sensor_pixels / half_ccd; + settings.lines = dev->model->shading_lines; + settings.depth = 16; + settings.color_filter = dev->settings.color_filter; - /* dpi=600 for scan at 600 dpi and below, and dpi=1200 when above */ - dpiset = dev->sensor.optical_res; + settings.disable_interpolation = dev->settings.disable_interpolation; + settings.threshold = dev->settings.threshold; + settings.exposure_time = dev->settings.exposure_time; - if (dev->settings.xres <= dev->sensor.optical_res / 2) - { - num_pixels = dev->sensor.sensor_pixels / 2; - half_ccd = 1; - } - else - { - num_pixels = dev->sensor.sensor_pixels; - half_ccd = 0; - } - if (dev->model->motor_type == MOTOR_HP2400) - { - exposure_time = - sanei_genesys_exposure_time2 (dev, dev->settings.yres, - 1, - num_pixels + - dev->sensor.dummy_pixel, 0, 0); - } - else - { - exposure_time = - sanei_genesys_exposure_time (dev, dev->calib_reg, dev->settings.yres); - } - DBG (DBG_info, - "gl646_init_regs_for_shading: half_ccd = %d, yres = %d\n", - half_ccd, dev->settings.yres); + /* we don't want top offset, but we need right margin to be the same + * than the one for the final scan */ + status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); - if (dev->model->motor_type == MOTOR_5345) - { - dev->calib_reg[reg_0x02].value = - REG02_ACDCDIS | REG02_MTRPWR | REG02_QUATERSTEP; - dev->calib_reg[reg_0x03].value |= REG03_AVEENB; - dev->calib_reg[reg_0x04].value |= REG04_BITSET; - dev->calib_reg[reg_0x05].value &= ~REG05_GMMENB; - } + /* no shading */ + dev->reg[reg_0x01].value &= ~REG01_DVDSET; + dev->reg[reg_0x02].value |= REG02_ACDCDIS; /* ease backtracking */ + dev->reg[reg_0x02].value &= ~(REG02_FASTFED | REG02_AGOHOME); - /* full, half or quarter step, 0x11 is reserved! (--> 1 << 1 = 0x02) */ - step_parts = (1 << (dev->calib_reg[reg_0x02].value & REG02_STEPSEL)); - steps = step_parts * 0x40; /* base = 64 lines --> 0x80 */ - if (steps > 255) - steps = 255; + /* TODO another flag to setup regs ? */ + /* enforce needed LINCNT, getting rid of extra lines for color reordering */ + gl646_set_triple_reg (dev->reg, REG_LINCNT, dev->model->shading_lines); - if (dev->model->motor_type == MOTOR_5345) - gl646_setup_steps (dev, dev->calib_reg, dpiset); - else if (dev->model->motor_type == MOTOR_HP2300 - || dev->model->motor_type == MOTOR_HP2400) - { - dev->calib_reg[reg_0x21].value = 2; - dev->calib_reg[reg_0x22].value = 16; - } - else - { - dev->calib_reg[reg_0x21].value = (uint8_t) steps; - steps = 2 * step_parts; - if (steps > 255) - steps = 255; + /* copy reg to calib_reg */ + memcpy (dev->calib_reg, dev->reg, + GENESYS_GL646_MAX_REGS * sizeof (Genesys_Register_Set)); - dev->calib_reg[reg_0x22].value = (uint8_t) steps; - } - dev->calib_reg[reg_0x23].value = dev->calib_reg[reg_0x22].value; - dev->calib_reg[reg_0x24].value = dev->calib_reg[reg_0x21].value; - - - steps = dev->model->y_offset * step_parts; - if (dev->model->motor_type == MOTOR_5345) - steps = 0; - else if (dev->model->motor_type == MOTOR_HP2300 - || dev->model->motor_type == MOTOR_HP2400) - steps = 1; - else - dev->calib_reg[reg_0x6b].value = 0x20 * step_parts; - - bytes_per_line = - (channels * 2 * num_pixels * dpiset) / dev->sensor.optical_res; - - dev->calib_reg[reg_0x25].value = - LOBYTE (HIWORD (dev->model->shading_lines)); - dev->calib_reg[reg_0x26].value = - HIBYTE (LOWORD (dev->model->shading_lines)); - dev->calib_reg[reg_0x27].value = - LOBYTE (LOWORD (dev->model->shading_lines)); - - dev->calib_reg[reg_0x2c].value = HIBYTE (dpiset); - dev->calib_reg[reg_0x2d].value = LOBYTE (dpiset); - - dev->calib_reg[reg_0x30].value = HIBYTE (dev->sensor.dummy_pixel); - dev->calib_reg[reg_0x31].value = LOBYTE (dev->sensor.dummy_pixel); - dev->calib_reg[reg_0x32].value = - HIBYTE (dev->sensor.dummy_pixel + num_pixels); - dev->calib_reg[reg_0x33].value = - LOBYTE (dev->sensor.dummy_pixel + num_pixels); - - dev->calib_reg[reg_0x35].value = LOBYTE (HIWORD (bytes_per_line)); - dev->calib_reg[reg_0x36].value = HIBYTE (LOWORD (bytes_per_line)); - dev->calib_reg[reg_0x37].value = LOBYTE (LOWORD (bytes_per_line)); - - dev->calib_reg[reg_0x38].value = HIBYTE (exposure_time); - dev->calib_reg[reg_0x39].value = LOBYTE (exposure_time); - - dev->calib_reg[reg_0x3d].value = LOBYTE (HIWORD (steps)); - dev->calib_reg[reg_0x3e].value = HIBYTE (LOWORD (steps)); - dev->calib_reg[reg_0x3f].value = LOBYTE (LOWORD (steps)); - - gl646_setup_sensor (dev, dev->calib_reg, 1, half_ccd); - - z1 = 0; - z2 = 0; - if (dev->model->motor_type != MOTOR_5345) - { - dpiset /= (1 + half_ccd); - steps_sum = sanei_genesys_create_slope_table (dev, - slope_table, - dev-> - calib_reg[reg_0x21]. - value, - dev-> - calib_reg[reg_0x02]. - value & - REG02_STEPSEL, - sanei_genesys_exposure_time - (dev, dev->reg, - dpiset), 0, dpiset, 0); - move = (dev->model->shading_lines * dev->motor.base_ydpi) / dpiset; - DBG (DBG_info, - "gl646_init_regs_for_shading: computed move = %d, dpiset = %d\n", - move, dpiset); - /* TODO: sort this out, there's an offset somewhere ... */ - /* I really don't get what's going on here ... */ - /* Or move computing is wrong when doing reg init for final scan */ - if (dev->settings.yres == 300) - move = 115; - else if (dev->settings.yres == 150) - move = 0; - else if (dev->settings.yres == 75) - move = 60; - DBG (DBG_info, - "gl646_init_regs_for_shading: overrided move = %d, yres = %d\n", - move, dev->settings.yres); - } - else - { - dev->calib_reg[reg_0x21].value = 1; - dev->calib_reg[reg_0x6b].value = 255; - - /* seems to be 2 if dpi <= 150, but is it useful ? */ - if (dev->settings.yres <= 150) - dev->calib_reg[reg_0x65].value = 2; - else - dev->calib_reg[reg_0x65].value = 0; - - /* specific slope-table for shading */ - /* it appears win200 and winMe aren't using the same speeds */ - /* consumer / pro settings ? */ - /* this is currently real magic to me */ - /* todo: find out the real rule */ - /* quarter steps for every resolution */ - if (dev->settings.yres <= 150) /* 11000 exposure time */ - { - slope_table[0] = 3471; - dummy_lines = 2; - workaround = -390; - } - else if (dev->settings.yres <= 300) /* 5500 exposure time */ - { - slope_table[0] = 4400; - dummy_lines = 7; - workaround = -260; - } - else if (dev->settings.yres <= 600) /* 11000 exposure time */ - { - slope_table[0] = 4400; - if (channels > 1) - dummy_lines = 3; - else - dummy_lines = 1; - workaround = -600; - } - else if (dev->settings.yres <= 800) /* 11000 exposure time */ - { - slope_table[0] = 9258; - dummy_lines = 7; - workaround = -600; - } - else - { - slope_table[0] = 8378; - dummy_lines = 7; - workaround = -600; - } - - /* computes motor steps done during shading calibration - dpi = slope_table[0] * dev->motor.base_ydpi * step_parts / (exposure_time * (1+dummy_lines)); - move = (lines / dpi) * dev->motor.optical_ydpi */ - move = - (dev->model->shading_lines * exposure_time * (1 + dummy_lines) * - 2) / (step_parts * slope_table[0]); - - /* todo: find a way to remove this workaround */ - move -= (dev->model->shading_lines * workaround) / 32; - - /* rest of table */ - for (steps = 1; steps < 255; steps++) - slope_table[steps] = slope_table[0]; - - /* set all available bits */ - if (dev->model->motor_type == MOTOR_5345) - { - dev->calib_reg[reg_0x66].value = dev->gpo.value[0]; - dev->calib_reg[reg_0x67].value = dev->gpo.value[1]; - } - } - - DBG (DBG_info, "gl646_init_regs_for_shading: move = %d\n", move); - dev->calib_reg[reg_0x60].value = HIBYTE (z1); - dev->calib_reg[reg_0x61].value = LOBYTE (z1); - dev->calib_reg[reg_0x62].value = HIBYTE (z2); - dev->calib_reg[reg_0x63].value = LOBYTE (z2); - - /* linesel = 3 */ - dev->calib_reg[reg_0x1e].value = - (dev->calib_reg[reg_0x1e].value & ~REG1E_LINESEL) | dummy_lines; - - /* dark calibration move : motor if off ..., so we don't move */ - /* if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) - dev->scanhead_position_in_steps += move; */ - - /* white shading */ - dev->scanhead_position_in_steps += move; - - status = - gl646_send_slope_table (dev, 0, slope_table, - dev->calib_reg[reg_0x21].value); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_init_regs_for_shading: Failed to send slope table: %s\n", - sane_strstatus (status)); - return status; - } - - status = - gl646_bulk_write_register (dev, dev->calib_reg, GENESYS_GL646_MAX_REGS); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_init_regs_for_shading: Failed to bulk write registers: %s\n", - sane_strstatus (status)); - return status; - } - - status = gl646_set_fe (dev, AFE_SET); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_init_regs_for_shading: Failed to set frontend: %s\n", - sane_strstatus (status)); - return status; - } - - DBG (DBG_proc, "gl646_init_register_for_shading: completed\n"); - - return SANE_STATUS_GOOD; + DBG (DBG_proc, "gl646_init_register_for_shading: end\n"); + return status; } -/* set up registers for the actual scan - * to be removed when the new setup method will be mature - */ -static SANE_Status -gl646_init_regs_for_scan_old (Genesys_Device * dev) -{ - SANE_Bool same_speed = 0; - int dpiset; - int start, end, pixels; - int channels; - int words_per_line; - int move, lincnt; - int exposure_time; - int i, depth; - int slope_dpi = 0; - int move_dpi = 0; - int fast_dpi = 0; - int fast_exposure = 0; - int dummy; - uint32_t steps_sum, z1, z2; - SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ - SANE_Status status; - unsigned int stagger; - unsigned int max_shift; - float read_factor; - size_t requested_buffer_size; - size_t read_buffer_size; - DBG (DBG_info, - "gl646_init_regs_for_scan_old settings:\nResolution: %ux%uDPI\n" - "Lines : %u\nPPL : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", - dev->settings.xres, dev->settings.yres, dev->settings.lines, - dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, - dev->settings.scan_mode); - - /* we have 2 domains for ccd: yres below or above half ccd max dpi */ - /* for some reason, windows sets DPISET to twice the needed value, - we're doing the same for now, but maybe we could avoid this, which - would avoid cropping data in reads */ - half_ccd = SANE_TRUE; - dpiset = dev->sensor.optical_res; - i = dev->sensor.optical_res / dev->settings.xres; - if (i <= 1) - half_ccd = SANE_FALSE; - if (i <= 3) - dpiset = dev->sensor.optical_res; - else if (i <= 5) - dpiset = dev->sensor.optical_res / 2; - else if (i <= 7) - dpiset = dev->sensor.optical_res / 3; - else if (i <= 11) - dpiset = dev->sensor.optical_res / 4; - else if (i <= 15) - dpiset = dev->sensor.optical_res / 6; - else if (i <= 23) - dpiset = dev->sensor.optical_res / 8; - else if (i <= 24) - dpiset = dev->sensor.optical_res / 12; - DBG (DBG_info, - "gl646_init_regs_for_scan_old : i=%d, dpiset=%d, half_ccd=%d\n", - i, dpiset, half_ccd); - - /* sigh ... MD6471 motor's provide vertically shifted columns at hi res ... */ - if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) - stagger = (4 * dev->settings.yres) / dev->motor.base_ydpi; - else - stagger = 0; - DBG (DBG_info, "gl646_init_regs_for_scan_old : stagger=%d lines\n", - stagger); - - /* compute scan parameters values */ - /* pixels are allways given at half or full CCD optical resolution */ - /* use detected left margin and fixed value */ - start = - dev->sensor.CCD_start_xoffset + - (SANE_UNFIX (dev->model->x_offset) * dev->sensor.optical_res) / - MM_PER_INCH; - - /* add x coordinates */ - start += (dev->settings.tl_x * dev->sensor.optical_res) / MM_PER_INCH; - if (half_ccd) - start = start / 2; - if (stagger > 0) - start = start | 1; - - /* compute correct pixels number */ - read_factor = 0.0; - pixels = - (dev->settings.pixels * dev->sensor.optical_res) / dev->settings.xres; - if (half_ccd) - pixels = pixels / 2; - - /* round up pixels number if needed */ - if (dpiset != 2 * dev->settings.xres - && dev->settings.xres < dev->sensor.optical_res) - { - i = dev->sensor.optical_res / dpiset; - pixels = ((pixels + i - 1) / i) * i; - /* sets flag for reading */ - /* the 2 factor is due to the fact that dpiset = 2 desired ccd dpi */ - read_factor = (float) pixels / (float) (dev->settings.pixels * 2); - DBG (DBG_info, - "gl646_init_regs_for_scan_old : rounding up pixels, factor=%f\n", - read_factor); - } - - end = start + pixels; - - /* set line size */ - if (dev->settings.scan_mode == 4) /* single pass color */ - channels = 3; - else - channels = 1; - - /* scanned area must be enlarged by max color shift needed */ - /* all values are assumed >= 0 */ - if (channels > 1) - { - max_shift = dev->model->ld_shift_r; - if ((unsigned int) dev->model->ld_shift_b > max_shift) - max_shift = dev->model->ld_shift_b; - if ((unsigned int) dev->model->ld_shift_g > max_shift) - max_shift = dev->model->ld_shift_g; - max_shift = (max_shift * dev->settings.yres) / dev->motor.base_ydpi; - } - else - { - max_shift = 0; - } - - /* enable shading */ - dev->reg[reg_0x01].value |= REG01_DVDSET; - dev->reg[reg_0x01].value &= ~REG01_FASTMOD; - - dev->reg[reg_0x02].value = REG02_NOTHOME | REG02_MTRPWR; - - /* if dpi is low enough, we don't need to use 2 tables moving */ - if (dev->settings.yres > dev->sensor.optical_res / 4) - dev->reg[reg_0x02].value |= REG02_FASTFED; - - /* motor speed */ - dev->reg[reg_0x02].value &= ~REG02_STEPSEL; - if (dev->model->motor_type == MOTOR_5345 - || dev->model->motor_type == MOTOR_HP2400) - { - if (half_ccd) - dev->reg[reg_0x02].value |= REG02_HALFSTEP; - else - dev->reg[reg_0x02].value |= REG02_QUATERSTEP; - } - else - dev->reg[reg_0x02].value |= REG02_FULLSTEP; - - /* monochrome / color scan */ - dev->reg[reg_0x04].value &= ~(REG04_FILTER | REG04_BITSET); - - /* select color filter based on settings */ - if (channels == 1) - { - switch (dev->settings.color_filter) - { - /* red */ - case 0: - dev->reg[reg_0x04].value |= 0x04; - break; - /* green */ - case 1: - dev->reg[reg_0x04].value |= 0x08; - break; - /* blue */ - case 2: - dev->reg[reg_0x04].value |= 0x0c; - break; - default: - return SANE_STATUS_INVAL; - } - } - - /* bit depth: 8bit + gamma, 16 bits + no gamma */ - if (dev->settings.scan_mode == 0) - { - /* lineart, TODO : find logs of real lineart, not an emulated one - with gray level scanning, since can't make it work on doc basis */ - depth = 8; - dev->reg[reg_0x04].value &= ~REG04_LINEART; - } - else - { - if (dev->settings.depth > 8) - { - depth = 16; - dev->reg[reg_0x04].value |= REG04_BITSET; - } - else - depth = 8; - dev->reg[reg_0x04].value &= ~REG04_LINEART; - } - - /* it is useles to scan at 16 bit if gamma table is at 12 or 14 bits - so we disable hardware gamma correction when doing 16 bits scans */ - if (dev->settings.depth < 16) - dev->reg[reg_0x05].value |= REG05_GMMENB; - else - dev->reg[reg_0x05].value &= ~REG05_GMMENB; - - /* sensor parameters */ - gl646_setup_sensor (dev, dev->reg, 1, half_ccd); - - /* 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 - slower (higher dpi) */ - dev->reg[reg_0x1e].value = dev->reg[reg_0x1e].value & 0xf0; /* 0 dummy lines */ - dummy = 0; - if (dev->model->ccd_type == CCD_5345) - { - if (dpiset >= dev->sensor.optical_res / 3 - && dpiset <= dev->sensor.optical_res / 2) - dummy = 1; - if (dev->settings.yres == 800) - dummy = 3; - } - dev->reg[reg_0x1e].value = dev->reg[reg_0x1e].value | dummy; /* dummy lines */ - - switch (dev->model->motor_type) - { - case MOTOR_5345: - gl646_setup_steps (dev, dev->reg, dev->settings.yres); - fast_dpi = 200; - fast_exposure = 3600; - slope_dpi = dev->settings.yres; - - /* we use same_speed until below a threshold */ - if (slope_dpi < dev->motor.base_ydpi / 2) - same_speed = 0; - else - same_speed = 1; - break; - - case MOTOR_HP2400: - case MOTOR_HP2300: - gl646_setup_steps (dev, dev->reg, dev->settings.yres); - fast_dpi = dev->motor.base_ydpi / 4; - fast_exposure = 2700; - slope_dpi = dev->settings.yres; - same_speed = 0; - break; - } - if (slope_dpi == 75 && dev->model->motor_type == MOTOR_5345) /* todo: do not hard code this one */ - slope_dpi = 100; - slope_dpi = slope_dpi * (1 + dummy); - - lincnt = dev->settings.lines - 1 + max_shift + stagger; - - dev->reg[reg_0x25].value = LOBYTE (HIWORD (lincnt)); /* scan line numbers - here one line */ - dev->reg[reg_0x26].value = HIBYTE (LOWORD (lincnt)); - dev->reg[reg_0x27].value = LOBYTE (LOWORD (lincnt)); - - if ((dev->model->ccd_type == CCD_5345) && (channels == 1) && (!half_ccd)) - { - dev->reg[reg_0x28].value = HIBYTE (250); - dev->reg[reg_0x29].value = LOBYTE (250); - } - else - { - dev->reg[reg_0x28].value = HIBYTE (511); - dev->reg[reg_0x29].value = LOBYTE (511); - } - - - dev->reg[reg_0x2c].value = HIBYTE (dpiset); - dev->reg[reg_0x2d].value = LOBYTE (dpiset); - - dev->reg[reg_0x30].value = HIBYTE (start); - dev->reg[reg_0x31].value = LOBYTE (start); - dev->reg[reg_0x32].value = HIBYTE (end); - dev->reg[reg_0x33].value = LOBYTE (end); - - if (half_ccd) - words_per_line = (dpiset * pixels * channels) / dev->sensor.optical_res; - else - words_per_line = pixels * channels; - words_per_line = (words_per_line * depth) / 8; - - dev->reg[reg_0x35].value = LOBYTE (HIWORD (words_per_line)); - dev->reg[reg_0x36].value = HIBYTE (LOWORD (words_per_line)); - dev->reg[reg_0x37].value = LOBYTE (LOWORD (words_per_line)); - - exposure_time = - sanei_genesys_exposure_time (dev, dev->reg, dev->settings.xres); - DBG (DBG_proc, "gl646_init_regs_for_scan_old exposure=%d\n", exposure_time); - - dev->reg[reg_0x38].value = HIBYTE (exposure_time); - dev->reg[reg_0x39].value = LOBYTE (exposure_time); - - /* build slope table for choosen dpi */ - steps_sum = sanei_genesys_create_slope_table (dev, - dev->slope_table0, - dev->reg[reg_0x21]. - value, - dev->reg[reg_0x02]. - value & REG02_STEPSEL, - exposure_time, - same_speed, slope_dpi, 0); - - /* build slope1 (fast moving) */ - sanei_genesys_create_slope_table (dev, - dev->slope_table1, - dev->reg[reg_0x6b].value, - (dev->reg[reg_0x6a]. - value & REG6A_FSTPSEL) >> 6, - fast_exposure, 0, fast_dpi, 0); - - /* 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 - - TODO: substract steps done during motor acceleration or - will it be included in y_offset ? - - assumption: steps are expressed at maximum motor resolution - - we need: - SANE_Fixed y_offset; - SANE_Fixed y_size; - SANE_Fixed 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 */ - switch (dev->model->motor_type) - { - case MOTOR_5345: - move_dpi = dev->motor.optical_ydpi; - break; - default: - move_dpi = dev->motor.base_ydpi; - break; - } - if (dev->model->flags & GENESYS_FLAG_SEARCH_START) - move = (SANE_UNFIX (dev->model->y_offset_calib) * move_dpi) / MM_PER_INCH; - else - move = 0; - DBG (DBG_info, "gl646_init_regs_for_scan_old: move=%d steps\n", move); - - move += (SANE_UNFIX (dev->model->y_offset) * move_dpi) / MM_PER_INCH; - - /* the right fix involves computing distance for acceleration, do it - * this crudly for now, it might also come from the way slopes table - * are generated, we may consider switching to the newer and more - * accurate method */ - DBG (DBG_info, - "gl646_init_regs_for_scan_old: move=%d steps/yres=%d\n", move, - dev->settings.yres); - if (dev->model->motor_type == MOTOR_5345) - { - switch (dev->settings.yres) - { - case 2400: - move += 50; - break; - case 1200: - move += 100; - break; - case 600: - move -= 150; - break; - case 500: - move -= 150; - break; - case 400: - move -= 100; - break; - case 300: - case 250: - case 200: - break; - case 150: - move += 100; - break; - case 100: - move += 120; - break; - case 50: - move += 100; - break; - default: - break; - } - } - - /* add tl_y to base movement */ - /* move += (dev->settings.tl_y * dev->motor.optical_ydpi) / MM_PER_INCH; */ - move += (dev->settings.tl_y * move_dpi) / MM_PER_INCH; - DBG (DBG_info, "gl646_init_regs_for_scan_old: move=%d steps\n", move); - - /* substract current head position */ - move -= dev->scanhead_position_in_steps - stagger; - DBG (DBG_info, "gl646_init_regs_for_scan_old: move=%d steps\n", move); - - if ((dev->reg[reg_0x02].value & REG02_FASTFED) - && (dev->model->motor_type == MOTOR_HP2300)) - { - move *= 2; - DBG (DBG_info, "gl646_init_regs_for_scan_old: move=%d steps\n", move); - } - - /* round it */ - move = ((move + dummy) / (dummy + 1)) * (dummy + 1); - DBG (DBG_info, "gl646_init_regs_for_scan_old: move=%d steps\n", move); - - /* security check */ - if (move < 0) - { - DBG (DBG_error, - "gl646_init_regs_for_scan_old: overriding negative move value %d\n", - move); - move = 1; - } - DBG (DBG_info, "gl646_init_regs_for_scan_old: move=%d steps\n", move); - - /* set feed steps number of motor move */ - dev->reg[reg_0x3d].value = LOBYTE (HIWORD (move)); - dev->reg[reg_0x3e].value = HIBYTE (LOWORD (move)); - dev->reg[reg_0x3f].value = LOBYTE (LOWORD (move)); - - sanei_genesys_calculate_zmode2 (dev->reg[reg_0x02]. - value & REG02_FASTFED, exposure_time, - dev->slope_table0, - dev->reg[reg_0x21].value, move, - dev->reg[reg_0x22].value, &z1, &z2); - DBG (DBG_info, "gl646_init_regs_for_scan_old: z1 = %d\n", z1); - DBG (DBG_info, "gl646_init_regs_for_scan_old: z2 = %d\n", z2); - dev->reg[reg_0x60].value = HIBYTE (z1); - dev->reg[reg_0x61].value = LOBYTE (z1); - dev->reg[reg_0x62].value = HIBYTE (z2); - dev->reg[reg_0x63].value = LOBYTE (z2); - dev->reg[reg_0x6c].value = (dev->reg[reg_0x6c].value & REG6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16) & 0x07); /* todo: double check */ - - /* todo: is it really that useful ? */ - if (dev->model->motor_type == MOTOR_5345) - { - if (dev->settings.yres > 150) - dev->reg[reg_0x65].value = 0; - else - dev->reg[reg_0x65].value = 2; - } - else - dev->reg[reg_0x65].value = 0x3f; - dev->reg[reg_0x67].value = dev->gpo.value[1]; - - /* prepares data reordering */ - - /* we must use a round number of words_per_line */ - requested_buffer_size = - (GL646_BULKIN_MAXSIZE / words_per_line) * words_per_line; - - read_buffer_size = - 2 * requested_buffer_size + - ((max_shift + stagger) * pixels * channels * depth) / 8; - - RIE (sanei_genesys_buffer_free (&(dev->read_buffer))); - RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size)); - - RIE (sanei_genesys_buffer_free (&(dev->lines_buffer))); - RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size)); - - RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer))); - RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer), - requested_buffer_size)); - - RIE (sanei_genesys_buffer_free (&(dev->out_buffer))); - RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer), - (8 * dev->settings.pixels * - channels * depth) / 8)); - - /* scan bytes to read */ - dev->read_bytes_left = words_per_line * (lincnt + 1); - - - DBG (DBG_info, - "gl646_init_regs_for_scan_old: physical bytes to read = %lu\n", - (u_long) dev->read_bytes_left); - dev->read_active = SANE_TRUE; - - - dev->current_setup.pixels = (pixels * dpiset) / dev->sensor.optical_res; - dev->current_setup.lines = lincnt + 1; - dev->current_setup.depth = depth; - dev->current_setup.channels = channels; - dev->current_setup.exposure_time = exposure_time; - if (half_ccd) - dev->current_setup.xres = dpiset / 2; - else - dev->current_setup.xres = dpiset; - dev->current_setup.yres = dev->settings.yres; - dev->current_setup.half_ccd = half_ccd; - dev->current_setup.stagger = stagger; - dev->current_setup.max_shift = max_shift + stagger; - - -/* TODO: should this be done elsewhere? */ - /* scan bytes to send to the frontend */ - /* theory : - target_size = - (dev->settings.pixels * dev->settings.lines * channels * depth) / 8; - but it suffers from integer overflow so we do the following: - - 1 bit color images store color data byte-wise, eg byte 0 contains - 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains - 8 bits of blue. - This does not fix the overflow, though. - 644mp*16 = 10gp, leading to an overflow - -- pierre - */ - - dev->total_bytes_read = 0; - if (depth == 1 || dev->settings.scan_mode == 0) - dev->total_bytes_to_read = - ((dev->settings.pixels * dev->settings.lines) / 8 + - (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) * - channels; - else - dev->total_bytes_to_read = - dev->settings.pixels * dev->settings.lines * channels * (depth / 8); - - DBG (DBG_info, - "gl646_init_regs_for_scan_old: total bytes to send to frontend = %lu\n", - (u_long) dev->total_bytes_to_read); -/* END TODO */ - - - - - status = - gl646_send_slope_table (dev, 0, dev->slope_table0, - sanei_genesys_read_reg_from_set (dev->reg, 0x21)); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_init_regs_for_scan_old: failed to send slope table 0: %s\n", - sane_strstatus (status)); - return status; - } - - status = - gl646_send_slope_table (dev, 1, dev->slope_table1, - sanei_genesys_read_reg_from_set (dev->reg, 0x6b)); - - - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_init_regs_for_scan_old: failed to send slope table 1: %s\n", - sane_strstatus (status)); - return status; - } - - DBG (DBG_proc, "gl646_init_regs_for_scan_old: completed\n"); - return SANE_STATUS_GOOD; -} - -/* set up registers for the actual scan +/** + * set up registers for the actual scan. The scan's parameters are given + * through the device settings. It allocates the scan buffers. */ static SANE_Status gl646_init_regs_for_scan (Genesys_Device * dev) { - SANE_Status status; + usleep (10000UL); + return setup_for_scan (dev, dev->settings, SANE_FALSE, SANE_TRUE, + SANE_TRUE); +} + +/** + * 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 settings settings of scan + * @param split SANE_TRUE if move to scan area is split from scan, SANE_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 SANE_Status +setup_for_scan (Genesys_Device * dev, Genesys_Settings settings, + SANE_Bool split, SANE_Bool xcorrection, SANE_Bool ycorrection) +{ + SANE_Status status = SANE_STATUS_GOOD; SANE_Bool color; int channels; - uint16_t startx, endx; - int move; + uint16_t startx = 0, endx; + int move = 0; - /* these 2 models use the old way to setup registers */ - if (dev->model->ccd_type == - CCD_5345 || dev->model->ccd_type == CCD_HP2300) - return gl646_init_regs_for_scan_old (dev); - - DBG (DBG_proc, "gl646_init_regs_for_scan: start\n"); + DBG (DBG_proc, "setup_for_scan: start\n"); DBG (DBG_info, - "gl646_init_regs_for_scan settings:\nResolution: %ux%uDPI\n" - "Lines : %u\nPPL : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", - dev->settings.xres, dev->settings.yres, dev->settings.lines, - dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, - dev->settings.scan_mode); + "setup_for_scan settings:\nResolution: %ux%uDPI\n" + "Lines : %u\nPixels : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", + settings.xres, settings.yres, settings.lines, + settings.pixels, settings.tl_x, settings.tl_y, settings.scan_mode); - if (dev->settings.scan_mode == 4) /* single pass color */ + if (settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { channels = 3; color = SANE_TRUE; @@ -4558,65 +3376,89 @@ gl646_init_regs_for_scan (Genesys_Device * dev) /* compute distance to move */ move = 0; - if (dev->model->is_sheetfed == SANE_FALSE) + /* XXX STEF XXX mD5345 -> optical_ydpi, other base_ydpi => half/full step ? */ + if (split == SANE_FALSE) { - move = - (SANE_UNFIX (dev->model->y_offset) * dev->motor.base_ydpi) / - MM_PER_INCH; + if (dev->model->is_sheetfed == SANE_FALSE) + { + if (ycorrection == SANE_TRUE) + { + move = + (SANE_UNFIX (dev->model->y_offset) * + dev->motor.optical_ydpi) / MM_PER_INCH; + } - /* add tl_y to base movement */ - move += (dev->settings.tl_y * dev->motor.base_ydpi) / MM_PER_INCH; + /* add tl_y to base movement */ + move += (settings.tl_y * dev->motor.optical_ydpi) / MM_PER_INCH; - /* substract current head position for flatbed scanners */ - /* XXX STEF XXX move -= dev->scanhead_position_in_steps; */ + } + else + { + move += (settings.tl_y * dev->motor.optical_ydpi) / MM_PER_INCH; + } + + DBG (DBG_info, "setup_for_scan: move=%d steps\n", move); + + /* security check */ + if (move < 0) + { + DBG (DBG_error, + "setup_for_scan: overriding negative move value %d\n", move); + move = 0; + } } - else - { - move += (dev->settings.tl_y * dev->motor.base_ydpi) / MM_PER_INCH; - } - - DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move); - - /* security check */ - if (move < 0) - { - DBG (DBG_error, - "gl646_init_regs_for_scan: overriding negative move value %d\n", - move); - move = 1; - } - DBG (DBG_info, "gl646_init_regs_for_scan: move=%d steps\n", move); + DBG (DBG_info, "setup_for_scan: move=%d steps\n", move); /* pixels are allways given at full CCD optical resolution */ /* use detected left margin and fixed value */ - startx = - dev->sensor.CCD_start_xoffset + - (SANE_UNFIX (dev->model->x_offset) * dev->sensor.optical_res) / - MM_PER_INCH; + if (xcorrection == SANE_TRUE) + { + if (dev->sensor.CCD_start_xoffset > 0) + startx = dev->sensor.CCD_start_xoffset; + else + startx = dev->sensor.dummy_pixel; + startx += + ((SANE_UNFIX (dev->model->x_offset) * dev->sensor.optical_res) / + MM_PER_INCH); + } + else + { + /* startx cannot be below dummy pixel value */ + startx = dev->sensor.dummy_pixel; + } /* add x coordinates : expressed in sensor max dpi */ - startx += (dev->settings.tl_x * dev->sensor.optical_res) / MM_PER_INCH; + startx += (settings.tl_x * dev->sensor.optical_res) / MM_PER_INCH; - endx = - startx + - (dev->settings.pixels * dev->sensor.optical_res) / dev->settings.xres; + endx = startx + (settings.pixels * dev->sensor.optical_res) / settings.xres; + + /* XXX STEF XXX TODO check for pixel width overflow */ /* set up correct values for scan (gamma and shading enabled) */ status = gl646_setup_registers (dev, dev->reg, + settings, dev->slope_table0, dev->slope_table1, - dev->settings.xres, + settings.xres, move, - dev->settings.lines, - startx, endx, color, dev->settings.depth); + settings.lines, + startx, endx, color, settings.depth); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "setup_for_scan: failed setup registers: %s\n", + sane_strstatus (status)); + return status; + } /* now post-process values for register and options fine tuning */ /* select color filter based on settings */ + dev->reg[reg_0x04].value &= ~REG04_FILTER; if (channels == 1) { - switch (dev->settings.color_filter) + switch (settings.color_filter) { /* red */ case 0: @@ -4631,6 +3473,7 @@ gl646_init_regs_for_scan (Genesys_Device * dev) dev->reg[reg_0x04].value |= 0x0c; break; default: + DBG (DBG_error, "setup_for_scan: invalid color filter\n"); return SANE_STATUS_INVAL; } } @@ -4642,7 +3485,7 @@ gl646_init_regs_for_scan (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_init_regs_for_scan: failed to send slope table 0: %s\n", + "setup_for_scan: failed to send slope table 0: %s\n", sane_strstatus (status)); return status; } @@ -4653,12 +3496,12 @@ gl646_init_regs_for_scan (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_init_regs_for_scan: failed to send slope table 1: %s\n", + "setup_for_scan: failed to send slope table 1: %s\n", sane_strstatus (status)); return status; } - DBG (DBG_proc, "gl646_init_regs_for_scan: completed\n"); + DBG (DBG_proc, "setup_for_scan: end\n"); return status; } @@ -4763,7 +3606,7 @@ gl646_send_gamma_table (Genesys_Device * dev, SANE_Bool generic) return status; } - DBG (DBG_proc, "gl646_send_gamma_table: completed\n"); + DBG (DBG_proc, "gl646_send_gamma_table: end\n"); free (gamma); return SANE_STATUS_GOOD; } @@ -4779,762 +3622,422 @@ gl646_led_calibration (Genesys_Device * dev) return SANE_STATUS_INVAL; } -/* 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. - genesys_search_start() must have been called so that the offsets and margins - are allready known. +/** + * average dark pixels of a 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, "dark_average: avg[%d] = %d\n", k, avg[k]); + } + average = 0; + for (i = 0; i < channels; i++) + average += avg[i]; + average /= channels; + DBG (DBG_info, "dark_average: average = %d\n", average); + return average; +} + +#define DARK_TARGET 8 +/** + * 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. + * genesys_search_start() must have been called so that the offsets and margins + * are allready known. + * @param dev scanner's device + * @return SANE_STATUS_GOOD if success, else error code is failure */ static SANE_Status gl646_offset_calibration (Genesys_Device * dev) { - int num_pixels; - int total_size; - int avg[3]; - uint8_t *first_line, *second_line; - int i, j; SANE_Status status = SANE_STATUS_GOOD; - int average, val, count; - int minimum, offset, dpi, channels; - SANE_Bool half_ccd = 1; - int steps = 0, lincnt = 1, start_pixel; - uint16_t slope_table[256]; + uint8_t *first_line, *second_line; + unsigned int channels; + char title[32]; + int pass = 0, avg, direction; + SANE_Int resolution; + Genesys_Settings settings; + int topavg, bottomavg; + int top, bottom, black_pixels; - DBG (DBG_proc, "gl646_offset_calibration\n"); + DBG (DBG_proc, "gl646_offset_calibration: start\n"); - /* offset calibration is allways done in color mode */ + /* setup for a RGB scan, one full sensor's width line */ + /* resolution is the one from the final scan */ + resolution = get_closest_resolution (dev->model->ccd_type, 150, SANE_TRUE); channels = 3; + black_pixels = + (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res; - /* todo : turn it into a switch */ - /* full CCD width is used */ - if (dev->model->ccd_type == CCD_5345) - { - if (dev->settings.xres > dev->sensor.optical_res / 2) - { - half_ccd = 0; - num_pixels = dev->sensor.sensor_pixels; - } - else - { - half_ccd = 1; - num_pixels = dev->sensor.sensor_pixels / 2; - } - dpi = 1200; - steps = 0; - lincnt = 1; - } - else if (dev->model->ccd_type == CCD_HP2300 - || dev->model->ccd_type == CCD_HP2400) - { - dpi = dev->settings.xres; - steps = 1; - lincnt = 2; - num_pixels = 2668; - if (dev->settings.xres > dev->sensor.optical_res / 2) - half_ccd = 0; - else - half_ccd = 1; - } - else - { - dpi = 600; - num_pixels = 2 * dpi; - lincnt = 1; - } - start_pixel = dev->sensor.dummy_pixel; + settings.scan_method = SCAN_METHOD_FLATBED; + settings.scan_mode = SCAN_MODE_COLOR; + settings.xres = resolution; + settings.yres = resolution; + settings.tl_x = 0; + settings.tl_y = 0; + settings.pixels = + (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; + settings.lines = CALIBRATION_LINES; + settings.depth = 8; + settings.color_filter = 0; - total_size = num_pixels * channels * 2 * lincnt; /* colors * bytes_per_color * scan lines */ + settings.disable_interpolation = 0; + settings.threshold = 0; + settings.exposure_time = 0; - dev->calib_reg[reg_0x01].value &= ~REG01_DVDSET; - dev->calib_reg[reg_0x02].value = REG02_ACDCDIS; - if (dev->model->motor_type == MOTOR_5345 || MOTOR_HP2300 || MOTOR_HP2400) - { - if (half_ccd) - dev->calib_reg[reg_0x02].value = - (dev->calib_reg[reg_0x02].value & ~REG02_STEPSEL) | REG02_HALFSTEP; - else - dev->calib_reg[reg_0x02].value = - (dev->calib_reg[reg_0x02]. - value & ~REG02_STEPSEL) | REG02_QUATERSTEP; - if (dev->model->motor_type == CCD_5345) - dev->calib_reg[reg_0x03].value |= REG03_AVEENB; - else - dev->calib_reg[reg_0x03].value &= ~REG03_AVEENB; - } + /* scan first line of data with no gain, but with offset from + * last calibration */ + dev->frontend.gain[0] = 0; + dev->frontend.gain[1] = 0; + dev->frontend.gain[2] = 0; - dev->calib_reg[reg_0x04].value = - (dev->calib_reg[reg_0x04]. - value & ~REG04_LINEART & ~REG04_FILTER) | REG04_BITSET; - if (channels == 1) - { - switch (dev->settings.color_filter) - { - /* red */ - case 0: - dev->calib_reg[reg_0x04].value |= 0x04; - break; - /* green */ - case 1: - dev->calib_reg[reg_0x04].value |= 0x08; - break; - /* blue */ - case 2: - dev->calib_reg[reg_0x04].value |= 0x0c; - break; - default: - return SANE_STATUS_INVAL; - } - } - - dev->calib_reg[reg_0x05].value = (dev->calib_reg[reg_0x05].value & ~REG05_GMMENB); /* disable gamma */ - -/* ST12: 0x01 0x00 0x02 0x41 0x03 0x1f 0x04 0x53 0x05 0x10 0x06 0x10 0x08 0x02 0x09 0x00 0x0a 0x06 0x0b 0x04 */ -/* ST24: 0x02 0x71 0x04 0x5f 0x05 0x50 0x08 0x0e 0x09 0x0c 0x0a 0x00 0x0b 0x0c */ -#if 0 - dev->calib_reg[reg_0x01].value = 0x00 /*0x02 */ ; /* disable shading, enable CCD, color, 1M */ - dev->calib_reg[reg_0x02].value = 0x71 /*0x40 */ ; /* no forward/backward, no auto-home, motor off, full step */ - dev->calib_reg[reg_0x03].value = 0x1f /*0x17 */ ; /* lamp on */ - dev->calib_reg[reg_0x04].value = 0x53; /* 16 bits data, 16 bits A/D, color, Wolfson fe */ - dev->calib_reg[reg_0x05].value = 0x50 /*0x00 */ ; /* CCD res = 600 Dpi, 12 bits gamma, disable gamma, 24 clocks/pixel */ - dev->calib_reg[reg_0x06].value = 0x10; /* power bit set, shading gain = 4 times system, no asic test */ - dev->calib_reg[reg_0x07].value = 0x00; /* DMA access */ -#endif - - gl646_setup_sensor (dev, dev->calib_reg, 1, half_ccd); - - /* motor & movement control , todo : could be removed */ - if (dev->model->motor_type == MOTOR_5345) - dev->calib_reg[reg_0x1f].value = 0x01; /* scan feed step for table one in two table mode only */ - - if (dev->model->motor_type == MOTOR_5345) - { - gl646_setup_steps (dev, dev->calib_reg, dpi); - dev->calib_reg[reg_0x21].value = 1; - } - else - { - dev->calib_reg[reg_0x21].value = 2; - dev->calib_reg[reg_0x22].value = 16; - dev->calib_reg[reg_0x23].value = 16; - dev->calib_reg[reg_0x24].value = 2; - } - - dev->calib_reg[reg_0x25].value = LOBYTE (HIWORD (lincnt)); - dev->calib_reg[reg_0x26].value = HIBYTE (LOWORD (lincnt)); - dev->calib_reg[reg_0x27].value = LOBYTE (LOWORD (lincnt)); - - dev->calib_reg[reg_0x28].value = 0x01; /* PWM duty for lamp control */ - dev->calib_reg[reg_0x29].value = 0xff; - - dev->calib_reg[reg_0x2c].value = HIBYTE (dpi); - dev->calib_reg[reg_0x2d].value = LOBYTE (dpi); - - dev->calib_reg[reg_0x30].value = HIBYTE (start_pixel); - dev->calib_reg[reg_0x31].value = LOBYTE (start_pixel); - dev->calib_reg[reg_0x32].value = HIBYTE (start_pixel + num_pixels); - dev->calib_reg[reg_0x33].value = LOBYTE (start_pixel + num_pixels); - if (dev->model->ccd_type == CCD_5345) - { - /* full CCD width from 1st non dummy pixel */ - total_size = num_pixels * channels * 2 * lincnt; - - /* fixed maximum word number */ - dev->calib_reg[reg_0x35].value = LOBYTE (HIWORD (65536)); - dev->calib_reg[reg_0x36].value = HIBYTE (LOWORD (65536)); - dev->calib_reg[reg_0x37].value = LOBYTE (LOWORD (65536)); - } - else - { - total_size = - (num_pixels * channels * 2 * dpi * lincnt) / dev->sensor.optical_res; - dev->calib_reg[reg_0x35].value = LOBYTE (HIWORD (total_size / lincnt)); - dev->calib_reg[reg_0x36].value = HIBYTE (LOWORD (total_size / lincnt)); - dev->calib_reg[reg_0x37].value = LOBYTE (LOWORD (total_size / lincnt)); - } - - dev->calib_reg[reg_0x34].value = dev->sensor.dummy_pixel; /* set the CCD dummy & optical black pixels number, for whole line shading (64) */ - dev->calib_reg[reg_0x38].value = - HIBYTE (sanei_genesys_exposure_time - (dev, dev->calib_reg, dev->settings.xres)); - dev->calib_reg[reg_0x39].value = - LOBYTE (sanei_genesys_exposure_time - (dev, dev->calib_reg, dev->settings.xres)); - - /* set feed steps number of motor move */ - dev->calib_reg[reg_0x3d].value = LOBYTE (HIWORD (steps)); - dev->calib_reg[reg_0x3e].value = HIBYTE (LOWORD (steps)); - dev->calib_reg[reg_0x3f].value = LOBYTE (LOWORD (steps)); - -/* -ST12: 0x60 0x00 0x61 0x00 0x62 0x00 0x63 0x00 0x64 0x00 0x65 0x3f 0x66 0x00 0x67 0x00 0x68 0x51 0x69 0x20 */ -/* ST24: 0x60 0x00 0x61 0x00 0x62 0x00 0x63 0x00 0x64 0x00 0x65 0x00 0x66 0x00 0x67 0x00 0x68 0x51 0x69 0x20 */ - dev->calib_reg[reg_0x60].value = 0x00; /* Z1MOD, 60h:61h:(6D b5:b3), remainder for start/stop */ - dev->calib_reg[reg_0x61].value = 0x00; /* (21h+22h)/LPeriod */ - dev->calib_reg[reg_0x62].value = 0x00; /* Z2MODE, 62h:63h:(6D b2:b0), remainder for start scan */ - dev->calib_reg[reg_0x63].value = 0x00; /* (3Dh+3Eh+3Fh)/LPeriod for one-table mode,(21h+1Fh)/LPeriod */ - dev->calib_reg[reg_0x64].value = 0x00; /* motor PWM frequency */ - dev->calib_reg[reg_0x65].value = 0x00; /* PWM duty cycle for table one motor phase (63 = max) */ - if (dev->model->motor_type == MOTOR_5345) - { - dev->gpo.value[1] |= 0x18; /* has to do with bipolar V-ref */ - if (dev->settings.yres <= 150) - dev->calib_reg[reg_0x65].value = 0x02; - } - dev->calib_reg[reg_0x66].value = dev->gpo.value[0]; - dev->calib_reg[reg_0x67].value = dev->gpo.value[1]; - dev->calib_reg[reg_0x68].value = dev->gpo.enable[0]; - dev->calib_reg[reg_0x69].value = dev->gpo.enable[1]; - -/* ST12: 0x6a 0x7f 0x6b 0xff 0x6c 0x00 0x6d 0x01 */ -/* ST24: 0x6a 0x40 0x6b 0xff 0x6c 0x00 0x6d 0x01 */ - dev->calib_reg[reg_0x6c].value = 0x00; /* period times for LPeriod, expR,expG,expB, Z1MODE, Z2MODE (one period time) */ - dev->calib_reg[reg_0x6a].value = dev->calib_reg[reg_0x6a].value | 0x02; - if (dev->model->motor_type == MOTOR_5345) - { - dev->calib_reg[reg_0x6b].value = 0xff; - dev->calib_reg[reg_0x6d].value = 0x41; - } - - dev->calib_reg[reg_0x60].value = HIBYTE (0); - dev->calib_reg[reg_0x61].value = LOBYTE (0); - dev->calib_reg[reg_0x62].value = HIBYTE (0); - dev->calib_reg[reg_0x63].value = LOBYTE (0); - - if (dev->model->motor_type == MOTOR_HP2300 - || dev->model->motor_type == MOTOR_HP2400) - { - dev->calib_reg[reg_0x65].value = 0x3f; /* PWM duty cycle for table one motor phase (63 = max) */ - dev->calib_reg[reg_0x6b].value = 0x02; - dev->calib_reg[reg_0x6d].value = 0x7f; - slope_table[0] = 4480; - slope_table[1] = 4480; - RIE (gl646_send_slope_table - (dev, 0, slope_table, dev->calib_reg[reg_0x21].value)); - } - - /* work around incorrect calibration when frequent color/dpi scan changes */ - RIE (gl646_set_fe (dev, AFE_INIT)); - - RIE (gl646_set_fe (dev, AFE_SET)); - - RIE (gl646_bulk_write_register - (dev, dev->calib_reg, GENESYS_GL646_MAX_REGS)); - - first_line = malloc (total_size); - if (!first_line) - return SANE_STATUS_NO_MEM; - - second_line = malloc (total_size); - if (!second_line) - { - free (first_line); - return SANE_STATUS_NO_MEM; - } - - /* scan first line of data with no offset nor gain */ - dev->frontend.gain[0] = 0x00; - dev->frontend.gain[1] = 0x00; - dev->frontend.gain[2] = 0x00; - offset = 0; - dev->frontend.offset[0] = offset; - dev->frontend.offset[1] = offset; - dev->frontend.offset[2] = offset; - status = gl646_set_fe (dev, AFE_SET); + /* scan with no move */ + bottom = 90; + dev->frontend.offset[0] = bottom; + dev->frontend.offset[1] = bottom; + dev->frontend.offset[2] = bottom; + status = simple_scan (dev, settings, SANE_FALSE, &first_line); if (status != SANE_STATUS_GOOD) { - free (first_line); - free (second_line); DBG (DBG_error, - "gl646_offset_calibration: failed to set frontend: %s\n", - sane_strstatus (status)); + "gl646_offset_calibration: failed to scan first line\n"); + return status; + } + if (DBG_LEVEL >= DBG_data) + { + sanei_genesys_write_pnm_file ("offset000.pnm", first_line, 8, channels, + settings.pixels, settings.lines); + } + bottomavg = + dark_average (first_line, settings.pixels, settings.lines, channels, + black_pixels); + + /* now top value */ + top = 231; + dev->frontend.offset[0] = top; + dev->frontend.offset[1] = top; + dev->frontend.offset[2] = top; + status = simple_scan (dev, settings, SANE_FALSE, &second_line); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl646_offset_calibration: failed to scan first line\n"); return status; } - RIE (gl646_begin_scan (dev, dev->calib_reg, SANE_TRUE)); - RIE (sanei_genesys_read_data_from_scanner (dev, first_line, total_size)); - RIE (gl646_end_scan (dev, dev->calib_reg, SANE_FALSE)); - if (DBG_LEVEL >= DBG_data) - sanei_genesys_write_pnm_file ("offset1.pnm", - first_line, - 16, - channels, - (num_pixels * dpi) / - dev->sensor.optical_res, lincnt); - - /* We search for minimum dark value, then deduce a threshold from it. - This allow us to use data without knowing the geometry of the - black areas */ - val = 0; - minimum = 65535; - for (j = 0; j < channels; j++) { - for (i = 0; i < num_pixels; i++) + sprintf (title, "offset%03d.pnm", top); + sanei_genesys_write_pnm_file (title, second_line, 8, channels, + settings.pixels, settings.lines); + } + topavg = + dark_average (second_line, settings.pixels, settings.lines, channels, + black_pixels); + + /* loop until acceptable level */ + while ((pass < 32) && (top - bottom > 1)) + { + pass++; + + /* settings for new scan */ + dev->frontend.offset[0] = (top + bottom) / 2; + dev->frontend.offset[1] = (top + bottom) / 2; + dev->frontend.offset[2] = (top + bottom) / 2; + + /* scan with no move */ + status = simple_scan (dev, settings, SANE_FALSE, &second_line); + if (status != SANE_STATUS_GOOD) { - val = - first_line[i * 2 * channels + 2 * j + 1] * 256 + - first_line[i * 2 * channels + 2 * j]; - if (val < minimum) - minimum = val; + DBG (DBG_error, + "gl646_offset_calibration: failed to scan first line\n"); + return status; + } + + if (DBG_LEVEL >= DBG_data) + { + sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]); + sanei_genesys_write_pnm_file (title, second_line, 8, channels, + settings.pixels, settings.lines); + } + + avg = + dark_average (second_line, settings.pixels, settings.lines, channels, + black_pixels); + DBG (DBG_info, "gl646_offset_calibration: avg=%d offset=%d\n", avg, + dev->frontend.offset[1]); + + /* compute new boundaries */ + if (topavg == avg) + { + topavg = avg; + top = dev->frontend.offset[1]; + } + else + { + bottomavg = avg; + bottom = dev->frontend.offset[1]; } } - /* minimum accepted black pixel */ - minimum *= 1.1; - DBG (DBG_proc, "gl646_offset_calibration: black threshold = %d\n", - minimum); - - /* computes lowest average black value on black margin */ - for (j = 0; j < channels; j++) - { - avg[j] = 0; - count = 0; - for (i = 0; i < num_pixels; i++) - { - val = - first_line[i * 2 * channels + 2 * j + 1] * 256 + - first_line[i * 2 * channels + 2 * j]; - if (val <= minimum) - { - avg[j] += val; - count++; - } - } - if (count) - avg[j] /= count; - DBG (DBG_proc, "gl646_offset_calibration: avg[%d] = %d\n", j, - avg[j] / 256); - } - - /* now finds minimal black average */ - minimum = avg[0]; - if (channels > 1) - { - if (avg[1] < minimum) - minimum = avg[1]; - if (avg[2] < minimum) - minimum = avg[2]; - } - - switch (dev->model->ccd_type) - { - case CCD_5345: - offset = minimum / 256; - break; - case CCD_HP2300: - case CCD_HP2400: - offset = minimum / 2 * 256; - } - DBG (DBG_proc, - "gl646_offset_calibration: minimum = %.2f, offset = %d\n", - (float) minimum / 256.0, offset); - - /* scan second line of data with a fixed offset and no gain */ - dev->frontend.offset[0] = offset; - dev->frontend.offset[1] = offset; - dev->frontend.offset[2] = offset; - status = gl646_set_fe (dev, AFE_SET); - if (status != SANE_STATUS_GOOD) - { - free (first_line); - free (second_line); - DBG (DBG_error, - "gl646_offset_calibration: failed to set frontend: %s\n", - sane_strstatus (status)); - return status; - } - - RIE (gl646_begin_scan (dev, dev->calib_reg, SANE_TRUE)); - RIE (sanei_genesys_read_data_from_scanner (dev, second_line, total_size)); - RIE (gl646_end_scan (dev, dev->calib_reg, SANE_FALSE)); + /* in case of debug do a final scan to get result */ if (DBG_LEVEL >= DBG_data) - sanei_genesys_write_pnm_file ("offset2.pnm", - second_line, - 16, - channels, - (num_pixels * dpi) / - dev->sensor.optical_res, lincnt); - - /* compute final offsets */ - for (j = 0; j < channels; j++) { - /* finds minimum for current color channel */ - minimum = 65535; - for (i = 0; i < num_pixels; i++) + status = simple_scan (dev, settings, SANE_FALSE, &second_line); + if (status != SANE_STATUS_GOOD) { - val = - second_line[i * 2 * channels + 2 * j + 1] * 256 + - second_line[i * 2 * channels + 2 * j]; - if (val < minimum) - minimum = val; + DBG (DBG_error, + "gl646_offset_calibration: failed to scan final line\n"); + return status; } - minimum *= 1.1; - - /* computes black average for channel */ - average = 0; - count = 0; - for (i = 0; i < num_pixels; i++) - { - val = - 256 * second_line[i * 2 * channels + j * 2 + 1] + - second_line[i * 2 * channels + j * 2]; - if (val < minimum) - { - average += val; - count++; - } - } - if (count) - average /= count; - - switch (dev->model->ccd_type) - { - case CCD_5345: - /* dev->frontend.offset[j] = (offset*min[j]) / (min[j]-average); */ - /* we assume a linear law, the 0.95 coeff is there because while we want - a DC offset of 0, values are varying a little and we let a little offset - to get sure we don't have "negative" values */ - dev->frontend.offset[j] = - offset + ((float) (average * offset) * 0.95) / (avg[j] - average); - /* dev->frontend.offset[j] = offset + ((float) average) / (1.3 * 256) ; */ - break; - case CCD_HP2300: - if (j == 0) - dev->frontend.offset[j] = offset + average / (1.2 * 256); - else - dev->frontend.offset[j] = offset + average / (1.0 * 256); - break; - } - DBG (DBG_proc, - "gl646_offset_calibration: average[%d] = %.2f, offset = %d\n", - j, (float) average / 256, dev->frontend.offset[j]); - } - if (channels == 1) - { - dev->frontend.offset[1] = dev->frontend.offset[0]; - dev->frontend.offset[2] = dev->frontend.offset[0]; + sanei_genesys_write_pnm_file ("offset-final.pnm", second_line, 8, + channels, settings.pixels, + settings.lines); } /* cleanup before return */ free (first_line); free (second_line); - DBG (DBG_proc, "gl646_offset_calibration: completed\n"); + DBG (DBG_info, "gl646_offset_calibration: offset=(%d,%d,%d)\n", + dev->frontend.offset[0], dev->frontend.offset[1], + dev->frontend.offset[2]); + DBG (DBG_proc, "gl646_offset_calibration: end\n"); return status; } -/* alternative coarse gain calibration - this on uses the settings from offset_calibration and - uses only one scanline +/** + * Alternative coarse gain calibration + * this on uses the settings from offset_calibration. */ static SANE_Status gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) { - int num_pixels; - int black_pixels; - int total_size; uint8_t *line; - int i, j, channels; + unsigned int i, j, k, channels, val, maximum; + unsigned int size, count, resolution, pass; SANE_Status status = SANE_STATUS_GOOD; float average[3]; - int lincnt, words, count, val; - int maximum; + Genesys_Settings settings; + char title[32]; - DBG (DBG_proc, "gl646_coarse_gain_calibration\n"); + DBG (DBG_proc, "gl646_coarse_gain_calibration: start\n"); - /* coarse gain calibration is allways done in color mode */ + /* 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->ccd_type, 150, SANE_TRUE); - black_pixels = - (dev->sensor.CCD_start_xoffset * dpi) / dev->sensor.optical_res; + settings.scan_method = SCAN_METHOD_FLATBED; + settings.scan_mode = SCAN_MODE_COLOR; + settings.xres = resolution; + settings.yres = resolution; + settings.tl_x = 0; + settings.tl_y = 0; + settings.pixels = + (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; + settings.lines = CALIBRATION_LINES; + settings.depth = 8; + settings.color_filter = 0; - lincnt = 65536 * dev->calib_reg[reg_0x25].value; - lincnt += 256 * dev->calib_reg[reg_0x26].value; - lincnt += dev->calib_reg[reg_0x27].value; + settings.disable_interpolation = 0; + settings.threshold = 0; + settings.exposure_time = 0; - words = 65536 * dev->calib_reg[reg_0x35].value; - words += 256 * dev->calib_reg[reg_0x36].value; - words += dev->calib_reg[reg_0x37].value; + size = channels * settings.pixels * settings.lines; - num_pixels = words / (channels * 2); + /* start gain value */ + dev->frontend.gain[0] = 1; + dev->frontend.gain[1] = 1; + dev->frontend.gain[2] = 1; - total_size = words * lincnt; /* colors * bytes_per_color * scan lines */ - - line = malloc (total_size); - if (!line) - return SANE_STATUS_NO_MEM; - - /* sends offsets computed by offset calibration */ - status = gl646_set_fe (dev, AFE_SET); - if (status != SANE_STATUS_GOOD) + if (channels > 1) { - free (line); - DBG (DBG_error, - "gl646_coarse_gain_calibration: failed to set frontend: %s\n", - sane_strstatus (status)); - return status; + average[0] = 0; + average[1] = 0; + average[2] = 0; } - - RIE (gl646_begin_scan (dev, dev->calib_reg, SANE_TRUE)); - RIE (sanei_genesys_read_data_from_scanner (dev, line, total_size)); - RIE (gl646_end_scan (dev, dev->calib_reg, SANE_FALSE)); - - if (DBG_LEVEL >= DBG_data) - sanei_genesys_write_pnm_file ("alternative_coarse.pnm", line, 16, - channels, num_pixels, lincnt); - - /* average high level for each channel and compute gain - to reach the target code - we only use the central half of the CCD data */ - /* todo : use lincnt lines */ - for (j = 0; j < channels; j++) + else { - /* we find the maximum white value, so we can deduce a threshold - to average white values */ - maximum = 0; - for (i = 0; i < num_pixels; i++) - { - val = - 256 * line[i * 2 * channels + 2 * j + 1] + - line[i * 2 * channels + 2 * j]; - if (val > maximum) - maximum = val; - } - /* threshold */ - maximum *= 0.9; + average[0] = 0; + average[1] = 255; + average[2] = 255; + } + pass = 0; - /* computes white average */ - average[j] = 0; - count = 0; - for (i = 0; i < num_pixels; i++) + /* loop until each channel raises to acceptable level */ + while ((average[0] < dev->sensor.gain_white_ref) + || (average[1] < dev->sensor.gain_white_ref) + || (average[2] < dev->sensor.gain_white_ref)) + { + /* scan with no move */ + status = simple_scan (dev, settings, SANE_FALSE, &line); + if (status != SANE_STATUS_GOOD) { - /* averaging anly white points allow us not to care about dark margins */ - val = - 256 * line[i * 2 * channels + 2 * j + 1] + - line[i * 2 * channels + 2 * j]; - if (val > maximum) + DBG (DBG_error, + "gl646_coarse_gain_calibration: failed to scan first line\n"); + return status; + } + + /* log scanning data */ + if (DBG_LEVEL >= DBG_data) + { + sprintf (title, "alternative_coarse%02d.pnm", pass); + sanei_genesys_write_pnm_file (title, line, 8, + channels, settings.pixels, + settings.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 (k = 0; k < 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++) { - average[j] += val; - count++; + for (j = 0; j < settings.pixels; j++) + { + val = line[i * channels * settings.pixels + j + k]; + if (val > maximum) + maximum = val; + } } - } - average[j] = average[j] / count; - switch (dev->model->ccd_type) - { - case CCD_HP2300: - dev->frontend.gain[j] = - (int) (((dev->sensor.gain_white_ref * 256) / average[j] - - 1.0) / 0.4); - break; - case CCD_5345: - default: - /* 0.445 */ - dev->frontend.gain[j] = - (int) (((dev->sensor.gain_white_ref * 256) / average[j] - - 1.0) / 0.445); - break; - } + /* threshold */ + maximum *= 0.9; - DBG (DBG_proc, - "gl646_coarse_gain_calibration: channel %d, average = %.2f, gain = %d\n", - j, average[j], dev->frontend.gain[j]); + /* 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] < dev->sensor.gain_white_ref) + dev->frontend.gain[k]++; + + DBG (DBG_proc, + "gl646_coarse_gain_calibration: channel %d, average = %.2f, gain = %d\n", + k, average[k], dev->frontend.gain[k]); + } } - if (dev->settings.scan_mode != 4) /* single pass color */ + if (channels < 3) { - dev->frontend.gain[0] = dev->frontend.gain[1]; - dev->frontend.gain[2] = dev->frontend.gain[1]; + dev->frontend.gain[1] = dev->frontend.gain[0]; + dev->frontend.gain[2] = dev->frontend.gain[0]; } free (line); - DBG (DBG_proc, "gl646_coarse_gain_calibration: completed\n"); + DBG (DBG_info, "gl646_coarse_gain_calibration: gains=(%d,%d,%d)\n", + dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2]); + DBG (DBG_proc, "gl646_coarse_gain_calibration: end\n"); return status; } -/* - * wait for lamp warmup by scanning the same line until difference - * between 2 scans is below a threshold +/** + * sets up the scanner's register for warming up. We scan 2 lines without moving. + * */ static SANE_Status gl646_init_regs_for_warmup (Genesys_Device * dev, Genesys_Register_Set * local_reg, int *channels, int *total_size) { - int num_pixels = (int) (4 * 300); - int dpi = 300, lincnt, exposure_time, words_per_line; - int startpixel, endpixel; - int steps = 0; SANE_Status status = SANE_STATUS_GOOD; - uint16_t slope_table[256]; + Genesys_Settings settings; + int resolution, lines; - DBG (DBG_proc, "gl646_warmup_lamp\n"); + DBG (DBG_proc, "gl646_init_regs_for_warmup: start\n"); + /* we scan at sensor maximum resolution */ + resolution = get_closest_resolution (dev->model->ccd_type, 300, SANE_FALSE); + + /* set up for a half width 2 lines color scan without moving */ + settings.scan_method = SCAN_METHOD_FLATBED; + settings.scan_mode = SCAN_MODE_GRAY; + settings.xres = resolution; + settings.yres = resolution; + settings.tl_x = 0; + settings.tl_y = 0; + settings.pixels = + (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; + settings.lines = 2; + settings.depth = 8; + settings.color_filter = 0; + + settings.disable_interpolation = 0; + settings.threshold = 0; + settings.exposure_time = 0; + + /* setup for scan */ + status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "gl646_init_regs_for_warmup: setup_for_scan failed (%s)\n", + sane_strstatus (status)); + return status; + } + + /* we are not going to move, so clear these bits */ + dev->reg[reg_0x02].value &= ~(REG02_FASTFED | REG02_AGOHOME); + + /* don't enable gamma correction for this scan */ + dev->reg[reg_0x05].value &= ~REG05_GMMENB; + + /* copy reg to calib_reg */ memcpy (local_reg, dev->reg, - (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); - *total_size = num_pixels * 3 * 2 * 1; /* colors * bytes_per_color * scan lines */ + GENESYS_GL646_MAX_REGS * sizeof (Genesys_Register_Set)); -/* ST12: 0x01 0x00 0x02 0x41 0x03 0x1f 0x04 0x53 0x05 0x10 0x06 0x10 0x08 0x02 0x09 0x00 0x0a 0x06 0x0b 0x04 */ -/* ST24: 0x02 0x71 0x04 0x5f 0x05 0x50 0x08 0x0e 0x09 0x0c 0x0a 0x00 0x0b 0x0c */ -#if 0 - local_reg[reg_0x01].value = 0x00 /*0x02 */ ; /* disable shading, enable CCD, color, 1M */ - local_reg[reg_0x02].value = 0x71 /*0x40 */ ; /* no forward/backward, no auto-home, motor off, full step */ - local_reg[reg_0x03].value = 0x1f /*0x17 */ ; /* lamp on */ - local_reg[reg_0x04].value = 0x53; /* 16 bits data, 16 bits A/D, color, Wolfson fe */ - local_reg[reg_0x05].value = 0x50 /*0x00 */ ; /* CCD res = 600 dpi, 12 bits gamma, disable gamma, 24 clocks/pixel */ - local_reg[reg_0x06].value = 0x10; /* power bit set, shading gain = 4 times system, no asic test */ - local_reg[reg_0x07].value = 0x00; /* DMA access */ - gl646_setup_sensor (dev, local_reg); -#endif + /* turn off motor during this scan */ + gl646_set_motor_power (local_reg, SANE_FALSE); + /* returned value to higher level warmup function */ + *channels = 1; + lines = gl646_get_triple_reg (dev->reg, REG_LINCNT) + 1; + *total_size = lines * settings.pixels; - local_reg[reg_0x03].value |= REG03_LAMPPWR; - local_reg[reg_0x04].value = - (local_reg[reg_0x04].value & ~REG04_LINEART) | REG04_BITSET; - local_reg[reg_0x05].value = (local_reg[reg_0x05].value & ~REG05_GMMENB); /* disable gamma */ - - switch (dev->model->ccd_type) - { - case CCD_HP2300: - case CCD_HP2400: - local_reg[reg_0x01].value = REG01_DOGENB; - local_reg[reg_0x02].value = REG02_ACDCDIS | REG02_HALFSTEP; - local_reg[reg_0x04].value &= ~REG04_BITSET; /* disable 16 bits scanning */ - local_reg[reg_0x05].value |= REG05_GMMENB; /* enable gamma */ - *channels = 1; - steps = 1; - local_reg[reg_0x04].value = - (local_reg[reg_0x04].value & ~REG04_FILTER) | 0x08; - num_pixels = 2668; - if (dev->model->motor_type == MOTOR_HP2300) - { - dpi = 150; - slope_table[0] = 4480; - slope_table[1] = 4480; - } - else if (dev->model->motor_type == MOTOR_HP2400) - { - dpi = 200; - slope_table[0] = 7210; - slope_table[1] = 7210; - } - RIE (gl646_send_slope_table - (dev, 0, slope_table, local_reg[reg_0x21].value)); - - /* motor & movement control */ - local_reg[reg_0x1e].value = 0x80; - local_reg[reg_0x1d].value |= REG1D_CKMANUAL; - local_reg[reg_0x1f].value = 0x10; - lincnt = 2; - local_reg[reg_0x21].value = 2; /* table one steps number for forward slope curve of the acc/dec */ - local_reg[reg_0x22].value = 16; /* steps number of the forward steps for start/stop */ - - /* start pixel */ - startpixel = dev->sensor.dummy_pixel + 34; - local_reg[reg_0x30].value = HIBYTE (startpixel); - local_reg[reg_0x31].value = LOBYTE (startpixel); - - /* end CCD pixel */ - endpixel = startpixel + num_pixels; - local_reg[reg_0x32].value = HIBYTE (endpixel); - local_reg[reg_0x33].value = LOBYTE (endpixel); - - words_per_line = num_pixels / (dev->sensor.optical_res / dpi); - local_reg[reg_0x35].value = LOBYTE (HIWORD (words_per_line)); - local_reg[reg_0x36].value = HIBYTE (LOWORD (words_per_line)); - local_reg[reg_0x37].value = LOBYTE (LOWORD (words_per_line)); - - exposure_time = sanei_genesys_exposure_time (dev, local_reg, dpi), - local_reg[reg_0x38].value = HIBYTE (exposure_time); - local_reg[reg_0x39].value = LOBYTE (exposure_time); - - /* monochrome scan */ - *total_size = words_per_line * lincnt; - break; - default: - dpi = 300; - steps = 0; - *channels = 3; - num_pixels = 4 * 300; - local_reg[reg_0x1e].value = 0xf0 /*0x10 */ ; /* watch-dog time */ - local_reg[reg_0x1f].value = 0x01; /* scan feed step for table one in two table mode only */ - - lincnt = 1; - - /* motor & movement control */ - local_reg[reg_0x21].value = 0x00; /* table one steps number for forward slope curve of the acc/dec */ - local_reg[reg_0x22].value = 0x00; /* steps number of the forward steps for start/stop */ - - local_reg[reg_0x28].value = 0x01; /* PWM duty for lamp control */ - local_reg[reg_0x29].value = 0xff; - - local_reg[reg_0x2e].value = 0x88; /* set black&white threshold high level */ - local_reg[reg_0x2f].value = 0x78; /* set black&white threshold low level */ - - local_reg[reg_0x38].value = 0x2a /*0x2b */ ; /* line period (exposure time) */ - local_reg[reg_0x39].value = 0xf8 /*0x44 */ ; - local_reg[reg_0x35].value = 0x00 /*0x00 */ ; /* set maximum word size per line, for buffer full control (10800) */ - local_reg[reg_0x36].value = 0x1d; - local_reg[reg_0x37].value = 0xe3; - break; - } - - gl646_setup_sensor (dev, local_reg, 1, 1); - - /* motor & movement control */ - local_reg[reg_0x23].value = local_reg[reg_0x22].value; /* steps number of the backward steps for start/stop */ - local_reg[reg_0x24].value = local_reg[reg_0x21].value; /* table one steps number backward slope curve of the acc/dec */ - - - local_reg[reg_0x25].value = LOBYTE (HIWORD (lincnt)); /* scan line numbers - here one line */ - local_reg[reg_0x26].value = HIBYTE (LOWORD (lincnt)); - local_reg[reg_0x27].value = LOBYTE (LOWORD (lincnt)); - - local_reg[reg_0x2c].value = HIBYTE (dpi); - local_reg[reg_0x2d].value = LOBYTE (dpi); - - local_reg[reg_0x34].value = dev->sensor.dummy_pixel; - - /* set feed steps number of motor move */ - local_reg[reg_0x3d].value = HIWORD (LOBYTE (steps)); - local_reg[reg_0x3e].value = LOWORD (HIBYTE (steps)); - local_reg[reg_0x3f].value = LOWORD (LOBYTE (steps)); - -/* ST12: 0x60 0x00 0x61 0x00 0x62 0x00 0x63 0x00 0x64 0x00 0x65 0x3f 0x66 0x00 0x67 0x00 0x68 0x51 0x69 0x20 */ -/* ST24: 0x60 0x00 0x61 0x00 0x62 0x00 0x63 0x00 0x64 0x00 0x65 0x00 0x66 0x00 0x67 0x00 0x68 0x51 0x69 0x20 */ - local_reg[reg_0x60].value = 0x00; /* Z1MOD, 60h:61h:(6D b5:b3), remainder for start/stop */ - local_reg[reg_0x61].value = 0x00; /* (21h+22h)/LPeriod */ - local_reg[reg_0x62].value = 0x00; /* Z2MODE, 62h:63h:(6D b2:b0), remainder for start scan */ - local_reg[reg_0x63].value = 0x00; /* (3Dh+3Eh+3Fh)/LPeriod for one-table mode,(21h+1Fh)/LPeriod */ - local_reg[reg_0x64].value = 0x00; /* motor PWM frequency */ - - local_reg[reg_0x66].value = dev->gpo.value[0] & 0x10; - local_reg[reg_0x67].value = dev->gpo.value[1]; - local_reg[reg_0x68].value = dev->gpo.enable[0]; - local_reg[reg_0x69].value = dev->gpo.enable[1]; - -/* ST12: 0x6a 0x7f 0x6b 0xff 0x6c 0x00 0x6d 0x01 */ -/* ST24: 0x6a 0x40 0x6b 0xff 0x6c 0x00 0x6d 0x01 */ - switch (dev->model->motor_type) - { - default: - local_reg[reg_0x65].value = 0x00; /* PWM duty cycle for table one motor phase (63 = max) */ - local_reg[reg_0x6a].value = 0x40; /* table two fast moving step type, PWM duty for table two */ - local_reg[reg_0x6b].value = 0x01; /* table two steps number for acc/dec */ - local_reg[reg_0x6c].value = 0x00; /* period times for LPeriod, expR,expG,expB, Z1MODE, Z2MODE (one period time) */ - local_reg[reg_0x6d].value = 0x1f; /* select deceleration steps whenever go home (0), accel/decel stop time (31 * LPeriod) */ - break; - case MOTOR_HP2300: - case MOTOR_HP2400: - local_reg[reg_0x65].value = 0x3f; - local_reg[reg_0x6a].value = 0x7f; - local_reg[reg_0x6b].value = 0x02; - local_reg[reg_0x6d].value = 0x7f; - break; - } - - RIE (gl646_set_fe (dev, AFE_INIT)); - + /* now registers are ok, write them to scanner */ + RIE (gl646_set_fe (dev, AFE_SET)); RIE (gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS)); + DBG (DBG_proc, "gl646_init_regs_for_warmup: end\n"); return status; } @@ -5547,131 +4050,40 @@ gl646_init_regs_for_warmup (Genesys_Device * dev, static SANE_Status gl646_repark_head (Genesys_Device * dev) { - Genesys_Register_Set local_reg[GENESYS_GL646_MAX_REGS + 1]; - uint16_t slope_table[256]; - unsigned int exposure_time; /* todo : modify sanei_genesys_exposure_time() */ SANE_Status status; - unsigned int steps = 232; - unsigned int lincnt = 212; - unsigned int dpi = 600; - unsigned int endpixel, expected; + Genesys_Settings settings; + unsigned int expected, steps; - DBG (DBG_proc, "gl646_repark_head\n"); + DBG (DBG_proc, "gl646_repark_head: start\n"); - memset (local_reg, 0, sizeof (local_reg)); - memcpy (local_reg, dev->reg, - (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); + settings.scan_method = SCAN_METHOD_FLATBED; + settings.scan_mode = SCAN_MODE_COLOR; + settings.xres = 75; + settings.yres = 75; + settings.tl_x = 0; + settings.tl_y = 5; + settings.pixels = 600; + settings.lines = 4; + settings.depth = 8; + settings.color_filter = 0; - local_reg[reg_0x01].value = - local_reg[reg_0x01].value & ~REG01_DVDSET & ~REG01_FASTMOD & ~REG01_SCAN; - local_reg[reg_0x02].value = - (local_reg[reg_0x02]. - value & ~REG02_FASTFED & ~REG02_STEPSEL) | REG02_HALFSTEP; - local_reg[reg_0x03].value = - (local_reg[reg_0x03].value & ~REG03_LAMPTIM) | 0x01; + settings.disable_interpolation = 0; + settings.threshold = 0; + settings.exposure_time = 0; - gl646_setup_sensor (dev, local_reg, 0, 0); - - local_reg[reg_0x1e].value = 0x10; - local_reg[reg_0x1f].value = 0x10; - local_reg[reg_0x20].value = 0x20; - - if (dev->model->motor_type == MOTOR_5345) - gl646_setup_steps (dev, local_reg, dpi); - else - { - local_reg[reg_0x21].value = 4; - local_reg[reg_0x22].value = 16; - local_reg[reg_0x23].value = 16; - local_reg[reg_0x24].value = 4; - } - - local_reg[reg_0x25].value = LOBYTE (HIWORD (lincnt)); - local_reg[reg_0x26].value = HIBYTE (LOWORD (lincnt)); - local_reg[reg_0x27].value = LOBYTE (LOWORD (lincnt)); - - local_reg[reg_0x2c].value = HIBYTE (dpi); - local_reg[reg_0x2d].value = LOBYTE (dpi); - - /* start pixel */ - local_reg[reg_0x30].value = HIBYTE (dev->sensor.dummy_pixel); - local_reg[reg_0x31].value = LOBYTE (dev->sensor.dummy_pixel); - - - /* end CCD pixel */ - endpixel = dev->sensor.dummy_pixel + 2400; - local_reg[reg_0x32].value = HIBYTE (endpixel); - local_reg[reg_0x33].value = LOBYTE (endpixel); - - local_reg[reg_0x34].value = dev->sensor.dummy_pixel; - - local_reg[reg_0x35].value = LOBYTE (HIWORD (3600)); - local_reg[reg_0x36].value = HIBYTE (LOWORD (3600)); /* */ - local_reg[reg_0x37].value = LOBYTE (LOWORD (3600)); /* maximum word size per line=1200 */ - - local_reg[reg_0x3d].value = LOBYTE (HIWORD (steps)); - local_reg[reg_0x3e].value = HIBYTE (LOWORD (steps)); - local_reg[reg_0x3f].value = LOBYTE (LOWORD (steps)); - - exposure_time = 1600; - local_reg[reg_0x38].value = HIBYTE (exposure_time); - local_reg[reg_0x39].value = LOBYTE (exposure_time); - - /* Z1MOD = Z2MOD = 0 */ - local_reg[reg_0x60].value = LOBYTE (0); - local_reg[reg_0x61].value = HIBYTE (0); - local_reg[reg_0x62].value = LOBYTE (0); - local_reg[reg_0x63].value = HIBYTE (0); - - local_reg[reg_0x65].value = 0x3f; - - /* todo : maybe move thes in init once for all */ - local_reg[reg_0x66].value = dev->gpo.value[0] & 0x10; - local_reg[reg_0x67].value = dev->gpo.value[1]; - local_reg[reg_0x68].value = dev->gpo.enable[0]; - local_reg[reg_0x69].value = dev->gpo.enable[1]; - local_reg[reg_0x6a].value = 0x7f; - local_reg[reg_0x6b].value = 0x80; - local_reg[reg_0x6c].value = 0x00; - local_reg[reg_0x6d].value = 0x7f; - - /* todo : move this into create_slope_table */ - sanei_genesys_create_slope_table (dev, - slope_table, - local_reg[reg_0x21].value, - local_reg[reg_0x02]. - value & REG02_STEPSEL, - exposure_time, 0, 600, 0); - - sanei_genesys_create_slope_table (dev, - dev->slope_table1, - local_reg[reg_0x6b].value, - (local_reg[reg_0x6a]. - value & REG6A_FSTPSEL) >> 6, 2700, - SANE_FALSE, dev->motor.base_ydpi / 4, 0); - - status = - gl646_send_slope_table (dev, 0, slope_table, local_reg[reg_0x21].value); + status = setup_for_scan (dev, settings, SANE_FALSE, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_repark_head: failed to send slope table 0: %s\n", + "gl646_repark_head: failed to setup for scan: %s\n", sane_strstatus (status)); return status; } - status = - gl646_send_slope_table (dev, 1, dev->slope_table1, - local_reg[reg_0x6b].value); - if (status != SANE_STATUS_GOOD) - { - DBG (DBG_error, - "gl646_repark_head: failed to send slope table 1: %s\n", - sane_strstatus (status)); - return status; - } + /* TODO seems wrong ... no effective scan */ + dev->reg[reg_0x01].value &= ~REG01_SCAN; - status = gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS); + status = gl646_bulk_write_register (dev, dev->reg, GENESYS_GL646_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, @@ -5680,17 +4092,15 @@ gl646_repark_head (Genesys_Device * dev) return status; } - status = gl646_start_motor (dev); + /* start scan */ + status = gl646_begin_scan (dev, dev->reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { - DBG (DBG_error, "gl646_repark_head: failed to start motor: %s\n", - sane_strstatus (status)); - return SANE_STATUS_IO_ERROR; + DBG (DBG_error, "gl646_repark_head: failed to begin scan: \n"); + return status; } - expected = - local_reg[reg_0x3d].value * 65536 + - local_reg[reg_0x3e].value * 256 + local_reg[reg_0x3f].value; + expected = gl646_get_triple_reg (dev->reg, REG_FEEDL); do { usleep (100 * 1000); @@ -5698,7 +4108,7 @@ gl646_repark_head (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "gl646_repark_head: Failed to read feed steps: %s\n", + "gl646_repark_head: failed to read feed steps: %s\n", sane_strstatus (status)); return status; } @@ -5706,14 +4116,16 @@ gl646_repark_head (Genesys_Device * dev) while (steps < expected); /* toggle motor flag, put an huge step number and redo move backward */ - status = gl646_park_head (dev, local_reg, 1); - DBG (DBG_proc, "gl646_repark_head: completed\n"); + status = gl646_slow_back_home (dev, 1); + DBG (DBG_proc, "gl646_repark_head: end\n"); return status; } -/* +/* * * initialize ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home + * @param dev device description of the scanner to initailize + * @return SANE_STATUS_GOOD if success, error code if failure */ static SANE_Status gl646_init (Genesys_Device * dev) @@ -5723,9 +4135,10 @@ gl646_init (Genesys_Device * dev) uint8_t cold = 0, val = 0; uint32_t addr = 0xdead; int size; + size_t len; DBG_INIT (); - DBG (DBG_proc, "gl646_init\n"); + DBG (DBG_proc, "gl646_init: start\n"); /* to detect real power up condition, we write to REG41 * with pwrbit set, then read it back. When scanner is cold (just replugged) @@ -5772,51 +4185,6 @@ gl646_init (Genesys_Device * dev) /* Set default values for registers */ gl646_init_regs (dev); - /* create slopes */ - if (dev->model->motor_type == MOTOR_5345) - { - dev->reg[reg_0x02].value = - (dev->reg[reg_0x02].value & ~REG02_STEPSEL) | REG02_HALFSTEP; - sanei_genesys_create_slope_table (dev, dev->slope_table0, - dev->reg[reg_0x21].value, - dev->reg[reg_0x02]. - value & REG02_STEPSEL, - sanei_genesys_exposure_time - (dev, dev->reg, 150), 0, 150, 0); - sanei_genesys_create_slope_table (dev, dev->slope_table1, - dev->reg[reg_0x6b].value, - (dev->reg[reg_0x6a]. - value & REG6A_FSTPSEL) >> - 6, 3600, 0, 200, 0); - } - else if (dev->model->motor_type == MOTOR_ST24) - { - sanei_genesys_create_slope_table (dev, dev->slope_table0, - dev->reg[reg_0x21].value, - dev->reg[reg_0x02]. - value & REG02_STEPSEL, - dev->settings.exposure_time, - 0, 600, 0); - sanei_genesys_create_slope_table (dev, dev->slope_table1, - dev->reg[reg_0x6b].value, - (dev->reg[reg_0x6a]. - value & REG6A_FSTPSEL) >> - 6, 1200, 0, 400, 0); - } - else - { - sanei_genesys_create_slope_table (dev, dev->slope_table0, - dev->reg[reg_0x21].value, - dev->reg[reg_0x02]. - value & REG02_STEPSEL, 250, - 0, 600, 0); - sanei_genesys_create_slope_table (dev, dev->slope_table1, - dev->reg[reg_0x6b].value, - (dev->reg[reg_0x6a]. - value & REG6A_FSTPSEL) >> - 6, 250, 0, 600, 0); - } - /* build default gamma tables */ if (dev->reg[reg_0x05].value & REG05_GMMTYPE) size = 16384; @@ -5895,9 +4263,6 @@ gl646_init (Genesys_Device * dev) RIE (gl646_asic_test (dev)); } - /* Set analog frontend */ - RIE (gl646_set_fe (dev, AFE_INIT)); - /* send gamma tables if needed */ status = gl646_send_gamma_table (dev, 1); if (status != SANE_STATUS_GOOD) @@ -5912,6 +4277,9 @@ gl646_init (Genesys_Device * dev) RIE (gl646_set_powersaving (dev, 15)); } /* end if cold */ + /* Set analog frontend */ + RIE (gl646_set_fe (dev, AFE_INIT)); + /* GPO enabling for XP200 */ if (dev->model->ccd_type == CIS_XP200) { @@ -5969,14 +4337,15 @@ gl646_init (Genesys_Device * dev) return SANE_STATUS_INVAL; } sanei_usb_set_timeout (2 * 1000); - status = gl646_bulk_read_data (dev, 0x45, dev->control, 6); - /* for some reason, read fails here for both MD6471 and XP200 + len = 6; + status = gl646_bulk_read_data (dev, 0x45, dev->control, len); + /* for some reason, read fails here for MD6471, HP2300 and XP200 * one time out of 2 scanimage launches */ if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "gl646_init: failed to read control\n"); - status = gl646_bulk_read_data (dev, 0x45, dev->control, 6); + status = gl646_bulk_read_data (dev, 0x45, dev->control, len); } if (status != SANE_STATUS_GOOD) { @@ -6020,18 +4389,147 @@ gl646_init (Genesys_Device * dev) /* here session and device are initialized */ dev->already_initialized = SANE_TRUE; - DBG (DBG_proc, "gl646_init: completed\n"); + DBG (DBG_proc, "gl646_init: end\n"); return SANE_STATUS_GOOD; } + +/** + * 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 SANE_TRUE if moving during scan + * @param data pointer for the data + */ +static SANE_Status +simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, + unsigned char **data) +{ + SANE_Status status; + unsigned int size, lines; + SANE_Bool empty; + + DBG (DBG_proc, "simple_scan: starting\n"); + status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "simple_scan: setup_for_scan failed (%s)\n", + sane_strstatus (status)); + return status; + } + + /* allocate memory fo scan : LINCNT may have been adjusted for CCD reordering */ + lines = gl646_get_triple_reg (dev->reg, REG_LINCNT) + 1; + size = lines * settings.pixels; + if (settings.depth == 16) + size *= 2; + if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ + size *= 3; + *data = malloc (size); + if (!*data) + { + DBG (DBG_error, + "simple_scan: failed to allocate %d bytes of memory\n", size); + return SANE_STATUS_NO_MEM; + } + + /* initialize frontend */ + status = gl646_set_fe (dev, AFE_SET); + if (status != SANE_STATUS_GOOD) + { + free (*data); + DBG (DBG_error, + "simple_scan: failed to set frontend: %s\n", + sane_strstatus (status)); + return status; + } + + /* no shading correction and not wathc dog for simple scan */ + dev->reg[reg_0x01].value &= ~(REG01_DVDSET | REG01_DOGENB); + + /* clear motor power flag if no move */ + if (move == SANE_FALSE) + { + dev->reg[reg_0x02].value &= ~REG02_MTRPWR; + } + + /* one table movement for simple scan */ + dev->reg[reg_0x02].value &= ~REG02_FASTFED; + + /* no automatic go home if no movement */ + if (move == SANE_FALSE) + { + dev->reg[reg_0x02].value &= ~REG02_AGOHOME; + } + + /* write scan registers */ + status = gl646_bulk_write_register (dev, dev->reg, + sizeof (dev->reg) / + sizeof (dev->reg[0])); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, + "simple_scan: failed to bulk write registers: %s\n", + sane_strstatus (status)); + free (data); + return status; + } + + /* starts scan */ + status = gl646_begin_scan (dev, dev->reg, move); + if (status != SANE_STATUS_GOOD) + { + free (*data); + DBG (DBG_error, "simple_scan: failed to begin scan: \n"); + return status; + } + + /* wait for buffers to be filled */ + do + { + /* XXX STEF XXX status = sanei_genesys_get_status (dev, &val); + read_triple_reg (dev, REG_SCANCNT, &lines); + print_status (val); */ + RIE (sanei_genesys_test_buffer_empty (dev, &empty)); + /* XXX STEF XXX usleep (10000UL); */ + } + while (empty); + + /* now we're on target, we can read data */ + status = sanei_genesys_read_data_from_scanner (dev, *data, size); + if (status != SANE_STATUS_GOOD) + { + free (*data); + DBG (DBG_error, + "simple_scan: failed to read data: %s\n", sane_strstatus (status)); + return status; + } + + /* end scan , waiting the motor to stop if needed (if moving), but without ejecting doc */ + status = end_scan (dev, dev->reg, SANE_TRUE, SANE_FALSE); + if (status != SANE_STATUS_GOOD) + { + free (*data); + DBG (DBG_error, + "simple_scan: failed to end scan: %s\n", sane_strstatus (status)); + return status; + } + /* XXX STEF XXX usleep (50000UL); */ + + DBG (DBG_proc, "simple_scan: end\n"); + return status; +} + /** * update the status of the required sensor in the scanner session * the last_val fileds are used to make events 'sticky' */ static SANE_Status -gl646_update_hardware_sensors (Genesys_Scanner *session) +gl646_update_hardware_sensors (Genesys_Scanner * session) { - Genesys_Device *dev=session->dev; + Genesys_Device *dev = session->dev; uint8_t value; SANE_Status status; @@ -6129,7 +4627,8 @@ gl646_update_hardware_sensors (Genesys_Scanner *session) /* document detection */ if ((dev->model->buttons & GENESYS_HAS_PAGE_LOADED_SW) - && session->val[OPT_PAGE_LOADED_SW].b == session->last_val[OPT_PAGE_LOADED_SW].b) + && session->val[OPT_PAGE_LOADED_SW].b == + session->last_val[OPT_PAGE_LOADED_SW].b) { switch (dev->model->gpo_type) { @@ -6145,6 +4644,74 @@ gl646_update_hardware_sensors (Genesys_Scanner *session) return status; } + +static SANE_Status +write_control (Genesys_Device * dev, int resolution) +{ + SANE_Status status; + uint8_t control[4]; + uint32_t addr = 0xdead; + + /* 2300 does not write to 'control' */ + if (dev->model->motor_type == MOTOR_HP2300) + return SANE_STATUS_GOOD; + + /* MD6471/G2410/HP2300 and XP200 read/write data from an undocumented memory area which + * is after the second slope table */ + switch (dev->sensor.optical_res) + { + case 600: + addr = 0x08200; + break; + case 1200: + addr = 0x10200; + break; + case 2400: + addr = 0x1fa00; + break; + default: + DBG (DBG_error, "write_control: failed to compute control address\n"); + return SANE_STATUS_INVAL; + } + + /* XP200 sets dpi, what other scanner put is unknown yet */ + switch (dev->model->motor_type) + { + case MOTOR_XP200: + /* we put scan's dpi, not motor one */ + control[0] = LOBYTE (resolution); + control[1] = HIBYTE (resolution); + control[2] = dev->control[4]; + control[3] = dev->control[5]; + break; + case MOTOR_5345: + case MOTOR_HP3670: + control[0] = dev->control[2]; + control[1] = dev->control[3]; + control[2] = dev->control[4]; + control[3] = dev->control[5]; + default: + break; + } + + DBG (DBG_info, + "write_control: control write=0x%02x 0x%02x 0x%02x 0x%02x\n", + control[0], control[1], control[2], control[3]); + status = sanei_genesys_set_buffer_address (dev, addr); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "write_control: failed to set up control address\n"); + return SANE_STATUS_INVAL; + } + status = gl646_bulk_write_data (dev, 0x3c, control, 4); + if (status != SANE_STATUS_GOOD) + { + DBG (DBG_error, "write_control: failed to set up control\n"); + return SANE_STATUS_INVAL; + } + return status; +} + /** the gl646 command set */ static Genesys_Command_Set gl646_cmd_set = { "gl646-generic", /* the name of this set */ diff --git a/backend/genesys_gl841.c b/backend/genesys_gl841.c index 05ea4dafd..b601db6cd 100644 --- a/backend/genesys_gl841.c +++ b/backend/genesys_gl841.c @@ -58,7 +58,6 @@ #include #include #include - #include "_stdint.h" #include "../include/sane/sane.h" @@ -127,7 +126,7 @@ #define REG07_DMASEL 0x02 #define REG07_DMARDWR 0x01 -#define REG08_DECFLAG 0x40 +#define REG08_DECFLAG 0x40 #define REG08_GMMFFR 0x20 #define REG08_GMMFFG 0x10 #define REG08_GMMFFB 0x08 diff --git a/backend/genesys_low.h b/backend/genesys_low.h index 4b53dbaaa..9241ac8c4 100644 --- a/backend/genesys_low.h +++ b/backend/genesys_low.h @@ -3,8 +3,8 @@ Copyright (C) 2003 Oliver Rauch Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004, 2005 Gerhard Jaeger - Copyright (C) 2004, 2005 Stephane Voltz - Copyright (C) 2005 - 2009 Pierre Willenbrock + Copyright (C) 2004-2009 Stéphane Voltz + Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2006 Laurent Charpentier Parts of the structs have been taken from the gt68xx backend by Sergey Vlasov et al. @@ -107,6 +107,7 @@ #define GENESYS_HAS_PAGE_LOADED_SW (1 << 4) /* scanner has paper in detection */ #define GENESYS_HAS_OCR_SW (1 << 5) /* scanner has OCR button */ #define GENESYS_HAS_POWER_SW (1 << 6) /* scanner has power button */ +#define GENESYS_HAS_CALIBRATE (1 << 7) /* scanner has 'calibrate' software button to start calibration */ /* USB control message values */ #define REQUEST_TYPE_IN (USB_TYPE_VENDOR | USB_DIR_IN) @@ -166,6 +167,7 @@ typedef struct typedef struct { + uint8_t fe_id; /**> id of the frontend description */ uint8_t reg[4]; uint8_t sign[3]; uint8_t offset[3]; @@ -175,6 +177,7 @@ typedef struct typedef struct { + uint8_t sensor_id; /**> id of the sensor description */ int optical_res; int black_pixels; int dummy_pixel; /* value of dummy register. */ @@ -195,6 +198,7 @@ typedef struct typedef struct { + uint8_t gpo_id; /**> id of the gpo description */ uint8_t value[2]; uint8_t enable[2]; } Genesys_Gpo; @@ -213,6 +217,7 @@ typedef struct typedef struct { + uint8_t motor_id; /**> id of the motor description */ SANE_Int base_ydpi; /* motor base steps. Unit: 1/" */ SANE_Int optical_ydpi; /* maximum resolution in y-direction. Unit: 1/" */ SANE_Int max_step_type; /* maximum step type. 0-2 */ @@ -247,6 +252,7 @@ Genesys_Color_Order; #define DAC_CANONLIDE35 6 #define DAC_AD_XP200 7 /* Analog Device frontend */ #define DAC_WOLFSON_XP300 8 +#define DAC_WOLFSON_HP3670 9 #define CCD_UMAX 0 #define CCD_ST12 1 /* SONY ILX548: 5340 Pixel ??? */ @@ -257,6 +263,7 @@ Genesys_Color_Order; #define CCD_CANONLIDE35 6 #define CIS_XP200 7 /* CIS sensor for Strobe XP200 */ #define CCD_XP300 8 +#define CCD_HP3670 9 #define GPO_UMAX 0 #define GPO_ST12 1 @@ -267,6 +274,7 @@ Genesys_Color_Order; #define GPO_CANONLIDE35 6 #define GPO_XP200 7 #define GPO_XP300 8 +#define GPO_HP3670 9 #define MOTOR_UMAX 0 #define MOTOR_5345 1 @@ -276,6 +284,8 @@ Genesys_Color_Order; #define MOTOR_CANONLIDE35 5 #define MOTOR_XP200 6 #define MOTOR_XP300 7 +#define MOTOR_HP3670 9 + /* Forward typedefs */ typedef struct Genesys_Device Genesys_Device; @@ -439,6 +449,14 @@ typedef struct Genesys_Model SANE_Int search_lines; /* how many lines are used to search start position */ } Genesys_Model; +#define SCAN_METHOD_FLATBED 0 /**> normal scan method */ +#define SCAN_METHOD_TRANSPARENCY 2 /**> scan using transparency adaptor */ +#define SCAN_METHOD_NEGATIVE 0x88 /**> scan using negative adaptor */ + +#define SCAN_MODE_LINEART 0 /**> lineart scan mode */ +#define SCAN_MODE_HALFTONE 1 /**> halftone scan mode */ +#define SCAN_MODE_GRAY 2 /**> gray scan mode */ +#define SCAN_MODE_COLOR 4 /**> color scan mode */ typedef struct {