📄 qc-hdcs.c
字号:
I2C_SET_CHECK(HDCS_PCTRL, BIT(6)|BIT(5)|BIT(1)|BIT(0)); I2C_SET_CHECK(HDCS_PDRV, 0x00); I2C_SET_CHECK(HDCS_ICTRL, (sd->subsample ? BIT(7) : 0) | BIT(5)); I2C_SET_CHECK(HDCS_ITMG, BIT(4)|BIT(1)); /* CONFIG: Bit 3: continous frame capture, bit 2: stop when frame complete */ I2C_SET_CHECK(config, (sd->subsample ? BIT(5) : 0) | BIT(3)); I2C_SET_CHECK(HDCS_ADCCTRL, 10); /* ADC output resolution to 10 bits */ if ((r = qc_i2c_wait(qc))<0) goto fail;fail: return r;}/* }}} *//* {{{ [fold] hdcs_start: Start grabbing */static int hdcs_start(struct quickcam *qc){ int r;#if HDCS_COMPRESSr = hdcs_compress_init(qc, 2);qc_i2c_wait(qc);if (r) PDEBUG("hdcs_compress_init(1) = %i", r);return 0;#endif if ((r = qc_i2c_break(qc))<0) goto fail; I2C_SET_CHECK(GET_CONTROL, BIT(2)); /* Run enable */ if ((r = qc_i2c_break(qc))<0) goto fail;fail: return r;}/* }}} *//* {{{ [fold] hdcs_stop: Stop grabbing */static int hdcs_stop(struct quickcam *qc){ int r; if ((r = qc_i2c_break(qc))<0) goto fail; I2C_SET_CHECK(GET_CONTROL, BIT(1)); /* Stop and enter sleep mode */ r = qc_i2c_wait(qc);fail: return r;}/* }}} *//* {{{ [fold] hdcs_set_exposure: Set exposure time, val=0..65535 */static int hdcs_set_exposure(struct quickcam *qc, unsigned int val){ struct qc_sensor_data *sd = &qc->sensor_data; unsigned char control = GET_CONTROL; unsigned int rowexp; /* rowexp,srowexp = 15 bits (0..32767) */ unsigned int srowexp; /* sub-row exposure (smaller is brighter) */ unsigned int max_srowexp; /* Maximum srowexp value + 1 */ int r; /* Absolute black at srowexp=2672,width=360; 2616, width=352; 1896, width=256 for hdcs1000 */ if (val==sd->exposure) return 0; sd->exposure = val; val *= 16; /* 16 seems to be the smallest change that actually affects brightness */ max_srowexp = sd->width*15/2 - 104 + 1; srowexp = max_srowexp - (val % max_srowexp) - 1; rowexp = val / max_srowexp; if (qcdebug&QC_DEBUGCAMERA) PDEBUG("width=%i height=%i rowexp=%i srowexp=%i",sd->width,sd->height,rowexp,srowexp); if ((r = qc_i2c_break(qc))<0) goto fail; /* The following setting must go into same I2C packet */ I2C_SET_CHECK(control, 0); /* Stop grabbing */ I2C_SET_CHECK(HDCS_ROWEXPL, rowexp & 0xFF); /* Number of rows to expose */ I2C_SET_CHECK(HDCS_ROWEXPH, rowexp >> 8); if (IS_1020(qc)) { srowexp = 0; //FIXME:need formula to compute srowexp for HDCS1020! srowexp >>= 2; /* Bits 0..1 are hardwired to 0 */ I2C_SET_CHECK(HDCS20_SROWEXP, srowexp & 0xFF); /* Number of pixels to expose */ } else { I2C_SET_CHECK(HDCS00_SROWEXPL, srowexp & 0xFF); /* Number of pixels to expose */ I2C_SET_CHECK(HDCS00_SROWEXPH, srowexp >> 8); } if (IS_1020(qc)) { I2C_SET_CHECK(HDCS20_ERROR, BIT(0)); /* Reset exposure error flag */ } else { I2C_SET_CHECK(HDCS_STATUS, BIT(4)); /* Reset exposure error flag */ } I2C_SET_CHECK(control, BIT(2)); /* Restart grabbing */ if ((r = qc_i2c_break(qc))<0) goto fail;#if 0 /* Warning: the code below will cause about 0.1 second delay and may cause lost frames */ if (PARANOID) { /* Check if the new exposure setting is valid */ if ((r = qc_i2c_wait(qc))<0) goto fail; if (IS_1020(qc)) { if ((r = qc_get_i2c(qc,qc->sensor_data.sensor, HDCS20_ERROR))<0) goto fail; if (r & BIT(0)) PDEBUG("exposure error (1020)"); } else { if ((r = qc_get_i2c(qc,qc->sensor_data.sensor, HDCS_STATUS))<0) goto fail; if (r & BIT(4)) PDEBUG("exposure error (1000)"); } } if ((r = qc_i2c_wait(qc))<0) goto fail;#endif qc_frame_flush(qc);fail: return (r<0) ? r : 0;}/* }}} *//* {{{ [fold] hdcs_set_gains: Set gains */static int hdcs_set_gains(struct quickcam *qc, unsigned int hue, unsigned int sat, unsigned int val){ static const unsigned int min_gain = 8; struct qc_sensor_data *sd = &qc->sensor_data; unsigned int rgain, bgain, ggain; int r; qc_hsv2rgb(hue, sat, val, &rgain, &bgain, &ggain); rgain >>= 8; /* After this the values are 0..255 */ ggain >>= 8; bgain >>= 8; rgain = MAX(rgain, min_gain); /* Do not allow very small values, they cause bad (low-contrast) image */ ggain = MAX(ggain, min_gain); bgain = MAX(bgain, min_gain); if (rgain==sd->rgain && ggain==sd->ggain && bgain==sd->bgain) return 0; sd->rgain = rgain; sd->ggain = ggain; sd->bgain = bgain; if (rgain > 127) rgain = rgain/2 | BIT(7); /* Bit 7 doubles the programmed values */ if (ggain > 127) ggain = ggain/2 | BIT(7); /* Double programmed value if necessary */ if (bgain > 127) bgain = bgain/2 | BIT(7); if ((r = qc_i2c_break(qc))<0) goto fail; I2C_SET_CHECK(HDCS_ERECPGA, ggain); I2C_SET_CHECK(HDCS_EROCPGA, rgain); I2C_SET_CHECK(HDCS_ORECPGA, bgain); I2C_SET_CHECK(HDCS_OROCPGA, ggain);fail: return r;}/* }}} *//* {{{ [fold] hdcs_set_levels() */static int hdcs_set_levels(struct quickcam *qc, unsigned int exp, unsigned int gain, unsigned int hue, unsigned int sat){ int r = 0;//#if !HDCS_COMPRESS if ((r = hdcs_set_exposure(qc, gain))<0) goto fail;//#endif hdcs_set_gains(qc, hue, sat, exp);fail: return r;}/* }}} *//* {{{ [fold] hdcs_set_size: Sets the size of the capture window *//* * Sets the size (scaling) of the capture window. * If subsample could return the image size we use subsample. */static int hdcs_set_size(struct quickcam *qc, unsigned int width, unsigned int height){ /* The datasheet doesn't seem to say this, but HDCS-1000 * has visible windows size of 360x296 pixels, the first upper-left * visible pixel is at 8,8. * From Andrey's test image: looks like HDCS-1020 upper-left * visible pixel is at 24,8 (y maybe even smaller?) and lower-right * visible pixel at 375,299 (x maybe even larger?) */ unsigned int originx = IS_1020(qc) ? 24 : 8; /* First visible pixel */ unsigned int maxwidth = IS_1020(qc) ? 352 : 360; /* Visible sensor size */ unsigned int originy = 8; unsigned int maxheight = IS_1020(qc) ? 292 : 296; unsigned char control = GET_CONTROL; struct qc_sensor_data *sd = &qc->sensor_data; int r; unsigned int x, y;#if HDCS_COMPRESS return 0;#endif if (sd->subsample) { width *= 2; height *= 2; width = (width + 3)/4*4; /* Width must be multiple of 4 */ height = (height + 3)/4*4; /* Height must be multiple of 4 */ sd->width = width / 2; sd->height = height / 2; /* The image sent will be subsampled by 2 */ } else { sd->width = width = (width + 3)/4*4; /* Width must be multiple of 4 */ sd->height = height = (height + 3)/4*4; /* Height must be multiple of 4 */ } x = (maxwidth - width)/2; /* Center image by computing upper-left corner */ y = (maxheight - height)/2; width /= 4; height /= 4; x = (x + originx)/4; /* Must be multiple of 4 (low bits wired to 0) */ y = (y + originy)/4; if ((r = qc_i2c_break(qc))<0) goto fail; I2C_SET_CHECK(control, 0); /* Stop grabbing */ I2C_SET_CHECK(HDCS_FWROW, y); I2C_SET_CHECK(HDCS_FWCOL, x); I2C_SET_CHECK(HDCS_LWROW, y+height-1); I2C_SET_CHECK(HDCS_LWCOL, x+width-1); I2C_SET_CHECK(control, BIT(2)); /* Restart grabbing */ /* The exposure timings need to be recomputed when size is changed */ x = sd->exposure; sd->exposure = -1; if ((r = hdcs_set_exposure(qc, x))<0) goto fail;fail: return r;}/* }}} *//* {{{ [fold] struct qc_sensor qc_sensor_hdcs1000 */const struct qc_sensor qc_sensor_hdcs1000 = { name: "HDCS-1000/1100", manufacturer: "Hewlett Packard", init: hdcs_init, start: hdcs_start, stop: hdcs_stop, set_size: hdcs_set_size, set_levels: hdcs_set_levels, /* Exposure and gain control information */ autoexposure: FALSE, adapt_gainlow: 20, adapt_gainhigh: 20000, /* Information needed to access the sensor via I2C */ reg23: 0, i2c_addr: HDCS_ADDR, /* Identification information used for auto-detection */ id_reg: HDCS_IDENT | 1, id: 0x08, length_id: 1, flag: 0,};/* }}} *//* {{{ [fold] struct qc_sensor qc_sensor_hdcs1020 */const struct qc_sensor qc_sensor_hdcs1020 = { name: "HDCS-1020", manufacturer: "Agilent Technologies", init: hdcs_init, start: hdcs_start, stop: hdcs_stop, set_size: hdcs_set_size, set_levels: hdcs_set_levels, /* Exposure and gain control information */ autoexposure: FALSE, adapt_gainlow: 20, adapt_gainhigh: 20000, /* Information needed to access the sensor via I2C */ reg23: 0, i2c_addr: HDCS_ADDR, /* Identification information used for auto-detection */ id_reg: HDCS_IDENT | 1, id: 0x10, length_id: 1, flag: 1,};/* }}} *//* End of file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -