5 Commits

Author SHA1 Message Date
jim
5a14055029 Fix some build stuff with dependency tracking (oops)
git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@8317 ddd99763-3ecb-0310-9145-efcb8ce7c51f
2010-02-08 21:35:23 +00:00
jim
25bed4b644 rename
git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@8316 ddd99763-3ecb-0310-9145-efcb8ce7c51f
2010-02-08 21:25:26 +00:00
jim
cd63e2fb11 Move ethstream to the parent directory
git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@8314 ddd99763-3ecb-0310-9145-efcb8ce7c51f
2010-02-08 21:23:12 +00:00
zacharyc
329871bf56 Fixed example formatting a bit.
git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@7464 ddd99763-3ecb-0310-9145-efcb8ce7c51f
2009-04-23 16:26:24 +00:00
zacharyc
f4f809eee3 Added "examples" to code
git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@7463 ddd99763-3ecb-0310-9145-efcb8ce7c51f
2009-04-23 16:20:07 +00:00
23 changed files with 2212 additions and 2304 deletions

View File

@@ -19,7 +19,8 @@ PREFIX = /usr/local
MANPATH = ${PREFIX}/man/man1
BINPATH = ${PREFIX}/bin
WINCC = i386-mingw32-gcc
#WINCC = i386-mingw32-gcc
WINCC = i586-mingw32msvc-gcc
WINCFLAGS += $(CFLAGS)
WINLDFLAGS += $(LDFLAGS) -lws2_32 -liphlpapi -s
@@ -32,11 +33,10 @@ default: lin
all: lin win
.PHONY: lin
lin: ljtest ethstream ljconfig \
ethstream.1 ljconfig.1
lin: ethstream ethstream.1 ethstream.txt
.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,16 +86,19 @@ 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 *.dobj *.1 *.txt
# Dependency tracking:
allsources = $(wildcard *.c)
-include $(allsources:.c=.d)
%.o : %.c
$(COMPILE.c) -MP -MMD -MT '$*.obj' -o $@ $<
$(COMPILE.c) -MP -MMD -MT '$*.o' -MF '$*.d' -o $@ $<
-include $(allsources:.c=.dobj)
%.obj : %.c
$(WINCC) $(WINCFLAGS) -MP -MMD -MT '$*.o' -c -o $@ $<
$(WINCC) $(WINCFLAGS) -MP -MMD -MT '$*.obj' -MF '$*.dobj' -c -o $@ $<
# Win32 executable

7
README
View File

@@ -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.

View File

@@ -1 +1 @@
1.1
1.2

View File

@@ -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)
{
int i;
static char buf[128];
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},
};
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);
char *compat_strerror(int errnum)
{
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);
}
#ifdef __WIN32__

View File

@@ -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

17
debug.c
View File

@@ -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;
}

View File

@@ -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) \

File diff suppressed because it is too large Load Diff

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)

74
example.inc Normal file
View File

