vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Button_NI_DIO24.C
Go to the documentation of this file.
1 // vrpn_Button_NI_DIO24.C
2 //
3 // This is a driver for National Instruments DAQCard
4 // DIO-24, a PCMCIA card, which provides 24-bit digital I/O.
5 // The I/O is accessed in 3 "ports" with 8 bits per port,
6 // though the user is protected from that detail. The
7 // user of this class need only request inputs 1 through 24.
8 //
9 // Unlike the other National Instrument devices currently
10 // in vrpn, this uses their new "mx" library. To access
11 // that library, install their software from the NI-DAQmx
12 // CD. Then uncomment the following line in vrpn_configure.h:
13 // #define VRPN_USE_NATIONAL_INSTRUMENTS_MX
14 //
15 // Note that because the 3rd party library is used, this class
16 // will only work under Windows.
17 //
18 // You must also include the following in your compilers include
19 // path for the 'vrpn' and 'vrpn_server' projects:
20 // $(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C DEV\include
21 //
22 // Finally, the following must be included in vrpn.cfg to use
23 // the generic server:
24 //
25 // ################################################################################
26 // # This is a driver for National Instruments DAQCard-
27 // # DIO-24, a PCMCIA card, which provides 24-bit digital I/O.
28 // #
29 // # Arguments:
30 // # char name_of_this_device[]
31 // # int number_of_channls to read: 1-24 (optional. default=24)
32 //
33 // vrpn_Button_NI_DIO24 Button0 1
34 //
35 // This code was written in October 2006 by Bill West, based on some example
36 // code provided by National Instruments.
37 
38 #include "vrpn_Button_NI_DIO24.h"
39 
41 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
42 extern "C" {
43 #include <NIDAQmx.h>
44 }
45 #else
46 typedef vrpn_int32 int32;
47 #endif
48 #include <stdio.h> // for fprintf, sprintf, stderr, etc
49 
50 // Constants used by this class
52  (24<vrpn_BUTTON_MAX_BUTTONS) ? 24 : vrpn_BUTTON_MAX_BUTTONS ; // pick the least
53 
55  vrpn_Connection * c,
56  vrpn_int32 numChannels) :
57 vrpn_Button_Filter (name, c)
58 {
59  char portName[127] ;
60 
61  this->setNumChannels( numChannels );
62 
63  // Check if we got a connection.
64  if (d_connection == NULL) {
65  fprintf(stderr,"vrpn_Button_NI_DIO24: Can't get connection!\n");
66  }
67 
68  // Initialize the task handles
69 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
70  _taskHandle = 0 ;
71 #else
72  fprintf(stderr,"vrpn_Button_NI_DIO24::vrpn_Button_NI_DIO24(): Not compiled into VRPN, edit vrpn_Configure.h and define VRPN_USE_NATIONAL_INSTRUMENTS_MX and then recompile VRPN.\n");
73 #endif
74 
75  // Initialize the DAQCard-DIO-24 for each of the ports used
76  // Define various names the library needs
77  sprintf(portName,"Dev1/line0:%d", num_buttons-1) ;
78 
79  /*********************************************/
80  // DAQmx Configure Code
81  /*********************************************/
82 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
83  int32 error=0;
84  error = DAQmxCreateTask(d_servicename,&_taskHandle);
85 
86  if (!error)
87  error = DAQmxCreateDIChan(_taskHandle,portName,"",DAQmx_Val_ChanForAllLines);
88 #endif
89 
90 /* The following code *should* make the 0's into 1's, and vice versa, but it only works
91  * for one channel, and even then, it causes the 1's (button pressed) to "flicker" 1-0-1.
92  * National Instruments can't explain it. Furthermore, if you try to set this property
93  * for all inputs, it errors out.
94  *
95  * if (!error)
96  * error = DAQmxSetDIInvertLines(_taskHandle, portName, true) ;
97  */
98 
99  /*********************************************/
100  // DAQmx Start Code
101  /*********************************************/
102 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
103  if (!error)
104  error = DAQmxStartTask(_taskHandle);
105 
106  // If error, report it and exit
107  if (error)
108  reportError(error, vrpn_true) ;
109 #endif
110 
111 } // constructor
112 
113 // This destructor closes out the SEI bus, and deallocates memory
115 {
116 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
117  if( _taskHandle!=0 )
118  {
119  /*********************************************/
120  // DAQmx Stop Code
121  /*********************************************/
122  DAQmxStopTask(_taskHandle);
123  DAQmxClearTask(_taskHandle);
124  _taskHandle = 0 ;
125  }
126 #endif
127 } // destructor
128 
137 {
138 
139  server_mainloop(); // let the server do its stuff
140 
141  // Read the data from the available ports
142  /*********************************************/
143  // DAQmx Read Code
144  /*********************************************/
145 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
146  int32 error ;
147  int32 bytesRead,bytesPerSamp;
148  error = DAQmxReadDigitalLines(_taskHandle,1,5.0,DAQmx_Val_GroupByChannel,
150  &bytesPerSamp,&bytesRead,NULL);
151 
152  // check for obvious errors
153  if (bytesRead < num_buttons)
154  fprintf(stderr,
155  "vrpn_Button_NI_DIO24: Warning, number of bytes read was %d, not %d as expected.\n",
156  bytesRead, num_buttons) ;
157  // If other error, report it and sleep
158  if (error)
159  reportError(error, vrpn_false) ;
160 #endif
161 
162  // Finally, the point of all this, deliver the data
163  report_changes() ;
164 
165 } // mainloop
166 
167 vrpn_int32 vrpn_Button_NI_DIO24::setNumChannels (vrpn_int32 sizeRequested)
168 {
169  // Set the number of buttons we have to read
170  // If the number is invalid, default to the maximum
171  if (sizeRequested<1 || sizeRequested > vrpn_Button_NI_DIO24::vrpn_Button_NI_DIO24_CHANNEL_MAX)
173  else
174  num_buttons = sizeRequested;
175 
176  this->set_all_momentary() ; // as the default case anyway
177 
178  return num_buttons;
179 
180 } // setNumChannels
181 
182 // This handles error reporting
183 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
184 void vrpn_Button_NI_DIO24::reportError(int32 errnumber, vrpn_bool exitProgram)
185 {
186  char errBuff[2048]={'\0'};
187 
188  if( DAQmxFailed(errnumber) )
189  {
190  DAQmxGetExtendedErrorInfo(errBuff,2048);
191  printf("DAQmx Error: %s\n",errBuff);
192  if (exitProgram==vrpn_true)
193  {
194  printf("Exiting...\n") ;
195  throw(errnumber) ; // this will quit, cause the destructor to be called
196  }
197  else
198  {
199  printf("Sleeping...\n") ;
200  vrpn_SleepMsecs(1000.0*1) ; // so at least the log will slow down so someone can see the error
201  }
202  }
203 } // reportError
204 #endif
205 
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
void vrpn_SleepMsecs(double dMsecs)
Definition: vrpn_Shared.C:157
char * d_servicename
Name of this device, not including the connection part.
vrpn_Button_NI_DIO24(const char *name, vrpn_Connection *c, vrpn_int32 numChannels=vrpn_Button_NI_DIO24_CHANNEL_MAX)
vrpn_int32 num_buttons
Definition: vrpn_Button.h:47
static const vrpn_int32 vrpn_Button_NI_DIO24_CHANNEL_MAX
Generic connection class not specific to the transport mechanism.
virtual void set_all_momentary(void)
Definition: vrpn_Button.C:244
virtual void mainloop()
This routine is called each time through the server&#39;s main loop.
#define VRPN_API
virtual void report_changes(void)
Definition: vrpn_Button.C:382
vrpn_Connection * d_connection
Connection that this object talks to.
const int vrpn_BUTTON_MAX_BUTTONS
Definition: vrpn_Button.h:12
All button servers should derive from this class, which provides the ability to turn any of the butto...
Definition: vrpn_Button.h:65
unsigned char buttons[vrpn_BUTTON_MAX_BUTTONS]
Definition: vrpn_Button.h:44