|
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <errno.h>
- #include <unistd.h>
- #include <getopt.h>
- #include <stdint.h>
- #include <syslog.h>
- #include <err.h>
- #include <linux/serial.h>
- #include "serial-util.h"
- #include <string.h>
-
- int hex = 0;
- int dec = 0;
- int screen = 0;
- int unprocessed = 0;
- int total = 0;
-
- int process(const uint8_t *buf, int len);
-
- int main(int argc, char *argv[])
- {
- char *device=strdup("/dev/ttyUSB0");
- int rate=500000;
- int fd;
- int getopt_index;
- char buf[1024];
- int len;
-
- static struct option long_opts[] = {
- { "device", required_argument, NULL, 'd' },
- { "rate", required_argument, NULL, 'r' },
- { "hex", no_argument, NULL, 'x' },
- { "dec", no_argument, NULL, 'D' },
- { "total", no_argument, NULL, 't' },
- { "raw", no_argument, NULL, 'R' },
- { "unprocessed", no_argument, NULL, 'u' },
- { "screen", no_argument, NULL, 's' },
- { "help", no_argument, NULL, 'h' },
- { 0, 0, 0, 0 }
- };
- int help=0;
- char c;
-
- while ((c = getopt_long(argc, argv, "d:r:xDutsh?",
- long_opts, &getopt_index)) != -1) {
- switch(c)
- {
- case 'd':
- free(device);
- device = strdup(optarg);
- break;
- case 'r':
- rate = atoi(optarg);
- if(rate == 0)
- errx(1, "invalid rate: %s",optarg);
- break;
- case 'x':
- hex = 1;
- break;
- case 'D':
- dec = 1;
- break;
- case 't':
- total = 1;
- break;
- case 'u':
- unprocessed = 1;
- break;
- case 's':
- screen = 1;
- break;
- case 'h':
- case '?':
- default:
- help = 1;
- break;
- }
- }
-
- if (help) {
- fprintf(stderr, "Zoom Nilm Client\n");
- fprintf(stderr, "usage: %s [options]\n\n", *argv);
- fprintf(stderr, " -d, --device %-14s serial port\n", device);
- fprintf(stderr, " -r, --rate %-16d baud rate\n", rate);
- fprintf(stderr, " -x, --hex hex out\n");
- fprintf(stderr, " -u, --unprocessed dump raw unprocessed data\n");
- fprintf(stderr, " -s, --screen send \\r instead of \\n\n");
- fprintf(stderr, " -t, --total just display total amps\n");
- fprintf(stderr, " -h, --help this cruft\n");
- return 1;
- }
-
- if ((fd = serial_open(device, rate)) == -1)
- err(1, "serial_open failed for %s", device);
-
- len = 0;
- while (1) {
- int processed, n;
- n = read(fd, buf + len, sizeof(buf) - len);
- if (n <= 0)
- err(1, "read");
- len += n;
- processed = process((uint8_t *) buf, len);
- memmove(buf, buf + processed, len - processed);
- len -= processed;
- }
-
- return 1;
- }
-
- uint16_t current_to_dac(float amps)
- {
- float tmp;
- uint16_t dacc;
-
- tmp = 536.0 / 1.0 * amps + 32524;
- if (tmp < 0)
- tmp = 0;
- if (tmp > 65535)
- tmp = 65535;
- dacc = (uint16_t)(tmp + 0.5);
-
- return dacc;
- }
-
- /* Convert the DAC output value to an effective current in the measuring loop */
- float dac_to_current(uint16_t dacv)
- {
- float amps;
- amps = ((float)dacv - 32524.0) * 1.0 / 536.0;
- return amps;
- }
-
- float adc12_to_current(int16_t picv)
- {
- float amps;
-
- if (picv < 0)
- picv = 0;
- if (picv > 2047)
- picv = 2047;
-
- amps = (picv - 1024.0) / 404.0;
- return amps;
- }
-
- int process(const uint8_t *buf, int len)
- {
- int n = 0;
- uint16_t dac, tmp;
- int16_t adc;
- float idac = dac_to_current(dac);
- float iadc = adc12_to_current(adc);
-
- if (unprocessed) {
- n = write(fileno(stdout), buf, len);
- if (n >= 0)
- return n;
- return 0;
- }
-
- /* Process blocks */
- retry:
- for (; (n + 4) <= len; buf += 4, n += 4) {
- if ((!buf[0] & 0x80) ||
- (buf[1] & 0x80) ||
- (buf[2] & 0x80) ||
- (buf[3] & 0x80)) {
- /* badly formed data, eat one byte and retry */
- buf++;
- n++;
- goto retry;
- }
-
- tmp = ((buf[0] & 0x7f) << 5) |
- ((buf[1] & 0x7c) >> 2);
- dac = ((buf[1] & 0x03) << 14) |
- (buf[2] << 7) | buf[3];
-
- /* sign-extend ADC value */
- if (tmp & 0x0800)
- tmp |= 0xF000;
- else
- tmp &= ~0xF000;
- adc = (int16_t)tmp;
-
- /* compute floating-point currents */
- idac = dac_to_current(dac);
- iadc = adc12_to_current(adc);
-
- /* send it out */
- if (hex) {
- printf("%04x %03x", dac, adc & 0x0FFF);
- } else if (dec) {
- printf("%d %d", dac, adc & 0x0FFF);
- } else if (total) {
- printf("%.6f", idac - iadc);
- } else {
- printf("DAC: %5d (% f) ADC: % 5d (% f) Total: % 10.6f amps",
- dac, idac, (int16_t)adc, iadc, idac - iadc);
-
- if (adc < 0 || adc >= 2047)
- printf(" **** adc limit");
- }
-
- if (screen)
- printf("\033[K\r");
- else
- printf("\n");
- }
- return n;
- }
|