use ftdi_usb_open_string() in baud_test example
[libftdi] / examples / baud_test.c
1 /* baud_test.c
2  *
3  * test setting the baudrate and compare it with the expected runtime
4  *
5  * options:
6  *  -p <devicestring> defaults to "i:0x0403:0x6001" (this is the first FT232R with default id)
7  *       d:<devicenode> path of bus and device-node (e.g. "003/001") within usb device tree (usually at /proc/bus/usb/)
8  *       i:<vendor>:<product> first device with given vendor and product id,
9  *                            ids can be decimal, octal (preceded by "0") or hex (preceded by "0x")
10  *       i:<vendor>:<product>:<index> as above with index being the number of the device (starting with 0)
11  *                            if there are more than one
12  *       s:<vendor>:<product>:<serial> first device with given vendor id, product id and serial string
13  *  -d <datasize to send in bytes>
14  *  -b <baudrate> (divides by 16 if bitbang as taken from the ftdi datasheets)
15  *  -m <mode to use> r: serial a: async bitbang s:sync bitbang 
16  *  -c <chunksize>
17  *
18  * (C) 2009 by Gerd v. Egidy <gerd.von.egidy@intra2net.com>
19  *
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation; either version 2 of the License, or
23  * (at your option) any later version.
24
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  */
31
32 #include <sys/time.h>
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <ftdi.h>
36
37 double get_prec_time()
38 {
39     struct timeval tv;
40     double res;
41     
42     gettimeofday(&tv,NULL);
43
44     res=tv.tv_sec;
45     res+=((double)tv.tv_usec/1000000);
46
47     return res;
48 }
49
50 int main(int argc, char **argv)
51 {
52     struct ftdi_context ftdic;
53     int i, t;
54     char *txbuf;
55     char *rxbuf;
56     double start, duration, plan;
57
58     // default values
59     int baud=9600;
60     int set_baud;
61     int datasize=100000;
62
63     char default_devicedesc[] = "i:0x0403:0x6001";
64     char *devicedesc=default_devicedesc;
65     int txchunksize=256;
66     enum ftdi_mpsse_mode test_mode=BITMODE_BITBANG;
67     
68     while ((t = getopt (argc, argv, "b:d:p:m:c:")) != -1)
69     {
70         switch (t)
71         {
72             case 'd':
73                 datasize = atoi (optarg);
74                 break;
75             case 'm':
76                 switch(*optarg)
77                 {
78                     case 'r':
79                         // serial
80                         test_mode=BITMODE_RESET;
81                         break;
82                     case 'a':
83                         // async
84                         test_mode=BITMODE_BITBANG;
85                         break;
86                     case 's':
87                         // sync
88                         test_mode=BITMODE_SYNCBB;
89                         break;
90                 }
91                 break;
92             case 'b':
93                 baud = atoi (optarg);
94                 break;
95             case 'p':
96                 devicedesc=optarg;
97                 break;
98             case 'c':
99                 txchunksize = atoi (optarg);
100                 break;
101         }
102     }
103
104     txbuf=malloc(txchunksize);
105     rxbuf=malloc(txchunksize);
106     if (txbuf == NULL || rxbuf == NULL)
107     {
108         fprintf(stderr, "can't malloc\n");
109         return EXIT_FAILURE;
110     }
111
112     if (ftdi_init(&ftdic) < 0)
113     {
114         fprintf(stderr, "ftdi_init failed\n");
115         return EXIT_FAILURE;
116     }
117
118     if (ftdi_usb_open_string(&ftdic, devicedesc) < 0)
119     {
120         fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(&ftdic));
121         return EXIT_FAILURE;
122     }
123
124     set_baud=baud;
125     if (test_mode!=BITMODE_RESET)
126     {
127         // we do bitbang, so real baudrate / 16
128         set_baud=baud/16;
129     }
130
131     ftdi_set_baudrate(&ftdic,set_baud);
132     printf("real baudrate used: %d\n",(test_mode==BITMODE_RESET) ? ftdic.baudrate : ftdic.baudrate*16);
133
134     if (ftdi_set_bitmode(&ftdic, 0xFF,test_mode) < 0)
135     {
136         fprintf(stderr,"Can't set mode: %s\n",ftdi_get_error_string(&ftdic));
137         return EXIT_FAILURE;
138     }
139
140     if (test_mode==BITMODE_RESET)
141     {
142         // serial 8N1: 8 data bits, 1 startbit, 1 stopbit
143         plan=((double)(datasize*10))/baud;
144     }
145     else
146     {
147         // bitbang means 8 bits at once
148         plan=((double)datasize)/baud;
149     }
150
151     printf("this test should take %.2f seconds\n",plan);
152
153     // prepare data to send: 0 and 1 bits alternating (except for serial start/stopbit):
154     // maybe someone wants to look at this with a scope or logic analyzer
155     for (i=0; i<txchunksize; i++)
156     {
157         if (test_mode==BITMODE_RESET)
158             txbuf[i]=0xAA;
159         else
160             txbuf[i]=(i%2) ? 0xff : 0;
161     }
162
163     if (ftdi_write_data_set_chunksize(&ftdic, txchunksize) < 0 ||
164         ftdi_read_data_set_chunksize(&ftdic, txchunksize) < 0)
165     {
166         fprintf(stderr,"Can't set chunksize: %s\n",ftdi_get_error_string(&ftdic));
167         return EXIT_FAILURE;
168     }
169
170     if(test_mode==BITMODE_SYNCBB)
171     {
172         // completely clear the receive buffer before beginning
173         while(ftdi_read_data(&ftdic, rxbuf, txchunksize)>0);
174     }
175
176     start=get_prec_time();
177
178     // don't wait for more data to arrive, take what we get and keep on sending
179     // yes, we really would like to have libusb 1.0+ with async read/write...
180     ftdic.usb_read_timeout=1;
181
182     i=0;
183     while(i < datasize)
184     {
185         int sendsize=txchunksize;
186         if (i+sendsize > datasize)
187             sendsize=datasize-i;
188
189         if ((sendsize=ftdi_write_data(&ftdic, txbuf, sendsize)) < 0)
190         {
191             fprintf(stderr,"write failed at %d: %s\n",
192                     i, ftdi_get_error_string(&ftdic));
193             return EXIT_FAILURE;
194         }
195
196         i+=sendsize;
197
198         if(test_mode==BITMODE_SYNCBB)
199         {
200             // read the same amount of data as sent
201             ftdi_read_data(&ftdic, rxbuf, sendsize);
202         }
203     }
204
205     duration=get_prec_time()-start;
206     printf("and took %.4f seconds, this is %.0f baud or factor %.3f\n",duration,(plan*baud)/duration,plan/duration);
207
208     ftdi_usb_close(&ftdic);
209     ftdi_deinit(&ftdic);
210     exit (0);
211 }