]> sigrok.org Git - libsigrok.git/blobdiff - hardware/tekpower-dmm/protocol.c
tekpower-dmm: Generalize & first-class TP4000ZC driver.
[libsigrok.git] / hardware / tekpower-dmm / protocol.c
index 2d495f1a70ad6a15d7b8fe5f000dd50a7a1e9235..eabca4865c88f0053a2108586afdcd8a72daadb8 100644 (file)
@@ -2,6 +2,7 @@
  * This file is part of the sigrok project.
  *
  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
+ * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "libsigrok-internal.h"
 #include "protocol.h"
 
-/* User-defined FS9721_LP3 flag 'c2c1_10' means temperature on this DMM. */
-#define is_temperature info.is_c2c1_10
+static void log_dmm_packet(const uint8_t *buf)
+{
+       sr_dbg("DMM packet: %02x %02x %02x %02x %02x %02x %02x"
+              " %02x %02x %02x %02x %02x %02x %02x",
+              buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
+              buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]);
+}
 
-/* Now see what the value means, and pass that on. */
-static void fs9721_serial_handle_packet(const uint8_t *buf,
-                                       struct dev_context *devc)
+SR_PRIV void dmm_details_tp4000zc(struct sr_datafeed_analog *analog, void *info)
+{
+       struct fs9721_info *info_local;
+
+       info_local = (struct fs9721_info *)info;
+
+       /* User-defined FS9721_LP3 flag 'c2c1_10' means temperature. */
+       if (info_local->is_c2c1_10) {
+               analog->mq = SR_MQ_TEMPERATURE;
+               /* No Kelvin or Fahrenheit from the device, just Celsius. */
+               analog->unit = SR_UNIT_CELSIUS;
+       }
+}
+
+static void handle_packet(const uint8_t *buf, struct dev_context *devc,
+                         int dmm, void *info)
 {
        float floatval;
        struct sr_datafeed_packet packet;
        struct sr_datafeed_analog *analog;
-       struct fs9721_info info;
+
+       log_dmm_packet(buf);
 
        if (!(analog = g_try_malloc0(sizeof(struct sr_datafeed_analog)))) {
                sr_err("Analog packet malloc failed.");
                return;
        }
 
-       if (!(analog->data = g_try_malloc(sizeof(float)))) {
-               sr_err("Analog value malloc failed.");
-               g_free(analog);
-               return;
-       }
-
        analog->num_samples = 1;
        analog->mq = -1;
 
-       sr_fs9721_parse(buf, &floatval, analog, &info);
-       *analog->data = floatval;
+       dmms[dmm].packet_parse(buf, &floatval, analog, info);
+       analog->data = &floatval;
 
-       if (is_temperature) {
-               analog->mq = SR_MQ_TEMPERATURE;
-               /* No Kelvin or Fahrenheit from the device, just Celsius. */
-               analog->unit = SR_UNIT_CELSIUS;
-       }
+       dmms[dmm].dmm_details(analog, info);
 
        if (analog->mq != -1) {
                /* Got a measurement. */
@@ -69,17 +79,16 @@ static void fs9721_serial_handle_packet(const uint8_t *buf,
                devc->num_samples++;
        }
 
-       g_free(analog->data);
        g_free(analog);
 }
 
-static void handle_new_data(struct dev_context *devc, int fd)
+static void handle_new_data(struct dev_context *devc, int dmm, void *info)
 {
        int len, i, offset = 0;
 
        /* Try to get as much data as the buffer can hold. */
        len = DMM_BUFSIZE - devc->buflen;
-       len = serial_read(fd, devc->buf + devc->buflen, len);
+       len = serial_read(devc->serial, devc->buf + devc->buflen, len);
        if (len < 1) {
                sr_err("Serial port read error: %d.", len);
                return;
@@ -87,10 +96,10 @@ static void handle_new_data(struct dev_context *devc, int fd)
        devc->buflen += len;
 
        /* Now look for packets in that data. */
-       while ((devc->buflen - offset) >= FS9721_PACKET_SIZE) {
-               if (sr_fs9721_packet_valid(devc->buf + offset)) {
-                       fs9721_serial_handle_packet(devc->buf + offset, devc);
-                       offset += FS9721_PACKET_SIZE;
+       while ((devc->buflen - offset) >= dmms[dmm].packet_size) {
+               if (dmms[dmm].packet_valid(devc->buf + offset)) {
+                       handle_packet(devc->buf + offset, devc, dmm, info);
+                       offset += dmms[dmm].packet_size;
                } else {
                        offset++;
                }
@@ -102,11 +111,13 @@ static void handle_new_data(struct dev_context *devc, int fd)
        devc->buflen -= offset;
 }
 
-SR_PRIV int tekpower_dmm_receive_data(int fd, int revents, void *cb_data)
+static int receive_data(int fd, int revents, int dmm, void *info, void *cb_data)
 {
        struct sr_dev_inst *sdi;
        struct dev_context *devc;
 
+       (void)fd;
+
        if (!(sdi = cb_data))
                return TRUE;
 
@@ -115,13 +126,21 @@ SR_PRIV int tekpower_dmm_receive_data(int fd, int revents, void *cb_data)
 
        if (revents == G_IO_IN) {
                /* Serial data arrived. */
-               handle_new_data(devc, fd);
+               handle_new_data(devc, dmm, info);
        }
 
        if (devc->num_samples >= devc->limit_samples) {
+               sr_info("Requested number of samples reached, stopping.");
                sdi->driver->dev_acquisition_stop(sdi, cb_data);
                return TRUE;
        }
 
        return TRUE;
 }
+
+SR_PRIV int tekpower_tp4000zc_receive_data(int fd, int revents, void *cb_data)
+{
+       struct fs9721_info info;
+
+       return receive_data(fd, revents, TEKPOWER_TP4000ZC, &info, cb_data);
+}