mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
Merge branch 'node-uldaq' of git.rwth-aachen.de:acs/public/villas/VILLASnode into node-uldaq
This commit is contained in:
commit
791b314121
19 changed files with 296 additions and 130 deletions
|
@ -62,6 +62,12 @@ else()
|
|||
add_compile_options(-Wall -Werror)
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND uname -m
|
||||
COMMAND tr -d '\n'
|
||||
OUTPUT_VARIABLE ARCH
|
||||
)
|
||||
|
||||
# Check OS
|
||||
check_include_file("sys/eventfd.h" HAS_EVENTFD)
|
||||
check_include_file("semaphore.h" HAS_SEMAPHORE)
|
||||
|
@ -75,7 +81,6 @@ endif()
|
|||
# Check packages
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(Libwebsockets 2.3.0 REQUIRED)
|
||||
find_package(OpenSSL 1.0.0 REQUIRED)
|
||||
find_package(CURL 7.29 REQUIRED)
|
||||
find_package(Mosquitto)
|
||||
|
@ -99,7 +104,8 @@ pkg_check_modules(LIBCONFIG IMPORTED_TARGET libconfig>=1.4.9)
|
|||
pkg_check_modules(RABBITMQ_C IMPORTED_TARGET librabbitmq>=0.8.0)
|
||||
pkg_check_modules(COMEDILIB IMPORTED_TARGET comedilib>=0.11.0)
|
||||
pkg_check_modules(LIBZMQ IMPORTED_TARGET libzmq>=2.2.0)
|
||||
pkg_check_modules(ULDAQ IMPORTED_TARGET libuldaq>=1.0.0)
|
||||
pkg_check_modules(LIBULDAQ IMPORTED_TARGET libuldaq>=1.0.0)
|
||||
pkg_check_modules(LIBWEBSOCKETS IMPORTED_TARGET libwebsockets>=2.3.0)
|
||||
pkg_check_modules(NANOMSG IMPORTED_TARGET nanomsg)
|
||||
if(NOT NANOMSG_FOUND)
|
||||
pkg_check_modules(NANOMSG IMPORTED_TARGET libnanomsg>=1.0.0)
|
||||
|
|
|
@ -10,7 +10,7 @@ nodes = {
|
|||
range = "bipolar-10",
|
||||
input_mode = "single-ended"
|
||||
signals = (
|
||||
{ name = "ch0", type = "float", channel = 0 },
|
||||
{ name = "ch0", type = "float", channel = 0 }
|
||||
)
|
||||
|
||||
sample_rate = 5000,
|
||||
|
@ -37,7 +37,7 @@ nodes = {
|
|||
},
|
||||
out = {
|
||||
vectorize = 100
|
||||
address = "127.0.0.1:13000"
|
||||
address = "192.168.104.10:13000"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ enum log_facilities {
|
|||
LOG_WEBSOCKET = (1L << 29),
|
||||
LOG_OPAL = (1L << 30),
|
||||
LOG_COMEDI = (1L << 31),
|
||||
LOG_IB = (1L << 32),
|
||||
LOG_IB = (1LL << 32),
|
||||
|
||||
/* Classes */
|
||||
LOG_NODES = LOG_NODE | LOG_SOCKET | LOG_FILE | LOG_FPGA | LOG_NGSI | LOG_WEBSOCKET | LOG_OPAL | LOG_IB,
|
||||
|
@ -148,7 +148,7 @@ void log_print(struct log *l, const char *lvl, const char *fmt, ...)
|
|||
void log_vprint(struct log *l, const char *lvl, const char *fmt, va_list va);
|
||||
|
||||
/** Printf alike debug message with level. */
|
||||
void debug(long lvl, const char *fmt, ...)
|
||||
void debug(long long lvl, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
/** Printf alike info message. */
|
||||
|
|
|
@ -45,8 +45,10 @@ extern "C" {
|
|||
#define ULDAQ_MAX_RANGE_COUNT 8
|
||||
|
||||
struct uldaq {
|
||||
const char *device_id;
|
||||
|
||||
DaqDeviceHandle device_handle;
|
||||
DaqDeviceDescriptor device_descriptor;
|
||||
DaqDeviceDescriptor *device_descriptor;
|
||||
DaqDeviceInterface device_interface_type;
|
||||
|
||||
uint64_t sequence;
|
||||
|
@ -55,8 +57,9 @@ struct uldaq {
|
|||
struct {
|
||||
double sample_rate;
|
||||
double *buffer;
|
||||
unsigned buffer_len;
|
||||
unsigned channel_count;
|
||||
size_t buffer_len;
|
||||
size_t buffer_pos;
|
||||
size_t channel_count;
|
||||
|
||||
ScanOption scan_options;
|
||||
AInScanFlag flags;
|
||||
|
|
|
@ -34,6 +34,7 @@ set(LIBRARIES
|
|||
PkgConfig::JANSSON
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
m
|
||||
)
|
||||
|
||||
set(LIB_SRC
|
||||
|
@ -72,9 +73,13 @@ set(LIB_SRC
|
|||
table.c
|
||||
bitset.c
|
||||
signal.c
|
||||
tsc.c
|
||||
)
|
||||
|
||||
|
||||
if(ARCH STREQUAL "x86_64")
|
||||
list(APPEND LIB_SRC tsc.c)
|
||||
endif()
|
||||
|
||||
if(IBVERBS_FOUND AND RDMACM_FOUND)
|
||||
list(APPEND LIB_SRC memory/ib.c)
|
||||
endif()
|
||||
|
@ -113,7 +118,7 @@ if(WITH_WEB)
|
|||
)
|
||||
|
||||
list(APPEND INCLUDE_DIRS ${LIBWEBSOCKETS_INCLUDE_DIRS})
|
||||
list(APPEND LIBRARIES websockets_shared)
|
||||
list(APPEND LIBRARIES PkgConfig::LIBWEBSOCKETS)
|
||||
endif()
|
||||
|
||||
if(WITH_API AND WITH_WEB)
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
int kernel_get_cacheline_size()
|
||||
{
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && defined(__x86_64__)
|
||||
return sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
|
||||
#else
|
||||
return 64; /** @todo fixme */
|
||||
|
|
|
@ -216,7 +216,7 @@ int log_set_facility_expression(struct log *l, const char *expression)
|
|||
{
|
||||
bool negate;
|
||||
char *copy, *token;
|
||||
long mask = 0, facilities = 0;
|
||||
long long mask = 0, facilities = 0;
|
||||
|
||||
copy = strdup(expression);
|
||||
token = strtok(copy, ",");
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <villas/utils.h>
|
||||
#include <villas/log.h>
|
||||
|
||||
void debug(long class, const char *fmt, ...)
|
||||
void debug(long long class, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ int memory_init(int hugepages)
|
|||
{
|
||||
info("Initialize memory sub-system: #hugepages=%d", hugepages);
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && defined(__x86_64__)
|
||||
int pagecnt, pagesz, ret;
|
||||
struct rlimit l;
|
||||
|
||||
|
@ -85,7 +85,7 @@ int memory_init(int hugepages)
|
|||
if (l.rlim_cur < lock) {
|
||||
if (l.rlim_max < lock) {
|
||||
if (getuid() != 0) {
|
||||
warn("Failed to in increase ressource limit of locked memory from %zu to %zu bytes", l.rlim_cur, lock);
|
||||
warn("Failed to in increase ressource limit of locked memory from %lu to %zu bytes", l.rlim_cur, lock);
|
||||
warn("Please re-run as super-user or raise manually via:");
|
||||
warn(" $ ulimit -Hl %zu", lock);
|
||||
|
||||
|
|
|
@ -47,10 +47,10 @@ if(HAS_EVENTFD)
|
|||
endif()
|
||||
|
||||
# Enable Universal Library for Linux DAQ devices (libuldaq)
|
||||
if(ULDAQ_FOUND)
|
||||
if(LIBULDAQ_FOUND)
|
||||
list(APPEND NODE_SRC uldaq.c)
|
||||
list(APPEND INCLUDE_DIRS ${ULDAQ_INCLUDE_DIRS})
|
||||
list(APPEND LIBRARIES uldaq)
|
||||
list(APPEND LIBRARIES PkgConfig::LIBULDAQ)
|
||||
endif()
|
||||
|
||||
# Enable shared memory node-type
|
||||
|
@ -66,7 +66,7 @@ endif()
|
|||
if(LIBIEC61850_FOUND)
|
||||
list(APPEND NODE_SRC iec61850_sv.c iec61850.c)
|
||||
list(APPEND INCLUDE_DIRS ${LIBIEC61850_INCLUDE_DIRS})
|
||||
list(APPEND LIBRARIES ${LIBIEC61850_LIBRARIES} PkgConfig::LIBIEC61850)
|
||||
list(APPEND LIBRARIES PkgConfig::LIBIEC61850)
|
||||
endif()
|
||||
|
||||
# Enable OPAL-RT Asynchronous Process support (will result in 32bit binary!!!)
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
#include <villas/nodes/uldaq.h>
|
||||
#include <villas/memory.h>
|
||||
|
||||
static unsigned num_devs = ULDAQ_MAX_DEV_COUNT;
|
||||
static DaqDeviceDescriptor descriptors[ULDAQ_MAX_DEV_COUNT];
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
AiInputMode mode;
|
||||
|
@ -97,34 +100,6 @@ static const struct {
|
|||
{ "unipolar-0.005", UNIPT005VOLTS, 0.0, +0.005 }
|
||||
};
|
||||
|
||||
__attribute__((unused))
|
||||
static UlError uldag_range_info(DaqDeviceHandle device_handle, AiInputMode input_mode, int *number_of_ranges, Range* ranges)
|
||||
{
|
||||
UlError err;
|
||||
long long num_ranges = 0;
|
||||
long long range;
|
||||
|
||||
err = input_mode == AI_SINGLE_ENDED
|
||||
? ulAIGetInfo(device_handle, AI_INFO_NUM_SE_RANGES, 0, &num_ranges)
|
||||
: ulAIGetInfo(device_handle, AI_INFO_NUM_DIFF_RANGES, 0, &num_ranges);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return err;
|
||||
|
||||
for (int i = 0; i < num_ranges; i++) {
|
||||
err = input_mode == AI_SINGLE_ENDED
|
||||
? ulAIGetInfo(device_handle, AI_INFO_SE_RANGE, i, &range)
|
||||
: ulAIGetInfo(device_handle, AI_INFO_DIFF_RANGE, i, &range);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return err;
|
||||
|
||||
ranges[i] = (Range) range;
|
||||
}
|
||||
|
||||
*number_of_ranges = (int) num_ranges;
|
||||
|
||||
return ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
static AiInputMode uldaq_parse_input_mode(const char *str)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_LEN(input_modes); i++) {
|
||||
|
@ -165,10 +140,100 @@ static Range uldaq_parse_range(const char *str)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int uldaq_init(struct node *n)
|
||||
static DaqDeviceDescriptor * uldaq_find_device(struct uldaq *u) {
|
||||
DaqDeviceDescriptor *d = NULL;
|
||||
|
||||
if (num_devs == 0)
|
||||
return NULL;
|
||||
|
||||
if (u->device_interface_type == ANY_IFC && u->device_id == NULL)
|
||||
return &descriptors[0];
|
||||
|
||||
for (int i = 0; i < num_devs; i++) {
|
||||
if (u->device_id) {
|
||||
if (strcmp(u->device_id, d->uniqueId))
|
||||
break;
|
||||
}
|
||||
|
||||
if (u->device_interface_type != ANY_IFC) {
|
||||
if (u->device_interface_type != d->devInterface)
|
||||
break;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int uldaq_connect(struct node *n)
|
||||
{
|
||||
struct uldaq *u = (struct uldaq *) n->_vd;
|
||||
UlError err;
|
||||
|
||||
/* Find Matching device */
|
||||
if (!u->device_descriptor) {
|
||||
u->device_descriptor = uldaq_find_device(u);
|
||||
if (u->device_descriptor) {
|
||||
warn("Unable to find a matching device for node '%s'", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a handle to the DAQ device associated with the first descriptor */
|
||||
if (!u->device_handle) {
|
||||
u->device_handle = ulCreateDaqDevice(descriptors[0]);
|
||||
if (!u->device_handle) {
|
||||
warn("Unable to create handle for DAQ device for node '%s'", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if device is already connected */
|
||||
int connected;
|
||||
err = ulIsDaqDeviceConnected(u->device_handle, &connected);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
|
||||
/* Connect to device */
|
||||
if (!connected) {
|
||||
err = ulConnectDaqDevice(u->device_handle);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
warn("Failed to connect to DAQ device for node '%s'", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uldaq_type_start(struct super_node *sn)
|
||||
{
|
||||
UlError err;
|
||||
|
||||
/* Get descriptors for all of the available DAQ devices */
|
||||
err = ulGetDaqDeviceInventory(ANY_IFC, descriptors, &num_devs);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
warn("Failed to retrieve DAQ device list");
|
||||
return -1;
|
||||
}
|
||||
|
||||
info("Found %d DAQ devices", num_devs);
|
||||
for (int i = 0; i < num_devs; i++) {
|
||||
DaqDeviceDescriptor *desc = &descriptors[i];
|
||||
|
||||
info(" %d: %s %s", i, desc->uniqueId, desc->devString);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uldaq_init(struct node *n)
|
||||
{
|
||||
int ret;
|
||||
struct uldaq *u = (struct uldaq *) n->_vd;
|
||||
|
||||
u->device_id = NULL;
|
||||
u->device_interface_type = ANY_IFC;
|
||||
|
||||
u->in.queues = NULL;
|
||||
|
@ -176,21 +241,32 @@ int uldaq_init(struct node *n)
|
|||
u->in.scan_options = (ScanOption) (SO_DEFAULTIO | SO_CONTINUOUS);
|
||||
u->in.flags = AINSCAN_FF_DEFAULT;
|
||||
|
||||
pthread_mutex_init(&u->in.mutex, NULL);
|
||||
pthread_cond_init(&u->in.cv, NULL);
|
||||
ret = pthread_mutex_init(&u->in.mutex, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pthread_cond_init(&u->in.cv, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uldaq_destroy(struct node *n)
|
||||
{
|
||||
int ret;
|
||||
struct uldaq *u = (struct uldaq *) n->_vd;
|
||||
|
||||
if (u->in.queues)
|
||||
free(u->in.queues);
|
||||
|
||||
pthread_mutex_destroy(&u->in.mutex);
|
||||
pthread_cond_destroy(&u->in.cv);
|
||||
ret = pthread_mutex_destroy(&u->in.mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pthread_cond_destroy(&u->in.cv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -209,8 +285,9 @@ int uldaq_parse(struct node *n, json_t *cfg)
|
|||
json_t *json_signal;
|
||||
json_error_t err;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s?: s, s: { s: o, s: F, s?: s, s?: s } }",
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s?: s, s?: s, s: { s: o, s: F, s?: s, s?: s } }",
|
||||
"interface_type", &interface_type,
|
||||
"device_id", &u->device_id,
|
||||
"in",
|
||||
"signals", &json_signals,
|
||||
"sample_rate", &u->in.sample_rate,
|
||||
|
@ -279,9 +356,9 @@ char * uldaq_print(struct node *n)
|
|||
struct uldaq *u = (struct uldaq *) n->_vd;
|
||||
|
||||
char *buf = NULL;
|
||||
char *uid = u->device_descriptor.uniqueId;
|
||||
char *name = u->device_descriptor.productName;
|
||||
const char *iftype = uldaq_print_interface_type(u->device_interface_type);
|
||||
char *uid = u->device_descriptor->uniqueId;
|
||||
char *name = u->device_descriptor->productName;
|
||||
const char *iftype = uldaq_print_interface_type(u->device_descriptor->devInterface);
|
||||
|
||||
buf = strcatf(&buf, "device=%s (%s), interface=%s", uid, name, iftype);
|
||||
buf = strcatf(&buf, ", in.sample_rate=%f", u->in.sample_rate);
|
||||
|
@ -291,22 +368,112 @@ char * uldaq_print(struct node *n)
|
|||
|
||||
int uldaq_check(struct node *n)
|
||||
{
|
||||
int ret;
|
||||
long long has_ai, event_types, max_channel, scan_options, num_ranges_se, num_ranges_diff;
|
||||
struct uldaq *u = (struct uldaq *) n->_vd;
|
||||
|
||||
(void) u; // unused for now
|
||||
UlError err;
|
||||
|
||||
if (n->in.vectorize < 100) {
|
||||
warn("vectorize setting of node '%s' must be larger than 100", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = uldaq_connect(n);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err = ulDevGetInfo(u->device_handle, DEV_INFO_HAS_AI_DEV, 0, &has_ai);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
|
||||
err = ulDevGetInfo(u->device_handle, DEV_INFO_DAQ_EVENT_TYPES, 0, &event_types);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
|
||||
err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_CHANS, 0, &max_channel);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
|
||||
err = ulAIGetInfo(u->device_handle, AI_INFO_SCAN_OPTIONS, 0, &scan_options);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
|
||||
err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_DIFF_RANGES, 0, &num_ranges_diff);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
|
||||
err = ulAIGetInfo(u->device_handle, AI_INFO_NUM_SE_RANGES, 0, &num_ranges_se);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
|
||||
Range ranges_diff[num_ranges_diff];
|
||||
Range ranges_se[num_ranges_se];
|
||||
|
||||
for (int i = 0; i < num_ranges_diff; i++) {
|
||||
long long rng;
|
||||
|
||||
err = ulAIGetInfo(u->device_handle, AI_INFO_DIFF_RANGE, i, &rng);
|
||||
|
||||
ranges_diff[i] = *(Range *) rng;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_ranges_se; i++) {
|
||||
long long rng;
|
||||
|
||||
err = ulAIGetInfo(u->device_handle, AI_INFO_SE_RANGE, i, &rng);
|
||||
|
||||
ranges_se[i] = *(Range *) rng;
|
||||
}
|
||||
|
||||
if (!has_ai) {
|
||||
warn("DAQ device has no analog input channels");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(event_types & DE_ON_DATA_AVAILABLE)) {
|
||||
warn("DAQ device does not support events");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((scan_options & u->in.scan_options) != u->in.scan_options) {
|
||||
warn("DAQ device does not support required scan options");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < list_length(&n->signals); i++) {
|
||||
struct signal *s = (struct signal *) list_at(&n->signals, i);
|
||||
AiQueueElement *q = &u->in.queues[i];
|
||||
|
||||
if (s->type != SIGNAL_TYPE_FLOAT) {
|
||||
warn("Node '%s' only supports signals of type = float!", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (q->inputMode) {
|
||||
case AI_PSEUDO_DIFFERENTIAL:
|
||||
case AI_DIFFERENTIAL:
|
||||
for (int j = 0; j < num_ranges_diff; j++) {
|
||||
if (q->range == ranges_diff[j])
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
|
||||
case AI_SINGLE_ENDED:
|
||||
for (int j = 0; j < num_ranges_se; j++) {
|
||||
if (q->range == ranges_se[j])
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
warn("Unsupported range for signal %zu", i);
|
||||
return -1;
|
||||
|
||||
found: if (q->channel > max_channel) {
|
||||
warn("DAQ device does not support more than %lld channels", max_channel);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -319,14 +486,10 @@ void uldaq_data_available(DaqDeviceHandle device_handle, DaqEventType event_type
|
|||
|
||||
pthread_mutex_lock(&u->in.mutex);
|
||||
|
||||
#if 0
|
||||
UlError err;
|
||||
err = ulAInScanStatus(device_handle, &u->in.status, &u->in.transfer_status);
|
||||
if (err != ERR_NO_ERROR)
|
||||
warn("Failed to retrieve scan status in event callback");
|
||||
#else
|
||||
u->in.transfer_status.currentIndex = (event_data - 1) * u->in.channel_count;
|
||||
#endif
|
||||
|
||||
pthread_mutex_unlock(&u->in.mutex);
|
||||
|
||||
|
@ -339,10 +502,9 @@ int uldaq_start(struct node *n)
|
|||
struct uldaq *u = (struct uldaq *) n->_vd;
|
||||
|
||||
u->sequence = 0;
|
||||
u->buffer_pos = 0;
|
||||
u->in.buffer_pos = 0;
|
||||
|
||||
unsigned num_devs = ULDAQ_MAX_DEV_COUNT;
|
||||
DaqDeviceDescriptor descriptors[num_devs];
|
||||
int ret;
|
||||
UlError err;
|
||||
|
||||
/* Allocate a buffer to receive the data */
|
||||
|
@ -353,40 +515,9 @@ int uldaq_start(struct node *n)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Get descriptors for all of the available DAQ devices */
|
||||
err = ulGetDaqDeviceInventory(u->device_interface_type, descriptors, &num_devs);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
warn("Failed to retrieve DAQ device list for node '%s'", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Verify at least one DAQ device is detected */
|
||||
if (num_devs == 0) {
|
||||
warn("No DAQ devices found for node '%s'", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get a handle to the DAQ device associated with the first descriptor */
|
||||
u->device_handle = ulCreateDaqDevice(descriptors[0]);
|
||||
if (u->device_handle == 0) {
|
||||
warn("Unabled to create handle for DAQ device for node '%s'", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int num_ranges;
|
||||
Range ranges[ULDAQ_MAX_RANGE_COUNT];
|
||||
/* Get the analog input ranges */
|
||||
err = uldag_range_info(u->device_handle, u->in.input_mode, &num_ranges, ranges);
|
||||
if (err != ERR_NO_ERROR)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
err = ulConnectDaqDevice(u->device_handle);
|
||||
if (err != ERR_NO_ERROR) {
|
||||
warn("Failed to connect to DAQ device for node '%s'", node_name(n));
|
||||
return -1;
|
||||
}
|
||||
ret = uldaq_connect(n);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err = ulAInLoadQueue(u->device_handle, u->in.queues, list_length(&n->signals));
|
||||
if (err != ERR_NO_ERROR) {
|
||||
|
@ -425,6 +556,7 @@ int uldaq_stop(struct node *n)
|
|||
|
||||
UlError err;
|
||||
|
||||
// @todo: fix deadlock
|
||||
//pthread_mutex_lock(&u->in.mutex);
|
||||
|
||||
/* Get the current status of the acquisition */
|
||||
|
@ -456,10 +588,22 @@ int uldaq_read(struct node *n, struct sample *smps[], unsigned cnt, unsigned *re
|
|||
{
|
||||
struct uldaq *u = (struct uldaq *) n->_vd;
|
||||
|
||||
if (u->in.status != SS_RUNNING)
|
||||
return -1;
|
||||
size_t buffer_incr = n->in.vectorize * u->in.channel_count;
|
||||
|
||||
if (cnt != n->in.vectorize)
|
||||
pthread_mutex_lock(&u->in.mutex);
|
||||
|
||||
/* Wait for data available condition triggered by event callback */
|
||||
if (u->in.buffer_pos + buffer_incr < u->in.transfer_status.currentIndex)
|
||||
pthread_cond_wait(&u->in.cv, &u->in.mutex);
|
||||
|
||||
#if 1
|
||||
debug(2, "Total count = %lld", u->in.transfer_status.currentTotalCount);
|
||||
debug(2, "Index = %lld", u->in.transfer_status.currentIndex);
|
||||
debug(2, "Scan count = %lld", u->in.transfer_status.currentScanCount);
|
||||
debug(2, "Buffer pos = %zu", u->in.buffer_pos);
|
||||
#endif
|
||||
|
||||
if (u->in.status != SS_RUNNING)
|
||||
return -1;
|
||||
|
||||
/* Wait for data available condition triggered by event callback */
|
||||
|
@ -494,7 +638,9 @@ int uldaq_read(struct node *n, struct sample *smps[], unsigned cnt, unsigned *re
|
|||
smp->sequence = u->sequence++;
|
||||
smp->flags = SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
|
||||
}
|
||||
u->buffer_pos += u->in.channel_count * n->in.vectorize;
|
||||
|
||||
u->buffer_pos += u->in.channel_count * cnt;
|
||||
|
||||
pthread_mutex_unlock(&u->in.mutex);
|
||||
|
||||
return cnt;
|
||||
|
@ -502,19 +648,20 @@ int uldaq_read(struct node *n, struct sample *smps[], unsigned cnt, unsigned *re
|
|||
|
||||
static struct plugin p = {
|
||||
.name = "uldaq",
|
||||
.description = "Read USB analog to digital converters like UL201",
|
||||
.description = "Measurement Computing DAQ devices like UL201 (libuldaq)",
|
||||
.type = PLUGIN_TYPE_NODE,
|
||||
.node = {
|
||||
.vectorize = 0,
|
||||
.flags = 0,
|
||||
.size = sizeof(struct uldaq),
|
||||
.parse = uldaq_parse,
|
||||
.init = uldaq_init,
|
||||
.destroy= uldaq_destroy,
|
||||
.print = uldaq_print,
|
||||
.start = uldaq_start,
|
||||
.stop = uldaq_stop,
|
||||
.read = uldaq_read
|
||||
.vectorize = 0,
|
||||
.flags = 0,
|
||||
.size = sizeof(struct uldaq),
|
||||
.type.start = uldaq_type_start,
|
||||
.parse = uldaq_parse,
|
||||
.init = uldaq_init,
|
||||
.destroy = uldaq_destroy,
|
||||
.print = uldaq_print,
|
||||
.start = uldaq_start,
|
||||
.stop = uldaq_stop,
|
||||
.read = uldaq_read
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ int queue_init(struct queue *q, size_t size, struct memory_type *m)
|
|||
if (!IS_POW2(size)) {
|
||||
size_t old_size = size;
|
||||
size = LOG2_CEIL(size);
|
||||
warn("A queue size was changed from %lu to %lu", old_size, size);
|
||||
warn("A queue size was changed from %zu to %zu", old_size, size);
|
||||
}
|
||||
|
||||
q->buffer_mask = size - 1;
|
||||
|
|
|
@ -42,7 +42,7 @@ RUN cmake -DCPACK_GENERATOR=RPM ..
|
|||
RUN make -j$(nproc) doc
|
||||
RUN make -j$(nproc) package
|
||||
|
||||
FROM fedora:28
|
||||
FROM fedora:29
|
||||
|
||||
# Some of the dependencies are only available in our own repo
|
||||
ADD https://packages.fein-aachen.org/redhat/fein.repo /etc/yum.repos.d/
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
###################################################################################
|
||||
|
||||
FROM fedora:28
|
||||
FROM fedora:29
|
||||
|
||||
ARG GIT_REV=unknown
|
||||
ARG GIT_BRANCH=unknown
|
||||
|
@ -36,12 +36,7 @@ ARG VERSION=unknown
|
|||
ARG VARIANT=unknown
|
||||
|
||||
# Some of the dependencies are only available in our own repo
|
||||
ADD https://packages.fein-aachen.org/redhat/fein.repo /etc/yum.repos.d/
|
||||
|
||||
# We need to use our own RPM packages of libwebsockets
|
||||
# as the official ones do contain the CMake files
|
||||
RUN dnf -y install --repo=fein \
|
||||
libwebsockets-2.4.2
|
||||
ADD https://packages.fein-aachen.org/fedora/fein.repo /etc/yum.repos.d/
|
||||
|
||||
# Toolchain
|
||||
RUN dnf -y install \
|
||||
|
@ -76,15 +71,16 @@ RUN dnf -y install \
|
|||
libcurl-devel \
|
||||
jansson-devel \
|
||||
zeromq-devel \
|
||||
nanomsg-devel \
|
||||
protobuf-devel \
|
||||
protobuf-c-devel \
|
||||
libiec61850-devel \
|
||||
librabbitmq-devel \
|
||||
mosquitto-devel \
|
||||
comedilib-devel comedilib \
|
||||
libibverbs-devel \
|
||||
librdmacm-devel
|
||||
librdmacm-devel \
|
||||
libwebsockets-devel \
|
||||
nanomsg \
|
||||
libiec61850
|
||||
|
||||
# Build & Install Criterion
|
||||
RUN cd /tmp && \
|
||||
|
|
|
@ -50,7 +50,9 @@ int main(int argc, char *argv[])
|
|||
const char *input_format = "villas.human";
|
||||
const char *output_format = "villas.human";
|
||||
|
||||
char c, *endptr;
|
||||
/* Parse optional command line arguments */
|
||||
int c;
|
||||
char *endptr;
|
||||
while ((c = getopt(argc, argv, "Vhd:i:o:")) != -1) {
|
||||
switch (c) {
|
||||
case 'V':
|
||||
|
|
|
@ -121,7 +121,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
json_t *cfg_cli = json_object();
|
||||
|
||||
char c, *endptr;
|
||||
/* Parse optional command line arguments */
|
||||
int c;
|
||||
char *endptr;
|
||||
while ((c = getopt(argc, argv, "Vhv:d:f:o:")) != -1) {
|
||||
switch (c) {
|
||||
case 'V':
|
||||
|
|
|
@ -117,7 +117,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
const char *uri = "opal-shmem.conf";
|
||||
#else
|
||||
char c;
|
||||
|
||||
/* Parse optional command line arguments */
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "hV")) != -1) {
|
||||
switch (c) {
|
||||
case 'V':
|
||||
|
|
|
@ -255,7 +255,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
json_t *cfg_cli = json_object();
|
||||
|
||||
char c, *endptr;
|
||||
/* Parse optional command line arguments */
|
||||
int c;
|
||||
char *endptr;
|
||||
while ((c = getopt(argc, argv, "Vhxrsd:l:L:t:f:o:")) != -1) {
|
||||
switch (c) {
|
||||
case 'V':
|
||||
|
|
|
@ -59,7 +59,8 @@ json_t * parse_cli(int argc, char *argv[])
|
|||
int limit = -1;
|
||||
|
||||
/* Parse optional command line arguments */
|
||||
char c, *endptr;
|
||||
int c;
|
||||
char *endptr;
|
||||
while ((c = getopt(argc, argv, "v:r:f:l:a:D:no:")) != -1) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
|
|
Loading…
Add table
Reference in a new issue