Re: PATCH: gspca-mercurial OV7630 light frequency filter

"Andoni Zubimendi" <[email protected]> Mon, 21 Jul 2008 21:21:29 -0300
Newsgroups gmane.linux.drivers.spca50x.devel
Message-ID <[email protected]>
Hans,


> So can you please give things a try in 640x480 mode with the divisor kept
> at 3
> or higher, and no changes to 2a / 13 ?


After a weekend away from home (visit a sister in another town), I came back
and made some tests following your suggestions. Taking away the
modifications to the register 0x76, and not touching 0x2a and register 0x13,
I can see a clear image in both resolutions.

I get 30 fps in 320x240 and 10 fps (1/3) in 640x480. The light filter works
fine in both resolutions (tested). As the modifications to 0x2a / 13 is not
needed anymore, I've deleted that part.

After that, I begin playing with the exposure, the reg10_max, I find out
that it's better as you've said, keeping the 0x76 register constant and
playing with register 0x10, 0x11. The value 0x41 is a good value for the
reg10_max, the transition now is smooth when the register 0x11 changes.

Playing with the exposure and changes in the registers gave me 2 problems,
when the register 0x11 was changed, one frame was empty (the one with 0 avg.
lum in the logs) and the next one had half of the picture normal, and the
other half more bright (that's why the avg.lum of the next frame is too high
compared with the others values). It appears that we're changing a register
in the middle of a frame.

I've made a patch that keeps the record of the value of the reg11, and write
it only when the value changes, this made the previous problem appear only
when reg11 changed. To make the bad frames not to be processed I've added
the option to drop 2 frames, when the avg. lum == 0 is detected.

With this modifications, I can make the Auto Exposure control work smooth,
now (with this patches) it's working fine.

I also attach 2 pictures, one "normal" frame and the other with the half
bright.

Regards,

Andoni

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

_______________________________________________
Spca50x-devs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spca50x-devs
patch-ov7630-sonixb-002.patch (text/x-patch, 1.9 KB)
--- a/linux/drivers/media/video/gspca/sonixb.c	2008-07-21 20:41:08.000000000 -0300
+++ b/linux/drivers/media/video/gspca/sonixb.c	2008-07-21 20:40:03.000000000 -0300
@@ -774,6 +778,12 @@
 		i2c[1] = sd->sensor_addr;
 		i2c[3] = reg10;
 		i2c[4] |= reg11 - 1;
+
+		/* If register 11 didn't change, don't change it */
+		if (sd->reg11 == reg11 )
+			i2c[0] = 0xa0;
+		
+		sd->reg11 = reg11;
 		if (i2c_w(gspca_dev, i2c) < 0)
 			PDEBUG(D_ERR, "i2c error exposure");
 		break;
@@ -910,7 +920,8 @@
 	sd->fr_h_sz = 12;		/* default size of the frame header */
 	sd->sd_desc.nctrls = 2;		/* default nb of ctrls */
 	sd->autogain = AUTOGAIN_DEF;    /* default is autogain active */
-
+	sd->reg11 = 1;
+	sd->frames_to_drop = 0;
 	product = id->idProduct;
 /*	switch (id->idVendor) { */
 /*	case 0x0c45:				 * Sonix */
@@ -1205,6 +1216,7 @@
 {
 	int i;
 	struct sd *sd = (struct sd *) gspca_dev;
+	int pkt_type = LAST_PACKET;
 
 	/* frames start with:
 	 *	ff ff 00 c4 c4 96	synchro
@@ -1223,8 +1235,6 @@
 			    && data[3 + i] == 0xc4
 			    && data[4 + i] == 0xc4
 			    && data[5 + i] == 0x96) {	/* start of frame */
-				frame = gspca_frame_add(gspca_dev, LAST_PACKET,
-							frame, data, 0);
 				if (len - i < sd->fr_h_sz) {
 					atomic_set(&sd->avg_lum, -1);
 					PDEBUG(D_STREAM, "packet too short to"
@@ -1234,10 +1244,18 @@
 						data[i + 8] +
 							(data[i + 9] << 8));
 				} else {
-					atomic_set(&sd->avg_lum,
-						data[i + 9] +
-							(data[i + 10] << 8));
+					unsigned short lum = data[i+9] +
+							(data[i + 10] << 8);
+					atomic_set(&sd->avg_lum, lum);
+					if (lum == 0)
+		  				sd->frames_to_drop = 2;
 				}
+				if (sd->frames_to_drop) {
+	      				sd->frames_to_drop--;
+	      				pkt_type = DISCARD_PACKET;
+				}
+				frame = gspca_frame_add(gspca_dev, pkt_type,
+							frame, data, 0);
 				data += i + sd->fr_h_sz;
 				len -= i + sd->fr_h_sz;
 				gspca_frame_add(gspca_dev, FIRST_PACKET,
patch-ov7630-sonixb-001.patch (text/x-patch, 2 KB)
diff -r 822926411b6e linux/drivers/media/video/gspca/sonixb.c
--- a/linux/drivers/media/video/gspca/sonixb.c	Mon Jul 21 18:19:59 2008 +0200
+++ b/linux/drivers/media/video/gspca/sonixb.c	Mon Jul 21 18:56:31 2008 -0300
@@ -358,7 +360,7 @@
 	{0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
 	{0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
 /*	{0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10},	   jfm */
-	{0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10},	/* jfm */
+	{0xd0, 0x21, 0x12, 0x1c, 0x80, 0x80, 0x34, 0x10},	/* jfm */
 	{0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
 	{0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
 	{0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
@@ -381,10 +383,6 @@
 	{0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
 	{0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
 	{0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15},	/* gain */
-};
-static const __u8 ov7630_sensor_init_3[][8] = {
-	{0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
-	{0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
 };
 
 static const __u8 initPas106[] = {
@@ -768,19 +766,16 @@
 		else if (reg10 > reg10_max)
 			reg10 = reg10_max;
 
+		/* In 640x480, if the reg11 has less than 3, the image is 
+		   unstable. */
+		if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv == 0
+		    && reg11 < 3)
+			reg11 = 3;
+
 		/* Write reg 10 and reg11 low nibble */
 		i2c[1] = sd->sensor_addr;
 		i2c[3] = reg10;
 		i2c[4] |= reg11 - 1;
-		if (sd->sensor == SENSOR_OV7630_3) {
-			__u8 reg76 = reg10 & 0x03;
-			__u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00,
-					    0x00, 0x00, 0x00, 0x10};
-			reg10 >>= 2;
-			i2c_reg76[3] = reg76;
-			if (i2c_w(gspca_dev, i2c_reg76) < 0)
-				PDEBUG(D_ERR, "i2c error exposure");
-		}
 		if (i2c_w(gspca_dev, i2c) < 0)
 			PDEBUG(D_ERR, "i2c error exposure");
 		break;
@@ -1138,7 +1133,6 @@
 		i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
 				sizeof ov7630_sensor_init_com);
 		msleep(200);
-		i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
 		break;
 	case SENSOR_PAS106:
 		pas106_i2cinit(gspca_dev);
00000021.jpg (image/jpeg, 15.4 KB) - not displayed
00000022.jpg (image/jpeg, 23.1 KB) - not displayed