kopia lustrzana https://gitlab.com/sane-project/backends
LiDE 80 WIP:
- 1200 shading working - 600 and below resolution are ok, but shading needs to be fixed - 1200 dpi motor resolution doesn't workmerge-requests/1/head
rodzic
ebcc2c0a3f
commit
e500d44e65
|
@ -919,10 +919,11 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
|
|||
int start_address;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (DBG_proc, "genesys_send_offset_and_shading (size = %d)\n", size);
|
||||
DBG (DBG_proc, "%s: (size = %d)\n", __FUNCTION__, size);
|
||||
|
||||
/* ASIC higher than gl843 doesn't have register 2A/2B, so we route to
|
||||
* a per ASIC shading data loading function if available */
|
||||
* a per ASIC shading data loading function if available.
|
||||
* It is also used for scanners using SHDAREA */
|
||||
if(dev->model->cmd_set->send_shading_data!=NULL)
|
||||
{
|
||||
status=dev->model->cmd_set->send_shading_data(dev, data, size);
|
||||
|
@ -946,6 +947,7 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
|
|||
&& dev->model->ccd_type != CCD_XP300
|
||||
&& dev->model->ccd_type != CCD_DP665
|
||||
&& dev->model->ccd_type != CCD_DP685
|
||||
&& dev->model->ccd_type != CIS_CANONLIDE80
|
||||
&& dev->model->ccd_type != CCD_ROADWARRIOR
|
||||
&& dev->model->ccd_type != CCD_HP2300
|
||||
&& dev->model->ccd_type != CCD_HP2400
|
||||
|
@ -967,17 +969,15 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
|
|||
status = sanei_genesys_set_buffer_address (dev, start_address);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_send_offset_and_shading: failed to set buffer address: %s\n",
|
||||
sane_strstatus (status));
|
||||
DBG (DBG_error, "%s: failed to set buffer address: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_send_offset_and_shading: failed to send shading table: %s\n",
|
||||
DBG (DBG_error, "%s: failed to send shading table: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
@ -1031,15 +1031,15 @@ sanei_genesys_init_shading_data (Genesys_Device * dev, int pixels_per_line)
|
|||
*shading_data_ptr++ = 0x40; /* white hi -> 0x4000 */
|
||||
}
|
||||
|
||||
status =
|
||||
genesys_send_offset_and_shading (dev, shading_data,
|
||||
pixels_per_line * 4 * channels);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
DBG (DBG_error,
|
||||
"sanei_genesys_init_shading_data: failed to send shading data: %s\n",
|
||||
sane_strstatus (status));
|
||||
|
||||
status = genesys_send_offset_and_shading (dev,
|
||||
shading_data,
|
||||
pixels_per_line * 4 * channels);
|
||||
free (shading_data);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "%s: failed to send shading data: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
}
|
||||
|
||||
DBGCOMPLETED;
|
||||
return status;
|
||||
|
@ -2153,7 +2153,7 @@ genesys_white_shading_calibration (Genesys_Device * dev)
|
|||
/* This calibration uses a scan over the calibration target, comprising a
|
||||
* black and a white strip. (So the motor must be on.)
|
||||
*/
|
||||
static SANE_Status
|
||||
GENESYS_STATIC SANE_Status
|
||||
genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
||||
{
|
||||
SANE_Status status;
|
||||
|
@ -2168,8 +2168,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
SANE_Bool motor;
|
||||
|
||||
|
||||
DBG (DBG_proc, "genesys_black_white_shading_calibration (lines = %d)\n",
|
||||
(unsigned int)dev->calib_lines);
|
||||
DBG (DBG_proc, "%s: (lines = %d)\n", __FUNCTION__, (unsigned int)dev->calib_lines);
|
||||
|
||||
pixels_per_line = dev->calib_pixels;
|
||||
channels = dev->calib_channels;
|
||||
|
@ -2182,8 +2181,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
dev->white_average_data = malloc (dev->average_size);
|
||||
if (!dev->white_average_data)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_white_shading_calibration: failed to allocate average memory\n");
|
||||
DBG (DBG_error, "%s: failed to allocate white average memory\n", __FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -2193,8 +2191,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
dev->dark_average_data = malloc (channels * 2 * pixels_per_line);
|
||||
if (!dev->dark_average_data)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_white_shading_shading_calibration: failed to allocate average memory\n");
|
||||
DBG (DBG_error, "%s: failed to allocate dark average memory\n", __FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -2203,8 +2200,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
calibration_data = malloc (size);
|
||||
if (!calibration_data)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_white_shading_calibration: failed to allocate calibration memory\n");
|
||||
DBG (DBG_error, "%s: failed to allocate calibration memory\n", __FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -2225,9 +2221,8 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (calibration_data);
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_white_shading_calibration: failed to bulk write registers: %s\n",
|
||||
sane_strstatus (status));
|
||||
DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -2236,8 +2231,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (calibration_data);
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_white_shading_calibration: Failed to begin scan: %s\n",
|
||||
DBG (DBG_error, "%s: failed to begin scan: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
@ -2246,8 +2240,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (calibration_data);
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_white_shading_calibration: Failed to read data: %s\n",
|
||||
DBG (DBG_error, "%s: failed to read data: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
@ -2256,16 +2249,26 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (calibration_data);
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_white_shading_calibration: Failed to end scan: %s\n",
|
||||
DBG (DBG_error, "%s: Failed to end scan: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data,
|
||||
16, channels, pixels_per_line,
|
||||
dev->calib_lines);
|
||||
{
|
||||
if (dev->model->is_cis)
|
||||
{
|
||||
sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data,
|
||||
16, 1, pixels_per_line*channels,
|
||||
dev->calib_lines);
|
||||
}
|
||||
else
|
||||
{
|
||||
sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data,
|
||||
16, channels, pixels_per_line,
|
||||
dev->calib_lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
average_white = dev->white_average_data;
|
||||
|
@ -2418,8 +2421,8 @@ compute_averaged_planar (Genesys_Device * dev,
|
|||
{
|
||||
unsigned int x, i, j, br, dk, res, avgpixels, basepixels, val;
|
||||
|
||||
DBG (DBG_info, "%s: pixels=%d, offset=%d\n", __FUNCTION__, pixels_per_line,
|
||||
o);
|
||||
DBG (DBG_info, "%s: pixels=%d, offset=%d\n", __FUNCTION__, pixels_per_line, o);
|
||||
|
||||
/* initialize result */
|
||||
memset (shading_data, 0xff, words_per_color * 3 * 2);
|
||||
|
||||
|
@ -2455,10 +2458,10 @@ compute_averaged_planar (Genesys_Device * dev,
|
|||
if ((dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE) &&
|
||||
dev->settings.xres <= dev->sensor.optical_res / 2)
|
||||
res *= 2; /* scanner is using half-ccd mode */
|
||||
/*this should be evenly dividable */
|
||||
/* this should be evenly dividable */
|
||||
basepixels = dev->sensor.optical_res / res;
|
||||
|
||||
/* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */
|
||||
/* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */
|
||||
if (basepixels < 1)
|
||||
avgpixels = 1;
|
||||
else if (basepixels < 6)
|
||||
|
@ -2478,7 +2481,6 @@ compute_averaged_planar (Genesys_Device * dev,
|
|||
|
||||
for (x = 0; x <= pixels_per_line - avgpixels; x += avgpixels)
|
||||
{
|
||||
|
||||
if ((x + o) * 2 * 2 + 3 > words_per_color * 2)
|
||||
break;
|
||||
|
||||
|
@ -2515,59 +2517,47 @@ compute_averaged_planar (Genesys_Device * dev,
|
|||
65535 * (target_bright - target_dark))
|
||||
val = 65535;
|
||||
else
|
||||
val =
|
||||
(dk * target_bright - br * target_dark) / (target_bright -
|
||||
target_dark);
|
||||
{
|
||||
val = (dk * target_bright - br * target_dark) / (target_bright - target_dark);
|
||||
}
|
||||
|
||||
/*fill all pixels, even if only the last one is relevant*/
|
||||
/*fill all pixels, even if only the last one is relevant*/
|
||||
for (i = 0; i < avgpixels; i++)
|
||||
{
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j] = val & 0xff;
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j + 1] = val >> 8;
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j] = val & 0xff;
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 1] = val >> 8;
|
||||
}
|
||||
|
||||
val = br - dk;
|
||||
|
||||
if (65535 * val > (target_bright - target_dark) * coeff)
|
||||
val = (coeff * (target_bright - target_dark)) / val;
|
||||
{
|
||||
val = (coeff * (target_bright - target_dark)) / val;
|
||||
}
|
||||
else
|
||||
val = 65535;
|
||||
{
|
||||
val = 65535;
|
||||
}
|
||||
|
||||
/*fill all pixels, even if only the last one is relevant*/
|
||||
/*fill all pixels, even if only the last one is relevant*/
|
||||
for (i = 0; i < avgpixels; i++)
|
||||
{
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j + 2] = val & 0xff;
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j + 3] = val >> 8;
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 2] = val & 0xff;
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 3] = val >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
/*fill remaining channels*/
|
||||
/* fill remaining channels */
|
||||
for (j = channels; j < 3; j++)
|
||||
{
|
||||
for (i = 0; i < avgpixels; i++)
|
||||
{
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j] =
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 0];
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j + 1] =
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * 0 + 1];
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j + 2] =
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * 0 + 2];
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * j + 3] =
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 2 * 0 + 3];
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j ] = shading_data[(x + o + i) * 2 * 2 ];
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 1] = shading_data[(x + o + i) * 2 * 2 + 1];
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 2] = shading_data[(x + o + i) * 2 * 2 + 2];
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 3] = shading_data[(x + o + i) * 2 * 2 + 3];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2870,13 +2860,21 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
break;
|
||||
}
|
||||
|
||||
/* special case, memory is aligned on 0x5400, this has yet to be explained */
|
||||
/* could be 0xa800 because sensor is truly 2400 dpi, then halved because
|
||||
* we only set 1200 dpi */
|
||||
if(dev->model->ccd_type==CIS_CANONLIDE80)
|
||||
{
|
||||
words_per_color = 0x5400;
|
||||
}
|
||||
|
||||
length = words_per_color * 3 * 2;
|
||||
|
||||
/* allocate computed size */
|
||||
shading_data = malloc (length);
|
||||
if (!shading_data)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_send_shading_coefficient: failed to allocate memory\n");
|
||||
DBG (DBG_error, "%s: failed to allocate memory\n", __FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
memset (shading_data, 0, length);
|
||||
|
@ -3040,8 +3038,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
shading_data = malloc (length);
|
||||
if (!shading_data)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_send_shading_coefficient: failed to allocate memory\n");
|
||||
DBG (DBG_error, "%s: failed to allocate memory\n", __FUNCTION__);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
memset (shading_data, 0, length);
|
||||
|
@ -3057,7 +3054,6 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
target_code);
|
||||
break;
|
||||
case CCD_CANONLIDE35:
|
||||
case CIS_CANONLIDE80:
|
||||
compute_averaged_planar (dev,
|
||||
shading_data,
|
||||
pixels_per_line,
|
||||
|
@ -3068,6 +3064,17 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
0xfa00,
|
||||
0x0a00);
|
||||
break;
|
||||
case CIS_CANONLIDE80:
|
||||
compute_averaged_planar (dev,
|
||||
shading_data,
|
||||
pixels_per_line,
|
||||
words_per_color,
|
||||
channels,
|
||||
0,
|
||||
coeff,
|
||||
0xfa00,
|
||||
0x0a00);
|
||||
break;
|
||||
case CCD_PLUSTEK_3600:
|
||||
compute_shifted_coefficients (dev,
|
||||
shading_data,
|
||||
|
@ -3081,23 +3088,21 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
256); /* patch_size: contigous extent */
|
||||
break;
|
||||
default:
|
||||
DBG (DBG_error,
|
||||
"genesys_send_shading_coefficient: sensor %d not supported\n",
|
||||
dev->model->ccd_type);
|
||||
DBG (DBG_error, "%s: sensor %d not supported\n", __FUNCTION__, dev->model->ccd_type);
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* do the actual write of shading calibration data to the scanner */
|
||||
status = genesys_send_offset_and_shading (dev, shading_data, length);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
DBG (DBG_error,
|
||||
"genesys_send_shading_coefficient: failed to send shading data: %s\n",
|
||||
sane_strstatus (status));
|
||||
|
||||
free (shading_data);
|
||||
DBGCOMPLETED;
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "%s: failed to send shading data: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
}
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,4 +146,7 @@ typedef struct Genesys_Scanner
|
|||
SANE_Int bpp_list[5]; /**< */
|
||||
} Genesys_Scanner;
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
SANE_Status genesys_dark_white_shading_calibration (Genesys_Device * dev);
|
||||
#endif
|
||||
#endif /* not GENESYS_H */
|
||||
|
|
|
@ -305,11 +305,12 @@ static Genesys_Sensor Sensor[] = {
|
|||
}
|
||||
,
|
||||
/* CANOLIDE35 */
|
||||
{CCD_CANONLIDE35, 1200,
|
||||
87, /*(black) */
|
||||
{CCD_CANONLIDE35,
|
||||
1200,
|
||||
87, /* (black) */
|
||||
87, /* (dummy) */
|
||||
0, /* (startxoffset) */
|
||||
10400, /*sensor_pixels */
|
||||
10400, /* sensor_pixels */
|
||||
210,
|
||||
200,
|
||||
{0x00, 0x00, 0x00, 0x00},
|
||||
|
@ -760,10 +761,10 @@ static Genesys_Sensor Sensor[] = {
|
|||
/* CANOLIDE80 */
|
||||
{CIS_CANONLIDE80,
|
||||
1200, /* real hardware limit is 2400 */
|
||||
9*2,
|
||||
9*2,
|
||||
0,
|
||||
10304, /* up to 5144, 5390, 10264, 20504, 21762 : capped by max exposure from logs */
|
||||
20, /* black pixels */
|
||||
6, /* expdummy */
|
||||
31, /* CCD_start_xoffset 14=>3, 20=>2 */
|
||||
10240, /* 10400, too wide=>10288 in shading data 10240~, 10208 too short for shading, max shading data = 10240 pixels, endpix-startpix=10208 */
|
||||
230,
|
||||
230,
|
||||
{0x00, 0x05, 0x07, 0x09}, /* in fact ,maps to 0x70-0x73 for GL841 */
|
||||
|
@ -1288,16 +1289,16 @@ static Genesys_Motor Motor[] = {
|
|||
},},
|
||||
{MOTOR_CANONLIDE80,
|
||||
2400, /* 2400 ???? */
|
||||
7200,
|
||||
2, /* max step type */
|
||||
9600, /* 7200 ???? */
|
||||
1, /* max step type */
|
||||
1, /* power mode count */
|
||||
{
|
||||
{ /* start speed, max end speed, step number */
|
||||
/* 5144 = max pixels at 600 dpi */
|
||||
/* 1288=(5144+8)*ydpi(=300)/base_dpi(=1200) , where 5152 is exposure */
|
||||
/* 6440=9660/(1932/1288) */
|
||||
{ 6440, 1288, 60, 0.8 }, /* full step 9660 1932 32 values from logs */
|
||||
{ 18750, 1875, 60, 0.8 }, /* half step 18750 1875 16 values from logs */
|
||||
{ 6440, 1288, 60, 0.8 }, /* full step 9660 1932 32 values from logs */
|
||||
{ 15869, 15869, 16, 0.8 }, /* half step 18750 1875 16 values from logs */
|
||||
},
|
||||
},},
|
||||
};
|
||||
|
@ -1360,8 +1361,8 @@ static Genesys_Model canon_lide_50_model = {
|
|||
GENESYS_GL841,
|
||||
NULL,
|
||||
|
||||
{1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */
|
||||
{2400, 1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */
|
||||
{ 1200, 600, 400, 300, 240, 200, 150, 75, 0}, /* possible x-resolutions */
|
||||
{2400, 1200, 600, 400, 300, 240, 200, 150, 75, 0}, /* possible y-resolutions */
|
||||
{16, 8, 0}, /* possible depths in gray mode */
|
||||
{16, 8, 0}, /* possible depths in color mode */
|
||||
|
||||
|
@ -2128,14 +2129,14 @@ static Genesys_Model canon_lide_80_model = {
|
|||
GENESYS_GL841,
|
||||
NULL,
|
||||
|
||||
{ 1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */
|
||||
{2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */
|
||||
{ 1200, 600, 400, 300, 240, 150, 100, 75, 0}, /* possible x-resolutions */
|
||||
{2400, 1200, 600, 400, 300, 240, 150, 100, 75, 0}, /* possible y-resolutions */
|
||||
{16, 8, 0}, /* possible depths in gray mode */
|
||||
{16, 8, 0}, /* possible depths in color mode */
|
||||
|
||||
SANE_FIX (6.5), /* Start of scan area in mm (x) */
|
||||
SANE_FIX (7.9), /* Start of scan area in mm (y) */
|
||||
SANE_FIX (218.0), /* Size of scan area in mm (x) */
|
||||
SANE_FIX (0.42), /* Start of scan area in mm (x) 0.42 */
|
||||
SANE_FIX (7.90), /* Start of scan area in mm (y) 7.90 */
|
||||
SANE_FIX (216.07), /* Size of scan area in mm (x) 218.00 */
|
||||
SANE_FIX (299.0), /* Size of scan area in mm (y) */
|
||||
|
||||
SANE_FIX (3.0), /* Start of white strip in mm (y) */
|
||||
|
@ -2173,7 +2174,7 @@ static Genesys_Model canon_lide_80_model = {
|
|||
GENESYS_HAS_FILE_SW |
|
||||
GENESYS_HAS_EMAIL_SW |
|
||||
GENESYS_HAS_COPY_SW,
|
||||
200,
|
||||
280,
|
||||
400
|
||||
};
|
||||
|
||||
|
|
|
@ -214,8 +214,8 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr,
|
|||
uint8_t * data, size_t len)
|
||||
{
|
||||
SANE_Status status;
|
||||
size_t size;
|
||||
uint8_t outdata[8];
|
||||
size_t size, target;
|
||||
uint8_t outdata[8], *buffer;
|
||||
|
||||
DBG (DBG_io, "gl841_bulk_read_data: requesting %lu bytes\n",
|
||||
(u_long) len);
|
||||
|
@ -254,12 +254,14 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr,
|
|||
return status;
|
||||
}
|
||||
|
||||
while (len)
|
||||
target = len;
|
||||
buffer = data;
|
||||
while (target)
|
||||
{
|
||||
if (len > BULKIN_MAXSIZE)
|
||||
if (target > BULKIN_MAXSIZE)
|
||||
size = BULKIN_MAXSIZE;
|
||||
else
|
||||
size = len;
|
||||
size = target;
|
||||
|
||||
DBG (DBG_io2,
|
||||
"gl841_bulk_read_data: trying to read %lu bytes of data\n",
|
||||
|
@ -277,14 +279,18 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr,
|
|||
|
||||
DBG (DBG_io2,
|
||||
"gl841_bulk_read_data read %lu bytes, %lu remaining\n",
|
||||
(u_long) size, (u_long) (len - size));
|
||||
(u_long) size, (u_long) (target - size));
|
||||
|
||||
len -= size;
|
||||
target -= size;
|
||||
data += size;
|
||||
}
|
||||
|
||||
DBG (DBG_io, "gl841_bulk_read_data: completed\n");
|
||||
|
||||
if (DBG_LEVEL >= DBG_data && dev->binary!=NULL)
|
||||
{
|
||||
fwrite(buffer, len, 1, dev->binary);
|
||||
}
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -788,12 +794,12 @@ gl841_init_lide80 (Genesys_Device * dev)
|
|||
uint8_t val;
|
||||
int index=0;
|
||||
|
||||
INITREG (0x01, 0x02);
|
||||
INITREG (0x01, 0x82); /* 0x02 = SHDAREA and no CISSET ! */
|
||||
INITREG (0x02, 0x10);
|
||||
INITREG (0x03, 0x50);
|
||||
INITREG (0x04, 0x02);
|
||||
INITREG (0x05, 0x4c);
|
||||
INITREG (0x06, 0x38);
|
||||
INITREG (0x05, 0x4c); /* 1200 DPI */
|
||||
INITREG (0x06, 0x30); /* 0x38 scanmod=1, pwrbit, GAIN4 */
|
||||
INITREG (0x07, 0x00);
|
||||
INITREG (0x08, 0x00);
|
||||
INITREG (0x09, 0x11);
|
||||
|
@ -1975,8 +1981,11 @@ gl841_init_motor_regs_scan(Genesys_Device * dev,
|
|||
&fast_slope_steps,
|
||||
&fast_exposure,
|
||||
scan_power_mode);
|
||||
|
||||
if (dev->model->gpo_type == GPO_XP300 || dev->model->gpo_type == GPO_DP685)
|
||||
|
||||
/* fast fed special cases handling */
|
||||
if (dev->model->gpo_type == GPO_XP300
|
||||
|| ((dev->model->motor_type== MOTOR_CANONLIDE80) && (scan_yres>600)) /* no fast fed at high res for this motor */
|
||||
|| dev->model->gpo_type == GPO_DP685)
|
||||
{
|
||||
/* quirk: looks like at least this scanner is unable to use
|
||||
2-feed mode */
|
||||
|
@ -2428,19 +2437,9 @@ gl841_init_optical_regs_scan(Genesys_Device * dev,
|
|||
r = sanei_genesys_get_address (reg, 0x29);
|
||||
r->value = 255; /*<<<"magic" number, only suitable for cis*/
|
||||
|
||||
r = sanei_genesys_get_address (reg, 0x2c);
|
||||
r->value = HIBYTE (dpiset);
|
||||
r = sanei_genesys_get_address (reg, 0x2d);
|
||||
r->value = LOBYTE (dpiset);
|
||||
|
||||
r = sanei_genesys_get_address (reg, 0x30);
|
||||
r->value = HIBYTE (start);
|
||||
r = sanei_genesys_get_address (reg, 0x31);
|
||||
r->value = LOBYTE (start);
|
||||
r = sanei_genesys_get_address (reg, 0x32);
|
||||
r->value = HIBYTE (end);
|
||||
r = sanei_genesys_get_address (reg, 0x33);
|
||||
r->value = LOBYTE (end);
|
||||
sanei_genesys_set_double(reg, REG_DPISET, dpiset);
|
||||
sanei_genesys_set_double(reg, REG_STRPIXEL, start);
|
||||
sanei_genesys_set_double(reg, REG_ENDPIXEL, end);
|
||||
|
||||
/* words(16bit) before gamma, conversion to 8 bit or lineart*/
|
||||
words_per_line = (pixels * dpiset) / gl841_get_dpihw(dev);
|
||||
|
@ -2470,7 +2469,7 @@ gl841_init_optical_regs_scan(Genesys_Device * dev,
|
|||
r = sanei_genesys_get_address (reg, 0x34);
|
||||
r->value = dev->sensor.dummy_pixel;
|
||||
|
||||
DBG (DBG_proc, "gl841_init_optical_regs_scan : completed. \n");
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -2704,10 +2703,6 @@ dummy \ scanned lines
|
|||
scan_step_type = 1;
|
||||
else
|
||||
scan_step_type = 2;
|
||||
if (dev->model->motor_type == MOTOR_CANONLIDE80 && yres>=600)
|
||||
{
|
||||
scan_step_type = 1;
|
||||
}
|
||||
|
||||
/* exposure_time */
|
||||
led_exposure = gl841_get_led_exposure(dev);
|
||||
|
@ -2734,7 +2729,6 @@ dummy \ scanned lines
|
|||
scan_power_mode++;
|
||||
}
|
||||
|
||||
|
||||
DBG (DBG_info, "gl841_init_scan_regs : exposure_time=%d pixels\n",
|
||||
exposure_time);
|
||||
|
||||
|
@ -3096,10 +3090,6 @@ dummy \ scanned lines
|
|||
scan_step_type = 1;
|
||||
else
|
||||
scan_step_type = 2;
|
||||
if (dev->model->motor_type == MOTOR_CANONLIDE80 && yres>=600)
|
||||
{
|
||||
scan_step_type = 1;
|
||||
}
|
||||
|
||||
led_exposure = gl841_get_led_exposure(dev);
|
||||
|
||||
|
@ -3126,8 +3116,7 @@ dummy \ scanned lines
|
|||
scan_power_mode++;
|
||||
}
|
||||
|
||||
DBG (DBG_info, "gl841_calculate_current_setup : exposure_time=%d pixels\n",
|
||||
exposure_time);
|
||||
DBG (DBG_info, "%s : exposure_time=%d pixels\n", __FUNCTION__, exposure_time);
|
||||
|
||||
/* scanned area must be enlarged by max color shift needed */
|
||||
max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0);
|
||||
|
@ -3146,7 +3135,7 @@ dummy \ scanned lines
|
|||
dev->current_setup.stagger = stagger;
|
||||
dev->current_setup.max_shift = max_shift + stagger;
|
||||
|
||||
DBG (DBG_proc, "gl841_calculate_current_setup: completed\n");
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -4254,8 +4243,7 @@ gl841_init_regs_for_coarse_calibration (Genesys_Device * dev)
|
|||
uint8_t channels;
|
||||
uint8_t cksel;
|
||||
|
||||
DBG (DBG_proc, "gl841_init_regs_for_coarse_calibration\n");
|
||||
|
||||
DBGSTART;
|
||||
|
||||
cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */
|
||||
|
||||
|
@ -4303,13 +4291,11 @@ gl841_init_regs_for_coarse_calibration (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
DBG (DBG_proc,
|
||||
"gl841_init_register_for_coarse_calibration: completed\n");
|
||||
|
||||
/* if (DBG_LEVEL >= DBG_info)
|
||||
sanei_gl841_print_registers (dev->calib_reg);*/
|
||||
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -4320,14 +4306,30 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
|
|||
{
|
||||
SANE_Status status;
|
||||
SANE_Int ydpi;
|
||||
float starty;
|
||||
|
||||
DBG (DBG_proc, "gl841_init_regs_for_shading: lines = %d\n", (int)dev->calib_lines);
|
||||
DBGSTART;
|
||||
DBG (DBG_proc, "%s: lines = %d\n", __FUNCTION__, (int)dev->calib_lines);
|
||||
|
||||
ydpi = dev->motor.base_ydpi;
|
||||
if (dev->motor.motor_id == MOTOR_PLUSTEK_3600) /* TODO PLUSTEK_3600: 1200dpi not yet working, produces dark bar */
|
||||
starty = 0;
|
||||
if (dev->model->motor_type == MOTOR_PLUSTEK_3600) /* TODO PLUSTEK_3600: 1200dpi not yet working, produces dark bar */
|
||||
{
|
||||
ydpi = 600;
|
||||
}
|
||||
if (dev->model->motor_type== MOTOR_CANONLIDE80)
|
||||
{
|
||||
/* ydpi = sensor dpi * channels / (1+half_ccd) */
|
||||
if(dev->settings.xres>600)
|
||||
{
|
||||
ydpi = 1200;
|
||||
}
|
||||
else
|
||||
{
|
||||
ydpi = 600;
|
||||
}
|
||||
starty = (SANE_UNFIX (dev->model->y_offset_calib)*ydpi)/MM_PER_INCH;
|
||||
}
|
||||
|
||||
dev->calib_channels = 3;
|
||||
dev->calib_lines = dev->model->shading_lines;
|
||||
|
@ -4336,7 +4338,7 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
|
|||
dev->settings.xres,
|
||||
ydpi,
|
||||
0,
|
||||
0,
|
||||
starty,
|
||||
(dev->sensor.sensor_pixels * dev->settings.xres) / dev->sensor.optical_res,
|
||||
dev->calib_lines,
|
||||
16,
|
||||
|
@ -4344,14 +4346,8 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
|
|||
dev->settings.color_filter,
|
||||
SCAN_FLAG_DISABLE_SHADING |
|
||||
SCAN_FLAG_DISABLE_GAMMA |
|
||||
/* we don't handle differing shading areas very well */
|
||||
/* SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |*/
|
||||
SCAN_FLAG_IGNORE_LINE_DISTANCE |
|
||||
SCAN_FLAG_USE_OPTICAL_RES
|
||||
);
|
||||
|
||||
dev->calib_pixels = dev->current_setup.pixels;
|
||||
|
||||
SCAN_FLAG_USE_OPTICAL_RES);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -4360,20 +4356,18 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
dev->calib_pixels = dev->current_setup.pixels;
|
||||
dev->scanhead_position_in_steps += dev->calib_lines;
|
||||
|
||||
status =
|
||||
gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS);
|
||||
status = gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl841_init_registers_for_shading: failed to bulk write registers: %s\n",
|
||||
DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
DBG (DBG_proc, "gl841_init_regs_for_shading: completed\n");
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -4434,7 +4428,9 @@ gl841_init_regs_for_scan (Genesys_Device * dev)
|
|||
|
||||
move = 0;
|
||||
if (dev->model->flags & GENESYS_FLAG_SEARCH_START)
|
||||
move += SANE_UNFIX (dev->model->y_offset_calib);
|
||||
{
|
||||
move += SANE_UNFIX (dev->model->y_offset_calib);
|
||||
}
|
||||
|
||||
DBG (DBG_info, "gl841_init_regs_for_scan: move=%f steps\n", move);
|
||||
|
||||
|
@ -5424,7 +5420,7 @@ gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi)
|
|||
}
|
||||
else if (dev->model->dac_type == DAC_CANONLIDE80)
|
||||
{
|
||||
dev->frontend.gain[j] = gain[j]*8;
|
||||
dev->frontend.gain[j] = gain[j]*12;
|
||||
}
|
||||
|
||||
DBG (DBG_proc,
|
||||
|
@ -6145,6 +6141,132 @@ gl841_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
|
|||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send shading calibration data. The buffer is considered to always hold values
|
||||
* for all the channels.
|
||||
*/
|
||||
GENESYS_STATIC
|
||||
SANE_Status
|
||||
gl841_send_shading_data (Genesys_Device * dev, uint8_t * data, int size)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
uint32_t length, x, factor, pixels, i;
|
||||
uint32_t lines, channels;
|
||||
uint16_t dpiset, dpihw, strpixel ,endpixel, beginpixel;
|
||||
uint8_t *buffer,*ptr,*src;
|
||||
|
||||
DBGSTART;
|
||||
DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__FUNCTION__,size);
|
||||
|
||||
/* old method if no SHDAREA */
|
||||
if((dev->reg[reg_0x01].value & REG01_SHDAREA) == 0)
|
||||
{
|
||||
/* start address */
|
||||
status = sanei_genesys_set_buffer_address (dev, 0x0000);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "%s: failed to set buffer address: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
/* shading data whole line */
|
||||
status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "%s: failed to send shading table: %s\n", __FUNCTION__,
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
DBGCOMPLETED;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* data is whole line, we extract only the part for the scanned area */
|
||||
length = (uint32_t) (size / 3);
|
||||
sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&strpixel);
|
||||
sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&endpixel);
|
||||
DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d\n",__FUNCTION__,strpixel,endpixel,endpixel-strpixel);
|
||||
|
||||
/* compute deletion/average factor */
|
||||
sanei_genesys_get_double(dev->reg,REG_DPISET,&dpiset);
|
||||
dpihw = dev->reg[reg_0x05].value >> 6;
|
||||
if (dpihw == 0)
|
||||
{
|
||||
dpihw=600;
|
||||
}
|
||||
else if (dpihw == 1)
|
||||
{
|
||||
dpihw=1200;
|
||||
}
|
||||
else
|
||||
{
|
||||
dpihw=2400;
|
||||
}
|
||||
factor=dpihw/dpiset;
|
||||
DBG( DBG_io2, "%s: factor=%d\n",__FUNCTION__,factor);
|
||||
|
||||
/* binary data logging */
|
||||
if(DBG_LEVEL>=DBG_data)
|
||||
{
|
||||
dev->binary=fopen("binary.pnm","wb");
|
||||
sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines);
|
||||
channels=dev->current_setup.channels;
|
||||
if(dev->binary!=NULL)
|
||||
{
|
||||
fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255);
|
||||
}
|
||||
}
|
||||
|
||||
/* turn pixel value into bytes 2x16 bits words */
|
||||
strpixel*=2*2; /* 2 words of 2 bytes */
|
||||
endpixel*=2*2;
|
||||
pixels=endpixel-strpixel;
|
||||
/* shading pixel begin is start pixel minus start pixel during shading
|
||||
* calibration */
|
||||
beginpixel = dev->sensor.CCD_start_xoffset / factor + dev->sensor.dummy_pixel + 1;
|
||||
beginpixel = strpixel-beginpixel*2*2;
|
||||
DBG( DBG_io2, "%s: begin pixel %d\n",__FUNCTION__,beginpixel/4);
|
||||
|
||||
DBG( DBG_io2, "%s: using chunks of %d bytes (%d shading data pixels)\n",__FUNCTION__,length, length/4);
|
||||
buffer=(uint8_t *)malloc(pixels);
|
||||
memset(buffer,0,pixels);
|
||||
|
||||
/* write actual shading data contigously
|
||||
* channel by channel, starting at addr 0x0000
|
||||
* */
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
/* copy data to work buffer and process it */
|
||||
/* coefficent destination */
|
||||
ptr=buffer;
|
||||
|
||||
/* iterate on both sensor segment */
|
||||
for(x=0;x<pixels;x+=4*factor)
|
||||
{
|
||||
/* coefficient source */
|
||||
src=data+x+beginpixel+i*length;
|
||||
|
||||
ptr[0]=src[0];
|
||||
ptr[1]=src[1];
|
||||
ptr[2]=src[2];
|
||||
ptr[3]=src[3];
|
||||
|
||||
/* next shading coefficient */
|
||||
ptr+=4;
|
||||
}
|
||||
/* 0x5400 alignment for LIDE80 internal memory */
|
||||
RIEF(sanei_genesys_set_buffer_address (dev, 0x5400*i), buffer);
|
||||
RIEF(dev->model->cmd_set->bulk_write_data (dev, 0x3c, buffer, pixels), buffer);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
DBGCOMPLETED;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** the gl841 command set */
|
||||
static Genesys_Command_Set gl841_cmd_set = {
|
||||
"gl841-generic", /* the name of this set */
|
||||
|
@ -6198,7 +6320,7 @@ static Genesys_Command_Set gl841_cmd_set = {
|
|||
|
||||
gl841_is_compatible_calibration,
|
||||
NULL,
|
||||
NULL,
|
||||
gl841_send_shading_data,
|
||||
gl841_calculate_current_setup,
|
||||
NULL
|
||||
};
|
||||
|
|
|
@ -162,6 +162,11 @@
|
|||
#define REG1E_LINESEL 0x0f
|
||||
#define REG1ES_LINESEL 0
|
||||
|
||||
#define REG_LINCNT 0x25
|
||||
#define REG_DPISET 0x2c
|
||||
#define REG_STRPIXEL 0x30
|
||||
#define REG_ENDPIXEL 0x32
|
||||
|
||||
#define REG40_HISPDFLG 0x04
|
||||
#define REG40_MOTMFLG 0x02
|
||||
#define REG40_DATAENB 0x01
|
||||
|
@ -426,4 +431,6 @@ SANE_Status gl841_offset_calibration (Genesys_Device * dev);
|
|||
SANE_Status gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi);
|
||||
|
||||
SANE_Status gl841_led_calibration (Genesys_Device * dev);
|
||||
|
||||
SANE_Status gl841_send_shading_data (Genesys_Device * dev, uint8_t * data, int size);
|
||||
#endif
|
||||
|
|
Ładowanie…
Reference in New Issue