[Asterisk-cvs] zaptel fxotune.c,1.13,1.14 Makefile,1.67,1.68

mattf at lists.digium.com mattf at lists.digium.com
Wed Feb 2 11:59:57 CST 2005


Update of /usr/cvsroot/zaptel
In directory mongoose.digium.com:/tmp/cvs-serv32074

Modified Files:
	fxotune.c Makefile 
Log Message:
New impedance tuning algorithms.


Index: fxotune.c
===================================================================
RCS file: /usr/cvsroot/zaptel/fxotune.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- fxotune.c	28 Jan 2005 16:24:52 -0000	1.13
+++ fxotune.c	2 Feb 2005 18:01:08 -0000	1.14
@@ -20,6 +20,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <math.h>
+
 #ifdef STANDALONE_ZAPATA
 #include "zaptel.h"
 #else
@@ -28,8 +30,11 @@
 #include "wctdm.h"
 #include "fxotune.h"
 
-#define TESTDURATION 64			/* 64 samples of test */
-#define BUFFER_LENGTH 128			/* 128 sample buffers */
+#define TEST_DURATION 4000			/* 4000 samples (or 500 ms) of test */
+#define BUFFER_LENGTH 8000			/* 4000 sample buffers */
+#define SKIP_BYTES 1600
+
+#define PI 3.14
 
 static char *zappath = "/dev/zap";
 static char *configfile = "/etc/fxotune.conf";
@@ -41,9 +46,11 @@
 
 #define OUT_OF_BOUNDS(x) ((x) < 0 || (x) > 255)
 
-static short outbuf[TESTDURATION];
+static short outbuf[TEST_DURATION];
 static int debug = 0;
 
+
+#if 0
 int process_readbuf(short *ibuf)
 {
 	int sum=0;
@@ -53,12 +60,76 @@
 	}
 	return sum;
 }
+#endif
 
-int fill_outputdata(void)
+/* Generates a tone of hz frequency.  Index is the current sample
+ * to begenerated.  For a normal waveform you need to increment
+ * this every time you execute the function.
+ * Returns a 16bit slinear sample. */
+short gentone(int hz, int index)
+{
+	return sinf(index * 2 * PI * hz/8000);
+}
+
+/* Returns the power of the buffer of samples in 16bit slinear format.
+ * power function = (sum of squares) - (square of sums).
+ *
+ * TODO: make the function stateless so that you can have some sort of
+ * progressive power calculation on the line */
+float power_of(void *prebuf, int bufsize, int short_format)
 {
+	float sum_of_squares = 0, square_of_sums = 0;
+	int numsamples = 0;
+	float finalanswer = 0;
+	short *sbuf = (short*)prebuf;
+	float *fbuf = (float*)prebuf;
+	int i = 0;
+
+	if (short_format) {
+		/* idiot proof checks */
+		if (bufsize <= 0)
+			return -1;
+
+		if (bufsize % 2 != 0)
+			return -2;
+
+		numsamples = bufsize / 2;
+
+		for (i = 0; i < numsamples; i++) {
+			sum_of_squares += ((float)sbuf[i] * (float)sbuf[i])/(float)32768;
+			square_of_sums += (float)sbuf[i]/(float)32768;
+		}
+	} else {
+		/* Version for float inputs */
+		for (i = 0; i < bufsize; i++) {
+			sum_of_squares += (fbuf[i] * fbuf[i]);
+			square_of_sums += fbuf[i];
+		}
+	}
+
+	square_of_sums *= square_of_sums; /* sums ^ 2 */
+
+	finalanswer = sum_of_squares - square_of_sums;
+
+	if (finalanswer < 0)
+		return -3;
+
+	return sqrtf(finalanswer);
+}
+
+#if 0
+int fill_outputdata(int freq)
+{
+	int i = 0;
+
+	for (i = 0; i < TESTDURATIION; i++)
+		outbuf[i] = gentone(freq, i);
+
+		
+
 	int randdev;
 	int cursize = 0;
-	int needlen = TESTDURATION * 2;
+	int needlen = TEST_DURATION * 2;
 	int res;
 
 	fprintf(stdout, "Getting random impulse data\n");
@@ -78,13 +149,15 @@
 		needlen -= res;
 	}
 	
