- 1200 shading working
- 600 and below resolution are ok, but shading needs to be fixed
- 1200 dpi motor resolution doesn't work
merge-requests/1/head
Stphane Voltz 2013-11-21 07:38:30 +01:00
rodzic ebcc2c0a3f
commit e500d44e65
5 zmienionych plików z 307 dodań i 169 usunięć

Wyświetl plik

@ -919,10 +919,11 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
int start_address; int start_address;
SANE_Status status; 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 /* 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) if(dev->model->cmd_set->send_shading_data!=NULL)
{ {
status=dev->model->cmd_set->send_shading_data(dev, data, size); 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_XP300
&& dev->model->ccd_type != CCD_DP665 && dev->model->ccd_type != CCD_DP665
&& dev->model->ccd_type != CCD_DP685 && dev->model->ccd_type != CCD_DP685
&& dev->model->ccd_type != CIS_CANONLIDE80
&& dev->model->ccd_type != CCD_ROADWARRIOR && dev->model->ccd_type != CCD_ROADWARRIOR
&& dev->model->ccd_type != CCD_HP2300 && dev->model->ccd_type != CCD_HP2300
&& dev->model->ccd_type != CCD_HP2400 && dev->model->ccd_type != CCD_HP2400
@ -967,8 +969,7 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
status = sanei_genesys_set_buffer_address (dev, start_address); status = sanei_genesys_set_buffer_address (dev, start_address);
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to set buffer address: %s\n", __FUNCTION__,
"genesys_send_offset_and_shading: failed to set buffer address: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }
@ -976,8 +977,7 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size); status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size);
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to send shading table: %s\n", __FUNCTION__,
"genesys_send_offset_and_shading: failed to send shading table: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return 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 */ *shading_data_ptr++ = 0x40; /* white hi -> 0x4000 */
} }
status = status = genesys_send_offset_and_shading (dev,
genesys_send_offset_and_shading (dev, shading_data, shading_data,
pixels_per_line * 4 * channels); 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));
free (shading_data); free (shading_data);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "%s: failed to send shading data: %s\n", __FUNCTION__,
sane_strstatus (status));
}
DBGCOMPLETED; DBGCOMPLETED;
return status; return status;
@ -2153,7 +2153,7 @@ genesys_white_shading_calibration (Genesys_Device * dev)
/* This calibration uses a scan over the calibration target, comprising a /* This calibration uses a scan over the calibration target, comprising a
* black and a white strip. (So the motor must be on.) * 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) genesys_dark_white_shading_calibration (Genesys_Device * dev)
{ {
SANE_Status status; SANE_Status status;
@ -2168,8 +2168,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
SANE_Bool motor; SANE_Bool motor;
DBG (DBG_proc, "genesys_black_white_shading_calibration (lines = %d)\n", DBG (DBG_proc, "%s: (lines = %d)\n", __FUNCTION__, (unsigned int)dev->calib_lines);
(unsigned int)dev->calib_lines);
pixels_per_line = dev->calib_pixels; pixels_per_line = dev->calib_pixels;
channels = dev->calib_channels; channels = dev->calib_channels;
@ -2182,8 +2181,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
dev->white_average_data = malloc (dev->average_size); dev->white_average_data = malloc (dev->average_size);
if (!dev->white_average_data) if (!dev->white_average_data)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to allocate white average memory\n", __FUNCTION__);
"genesys_dark_white_shading_calibration: failed to allocate average memory\n");
return SANE_STATUS_NO_MEM; 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); dev->dark_average_data = malloc (channels * 2 * pixels_per_line);
if (!dev->dark_average_data) if (!dev->dark_average_data)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to allocate dark average memory\n", __FUNCTION__);
"genesys_dark_white_shading_shading_calibration: failed to allocate average memory\n");
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} }
@ -2203,8 +2200,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
calibration_data = malloc (size); calibration_data = malloc (size);
if (!calibration_data) if (!calibration_data)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to allocate calibration memory\n", __FUNCTION__);
"genesys_dark_white_shading_calibration: failed to allocate calibration memory\n");
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} }
@ -2225,8 +2221,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
free (calibration_data); free (calibration_data);
DBG (DBG_error, DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__,
"genesys_dark_white_shading_calibration: failed to bulk write registers: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }
@ -2236,8 +2231,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
free (calibration_data); free (calibration_data);
DBG (DBG_error, DBG (DBG_error, "%s: failed to begin scan: %s\n", __FUNCTION__,
"genesys_dark_white_shading_calibration: Failed to begin scan: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }
@ -2246,8 +2240,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
free (calibration_data); free (calibration_data);
DBG (DBG_error, DBG (DBG_error, "%s: failed to read data: %s\n", __FUNCTION__,
"genesys_dark_white_shading_calibration: Failed to read data: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }
@ -2256,16 +2249,26 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
free (calibration_data); free (calibration_data);
DBG (DBG_error, DBG (DBG_error, "%s: Failed to end scan: %s\n", __FUNCTION__,
"genesys_dark_white_shading_calibration: Failed to end scan: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }
if (DBG_LEVEL >= DBG_data) if (DBG_LEVEL >= DBG_data)
{
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, sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data,
16, channels, pixels_per_line, 16, channels, pixels_per_line,
dev->calib_lines); dev->calib_lines);
}
}
average_white = dev->white_average_data; 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; unsigned int x, i, j, br, dk, res, avgpixels, basepixels, val;
DBG (DBG_info, "%s: pixels=%d, offset=%d\n", __FUNCTION__, pixels_per_line, DBG (DBG_info, "%s: pixels=%d, offset=%d\n", __FUNCTION__, pixels_per_line, o);
o);
/* initialize result */ /* initialize result */
memset (shading_data, 0xff, words_per_color * 3 * 2); memset (shading_data, 0xff, words_per_color * 3 * 2);
@ -2478,7 +2481,6 @@ compute_averaged_planar (Genesys_Device * dev,
for (x = 0; x <= pixels_per_line - avgpixels; x += avgpixels) for (x = 0; x <= pixels_per_line - avgpixels; x += avgpixels)
{ {
if ((x + o) * 2 * 2 + 3 > words_per_color * 2) if ((x + o) * 2 * 2 + 3 > words_per_color * 2)
break; break;
@ -2515,33 +2517,33 @@ compute_averaged_planar (Genesys_Device * dev,
65535 * (target_bright - target_dark)) 65535 * (target_bright - target_dark))
val = 65535; val = 65535;
else else
val = {
(dk * target_bright - br * target_dark) / (target_bright - val = (dk * target_bright - br * target_dark) / (target_bright - target_dark);
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++) for (i = 0; i < avgpixels; i++)
{ {
shading_data[(x + o + i) * 2 * 2 + shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j] = val & 0xff;
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 + 1] = val >> 8;
} }
val = br - dk; val = br - dk;
if (65535 * val > (target_bright - target_dark) * coeff) if (65535 * val > (target_bright - target_dark) * coeff)
{
val = (coeff * (target_bright - target_dark)) / val; val = (coeff * (target_bright - target_dark)) / val;
}
else 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++) for (i = 0; i < avgpixels; i++)
{ {
shading_data[(x + o + i) * 2 * 2 + shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 2] = val & 0xff;
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 + 3] = val >> 8;
} }
} }
@ -2550,24 +2552,12 @@ compute_averaged_planar (Genesys_Device * dev,
{ {
for (i = 0; i < avgpixels; i++) for (i = 0; i < avgpixels; i++)
{ {
shading_data[(x + o + i) * 2 * 2 + shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j ] = shading_data[(x + o + i) * 2 * 2 ];
words_per_color * 2 * j] = 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 * 0]; 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 + shading_data[(x + o + i) * 2 * 2 + words_per_color * 2 * j + 3] = shading_data[(x + o + i) * 2 * 2 + 3];
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];
} }
} }
} }
} }
@ -2870,13 +2860,21 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
break; 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; length = words_per_color * 3 * 2;
/* allocate computed size */ /* allocate computed size */
shading_data = malloc (length); shading_data = malloc (length);
if (!shading_data) if (!shading_data)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to allocate memory\n", __FUNCTION__);
"genesys_send_shading_coefficient: failed to allocate memory\n");
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} }
memset (shading_data, 0, length); memset (shading_data, 0, length);
@ -3040,8 +3038,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
shading_data = malloc (length); shading_data = malloc (length);
if (!shading_data) if (!shading_data)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to allocate memory\n", __FUNCTION__);
"genesys_send_shading_coefficient: failed to allocate memory\n");
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
} }
memset (shading_data, 0, length); memset (shading_data, 0, length);
@ -3057,7 +3054,6 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
target_code); target_code);
break; break;
case CCD_CANONLIDE35: case CCD_CANONLIDE35:
case CIS_CANONLIDE80:
compute_averaged_planar (dev, compute_averaged_planar (dev,
shading_data, shading_data,
pixels_per_line, pixels_per_line,
@ -3068,6 +3064,17 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
0xfa00, 0xfa00,
0x0a00); 0x0a00);
break; 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: case CCD_PLUSTEK_3600:
compute_shifted_coefficients (dev, compute_shifted_coefficients (dev,
shading_data, shading_data,
@ -3081,23 +3088,21 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
256); /* patch_size: contigous extent */ 256); /* patch_size: contigous extent */
break; break;
default: default:
DBG (DBG_error, DBG (DBG_error, "%s: sensor %d not supported\n", __FUNCTION__, dev->model->ccd_type);
"genesys_send_shading_coefficient: sensor %d not supported\n",
dev->model->ccd_type);
return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_UNSUPPORTED;
break; break;
} }
/* do the actual write of shading calibration data to the scanner */ /* do the actual write of shading calibration data to the scanner */
status = genesys_send_offset_and_shading (dev, shading_data, length); 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); 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; return SANE_STATUS_GOOD;
} }

Wyświetl plik

@ -146,4 +146,7 @@ typedef struct Genesys_Scanner
SANE_Int bpp_list[5]; /**< */ SANE_Int bpp_list[5]; /**< */
} Genesys_Scanner; } Genesys_Scanner;
#ifdef UNIT_TESTING
SANE_Status genesys_dark_white_shading_calibration (Genesys_Device * dev);
#endif
#endif /* not GENESYS_H */ #endif /* not GENESYS_H */

Wyświetl plik

@ -305,7 +305,8 @@ static Genesys_Sensor Sensor[] = {
} }
, ,
/* CANOLIDE35 */ /* CANOLIDE35 */
{CCD_CANONLIDE35, 1200, {CCD_CANONLIDE35,
1200,
87, /* (black) */ 87, /* (black) */
87, /* (dummy) */ 87, /* (dummy) */
0, /* (startxoffset) */ 0, /* (startxoffset) */
@ -760,10 +761,10 @@ static Genesys_Sensor Sensor[] = {
/* CANOLIDE80 */ /* CANOLIDE80 */
{CIS_CANONLIDE80, {CIS_CANONLIDE80,
1200, /* real hardware limit is 2400 */ 1200, /* real hardware limit is 2400 */
9*2, 20, /* black pixels */
9*2, 6, /* expdummy */
0, 31, /* CCD_start_xoffset 14=>3, 20=>2 */
10304, /* up to 5144, 5390, 10264, 20504, 21762 : capped by max exposure from logs */ 10240, /* 10400, too wide=>10288 in shading data 10240~, 10208 too short for shading, max shading data = 10240 pixels, endpix-startpix=10208 */
230, 230,
230, 230,
{0x00, 0x05, 0x07, 0x09}, /* in fact ,maps to 0x70-0x73 for GL841 */ {0x00, 0x05, 0x07, 0x09}, /* in fact ,maps to 0x70-0x73 for GL841 */
@ -1288,8 +1289,8 @@ static Genesys_Motor Motor[] = {
},}, },},
{MOTOR_CANONLIDE80, {MOTOR_CANONLIDE80,
2400, /* 2400 ???? */ 2400, /* 2400 ???? */
7200, 9600, /* 7200 ???? */
2, /* max step type */ 1, /* max step type */
1, /* power mode count */ 1, /* power mode count */
{ {
{ /* start speed, max end speed, step number */ { /* start speed, max end speed, step number */
@ -1297,7 +1298,7 @@ static Genesys_Motor Motor[] = {
/* 1288=(5144+8)*ydpi(=300)/base_dpi(=1200) , where 5152 is exposure */ /* 1288=(5144+8)*ydpi(=300)/base_dpi(=1200) , where 5152 is exposure */
/* 6440=9660/(1932/1288) */ /* 6440=9660/(1932/1288) */
{ 6440, 1288, 60, 0.8 }, /* full step 9660 1932 32 values from logs */ { 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 */ { 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, GENESYS_GL841,
NULL, NULL,
{1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ { 1200, 600, 400, 300, 240, 200, 150, 75, 0}, /* possible x-resolutions */
{2400, 1200, 600, 300, 150, 75, 0}, /* possible y-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 gray mode */
{16, 8, 0}, /* possible depths in color mode */ {16, 8, 0}, /* possible depths in color mode */
@ -2128,14 +2129,14 @@ static Genesys_Model canon_lide_80_model = {
GENESYS_GL841, GENESYS_GL841,
NULL, NULL,
{ 1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */ { 1200, 600, 400, 300, 240, 150, 100, 75, 0}, /* possible x-resolutions */
{2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible y-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 gray mode */
{16, 8, 0}, /* possible depths in color mode */ {16, 8, 0}, /* possible depths in color mode */
SANE_FIX (6.5), /* Start of scan area in mm (x) */ SANE_FIX (0.42), /* Start of scan area in mm (x) 0.42 */
SANE_FIX (7.9), /* Start of scan area in mm (y) */ SANE_FIX (7.90), /* Start of scan area in mm (y) 7.90 */
SANE_FIX (218.0), /* Size of scan area in mm (x) */ 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 (299.0), /* Size of scan area in mm (y) */
SANE_FIX (3.0), /* Start of white strip 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_FILE_SW |
GENESYS_HAS_EMAIL_SW | GENESYS_HAS_EMAIL_SW |
GENESYS_HAS_COPY_SW, GENESYS_HAS_COPY_SW,
200, 280,
400 400
}; };

Wyświetl plik

@ -214,8 +214,8 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr,
uint8_t * data, size_t len) uint8_t * data, size_t len)
{ {
SANE_Status status; SANE_Status status;
size_t size; size_t size, target;
uint8_t outdata[8]; uint8_t outdata[8], *buffer;
DBG (DBG_io, "gl841_bulk_read_data: requesting %lu bytes\n", DBG (DBG_io, "gl841_bulk_read_data: requesting %lu bytes\n",
(u_long) len); (u_long) len);
@ -254,12 +254,14 @@ gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr,
return status; return status;
} }
while (len) target = len;
buffer = data;
while (target)
{ {
if (len > BULKIN_MAXSIZE) if (target > BULKIN_MAXSIZE)
size = BULKIN_MAXSIZE; size = BULKIN_MAXSIZE;
else else
size = len; size = target;
DBG (DBG_io2, DBG (DBG_io2,
"gl841_bulk_read_data: trying to read %lu bytes of data\n", "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, DBG (DBG_io2,
"gl841_bulk_read_data read %lu bytes, %lu remaining\n", "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; 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; return SANE_STATUS_GOOD;
} }
@ -788,12 +794,12 @@ gl841_init_lide80 (Genesys_Device * dev)
uint8_t val; uint8_t val;
int index=0; int index=0;
INITREG (0x01, 0x02); INITREG (0x01, 0x82); /* 0x02 = SHDAREA and no CISSET ! */
INITREG (0x02, 0x10); INITREG (0x02, 0x10);
INITREG (0x03, 0x50); INITREG (0x03, 0x50);
INITREG (0x04, 0x02); INITREG (0x04, 0x02);
INITREG (0x05, 0x4c); INITREG (0x05, 0x4c); /* 1200 DPI */
INITREG (0x06, 0x38); INITREG (0x06, 0x30); /* 0x38 scanmod=1, pwrbit, GAIN4 */
INITREG (0x07, 0x00); INITREG (0x07, 0x00);
INITREG (0x08, 0x00); INITREG (0x08, 0x00);
INITREG (0x09, 0x11); INITREG (0x09, 0x11);
@ -1976,7 +1982,10 @@ gl841_init_motor_regs_scan(Genesys_Device * dev,
&fast_exposure, &fast_exposure,
scan_power_mode); 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 /* quirk: looks like at least this scanner is unable to use
2-feed mode */ 2-feed mode */
@ -2428,19 +2437,9 @@ gl841_init_optical_regs_scan(Genesys_Device * dev,
r = sanei_genesys_get_address (reg, 0x29); r = sanei_genesys_get_address (reg, 0x29);
r->value = 255; /*<<<"magic" number, only suitable for cis*/ r->value = 255; /*<<<"magic" number, only suitable for cis*/
r = sanei_genesys_get_address (reg, 0x2c); sanei_genesys_set_double(reg, REG_DPISET, dpiset);
r->value = HIBYTE (dpiset); sanei_genesys_set_double(reg, REG_STRPIXEL, start);
r = sanei_genesys_get_address (reg, 0x2d); sanei_genesys_set_double(reg, REG_ENDPIXEL, end);
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);
/* words(16bit) before gamma, conversion to 8 bit or lineart*/ /* words(16bit) before gamma, conversion to 8 bit or lineart*/
words_per_line = (pixels * dpiset) / gl841_get_dpihw(dev); 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 = sanei_genesys_get_address (reg, 0x34);
r->value = dev->sensor.dummy_pixel; r->value = dev->sensor.dummy_pixel;
DBG (DBG_proc, "gl841_init_optical_regs_scan : completed. \n"); DBGCOMPLETED;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
@ -2704,10 +2703,6 @@ dummy \ scanned lines
scan_step_type = 1; scan_step_type = 1;
else else
scan_step_type = 2; scan_step_type = 2;
if (dev->model->motor_type == MOTOR_CANONLIDE80 && yres>=600)
{
scan_step_type = 1;
}
/* exposure_time */ /* exposure_time */
led_exposure = gl841_get_led_exposure(dev); led_exposure = gl841_get_led_exposure(dev);
@ -2734,7 +2729,6 @@ dummy \ scanned lines
scan_power_mode++; scan_power_mode++;
} }
DBG (DBG_info, "gl841_init_scan_regs : exposure_time=%d pixels\n", DBG (DBG_info, "gl841_init_scan_regs : exposure_time=%d pixels\n",
exposure_time); exposure_time);
@ -3096,10 +3090,6 @@ dummy \ scanned lines
scan_step_type = 1; scan_step_type = 1;
else else
scan_step_type = 2; scan_step_type = 2;
if (dev->model->motor_type == MOTOR_CANONLIDE80 && yres>=600)
{
scan_step_type = 1;
}
led_exposure = gl841_get_led_exposure(dev); led_exposure = gl841_get_led_exposure(dev);
@ -3126,8 +3116,7 @@ dummy \ scanned lines
scan_power_mode++; scan_power_mode++;
} }
DBG (DBG_info, "gl841_calculate_current_setup : exposure_time=%d pixels\n", DBG (DBG_info, "%s : exposure_time=%d pixels\n", __FUNCTION__, exposure_time);
exposure_time);
/* scanned area must be enlarged by max color shift needed */ /* scanned area must be enlarged by max color shift needed */
max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0); 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.stagger = stagger;
dev->current_setup.max_shift = max_shift + stagger; dev->current_setup.max_shift = max_shift + stagger;
DBG (DBG_proc, "gl841_calculate_current_setup: completed\n"); DBGCOMPLETED;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
@ -4254,8 +4243,7 @@ gl841_init_regs_for_coarse_calibration (Genesys_Device * dev)
uint8_t channels; uint8_t channels;
uint8_t cksel; 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 */ 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; return status;
} }
DBG (DBG_proc,
"gl841_init_register_for_coarse_calibration: completed\n");
/* if (DBG_LEVEL >= DBG_info) /* if (DBG_LEVEL >= DBG_info)
sanei_gl841_print_registers (dev->calib_reg);*/ sanei_gl841_print_registers (dev->calib_reg);*/
DBGCOMPLETED;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
@ -4320,14 +4306,30 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
{ {
SANE_Status status; SANE_Status status;
SANE_Int ydpi; 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; 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; 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_channels = 3;
dev->calib_lines = dev->model->shading_lines; dev->calib_lines = dev->model->shading_lines;
@ -4336,7 +4338,7 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
dev->settings.xres, dev->settings.xres,
ydpi, ydpi,
0, 0,
0, starty,
(dev->sensor.sensor_pixels * dev->settings.xres) / dev->sensor.optical_res, (dev->sensor.sensor_pixels * dev->settings.xres) / dev->sensor.optical_res,
dev->calib_lines, dev->calib_lines,
16, 16,
@ -4344,14 +4346,8 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
dev->settings.color_filter, dev->settings.color_filter,
SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_SHADING |
SCAN_FLAG_DISABLE_GAMMA | 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_IGNORE_LINE_DISTANCE |
SCAN_FLAG_USE_OPTICAL_RES SCAN_FLAG_USE_OPTICAL_RES);
);
dev->calib_pixels = dev->current_setup.pixels;
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_error, DBG (DBG_error,
@ -4360,20 +4356,18 @@ gl841_init_regs_for_shading (Genesys_Device * dev)
return status; return status;
} }
dev->calib_pixels = dev->current_setup.pixels;
dev->scanhead_position_in_steps += dev->calib_lines; dev->scanhead_position_in_steps += dev->calib_lines;
status = status = gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS);
gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS);
if (status != SANE_STATUS_GOOD) if (status != SANE_STATUS_GOOD)
{ {
DBG (DBG_error, DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __FUNCTION__,
"gl841_init_registers_for_shading: failed to bulk write registers: %s\n",
sane_strstatus (status)); sane_strstatus (status));
return status; return status;
} }
DBG (DBG_proc, "gl841_init_regs_for_shading: completed\n"); DBGCOMPLETED;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
@ -4434,7 +4428,9 @@ gl841_init_regs_for_scan (Genesys_Device * dev)
move = 0; move = 0;
if (dev->model->flags & GENESYS_FLAG_SEARCH_START) 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); 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) 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, DBG (DBG_proc,
@ -6145,6 +6141,132 @@ gl841_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black)
return status; 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 */ /** the gl841 command set */
static Genesys_Command_Set gl841_cmd_set = { static Genesys_Command_Set gl841_cmd_set = {
"gl841-generic", /* the name of this set */ "gl841-generic", /* the name of this set */
@ -6198,7 +6320,7 @@ static Genesys_Command_Set gl841_cmd_set = {
gl841_is_compatible_calibration, gl841_is_compatible_calibration,
NULL, NULL,
NULL, gl841_send_shading_data,
gl841_calculate_current_setup, gl841_calculate_current_setup,
NULL NULL
}; };

Wyświetl plik

@ -162,6 +162,11 @@
#define REG1E_LINESEL 0x0f #define REG1E_LINESEL 0x0f
#define REG1ES_LINESEL 0 #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_HISPDFLG 0x04
#define REG40_MOTMFLG 0x02 #define REG40_MOTMFLG 0x02
#define REG40_DATAENB 0x01 #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_coarse_gain_calibration (Genesys_Device * dev, int dpi);
SANE_Status gl841_led_calibration (Genesys_Device * dev); SANE_Status gl841_led_calibration (Genesys_Device * dev);
SANE_Status gl841_send_shading_data (Genesys_Device * dev, uint8_t * data, int size);
#endif #endif