@@ -0,0 +1,74 @@
char examplestring[] = "\n\
\n\
Welcome to the NILM Ethstream examples.\n\
\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 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 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 currents at 16 kHz and 10V range:\n\
\n\
ethstream -n 3 -r 16000\n\
\n\
The -n option samples a number of channels starting at 0. The rate can be\n\
at least 16000 if 12 channels are sampled , but it can do more if\n\
fewer channels are sampled. The limiting factor is the highest channel\n\
sampled. Sampling just the top channel (11) is as bad as sampling\n\
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, but be aware of the possibility of\n\
data corruption.\n\
\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\
\n\
All of the above examples output a digital number from 0 to 65535 with\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\
\n\
The channels will be output in the order given in the C command. This\n\
command will group the current and voltage data by phase.\n\
\n\
If you are supplying data from ethstream to another program, you might\n\
want to dump its output to a file and terminate after a certain number of\n\
samples:\n\
\n\
ethstream -n 6 -r 8000 - l 16000 > outfile.dat\n\
\n\
This will take 16000 samples at 8 kHz (2 seconds of acquisition) of all\n\
channels and write the data to outfile.dat. This can be directly read\n\
by a package like MATLAB.\n\
\n\
If there are multiple NerdJacks or you have changed the TCP/IP settings\n\
from default, you might have to specify which one you want to talk to:\n\
\n\
ethstream -a 192.168.1.210\n\
\n\
This will sample two channels at 8 kHz from the NerdJack at 192.168.1.210.\n\
This is the default \"1\" setting on the NerdJack. If no address is\n\
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\
the same network, but it will get confused if there are multiple NerdJacks\n\
on the network.\n\
";

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -30,14 +30,13 @@
#define NERD_HEADER_SIZE 8
#define MAX_SOCKETS 32
typedef struct __attribute__ ((__packed__))
{
unsigned char headerone;
unsigned char headertwo;
unsigned short packetNumber;
unsigned short adcused;
unsigned short packetsready;
signed short data[NERDJACK_NUM_SAMPLES];
typedef struct __attribute__ ((__packed__)) {
unsigned char headerone;
unsigned char headertwo;
unsigned short packetNumber;
unsigned short adcused;
unsigned short packetsready;
signed short data[NERDJACK_NUM_SAMPLES];
} dataPacket;
struct discovered_socket {
@@ -54,34 +53,33 @@ struct discover_t {
/* 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)
nerdjack_choose_scan(double desired_rate, double *actual_rate,
unsigned long *period)
{
//The ffffe is because of a silicon bug. The last bit is unusable in all
//devices so far. It is worked around on the chip, but giving it exactly
//0xfffff would cause the workaround code to roll over.
*period = floor ((double) NERDJACK_CLOCK_RATE / desired_rate);
if (*period > 0x0ffffe)
{
info ("Cannot sample that slowly\n");
*actual_rate = (double) NERDJACK_CLOCK_RATE / (double) 0x0ffffe;
*period = 0x0ffffe;
return -1;
}
//Period holds the period register for the NerdJack, so it needs to be right
*actual_rate = (double) NERDJACK_CLOCK_RATE / (double) *period;
if (*actual_rate != desired_rate)
{
return -1;
}
return 0;
//The ffffe is because of a silicon bug. The last bit is unusable in all
//devices so far. It is worked around on the chip, but giving it exactly
//0xfffff would cause the workaround code to roll over.
*period = floor((double)NERDJACK_CLOCK_RATE / desired_rate);
if (*period > 0x0ffffe) {
info("Cannot sample that slowly\n");
*actual_rate = (double)NERDJACK_CLOCK_RATE / (double)0x0ffffe;
*period = 0x0ffffe;
return -1;
}
//Period holds the period register for the NerdJack, so it needs to be right
*actual_rate = (double)NERDJACK_CLOCK_RATE / (double)*period;
if (*actual_rate != desired_rate) {
return -1;
}
return 0;
}
/**
* Create a discovered socket and add it to the socket list structure.
* All sockets in the structure should be created, bound, and ready for broadcasting
*/
static int discovered_sock_create(struct discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)
static int discovered_sock_create(struct discover_t *ds, uint32_t local_ip,
uint32_t subnet_mask)
{
if (ds->sock_count >= MAX_SOCKETS) {
return 0;
@@ -95,14 +93,14 @@ static int discovered_sock_create(struct discover_t *ds, uint32_t local_ip, uint
/* Allow broadcast. */
int sock_opt = 1;
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt,
sizeof(sock_opt));
/* Set nonblocking */
if (soblock (sock, 0) < 0)
{
verb ("can't set nonblocking\n");
return 0;
}
/* Set nonblocking */
if (soblock(sock, 0) < 0) {
verb("can't set nonblocking\n");
return 0;
}
/* Bind socket. */
struct sockaddr_in sock_addr;
@@ -123,13 +121,15 @@ static int discovered_sock_create(struct discover_t *ds, uint32_t local_ip, uint
return 1;
}
/**
* Enumerate all interfaces we can find and open sockets on each
*/
#if defined(USE_IPHLPAPI)
#if defined(USE_IPHLPAPI)
static void enumerate_interfaces(struct discover_t *ds)
{
PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
PIP_ADAPTER_INFO pAdapterInfo =
(IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO));
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
DWORD Ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
@@ -138,7 +138,7 @@ static void enumerate_interfaces(struct discover_t *ds)
if (Ret != ERROR_BUFFER_OVERFLOW) {
return;
}
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
Ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
if (Ret != NO_ERROR) {
free(pAdapterInfo);
@@ -150,8 +150,10 @@ static void enumerate_interfaces(struct discover_t *ds)
while (pAdapter) {
IP_ADDR_STRING *pIPAddr = &pAdapter->IpAddressList;
while (pIPAddr) {
uint32_t local_ip = ntohl(inet_addr(pIPAddr->IpAddress.String));
uint32_t mask = ntohl(inet_addr(pIPAddr->IpMask.String));
uint32_t local_ip =
ntohl(inet_addr(pIPAddr->IpAddress.String));
uint32_t mask =
ntohl(inet_addr(pIPAddr->IpMask.String));
if (local_ip == 0) {
pIPAddr = pIPAddr->Next;
@@ -169,9 +171,10 @@ static void enumerate_interfaces(struct discover_t *ds)
}
#else
static void enumerate_interfaces(struct discover_t *ds) {
static void enumerate_interfaces(struct discover_t *ds)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) {
if (fd == -1) {
return;
}
@@ -187,8 +190,8 @@ static void enumerate_interfaces(struct discover_t *ds) {
return;
}
uint8_t *ptr = (uint8_t *)ifc.ifc_req;
uint8_t *end = (uint8_t *)&ifc.ifc_buf[ifc.ifc_len];
uint8_t *ptr = (uint8_t *) ifc.ifc_req;
uint8_t *end = (uint8_t *) & ifc.ifc_buf[ifc.ifc_len];
while (ptr <= end) {
struct ifreq *ifr = (struct ifreq *)ptr;
@@ -197,7 +200,8 @@ static void enumerate_interfaces(struct discover_t *ds) {
if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
continue;
}
struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr);
struct sockaddr_in *addr_in =
(struct sockaddr_in *)&(ifr->ifr_addr);
uint32_t local_ip = ntohl(addr_in->sin_addr.s_addr);
if (local_ip == 0) {
continue;
@@ -207,7 +211,8 @@ static void enumerate_interfaces(struct discover_t *ds) {
continue;
}
struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr);
struct sockaddr_in *mask_in =
(struct sockaddr_in *)&(ifr->ifr_addr);
uint32_t mask = ntohl(mask_in->sin_addr.s_addr);
discovered_sock_create(ds, local_ip, mask);
@@ -228,55 +233,51 @@ static void destroy_socks(struct discover_t *ds)
free(ds);
}
/* Perform autodetection. Returns 0 on success, -1 on error
* Sets ipAddress to the detected address
*/
int
nerdjack_detect (char *ipAddress)
int nerdjack_detect(char *ipAddress)
{
int32_t receivesock;
struct sockaddr_in sa, receiveaddr, sFromAddr;
int buffer_length;
char buffer[200];
char incomingData[10];
unsigned int lFromLen;
int32_t receivesock;
struct sockaddr_in sa, receiveaddr, sFromAddr;
int buffer_length;
char buffer[200];
char incomingData[10];
unsigned int lFromLen;
sprintf (buffer, "TEST");
buffer_length = strlen (buffer) + 1;
sprintf(buffer, "TEST");
buffer_length = strlen(buffer) + 1;
net_init ();
receivesock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
net_init();
/* Set nonblocking */
if (soblock (receivesock, 0) < 0)
{
verb ("can't set nonblocking\n");
return -1;
}
receivesock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (-1 == receivesock) /* if socket failed to initialize, exit */
{
verb ("Error Creating Socket\n");
return -1;
}
/* Set nonblocking */
if (soblock(receivesock, 0) < 0) {
verb("can't set nonblocking\n");
return -1;
}
//Setup family for both sockets
sa.sin_family = PF_INET;
receiveaddr.sin_family = PF_INET;
if (-1 == receivesock) { /* if socket failed to initialize, exit */
verb("Error Creating Socket\n");
return -1;
}
//Setup family for both sockets
sa.sin_family = PF_INET;
receiveaddr.sin_family = PF_INET;
//Setup ports to send on DATA and receive on RECEIVE
receiveaddr.sin_port = htons (NERDJACK_UDP_RECEIVE_PORT);
sa.sin_port = htons (NERDJACK_DATA_PORT);
//Setup ports to send on DATA and receive on RECEIVE
receiveaddr.sin_port = htons(NERDJACK_UDP_RECEIVE_PORT);
sa.sin_port = htons(NERDJACK_DATA_PORT);
//Receive from any IP address
receiveaddr.sin_addr.s_addr = INADDR_ANY;
//Receive from any IP address
receiveaddr.sin_addr.s_addr = INADDR_ANY;
bind (receivesock, (struct sockaddr *) &receiveaddr,
sizeof (struct sockaddr_in));
struct discover_t *ds = (struct discover_t *)calloc(1, sizeof(struct discover_t));
bind(receivesock, (struct sockaddr *)&receiveaddr,
sizeof(struct sockaddr_in));
struct discover_t *ds =
(struct discover_t *)calloc(1, sizeof(struct discover_t));
if (!ds) {
return -1;
}
@@ -298,406 +299,400 @@ nerdjack_detect (char *ipAddress)
for (i = 0; i < ds->sock_count; i++) {
struct discovered_socket *dss = &ds->socks[i];
uint32_t target_ip = dss->local_ip | ~dss->subnet_mask;
sa.sin_addr.s_addr = htonl(target_ip);
sendto (dss->sock, buffer, buffer_length, 0, (struct sockaddr *) &sa,
sizeof (struct sockaddr_in));
sa.sin_addr.s_addr = htonl(target_ip);
sendto(dss->sock, buffer, buffer_length, 0,
(struct sockaddr *)&sa, sizeof(struct sockaddr_in));
}
destroy_socks(ds);
destroy_socks(ds);
lFromLen = sizeof (sFromAddr);
lFromLen = sizeof(sFromAddr);
if (0 >
recvfrom_timeout (receivesock, incomingData, sizeof (incomingData), 0,
(struct sockaddr *) &sFromAddr, &lFromLen,
&(struct timeval)
{
.tv_sec = NERDJACK_TIMEOUT}))
{
close(receivesock);
return -1;
}
if (0 >
recvfrom_timeout(receivesock, incomingData, sizeof(incomingData), 0,
(struct sockaddr *)&sFromAddr, &lFromLen,
&(struct timeval) {
.tv_sec = NERDJACK_TIMEOUT})) {
close(receivesock);
return -1;
}
ipAddress = malloc (INET_ADDRSTRLEN);
ipAddress = malloc(INET_ADDRSTRLEN);
//It isn't ipv6 friendly, but inet_ntop isn't on Windows...
strcpy (ipAddress, inet_ntoa (sFromAddr.sin_addr));
//It isn't ipv6 friendly, but inet_ntop isn't on Windows...
strcpy(ipAddress, inet_ntoa(sFromAddr.sin_addr));
close (receivesock);
return 0;
close(receivesock);
return 0;
}
/*
* Get the NerdJack version string and print it
*/
int nerd_get_version(const char *address)
{
int ret, fd_command;
char buf[200];
fd_command = nerd_open(address, NERDJACK_COMMAND_PORT);
if (fd_command < 0) {
info("Connect failed: %s:%d\n", address, NERDJACK_COMMAND_PORT);
return -2;
}
/* Send request */
ret = send_all_timeout(fd_command, "VERS", 4, 0, &(struct timeval) {
.tv_sec = NERDJACK_TIMEOUT});
if (ret < 0) {
verb("short send %d\n", (int)ret);
return -1;
}
ret = recv_all_timeout(fd_command, buf, 200, 0, &(struct timeval) {
.tv_sec = NERDJACK_TIMEOUT});
nerd_close_conn(fd_command);
if (ret < 0) {
verb("Error receiving command\n");
return -1;
}
//Slice off the "OK" from the string
buf[strlen(buf) - 2] = '\0';
printf("%s\n", buf);
return 0;
}
/* Send the given command to address. The command should be something
* of the specified length. This expects the NerdJack to reply with OK
* or NO
*/
int
nerd_send_command (const char *address, void *command, int length)
int nerd_send_command(const char *address, void *command, int length)
{
int ret, fd_command;
char buf[3];
fd_command = nerd_open (address, NERDJACK_COMMAND_PORT);
if (fd_command < 0)
{
info ("Connect failed: %s:%d\n", address, NERDJACK_COMMAND_PORT);
return -2;
}
int ret, fd_command;
char buf[3];
fd_command = nerd_open(address, NERDJACK_COMMAND_PORT);
if (fd_command < 0) {
info("Connect failed: %s:%d\n", address, NERDJACK_COMMAND_PORT);
return -2;
}
/* Send request */
ret = send_all_timeout (fd_command, command, length, 0, &(struct timeval)
{
.tv_sec = NERDJACK_TIMEOUT});
if (ret < 0 || ret != length)
{
verb ("short send %d\n", (int) ret);
return -1;
}
/* Send request */
ret = send_all_timeout(fd_command, command, length, 0, &(struct timeval) {
.tv_sec = NERDJACK_TIMEOUT});
if (ret < 0 || ret != length) {
verb("short send %d\n", (int)ret);
return -1;
}
ret = recv_all_timeout (fd_command, buf, 3, 0, &(struct timeval)
{
.tv_sec = NERDJACK_TIMEOUT});
ret = recv_all_timeout(fd_command, buf, 3, 0, &(struct timeval) {
.tv_sec = NERDJACK_TIMEOUT});
nerd_close_conn (fd_command);
nerd_close_conn(fd_command);
if (ret < 0 || ret != 3)
{
verb ("Error receiving OK for command\n");
return -1;
}
if (ret < 0 || ret != 3) {
verb("Error receiving OK for command\n");
return -1;
}
if (0 != strcmp ("OK", buf))
{
verb ("Did not receive OK. Received %s\n", buf);
return -4;
}
if (0 != strcmp("OK", buf)) {
verb("Did not receive OK. Received %s\n", buf);
return -4;
}
return 0;
return 0;
}
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)
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)
{
//Variables that should persist across retries
static dataPacket buf;
static int linesleft = 0;
static int linesdumped = 0;
//Variables that should persist across retries
static dataPacket buf;
static int linesleft = 0;
static int linesdumped = 0;
//Variables essential to packet processing
signed short datapoint = 0;
int i;
//Variables essential to packet processing
signed short datapoint = 0;
int i;
int numChannelsSampled = channel_list[0] + 1;
int numChannelsSampled = channel_list[0] + 1;
//The number sampled will be the highest channel requested plus 1
//(i.e. channel 0 requested means 1 sampled)
for (i = 0; i < numChannels; i++)
{
if (channel_list[i] + 1 > numChannelsSampled)
numChannelsSampled = channel_list[i] + 1;
}
double voltline[numChannels];
unsigned short dataline[numChannels];
unsigned short packetsready = 0;
unsigned short adcused = 0;
unsigned short tempshort = 0;
int charsread = 0;
int numgroupsProcessed = 0;
double volts;
//The timeout should be the expected time plus 60 seconds
//This permits slower speeds to work properly
unsigned int expectedtimeout =
(period * NERDJACK_NUM_SAMPLES / NERDJACK_CLOCK_RATE) + 60;
//Check to see if we're trying to resume
//Don't blow away linesleft in that case
if (lines != 0 && linesleft == 0)
{
linesleft = lines;
}
//If there was a reset, we still need to dump a line because of faulty PDCA start
if (wasreset)
{
linesdumped = 0;
}
//If this is the first time called, warn the user if we're too fast
if (linesdumped == 0)
{
if (period < (numChannelsSampled * 200 + 600))
{
info ("You are sampling close to the limit of NerdJack\n");
info ("Sample fewer channels or sample slower\n");
}
}
//Now destination structure array is set as well as numDuplicates.
int totalGroups = NERDJACK_NUM_SAMPLES / numChannelsSampled;
//Loop forever to grab data
while ((charsread =
recv_all_timeout (data_fd, &buf, NERDJACK_PACKET_SIZE, 0,
&(struct timeval)
{
.tv_sec = expectedtimeout})))
{
if (charsread != NERDJACK_PACKET_SIZE)
{
//There was a problem getting data. Probably a closed
//connection.
info ("Packet timed out or was too short\n");
return -2;
//The number sampled will be the highest channel requested plus 1
//(i.e. channel 0 requested means 1 sampled)
for (i = 0; i < numChannels; i++) {
if (channel_list[i] + 1 > numChannelsSampled)
numChannelsSampled = channel_list[i] + 1;
}
//First check the header info
if (buf.headerone != 0xF0 || buf.headertwo != 0xAA)
{
info ("No Header info\n");
return -1;
double voltline[numChannels];
unsigned short dataline[numChannels];
unsigned short packetsready = 0;
unsigned short adcused = 0;
unsigned short tempshort = 0;
int charsread = 0;
int numgroupsProcessed = 0;
double volts;
//The timeout should be the expected time plus 60 seconds
//This permits slower speeds to work properly
unsigned int expectedtimeout =
(period * NERDJACK_NUM_SAMPLES / NERDJACK_CLOCK_RATE) + 60;
//Check to see if we're trying to resume
//Don't blow away linesleft in that case
if (lines != 0 && linesleft == 0) {
linesleft = lines;
}
//Check counter info to make sure not out of order
tempshort = ntohs (buf.packetNumber);
if (tempshort != *currentcount)
{
info ("Count wrong. Expected %hd but got %hd\n", *currentcount,
tempshort);
return -1;
//If there was a reset, we still need to dump a line because of faulty PDCA start
if (wasreset) {
linesdumped = 0;
}
//Increment number of packets received
*currentcount = *currentcount + 1;
adcused = ntohs (buf.adcused);
packetsready = ntohs (buf.packetsready);
numgroupsProcessed = 0;
if (showmem)
{
printf ("%hd %hd\n", adcused, packetsready);
continue;
}
//While there is still more data in the packet, process it
while (numgroupsProcessed < totalGroups)
{
//Poison the data structure
switch (convert)
{
case CONVERT_VOLTS:
memset (voltline, 0, numChannels * sizeof (double));
break;
default:
case CONVERT_HEX:
case CONVERT_DEC:
memset (dataline, 0, numChannels * sizeof (unsigned char));
}
//Read in each group
for (i = 0; i < numChannels; i++)
{
//Get the datapoint associated with the desired channel
datapoint =
ntohs (buf.
data[channel_list[i] +
numgroupsProcessed * numChannelsSampled]);
//Place it into the line
switch (convert)
{
case CONVERT_VOLTS:
if (channel_list[i] <= 5)
{
volts =
(double) (datapoint / 32767.0) *
((precision & 0x01) ? 5.0 : 10.0);
}
else
{
volts =
(double) (datapoint / 32767.0) *
((precision & 0x02) ? 5.0 : 10.0);
}
voltline[i] = volts;
break;
default:
case CONVERT_HEX:
case CONVERT_DEC:
dataline[i] = (unsigned short) (datapoint - INT16_MIN);
break;
//If this is the first time called, warn the user if we're too fast
if (linesdumped == 0) {
if (period < (numChannelsSampled * 200 + 600)) {
info("You are sampling close to the limit of NerdJack\n");
info("Sample fewer channels or sample slower\n");
}
}
//We want to dump the first line because it's usually spurious
if (linesdumped != 0)
{
//Now print the group
switch (convert)
{
case CONVERT_VOLTS:
for (i = 0; i < numChannels; i++)
{
if (printf ("%lf ", voltline[i]) < 0)
goto bad;
}
break;
case CONVERT_HEX:
for (i = 0; i < numChannels; i++)
{
if (printf ("%04hX", dataline[i]) < 0)
goto bad;
}
break;
default:
case CONVERT_DEC:
for (i = 0; i < numChannels; i++)
{
if (printf ("%hu ", dataline[i]) < 0)
goto bad;
}
break;
}
if (printf ("\n") < 0)
goto bad;
//If we're counting lines, decrement them
if (lines != 0)
{
linesleft--;
if (linesleft == 0)
{
return 0;
}
}
}
else
{
linesdumped = linesdumped + 1;
}
//We've processed this group, so advance the counter
numgroupsProcessed++;
}
}
//Now destination structure array is set as well as numDuplicates.
return 0;
int totalGroups = NERDJACK_NUM_SAMPLES / numChannelsSampled;
bad:
info ("Output error (disk full?)\n");
return -3;
//Loop forever to grab data
while ((charsread =
recv_all_timeout(data_fd, &buf, NERDJACK_PACKET_SIZE, 0,
&(struct timeval) {
.tv_sec = expectedtimeout}))) {
if (charsread != NERDJACK_PACKET_SIZE) {
//There was a problem getting data. Probably a closed
//connection.
info("Packet timed out or was too short\n");
return -2;
}
//First check the header info
if (buf.headerone != 0xF0 || buf.headertwo != 0xAA) {
info("No Header info\n");
return -1;
}
//Check counter info to make sure not out of order
tempshort = ntohs(buf.packetNumber);
if (tempshort != *currentcount) {
info("Count wrong. Expected %hd but got %hd\n",
*currentcount, tempshort);
return -1;
}
//Increment number of packets received
*currentcount = *currentcount + 1;
adcused = ntohs(buf.adcused);
packetsready = ntohs(buf.packetsready);
numgroupsProcessed = 0;
if (showmem) {
printf("%hd %hd\n", adcused, packetsready);
continue;
}
//While there is still more data in the packet, process it
while (numgroupsProcessed < totalGroups) {
//Poison the data structure
switch (convert) {
case CONVERT_VOLTS:
memset(voltline, 0,
numChannels * sizeof(double));
break;
default:
case CONVERT_HEX:
case CONVERT_DEC:
memset(dataline, 0,
numChannels * sizeof(unsigned char));
}
//Read in each group
for (i = 0; i < numChannels; i++) {
//Get the datapoint associated with the desired channel
datapoint =
ntohs(buf.data[channel_list[i] +
numgroupsProcessed *
numChannelsSampled]);
//Place it into the line
switch (convert) {
case CONVERT_VOLTS:
if (channel_list[i] <= 5) {
volts =
(double)(datapoint /
32767.0) *
((precision & 0x01) ? 5.0 :
10.0);
} else {
volts =
(double)(datapoint /
32767.0) *
((precision & 0x02) ? 5.0 :
10.0);
}
voltline[i] = volts;
break;
default:
case CONVERT_HEX:
case CONVERT_DEC:
dataline[i] =
(unsigned short)(datapoint -
INT16_MIN);
break;
}
}
//We want to dump the first line because it's usually spurious
if (linesdumped != 0) {
//Now print the group
switch (convert) {
case CONVERT_VOLTS:
for (i = 0; i < numChannels; i++) {
if (printf("%lf ", voltline[i])
< 0)
goto bad;
}
break;
case CONVERT_HEX:
for (i = 0; i < numChannels; i++) {
if (printf("%04hX", dataline[i])
< 0)
goto bad;
}
break;
default:
case CONVERT_DEC:
for (i = 0; i < numChannels; i++) {
if (printf("%hu ", dataline[i])
< 0)
goto bad;
}
break;
}
if (printf("\n") < 0)
goto bad;
//If we're counting lines, decrement them
if (lines != 0) {
linesleft--;
if (linesleft == 0) {
return 0;
}
}
} else {
linesdumped = linesdumped + 1;
}
//We've processed this group, so advance the counter
numgroupsProcessed++;
}
}
return 0;
bad:
info("Output error (disk full?)\n");
return -3;
}
/* Open a connection to the NerdJack */
int
nerd_open (const char *address, int port)
int nerd_open(const char *address, int port)
{
struct hostent *he;
struct hostent *he;
net_init ();
net_init();
int32_t i32SocketFD = socket (PF_INET, SOCK_STREAM, 0);
int32_t i32SocketFD = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == i32SocketFD)
{
verb ("cannot create socket");
return -1;
}
if (-1 == i32SocketFD) {
verb("cannot create socket");
return -1;
}
/* Set nonblocking */
if (soblock (i32SocketFD, 0) < 0)
{
verb ("can't set nonblocking\n");
return -1;
}
/* Set nonblocking */
if (soblock(i32SocketFD, 0) < 0) {
verb("can't set nonblocking\n");
return -1;
}
struct sockaddr_in stSockAddr;
memset (&stSockAddr, 0, sizeof (stSockAddr));
struct sockaddr_in stSockAddr;
memset(&stSockAddr, 0, sizeof(stSockAddr));
stSockAddr.sin_family = AF_INET;
stSockAddr.sin_port = htons (port);
stSockAddr.sin_family = AF_INET;
stSockAddr.sin_port = htons(port);
he = gethostbyname (address);
if (he == NULL)
{
verb ("gethostbyname(\"%s\") failed\n", address);
return -1;
}
stSockAddr.sin_addr = *((struct in_addr *) he->h_addr);
he = gethostbyname(address);
if (he == NULL) {
verb("gethostbyname(\"%s\") failed\n", address);
return -1;
}
stSockAddr.sin_addr = *((struct in_addr *)he->h_addr);
debug ("Resolved %s -> %s\n", address, inet_ntoa (stSockAddr.sin_addr));
debug("Resolved %s -> %s\n", address, inet_ntoa(stSockAddr.sin_addr));
/* Connect */
if (connect_timeout
(i32SocketFD, (struct sockaddr *) &stSockAddr, sizeof (stSockAddr),
&(struct timeval)
{
.tv_sec = 3}) < 0)
{
verb ("connection to %s:%d failed: %s\n",
inet_ntoa (stSockAddr.sin_addr), port, compat_strerror (errno));
return -1;
}
/* Connect */
if (connect_timeout
(i32SocketFD, (struct sockaddr *)&stSockAddr, sizeof(stSockAddr),
&(struct timeval) {
.tv_sec = 3}) < 0) {
verb("connection to %s:%d failed: %s\n",
inet_ntoa(stSockAddr.sin_addr), port,
compat_strerror(errno));
return -1;
}
return i32SocketFD;
return i32SocketFD;
}
//Generate an appropriate sample initiation command
int
nerd_generate_command (getPacket * command, int *channel_list,
int channel_count, int precision, unsigned long period)
nerd_generate_command(getPacket * command, int *channel_list,
int channel_count, int precision, unsigned long period)
{
short channelbit = 0;
int i;
int highestchannel = 0;
short channelbit = 0;
int i;
int highestchannel = 0;
for (i = 0; i < channel_count; i++)
{
if (channel_list[i] > highestchannel)
{
highestchannel = channel_list[i];
for (i = 0; i < channel_count; i++) {
if (channel_list[i] > highestchannel) {
highestchannel = channel_list[i];
}
//channelbit = channelbit | (0x1 << channel_list[i]);
}
//channelbit = channelbit | (0x1 << channel_list[i]);
}
for (i = 0; i <= highestchannel; i++)
{
channelbit = channelbit | (0x01 << i);
}
for (i = 0; i <= highestchannel; i++) {
channelbit = channelbit | (0x01 << i);
}
command->word[0] = 'G';
command->word[1] = 'E';
command->word[2] = 'T';
command->word[3] = 'D';
command->channelbit = htons (channelbit);
command->precision = precision;
command->period = htonl (period);
command->prescaler = 0;
command->word[0] = 'G';
command->word[1] = 'E';
command->word[2] = 'T';
command->word[3] = 'D';
command->channelbit = htons(channelbit);
command->precision = precision;
command->period = htonl(period);
command->prescaler = 0;
return 0;
return 0;
}
int
nerd_close_conn (int data_fd)
int nerd_close_conn(int data_fd)
{
shutdown (data_fd, 2);
close (data_fd);
return 0;
shutdown(data_fd, 2);
close(data_fd);
return 0;
}

View File

@@ -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

336
netutil.c
View File

@@ -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;
int sockopt;
/* Get flags */
sockopt = fcntl (socket, F_GETFL);
if (sockopt == -1)
{
return -1;
}
/* Get flags */
sockopt = fcntl(socket, F_GETFL);
if (sockopt == -1) {
return -1;
}
/* Modify */
if (blocking)
sockopt &= ~O_NONBLOCK;
else
sockopt |= O_NONBLOCK;
/* Modify */
if (blocking)
sockopt &= ~O_NONBLOCK;
else
sockopt |= O_NONBLOCK;
/* Set flags */
if (fcntl (socket, F_SETFL, sockopt) != 0)
return -1;
/* Set flags */
if (fcntl(socket, F_SETFL, sockopt) != 0)
return -1;
return 0;
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;
int ret;
fd_set writefds;
fd_set exceptfds;
int optval;
socklen_t optlen;
/* Start connect */
ret = connect (s, serv_addr, addrlen);
/* Start connect */
ret = connect(s, serv_addr, addrlen);
if (ret == 0)
{
/* Success */
return 0;
}
if (ret == 0) {
/* Success */
return 0;
}
/* Check for immediate failure */
/* 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;
}
/* 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;
/* 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;
}
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;
}
/* 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;
/* 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_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;
}
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);
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_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;
}
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);
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_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;
}
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);
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;
}

View File

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

155
opt.c
View File

@@ -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);
}
}

19
opt.h
View File

@@ -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

1069
ue9.c

File diff suppressed because it is too large Load Diff

148
ue9.h
View File

@@ -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

View File

@@ -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];
}

View File

@@ -44,6 +44,6 @@
extern const char *ue9_error_text[];
const char *ue9_error (int errorcode);
const char *ue9_error(int errorcode);
#endif

View File

@@ -1,2 +1,2 @@
/* This file was automatically generated. */
#define VERSION "1.1 (2009-04-17)"
#define VERSION "1.2 (2010-02-08)"