-	fprintf(stdout, "Cool, we filled the random data buffer\n");
+	fprintf(stdout, "Succesfully filled the random data buffer\n");
 	close(randdev);
 
 	return 0;
 }
+#endif
 
 
+#if 0
 /* Returns index in echocan table with the lowest power pulse readback
  * -1 means the device is not an FXO module or fails */
 static int echo_tune(int whichzap, const char *dialstr)
@@ -164,14 +237,14 @@
 			}
 	
 			/* write samples */
-			res = write(whichzap, outbuf, TESTDURATION * 2);
+			res = write(whichzap, outbuf, TEST_DURATION * 2);
 			if (res < 0) {
 				fprintf(stdout, "Unable to write: %s\n", strerror(errno));
 				return -1;
 			}
 
-			if (res != TESTDURATION * 2) {
-				fprintf(stdout, "Only could write %d of %d bytes.\n", res, TESTDURATION * 2);
+			if (res != TEST_DURATION * 2) {
+				fprintf(stdout, "Only could write %d of %d bytes.\n", res, TEST_DURATION * 2);
 				return -1;
 			}
 
@@ -210,6 +283,136 @@
 	return 0;
 
 }
+#endif
+
+/* Tune the line impedance.  Look for best response range */
+int acim_tune(int whichzap, char *dialstr)
+{
+	int i = 0, freq = 0, acim = 0;
+	int res = 0, x = 0;
+	struct zt_bufferinfo bi;
+	struct zt_dialoperation dop;
+	struct wctdm_echo_coefs coefs;
+	short inbuf[BUFFER_LENGTH]; 
+	int lowest = 0;
+	float acim_results[16];
+
+	/* Set echo settings */
+	memset(&coefs, 0, sizeof(coefs));
+	if (ioctl(whichzap, WCTDM_SET_ECHOTUNE, &coefs)) {
+		fprintf(stdout, "Skipping non-TDM / non-FXO\n");
+		return -1;
+	}
+
+	x = 1;
+	if (ioctl(whichzap, ZT_SETLINEAR, &x)) {
+		fprintf(stderr, "Unable to set channel to signed linear mode.\n");
+		return -1;
+	}
+
+	memset(&bi, 0, sizeof(bi));
+	if (ioctl(whichzap, ZT_GET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to get buffer information!\n");
+		return -1;
+	}
+	bi.numbufs = 2;
+	bi.bufsize = BUFFER_LENGTH;
+	bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
+	bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
+	if (ioctl(whichzap, ZT_SET_BUFINFO, &bi)) {
+		fprintf(stderr, "Unable to set buffer information!\n");
+		return -1;
+	}
+	x = ZT_OFFHOOK;
+	if (ioctl(whichzap, ZT_HOOK, &x)) {
+		fprintf(stderr, "Cannot bring fd %d off hook", whichzap);
+		return -1;
+	}
+
+	for (acim = 0; acim < 16; acim++) {
+		float freq_results[15];
+		int needtoreset = 0;
+
+		coefs.acim = acim;
+		if (ioctl(whichzap, WCTDM_SET_ECHOTUNE, &coefs)) {
+			fprintf(stderr, "Unable to set impedance on fd %d\n", whichzap);
+			return -1;
+		}
+
+		for (freq = 200; freq <=3000; freq+=200, needtoreset++) {
+			/* Fill the output buffers */
+			for (i = 0; i < TEST_DURATION; i++)
+				outbuf[i] = gentone(freq, i);
+
+			/* Prepare line for data */
+			if (needtoreset > 8) {
+				/* Do line hookstate reset */
+				x = ZT_ONHOOK;
+
+				if (ioctl(whichzap, ZT_HOOK, &x)) {
+					fprintf(stderr, "Unable to hang up fd %d\n", whichzap);
+					return -1;
+				}
+
+				sleep(2);
+				x = ZT_OFFHOOK;
+				if (ioctl(whichzap, ZT_HOOK, &x)) {
+					fprintf(stderr, "Cannot bring fd %d off hook", whichzap);
+					return -1;
+				}
+
+				memset(&dop, 0, sizeof(dop));
+				dop.op = ZT_DIAL_OP_REPLACE;
+				dop.dialstr[0] = 'T';
+				strncpy(dop.dialstr + 1, dialstr, sizeof(dop.dialstr) - 1);
+				printf("Dialing...\n");
+				if (ioctl(whichzap, ZT_DIAL, &dop)) {
+					fprintf(stderr, "Unable to dial!\n");
+					return -1;
+				}
+				sleep(2);
+
+				needtoreset = 0;
+			}
+
+			/* Flush buffers */
+			x = ZT_FLUSH_READ | ZT_FLUSH_WRITE | ZT_FLUSH_EVENT;
+			if (ioctl(whichzap, ZT_FLUSH, &x)) {
+				fprintf(stderr, "Unable to flush I/O: %s\n", strerror(errno));
+				return -1;
+			}
+	
+			/* send data out on line */
+			res = write(whichzap, &outbuf, BUFFER_LENGTH);
+			if (res != BUFFER_LENGTH) {
+				fprintf(stderr, "Could not write all data to line\n");
+				return -1;
+			}
+
+			/* read return response */
+			res = read(whichzap, inbuf, BUFFER_LENGTH);
+			if (res != BUFFER_LENGTH) {
+				fprintf(stderr, "Could not fill input buffer\n");
+				return -1;
+			}
+
+			/* calculate power of response */
+			
+			freq_results[(freq/200)-1] = power_of(inbuf+SKIP_BYTES, BUFFER_LENGTH-SKIP_BYTES, 1);
+		}
+		acim_results[i] = power_of(freq_results, 16, 0);
+	}
+
+	/* Find out what the "best" impedance is for the line */
+	lowest = 1;
+	for (i = 0; i < 16; i++) {
+		if (acim_results[i] < acim_results[lowest]) {
+			lowest = i;
+		}
+	}
+
+	return lowest;
+}
 	
 int main (int argc , char **argv)
 {
@@ -299,11 +502,6 @@
 			return -1;
 		}
 
-		if (fill_outputdata()) {
-			fprintf(stdout, "Error in generating outputdata... dieing\n");
-			return -1;
-		}
-
 		for (i = 0; i < 252; i++) {
 			snprintf(zapdev, sizeof(zapdev), "%s/%d", zappath, i+1);
 
@@ -314,18 +512,22 @@
 				continue;
 			}
 
-			res = echo_tune(fd, argv[2]);
+			res = acim_tune(fd, argv[2]);
 
 			close(fd);
 			if (res > -1) {
 			/* Do output to file */
 				int len = 0;
 				static char output[255] = "";
+#if 0
 				snprintf(output, sizeof(output), "%d=%d,%d,%d,%d,%d,%d,%d,%d,%d\n", i+1,
-						echo_trys[res].acim, echo_trys[res].coef1, echo_trys[res].coef2,
-						echo_trys[res].coef3, echo_trys[res].coef4, echo_trys[res].coef5,
-						echo_trys[res].coef6, echo_trys[res].coef7, echo_trys[res].coef8 );
+						echo_trys[i].acim, echo_trys[i].coef1, echo_trys[i].coef2,
+						echo_trys[i].coef3, echo_trys[i].coef4, echo_trys[i].coef5,
+						echo_trys[i].coef6, echo_trys[i].coef7, echo_trys[i].coef8 );
+#endif
 
+				snprintf(output, sizeof(output), "%d=%d,%d,%d,%d,%d,%d,%d,%d,%d\n", i+1, res,
+						0, 0, 0, 0, 0, 0, 0, 0);
 				len = strlen(output);
 				res = write(configfd, output, strlen(output));
 				if (res != len) {

Index: Makefile
===================================================================
RCS file: /usr/cvsroot/zaptel/Makefile,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- Makefile	26 Jan 2005 19:31:57 -0000	1.67
+++ Makefile	2 Feb 2005 18:01:08 -0000	1.68
@@ -235,7 +235,7 @@
 	$(CC) -o fxstest fxstest.o -ltonezone
 
 fxotune: fxotune.o
-	$(CC) -o fxotune fxotune.o
+	$(CC) -o fxotune fxotune.o -lm
 
 fxsdump: fxsdump.o
 	$(CC) -o fxsdump fxsdump.o -lm




More information about the svn-commits mailing list