691 lines
22 KiB
C++
691 lines
22 KiB
C++
/********************************************************************\
|
|
|
|
Name: uWave.cxx
|
|
Created by: Zaher Salman 05/03/2021
|
|
|
|
Contents: Device driver for the RPi uWave controller.
|
|
TCP/IP calls sent to the RPi.
|
|
|
|
TCPIP: IEEE-448
|
|
termination: \n "new line"
|
|
|
|
\********************************************************************/
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstdarg>
|
|
#include <cstring>
|
|
#include <cmath>
|
|
|
|
#include "midas.h"
|
|
#include "mfe.h"
|
|
#include "msystem.h"
|
|
|
|
#include "uWave.h"
|
|
|
|
//----- globals -----------------------------------------------------
|
|
|
|
#define UWAVE_MAX_ERROR 10 //!< maximum number of error messages
|
|
|
|
//! timeout in (ms) for the communication between pc and uWave
|
|
#define UWAVE_TIME_OUT 20000
|
|
#define UWAVE_TIME_OUT_SLOW 100000
|
|
|
|
//! timeout in (sec) between logout terminal server an reconnection trial
|
|
#define UWAVE_RECONNECTION_TIMEOUT 5
|
|
//! maximum number of readback failures before a reconnect will take place
|
|
#define UWAVE_MAX_READBACK_FAILURE 5
|
|
//! maximum number of reconnections before bailing off
|
|
#define UWAVE_MAX_RECONNECTION_FAILURE 5
|
|
|
|
//--------- to handle error messages -------------------------------
|
|
|
|
#define UWAVE_SUCCESS 1
|
|
#define UWAVE_STANDBY 0 //!< uWave standby tag
|
|
#define UWAVE_CMD_ERROR -3 //!< invalid command error
|
|
#define UWAVE_INIT_ERROR -2 //!< initialize error tag
|
|
#define UWAVE_READ_ERROR -1 //!< read error tag
|
|
|
|
#define UWAVE_DELTA_TIME_ERROR 3600 //!< reset error counter after _DELTA_TIME_ERROR seconds
|
|
|
|
//---------- channel definition tags --------------------------------
|
|
#define UWAVE_IN_PH1_RB 0
|
|
#define UWAVE_IN_PH2_RB 1
|
|
#define UWAVE_IN_AMPL_RB 2
|
|
#define UWAVE_IN_FREQ_RB 3
|
|
#define UWAVE_IN_ONOFF_RB 4
|
|
|
|
#define UWAVE_OUT_PH1 0
|
|
#define UWAVE_OUT_PH2 1
|
|
#define UWAVE_OUT_AMPL 2
|
|
#define UWAVE_OUT_FREQ 3
|
|
#define UWAVE_OUT_ONOFF 4
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
/*!
|
|
* <p> Generally it stores internal informations within the DD. In this
|
|
* case these are the names for the ODB describing the <b>in-channels</b>.
|
|
*/
|
|
typedef struct {
|
|
INT detailed_msg; //!< flag 0: no add. msg, 1: some add. msg, 2: debug
|
|
char name[5][NAME_LENGTH]; //!< input channel names
|
|
} UWAVE_IN_SETTINGS;
|
|
|
|
/*!
|
|
* <p> Generally it stores internal informations within the DD. In this
|
|
* case this are the names for the ODB describing the <b>out-channels</b>.
|
|
*/
|
|
typedef struct {
|
|
char name[5][NAME_LENGTH]; //!< output channel names
|
|
} UWAVE_OUT_SETTINGS;
|
|
|
|
//! Initializing string for the UWAVE_IN_SETTINGS structure.
|
|
const char *uWave_in_settings_str =
|
|
"Detailed Messages = FLOAT : 0\n\
|
|
Input = STRING[5]:\n\
|
|
[32] Phase 1 (deg)\n\
|
|
[32] Phase 2 (deg)\n\
|
|
[32] Amplitude (dBm)\n\
|
|
[32] Frequency (GHz)\n\
|
|
[32] On/Off (1/0)\n\
|
|
";
|
|
|
|
//! initializing string for the UWAVE_OUT_SETTINGS structure.
|
|
const char *uWave_out_settings_str =
|
|
"Output = STRING[5] :\n\
|
|
[32] Phase 1 (deg)\n\
|
|
[32] Phase 2 (deg)\n\
|
|
[32] Amplitude (dBm)\n\
|
|
[32] Frequency (GHz)\n\
|
|
[32] On/Off (1/0)\n\
|
|
";
|
|
|
|
/*!
|
|
* <p> This structure contains private variables for the device driver.
|
|
*/
|
|
typedef struct {
|
|
UWAVE_IN_SETTINGS uWave_in_settings; //!< internal DD settings for the <b>in-channels</b>
|
|
UWAVE_OUT_SETTINGS uWave_out_settings; //!< internal DD settings for the <b>out-channels</b>
|
|
HNDLE hkey; //!< ODB key for bus driver info
|
|
INT (*bd)(INT cmd, ...); //!< bus driver entry function
|
|
void *bd_info; //!< private info of bus driver
|
|
INT bd_connected; //!< flag showing if bus driver is connected
|
|
INT first_bd_error; //!< flag showing if the bus driver error message is already given
|
|
INT errorcount; //!< error coutner
|
|
INT startup_error; //!< startup error tag; if set, the get and bh_set and bh_get routines wont do anything
|
|
DWORD lasterrtime; //!< timer for error handling
|
|
INT readback_failure; //!< counts the number of readback failures
|
|
DWORD last_reconnect; //!< timer for bus driver reconnect error handling
|
|
INT reconnection_failures; //!< how often reconnection failed
|
|
INT ph1; //!< Phase1 in degrees
|
|
INT ph2; //!< Phase2 in degrees
|
|
INT ampl; //!< Amplitude in dBm
|
|
INT freq; //!< Frequency in GHz
|
|
INT onoff; //!< On/Off state (1/0)
|
|
INT ph1_sp; //!< keep Phase1 in degrees
|
|
INT ph2_sp; //!< keep Phase2 in degrees
|
|
INT ampl_sp; //!< keep Amplitude in dBm
|
|
INT freq_sp; //!< keep Frequency in GHz
|
|
INT onoff_sp; //!< keep On/Off state (1/0)
|
|
} UWAVE_INFO;
|
|
|
|
UWAVE_INFO *uWave_info; //!< global info structure since port can only be initialized once.
|
|
|
|
typedef INT(func_t) (INT cmd, ...);
|
|
|
|
/*---- device driver routines ---------------------------------------------------------*/
|
|
/*!
|
|
* <p>Initializes the uWave device driver, i.e. generates all the necessary
|
|
* structures in the ODB if necessary, initializes the bus driver and the uWave.</p>
|
|
* <p><b>Return:</b>
|
|
* - FE_SUCCESS if everything went smooth
|
|
* - FE_ERR_ODB otherwise
|
|
* \param hKey is the device driver handle given from the class driver
|
|
* \param pinfo is needed to store the internal info structure
|
|
* \param channels is the number of channels of the device (from the class driver)
|
|
* \param bd is a pointer to the bus driver
|
|
*/
|
|
INT uWave_in_init(HNDLE hKey, UWAVE_INFO **pinfo, INT channels, func_t *bd)
|
|
{
|
|
INT status, size;
|
|
HNDLE hDB, hKeyLocal;
|
|
char cmd[1024], rcv[128];
|
|
float fval;
|
|
|
|
cm_get_experiment_database(&hDB, NULL);
|
|
|
|
// allocate info structure
|
|
UWAVE_INFO *info = (UWAVE_INFO*)calloc(1, sizeof(UWAVE_INFO));
|
|
uWave_info = info;
|
|
*pinfo = info;
|
|
|
|
// create uWave settings record
|
|
status = db_create_record(hDB, hKey, "DD/uWave", uWave_in_settings_str);
|
|
if (status != DB_SUCCESS)
|
|
return FE_ERR_ODB;
|
|
|
|
// copy DD entries into the info structure
|
|
db_find_key(hDB, hKey, "DD/uWave", &hKeyLocal);
|
|
db_open_record(hDB, hKeyLocal, &info->uWave_in_settings, sizeof(info->uWave_in_settings), MODE_READ, NULL, NULL);
|
|
|
|
// initialize driver
|
|
info->hkey = hKey;
|
|
info->bd = bd;
|
|
info->errorcount = 0;
|
|
info->lasterrtime = ss_time();
|
|
info->startup_error = 0;
|
|
info->readback_failure = 0;
|
|
info->last_reconnect = ss_time();
|
|
info->reconnection_failures = 0;
|
|
|
|
if (!bd)
|
|
return FE_ERR_ODB;
|
|
|
|
// initialize bus driver
|
|
status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
|
|
if (status != SUCCESS) {
|
|
info->startup_error = 1;
|
|
info->bd_connected = FALSE;
|
|
cm_msg(MINFO, "uWave_in_init", "Bus driver failed to initialize! status=%d",status);
|
|
return status;
|
|
}
|
|
cm_msg(MINFO, "uWave_in_init", "Bus driver initialized!");
|
|
info->bd_connected = TRUE;
|
|
|
|
// read back from ODB
|
|
status = db_find_key(hDB, 0, "/Equipment/uWave/Variables/Output", &hKeyLocal);
|
|
if (status != DB_SUCCESS) {
|
|
cm_msg(MERROR, "uWave_in_init", "uWave_in_init: couldn't obtain readback ...");
|
|
cm_yield(0);
|
|
info->startup_error = UWAVE_INIT_ERROR;
|
|
return FE_SUCCESS;
|
|
}
|
|
// read back from ODB Phase 1
|
|
size = sizeof(fval);
|
|
db_get_data_index(hDB, hKeyLocal, &fval, &size, UWAVE_OUT_PH1, TID_FLOAT);
|
|
info->ph1 = fval;
|
|
|
|
// read back from ODB Phase 2
|
|
size = sizeof(fval);
|
|
db_get_data_index(hDB, hKeyLocal, &fval, &size, UWAVE_OUT_PH2, TID_FLOAT);
|
|
info->ph2 = fval;
|
|
|
|
// read back from ODB Amplitude
|
|
size = sizeof(fval);
|
|
db_get_data_index(hDB, hKeyLocal, &fval, &size, UWAVE_OUT_AMPL, TID_FLOAT);
|
|
info->ampl = fval;
|
|
|
|
// read back from ODB Frequency
|
|
size = sizeof(fval);
|
|
db_get_data_index(hDB, hKeyLocal, &fval, &size, UWAVE_OUT_FREQ, TID_FLOAT);
|
|
info->freq = fval;
|
|
|
|
if (info->uWave_in_settings.detailed_msg == 2) {
|
|
cm_msg(MINFO, "uWave_in_init", "uWave_in_init: phase 1 = %f", info->ph1);
|
|
cm_yield(0);
|
|
}
|
|
|
|
// read back from ODB On/Off
|
|
size = sizeof(fval);
|
|
db_get_data_index(hDB, hKeyLocal, &fval, &size, UWAVE_OUT_ONOFF, TID_FLOAT);
|
|
info->onoff = (int)fval;
|
|
|
|
// How to check that the device is responding
|
|
strcpy(cmd, "OUTP?\n");
|
|
BD_PUTS(cmd);
|
|
status = BD_GETS(rcv, sizeof(rcv), "\n", UWAVE_TIME_OUT);
|
|
if (status) {
|
|
sscanf(rcv, "%f", &fval);
|
|
cm_msg(MINFO, "uWave_in_init", "uWave initialized ...");
|
|
cm_yield(0);
|
|
} else {
|
|
info->startup_error = UWAVE_INIT_ERROR;
|
|
cm_msg(MINFO, "uWave_in_init", "uWave driver failed to initialize ...");
|
|
cm_yield(0);
|
|
}
|
|
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/*!
|
|
* <p>Initializes the uWave device driver, i.e. generates all the necessary
|
|
* structures in the ODB if necessary, <b>no</b> initialization of the bus driver etc.
|
|
* is done, since this is part of uWave_in_init.</p>
|
|
* <p><b>Return:</b>
|
|
* - FE_SUCCESS if everything went smooth
|
|
* - FE_ERR_ODB otherwise
|
|
* \param hKey is the device driver handle given from the class driver
|
|
* \param pinfo is needed to store the internal info structure
|
|
* \param channels is the number of channels of the device (from the class driver)
|
|
* \param bd is a pointer to the bus driver
|
|
*/
|
|
INT uWave_out_init(HNDLE hKey, UWAVE_INFO **pinfo, INT channels, func_t *bd)
|
|
{
|
|
INT status;
|
|
HNDLE hDB, hKeyLocal;
|
|
|
|
cm_get_experiment_database(&hDB, NULL);
|
|
|
|
UWAVE_INFO *info = uWave_info;
|
|
*pinfo = info;
|
|
|
|
/* create uWave settings record */
|
|
status = db_create_record(hDB, hKey, "DD", uWave_out_settings_str);
|
|
if (status != DB_SUCCESS)
|
|
return FE_ERR_ODB;
|
|
|
|
// copy DD entries into the info structure
|
|
db_find_key(hDB, hKey, "DD", &hKeyLocal);
|
|
db_open_record(hDB, hKeyLocal, &info->uWave_out_settings,
|
|
sizeof(info->uWave_out_settings), MODE_READ, NULL, NULL);
|
|
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/*!
|
|
* <p>terminates the bus driver and free's the memory allocated for the info structure
|
|
* UWAVE_INFO.</p>
|
|
* <p><b>Return:</b> FE_SUCCESS</p>
|
|
* \param info is a pointer to the DD specific info structure
|
|
*/
|
|
INT uWave_exit(UWAVE_INFO *info)
|
|
{
|
|
if (info->startup_error)
|
|
return FE_SUCCESS;
|
|
|
|
// call EXIT function of bus driver, usually closes device
|
|
info->bd(CMD_EXIT, info->bd_info);
|
|
|
|
free(info);
|
|
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/*!
|
|
* <p>set a value of the uWave.</p>
|
|
* <p><b>Return:</b> FE_SUCCESS</p>
|
|
* \param info is a pointer to the DD specific info structure.
|
|
* \param channel is the channel number
|
|
* \param value to be set
|
|
*/
|
|
INT uWave_set(UWAVE_INFO *info, INT channel, float value)
|
|
{
|
|
char cmd[128];
|
|
|
|
// Debug message
|
|
// cm_msg(MINFO, "uWave_set", "uWave_set: %d, set cmd: %f", channel, value);
|
|
|
|
if (info->startup_error)
|
|
return FE_SUCCESS;
|
|
|
|
if (!info->bd_connected) {
|
|
if (info->first_bd_error) {
|
|
info->first_bd_error = 0;
|
|
cm_msg(MINFO, "uWave_set",
|
|
"uWave_set: set values not possible at the moment, since the bus driver is not available!");
|
|
}
|
|
ss_sleep(10);
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
// set command should go here
|
|
switch (channel) {
|
|
// Phase 1
|
|
case UWAVE_OUT_PH1: // set Phase 1 in degrees
|
|
sprintf(cmd, "PH1 %f\n",value);
|
|
if (info->uWave_in_settings.detailed_msg == 2) // debug only
|
|
cm_msg(MINFO, "uWave_set", "uWave_set: cmd: %s", cmd);
|
|
BD_PUTS(cmd);
|
|
info->ph1_sp = value;
|
|
return FE_SUCCESS;
|
|
break;
|
|
|
|
// Phase 2
|
|
case UWAVE_OUT_PH2: // set Phase 2 in degrees
|
|
sprintf(cmd, "PH2 %f\n",value);
|
|
if (info->uWave_in_settings.detailed_msg == 2) // debug only
|
|
cm_msg(MINFO, "uWave_set", "uWave_set: cmd: %s", cmd);
|
|
BD_PUTS(cmd);
|
|
info->ph2_sp = value;
|
|
return FE_SUCCESS;
|
|
break;
|
|
|
|
// Amplitude
|
|
case UWAVE_OUT_AMPL: // set Amplitude in dBm
|
|
sprintf(cmd, "AMPL %f\n",value);
|
|
if (info->uWave_in_settings.detailed_msg == 2) // debug only
|
|
cm_msg(MINFO, "uWave_set", "uWave_set: cmd: %s", cmd);
|
|
BD_PUTS(cmd);
|
|
info->ampl_sp = value;
|
|
return FE_SUCCESS;
|
|
break;
|
|
|
|
// Frequency
|
|
case UWAVE_OUT_FREQ: // set Frequency in GHz
|
|
sprintf(cmd, "FREQ %f\n",value);
|
|
if (info->uWave_in_settings.detailed_msg == 2) // debug only
|
|
cm_msg(MINFO, "uWave_set", "uWave_set: cmd: %s", cmd);
|
|
BD_PUTS(cmd);
|
|
info->freq_sp = value;
|
|
return FE_SUCCESS;
|
|
break;
|
|
|
|
// Toggle on/off
|
|
case UWAVE_OUT_ONOFF: // output on=1, off=0
|
|
sprintf(cmd, "OUTP %d\n",(int)value);
|
|
if (info->uWave_in_settings.detailed_msg == 2) // debug only
|
|
cm_msg(MINFO, "uWave_set", "uWave_set: cmd: %s", cmd);
|
|
BD_PUTS(cmd);
|
|
info->onoff_sp = (int)value;
|
|
return FE_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
return FE_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (info->uWave_in_settings.detailed_msg > 0)
|
|
cm_msg(MINFO, "uWave_set", "uWave_set: cmd: %s", cmd);
|
|
|
|
ss_sleep(100);
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/*!
|
|
* <p>get a value from the uWave.</p>
|
|
* <p><b>Return:</b> FE_SUCCESS</p>
|
|
* \param info is a pointer to the DD specific info structure.
|
|
* \param channel is the channel number
|
|
* \param pvalue read
|
|
*/
|
|
INT uWave_get(UWAVE_INFO *info, INT channel, float *pvalue)
|
|
{
|
|
int status;
|
|
int chan;
|
|
char cmd[128], rcv[128];
|
|
DWORD nowtime, difftime;
|
|
// float fval, fval1;
|
|
|
|
// error timeout facility
|
|
nowtime = ss_time();
|
|
difftime = nowtime - info->lasterrtime;
|
|
if ( difftime > UWAVE_DELTA_TIME_ERROR ) {
|
|
info->errorcount = 0;
|
|
info->lasterrtime = ss_time();
|
|
}
|
|
|
|
// check if there was a startup error
|
|
if ( info->startup_error ) {
|
|
*pvalue = (float) UWAVE_INIT_ERROR;
|
|
ss_sleep(10); // to keep CPU load low when Run active
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
// check if there where too many reconnection failures
|
|
if (info->reconnection_failures > UWAVE_MAX_RECONNECTION_FAILURE) {
|
|
*pvalue = (float) UWAVE_READ_ERROR;
|
|
if (info->reconnection_failures == UWAVE_MAX_RECONNECTION_FAILURE+1) {
|
|
cm_msg(MERROR, "uWave_get", "too many reconnection failures, bailing out :-(");
|
|
info->reconnection_failures++;
|
|
}
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
// if disconnected, try to reconnect after a timeout of a timeout
|
|
if (!info->bd_connected) {
|
|
if (ss_time()-info->last_reconnect > UWAVE_RECONNECTION_TIMEOUT) { // timeout expired
|
|
if (info->uWave_in_settings.detailed_msg > 0)
|
|
cm_msg(MINFO, "uWave_get", "uWave: reconnection trial ...");
|
|
status = info->bd(CMD_INIT, info->hkey, &info->bd_info);
|
|
if (status != FE_SUCCESS) {
|
|
info->reconnection_failures++;
|
|
*pvalue = (float) UWAVE_READ_ERROR;
|
|
if (info->uWave_in_settings.detailed_msg > 0)
|
|
cm_msg(MINFO, "uWave_get", "uWave: reconnection attempted failed");
|
|
return FE_ERR_HW;
|
|
} else {
|
|
info->bd_connected = 1; // bus driver is connected again
|
|
info->last_reconnect = ss_time();
|
|
info->reconnection_failures = 0;
|
|
info->first_bd_error = 1;
|
|
if (info->uWave_in_settings.detailed_msg > 0)
|
|
cm_msg(MINFO, "uWave_get", "uWave: successfully reconnected");
|
|
}
|
|
} else { // timeout still running
|
|
ss_sleep(10);
|
|
return FE_SUCCESS;
|
|
}
|
|
}
|
|
|
|
// set the read command
|
|
switch (channel) {
|
|
case UWAVE_IN_PH1_RB: // check what is Phase 1
|
|
sprintf(cmd, "PH1?\n");
|
|
break;
|
|
case UWAVE_IN_PH2_RB: // check what is Phase 2
|
|
sprintf(cmd, "PH2?\n");
|
|
break;
|
|
case UWAVE_IN_AMPL_RB: // check what is the Amplitude
|
|
sprintf(cmd, "AMPL?\n");
|
|
break;
|
|
case UWAVE_IN_FREQ_RB: // check what is the Frequency
|
|
sprintf(cmd, "FREQ?\n");
|
|
break;
|
|
case UWAVE_IN_ONOFF_RB: // check what is the trigger level
|
|
sprintf(cmd, "OUTP?\n");
|
|
break;
|
|
default:
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
// The above commands return relative channel, value
|
|
// these need to be processed.
|
|
|
|
// send the command and read the response
|
|
BD_PUTS(cmd);
|
|
status = BD_GETS(rcv, sizeof(rcv), "\n", UWAVE_TIME_OUT);
|
|
|
|
if (info->uWave_in_settings.detailed_msg == 2) {// debug only
|
|
cm_msg(MINFO, "uWave_get", "uWave_get: cmd:\"%s\", %d, %s, status=%d", cmd, channel, rcv, status);
|
|
cm_msg(MINFO, "uWave_get", "uWave_get: cmd: %s", cmd);
|
|
cm_msg(MINFO, "uWave_get", "uWave_get: rdb: %s", rcv);
|
|
}
|
|
|
|
// check for any error
|
|
if (!status) { // error occured
|
|
*pvalue = (float) UWAVE_READ_ERROR;
|
|
status = UWAVE_READ_ERROR;
|
|
} else { // no error -> decode data
|
|
status = UWAVE_SUCCESS;
|
|
|
|
// interpret the response
|
|
switch (channel) {
|
|
case UWAVE_IN_PH1_RB: // read Phase 1
|
|
sscanf(rcv, "%f", pvalue);
|
|
break;
|
|
case UWAVE_IN_PH2_RB: // read Phase 2
|
|
sscanf(rcv, "%f", pvalue);
|
|
break;
|
|
case UWAVE_IN_AMPL_RB: // read Amplitude
|
|
sscanf(rcv, "%f", pvalue);
|
|
break;
|
|
case UWAVE_IN_FREQ_RB: // read Frequency
|
|
sscanf(rcv, "%f", pvalue);
|
|
break;
|
|
case UWAVE_IN_ONOFF_RB: // read On/Off state
|
|
sscanf(rcv, "%f", pvalue);
|
|
break;
|
|
default:
|
|
return FE_SUCCESS;
|
|
}
|
|
}
|
|
|
|
if (status != UWAVE_SUCCESS) {
|
|
if ( info->errorcount < UWAVE_MAX_ERROR ) {
|
|
if (info->uWave_in_settings.detailed_msg > 0)
|
|
cm_msg(MERROR, "uWave_get", "uWave communication or command error. Status = %d", status);
|
|
info->errorcount++;
|
|
}
|
|
info->readback_failure++;
|
|
|
|
if (info->readback_failure == UWAVE_MAX_READBACK_FAILURE) {
|
|
info->readback_failure = 0;
|
|
// try to disconnect and reconnect the bus driver
|
|
if ((ss_time()-info->last_reconnect > UWAVE_RECONNECTION_TIMEOUT) && info->bd_connected) {
|
|
info->bd(CMD_EXIT, info->bd_info); // disconnect bus driver
|
|
if (info->uWave_in_settings.detailed_msg > 0)
|
|
cm_msg(MINFO, "uWave_get", "uWave: try to disconnect and reconnect the bus driver");
|
|
info->last_reconnect = ss_time();
|
|
info->bd_connected = 0;
|
|
}
|
|
}
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
ss_sleep(1000);
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/*!
|
|
* <p>at startup, after initialization of the DD, this routine allows to write
|
|
* default names of the in-channels into the ODB.</p>
|
|
* <p><b>Return:</b> FE_SUCCESS
|
|
* \param info is a pointer to the DD specific info structure
|
|
* \param channel of the name to be set
|
|
* \param name pointer to the ODB name
|
|
*/
|
|
INT uWave_in_get_label(UWAVE_INFO *info, INT channel, char *name)
|
|
{
|
|
strcpy(name, info->uWave_in_settings.name[channel]);
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------------*/
|
|
/*!
|
|
* <p>at startup, after initialization of the DD, this routine allows to write
|
|
* default names of the out-channels into the ODB.</p>
|
|
* <p><b>Return:</b> FE_SUCCESS
|
|
* \param info is a pointer to the DD specific info structure
|
|
* \param channel of the name to be set
|
|
* \param name pointer to the ODB name
|
|
*/
|
|
INT uWave_out_get_label(UWAVE_INFO *info, INT channel, char *name)
|
|
{
|
|
strcpy(name, info->uWave_out_settings.name[channel]);
|
|
return FE_SUCCESS;
|
|
}
|
|
|
|
/*---- device driver entry point ---------------------------------------------------*/
|
|
/*!
|
|
* <p>The device driver for the uWave is setup such that it can send TCP/IP commands
|
|
* to an RPi to control uWave properties.
|
|
*/
|
|
INT uWave_in(INT cmd, ...)
|
|
{
|
|
va_list argptr;
|
|
HNDLE hKey;
|
|
INT channel, status;
|
|
float *pvalue;
|
|
UWAVE_INFO *info;
|
|
char *name;
|
|
|
|
va_start(argptr, cmd);
|
|
status = FE_SUCCESS;
|
|
|
|
switch (cmd) {
|
|
case CMD_INIT:
|
|
{
|
|
hKey = va_arg(argptr, HNDLE);
|
|
UWAVE_INFO **pinfo = va_arg(argptr, UWAVE_INFO**);
|
|
channel = va_arg(argptr, INT);
|
|
va_arg(argptr, DWORD); // flags - currently not used
|
|
func_t *bd = va_arg(argptr, func_t*);
|
|
status = uWave_in_init(hKey, pinfo, channel, bd);
|
|
}
|
|
break;
|
|
|
|
case CMD_EXIT:
|
|
info = va_arg(argptr, UWAVE_INFO*);
|
|
status = uWave_exit(info);
|
|
break;
|
|
|
|
case CMD_GET:
|
|
info = va_arg(argptr, UWAVE_INFO*);
|
|
channel = va_arg(argptr, INT);
|
|
pvalue = va_arg(argptr, float*);
|
|
status = uWave_get(info, channel, pvalue);
|
|
break;
|
|
|
|
case CMD_GET_LABEL:
|
|
info = va_arg(argptr, UWAVE_INFO*);
|
|
channel = va_arg(argptr, INT);
|
|
name = va_arg(argptr, char *);
|
|
status = uWave_in_get_label(info, channel, name);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
va_end(argptr);
|
|
return status;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
INT uWave_out(INT cmd, ...)
|
|
{
|
|
va_list argptr;
|
|
HNDLE hKey;
|
|
INT channel, status;
|
|
float value;
|
|
UWAVE_INFO *info;
|
|
char *name;
|
|
|
|
va_start(argptr, cmd);
|
|
status = FE_SUCCESS;
|
|
|
|
switch (cmd) {
|
|
case CMD_INIT:
|
|
{
|
|
hKey = va_arg(argptr, HNDLE);
|
|
UWAVE_INFO **pinfo = va_arg(argptr, UWAVE_INFO**);
|
|
channel = va_arg(argptr, INT);
|
|
va_arg(argptr, DWORD); // flags - currently not used
|
|
func_t *bd = va_arg(argptr, func_t*);
|
|
status = uWave_out_init(hKey, pinfo, channel, bd);
|
|
}
|
|
break;
|
|
|
|
case CMD_SET:
|
|
info = va_arg(argptr, UWAVE_INFO*);
|
|
channel = va_arg(argptr, INT);
|
|
value = (float) va_arg(argptr, double);
|
|
status = uWave_set(info, channel, value);
|
|
break;
|
|
|
|
case CMD_GET_LABEL:
|
|
info = va_arg(argptr, UWAVE_INFO*);
|
|
channel = va_arg(argptr, INT);
|
|
name = va_arg(argptr, char *);
|
|
status = uWave_out_get_label(info, channel, name);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
va_end(argptr);
|
|
|
|
return status;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|