From e9530e6b1e909e6c9c37e62380c2294c305b7cbc Mon Sep 17 00:00:00 2001 From: jim Date: Wed, 14 Oct 2009 21:05:24 +0000 Subject: [PATCH] cleanup git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@7987 ddd99763-3ecb-0310-9145-efcb8ce7c51f --- pc/dctest.c | 189 ++++++++++++++++++++++++++++++++++++++++++++-------- pc/test.txt | 6 ++ 2 files changed, 167 insertions(+), 28 deletions(-) create mode 100644 pc/test.txt diff --git a/pc/dctest.c b/pc/dctest.c index 484ed8a..5fcbd7a 100644 --- a/pc/dctest.c +++ b/pc/dctest.c @@ -15,13 +15,14 @@ #include "zoom.h" #include "math.h" #include +#include #define info(x...) fprintf(stderr,x) -void dctest(int zoom, int gpib); +static void dctest(int zoom, int gpib); int g_quit = 0; -void handle_sig(int sig) { g_quit = 1; } +static void handle_sig(int sig) { g_quit = 1; } int main(int argc, char *argv[]) { @@ -95,72 +96,204 @@ int main(int argc, char *argv[]) return 0; } +struct keithley_t { + pthread_mutex_t mutex; + double desired; + double actual; + int stable; +}; + struct threadinfo_t { int quit_flag; int fd; + float calibration; + struct keithley_t k; }; -void *read_data(void *arg) +int process_adc_dac(const uint8_t *buf, struct threadinfo_t *ti) +{ + uint16_t dac, tmp; + int16_t adc; + int overflow; + double idesired, iactual; + int stable; + + /* data OK? */ + if ((buf[0] & 0xC0) != 0) return 0; + + /* extract */ + overflow = (buf[0] & 0x10) ? 1 : 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]; + + /* get keithley data */ + pthread_mutex_lock(&ti->k.mutex); + idesired = ti->k.desired; + iactual = ti->k.actual; + stable = ti->k.stable; + pthread_mutex_unlock(&ti->k.mutex); + + /* write it out */ + printf("%d %.8f %.8f %.8f %5d %5d %d\n", + stable, + idesired, + iactual, + ti->calibration, + dac, + adc, + overflow); + + return 1; +} + +static int process_calibration(const uint8_t *buf, struct threadinfo_t *ti) +{ + float f = *(float *)buf; + ti->calibration = f; + info("new calibration value: %.8f\n", ti->calibration); + return 1; +} + +static int process(const uint8_t *buf, int len, struct threadinfo_t *ti) +{ + int n = 0; + + /* Process blocks */ + retry: + for (; (n + 5) <= len; buf += 5, n += 5) { + int ok = 0; + switch (buf[0]) { + case 0xA0: + if (process_adc_dac(buf + 1, ti)) ok = 1; + break; + case 0xA1: + if (process_calibration(buf + 1, ti)) ok = 1; + break; + default: + break; + } + if (!ok) { + /* badly formed data; eat one byte and retry */ + info("throwing away 0x%02x '%c'\n", buf[0], isprint(buf[0]) ? buf[0] : '.'); + buf++; + n++; + goto retry; + } + } + + return n; +} + +static void *read_data(void *arg) { struct threadinfo_t *ti = (struct threadinfo_t *)arg; + char buf[1024]; + int len; - printf("ti->fd=%d\n", ti->fd); + /* read data in a loop. Use saferead_timeout here so we can + notice quit_flag before too long. */ + len = 0; while (!ti->quit_flag) { - printf("thread sleeping\n"); - sleep(1); + int processed, n; + n = saferead_timeout(ti->fd, + buf + len, + sizeof(buf) - len, + 1000); + if (n < 0) + err(1, "read"); + if (n == 0) + continue; + len += n; + processed = process((uint8_t *) buf, len, ti); + memmove(buf, buf + processed, len - processed); + len -= processed; } - printf("thread quitting\n"); + info("read thread quitting\n"); return NULL; } -void dctest(int zoom, int gpib) +/* change keithley and update keithley_t structure with locking */ +static int keithley_change(int gpib, double desired, struct keithley_t *k) +{ + double actual; + + pthread_mutex_lock(&k->mutex); + k->stable = 0; + k->desired = desired; + pthread_mutex_unlock(&k->mutex); + + if (keithley_current(gpib, desired) < 0) + return -1; + + actual = keithley_read(gpib); + if (isnan(actual)) + return -1; + + pthread_mutex_lock(&k->mutex); + k->actual = actual; + pthread_mutex_unlock(&k->mutex); + return 0; +} + +static void dctest(int zoom, int gpib) { -// double idesired, iactual; -// int i; -// int zero; -// int dac[ZOOM_SWEEP_COUNT]; -// int adc[ZOOM_SWEEP_COUNT]; pthread_t thread; - struct threadinfo_t threadinfo; + struct threadinfo_t ti; /* Do a calibration with Keithley off */ info("Triggering calibration\n"); zoomrun_trigger_calibrate(zoom); - usleep(500000); + usleep(1000000); - printf("zoom=%d gpib=%d\n", zoom,gpib); - /* Init Keithley */ info("Initializing GPIB\n"); -// if (gpib_init(gpib) < 0) { info("failed\n"); goto out1; } + if (gpib_init(gpib) < 0) { info("failed\n"); goto out1; } info("Initializing Keithley\n"); -// if (gpib_addr(gpib, 24) < 0) { info("failed\n"); goto out1; } -// if (keithley_init(gpib) < 0) { info("failed\n"); goto out2; } -// if (keithley_current(gpib, 0) < 0) { info("failed\n"); goto out2; } -// if (isnan(keithley_read(gpib))) { info("failed\n"); goto out2; } + if (gpib_addr(gpib, 24) < 0) { info("failed\n"); goto out1; } + if (keithley_init(gpib) < 0) { info("failed\n"); goto out2; } + if (keithley_current(gpib, 0) < 0) { info("failed\n"); goto out2; } + if (isnan(keithley_read(gpib))) { info("failed\n"); goto out2; } /* Start the thread that reads and dumps data */ info("Spawning thread\n"); - threadinfo.quit_flag = 0; - threadinfo.fd = zoom; - if (pthread_create(&thread, NULL, read_data, &threadinfo) != 0) { + if (pthread_mutex_init(&ti.k.mutex, NULL) != 0) { + info("failed\n"); + goto out2; + } + ti.calibration = 1.0; + ti.k.desired = 0; + ti.k.actual = 0; + ti.k.stable = 0; + ti.quit_flag = 0; + ti.fd = zoom; + if (pthread_create(&thread, NULL, read_data, &ti) != 0) { info("failed\n"); goto out2; } /* Do another calibration now */ info("Triggering calibration\n"); + if (keithley_change(gpib, 0.0, &ti.k) < 0) { info("failed\n"); goto out3; } zoomrun_trigger_calibrate(zoom); + usleep(1000000); /* Change Keithley values */ while (!g_quit) { - info("sleeping\n"); sleep(1); } - printf("quitting\n"); + printf("main thread quitting\n"); - threadinfo.quit_flag = 1; +out3: + ti.quit_flag = 1; pthread_join(thread, NULL); out2: keithley_off(gpib); diff --git a/pc/test.txt b/pc/test.txt new file mode 100644 index 0000000..ed33ad7 --- /dev/null +++ b/pc/test.txt @@ -0,0 +1,6 @@ +Window is something like +- 2A equivalent + +- Run Zoom NILM in "normal" mode +- Switch Keithley around randomly: + 1 big jump (anywhere in 50A window) + 1000 small jumps (within a 1A window)