git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@7298 ddd99763-3ecb-0310-9145-efcb8ce7c51ftags/ethstream-1.1
@@ -3,55 +3,83 @@ | |||||
#include "compat.h" | #include "compat.h" | ||||
#include <windows.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 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); | |||||
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]; | |||||
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__ | #ifdef __WIN32__ | ||||
@@ -80,4 +108,3 @@ char *compat_strerror(int errnum) | |||||
} | } | ||||
*/ | */ | ||||
#endif | #endif | ||||
@@ -2,8 +2,8 @@ | |||||
#define COMPAT_H | #define COMPAT_H | ||||
#ifdef __WIN32__ | #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); | //const char *inet_ntop(int af, void *src, const char *dst, socklen_t cnt); | ||||
#define INET_ADDRSTRLEN 16 | #define INET_ADDRSTRLEN 16 | ||||
#define ETIMEDOUT 110 | #define ETIMEDOUT 110 | ||||
@@ -4,15 +4,15 @@ | |||||
int verb_count = 0; | 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> | #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...) ({ \ | #define debug(x...) ({ \ | ||||
if(verb_count >= 2) \ | if(verb_count >= 2) \ | ||||
@@ -25,74 +25,78 @@ | |||||
#define UE9_COMMAND_PORT 52360 | #define UE9_COMMAND_PORT 52360 | ||||
struct options opt[] = { | 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 } | |||||
{'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 | |||||
main (int argc, char *argv[]) | |||||
{ | { | ||||
int optind; | |||||
char *optarg; | |||||
char c; | |||||
FILE *help = stderr; | |||||
char *address = strdup(DEFAULT_HOST); | |||||
int fd; | |||||
int ret; | |||||
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; | |||||
} | |||||
/* 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; | |||||
if (optind < argc) | |||||
{ | |||||
info ("Error: too many arguments (%s)\n\n", argv[optind]); | |||||
goto printhelp; | |||||
} | |||||
/* Open */ | |||||
fd = ue9_open(address, UE9_COMMAND_PORT); | |||||
if (fd < 0) { | |||||
info("Connect failed: %s:%d\n", address, UE9_COMMAND_PORT); | |||||
goto out0; | |||||
} | |||||
ret = 1; | |||||
goto out1; | |||||
ret = 0; | |||||
out1: | |||||
/* Close */ | |||||
ue9_close(fd); | |||||
out0: | |||||
return ret; | |||||
} | |||||
/* 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; | |||||
} |
@@ -16,52 +16,53 @@ | |||||
#include "ue9.h" | #include "ue9.h" | ||||
#include "compat.h" | #include "compat.h" | ||||
int main(int argc, char *argv[]) | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | { | ||||
int fd_cmd; | |||||
struct ue9Calibration calib; | |||||
int fd_cmd; | |||||
struct ue9Calibration calib; | |||||
verb_count = 2; | |||||
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; | |||||
} | |||||
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; | |||||
} | |||||
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); | |||||
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); | |||||
ue9_close (fd_cmd); | |||||
return 0; | |||||
return 0; | |||||
} | } |
@@ -25,464 +25,553 @@ | |||||
#include "netutil.h" | #include "netutil.h" | ||||
#include "ethstream.h" | #include "ethstream.h" | ||||
#define NERDJACK_TIMEOUT 5 /* Timeout for connect/send/recv, in seconds */ | |||||
#define NERDJACK_TIMEOUT 5 /* Timeout for connect/send/recv, in seconds */ | |||||
//Struct holding information about how channels should be reordered for output | //Struct holding information about how channels should be reordered for output | ||||
typedef struct { | |||||
int numCopies; | |||||
int * destlist; | |||||
typedef struct | |||||
{ | |||||
int numCopies; | |||||
int *destlist; | |||||
} deststruct; | } deststruct; | ||||
typedef struct __attribute__((__packed__)) { | |||||
unsigned char headerone; | |||||
unsigned char headertwo; | |||||
unsigned short packetNumber; | |||||
unsigned long lwipmemoryused; | |||||
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 long lwipmemoryused; | |||||
unsigned short adcused; | |||||
unsigned short packetsready; | |||||
signed short data[NERDJACK_NUM_SAMPLES]; | |||||
} dataPacket; | } dataPacket; | ||||
/* Choose the best ScanConfig and ScanInterval parameters for the | /* Choose the best ScanConfig and ScanInterval parameters for the | ||||
desired scanrate. Returns -1 if no valid config found */ | desired scanrate. Returns -1 if no valid config found */ | ||||
int nerdjack_choose_scan(double desired_rate, double *actual_rate, unsigned long *period) | |||||
int | |||||
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; | |||||
//info("Sampling at slowest rate:%f\n",*actual_rate); | |||||
return -1; | |||||
//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; | |||||
//info("Sampling at slowest rate:%f\n",*actual_rate); | |||||
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) { | |||||
//info("Sampling at nearest rate:%f\n",*actual_rate); | |||||
return -1; | |||||
} | |||||
return 0; | |||||
//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) | |||||
{ | |||||
//info("Sampling at nearest rate:%f\n",*actual_rate); | |||||
return -1; | |||||
} | |||||
return 0; | |||||
} | } | ||||
int nerdjack_detect(char * ipAddress) { | |||||
int32_t sock, receivesock; | |||||
struct sockaddr_in sa, receiveaddr, sFromAddr; | |||||
int bytes_sent, buffer_length; | |||||
char buffer[200]; | |||||
char incomingData[10]; | |||||
unsigned int lFromLen; | |||||
sprintf(buffer, "TEST"); | |||||
buffer_length = strlen(buffer) + 1; | |||||
net_init(); | |||||
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); | |||||
receivesock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); | |||||
/* Set nonblocking */ | |||||
if (soblock(sock, 0) < 0) { | |||||
verb("can't set nonblocking\n"); | |||||
int | |||||
nerdjack_detect (char *ipAddress) | |||||
{ | |||||
int32_t sock, receivesock; | |||||
struct sockaddr_in sa, receiveaddr, sFromAddr; | |||||
int bytes_sent, buffer_length; | |||||
char buffer[200]; | |||||
char incomingData[10]; | |||||
unsigned int lFromLen; | |||||
sprintf (buffer, "TEST"); | |||||
buffer_length = strlen (buffer) + 1; | |||||
net_init (); | |||||
sock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); | |||||
receivesock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); | |||||
/* Set nonblocking */ | |||||
if (soblock (sock, 0) < 0) | |||||
{ | |||||
verb ("can't set nonblocking\n"); | |||||
return -1; | return -1; | ||||
} | |||||
/* Set nonblocking */ | |||||
if (soblock(receivesock, 0) < 0) { | |||||
verb("can't set nonblocking\n"); | |||||
} | |||||
/* Set nonblocking */ | |||||
if (soblock (receivesock, 0) < 0) | |||||
{ | |||||
verb ("can't set nonblocking\n"); | |||||
return -1; | return -1; | ||||
} | |||||
} | |||||
int opt = 1; | |||||
setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(void *) &opt,sizeof(int)); | |||||
if((-1 == sock) || (-1 == receivesock)) /* if socket failed to initialize, exit */ | |||||
{ | |||||
verb("Error Creating Socket\n"); | |||||
int opt = 1; | |||||
setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (void *) &opt, sizeof (int)); | |||||
if ((-1 == sock) || (-1 == receivesock)) /* if socket failed to initialize, exit */ | |||||
{ | |||||
verb ("Error Creating Socket\n"); | |||||
return -1; | 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); | |||||
//Receive from any IP address, Will send to broadcast | |||||
receiveaddr.sin_addr.s_addr = INADDR_ANY; | |||||
sa.sin_addr.s_addr = INADDR_BROADCAST; | |||||
bind(receivesock,(struct sockaddr*) &receiveaddr, sizeof(struct sockaddr_in)); | |||||
bytes_sent = sendto(sock, buffer, buffer_length, 0,(struct sockaddr*) &sa, sizeof(struct sockaddr_in) ); | |||||
if(bytes_sent < 0) { | |||||
info("Error sending packet: %s\n", strerror(errno) ); | |||||
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); | |||||
//Receive from any IP address, Will send to broadcast | |||||
receiveaddr.sin_addr.s_addr = INADDR_ANY; | |||||
sa.sin_addr.s_addr = INADDR_BROADCAST; | |||||
lFromLen = sizeof(sFromAddr); | |||||
if(0 > recvfrom_timeout(receivesock, incomingData, sizeof(incomingData),0,(struct sockaddr *) &sFromAddr, &lFromLen, | |||||
& (struct timeval) { .tv_sec = NERDJACK_TIMEOUT })) { | |||||
return -1; | |||||
bind (receivesock, (struct sockaddr *) &receiveaddr, | |||||
sizeof (struct sockaddr_in)); | |||||
bytes_sent = | |||||
sendto (sock, buffer, buffer_length, 0, (struct sockaddr *) &sa, | |||||
sizeof (struct sockaddr_in)); | |||||
if (bytes_sent < 0) | |||||
{ | |||||
info ("Error sending packet: %s\n", strerror (errno)); | |||||
return -1; | |||||
} | } | ||||
ipAddress = malloc(INET_ADDRSTRLEN); | |||||
//It isn't ipv6 friendly, but inet_ntop isn't on Windows... | |||||
strcpy(ipAddress, inet_ntoa(sFromAddr.sin_addr)); | |||||
close(sock); /* close the socket */ | |||||
close(receivesock); | |||||
return 0; | |||||
lFromLen = sizeof (sFromAddr); | |||||
if (0 > | |||||
recvfrom_timeout (receivesock, incomingData, sizeof (incomingData), 0, | |||||
(struct sockaddr *) &sFromAddr, &lFromLen, | |||||
&(struct timeval) | |||||
{ | |||||
.tv_sec = NERDJACK_TIMEOUT})) | |||||
{ | |||||
return -1; | |||||
} | |||||
ipAddress = malloc (INET_ADDRSTRLEN); | |||||
//It isn't ipv6 friendly, but inet_ntop isn't on Windows... | |||||
strcpy (ipAddress, inet_ntoa (sFromAddr.sin_addr)); | |||||
close (sock); /* close the socket */ | |||||
close (receivesock); | |||||
return 0; | |||||
} | } | ||||
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 -3; | |||||
if (0 != strcmp ("OK", buf)) | |||||
{ | |||||
verb ("Did not receive OK. Received %s\n", buf); | |||||
return -3; | |||||
} | } | ||||
return 0; | |||||
return 0; | |||||
} | } | ||||
//Initialize the channel structure to distill how data should be displayed | //Initialize the channel structure to distill how data should be displayed | ||||
static void nerd_init_channels(deststruct * destination, int numChannels, int numChannelsSampled, int *channel_list) { | |||||
int channelprocessing = 0; | |||||
int currentalign = 0; //Index into sampled channels | |||||
int i; | |||||
int tempdestlist[NERDJACK_CHANNELS]; | |||||
//Clear out destination stuff | |||||
for(i=0; i < numChannelsSampled;i++) { | |||||
destination[i].numCopies = 0; | |||||
static void | |||||
nerd_init_channels (deststruct * destination, int numChannels, | |||||
int numChannelsSampled, int *channel_list) | |||||
{ | |||||
int channelprocessing = 0; | |||||
int currentalign = 0; //Index into sampled channels | |||||
int i; | |||||
int tempdestlist[NERDJACK_CHANNELS]; | |||||
//Clear out destination stuff | |||||
for (i = 0; i < numChannelsSampled; i++) | |||||
{ | |||||
destination[i].numCopies = 0; | |||||
} | } | ||||
for(channelprocessing = 0; channelprocessing < numChannelsSampled; channelprocessing++) { | |||||
//Find out how many copies of each channel so we malloc the right things | |||||
currentalign = 0; | |||||
for(i = 0; i < numChannels; i++) { | |||||
if(channelprocessing == channel_list[i]) { | |||||
tempdestlist[currentalign] = i; | |||||
currentalign++; | |||||
} | |||||
} | |||||
//If this channel is wanted, set it up. | |||||
if(currentalign > 0) { | |||||
destination[channelprocessing].numCopies = currentalign; | |||||
destination[channelprocessing].destlist = malloc( destination[channelprocessing].numCopies * sizeof(int) ); | |||||
memcpy(destination[channelprocessing].destlist, tempdestlist, destination[channelprocessing].numCopies * sizeof(int) ); | |||||
} | |||||
for (channelprocessing = 0; channelprocessing < numChannelsSampled; | |||||
channelprocessing++) | |||||
{ | |||||
//Find out how many copies of each channel so we malloc the right things | |||||
currentalign = 0; | |||||
for (i = 0; i < numChannels; i++) | |||||
{ | |||||
if (channelprocessing == channel_list[i]) | |||||
{ | |||||
tempdestlist[currentalign] = i; | |||||
currentalign++; | |||||
} | |||||
} | |||||
//If this channel is wanted, set it up. | |||||
if (currentalign > 0) | |||||
{ | |||||
destination[channelprocessing].numCopies = currentalign; | |||||
destination[channelprocessing].destlist = | |||||
malloc (destination[channelprocessing].numCopies * sizeof (int)); | |||||
memcpy (destination[channelprocessing].destlist, tempdestlist, | |||||
destination[channelprocessing].numCopies * sizeof (int)); | |||||
} | |||||
} | } | ||||
return; | |||||
return; | |||||
} | } | ||||
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 | |||||
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) | |||||
{ | { | ||||
//Variables that should persist across retries | |||||
static dataPacket buf; | |||||
static int linesleft = 0; | |||||
static int linesdumped = 0; | |||||
int index = 0; | |||||
int charsprocessed = 0; | |||||
int alignment = 0; | |||||
signed short datapoint = 0; | |||||
unsigned short dataline[NERDJACK_CHANNELS]; | |||||
long double voltline[NERDJACK_CHANNELS]; | |||||
int i; | |||||
unsigned long memused = 0; | |||||
unsigned short packetsready = 0; | |||||
unsigned short adcused = 0; | |||||
unsigned short tempshort = 0; | |||||
int charsread = 0; | |||||
int numgroups = 0; | |||||
long double volts; | |||||
unsigned int expectedtimeout = (period * NERDJACK_NUM_SAMPLES / NERDJACK_CLOCK_RATE) + 2; | |||||
//Check to see if we're trying to resume | |||||
//Don't blow away linesleft in that case | |||||
if(lines != 0 && linesleft == 0) { | |||||
linesleft = lines; | |||||
//Variables that should persist across retries | |||||
static dataPacket buf; | |||||
static int linesleft = 0; | |||||
static int linesdumped = 0; | |||||
int index = 0; | |||||
int charsprocessed = 0; | |||||
int alignment = 0; | |||||
signed short datapoint = 0; | |||||
unsigned short dataline[NERDJACK_CHANNELS]; | |||||
long double voltline[NERDJACK_CHANNELS]; | |||||
int i; | |||||
unsigned long memused = 0; | |||||
unsigned short packetsready = 0; | |||||
unsigned short adcused = 0; | |||||
unsigned short tempshort = 0; | |||||
int charsread = 0; | |||||
int numgroups = 0; | |||||
long double volts; | |||||
unsigned int expectedtimeout = | |||||
(period * NERDJACK_NUM_SAMPLES / NERDJACK_CLOCK_RATE) + 2; | |||||
//Check to see if we're trying to resume | |||||
//Don't blow away linesleft in that case | |||||
if (lines != 0 && linesleft == 0) | |||||
{ | |||||
linesleft = lines; | |||||
} | } | ||||
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; | |||||
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; | |||||
} | } | ||||
deststruct destination[numChannelsSampled]; | |||||
nerd_init_channels(destination,numChannels,numChannelsSampled, channel_list); | |||||
//Now destination structure array is set as well as numDuplicates. | |||||
deststruct destination[numChannelsSampled]; | |||||
//int numChannelsSampled = numChannels - numDuplicates; | |||||
int numGroups = NERDJACK_NUM_SAMPLES / numChannelsSampled; | |||||
nerd_init_channels (destination, numChannels, numChannelsSampled, | |||||
channel_list); | |||||
//Loop forever to grab data | |||||
while((charsread = recv_all_timeout(data_fd,&buf,NERDJACK_PACKET_SIZE,0, | |||||
& (struct timeval) { .tv_sec = expectedtimeout }))){ | |||||
//Now destination structure array is set as well as numDuplicates. | |||||
//We want a complete packet, so take the chars so far and keep waiting | |||||
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; | |||||
} | |||||
//int numChannelsSampled = numChannels - numDuplicates; | |||||
int numGroups = NERDJACK_NUM_SAMPLES / numChannelsSampled; | |||||
//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); | |||||
//tempshort = (buf[2] << 8) | buf[3]; | |||||
if(tempshort != *currentcount ){ | |||||
info("Count wrong. Expected %hd but got %hd\n", *currentcount, tempshort); | |||||
return -1; | |||||
//Loop forever to grab data | |||||
while ((charsread = | |||||
recv_all_timeout (data_fd, &buf, NERDJACK_PACKET_SIZE, 0, | |||||
&(struct timeval) | |||||
{ | |||||
.tv_sec = expectedtimeout}))) | |||||
{ | |||||
//We want a complete packet, so take the chars so far and keep waiting | |||||
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); | |||||
//tempshort = (buf[2] << 8) | buf[3]; | |||||
if (tempshort != *currentcount) | |||||
{ | |||||
info ("Count wrong. Expected %hd but got %hd\n", *currentcount, | |||||
tempshort); | |||||
return -1; | |||||
} | |||||
//Increment number of packets received | |||||
*currentcount = *currentcount + 1; | |||||
//Process the rest of the header and update the index value to be pointing after it | |||||
charsprocessed = 12; | |||||
memused = ntohl (buf.lwipmemoryused); | |||||
adcused = ntohs (buf.adcused); | |||||
packetsready = ntohs (buf.packetsready); | |||||
alignment = 0; | |||||
numgroups = 0; | |||||
if (showmem) | |||||
{ | |||||
printf ("%lX %hd %hd\n", memused, adcused, packetsready); | |||||
continue; | |||||
} | |||||
index = 0; | |||||
//While there is still more data in the packet, process it | |||||
//use the destination structure to load the line before printing | |||||
while (charsread > charsprocessed) | |||||
{ | |||||
datapoint = ntohs (buf.data[index]); | |||||
if (destination[alignment].numCopies != 0) | |||||
{ | |||||
switch (convert) | |||||
{ | |||||
case CONVERT_VOLTS: | |||||
if (alignment <= 5) | |||||
{ | |||||
volts = | |||||
(long double) (datapoint / 32767.0) * | |||||
((precision & 0x01) ? 5.0 : 10.0); | |||||
} | |||||
else | |||||
{ | |||||
volts = | |||||
(long double) (datapoint / 32767.0) * | |||||
((precision & 0x02) ? 5.0 : 10.0); | |||||
} | |||||
for (i = 0; i < destination[alignment].numCopies; i++) | |||||
{ | |||||
voltline[destination[alignment].destlist[i]] = volts; | |||||
} | |||||
break; | |||||
default: | |||||
case CONVERT_HEX: | |||||
case CONVERT_DEC: | |||||
for (i = 0; i < destination[alignment].numCopies; i++) | |||||
{ | |||||
dataline[destination[alignment].destlist[i]] = | |||||
(unsigned short) (datapoint - INT16_MIN); | |||||
} | |||||
break; | |||||
} | } | ||||
//Increment number of packets received | |||||
*currentcount = *currentcount + 1; | |||||
//Process the rest of the header and update the index value to be pointing after it | |||||
charsprocessed = 12; | |||||
memused = ntohl(buf.lwipmemoryused); | |||||
adcused = ntohs(buf.adcused); | |||||
packetsready = ntohs(buf.packetsready); | |||||
alignment = 0; | |||||
numgroups = 0; | |||||
if(showmem) { | |||||
printf("%lX %hd %hd\n",memused, adcused, packetsready); | |||||
continue; | |||||
} | |||||
index = 0; | |||||
//While there is still more data in the packet, process it | |||||
//use the destination structure to load the line before printing | |||||
while(charsread > charsprocessed) { | |||||
datapoint = ntohs(buf.data[index]); | |||||
if(destination[alignment].numCopies != 0) { | |||||
switch(convert) { | |||||
case CONVERT_VOLTS: | |||||
if(alignment <= 5) { | |||||
volts = (long double) ( datapoint / 32767.0 ) * ((precision & 0x01) ? 5.0 : 10.0); | |||||
} else { | |||||
volts = (long double) (datapoint / 32767.0 ) * ((precision & 0x02) ? 5.0 : 10.0); | |||||
} | |||||
for(i = 0; i < destination[alignment].numCopies; i++) { | |||||
voltline[destination[alignment].destlist[i]] = volts; | |||||
} | |||||
break; | |||||
default: | |||||
case CONVERT_HEX: | |||||
case CONVERT_DEC: | |||||
for(i = 0; i < destination[alignment].numCopies; i++) { | |||||
dataline[destination[alignment].destlist[i]] = | |||||
(unsigned short) (datapoint - INT16_MIN); | |||||
} | |||||
break; | |||||
} | |||||
//Each point is two bytes, so increment index and total bytes read | |||||
charsprocessed++; | |||||
charsprocessed++; | |||||
index++; | |||||
alignment++; | |||||
//Since channel data is packed, we need to know when to insert a newline | |||||
if (alignment == numChannelsSampled) | |||||
{ | |||||
if (linesdumped != 0) | |||||
{ | |||||
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; | |||||
} | } | ||||
} | |||||
//Each point is two bytes, so increment index and total bytes read | |||||
charsprocessed++; | |||||
charsprocessed++; | |||||
index++; | |||||
alignment++; | |||||
//Since channel data is packed, we need to know when to insert a newline | |||||
if(alignment == numChannelsSampled){ | |||||
if(linesdumped != 0){ | |||||
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; | |||||
} else { | |||||
linesdumped = linesdumped + 1; | |||||
if(lines != 0) { | |||||
linesleft++; | |||||
} | |||||
} | |||||
alignment = 0; | |||||
numgroups++; | |||||
if(lines != 0) { | |||||
linesleft--; | |||||
if(linesleft == 0) { | |||||
return 0; | |||||
} | |||||
} | |||||
//If numgroups so far is equal to the numGroups in a packet, this packet is done | |||||
if(numgroups == numGroups) { | |||||
break; | |||||
} | |||||
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; | |||||
} | |||||
else | |||||
{ | |||||
linesdumped = linesdumped + 1; | |||||
if (lines != 0) | |||||
{ | |||||
linesleft++; | |||||
} | |||||
} | |||||
alignment = 0; | |||||
numgroups++; | |||||
if (lines != 0) | |||||
{ | |||||
linesleft--; | |||||
if (linesleft == 0) | |||||
{ | |||||
return 0; | |||||
} | |||||
} | } | ||||
index = 0; | |||||
charsprocessed = 0; | |||||
//If numgroups so far is equal to the numGroups in a packet, this packet is done | |||||
if (numgroups == numGroups) | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
} | } | ||||
index = 0; | |||||
charsprocessed = 0; | |||||
} | |||||
return 0; | |||||
return 0; | |||||
bad: | bad: | ||||
info("Output error (disk full?)\n"); | |||||
return -1; | |||||
info ("Output error (disk full?)\n"); | |||||
return -1; | |||||
} | } | ||||
int nerd_open(const char *address,int port) { | |||||
struct hostent *he; | |||||
net_init(); | |||||
int32_t i32SocketFD = socket(PF_INET, SOCK_STREAM, 0); | |||||
int | |||||
nerd_open (const char *address, int port) | |||||
{ | |||||
if(-1 == i32SocketFD) | |||||
struct hostent *he; | |||||
net_init (); | |||||
int32_t i32SocketFD = socket (PF_INET, SOCK_STREAM, 0); | |||||
if (-1 == i32SocketFD) | |||||
{ | { | ||||
verb("cannot create socket"); | |||||
verb ("cannot create socket"); | |||||
return -1; | |||||
} | |||||
/* Set nonblocking */ | |||||
if (soblock (i32SocketFD, 0) < 0) | |||||
{ | |||||
verb ("can't set nonblocking\n"); | |||||
return -1; | 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); | |||||
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)); | |||||
/* Connect */ | |||||
if (connect_timeout(i32SocketFD, (struct sockaddr *) &stSockAddr, sizeof(stSockAddr), | |||||
& (struct timeval) { .tv_sec = NERDJACK_TIMEOUT }) < 0) { | |||||
verb("connection to %s:%d failed: %s\n", | |||||
inet_ntoa(stSockAddr.sin_addr), port, compat_strerror(errno)); | |||||
return -1; | |||||
} | |||||
return i32SocketFD; | |||||
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); | |||||
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 = NERDJACK_TIMEOUT}) < 0) | |||||
{ | |||||
verb ("connection to %s:%d failed: %s\n", | |||||
inet_ntoa (stSockAddr.sin_addr), port, compat_strerror (errno)); | |||||
return -1; | |||||
} | |||||
return i32SocketFD; | |||||
} | } | ||||
//Generate an appropriate sample initiation command | //Generate an appropriate sample initiation command | ||||
int nerd_generate_command(getPacket * command, int * channel_list, int channel_count, int precision, | |||||
unsigned long period) { | |||||
short channelbit = 0; | |||||
int i; | |||||
for( i = 0; i < channel_count; i++) { | |||||
channelbit = channelbit | (0x1 << channel_list[i]); | |||||
int | |||||
nerd_generate_command (getPacket * command, int *channel_list, | |||||
int channel_count, int precision, unsigned long period) | |||||
{ | |||||
short channelbit = 0; | |||||
int i; | |||||
for (i = 0; i < channel_count; i++) | |||||
{ | |||||
channelbit = channelbit | (0x1 << channel_list[i]); | |||||
} | } | ||||
//command->word = "GETD"; | |||||
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; | |||||
//sprintf(command,"GETD%3.3X%d%5.5d", channelbit,precision,period); | |||||
return 0; | |||||
//command->word = "GETD"; | |||||
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; | |||||
//sprintf(command,"GETD%3.3X%d%5.5d", channelbit,precision,period); | |||||
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; | |||||
} | } |
@@ -24,33 +24,38 @@ | |||||
#define NERDJACK_PACKET_SIZE 1460 | #define NERDJACK_PACKET_SIZE 1460 | ||||
#define NERDJACK_NUM_SAMPLES 724 | #define NERDJACK_NUM_SAMPLES 724 | ||||
typedef struct __attribute__((__packed__)) { | |||||
char word[4]; | |||||
unsigned short channelbit; | |||||
unsigned char precision; | |||||
unsigned long period; | |||||
unsigned char prescaler; | |||||
typedef struct __attribute__ ((__packed__)) | |||||
{ | |||||
char word[4]; | |||||
unsigned short channelbit; | |||||
unsigned char precision; | |||||
unsigned long period; | |||||
unsigned char prescaler; | |||||
} getPacket; | } getPacket; | ||||
/* Open/close TCP/IP connection to the NerdJack */ | /* Open/close TCP/IP connection to the NerdJack */ | ||||
int nerd_open(const char *address,int port); | |||||
int nerd_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 */ | /* 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 */ | /* 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); | |||||
/* Stream data out of the NerdJack */ | /* Stream data out of the NerdJack */ | ||||
int nerd_data_stream(int data_fd, int numChannels, int * channel_list, int precision, int convert, int lines, int showmem, unsigned short * currentcount, unsigned int period); | |||||
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); | |||||
/* Detect the IP Address of the NerdJack and return in ipAddress */ | /* Detect the IP Address of the NerdJack and return in ipAddress */ | ||||
int nerdjack_detect(char * ipAddress); | |||||
int nerdjack_detect (char *ipAddress); | |||||
/* Choose the best ScanConfig and ScanInterval parameters for the | /* Choose the best ScanConfig and ScanInterval parameters for the | ||||
desired scanrate. Returns -1 if no valid config found */ | desired scanrate. Returns -1 if no valid config found */ | ||||
int nerdjack_choose_scan(double desired_rate, double *actual_rate, unsigned long *period); | |||||
int nerdjack_choose_scan (double desired_rate, double *actual_rate, | |||||
unsigned long *period); | |||||
#endif | #endif |
@@ -5,239 +5,262 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
/* Initialize networking */ | /* Initialize networking */ | ||||
void net_init(void) | |||||
void | |||||
net_init (void) | |||||
{ | { | ||||
#ifdef __WIN32__ | #ifdef __WIN32__ | ||||
WSADATA blah; | |||||
WSAStartup(0x0101, &blah); | |||||
WSADATA blah; | |||||
WSAStartup (0x0101, &blah); | |||||
#endif | #endif | ||||
} | } | ||||
/* Set socket blocking/nonblocking */ | /* Set socket blocking/nonblocking */ | ||||
int soblock(int socket, int blocking) | |||||
int | |||||
soblock (int socket, int blocking) | |||||
{ | { | ||||
#ifdef __WIN32__ | #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 | #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 | #endif | ||||
} | } | ||||
/* Like connect(2), but with a timeout. Socket must be non-blocking. */ | /* Like connect(2), but with a timeout. Socket must be non-blocking. */ | ||||
int connect_timeout(int s, const struct sockaddr *serv_addr, socklen_t addrlen, | |||||
struct timeval *timeout) | |||||
int | |||||
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__ | #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 | #else | ||||
if (ret < 0 && errno != EINPROGRESS && errno != EALREADY) | |||||
return -1; | |||||
if (ret < 0 && errno != EINPROGRESS && errno != EALREADY) | |||||
return -1; | |||||
#endif | #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. | /* 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 | The timeout only applies if no data at all is sent -- this function | ||||
may still send less than requested. */ | may still send less than requested. */ | ||||
ssize_t send_timeout(int s, const void *buf, size_t len, int flags, | |||||
struct timeval *timeout) | |||||
ssize_t | |||||
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. | /* Like recv(2), but with a timeout. Socket must be non-blocking. | ||||
The timeout only applies if no data at all is received -- this | The timeout only applies if no data at all is received -- this | ||||
function may still return less than requested. */ | function may still return less than requested. */ | ||||
ssize_t recv_timeout(int s, 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) | |||||
{ | { | ||||
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. | /* Like recvfrom(2), but with a timeout. Socket must be non-blocking. | ||||
The timeout only applies if no data at all is received -- this | The timeout only applies if no data at all is received -- this | ||||
function may still return less than requested. */ | function may still return less than requested. */ | ||||
ssize_t recvfrom_timeout(int s, void *buf, size_t len, int flags, struct sockaddr *address, socklen_t *address_len, | |||||
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) | |||||
{ | { | ||||
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 | /* Like send_timeout, but retries (with the same timeout) in case of | ||||
partial transfers. This is a stronger attempt to send all | partial transfers. This is a stronger attempt to send all | ||||
requested data. */ | requested data. */ | ||||
ssize_t send_all_timeout(int s, const 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) | |||||
{ | { | ||||
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 | /* Like recv_timeout, but retries (with the same timeout) in case of | ||||
partial transfers. This is a stronger attempt to recv all | partial transfers. This is a stronger attempt to recv all | ||||
requested data. */ | requested data. */ | ||||
ssize_t recv_all_timeout(int s, 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) | |||||
{ | { | ||||
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; | |||||
} | } |
@@ -19,27 +19,28 @@ | |||||
#endif | #endif | ||||
/* Initialize networking */ | /* Initialize networking */ | ||||
void net_init(void); | |||||
void net_init (void); | |||||
/* Set socket blocking/nonblocking */ | /* Set socket blocking/nonblocking */ | ||||
int soblock(int socket, int blocking); | |||||
int soblock (int socket, int blocking); | |||||
/* Like send(2), recv(2), connect(2), but with timeouts. | /* Like send(2), recv(2), connect(2), but with timeouts. | ||||
Socket must be O_NONBLOCK. */ | Socket must be O_NONBLOCK. */ | ||||
int connect_timeout(int s, const struct sockaddr *serv_addr, 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) | /* Like send_timeout and recv_timeout, but they retry (with the same timeout) | ||||
in case of partial transfers, in order to try to transfer all data. */ | in case of partial transfers, in order to try to transfer all data. */ | ||||
ssize_t send_all_timeout(int s, const void *buf, size_t len, int flags, | |||||
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 | #endif |
@@ -11,85 +11,98 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "opt.h" | #include "opt.h" | ||||
void opt_init(int *optind) { | |||||
*optind=0; | |||||
void | |||||
opt_init (int *optind) | |||||
{ | |||||
*optind = 0; | |||||
} | } | ||||
char opt_parse(int argc, char **argv, int *optind, char **optarg, | |||||
struct options *opt) { | |||||
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(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; | |||||
char | |||||
opt_parse (int argc, char **argv, int *optind, char **optarg, | |||||
struct options *opt) | |||||
{ | |||||
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 (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) { | |||||
int i; | |||||
int printed; | |||||
void | |||||
opt_help (struct options *opt, FILE * out) | |||||
{ | |||||
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,18 +11,19 @@ | |||||
#include <stdlib.h> | #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 | #endif |
@@ -16,56 +16,59 @@ | |||||
#include "netutil.h" | #include "netutil.h" | ||||
/* Calibration data */ | /* 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 */ | /* 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 */ | /* 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 | #define UE9_UNIPOLAR_GAIN1 0x00 | ||||
@@ -77,65 +80,65 @@ struct ue9ControlConfig { | |||||
#define UE9_CHANNELS 14 | #define UE9_CHANNELS 14 | ||||
/* Fill checksums in data buffers */ | /* 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. */ | /* 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 */ | /* 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. */ | /* Read a memory block from the device. Returns -1 on error. */ | ||||
int ue9_memory_read(int fd, int blocknum, uint8_t *buffer, int len); | |||||
int ue9_memory_read (int fd, int blocknum, uint8_t * buffer, int len); | |||||
/* Convert 64-bit fixed point to double type */ | /* Convert 64-bit fixed point to double type */ | ||||
double ue9_fp64_to_double(uint8_t *data); | |||||
double ue9_fp64_to_double (uint8_t * data); | |||||
/* Retrieve calibration data or configuration from the device */ | /* Retrieve calibration data or configuration from the device */ | ||||
int ue9_get_calibration(int fd, struct ue9Calibration *calib); | |||||
int ue9_get_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. */ | /* 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. */ | /* Compute scanrate based on the provided values. */ | ||||
double ue9_compute_rate(uint8_t scanconfig, uint16_t scaninterval); | |||||
double ue9_compute_rate (uint8_t scanconfig, uint16_t scaninterval); | |||||
/* Choose the best ScanConfig and ScanInterval parameters for the | /* Choose the best ScanConfig and ScanInterval parameters for the | ||||
desired scanrate. Returns 0 if nothing can be chosen. */ | desired scanrate. Returns 0 if nothing can be chosen. */ | ||||
int ue9_choose_scan(double desired_rate, double *actual_rate, | |||||
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 */ | /* Flush data buffers */ | ||||
void ue9_buffer_flush(int fd); | |||||
void ue9_buffer_flush (int fd); | |||||
/* Stop stream. Returns < 0 on failure. */ | /* Stop stream. Returns < 0 on failure. */ | ||||
int ue9_stream_stop(int fd); | |||||
int ue9_stream_stop (int fd); | |||||
/* Start stream. Returns < 0 on failure. */ | /* Start stream. Returns < 0 on failure. */ | ||||
int ue9_stream_start(int fd); | |||||
int ue9_stream_start (int fd); | |||||
/* Execute a command on the UE9. Returns -1 on error. Fills the | /* Execute a command on the UE9. Returns -1 on error. Fills the | ||||
checksums on the outgoing packets, and verifies them on the | checksums on the outgoing packets, and verifies them on the | ||||
incoming packets. Data in "out" is transmitted, data in "in" is | incoming packets. Data in "out" is transmitted, data in "in" is | ||||
received. */ | received. */ | ||||
int ue9_command(int fd, uint8_t *out, uint8_t *in, int inlen); | |||||
int ue9_command (int fd, uint8_t * out, uint8_t * in, int inlen); | |||||
/* "Simple" stream configuration, assumes the channels are all | /* "Simple" stream configuration, assumes the channels are all | ||||
configured with the same gain. */ | configured with the same gain. */ | ||||
int ue9_streamconfig_simple(int fd, int *channel_list, int channel_count, | |||||
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); | |||||
/* Stream data and pass it to the data callback. If callback returns | /* Stream data and pass it to the data callback. If callback returns | ||||
negative, stops reading and returns 0. Returns < 0 on error. */ | negative, stops reading and returns 0. Returns < 0 on error. */ | ||||
typedef int (*ue9_stream_cb_t)(int channels, uint16_t *data, void *context); | |||||
int ue9_stream_data(int fd, int channels, | |||||
ue9_stream_cb_t callback, void *context); | |||||
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); | |||||
#endif | #endif |
@@ -1,51 +1,52 @@ | |||||
#include "ue9error.h" | #include "ue9error.h" | ||||
const char *ue9_error_text[] = { | 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[]; | extern const char *ue9_error_text[]; | ||||
const char *ue9_error(int errorcode); | |||||
const char *ue9_error (int errorcode); | |||||
#endif | #endif |