Hi!
I've been working on gain support for aes1610. So here's a patch for that.
I would really like to have some feedback from other users having this device. I'd like to know if you get better results with it (or not).
>From my tests, I get a bit more minutiae (something like 20~25) but the scores I get are still not that much > 10 when it matches... I didn't have any false positive but there are still too many false negatives compared to the windows driver. There will be some work to do on enrollment/matching.
It will need some adjustments and tweaking. The code will need some cleaning after that.

diff -aburNp ./git/libfprint/drivers/aes1610.c ./patched/libfprint/drivers/aes1610.c
--- ./git/libfprint/drivers/aes1610.c	2008-01-05 12:56:15.000000000 +0100
+++ ./patched/libfprint/drivers/aes1610.c	2008-01-05 13:04:09.000000000 +0100
@@ -59,6 +59,8 @@
 /* maximum number of frames to read during a scan */
 /* FIXME reduce substantially */
 #define MAX_FRAMES		350
+#define GAIN_STATUS_FIRST 1
+#define GAIN_STATUS_NORMAL 2
 
 static int read_data(struct fp_img_dev *dev, unsigned char *data, size_t len)
 {
@@ -143,119 +145,7 @@ static const struct aes_regwrite finger_
 	{ 0x1D, 0x00 }
 };
 
