]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/gmc-mh-1x-2x/protocol.c
gmc-mh-1x-2x: Use software limits helpers
[libsigrok.git] / src / hardware / gmc-mh-1x-2x / protocol.c
index dc1a683ed37d5453cab9c95cf668dc917dd14dad..4758593d5aa4a389f8652764651e3fa1c1012458 100644 (file)
  *  @internal
  */
 
+#include <config.h>
 #include <math.h>
 #include <string.h>
 #include "protocol.h"
 
 /* Internal Headers */
-static guchar calc_chksum_14(guchardta);
+static guchar calc_chksum_14(guchar *dta);
 static int chk_msg14(struct sr_dev_inst *sdi);
 
 /** Set or clear flags in devc->mqflags. */
@@ -257,7 +258,7 @@ static void decode_ctmv_18(uint8_t ctmv, struct dev_context *devc)
 /**
  * Decode range/sign/acdc byte special chars, Metrahit 18.
  *
- * @param[in] rs Rance/sign byte.
+ * @param[in] rs Range/sign byte.
  */
 static void decode_rs_18(uint8_t rs, struct dev_context *devc)
 {
@@ -282,8 +283,6 @@ static void decode_rs_18(uint8_t rs, struct dev_context *devc)
                         * identify relative mode.
                         */
                }
-               else if (devc->vmains_29S)
-                       devc->scale *= pow(10.0, range - 2);
                else
                        devc->scale *= pow(10.0, range - 5);
                break;
@@ -346,8 +345,8 @@ static void decode_spc_18(uint8_t spc, struct dev_context *devc)
  */
 static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
 {
-       if ((ctmv > 0x1c) || (!devc)) {
-               sr_err("decode_ctmv_2x(%d): invalid param(s)!", ctmv);
+       if ((ctmv > 0x20) || (!devc)) {
+               sr_err("decode_ctmv_2x(0x%x): invalid param(s)!", ctmv);
                return;
        }
 
@@ -373,6 +372,7 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
        case 0x04: /* 00100 mA DC */
        case 0x05: /* 00101 mA AC+DC */
                devc->scale1000 = -1;
+               /* Fall through! */
        case 0x06: /* 00110 A DC */
        case 0x07: /* 00111 A AC+DC */
                devc->mq = SR_MQ_CURRENT;
@@ -409,11 +409,14 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
                        devc->mqflags |= SR_MQFLAG_DC;
                break;
        case 0x0d: /* 01101 W on power, mA range (29S only) */
-               devc->scale *= 0.001;
+               devc->scale *= 0.1;
                /* Fall through! */
        case 0x0e: /* 01110 W on power, A range (29S only) */
+               devc->scale *= 0.1;
+               devc->scale1000 = -1;
                devc->mq = SR_MQ_POWER;
                devc->unit = SR_UNIT_WATT;
+               devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS);
                break;
        case 0x0f: /* 01111 Diode */
        case 0x10: /* 10000 Diode with buzzer (actually cont. with voltage) */
@@ -437,7 +440,8 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
                devc->unit = SR_UNIT_CELSIUS;
                /* This can be Fahrenheit. That is detected by range=4 later. */
                break;
-       /* 0x13 10011, 0x14 10100 unsed */
+       /* 0x13 10011 unused */
+       /* 0x14 10100 unused */
        case 0x15: /* 10101 Press (29S only) */
                /* TODO: What does that mean? Possibly phase shift?
                   Then we need a unit/flag for it. */
@@ -452,8 +456,7 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
        case 0x17: /* 10111 TRMS V on mains (29S only) */
                devc->mq = SR_MQ_VOLTAGE;
                devc->unit = SR_UNIT_VOLT;
-               devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_RMS);
-               devc->vmains_29S = TRUE;
+               devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS);
                break;
        case 0x18: /* 11000 Counter (zero crossings of a signal) */
                devc->mq = SR_MQ_VOLTAGE;
