📄 spca561.h
字号:
}static int init_161rev12A(struct usb_spca50x *spca50x){ int err; __u8 Reg8391[] = { 0x23, 0x31, 0x10, 0x00, 0x3a, 0x00, 0x00, 0x00 }; //14 __u8 Reg8307[] = { 0xaa, 0x00 }; err = spca50x_reg_write(spca50x->dev, 0, 0x8620, 0x00); // 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); err = spca50x_reg_write(spca50x->dev, 0, 0x8700, 0x85); // 0x27 clock spca5xxRegWrite(spca50x->dev, 0, 0, 0x8391, Reg8391, 8); spca5xxRegWrite(spca50x->dev, 0, 0, 0x8390, Reg8391, 8); err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x10 | 0x20); err = spca50x_reg_write(spca50x->dev, 0, 0x850b, 0x03); err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x00);//set_alternate setting 0 err = spca50x_reg_write(spca50x->dev, 0, 0x8118, 0x29); err = spca50x_reg_write(spca50x->dev, 0, 0x8114, 0x00);//set_alternate setting 7 spca50x_write_vector(spca50x, spca561_161rev12A_data2); spca5xxRegWrite(spca50x->dev, 0, 0, 0x8307, Reg8307, 2); err = spca50x_reg_write(spca50x->dev, 0, 0x8700, 0x85); // 0x27 clock spca5xxRegWrite(spca50x->dev, 0, 0, 0x8391, Reg8391, 8); spca5xxRegWrite(spca50x->dev, 0, 0, 0x8390, Reg8391, 8); err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x10 | 0x20); err = spca50x_reg_write(spca50x->dev, 0, 0x850b, 0x03); err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x20); // 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 }; __u8 Reg8391[] = { 0x90, 0x31, 0x0b, 0x00, 0x25, 0x00, 0x00, 0x00 }; //90 31 0c 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 =(spca50x->customid == 0x403b) ? 0x8a : 0x8f; Clck = 0x8a; break; case 1: Clck = 0x8a; break; case 2: Clck = 0x85; Reg8391[1] = 0x22; // increase pixel clock increase time exposure break; case 3: Clck = 0x83; Reg8391[1] = 0x22; break; default: Clck = 0x25; break; } if (compress && spca50x->mode <= 1) { // this is correct for 320x240; it also works at 352x288 // hell, I don't even know what this value means :) Clck = 0x83; 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 spca5xxRegWrite(spca50x->dev, 0, 0, 0x8391, Reg8391, 8); spca5xxRegWrite(spca50x->dev, 0, 0, 0x8390, Reg8391, 8); spca50x->exposure = ((Reg8391[1]) << 8) | Reg8391[0]; //set exposure with clock err = spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x10 | 0x20); err = spca50x_reg_write(spca50x->dev, 0, 0x850b, 0x03); 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; value = spca50x->brightness >> 9; switch (spca50x->chip_revision) { case Rev072A: 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: spca5xxRegWrite(spca50x->dev, 0, value, 0x8615, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, value, 0x8614, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, value, 0x8616, NULL, 0); spca5xxRegWrite(spca50x->dev, 0, value, 0x8617, NULL, 0); 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: spca5xxRegRead(spca50x->dev, 0, 0, 0x8615, &value, 1); spca50x->brightness = value << 9; break; } return spca50x->brightness;}static void spca561_setcontrast(struct usb_spca50x *spca50x){ __u8 lowb = 0; int expotimes = 0; int pixelclk = 0; __u8 Reg8391[] = { 0x90, 0x31, 0x0b, 0x00, 0x25, 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: lowb = (spca50x->contrast >> 10) & 0x7F; if (lowb < 4) lowb = 3; pixelclk = spca50x->exposure & 0xf800; spca50x->exposure = ((spca50x->contrast >> 5) & 0x07ff) | pixelclk; expotimes = spca50x->exposure & 0x07ff; Reg8391[0] = expotimes & 0xff; Reg8391[1] = ((pixelclk >> 8) & 0xf8) | ((expotimes >> 8) & 0x07); Reg8391[2] = lowb; PDEBUG(4, "Set Exposure 0x%02x 0x%02x gain 0x%02x", Reg8391[0], Reg8391[1], Reg8391[2]); spca5xxRegWrite(spca50x->dev, 0, 0, 0x8390, Reg8391, 8); break; }}static __u16 spca561_getcontrast(struct usb_spca50x *spca50x){ __u8 value = 0; __u16 tot = 0; __u8 contrast = 0x0b; __u8 RegSens[] = { 0, 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: spca5xxRegWrite(spca50x->dev, 0, 0, 0x8335, &contrast, 1); /* always 0x8335 return 0 */ spca5xxRegRead(spca50x->dev, 0, 0, 0x8335, RegSens, 2); spca50x->contrast = (contrast & 0x7f) << 10; PDEBUG(2, "Get constrast 0x8335 0x%04x", RegSens[1] << 8 | RegSens[0]); 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 + -