kopia lustrzana https://gitlab.com/sane-project/backends
first working version of sheetfed scanners shading calibration
- added a function to build planar shading data - improved sheetfed_calibration functionmerge-requests/1/head
rodzic
d522b2c2f7
commit
247b585de7
|
@ -1290,7 +1290,10 @@ sanei_genesys_exposure_time (Genesys_Device * dev, Genesys_Register_Set * reg,
|
|||
|
||||
The data needs to be of size "size", and in little endian byte order.
|
||||
*/
|
||||
static SANE_Status
|
||||
#ifndef UNIT_TESTING
|
||||
static
|
||||
#endif
|
||||
SANE_Status
|
||||
genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
|
||||
int size)
|
||||
{
|
||||
|
@ -2924,62 +2927,66 @@ compute_coefficients (Genesys_Device * dev,
|
|||
* @shading_data memory area where to store the computed shading coefficients
|
||||
* @param pixels_per_line number of pixels per line
|
||||
* @param channels number of color channels (actually 1 or 3)
|
||||
* @param avgpixels number of pixels to average
|
||||
* @param cmat transcoding matrix for color channel order
|
||||
* @param offset shading coefficients left offset
|
||||
* @param coeff 4000h or 2000h depending on fast scan mode or not
|
||||
* @param target white target value
|
||||
*/
|
||||
static void
|
||||
compute_planar_coefficients (Genesys_Device * dev,
|
||||
uint8_t * shading_data,
|
||||
unsigned int pixels_per_line,
|
||||
unsigned int words_per_color,
|
||||
unsigned int channels,
|
||||
unsigned int avgpixels,
|
||||
int cmat[3],
|
||||
unsigned int offset,
|
||||
unsigned int coeff, unsigned int target_code)
|
||||
unsigned int coeff, unsigned int target)
|
||||
{
|
||||
uint8_t *ptr; /*contain 16bit words in little endian */
|
||||
uint8_t *ptr; /* contains 16bit words in little endian */
|
||||
unsigned int x, j, c;
|
||||
unsigned int val, dk;
|
||||
unsigned int val, dk, br;
|
||||
|
||||
|
||||
DBG (DBG_io,
|
||||
"compute_planar_coefficients: pixels_per_line=%d, words=%d, coeff=0x%04x\n",
|
||||
pixels_per_line, words_per_color, coeff);
|
||||
for (c = 0; c < channels; c++)
|
||||
{
|
||||
for (x = 0; x < pixels_per_line - offset - avgpixels - 1;
|
||||
x += avgpixels)
|
||||
/* shading data is larger than pixels_per_line so offset can be neglected */
|
||||
for (x = 0; x < pixels_per_line; x++)
|
||||
{
|
||||
/* x2 because of 16 bit values, and x2 since one coeff for dark
|
||||
* and another for white */
|
||||
ptr = shading_data + pixels_per_line * c + (x + offset) * 2 * 2;
|
||||
ptr =
|
||||
shading_data + words_per_color * cmat[c] * 2 + (x + offset) * 4;
|
||||
|
||||
/* dark data */
|
||||
/* we only handle deletion and not average */
|
||||
dk = 0;
|
||||
for (j = 0; j < avgpixels; j++)
|
||||
br = 0;
|
||||
dk +=
|
||||
256 * dev->dark_average_data[(x + pixels_per_line * c) * 2 + 1];
|
||||
dk += dev->dark_average_data[(x + pixels_per_line * c) * 2];
|
||||
br +=
|
||||
256 * dev->white_average_data[(x + pixels_per_line * c) * 2 + 1];
|
||||
br += dev->white_average_data[(x + pixels_per_line * c) * 2];
|
||||
|
||||
if (br - dk > 0)
|
||||
{
|
||||
dk += 256 * dev->dark_average_data[(x + j) * 2 + 1];
|
||||
dk += dev->dark_average_data[(x + j) * 2];
|
||||
val = (coeff * target) / (br - dk);
|
||||
if (val >= 65535)
|
||||
{
|
||||
val = 65535;
|
||||
}
|
||||
}
|
||||
dk /= j;
|
||||
if (dk > 65535)
|
||||
dk = 65535;
|
||||
for (j = 0; j < avgpixels; j++)
|
||||
else
|
||||
{
|
||||
ptr[0 + j * 2] = dk & 255;
|
||||
ptr[1 + j * 2] = dk / 256;
|
||||
}
|
||||
/* white data */
|
||||
val = 0;
|
||||
for (j = 0; j < avgpixels; j++)
|
||||
{
|
||||
val += 256 * dev->white_average_data[(x + j) * 2 + 1];
|
||||
val += dev->white_average_data[(x + j) * 2];
|
||||
}
|
||||
val /= j;
|
||||
val -= (256 * ptr[1] + ptr[0]);
|
||||
val = compute_coefficient (coeff, target_code, val);
|
||||
for (j = 0; j < avgpixels; j++)
|
||||
{
|
||||
ptr[2 + j * 2] = val & 0xff;
|
||||
ptr[3 + j * 2] = val / 256;
|
||||
val = coeff;
|
||||
}
|
||||
|
||||
ptr[0] = dk & 255;
|
||||
ptr[1] = dk / 256;
|
||||
ptr[2] = val & 0xff;
|
||||
ptr[3] = val / 256;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2992,8 +2999,9 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
uint8_t *shading_data; /**> contains 16bit words in little endian */
|
||||
uint8_t channels;
|
||||
unsigned int x, j, o;
|
||||
unsigned int length; /**> number of shading calibration data words */
|
||||
unsigned int length; /**> number of shading calibration data words */
|
||||
unsigned int i, res;
|
||||
int cmat[3]; /**> matrix of color channels */
|
||||
unsigned int coeff, target_code, val, avgpixels, dk, words_per_color = 0;
|
||||
unsigned int target_dark, target_bright, br;
|
||||
|
||||
|
@ -3020,10 +3028,10 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
words_per_color = 0x15400;
|
||||
break;
|
||||
}
|
||||
length=0x1fe00;
|
||||
length = 0x1fe00;
|
||||
}
|
||||
else /* GL646 case */
|
||||
{ /* DPIHW */
|
||||
{ /* DPIHW */
|
||||
/* we make the shading data such that each color channel data line is contiguous
|
||||
* to the next one, which allow to write thes 3 channels in 1 write
|
||||
* during genesys_send_shading_coefficient, some values are words, other bytes
|
||||
|
@ -3032,35 +3040,37 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
{
|
||||
/* 600 dpi */
|
||||
case 0:
|
||||
words_per_color = 0x2A00 * 2;
|
||||
length=0x2A00 * 3;
|
||||
/* 5376 * 2 max */
|
||||
words_per_color = 0x2a00;
|
||||
break;
|
||||
/* 1200 dpi */
|
||||
case 1:
|
||||
words_per_color = 0x5500 * 2;
|
||||
length=0x5500 * 3;
|
||||
words_per_color = 0x5500;
|
||||
break;
|
||||
/* 2400 dpi */
|
||||
case 2:
|
||||
words_per_color = 0xA800 * 2;
|
||||
length=0xA800 * 3;
|
||||
words_per_color = 0xa800;
|
||||
break;
|
||||
}
|
||||
/* 3 channels, 2 bytes a word */
|
||||
length = words_per_color * 3 * 2;
|
||||
}
|
||||
shading_data = malloc (words_per_color * 3); /* 16 bit black, 16 bit white */
|
||||
memset (shading_data, 0, words_per_color * 3);
|
||||
shading_data = malloc (length); /* 16 bit black, 16 bit white */
|
||||
}
|
||||
else
|
||||
else /* chunky calibration data case */
|
||||
{
|
||||
length=pixels_per_line * 2 * 3;
|
||||
shading_data = malloc (length*2); /* 16 bit black, 16 bit white */
|
||||
length = pixels_per_line * 2 * 2 * 3; /* 16 bit black, 16 bit white */
|
||||
}
|
||||
|
||||
/* allocate computed size */
|
||||
shading_data = malloc (length);
|
||||
if (!shading_data)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_send_shading_coefficient: failed to allocate memory\n");
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
memset (shading_data, 0, length);
|
||||
|
||||
/* TARGET/(Wn-Dn) = white gain -> ~1.xxx then it is multiplied by 0x2000
|
||||
or 0x4000 to give an integer
|
||||
|
@ -3081,20 +3091,19 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
switch (dev->model->ccd_type)
|
||||
{
|
||||
case CIS_XP200:
|
||||
target_code = 0xf000;
|
||||
memset (shading_data, 0x00, pixels_per_line * 4 * 3);
|
||||
o = 0;
|
||||
/* XXX STEF XXX : TODO compute avgpixels on scan settings */
|
||||
avgpixels = 1;
|
||||
target_code = 0xdc00;
|
||||
o = 2;
|
||||
cmat[0] = 2; /* red is last */
|
||||
cmat[1] = 0; /* green is first */
|
||||
cmat[2] = 1; /* blue is second */
|
||||
compute_planar_coefficients (dev,
|
||||
shading_data,
|
||||
pixels_per_line,
|
||||
channels, avgpixels, o, coeff,
|
||||
target_code);
|
||||
words_per_color,
|
||||
channels, cmat, o, coeff, target_code);
|
||||
break;
|
||||
case CCD_5345:
|
||||
target_code = 0xfa00;
|
||||
memset (shading_data, 0x00, pixels_per_line * 4 * channels);
|
||||
o = 4;
|
||||
avgpixels = 1;
|
||||
compute_coefficients (dev,
|
||||
|
@ -3106,7 +3115,6 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
case CCD_HP2400:
|
||||
case CCD_HP3670:
|
||||
target_code = 0xfa00;
|
||||
memset (shading_data, 0x00, pixels_per_line * 4 * channels);
|
||||
o = 2;
|
||||
avgpixels = 1;
|
||||
compute_coefficients (dev,
|
||||
|
@ -3689,6 +3697,7 @@ static SANE_Status
|
|||
genesys_sheetfed_calibration (Genesys_Device * dev)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
SANE_Bool forward = SANE_TRUE;
|
||||
|
||||
DBG (DBG_proc, "genesys_sheetfed_calibration: start\n");
|
||||
if (dev->model->cmd_set->search_strip == NULL)
|
||||
|
@ -3708,39 +3717,26 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
/* we set up for shading calibration, start scan and then scan lines by lines until
|
||||
* we find a black strip crossing the calibration sheet */
|
||||
|
||||
/* seek black/white reverse/forward */
|
||||
status = dev->model->cmd_set->search_strip (dev, SANE_TRUE, SANE_TRUE);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_sheetfed_calibration: failed to find black strip: %s\n",
|
||||
sane_strstatus (status));
|
||||
dev->model->cmd_set->eject_document (dev);
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************* shading calibration ***************************/
|
||||
/* send default shading data */
|
||||
/* XXX STEF XXX status = sanei_genesys_init_shading_data (dev, pixels_per_line);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_sheetfed_calibration: failed to init shading process: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
} */
|
||||
|
||||
/* we know we hare on a black area */
|
||||
/* search for a full width black strip and then do a 16 bit scan to
|
||||
* gather black shading data */
|
||||
if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION)
|
||||
{
|
||||
/* seek black/white reverse/forward */
|
||||
status = dev->model->cmd_set->search_strip (dev, forward, SANE_TRUE);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_sheetfed_calibration: failed to find black strip: %s\n",
|
||||
sane_strstatus (status));
|
||||
dev->model->cmd_set->eject_document (dev);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = dev->model->cmd_set->init_regs_for_shading (dev);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_sheetfed_calibration: failed to do wset up registers for shading calibration: %s\n",
|
||||
"genesys_sheetfed_calibration: failed to do set up registers for shading calibration: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
@ -3753,14 +3749,16 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
|
|||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
forward = SANE_FALSE;
|
||||
}
|
||||
|
||||
/* go back to a white area */
|
||||
status = dev->model->cmd_set->search_strip (dev, SANE_FALSE, SANE_FALSE);
|
||||
|
||||
/* go to a white area */
|
||||
status = dev->model->cmd_set->search_strip (dev, forward, SANE_FALSE);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_sheetfed_calibration: failed to find black strip: %s\n",
|
||||
"genesys_sheetfed_calibration: failed to find white strip: %s\n",
|
||||
sane_strstatus (status));
|
||||
dev->model->cmd_set->eject_document (dev);
|
||||
return status;
|
||||
|
@ -3770,7 +3768,7 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_sheetfed_calibration: failed to do wset up registers for shading calibration: %s\n",
|
||||
"genesys_sheetfed_calibration: failed to do set up registers for shading calibration: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
@ -3779,10 +3777,17 @@ genesys_sheetfed_calibration (Genesys_Device * dev)
|
|||
{
|
||||
dev->model->cmd_set->eject_document (dev);
|
||||
DBG (DBG_error,
|
||||
"genesys_sheetfed_calibration: failed to do white shading calibration: %s\n",
|
||||
"genesys_sheetfed_calibration: failed eject target: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
/* in case we haven't black shading data, build it from black pixels
|
||||
* of white calibration */
|
||||
if (!(dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION))
|
||||
{
|
||||
/* XXX STEF TODO XXX */
|
||||
}
|
||||
|
||||
/* send the shading coefficient */
|
||||
status = genesys_send_shading_coefficient (dev);
|
||||
|
|
|
@ -104,8 +104,8 @@ static Genesys_Frontend Wolfson[] = {
|
|||
, /* 6: CANONLIDE35 */
|
||||
{DAC_AD_XP200,{0x58, 0x00, 0x00, 0x00} /* TODO create an AnalogDevice struct */
|
||||
, {0x00, 0x00, 0x00}
|
||||
, {0x0a, 0x00, 0x00} /* offset */
|
||||
, {0x20, 0x00, 0x00} /* gain */
|
||||
, {0x05, 0x00, 0x00} /* offset */ /* 0A */
|
||||
, {0x0d, 0x00, 0x00} /* gain */ /* 20 */
|
||||
, {0x00, 0x00, 0x00}
|
||||
}
|
||||
,
|
||||
|
@ -251,7 +251,7 @@ static Genesys_Sensor Sensor[] = {
|
|||
/* 7: Strobe XP200 */
|
||||
{CIS_XP200, 600,
|
||||
48,
|
||||
38, 0, 5454, 210, 200,
|
||||
38, 0, 5200, 210, 200, /* 5125 */
|
||||
{0x16, 0x00, 0x01, 0x03}
|
||||
,
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a,
|
||||
|
@ -977,7 +977,7 @@ Genesys_Model visioneer_xp200_model = {
|
|||
| GENESYS_FLAG_DARK_CALIBRATION
|
||||
| GENESYS_FLAG_NO_CALIBRATION,
|
||||
GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE,
|
||||
20,
|
||||
120,
|
||||
132
|
||||
};
|
||||
|
||||
|
|
|
@ -159,6 +159,8 @@ gl646_bulk_write_register (Genesys_Device * dev,
|
|||
{
|
||||
DBG (DBG_io2, "DPISET =%d\n",
|
||||
gl646_get_double_reg (reg, REG_DPISET));
|
||||
DBG (DBG_io2, "DUMMY =%d\n",
|
||||
sanei_genesys_get_address (reg, REG_DUMMY)->value);
|
||||
DBG (DBG_io2, "STRPIXEL =%d\n",
|
||||
gl646_get_double_reg (reg, REG_STRPIXEL));
|
||||
DBG (DBG_io2, "ENDPIXEL =%d\n",
|
||||
|
@ -886,9 +888,15 @@ gl646_setup_registers (Genesys_Device * dev,
|
|||
else
|
||||
regs[reg_0x05].value &= ~REG05_GMMENB;
|
||||
|
||||
/* true CIS gray */
|
||||
/* true CIS gray if needed */
|
||||
if (dev->model->is_cis == SANE_TRUE && color == SANE_FALSE)
|
||||
regs[reg_0x05].value |= REG05_LEDADD;
|
||||
{
|
||||
regs[reg_0x05].value |= REG05_LEDADD;
|
||||
}
|
||||
else
|
||||
{
|
||||
regs[reg_0x05].value &= ~REG05_LEDADD;
|
||||
}
|
||||
|
||||
/* cktoggle, ckdelay and cksel at once, cktdelay=2 => half_ccd for md5345 */
|
||||
regs[reg_0x18].value = sensor->reg_0x18;
|
||||
|
@ -1510,7 +1518,7 @@ gl646_init_regs (Genesys_Device * dev)
|
|||
dev->reg[reg_0x2e].value = 0x78; /* set black&white threshold high level */
|
||||
dev->reg[reg_0x2f].value = 0x7f; /* set black&white threshold low level */
|
||||
|
||||
dev->reg[reg_0x30].value = 0x00; /* begin pixel positon (16) */
|
||||
dev->reg[reg_0x30].value = 0x00; /* begin pixel position (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) */
|
||||
dev->reg[reg_0x33].value = 0xf8 /*0x0e */ ; /* TGW + 2*TG_SHLD + y */
|
||||
|
@ -2011,7 +2019,10 @@ gl646_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
|
|||
* HOMESNR becomes 1 ->document left sensor
|
||||
* paper event -> document is out
|
||||
*/
|
||||
static SANE_Status
|
||||
#ifndef UNIT_TESTING
|
||||
static
|
||||
#endif
|
||||
SANE_Status
|
||||
gl646_load_document (Genesys_Device * dev)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
@ -2262,12 +2273,12 @@ gl646_eject_document (Genesys_Device * dev)
|
|||
Genesys_Register_Set regs[11];
|
||||
unsigned int used, vfinal, count;
|
||||
uint16_t slope_table[255];
|
||||
uint8_t val;
|
||||
uint8_t gpio, state;
|
||||
|
||||
DBG (DBG_proc, "gl646_eject_document: start\n");
|
||||
|
||||
/* first check for document event */
|
||||
status = gl646_gpio_read (dev->dn, &val);
|
||||
status = gl646_gpio_read (dev->dn, &gpio);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -2275,19 +2286,10 @@ gl646_eject_document (Genesys_Device * dev)
|
|||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", val);
|
||||
|
||||
/* no need for eject if document left during regular scan */
|
||||
if (val != 0)
|
||||
{
|
||||
dev->document = SANE_FALSE;
|
||||
DBG (DBG_info, "gl646_eject_document: no more document to eject\n");
|
||||
DBG (DBG_proc, "gl646_eject_document: end\n");
|
||||
return status;
|
||||
}
|
||||
DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", gpio);
|
||||
|
||||
/* test status : paper event + HOMESNR -> no more doc ? */
|
||||
status = sanei_genesys_get_status (dev, &val);
|
||||
status = sanei_genesys_get_status (dev, &state);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -2295,7 +2297,22 @@ gl646_eject_document (Genesys_Device * dev)
|
|||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
DBG (DBG_info, "gl646_eject_document: state=0x%02x\n", state);
|
||||
if (DBG_LEVEL > DBG_info)
|
||||
{
|
||||
print_status (state);
|
||||
}
|
||||
|
||||
/* HOMSNR=0 if no document inserted */
|
||||
if ((state & REG41_HOMESNR) != 0)
|
||||
{
|
||||
dev->document = SANE_FALSE;
|
||||
DBG (DBG_info, "gl646_eject_document: no more document to eject\n");
|
||||
DBG (DBG_proc, "gl646_eject_document: end\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
/* there is a document inserted, eject it */
|
||||
status = sanei_genesys_write_register (dev, 0x01, 0xb0);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
|
@ -2309,7 +2326,7 @@ gl646_eject_document (Genesys_Device * dev)
|
|||
do
|
||||
{
|
||||
usleep (200000UL);
|
||||
status = sanei_genesys_get_status (dev, &val);
|
||||
status = sanei_genesys_get_status (dev, &state);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -2318,7 +2335,7 @@ gl646_eject_document (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
}
|
||||
while (val & REG41_MOTMFLG);
|
||||
while (state & REG41_MOTMFLG);
|
||||
|
||||
/* set up to fast move before scan then move until document is detected */
|
||||
regs[0].address = 0x01;
|
||||
|
@ -2397,8 +2414,8 @@ gl646_eject_document (Genesys_Device * dev)
|
|||
count = 0;
|
||||
do
|
||||
{
|
||||
status = sanei_genesys_get_status (dev, &val);
|
||||
print_status (val);
|
||||
status = sanei_genesys_get_status (dev, &state);
|
||||
print_status (state);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -2409,7 +2426,18 @@ gl646_eject_document (Genesys_Device * dev)
|
|||
usleep (200000UL); /* sleep 200 ms */
|
||||
count++;
|
||||
}
|
||||
while (((val & REG41_HOMESNR) == 0) && (count < 150));
|
||||
while (((state & REG41_HOMESNR) == 0) && (count < 150));
|
||||
|
||||
/* read GPIO on exit */
|
||||
status = gl646_gpio_read (dev->dn, &gpio);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl646_eject_document: failed to read paper sensor %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", gpio);
|
||||
|
||||
DBG (DBG_proc, "gl646_eject_document: end\n");
|
||||
return status;
|
||||
|
@ -2758,7 +2786,7 @@ gl646_search_start_position (Genesys_Device * dev)
|
|||
settings.exposure_time = 0;
|
||||
|
||||
/* scan the desired area */
|
||||
status = simple_scan (dev, settings, SANE_TRUE, SANE_TRUE, &data);
|
||||
status = simple_scan (dev, settings, SANE_TRUE, SANE_TRUE, SANE_FALSE, &data);
|
||||
|
||||
/* process data if scan is OK */
|
||||
if (status == SANE_STATUS_GOOD)
|
||||
|
@ -2899,7 +2927,15 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
|
|||
|
||||
/* 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->is_cis == SANE_FALSE)
|
||||
{
|
||||
gl646_set_triple_reg (dev->reg, REG_LINCNT, dev->model->shading_lines);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl646_set_triple_reg (dev->reg, REG_LINCNT,
|
||||
dev->model->shading_lines * 3);
|
||||
}
|
||||
|
||||
/* copy reg to calib_reg */
|
||||
memcpy (dev->calib_reg, dev->reg,
|
||||
|
@ -2938,6 +2974,7 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
|
|||
}
|
||||
dev->scanhead_position_in_steps = 0;
|
||||
}
|
||||
|
||||
return setup_for_scan (dev, dev->settings, SANE_FALSE, SANE_TRUE,
|
||||
SANE_TRUE);
|
||||
}
|
||||
|
@ -3346,7 +3383,7 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
dev->frontend.offset[0] = bottom;
|
||||
dev->frontend.offset[1] = bottom;
|
||||
dev->frontend.offset[2] = bottom;
|
||||
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &first_line);
|
||||
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &first_line);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -3372,7 +3409,7 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
dev->frontend.offset[0] = top;
|
||||
dev->frontend.offset[1] = top;
|
||||
dev->frontend.offset[2] = top;
|
||||
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &second_line);
|
||||
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -3403,7 +3440,7 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
|
||||
/* scan with no move */
|
||||
status =
|
||||
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &second_line);
|
||||
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -3442,7 +3479,7 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
status =
|
||||
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &second_line);
|
||||
simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -3542,7 +3579,7 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi)
|
|||
|| (average[2] < dev->sensor.gain_white_ref)) && (pass < 30))
|
||||
{
|
||||
/* scan with no move */
|
||||
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, &line);
|
||||
status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE,&line);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -4053,9 +4090,12 @@ gl646_init (Genesys_Device * dev)
|
|||
* @param move SANE_TRUE if moving forward during scan
|
||||
* @param data pointer for the data
|
||||
*/
|
||||
static SANE_Status
|
||||
#ifndef UNIT_TESTING
|
||||
static
|
||||
#endif
|
||||
SANE_Status
|
||||
simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
||||
SANE_Bool forward, unsigned char **data)
|
||||
SANE_Bool forward, SANE_Bool shading, unsigned char **data)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_INVAL;
|
||||
unsigned int size, lines, x, y, bpp;
|
||||
|
@ -4093,7 +4133,7 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
else
|
||||
bpp = 1;
|
||||
size *= bpp;
|
||||
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
|
||||
if (settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
|
||||
size *= 3;
|
||||
*data = malloc (size);
|
||||
if (!*data)
|
||||
|
@ -4103,6 +4143,9 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
/* put back real line number in settings */
|
||||
settings.lines = lines;
|
||||
|
||||
/* initialize frontend */
|
||||
status = gl646_set_fe (dev, AFE_SET);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
@ -4116,6 +4159,10 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
|
||||
/* no shading correction and not watch dog for simple scan */
|
||||
dev->reg[reg_0x01].value &= ~(REG01_DVDSET | REG01_DOGENB);
|
||||
if(shading==SANE_TRUE)
|
||||
{
|
||||
dev->reg[reg_0x01].value |= REG01_DVDSET;
|
||||
}
|
||||
|
||||
/* one table movement for simple scan */
|
||||
dev->reg[reg_0x02].value &= ~REG02_FASTFED;
|
||||
|
@ -4181,59 +4228,50 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
&& settings.scan_mode == SCAN_MODE_COLOR)
|
||||
{
|
||||
/* alloc one line sized working buffer */
|
||||
size = size / settings.lines;
|
||||
buffer = (unsigned char *) malloc (size);
|
||||
buffer = (unsigned char *) malloc (settings.pixels * 3 * bpp);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"simple_scan: failed to allocate %d bytes of memory\n", size);
|
||||
"simple_scan: failed to allocate %d bytes of memory\n", settings.pixels * 3);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
/* reorder one line of data and put it back to buffer */
|
||||
if (bpp == 1)
|
||||
{
|
||||
for (y = 0; y < settings.lines; y++)
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
/* reorder line */
|
||||
for (x = 0; x < settings.pixels; x++)
|
||||
{
|
||||
buffer[x * 3] = (*data)[y * size + x];
|
||||
buffer[x * 3 + 1] = (*data)[y * size + settings.pixels + x];
|
||||
buffer[x * 3 + 2] =
|
||||
(*data)[y * size + 2 * settings.pixels + x];
|
||||
buffer[x * 3 ] = (*data)[y * settings.pixels * 3 + x];
|
||||
buffer[x * 3 + 1] = (*data)[y * settings.pixels * 3 + settings.pixels + x];
|
||||
buffer[x * 3 + 2] = (*data)[y * settings.pixels * 3 + 2 * settings.pixels + x];
|
||||
}
|
||||
/* copy line back */
|
||||
memcpy ((*data) + size * y, buffer, size);
|
||||
memcpy ((*data) + settings.pixels * 3 * y, buffer, settings.pixels * 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < settings.lines; y++)
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
/* reorder line */
|
||||
for (x = 0; x < settings.pixels; x++)
|
||||
{
|
||||
buffer[x * 6] = (*data)[y * size + x];
|
||||
buffer[x * 6 + 1] = (*data)[y * size + x + 1];
|
||||
buffer[x * 6 + 2] = (*data)[y * size + settings.pixels + x];
|
||||
buffer[x * 6 + 3] =
|
||||
(*data)[y * size + settings.pixels + x + 1];
|
||||
buffer[x * 6 + 4] =
|
||||
(*data)[y * size + 2 * settings.pixels + x];
|
||||
buffer[x * 6 + 5] =
|
||||
(*data)[y * size + 2 * settings.pixels + x + 1];
|
||||
buffer[x * 6 ] = (*data)[y * settings.pixels * 6 + x * 2 ];
|
||||
buffer[x * 6 + 1] = (*data)[y * settings.pixels * 6 + x * 2 + 1];
|
||||
buffer[x * 6 + 2] = (*data)[y * settings.pixels * 6 + 2 * settings.pixels + x * 2 ];
|
||||
buffer[x * 6 + 3] = (*data)[y * settings.pixels * 6 + 2 * settings.pixels + x * 2 + 1];
|
||||
buffer[x * 6 + 4] = (*data)[y * settings.pixels * 6 + 4 * settings.pixels + x * 2 ];
|
||||
buffer[x * 6 + 5] = (*data)[y * settings.pixels * 6 + 4 * settings.pixels + x * 2 + 1];
|
||||
}
|
||||
/* copy line back */
|
||||
memcpy ((*data) + size * y, buffer, size);
|
||||
memcpy ((*data) + settings.pixels * 6 * y, buffer, settings.pixels * 6);
|
||||
}
|
||||
}
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
/* put back real line number in settings */
|
||||
/* XXX STEF XXX */
|
||||
settings.lines = lines;
|
||||
|
||||
/* 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);
|
||||
|
@ -4523,7 +4561,7 @@ gl646_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
|
|||
settings.yres = res;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = (SANE_UNFIX (dev->model->x_size) * res) / MM_PER_INCH;
|
||||
settings.pixels = (SANE_UNFIX (dev->model->x_size) * res) / MM_PER_INCH;
|
||||
if (half_ccd == SANE_TRUE)
|
||||
{
|
||||
settings.pixels /= 2;
|
||||
|
@ -4548,7 +4586,7 @@ gl646_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
|
|||
while (pass < 20 && !found)
|
||||
{
|
||||
/* scan a full width strip */
|
||||
status = simple_scan (dev, settings, SANE_TRUE, forward, &data);
|
||||
status = simple_scan (dev, settings, SANE_TRUE, forward, SANE_FALSE, &data);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_search_strip: simple_scan failed\n");
|
||||
|
@ -4557,7 +4595,8 @@ gl646_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
|
|||
}
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
sprintf (title, "search_strip_%s%02d.pnm", forward ? "fwd" : "bwd", pass);
|
||||
sprintf (title, "search_strip_%s%02d.pnm", forward ? "fwd" : "bwd",
|
||||
pass);
|
||||
sanei_genesys_write_pnm_file (title, data, settings.depth, 1,
|
||||
settings.pixels, settings.lines);
|
||||
}
|
||||
|
|
|
@ -173,6 +173,7 @@
|
|||
#define REG_DPISET 0x2c
|
||||
#define REG_STRPIXEL 0x30
|
||||
#define REG_ENDPIXEL 0x32
|
||||
#define REG_DUMMY 0x34
|
||||
#define REG_MAXWD 0x35
|
||||
#define REG_LPERIOD 0x38
|
||||
#define REG_FEEDL 0x3d
|
||||
|
@ -316,11 +317,15 @@ gl646_setup_registers (Genesys_Device * dev,
|
|||
* @param settings settings of the scan
|
||||
* @param move flag to enable scanhead to move
|
||||
* @param forward flag to tell movement direction
|
||||
* @param shading flag to tell if shading correction should be done
|
||||
* @param data pointer that will point to the scanned data
|
||||
*/
|
||||
static SANE_Status
|
||||
#ifndef UNIT_TESTING
|
||||
static
|
||||
#endif
|
||||
SANE_Status
|
||||
simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, SANE_Bool forward,
|
||||
unsigned char **data);
|
||||
SANE_Bool shading, unsigned char **data);
|
||||
|
||||
/**
|
||||
* Send the stop scan command
|
||||
|
@ -339,6 +344,11 @@ static SANE_Status write_control (Genesys_Device * dev, int resolution);
|
|||
*/
|
||||
static void gl646_init_regs (Genesys_Device * dev);
|
||||
|
||||
#ifndef UNIT_TESTING
|
||||
static
|
||||
#endif
|
||||
SANE_Status gl646_load_document (Genesys_Device * dev);
|
||||
|
||||
|
||||
#define FULL_STEP 0
|
||||
#define HALF_STEP 1
|
||||
|
|
Ładowanie…
Reference in New Issue