vrpn 07.35
Virtual Reality Peripheral Network
 
Loading...
Searching...
No Matches
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)
24#else
25 d_device_number(-1),
26#endif
27 d_in_gain(inputGain),
28 d_in_min_delay(minInputReportDelaySecs),
29 d_out_min_voltage(minOutVoltage),
30 d_out_max_voltage(maxOutVoltage)
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) {
40 } else {
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++) {
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);
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);
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 // Handle parameters that are not used, avoiding compiler warnings.
201 const char *unused = boardName;
202 unused++;
203 inputMode = inputMode + 1;
204 inputRange = inputRange + 1;
205 driveAIS = !driveAIS;
206#endif
207
208 // Check if we have a connection
209 if (d_connection == NULL) {
210 fprintf(stderr, "vrpn_National_Instruments_Server: Can't get connection!\n");
211 }
212
213 // Register a handler for the request channel change message
216 fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channel request handler\n");
217 d_connection = NULL;
218 }
219
220 // Register a handler for the request channels change message
223 fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channels request handler\n");
224 d_connection = NULL;
225 }
226
227 // Register a handler for vrpn_got_connection, so we can tell the
228 // client how many channels are active
230 {
231 fprintf( stderr, "vrpn_Analog_Output_Server_NI: can't register new connection handler\n");
232 d_connection = NULL;
233 }
234
235 // No report yet sent.
236 d_last_report_time.tv_sec = 0;
237 d_last_report_time.tv_usec = 0;
238}
239
240// virtual
242{
243#ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
244 if( d_analog_task_handle != 0 )
245 {
246 /*********************************************/
247 // DAQmx Stop Code
248 /*********************************************/
249 DAQmxStopTask(d_analog_task_handle);
250 DAQmxClearTask(d_analog_task_handle);
252 }
253
254 if( d_analog_out_task_handle != 0 )
255 {
256 /*********************************************/
257 // DAQmx Stop Code
258 /*********************************************/
259 DAQmxStopTask(d_analog_out_task_handle);
260 DAQmxClearTask(d_analog_out_task_handle);
262 }
263#endif
264}
265
266// virtual
268{
269 // Let the server code do its thing (ping/pong messages)
271
272 // See if it has been long enough since we sent the last report.
273 // If so, then read the channels and send a new report.
274 struct timeval now;
275 vrpn_gettimeofday(&now, NULL);
277 d_last_report_time = now;
278
279#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
280 // Read one complete set of channel values from the board and store
281 // the results (which are already in volts) into the channels.
282 if (vrpn_Analog::num_channel > 0) {
283 int32 error;
284 int32 channelsRead = 0;
285 float64 data[vrpn_CHANNEL_MAX];
286 error = DAQmxReadAnalogF64(d_analog_task_handle, 1, 1.0, DAQmx_Val_GroupByChannel,
287 data, vrpn_CHANNEL_MAX, &channelsRead, NULL);
288 if (channelsRead != vrpn_Analog::num_channel) {
289 send_text_message("vrpn_National_Instruments_Server::mainloop(): Cannot read channel", now, vrpn_TEXT_ERROR);
291 return;
292 }
293 if (error) {
294 reportError(error);
295 return;
296 }
297 int i;
298 for (i = 0; i < channelsRead; i++) {
299 channel[i] = data[i];
300 }
301 }
302
303#elif defined(VRPN_USE_NATIONAL_INSTRUMENTS)
304 // Read from the board, convert to volts, and store in the channel array
305 i16 value;
306 int i;
307 for (i = 0; i < vrpn_Analog::num_channel; i++) {
308 int ret = AI_Read(d_device_number, i, d_in_gain, &value);
309 if (ret != 0) {
310 send_text_message("vrpn_National_Instruments_Server::mainloop(): Cannot read channel", now, vrpn_TEXT_ERROR);
312 return;
313 }
314 if(0 == d_in_polarity){ //Bipolar: We multiply by 10, but it will only go halfway (it is signed).
315 channel[i] = (value / 65536.0) * (10.0 / d_in_gain);
316 } else { //Unipolar (cast it to unsigned, so it will be from zero to almost 10 volts).
317 channel[i] = ((vrpn_uint16)value / 65536.0) * (10.0 / d_in_gain);
318 }
319 }
320#endif
321
322 // Send a report.
324 }
325}
326
328 if (sizeRequested < 0) sizeRequested = 0;
329 if (sizeRequested > vrpn_CHANNEL_MAX) sizeRequested = vrpn_CHANNEL_MAX;
330 vrpn_Analog::num_channel = sizeRequested;
331
333}
334
336 if (sizeRequested < 0) sizeRequested = 0;
337 if (sizeRequested > vrpn_CHANNEL_MAX) sizeRequested = vrpn_CHANNEL_MAX;
338
339 o_num_channel = sizeRequested;
340 return o_num_channel;
341}
342
343/* static */
346{
347 const char* bufptr = p.buffer;
348 vrpn_int32 chan_num;
349 vrpn_int32 pad;
350 vrpn_float64 value;
352
353 // Read the parameters from the buffer
354 vrpn_unbuffer(&bufptr, &chan_num);
355 vrpn_unbuffer(&bufptr, &pad);
356 vrpn_unbuffer(&bufptr, &value);
357
358 // Set the appropriate value, if the channel number is in the
359 // range of the ones we have.
360 if ( (chan_num < 0) || (chan_num >= me->o_num_channel) ) {
361 char msg[1024];
362 sprintf( msg, "Error: (handle_request_message): channel %d is not active. Squelching.", chan_num );
364 return 0;
365 }
366 // Make sure the voltage value is within the allowed range.
367 if (value < me->d_out_min_voltage) {
368 char msg[1024];
369 sprintf( msg, "Error: (handle_request_message): voltage %g is too low. Clamping to %g.", value, me->d_out_min_voltage);
371 value = me->d_out_min_voltage;
372 }
373 if (value > me->d_out_max_voltage) {
374 char msg[1024];
375 sprintf( msg, "Error: (handle_request_message): voltage %g is too high. Clamping to %g.", value, me->d_out_max_voltage);
377 value = me->d_out_max_voltage;
378 }
379 me->o_channel[chan_num] = value;
380
381 // Send the new value to the D/A board
382#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
383 if (!me->setValues()) {
384 me->send_text_message( "vrpn_National_Instruments_Server::handle_request_message(): Could not set values", p.msg_time, vrpn_TEXT_ERROR );
385 return -1;
386 }
387
388#elif defined(VRPN_USE_NATIONAL_INSTRUMENTS)
389 if (me->d_device_number != -1) {
390 AO_VWrite(me->d_device_number, (short)(chan_num), value);
391 }
392#endif
393 return 0;
394}
395
396/* static */
399{
400 const char* bufptr = p.buffer;
401 vrpn_int32 num;
402 vrpn_int32 pad;
404 vrpn_int32 chan_num;
405 vrpn_float64 value;
406
407 // Read the values from the buffer
408 vrpn_unbuffer(&bufptr, &num);
409 vrpn_unbuffer(&bufptr, &pad);
410 if (num > me->o_num_channel)
411 {
412 char msg[1024];
413 sprintf( msg, "Error: (handle_request_channels_message): channels above %d not active; "
414 "bad request up to channel %d. Squelching.", me->o_num_channel, num );
416 num = me->o_num_channel;
417 }
418 if (num < 0)
419 {
420 char msg[1024];
421 sprintf( msg, "Error: (handle_request_channels_message): invalid channel %d. Squelching.", num );
423 return 0;
424 }
425 for (chan_num = 0; chan_num < num; chan_num++) {
426 vrpn_unbuffer(&bufptr, &value);
427
428 // Make sure the voltage value is within the allowed range.
429 if (value < me->d_out_min_voltage) {
430 char msg[1024];
431 sprintf( msg, "Error: (handle_request_messages): voltage %g is too low. Clamping to %g.", value, me->d_out_min_voltage);
433 value = me->d_out_min_voltage;
434 }
435 if (value > me->d_out_max_voltage) {
436 char msg[1024];
437 sprintf( msg, "Error: (handle_request_messages): voltage %g is too high. Clamping to %g.", value, me->d_out_max_voltage);
439 value = me->d_out_max_voltage;
440 }
441 me->o_channel[chan_num] = value;
442
443 // Send the new value to the D/A board
444#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
445 if (me->d_device_number != -1) {
446 AO_VWrite(me->d_device_number, (short)(chan_num), value);
447 }
448#endif
449 }
450
451#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
452 if (!me->setValues()) {
453 me->send_text_message( "vrpn_National_Instruments_Server::handle_request_channels_message(): Could not set values", p.msg_time, vrpn_TEXT_ERROR );
454 return -1;
455 }
456#endif
457
458 return 0;
459}
460
461#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
463 // Send all current values to the board, including the
464 // changed one.
465 float64 outbuffer[vrpn_CHANNEL_MAX];
466 int i;
467 for (i = 0; i < vrpn_Analog_Output::o_num_channel ; i++) {
468 outbuffer[i] = vrpn_Analog_Output::o_channel[i];
469 }
470 int32 error;
471 error = DAQmxWriteAnalogF64(d_analog_out_task_handle, 1, true, 1.0,
472 DAQmx_Val_GroupByChannel, outbuffer, NULL, NULL);
473 if (error) {
474 reportError(error);
475 return false;
476 }
477 /*
478 printf("Debug: Setting %d channels:", o_num_channel);
479 for (i = 0; i < o_num_channel; i++) {
480 printf(" %lg", outbuffer[i]);
481 }
482 printf("\n");
483 */
484 return true;
485}
486#endif
487
488/* static */
490{
492 if( me->report_num_channels( ) == false ) {
493 fprintf( stderr, "Error: failed sending active channels to client.\n" );
494 }
495 return 0;
496}
497
499{
500 char msgbuf[ sizeof( vrpn_int32) ];
501 vrpn_int32 len = sizeof( vrpn_int32 );;
502
505 if( d_connection &&
507 d_sender_id, msgbuf, class_of_service ) )
508 {
509 fprintf(stderr, "vrpn_Analog_Output_Server_NI (report_num_channels): cannot write message: tossing\n");
510 return false;
511 }
512 return true;
513}
514
515
516vrpn_int32 vrpn_National_Instruments_Server::encode_num_channels_to( char* buf, vrpn_int32 num )
517{
518 // Message includes: int32 number of active channels
519 int buflen = sizeof(vrpn_int32);
520
521 vrpn_buffer(&buf, &buflen, num);
522 return sizeof(vrpn_int32);
523}
524
526 const char *boardName,
527 vrpn_int16 numChannels, bool bipolar,
528 double minVoltage, double maxVoltage) :
529 vrpn_Analog_Output(name, c),
531 NI_num_channels(numChannels),
532 min_voltage(minVoltage),
533 max_voltage(maxVoltage)
534{
535#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
536 short i;
537 short update_mode = 0; //< Mode 0 is immediate
538 short ref_source = 0; //< Reference source, 0 = internal, 1 = external
539 double ref_voltage = 0.0;
540
541 // Set the polarity
542 if (bipolar) {
543 polarity = 0;
544 } else {
545 polarity = 1;
546 }
547
548 // Open the D/A board and set the parameters for each channel. Set the voltage for each
549 // channel to the minimum.
550 NI_device_number = NIUtil::findDevice(boardName);
551 if (NI_device_number == -1) {
552 fprintf(stderr, "vrpn_Analog_Output_Server_NI: Error opening the D/A board %s\n", boardName);
553 return;
554 }
555 for (i = 0; i < NI_num_channels; i++) {
556 AO_Configure(NI_device_number, i, polarity, ref_source, ref_voltage,
557 update_mode);
558/*
559 fprintf(stderr,"Configuring channel %d, polarity: %d, reference source: %d, reference_voltage: %lg, update_mode: %d\n",
560 i, polarity, ref_source, ref_voltage, update_mode);
561*/
562 AO_VWrite(NI_device_number, i, min_voltage);
563 }
564
565
566 setNumChannels( numChannels );
567
568 // Check if we have a connection
569 if (d_connection == NULL) {
570 fprintf(stderr, "vrpn_Analog_Output_Server_NI: Can't get connection!\n");
571 }
572
573 // Register a handler for the request channel change message
576 fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channel request handler\n");
577 d_connection = NULL;
578 }
579
580 // Register a handler for the request channels change message
583 fprintf(stderr,"vrpn_Analog_Output_Server_NI: can't register change channels request handler\n");
584 d_connection = NULL;
585 }
586
587 // Register a handler for vrpn_got_connection, so we can tell the
588 // client how many channels are active
590 {
591 fprintf( stderr, "vrpn_Analog_Output_Server_NI: can't register new connection handler\n");
592 d_connection = NULL;
593 }
594#else
595 fprintf(stderr,"vrpn_Analog_Output_Server_NI: Support for NI not compiled in, edit vrpn_Configure.h and recompile\n");
596 const char *unused = boardName;
597 unused++;
598 bipolar = !bipolar;
599#endif
600}
601
602// virtual
604
605// virtual
607{
608 // Let the server code do its thing (ping/pong messages)
610}
611
612vrpn_int32 vrpn_Analog_Output_Server_NI::setNumChannels (vrpn_int32 sizeRequested) {
613 if (sizeRequested < 0) sizeRequested = 0;
614 if (sizeRequested > vrpn_CHANNEL_MAX) sizeRequested = vrpn_CHANNEL_MAX;
615
616 o_num_channel = sizeRequested;
617
618 return o_num_channel;
619}
620
621/* static */
624{
625 const char* bufptr = p.buffer;
626 vrpn_int32 chan_num;
627 vrpn_int32 pad;
628 vrpn_float64 value;
630
631 // Read the parameters from the buffer
632 vrpn_unbuffer(&bufptr, &chan_num);
633 vrpn_unbuffer(&bufptr, &pad);
634 vrpn_unbuffer(&bufptr, &value);
635
636 // Set the appropriate value, if the channel number is in the
637 // range of the ones we have.
638 if ( (chan_num < 0) || (chan_num >= me->o_num_channel) ) {
639 char msg[1024];
640 sprintf( msg, "Error: (handle_request_message): channel %d is not active. Squelching.", chan_num );
642 return 0;
643 }
644 // Make sure the voltage value is within the allowed range.
645 if (value < me->min_voltage) {
646 char msg[1024];
647 sprintf( msg, "Error: (handle_request_message): voltage %g is too low. Clamping to %g.", value, me->min_voltage);
649 value = me->min_voltage;
650 }
651 if (value > me->max_voltage) {
652 char msg[1024];
653 sprintf( msg, "Error: (handle_request_message): voltage %g is too high. Clamping to %g.", value, me->max_voltage);
655 value = me->max_voltage;
656 }
657 me->o_channel[chan_num] = value;
658
659 // Send the new value to the D/A board
660#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
661 if (me->NI_device_number != -1) {
662 AO_VWrite(me->NI_device_number, (short)(chan_num), value);
663 }
664#endif
665 return 0;
666}
667
668/* static */
671{
672 const char* bufptr = p.buffer;
673 vrpn_int32 num;
674 vrpn_int32 pad;
676 vrpn_int32 chan_num;
677 vrpn_float64 value;
678
679 // Read the values from the buffer
680 vrpn_unbuffer(&bufptr, &num);
681 vrpn_unbuffer(&bufptr, &pad);
682 if (num > me->o_num_channel)
683 {
684 char msg[1024];
685 sprintf( msg, "Error: (handle_request_channels_message): channels above %d not active; "
686 "bad request up to channel %d. Squelching.", me->o_num_channel, num );
688 num = me->o_num_channel;
689 }
690 if (num < 0)
691 {
692 char msg[1024];
693 sprintf( msg, "Error: (handle_request_channels_message): invalid channel %d. Squelching.", num );
695 return 0;
696 }
697 for (chan_num = 0; chan_num < num; chan_num++) {
698 vrpn_unbuffer(&bufptr, &value);
699
700 // Make sure the voltage value is within the allowed range.
701 if (value < me->min_voltage) {
702 char msg[1024];
703 sprintf( msg, "Error: (handle_request_messages): voltage %g is too low. Clamping to %g.", value, me->min_voltage);
705 value = me->min_voltage;
706 }
707 if (value > me->max_voltage) {
708 char msg[1024];
709 sprintf( msg, "Error: (handle_request_messages): voltage %g is too high. Clamping to %g.", value, me->max_voltage);
711 value = me->max_voltage;
712 }
713 me->o_channel[chan_num] = value;
714
715 // Send the new value to the D/A board
716#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
717 if (me->NI_device_number != -1) {
718 AO_VWrite(me->NI_device_number, (short)(chan_num), value);
719 }
720#endif
721 }
722
723 return 0;
724}
725
726
727/* static */
729{
731 if( me->report_num_channels( ) == false )
732 {
733 fprintf( stderr, "Error: failed sending active channels to client.\n" );
734 }
735 return 0;
736}
737
738
739bool vrpn_Analog_Output_Server_NI::report_num_channels( vrpn_uint32 class_of_service )
740{
741 char msgbuf[ sizeof( vrpn_int32) ];
742 vrpn_int32 len = sizeof( vrpn_int32 );;
743
746 if( d_connection &&
748 d_sender_id, msgbuf, class_of_service ) )
749 {
750 fprintf(stderr, "vrpn_Analog_Output_Server_NI (report_num_channels): cannot write message: tossing\n");
751 return false;
752 }
753 return true;
754}
755
756
758encode_num_channels_to( char* buf, vrpn_int32 num )
759{
760 // Message includes: int32 number of active channels
761 int buflen = sizeof(vrpn_int32);
762
763 vrpn_buffer(&buf, &buflen, num);
764 return sizeof(vrpn_int32);
765}
766
767// This handles error reporting
768#ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
769void vrpn_National_Instruments_Server::reportError(int32 errnumber, vrpn_bool exitProgram)
770{
771 char errBuff[2048]={'\0'};
772
773 if( DAQmxFailed(errnumber) )
774 {
775 DAQmxGetExtendedErrorInfo(errBuff,2048);
776 printf("DAQmx Error: %s\n",errBuff);
777 if (exitProgram==vrpn_true) {
778 printf("Exiting...\n") ;
779 throw(errnumber) ; // this will quit, cause the destructor to be called
780 } else {
781 printf("Sleeping...\n") ;
782 vrpn_SleepMsecs(1000.0*1) ; // so at least the log will slow down so someone can see the error
783 }
784 }
785} // reportError
786#endif
virtual vrpn_int32 encode_num_channels_to(char *buf, vrpn_int32 num)
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 ...
virtual bool report_num_channels(vrpn_uint32 class_of_service=vrpn_CONNECTION_RELIABLE)
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...
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...
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
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....
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)
vrpn_int32 report_num_channels_m_id
vrpn_float64 o_channel[vrpn_CHANNEL_MAX]
vrpn_int32 request_channels_m_id
struct timeval o_timestamp
vrpn_Analog_Output(const char *name, vrpn_Connection *c=NULL)
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Definition vrpn_Analog.h:38
vrpn_Analog(const char *name, vrpn_Connection *c=NULL)
Definition vrpn_Analog.C:14
vrpn_int32 num_channel
Definition vrpn_Analog.h:40
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
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.
vrpn_Connection * d_connection
Connection that this object talks to.
vrpn_int32 d_sender_id
Sender ID registered with the connection.
void server_mainloop(void)
Handles functions that all servers should provide in their mainloop() (ping/pong, for example) Should...
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.
Generic connection class not specific to the transport mechanism.
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...
void reportError(int32 errnumber, vrpn_bool exitProgram=vrpn_false)
int setNumOutChannels(int sizeRequested)
Sets the size of the array; returns the size actually set. (May be clamped to vrpn_CHANNEL_MAX) This ...
virtual bool report_num_channels(vrpn_uint32 class_of_service=vrpn_CONNECTION_RELIABLE)
virtual void mainloop()
Called once through each main loop iteration to handle updates. Remote object mainloop() should call ...
int setNumInChannels(int sizeRequested)
Sets the size of the array; returns the size actually set. (May be clamped to vrpn_CHANNEL_MAX) This ...
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...
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 ...
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)
virtual vrpn_int32 encode_num_channels_to(char *buf, vrpn_int32 num)
This structure is what is passed to a vrpn_Connection message callback.
const char * buffer
struct timeval msg_time
#define vrpn_CHANNEL_MAX
Definition vrpn_Analog.h:16
All types of client/server/peer objects in VRPN should be derived from the vrpn_BaseClass type descri...
@ vrpn_TEXT_WARNING
@ vrpn_TEXT_ERROR
#define VRPN_CALLBACK
#define vrpn_NI_INPUT_MODE_REF_SINGLE_ENDED
#define vrpn_NI_INPUT_MODE_DIFFERENTIAL
#define vrpn_NI_INPUT_MODE_NON_REF_SINGLE_ENDED
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.
double vrpn_TimevalDurationSeconds(struct timeval endT, struct timeval startT)
Return the number of seconds between startT and endT as a floating-point value.
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.
void vrpn_SleepMsecs(double dMilliSecs)
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99