-static int detect_finger(struct fp_img_dev *dev)
-{
-	unsigned char buffer[19];
-	int r;
-	int i;
-	int sum = 0;
-
-	r = aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs));
-	if (r < 0)
-		return r;
-
-	r = read_data(dev, buffer, 19);
-	if (r < 0)
-		return r;
-
-	for (i = 3; i < 17; i++)
-		sum += (buffer[i] & 0xf) + (buffer[i] >> 4);
-		
-	/* We need to answer something if no finger has been detected */
-	if (sum <= 20) {
-		r = aes_write_regv(dev, finger_det_none, G_N_ELEMENTS(finger_det_none));
-		if (r < 0)
-			return r;
-	}
-	
-	return sum > 20;
-}
-
-static int await_finger_on(struct fp_img_dev *dev)
-{
-	int r;
-	do {
-		r = detect_finger(dev);
-	} while (r == 0);
-	return (r < 0) ? r : 0;
-}
-
-/* find overlapping parts of frames */
-static unsigned int find_overlap(unsigned char *first_frame,
-	unsigned char *second_frame, unsigned int *min_error)
-{
-	unsigned int dy;
-	unsigned int not_overlapped_height = 0;
-	*min_error = 255 * FRAME_SIZE;
-	for (dy = 0; dy < FRAME_HEIGHT; dy++) {
-		/* Calculating difference (error) between parts of frames */
-		unsigned int i;
-		unsigned int error = 0;
-		for (i = 0; i < FRAME_WIDTH * (FRAME_HEIGHT - dy); i++) {
-			/* Using ? operator to avoid abs function */
-			error += first_frame[i] > second_frame[i] ? 
-					(first_frame[i] - second_frame[i]) :
-					(second_frame[i] - first_frame[i]); 
-		}
-		
-		/* Normalize error */
-		error *= 15;
-		error /= i;
-		if (error < *min_error) {
-			*min_error = error;
-			not_overlapped_height = dy;
-		}
-		first_frame += FRAME_WIDTH;
-	}
-	
-	return not_overlapped_height; 
-}
-
-/* assemble a series of frames into a single image */
-static unsigned int assemble(unsigned char *input, unsigned char *output,
-	int num_strips, gboolean reverse, unsigned int *errors_sum)
-{
-	uint8_t *assembled = output;
-	int frame;
-	uint32_t image_height = FRAME_HEIGHT;
-	unsigned int min_error;
-	*errors_sum = 0;
-
-	if (num_strips < 1)
-		return 0;
-	
-	/* Rotating given data by 90 degrees 
-	 * Taken from document describing aes1610 image format
-	 * TODO: move reversing detection here */
-	
-	if (reverse)
-		output += (num_strips - 1) * FRAME_SIZE;
-	for (frame = 0; frame < num_strips; frame++) {
-		aes_assemble_image(input, FRAME_WIDTH, FRAME_HEIGHT, output);
-		input += FRAME_WIDTH * (FRAME_HEIGHT / 2);
-
-		if (reverse)
-			output -= FRAME_SIZE;
-		else
-			output += FRAME_SIZE;
-	}
-
-	/* Detecting where frames overlaped */
-	output = assembled;
-	for (frame = 1; frame < num_strips; frame++) {
-		int not_overlapped;
-
-		output += FRAME_SIZE;
-		not_overlapped = find_overlap(assembled, output, &min_error);
-		*errors_sum += min_error;
-		image_height += not_overlapped;
-		assembled += FRAME_WIDTH * not_overlapped;
-		memcpy(assembled, output, FRAME_SIZE); 
-	}
-	return image_height;
-}
-
-static const struct aes_regwrite capture_reqs[] = {
+static struct aes_regwrite capture_reqs[] = {
 	{ 0x80, 0x01 },
 	{ 0x80, 0x12 },
 	{ 0x84, 0x01 },
@@ -265,8 +155,8 @@ static const struct aes_regwrite capture
 	{ 0x8B, 0x0E },
 	{ 0x8C, 0x90 },
 	{ 0xBE, 0x23 },
-	{ 0x29, 0x06 },
-	{ 0x2A, 0x35 },
+	{ 0x29, 0x04 },
+	{ 0x2A, 0xFF },
 	{ 0x96, 0x00 },
 	{ 0x98, 0x03 },
 	{ 0x99, 0x00 },
@@ -381,14 +271,277 @@ static const struct aes_regwrite capture
 	{ 0x81, 0x01 }
 };
 
-static const struct aes_regwrite strip_scan_reqs[] = {
-	{ 0xBE, 0x23 },
-	{ 0x29, 0x06 },
-	{ 0x2A, 0x35 },
-	{ 0xBD, 0x4F },
+/* Sent to the device every 2/3 strips to adjust the gain */
+static struct aes_regwrite strip_scan_reqs[] = {
+	{ 0xBE, 0x23 }, // default value for the gain
+	{ 0x29, 0x04 }, // default value for the gain
+	{ 0x2A, 0xFF }, // default value for the gain
+	{ 0xBD, 0x4F }, // default value for the gain
 	{ 0xFF, 0x00 }
 };
 
+/*
+	The different possible values for 0xBE register
+*/
+static unsigned char list_BE_values[10] = {
+	0x23, 0x43, 0x63, 0x64, 0x65, 0x67, 0x6A, 0x6B
+};
+
+/*
+	The different possible values for 0xBD register
+*/
+static unsigned char list_BD_values[10] = {
+	0x48, 0x4B, 0x4F, 0x52, 0x57, 0x59, 0x5B
+};
+
+/*
+	Adjust the gain according to the histogram data
+	0xbd, 0xbe, 0x29 and 0x2A registers are affected
+	Returns 0 if no problem occured
+	TODO: This is a basic support for gain. It needs testing/tweaking.
+ */
+static int adjust_gain(unsigned char *buffer, int status)
+{
+	// The position in the array of possible values for 0xBE and 0xBD registers
+	static int pos_list_BE = 0;
+	static int pos_list_BD = 0;
+	
+	// This is the first adjustement (we begin acquisition)
+	// We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step
+	if (status == GAIN_STATUS_FIRST) {
+		if (buffer[1] > 0x78) { // maximum gain needed
+			strip_scan_reqs[0].value = 0x6B;
+			strip_scan_reqs[1].value = 0x04;
+			strip_scan_reqs[2].value = 0xFF;
+			strip_scan_reqs[3].value = 0x5B;
+		}
+		else if (buffer[1] > 0x55) {
+			strip_scan_reqs[0].value = 0x63;
+			strip_scan_reqs[1].value = 0x15;
+			strip_scan_reqs[2].value = 0x35;
+			strip_scan_reqs[3].value = 0x4F;
+		}
+		else if (buffer[1] > 0x40 || buffer[16] > 0x19) {
+			strip_scan_reqs[0].value = 0x43;
+			strip_scan_reqs[1].value = 0x13;
+			strip_scan_reqs[2].value = 0x35;
+			strip_scan_reqs[3].value = 0x4B;
+		}
+		else { // minimum gain needed
+			strip_scan_reqs[0].value = 0x23;
+			strip_scan_reqs[1].value = 0x07;
+			strip_scan_reqs[2].value = 0x35;
+			strip_scan_reqs[3].value = 0x48;
+		}
+		
+		// Now copy this values in capture_reqs
+		capture_reqs[8].value = strip_scan_reqs[0].value;
+		capture_reqs[9].value = strip_scan_reqs[1].value;
+		capture_reqs[10].value = strip_scan_reqs[2].value;
+		capture_reqs[21].value = strip_scan_reqs[3].value;
+		
+		fp_dbg("first gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value);
+	}
+	
+	// Every 2/3 strips
+	// We try to soften big changes of the gain (at least for 0xBE and 0xBD
+	// FIXME: This softenning will need testing and tweaking too
+	else if (status == GAIN_STATUS_NORMAL) {
+		if (buffer[514] > 0x78) { // maximum gain needed
+			if (pos_list_BE < 7)
+				pos_list_BE++;
+				
+			if (pos_list_BD < 6)
+				pos_list_BD++;
+				
+			strip_scan_reqs[1].value = 0x04;
+			strip_scan_reqs[2].value = 0xFF;
+		}
+		else if (buffer[514] > 0x55) {
+			if (pos_list_BE < 2)
+				pos_list_BE++;
+			else if (pos_list_BE > 2)
+				pos_list_BE--;
+				
+			if (pos_list_BD < 2)
+				pos_list_BD++;
+			else if (pos_list_BD > 2)
+				pos_list_BD--;
+				
+			strip_scan_reqs[1].value = 0x15;
+			strip_scan_reqs[2].value = 0x35;
+		}
+		else if (buffer[514] > 0x40 || buffer[529] > 0x19) {
+			if (pos_list_BE < 1)
+				pos_list_BE++;
+			else if (pos_list_BE > 1)
+				pos_list_BE--;
+				
+			if (pos_list_BD < 1)
+				pos_list_BD++;
+			else if (pos_list_BD > 1)
+				pos_list_BD--;
+				
+			strip_scan_reqs[1].value = 0x13;
+			strip_scan_reqs[2].value = 0x35;
+		}
+		else { // minimum gain needed
+			if (pos_list_BE > 0)
+				pos_list_BE--;
+				
+			if (pos_list_BD > 0)
+				pos_list_BD--;
+				
+			strip_scan_reqs[1].value = 0x07;
+			strip_scan_reqs[2].value = 0x35;
+		}
+		
+		strip_scan_reqs[0].value = list_BE_values[pos_list_BE];
+		strip_scan_reqs[3].value = list_BD_values[pos_list_BD];
+		
+		fp_dbg("gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value);
+	}
+	
+	// Unknown status
+	else {
+		fp_err("Unexpected gain status.");
+		return 1;
+	}
+	
+	return 0;
+}
+
+/*
+	Restore the default gain values
+*/
+static void restore_gain()
+{
+	strip_scan_reqs[0].value = list_BE_values[0];
+	strip_scan_reqs[1].value = 0x04;
+	strip_scan_reqs[2].value = 0xFF;
+	strip_scan_reqs[3].value = list_BD_values[0];
+	
+	capture_reqs[8].value = list_BE_values[0];
+	capture_reqs[9].value = 0x04;
+	capture_reqs[10].value = 0xFF;
+	capture_reqs[21].value = list_BD_values[0];
+}
+
+static int detect_finger(struct fp_img_dev *dev)
+{
+	unsigned char buffer[19];
+	int r;
+	int i;
+	int sum = 0;
+
+	r = aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs));
+	if (r < 0)
+		return r;
+
+	r = read_data(dev, buffer, 19);
+	if (r < 0)
+		return r;
+
+	for (i = 3; i < 17; i++)
+		sum += (buffer[i] & 0xf) + (buffer[i] >> 4);
+		
+	/* We need to answer something if no finger has been detected */
+	if (sum <= 20) {
+		r = aes_write_regv(dev, finger_det_none, G_N_ELEMENTS(finger_det_none));
+		if (r < 0)
+			return r;
+	}
+	
+	if (sum > 20)
+		adjust_gain(buffer,GAIN_STATUS_FIRST);
+	
+	return sum > 20;
+}
+
+static int await_finger_on(struct fp_img_dev *dev)
+{
+	int r;
+	do {
+		r = detect_finger(dev);
+	} while (r == 0);
+	return (r < 0) ? r : 0;
+}
+
+/* find overlapping parts of frames */
+static unsigned int find_overlap(unsigned char *first_frame,
+	unsigned char *second_frame, unsigned int *min_error)
+{
+	unsigned int dy;
+	unsigned int not_overlapped_height = 0;
+	*min_error = 255 * FRAME_SIZE;
+	for (dy = 0; dy < FRAME_HEIGHT; dy++) {
+		/* Calculating difference (error) between parts of frames */
+		unsigned int i;
+		unsigned int error = 0;
+		for (i = 0; i < FRAME_WIDTH * (FRAME_HEIGHT - dy); i++) {
+			/* Using ? operator to avoid abs function */
+			error += first_frame[i] > second_frame[i] ? 
+					(first_frame[i] - second_frame[i]) :
+					(second_frame[i] - first_frame[i]); 
+		}
+		
+		/* Normalize error */
+		error *= 15;
+		error /= i;
+		if (error < *min_error) {
+			*min_error = error;
+			not_overlapped_height = dy;
+		}
+		first_frame += FRAME_WIDTH;
+	}
+	
+	return not_overlapped_height; 
+}
+
+/* assemble a series of frames into a single image */
+static unsigned int assemble(unsigned char *input, unsigned char *output,
+	int num_strips, gboolean reverse, unsigned int *errors_sum)
+{
+	uint8_t *assembled = output;
+	int frame;
+	uint32_t image_height = FRAME_HEIGHT;
+	unsigned int min_error;
+	*errors_sum = 0;
+
+	if (num_strips < 1)
+		return 0;
+	
+	/* Rotating given data by 90 degrees 
+	 * Taken from document describing aes1610 image format
+	 * TODO: move reversing detection here */
+	
+	if (reverse)
+		output += (num_strips - 1) * FRAME_SIZE;
+	for (frame = 0; frame < num_strips; frame++) {
+		aes_assemble_image(input, FRAME_WIDTH, FRAME_HEIGHT, output);
+		input += FRAME_WIDTH * (FRAME_HEIGHT / 2);
+
+		if (reverse)
+			output -= FRAME_SIZE;
+		else
+			output += FRAME_SIZE;
+	}
+
+	/* Detecting where frames overlaped */
+	output = assembled;
+	for (frame = 1; frame < num_strips; frame++) {
+		int not_overlapped;
+
+		output += FRAME_SIZE;
+		not_overlapped = find_overlap(assembled, output, &min_error);
+		*errors_sum += min_error;
+		image_height += not_overlapped;
+		assembled += FRAME_WIDTH * not_overlapped;
+		memcpy(assembled, output, FRAME_SIZE); 
+	}
+	return image_height;
+}
+
 static const struct aes_regwrite capture_stop[] = {
 	{ 0x81,0x00 }
 };
@@ -415,30 +568,20 @@ static int capture(struct fp_img_dev *de
 	if (r < 0)
 		return r;
   
-	/* FIXME: use histogram data above for gain calibration (0x8e xx) */
 
 	img = fpi_img_new((3 * MAX_FRAMES * FRAME_SIZE) / 2);
 	imgptr = img->data;
 	cooked = imgptr + (MAX_FRAMES * FRAME_SIZE) / 2;
 
-	r = read_data(dev, buf, 665);
-	if (r < 0)
-		goto err;
-	memcpy(imgptr, buf + 1, 128*4);
-	imgptr += 128*4;
-
-	r = read_data(dev, buf, 665);
-	if (r < 0)
-		goto err;
-	memcpy(imgptr, buf + 1, 128*4);
-	imgptr += 128*4;
-
-	/* we start at 2 because we captured 2 frames above. the above captures
-	 * should possibly be moved into the loop below, or discarded altogether */
-	for (nstrips = 2; nstrips < MAX_FRAMES - 2; nstrips++) {
+	/* we stop at nstrips-2 because we captured 2 frames after the loop. */
+	for (nstrips = 0; nstrips < MAX_FRAMES - 2; nstrips += 2) {
+		/* we don't have to request more frames until we have received the 2 firsts */
+		if (nstrips >= 2) {
 		r = aes_write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs));
 		if (r < 0)
 			goto err;
+		}
+			
 		r = read_data(dev, buf, 665);
 		if (r < 0)
 			goto err;
@@ -452,7 +595,7 @@ static int capture(struct fp_img_dev *de
 		imgptr += 128*4;
 
 		sum = 0;
-		for (i = 515; i != 530; i++)
+		for (i = 516; i != 530; i++)
 		{
 			/* histogram[i] = number of pixels of value i
 			   Only the pixel values from 10 to 15 are used to detect finger. */
@@ -468,11 +611,17 @@ static int capture(struct fp_img_dev *de
 		else
 			count_blank = 0;
 			
-		/* if we got 50 blank frames, assume scan has ended. */
-		if (count_blank >= 50)
+		/* if we got 5 blank frames, assume scan has ended. */
+		if (count_blank >= 5)
 			break;
+		
+		/* use histogram data above for gain calibration (0xbd, 0xbe, 0x29 and 0x2A ) */
+		adjust_gain(buf, GAIN_STATUS_NORMAL);
 	}
 	
+	// Acquisition finished: restore default gain values
+	restore_gain();
+	
 	r = aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop));
 	if (r < 0)
 		goto err;
_______________________________________________
fprint mailing list
[email protected]
http://lists.reactivated.net/mailman/listinfo/fprint

Reply via email to