git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@8314 ddd99763-3ecb-0310-9145-efcb8ce7c51ftags/ethstream-1.2
@@ -32,11 +32,11 @@ default: lin | |||
all: lin win | |||
.PHONY: lin | |||
lin: ljtest ethstream ljconfig \ | |||
ethstream.1 ljconfig.1 | |||
lin: ethstream \ | |||
ethstream.1 | |||
.PHONY: win | |||
win: ljtest.exe ethstream.exe ljconfig.exe | |||
win: ethstream.exe | |||
version.h: VERSION | |||
@@ -46,17 +46,11 @@ version.h: VERSION | |||
# Object files for each executable | |||
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-ljtest = ljtest.o $(obj-common) | |||
ljconfig: $(obj-ljconfig) | |||
ethstream: $(obj-ethstream) | |||
ljtest: $(obj-ljtest) | |||
ljconfig.exe: $(obj-ljconfig:.o=.obj) compat-win32.obj | |||
ethstream.exe: $(obj-ethstream:.o=.obj) compat-win32.obj | |||
ljtest.exe: $(obj-ljtest:.o=.obj) compat-win32.obj | |||
# Manpages | |||
@@ -92,7 +86,7 @@ dist: version.h | |||
.PHONY: 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: | |||
@@ -2,5 +2,10 @@ Labjack/Nerdjack Tools | |||
by Jim Paris <jim@jtan.com> | |||
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 | |||
The NerdJack device is a custom board made in LEES by Zach Clifford. | |||
Use ethstream -h or ethstream -X for usage instructions and examples. |
@@ -1 +1 @@ | |||
1.1 | |||
1.2 |
@@ -3,83 +3,56 @@ | |||
#include "compat.h" | |||
#include <windows.h> | |||
unsigned int | |||
sleep (unsigned int seconds) | |||
unsigned int sleep(unsigned int seconds) | |||
{ | |||
Sleep (seconds * 1000); | |||
return 0; | |||
Sleep(seconds * 1000); | |||
return 0; | |||
} | |||
static struct | |||
{ | |||
int num; | |||
char *msg; | |||
} win32_error[] = | |||
{ | |||
/* Errors that we might vaguely expect to see */ | |||
{ | |||
WSAEINTR, "Winsock: Interrupted system call"}, | |||
{ | |||
WSAEBADF, "Winsock: Bad file number"}, | |||
{ | |||
WSAEFAULT, "Winsock: Bad address"}, | |||
{ | |||
WSAEINVAL, "Winsock: Invalid argument"}, | |||
{ | |||
WSAEMFILE, "Winsock: Too many open files"}, | |||
{ | |||
WSAEWOULDBLOCK, "Winsock: Operation would block"}, | |||
{ | |||
WSAEINPROGRESS, "Winsock: Operation now in progress"}, | |||
{ | |||
WSAEALREADY, "Winsock: Operation already in progress"}, | |||
{ | |||
WSAENOTSOCK, "Winsock: Socket operation on nonsocket"}, | |||
{ | |||
WSAEADDRINUSE, "Winsock: Address already in use"}, | |||
{ | |||
WSAEADDRNOTAVAIL, "Winsock: Cannot assign requested address"}, | |||
{ | |||
WSAENETDOWN, "Winsock: Network is down"}, | |||
{ | |||
WSAENETUNREACH, "Winsock: Network is unreachable"}, | |||
{ | |||
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) | |||
static struct { | |||
int num; | |||
char *msg; | |||
} win32_error[] = { | |||
/* Errors that we might vaguely expect to see */ | |||
{ WSAEINTR, "Winsock: Interrupted system call"}, | |||
{ WSAEBADF, "Winsock: Bad file number"}, | |||
{ WSAEFAULT, "Winsock: Bad address"}, | |||
{ WSAEINVAL, "Winsock: Invalid argument"}, | |||
{ WSAEMFILE, "Winsock: Too many open files"}, | |||
{ WSAEWOULDBLOCK, "Winsock: Operation would block"}, | |||
{ WSAEINPROGRESS, "Winsock: Operation now in progress"}, | |||
{ WSAEALREADY, "Winsock: Operation already in progress"}, | |||
{ WSAENOTSOCK, "Winsock: Socket operation on nonsocket"}, | |||
{ WSAEADDRINUSE, "Winsock: Address already in use"}, | |||
{ WSAEADDRNOTAVAIL, "Winsock: Cannot assign requested address"}, | |||
{ WSAENETDOWN, "Winsock: Network is down"}, | |||
{ WSAENETUNREACH, "Winsock: Network is unreachable"}, | |||
{ 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; | |||
static char buf[128]; | |||
int i; | |||
static char buf[128]; | |||
for (i = 0; win32_error[i].num != -1; i++) | |||
if (errnum == win32_error[i].num) | |||
return win32_error[i].msg; | |||
if (errnum >= 10000) | |||
{ | |||
sprintf (buf, "Winsock: unknown error %d\n", errnum); | |||
return buf; | |||
} | |||
return strerror (errnum); | |||
for (i = 0; win32_error[i].num != -1; i++) | |||
if (errnum == win32_error[i].num) | |||
return win32_error[i].msg; | |||
if (errnum >= 10000) { | |||
sprintf(buf, "Winsock: unknown error %d\n", errnum); | |||
return buf; | |||
} | |||
return strerror(errnum); | |||
} | |||
#ifdef __WIN32__ | |||
@@ -2,8 +2,8 @@ | |||
#define COMPAT_H | |||
#ifdef __WIN32__ | |||
unsigned int sleep (unsigned int seconds); | |||
char *compat_strerror (int errnum); | |||
unsigned int sleep(unsigned int seconds); | |||
char *compat_strerror(int errnum); | |||
//const char *inet_ntop(int af, void *src, const char *dst, socklen_t cnt); | |||
#define INET_ADDRSTRLEN 16 | |||
#define ETIMEDOUT 110 | |||
@@ -4,15 +4,14 @@ | |||
int verb_count = 0; | |||
int | |||
func_fprintf (const char *func, FILE * stream, const char *format, ...) | |||
int func_fprintf(const char *func, FILE * stream, const char *format, ...) | |||
{ | |||
va_list ap; | |||
int ret; | |||
va_list ap; | |||
int ret; | |||
fprintf (stream, "%s: ", func); | |||
va_start (ap, format); | |||
ret = vfprintf (stream, format, ap); | |||
va_end (ap); | |||
return ret; | |||
fprintf(stream, "%s: ", func); | |||
va_start(ap, format); | |||
ret = vfprintf(stream, format, ap); | |||
va_end(ap); | |||
return ret; | |||
} |
@@ -14,8 +14,8 @@ extern int verb_count; | |||
#include <stdio.h> | |||
int func_fprintf (const char *func, FILE * stream, const char *format, | |||
...) __attribute__ ((format (printf, 3, 4))); | |||
int func_fprintf(const char *func, FILE * stream, const char *format, | |||
...) __attribute__ ((format(printf, 3, 4))); | |||
#define debug(x...) ({ \ | |||
if(verb_count >= 2) \ | |||
@@ -6,15 +6,18 @@ char examplestring[] = "\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\ | |||
\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\ | |||
\n\ | |||
ethstream -C 0,3\n\ | |||
\n\ | |||
The device is configured so that channels 0 through 2 are voltages for\n\ | |||
the three phases and channels 3-5 are for currents of the three phases\n\ | |||
The device is configured so that channels 0 through 2 are currents for\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\ | |||
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\ | |||
ethstream -n 3 -r 16000\n\ | |||
\n\ | |||
@@ -26,20 +29,20 @@ all 12 at once.\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\ | |||
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\ | |||
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\ | |||
ethstream -R 5,10 -C 3,4,5\n\ | |||
\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\ | |||
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\ | |||
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\ | |||
\n\ | |||
ethstream -c -C 0,3,1,4,2,5\n\ | |||
@@ -1,102 +0,0 @@ | |||
/* | |||
* 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; | |||
} |
@@ -1,68 +0,0 @@ | |||
/* | |||
* 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,39 +25,41 @@ | |||
#define NERDJACK_NUM_SAMPLES 726 | |||
/* Packet structure used in message to start sampling on NerdJack */ | |||
typedef struct __attribute__ ((__packed__)) | |||
{ | |||
char word[4]; | |||
unsigned long period; | |||
unsigned short channelbit; | |||
unsigned char precision; | |||
unsigned char prescaler; | |||
typedef struct __attribute__ ((__packed__)) { | |||
char word[4]; | |||
unsigned long period; | |||
unsigned short channelbit; | |||
unsigned char precision; | |||
unsigned char prescaler; | |||
} getPacket; | |||
/* Open/close TCP/IP connection to the NerdJack */ | |||
int nerd_open (const char *address, int port); | |||
int nerd_close_conn (int data_fd); | |||
int nerd_open(const char *address, int port); | |||
int nerd_close_conn(int data_fd); | |||
/* Generate the command word for the NerdJack */ | |||
int nerd_generate_command (getPacket * command, int *channel_list, | |||
int channel_count, int precision, | |||
unsigned long period); | |||
int nerd_generate_command(getPacket * command, int *channel_list, | |||
int channel_count, int precision, | |||
unsigned long period); | |||
/* 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 */ | |||
int nerd_data_stream (int data_fd, int numChannels, int *channel_list, | |||
int precision, int convert, int lines, int showmem, | |||
unsigned short *currentcount, unsigned int period, | |||
int wasreset); | |||
int nerd_data_stream(int data_fd, int numChannels, int *channel_list, | |||
int precision, int convert, int lines, int showmem, | |||
unsigned short *currentcount, unsigned int period, | |||
int wasreset); | |||
/* 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 | |||
desired scanrate. Returns -1 if no valid config found */ | |||
int nerdjack_choose_scan (double desired_rate, double *actual_rate, | |||
unsigned long *period); | |||
int nerdjack_choose_scan(double desired_rate, double *actual_rate, | |||
unsigned long *period); | |||
#endif |
@@ -5,262 +5,244 @@ | |||
#include <stdio.h> | |||
/* Initialize networking */ | |||
void | |||
net_init (void) | |||
void net_init(void) | |||
{ | |||
#ifdef __WIN32__ | |||
WSADATA blah; | |||
WSAStartup (0x0101, &blah); | |||
WSADATA blah; | |||
WSAStartup(0x0101, &blah); | |||
#endif | |||
} | |||
/* Set socket blocking/nonblocking */ | |||
int | |||
soblock (int socket, int blocking) | |||
int soblock(int socket, int blocking) | |||
{ | |||
#ifdef __WIN32__ | |||
unsigned long arg = blocking ? 0 : 1; | |||
if (ioctlsocket (socket, FIONBIO, &arg) != 0) | |||
return -1; | |||
return 0; | |||
unsigned long arg = blocking ? 0 : 1; | |||
if (ioctlsocket(socket, FIONBIO, &arg) != 0) | |||
return -1; | |||
return 0; | |||
#else | |||
int sockopt; | |||
/* Get flags */ | |||
sockopt = fcntl (socket, F_GETFL); | |||
if (sockopt == -1) | |||
{ | |||
return -1; | |||
} | |||
/* Modify */ | |||
if (blocking) | |||
sockopt &= ~O_NONBLOCK; | |||
else | |||
sockopt |= O_NONBLOCK; | |||
/* Set flags */ | |||
if (fcntl (socket, F_SETFL, sockopt) != 0) | |||
return -1; | |||
return 0; | |||
int sockopt; | |||
/* Get flags */ | |||
sockopt = fcntl(socket, F_GETFL); | |||
if (sockopt == -1) { | |||
return -1; | |||
} | |||
/* Modify */ | |||
if (blocking) | |||
sockopt &= ~O_NONBLOCK; | |||
else | |||
sockopt |= O_NONBLOCK; | |||
/* Set flags */ | |||
if (fcntl(socket, F_SETFL, sockopt) != 0) | |||
return -1; | |||
return 0; | |||
#endif | |||
} | |||
/* Like connect(2), but with a timeout. Socket must be non-blocking. */ | |||
int | |||
connect_timeout (int s, const struct sockaddr *serv_addr, socklen_t addrlen, | |||
struct timeval *timeout) | |||
connect_timeout(int s, const struct sockaddr *serv_addr, socklen_t addrlen, | |||
struct timeval *timeout) | |||
{ | |||
int ret; | |||
fd_set writefds; | |||
fd_set exceptfds; | |||
int optval; | |||
socklen_t optlen; | |||
/* Start connect */ | |||
ret = connect (s, serv_addr, addrlen); | |||
if (ret == 0) | |||
{ | |||
/* Success */ | |||
return 0; | |||
} | |||
/* Check for immediate failure */ | |||
int ret; | |||
fd_set writefds; | |||
fd_set exceptfds; | |||
int optval; | |||
socklen_t optlen; | |||
/* Start connect */ | |||
ret = connect(s, serv_addr, addrlen); | |||
if (ret == 0) { | |||
/* Success */ | |||
return 0; | |||
} | |||
/* Check for immediate failure */ | |||
#ifdef __WIN32__ | |||
errno = WSAGetLastError (); | |||
if (ret < 0 && errno != WSAEWOULDBLOCK && errno != WSAEINVAL) | |||
return -1; | |||
errno = WSAGetLastError(); | |||
if (ret < 0 && errno != WSAEWOULDBLOCK && errno != WSAEINVAL) | |||
return -1; | |||
#else | |||
if (ret < 0 && errno != EINPROGRESS && errno != EALREADY) | |||
return -1; | |||
if (ret < 0 && errno != EINPROGRESS && errno != EALREADY) | |||
return -1; | |||
#endif | |||
/* In progress, wait for result. */ | |||
FD_ZERO (&writefds); | |||
FD_SET (s, &writefds); | |||
FD_ZERO (&exceptfds); | |||
FD_SET (s, &exceptfds); | |||
ret = select (s + 1, NULL, &writefds, &exceptfds, timeout); | |||
if (ret < 0) | |||
{ | |||
/* Error */ | |||
return -1; | |||
} | |||
if (ret == 0) | |||
{ | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
/* Check the socket state */ | |||
optlen = sizeof (optval); | |||
if (getsockopt (s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen) != 0) | |||
return -1; | |||
if (optval != 0) | |||
{ | |||
/* Connection failed. */ | |||
errno = optval; | |||
return -1; | |||
} | |||
/* On Windows, SO_ERROR sometimes shows no error but the connection | |||
still failed. Sigh. */ | |||
if (FD_ISSET (s, &exceptfds) || !FD_ISSET (s, &writefds)) | |||
{ | |||
errno = EIO; | |||
return -1; | |||
} | |||
/* Success */ | |||
return 0; | |||
/* In progress, wait for result. */ | |||
FD_ZERO(&writefds); | |||
FD_SET(s, &writefds); | |||
FD_ZERO(&exceptfds); | |||
FD_SET(s, &exceptfds); | |||
ret = select(s + 1, NULL, &writefds, &exceptfds, timeout); | |||
if (ret < 0) { | |||
/* Error */ | |||
return -1; | |||
} | |||
if (ret == 0) { | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
/* Check the socket state */ | |||
optlen = sizeof(optval); | |||
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen) != 0) | |||
return -1; | |||
if (optval != 0) { | |||
/* Connection failed. */ | |||
errno = optval; | |||
return -1; | |||
} | |||
/* On Windows, SO_ERROR sometimes shows no error but the connection | |||
still failed. Sigh. */ | |||
if (FD_ISSET(s, &exceptfds) || !FD_ISSET(s, &writefds)) { | |||
errno = EIO; | |||
return -1; | |||
} | |||
/* Success */ | |||
return 0; | |||
} | |||
/* Like send(2), but with a timeout. Socket must be non-blocking. | |||
The timeout only applies if no data at all is sent -- this function | |||
may still send less than requested. */ | |||
ssize_t | |||
send_timeout (int s, const void *buf, size_t len, int flags, | |||
struct timeval * timeout) | |||
send_timeout(int s, const void *buf, size_t len, int flags, | |||
struct timeval * timeout) | |||
{ | |||
fd_set writefds; | |||
int ret; | |||
FD_ZERO (&writefds); | |||
FD_SET (s, &writefds); | |||
ret = select (s + 1, NULL, &writefds, NULL, timeout); | |||
if (ret == 0) | |||
{ | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
if (ret != 1) | |||
{ | |||
/* Error */ | |||
return -1; | |||
} | |||
return send (s, buf, len, flags); | |||
fd_set writefds; | |||
int ret; | |||
FD_ZERO(&writefds); | |||
FD_SET(s, &writefds); | |||
ret = select(s + 1, NULL, &writefds, NULL, timeout); | |||
if (ret == 0) { | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
if (ret != 1) { | |||
/* Error */ | |||
return -1; | |||
} | |||
return send(s, buf, len, flags); | |||
} | |||
/* Like recv(2), but with a timeout. Socket must be non-blocking. | |||
The timeout only applies if no data at all is received -- this | |||
function may still return less than requested. */ | |||
ssize_t | |||
recv_timeout (int s, void *buf, size_t len, int flags, | |||
struct timeval * timeout) | |||
recv_timeout(int s, void *buf, size_t len, int flags, struct timeval * timeout) | |||
{ | |||
fd_set readfds; | |||
int ret; | |||
FD_ZERO (&readfds); | |||
FD_SET (s, &readfds); | |||
ret = select (s + 1, &readfds, NULL, NULL, timeout); | |||
if (ret == 0) | |||
{ | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
if (ret != 1) | |||
{ | |||
/* Error */ | |||
return -1; | |||
} | |||
return recv (s, buf, len, flags); | |||
fd_set readfds; | |||
int ret; | |||
FD_ZERO(&readfds); | |||
FD_SET(s, &readfds); | |||
ret = select(s + 1, &readfds, NULL, NULL, timeout); | |||
if (ret == 0) { | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
if (ret != 1) { | |||
/* Error */ | |||
return -1; | |||
} | |||
return recv(s, buf, len, flags); | |||
} | |||
/* Like recvfrom(2), but with a timeout. Socket must be non-blocking. | |||
The timeout only applies if no data at all is received -- this | |||
function may still return less than requested. */ | |||
ssize_t | |||
recvfrom_timeout (int s, void *buf, size_t len, int flags, | |||
struct sockaddr * address, socklen_t * address_len, | |||
struct timeval * timeout) | |||
recvfrom_timeout(int s, void *buf, size_t len, int flags, | |||
struct sockaddr * address, socklen_t * address_len, | |||
struct timeval * timeout) | |||
{ | |||
fd_set readfds; | |||
int ret; | |||
FD_ZERO (&readfds); | |||
FD_SET (s, &readfds); | |||
ret = select (s + 1, &readfds, NULL, NULL, timeout); | |||
if (ret == 0) | |||
{ | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
if (ret != 1) | |||
{ | |||
/* Error */ | |||
return -1; | |||
} | |||
return recvfrom (s, buf, len, flags, address, address_len); | |||
fd_set readfds; | |||
int ret; | |||
FD_ZERO(&readfds); | |||
FD_SET(s, &readfds); | |||
ret = select(s + 1, &readfds, NULL, NULL, timeout); | |||
if (ret == 0) { | |||
/* Timed out */ | |||
errno = ETIMEDOUT; | |||
return -1; | |||
} | |||
if (ret != 1) { | |||
/* Error */ | |||
return -1; | |||
} | |||
return recvfrom(s, buf, len, flags, address, address_len); | |||
} | |||
/* Like send_timeout, but retries (with the same timeout) in case of | |||
partial transfers. This is a stronger attempt to send all | |||
requested data. */ | |||
ssize_t | |||
send_all_timeout (int s, const void *buf, size_t len, int flags, | |||
struct timeval * timeout) | |||
send_all_timeout(int s, const void *buf, size_t len, int flags, | |||
struct timeval * timeout) | |||
{ | |||
struct timeval tv; | |||
size_t left = len; | |||
ssize_t ret; | |||
struct timeval tv; | |||
size_t left = len; | |||
ssize_t ret; | |||
while (left > 0) | |||
{ | |||
tv.tv_sec = timeout->tv_sec; | |||
tv.tv_usec = timeout->tv_usec; | |||
ret = send_timeout (s, buf, left, flags, &tv); | |||
while (left > 0) { | |||
tv.tv_sec = timeout->tv_sec; | |||
tv.tv_usec = timeout->tv_usec; | |||
ret = send_timeout(s, buf, left, flags, &tv); | |||
if (ret < 0) | |||
return ret; | |||
if (ret < 0) | |||
return ret; | |||
if (ret == 0) | |||
break; | |||
if (ret == 0) | |||
break; | |||
left -= ret; | |||
buf += ret; | |||
} | |||
left -= ret; | |||
buf += ret; | |||
} | |||
return len - left; | |||
return len - left; | |||
} | |||
/* Like recv_timeout, but retries (with the same timeout) in case of | |||
partial transfers. This is a stronger attempt to recv all | |||
requested data. */ | |||
ssize_t | |||
recv_all_timeout (int s, void *buf, size_t len, int flags, | |||
struct timeval * timeout) | |||
recv_all_timeout(int s, void *buf, size_t len, int flags, | |||
struct timeval * timeout) | |||
{ | |||
struct timeval tv; | |||
size_t left = len; | |||
ssize_t ret; | |||
struct timeval tv; | |||
size_t left = len; | |||
ssize_t ret; | |||
while (left > 0) | |||
{ | |||
tv.tv_sec = timeout->tv_sec; | |||
tv.tv_usec = timeout->tv_usec; | |||
ret = recv_timeout (s, buf, left, flags, &tv); | |||
while (left > 0) { | |||
tv.tv_sec = timeout->tv_sec; | |||
tv.tv_usec = timeout->tv_usec; | |||
ret = recv_timeout(s, buf, left, flags, &tv); | |||
if (ret < 0) | |||
return ret; | |||
if (ret < 0) | |||
return ret; | |||
if (ret == 0) | |||
break; | |||
if (ret == 0) | |||
break; | |||
left -= ret; | |||
buf += ret; | |||
} | |||
left -= ret; | |||
buf += ret; | |||
} | |||
return len - left; | |||
return len - left; | |||
} |
@@ -27,28 +27,28 @@ | |||
#endif | |||
/* Initialize networking */ | |||
void net_init (void); | |||
void net_init(void); | |||
/* 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. | |||
Socket must be O_NONBLOCK. */ | |||
int connect_timeout (int s, const struct sockaddr *serv_addr, | |||
socklen_t addrlen, struct timeval *timeout); | |||
ssize_t send_timeout (int s, const void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
ssize_t recv_timeout (int s, void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
ssize_t recvfrom_timeout (int s, void *buf, size_t len, int flags, | |||
struct sockaddr *address, socklen_t * address_len, | |||
struct timeval *timeout); | |||
int connect_timeout(int s, const struct sockaddr *serv_addr, | |||
socklen_t addrlen, struct timeval *timeout); | |||
ssize_t send_timeout(int s, const void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
ssize_t recv_timeout(int s, void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
ssize_t recvfrom_timeout(int s, void *buf, size_t len, int flags, | |||
struct sockaddr *address, socklen_t * address_len, | |||
struct timeval *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. */ | |||
ssize_t send_all_timeout (int s, const void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
ssize_t recv_all_timeout (int s, void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
ssize_t send_all_timeout(int s, const void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
ssize_t recv_all_timeout(int s, void *buf, size_t len, int flags, | |||
struct timeval *timeout); | |||
#endif |
@@ -11,98 +11,87 @@ | |||
#include <string.h> | |||
#include "opt.h" | |||
void | |||
opt_init (int *optind) | |||
void opt_init(int *optind) | |||
{ | |||
*optind = 0; | |||
*optind = 0; | |||
} | |||
char | |||
opt_parse (int argc, char **argv, int *optind, char **optarg, | |||
struct options *opt) | |||
opt_parse(int argc, char **argv, int *optind, char **optarg, | |||
struct options *opt) | |||
{ | |||
char c; | |||
int i; | |||
(*optind)++; | |||
if (*optind >= argc) | |||
return 0; | |||
char c; | |||
int i; | |||
(*optind)++; | |||
if (*optind >= argc) | |||
return 0; | |||
if (argv[*optind][0] == '-' && | |||
argv[*optind][1] != '-' && argv[*optind][1] != 0) | |||
{ | |||
/* Short option (or a bunch of 'em) */ | |||
/* Save this and shift others over */ | |||
c = argv[*optind][1]; | |||
for (i = 2; argv[*optind][i] != 0; i++) | |||
argv[*optind][i - 1] = argv[*optind][i]; | |||
argv[*optind][i - 1] = 0; | |||
if (argv[*optind][1] != 0) | |||
(*optind)--; | |||
/* Now find it */ | |||
for (i = 0; opt[i].shortopt != 0; i++) | |||
if (opt[i].shortopt == c) | |||
break; | |||
if (opt[i].shortopt == 0) | |||
{ | |||
fprintf (stderr, "Error: unknown option '-%c'\n", c); | |||
return '?'; | |||
if (argv[*optind][0] == '-' && | |||
argv[*optind][1] != '-' && argv[*optind][1] != 0) { | |||
/* Short option (or a bunch of 'em) */ | |||
/* Save this and shift others over */ | |||
c = argv[*optind][1]; | |||
for (i = 2; argv[*optind][i] != 0; i++) | |||
argv[*optind][i - 1] = argv[*optind][i]; | |||
argv[*optind][i - 1] = 0; | |||
if (argv[*optind][1] != 0) | |||
(*optind)--; | |||
/* Now find it */ | |||
for (i = 0; opt[i].shortopt != 0; i++) | |||
if (opt[i].shortopt == c) | |||
break; | |||
if (opt[i].shortopt == 0) { | |||
fprintf(stderr, "Error: unknown option '-%c'\n", c); | |||
return '?'; | |||
} | |||
if (opt[i].arg == NULL) | |||
return c; | |||
(*optind)++; | |||
if (*optind >= argc || (argv[*optind][0] == '-' && | |||
argv[*optind][1] != 0)) { | |||
fprintf(stderr, "Error: option '-%c' requires an " | |||
"argument\n", c); | |||
return '?'; | |||
} | |||
(*optarg) = argv[*optind]; | |||
return c; | |||
} else if (argv[*optind][0] == '-' && | |||
argv[*optind][1] == '-' && argv[*optind][2] != 0) { | |||
/* Long option */ | |||
for (i = 0; (c = opt[i].shortopt) != 0; i++) | |||
if (strcmp(opt[i].longopt, argv[*optind] + 2) == 0) | |||
break; | |||
if (opt[i].shortopt == 0) { | |||
fprintf(stderr, "Error: unknown option '%s'\n", | |||
argv[*optind]); | |||
return '?'; | |||
} | |||
if (opt[i].arg == NULL) | |||
return c; | |||
(*optind)++; | |||
if (*optind >= argc || (argv[*optind][0] == '-' && | |||
argv[*optind][1] != 0)) { | |||
fprintf(stderr, "Error: option '%s' requires an " | |||
"argument\n", argv[*optind - 1]); | |||
return '?'; | |||
} | |||
(*optarg) = argv[*optind]; | |||
return c; | |||
} else { | |||
/* End of options */ | |||
return 0; | |||
} | |||
if (opt[i].arg == NULL) | |||
return c; | |||
(*optind)++; | |||
if (*optind >= argc || (argv[*optind][0] == '-' && | |||
argv[*optind][1] != 0)) | |||
{ | |||
fprintf (stderr, "Error: option '-%c' requires an " | |||
"argument\n", c); | |||
return '?'; | |||
} | |||
(*optarg) = argv[*optind]; | |||
return c; | |||
} | |||
else if (argv[*optind][0] == '-' && | |||
argv[*optind][1] == '-' && argv[*optind][2] != 0) | |||
{ | |||
/* Long option */ | |||
for (i = 0; (c = opt[i].shortopt) != 0; i++) | |||
if (strcmp (opt[i].longopt, argv[*optind] + 2) == 0) | |||
break; | |||
if (opt[i].shortopt == 0) | |||
{ | |||
fprintf (stderr, "Error: unknown option '%s'\n", argv[*optind]); | |||
return '?'; | |||
} | |||
if (opt[i].arg == NULL) | |||
return c; | |||
(*optind)++; | |||
if (*optind >= argc || (argv[*optind][0] == '-' && | |||
argv[*optind][1] != 0)) | |||
{ | |||
fprintf (stderr, "Error: option '%s' requires an " | |||
"argument\n", argv[*optind - 1]); | |||
return '?'; | |||
} | |||
(*optarg) = argv[*optind]; | |||
return c; | |||
} | |||
else | |||
{ | |||
/* End of options */ | |||
return 0; | |||
} | |||
} | |||
void | |||
opt_help (struct options *opt, FILE * out) | |||
void opt_help(struct options *opt, FILE * out) | |||
{ | |||
int i; | |||
int printed; | |||
int i; | |||
int printed; | |||
for (i = 0; opt[i].shortopt != 0; i++) | |||
{ | |||
fprintf (out, " -%c, --%s%n", opt[i].shortopt, | |||
opt[i].longopt, &printed); | |||
fprintf (out, " %-*s%s\n", 30 - printed, | |||
opt[i].arg ? opt[i].arg : "", opt[i].help); | |||
} | |||
for (i = 0; opt[i].shortopt != 0; i++) { | |||
fprintf(out, " -%c, --%s%n", opt[i].shortopt, | |||
opt[i].longopt, &printed); | |||
fprintf(out, " %-*s%s\n", 30 - printed, | |||
opt[i].arg ? opt[i].arg : "", opt[i].help); | |||
} | |||
} |
@@ -11,19 +11,18 @@ | |||
#include <stdlib.h> | |||
struct options | |||
{ | |||
char shortopt; | |||
char *longopt; | |||
char *arg; | |||
char *help; | |||
struct options { | |||
char shortopt; | |||
char *longopt; | |||
char *arg; | |||
char *help; | |||
}; | |||
void opt_init (int *optind); | |||
void opt_init(int *optind); | |||
char opt_parse (int argc, char **argv, int *optind, char **optarg, | |||
struct options *opt); | |||
char opt_parse(int argc, char **argv, int *optind, char **optarg, | |||
struct options *opt); | |||
void opt_help (struct options *opt, FILE * out); | |||
void opt_help(struct options *opt, FILE * out); | |||
#endif |
@@ -16,59 +16,56 @@ | |||
#include "netutil.h" | |||
/* Calibration data */ | |||
struct ue9Calibration | |||
{ | |||
double unipolarSlope[4]; | |||
double unipolarOffset[4]; | |||
double bipolarSlope; | |||
double bipolarOffset; | |||
double DACSlope[2]; | |||
double DACOffset[2]; | |||
double tempSlope; | |||
double tempSlopeLow; | |||
double calTemp; | |||
double Vref; | |||
double VrefDiv2; | |||
double VsSlope; | |||
double hiResUnipolarSlope; | |||
double hiResUnipolarOffset; | |||
double hiResBipolarSlope; | |||
double hiResBipolarOffset; | |||
struct ue9Calibration { | |||
double unipolarSlope[4]; | |||
double unipolarOffset[4]; | |||
double bipolarSlope; | |||
double bipolarOffset; | |||
double DACSlope[2]; | |||
double DACOffset[2]; | |||
double tempSlope; | |||
double tempSlopeLow; | |||
double calTemp; | |||
double Vref; | |||
double VrefDiv2; | |||
double VsSlope; | |||
double hiResUnipolarSlope; | |||
double hiResUnipolarOffset; | |||
double hiResBipolarSlope; | |||
double hiResBipolarOffset; | |||
}; | |||
/* Comm config */ | |||
struct ue9CommConfig | |||
{ | |||
uint8_t local_id; | |||
uint8_t power_level; | |||
in_addr_t address; | |||
in_addr_t gateway; | |||
in_addr_t subnet; | |||
in_port_t portA; | |||
in_port_t portB; | |||
uint8_t dhcp_enabled; | |||
uint8_t product_id; | |||
uint8_t mac_address[6]; | |||
double hw_version; | |||
double comm_fw_version; | |||
struct ue9CommConfig { | |||
uint8_t local_id; | |||
uint8_t power_level; | |||
in_addr_t address; | |||
in_addr_t gateway; | |||
in_addr_t subnet; | |||
in_port_t portA; | |||
in_port_t portB; | |||
uint8_t dhcp_enabled; | |||
uint8_t product_id; | |||
uint8_t mac_address[6]; | |||
double hw_version; | |||
double comm_fw_version; | |||
}; | |||
/* Control config */ | |||
struct ue9ControlConfig | |||
{ | |||
uint8_t power_level; | |||
uint8_t reset_source; | |||
double control_fw_version; | |||
double control_bl_version; | |||
uint8_t hires; | |||
uint8_t fio_dir; | |||
uint8_t fio_state; | |||
uint8_t eio_dir; | |||
uint8_t eio_state; | |||
uint8_t cio_dirstate;; | |||
uint8_t mio_dirstate; | |||
uint16_t dac0; | |||
uint16_t dac1; | |||
struct ue9ControlConfig { | |||
uint8_t power_level; | |||
uint8_t reset_source; | |||
double control_fw_version; | |||
double control_bl_version; | |||
uint8_t hires; | |||
uint8_t fio_dir; | |||
uint8_t fio_state; | |||
uint8_t eio_dir; | |||
uint8_t eio_state; | |||
uint8_t cio_dirstate;; | |||
uint8_t mio_dirstate; | |||
uint16_t dac0; | |||
uint16_t dac1; | |||
}; | |||
#define UE9_UNIPOLAR_GAIN1 0x00 | |||
@@ -77,68 +74,73 @@ struct ue9ControlConfig | |||
#define UE9_UNIPOLAR_GAIN8 0x03 | |||
#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 */ | |||
void ue9_checksum_normal (uint8_t * buffer, size_t len); | |||
void ue9_checksum_extended (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); | |||
/* Verify checksums in data buffers. Returns 0 on error. */ | |||
int ue9_verify_normal (uint8_t * buffer, size_t len); | |||
int ue9_verify_extended (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); | |||
/* Open/close TCP/IP connection to the UE9 */ | |||
int ue9_open (const char *host, int port); | |||
void ue9_close (int fd); | |||
int ue9_open(const char *host, int port); | |||
void ue9_close(int fd); | |||
/* 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 */ | |||
double ue9_fp64_to_double (uint8_t * data); | |||
double ue9_fp64_to_double(uint8_t * data); | |||
/* Retrieve calibration data or configuration from the device */ | |||
int ue9_get_calibration (int fd, struct ue9Calibration *calib); | |||
int ue9_get_comm_config (int fd, struct ue9CommConfig *config); | |||
int ue9_get_control_config (int fd, struct ue9ControlConfig *config); | |||
int ue9_get_calibration(int fd, struct ue9Calibration *calib); | |||
int ue9_get_comm_config(int fd, struct ue9CommConfig *config); | |||
int ue9_get_control_config(int fd, struct ue9ControlConfig *config); | |||
/* Data conversion. If calib is NULL, use uncalibrated conversions. */ | |||
double ue9_binary_to_analog (struct ue9Calibration *calib, | |||
uint8_t gain, uint8_t resolution, uint16_t data); | |||
double ue9_binary_to_analog(struct ue9Calibration *calib, | |||
uint8_t gain, uint8_t resolution, uint16_t data); | |||
/* 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 | |||
desired scanrate. Returns 0 if nothing can be chosen. */ | |||
int ue9_choose_scan (double desired_rate, double *actual_rate, | |||
uint8_t * scanconfig, uint16_t * scaninterval); | |||
int ue9_choose_scan(double desired_rate, double *actual_rate, | |||
uint8_t * scanconfig, uint16_t * scaninterval); | |||
/* Flush data buffers */ | |||
void ue9_buffer_flush (int fd); | |||
void ue9_buffer_flush(int fd); | |||
/* Stop stream. Returns < 0 on failure. */ | |||
int ue9_stream_stop (int fd); | |||
int ue9_stream_stop(int fd); | |||
/* 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 | |||
checksums on the outgoing packets, and verifies them on the | |||
incoming packets. Data in "out" is transmitted, data in "in" is | |||
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 | |||
configured with the same gain. */ | |||
int ue9_streamconfig_simple (int fd, int *channel_list, int channel_count, | |||
uint8_t scanconfig, uint16_t scaninterval, | |||
uint8_t gain); | |||
int ue9_streamconfig_simple(int fd, int *channel_list, int channel_count, | |||
uint8_t scanconfig, uint16_t scaninterval, | |||
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 | |||
negative, stops reading and returns 0. Returns < 0 on error. */ | |||
typedef int (*ue9_stream_cb_t) (int channels, uint16_t * data, void *context); | |||
int ue9_stream_data (int fd, int channels, | |||
ue9_stream_cb_t callback, void *context); | |||
int ue9_stream_data(int fd, int channels, | |||
ue9_stream_cb_t callback, void *context); | |||
#endif |
@@ -1,52 +1,51 @@ | |||
#include "ue9error.h" | |||
const char *ue9_error_text[] = { | |||
[0] = "(no error)", | |||
[SCRATCH_WRT_FAIL] = "SCRATCH_WRT_FAIL", | |||
[SCRATCH_ERASE_FAIL] = "SCRATCH_ERASE_FAIL", | |||
[DATA_BUFFER_OVERFLOW] = "DATA_BUFFER_OVERFLOW", | |||
[ADC0_BUFFER_OVERFLOW] = "ADC0_BUFFER_OVERFLOW", | |||
[FUNCTION_INVALID] = "FUNCTION_INVALID", | |||
[SWDT_TIME_INVALID] = "SWDT_TIME_INVALID", | |||
[FLASH_WRITE_FAIL] = "FLASH_WRITE_FAIL", | |||
[FLASH_ERASE_FAIL] = "FLASH_ERASE_FAIL", | |||
[FLASH_JMP_FAIL] = "FLASH_JMP_FAIL", | |||
[FLASH_PSP_TIMEOUT] = "FLASH_PSP_TIMEOUT", | |||
[FLASH_ABORT_RECEIVED] = "FLASH_ABORT_RECEIVED", | |||
[FLASH_PAGE_MISMATCH] = "FLASH_PAGE_MISMATCH", | |||
[FLASH_BLOCK_MISMATCH] = "FLASH_BLOCK_MISMATCH", | |||
[FLASH_PAGE_NOT_IN_CODE_AREA] = "FLASH_PAGE_NOT_IN_CODE_AREA", | |||
[MEM_ILLEGAL_ADDRESS] = "MEM_ILLEGAL_ADDRESS", | |||
[FLASH_LOCKED] = "FLASH_LOCKED", | |||
[INVALID_BLOCK] = "INVALID_BLOCK", | |||
[FLASH_ILLEGAL_PAGE] = "FLASH_ILLEGAL_PAGE", | |||
[STREAM_IS_ACTIVE] = "STREAM_IS_ACTIVE", | |||
[STREAM_TABLE_INVALID] = "STREAM_TABLE_INVALID", | |||
[STREAM_CONFIG_INVALID] = "STREAM_CONFIG_INVALID", | |||
[STREAM_BAD_TRIGGER_SOURCE] = "STREAM_BAD_TRIGGER_SOURCE", | |||
[STREAM_NOT_RUNNING] = "STREAM_NOT_RUNNING", | |||
[STREAM_INVALID_TRIGGER] = "STREAM_INVALID_TRIGGER", | |||
[STREAM_CONTROL_BUFFER_OVERFLOW] = "STREAM_CONTROL_BUFFER_OVERFLOW", | |||
[STREAM_SCAN_OVERLAP] = "STREAM_SCAN_OVERLAP", | |||
[STREAM_SAMPLE_NUM_INVALID] = "STREAM_SAMPLE_NUM_INVALID", | |||
[STREAM_BIPOLAR_GAIN_INVALID] = "STREAM_BIPOLAR_GAIN_INVALID", | |||
[STREAM_SCAN_RATE_INVALID] = "STREAM_SCAN_RATE_INVALID", | |||
[TIMER_INVALID_MODE] = "TIMER_INVALID_MODE", | |||
[TIMER_QUADRATURE_AB_ERROR] = "TIMER_QUADRATURE_AB_ERROR", | |||
[TIMER_QUAD_PULSE_SEQUENCE] = "TIMER_QUAD_PULSE_SEQUENCE", | |||
[TIMER_BAD_CLOCK_SOURCE] = "TIMER_BAD_CLOCK_SOURCE", | |||
[TIMER_STREAM_ACTIVE] = "TIMER_STREAM_ACTIVE", | |||
[TIMER_PWMSTOP_MODULE_ERROR] = "TIMER_PWMSTOP_MODULE_ERROR", | |||
[EXT_OSC_NOT_STABLE] = "EXT_OSC_NOT_STABLE", | |||
[INVALID_POWER_SETTING] = "INVALID_POWER_SETTING", | |||
[PLL_NOT_LOCKED] = "PLL_NOT_LOCKED" | |||
[0] = "(no error)", | |||
[SCRATCH_WRT_FAIL] = "SCRATCH_WRT_FAIL", | |||
[SCRATCH_ERASE_FAIL] = "SCRATCH_ERASE_FAIL", | |||
[DATA_BUFFER_OVERFLOW] = "DATA_BUFFER_OVERFLOW", | |||
[ADC0_BUFFER_OVERFLOW] = "ADC0_BUFFER_OVERFLOW", | |||
[FUNCTION_INVALID] = "FUNCTION_INVALID", | |||
[SWDT_TIME_INVALID] = "SWDT_TIME_INVALID", | |||
[FLASH_WRITE_FAIL] = "FLASH_WRITE_FAIL", | |||
[FLASH_ERASE_FAIL] = "FLASH_ERASE_FAIL", | |||
[FLASH_JMP_FAIL] = "FLASH_JMP_FAIL", | |||
[FLASH_PSP_TIMEOUT] = "FLASH_PSP_TIMEOUT", | |||
[FLASH_ABORT_RECEIVED] = "FLASH_ABORT_RECEIVED", | |||
[FLASH_PAGE_MISMATCH] = "FLASH_PAGE_MISMATCH", | |||
[FLASH_BLOCK_MISMATCH] = "FLASH_BLOCK_MISMATCH", | |||
[FLASH_PAGE_NOT_IN_CODE_AREA] = "FLASH_PAGE_NOT_IN_CODE_AREA", | |||
[MEM_ILLEGAL_ADDRESS] = "MEM_ILLEGAL_ADDRESS", | |||
[FLASH_LOCKED] = "FLASH_LOCKED", | |||
[INVALID_BLOCK] = "INVALID_BLOCK", | |||
[FLASH_ILLEGAL_PAGE] = "FLASH_ILLEGAL_PAGE", | |||
[STREAM_IS_ACTIVE] = "STREAM_IS_ACTIVE", | |||
[STREAM_TABLE_INVALID] = "STREAM_TABLE_INVALID", | |||
[STREAM_CONFIG_INVALID] = "STREAM_CONFIG_INVALID", | |||
[STREAM_BAD_TRIGGER_SOURCE] = "STREAM_BAD_TRIGGER_SOURCE", | |||
[STREAM_NOT_RUNNING] = "STREAM_NOT_RUNNING", | |||
[STREAM_INVALID_TRIGGER] = "STREAM_INVALID_TRIGGER", | |||
[STREAM_CONTROL_BUFFER_OVERFLOW] = "STREAM_CONTROL_BUFFER_OVERFLOW", | |||
[STREAM_SCAN_OVERLAP] = "STREAM_SCAN_OVERLAP", | |||
[STREAM_SAMPLE_NUM_INVALID] = "STREAM_SAMPLE_NUM_INVALID", | |||
[STREAM_BIPOLAR_GAIN_INVALID] = "STREAM_BIPOLAR_GAIN_INVALID", | |||
[STREAM_SCAN_RATE_INVALID] = "STREAM_SCAN_RATE_INVALID", | |||
[TIMER_INVALID_MODE] = "TIMER_INVALID_MODE", | |||
[TIMER_QUADRATURE_AB_ERROR] = "TIMER_QUADRATURE_AB_ERROR", | |||
[TIMER_QUAD_PULSE_SEQUENCE] = "TIMER_QUAD_PULSE_SEQUENCE", | |||
[TIMER_BAD_CLOCK_SOURCE] = "TIMER_BAD_CLOCK_SOURCE", | |||
[TIMER_STREAM_ACTIVE] = "TIMER_STREAM_ACTIVE", | |||
[TIMER_PWMSTOP_MODULE_ERROR] = "TIMER_PWMSTOP_MODULE_ERROR", | |||
[EXT_OSC_NOT_STABLE] = "EXT_OSC_NOT_STABLE", | |||
[INVALID_POWER_SETTING] = "INVALID_POWER_SETTING", | |||
[PLL_NOT_LOCKED] = "PLL_NOT_LOCKED" | |||
}; | |||
const char * | |||
ue9_error (int errorcode) | |||
const char *ue9_error(int errorcode) | |||
{ | |||
if (errorcode > ARRAY_SIZE (ue9_error_text)) | |||
return "(invalid errorcode)"; | |||
else | |||
return ue9_error_text[errorcode]; | |||
if (errorcode > ARRAY_SIZE(ue9_error_text)) | |||
return "(invalid errorcode)"; | |||
else | |||
return ue9_error_text[errorcode]; | |||
} |
@@ -44,6 +44,6 @@ | |||
extern const char *ue9_error_text[]; | |||
const char *ue9_error (int errorcode); | |||
const char *ue9_error(int errorcode); | |||
#endif |