@@ -468,11 +471,11 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
                if (ctmv <= 0x19)
                        devc->mqflags |= SR_MQFLAG_DC;
                break;
-       case 0x1b: /* 11011 pulse on mains (29S only) */
-               /* TODO: No unit or flags for this yet! */
-               devc->mq = SR_MQ_VOLTAGE;
-               devc->unit = SR_UNIT_UNITLESS;
-               devc->mqflags |= SR_MQFLAG_AC;
+       case 0x1b: /* 11011 Milliamperes in power mode (29S only); error in docs, "pulse on mains" */
+               devc->mq = SR_MQ_CURRENT;
+               devc->unit = SR_UNIT_AMPERE;
+               devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS);
+               devc->scale1000 = -1;
                break;
        case 0x1c: /* 11100 dropout on mains (29S only) */
                /* TODO: No unit or flags for this yet! */
@@ -480,14 +483,20 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
                devc->unit = SR_UNIT_UNITLESS;
                devc->mqflags |= SR_MQFLAG_AC;
                break;
-       case 0x1f: /* 11111 Undocumented: 25S in stopwatch mode.
+       case 0x1d: /* 11101 Voltage in power mode (29S); undocumented! */
+               devc->mq = SR_MQ_VOLTAGE;
+               devc->unit = SR_UNIT_VOLT;
+               devc->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS);
+               break;
+       /* 0x1e: 11110 Undocumented */
+       case 0x1f: /* 11111 25S in stopwatch mode; undocumented!
                        The value is voltage, not time, so treat it such. */
                devc->mq = SR_MQ_VOLTAGE;
                devc->unit = SR_UNIT_VOLT;
                devc->mqflags |= SR_MQFLAG_DC;
                break;
-       case 0x20: /* 100000 Undocumented: 25S in event count mode.
-               Value is 0 anyway. */
+       case 0x20: /* 100000 25S in event count mode; undocumented!
+                       Value is 0 anyway. */
                devc->mq = SR_MQ_VOLTAGE;
                devc->unit = SR_UNIT_UNITLESS;
                break;
@@ -517,8 +526,6 @@ static void decode_rs_2x(uint8_t rs, struct dev_context *devc)
        case SR_MQ_VOLTAGE:
                if (devc->unit == SR_UNIT_DECIBEL_VOLT)
                        devc->scale *= pow(10.0, -3);
-               else if (devc->vmains_29S)
-                       devc->scale *= pow(10.0, range - 2);
                else
                        devc->scale *= pow(10.0, range - 6);
                break;
