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