Compare commits

..

No commits in common. "master" and "ethstream-1.2" have entirely different histories.

18 changed files with 167 additions and 375 deletions

10
.gitignore vendored
View File

@ -1,10 +0,0 @@
ethstream
ethstream.1
ethstream.txt
ethstream.exe
*.obj
*.d
*.dobj
*.o

View File

@ -14,11 +14,9 @@
# Build options # Build options
CFLAGS += -Wall -g #-pg CFLAGS += -Wall -g #-pg
LDFLAGS += #-pg LDFLAGS += -lm #-pg
LDLIBS += -lm
PREFIX = /usr/local PREFIX = /usr/local
MANPATH = ${PREFIX}/man/man1/ MANPATH = ${PREFIX}/man/man1
BINPATH = ${PREFIX}/bin BINPATH = ${PREFIX}/bin
#WINCC = i386-mingw32-gcc #WINCC = i386-mingw32-gcc
@ -51,7 +49,6 @@ obj-common = opt.o ue9.o ue9error.o netutil.o debug.o nerdjack.o
obj-ethstream = ethstream.o $(obj-common) obj-ethstream = ethstream.o $(obj-common)
ethstream: $(obj-ethstream) ethstream: $(obj-ethstream)
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
ethstream.exe: $(obj-ethstream:.o=.obj) compat-win32.obj ethstream.exe: $(obj-ethstream:.o=.obj) compat-win32.obj
@ -68,7 +65,6 @@ ethstream.exe: $(obj-ethstream:.o=.obj) compat-win32.obj
.PHONY: install .PHONY: install
install: ethstream.1 ethstream install: ethstream.1 ethstream
mkdir -p ${BINPATH} ${MANPATH}
install -m 0755 ethstream ${BINPATH} install -m 0755 ethstream ${BINPATH}
install -m 0644 ethstream.1 ${MANPATH} install -m 0644 ethstream.1 ${MANPATH}

4
README
View File

@ -1,8 +1,6 @@
Labjack/Nerdjack Tools Labjack/Nerdjack Tools
by Jim Paris <jim@jtan.com> by Jim Paris <jim@jtan.com>
with modifications by with modifications by Zach Clifford <zacharyc@mit.edu>
Zach Clifford <zacharyc@mit.edu>
John Donnal <jdonnal@mit.edu>
These tools are for interacting with the LabJack UE9 or the NerdJack These tools are for interacting with the LabJack UE9 or the NerdJack
over the Ethernet interface. More information about the UE9 device: over the Ethernet interface. More information about the UE9 device:

View File

@ -1 +1 @@
1.3.2 1.2

View File

@ -2,7 +2,6 @@
#include <stdio.h> #include <stdio.h>
#include "compat.h" #include "compat.h"
#include <windows.h> #include <windows.h>
#include "errno.h"
unsigned int sleep(unsigned int seconds) unsigned int sleep(unsigned int seconds)
{ {

View File

@ -5,6 +5,9 @@
unsigned int sleep(unsigned int seconds); unsigned int sleep(unsigned int seconds);
char *compat_strerror(int errnum); char *compat_strerror(int errnum);
//const char *inet_ntop(int af, void *src, const char *dst, socklen_t cnt); //const char *inet_ntop(int af, void *src, const char *dst, socklen_t cnt);
#define INET_ADDRSTRLEN 16
#define ETIMEDOUT 110
#define ENOTCONN 107
#else #else
#define compat_strerror strerror #define compat_strerror strerror
#endif #endif

18
debug.c
View File

@ -1,7 +1,6 @@
#include "debug.h" #include "debug.h"
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/time.h>
int verb_count = 0; int verb_count = 0;
@ -9,27 +8,10 @@ int func_fprintf(const char *func, FILE * stream, const char *format, ...)
{ {
va_list ap; va_list ap;
int ret; int ret;
struct timeval tv;
gettimeofday(&tv, NULL);
fprintf(stream, "%ld.%06ld: ", (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
fprintf(stream, "%s: ", func); fprintf(stream, "%s: ", func);
va_start(ap, format); va_start(ap, format);
ret = vfprintf(stream, format, ap); ret = vfprintf(stream, format, ap);
va_end(ap); va_end(ap);
return ret; return ret;
} }
int my_fprintf(FILE * stream, const char *format, ...)
{
va_list ap;
int ret;
struct timeval tv;
gettimeofday(&tv, NULL);
fprintf(stream, "%ld.%06ld: ", (unsigned long)tv.tv_sec, (unsigned long)tv.tv_usec);
va_start(ap, format);
ret = vfprintf(stream, format, ap);
va_end(ap);
return ret;
}

View File

@ -16,8 +16,6 @@ extern int verb_count;
int func_fprintf(const char *func, FILE * stream, const char *format, int func_fprintf(const char *func, FILE * stream, const char *format,
...) __attribute__ ((format(printf, 3, 4))); ...) __attribute__ ((format(printf, 3, 4)));
int my_fprintf(FILE * stream, const char *format,
...) __attribute__ ((format(printf, 2, 3)));
#define debug(x...) ({ \ #define debug(x...) ({ \
if(verb_count >= 2) \ if(verb_count >= 2) \
@ -30,11 +28,6 @@ int my_fprintf(FILE * stream, const char *format,
}) })
#define info(x...) ({ \ #define info(x...) ({ \
if(verb_count >= 0) \
my_fprintf(stderr,x); \
})
#define info_no_timestamp(x...) ({ \
if(verb_count >= 0) \ if(verb_count >= 0) \
fprintf(stderr,x); \ fprintf(stderr,x); \
}) })

