vrpn  07.33
Virtual Reality Peripheral Network
vrpn_NationalInstruments.C
Go to the documentation of this file.
1 #include <stdio.h> // for sprintf, fprintf, stderr, etc
2 #include "vrpn_Shared.h" // for vrpn_gettimeofday
3 
4 #include "vrpn_BaseClass.h" // for ::vrpn_TEXT_WARNING, etc
5 #include "vrpn_Connection.h" // for vrpn_HANDLERPARAM, etc
7 
8 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS
9 #include "server_src/NIUtil.cpp"
10 #endif
11 
12 
14  const char *boardName,
15  int numInChannels, int numOutChannels,
16  double minInputReportDelaySecs,
17  bool inBipolar, int inputMode, int inputRange, bool driveAIS, int inputGain,
18  bool outBipolar, double minOutVoltage, double maxOutVoltage) :
19  vrpn_Analog(name, c),
20  vrpn_Analog_Output(name, c),
21 #if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
22  d_analog_task_handle(0),
23  d_analog_out_task_handle(0),
24 #else
25  d_device_number(-1),
26 #endif
27  d_out_min_voltage(minOutVoltage),
28  d_out_max_voltage(maxOutVoltage),
29  d_in_min_delay(minInputReportDelaySecs),
30  d_in_gain(inputGain)
31 {
32  // Set the polarity. 0 is bipolar, 1 is unipolar.
33  if (inBipolar) {
34  d_in_polarity = 0;
35  } else {
36  d_in_polarity = 1;
37  }
38  if (outBipolar) {
39  d_out_polarity = 0;
40  } else {
41  d_out_polarity = 1;
42  }
43 
44  setNumInChannels( numInChannels );
45  setNumOutChannels( numOutChannels );
46 
47 #if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
48  char portName[1024];
49  int32 error=0;
50 
51  // Input mode that we are using
52  int32 terminalConfig;
53  switch(inputMode) {
55  terminalConfig = DAQmx_Val_Diff;
56  break;
58  terminalConfig = DAQmx_Val_RSE;
59  break;
61  terminalConfig = DAQmx_Val_NRSE;
62  break;
63  default:
64  fprintf(stderr,"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Invalid inputMode (%d)\n", inputMode);
65  return;
66  }
67 
68  // Minimum and maximum values that we expect to read.
69  // Set the high end of the voltage range. If we're bipolar, then
70  // we get half the range above and half below zero.
71  double min_val = 0.0, max_val = inputRange;
72  if (inBipolar) {
73  min_val = -max_val/2;
74  max_val = max_val/2;
75  }
76 
77  // If we are going analog input, then we specify the range of input
78  // ports that we use from 0 through the number requested. We make a
79  // task to handle reading of these channels as a group. We then
80  // start this task.
81  if (numInChannels > 0) {
82  sprintf(portName, "%s/ai0:%d", boardName, numInChannels-1);
83  error = DAQmxCreateTask("", &d_analog_task_handle);
84  if (error == 0) {
85  error = DAQmxCreateAIVoltageChan(
86  d_analog_task_handle // The handle we'll use to read values
87  , portName // Device name and port range
88  , "" // Our nickname for the channel
89  , terminalConfig // Single-ended vs. differentil
90  , min_val, max_val // Range of values we expect to read
91  , DAQmx_Val_Volts, "" // Units, no custom scale
92  );
93  if (error == 0) {
94  fprintf(stderr,"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create input voltage channel\n");
95  error = DAQmxStartTask(d_analog_task_handle);
96  }
97  }
98  if (error) {
99  fprintf(stderr,"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create input voltage task\n");
100  reportError(error);
101  return;
102  }
103  }
104 
105  // If we are going analog output, then we specify the range of output
106  // ports that we use from 0 through the number requested. We make a
107  // task to handle writing of these channels as a group. Start the
108  // task. Also, set the outputs to their minimum value at startup.
109  if (numOutChannels > 0) {
110  sprintf(portName, "%s/ao0:%d", boardName, numOutChannels-1);
111  error = DAQmxCreateTask("", &d_analog_out_task_handle);
112  if (error == 0) {
113  error = DAQmxCreateAOVoltageChan(
114  d_analog_out_task_handle // The handle we'll use to write values
115  , portName // Device name and port range
116  , "" // Our nickname for the channel
117  , minOutVoltage, maxOutVoltage// Range of values we expect to write
118  , DAQmx_Val_Volts, "" // Units, no custom scale
119  );
120  if (error) {
121  fprintf(stderr,"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create output voltage channel\n");
122  reportError(error);
123  return;
124  }
125  }
126  if (error == 0) {
127  error = DAQmxStartTask(d_analog_out_task_handle);
128  }
129  if (error) {
130  fprintf(stderr,"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create or start output voltage task\n");
131  reportError(error);
132  return;
133  }
134 
135  // Set the output values to zero or to the minimum if the minimum
136  // is above 0. Also send these values to the board.
137  float64 minval = 0.0;
138  if (minval < minOutVoltage) { minval = minOutVoltage; }
139  int i;
140  for (i = 0; i < vrpn_Analog_Output::o_num_channel; i++) {
141  vrpn_Analog_Output::o_channel[i] = minval;
142  }
143  if (!setValues()) {
144  fprintf(stderr, "vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Could not set values\n");
145  return;
146  }
147  }
148 
149 #elif defined(VRPN_USE_NATIONAL_INSTRUMENTS)
150  short i;
151  short update_mode = 0; //< Mode 0 is immediate
152  short ref_source = 0; //< Reference source, 0 = internal, 1 = external
153  double ref_voltage = 10.0;
154 
155  // Open the board
156  d_device_number = NIUtil::findDevice(boardName);
157  if (d_device_number == -1) {
158  fprintf(stderr, "vrpn_National_Instruments_Server: Error opening the D/A board %s\n", boardName);
159  return;
160  }
161 
162  // Set the parameters for each input channel.
163  if (vrpn_Analog::num_channel > 0) {
164  int ret = AI_Clear(d_device_number);
165  if (ret < 0) {
166  fprintf(stderr,"vrpn_National_Instruments_Server: Cannot clear analog input (error %d)\n", ret);
167  setNumInChannels(0);
168  }
169  }
170  for (i = 0; i < vrpn_Analog::num_channel; i++) {
171  int ret = AI_Configure(d_device_number, i, inputMode, inputRange, d_in_polarity, driveAIS);
172  if (ret < 0) {
173  fprintf(stderr,"vrpn_National_Instruments_Server: Cannot configure input channel %d (error %d)\n", i, ret);
174  setNumInChannels(0);
175  break;
176  }
177  }
178 
179  // Set the parameters for each output channel. Set the voltage for each channel to the minimum.
180  for (i = 0; i < o_num_channel; i++) {
181 
182  int ret = AO_Configure(d_device_number, i, d_out_polarity, ref_source, ref_voltage, update_mode);
183  // Code -10403 shows up but did not cause problems for the NI server, so we ignore it (probably at our peril)
184  if ( (ret < 0) && (ret != -10403) ) {
185  fprintf(stderr,"vrpn_National_Instruments_Server: Cannot configure output channel %d (error %d)\n", i, ret);
186  fprintf(stderr," polarity: %d, reference source: %d, reference_voltage: %lg, update_mode: %d\n",
187  d_out_polarity, ref_source, ref_voltage, update_mode);
189  break;
190  }
191 
192  if (AO_VWrite(d_device_number, i, d_out_min_voltage)) {
193  fprintf(stderr,"vrpn_National_Instruments_Server: Cannot set output channel %d to %lg\n", i, d_out_min_voltage);
195  }
196  }
197 
198 #else
199  fprintf(stderr,"vrpn_National_Instruments_Server: Support for NI not compiled in, edit vrpn_Configure.h and recompile VRPN\n");
200 #endif
201 
202  // Check if we have a connection
203  if (d_connection == NULL) {
204  fprintf(stderr, "vrpn_National_Instruments_Server: Can't get connection!\n");
205  }
206 
207  // Register a handler for the request channel change message
210  fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channel request handler\n");
211  d_connection = NULL;
212  }
213 
214  // Register a handler for the request channels change message
217  fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channels request handler\n");
218  d_connection = NULL;
219  }
220 
221  // Register a handler for vrpn_got_connection, so we can tell the
222  // client how many channels are active
224  {
225  fprintf( stderr, "vrpn_Analog_Output_Server_NI: can't register new connection handler\n");
226  d_connection = NULL;
227  }
228 
229  // No report yet sent.
230  d_last_report_time.tv_sec = 0;
231  d_last_report_time.tv_usec = 0;
232 }
233 
234 // virtual
236 {
237 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
238  if( d_analog_task_handle != 0 )
239  {
240  /*********************************************/
241  // DAQmx Stop Code
242  /*********************************************/
243  DAQmxStopTask(d_analog_task_handle);
244  DAQmxClearTask(d_analog_task_handle);
246  }
247 
248  if( d_analog_out_task_handle != 0 )
249  {
250  /*********************************************/
251  // DAQmx Stop Code
252  /*********************************************/
253  DAQmxStopTask(d_analog_out_task_handle);
254  DAQmxClearTask(d_analog_out_task_handle);
256  }
257 #endif
258 }
259 
260 // virtual
262 {
263  // Let the server code do its thing (ping/pong messages)
264  server_mainloop();
265 
266  // See if it has been long enough since we sent the last report.
267  // If so, then read the channels and send a new report.
268  struct timeval now;
269  vrpn_gettimeofday(&now, NULL);
271  d_last_report_time = now;
272 
273 #if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
274  // Read one complete set of channel values from the board and store
275  // the results (which are already in volts) into the channels.
276  if (vrpn_Analog::num_channel > 0) {
277  int32 error;
278  int32 channelsRead = 0;
279  float64 data[vrpn_CHANNEL_MAX];
280  error = DAQmxReadAnalogF64(d_analog_task_handle, 1, 1.0, DAQmx_Val_GroupByChannel,
281  data, vrpn_CHANNEL_MAX, &channelsRead, NULL);
282  if (channelsRead != vrpn_Analog::num_channel) {
283  send_text_message("vrpn_National_Instruments_Server::mainloop(): Cannot read channel", now, vrpn_TEXT_ERROR);
284  setNumInChannels(0);
285  return;
286  }
287  if (error) {
288  reportError(error);
289  return;
290  }
291  int i;
292  for (i = 0; i < channelsRead; i++) {
293  channel[i] = data[i];
294  }
295  }
296 
297 #elif defined(VRPN_USE_NATIONAL_INSTRUMENTS)
298  // Read from the board, convert to volts, and store in the channel array
299  i16 value;
300  int i;
301  for (i = 0; i < vrpn_Analog::num_channel; i++) {
302  int ret = AI_Read(d_device_number, i, d_in_gain, &value);
303  if (ret != 0) {
304  send_text_message("vrpn_National_Instruments_Server::mainloop(): Cannot read channel", now, vrpn_TEXT_ERROR);
305  setNumInChannels(0);
306  return;
307  }
308  if(0 == d_in_polarity){ //Bipolar: We multiply by 10, but it will only go halfway (it is signed).
309  channel[i] = (value / 65536.0) * (10.0 / d_in_gain);
310  } else { //Unipolar (cast it to unsigned, so it will be from zero to almost 10 volts).
311  channel[i] = ((vrpn_uint16)value / 65536.0) * (10.0 / d_in_gain);
312  }
313  }
314 #endif
315 
316  // Send a report.
318  }
319 }
320 
322  if (sizeRequested < 0) sizeRequested = 0;
323  if (sizeRequested > vrpn_CHANNEL_MAX) sizeRequested = vrpn_CHANNEL_MAX;
324  vrpn_Analog::num_channel = sizeRequested;
325 
327 }
328 
330  if (sizeRequested < 0) sizeRequested = 0;
331  if (sizeRequested > vrpn_CHANNEL_MAX) sizeRequested = vrpn_CHANNEL_MAX;
332 
333  o_num_channel = sizeRequested;
334  return o_num_channel;
335 }
336 
337 /* static */
340 {
341  const char* bufptr = p.buffer;
342  vrpn_int32 chan_num;
343  vrpn_int32 pad;
344  vrpn_float64 value;
346 
347  // Read the parameters from the buffer
348  vrpn_unbuffer(&bufptr, &chan_num);
349  vrpn_unbuffer(&bufptr, &pad);
350  vrpn_unbuffer(&bufptr, &value);
351 
352  // Set the appropriate value, if the channel number is in the
353  // range of the ones we have.
354  if ( (chan_num < 0) || (chan_num >= me->o_num_channel) ) {
355  char msg[1024];
356  sprintf( msg, "Error: (handle_request_message): channel %d is not active. Squelching.", chan_num );
358  return 0;
359  }
360  // Make sure the voltage value is within the allowed range.
361  if (value < me->d_out_min_voltage) {
362  char msg[1024];
363  sprintf( msg, "Error: (handle_request_message): voltage %g is too low. Clamping to %g.", value, me->d_out_min_voltage);
365  value = me->d_out_min_voltage;
366  }
367  if (value > me->d_out_max_voltage) {
368  char msg[1024];
369  sprintf( msg, "Error: (handle_request_message): voltage %g is too high. Clamping to %g.", value, me->d_out_max_voltage);
371  value = me->d_out_max_voltage;
372  }
373  me->o_channel[chan_num] = value;
374 
375  // Send the new value to the D/A board
376 #if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
377  if (!me->setValues()) {
378  me->send_text_message( "vrpn_National_Instruments_Server::handle_request_message(): Could not set values", p.msg_time, vrpn_TEXT_ERROR );
379  return -1;
380  }
381 
382 #elif defined(VRPN_USE_NATIONAL_INSTRUMENTS)
383  if (me->d_device_number != -1) {
384  AO_VWrite(me->d_device_number, (short)(chan_num), value);
385  }
386 #endif
387  return 0;
388 }
389 
390 /* static */
393 {
394  const char* bufptr = p.buffer;
395  vrpn_int32 num;
396  vrpn_int32 pad;
398  vrpn_int32 chan_num;
399  vrpn_float64 value;
400 
401  // Read the values from the buffer
402  vrpn_unbuffer(&bufptr, &num);
403  vrpn_unbuffer(&bufptr, &pad);
404  if (num > me->o_num_channel)
405  {
406  char msg[1024];
407  sprintf( msg, "Error: (handle_request_channels_message): channels above %d not active; "
408  "bad request up to channel %d. Squelching.", me->o_num_channel, num );
410  num = me->o_num_channel;
411  }
412  if (num < 0)
413  {
414  char msg[1024];
415  sprintf( msg, "Error: (handle_request_channels_message): invalid channel %d. Squelching.", num );
417  return 0;
418  }
419  for (chan_num = 0; chan_num < num; chan_num++) {
420  vrpn_unbuffer(&bufptr, &value);
421 
422  // Make sure the voltage value is within the allowed range.
423  if (value < me->d_out_min_voltage) {
424  char msg[1024];
425  sprintf( msg, "Error: (handle_request_messages): voltage %g is too low. Clamping to %g.", value, me->d_out_min_voltage);
427  value = me->d_out_min_voltage;
428  }
429  if (value > me->d_out_max_voltage) {
430  char msg[1024];
431  sprintf( msg, "Error: (handle_request_messages): voltage %g is too high. Clamping to %g.", value, me->d_out_max_voltage);
433  value = me->d_out_max_voltage;
434  }
435  me->o_channel[chan_num] = value;
436 
437  // Send the new value to the D/A board
438 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS
439  if (me->d_device_number != -1) {
440  AO_VWrite(me->d_device_number, (short)(chan_num), value);
441  }
442 #endif
443  }
444 
445 #if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
446  if (!me->setValues()) {
447  me->send_text_message( "vrpn_National_Instruments_Server::handle_request_channels_message(): Could not set values", p.msg_time, vrpn_TEXT_ERROR );
448  return -1;
449  }
450 #endif
451 
452  return 0;
453 }
454 
455 #if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
457  // Send all current values to the board, including the
458  // changed one.
459  float64 outbuffer[vrpn_CHANNEL_MAX];
460  int i;
461  for (i = 0; i < vrpn_Analog_Output::o_num_channel ; i++) {
462  outbuffer[i] = vrpn_Analog_Output::o_channel[i];
463  }
464  int32 error;
465  error = DAQmxWriteAnalogF64(d_analog_out_task_handle, 1, true, 1.0,
466  DAQmx_Val_GroupByChannel, outbuffer, NULL, NULL);
467  if (error) {
468  reportError(error);
469  return false;
470  }
471  /*
472  printf("Debug: Setting %d channels:", o_num_channel);
473  for (i = 0; i < o_num_channel; i++) {
474  printf(" %lg", outbuffer[i]);
475  }
476  printf("\n");
477  */
478  return true;
479 }
480 #endif
481 
482 /* static */
484 {
486  if( me->report_num_channels( ) == false ) {
487  fprintf( stderr, "Error: failed sending active channels to client.\n" );
488  }
489  return 0;
490 }
491 
492 bool vrpn_National_Instruments_Server::report_num_channels( vrpn_uint32 class_of_service )
493 {
494  char msgbuf[ sizeof( vrpn_int32) ];
495  vrpn_int32 len = sizeof( vrpn_int32 );;
496 
498  vrpn_gettimeofday( &o_timestamp, NULL );
499  if( d_connection &&
501  d_sender_id, msgbuf, class_of_service ) )
502  {
503  fprintf(stderr, "vrpn_Analog_Output_Server_NI (report_num_channels): cannot write message: tossing\n");
504  return false;
505  }
506  return true;
507 }
508 
509 
510 vrpn_int32 vrpn_National_Instruments_Server::encode_num_channels_to( char* buf, vrpn_int32 num )
511 {
512  // Message includes: int32 number of active channels
513  int buflen = sizeof(vrpn_int32);
514 
515  vrpn_buffer(&buf, &buflen, num);
516  return sizeof(vrpn_int32);
517 }
518 
520  const char *boardName,
521  vrpn_int16 numChannels, bool bipolar,
522  double minVoltage, double maxVoltage) :
523  vrpn_Analog_Output(name, c),
524  NI_device_number(-1),
525  min_voltage(minVoltage),
526  max_voltage(maxVoltage),
527  NI_num_channels(numChannels)
528 {
529 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS
530  short i;
531  short update_mode = 0; //< Mode 0 is immediate
532  short ref_source = 0; //< Reference source, 0 = internal, 1 = external
533  double ref_voltage = 0.0;
534 
535  // Set the polarity
536  if (bipolar) {
537  polarity = 0;
538  } else {
539  polarity = 1;
540  }
541 
542  // Open the D/A board and set the parameters for each channel. Set the voltage for each
543  // channel to the minimum.
544  NI_device_number = NIUtil::findDevice(boardName);
545  if (NI_device_number == -1) {
546  fprintf(stderr, "vrpn_Analog_Output_Server_NI: Error opening the D/A board %s\n", boardName);
547  return;
548  }
549  for (i = 0; i < NI_num_channels; i++) {
550  AO_Configure(NI_device_number, i, polarity, ref_source, ref_voltage,
551  update_mode);
552 /*
553  fprintf(stderr,"Configuring channel %d, polarity: %d, reference source: %d, reference_voltage: %lg, update_mode: %d\n",
554  i, polarity, ref_source, ref_voltage, update_mode);
555 */
556  AO_VWrite(NI_device_number, i, min_voltage);
557  }
558 
559 
560  setNumChannels( numChannels );
561 
562  // Check if we have a connection
563  if (d_connection == NULL) {
564  fprintf(stderr, "vrpn_Analog_Output_Server_NI: Can't get connection!\n");
565  }
566 
567  // Register a handler for the request channel change message
570  fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channel request handler\n");
571  d_connection = NULL;
572  }
573 
574  // Register a handler for the request channels change message
577  fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channels request handler\n");
578  d_connection = NULL;
579  }
580 
581  // Register a handler for vrpn_got_connection, so we can tell the
582  // client how many channels are active
584  {
585  fprintf( stderr, "vrpn_Analog_Output_Server_NI: can't register new connection handler\n");
586  d_connection = NULL;
587  }
588 #else
589  fprintf(stderr,"vrpn_Analog_Output_Server_NI: Support for NI not compiled in, edit vrpn_Configure.h and recompile\n");
590 #endif
591 }
592 
593 // virtual
595 
596 // virtual
598 {
599  // Let the server code do its thing (ping/pong messages)
600  server_mainloop();
601 }
602 
603 vrpn_int32 vrpn_Analog_Output_Server_NI::setNumChannels (vrpn_int32 sizeRequested) {
604  if (sizeRequested < 0) sizeRequested = 0;
605  if (sizeRequested > vrpn_CHANNEL_MAX) sizeRequested = vrpn_CHANNEL_MAX;
606 
607  o_num_channel = sizeRequested;
608 
609  return o_num_channel;
610 }
611 
612 /* static */
615 {
616  const char* bufptr = p.buffer;
617  vrpn_int32 chan_num;
618  vrpn_int32 pad;
619  vrpn_float64 value;
621 
622  // Read the parameters from the buffer
623  vrpn_unbuffer(&bufptr, &chan_num);
624  vrpn_unbuffer(&bufptr, &pad);
625  vrpn_unbuffer(&bufptr, &value);
626 
627  // Set the appropriate value, if the channel number is in the
628  // range of the ones we have.
629  if ( (chan_num < 0) || (chan_num >= me->o_num_channel) ) {
630  char msg[1024];
631  sprintf( msg, "Error: (handle_request_message): channel %d is not active. Squelching.", chan_num );
633  return 0;
634  }
635  // Make sure the voltage value is within the allowed range.
636  if (value < me->min_voltage) {
637  char msg[1024];
638  sprintf( msg, "Error: (handle_request_message): voltage %g is too low. Clamping to %g.", value, me->min_voltage);
640  value = me->min_voltage;
641  }
642  if (value > me->max_voltage) {
643  char msg[1024];
644  sprintf( msg, "Error: (handle_request_message): voltage %g is too high. Clamping to %g.", value, me->max_voltage);
646  value = me->max_voltage;
647  }
648  me->o_channel[chan_num] = value;
649 
650  // Send the new value to the D/A board
651 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS
652  if (me->NI_device_number != -1) {
653  AO_VWrite(me->NI_device_number, (short)(chan_num), value);
654  }
655 #endif
656  return 0;
657 }
658 
659 /* static */
662 {
663  const char* bufptr = p.buffer;
664  vrpn_int32 num;
665  vrpn_int32 pad;
667  vrpn_int32 chan_num;
668  vrpn_float64 value;
669 
670  // Read the values from the buffer
671  vrpn_unbuffer(&bufptr, &num);
672  vrpn_unbuffer(&bufptr, &pad);
673  if (num > me->o_num_channel)
674  {
675  char msg[1024];
676  sprintf( msg, "Error: (handle_request_channels_message): channels above %d not active; "
677  "bad request up to channel %d. Squelching.", me->o_num_channel, num );
679  num = me->o_num_channel;
680  }
681  if (num < 0)
682  {
683  char msg[1024];
684  sprintf( msg, "Error: (handle_request_channels_message): invalid channel %d. Squelching.", num );
686  return 0;
687  }
688  for (chan_num = 0; chan_num < num; chan_num++) {
689  vrpn_unbuffer(&bufptr, &value);
690 
691  // Make sure the voltage value is within the allowed range.
692  if (value < me->min_voltage) {
693  char msg[1024];
694  sprintf( msg, "Error: (handle_request_messages): voltage %g is too low. Clamping to %g.", value, me->min_voltage);
696  value = me->min_voltage;
697  }
698  if (value > me->max_voltage) {
699  char msg[1024];
700  sprintf( msg, "Error: (handle_request_messages): voltage %g is too high. Clamping to %g.", value, me->max_voltage);
702  value = me->max_voltage;
703  }
704  me->o_channel[chan_num] = value;
705 
706  // Send the new value to the D/A board
707 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS
708  if (me->NI_device_number != -1) {
709  AO_VWrite(me->NI_device_number, (short)(chan_num), value);
710  }
711 #endif
712  }
713 
714  return 0;
715 }
716 
717 
718 /* static */
720 {
722  if( me->report_num_channels( ) == false )
723  {
724  fprintf( stderr, "Error: failed sending active channels to client.\n" );
725  }
726  return 0;
727 }
728 
729 
730 bool vrpn_Analog_Output_Server_NI::report_num_channels( vrpn_uint32 class_of_service )
731 {
732  char msgbuf[ sizeof( vrpn_int32) ];
733  vrpn_int32 len = sizeof( vrpn_int32 );;
734 
736  vrpn_gettimeofday( &o_timestamp, NULL );
737  if( d_connection &&
739  d_sender_id, msgbuf, class_of_service ) )
740  {
741  fprintf(stderr, "vrpn_Analog_Output_Server_NI (report_num_channels): cannot write message: tossing\n");
742  return false;
743  }
744  return true;
745 }
746 
747 
749 encode_num_channels_to( char* buf, vrpn_int32 num )
750 {
751  // Message includes: int32 number of active channels
752  int buflen = sizeof(vrpn_int32);
753 
754  vrpn_buffer(&buf, &buflen, num);
755  return sizeof(vrpn_int32);
756 }
757 
758 // This handles error reporting
759 #ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
760 void vrpn_National_Instruments_Server::reportError(int32 errnumber, vrpn_bool exitProgram)
761 {
762  char errBuff[2048]={'\0'};
763 
764  if( DAQmxFailed(errnumber) )
765  {
766  DAQmxGetExtendedErrorInfo(errBuff,2048);
767  printf("DAQmx Error: %s\n",errBuff);
768  if (exitProgram==vrpn_true) {
769  printf("Exiting...\n") ;
770  throw(errnumber) ; // this will quit, cause the destructor to be called
771  } else {
772  printf("Sleeping...\n") ;
773  vrpn_SleepMsecs(1000.0*1) ; // so at least the log will slow down so someone can see the error
774  }
775  }
776 } // reportError
777 #endif
vrpn_BaseClassUnique::register_autodeleted_handler
int register_autodeleted_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Registers a handler with the connection, and remembers to delete at destruction.
Definition: vrpn_BaseClass.C:503
vrpn_Connection::pack_message
virtual int pack_message(vrpn_uint32 len, struct timeval time, vrpn_int32 type, vrpn_int32 sender, const char *buffer, vrpn_uint32 class_of_service)
Pack a message that will be sent the next time mainloop() is called. Turn off the RELIABLE flag if yo...
Definition: vrpn_Connection.C:4632
vrpn_Analog_Output_Server_NI::min_voltage
double min_voltage
Definition: vrpn_NationalInstruments.h:118
vrpn_National_Instruments_Server::d_last_report_time
struct timeval d_last_report_time
Definition: vrpn_NationalInstruments.h:65
vrpn_National_Instruments_Server::reportError
void reportError(int32 errnumber, vrpn_bool exitProgram=vrpn_false)
Definition: vrpn_NationalInstruments.C:760
vrpn_BaseClass.h
vrpn_Analog_Output_Server_NI::max_voltage
double max_voltage
Definition: vrpn_NationalInstruments.h:119
vrpn_Analog_Output_Server_NI::encode_num_channels_to
virtual vrpn_int32 encode_num_channels_to(char *buf, vrpn_int32 num)
Definition: vrpn_NationalInstruments.C:749
vrpn_Analog::channel
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog.h:38
vrpn_TimevalDurationSeconds
double vrpn_TimevalDurationSeconds(struct timeval endT, struct timeval startT)
Return the number of seconds between startT and endT as a floating-point value.
Definition: vrpn_Shared.C:135
vrpn_Analog_Output_Server_NI::vrpn_Analog_Output_Server_NI
vrpn_Analog_Output_Server_NI(const char *name, vrpn_Connection *c, const char *boardName="PCI-6713", vrpn_int16 numChannels=vrpn_CHANNEL_MAX, bool bipolar=false, double minVoltage=0.0, double maxVoltage=10.0)
Definition: vrpn_NationalInstruments.C:519
vrpn_Analog_Output_Server_NI
Definition: vrpn_NationalInstruments.h:103
vrpn_Analog_Output_Server_NI::setNumChannels
vrpn_int32 setNumChannels(vrpn_int32 sizeRequested)
Sets the size of the array; returns the size actually set. (May be clamped to vrpn_CHANNEL_MAX) This ...
Definition: vrpn_NationalInstruments.C:603
vrpn_National_Instruments_Server::d_out_polarity
short d_out_polarity
Definition: vrpn_NationalInstruments.h:64
vrpn_Analog_Output_Server_NI::NI_num_channels
short NI_num_channels
Definition: vrpn_NationalInstruments.h:117
vrpn_National_Instruments_Server::mainloop
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_NationalInstruments.C:261
vrpn_National_Instruments_Server::~vrpn_National_Instruments_Server
virtual ~vrpn_National_Instruments_Server()
Definition: vrpn_NationalInstruments.C:235
vrpn_Analog::report
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
vrpn_BaseClassUnique::userdata
void * userdata
Definition: vrpn_BaseClass.h:287
vrpn_Analog
Definition: vrpn_Analog.h:28
vrpn_Analog_Output_Server_NI::handle_got_connection
static int VRPN_CALLBACK handle_got_connection(void *userdata, vrpn_HANDLERPARAM p)
Used to notify us when a new connection is requested, so that we can let the client know how many cha...
Definition: vrpn_NationalInstruments.C:719
vrpn_Analog_Output::o_num_channel
vrpn_int32 o_num_channel
Definition: vrpn_Analog_Output.h:37
vrpn_Analog_Output
Definition: vrpn_Analog_Output.h:26
vrpn_CHANNEL_MAX
#define vrpn_CHANNEL_MAX
Definition: vrpn_Analog.h:16
vrpn_National_Instruments_Server::report_num_channels
virtual bool report_num_channels(vrpn_uint32 class_of_service=vrpn_CONNECTION_RELIABLE)
Definition: vrpn_NationalInstruments.C:492
vrpn_Analog_Output_Server_NI::handle_request_message
static int VRPN_CALLBACK handle_request_message(void *userdata, vrpn_HANDLERPARAM p)
Responds to a request to change one of the values by setting the channel to that value....
Definition: vrpn_NationalInstruments.C:613
vrpn_unbuffer
VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t)
Utility routine for taking a struct timeval from a buffer that was sent as a message.
Definition: vrpn_Shared.C:312
vrpn_BaseClassUnique::d_connection
vrpn_Connection * d_connection
Connection that this object talks to.
Definition: vrpn_BaseClass.h:224
vrpn_HANDLERPARAM::buffer
const char * buffer
Definition: vrpn_Connection.h:49
vrpn_National_Instruments_Server::d_in_polarity
short d_in_polarity
Definition: vrpn_NationalInstruments.h:59
vrpn_Analog_Output::got_connection_m_id
vrpn_int32 got_connection_m_id
Definition: vrpn_Analog_Output.h:44
vrpn_TEXT_ERROR
Definition: vrpn_BaseClass.h:103
vrpn_National_Instruments_Server::handle_request_channels_message
static int VRPN_CALLBACK handle_request_channels_message(void *userdata, vrpn_HANDLERPARAM p)
Responds to a request to change a number of channels Derived class must either install handlers for t...
Definition: vrpn_NationalInstruments.C:391
vrpn_SleepMsecs
void vrpn_SleepMsecs(double dMsecs)
Definition: vrpn_Shared.C:157
vrpn_National_Instruments_Server::handle_request_message
static int VRPN_CALLBACK handle_request_message(void *userdata, vrpn_HANDLERPARAM p)
Responds to a request to the AnalogOutput to change one of the values by setting the channel to that ...
Definition: vrpn_NationalInstruments.C:338
vrpn_HANDLERPARAM
This structure is what is passed to a vrpn_Connection message callback.
Definition: vrpn_Connection.h:44
vrpn_Shared.h
vrpn_TEXT_WARNING
Definition: vrpn_BaseClass.h:102
vrpn_BaseClassUnique::d_sender_id
vrpn_int32 d_sender_id
Sender ID registered with the connection.
Definition: vrpn_BaseClass.h:228
vrpn_Analog_Output_Server_NI::handle_request_channels_message
static int VRPN_CALLBACK handle_request_channels_message(void *userdata, vrpn_HANDLERPARAM p)
Responds to a request to change a number of channels Derived class must either install handlers for t...
Definition: vrpn_NationalInstruments.C:660
vrpn_Analog_Output_Server_NI::NI_device_number
short NI_device_number
Definition: vrpn_NationalInstruments.h:116
vrpn_NI_INPUT_MODE_DIFFERENTIAL
#define vrpn_NI_INPUT_MODE_DIFFERENTIAL
Definition: vrpn_NationalInstruments.h:19
vrpn_Analog_Output_Server_NI::mainloop
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
Definition: vrpn_NationalInstruments.C:597
vrpn_National_Instruments_Server::handle_got_connection
static int VRPN_CALLBACK handle_got_connection(void *userdata, vrpn_HANDLERPARAM p)
Used to notify us when a new connection is requested, so that we can let the client know how many cha...
Definition: vrpn_NationalInstruments.C:483
vrpn_National_Instruments_Server::d_analog_out_task_handle
TaskHandle d_analog_out_task_handle
Definition: vrpn_NationalInstruments.h:53
vrpn_National_Instruments_Server::d_out_max_voltage
double d_out_max_voltage
Definition: vrpn_NationalInstruments.h:63
vrpn_National_Instruments_Server::encode_num_channels_to
virtual vrpn_int32 encode_num_channels_to(char *buf, vrpn_int32 num)
Definition: vrpn_NationalInstruments.C:510
vrpn_HANDLERPARAM::msg_time
struct timeval msg_time
Definition: vrpn_Connection.h:47
vrpn_Connection
Generic connection class not specific to the transport mechanism.
Definition: vrpn_Connection.h:510
vrpn_Connection.h
vrpn_Analog::num_channel
vrpn_int32 num_channel
Definition: vrpn_Analog.h:40
vrpn_NationalInstruments.h
vrpn_gettimeofday
#define vrpn_gettimeofday
Definition: vrpn_Shared.h:89
vrpn_NI_INPUT_MODE_NON_REF_SINGLE_ENDED
#define vrpn_NI_INPUT_MODE_NON_REF_SINGLE_ENDED
Definition: vrpn_NationalInstruments.h:21
VRPN_CALLBACK
#define VRPN_CALLBACK
Definition: vrpn_Configure.h:647
vrpn_National_Instruments_Server::vrpn_National_Instruments_Server
vrpn_National_Instruments_Server(const char *name, vrpn_Connection *c, const char *boardName="PCI-6713", int numInChannels=vrpn_CHANNEL_MAX, int numOutChannels=vrpn_CHANNEL_MAX, double minInputReportDelaySecs=0.0, bool inBipolar=false, int inputMode=vrpn_NI_INPUT_MODE_DIFFERENTIAL, int inputRange=vrpn_NI_INPUT_RANGE_10V, bool driveAIS=false, int inputGain=1, bool outBipolar=false, double minOutVoltage=0.0, double maxOutVoltage=10.0)
Definition: vrpn_NationalInstruments.C:13
vrpn_Analog_Output::o_timestamp
struct timeval o_timestamp
Definition: vrpn_Analog_Output.h:38
vrpn_Analog_Output::o_channel
vrpn_float64 o_channel[vrpn_CHANNEL_MAX]
Definition: vrpn_Analog_Output.h:36
vrpn_buffer
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const timeval t)
Utility routine for placing a timeval struct into a buffer that is to be sent as a message.
Definition: vrpn_Shared.C:241
vrpn_National_Instruments_Server::setNumOutChannels
int setNumOutChannels(int sizeRequested)
Sets the size of the array; returns the size actually set. (May be clamped to vrpn_CHANNEL_MAX) This ...
Definition: vrpn_NationalInstruments.C:329
vrpn_BaseClassUnique::send_text_message
int send_text_message(const char *msg, struct timeval timestamp, vrpn_TEXT_SEVERITY type=vrpn_TEXT_NORMAL, vrpn_uint32 level=0)
Sends a NULL-terminated text message from the device d_sender_id.
Definition: vrpn_BaseClass.C:568
vrpn_Analog_Output_Server_NI::polarity
short polarity
Definition: vrpn_NationalInstruments.h:120
vrpn_National_Instruments_Server::d_in_gain
int d_in_gain
Definition: vrpn_NationalInstruments.h:60
vrpn_Analog_Output_Server_NI::report_num_channels
virtual bool report_num_channels(vrpn_uint32 class_of_service=vrpn_CONNECTION_RELIABLE)
Definition: vrpn_NationalInstruments.C:730
vrpn_National_Instruments_Server::d_out_min_voltage
double d_out_min_voltage
Definition: vrpn_NationalInstruments.h:62
vrpn_Analog_Output::request_channels_m_id
vrpn_int32 request_channels_m_id
Definition: vrpn_Analog_Output.h:40
vrpn_National_Instruments_Server::d_analog_task_handle
TaskHandle d_analog_task_handle
Definition: vrpn_NationalInstruments.h:52
vrpn_National_Instruments_Server
Definition: vrpn_NationalInstruments.h:30
vrpn_Analog_Output::request_m_id
vrpn_int32 request_m_id
Definition: vrpn_Analog_Output.h:39
vrpn_National_Instruments_Server::setNumInChannels
int setNumInChannels(int sizeRequested)
Sets the size of the array; returns the size actually set. (May be clamped to vrpn_CHANNEL_MAX) This ...
Definition: vrpn_NationalInstruments.C:321
vrpn_National_Instruments_Server::d_in_min_delay
double d_in_min_delay
Definition: vrpn_NationalInstruments.h:61
vrpn_National_Instruments_Server::setValues
bool setValues()
Definition: vrpn_NationalInstruments.C:456
vrpn_BaseClassUnique::server_mainloop
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
Definition: vrpn_BaseClass.C:603
vrpn_Analog_Output::report_num_channels_m_id
vrpn_int32 report_num_channels_m_id
Definition: vrpn_Analog_Output.h:42
vrpn_Analog_Output_Server_NI::~vrpn_Analog_Output_Server_NI
virtual ~vrpn_Analog_Output_Server_NI(void)
Definition: vrpn_NationalInstruments.C:594
vrpn_NI_INPUT_MODE_REF_SINGLE_ENDED
#define vrpn_NI_INPUT_MODE_REF_SINGLE_ENDED
Definition: vrpn_NationalInstruments.h:20