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