View File

@ -47,17 +47,16 @@ struct options opt[] = {
{'r', "rate", "hz", "sample each channel at this rate (8000.0)"}, {'r', "rate", "hz", "sample each channel at this rate (8000.0)"},
{'L', "labjack", NULL, "Force LabJack device"}, {'L', "labjack", NULL, "Force LabJack device"},
{'t', "timers", "a[:A],b[:B]", "set LabJack timer modes a,b and optional values A,B"}, {'t', "timers", "a,b,c", "set LabJack timer modes to a, b, and c"},
{'T', "timerdivisor", "n", "set LabJack timer divisor to n"}, {'T', "timerdivisor", "n", "set LabJack timer divisor to n"},
{'N', "nerdjack", NULL, "Force NerdJack device"}, {'N', "nerdjack", NULL, "Force NerdJack device"},
{'d', "detect", NULL, "Detect NerdJack IP address"}, {'d', "detect", NULL, "Detect NerdJack IP address"},
{'R', "range", "a,b", {'R', "range", "a,b",
"Set range on NerdJack for channels 0-5,6-11 to either 5 or 10 (10,10)"}, "Set range on NerdJack for channels 0-5,6-11 to either 5 or 10 (10,10)"},
{'g', "gain", "a,b,c", "Set Labjack AIN channel gains: 0,1,2,4,8 in -C channel order"},
{'o', "oneshot", NULL, "don't retry in case of errors"}, {'o', "oneshot", NULL, "don't retry in case of errors"},
{'f', "forceretry", NULL, "retry no matter what happens"}, {'f', "forceretry", NULL, "retry no matter what happens"},
{'c', "convert", NULL, "convert output to volts/temperature"}, {'c', "convert", NULL, "convert output to volts"},
{'H', "converthex", NULL, "convert output to hex"}, {'H', "converthex", NULL, "convert output to hex"},
{'m', "showmem", NULL, "output memory stats with data (NJ only)"}, {'m', "showmem", NULL, "output memory stats with data (NJ only)"},
{'l', "lines", "num", "if set, output this many lines and quit"}, {'l', "lines", "num", "if set, output this many lines and quit"},
@ -71,44 +70,19 @@ struct options opt[] = {
int doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval, int doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval,
int *channel_list, int channel_count, int *channel_list, int channel_count,
int *timer_mode_list, int *timer_value_list, int *timer_mode_list, int timer_mode_count, int timer_divisor,
int timer_mode_count, int timer_divisor,
int *gain_list, int gain_count,
int convert, int maxlines); int convert, int maxlines);
int nerdDoStream(const char *address, int *channel_list, int channel_count, int nerdDoStream(const char *address, int *channel_list, int channel_count,
int precision, unsigned long period, int convert, int lines, int precision, unsigned long period, int convert, int lines,
int showmem); int showmem);
int data_callback(int channels, int *channel_list, int gain_count, int *gain_list, int data_callback(int channels, uint16_t * data, void *context);
uint16_t * data, void *context);
int columns_left = 0; int columns_left = 0;
////////EXTRA GLOBAL VARS///////////
// for clean shutdown //
// added by John Donnal 2015 //
////////////////////////////////////
int fd_cmd, fd_data;
int ue9_running = 0; //flag if labjack is currently streaming data
void handle_sig(int sig) void handle_sig(int sig)
{ {
while (columns_left--) { while (columns_left--) {
printf(" 0"); printf(" 0");
} }
/******************************************************
* added by John Donnal 2015 *
* Close out connection to LabJack, firmware glitches *
* if the stream is not closed correctly *
******************************************************/
if(ue9_running==1){
printf("Performing clean shutdown of LabJack\n");
ue9_stream_stop(fd_cmd);
ue9_buffer_flush(fd_cmd);
ue9_close(fd_data);
ue9_close(fd_cmd);
}
/******************************************************/
fflush(stdout); fflush(stdout);
exit(0); exit(0);
} }
@ -132,11 +106,8 @@ int main(int argc, char *argv[])
uint8_t scanconfig; uint8_t scanconfig;
uint16_t scaninterval; uint16_t scaninterval;
int timer_mode_list[UE9_TIMERS]; int timer_mode_list[UE9_TIMERS];
int timer_value_list[UE9_TIMERS];
int timer_mode_count = 0; int timer_mode_count = 0;
int timer_divisor = 1; int timer_divisor = 1;
int gain_list[MAX_CHANNELS];
int gain_count = 0;
int channel_list[MAX_CHANNELS]; int channel_list[MAX_CHANNELS];
int channel_count = 0; int channel_count = 0;
int nerdjack = 0; int nerdjack = 0;
@ -188,35 +159,11 @@ int main(int argc, char *argv[])
} }
while (*endp); while (*endp);
break; break;
case 'g': /* labjack only */
gain_count = 0;
do {
tmp = strtol(optarg, &endp, 0);
if (*endp != '\0' && *endp != ',') {
info("bad gain number: %s\n",
optarg);
goto printhelp;
}
if (gain_count >= MAX_CHANNELS) {
info("error: too many gains specified\n");
goto printhelp;
}
if (!(tmp == 0 || tmp == 1 || tmp == 2 || tmp == 3 || tmp == 8)) {
info("error: invalid gain specified\n");
goto printhelp;
}
gain_list[gain_count++] = tmp;
optarg = endp + 1;
}
while (*endp);
break;
case 't': /* labjack only */ case 't': /* labjack only */
timer_mode_count = 0; timer_mode_count = 0;
do { do {
/* get mode */
tmp = strtol(optarg, &endp, 0); tmp = strtol(optarg, &endp, 0);
if (*endp != '\0' && *endp != ',' && *endp != ':') { if (*endp != '\0' && *endp != ',') {
info("bad timer mode: %s\n", optarg); info("bad timer mode: %s\n", optarg);
goto printhelp; goto printhelp;
} }
@ -224,22 +171,7 @@ int main(int argc, char *argv[])
info("error: too many timers specified\n"); info("error: too many timers specified\n");
goto printhelp; goto printhelp;
} }
timer_mode_list[timer_mode_count] = tmp; timer_mode_list[timer_mode_count++] = tmp;
/* get optional value */
if (*endp == ':') {
optarg = endp + 1;
tmp = strtol(optarg, &endp, 0);
if (*endp != '\0' && *endp != ',') {
info("bad timer value: %s\n", optarg);
goto printhelp;
}
timer_value_list[timer_mode_count] = tmp;
} else {
timer_value_list[timer_mode_count] = 0;
}
timer_mode_count++;
optarg = endp + 1; optarg = endp + 1;
} }
while (*endp); while (*endp);
@ -334,9 +266,8 @@ int main(int argc, char *argv[])
return 0; return 0;
break; break;
case 'V': case 'V':
printf("ethstream " VERSION "\n"); printf("etherstream " VERSION "\n");
printf("Written by Jim Paris <jim@jtan.com>\n"); printf("Written by Jim Paris <jim@jtan.com>\n");
printf("and John Donnal <jdonnal@mit.edu>\n");
printf("and Zachary Clifford <zacharyc@mit.edu>.\n"); printf("and Zachary Clifford <zacharyc@mit.edu>.\n");
printf("This program comes with no warranty and is " printf("This program comes with no warranty and is "
"provided under the GPLv2.\n"); "provided under the GPLv2.\n");
@ -444,12 +375,6 @@ int main(int argc, char *argv[])
goto printhelp; goto printhelp;
} }
/* Individual Analog Channel Gain Set requires Labjack*/
if (gain_count && !labjack) {
info("Can't use Individual Gain Set on NerdJack\n");
goto printhelp;
}
if (optind < argc) { if (optind < argc) {
info("error: too many arguments (%s)\n\n", argv[optind]); info("error: too many arguments (%s)\n\n", argv[optind]);
goto printhelp; goto printhelp;
@ -469,8 +394,8 @@ int main(int argc, char *argv[])
if (verb_count) { if (verb_count) {
info("Scanning channels:"); info("Scanning channels:");
for (i = 0; i < channel_count; i++) for (i = 0; i < channel_count; i++)
info_no_timestamp(" AIN%d", channel_list[i]); info(" AIN%d", channel_list[i]);
info_no_timestamp("\n"); info("\n");
} }
/* Figure out actual rate. */ /* Figure out actual rate. */
@ -498,11 +423,6 @@ int main(int argc, char *argv[])
signal(SIGINT, handle_sig); signal(SIGINT, handle_sig);
signal(SIGTERM, handle_sig); signal(SIGTERM, handle_sig);
#ifdef SIGPIPE /* not on Windows */
/* Ignore SIGPIPE so I/O errors to the network device won't kill the process */
signal(SIGPIPE, SIG_IGN);
#endif
if (detect) { if (detect) {
info("Autodetecting NerdJack address\n"); info("Autodetecting NerdJack address\n");
free(address); free(address);
@ -526,9 +446,7 @@ int main(int argc, char *argv[])
} else { } else {
ret = doStream(address, scanconfig, scaninterval, ret = doStream(address, scanconfig, scaninterval,
channel_list, channel_count, channel_list, channel_count,
timer_mode_list, timer_value_list, timer_mode_list, timer_mode_count, timer_divisor,
timer_mode_count, timer_divisor,
gain_list, gain_count,
convert, lines); convert, lines);
verb("doStream returned %d\n", ret); verb("doStream returned %d\n", ret);
} }
@ -677,13 +595,11 @@ nerdDoStream(const char *address, int *channel_list, int channel_count,
int int
doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval, doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval,
int *channel_list, int channel_count, int *channel_list, int channel_count,
int *timer_mode_list, int *timer_value_list, int *timer_mode_list, int timer_mode_count, int timer_divisor,
int timer_mode_count, int timer_divisor,
int *gain_list, int gain_count,
int convert, int lines) int convert, int lines)
{ {
int retval = -EAGAIN; int retval = -EAGAIN;
// int fd_cmd, fd_data; *these are now globals so sighandler can use them* int fd_cmd, fd_data;
int ret; int ret;
static int first_call = 1; static int first_call = 1;
struct callbackInfo ci = { struct callbackInfo ci = {
@ -722,28 +638,18 @@ doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval,
/* Set timer configuration */ /* Set timer configuration */
if (timer_mode_count && if (timer_mode_count &&
ue9_timer_config(fd_cmd, timer_mode_list, timer_value_list, ue9_timer_config(fd_cmd, timer_mode_list, timer_mode_count,
timer_mode_count, timer_divisor) < 0) { timer_divisor) < 0) {
info("Failed to set timer configuration\n"); info("Failed to set timer configuration\n");
goto out2; goto out2;
} }
if (gain_count) { /* Set stream configuration */
/* Set stream configuration */ if (ue9_streamconfig_simple(fd_cmd, channel_list, channel_count,
if (ue9_streamconfig(fd_cmd, channel_list, channel_count, scanconfig, scaninterval,
scanconfig, scaninterval, UE9_BIPOLAR_GAIN1) < 0) {
gain_list, gain_count) < 0) { info("Failed to set stream configuration\n");
info("Failed to set stream configuration\n"); goto out2;
goto out2;
}
} else {
/* Set stream configuration */
if (ue9_streamconfig_simple(fd_cmd, channel_list, channel_count,
scanconfig, scaninterval,
UE9_BIPOLAR_GAIN1) < 0) {
info("Failed to set stream configuration\n");
goto out2;
}
} }
/* Start stream */ /* Start stream */
@ -753,9 +659,8 @@ doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval,
} }
/* Stream data */ /* Stream data */
ue9_running = 1;
ret = ret =
ue9_stream_data(fd_data, channel_count, channel_list, gain_count, gain_list, data_callback, (void *)&ci); ue9_stream_data(fd_data, channel_count, data_callback, (void *)&ci);
if (ret < 0) { if (ret < 0) {
info("Data stream failed with error %d\n", ret); info("Data stream failed with error %d\n", ret);
goto out3; goto out3;
@ -773,11 +678,10 @@ doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval,
out1: out1:
ue9_close(fd_cmd); ue9_close(fd_cmd);
out: out:
ue9_running = 0;
return retval; return retval;
} }
int data_callback(int channels, int *channel_list, int gain_count, int *gain_list, uint16_t * data, void *context) int data_callback(int channels, uint16_t * data, void *context)
{ {
int i; int i;
struct callbackInfo *ci = (struct callbackInfo *)context; struct callbackInfo *ci = (struct callbackInfo *)context;
@ -785,35 +689,23 @@ int data_callback(int channels, int *channel_list, int gain_count, int *gain_lis
columns_left = channels; columns_left = channels;
for (i = 0; i < channels; i++) { for (i = 0; i < channels; i++) {
if (ci->convert == CONVERT_VOLTS && switch (ci->convert) {
channel_list[i] <= UE9_MAX_ANALOG_CHANNEL) { case CONVERT_VOLTS:
/* CONVERT_VOLTS */ if (printf
if (i < gain_count) ("%lf",
{ ue9_binary_to_analog(&ci->calib, UE9_BIPOLAR_GAIN1,
if (printf("%lf", ue9_binary_to_analog( 12, data[i])) < 0)
&ci->calib, gain_list[i],
12, data[i])) < 0)
goto bad;
} else {
if (printf("%lf", ue9_binary_to_analog(
&ci->calib, 0,
12, data[i])) < 0)
goto bad;
}
} else if (ci->convert == CONVERT_VOLTS &&
(channel_list[i] == 141 || channel_list[i] == 133)) {
/* CONVERT_VOLTS but output temperature */
if (printf("%lf", ue9_binary_to_temperature(
&ci->calib, data[i])) < 0)
goto bad; goto bad;
} else if (ci->convert == CONVERT_HEX) { break;
/* CONVERT_HEX */ case CONVERT_HEX:
if (printf("%04X", data[i]) < 0) if (printf("%04X", data[i]) < 0)
goto bad; goto bad;
} else { break;
/* CONVERT_DEC */ default:
case CONVERT_DEC:
if (printf("%d", data[i]) < 0) if (printf("%d", data[i]) < 0)
goto bad; goto bad;
break;
} }
columns_left--; columns_left--;
if (i < (channels - 1)) { if (i < (channels - 1)) {

View File

@ -5,6 +5,4 @@
#define CONVERT_VOLTS 1 #define CONVERT_VOLTS 1
#define CONVERT_HEX 2 #define CONVERT_HEX 2
#define TIMEOUT 5 /* Timeout for connect/send/recv, in seconds */
#endif #endif

87
ethstream.txt Normal file
View File

@ -0,0 +1,87 @@
ETHERSTREAM(1) User Commands ETHERSTREAM(1)
NAME
etherstream - manual page for etherstream 1.2 (2010-02-08)
SYNOPSIS
ethstream [options]
-------
DESCRIPTION
-a, --address string
host/address of device (192.168.1.209)
-n, --numchannels n
sample the first N ADC channels (2)
-C, --channels a,b,c
sample channels a, b, and c
-r, --rate hz
sample each channel at this rate (8000.0)
-L, --labjack
Force LabJack device
-t, --timers a,b,c
set LabJack timer modes to a, b, and c
-T, --timerdivisor n
set LabJack timer divisor to n
-N, --nerdjack
Force NerdJack device
-d, --detect
Detect NerdJack IP address
-R, --range a,b
Set range on NerdJack for channels 0-5,6-11 to either 5 or 10
(10,10)
-o, --oneshot
dont retry in case of errors
-f, --forceretry
retry no matter what happens
-c, --convert
convert output to volts
-H, --converthex
convert output to hex
-m, --showmem
output memory stats with data (NJ only)
-l, --lines num
if set, output this many lines and quit
-h, --help
this help
-v, --verbose
be verbose
-V, --version
show version number and exit
-i, --info
get info from device (NJ only)
-X, --examples
show ethstream examples and exit
Read data from the specified Labjack UE9 via Ethernet. See README for
details.
AUTHOR
Written by Jim Paris <jim@jtan.com> and Zachary Clifford
<zacharyc@mit.edu>. This program comes with no warranty and is pro
vided under the GPLv2.
etherstream 1.2 (2010-02-08) February 2010 ETHERSTREAM(1)

View File

@ -71,36 +71,4 @@ specified, ethstream connects first to 192.168.1.209. It then tries\n\
to autodetect the NerdJack. This should find the device if you are on\n\ to autodetect the NerdJack. This should find the device if you are on\n\
the same network, but it will get confused if there are multiple NerdJacks\n\ the same network, but it will get confused if there are multiple NerdJacks\n\
on the network.\n\ on the network.\n\
\n\
Labjack only Timer modes are also avaliable. Read the Labjack UE9 Users Guide\n\
for more information. Upto 6 timers of various modes can be specified,\n\
they occur on FIO0-FIO5 which are on channels 200-205 respectively in order\n\
of specification. For 32 bit timer modes, the MSW should be read from\n\
channel 224 imeadiately after the LSW is read from one the timer channel.\n\
A clock frequency divisor is specified on a per device basis. For example:\n\
\n\
ethstream -t 4,12 -T 1 -C 200,224,201\n\
\n\
This will enable two timers with the fastest system clock divisor (48 MhZ/1)\n\
and read the two 16 bit words for timer mode 4 and the single 16 bit word of\n\
timer mode 12. These three words will occupy their own columns in the output\n\
stream. Digital timer mode channels can be interspersed with analog inouts.\n\
\n\
Labjack only individual analog input channel gain set is also avaliable.\n\
Gain 0 is default on labjack and corresponds to -5.18v to +5.07v. Gain 1 is\n\
is -0.01 to +5.07v. Gain 2 is -0.01 to +2.53v. Gain 4 is -0.01 to +1.26v.\n\
Gain 8 is -0.01 to +0.62v. Gains on the -g flag should be put in the desired\n\
order corresponding to the channels as specified by the -C flag. If there are\n\
less gains specified than channels the remainder default to gain 0. Extra gains\n\
are ignored. Gains can be specified for digital inputs or timer modes but they\n\
are irrelevant. A case where one should do this is if there are dital input\n\
channels intersperced within analog input channels; this keeps the order matched\n\
up so later analog input channels have the expected gain.\n\
\n\
ethstream -t 4 -T 1 -C 0,1,200,224,2,3 -g 2,2,0,0,4,4 -c\n\
\n\
This will set channles 0,1 and 2,3 to gain 2,2 and 4,4, respectively and convert\n\
the data to volts using the firmware stored factory calibrated data on the\n\
labjack. The digital channels 200 and 224 will remain undisturbed as integers.\n\
\n\
"; ";

View File

@ -25,6 +25,8 @@
#include "netutil.h" #include "netutil.h"
#include "ethstream.h" #include "ethstream.h"
#define NERDJACK_TIMEOUT 5 /* Timeout for connect/send/recv, in seconds */
#define NERD_HEADER_SIZE 8 #define NERD_HEADER_SIZE 8
#define MAX_SOCKETS 32 #define MAX_SOCKETS 32
@ -97,7 +99,6 @@ static int discovered_sock_create(struct discover_t *ds, uint32_t local_ip,
/* Set nonblocking */ /* Set nonblocking */
if (soblock(sock, 0) < 0) { if (soblock(sock, 0) < 0) {
verb("can't set nonblocking\n"); verb("can't set nonblocking\n");
close(sock);
return 0; return 0;
} }
@ -242,7 +243,7 @@ int nerdjack_detect(char *ipAddress)
int buffer_length; int buffer_length;
char buffer[200]; char buffer[200];
char incomingData[10]; char incomingData[10];
socklen_t lFromLen; unsigned int lFromLen;
sprintf(buffer, "TEST"); sprintf(buffer, "TEST");
buffer_length = strlen(buffer) + 1; buffer_length = strlen(buffer) + 1;
@ -311,7 +312,7 @@ int nerdjack_detect(char *ipAddress)
recvfrom_timeout(receivesock, incomingData, sizeof(incomingData), 0, recvfrom_timeout(receivesock, incomingData, sizeof(incomingData), 0,
(struct sockaddr *)&sFromAddr, &lFromLen, (struct sockaddr *)&sFromAddr, &lFromLen,
&(struct timeval) { &(struct timeval) {
.tv_sec = TIMEOUT})) { .tv_sec = NERDJACK_TIMEOUT})) {
close(receivesock); close(receivesock);
return -1; return -1;
} }
@ -340,14 +341,14 @@ int nerd_get_version(const char *address)
/* Send request */ /* Send request */
ret = send_all_timeout(fd_command, "VERS", 4, 0, &(struct timeval) { ret = send_all_timeout(fd_command, "VERS", 4, 0, &(struct timeval) {
.tv_sec = TIMEOUT}); .tv_sec = NERDJACK_TIMEOUT});
if (ret < 0) { if (ret < 0) {
verb("short send %d\n", (int)ret); verb("short send %d\n", (int)ret);
return -1; return -1;
} }
ret = recv_all_timeout(fd_command, buf, 200, 0, &(struct timeval) { ret = recv_all_timeout(fd_command, buf, 200, 0, &(struct timeval) {
.tv_sec = TIMEOUT}); .tv_sec = NERDJACK_TIMEOUT});
nerd_close_conn(fd_command); nerd_close_conn(fd_command);
@ -379,14 +380,14 @@ int nerd_send_command(const char *address, void *command, int length)
/* Send request */ /* Send request */
ret = send_all_timeout(fd_command, command, length, 0, &(struct timeval) { ret = send_all_timeout(fd_command, command, length, 0, &(struct timeval) {
.tv_sec = TIMEOUT}); .tv_sec = NERDJACK_TIMEOUT});
if (ret < 0 || ret != length) { if (ret < 0 || ret != length) {
verb("short send %d\n", (int)ret); verb("short send %d\n", (int)ret);
return -1; return -1;
} }
ret = recv_all_timeout(fd_command, buf, 3, 0, &(struct timeval) { ret = recv_all_timeout(fd_command, buf, 3, 0, &(struct timeval) {
.tv_sec = TIMEOUT}); .tv_sec = NERDJACK_TIMEOUT});
nerd_close_conn(fd_command); nerd_close_conn(fd_command);

View File

@ -27,8 +27,7 @@
/* Packet structure used in message to start sampling on NerdJack */ /* Packet structure used in message to start sampling on NerdJack */
typedef struct __attribute__ ((__packed__)) { typedef struct __attribute__ ((__packed__)) {
char word[4]; char word[4];
unsigned int period; //CHANGED FROM TYPE LONG. With 64 bit compilers longs are 8 bytes and nerdjack expects a 4 byte value unsigned long period;
//since the int type is 4 bytes this works but should be changed to use defined datatypes rather than rely on compiler data types
unsigned short channelbit; unsigned short channelbit;
unsigned char precision; unsigned char precision;
unsigned char prescaler; unsigned char prescaler;

View File

@ -8,7 +8,7 @@
#ifdef __WIN32__ #ifdef __WIN32__
# include <winsock2.h> # include <winsock2.h>
# include <ws2tcpip.h> # include <ws2tcpip.h>
# define socklen_t int # define socklen_t unsigned int
# define in_addr_t uint32_t # define in_addr_t uint32_t
# define in_port_t uint16_t # define in_port_t uint16_t
# include <windows.h> # include <windows.h>

152
ue9.c
View File

@ -24,7 +24,8 @@
#include "ue9error.h" #include "ue9error.h"
#include "util.h" #include "util.h"
#include "netutil.h" #include "netutil.h"
#include "ethstream.h"
#define UE9_TIMEOUT 5 /* Timeout for connect/send/recv, in seconds */
/* Fill checksums in data buffers, with "normal" checksum format */ /* Fill checksums in data buffers, with "normal" checksum format */
void ue9_checksum_normal(uint8_t * buffer, size_t len) void ue9_checksum_normal(uint8_t * buffer, size_t len)
@ -116,24 +117,10 @@ int ue9_verify_extended(uint8_t * buffer, size_t len)
return 1; return 1;
} }
/* Temperature conversion. If calib is NULL, use uncalibrated conversions. */
double ue9_binary_to_temperature(struct ue9Calibration *calib, uint16_t data)
{
double slope;
if (calib == NULL) {
slope = 0.012683;
} else {
slope = calib->tempSlope;
}
return data * slope; /* output is in Kelvin */
}
/* Data conversion. If calib is NULL, use uncalibrated conversions. */ /* Data conversion. If calib is NULL, use uncalibrated conversions. */
double double
ue9_binary_to_analog(struct ue9Calibration *calib, ue9_binary_to_analog(struct ue9Calibration *calib,
int gain, uint8_t resolution, uint16_t data) uint8_t gain, uint8_t resolution, uint16_t data)
{ {
double slope = 0, offset; double slope = 0, offset;
@ -147,27 +134,13 @@ ue9_binary_to_analog(struct ue9Calibration *calib,
} }
if (resolution < 18) { if (resolution < 18) {
switch (gain) { if (gain <= 3) {
case 1: slope = calib->unipolarSlope[gain];
slope = calib->unipolarSlope[0]; offset = calib->unipolarOffset[gain];
offset = calib->unipolarOffset[0]; } else if (gain == 8) {
break; slope = calib->bipolarSlope;
case 2: offset = calib->bipolarOffset;
slope = calib->unipolarSlope[1]; }
offset = calib->unipolarOffset[1];
break;
case 4:
slope = calib->unipolarSlope[2];
offset = calib->unipolarOffset[2];
break;
case 8:
slope = calib->unipolarSlope[3];
offset = calib->unipolarOffset[3];
break;
default:
slope = calib->bipolarSlope;
offset = calib->bipolarOffset;
}
} else { } else {
if (gain == 0) { if (gain == 0) {
slope = calib->hiResUnipolarSlope; slope = calib->hiResUnipolarSlope;
@ -210,7 +183,7 @@ int ue9_command(int fd, uint8_t * out, uint8_t * in, int inlen)
/* Send request */ /* Send request */
ret = send_all_timeout(fd, out, outlen, 0, &(struct timeval) { ret = send_all_timeout(fd, out, outlen, 0, &(struct timeval) {
.tv_sec = TIMEOUT}); .tv_sec = UE9_TIMEOUT});
if (ret < 0 || ret != outlen) { if (ret < 0 || ret != outlen) {
verb("short send %d\n", (int)ret); verb("short send %d\n", (int)ret);
return -1; return -1;
@ -224,7 +197,7 @@ int ue9_command(int fd, uint8_t * out, uint8_t * in, int inlen)
/* Receive result */ /* Receive result */
ret = recv_all_timeout(fd, in, inlen, 0, &(struct timeval) { ret = recv_all_timeout(fd, in, inlen, 0, &(struct timeval) {
.tv_sec = TIMEOUT}); .tv_sec = UE9_TIMEOUT});
if (ret < 0 || ret != inlen) { if (ret < 0 || ret != inlen) {
verb("short recv %d\n", (int)ret); verb("short recv %d\n", (int)ret);
return -1; return -1;
@ -402,7 +375,6 @@ int ue9_open(const char *host, int port)
/* Set nonblocking */ /* Set nonblocking */
if (soblock(fd, 0) < 0) { if (soblock(fd, 0) < 0) {
verb("can't set nonblocking\n"); verb("can't set nonblocking\n");
close(fd);
return -1; return -1;
} }
@ -418,7 +390,6 @@ int ue9_open(const char *host, int port)
he = gethostbyname(host); he = gethostbyname(host);
if (he == NULL) { if (he == NULL) {
verb("gethostbyname(\"%s\") failed\n", host); verb("gethostbyname(\"%s\") failed\n", host);
close(fd);
return -1; return -1;
} }
address.sin_addr = *((struct in_addr *)he->h_addr); address.sin_addr = *((struct in_addr *)he->h_addr);
@ -428,15 +399,12 @@ int ue9_open(const char *host, int port)
/* Connect */ /* Connect */
if (connect_timeout(fd, (struct sockaddr *)&address, sizeof(address), if (connect_timeout(fd, (struct sockaddr *)&address, sizeof(address),
&(struct timeval) { &(struct timeval) {
.tv_sec = TIMEOUT}) < 0) { .tv_sec = UE9_TIMEOUT}) < 0) {
verb("connection to %s:%d failed: %s\n", verb("connection to %s:%d failed: %s\n",
inet_ntoa(address.sin_addr), port, compat_strerror(errno)); inet_ntoa(address.sin_addr), port, compat_strerror(errno));
close(fd);
return -1; return -1;
} }
debug("Connected to port %d\n", port);
return fd; return fd;
} }
@ -619,81 +587,13 @@ ue9_streamconfig_simple(int fd, int *channel_list, int channel_count,
return 0; return 0;
} }
/* Stream configuration, each Analog Input channel can have its own gain. */
int
ue9_streamconfig(int fd, int *channel_list, int channel_count,
uint8_t scanconfig, uint16_t scaninterval, int *gain_list, int gain_count)
{
int i;
uint8_t buf[256];
/* Set up StreamConfig command with channels and scan options */
buf[1] = 0xF8; /* Extended command */
buf[2] = channel_count + 3; /* Command data words */
buf[3] = 0x11; /* StreamConfig */
buf[6] = channel_count; /* Number of channels */
buf[7] = 12; /* Bit resolution */
buf[8] = 0; /* Extra settling time */
buf[9] = scanconfig;
buf[10] = scaninterval & 0xff;
buf[11] = scaninterval >> 8;
for (i = 0; i < channel_count; i++) {
buf[12 + 2 * i] = channel_list[i]; /* Channel number */
if (i < gain_count) {
switch (gain_list[i]) {
case 0:
buf[13 + 2 * i] = UE9_BIPOLAR_GAIN1;
break;
case 1:
buf[13 + 2 * i] = UE9_UNIPOLAR_GAIN1;
break;
case 2:
buf[13 + 2 * i] = UE9_UNIPOLAR_GAIN2;
break;
case 4:
buf[13 + 2 * i] = UE9_UNIPOLAR_GAIN4;
break;
case 8:
buf[13 + 2 * i] = UE9_UNIPOLAR_GAIN8;
break;
default:
buf[13 + 2 * i] = UE9_BIPOLAR_GAIN1;
}
}
else
{
buf[13 + 2 * i] = UE9_BIPOLAR_GAIN1;
}
}
/* Send StreamConfig */
if (ue9_command(fd, buf, buf, 8) < 0) {
debug("command failed\n");
return -1;
}
if (buf[6] != 0) {
verb("returned error %s\n", ue9_error(buf[6]));
return -1;
}
return 0;
}
/* Timer configuration */ /* Timer configuration */
int ue9_timer_config(int fd, int *mode_list, int *value_list, int count, int divisor) int ue9_timer_config(int fd, int *mode_list, int mode_count, int divisor)
{ {
int i; int i;
uint8_t buf[256]; uint8_t buf[256];
if (count < 0 || count > 6) { if (mode_count < 0 || mode_count > 6) {
verb("invalid count\n"); verb("invalid count\n");
return -1; return -1;
} }
@ -703,21 +603,17 @@ int ue9_timer_config(int fd, int *mode_list, int *value_list, int count, int div
buf[2] = 0x0C; /* Command data words */ buf[2] = 0x0C; /* Command data words */
buf[3] = 0x18; /* TimerConfig */ buf[3] = 0x18; /* TimerConfig */
buf[6] = divisor; /* TimerClockDivisor */ buf[6] = divisor; /* TimerClockDivisor */
buf[7] = 0x80 | count; /* Number of timers enabled, UpdateConfig=1 */ buf[7] = 0x80 | mode_count; /* Number of timers enabled, UpdateConfig=1 */
buf[8] = 0x01; /* TimerClockBase = System 48MHz */ buf[8] = 0x01; /* TimerClockBase = System 48MHz */
buf[9] = 0x00; /* Don't reset */ buf[9] = 0x00; /* Don't reset */
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
if (i < count) { if (i < mode_count)
buf[10 + 3 * i] = mode_list[i]; buf[10 + 3 * i] = mode_list[i];
buf[11 + 3 * i] = value_list[i] & 0xff; else
buf[12 + 3 * i] = value_list[i] >> 8;
}
else {
buf[10 + 3 * i] = 0; buf[10 + 3 * i] = 0;
buf[11 + 3 * i] = 0; buf[11 + 3 * i] = 0;
buf[12 + 3 * i] = 0; buf[12 + 3 * i] = 0;
}
} }
buf[28] = 0; buf[28] = 0;
@ -742,7 +638,7 @@ int ue9_timer_config(int fd, int *mode_list, int *value_list, int count, int div
/* Stream data and pass it to the data callback. If callback returns /* Stream data and pass it to the data callback. If callback returns
negative, stops reading and returns 0. Returns < 0 on error. */ negative, stops reading and returns 0. Returns < 0 on error. */
int int
ue9_stream_data(int fd, int channels, int *channel_list, int gain_count, int *gain_list, ue9_stream_cb_t callback, void *context) ue9_stream_data(int fd, int channels, ue9_stream_cb_t callback, void *context)
{ {
int ret; int ret;
uint8_t buf[46]; uint8_t buf[46];
@ -754,7 +650,7 @@ ue9_stream_data(int fd, int channels, int *channel_list, int gain_count, int *ga
for (;;) { for (;;) {
/* Receive data */ /* Receive data */
ret = recv_all_timeout(fd, buf, 46, 0, &(struct timeval) { ret = recv_all_timeout(fd, buf, 46, 0, &(struct timeval) {
.tv_sec = TIMEOUT}); .tv_sec = UE9_TIMEOUT});
/* Verify packet format */ /* Verify packet format */
if (ret != 46) { if (ret != 46) {
@ -811,7 +707,7 @@ ue9_stream_data(int fd, int channels, int *channel_list, int gain_count, int *ga
/* Received a full scan, send to callback */ /* Received a full scan, send to callback */
channel = 0; channel = 0;
if ((*callback) (channels, channel_list, gain_count, gain_list, data, context) < 0) { if ((*callback) (channels, data, context) < 0) {
/* We're done */ /* We're done */
return 0; return 0;
} }
@ -821,6 +717,6 @@ ue9_stream_data(int fd, int channels, int *channel_list, int gain_count, int *ga
/* /*
Local variables: Local variables:
c-basic-offset: 8 c-basic-offset: 2
End: End:
*/ */

18
ue9.h
View File

@ -68,7 +68,6 @@ struct ue9ControlConfig {
uint16_t dac1; uint16_t dac1;
}; };
/* These are correct! 0, 1, 2, 3, 8 */
#define UE9_UNIPOLAR_GAIN1 0x00 #define UE9_UNIPOLAR_GAIN1 0x00
#define UE9_UNIPOLAR_GAIN2 0x01 #define UE9_UNIPOLAR_GAIN2 0x01
#define UE9_UNIPOLAR_GAIN4 0x02 #define UE9_UNIPOLAR_GAIN4 0x02
@ -77,7 +76,6 @@ struct ue9ControlConfig {
#define UE9_MAX_CHANNEL_COUNT 128 #define UE9_MAX_CHANNEL_COUNT 128
#define UE9_MAX_CHANNEL 255 #define UE9_MAX_CHANNEL 255
#define UE9_MAX_ANALOG_CHANNEL 13
#define UE9_TIMERS 6 #define UE9_TIMERS 6
/* Fill checksums in data buffers */ /* Fill checksums in data buffers */
@ -105,10 +103,7 @@ int ue9_get_control_config(int fd, struct ue9ControlConfig *config);
/* Data conversion. If calib is NULL, use uncalibrated conversions. */ /* Data conversion. If calib is NULL, use uncalibrated conversions. */
double ue9_binary_to_analog(struct ue9Calibration *calib, double ue9_binary_to_analog(struct ue9Calibration *calib,
int gain, uint8_t resolution, uint16_t data); uint8_t gain, uint8_t resolution, uint16_t data);
/* Temperature conversion. If calib is NULL, use uncalibrated conversions. */
double ue9_binary_to_temperature(struct ue9Calibration *calib, uint16_t data);
/* Compute scanrate based on the provided values. */ /* Compute scanrate based on the provided values. */
double ue9_compute_rate(uint8_t scanconfig, uint16_t scaninterval); double ue9_compute_rate(uint8_t scanconfig, uint16_t scaninterval);
@ -139,18 +134,13 @@ int ue9_streamconfig_simple(int fd, int *channel_list, int channel_count,
uint8_t scanconfig, uint16_t scaninterval, uint8_t scanconfig, uint16_t scaninterval,
uint8_t gain); uint8_t gain);
/* Stream configuration, each Analog Input channel can have its own gain. */
int ue9_streamconfig(int fd, int *channel_list, int channel_count,
uint8_t scanconfig, uint16_t scaninterval,
int *gain_list, int gain_count);
/* Timer configuration */ /* Timer configuration */
int ue9_timer_config(int fd, int *mode_list, int *value_list, int count, int divisor); int ue9_timer_config(int fd, int *mode_list, int mode_count, int divisor);
/* Stream data and pass it to the data callback. If callback returns /* Stream data and pass it to the data callback. If callback returns
negative, stops reading and returns 0. Returns < 0 on error. */ negative, stops reading and returns 0. Returns < 0 on error. */
typedef int (*ue9_stream_cb_t) (int channels, int *channel_list, int gain_count, int *gain_list, uint16_t * data, void *context); typedef int (*ue9_stream_cb_t) (int channels, uint16_t * data, void *context);
int ue9_stream_data(int fd, int channels, int *channel_list, int gain_count, int *gain_list, int ue9_stream_data(int fd, int channels,
ue9_stream_cb_t callback, void *context); ue9_stream_cb_t callback, void *context);
#endif #endif

View File

@ -1,2 +1,2 @@
/* This file was automatically generated. */ /* This file was automatically generated. */
#define VERSION "1.3.2 (2016-07-13)" #define VERSION "1.2 (2010-02-08)"