Commit cd63e2fb by jim

Move ethstream to the parent directory


git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@8314 ddd99763-3ecb-0310-9145-efcb8ce7c51f
parent 329871bf
...@@ -32,11 +32,11 @@ default: lin ...@@ -32,11 +32,11 @@ default: lin
all: lin win all: lin win
.PHONY: lin .PHONY: lin
lin: ljtest ethstream ljconfig \ lin: ethstream \
ethstream.1 ljconfig.1 ethstream.1
.PHONY: win .PHONY: win
win: ljtest.exe ethstream.exe ljconfig.exe win: ethstream.exe
version.h: VERSION version.h: VERSION
...@@ -46,17 +46,11 @@ version.h: VERSION ...@@ -46,17 +46,11 @@ version.h: VERSION
# Object files for each executable # Object files for each executable
obj-common = opt.o ue9.o ue9error.o netutil.o debug.o nerdjack.o obj-common = opt.o ue9.o ue9error.o netutil.o debug.o nerdjack.o
obj-ljconfig = ljconfig.o $(obj-common)
obj-ethstream = ethstream.o $(obj-common) obj-ethstream = ethstream.o $(obj-common)
obj-ljtest = ljtest.o $(obj-common)
ljconfig: $(obj-ljconfig)
ethstream: $(obj-ethstream) ethstream: $(obj-ethstream)
ljtest: $(obj-ljtest)
ljconfig.exe: $(obj-ljconfig:.o=.obj) compat-win32.obj
ethstream.exe: $(obj-ethstream:.o=.obj) compat-win32.obj ethstream.exe: $(obj-ethstream:.o=.obj) compat-win32.obj
ljtest.exe: $(obj-ljtest:.o=.obj) compat-win32.obj
# Manpages # Manpages
...@@ -92,7 +86,7 @@ dist: version.h ...@@ -92,7 +86,7 @@ dist: version.h
.PHONY: clean distclean .PHONY: clean distclean
clean distclean: clean distclean:
rm -f *.o *.obj *.exe ethstream ljtest ljconfig core *.d *.1 *.txt rm -f *.o *.obj *.exe ethstream core *.d *.1 *.txt
# Dependency tracking: # Dependency tracking:
......
...@@ -2,5 +2,10 @@ Labjack/Nerdjack Tools ...@@ -2,5 +2,10 @@ Labjack/Nerdjack Tools
by Jim Paris <jim@jtan.com> by Jim Paris <jim@jtan.com>
with modifications by Zach Clifford <zacharyc@mit.edu> with modifications by Zach Clifford <zacharyc@mit.edu>
These tools are for interacting with the LabJack UE9 or the NerdJack over the Ethernet interface. More information about the UE9 device: These tools are for interacting with the LabJack UE9 or the NerdJack
over the Ethernet interface. More information about the UE9 device:
http://www.labjack.com/labjack_ue9.php http://www.labjack.com/labjack_ue9.php
The NerdJack device is a custom board made in LEES by Zach Clifford.
Use ethstream -h or ethstream -X for usage instructions and examples.
...@@ -3,70 +3,44 @@ ...@@ -3,70 +3,44 @@
#include "compat.h" #include "compat.h"
#include <windows.h> #include <windows.h>
unsigned int unsigned int sleep(unsigned int seconds)
sleep (unsigned int seconds)
{ {
Sleep (seconds * 1000); Sleep(seconds * 1000);
return 0; return 0;
} }
static struct static struct {
{
int num; int num;
char *msg; char *msg;
} win32_error[] = } win32_error[] = {
{
/* Errors that we might vaguely expect to see */ /* Errors that we might vaguely expect to see */
{ { WSAEINTR, "Winsock: Interrupted system call"},
WSAEINTR, "Winsock: Interrupted system call"}, { WSAEBADF, "Winsock: Bad file number"},
{ { WSAEFAULT, "Winsock: Bad address"},
WSAEBADF, "Winsock: Bad file number"}, { WSAEINVAL, "Winsock: Invalid argument"},
{ { WSAEMFILE, "Winsock: Too many open files"},
WSAEFAULT, "Winsock: Bad address"}, { WSAEWOULDBLOCK, "Winsock: Operation would block"},
{ { WSAEINPROGRESS, "Winsock: Operation now in progress"},
WSAEINVAL, "Winsock: Invalid argument"}, { WSAEALREADY, "Winsock: Operation already in progress"},
{ { WSAENOTSOCK, "Winsock: Socket operation on nonsocket"},
WSAEMFILE, "Winsock: Too many open files"}, { WSAEADDRINUSE, "Winsock: Address already in use"},
{ { WSAEADDRNOTAVAIL, "Winsock: Cannot assign requested address"},
WSAEWOULDBLOCK, "Winsock: Operation would block"}, { WSAENETDOWN, "Winsock: Network is down"},
{ { WSAENETUNREACH, "Winsock: Network is unreachable"},
WSAEINPROGRESS, "Winsock: Operation now in progress"}, { WSAENETRESET, "Winsock: Network dropped connection on reset"},
{ { WSAECONNABORTED, "Winsock: Software caused connection abort"},
WSAEALREADY, "Winsock: Operation already in progress"}, { WSAECONNRESET, "Winsock: Connection reset by peer"},
{ { WSAETIMEDOUT, "Winsock: Connection timed out"},
WSAENOTSOCK, "Winsock: Socket operation on nonsocket"}, { WSAECONNREFUSED, "Winsock: Connection refused"},
{ { WSAEHOSTDOWN, "Winsock: Host is down"},
WSAEADDRINUSE, "Winsock: Address already in use"}, { WSAEHOSTUNREACH, "Winsock: No route to host"},
{ { WSAVERNOTSUPPORTED, "Winsock: Unsupported Winsock version"},
WSAEADDRNOTAVAIL, "Winsock: Cannot assign requested address"}, { ETIMEDOUT, "Connection timed out"},
{ { ENOTCONN, "Not connected"},
WSAENETDOWN, "Winsock: Network is down"}, { -1, NULL},
{ };
WSAENETUNREACH, "Winsock: Network is unreachable"},
{ char *compat_strerror(int errnum)
WSAENETRESET, "Winsock: Network dropped connection on reset"},
{
WSAECONNABORTED, "Winsock: Software caused connection abort"},
{
WSAECONNRESET, "Winsock: Connection reset by peer"},
{
WSAETIMEDOUT, "Winsock: Connection timed out"},
{
WSAECONNREFUSED, "Winsock: Connection refused"},
{
WSAEHOSTDOWN, "Winsock: Host is down"},
{
WSAEHOSTUNREACH, "Winsock: No route to host"},
{
WSAVERNOTSUPPORTED, "Winsock: Unsupported Winsock version"},
{
ETIMEDOUT, "Connection timed out"},
{
ENOTCONN, "Not connected"},
{
-1, NULL},};
char *
compat_strerror (int errnum)
{ {
int i; int i;
static char buf[128]; static char buf[128];
...@@ -74,12 +48,11 @@ compat_strerror (int errnum) ...@@ -74,12 +48,11 @@ compat_strerror (int errnum)
for (i = 0; win32_error[i].num != -1; i++) for (i = 0; win32_error[i].num != -1; i++)
if (errnum == win32_error[i].num) if (errnum == win32_error[i].num)
return win32_error[i].msg; return win32_error[i].msg;
if (errnum >= 10000) if (errnum >= 10000) {
{ sprintf(buf, "Winsock: unknown error %d\n", errnum);
sprintf (buf, "Winsock: unknown error %d\n", errnum);
return buf; return buf;
} }
return strerror (errnum); return strerror(errnum);
} }
#ifdef __WIN32__ #ifdef __WIN32__
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
#define COMPAT_H #define COMPAT_H
#ifdef __WIN32__ #ifdef __WIN32__
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 INET_ADDRSTRLEN 16
#define ETIMEDOUT 110 #define ETIMEDOUT 110
......
...@@ -4,15 +4,14 @@ ...@@ -4,15 +4,14 @@
int verb_count = 0; int verb_count = 0;
int int func_fprintf(const char *func, FILE * stream, const char *format, ...)
func_fprintf (const char *func, FILE * stream, const char *format, ...)
{ {
va_list ap; va_list ap;
int ret; int ret;
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;
} }
...@@ -14,8 +14,8 @@ extern int verb_count; ...@@ -14,8 +14,8 @@ extern int verb_count;
#include <stdio.h> #include <stdio.h>
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)));
#define debug(x...) ({ \ #define debug(x...) ({ \
if(verb_count >= 2) \ if(verb_count >= 2) \
......
...@@ -6,15 +6,18 @@ char examplestring[] = "\n\ ...@@ -6,15 +6,18 @@ char examplestring[] = "\n\
For the most part, typing \"ethstream\" by itself will sample the first\n\ For the most part, typing \"ethstream\" by itself will sample the first\n\
two channels at 8 kHz on 10V range. Press CTRL-C to terminate sampling.\n\ two channels at 8 kHz on 10V range. Press CTRL-C to terminate sampling.\n\
\n\ \n\
If you want a voltage and current measurement on the first phase of NILM\n\ If you want current measurements on the first two phases of NILM\n\
with default sample rate of 8 kHz and 10V range:\n\ with default sample rate of 8 kHz and 10V range:\n\
\n\ \n\
ethstream -C 0,3\n\ ethstream -C 0,3\n\
\n\ \n\
The device is configured so that channels 0 through 2 are voltages for\n\ The device is configured so that channels 0 through 2 are currents for\n\
the three phases and channels 3-5 are for currents of the three phases\n\ the three phases and channels 3-5 are for voltages of the three phases.\n\
The current channels sample voltages that will depend on the DIP switch\n\
settings in the NILM box. The DIP switch positions allow you to convert\n\
ethstream's readings to true current readings.\n\
\n\ \n\
If you want only voltages at 16 kHz and 10V range:\n\ If you want only currents at 16 kHz and 10V range:\n\
\n\ \n\
ethstream -n 3 -r 16000\n\ ethstream -n 3 -r 16000\n\
\n\ \n\
...@@ -26,20 +29,20 @@ all 12 at once.\n\ ...@@ -26,20 +29,20 @@ all 12 at once.\n\
Ethstream will warn if you approach the limits of the NerdJack with the\n\ Ethstream will warn if you approach the limits of the NerdJack with the\n\
given sampled channels. Sampling outside the range of the NerdJack might\n\ given sampled channels. Sampling outside the range of the NerdJack might\n\
result in corrupt data or crashing of the device. There will be no\n\ result in corrupt data or crashing of the device. There will be no\n\
permanent damage to NILM or NerdJack.\n\ permanent damage to NILM or NerdJack, but be aware of the possibility of\n\
data corruption.\n\
\n\ \n\
If you need a higher accuracy but lower range measurement on the currents:\n\ If you need a higher accuracy but lower range measurement on the voltages:\n\
\n\ \n\
ethstream -R 5,10 -C 3,4,5\n\ ethstream -R 5,10 -C 3,4,5\n\
\n\ \n\
The two numbers to the R command set the range to either 5V or 10V. Above,\n\ The two numbers to the R command set the range to either 5V or 10V. Above,\n\
we are setting channels 0-5 to 5 V range and channels 6-11 to 10 V range.\n\ we are setting channels 0-5 to 5 V range and channels 6-11 to 10 V range.\n\
Channels 6-11 are unconnected, but they can have range set independently.\n\ Channels 6-11 are unconnected, but they can have range set independently.\n\
The values here depend on the NILM box settings to the current transducers.\n\
The value read is the voltage seen by the NerdJack.\n\
\n\ \n\
All of the above examples output a digital number from 0 to 65535 with\n\ All of the above examples output a digital number from 0 to 65535 with\n\
65535 representing the highest range (5V or 10V). If you want conversion\n\ 65535 representing the highest range (5V or 10V). 0 represents the most\n\
negative range (-5V or -10V). If you want conversion\n\
to volts for all six voltages and currents:\n\ to volts for all six voltages and currents:\n\
\n\ \n\
ethstream -c -C 0,3,1,4,2,5\n\ ethstream -c -C 0,3,1,4,2,5\n\
......
/*
* Labjack Tools
* Copyright (c) 2003-2007 Jim Paris <jim@jtan.com>
*
* This is free software; you can redistribute it and/or modify it and
* it is provided under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation; see COPYING.
*/
/* ljconfig: display/change comm/control processor configuration */
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "debug.h"
#include "ue9.h"
#include "ue9error.h"
#include "opt.h"
#include "version.h"
#define DEFAULT_HOST "192.168.1.209"
#define UE9_COMMAND_PORT 52360
struct options opt[] = {
{'a', "address", "string", "host/address of UE9 (192.168.1.209)"},
{'h', "help", NULL, "this help"},
{'v', "verbose", NULL, "be verbose"},
{'V', "version", NULL, "show version number and exit"},
{0, NULL, NULL, NULL}
};
int
main (int argc, char *argv[])
{
int optind;
char *optarg;
char c;
FILE *help = stderr;
char *address = strdup (DEFAULT_HOST);
int fd;
int ret;
/* Parse arguments */
opt_init (&optind);
while ((c = opt_parse (argc, argv, &optind, &optarg, opt)) != 0)
{
switch (c)
{
case 'a':
free (address);
address = strdup (optarg);
break;
case 'v':
verb_count++;
break;
case 'V':
printf ("ljconfig " VERSION "\n");
printf ("Written by Jim Paris <jim@jtan.com>\n");
printf ("This program comes with no warranty and is "
"provided under the GPLv2.\n");
return 0;
break;
case 'h':
help = stdout;
default:
printhelp:
fprintf (help, "Usage: %s [options]\n", *argv);
opt_help (opt, help);
fprintf (help, "Displays/changes Labjack UE9 config.\n");
return (help == stdout) ? 0 : 1;
}
}
if (optind < argc)
{
info ("Error: too many arguments (%s)\n\n", argv[optind]);
goto printhelp;
}
ret = 1;
/* Open */
fd = ue9_open (address, UE9_COMMAND_PORT);
if (fd < 0)
{
info ("Connect failed: %s:%d\n", address, UE9_COMMAND_PORT);
goto out0;
}
goto out1;
ret = 0;
out1:
/* Close */
ue9_close (fd);
out0:
return ret;
}
/*
* Labjack Tools
* Copyright (c) 2003-2007 Jim Paris <jim@jtan.com>
*
* This is free software; you can redistribute it and/or modify it and
* it is provided under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation; see COPYING.
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "debug.h"
#include "ue9.h"
#include "compat.h"
int
main (int argc, char *argv[])
{
int fd_cmd;
struct ue9Calibration calib;
verb_count = 2;
fd_cmd = ue9_open ("192.168.1.209", 52360);
if (fd_cmd < 0)
{
fprintf (stderr, "ue9_open: %s\n", compat_strerror (errno));
return 1;
}
if (ue9_get_calibration (fd_cmd, &calib) < 0)
{
fprintf (stderr, "ue9_get_calibration: %s\n", compat_strerror (errno));
return 1;
}
printf ("double unipolarSlope[0] = %lf\n", calib.unipolarSlope[0]);
printf ("double unipolarSlope[1] = %lf\n", calib.unipolarSlope[1]);
printf ("double unipolarSlope[2] = %lf\n", calib.unipolarSlope[2]);
printf ("double unipolarSlope[3] = %lf\n", calib.unipolarSlope[3]);
printf ("double unipolarOffset[0] = %lf\n", calib.unipolarOffset[0]);
printf ("double unipolarOffset[1] = %lf\n", calib.unipolarOffset[1]);
printf ("double unipolarOffset[2] = %lf\n", calib.unipolarOffset[2]);
printf ("double unipolarOffset[3] = %lf\n", calib.unipolarOffset[3]);
printf ("double bipolarSlope = %lf\n", calib.bipolarSlope);
printf ("double bipolarOffset = %lf\n", calib.bipolarOffset);
printf ("double DACSlope[0] = %lf\n", calib.DACSlope[0]);
printf ("double DACSlope[1] = %lf\n", calib.DACSlope[1]);
printf ("double DACOffset[0] = %lf\n", calib.DACOffset[0]);
printf ("double DACOffset[1] = %lf\n", calib.DACOffset[1]);
printf ("double tempSlope = %lf\n", calib.tempSlope);
printf ("double tempSlopeLow = %lf\n", calib.tempSlopeLow);
printf ("double calTemp = %lf\n", calib.calTemp);
printf ("double Vref = %lf\n", calib.Vref);
printf ("double VrefDiv2 = %lf\n", calib.VrefDiv2);
printf ("double VsSlope = %lf\n", calib.VsSlope);
printf ("double hiResUnipolarSlope = %lf\n", calib.hiResUnipolarSlope);
printf ("double hiResUnipolarOffset = %lf\n", calib.hiResUnipolarOffset);
printf ("double hiResBipolarSlope = %lf\n", calib.hiResBipolarSlope);
printf ("double hiResBipolarOffset = %lf\n", calib.hiResBipolarOffset);
ue9_close (fd_cmd);
return 0;
}
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
#define NERDJACK_NUM_SAMPLES 726 #define NERDJACK_NUM_SAMPLES 726
/* 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 long period; unsigned long period;
unsigned short channelbit; unsigned short channelbit;
...@@ -35,29 +34,32 @@ typedef struct __attribute__ ((__packed__)) ...@@ -35,29 +34,32 @@ typedef struct __attribute__ ((__packed__))
} getPacket; } getPacket;
/* Open/close TCP/IP connection to the NerdJack */ /* Open/close TCP/IP connection to the NerdJack */
int nerd_open (const char *address, int port); int nerd_open(const char *address, int port);
int nerd_close_conn (int data_fd); int nerd_close_conn(int data_fd);
/* Generate the command word for the NerdJack */ /* Generate the command word for the NerdJack */
int nerd_generate_command (getPacket * command, int *channel_list, int nerd_generate_command(getPacket * command, int *channel_list,
int channel_count, int precision, int channel_count, int precision,
unsigned long period); unsigned long period);
/* Send given command to NerdJack */ /* Send given command to NerdJack */
int nerd_send_command (const char *address, void *command, int length); int nerd_send_command(const char *address, void *command, int length);
/* Get the version string from NerdJack */
int nerd_get_version(const char *address);
/* Stream data out of the NerdJack */ /* Stream data out of the NerdJack */
int nerd_data_stream (int data_fd, int numChannels, int *channel_list, int nerd_data_stream(int data_fd, int numChannels, int *channel_list,
int precision, int convert, int lines, int showmem, int precision, int convert, int lines, int showmem,
unsigned short *currentcount, unsigned int period, unsigned short *currentcount, unsigned int period,
int wasreset); int wasreset);
/* Detect the IP Address of the NerdJack and return in ipAddress */ /* Detect the IP Address of the NerdJack and return in ipAddress */
int nerdjack_detect (char *ipAddress); int nerdjack_detect(char *ipAddress);
/* Choose the best ScanConfig and ScanInterval parameters for the /* Choose the best ScanConfig and ScanInterval parameters for the
desired scanrate. Returns -1 if no valid config found */ desired scanrate. Returns -1 if no valid config found */
int nerdjack_choose_scan (double desired_rate, double *actual_rate, int nerdjack_choose_scan(double desired_rate, double *actual_rate,
unsigned long *period); unsigned long *period);
#endif #endif
...@@ -5,31 +5,28 @@ ...@@ -5,31 +5,28 @@
#include <stdio.h> #include <stdio.h>
/* Initialize networking */ /* Initialize networking */
void void net_init(void)
net_init (void)
{ {
#ifdef __WIN32__ #ifdef __WIN32__
WSADATA blah; WSADATA blah;
WSAStartup (0x0101, &blah); WSAStartup(0x0101, &blah);
#endif #endif
} }
/* Set socket blocking/nonblocking */ /* Set socket blocking/nonblocking */
int int soblock(int socket, int blocking)
soblock (int socket, int blocking)
{ {
#ifdef __WIN32__ #ifdef __WIN32__
unsigned long arg = blocking ? 0 : 1; unsigned long arg = blocking ? 0 : 1;
if (ioctlsocket (socket, FIONBIO, &arg) != 0) if (ioctlsocket(socket, FIONBIO, &arg) != 0)
return -1; return -1;
return 0; return 0;
#else #else
int sockopt; int sockopt;
/* Get flags */ /* Get flags */
sockopt = fcntl (socket, F_GETFL); sockopt = fcntl(socket, F_GETFL);
if (sockopt == -1) if (sockopt == -1) {
{
return -1; return -1;
} }
...@@ -40,17 +37,16 @@ soblock (int socket, int blocking) ...@@ -40,17 +37,16 @@ soblock (int socket, int blocking)
sockopt |= O_NONBLOCK; sockopt |= O_NONBLOCK;
/* Set flags */ /* Set flags */
if (fcntl (socket, F_SETFL, sockopt) != 0) if (fcntl(socket, F_SETFL, sockopt) != 0)
return -1; return -1;
return 0; return 0;
#endif #endif
} }
/* Like connect(2), but with a timeout. Socket must be non-blocking. */ /* Like connect(2), but with a timeout. Socket must be non-blocking. */
int int
connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen, connect_timeout(int s, const struct sockaddr *serv_addr, socklen_t addrlen,
struct timeval *timeout) struct timeval *timeout)
{ {
int ret; int ret;
...@@ -60,17 +56,16 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen, ...@@ -60,17 +56,16 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen,
socklen_t optlen; socklen_t optlen;
/* Start connect */ /* Start connect */
ret = connect (s, serv_addr, addrlen); ret = connect(s, serv_addr, addrlen);
if (ret == 0) if (ret == 0) {
{
/* Success */ /* Success */
return 0; return 0;
} }
/* Check for immediate failure */ /* Check for immediate failure */
#ifdef __WIN32__ #ifdef __WIN32__
errno = WSAGetLastError (); errno = WSAGetLastError();
if (ret < 0 && errno != WSAEWOULDBLOCK && errno != WSAEINVAL) if (ret < 0 && errno != WSAEWOULDBLOCK && errno != WSAEINVAL)
return -1; return -1;
#else #else
...@@ -79,30 +74,27 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen, ...@@ -79,30 +74,27 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen,
#endif #endif
/* In progress, wait for result. */ /* In progress, wait for result. */
FD_ZERO (&writefds); FD_ZERO(&writefds);
FD_SET (s, &writefds); FD_SET(s, &writefds);
FD_ZERO (&exceptfds); FD_ZERO(&exceptfds);
FD_SET (s, &exceptfds); FD_SET(s, &exceptfds);
ret = select (s + 1, NULL, &writefds, &exceptfds, timeout); ret = select(s + 1, NULL, &writefds, &exceptfds, timeout);
if (ret < 0) if (ret < 0) {
{
/* Error */ /* Error */
return -1; return -1;
} }
if (ret == 0) if (ret == 0) {
{
/* Timed out */ /* Timed out */
errno = ETIMEDOUT; errno = ETIMEDOUT;
return -1; return -1;
} }
/* Check the socket state */ /* Check the socket state */
optlen = sizeof (optval); optlen = sizeof(optval);
if (getsockopt (s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen) != 0) if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen) != 0)
return -1; return -1;
if (optval != 0) if (optval != 0) {
{
/* Connection failed. */ /* Connection failed. */
errno = optval; errno = optval;
return -1; return -1;
...@@ -110,8 +102,7 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen, ...@@ -110,8 +102,7 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen,
/* On Windows, SO_ERROR sometimes shows no error but the connection /* On Windows, SO_ERROR sometimes shows no error but the connection
still failed. Sigh. */ still failed. Sigh. */
if (FD_ISSET (s, &exceptfds) || !FD_ISSET (s, &writefds)) if (FD_ISSET(s, &exceptfds) || !FD_ISSET(s, &writefds)) {
{
errno = EIO; errno = EIO;
return -1; return -1;
} }
...@@ -124,103 +115,95 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen, ...@@ -124,103 +115,95 @@ connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen,
The timeout only applies if no data at all is sent -- this function The timeout only applies if no data at all is sent -- this function
may still send less than requested. */ may still send less than requested. */
ssize_t ssize_t
send_timeout (int s, const void *buf, size_t len, int flags, send_timeout(int s, const void *buf, size_t len, int flags,
struct timeval * timeout) struct timeval * timeout)
{ {
fd_set writefds; fd_set writefds;
int ret; int ret;
FD_ZERO (&writefds); FD_ZERO(&writefds);
FD_SET (s, &writefds); FD_SET(s, &writefds);
ret = select (s + 1, NULL, &writefds, NULL, timeout); ret = select(s + 1, NULL, &writefds, NULL, timeout);
if (ret == 0) if (ret == 0) {
{
/* Timed out */ /* Timed out */
errno = ETIMEDOUT; errno = ETIMEDOUT;
return -1; return -1;
} }
if (ret != 1) if (ret != 1) {
{
/* Error */ /* Error */
return -1; return -1;
} }
return send (s, buf, len, flags); return send(s, buf, len, flags);
} }
/* Like recv(2), but with a timeout. Socket must be non-blocking. /* Like recv(2), but with a timeout. Socket must be non-blocking.
The timeout only applies if no data at all is received -- this The timeout only applies if no data at all is received -- this
function may still return less than requested. */ function may still return less than requested. */
ssize_t ssize_t
recv_timeout (int s, void *buf, size_t len, int flags, recv_timeout(int s, void *buf, size_t len, int flags, struct timeval * timeout)
struct timeval * timeout)
{ {
fd_set readfds; fd_set readfds;
int ret; int ret;
FD_ZERO (&readfds); FD_ZERO(&readfds);
FD_SET (s, &readfds); FD_SET(s, &readfds);
ret = select (s + 1, &readfds, NULL, NULL, timeout); ret = select(s + 1, &readfds, NULL, NULL, timeout);
if (ret == 0) if (ret == 0) {
{
/* Timed out */ /* Timed out */
errno = ETIMEDOUT; errno = ETIMEDOUT;
return -1; return -1;
} }
if (ret != 1) if (ret != 1) {
{
/* Error */ /* Error */
return -1; return -1;
} }
return recv (s, buf, len, flags); return recv(s, buf, len, flags);
} }
/* Like recvfrom(2), but with a timeout. Socket must be non-blocking. /* Like recvfrom(2), but with a timeout. Socket must be non-blocking.
The timeout only applies if no data at all is received -- this The timeout only applies if no data at all is received -- this
function may still return less than requested. */ function may still return less than requested. */
ssize_t ssize_t
recvfrom_timeout (int s, void *buf, size_t len, int flags, recvfrom_timeout(int s, void *buf, size_t len, int flags,
struct sockaddr * address, socklen_t * address_len, struct sockaddr * address, socklen_t * address_len,
struct timeval * timeout) struct timeval * timeout)
{ {
fd_set readfds; fd_set readfds;
int ret; int ret;
FD_ZERO (&readfds); FD_ZERO(&readfds);
FD_SET (s, &readfds); FD_SET(s, &readfds);
ret = select (s + 1, &readfds, NULL, NULL, timeout); ret = select(s + 1, &readfds, NULL, NULL, timeout);
if (ret == 0) if (ret == 0) {
{
/* Timed out */ /* Timed out */
errno = ETIMEDOUT; errno = ETIMEDOUT;
return -1; return -1;
} }
if (ret != 1) if (ret != 1) {
{
/* Error */ /* Error */
return -1; return -1;
} }
return recvfrom (s, buf, len, flags, address, address_len); return recvfrom(s, buf, len, flags, address, address_len);
} }
/* Like send_timeout, but retries (with the same timeout) in case of /* Like send_timeout, but retries (with the same timeout) in case of
partial transfers. This is a stronger attempt to send all partial transfers. This is a stronger attempt to send all
requested data. */ requested data. */
ssize_t ssize_t
send_all_timeout (int s, const void *buf, size_t len, int flags, send_all_timeout(int s, const void *buf, size_t len, int flags,
struct timeval * timeout) struct timeval * timeout)
{ {
struct timeval tv; struct timeval tv;
size_t left = len; size_t left = len;
ssize_t ret; ssize_t ret;
while (left > 0) while (left > 0) {
{
tv.tv_sec = timeout->tv_sec; tv.tv_sec = timeout->tv_sec;
tv.tv_usec = timeout->tv_usec; tv.tv_usec = timeout->tv_usec;
ret = send_timeout (s, buf, left, flags, &tv); ret = send_timeout(s, buf, left, flags, &tv);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -239,18 +222,17 @@ send_all_timeout (int s, const void *buf, size_t len, int flags, ...@@ -239,18 +222,17 @@ send_all_timeout (int s, const void *buf, size_t len, int flags,
partial transfers. This is a stronger attempt to recv all partial transfers. This is a stronger attempt to recv all
requested data. */ requested data. */
ssize_t ssize_t
recv_all_timeout (int s, void *buf, size_t len, int flags, recv_all_timeout(int s, void *buf, size_t len, int flags,
struct timeval * timeout) struct timeval * timeout)
{ {
struct timeval tv; struct timeval tv;
size_t left = len; size_t left = len;
ssize_t ret; ssize_t ret;
while (left > 0) while (left > 0) {
{
tv.tv_sec = timeout->tv_sec; tv.tv_sec = timeout->tv_sec;
tv.tv_usec = timeout->tv_usec; tv.tv_usec = timeout->tv_usec;
ret = recv_timeout (s, buf, left, flags, &tv); ret = recv_timeout(s, buf, left, flags, &tv);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -27,28 +27,28 @@ ...@@ -27,28 +27,28 @@
#endif #endif
/* Initialize networking */ /* Initialize networking */
void net_init (void); void net_init(void);
/* Set socket blocking/nonblocking */ /* Set socket blocking/nonblocking */
int soblock (int socket, int blocking); int soblock(int socket, int blocking);
/* Like send(2), recv(2), connect(2), but with timeouts. /* Like send(2), recv(2), connect(2), but with timeouts.
Socket must be O_NONBLOCK. */ Socket must be O_NONBLOCK. */
int connect_timeout (int s, const struct sockaddr *serv_addr, int connect_timeout(int s, const struct sockaddr *serv_addr,
socklen_t addrlen, struct timeval *timeout); socklen_t addrlen, struct timeval *timeout);
ssize_t send_timeout (int s, const void *buf, size_t len, int flags, ssize_t send_timeout(int s, const void *buf, size_t len, int flags,
struct timeval *timeout); struct timeval *timeout);
ssize_t recv_timeout (int s, void *buf, size_t len, int flags, ssize_t recv_timeout(int s, void *buf, size_t len, int flags,
struct timeval *timeout); struct timeval *timeout);
ssize_t recvfrom_timeout (int s, void *buf, size_t len, int flags, ssize_t recvfrom_timeout(int s, void *buf, size_t len, int flags,
struct sockaddr *address, socklen_t * address_len, struct sockaddr *address, socklen_t * address_len,
struct timeval *timeout); struct timeval *timeout);
/* Like send_timeout and recv_timeout, but they retry (with the same timeout) /* Like send_timeout and recv_timeout, but they retry (with the same timeout)
in case of partial transfers, in order to try to transfer all data. */ in case of partial transfers, in order to try to transfer all data. */
ssize_t send_all_timeout (int s, const void *buf, size_t len, int flags, ssize_t send_all_timeout(int s, const void *buf, size_t len, int flags,
struct timeval *timeout); struct timeval *timeout);
ssize_t recv_all_timeout (int s, void *buf, size_t len, int flags, ssize_t recv_all_timeout(int s, void *buf, size_t len, int flags,
struct timeval *timeout); struct timeval *timeout);
#endif #endif
...@@ -11,14 +11,13 @@ ...@@ -11,14 +11,13 @@
#include <string.h> #include <string.h>
#include "opt.h" #include "opt.h"
void void opt_init(int *optind)
opt_init (int *optind)
{ {
*optind = 0; *optind = 0;
} }
char char
opt_parse (int argc, char **argv, int *optind, char **optarg, opt_parse(int argc, char **argv, int *optind, char **optarg,
struct options *opt) struct options *opt)
{ {
char c; char c;
...@@ -28,8 +27,7 @@ opt_parse (int argc, char **argv, int *optind, char **optarg, ...@@ -28,8 +27,7 @@ opt_parse (int argc, char **argv, int *optind, char **optarg,
return 0; return 0;
if (argv[*optind][0] == '-' && if (argv[*optind][0] == '-' &&
argv[*optind][1] != '-' && argv[*optind][1] != 0) argv[*optind][1] != '-' && argv[*optind][1] != 0) {
{
/* Short option (or a bunch of 'em) */ /* Short option (or a bunch of 'em) */
/* Save this and shift others over */ /* Save this and shift others over */
c = argv[*optind][1]; c = argv[*optind][1];
...@@ -42,67 +40,58 @@ opt_parse (int argc, char **argv, int *optind, char **optarg, ...@@ -42,67 +40,58 @@ opt_parse (int argc, char **argv, int *optind, char **optarg,
for (i = 0; opt[i].shortopt != 0; i++) for (i = 0; opt[i].shortopt != 0; i++)
if (opt[i].shortopt == c) if (opt[i].shortopt == c)
break; break;
if (opt[i].shortopt == 0) if (opt[i].shortopt == 0) {
{ fprintf(stderr, "Error: unknown option '-%c'\n", c);
fprintf (stderr, "Error: unknown option '-%c'\n", c);
return '?'; return '?';
} }
if (opt[i].arg == NULL) if (opt[i].arg == NULL)
return c; return c;
(*optind)++; (*optind)++;
if (*optind >= argc || (argv[*optind][0] == '-' && if (*optind >= argc || (argv[*optind][0] == '-' &&
argv[*optind][1] != 0)) argv[*optind][1] != 0)) {
{ fprintf(stderr, "Error: option '-%c' requires an "
fprintf (stderr, "Error: option '-%c' requires an "
"argument\n", c); "argument\n", c);
return '?'; return '?';
} }
(*optarg) = argv[*optind]; (*optarg) = argv[*optind];
return c; return c;
} } else if (argv[*optind][0] == '-' &&
else if (argv[*optind][0] == '-' && argv[*optind][1] == '-' && argv[*optind][2] != 0) {
argv[*optind][1] == '-' && argv[*optind][2] != 0)
{
/* Long option */ /* Long option */
for (i = 0; (c = opt[i].shortopt) != 0; i++) for (i = 0; (c = opt[i].shortopt) != 0; i++)
if (strcmp (opt[i].longopt, argv[*optind] + 2) == 0) if (strcmp(opt[i].longopt, argv[*optind] + 2) == 0)
break; break;
if (opt[i].shortopt == 0) if (opt[i].shortopt == 0) {
{ fprintf(stderr, "Error: unknown option '%s'\n",
fprintf (stderr, "Error: unknown option '%s'\n", argv[*optind]); argv[*optind]);
return '?'; return '?';
} }
if (opt[i].arg == NULL) if (opt[i].arg == NULL)
return c; return c;
(*optind)++; (*optind)++;
if (*optind >= argc || (argv[*optind][0] == '-' && if (*optind >= argc || (argv[*optind][0] == '-' &&
argv[*optind][1] != 0)) argv[*optind][1] != 0)) {
{ fprintf(stderr, "Error: option '%s' requires an "
fprintf (stderr, "Error: option '%s' requires an "
"argument\n", argv[*optind - 1]); "argument\n", argv[*optind - 1]);
return '?'; return '?';
} }
(*optarg) = argv[*optind]; (*optarg) = argv[*optind];
return c; return c;
} } else {
else
{
/* End of options */ /* End of options */
return 0; return 0;
} }
} }
void void opt_help(struct options *opt, FILE * out)
opt_help (struct options *opt, FILE * out)
{ {
int i; int i;
int printed; int printed;
for (i = 0; opt[i].shortopt != 0; i++) for (i = 0; opt[i].shortopt != 0; i++) {
{ fprintf(out, " -%c, --%s%n", opt[i].shortopt,
fprintf (out, " -%c, --%s%n", opt[i].shortopt,
opt[i].longopt, &printed); opt[i].longopt, &printed);
fprintf (out, " %-*s%s\n", 30 - printed, fprintf(out, " %-*s%s\n", 30 - printed,
opt[i].arg ? opt[i].arg : "", opt[i].help); opt[i].arg ? opt[i].arg : "", opt[i].help);
} }
} }
...@@ -11,19 +11,18 @@ ...@@ -11,19 +11,18 @@
#include <stdlib.h> #include <stdlib.h>
struct options struct options {
{
char shortopt; char shortopt;
char *longopt; char *longopt;
char *arg; char *arg;
char *help; char *help;
}; };
void opt_init (int *optind); void opt_init(int *optind);
char opt_parse (int argc, char **argv, int *optind, char **optarg, char opt_parse(int argc, char **argv, int *optind, char **optarg,
struct options *opt); struct options *opt);
void opt_help (struct options *opt, FILE * out); void opt_help(struct options *opt, FILE * out);
#endif #endif
...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
#include "netutil.h" #include "netutil.h"
/* Calibration data */ /* Calibration data */
struct ue9Calibration struct ue9Calibration {
{
double unipolarSlope[4]; double unipolarSlope[4];
double unipolarOffset[4]; double unipolarOffset[4];
double bipolarSlope; double bipolarSlope;
...@@ -37,8 +36,7 @@ struct ue9Calibration ...@@ -37,8 +36,7 @@ struct ue9Calibration
}; };
/* Comm config */ /* Comm config */
struct ue9CommConfig struct ue9CommConfig {
{
uint8_t local_id; uint8_t local_id;
uint8_t power_level; uint8_t power_level;
in_addr_t address; in_addr_t address;
...@@ -54,8 +52,7 @@ struct ue9CommConfig ...@@ -54,8 +52,7 @@ struct ue9CommConfig
}; };
/* Control config */ /* Control config */
struct ue9ControlConfig struct ue9ControlConfig {
{
uint8_t power_level; uint8_t power_level;
uint8_t reset_source; uint8_t reset_source;
double control_fw_version; double control_fw_version;
...@@ -77,68 +74,73 @@ struct ue9ControlConfig ...@@ -77,68 +74,73 @@ struct ue9ControlConfig
#define UE9_UNIPOLAR_GAIN8 0x03 #define UE9_UNIPOLAR_GAIN8 0x03
#define UE9_BIPOLAR_GAIN1 0x08 #define UE9_BIPOLAR_GAIN1 0x08
#define UE9_CHANNELS 14 #define UE9_MAX_CHANNEL_COUNT 128
#define UE9_MAX_CHANNEL 255
#define UE9_TIMERS 6
/* Fill checksums in data buffers */ /* Fill checksums in data buffers */
void ue9_checksum_normal (uint8_t * buffer, size_t len); void ue9_checksum_normal(uint8_t * buffer, size_t len);
void ue9_checksum_extended (uint8_t * buffer, size_t len); void ue9_checksum_extended(uint8_t * buffer, size_t len);
/* Verify checksums in data buffers. Returns 0 on error. */ /* Verify checksums in data buffers. Returns 0 on error. */
int ue9_verify_normal (uint8_t * buffer, size_t len); int ue9_verify_normal(uint8_t * buffer, size_t len);
int ue9_verify_extended (uint8_t * buffer, size_t len); int ue9_verify_extended(uint8_t * buffer, size_t len);
/* Open/close TCP/IP connection to the UE9 */ /* Open/close TCP/IP connection to the UE9 */
int ue9_open (const char *host, int port); int ue9_open(const char *host, int port);
void ue9_close (int fd); void ue9_close(int fd);
/* Read a memory block from the device. Returns -1 on error. */ /* Read a memory block from the device. Returns -1 on error. */
int ue9_memory_read (int fd, int blocknum, uint8_t * buffer, int len); int ue9_memory_read(int fd, int blocknum, uint8_t * buffer, int len);
/* Convert 64-bit fixed point to double type */ /* Convert 64-bit fixed point to double type */
double ue9_fp64_to_double (uint8_t * data); double ue9_fp64_to_double(uint8_t * data);
/* Retrieve calibration data or configuration from the device */ /* Retrieve calibration data or configuration from the device */
int ue9_get_calibration (int fd, struct ue9Calibration *calib); int ue9_get_calibration(int fd, struct ue9Calibration *calib);
int ue9_get_comm_config (int fd, struct ue9CommConfig *config); int ue9_get_comm_config(int fd, struct ue9CommConfig *config);
int ue9_get_control_config (int fd, struct ue9ControlConfig *config); 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,
uint8_t gain, uint8_t resolution, uint16_t data); uint8_t gain, uint8_t resolution, 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);
/* Choose the best ScanConfig and ScanInterval parameters for the /* Choose the best ScanConfig and ScanInterval parameters for the
desired scanrate. Returns 0 if nothing can be chosen. */ desired scanrate. Returns 0 if nothing can be chosen. */
int ue9_choose_scan (double desired_rate, double *actual_rate, int ue9_choose_scan(double desired_rate, double *actual_rate,
uint8_t * scanconfig, uint16_t * scaninterval); uint8_t * scanconfig, uint16_t * scaninterval);
/* Flush data buffers */ /* Flush data buffers */
void ue9_buffer_flush (int fd); void ue9_buffer_flush(int fd);
/* Stop stream. Returns < 0 on failure. */ /* Stop stream. Returns < 0 on failure. */
int ue9_stream_stop (int fd); int ue9_stream_stop(int fd);
/* Start stream. Returns < 0 on failure. */ /* Start stream. Returns < 0 on failure. */
int ue9_stream_start (int fd); int ue9_stream_start(int fd);
/* Execute a command on the UE9. Returns -1 on error. Fills the /* Execute a command on the UE9. Returns -1 on error. Fills the
checksums on the outgoing packets, and verifies them on the checksums on the outgoing packets, and verifies them on the
incoming packets. Data in "out" is transmitted, data in "in" is incoming packets. Data in "out" is transmitted, data in "in" is
received. */ received. */
int ue9_command (int fd, uint8_t * out, uint8_t * in, int inlen); int ue9_command(int fd, uint8_t * out, uint8_t * in, int inlen);
/* "Simple" stream configuration, assumes the channels are all /* "Simple" stream configuration, assumes the channels are all
configured with the same gain. */ configured with the same gain. */
int ue9_streamconfig_simple (int fd, int *channel_list, int channel_count, 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);
/* Timer configuration */
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, 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 ue9_stream_data(int fd, int channels,
ue9_stream_cb_t callback, void *context); ue9_stream_cb_t callback, void *context);
#endif #endif
...@@ -42,10 +42,9 @@ const char *ue9_error_text[] = { ...@@ -42,10 +42,9 @@ const char *ue9_error_text[] = {
[PLL_NOT_LOCKED] = "PLL_NOT_LOCKED" [PLL_NOT_LOCKED] = "PLL_NOT_LOCKED"
}; };
const char * const char *ue9_error(int errorcode)
ue9_error (int errorcode)
{ {
if (errorcode > ARRAY_SIZE (ue9_error_text)) if (errorcode > ARRAY_SIZE(ue9_error_text))
return "(invalid errorcode)"; return "(invalid errorcode)";
else else
return ue9_error_text[errorcode]; return ue9_error_text[errorcode];
......
...@@ -44,6 +44,6 @@ ...@@ -44,6 +44,6 @@
extern const char *ue9_error_text[]; extern const char *ue9_error_text[];
const char *ue9_error (int errorcode); const char *ue9_error(int errorcode);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment