Reformat example code to match libftdi style:
[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 <stdlib.h>
35 #include <unistd.h>
36 #include <ftdi.h>
37
38 double get_prec_time()
39 {
40     struct timeval tv;
41     double res;
42
43     gettimeofday(&tv,NULL);
44
45     res=tv.tv_sec;
46     res+=((double)tv.tv_usec/1000000);
47
48     return res;
49 }
50
51 int main(int argc, char **argv)
52 {
53     struct ftdi_context ftdic;
54     int i, t;
55     unsigned char *txbuf;
56     unsigned char *rxbuf;
57     double start, duration, plan;
58
59     // default values
60     int baud=9600;
61     int set_baud;
62     int datasize=100000;
63
64     char default_devicedesc[] = "i:0x0403:0x6001";
65     char *devicedesc=default_devicedesc;
66     int txchunksize=256;
67     enum ftdi_mpsse_mode test_mode=BITMODE_BITBANG;
68
69     while ((t = getopt (argc, argv, "b:d:p:m:c:")) != -1)
70     {
71         switch (t)
72         {
73             case 'd':
74                 datasize = atoi (optarg);
75                 break;
76             case 'm':
77                 switch (*optarg)
78                 {
79                     case 'r':
80                         // serial
81                         test_mode=BITMODE_RESET;
82                         break;
83                     case 'a':
84                         // async
85                         test_mode=BITMODE_BITBANG;
86                         break;
87                     case 's':
88                         // sync
89                         test_mode=BITMODE_SYNCBB;
90                         break;
91                 }
92                 break;
93             case 'b':
94                 baud = atoi (optarg);
95                 break;
96             case 'p':
97                 devicedesc=optarg;
98                 break;
99             case 'c':
100                 txchunksize = atoi (optarg);
101                 break;
102         }
103     }
104
105     txbuf=malloc(txchunksize);
106     rxbuf=malloc(txchunksize);
107     if (txbuf == NULL || rxbuf == NULL)
108     {
109         fprintf(stderr, "can't malloc\n");
110         return EXIT_FAILURE;
111     }
112
113     if (ftdi_init(&ftdic) < 0)
114     {
115         fprintf(stderr, "ftdi_init failed\n");
116         return EXIT_FAILURE;
117     }
118
119     if (ftdi_usb_open_string(&ftdic, devicedesc) < 0)
120     {
121         fprintf(stderr,"Can't open ftdi device: %s\n",ftdi_get_error_string(&ftdic));
122         return EXIT_FAILURE;
123     }
124
125     set_baud=baud;
126     if (test_mode!=BITMODE_RESET)
127     {
128         // we do bitbang, so real baudrate / 16
129         set_baud=baud/16;
130     }
131
132     ftdi_set_baudrate(&ftdic,set_baud);
133     printf("real baudrate used: %d\n",(test_mode==BITMODE_RESET) ? ftdic.baudrate : ftdic.baudrate*16);
134
135     if (ftdi_set_bitmode(&ftdic, 0xFF,test_mode) < 0)
136     {
137         fprintf(stderr,"Can't set mode: %s\n",ftdi_get_error_string(&ftdic));
138         return EXIT_FAILURE;
139     }
140
141     if (test_mode==BITMODE_RESET)
142     {
143         // serial 8N1: 8 data bits, 1 startbit, 1 stopbit
144         plan=((double)(datasize*10))/baud;
145     }
146     else
147     {
148         // bitbang means 8 bits at once
149         plan=((double)datasize)/baud;
150     }
151
152     printf("this test should take %.2f seconds\n",plan);
153
154     // prepare data to send: 0 and 1 bits alternating (except for serial start/stopbit):
155     // maybe someone wants to look at this with a scope or logic analyzer
156     for (i=0; i<txchunksize; i++)
157     {
158         if (test_mode==BITMODE_RESET)
159             txbuf[i]=0xAA;
160         else
161             txbuf[i]=(i%2) ? 0xff : 0;
162     }
163
164     if (ftdi_write_data_set_chunksize(&ftdic, txchunksize) < 0 ||
165             ftdi_read_data_set_chunksize(&ftdic, txchunksize) < 0)
166     {
167         fprintf(stderr,"Can't set chunksize: %s\n",ftdi_get_error_string(&ftdic));
168         return EXIT_FAILURE;
169     }
170
171     if (test_mode==BITMODE_SYNCBB)
172     {
173         // completely clear the receive buffer before beginning
174         while (ftdi_read_data(&ftdic, rxbuf, txchunksize)>0);
175     }
176
177     start=get_prec_time();
178
179     // don't wait for more data to arrive, take what we get and keep on sending
180     // yes, we really would like to have libusb 1.0+ with async read/write...
181     ftdic.usb_read_timeout=1;
182
183     i=0;
184     while (i < datasize)
185     {
186         int sendsize=txchunksize;
187         if (i+sendsize > datasize)
188             sendsize=datasize-i;
189
190         if ((sendsize=ftdi_write_data(&ftdic, txbuf, sendsize)) < 0)
191         {
192             fprintf(stderr,"write failed at %d: %s\n",
193                     i, ftdi_get_error_string(&ftdic));
194             return EXIT_FAILURE;
195         }
196
197         i+=sendsize;
198
199         if (test_mode==BITMODE_SYNCBB)
200         {
201             // read the same amount of data as sent
202             ftdi_read_data(&ftdic, rxbuf, sendsize);
203         }
204     }
205
206     duration=get_prec_time()-start;
207     printf("and took %.4f seconds, this is %.0f baud or factor %.3f\n",duration,(plan*baud)/duration,plan/duration);
208
209     ftdi_usb_close(&ftdic);
210     ftdi_deinit(&ftdic);
211     exit (0);
212 }