|
|
@@ -15,7 +15,6 @@ int hex = 0; |
|
|
|
int dec = 0; |
|
|
|
int screen = 0; |
|
|
|
int unprocessed = 0; |
|
|
|
int total = 0; |
|
|
|
|
|
|
|
int process(const uint8_t *buf, int len); |
|
|
|
|
|
|
@@ -27,15 +26,16 @@ int main(int argc, char *argv[]) |
|
|
|
int getopt_index; |
|
|
|
char buf[1024]; |
|
|
|
int len; |
|
|
|
int calibrate = 1; |
|
|
|
|
|
|
|
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' }, |
|
|
|
{ "no-calibrate", no_argument, NULL, 'n' }, |
|
|
|
{ "screen", no_argument, NULL, 's' }, |
|
|
|
{ "help", no_argument, NULL, 'h' }, |
|
|
|
{ 0, 0, 0, 0 } |
|
|
@@ -43,7 +43,7 @@ int main(int argc, char *argv[]) |
|
|
|
int help=0; |
|
|
|
char c; |
|
|
|
|
|
|
|
while ((c = getopt_long(argc, argv, "d:r:xDutsh?", |
|
|
|
while ((c = getopt_long(argc, argv, "d:r:xDunsh?", |
|
|
|
long_opts, &getopt_index)) != -1) { |
|
|
|
switch(c) |
|
|
|
{ |
|
|
@@ -62,12 +62,12 @@ int main(int argc, char *argv[]) |
|
|
|
case 'D': |
|
|
|
dec = 1; |
|
|
|
break; |
|
|
|
case 't': |
|
|
|
total = 1; |
|
|
|
break; |
|
|
|
case 'u': |
|
|
|
unprocessed = 1; |
|
|
|
break; |
|
|
|
case 'n': |
|
|
|
calibrate = 0; |
|
|
|
break; |
|
|
|
case 's': |
|
|
|
screen = 1; |
|
|
|
break; |
|
|
@@ -86,8 +86,8 @@ int main(int argc, char *argv[]) |
|
|
|
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, " -n, --no-calibrate skip calibration routine\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; |
|
|
|
} |
|
|
@@ -95,6 +95,11 @@ int main(int argc, char *argv[]) |
|
|
|
if ((fd = serial_open(device, rate)) == -1) |
|
|
|
err(1, "serial_open failed for %s", device); |
|
|
|
|
|
|
|
if (calibrate) { |
|
|
|
char c = 'c'; |
|
|
|
write(fd, &c, 1); |
|
|
|
} |
|
|
|
|
|
|
|
len = 0; |
|
|
|
while (1) { |
|
|
|
int processed, n; |
|
|
@@ -110,49 +115,64 @@ int main(int argc, char *argv[]) |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
uint16_t current_to_dac(float amps) |
|
|
|
int process_adc_dac(const uint8_t *buf) |
|
|
|
{ |
|
|
|
float tmp; |
|
|
|
uint16_t dacc; |
|
|
|
uint16_t dac, tmp; |
|
|
|
int16_t adc; |
|
|
|
int overflow; |
|
|
|
|
|
|
|
/* data OK? */ |
|
|
|
if ((buf[0] & 0xC0) != 0) |
|
|
|
return 0; |
|
|
|
|
|
|
|
tmp = 536.0 / 1.0 * amps + 32524; |
|
|
|
if (tmp < 0) |
|
|
|
tmp = 0; |
|
|
|
if (tmp > 65535) |
|
|
|
tmp = 65535; |
|
|
|
dacc = (uint16_t)(tmp + 0.5); |
|
|
|
/* extract */ |
|
|
|
|
|
|
|
if (buf[0] & 0x10) |
|
|
|
overflow = 1; |
|
|
|
else |
|
|
|
overflow = 0; |
|
|
|
|
|
|
|
tmp = ((buf[0] & 0x0F) << 8) | buf[1]; |
|
|
|
/* sign-extend ADC value */ |
|
|
|
if (tmp & 0x0800) |
|
|
|
tmp |= 0xF000; |
|
|
|
else |
|
|
|
tmp &= ~0xF000; |
|
|
|
adc = (int16_t)tmp; |
|
|
|
|
|
|
|
dac = (buf[2] << 8) | buf[3]; |
|
|
|
|
|
|
|
/* send it out */ |
|
|
|
if (hex) { |
|
|
|
printf("%04x %03x", dac, adc & 0x0FFF); |
|
|
|
} else if (dec) { |
|
|
|
printf("%d %d", dac, adc & 0x0FFF); |
|
|
|
} else { |
|
|
|
printf("DAC: %5d ADC: % 5d Total: xxx", dac, adc); |
|
|
|
if (overflow) |
|
|
|
printf(" **** adc may have clamped"); |
|
|
|
} |
|
|
|
|
|
|
|
if (screen) |
|
|
|
printf("\033[K\r"); |
|
|
|
else |
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
return dacc; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
/* Convert the DAC output value to an effective current in the measuring loop */ |
|
|
|
float dac_to_current(uint16_t dacv) |
|
|
|
int process_calibration(const uint8_t *buf) |
|
|
|
{ |
|
|
|
float amps; |
|
|
|
amps = ((float)dacv - 32524.0) * 1.0 / 536.0; |
|
|
|
return amps; |
|
|
|
} |
|
|
|
float f = *(float *)buf; |
|
|
|
|
|
|
|
float adc12_to_current(int16_t picv) |
|
|
|
{ |
|
|
|
float amps; |
|
|
|
printf("got calibration value: %f\n", f); |
|
|
|
|
|
|
|
if (picv < 0) |
|
|
|
picv = 0; |
|
|
|
if (picv > 2047) |
|
|
|
picv = 2047; |
|
|
|
|
|
|
|
amps = (picv - 1024.0) / 404.0; |
|
|
|
return amps; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
@@ -163,52 +183,26 @@ int process(const uint8_t *buf, int len) |
|
|
|
|
|
|
|
/* 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 */ |
|
|
|
for (; (n + 5) <= len; buf += 5, n += 5) { |
|
|
|
int ok = 0; |
|
|
|
switch (buf[0]) { |
|
|
|
case 0xA0: |
|
|
|
if (process_adc_dac(buf + 1)) ok = 1; |
|
|
|
break; |
|
|
|
case 0xA1: |
|
|
|
if (process_calibration(buf + 1)) ok = 1; |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
if (!ok) { |
|
|
|
/* 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; |
|
|
|
} |
|
|
|
|