@@ -561,23 +568,28 @@ static void decode_rs_2x_TR2(uint8_t rs, struct dev_context *devc)
        switch (devc->mq) {
        case SR_MQ_CURRENT:
                if (devc->scale1000 == -1) /* mA */
-                       switch(range) {
-                       case 0: case 1: /* 100, 300 µA */
+                       switch (range) {
+                       case 0:
+                       case 1: /* 100, 300 µA */
                                devc->scale *= pow(10.0, -6);
                                break;
-                       case 2: case 3: /* 1, 3 mA */
+                       case 2:
+                       case 3: /* 1, 3 mA */
                                devc->scale *= pow(10.0, -5);
                                break;
-                       case 4: case 5: /* 10, 30 mA */
+                       case 4:
+                       case 5: /* 10, 30 mA */
                                devc->scale *= pow(10.0, -4);
                                break;
-                       case 6: case 7: /* 100, 300 mA */
+                       case 6:
+                       case 7: /* 100, 300 mA */
                                devc->scale *= pow(10.0, -3);
                                break;
                        }
                else /* A */
-                       switch(range) {
-                       case 0: case 1: /* 1, 3 A */
+                       switch (range) {
+                       case 0:
+                       case 1: /* 1, 3 A */
                                devc->scale *= pow(10.0, -5);
                                break;
                        case 2: /* 10 A */
@@ -596,7 +608,6 @@ static void decode_rs_2x_TR2(uint8_t rs, struct dev_context *devc)
                devc->scale *= -1.0;
 }
 
-
 /**
  * Decode special chars (Metrahit 2x).
  *
@@ -634,7 +645,6 @@ static void clean_ctmv_rs_v(struct dev_context *devc)
        devc->unit = 0;
        devc->mqflags = 0;
        devc->scale1000 = 0;
-       devc->vmains_29S = FALSE;
        clean_rs_v(devc);
 }
 
@@ -642,12 +652,12 @@ static void clean_ctmv_rs_v(struct dev_context *devc)
 static void send_value(struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
-       struct sr_datafeed_analog analog;
+       struct sr_datafeed_analog_old analog;
        struct sr_datafeed_packet packet;
 
        devc = sdi->priv;
 
-       memset(&analog, 0, sizeof(analog));
+       memset(&analog, 0, sizeof(struct sr_datafeed_analog_old));
        analog.channels = sdi->channels;
        analog.num_samples = 1;
        analog.mq = devc->mq;
@@ -655,12 +665,12 @@ static void send_value(struct sr_dev_inst *sdi)
        analog.mqflags = devc->mqflags;
        analog.data = &devc->value;
 
-       memset(&packet, 0, sizeof(packet));
-       packet.type = SR_DF_ANALOG;
+       memset(&packet, 0, sizeof(struct sr_datafeed_packet));
+       packet.type = SR_DF_ANALOG_OLD;
        packet.payload = &analog;
-       sr_session_send(devc->cb_data, &packet);
+       sr_session_send(sdi, &packet);
 
-       devc->num_samples++;
+       sr_sw_limits_update_samples_read(&devc->limits, 1);
 }
 
 /** Process 6-byte data message, Metrahit 1x/2x send mode. */
@@ -847,7 +857,7 @@ static void process_msg_inf_13(struct sr_dev_inst *sdi)
                devc->value += pow(10.0, cnt) * dgt;
        }
        sr_spew("process_msg_inf_13() value=%f scale=%f scale1000=%d mq=%d "
-               "unit=%d mqflags=0x%02llx", devc->value, devc->scale,
+               "unit=%d mqflags=0x%02" PRIx64, devc->value, devc->scale,
                devc->scale1000, devc->mq, devc->unit, devc->mqflags);
        if (devc->value != NAN)
                devc->value *= devc->scale * pow(1000.0, devc->scale1000);
@@ -863,7 +873,7 @@ static void process_msg_inf_13(struct sr_dev_inst *sdi)
  *  @param buf Pointer to array of 14 data bytes.
  *  @param[in] raw Write only data bytes, no interpretation.
  */
-void dump_msg14(guchar* buf, gboolean raw)
+static void dump_msg14(guchar *buf, gboolean raw)
 {
        if (!buf)
                return;
@@ -887,11 +897,11 @@ void dump_msg14(guchar* buf, gboolean raw)
  *  @param[in] dta Pointer to array of 13 data bytes.
  *  @return Checksum.
  */
-static guchar calc_chksum_14(guchardta)
+static guchar calc_chksum_14(guchar *dta)
 {
        guchar cnt, chs;
 
-       for (chs = 0, cnt = 0; cnt < 13; cnt++)
+       for (chs = 0, cnt = 0; cnt < (GMC_REPLY_SIZE - 1); cnt++)
                chs += dta[cnt];
 
        return (64 - chs) & MASK_6BITS;
@@ -928,7 +938,6 @@ static int chk_msg14(struct sr_dev_inst *sdi)
        }
 
        if (devc->buf[1] == 0) { /* Error msg from device! */
-               retc = SR_ERR_ARG;
                switch (devc->buf[2]) {
                case 1: /* Not used */
                        sr_err("Device: Illegal error code!");
@@ -993,7 +1002,7 @@ SR_PRIV int process_msg14(struct sr_dev_inst *sdi)
                sr_spew("Cmd %d unimplemented!", devc->buf[3]);
                break;
        case 3: /* Read firmware version and status */
-               sr_spew("Cmd 3, Read firmware and status", devc->buf[3]);
+               sr_spew("Cmd 3, Read firmware and status");
                switch (devc->cmd_idx) {
                case 0:
                        devc->fw_ver_maj = devc->buf[5];
@@ -1064,7 +1073,7 @@ SR_PRIV int process_msg14(struct sr_dev_inst *sdi)
                        devc->value += pow(10.0, cnt) * dgt;
                }
                sr_spew("process_msg14() value=%f scale=%f scale1000=%d mq=%d "
-                       "unit=%d mqflags=0x%02llx", devc->value, devc->scale,
+                       "unit=%d mqflags=0x%02" PRIx64, devc->value, devc->scale,
                        devc->scale1000, devc->mq, devc->unit, devc->mqflags);
                if (devc->value != NAN)
                        devc->value *= devc->scale * pow(1000.0, devc->scale1000);
@@ -1088,7 +1097,6 @@ SR_PRIV int gmc_mh_1x_2x_receive_data(int fd, int revents, void *cb_data)
        struct sr_serial_dev_inst *serial;
        uint8_t buf, msgt;
        int len;
-       gdouble elapsed_s;
 
        (void)fd;
 
@@ -1102,7 +1110,7 @@ SR_PRIV int gmc_mh_1x_2x_receive_data(int fd, int revents, void *cb_data)
 
        if (revents == G_IO_IN) { /* Serial data arrived. */
                while (GMC_BUFSIZE - devc->buflen - 1 > 0) {
-                       len = serial_read(serial, devc->buf + devc->buflen, 1);
+                       len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1);
                        if (len < 1)
                                break;
                        buf = *(devc->buf + devc->buflen);
@@ -1162,15 +1170,8 @@ SR_PRIV int gmc_mh_1x_2x_receive_data(int fd, int revents, void *cb_data)
                }
        }
 
-       /* If number of samples or time limit reached, stop acquisition. */
-       if (devc->limit_samples && (devc->num_samples >= devc->limit_samples))
-               sdi->driver->dev_acquisition_stop(sdi, cb_data);
-
-       if (devc->limit_msec) {
-               elapsed_s = g_timer_elapsed(devc->elapsed_msec, NULL);
-               if ((elapsed_s * 1000) >= devc->limit_msec)
-                       sdi->driver->dev_acquisition_stop(sdi, cb_data);
-       }
+       if (sr_sw_limits_check(&devc->limits))
+               sdi->driver->dev_acquisition_stop(sdi);
 
        return TRUE;
 }
@@ -1182,7 +1183,6 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data)
        struct sr_serial_dev_inst *serial;
        uint8_t buf;
        int len;
-       gdouble elapsed_s;
 
        (void)fd;
 
@@ -1196,7 +1196,7 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data)
 
        if (revents == G_IO_IN) { /* Serial data arrived. */
                while (GMC_BUFSIZE - devc->buflen - 1 > 0) {
-                       len = serial_read(serial, devc->buf + devc->buflen, 1);
+                       len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1);
                        if (len < 1)
                                break;
                        buf = *(devc->buf + devc->buflen);
@@ -1213,21 +1213,14 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data)
                }
        }
 
