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 */