/* baud_test.c * * test setting the baudrate and compare it with the expected runtime * * options: * -p defaults to "i:0x0403:0x6001" (this is the first FT232R with default id) * d: path of bus and device-node (e.g. "003/001") within usb device tree (usually at /proc/bus/usb/) * i:: first device with given vendor and product id, * ids can be decimal, octal (preceded by "0") or hex (preceded by "0x") * i::: as above with index being the number of the device (starting with 0) * if there are more than one * s::: first device with given vendor id, product id and serial string * -d * -b (divides by 16 if bitbang as taken from the ftdi datasheets) * -m r: serial a: async bitbang s:sync bitbang * -c * * (C) 2009 by Gerd v. Egidy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include #include #include #include #include double get_prec_time() { struct timeval tv; double res; gettimeofday(&tv,NULL); res=tv.tv_sec; res+=((double)tv.tv_usec/1000000); return res; } int main(int argc, char **argv) { struct ftdi_context ftdic; int i, t; unsigned char *txbuf; unsigned char *rxbuf; double start, duration, plan; // default values int baud=9600; int set_baud; int datasize=100000; char default_devicedesc[] = "i:0x0403:0x6001"; char *devicedesc=default_devicedesc; int txchunksize=256; enum ftdi_mpsse_mode test_mode=BITMODE_BITBANG; while ((t = getopt (argc, argv, "b:d:p:m:c:")) != -1) { switch (t) { case 'd': datasize = atoi (optarg); break; case 'm': switch (*optarg) { case 'r': // serial test_mode=BITMODE_RESET; break; case 'a': // async test_mode=BITMODE_BITBANG; break; case 's': // sync test_mode=BITMODE_SYNCBB; break; } break; case 'b': baud = atoi (optarg); break; case 'p': devicedesc=optarg; break; case 'c': txchunksize = atoi (optarg); break; } } txbuf=malloc(txchunksize); rxbuf=malloc(txchunksize); if (txbuf == NULL || rxbuf == NULL) { fprintf(stderr, "can't malloc\n"); return EXIT_FAILURE; } if (ftdi_init(&ftdic) < 0) { fprintf(stderr, "ftdi_init failed\n"); return EXIT_FAILURE; } if (ftdi_usb_open_string(&ftdic, devicedesc) < 0) { fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(&ftdic)); return EXIT_FAILURE; } set_baud=baud; if (test_mode!=BITMODE_RESET) { // we do bitbang, so real baudrate / 16 set_baud=baud/16; } ftdi_set_baudrate(&ftdic,set_baud); printf("real baudrate used: %d\n",(test_mode==BITMODE_RESET) ? ftdic.baudrate : ftdic.baudrate*16); if (ftdi_set_bitmode(&ftdic, 0xFF,test_mode) < 0) { fprintf(stderr,"Can't set mode: %s\n",ftdi_get_error_string(&ftdic)); return EXIT_FAILURE; } if (test_mode==BITMODE_RESET) { // serial 8N1: 8 data bits, 1 startbit, 1 stopbit plan=((double)(datasize*10))/baud; } else { // bitbang means 8 bits at once plan=((double)datasize)/baud; } printf("this test should take %.2f seconds\n",plan); // prepare data to send: 0 and 1 bits alternating (except for serial start/stopbit): // maybe someone wants to look at this with a scope or logic analyzer for (i=0; i0); } start=get_prec_time(); // don't wait for more data to arrive, take what we get and keep on sending // yes, we really would like to have libusb 1.0+ with async read/write... ftdic.usb_read_timeout=1; i=0; while (i < datasize) { int sendsize=txchunksize; if (i+sendsize > datasize) sendsize=datasize-i; if ((sendsize=ftdi_write_data(&ftdic, txbuf, sendsize)) < 0) { fprintf(stderr,"write failed at %d: %s\n", i, ftdi_get_error_string(&ftdic)); return EXIT_FAILURE; } i+=sendsize; if (test_mode==BITMODE_SYNCBB) { // read the same amount of data as sent ftdi_read_data(&ftdic, rxbuf, sendsize); } } duration=get_prec_time()-start; printf("and took %.4f seconds, this is %.0f baud or factor %.3f\n",duration,(plan*baud)/duration,plan/duration); ftdi_usb_close(&ftdic); ftdi_deinit(&ftdic); exit (0); }