-       /* If number of samples or time limit reached, stop acquisition. */
-       if (devc->limit_samples && (devc->num_samples >= devc->limit_samples))
-               sdi->driver->dev_acquisition_stop(sdi, cb_data);
-
-       if (devc->limit_msec) {
-               elapsed_s = g_timer_elapsed(devc->elapsed_msec, NULL);
-               if ((elapsed_s * 1000) >= devc->limit_msec)
-                       sdi->driver->dev_acquisition_stop(sdi, cb_data);
-       }
+       if (sr_sw_limits_check(&devc->limits))
+               sdi->driver->dev_acquisition_stop(sdi);
 
        /* Request next data set, if required */
        if (sdi->status == SR_ST_ACTIVE) {
                if (devc->response_pending) {
                        gint64 elapsed_us = g_get_monotonic_time() - devc->req_sent_at;
-                       if (elapsed_us > 1*1000*1000) /* Timeout! */
+                       if (elapsed_us > (1 * 1000 * 1000)) /* Timeout! */
                                devc->response_pending = FALSE;
                }
                if (!devc->response_pending) {
@@ -1252,9 +1245,9 @@ SR_PRIV int gmc_mh_2x_receive_data(int fd, int revents, void *cb_data)
  *  @param[in] params Further parameters (9 bytes)
  *  @param[out] buf Buffer to create msg in (42 bytes).
  */
-void create_cmd_14(guchar addr, guchar func, guchar* params, guchar* buf)
+static void create_cmd_14(guchar addr, guchar func, guchar *params, guchar *buf)
 {
-       uint8_t dta[14];        /* Unencoded message */
+       uint8_t dta[GMC_REPLY_SIZE];    /* Unencoded message */
        int cnt;
 
        if (!params || !buf)
@@ -1270,17 +1263,17 @@ void create_cmd_14(guchar addr, guchar func, guchar* params, guchar* buf)
 
        /* 4-12: Copy further parameters */
        for (cnt = 0; cnt < 9; cnt++)
-               dta[cnt+4] = (params[cnt] & MASK_6BITS);
+               dta[cnt + 4] = (params[cnt] & MASK_6BITS);
 
        /* 13: Checksum (b complement) */
        dta[13] = calc_chksum_14(dta);
 
        /* The whole message is packed into 3 bytes per byte now (lower 6 bits only) the most
         * peculiar way I have ever seen. Possibly to improve IR communication? */
-       for (cnt = 0; cnt < 14; cnt++) {
-               buf[3*cnt] = (dta[cnt] & 0x01 ? 0x0f : 0) | (dta[cnt] & 0x02 ? 0xf0 : 0);
-               buf[3*cnt + 1] = (dta[cnt] & 0x04 ? 0x0f : 0) | (dta[cnt] & 0x08 ? 0xf0 : 0);
-               buf[3*cnt + 2] = (dta[cnt] & 0x10 ? 0x0f : 0) | (dta[cnt] & 0x20 ? 0xf0 : 0);
+       for (cnt = 0; cnt < GMC_REPLY_SIZE; cnt++) {
+               buf[(3 * cnt) + 0] = (dta[cnt] & 0x01 ? 0x0f : 0) | (dta[cnt] & 0x02 ? 0xf0 : 0);
+               buf[(3 * cnt) + 1] = (dta[cnt] & 0x04 ? 0x0f : 0) | (dta[cnt] & 0x08 ? 0xf0 : 0);
+               buf[(3 * cnt) + 2] = (dta[cnt] & 0x10 ? 0x0f : 0) | (dta[cnt] & 0x20 ? 0xf0 : 0);
        }
 }
 
@@ -1302,7 +1295,8 @@ int req_meas14(const struct sr_dev_inst *sdi)
        devc->cmd_idx = 0;
        create_cmd_14(devc->addr, 8, params, msg);
        devc->req_sent_at = g_get_monotonic_time();
-       if (serial_write(serial, msg, sizeof(msg)) == -1) {
+       if (serial_write_blocking(serial, msg, sizeof(msg),
+                       serial_timeout(serial, sizeof(msg))) < (int)sizeof(msg)) {
                return SR_ERR;
        }
 
@@ -1331,21 +1325,25 @@ int req_stat14(const struct sr_dev_inst *sdi, gboolean power_on)
 
        if (power_on) {
                sr_info("Write some data and wait 3s to turn on powered off device...");
-               if (serial_write(serial, msg, sizeof(msg)) < 0)
+               if (serial_write_blocking(serial, msg, sizeof(msg),
+                               serial_timeout(serial, sizeof(msg))) < 0)
                        return SR_ERR;
-               g_usleep(1*1000*1000);
-               if (serial_write(serial, msg, sizeof(msg)) < 0)
+               g_usleep(1 * 1000 * 1000);
+               if (serial_write_blocking(serial, msg, sizeof(msg),
+                               serial_timeout(serial, sizeof(msg))) < 0)
                        return SR_ERR;
-               g_usleep(1*1000*1000);
-               if (serial_write(serial, msg, sizeof(msg)) < 0)
+               g_usleep(1 * 1000 * 1000);
+               if (serial_write_blocking(serial, msg, sizeof(msg),
+                               serial_timeout(serial, sizeof(msg))) < 0)
                        return SR_ERR;
-               g_usleep(1*1000*1000);
+               g_usleep(1 * 1000 * 1000);
                serial_flush(serial);
        }
 
        /* Write message and wait for reply */
        devc->req_sent_at = g_get_monotonic_time();
-       if (serial_write(serial, msg, sizeof(msg)) == -1) {
+       if (serial_write_blocking(serial, msg, sizeof(msg),
+                       serial_timeout(serial, sizeof(msg))) < (int)sizeof(msg)) {
                return SR_ERR;
        }
 
@@ -1366,7 +1364,7 @@ SR_PRIV int gmc_decode_model_sm(uint8_t mcode)
                return METRAHIT_NONE;
        }
 
-       switch(mcode) {
+       switch (mcode) {
        case 0x04: /* 0100b */
                return METRAHIT_12S;
        case 0x08: /* 1000b */
@@ -1492,11 +1490,9 @@ SR_PRIV const char *gmc_model_str(enum model mcode)
        }
 }
 
-
-/** @copydoc sr_dev_driver.config_set
- */
-SR_PRIV int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
-                      const struct sr_channel_group *cg)
+/** @copydoc sr_dev_driver.config_set */
+SR_PRIV int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
+               const struct sr_channel_group *cg)
 {
        struct dev_context *devc;
        uint8_t params[9];
@@ -1507,10 +1503,7 @@ SR_PRIV int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
        if (sdi->status != SR_ST_ACTIVE)
                return SR_ERR_DEV_CLOSED;
 
-       if (!(devc = sdi->priv)) {
-               sr_err("sdi->priv was NULL.");
-               return SR_ERR_BUG;
-       }
+       devc = sdi->priv;
 
        switch (key) {
        case SR_CONF_POWER_OFF:
@@ -1524,25 +1517,15 @@ SR_PRIV int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
                params[0] = 5;
                params[1] = 5;
                create_cmd_14(devc->addr, 6, params, msg);
-               if (serial_write(sdi->conn, msg, sizeof(msg)) == -1)
+               if (serial_write_blocking(sdi->conn, msg, sizeof(msg),
+                               serial_timeout(sdi->conn, sizeof(msg))) < 0)
                        return SR_ERR;
                else
-                       g_usleep(2000000); /* Wait to ensure transfer before interface switched off. */
-               break;
-       case SR_CONF_LIMIT_MSEC:
-               if (g_variant_get_uint64(data) == 0) {
-                       sr_err("LIMIT_MSEC can't be 0.");
-                       return SR_ERR;
-               }
-               devc->limit_msec = g_variant_get_uint64(data);
-               sr_dbg("Setting time limit to %" PRIu64 "ms.",
-                       devc->limit_msec);
+                       g_usleep(2 * 1000 * 1000); /* Wait to ensure transfer before interface switched off. */
                break;
        case SR_CONF_LIMIT_SAMPLES:
-               devc->limit_samples = g_variant_get_uint64(data);
-               sr_dbg("Setting sample limit to %" PRIu64 ".",
-                       devc->limit_samples);
-               break;
+       case SR_CONF_LIMIT_MSEC:
+               return sr_sw_limits_config_set(&devc->limits, key, data);
        default:
                return SR_ERR_NA;
        }