vrpn  07.33
Virtual Reality Peripheral Network
vrpn_Analog_USDigital_A2.C
Go to the documentation of this file.
1 // vrpn_Analog_USDigital_A2.C
2 //
3 // This is a driver for USDigital A2 Absolute Encoders.
4 // They can be daisy changed together, and utlimately, one or
5 // more plug into a serial port and communicate using RS-232.
6 // You can find out more at www.usdigital.com.
7 //
8 // To use this class, install the US Digital software, specifying
9 // the "SEI Explorer Demo Software" to install.
10 //
11 // Then uncomment the following line in vrpn_configure.h:
12 // #define VRPN_USE_USDIGITAL
13 //
14 // Note that because the 3rd party library is used, this class
15 // will only work under Windows.
16 //
17 // You must also include the following in your compilers include
18 // path for the 'vrpn' project:
19 // $(SYSTEMDRIVE)\Program Files\SEI Explorer
20 //
21 // Finally, the following must be included in vrpn.cfg to use
22 // the generic server:
23 //
24 // ################################################################################
25 // # US Digital A2 Absolute Encoder Analog Input server. This will open the COM
26 // # port specified, configure the number of channels specified, and report
27 // # Absolute Encoder values in tenths of a degree from 0 to 3599.
28 // #
29 // # Arguments:
30 // # char name_of_this_device[]
31 // # int COM_port. If 0, search for correct COM port.
32 // # int number_of_channels
33 // # int 0 to report always, 1 to report on change only (optional, default=0)
34 //
35 // vrpn_Analog_USDigital_A2 Analog0 0 2
36 //
37 // This code was written in October 2006 by Bill West, who
38 // used the vrpn_Analog_Server sample code written by
39 // Tom Hudson in March 1999 as a starting point. Bill also
40 // used some ideas from vrpn_Radamec_SPI.[Ch] written by
41 // Russ Taylor in August 2000.
42 
44 
46 #ifdef VRPN_USE_USDIGITAL
47 extern "C" {
48 #include <SEIDrv32.H>
49 }
50 #endif
51 #include <stdio.h> // for fprintf, stderr
52 
53 // Constants used by this class
55  // deallocate the list of device addresses.
56  (15<vrpn_CHANNEL_MAX) ? 15 : vrpn_CHANNEL_MAX ; // pick the least
58 
59 // Constructor initializes the USDigital's SEI communication, and prepares to read the A2
61  vrpn_Connection * c,
62  vrpn_uint32 portNum,
63  vrpn_uint32 numChannels,
64  vrpn_int32 reportOnChangeOnly) :
65 vrpn_Analog (name, c),
66 _SEIopened(vrpn_false),
67 _numDevices(0),
68 _devAddr(NULL),
69 _reportChange(reportOnChangeOnly!=0)
70 {
71 #ifdef VRPN_USE_USDIGITAL
73  if (this->_devAddr == NULL) {
74  fprintf(stderr,"vrpn_Analog_USDigital_A2: Out of memory!\n");
75  return;
76  }
77 
78  this->setNumChannels( numChannels );
79 
80  // Check if we got a connection.
81  if (d_connection == NULL) {
82  fprintf(stderr,"vrpn_Analog_USDigital_A2: Can't get connection!\n");
83  return;
84  }
85 
86  // Prepare to get data from the SEI bus
87  long err;
88 #ifdef VRPN_USE_USDIGITAL
89  err = InitializeSEI(portNum, AUTOASSIGN) ;
90 #else
91  fprintf(stderr,"vrpn_Analog_USDigital_A2::vrpn_Analog_USDigital_A2(): Not yet implemented for this architecture\n");
92  err = -1;
93 #endif
94  if (err) {
95  fprintf(stderr, "vrpn_Analog_USDigital_A2: Can't initialize SEI bus for port %d.\n",
96 #ifdef VRPN_USE_USDIGITAL
97  GetCommPort()
98 #else
99  0
100 #endif
101  );
102 
103  return ;
104  } else {
105  _SEIopened = vrpn_true ;
106  }
107 
108  // Check if the number of devices matches that expected
109 #ifdef VRPN_USE_USDIGITAL
110  _numDevices = GetNumberOfDevices() ;
111 #endif
112  if (_numDevices<0 || _numDevices>vrpn_Analog_USDigital_A2::vrpn_Analog_USDigital_A2_CHANNEL_MAX) {
113  fprintf(stderr,
114  "vrpn_Analog_USDigital_A2: Error (%d) returned from GetNumberOfDevices call on SEI bus",
115  _numDevices) ;
116  _numDevices = 0 ;
117  }
118  if (_numDevices != numChannels)
119  fprintf(stderr,
120  "vrpn_Analog_USDigital_A2: Warning, number of requested devices (%d) is not the same as found (%d)\n",
121  numChannels, _numDevices) ;
122 
123  // Initialize the addresses
125  _devAddr[c] = -1 ;
126 
127  // Get the device addresses.
128  for (vrpn_uint32 d=0 ; d<_numDevices ; d++) {
129  long deviceInfoErr, model, serialnum, version, addr ;
130 #ifdef VRPN_USE_USDIGITAL
131  deviceInfoErr = GetDeviceInfo(d, &model, &serialnum, &version, &addr) ;
132  if (!deviceInfoErr)
133  _devAddr[d] = addr ;
134 #endif
135 
136 #ifdef VERBOSE
137  // Dump out the device data
138  if (deviceInfoErr)
139  fprintf(stderr, "vrpn_Analog_USDigital_A2: could not get information on Device #%d!\n", d) ;
140  else
141  fprintf(stderr, "vrpn_Analog_USDigital_A2: Device #%d: model=%d, serialnum=%d, version=%d, addr=%d\n",
142  d, model, serialnum, version, addr) ;
143 #endif // VERBOSE
144  }
145 #else
146  fprintf(stderr,"vrpn_Analog_USDigital_A2::vrpn_Analog_USDigital_A2(): Not compiled in; define VRPN_USE_USDIGITAL in vrpn_Configure.h and recompile VRPN\n");
147 #endif
148 } // constructor
149 
150 // This destructor closes out the SEI bus, and deallocates memory
152 {
153 #ifdef VRPN_USE_USDIGITAL
154  // close out the SEI bus
155  if (_SEIopened==vrpn_true) {
156  (void) CloseSEI() ;
157  }
158 
159  // deallocate the list of device addresses.
160  delete _devAddr ;
161  _devAddr = 0 ;
162 #endif
163 } // destructor
164 
173 {
174  server_mainloop(); // let the server do its stuff
175 #ifdef VRPN_USE_USDIGITAL
176  long readErr, readVal ;
177 
178  // Read the data from the available channels
179  for (vrpn_uint32 c=0 ; c<(vrpn_uint32) num_channel ; c++)
180  {
181  // see if there's really a readable device there.
182  if (c<_numDevices && _devAddr[c]>=0)
183  {
184  readErr = A2GetPosition(_devAddr[c], &readVal) ;
185  if (readErr)
186  {
187  fprintf(stderr,
188  "vrpn_Analog_USDigital_A2: Error code %d received while reading channel %d.\n",
189  readErr, c) ;
190  fprintf(stderr, "vrpn_Analog_USDigital_A2: Attempting to reinitialize SEI bus...") ;
191  readErr = ResetSEI() ;
192  if (readErr)
193  fprintf(stderr, "failed.") ;
194  fprintf(stderr, "failed.") ;
195  // don't flood the log, and give the reset time to work
196  vrpn_SleepMsecs(1000) ;
197  }
198  else
199  channel[c] = (vrpn_float64) readVal ;
200  }
201  else
202  channel[c] = 0 ; // default to 0 for unreadable/unavailable.
203  } // for
204 #endif
205 
206  // Finally, the point of all this, deliver the data
207  if (_reportChange)
208  report_changes() ;
209  else
210  report() ;
211 
212 } // mainloop
213 
214 vrpn_int32 vrpn_Analog_USDigital_A2::setNumChannels (vrpn_int32 sizeRequested)
215 {
216  if (sizeRequested < 0)
217  num_channel = 0;
218  else if (static_cast<unsigned>(sizeRequested) > vrpn_Analog_USDigital_A2::vrpn_Analog_USDigital_A2_CHANNEL_MAX)
220  else
221  num_channel = (vrpn_int32) sizeRequested;
222 
223  return num_channel;
224 
225 } // setNumChannels
226 
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
virtual void report_changes(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report only if something has changed (for servers) Optionally, tell what time to stamp the val...
Definition: vrpn_Analog.C:71
static const vrpn_uint32 vrpn_Analog_USDigital_A2_FIND_PORT
void vrpn_SleepMsecs(double dMsecs)
Definition: vrpn_Shared.C:157
vrpn_Analog_USDigital_A2(const char *name, vrpn_Connection *c, vrpn_uint32 portNum=vrpn_Analog_USDigital_A2_FIND_PORT, vrpn_uint32 numChannels=vrpn_Analog_USDigital_A2_CHANNEL_MAX, vrpn_int32 reportOnChangeOnly=0)
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:38
static const vrpn_uint32 vrpn_Analog_USDigital_A2_CHANNEL_MAX
Generic connection class not specific to the transport mechanism.
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report whether something has changed or not (for servers) Optionally, tell what time to stamp ...
Definition: vrpn_Analog.C:94
#define VRPN_API
vrpn_int32 num_channel
Definition: vrpn_Analog.h:40
vrpn_Connection * d_connection
Connection that this object talks to.
virtual void mainloop()
This routine is called each time through the server's main loop.
#define vrpn_CHANNEL_MAX
Definition: vrpn_Analog.h:16