📄 spca561.h
字号:
{0x00, 0x1d, 0x8639}, //1d {0x00, 0x21, 0x863a}, //21 {0x00, 0xe3, 0x863b}, //e3 {0x00, 0xdf, 0x863c}, //df {0x00, 0xf0, 0x8505}, {0x00, 0x32, 0x850a}, {0, 0, 0}};static void sensor_mapwrite(struct usb_spca50x *spca50x, __u16 sensormap[][2]){ int i = 0; __u8 usbval[] = { 0, 0 }; while (sensormap[i][0]) { usbval[0] = sensormap[i][1] & 0xff; usbval[1] = (sensormap[i][1] >> 8) & 0xff; spca5xxRegWrite(spca50x->dev, 0x00, 0x00, sensormap[i][0], usbval, 2); i++; }}static int init_161rev12A(struct usb_spca50x *spca50x){ sensor_Reset(spca50x); spca50x_write_vector(spca50x, spca561_161rev12A_data1); sensor_mapwrite(spca50x, Pb100_1map8300); spca50x_write_vector(spca50x, spca561_161rev12A_data2); sensor_mapwrite(spca50x, Pb100_2map8300); return 0;}/************************* End spca561rev12A stuff **********************//************************* Core spca561 stuff ************************/static int spca561_init(struct usb_spca50x *spca50x){ int err; switch (spca50x->chip_revision) { case Rev072A: PDEBUG(0, "Find spca561 USB Product ID %x", spca50x->customid); spca50x_write_vector(spca50x, spca561_init_data); break; case Rev012A: PDEBUG(0, "Find spca561 USB Product ID %x", spca50x->customid); err = init_161rev12A(spca50x); break; default: PDEBUG(0, "Error reading USB Product ID from Global register"); break; } return 0;}#if 0static void spca561_dumpSensor(struct usb_spca50x *spca50x){ int i; __u8 RegSens[] = { 0, 0 }; switch (spca50x->chip_revision) { case Rev072A: /*dump sensor registers */ for (i = 0; i < 0x36; i++) { /* mode 0x10 561, 0x14 mapped */ err = spca561_ReadI2c(spca50x, i, 0x10); PDEBUG(0, "reading Sensor i2c register 0x%02X -> 0x%04X", i, err); } break; case Rev012A: /* Sensor mapped registers */ for (i = 0; i < 0x36; i++) { spca5xxRegRead(spca50x->dev, 0, 0, 0x8300 + i, RegSens, 2); PDEBUG(0, "reading Sensor map0x8300 register 0x%02X -> 0x%04X", i, RegSens[1] << 8 | RegSens[0]); } break; }}#endifstatic void spca561_start(struct usb_spca50x *spca50x){ int err; int Clck = 0; __u8 Reg8307[] = { 0xaa, 0x00 }; switch (spca50x->chip_revision) { case Rev072A: switch (spca50x->mode) { case 0: case 1: Clck = 0x25; break; case 2: Clck = 0x22; break; case 3: Clck = 0x21; break; default: Clck = 0x25; break; } err = spca50x_reg_write(spca50x->dev, 0, 0x8500, spca50x->mode); // mode err = spca50x_reg_write(spca50x->dev, 0, 0x8700, Clck); // 0x27 clock err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x10 | 0x20); break; case Rev012A: switch (spca50x->mode) { case 0: Clck = 0x8a; break; case 1: Clck = 0x8a; break; case 2: Clck = 0x85; break; default: Clck = 0x83; break; } if (spca50x->mode <= 1) { // Use compression on 320x240 and above err = spca50x_reg_write(spca50x->dev, 0, 0x8500, 0x10 | spca50x->mode); } else { // I couldn't get the compression to work below 320x240 // Fortunately at these resolutions the bandwidth is sufficient // to push raw frames at ~20fps err = spca50x_reg_write(spca50x->dev, 0, 0x8500, spca50x->mode); } // -- qq@kuku.eu.org spca5xxRegWrite(spca50x->dev, 0, 0, 0x8307, Reg8307, 2); err = spca50x_reg_write(spca50x->dev, 0, 0x8700, Clck); // 0x8f 0x85 0x27 clock err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x1e | 0x20); err = spca50x_reg_write(spca50x->dev, 0, 0x850b, 0x03); spca50x->brightness = 0x4000; spca50x->contrast = 0x2000; spca561_setcontrast(spca50x); break; default: PDEBUG(0, "Error reading USB Product ID from Global register"); break; }}static void spca561_stopN(struct usb_spca50x *spca50x){ int err; err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x20); //}static void spca561_setbrightness(struct usb_spca50x *spca50x){ __u8 value = 0; switch (spca50x->chip_revision) { case Rev072A: value = spca50x->brightness >> 9; spca5xxRegWrite(spca50x->dev, 0, value, 0x8611, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, value, 0x8612, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, value, 0x8613, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, value, 0x8614, NULL, 0); break; case Rev012A: spca561_setcontrast(spca50x); break; }}static __u16 spca561_getbrightness(struct usb_spca50x *spca50x){ __u8 value = 0; __u16 tot = 0; switch (spca50x->chip_revision) { case Rev072A: spca5xxRegRead(spca50x->dev, 0, 0, 0x8611, &value, 1); tot += value; spca5xxRegRead(spca50x->dev, 0, 0, 0x8612, &value, 1); tot += value; spca5xxRegRead(spca50x->dev, 0, 0, 0x8613, &value, 1); tot += value; spca5xxRegRead(spca50x->dev, 0, 0, 0x8614, &value, 1); tot += value; spca50x->brightness = tot << 7; break; case Rev012A: // no way to read sensor settings break; } return spca50x->brightness;}static void spca561_setcontrast(struct usb_spca50x *spca50x){ __u8 lowb; int expotimes = 0; __u8 Reg8391[] = { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 }; switch (spca50x->chip_revision) { case Rev072A: lowb = (spca50x->contrast >> 8) & 0xFF; spca5xxRegWrite(spca50x->dev, 0, lowb, 0x8651, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, lowb, 0x8652, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, lowb, 0x8653, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, lowb, 0x8654, NULL, 0); break; case Rev012A: // Write camera sensor settings expotimes = (spca50x->contrast >> 5) & 0x07ff; Reg8391[0] = expotimes & 0xff; // exposure Reg8391[1] = 0x18 | (expotimes >> 8); Reg8391[2] = spca50x->brightness >> 9; // gain spca5xxRegWrite(spca50x->dev, 0, 0, 0x8391, Reg8391, 8); spca5xxRegWrite(spca50x->dev, 0, 0, 0x8390, Reg8391, 8); break; }}static __u16 spca561_getcontrast(struct usb_spca50x *spca50x){ __u8 value = 0; __u16 tot = 0; switch (spca50x->chip_revision) { case Rev072A: value = 0; spca5xxRegRead(spca50x->dev, 0, 0, 0x8651, &value, 1); tot += value; spca5xxRegRead(spca50x->dev, 0, 0, 0x8652, &value, 1); tot += value; spca5xxRegRead(spca50x->dev, 0, 0, 0x8653, &value, 1); tot += value; spca5xxRegRead(spca50x->dev, 0, 0, 0x8654, &value, 1); tot += value; spca50x->contrast = tot << 6; break; case Rev012A: // no way to read sensor settings break; } PDEBUG(4,"get contrast %d\n",spca50x->contrast); return spca50x->contrast;}static int spca561_config(struct usb_spca50x *spca50x){ __u8 data1, data2; // Read frm global register the USB product and vendor IDs, just to // prove that we can communicate with the device. This works, which // confirms at we are communicating properly and that the device // is a 561. spca5xxRegRead(spca50x->dev, 0, 0, 0x8104, &data1, 1); spca5xxRegRead(spca50x->dev, 0, 0, 0x8105, &data2, 1); PDEBUG(1, "Read from GLOBAL: USB Vendor ID 0x%02x%02x", data2, data1); spca5xxRegRead(spca50x->dev, 0, 0, 0x8106, &data1, 1); spca5xxRegRead(spca50x->dev, 0, 0, 0x8107, &data2, 1); PDEBUG(1, "Read from GLOBAL: USB Product ID 0x%02x%02x", data2, data1); spca50x->customid = ((data2 << 8) | data1) & 0xffff; switch (spca50x->customid) { case 0x7004: case 0xa001: case 0x0815: case 0x0561: case 0xcdee: case 0x7e50: case 0x401a: spca50x->chip_revision = Rev072A; break; case 0x0928: case 0x0929: case 0x092a: case 0x403b: case 0x092b: case 0x092c: case 0x092d: case 0x092e: case 0x092f: spca50x->chip_revision = Rev012A; break; default: PDEBUG(0, "Spca561 chip Unknow Contact the Author"); return -EINVAL; break; } memset(spca50x->mode_cam, 0x00, TOTMODE * sizeof(struct mwebcam)); spca50x->mode_cam[SIF].width = 352; spca50x->mode_cam[SIF].height = 288; spca50x->mode_cam[SIF].t_palette = P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16; spca50x->mode_cam[SIF].pipe = 1023; spca50x->mode_cam[SIF].method = 0; spca50x->mode_cam[SIF].mode = 0; spca50x->mode_cam[CIF].width = 320; spca50x->mode_cam[CIF].height = 240; spca50x->mode_cam[CIF].t_palette = P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16; spca50x->mode_cam[CIF].pipe = 1023; spca50x->mode_cam[CIF].method = 0; spca50x->mode_cam[CIF].mode = 1; spca50x->mode_cam[QPAL].width = 192; spca50x->mode_cam[QPAL].height = 144; spca50x->mode_cam[QPAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16; spca50x->mode_cam[QPAL].pipe = 1023; spca50x->mode_cam[QPAL].method = 1; spca50x->mode_cam[QPAL].mode = 1; spca50x->mode_cam[QSIF].width = 176; spca50x->mode_cam[QSIF].height = 144; spca50x->mode_cam[QSIF].t_palette = P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16; spca50x->mode_cam[QSIF].pipe = 1023; spca50x->mode_cam[QSIF].method = 0; spca50x->mode_cam[QSIF].mode = 2; spca50x->mode_cam[QCIF].width = 160; spca50x->mode_cam[QCIF].height = 120; spca50x->mode_cam[QCIF].t_palette = P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16; spca50x->mode_cam[QCIF].pipe = 1023; spca50x->mode_cam[QCIF].method = 0; spca50x->mode_cam[QCIF].mode = 3; return 0; // success}static void spca561_shutdown(struct usb_spca50x *spca50x){ spca5xxRegWrite(spca50x->dev, 0, 0, 0x8114, NULL, 0);}static void spca561_setAutobright(struct usb_spca50x *spca50x){ int expotimes = 0; int pixelclk = 0; int gainG = 0; __u8 R, Gr, Gb, B; int y; __u8 luma_mean = 110; __u8 luma_delta = 20; __u8 spring = 4; switch (spca50x->chip_revision) { case Rev072A: spca5xxRegRead(spca50x->dev, 0, 0, 0x8621, &Gr, 1); spca5xxRegRead(spca50x->dev, 0, 0, 0x8622, &R, 1); spca5xxRegRead(spca50x->dev, 0, 0, 0x8623, &B, 1); spca5xxRegRead(spca50x->dev, 0, 0, 0x8624, &Gb, 1); y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8; //u= (128*B-(43*(Gr+Gb+R))) >> 8; //v= (128*R-(53*(Gr+Gb))-21*B) >> 8; //PDEBUG(0,"reading Y %d U %d V %d ",y,u,v); if ((y < (luma_mean - luma_delta)) || (y > (luma_mean + luma_delta))) { expotimes = spca561_ReadI2c(spca50x, 0x09, 0x10); pixelclk = 0x0800; expotimes = expotimes & 0x07ff; //PDEBUG(0,"Exposition Times 0x%03X Clock 0x%04X ",expotimes,pixelclk); gainG = spca561_ReadI2c(spca50x, 0x35, 0x10); //PDEBUG(0,"reading Gain register %d",gainG); expotimes += ((luma_mean - y) >> spring); gainG += ((luma_mean - y) / 50); // PDEBUG(0 , "compute expotimes %d gain %d",expotimes,gainG); if (gainG > 0x3F) gainG = 0x3f; else if (gainG < 4) gainG = 3; spca561_WriteI2c(spca50x, (__u16) gainG, 0x35); if (expotimes >= 0x0256) expotimes = 0x0256; else if (expotimes < 4) { expotimes = 3; } spca561_WriteI2c(spca50x, (__u16) (expotimes | pixelclk), 0x09); } break; case Rev012A: /* sensor registers is access and memory mapped to 0x8300 */ /* readind all 0x83xx block the sensor */ /* The data from the header seem wrong where is the luma and chroma mean value at the moment set exposure in contrast set */ ; break; default: break; }}static int spca561_sofdetect(struct usb_spca50x *spca50x,struct spca50x_frame *frame, unsigned char *cdata,int *iPix, int seqnum, int *datalength){ switch (cdata[0]){ case 0: *iPix = SPCA561_OFFSET_DATA; *datalength -= *iPix; return 0; case SPCA50X_SEQUENCE_DROP: return -1; default: *iPix = 1; *datalength -= *iPix; return seqnum+1 ; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -