From e500d44e6584b3e73495d18b1a966669dfc3412a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Voltz?= Date: Thu, 21 Nov 2013 07:38:30 +0100 Subject: [PATCH] LiDE 80 WIP: - 1200 shading working - 600 and below resolution are ok, but shading needs to be fixed - 1200 dpi motor resolution doesn't work --- backend/genesys.c | 179 ++++++++++++++------------- backend/genesys.h | 3 + backend/genesys_devices.c | 39 +++--- backend/genesys_gl841.c | 248 ++++++++++++++++++++++++++++---------- backend/genesys_gl841.h | 7 ++ 5 files changed, 307 insertions(+), 169 deletions(-) diff --git a/backend/genesys.c b/backend/genesys.c index 02abc6335..cc1bff344 100644 --- a/backend/genesys.c +++ b/backend/genesys.c @@ -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; } diff --git a/backend/genesys.h b/backend/genesys.h index 4d5fd94b5..93de4a768 100644 --- a/backend/genesys.h +++ b/backend/genesys.h @@ -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 */ diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c index 7275524fd..c3df32a73 100644 --- a/backend/genesys_devices.c +++ b/backend/genesys_devices.c @@ -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 }; diff --git a/backend/genesys_gl841.c b/backend/genesys_gl841.c index c1c34c4ec..64d5f4b28 100644 --- a/backend/genesys_gl841.c +++ b/backend/genesys_gl841.c @@ -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;xmodel->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 }; diff --git a/backend/genesys_gl841.h b/backend/genesys_gl841.h index 4dcae20cf..907d5a32e 100644 --- a/backend/genesys_gl841.h +++ b/backend/genesys_gl841.h @@ -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