working transparency support for gl646 based scanners

- add move to transparency adapter function to command set
- no warmup when using transparency adapter
- increase maximum warmup time to match HP3670 requirements
- tune HP3670's transparency adapter geometry
- handle calibration area geometry in gain calibration
- add simple move head function for gl646 based scanners
merge-requests/1/head
Stphane Voltz 2010-03-15 06:24:23 +01:00
rodzic 598d3c82ba
commit f91ceaddf4
7 zmienionych plików z 208 dodań i 61 usunięć

Wyświetl plik

@ -4309,8 +4309,10 @@ genesys_start_scan (Genesys_Device * dev)
return status; return status;
} }
/* wait for lamp warmup */ /* wait for lamp warmup : until a warmup for TRANSPARENCY is designed, skip
if (!(dev->model->flags & GENESYS_FLAG_SKIP_WARMUP)) * it when scanning from XPA */
if (!(dev->model->flags & GENESYS_FLAG_SKIP_WARMUP)
&& (dev->settings.scan_method == SCAN_METHOD_FLATBED))
{ {
RIE (genesys_warmup_lamp (dev)); RIE (genesys_warmup_lamp (dev));
} }
@ -4358,6 +4360,20 @@ genesys_start_scan (Genesys_Device * dev)
} }
} }
/* move to calibration area for transparency adapter */
if ((dev->settings.scan_method == SCAN_METHOD_TRANSPARENCY)
&& dev->model->cmd_set->move_to_ta != NULL)
{
status=dev->model->cmd_set->move_to_ta(dev);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"genesys_start_scan: failed to move to start of transparency adapter: %s\n",
sane_strstatus (status));
return status;
}
}
/* load document if needed (for sheetfed scanner for instance) */ /* load document if needed (for sheetfed scanner for instance) */
if (dev->model->is_sheetfed == SANE_TRUE if (dev->model->is_sheetfed == SANE_TRUE
&& dev->model->cmd_set->load_document != NULL) && dev->model->cmd_set->load_document != NULL)
@ -4518,7 +4534,7 @@ genesys_start_scan (Genesys_Device * dev)
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_error, DBG (DBG_error,
"genesys_start_scan: Failed to read valid words: %s\n", "genesys_start_scan: failed to read valid words: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }

Wyświetl plik

@ -56,7 +56,7 @@
#define GENESYS_CONFIG_FILE "genesys.conf" #define GENESYS_CONFIG_FILE "genesys.conf"
/* Maximum time for lamp warm-up */ /* Maximum time for lamp warm-up */
#define WARMUP_TIME 45 #define WARMUP_TIME 65
#define FLATBED "Flatbed" #define FLATBED "Flatbed"
#define TRANSPARENCY_ADAPTER "Transparency Adapter" #define TRANSPARENCY_ADAPTER "Transparency Adapter"

Wyświetl plik

@ -1060,12 +1060,12 @@ static Genesys_Model hp3670c_model = {
SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */
SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */
SANE_FIX (52.2), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (104.0), /* Start of scan area in TA mode in mm (x) */
SANE_FIX (55.6), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (55.6), /* Start of scan area in TA mode in mm (y) */
SANE_FIX (25.6), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (25.6), /* Size of scan area in TA mode in mm (x) */
SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (78.0), /* Size of scan area in TA mode in mm (y) */
SANE_FIX (43.2), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (76.0), /* Start of white strip in TA mode in mm (y) */
SANE_FIX (0.0), /* Size of scan area after paper sensor stops SANE_FIX (0.0), /* Size of scan area after paper sensor stops
sensing document in mm */ sensing document in mm */

Wyświetl plik

@ -530,6 +530,39 @@ gl646_stop_motor (Genesys_Device * dev)
} }
/**
* find the lowest resolution for the sensor in the given 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_lowest_resolution (int sensor, SANE_Bool color)
{
int i, nb;
int dpi;
i = 0;
dpi = 9600;
nb = sizeof (sensor_master) / sizeof (Sensor_Master);
while (sensor_master[i].sensor != -1 && i < nb)
{
/* computes distance and keep mode if it is closer than previous */
if (sensor == sensor_master[i].sensor
&& sensor_master[i].color == color)
{
if (sensor_master[i].dpi < dpi)
{
dpi = sensor_master[i].dpi;
}
}
i++;
}
DBG (DBG_info, "get_lowest_resolution: %d\n", dpi);
return dpi;
}
/** /**
* find the closest match in mode tables for the given resolution and scan mode. * find the closest match in mode tables for the given resolution and scan mode.
* @param sensor id of the sensor * @param sensor id of the sensor
@ -993,7 +1026,9 @@ gl646_setup_registers (Genesys_Device * dev,
if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE))
{ {
/* for HP3670, stagger happens only at >=1200 dpi */ /* for HP3670, stagger happens only at >=1200 dpi */
if((dev->model->motor_type != MOTOR_HP3670 && dev->model->motor_type != MOTOR_HP2400)|| scan_settings.yres >= dev->sensor.optical_res) if ((dev->model->motor_type != MOTOR_HP3670
&& dev->model->motor_type != MOTOR_HP2400)
|| scan_settings.yres >= dev->sensor.optical_res)
{ {
stagger = (4 * scan_settings.yres) / dev->motor.base_ydpi; stagger = (4 * scan_settings.yres) / dev->motor.base_ydpi;
} }
@ -3297,7 +3332,8 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
SANE_Status status; SANE_Status status;
/* park head after calibration if needed */ /* park head after calibration if needed */
if (dev->scanhead_position_in_steps > 0 && settings.scan_method==SCAN_METHOD_FLATBED) if (dev->scanhead_position_in_steps > 0
&& dev->settings.scan_method == SCAN_METHOD_FLATBED)
{ {
status = gl646_slow_back_home (dev, SANE_TRUE); status = gl646_slow_back_home (dev, SANE_TRUE);
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
@ -3336,7 +3372,8 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings,
DBG (DBG_info, DBG (DBG_info,
"setup_for_scan settings:\nResolution: %ux%uDPI\n" "setup_for_scan settings:\nResolution: %ux%uDPI\n"
"Lines : %u\nPixels : %u\nStartpos : %.3f/%.3f\nScan mode : %d\nScan method: %s\n\n", "Lines : %u\nPixels : %u\nStartpos : %.3f/%.3f\nScan mode : %d\nScan method: %s\n\n",
settings.xres, settings.yres, settings.lines, settings.pixels, settings.tl_x, settings.tl_y, settings.scan_mode, settings.xres, settings.yres, settings.lines, settings.pixels,
settings.tl_x, settings.tl_y, settings.scan_mode,
settings.scan_method == SCAN_METHOD_FLATBED ? "flatbed" : "XPA"); settings.scan_method == SCAN_METHOD_FLATBED ? "flatbed" : "XPA");
if (settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ if (settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
@ -3393,10 +3430,19 @@ setup_for_scan (Genesys_Device * dev, Genesys_Settings settings,
startx = dev->sensor.CCD_start_xoffset; startx = dev->sensor.CCD_start_xoffset;
else else
startx = dev->sensor.dummy_pixel; startx = dev->sensor.dummy_pixel;
if (settings.scan_method == SCAN_METHOD_FLATBED)
{
startx += startx +=
((SANE_UNFIX (dev->model->x_offset) * dev->sensor.optical_res) / ((SANE_UNFIX (dev->model->x_offset) * dev->sensor.optical_res) /
MM_PER_INCH); MM_PER_INCH);
} }
else
{
startx +=
((SANE_UNFIX (dev->model->x_offset_ta) *
dev->sensor.optical_res) / MM_PER_INCH);
}
}
else else
{ {
/* startx cannot be below dummy pixel value */ /* startx cannot be below dummy pixel value */
@ -4237,7 +4283,6 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi)
float average[3]; float average[3];
Genesys_Settings settings; Genesys_Settings settings;
char title[32]; char title[32];
SANE_Bool move=SANE_FALSE;
if (dev->model->ccd_type == CIS_XP200) if (dev->model->ccd_type == CIS_XP200)
{ {
@ -4259,27 +4304,26 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi)
else else
{ {
resolution = resolution =
get_closest_resolution (dev->model->ccd_type, dev->settings.xres, SANE_TRUE); get_closest_resolution (dev->model->ccd_type, dev->settings.xres,
SANE_TRUE);
} }
settings.scan_method = dev->settings.scan_method; settings.scan_method = dev->settings.scan_method;
settings.scan_mode = SCAN_MODE_COLOR; settings.scan_mode = SCAN_MODE_COLOR;
settings.xres = resolution; settings.xres = resolution;
settings.yres = resolution; settings.yres = resolution;
settings.tl_y = 0;
if (settings.scan_method == SCAN_METHOD_FLATBED) if (settings.scan_method == SCAN_METHOD_FLATBED)
{ {
settings.tl_x = 0; settings.tl_x = 0;
settings.tl_y = 0;
settings.pixels = settings.pixels =
(dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res;
move=SANE_FALSE;
} }
else else
{ {
settings.tl_x = (SANE_UNFIX(dev->model->x_offset_ta) * resolution) / MM_PER_INCH; settings.tl_x = SANE_UNFIX (dev->model->x_offset_ta);
settings.tl_y = (SANE_UNFIX(dev->model->y_offset_calib_ta) * resolution) / MM_PER_INCH; settings.pixels =
settings.pixels = (SANE_UNFIX(dev->model->x_size_ta) * resolution) / MM_PER_INCH; (SANE_UNFIX (dev->model->x_size_ta) * resolution) / MM_PER_INCH;
move=SANE_TRUE;
} }
settings.lines = CALIBRATION_LINES; settings.lines = CALIBRATION_LINES;
settings.depth = 8; settings.depth = 8;
@ -4318,9 +4362,9 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi)
|| (average[1] < dev->sensor.gain_white_ref) || (average[1] < dev->sensor.gain_white_ref)
|| (average[2] < dev->sensor.gain_white_ref)) && (pass < 30)) || (average[2] < dev->sensor.gain_white_ref)) && (pass < 30))
{ {
/* scan with no move but for first scan */ /* scan with no move */
status = status =
simple_scan (dev, settings, move, SANE_TRUE, SANE_FALSE, &line); simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &line);
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_error, DBG (DBG_error,
@ -4328,10 +4372,6 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi)
return status; return status;
} }
/* after first scan, we don't move anymore */
move = SANE_FALSE;
settings.tl_y = 0;
/* log scanning data */ /* log scanning data */
if (DBG_LEVEL >= DBG_data) if (DBG_LEVEL >= DBG_data)
{ {
@ -4846,6 +4886,26 @@ gl646_init (Genesys_Device * dev)
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
#ifndef UNIT_TESTING
static
#endif
gl646_move_to_ta (Genesys_Device * dev)
{
SANE_Status status = SANE_STATUS_GOOD;
DBG (DBG_proc, "gl646_move_to_ta: starting\n");
if (simple_move (dev, SANE_UNFIX (dev->model->y_offset_calib_ta)) !=
SANE_STATUS_GOOD)
{
DBG (DBG_error,
"gl646_move_to_ta: failed to move to calibration area\n");
return status;
}
DBG (DBG_proc, "gl646_move_to_ta: end\n");
return status;
}
/** /**
* Does a simple scan: ie no line reordering and avanced data buffering and * Does a simple scan: ie no line reordering and avanced data buffering and
@ -4872,7 +4932,8 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
u_int8_t val; u_int8_t val;
DBG (DBG_proc, "simple_scan: starting\n"); DBG (DBG_proc, "simple_scan: starting\n");
DBG (DBG_io, "simple_scan: move=%d, forward=%d, shading=%d\n",move,forward,shading); DBG (DBG_io, "simple_scan: move=%d, forward=%d, shading=%d\n", move,
forward, shading);
/* round up to multiple of 3 in case of CIS scanner */ /* round up to multiple of 3 in case of CIS scanner */
if (dev->model->is_cis == SANE_TRUE) if (dev->model->is_cis == SANE_TRUE)
@ -5010,8 +5071,7 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
if (count == 1000) if (count == 1000)
{ {
free (*data); free (*data);
DBG (DBG_error, DBG (DBG_error, "simple_scan: failed toread data\n");
"simple_scan: failed toread data\n");
return SANE_STATUS_IO_ERROR; return SANE_STATUS_IO_ERROR;
} }
@ -5104,6 +5164,55 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
return status; return status;
} }
/**
* Does a simple move of the given distance by doing a scan at lowest resolution
* shading correction. Memory for data is allocated in this function
* and must be freed by caller.
* @param dev device of the scanner
* @param distance distance to move in MM
*/
#ifndef UNIT_TESTING
static
#endif
SANE_Status
simple_move (Genesys_Device * dev, SANE_Int distance)
{
SANE_Status status = SANE_STATUS_INVAL;
unsigned char *data = NULL;
Genesys_Settings settings;
DBG (DBG_proc, "simple_move: %d mm\n", distance);
/* TODO give a no AGOHOME flag */
settings.scan_method = SCAN_METHOD_TRANSPARENCY;
settings.scan_mode = SCAN_MODE_COLOR;
settings.xres = get_lowest_resolution (dev->model->ccd_type, SANE_TRUE);
settings.yres = settings.xres;
settings.tl_y = 0;
settings.tl_x = 0;
settings.pixels =
(dev->sensor.sensor_pixels * settings.xres) / dev->sensor.optical_res;
settings.lines = (distance * settings.xres) / MM_PER_INCH;
settings.depth = 8;
settings.color_filter = 0;
settings.disable_interpolation = 0;
settings.threshold = 0;
settings.exposure_time = 0;
status =
simple_scan (dev, settings, SANE_TRUE, SANE_TRUE, SANE_FALSE, &data);
free (data);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "simple_move: simple_scan failed\n");
return status;
}
DBG (DBG_proc, "simple_move: end.\n");
return status;
}
/** /**
* update the status of the required sensor in the scanner session * update the status of the required sensor in the scanner session
* the last_val fileds are used to make events 'sticky' * the last_val fileds are used to make events 'sticky'
@ -5390,9 +5499,10 @@ gl646_is_compatible_calibration (Genesys_Device * dev,
} }
if (dev->current_setup.scan_method != cache->used_setup.scan_method) if (dev->current_setup.scan_method != cache->used_setup.scan_method)
{ {
DBG (DBG_io, "gl646_is_compatible_calibration: current method=%d, used=%d\n", DBG (DBG_io,
"gl646_is_compatible_calibration: current method=%d, used=%d\n",
dev->current_setup.scan_method, cache->used_setup.scan_method); dev->current_setup.scan_method, cache->used_setup.scan_method);
compatible = SANE_STATUS_UNSUPPORTED; compatible = 0;
} }
if (!compatible) if (!compatible)
{ {
@ -5401,12 +5511,12 @@ gl646_is_compatible_calibration (Genesys_Device * dev,
return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_UNSUPPORTED;
} }
/* a cache entry expires after 10 minutes for non CIS scanners */ /* a cache entry expires after 30 minutes for non CIS scanners */
/* TODO have depend on s->val[OPT_LAMP_OFF_TIME].w */
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
gettimeofday (&time, NULL); gettimeofday (&time, NULL);
if ((time.tv_sec - cache->last_calibration > 10 * 60) if ((time.tv_sec - cache->last_calibration > 30 * 60)
&& (dev->model->is_cis == SANE_FALSE)) && (dev->model->is_cis == SANE_FALSE)
&& (dev->settings.scan_method == SCAN_METHOD_FLATBED))
{ {
DBG (DBG_proc, DBG (DBG_proc,
"gl646_is_compatible_calibration: expired entry, non compatible cache\n"); "gl646_is_compatible_calibration: expired entry, non compatible cache\n");
@ -5641,7 +5751,8 @@ static Genesys_Command_Set gl646_cmd_set = {
gl646_eject_document, gl646_eject_document,
gl646_search_strip, gl646_search_strip,
gl646_is_compatible_calibration gl646_is_compatible_calibration,
gl646_move_to_ta
}; };
SANE_Status SANE_Status

Wyświetl plik

@ -312,6 +312,19 @@ gl646_setup_registers (Genesys_Device * dev,
uint16_t startx, uint16_t startx,
uint16_t endx, SANE_Bool color, SANE_Int depth); uint16_t endx, SANE_Bool color, SANE_Int depth);
/**
* Does a simple move of the given distance by doing a scan at lowest resolution
* shading correction. Memory for data is allocated in this function
* and must be freed by caller.
* @param dev device of the scanner
* @param distance distance to move in MM
*/
#ifndef UNIT_TESTING
static
#endif
SANE_Status
simple_move (Genesys_Device * dev, SANE_Int distance);
/** /**
* Does a simple scan of the area given by the settings. Scanned data * 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. * it put in an allocated area which must be freed by the caller.

Wyświetl plik

@ -6296,6 +6296,7 @@ static Genesys_Command_Set gl841_cmd_set = {
gl841_search_strip, gl841_search_strip,
gl841_is_compatible_calibration, gl841_is_compatible_calibration,
NULL
}; };
SANE_Status SANE_Status

Wyświetl plik

@ -3,7 +3,7 @@
Copyright (C) 2003 Oliver Rauch Copyright (C) 2003 Oliver Rauch
Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de> Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de> Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de>
Copyright (C) 2004-2009 Stéphane Voltz <stef.dev@free.fr> Copyright (C) 2004-2010 Stéphane Voltz <stef.dev@free.fr>
Copyright (C) 2005-2009 Pierre Willenbrock <pierre@pirsoft.dnsalias.org> Copyright (C) 2005-2009 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
Copyright (C) 2006 Laurent Charpentier <laurent_pubs@yahoo.com> Copyright (C) 2006 Laurent Charpentier <laurent_pubs@yahoo.com>
Parts of the structs have been taken from the gt68xx backend by Parts of the structs have been taken from the gt68xx backend by
@ -410,6 +410,12 @@ typedef struct Genesys_Command_Set
Genesys_Device * dev, Genesys_Device * dev,
Genesys_Calibration_Cache *cache, Genesys_Calibration_Cache *cache,
SANE_Bool for_overwrite); SANE_Bool for_overwrite);
/* functions for transparency adapter */
/**
* move scanning head to transparency adapter
*/
SANE_Status (*move_to_ta) (Genesys_Device * dev);
} Genesys_Command_Set; } Genesys_Command_Set;
typedef struct Genesys_Model typedef struct Genesys_Model