From 7f79ec8ff3c7a5bb69fac9bb7be2de120597da63 Mon Sep 17 00:00:00 2001 From: zacharyc Date: Wed, 18 Mar 2009 15:23:10 +0000 Subject: [PATCH] Ran indent on code to fix inconsistent style. git-svn-id: https://bucket.mit.edu/svn/nilm/acquisition/ethstream@7298 ddd99763-3ecb-0310-9145-efcb8ce7c51f --- compat-win32.c | 119 +++-- compat.h | 4 +- debug.c | 18 +- debug.h | 4 +- ethstream.c | 980 ++++++++++++++++++++++------------------- ljconfig.c | 128 +++--- ljtest.c | 83 ++-- nerdjack.c | 867 ++++++++++++++++++++---------------- nerdjack.h | 33 +- netutil.c | 375 ++++++++-------- netutil.h | 29 +- opt.c | 163 +++---- opt.h | 19 +- ue9.c | 1148 ++++++++++++++++++++++++++---------------------- ue9.h | 143 +++--- ue9error.c | 89 ++-- ue9error.h | 2 +- 17 files changed, 2276 insertions(+), 1928 deletions(-) diff --git a/compat-win32.c b/compat-win32.c index ae173be..2eed930 100644 --- a/compat-win32.c +++ b/compat-win32.c @@ -3,55 +3,83 @@ #include "compat.h" #include -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__ @@ -80,4 +108,3 @@ char *compat_strerror(int errnum) } */ #endif - diff --git a/compat.h b/compat.h index eee8d53..203f6f6 100644 --- a/compat.h +++ b/compat.h @@ -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 diff --git a/debug.c b/debug.c index a2d5b71..2173542 100644 --- a/debug.c +++ b/debug.c @@ -4,15 +4,15 @@ 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; } - diff --git a/debug.h b/debug.h index 7e6c58b..23d54b0 100644 --- a/debug.h +++ b/debug.h @@ -14,8 +14,8 @@ extern int verb_count; #include -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) \ diff --git a/ethstream.c b/ethstream.c index 253bd6b..383db01 100644 --- a/ethstream.c +++ b/ethstream.c @@ -36,512 +36,596 @@ #define UE9_DATA_PORT 52361 -struct callbackInfo { - struct ue9Calibration calib; - int convert; - int maxlines; +struct callbackInfo +{ + struct ue9Calibration calib; + int convert; + int maxlines; }; struct options opt[] = { - { 'a', "address", "string", "host/address of UE9 (192.168.1.209)" }, - { 'n', "numchannels", "n", "sample the first N ADC channels (2)" }, - { 'N', "nerdjack", NULL, "Use NerdJack device instead" }, - { 'd', "detect", NULL, "Detect NerdJack IP address" }, - { 'p', "precision", "0-3", "Set precision on NerdJack (0 - max range, 1 - max precision)"}, - { 'C', "channels", "a,b,c", "sample channels a, b, and c" }, - { 'r', "rate", "hz", "sample each channel at this rate (8000.0)" }, - { 'o', "oneshot", NULL, "don't retry in case of errors" }, - { 'f', "forceretry", NULL, "retry no matter what happens" }, - { 'c', "convert", NULL, "convert output to volts" }, - { 'H', "converthex", NULL, "convert output to hex" }, - { 'm', "showmem", NULL, "output memory stats with data (NJ only)" }, - { 'l', "lines", "num", "if set, output this many lines and quit" }, - { '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)"}, + {'n', "numchannels", "n", "sample the first N ADC channels (2)"}, + {'N', "nerdjack", NULL, "Use NerdJack device instead"}, + {'d', "detect", NULL, "Detect NerdJack IP address"}, + {'p', "precision", "0-3", + "Set precision on NerdJack (0 - max range, 1 - max precision)"}, + {'C', "channels", "a,b,c", "sample channels a, b, and c"}, + {'r', "rate", "hz", "sample each channel at this rate (8000.0)"}, + {'o', "oneshot", NULL, "don't retry in case of errors"}, + {'f', "forceretry", NULL, "retry no matter what happens"}, + {'c', "convert", NULL, "convert output to volts"}, + {'H', "converthex", NULL, "convert output to hex"}, + {'m', "showmem", NULL, "output memory stats with data (NJ only)"}, + {'l', "lines", "num", "if set, output this many lines and quit"}, + {'h', "help", NULL, "this help"}, + {'v', "verbose", NULL, "be verbose"}, + {'V', "version", NULL, "show version number and exit"}, + {0, NULL, NULL, NULL} }; -int doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval, - int *channel_list, int channel_count, int convert, int maxlines); -int nerdDoStream(const char *address, int *channel_list, int channel_count, int precision, - unsigned long period, int convert, int lines, int showmem); -int data_callback(int channels, uint16_t *data, void *context); +int doStream (const char *address, uint8_t scanconfig, uint16_t scaninterval, + int *channel_list, int channel_count, int convert, + int maxlines); +int nerdDoStream (const char *address, int *channel_list, int channel_count, + int precision, unsigned long period, int convert, int lines, + int showmem); +int data_callback (int channels, uint16_t * data, void *context); int columns_left = 0; -void handle_sig(int sig) +void +handle_sig (int sig) { - while (columns_left--) { - printf(" 0"); - } - fflush(stdout); - exit(0); + while (columns_left--) + { + printf (" 0"); + } + fflush (stdout); + exit (0); } -int main(int argc, char *argv[]) +int +main (int argc, char *argv[]) { - int optind; - char *optarg, *endp; - char c; - int tmp, i; - FILE *help = stderr; - char *address = strdup(DEFAULT_HOST); - double desired_rate = 8000.0; - int lines = 0; - double actual_rate; - int oneshot = 0; - int forceretry = 0; - int convert = CONVERT_DEC; - int showmem = 0; - uint8_t scanconfig; - uint16_t scaninterval; + int optind; + char *optarg, *endp; + char c; + int tmp, i; + FILE *help = stderr; + char *address = strdup (DEFAULT_HOST); + double desired_rate = 8000.0; + int lines = 0; + double actual_rate; + int oneshot = 0; + int forceretry = 0; + int convert = CONVERT_DEC; + int showmem = 0; + uint8_t scanconfig; + uint16_t scaninterval; #if UE9_CHANNELS > NERDJACK_CHANNELS - int channel_list[UE9_CHANNELS]; + int channel_list[UE9_CHANNELS]; #else - int channel_list[NERDJACK_CHANNELS]; + int channel_list[NERDJACK_CHANNELS]; #endif - int channel_count = 0; - int nerdjack = 0; - int detect = 0; - int precision = 0; - unsigned long period = NERDJACK_CLOCK_RATE / desired_rate; - - /* 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 'n': - channel_count = 0; - tmp = strtol(optarg, &endp, 0); - if (*endp || tmp < 1 || tmp > UE9_CHANNELS) { - info("bad number of channels: %s\n", optarg); - goto printhelp; - } - for (i = 0; i < tmp; i++) - channel_list[channel_count++] = i; - break; - case 'C': - channel_count = 0; - do { - tmp = strtol(optarg, &endp, 0); - if (*endp != '\0' && *endp != ',') { - //|| tmp < 0 || tmp >= UE9_CHANNELS) { - info("bad channel number: %s\n", optarg); - goto printhelp; - } - //We do not want to overflow channel_list, so we need the check here - //The rest of the sanity checking can come later after we know whether this is a - //LabJack or a NerdJack + int channel_count = 0; + int nerdjack = 0; + int detect = 0; + int precision = 0; + unsigned long period = NERDJACK_CLOCK_RATE / desired_rate; + + /* 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 'n': + channel_count = 0; + tmp = strtol (optarg, &endp, 0); + if (*endp || tmp < 1 || tmp > UE9_CHANNELS) + { + info ("bad number of channels: %s\n", optarg); + goto printhelp; + } + for (i = 0; i < tmp; i++) + channel_list[channel_count++] = i; + break; + case 'C': + channel_count = 0; + do + { + tmp = strtol (optarg, &endp, 0); + if (*endp != '\0' && *endp != ',') + { + //|| tmp < 0 || tmp >= UE9_CHANNELS) { + info ("bad channel number: %s\n", optarg); + goto printhelp; + } + //We do not want to overflow channel_list, so we need the check here + //The rest of the sanity checking can come later after we know whether this is a + //LabJack or a NerdJack #if UE9_CHANNELS > NERDJACK_CHANNELS - if (channel_count >= UE9_CHANNELS) { + if (channel_count >= UE9_CHANNELS) + { #else - if (channel_count >= NERDJACK_CHANNELS) { + if (channel_count >= NERDJACK_CHANNELS) + { #endif - info("error: too many channels specified\n"); - goto printhelp; - } - channel_list[channel_count++] = tmp; - optarg = endp + 1; - } while (*endp); - break; - case 'r': - desired_rate = strtod(optarg, &endp); - if(*endp || desired_rate <= 0) { - info("bad rate: %s\n", optarg); - goto printhelp; - } - break; - case 'l': - lines = strtol(optarg, &endp, 0); - if (*endp || lines <= 0) { - info("bad number of lines: %s\n", optarg); - goto printhelp; - } - break; - case 'p': - tmp = strtol(optarg, &endp, 0); - if (tmp <= 3 && tmp >= 0) { - precision = tmp; - } else { - info("Bad argument to p: %s\n",optarg); - goto printhelp; - } - break; - case 'N': - nerdjack++; - break; - case 'd': - detect++; - break; - case 'o': - oneshot++; - break; - case 'f': - forceretry++; - break; - case 'c': - if (convert != 0) { - info("specify only one conversion type\n"); - goto printhelp; - } - convert = CONVERT_VOLTS; - break; - case 'H': - if (convert != 0) { - info("specify only one conversion type\n"); - goto printhelp; - } - convert = CONVERT_HEX; - break; - case 'm': - showmem++; - case 'v': - verb_count++; - break; - case 'V': - printf("ljstream " VERSION "\n"); - printf("Written by Jim Paris \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, "Read data from the specified Labjack UE9" - " via Ethernet. See README for details.\n"); - return (help == stdout) ? 0 : 1; + info ("error: too many channels specified\n"); + goto printhelp; } + channel_list[channel_count++] = tmp; + optarg = endp + 1; + } + while (*endp); + break; + case 'r': + desired_rate = strtod (optarg, &endp); + if (*endp || desired_rate <= 0) + { + info ("bad rate: %s\n", optarg); + goto printhelp; + } + break; + case 'l': + lines = strtol (optarg, &endp, 0); + if (*endp || lines <= 0) + { + info ("bad number of lines: %s\n", optarg); + goto printhelp; + } + break; + case 'p': + tmp = strtol (optarg, &endp, 0); + if (tmp <= 3 && tmp >= 0) + { + precision = tmp; + } + else + { + info ("Bad argument to p: %s\n", optarg); + goto printhelp; + } + break; + case 'N': + nerdjack++; + break; + case 'd': + detect++; + break; + case 'o': + oneshot++; + break; + case 'f': + forceretry++; + break; + case 'c': + if (convert != 0) + { + info ("specify only one conversion type\n"); + goto printhelp; + } + convert = CONVERT_VOLTS; + break; + case 'H': + if (convert != 0) + { + info ("specify only one conversion type\n"); + goto printhelp; + } + convert = CONVERT_HEX; + break; + case 'm': + showmem++; + case 'v': + verb_count++; + break; + case 'V': + printf ("ljstream " VERSION "\n"); + printf ("Written by Jim Paris \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, "Read data from the specified Labjack UE9" + " via Ethernet. See README for details.\n"); + return (help == stdout) ? 0 : 1; } - - doneparse: - - if (nerdjack) { - if (channel_count > NERDJACK_CHANNELS) { - info("Too many channels for NerdJack\n"); - goto printhelp; - } - for (i = 0; i < channel_count; i++) { - if (channel_list[i] >= NERDJACK_CHANNELS) { - info("Channel is out of NerdJack range: %d\n",channel_list[i]); - goto printhelp; - } - } - } else { - if (channel_count > UE9_CHANNELS) { - info("Too many channels for LabJack\n"); - goto printhelp; - } - for (i = 0; i < channel_count; i++) { - if (channel_list[i] >= UE9_CHANNELS) { - info("Channel is out of LabJack range: %d\n",channel_list[i]); - goto printhelp; - } - } } - - - if (optind < argc) { - info("error: too many arguments (%s)\n\n", argv[optind]); - goto printhelp; - } +doneparse: - if (forceretry && oneshot) { - info("forceretry and oneshot options are mutually exclusive\n"); - goto printhelp; + if (nerdjack) + { + if (channel_count > NERDJACK_CHANNELS) + { + info ("Too many channels for NerdJack\n"); + goto printhelp; } - - /* Two channels if none specified */ - if (channel_count == 0) { - channel_list[channel_count++] = 0; - channel_list[channel_count++] = 1; + for (i = 0; i < channel_count; i++) + { + if (channel_list[i] >= NERDJACK_CHANNELS) + { + info ("Channel is out of NerdJack range: %d\n", + channel_list[i]); + goto printhelp; + } } - - if (verb_count) { - info("Scanning channels:"); - for (i = 0; i < channel_count; i++) - info(" AIN%d", channel_list[i]); - info("\n"); + } + else + { + if (channel_count > UE9_CHANNELS) + { + info ("Too many channels for LabJack\n"); + goto printhelp; + } + for (i = 0; i < channel_count; i++) + { + if (channel_list[i] >= UE9_CHANNELS) + { + info ("Channel is out of LabJack range: %d\n", channel_list[i]); + goto printhelp; + } } + } + - /* Figure out actual rate. */ - if (nerdjack) { - if (nerdjack_choose_scan(desired_rate, &actual_rate, &period) < 0) { - info("error: can't achieve requested scan rate (%lf Hz)\n", - desired_rate); - //return 1; - } - } else { - if (ue9_choose_scan(desired_rate, &actual_rate, - &scanconfig, &scaninterval) < 0) { - info("error: can't achieve requested scan rate (%lf Hz)\n", - desired_rate); - //return 1; - } + + if (optind < argc) + { + info ("error: too many arguments (%s)\n\n", argv[optind]); + goto printhelp; } - - if ((desired_rate != actual_rate) || verb_count){ - info("Actual scanrate is %lf Hz\n", actual_rate); - info("Period is %ld\n",period); + if (forceretry && oneshot) + { + info ("forceretry and oneshot options are mutually exclusive\n"); + goto printhelp; } - - if (verb_count && lines) { - info("Stopping capture after %d lines\n", lines); - } + /* Two channels if none specified */ + if (channel_count == 0) + { + channel_list[channel_count++] = 0; + channel_list[channel_count++] = 1; + } - signal(SIGINT, handle_sig); - signal(SIGTERM, handle_sig); - - if (detect) { - info("Autodetecting NerdJack address\n"); - free(address); - if(nerdjack_detect(address) < 0) { - info("Error with autodetection\n"); - } else { - info("Found NerdJack at address: %s\n",address); - } + if (verb_count) + { + info ("Scanning channels:"); + for (i = 0; i < channel_count; i++) + info (" AIN%d", channel_list[i]); + info ("\n"); } - - - for (;;) { - int ret; - if(nerdjack) { - ret = nerdDoStream(address, channel_list, channel_count, precision, period, convert, lines, showmem); - verb("nerdDoStream returned %d\n", ret); - - } else { - ret = doStream(address, scanconfig, scaninterval, - channel_list, channel_count, convert, - lines); - verb("doStream returned %d\n", ret); - } - if (oneshot) - break; - - if (ret == 0) - break; - - if (ret == -ENOTCONN && !nerdjack) { - info("Could not connect LabJack...Trying NerdJack\n"); - nerdjack = 1; - goto doneparse; - } - - if (ret == -ENOTCONN && !forceretry) { - info("Initial connection failed, giving up\n"); - break; - } - if (ret == -EAGAIN || ret == -ENOTCONN) { - /* Some transient error. Wait a tiny bit, then retry */ - info("Retrying in 5 secs.\n"); - sleep(5); - } else { - info("Retrying now.\n"); - } + /* Figure out actual rate. */ + if (nerdjack) + { + if (nerdjack_choose_scan (desired_rate, &actual_rate, &period) < 0) + { + info ("error: can't achieve requested scan rate (%lf Hz)\n", + desired_rate); + //return 1; + } + } + else + { + if (ue9_choose_scan (desired_rate, &actual_rate, + &scanconfig, &scaninterval) < 0) + { + info ("error: can't achieve requested scan rate (%lf Hz)\n", + desired_rate); + //return 1; } + } - debug("Done loop\n"); - return 0; -} + if ((desired_rate != actual_rate) || verb_count) + { + info ("Actual scanrate is %lf Hz\n", actual_rate); + info ("Period is %ld\n", period); + } -int nerdDoStream(const char *address, int *channel_list, int channel_count, int precision, - unsigned long period, int convert, int lines, int showmem) -{ - int retval = -EAGAIN; - int fd_data; - static int first_call = 1; - static int started = 0; - getPacket command; - static unsigned short currentcount = 0; - - //usleep(1000000); - - if(first_call) { - if (nerd_generate_command(&command, channel_list, channel_count, precision, period) < 0) { - info("Failed to create configuration command\n"); - goto out; - } - - - if (nerd_send_command(address,"STOP", 4) < 0) { - if (first_call) - retval = -ENOTCONN; - info("Failed to send STOP command\n"); - goto out; - } - - if (nerd_send_command(address,&command, sizeof(command)) < 0) { - info("Failed to send GET command\n"); - goto out; - } - } - //We have sent the configuration commands. If we retry later, don't resend them. We would like - //to resume the interrupted transmission - first_call = 0; - - //If we had a transmission in progress, send a command to resume from there - if(started == 1) { - char cmdbuf[10]; - sprintf(cmdbuf,"SETC%05hd",currentcount); - if (nerd_send_command(address,cmdbuf,strlen(cmdbuf)) < 0) { - info("Failed to send SETC command\n"); - goto out; - } + + if (verb_count && lines) + { + info ("Stopping capture after %d lines\n", lines); } - started = 1; - - /* Open connection */ - fd_data = nerd_open(address, NERDJACK_DATA_PORT); - if (fd_data < 0) { - info("Connect failed: %s:%d\n", address, NERDJACK_DATA_PORT); - goto out; + signal (SIGINT, handle_sig); + signal (SIGTERM, handle_sig); + + if (detect) + { + info ("Autodetecting NerdJack address\n"); + free (address); + if (nerdjack_detect (address) < 0) + { + info ("Error with autodetection\n"); + } + else + { + info ("Found NerdJack at address: %s\n", address); } - - if (nerd_data_stream(fd_data, channel_count, channel_list, precision, convert, lines, showmem, ¤tcount,period) < 0) { - info("Failed to open data stream\n"); - goto out1; } - info("Stream finished\n"); - retval = 0; - out1: - nerd_close_conn(fd_data); - out: - return retval; -} + for (;;) + { + int ret; + if (nerdjack) + { + ret = + nerdDoStream (address, channel_list, channel_count, precision, + period, convert, lines, showmem); + verb ("nerdDoStream returned %d\n", ret); -int doStream(const char *address, uint8_t scanconfig, uint16_t scaninterval, - int *channel_list, int channel_count, int convert, int lines) -{ - int retval = -EAGAIN; - int fd_cmd, fd_data; - int ret; - static int first_call = 1; - struct callbackInfo ci = { - .convert = convert, - .maxlines = lines, - }; - - /* Open command connection. If this fails, and this is the - first attempt, return a different error code so we give up. */ - fd_cmd = ue9_open(address, UE9_COMMAND_PORT); - if (fd_cmd < 0) { - info("Connect failed: %s:%d\n", address, UE9_COMMAND_PORT); - if (first_call) - retval = -ENOTCONN; - goto out; } - first_call = 0; - - /* Make sure nothing is left over from a previous stream */ - if (ue9_stream_stop(fd_cmd) == 0) - verb("Stopped previous stream.\n"); - ue9_buffer_flush(fd_cmd); - - /* Open data connection */ - fd_data = ue9_open(address, UE9_DATA_PORT); - if (fd_data < 0) { - info("Connect failed: %s:%d\n", address, UE9_DATA_PORT); - goto out1; + else + { + ret = doStream (address, scanconfig, scaninterval, + channel_list, channel_count, convert, lines); + verb ("doStream returned %d\n", ret); + } + if (oneshot) + break; + + if (ret == 0) + break; + + if (ret == -ENOTCONN && !nerdjack) + { + info ("Could not connect LabJack...Trying NerdJack\n"); + nerdjack = 1; + goto doneparse; + } + + if (ret == -ENOTCONN && !forceretry) + { + info ("Initial connection failed, giving up\n"); + break; + } + + if (ret == -EAGAIN || ret == -ENOTCONN) + { + /* Some transient error. Wait a tiny bit, then retry */ + info ("Retrying in 5 secs.\n"); + sleep (5); } - - /* Get calibration */ - if (ue9_get_calibration(fd_cmd, &ci.calib) < 0) { - info("Failed to get device calibration\n"); - goto out2; + else + { + info ("Retrying now.\n"); } + } + + debug ("Done loop\n"); - /* Set stream configuration */ - if (ue9_streamconfig_simple(fd_cmd, channel_list, channel_count, - scanconfig, scaninterval, - UE9_BIPOLAR_GAIN1) < 0) { - info("Failed to set stream configuration\n"); - goto out2; + return 0; +} + +int +nerdDoStream (const char *address, int *channel_list, int channel_count, + int precision, unsigned long period, int convert, int lines, + int showmem) +{ + int retval = -EAGAIN; + int fd_data; + static int first_call = 1; + static int started = 0; + getPacket command; + static unsigned short currentcount = 0; + + //usleep(1000000); + + if (first_call) + { + if (nerd_generate_command + (&command, channel_list, channel_count, precision, period) < 0) + { + info ("Failed to create configuration command\n"); + goto out; } - /* Start stream */ - if (ue9_stream_start(fd_cmd) < 0) { - info("Failed to start stream\n"); - goto out2; + + if (nerd_send_command (address, "STOP", 4) < 0) + { + if (first_call) + retval = -ENOTCONN; + info ("Failed to send STOP command\n"); + goto out; } - /* Stream data */ - ret = ue9_stream_data(fd_data, channel_count, data_callback, (void *)&ci); - if (ret < 0) { - info("Data stream failed with error %d\n", ret); - goto out3; + if (nerd_send_command (address, &command, sizeof (command)) < 0) + { + info ("Failed to send GET command\n"); + goto out; + } + } + //We have sent the configuration commands. If we retry later, don't resend them. We would like + //to resume the interrupted transmission + first_call = 0; + + //If we had a transmission in progress, send a command to resume from there + if (started == 1) + { + char cmdbuf[10]; + sprintf (cmdbuf, "SETC%05hd", currentcount); + if (nerd_send_command (address, cmdbuf, strlen (cmdbuf)) < 0) + { + info ("Failed to send SETC command\n"); + goto out; } + } - info("Stream finished\n"); - retval = 0; - - out3: - /* Stop stream and clean up */ - ue9_stream_stop(fd_cmd); - ue9_buffer_flush(fd_cmd); - out2: - ue9_close(fd_data); - out1: - ue9_close(fd_cmd); - out: - return retval; + started = 1; + + /* Open connection */ + fd_data = nerd_open (address, NERDJACK_DATA_PORT); + if (fd_data < 0) + { + info ("Connect failed: %s:%d\n", address, NERDJACK_DATA_PORT); + goto out; + } + + if (nerd_data_stream + (fd_data, channel_count, channel_list, precision, convert, lines, + showmem, ¤tcount, period) < 0) + { + info ("Failed to open data stream\n"); + goto out1; + } + + info ("Stream finished\n"); + retval = 0; + +out1: + nerd_close_conn (fd_data); +out: + return retval; } -int data_callback(int channels, uint16_t *data, void *context) +int +doStream (const char *address, uint8_t scanconfig, uint16_t scaninterval, + int *channel_list, int channel_count, int convert, int lines) { - int i; - struct callbackInfo *ci = (struct callbackInfo *)context; - static int lines = 0; - - columns_left = channels; - for (i = 0; i < channels; i++) { - switch (ci->convert) { - case CONVERT_VOLTS: - if (printf("%lf", ue9_binary_to_analog( - &ci->calib, UE9_BIPOLAR_GAIN1, 12, - data[i])) < 0) - goto bad; - break; - case CONVERT_HEX: - if (printf("%04X", data[i]) < 0) - goto bad; - break; - default: - case CONVERT_DEC: - if (printf("%d", data[i]) < 0) - goto bad; - break; - } - columns_left--; - if (i < (channels - 1)) { - if (ci->convert != CONVERT_HEX && putchar(' ') < 0) - goto bad; - } else { - if (putchar('\n') < 0) - goto bad; - lines++; - if (ci->maxlines && lines >= ci->maxlines) - return -1; - } + int retval = -EAGAIN; + int fd_cmd, fd_data; + int ret; + static int first_call = 1; + struct callbackInfo ci = { + .convert = convert, + .maxlines = lines, + }; + + /* Open command connection. If this fails, and this is the + first attempt, return a different error code so we give up. */ + fd_cmd = ue9_open (address, UE9_COMMAND_PORT); + if (fd_cmd < 0) + { + info ("Connect failed: %s:%d\n", address, UE9_COMMAND_PORT); + if (first_call) + retval = -ENOTCONN; + goto out; + } + first_call = 0; + + /* Make sure nothing is left over from a previous stream */ + if (ue9_stream_stop (fd_cmd) == 0) + verb ("Stopped previous stream.\n"); + ue9_buffer_flush (fd_cmd); + + /* Open data connection */ + fd_data = ue9_open (address, UE9_DATA_PORT); + if (fd_data < 0) + { + info ("Connect failed: %s:%d\n", address, UE9_DATA_PORT); + goto out1; + } + + /* Get calibration */ + if (ue9_get_calibration (fd_cmd, &ci.calib) < 0) + { + info ("Failed to get device calibration\n"); + goto out2; + } + + /* Set stream configuration */ + if (ue9_streamconfig_simple (fd_cmd, channel_list, channel_count, + scanconfig, scaninterval, + UE9_BIPOLAR_GAIN1) < 0) + { + info ("Failed to set stream configuration\n"); + goto out2; + } + + /* Start stream */ + if (ue9_stream_start (fd_cmd) < 0) + { + info ("Failed to start stream\n"); + goto out2; + } + + /* Stream data */ + ret = ue9_stream_data (fd_data, channel_count, data_callback, (void *) &ci); + if (ret < 0) + { + info ("Data stream failed with error %d\n", ret); + goto out3; + } + + info ("Stream finished\n"); + retval = 0; + +out3: + /* Stop stream and clean up */ + ue9_stream_stop (fd_cmd); + ue9_buffer_flush (fd_cmd); +out2: + ue9_close (fd_data); +out1: + ue9_close (fd_cmd); +out: + return retval; +} + +int +data_callback (int channels, uint16_t * data, void *context) +{ + int i; + struct callbackInfo *ci = (struct callbackInfo *) context; + static int lines = 0; + + columns_left = channels; + for (i = 0; i < channels; i++) + { + switch (ci->convert) + { + case CONVERT_VOLTS: + if (printf + ("%lf", + ue9_binary_to_analog (&ci->calib, UE9_BIPOLAR_GAIN1, 12, + data[i])) < 0) + goto bad; + break; + case CONVERT_HEX: + if (printf ("%04X", data[i]) < 0) + goto bad; + break; + default: + case CONVERT_DEC: + if (printf ("%d", data[i]) < 0) + goto bad; + break; } - - return 0; + columns_left--; + if (i < (channels - 1)) + { + if (ci->convert != CONVERT_HEX && putchar (' ') < 0) + goto bad; + } + else + { + if (putchar ('\n') < 0) + goto bad; + lines++; + if (ci->maxlines && lines >= ci->maxlines) + return -1; + } + } + + return 0; bad: - info("Output error (disk full?)\n"); - return -1; + info ("Output error (disk full?)\n"); + return -1; } diff --git a/ljconfig.c b/ljconfig.c index a5e9f1d..faf0b0f 100644 --- a/ljconfig.c +++ b/ljconfig.c @@ -25,74 +25,78 @@ #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 } + {'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 \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 \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 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; - } - - /* 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; - } + } - 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; - } - - //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 -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: - 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; } - - /* 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 -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; } diff --git a/nerdjack.h b/nerdjack.h index 50e98f7..06fdada 100644 --- a/nerdjack.h +++ b/nerdjack.h @@ -24,33 +24,38 @@ #define NERDJACK_PACKET_SIZE 1460 #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; /* 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); /* 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 */ -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 diff --git a/netutil.c b/netutil.c index 7b8490d..78fed8d 100644 --- a/netutil.c +++ b/netutil.c @@ -5,239 +5,262 @@ #include /* Initialize networking */ -void net_init(void) +void +net_init (void) { #ifdef __WIN32__ - WSADATA blah; - WSAStartup(0x0101, &blah); + WSADATA blah; + WSAStartup (0x0101, &blah); #endif } /* Set socket blocking/nonblocking */ -int soblock(int socket, int blocking) +int +soblock (int socket, int blocking) { #ifdef __WIN32__ - unsigned long arg = blocking ? 0 : 1; - if (ioctlsocket(socket, FIONBIO, &arg) != 0) - return -1; - return 0; + unsigned long arg = blocking ? 0 : 1; + if (ioctlsocket (socket, FIONBIO, &arg) != 0) + return -1; + return 0; #else - int sockopt; - - /* Get flags */ - sockopt = fcntl(socket, F_GETFL); - if (sockopt == -1) { - return -1; - } - - /* Modify */ - if (blocking) - sockopt &= ~O_NONBLOCK; - else - sockopt |= O_NONBLOCK; - - /* Set flags */ - if (fcntl(socket, F_SETFL, sockopt) != 0) - return -1; - - return 0; + int sockopt; + + /* Get flags */ + sockopt = fcntl (socket, F_GETFL); + if (sockopt == -1) + { + return -1; + } + + /* Modify */ + if (blocking) + sockopt &= ~O_NONBLOCK; + else + sockopt |= O_NONBLOCK; + + /* Set flags */ + if (fcntl (socket, F_SETFL, sockopt) != 0) + return -1; + + return 0; #endif } /* Like connect(2), but with a timeout. Socket must be non-blocking. */ -int connect_timeout(int s, const struct sockaddr *serv_addr, socklen_t addrlen, - struct timeval *timeout) +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__ - errno = WSAGetLastError(); - if (ret < 0 && errno != WSAEWOULDBLOCK && errno != WSAEINVAL) - return -1; + errno = WSAGetLastError (); + if (ret < 0 && errno != WSAEWOULDBLOCK && errno != WSAEINVAL) + return -1; #else - if (ret < 0 && errno != EINPROGRESS && errno != EALREADY) - return -1; + if (ret < 0 && errno != EINPROGRESS && errno != EALREADY) + return -1; #endif - /* In progress, wait for result. */ - FD_ZERO(&writefds); - FD_SET(s, &writefds); - FD_ZERO(&exceptfds); - FD_SET(s, &exceptfds); - ret = select(s + 1, NULL, &writefds, &exceptfds, timeout); - if (ret < 0) { - /* Error */ - return -1; - } - if (ret == 0) { - /* Timed out */ - errno = ETIMEDOUT; - return -1; - } - - /* Check the socket state */ - optlen = sizeof(optval); - if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen) != 0) - return -1; - - if (optval != 0) { - /* Connection failed. */ - errno = optval; - return -1; - } - - /* On Windows, SO_ERROR sometimes shows no error but the connection - still failed. Sigh. */ - if (FD_ISSET(s, &exceptfds) || !FD_ISSET(s, &writefds)) { - errno = EIO; - return -1; - } - - /* Success */ - return 0; + /* In progress, wait for result. */ + FD_ZERO (&writefds); + FD_SET (s, &writefds); + FD_ZERO (&exceptfds); + FD_SET (s, &exceptfds); + ret = select (s + 1, NULL, &writefds, &exceptfds, timeout); + if (ret < 0) + { + /* Error */ + return -1; + } + if (ret == 0) + { + /* Timed out */ + errno = ETIMEDOUT; + return -1; + } + + /* Check the socket state */ + optlen = sizeof (optval); + if (getsockopt (s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen) != 0) + return -1; + + if (optval != 0) + { + /* Connection failed. */ + errno = optval; + return -1; + } + + /* On Windows, SO_ERROR sometimes shows no error but the connection + still failed. Sigh. */ + if (FD_ISSET (s, &exceptfds) || !FD_ISSET (s, &writefds)) + { + errno = EIO; + return -1; + } + + /* Success */ + return 0; } /* Like send(2), but with a timeout. Socket must be non-blocking. The timeout only applies if no data at all is sent -- this function may still send less than requested. */ -ssize_t send_timeout(int s, const void *buf, size_t len, int flags, - struct timeval *timeout) +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. 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) +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. 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) +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 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) +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 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) +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; } diff --git a/netutil.h b/netutil.h index 3681fbb..5585b1b 100644 --- a/netutil.h +++ b/netutil.h @@ -19,27 +19,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 diff --git a/opt.c b/opt.c index 408537e..bc6aa24 100644 --- a/opt.c +++ b/opt.c @@ -11,85 +11,98 @@ #include #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); + } } diff --git a/opt.h b/opt.h index 7dbabdf..1611ebb 100644 --- a/opt.h +++ b/opt.h @@ -11,18 +11,19 @@ #include -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 diff --git a/ue9.c b/ue9.c index 2d326c9..462f3ed 100644 --- a/ue9.c +++ b/ue9.c @@ -25,629 +25,725 @@ #include "util.h" #include "netutil.h" -#define UE9_TIMEOUT 5 /* Timeout for connect/send/recv, in seconds */ +#define UE9_TIMEOUT 5 /* Timeout for connect/send/recv, in seconds */ /* Fill checksums in data buffers, with "normal" checksum format */ -void ue9_checksum_normal(uint8_t *buffer, size_t len) +void +ue9_checksum_normal (uint8_t * buffer, size_t len) { - uint16_t sum = 0; - - if (len < 1) { - fprintf(stderr, "ue9_checksum_normal: len too short\n"); - exit(1); - } - - while (--len >= 1) - sum += (uint16_t) buffer[len]; - sum = (sum / 256) + (sum % 256); - sum = (sum / 256) + (sum % 256); - buffer[0] = (uint8_t) sum; + uint16_t sum = 0; + + if (len < 1) + { + fprintf (stderr, "ue9_checksum_normal: len too short\n"); + exit (1); + } + + while (--len >= 1) + sum += (uint16_t) buffer[len]; + sum = (sum / 256) + (sum % 256); + sum = (sum / 256) + (sum % 256); + buffer[0] = (uint8_t) sum; } /* Fill checksums in data buffers, with "extended" checksum format */ -void ue9_checksum_extended(uint8_t *buffer, size_t len) +void +ue9_checksum_extended (uint8_t * buffer, size_t len) { - uint16_t sum = 0; - - if (len < 6) { - fprintf(stderr, "ue9_checksum_extended: len too short\n"); - exit(1); - } - - /* 16-bit extended checksum */ - while (--len >= 6) - sum += (uint16_t) buffer[len]; - buffer[4] = (uint8_t) (sum & 0xff); - buffer[5] = (uint8_t) (sum >> 8); - - /* 8-bit normal checksum over first 6 bytes */ - ue9_checksum_normal(buffer, 6); + uint16_t sum = 0; + + if (len < 6) + { + fprintf (stderr, "ue9_checksum_extended: len too short\n"); + exit (1); + } + + /* 16-bit extended checksum */ + while (--len >= 6) + sum += (uint16_t) buffer[len]; + buffer[4] = (uint8_t) (sum & 0xff); + buffer[5] = (uint8_t) (sum >> 8); + + /* 8-bit normal checksum over first 6 bytes */ + ue9_checksum_normal (buffer, 6); } /* Verify checksums in data buffers, with "normal" checksum format. */ -int ue9_verify_normal(uint8_t *buffer, size_t len) +int +ue9_verify_normal (uint8_t * buffer, size_t len) { - uint8_t saved, new; - - if (len < 1) { - fprintf(stderr, "ue9_verify_normal: len too short\n"); - exit(1); - } - - saved = buffer[0]; - ue9_checksum_normal(buffer, len); - new = buffer[0]; - buffer[0] = saved; - - if (new != saved) { - verb("got %02x, expected %02x\n", - saved, new); - return 0; - } - - return 1; + uint8_t saved, new; + + if (len < 1) + { + fprintf (stderr, "ue9_verify_normal: len too short\n"); + exit (1); + } + + saved = buffer[0]; + ue9_checksum_normal (buffer, len); + new = buffer[0]; + buffer[0] = saved; + + if (new != saved) + { + verb ("got %02x, expected %02x\n", saved, new); + return 0; + } + + return 1; } /* Verify checksums in data buffers, with "extended" checksum format. */ -int ue9_verify_extended(uint8_t *buffer, size_t len) +int +ue9_verify_extended (uint8_t * buffer, size_t len) { - uint8_t saved[3], new[3]; - - if (len < 6) { - fprintf(stderr, "ue9_verify_extended: len too short\n"); - exit(1); - } - - saved[0] = buffer[0]; - saved[1] = buffer[4]; - saved[2] = buffer[5]; - ue9_checksum_extended(buffer, len); - new[0] = buffer[0]; - new[1] = buffer[4]; - new[2] = buffer[5]; - buffer[0] = saved[0]; - buffer[4] = saved[1]; - buffer[5] = saved[2]; - - if (saved[0] != new[0] || - saved[1] != new[1] || - saved[2] != new[2]) { - verb("got %02x %02x %02x, expected %02x %02x %02x\n", - saved[0], saved[1], saved[2], new[0], new[1], new[2]); - return 0; - } - - return 1; -} + uint8_t saved[3], new[3]; + + if (len < 6) + { + fprintf (stderr, "ue9_verify_extended: len too short\n"); + exit (1); + } + + saved[0] = buffer[0]; + saved[1] = buffer[4]; + saved[2] = buffer[5]; + ue9_checksum_extended (buffer, len); + new[0] = buffer[0]; + new[1] = buffer[4]; + new[2] = buffer[5]; + buffer[0] = saved[0]; + buffer[4] = saved[1]; + buffer[5] = saved[2]; + + if (saved[0] != new[0] || saved[1] != new[1] || saved[2] != new[2]) + { + verb ("got %02x %02x %02x, expected %02x %02x %02x\n", + saved[0], saved[1], saved[2], new[0], new[1], new[2]); + return 0; + } + + return 1; +} /* 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) { - double slope = 0, offset; - - if (calib == NULL) { - double uncal[9] = { 5.08, 2.54, 1.27, 0.63, 0, 0, 0, 0, 10.25 }; - if (gain >= ARRAY_SIZE(uncal) || uncal[gain] == 0) { - fprintf(stderr, "ue9_binary_to_analog: bad gain\n"); - exit(1); - } - return data * uncal[gain] / 65536.0; + double slope = 0, offset; + + if (calib == NULL) + { + double uncal[9] = { 5.08, 2.54, 1.27, 0.63, 0, 0, 0, 0, 10.25 }; + if (gain >= ARRAY_SIZE (uncal) || uncal[gain] == 0) + { + fprintf (stderr, "ue9_binary_to_analog: bad gain\n"); + exit (1); } - - if (resolution < 18) { - if (gain <= 3) { - slope = calib->unipolarSlope[gain]; - offset = calib->unipolarOffset[gain]; - } else if (gain == 8) { - slope = calib->bipolarSlope; - offset = calib->bipolarOffset; - } - } else { - if (gain == 0) { - slope = calib->hiResUnipolarSlope; - offset = calib->hiResUnipolarOffset; - } else if (gain == 8) { - slope = calib->hiResBipolarSlope; - offset = calib->hiResBipolarOffset; - } + return data * uncal[gain] / 65536.0; + } + + if (resolution < 18) + { + if (gain <= 3) + { + slope = calib->unipolarSlope[gain]; + offset = calib->unipolarOffset[gain]; } - - if (slope == 0) { - fprintf(stderr, "ue9_binary_to_analog: bad gain\n"); - exit(1); + else if (gain == 8) + { + slope = calib->bipolarSlope; + offset = calib->bipolarOffset; + } + } + else + { + if (gain == 0) + { + slope = calib->hiResUnipolarSlope; + offset = calib->hiResUnipolarOffset; + } + else if (gain == 8) + { + slope = calib->hiResBipolarSlope; + offset = calib->hiResBipolarOffset; } - - return data * slope + offset; + } + + if (slope == 0) + { + fprintf (stderr, "ue9_binary_to_analog: bad gain\n"); + exit (1); + } + + return data * slope + offset; } /* 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) { - int extended = 0, outlen; - uint8_t saved_1, saved_3; - ssize_t ret; - - if ((out[1] & 0x78) == 0x78) - extended = 1; - - /* Figure out length of data payload, and fill checksums. */ - if (extended) { - outlen = 6 + (out[2]) * 2; - ue9_checksum_extended(out, outlen); - } else { - outlen = 2 + (out[1] & 7) * 2; - ue9_checksum_normal(out, outlen); - } - - /* Send request */ - ret = send_all_timeout(fd, out, outlen, 0, - & (struct timeval) { .tv_sec = UE9_TIMEOUT }); - if (ret < 0 || ret != outlen) { - verb("short send %d\n", (int)ret); - return -1; - } - - /* Save a few bytes that we'll want to compare against later, - in case the caller passed the same buffer twice. */ - saved_1 = out[1]; - if (extended) - saved_3 = out[3]; - - /* Receive result */ - ret = recv_all_timeout(fd, in, inlen, 0, - & (struct timeval) { .tv_sec = UE9_TIMEOUT }); - if (ret < 0 || ret != inlen) { - verb("short recv %d\n", (int)ret); - return -1; - } - - /* Verify it */ - if ((in[1] & 0xF8) != (saved_1 & 0xF8)) - verb("returned command doesn't match\n"); - else if (extended && (in[3] != saved_3)) - verb("extended command doesn't match\n"); - else if (extended && (inlen != (6 + (in[2]) * 2))) - verb("returned extended data is the wrong len\n"); - else if (!extended && (inlen != (2 + (in[1] & 7) * 2))) - verb("returned data is the wrong len\n"); - else if (extended && !ue9_verify_extended(in, inlen)) - verb("extended checksum is invalid\n"); - else if (!ue9_verify_normal(in, extended ? 6 : inlen)) - verb("normal checksum is invalid\n"); - else - return 0; /* looks good */ - - return -1; + int extended = 0, outlen; + uint8_t saved_1, saved_3; + ssize_t ret; + + if ((out[1] & 0x78) == 0x78) + extended = 1; + + /* Figure out length of data payload, and fill checksums. */ + if (extended) + { + outlen = 6 + (out[2]) * 2; + ue9_checksum_extended (out, outlen); + } + else + { + outlen = 2 + (out[1] & 7) * 2; + ue9_checksum_normal (out, outlen); + } + + /* Send request */ + ret = send_all_timeout (fd, out, outlen, 0, &(struct timeval) + { + .tv_sec = UE9_TIMEOUT}); + if (ret < 0 || ret != outlen) + { + verb ("short send %d\n", (int) ret); + return -1; + } + + /* Save a few bytes that we'll want to compare against later, + in case the caller passed the same buffer twice. */ + saved_1 = out[1]; + if (extended) + saved_3 = out[3]; + + /* Receive result */ + ret = recv_all_timeout (fd, in, inlen, 0, &(struct timeval) + { + .tv_sec = UE9_TIMEOUT}); + if (ret < 0 || ret != inlen) + { + verb ("short recv %d\n", (int) ret); + return -1; + } + + /* Verify it */ + if ((in[1] & 0xF8) != (saved_1 & 0xF8)) + verb ("returned command doesn't match\n"); + else if (extended && (in[3] != saved_3)) + verb ("extended command doesn't match\n"); + else if (extended && (inlen != (6 + (in[2]) * 2))) + verb ("returned extended data is the wrong len\n"); + else if (!extended && (inlen != (2 + (in[1] & 7) * 2))) + verb ("returned data is the wrong len\n"); + else if (extended && !ue9_verify_extended (in, inlen)) + verb ("extended checksum is invalid\n"); + else if (!ue9_verify_normal (in, extended ? 6 : inlen)) + verb ("normal checksum is invalid\n"); + else + return 0; /* looks good */ + + return -1; } /* 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) { - uint8_t sendbuf[8], recvbuf[136]; - - if (len != 128) { - fprintf(stderr,"ue9_memory_read: buffer length must be 128\n"); - exit(1); - } - - /* Request memory block */ - sendbuf[1] = 0xf8; - sendbuf[2] = 0x01; - sendbuf[3] = 0x2a; - sendbuf[6] = 0x00; - sendbuf[7] = blocknum; - - if (ue9_command(fd, sendbuf, recvbuf, sizeof(recvbuf)) < 0) { - verb("command failed\n"); - return -1; - } - - /* Got it */ - memcpy(buffer, recvbuf + 8, len); - - return 0; + uint8_t sendbuf[8], recvbuf[136]; + + if (len != 128) + { + fprintf (stderr, "ue9_memory_read: buffer length must be 128\n"); + exit (1); + } + + /* Request memory block */ + sendbuf[1] = 0xf8; + sendbuf[2] = 0x01; + sendbuf[3] = 0x2a; + sendbuf[6] = 0x00; + sendbuf[7] = blocknum; + + if (ue9_command (fd, sendbuf, recvbuf, sizeof (recvbuf)) < 0) + { + verb ("command failed\n"); + return -1; + } + + /* Got it */ + memcpy (buffer, recvbuf + 8, len); + + return 0; } /* Convert 64-bit fixed point to double type */ -double ue9_fp64_to_double(uint8_t *data) +double +ue9_fp64_to_double (uint8_t * data) { - int32_t a; - uint32_t b; + int32_t a; + uint32_t b; - a = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; - b = (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]; + a = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; + b = (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]; - return (double)a + (double)b / (double)4294967296.0L; + return (double) a + (double) b / (double) 4294967296.0L; } /* Retrieve calibration data from the device. Returns -1 on error. */ -int ue9_get_calibration(int fd, struct ue9Calibration *calib) +int +ue9_get_calibration (int fd, struct ue9Calibration *calib) { - uint8_t buf[128]; - - /* Block 0 */ - if (ue9_memory_read(fd, 0, buf, 128) < 0) return -1; - calib->unipolarSlope[0] = ue9_fp64_to_double(buf + 0); - calib->unipolarOffset[0] = ue9_fp64_to_double(buf + 8); - calib->unipolarSlope[1] = ue9_fp64_to_double(buf + 16); - calib->unipolarOffset[1] = ue9_fp64_to_double(buf + 24); - calib->unipolarSlope[2] = ue9_fp64_to_double(buf + 32); - calib->unipolarOffset[2] = ue9_fp64_to_double(buf + 40); - calib->unipolarSlope[3] = ue9_fp64_to_double(buf + 48); - calib->unipolarOffset[3] = ue9_fp64_to_double(buf + 56); - - /* Block 1 */ - if (ue9_memory_read(fd, 1, buf, 128) < 0) return -1; - calib->bipolarSlope = ue9_fp64_to_double(buf + 0); - calib->bipolarOffset = ue9_fp64_to_double(buf + 8); - - /* Block 2 */ - if (ue9_memory_read(fd, 2, buf, 128) < 0) return -1; - calib->DACSlope[0] = ue9_fp64_to_double(buf + 0); - calib->DACOffset[0] = ue9_fp64_to_double(buf + 8); - calib->DACSlope[1] = ue9_fp64_to_double(buf + 16); - calib->DACOffset[1] = ue9_fp64_to_double(buf + 24); - calib->tempSlope = ue9_fp64_to_double(buf + 32); - calib->tempSlopeLow = ue9_fp64_to_double(buf + 48); - calib->calTemp = ue9_fp64_to_double(buf + 64); - calib->Vref = ue9_fp64_to_double(buf + 72); - calib->VrefDiv2 = ue9_fp64_to_double(buf + 88); - calib->VsSlope = ue9_fp64_to_double(buf + 96); - - /* Block 3 */ - if (ue9_memory_read(fd, 3, buf, 128) < 0) return -1; - calib->hiResUnipolarSlope = ue9_fp64_to_double(buf + 0); - calib->hiResUnipolarOffset = ue9_fp64_to_double(buf + 8); - - /* Block 4 */ - if (ue9_memory_read(fd, 4, buf, 128) < 0) return -1; - calib->hiResBipolarSlope = ue9_fp64_to_double(buf + 0); - calib->hiResBipolarOffset = ue9_fp64_to_double(buf + 8); - - /* All done */ - return 1; + uint8_t buf[128]; + + /* Block 0 */ + if (ue9_memory_read (fd, 0, buf, 128) < 0) + return -1; + calib->unipolarSlope[0] = ue9_fp64_to_double (buf + 0); + calib->unipolarOffset[0] = ue9_fp64_to_double (buf + 8); + calib->unipolarSlope[1] = ue9_fp64_to_double (buf + 16); + calib->unipolarOffset[1] = ue9_fp64_to_double (buf + 24); + calib->unipolarSlope[2] = ue9_fp64_to_double (buf + 32); + calib->unipolarOffset[2] = ue9_fp64_to_double (buf + 40); + calib->unipolarSlope[3] = ue9_fp64_to_double (buf + 48); + calib->unipolarOffset[3] = ue9_fp64_to_double (buf + 56); + + /* Block 1 */ + if (ue9_memory_read (fd, 1, buf, 128) < 0) + return -1; + calib->bipolarSlope = ue9_fp64_to_double (buf + 0); + calib->bipolarOffset = ue9_fp64_to_double (buf + 8); + + /* Block 2 */ + if (ue9_memory_read (fd, 2, buf, 128) < 0) + return -1; + calib->DACSlope[0] = ue9_fp64_to_double (buf + 0); + calib->DACOffset[0] = ue9_fp64_to_double (buf + 8); + calib->DACSlope[1] = ue9_fp64_to_double (buf + 16); + calib->DACOffset[1] = ue9_fp64_to_double (buf + 24); + calib->tempSlope = ue9_fp64_to_double (buf + 32); + calib->tempSlopeLow = ue9_fp64_to_double (buf + 48); + calib->calTemp = ue9_fp64_to_double (buf + 64); + calib->Vref = ue9_fp64_to_double (buf + 72); + calib->VrefDiv2 = ue9_fp64_to_double (buf + 88); + calib->VsSlope = ue9_fp64_to_double (buf + 96); + + /* Block 3 */ + if (ue9_memory_read (fd, 3, buf, 128) < 0) + return -1; + calib->hiResUnipolarSlope = ue9_fp64_to_double (buf + 0); + calib->hiResUnipolarOffset = ue9_fp64_to_double (buf + 8); + + /* Block 4 */ + if (ue9_memory_read (fd, 4, buf, 128) < 0) + return -1; + calib->hiResBipolarSlope = ue9_fp64_to_double (buf + 0); + calib->hiResBipolarOffset = ue9_fp64_to_double (buf + 8); + + /* All done */ + return 1; } /* Retrieve comm config, returns -1 on error */ -int ue9_get_comm_config(int fd, struct ue9CommConfig *config) +int +ue9_get_comm_config (int fd, struct ue9CommConfig *config) { - uint8_t sendbuf[18]; - uint8_t recvbuf[24]; - - memset(sendbuf, 0, sizeof(sendbuf)); - memset(config, 0, sizeof(struct ue9CommConfig)); - - sendbuf[1] = 0xf8; - sendbuf[2] = 0x09; - sendbuf[3] = 0x08; - if (ue9_command(fd, sendbuf, recvbuf, sizeof(recvbuf)) < 0) { - verb("command failed\n"); - return -1; - } - verb("todo\n"); - return -1; + uint8_t sendbuf[18]; + uint8_t recvbuf[24]; + + memset (sendbuf, 0, sizeof (sendbuf)); + memset (config, 0, sizeof (struct ue9CommConfig)); + + sendbuf[1] = 0xf8; + sendbuf[2] = 0x09; + sendbuf[3] = 0x08; + if (ue9_command (fd, sendbuf, recvbuf, sizeof (recvbuf)) < 0) + { + verb ("command failed\n"); + return -1; + } + verb ("todo\n"); + return -1; } /* Retrieve control config, returns -1 on error */ -int ue9_get_control_config(int fd, struct ue9ControlConfig *config) +int +ue9_get_control_config (int fd, struct ue9ControlConfig *config) { - uint8_t sendbuf[18]; - uint8_t recvbuf[24]; - - memset(sendbuf, 0, sizeof(sendbuf)); - memset(config, 0, sizeof(struct ue9ControlConfig)); - - sendbuf[1] = 0xf8; - sendbuf[2] = 0x06; - sendbuf[3] = 0x08; - if (ue9_command(fd, sendbuf, recvbuf, sizeof(recvbuf)) < 0) { - verb("command failed\n"); - return -1; - } - verb("todo\n"); - return -1; + uint8_t sendbuf[18]; + uint8_t recvbuf[24]; + + memset (sendbuf, 0, sizeof (sendbuf)); + memset (config, 0, sizeof (struct ue9ControlConfig)); + + sendbuf[1] = 0xf8; + sendbuf[2] = 0x06; + sendbuf[3] = 0x08; + if (ue9_command (fd, sendbuf, recvbuf, sizeof (recvbuf)) < 0) + { + verb ("command failed\n"); + return -1; + } + verb ("todo\n"); + return -1; } /* Open TCP/IP connection to the UE9 */ -int ue9_open(const char *host, int port) +int +ue9_open (const char *host, int port) { - int fd; - struct sockaddr_in address; - struct hostent *he; - int window_size = 128 * 1024; - - net_init(); - - /* Create socket */ - fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (fd < 0) { - verb("socket returned %d\n", fd); - return -1; - } - - /* Set nonblocking */ - if (soblock(fd, 0) < 0) { - verb("can't set nonblocking\n"); - return -1; - } - - /* Set initial window size hint to workaround LabJack firmware bug */ - setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&window_size, - sizeof(window_size)); - setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&window_size, - sizeof(window_size)); - - /* Resolve host */ - address.sin_family = AF_INET; - address.sin_port = htons(port); - he = gethostbyname(host); - if (he == NULL) { - verb("gethostbyname(\"%s\") failed\n", host); - return -1; - } - address.sin_addr = *((struct in_addr *) he->h_addr); - - debug("Resolved %s -> %s\n", host, inet_ntoa(address.sin_addr)); - - /* Connect */ - if (connect_timeout(fd, (struct sockaddr *) &address, sizeof(address), - & (struct timeval) { .tv_sec = UE9_TIMEOUT }) < 0) { - verb("connection to %s:%d failed: %s\n", - inet_ntoa(address.sin_addr), port, compat_strerror(errno)); - return -1; - } - - return fd; + int fd; + struct sockaddr_in address; + struct hostent *he; + int window_size = 128 * 1024; + + net_init (); + + /* Create socket */ + fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) + { + verb ("socket returned %d\n", fd); + return -1; + } + + /* Set nonblocking */ + if (soblock (fd, 0) < 0) + { + verb ("can't set nonblocking\n"); + return -1; + } + + /* Set initial window size hint to workaround LabJack firmware bug */ + setsockopt (fd, SOL_SOCKET, SO_SNDBUF, (void *) &window_size, + sizeof (window_size)); + setsockopt (fd, SOL_SOCKET, SO_RCVBUF, (void *) &window_size, + sizeof (window_size)); + + /* Resolve host */ + address.sin_family = AF_INET; + address.sin_port = htons (port); + he = gethostbyname (host); + if (he == NULL) + { + verb ("gethostbyname(\"%s\") failed\n", host); + return -1; + } + address.sin_addr = *((struct in_addr *) he->h_addr); + + debug ("Resolved %s -> %s\n", host, inet_ntoa (address.sin_addr)); + + /* Connect */ + if (connect_timeout (fd, (struct sockaddr *) &address, sizeof (address), + &(struct timeval) + { + .tv_sec = UE9_TIMEOUT}) < 0) + { + verb ("connection to %s:%d failed: %s\n", + inet_ntoa (address.sin_addr), port, compat_strerror (errno)); + return -1; + } + + return fd; } /* Close connection to the UE9 */ -void ue9_close(int fd) +void +ue9_close (int fd) { - /* does anyone actually call shutdown these days? */ - shutdown(fd, 2 /* SHUT_RDWR */); - close(fd); + /* does anyone actually call shutdown these days? */ + shutdown (fd, 2 /* SHUT_RDWR */ ); + close (fd); } /* 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) { - double clock; - - /* A "scan" is across all channels. Each scan is triggered at - a fixed rate, and not affected by the number of channels. - Channels are scanned as quickly as possible. */ - - switch ((scanconfig >> 3) & 3) { - case 0: clock = 4e6; break; - case 1: clock = 48e6; break; - case 2: clock = 750e3; break; - case 3: clock = 24e6; break; - } - - if (scanconfig & 0x2) - clock /= 256; - - if (scaninterval == 0) - return 0; - - return clock / scaninterval; + double clock; + + /* A "scan" is across all channels. Each scan is triggered at + a fixed rate, and not affected by the number of channels. + Channels are scanned as quickly as possible. */ + + switch ((scanconfig >> 3) & 3) + { + case 0: + clock = 4e6; + break; + case 1: + clock = 48e6; + break; + case 2: + clock = 750e3; + break; + case 3: + clock = 24e6; + break; + } + + if (scanconfig & 0x2) + clock /= 256; + + if (scaninterval == 0) + return 0; + + return clock / scaninterval; } /* Choose the best ScanConfig and ScanInterval parameters for the desired scanrate. Returns -1 if no valid config found */ -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) { - int i; - struct { double clock; uint8_t config; } valid[] = { - { 48e6, 0x08 }, - { 24e6, 0x18 }, - { 4e6, 0x00 }, - { 750e3, 0x10 }, - { 48e6 / 256, 0x0a }, - { 24e6 / 256, 0x1a }, - { 4e6 / 256, 0x02 }, - { 750e3 / 256, 0x12 }, - { 0, 0 } }; - - /* Start with the fastest clock frequency. If the - scaninterval would be too large, knock it down until it - fits. */ - for (i = 0; valid[i].clock != 0; i++) { - double interval = valid[i].clock / desired_rate; - - debug("Considering clock %lf (interval %lf)\n", - valid[i].clock, interval); - - if (interval >= 0.5 && interval < 65535.5) { - - *scaninterval = floor(interval + 0.5); - - *scanconfig = valid[i].config; - *actual_rate = ue9_compute_rate( - *scanconfig, *scaninterval); - - debug("Config 0x%02x, desired %lf, actual %lf\n", - *scanconfig, desired_rate, *actual_rate); - - return 0; - } + int i; + struct + { + double clock; + uint8_t config; + } valid[] = + { + { + 48e6, 0x08}, + { + 24e6, 0x18}, + { + 4e6, 0x00}, + { + 750e3, 0x10}, + { + 48e6 / 256, 0x0a}, + { + 24e6 / 256, 0x1a}, + { + 4e6 / 256, 0x02}, + { + 750e3 / 256, 0x12}, + { + 0, 0}}; + + /* Start with the fastest clock frequency. If the + scaninterval would be too large, knock it down until it + fits. */ + for (i = 0; valid[i].clock != 0; i++) + { + double interval = valid[i].clock / desired_rate; + + debug ("Considering clock %lf (interval %lf)\n", + valid[i].clock, interval); + + if (interval >= 0.5 && interval < 65535.5) + { + + *scaninterval = floor (interval + 0.5); + + *scanconfig = valid[i].config; + *actual_rate = ue9_compute_rate (*scanconfig, *scaninterval); + + debug ("Config 0x%02x, desired %lf, actual %lf\n", + *scanconfig, desired_rate, *actual_rate); + + return 0; } + } - return -1; + return -1; } /* Flush data buffers */ -void ue9_buffer_flush(int fd) +void +ue9_buffer_flush (int fd) { - uint8_t sendbuf[2], recvbuf[2]; - - sendbuf[1] = 0x08; /* FlushBuffer */ + uint8_t sendbuf[2], recvbuf[2]; - if (ue9_command(fd, sendbuf, recvbuf, sizeof(recvbuf)) < 0) { - verb("command failed\n"); - } + sendbuf[1] = 0x08; /* FlushBuffer */ + + if (ue9_command (fd, sendbuf, recvbuf, sizeof (recvbuf)) < 0) + { + verb ("command failed\n"); + } } /* Stop stream. Returns < 0 on failure. */ -int ue9_stream_stop(int fd) +int +ue9_stream_stop (int fd) { - uint8_t sendbuf[2], recvbuf[4]; - - sendbuf[1] = 0xB0; + uint8_t sendbuf[2], recvbuf[4]; - if (ue9_command(fd, sendbuf, recvbuf, sizeof(recvbuf)) < 0) { - verb("command failed\n"); - return -1; - } - - if (recvbuf[2] == STREAM_NOT_RUNNING || recvbuf[2] == 0) - return 0; + sendbuf[1] = 0xB0; + + if (ue9_command (fd, sendbuf, recvbuf, sizeof (recvbuf)) < 0) + { + verb ("command failed\n"); + return -1; + } - debug("error %s\n", ue9_error(recvbuf[2])); - return -recvbuf[2]; + if (recvbuf[2] == STREAM_NOT_RUNNING || recvbuf[2] == 0) + return 0; + + debug ("error %s\n", ue9_error (recvbuf[2])); + return -recvbuf[2]; } /* Start stream. Returns < 0 on failure. */ -int ue9_stream_start(int fd) +int +ue9_stream_start (int fd) { - uint8_t sendbuf[2], recvbuf[4]; - - sendbuf[1] = 0xA8; + uint8_t sendbuf[2], recvbuf[4]; - if (ue9_command(fd, sendbuf, recvbuf, sizeof(recvbuf)) < 0) { - verb("command failed\n"); - return -1; - } - - if (recvbuf[2] == 0) - return 0; + sendbuf[1] = 0xA8; + + if (ue9_command (fd, sendbuf, recvbuf, sizeof (recvbuf)) < 0) + { + verb ("command failed\n"); + return -1; + } - debug("error %s\n", ue9_error(recvbuf[2])); - return -recvbuf[2]; + if (recvbuf[2] == 0) + return 0; + + debug ("error %s\n", ue9_error (recvbuf[2])); + return -recvbuf[2]; } /* "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) +{ + int i; + uint8_t buf[256]; + + /* Set up StreamConfig command with channels and scan options */ + buf[1] = 0xF8; /* Extended command */ + buf[2] = channel_count + 3; /* Command data words */ + buf[3] = 0x11; /* StreamConfig */ + buf[6] = channel_count; /* Number of channels */ + buf[7] = 12; /* Bit resolution */ + buf[8] = 0; /* Extra settling time */ + buf[9] = scanconfig; + buf[10] = scaninterval & 0xff; + buf[11] = scaninterval >> 8; + + for (i = 0; i < channel_count; i++) + { + buf[12 + 2 * i] = channel_list[i]; /* Channel number */ + buf[13 + 2 * i] = gain; /* Gain/bipolar setup */ + } + + /* Send StreamConfig */ + if (ue9_command (fd, buf, buf, 8) < 0) + { + debug ("command failed\n"); + return -1; + } + + if (buf[6] != 0) + { + verb ("returned error %s\n", ue9_error (buf[6])); + return -1; + } + + return 0; +} + +/* Stream data and pass it to the data callback. If callback returns + negative, stops reading and returns 0. Returns < 0 on error. */ +int +ue9_stream_data (int fd, int channels, + ue9_stream_cb_t callback, void *context) { - int i; - uint8_t buf[256]; - - /* Set up StreamConfig command with channels and scan options */ - buf[1] = 0xF8; /* Extended command */ - buf[2] = channel_count + 3; /* Command data words */ - buf[3] = 0x11; /* StreamConfig */ - buf[6] = channel_count; /* Number of channels */ - buf[7] = 12; /* Bit resolution */ - buf[8] = 0; /* Extra settling time */ - buf[9] = scanconfig; - buf[10] = scaninterval & 0xff; - buf[11] = scaninterval >> 8; - - for (i = 0; i < channel_count; i++) { - buf[12 + 2*i] = channel_list[i]; /* Channel number */ - buf[13 + 2*i] = gain; /* Gain/bipolar setup */ + int ret; + uint8_t buf[46]; + uint8_t packet = 0; + int channel = 0; + int i; + uint16_t data[channels]; + + for (;;) + { + /* Receive data */ + ret = recv_all_timeout (fd, buf, 46, 0, &(struct timeval) + { + .tv_sec = UE9_TIMEOUT}); + + /* Verify packet format */ + if (ret != 46) + { + verb ("short recv %d\n", (int) ret); + return -1; } - /* Send StreamConfig */ - if (ue9_command(fd, buf, buf, 8) < 0) { - debug("command failed\n"); - return -1; + if (!ue9_verify_extended (buf, 46) || !ue9_verify_normal (buf, 6)) + { + verb ("bad checksum\n"); + return -2; } - - if (buf[6] != 0) { - verb("returned error %s\n", ue9_error(buf[6])); - return -1; + + if (buf[1] != 0xF9 || buf[2] != 0x14 || buf[3] != 0xC0) + { + verb ("bad command bytes\n"); + return -3; } - return 0; -} + if (buf[11] != 0) + { + verb ("stream error: %s\n", ue9_error (buf[11])); + return -4; + } -/* Stream data and pass it to the data callback. If callback returns - negative, stops reading and returns 0. Returns < 0 on error. */ -int ue9_stream_data(int fd, int channels, - ue9_stream_cb_t callback, void *context) -{ - int ret; - uint8_t buf[46]; - uint8_t packet = 0; - int channel = 0; - int i; - uint16_t data[channels]; - - for (;;) { - /* Receive data */ - ret = recv_all_timeout(fd, buf, 46, 0, & (struct timeval) - { .tv_sec = UE9_TIMEOUT }); - - /* Verify packet format */ - if (ret != 46) { - verb("short recv %d\n", (int)ret); - return -1; - } - - if (!ue9_verify_extended(buf, 46) || - !ue9_verify_normal(buf, 6)) { - verb("bad checksum\n"); - return -2; - } - - if (buf[1] != 0xF9 || buf[2] != 0x14 || buf[3] != 0xC0) { - verb("bad command bytes\n"); - return -3; - } - - if (buf[11] != 0) { - verb("stream error: %s\n", ue9_error(buf[11])); - return -4; - } - - /* Check for dropped packets. */ - if (buf[10] != packet) { - verb("expected packet %d, but received packet %d\n", - packet, buf[10]); - return -5; - } - packet++; - - /* Check comm processor backlog (up to 512 kB) */ - if (buf[45] & 0x80) { - verb("buffer overflow in CommBacklog, aborting\n"); - return -6; - } - if ((buf[45] & 0x7f) > 112) - debug("warning: CommBacklog is high (%d bytes)\n", - (buf[45] & 0x7f) * 4096); - - /* Check control processor backlog (up to 256 bytes). */ - if (buf[44] == 255) { - verb("ControlBacklog is maxed out, aborting\n"); - return -7; - } - if (buf[44] > 224) - debug("warning: ControlBacklog is high (%d bytes)\n", - buf[44]); - - /* Read samples from the buffer */ - for (i = 12; i <= 42; i += 2) { - data[channel++] = buf[i] + (buf[i+1] << 8); - if (channel < channels) - continue; - - /* Received a full scan, send to callback */ - channel = 0; - if ((*callback)(channels, data, context) < 0) { - /* We're done */ - return 0; - } - } + /* Check for dropped packets. */ + if (buf[10] != packet) + { + verb ("expected packet %d, but received packet %d\n", + packet, buf[10]); + return -5; + } + packet++; + + /* Check comm processor backlog (up to 512 kB) */ + if (buf[45] & 0x80) + { + verb ("buffer overflow in CommBacklog, aborting\n"); + return -6; + } + if ((buf[45] & 0x7f) > 112) + debug ("warning: CommBacklog is high (%d bytes)\n", + (buf[45] & 0x7f) * 4096); + + /* Check control processor backlog (up to 256 bytes). */ + if (buf[44] == 255) + { + verb ("ControlBacklog is maxed out, aborting\n"); + return -7; + } + if (buf[44] > 224) + debug ("warning: ControlBacklog is high (%d bytes)\n", buf[44]); + + /* Read samples from the buffer */ + for (i = 12; i <= 42; i += 2) + { + data[channel++] = buf[i] + (buf[i + 1] << 8); + if (channel < channels) + continue; + + /* Received a full scan, send to callback */ + channel = 0; + if ((*callback) (channels, data, context) < 0) + { + /* We're done */ + return 0; + } } + } } diff --git a/ue9.h b/ue9.h index b049cd3..173554e 100644 --- a/ue9.h +++ b/ue9.h @@ -16,56 +16,59 @@ #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,65 +80,65 @@ struct ue9ControlConfig { #define UE9_CHANNELS 14 /* 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); /* 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); +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 diff --git a/ue9error.c b/ue9error.c index d8e8f6d..a7cb0c9 100644 --- a/ue9error.c +++ b/ue9error.c @@ -1,51 +1,52 @@ #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]; } diff --git a/ue9error.h b/ue9error.h index 28198e6..43ebc40 100644 --- a/ue9error.h +++ b/ue9error.h @@ -44,6 +44,6 @@ extern const char *ue9_error_text[]; -const char *ue9_error(int errorcode); +const char *ue9_error (int errorcode); #endif