From f59bc698cc7f139b93a9c51eb65f342a789e725f Mon Sep 17 00:00:00 2001 From: mattf Date: Sat, 8 Jan 2005 00:05:24 +0000 Subject: More TDM card echo API modifications. Making the fxotune program automatically find the correct coefficients for the module. Lots of neat stuff. git-svn-id: http://svn.digium.com/svn/zaptel/trunk@531 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- fxotune.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 242 insertions(+), 20 deletions(-) (limited to 'fxotune.c') diff --git a/fxotune.c b/fxotune.c index 6bdaeba..a11ba90 100755 --- a/fxotune.c +++ b/fxotune.c @@ -1,3 +1,16 @@ +/* + * This file and contents thereof are licensed under the terms and + * conditions of the Gnu Public License version 2. For more information + * (including terms and conditions) see http://www.gnu.org/ + * + * fxotune.c -- A utility for tuning the various settings on the fxo + * modules for the TDM400 cards. + * + * by Matthew Fredrickson + * + * (C) 2004 Digium, Inc. + */ + #include #include #include @@ -5,42 +18,251 @@ #include #include #include +#include #include #include #include "wctdm.h" +#include "fxotune.h" +#include "zaptel.h" + + +static int testduration = 100; /* Test the line for x milliseconds */ +static int readduration = 100 * 2; + +static char *zappath = "/dev/zap"; +static char *configfile = "/etc/fxotune.conf"; + +static char *usage = +"Usage: fxotest\n" +" -i : Tests for FXO modules and sets echo coefficients\n" +" -s : Sets the FXO modules echo coefficients on your system to the best settings\n"; + +#define OUT_OF_BOUNDS(x) ((x) < 0 || (x) > 255) + +int process_readbuf(short *ibuf, int isize, short *obuf, int osize) +{ + int i = 0; + short *samples = ibuf; + short minsample = samples[0]; + + for (i = 0; i < isize/2; i++) { + if (samples[i] < minsample) + minsample = samples[i]; + } + return minsample; +} + +/* Returns index in echocan table with the lowest power pulse readback + * -1 means the device is not an FXO module or fails */ +int echo_tune(int whichzap) +{ + short bestval = 32355; + int bestindex = -1; + int i = 0; + int res = 0; + int total = sizeof(echo_trys) / sizeof(struct wctdm_echo_coefs); + int randdev; + short *outbuf = NULL, *inbuf = NULL; + int obufsize = testduration * 8 * 2; /* In one milisecond there are 8 samples of 2 byte length */ + int ibufsize = readduration * 8 * 2; + + + randdev = open("/dev/random", O_RDONLY); + if (randdev < 0) { + fprintf(stdout, "Unable to open /dev/random: %s\n", strerror(errno)); + return -1; + } + outbuf = malloc(obufsize); + if (!outbuf) { + fprintf(stdout, "Malloc failed on outbuf. Bad, bad, bad...\n"); + exit(-1); + } + + res = read(randdev, outbuf, obufsize); + if (res <= 0) { + fprintf(stdout, "WARNING: could not read from /dev/random: %s\n", strerror(errno)); + return -1; + } + + if (res != obufsize) { + fprintf(stdout, "Could not read request %d bytes from /dev/random. Using only %d\n", obufsize, res); + ibufsize = res; + } + + close(randdev); + + outbuf = malloc(readduration); + if (!outbuf) { + fprintf(stdout, "Malloc failed on readbuf. Bad, bad, bad....\n"); + exit(-1); + } + + for (i = 0; i < total; i++) { + int x; + + /* Set echo settings */ + if (ioctl(whichzap, WCTDM_SET_ECHOTUNE, &echo_trys[i])) { + fprintf(stdout, "Unable to set echo params: %s\n", strerror(errno)); + return -1; + } + + x = 1; + if (ioctl(whichzap, ZT_SETLINEAR, &x)) { + fprintf(stdout, "Unable to set channel to signed linear mode.\n"); + return -1; + } + + /* Take off hook */ + x = ZT_OFFHOOK; + if(ioctl(whichzap, ZT_HOOK, &x)) { + fprintf(stdout, "Unable to set hook state.\n"); + return -1; + } + + /* write samples */ + res = write(whichzap, outbuf, obufsize); + if (res < 0) { + fprintf(stdout, "Unable to write: %s\n", strerror(errno)); + return -1; + } + + if (res != obufsize) { + fprintf(stdout, "Only could write %d of %d bytes.\n", res, obufsize); + return -1; + } + + res = read(whichzap, inbuf, ibufsize); + if (res < 0) { + fprintf(stdout, "Error in read: %s\n", strerror(errno)); + return -1; + } + if (res != ibufsize) { + fprintf(stdout, "Only could read %d of %d bytes.\n", res, ibufsize); + if (res > 0) + ibufsize = res; + else { + fprintf(stdout, "Cannot read from device\n"); + return -1; + } + } + + res = process_readbuf(outbuf, obufsize, inbuf, ibufsize); + /* Check to see if the echo values */ + if (res < bestval) { + bestval = res; + bestindex = i; + } + } + + return 0; + +} + int main (int argc , char **argv) { char zapdev[80] = ""; + int i = 0; int fd; - - if (argc < 4) { - fprintf(stdout, "Usage:\n"); - fprintf(stdout, "%s [zap device] echocan [0-7]\n", argv[0]); - exit(1); + int res = 0; + int configfd; + + if (argc != 2) { + /* Show usage */ + fputs(usage, stdout); + return -1; } - strncpy(zapdev, argv[1], sizeof(zapdev)); + if (!strcasecmp(argv[1], "-s")) { + for (i = 0;res != EOF; i++) { + struct wctdm_echo_coefs mycoefs; + char completezappath[56] = ""; + int myzap,myacim,mycoef1,mycoef2,mycoef3,mycoef4,mycoef5,mycoef6,mycoef7,mycoef8; + FILE *fp = NULL; + + fp = fopen(configfile, "r"); + + res = fscanf(fp, "%d=%d,%d,%d,%d,%d,%d,%d,%d,%d",&myzap,&myacim,&mycoef1, + &mycoef2,&mycoef3,&mycoef4,&mycoef5,&mycoef6,&mycoef7, + &mycoef8); + + if (res == EOF) { + break; + } + + /* Check to be sure conversion is done correctly */ + if (OUT_OF_BOUNDS(myacim) || OUT_OF_BOUNDS(mycoef1)|| + OUT_OF_BOUNDS(mycoef2)|| OUT_OF_BOUNDS(mycoef3)|| + OUT_OF_BOUNDS(mycoef4)|| OUT_OF_BOUNDS(mycoef5)|| + OUT_OF_BOUNDS(mycoef6)|| OUT_OF_BOUNDS(mycoef7)|| OUT_OF_BOUNDS(mycoef8)) { + + fprintf(stdout, "Bounds check error on inputs from %s:%d\n", configfile, i+1); + return -1; + } + + mycoefs.acim = myacim; + mycoefs.coef1 = mycoef1; + mycoefs.coef2 = mycoef2; + mycoefs.coef3 = mycoef3; + mycoefs.coef4 = mycoef4; + mycoefs.coef5 = mycoef5; + mycoefs.coef6 = mycoef6; + mycoefs.coef7 = mycoef7; + mycoefs.coef8 = mycoef8; + + snprintf(completezappath, sizeof(completezappath), "%s/%d", zappath, myzap); + fd = open(completezappath, O_RDWR); + + if (fd < 0) { + fprintf(stdout, "open error on %s: %s\n", completezappath, strerror(errno)); + return -1; + } - fd = open(zapdev, O_RDWR); - if (fd < 0) { - fprintf(stderr, "open: %s\n", strerror(errno)); - exit(1); + if (ioctl(fd, WCTDM_SET_ECHOTUNE, &mycoefs)) { + fprintf(stdout, "echotune: %s\n", strerror(errno)); + return -1; + } + } + + return 0; } - if (!strcasecmp(argv[2], "echocan")) { - int modeno = atoi(argv[3]); + if (!strcasecmp(argv[1], "-i")) { + configfd = open(configfile, O_CREAT|O_TRUNC|O_WRONLY); - if (modeno < 0 || modeno > 7) { - fprintf(stdout, "Echo canceller coefficient settings must be between 0 and 7.\n"); - exit(1); + if (configfd < 0) { + fprintf(stdout, "open: %s\n", strerror(errno)); + return -1; } - if (ioctl(fd, WCTDM_SET_ECHOTUNE, &modeno)) { - fprintf(stdout, "echotune: %s\n", strerror(errno)); - exit(1); + for (i = 0; i < 255; i++) { + snprintf(zapdev, sizeof(zapdev), "%s/%d", zappath, i); + + fd = open(zapdev, O_RDWR); + if (fd < 0) { + fprintf(stdout, "open(%s): %s\n", zapdev, strerror(errno)); + return -1; + } + + res = echo_tune(fd); + if (res > -1) { + /* Do output to file */ + int len = 0; + static char output[255] = ""; + snprintf(output, sizeof(output), "%d=%d,%d,%d,%d,%d,%d,%d,%d,%d", i, + 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 ); + + len = strlen(output); + res = write(configfd, output, strlen(output)); + if (res != len) { + fprintf(stdout, "Unable to write line \"%s\" to file.\n", output); + return -1; + } + } } - exit(0); } - exit(0); + + return 0; } -- cgit v1.2.3