📄 qc-vv6450.c
字号:
// low val -> ljus area blir ljusare./* LOGTAG */ { NULL, 0x1503, 0x45 },// high val-> ljus area blir morkare.// low val -> ljus area blir ljusare./* LOGTAG */ { NULL, 0x1505, 0x02 },// 2 : 324x248 80352 bytes// 7 : 248x162 40176 bytes// c+f: 162*124 20088 bytes/* LOGTAG */ { NULL, 0x150e, 0x8e },/* LOGTAG */ { NULL, 0x150f, 0x37 },/* LOGTAG */ { NULL, 0x15c0, 0x00 },/* LOGTAG */ { NULL, 0x15c1, ISOC_PACKET_SIZE }, /* 160x120 */ /* ISOC_PACKET_SIZE *//* LOGTAG */ { NULL, 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? *//* LOGTAG */ { NULL, 0x143f, 0x01 }, /* commit settings */ }; unsigned int cols = 416; unsigned int rows = 320; int i,j; if (qcdebug&QC_DEBUGLOGIC) PDEBUG("vv6450_init(quickcam=%p)",qc); if (PARANOID && !qc) { PDEBUG("qc==NULL"); return -EINVAL; } for (i=0; i<SIZE(stv_init); i++) { if (stv_init[i].data==NULL) { if(stv_init[i].len & 0xFF00) { if ((r = qc_stv_setw(qc,(stv_init[i].start), cpu_to_le16(stv_init[i].len)))<0) PDEBUG("qc_stv_setw: error"); } else { STV_SET_CHECK(stv_init[i].start, stv_init[i].len); } } else { for (j=0; j<stv_init[i].len; j++) { STV_SET_CHECK(stv_init[i].start+j, stv_init[i].data[j]); } } } sd->width = 324; // This is what is setup in the init-string sd->height = 248; sd->maxwidth = MAX_FRAME_WIDTH; sd->maxheight = MAX_FRAME_HEIGHT; //PDEBUG("Setup maxwidth=%d,%d\n", sd->maxwidth, sd->maxheight); if (!sd->compress) { /* Disable compression */#if 0 STV_SET_CHECK(0x1443, sd->subsample ? 0x00 : 0x10); /* Scan rate: Larger -> slower */ STV_SETW_CHECK(0x15C1, 1023); /* ISO-Size */ STV_SET_CHECK(0x15C3, 1); /* Y control */#endif if (qc->settings.subsample) { //FIXME:subsampling (still) doesn't work yet cols=250; rows=160; sd->width = 180; sd->height = 148;#if 0 I2C_SET_CHECK(VV6450_SETUP0, BIT(7)|BIT(6)|BIT(1)|BIT(0)); /* Subsampled timing mode */#endif if (qcdebug&QC_DEBUGLOGIC) PDEBUG("WARNING: subsample\n"); } } return r;fail: //PDEBUG("Error setup"); return r;}static int vv6450_set_exposure(struct quickcam *qc, unsigned int val){ struct qc_sensor_data *sd = &qc->sensor_data; int r = 0; int a = (val >> 12) & 0x0F;#if 1 int oldval = sd->exposure; if (val == oldval) return 0; sd->exposure = val; if ((oldval>>12) == a) return 0;#else if((sd->exposure>>12) == a) return 0; sd->exposure = val;#endif if(a >= 14) a = 14; if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("vv6450_set_exposure %d (%d)",sd->exposure, a); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x143A, 0xF0 | a); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x143F, 0x01); // commit settings //qc_frame_flush(qc); return r; fail: //PDEBUG("Error: vv6450_set_exposure"); return r;} int toggle = 0;int toggle_val[4] = {0x00, 0x15, 0x2A, 0x3F};static int vv6450_set_gains(struct quickcam *qc, u16 hue, u16 sat, u16 val){ static const unsigned int min_gain = 8; struct qc_sensor_data *sd = &qc->sensor_data; unsigned int rgain, bgain, ggain; int r = 0; qc_hsv2rgb(hue, sat, val, &rgain, &bgain, &ggain); rgain >>= 12; /* After this the values are 0..15 */ ggain >>= 12; bgain >>= 12; /* Do not allow very small values, they cause bad (low-contrast) image */ rgain = MAX(rgain, min_gain); ggain = MAX(ggain, min_gain); bgain = MAX(bgain, min_gain); //PDEBUG("debug: vv6450_set_gains hue=%d sat=%d val=%d rgain=%02d ggain=%02d bgain=%02d", hue, sat, val, rgain, ggain, bgain); if (rgain==sd->rgain && ggain==sd->ggain && bgain==sd->bgain) { return 0; } sd->rgain = rgain; sd->ggain = ggain; sd->bgain = bgain; //#define RAISE_GAIN#ifdef RAISE_GAIN // don't know if there are any other bit to raise gain... if (rgain > 15) rgain = rgain/2 | 0x80; else rgain += 0x30; if (ggain > 15) ggain = ggain/2 | 0x80; else ggain += 0x30; if (bgain > 15) bgain = bgain/2 | 0x80; else bgain += 0x30;#else rgain |= 0x30; ggain |= 0x30; bgain |= 0x30;#endif if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("vv6450_set_gains hue=%d sat=%d val=%d rgain=%02X(%02X) ggain=%02X(%02X) bgain=%02X(%02X)", hue, sat, val, rgain, sd->rgain, ggain, sd->ggain, bgain, sd->bgain); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x0509, rgain); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x050A, ggain); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x050B, bgain); r = qc_i2c_wait(qc); if(r) goto fail;#if 0 // a stupid test... val = toggle_val[toggle++ % 4]; STV_SET_CHECK(0x050C, val); // 0, 15, 2A, 3F have no idea about this#else STV_SET_CHECK(0x050C, 0x2A); // 0, 15, 2A, 3F have no idea about this#endif r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x050D, 0x01);#if 1 r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x143F, 0x01); // commit settings#endif return r;fail: if (qcdebug&QC_DEBUGADAPTATION) PDEBUG("vv6450_set_gains: error"); return r;}/* {{{ [fold] vv6450_set_levels() */static int vv6450_set_levels(struct quickcam *qc, unsigned int exp, unsigned int gain, unsigned int hue, unsigned int sat){//set_levels(qc, qc->vpic.brightness, qc->vpic.contrast, qc->vpic.hue, qc->vpic.colour)//set_target(qc, qc->vpic.brightness) int r = 0; if ((r = vv6450_set_exposure(qc, exp))<0) goto fail; r = vv6450_set_gains(qc, hue, sat, gain); if(r) goto fail; return r;fail: PDEBUG("vv6450_set_levels: error"); return r;}/* }}} *//* {{{ [fold] vv6450_set_shutter: Set shutter value for sensor, val=0..65535 */static int vv6450_set_shutter(struct quickcam *qc, unsigned int val){ struct qc_sensor_data *sd = &qc->sensor_data; int r; int oldval; //PDEBUG("vv6450_set_shutter: val=%d", val); if (val == sd->shutter) return 0; oldval = sd->shutter; sd->shutter = val;#define SHUTTER_SHIFT 8 if ((val>>SHUTTER_SHIFT) == (oldval>>SHUTTER_SHIFT)) return 0; /* rescale the value if greater than 0xC000 */ if(val > 0xC000) { val = 0xC000 + (val&0x3FFF)*8; } /* 0xZZZZ -> 03 FF (max value, but never used) 0xFFFF -> 02 B0 (extreme light and slow frame rate) 0xC100 -> 00 C8 0xC000 -> 00 C0 0x8000 -> 00 80 (normal value) 0x0000 -> 00 00 (extreme dark and fast frame rate) */ //PDEBUG("vv6450_set_shutter: val=%d (%04X)", val, (val >> SHUTTER_SHIFT)); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x143d, (val >> SHUTTER_SHIFT) & 0xff); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x143e, (val >> (SHUTTER_SHIFT+8)) & 0x03); r = qc_i2c_wait(qc); if(r) goto fail; STV_SET_CHECK(0x143F, 0x01); return r;fail: PDEBUG("error set_shutter"); return r;}/* }}} *//* {{{ [fold] vv6450_set_target: Set target brightness for sensor autoexposure, val=0..65535 */static int vv6450_set_target(struct quickcam *qc, unsigned int val){ int r = 0; //PDEBUG("vv6450_set_target: val=%d", val);#ifdef WHITENESS_IS_SHUTTER if (val == qc->vpic.whiteness) return 0; qc->vpic.whiteness = val;#else if (val == qc->vpic.brightness) return 0; qc->vpic.brightness = val;#endif //PDEBUG("vv6450_set_target: call set_shutter (%d) %d", val, qc->settings.shutteradapt); if(!qc->settings.shutteradapt) { r = vv6450_set_shutter(qc, val); } if(r) goto fail; return r;fail: PDEBUG("error set_target"); return r;}/* }}} */const struct qc_sensor qc_sensor_vv6450 = { name: "VV6450", manufacturer: "ST Microelectronics", init: vv6450_init, start: vv6450_start, stop: vv6450_stop, set_size: vv6450_set_size, set_levels: vv6450_set_levels, set_target: vv6450_set_target, set_shutter: vv6450_set_shutter, autoexposure: FALSE,#if 1 adapt_gainlow: 40000, adapt_gainhigh: 65535,#else adapt_gainlow: 1000, adapt_gainhigh: 65535,#endif /* Information needed to access the sensor via I2C */ reg23: -1, // not used i2c_addr: (unsigned char)-1, // not used /* Identification information used for auto-detection */ id_reg: VV6450_DEVICEH, /* 0x08F0, 0x08F5, 0x08F6 is known to be Messenger */ id: 0x08, length_id: 2,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -