1 /*
2 * $RCSfile: sample.cpp,v $
3 * $Revision: 1.13 $
4 * $Date: 2009/10/16 18:17:11 $
5 * :tabSize=4:collapseFolds=1:
6 *
7 * AIOUSB library sample program
8 */
9
10
11 // {{{ notes and build instructions
12 /*
13 * This source code looks best with a tab width of 4.
14 *
15 * All the API functions that DO NOT begin "AIOUSB_" are standard API functions, largely
16 * documented in http://accesio.com/MANUALS/USB%20Software%20Reference.pdf. The functions
17 * that DO begin with "AIOUSB_" are "extended" API functions added to the Linux
18 * implementation. Source code lines in this sample program that are prefixed with the
19 * comment "/ * API * /" highlight calls to the AIOUSB API.
20 *
21 * LIBUSB (http://www.libusb.org/) must be installed on the Linux box (the AIOUSB code
22 * was developed using libusb version 1.0.3). After installing libusb, it may also be
23 * necessary to set an environment variable so that the libusb and aiousb header files can
24 * be located:
25 *
26 * export CPATH=/usr/local/include/libusb-1.0/:/usr/local/include/aiousb/
27 *
28 * Once libusb is installed properly, it should be possible to compile the sample program
29 * using the simple command:
30 *
31 * make
32 *
33 * Alternatively, one can "manually" compile the sample program using the command:
34 *
35 * g++ sample.cpp -laiousb -lusb-1.0 -o sample
36 */
37 // }}}
38
39 // {{{ includes
40 #include <aiousb.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <unistd.h>
44 using namespace AIOUSB;
45 // }}}
46
47 int main( int argc, char **argv ) {
48 const int DEVICES_REQUIRED = 2; // change this to 1 if only one device
49 const int BITS_PER_BYTE = 8;
50 const int MAX_DIO_BYTES = 4; // a modest little assumption for convenience
51 const int MASK_BYTES = ( MAX_DIO_BYTES + BITS_PER_BYTE - 1 ) / BITS_PER_BYTE;
52 const int MAX_NAME_SIZE = 20;
53
54 static struct DeviceInfo {
55 unsigned char outputMask[ MASK_BYTES ];
56 unsigned char readBuffer[ MAX_DIO_BYTES ]; // image of data read from board
57 unsigned char writeBuffer[ MAX_DIO_BYTES ]; // image of data written to board
58 char name[ MAX_NAME_SIZE + 2 ];
59 unsigned long productID;
60 unsigned long nameSize;
61 unsigned long numDIOBytes;
62 unsigned long numCounters;
63 __uint64_t serialNumber;
64 int index;
65 } deviceTable[ DEVICES_REQUIRED ];
66
67 printf(
68 "USB-DIO-32 sample program $Revision: 1.13 $ $Date: 2009/10/16 18:17:11 $\n"
69 " (AIOUSB library %s)\n"
70 " This program demonstrates communicating with %d USB-DIO-32 devices on\n"
71 " the same USB bus. For simplicity, it uses the first %d such devices\n"
72 " found on the bus.\n"
73 /*API*/ , AIOUSB_GetVersion()
74 , DEVICES_REQUIRED, DEVICES_REQUIRED
75 );
76
77 /*
78 * MUST call AIOUSB_Init() before any meaningful AIOUSB functions;
79 * AIOUSB_GetVersion() above is an exception
80 */
81 /*API*/ unsigned long result = AIOUSB_Init();
82 if( result == AIOUSB_SUCCESS ) {
83 /*
84 * call GetDevices() to obtain "list" of devices found on the bus
85 */
86 /*API*/ unsigned long deviceMask = GetDevices();
87 if( deviceMask != 0 ) {
88 /*
89 * at least one ACCES device detected, but we want devices of a specific type
90 */
91 /*API*/ AIOUSB_ListDevices(); // print list of all devices found on the bus
92
93 /*
94 * search for required number of USB-DIO-32 devices
95 */
96 int devicesFound = 0;
97 int index = 0;
98 struct DeviceInfo *device;
99 while(
100 deviceMask != 0
101 && devicesFound < DEVICES_REQUIRED
102 ) {
103 if( ( deviceMask & 1 ) != 0 ) {
104 // found a device, but is it the correct type?
105 device = &deviceTable[ devicesFound ];
106 device->nameSize = MAX_NAME_SIZE;
107 /*API*/ result = QueryDeviceInfo( index, &device->productID
108 , &device->nameSize, device->name, &device->numDIOBytes, &device->numCounters );
109 if( result == AIOUSB_SUCCESS ) {
110 if( device->productID == USB_DIO_32 ) {
111 // found a USB-DIO-32
112 device->index = index;
113 devicesFound++;
114 } // if( device->productID ...
115 } else
116 printf( "Error '%s' querying device at index %d\n"
117 /*API*/ , AIOUSB_GetResultCodeAsString( result ), index );
118 } // if( ( deviceMask ...
119 index++;
120 deviceMask >>= 1;
121 } // while( deviceMask ...
122
123 if( devicesFound >= DEVICES_REQUIRED ) {
124 unsigned port, pattern;
125 BOOL correct, allCorrect;
126
127 for( index = 0; index < devicesFound; index++ ) {
128 device = &deviceTable[ index ];
129 /*API*/ result = GetDeviceSerialNumber( device->index, &device->serialNumber );
130 if( result == AIOUSB_SUCCESS )
131 printf( "Serial number of device at index %d: %llx\n", device->index, device->serialNumber );
132 else
133 printf( "Error '%s' getting serial number of device at index %d\n"
134 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
135 } // for( index ...
136
137 /*
138 * demonstrate DIO configuration
139 */
140 device = &deviceTable[ 0 ]; // select first device
141 /*API*/ AIOUSB_SetCommTimeout( device->index, 1000 ); // set timeout for all USB operations
142 /*
143 * set all ports to output mode (we could just write "device->outputMask[ 0 ] = 0x0f"
144 * here since there are only 4 ports)
145 */
146 memset( device->outputMask, 0xff, MASK_BYTES );
147 for( port = 0; port < device->numDIOBytes; port++ )
148 device->writeBuffer[ port ] = 0x11 * ( port + 1 ); // write unique pattern to each port
149 /*API*/ result = DIO_Configure( device->index, FALSE /* bTristate */, device->outputMask, device->writeBuffer );
150 if( result == AIOUSB_SUCCESS )
151 printf( "Device at index %d successfully configured\n", device->index );
152 else
153 printf( "Error '%s' configuring device at index %d\n"
154 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
155
156 if( devicesFound > 1 ) {
157 device = &deviceTable[ 1 ]; // select second device
158 /*API*/ AIOUSB_SetCommTimeout( device->index, 1000 ); // set timeout for all USB operations
159 /*
160 * set all ports to output mode (we could just write "device->outputMask[ 0 ] = 0x0f"
161 * here since there are only 4 ports)
162 */
163 memset( device->outputMask, 0xff, MASK_BYTES );
164 for( port = 0; port < device->numDIOBytes; port++ )
165 device->writeBuffer[ port ] = 0x66 - port; // write unique pattern to each port
166 /*API*/ result = DIO_Configure( device->index, FALSE /* bTristate */, device->outputMask, device->writeBuffer );
167 if( result == AIOUSB_SUCCESS )
168 printf( "Device at index %d successfully configured\n", device->index );
169 else
170 printf( "Error '%s' configuring device at index %d\n"
171 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
172 } // if( devicesFound ...
173
174 /*
175 * demonstrate DIO read
176 */
177 for( index = 0; index < devicesFound; index++ ) {
178 device = &deviceTable[ index ];
179 /*API*/ result = DIO_ReadAll( device->index, device->readBuffer );
180 if( result == AIOUSB_SUCCESS ) {
181 printf( "Read the following values from device at index %d:", device->index );
182 correct = TRUE;
183 for( port = 0; port < device->numDIOBytes; port++ ) {
184 if( device->readBuffer[ port ] != device->writeBuffer[ port ] )
185 correct = FALSE;
186 printf( " %#x", device->readBuffer[ port ] );
187 } // for( port ...
188 printf(
189 correct
190 ? " (correct)\n"
191 : " (INCORRECT)\n"
192 );
193 } else
194 printf( "Error '%s' reading inputs from device at index %d\n"
195 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
196 } // for( index ...
197
198 /*
199 * demonstrate DIO write (board LEDs should flash vigorously during this test)
200 */
201 printf( "Writing patterns to devices:" );
202 fflush( stdout ); // must do for "real-time" feedback
203 allCorrect = TRUE;
204 for( pattern = 0x00; pattern <= 0xf0; pattern += 0x10 ) {
205 printf( " %#x", pattern );
206 fflush( stdout ); // must do for "real-time" feedback
207 for( index = 0; index < devicesFound; index++ ) {
208 device = &deviceTable[ index ];
209 for( port = 0; port < device->numDIOBytes; port++ )
210 device->writeBuffer[ port ] = pattern + index * 0x04 + port;
211 /*API*/ result = DIO_WriteAll( device->index, device->writeBuffer );
212 if( result == AIOUSB_SUCCESS ) {
213 // verify values written
214 /*API*/ result = DIO_ReadAll( device->index, device->readBuffer );
215 if( result == AIOUSB_SUCCESS ) {
216 correct = TRUE;
217 for( port = 0; port < device->numDIOBytes; port++ ) {
218 if( device->readBuffer[ port ] != device->writeBuffer[ port ] ) {
219 allCorrect = correct = FALSE;
220 break; // from for()
221 } // if( device->readBuffer[ ...
222 } // for( port ...
223 if( ! correct )
224 printf( "Error in data read back from device at index %d\n", device->index );
225 } else {
226 printf( "Error '%s' reading inputs from device at index %d\n"
227 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
228 goto abort;
229 } // if( result ...
230 } else {
231 printf( "Error '%s' writing outputs to device at index %d\n"
232 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
233 goto abort;
234 } // if( result ...
235 } // for( index ...
236 sleep( 1 );
237 } // for( pattern ...
238 abort:;
239 printf(
240 allCorrect
241 ? "\nAll patterns written were read back correctly\n"
242 : "\n" // error messages already printed
243 );
244 } else
245 printf( "Failed to find %d USB-DIO-32 devices\n", DEVICES_REQUIRED );
246 } else
247 printf( "No ACCES devices found on USB bus\n" );
248
249 /*
250 * MUST call AIOUSB_Exit() before program exits,
251 * but only if AIOUSB_Init() succeeded
252 */
253 /*API*/ AIOUSB_Exit();
254 } // if( result ...
255 return ( int ) result;
256 } // main()
257
258
259 /* end of file */