8#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
9#include "server_src/NIUtil.cpp"
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) :
21#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
22 d_analog_task_handle(0),
23 d_analog_out_task_handle(0),
28 d_in_min_delay(minInputReportDelaySecs),
29 d_out_min_voltage(minOutVoltage),
30 d_out_max_voltage(maxOutVoltage)
47#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
55 terminalConfig = DAQmx_Val_Diff;
58 terminalConfig = DAQmx_Val_RSE;
61 terminalConfig = DAQmx_Val_NRSE;
64 fprintf(stderr,
"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Invalid inputMode (%d)\n", inputMode);
71 double min_val = 0.0, max_val = inputRange;
81 if (numInChannels > 0) {
82 sprintf(portName,
"%s/ai0:%d", boardName, numInChannels-1);
85 error = DAQmxCreateAIVoltageChan(
94 fprintf(stderr,
"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create input voltage channel\n");
99 fprintf(stderr,
"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create input voltage task\n");
109 if (numOutChannels > 0) {
110 sprintf(portName,
"%s/ao0:%d", boardName, numOutChannels-1);
113 error = DAQmxCreateAOVoltageChan(
117 , minOutVoltage, maxOutVoltage
118 , DAQmx_Val_Volts,
""
121 fprintf(stderr,
"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create output voltage channel\n");
130 fprintf(stderr,
"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Cannot create or start output voltage task\n");
137 float64 minval = 0.0;
138 if (minval < minOutVoltage) { minval = minOutVoltage; }
144 fprintf(stderr,
"vrpn_National_Instruments_Server::vrpn_National_Instruments_Server(): Could not set values\n");
149#elif defined(VRPN_USE_NATIONAL_INSTRUMENTS)
151 short update_mode = 0;
152 short ref_source = 0;
153 double ref_voltage = 10.0;
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);
164 int ret = AI_Clear(d_device_number);
166 fprintf(stderr,
"vrpn_National_Instruments_Server: Cannot clear analog input (error %d)\n", ret);
171 int ret = AI_Configure(d_device_number, i, inputMode, inputRange,
d_in_polarity, driveAIS);
173 fprintf(stderr,
"vrpn_National_Instruments_Server: Cannot configure input channel %d (error %d)\n", i, ret);
182 int ret = AO_Configure(d_device_number, i,
d_out_polarity, ref_source, ref_voltage, update_mode);
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",
193 fprintf(stderr,
"vrpn_National_Instruments_Server: Cannot set output channel %d to %lg\n", i,
d_out_min_voltage);
199 fprintf(stderr,
"vrpn_National_Instruments_Server: Support for NI not compiled in, edit vrpn_Configure.h and recompile VRPN\n");
201 const char *unused = boardName;
203 inputMode = inputMode + 1;
204 inputRange = inputRange + 1;
205 driveAIS = !driveAIS;
210 fprintf(stderr,
"vrpn_National_Instruments_Server: Can't get connection!\n");
216 fprintf(stderr,
"vrpn_Analog_Output_Server_NI: can't register change channel request handler\n");
223 fprintf(stderr,
"vrpn_Analog_Output_Server_NI: can't register change channels request handler\n");
231 fprintf( stderr,
"vrpn_Analog_Output_Server_NI: can't register new connection handler\n");
243#ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
279#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
284 int32 channelsRead = 0;
298 for (i = 0; i < channelsRead; i++) {
303#elif defined(VRPN_USE_NATIONAL_INSTRUMENTS)
308 int ret = AI_Read(d_device_number, i,
d_in_gain, &value);
328 if (sizeRequested < 0) sizeRequested = 0;
336 if (sizeRequested < 0) sizeRequested = 0;
347 const char* bufptr = p.
buffer;
362 sprintf( msg,
"Error: (handle_request_message): channel %d is not active. Squelching.", chan_num );
369 sprintf( msg,
"Error: (handle_request_message): voltage %g is too low. Clamping to %g.", value, me->
d_out_min_voltage);
375 sprintf( msg,
"Error: (handle_request_message): voltage %g is too high. Clamping to %g.", value, me->
d_out_max_voltage);
382#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
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);
400 const char* bufptr = p.
buffer;
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 );
421 sprintf( msg,
"Error: (handle_request_channels_message): invalid channel %d. Squelching.", num );
425 for (chan_num = 0; chan_num < num; chan_num++) {
431 sprintf( msg,
"Error: (handle_request_messages): voltage %g is too low. Clamping to %g.", value, me->
d_out_min_voltage);
437 sprintf( msg,
"Error: (handle_request_messages): voltage %g is too high. Clamping to %g.", value, me->
d_out_max_voltage);
444#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
445 if (me->d_device_number != -1) {
446 AO_VWrite(me->d_device_number, (
short)(chan_num), value);
451#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
461#if defined(VRPN_USE_NATIONAL_INSTRUMENTS_MX)
472 DAQmx_Val_GroupByChannel, outbuffer, NULL, NULL);
493 fprintf( stderr,
"Error: failed sending active channels to client.\n" );
500 char msgbuf[
sizeof( vrpn_int32) ];
501 vrpn_int32 len =
sizeof( vrpn_int32 );;
509 fprintf(stderr,
"vrpn_Analog_Output_Server_NI (report_num_channels): cannot write message: tossing\n");
519 int buflen =
sizeof(vrpn_int32);
522 return sizeof(vrpn_int32);
526 const char *boardName,
527 vrpn_int16 numChannels,
bool bipolar,
528 double minVoltage,
double maxVoltage) :
530 NI_device_number(-1),
531 NI_num_channels(numChannels),
532 min_voltage(minVoltage),
533 max_voltage(maxVoltage)
535#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
537 short update_mode = 0;
538 short ref_source = 0;
539 double ref_voltage = 0.0;
552 fprintf(stderr,
"vrpn_Analog_Output_Server_NI: Error opening the D/A board %s\n", boardName);
570 fprintf(stderr,
"vrpn_Analog_Output_Server_NI: Can't get connection!\n");
576 fprintf(stderr,
"vrpn_Analog_Output_Server_NI: can't register change channel request handler\n");
583 fprintf(stderr,
"vrpn_Analog_Output_Server_NI: can't register change channels request handler\n");
591 fprintf( stderr,
"vrpn_Analog_Output_Server_NI: can't register new connection handler\n");
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;
613 if (sizeRequested < 0) sizeRequested = 0;
625 const char* bufptr = p.
buffer;
640 sprintf( msg,
"Error: (handle_request_message): channel %d is not active. Squelching.", chan_num );
647 sprintf( msg,
"Error: (handle_request_message): voltage %g is too low. Clamping to %g.", value, me->
min_voltage);
653 sprintf( msg,
"Error: (handle_request_message): voltage %g is too high. Clamping to %g.", value, me->
max_voltage);
660#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
672 const char* bufptr = p.
buffer;
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 );
693 sprintf( msg,
"Error: (handle_request_channels_message): invalid channel %d. Squelching.", num );
697 for (chan_num = 0; chan_num < num; chan_num++) {
703 sprintf( msg,
"Error: (handle_request_messages): voltage %g is too low. Clamping to %g.", value, me->
min_voltage);
709 sprintf( msg,
"Error: (handle_request_messages): voltage %g is too high. Clamping to %g.", value, me->
max_voltage);
716#ifdef VRPN_USE_NATIONAL_INSTRUMENTS
733 fprintf( stderr,
"Error: failed sending active channels to client.\n" );
741 char msgbuf[
sizeof( vrpn_int32) ];
742 vrpn_int32 len =
sizeof( vrpn_int32 );;
750 fprintf(stderr,
"vrpn_Analog_Output_Server_NI (report_num_channels): cannot write message: tossing\n");
761 int buflen =
sizeof(vrpn_int32);
764 return sizeof(vrpn_int32);
768#ifdef VRPN_USE_NATIONAL_INSTRUMENTS_MX
771 char errBuff[2048]={
'\0'};
773 if( DAQmxFailed(errnumber) )
775 DAQmxGetExtendedErrorInfo(errBuff,2048);
776 printf(
"DAQmx Error: %s\n",errBuff);
777 if (exitProgram==vrpn_true) {
778 printf(
"Exiting...\n") ;
781 printf(
"Sleeping...\n") ;
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)
virtual ~vrpn_Analog_Output_Server_NI(void)
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 got_connection_m_id
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_float64 channel[vrpn_CHANNEL_MAX]
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 ...
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.
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...
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)
virtual ~vrpn_National_Instruments_Server()
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)
TaskHandle d_analog_task_handle
TaskHandle d_analog_out_task_handle
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...
struct timeval d_last_report_time
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.
All types of client/server/peer objects in VRPN should be derived from the vrpn_BaseClass type descri...
#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