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