1 /*
2 * $RCSfile: sample.cpp,v $
3 * $Revision: 1.17 $
4 * $Date: 2009/11/26 21:48:06 $
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 * or, to enable debug features
38 *
39 * g++ -ggdb sample.cpp -laiousbdbg -lusb-1.0 -o sample
40 */
41 // }}}
42
43 // {{{ includes
44 #include <aiousb.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <unistd.h>
48 using namespace AIOUSB;
49 // }}}
50
51 int main( int argc, char **argv ) {
52 const int DEVICES_REQUIRED = 2; // change this to 1 if only one device
53 const int BITS_PER_BYTE = 8;
54 const int MAX_DIO_BYTES = 4; // a modest little assumption for convenience
55 const int MASK_BYTES = ( MAX_DIO_BYTES + BITS_PER_BYTE - 1 ) / BITS_PER_BYTE;
56 const int MAX_NAME_SIZE = 20;
57
58 static struct DeviceInfo {
59 unsigned char outputMask[ MASK_BYTES ];
60 unsigned char readBuffer[ MAX_DIO_BYTES ]; // image of data read from board
61 unsigned char writeBuffer[ MAX_DIO_BYTES ]; // image of data written to board
62 char name[ MAX_NAME_SIZE + 2 ];
63 unsigned long productID;
64 unsigned long nameSize;
65 unsigned long numDIOBytes;
66 unsigned long numCounters;
67 __uint64_t serialNumber;
68 int index;
69 } deviceTable[ DEVICES_REQUIRED ];
70
71 printf(
72 "USB-DIO-32 sample program version 1.17, 26 November 2009\n"
73 " AIOUSB library version %s, %s\n"
74 " This program demonstrates communicating with %d USB-DIO-32 devices on\n"
75 " the same USB bus. For simplicity, it uses the first %d such devices\n"
76 " found on the bus.\n"
77 /*API*/ , AIOUSB_GetVersion(), AIOUSB_GetVersionDate()
78 , DEVICES_REQUIRED, DEVICES_REQUIRED
79 );
80
81 /*
82 * MUST call AIOUSB_Init() before any meaningful AIOUSB functions;
83 * AIOUSB_GetVersion() above is an exception
84 */
85 /*API*/ unsigned long result = AIOUSB_Init();
86 if( result == AIOUSB_SUCCESS ) {
87 /*
88 * call GetDevices() to obtain "list" of devices found on the bus
89 */
90 /*API*/ unsigned long deviceMask = GetDevices();
91 if( deviceMask != 0 ) {
92 /*
93 * at least one ACCES device detected, but we want devices of a specific type
94 */
95 /*API*/ AIOUSB_ListDevices(); // print list of all devices found on the bus
96
97 /*
98 * search for required number of USB-DIO-32 devices
99 */
100 int devicesFound = 0;
101 int index = 0;
102 struct DeviceInfo *device;
103 while(
104 deviceMask != 0
105 && devicesFound < DEVICES_REQUIRED
106 ) {
107 if( ( deviceMask & 1 ) != 0 ) {
108 // found a device, but is it the correct type?
109 device = &deviceTable[ devicesFound ];
110 device->nameSize = MAX_NAME_SIZE;
111 /*API*/ result = QueryDeviceInfo( index, &device->productID
112 , &device->nameSize, device->name, &device->numDIOBytes, &device->numCounters );
113 if( result == AIOUSB_SUCCESS ) {
114 if( device->productID == USB_DIO_32 ) {
115 // found a USB-DIO-32
116 device->index = index;
117 devicesFound++;
118 } // if( device->productID ...
119 } else
120 printf( "Error '%s' querying device at index %d\n"
121 /*API*/ , AIOUSB_GetResultCodeAsString( result ), index );
122 } // if( ( deviceMask ...
123 index++;
124 deviceMask >>= 1;
125 } // while( deviceMask ...
126
127 if( devicesFound >= DEVICES_REQUIRED ) {
128 unsigned port, pattern;
129 AIOUSB_BOOL correct, allCorrect;
130
131 for( index = 0; index < devicesFound; index++ ) {
132 device = &deviceTable[ index ];
133 /*API*/ result = GetDeviceSerialNumber( device->index, &device->serialNumber );
134 if( result == AIOUSB_SUCCESS )
135 printf( "Serial number of device at index %d: %llx\n", device->index, ( long long ) device->serialNumber );
136 else
137 printf( "Error '%s' getting serial number of device at index %d\n"
138 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
139 } // for( index ...
140
141 /*
142 * demonstrate DIO configuration
143 */
144 device = &deviceTable[ 0 ]; // select first device
145 /*API*/ AIOUSB_SetCommTimeout( device->index, 1000 ); // set timeout for all USB operations
146 /*
147 * set all ports to output mode (we could just write "device->outputMask[ 0 ] = 0x0f"
148 * here since there are only 4 ports)
149 */
150 memset( device->outputMask, 0xff, MASK_BYTES );
151 for( port = 0; port < device->numDIOBytes; port++ )
152 device->writeBuffer[ port ] = 0x11 * ( port + 1 ); // write unique pattern to each port
153 /*API*/ result = DIO_Configure( device->index, AIOUSB_FALSE /* bTristate */, device->outputMask, device->writeBuffer );
154 if( result == AIOUSB_SUCCESS )
155 printf( "Device at index %d successfully configured\n", device->index );
156 else
157 printf( "Error '%s' configuring device at index %d\n"
158 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
159
160 if( devicesFound > 1 ) {
161 device = &deviceTable[ 1 ]; // select second device
162 /*API*/ AIOUSB_SetCommTimeout( device->index, 1000 ); // set timeout for all USB operations
163 /*
164 * set all ports to output mode (we could just write "device->outputMask[ 0 ] = 0x0f"
165 * here since there are only 4 ports)
166 */
167 memset( device->outputMask, 0xff, MASK_BYTES );
168 for( port = 0; port < device->numDIOBytes; port++ )
169 device->writeBuffer[ port ] = 0x66 - port; // write unique pattern to each port
170 /*API*/ result = DIO_Configure( device->index, AIOUSB_FALSE /* bTristate */, device->outputMask, device->writeBuffer );
171 if( result == AIOUSB_SUCCESS )
172 printf( "Device at index %d successfully configured\n", device->index );
173 else
174 printf( "Error '%s' configuring device at index %d\n"
175 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
176 } // if( devicesFound ...
177
178 /*
179 * demonstrate DIO read
180 */
181 for( index = 0; index < devicesFound; index++ ) {
182 device = &deviceTable[ index ];
183 /*API*/ result = DIO_ReadAll( device->index, device->readBuffer );
184 if( result == AIOUSB_SUCCESS ) {
185 printf( "Read the following values from device at index %d:", device->index );
186 correct = AIOUSB_TRUE;
187 for( port = 0; port < device->numDIOBytes; port++ ) {
188 if( device->readBuffer[ port ] != device->writeBuffer[ port ] )
189 correct = AIOUSB_FALSE;
190 printf( " %#x", device->readBuffer[ port ] );
191 } // for( port ...
192 printf(
193 correct
194 ? " (correct)\n"
195 : " (INCORRECT)\n"
196 );
197 } else
198 printf( "Error '%s' reading inputs from device at index %d\n"
199 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
200 } // for( index ...
201
202 /*
203 * demonstrate DIO write (board LEDs should flash vigorously during this test)
204 */
205 printf( "Writing patterns to devices:" );
206 fflush( stdout ); // must do for "real-time" feedback
207 allCorrect = AIOUSB_TRUE;
208 for( pattern = 0x00; pattern <= 0xf0; pattern += 0x10 ) {
209 printf( " %#x", pattern );
210 fflush( stdout ); // must do for "real-time" feedback
211 for( index = 0; index < devicesFound; index++ ) {
212 device = &deviceTable[ index ];
213 for( port = 0; port < device->numDIOBytes; port++ )
214 device->writeBuffer[ port ] = pattern + index * 0x04 + port;
215 /*API*/ result = DIO_WriteAll( device->index, device->writeBuffer );
216 if( result == AIOUSB_SUCCESS ) {
217 // verify values written
218 /*API*/ result = DIO_ReadAll( device->index, device->readBuffer );
219 if( result == AIOUSB_SUCCESS ) {
220 correct = AIOUSB_TRUE;
221 for( port = 0; port < device->numDIOBytes; port++ ) {
222 if( device->readBuffer[ port ] != device->writeBuffer[ port ] ) {
223 allCorrect = correct = AIOUSB_FALSE;
224 break; // from for()
225 } // if( device->readBuffer[ ...
226 } // for( port ...
227 if( ! correct )
228 printf( "Error in data read back from device at index %d\n", device->index );
229 } else {
230 printf( "Error '%s' reading inputs from device at index %d\n"
231 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
232 goto abort;
233 } // if( result ...
234 } else {
235 printf( "Error '%s' writing outputs to device at index %d\n"
236 /*API*/ , AIOUSB_GetResultCodeAsString( result ), device->index );
237 goto abort;
238 } // if( result ...
239 } // for( index ...
240 sleep( 1 );
241 } // for( pattern ...
242 abort:;
243 printf(
244 allCorrect
245 ? "\nAll patterns written were read back correctly\n"
246 : "\n" // error messages already printed
247 );
248 } else
249 printf( "Failed to find %d USB-DIO-32 devices\n", DEVICES_REQUIRED );
250 } else
251 printf( "No ACCES devices found on USB bus\n" );
252
253 /*
254 * MUST call AIOUSB_Exit() before program exits,
255 * but only if AIOUSB_Init() succeeded
256 */
257 /*API*/ AIOUSB_Exit();
258 } // if( result ...
259 return ( int ) result;
260 } // main()
261
262
263 /* end of file */