]> sigrok.org Git - libsigrok.git/commitdiff
gmc-mh-1x-2x: Cleanup, docs, minor fixes.
authorMatthias Heidbrink <redacted>
Wed, 5 Feb 2014 13:40:40 +0000 (14:40 +0100)
committerUwe Hermann <redacted>
Tue, 11 Feb 2014 17:04:54 +0000 (18:04 +0100)
hardware/gmc-mh-1x-2x/api.c
hardware/gmc-mh-1x-2x/protocol.c
hardware/gmc-mh-1x-2x/protocol.h

index 197522a2cf3baccd7bfc103bb0f6b0affb63e062..02273ac572f2254e00dbdbb963591095ea8339c6 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+/** @file
+ *  Gossen Metrawatt Metrahit 1x/2x drivers
+ *  @private
+ */
+
 #include <string.h>
 #include "protocol.h"
 
 /* Serial communication parameters for Metrahit 1x/2x with 'RS232' adaptor */
 #define SERIALCOMM_1X_RS232 "8228/6n1/dtr=1/rts=1/flow=0" /* =8192, closer with divider */
 #define SERIALCOMM_2X_RS232 "9600/6n1/dtr=1/rts=1/flow=0"
+#define SERIALCOMM_2X "9600/8n1/dtr=1/rts=1/flow=0"
 #define VENDOR_GMC "Gossen Metrawatt"
 
 SR_PRIV struct sr_dev_driver gmc_mh_1x_2x_rs232_driver_info;
-static struct sr_dev_driver *di = &gmc_mh_1x_2x_rs232_driver_info;
 
 static const int32_t hwopts[] = {
        SR_CONF_CONN,
@@ -35,14 +40,23 @@ static const int32_t hwopts[] = {
 
 static const int32_t hwcaps[] = {
        SR_CONF_MULTIMETER,
+       SR_CONF_THERMOMETER,    /**< All GMC 1x/2x multimeters seem to support this */
        SR_CONF_LIMIT_SAMPLES,
        SR_CONF_LIMIT_MSEC,
        SR_CONF_CONTINUOUS,
 };
 
+/* TODO:
+ * - For the 29S SR_CONF_ENERGYMETER, too.
+ * - SR_CONF_PATTERN_MODE for some 2x devices
+ * - SR_CONF_DATALOG for 22M, 26M, 29S and storage adaptors.
+ * Need to implement device-specific lists.
+ */
+
+/** Init driver gmc_mh_1x_2x_rs232. */
 static int init(struct sr_context *sr_ctx)
 {
-       return std_init(sr_ctx, di, LOG_PREFIX);
+    return std_init(sr_ctx, &gmc_mh_1x_2x_rs232_driver_info, LOG_PREFIX);
 }
 
 /**
@@ -137,7 +151,7 @@ static GSList *scan(GSList *options)
        gboolean serialcomm_given;
 
        devices = NULL;
-       drvc = di->priv;
+       drvc = (&gmc_mh_1x_2x_rs232_driver_info)->priv;
        drvc->instances = NULL;
        conn = serialcomm = NULL;
        model = METRAHIT_NONE;
@@ -206,7 +220,7 @@ static GSList *scan(GSList *options)
 
                sdi->conn = serial;
                sdi->priv = devc;
-               sdi->driver = di;
+               sdi->driver = &gmc_mh_1x_2x_rs232_driver_info;
                if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1")))
                        return NULL;
                sdi->probes = g_slist_append(sdi->probes, probe);
@@ -219,12 +233,12 @@ static GSList *scan(GSList *options)
 
 static GSList *dev_list(void)
 {
-       return ((struct drv_context *)(di->priv))->instances;
+   return ((struct drv_context *)(gmc_mh_1x_2x_rs232_driver_info.priv))->instances;
 }
 
 static int dev_clear(void)
 {
-       return std_dev_clear(di, NULL);
+       return std_dev_clear(&gmc_mh_1x_2x_rs232_driver_info, NULL);
 }
 
 static int dev_close(struct sr_dev_inst *sdi)
@@ -250,19 +264,27 @@ static int cleanup(void)
        return dev_clear();
 }
 
-/** TODO */
+/** Get value of configuration item */
 static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
                const struct sr_probe_group *probe_group)
 {
        int ret;
+       ret = SR_OK;
+       struct dev_context *devc;
 
-       (void)sdi;
-       (void)data;
        (void)probe_group;
 
+       if (!sdi || !(devc = sdi->priv))
+               return SR_ERR_ARG;
+
        ret = SR_OK;
        switch (key) {
-       /* TODO */
+       case SR_CONF_LIMIT_SAMPLES:
+               *data = g_variant_new_uint64(devc->limit_samples);
+               break;
+       case SR_CONF_LIMIT_MSEC:
+               *data = g_variant_new_uint64(devc->limit_msec);
+               break;
        default:
                return SR_ERR_NA;
        }
index 66a73e9f639965d0e5e86b3be2352275ac11bccb..32425b4ec9573b28030179f2942adf27f7f0f015 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+/** @file
+ *  Gossen Metrawatt Metrahit 1x/2x drivers
+ *  @private
+ */
+
 #include <math.h>
 #include <string.h>
 #include "protocol.h"
@@ -358,7 +363,7 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
                if (ctmv >= 0x02) {
                        devc->mqflags |= SR_MQFLAG_AC;
                        if (devc->model >= METRAHIT_24S)
-                               devc->model |= SR_MQFLAG_RMS;
+                               devc->mqflags |= SR_MQFLAG_RMS;
                }
                break;
        case 0x04: /* 00100 mA DC */
@@ -384,10 +389,12 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
                devc->unit = SR_UNIT_FARAD;
                devc->scale *= 0.1;
                break;
-       case 0x0a: /* 01010 dB */
+       case 0x0a: /* 01010 dBV */
                devc->mq = SR_MQ_VOLTAGE;
                devc->unit = SR_UNIT_DECIBEL_VOLT;
                devc->mqflags |= SR_MQFLAG_AC;
+               if (devc->model >= METRAHIT_24S)
+                       devc->mqflags |= SR_MQFLAG_RMS;
                break;
        case 0x0b: /* 01011 Hz U ACDC */
        case 0x0c: /* 01100 Hz U AC */
@@ -398,8 +405,9 @@ 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;
+               /* Fall through! */
        case 0x0e: /* 01110 W on power, A range (29S only) */
-               /* TODO: Differences between Send Mode and bidir protocol here */
                devc->mq = SR_MQ_POWER;
                devc->unit = SR_UNIT_WATT;
                break;
@@ -409,7 +417,6 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
                if (ctmv == 0x0f) {
                        devc->mq = SR_MQ_VOLTAGE;
                        devc->mqflags |= SR_MQFLAG_DIODE;
-                       devc->scale *= 0.1;
                } else {
                        devc->mq = SR_MQ_CONTINUITY;
                        devc->scale *= 0.00001;
@@ -476,9 +483,9 @@ static void decode_ctmv_2x(uint8_t ctmv, struct dev_context *devc)
 }
 
 /**
- * Decode range/sign/acdc byte special chars, Metrahit 2x.
+ * Decode range/sign/acdc byte special chars, Metrahit 2x, table TR.
  *
- * @param[in] rs Rance/sign byte.
+ * @param[in] rs Range/sign byte.
  */
 static void decode_rs_2x(uint8_t rs, struct dev_context *devc)
 {
@@ -486,7 +493,7 @@ static void decode_rs_2x(uint8_t rs, struct dev_context *devc)
 
        /* Sign */
        if (((devc->scale > 0) && (rs & 0x08)) ||
-               ((devc->scale < 0) && !(rs & 0x08)))
+                       ((devc->scale < 0) && !(rs & 0x08)))
                devc->scale *= -1.0;
 
        /* Range */
@@ -497,17 +504,13 @@ static void decode_rs_2x(uint8_t rs, struct dev_context *devc)
                        devc->scale *= pow(10.0, -3);
                else if (devc->vmains_29S)
                        devc->scale *= pow(10.0, range - 2);
-               else if(devc->mqflags & SR_MQFLAG_AC)
+       else
                        devc->scale *= pow(10.0, range - 6);
-               else /* "Undocumented feature": Between AC and DC
-                       scaling differs by 1. */
-                       devc->scale *= pow(10.0, range - 5);
                break;
        case SR_MQ_CURRENT:
-               if (devc->scale1000 == -1)
-                       devc->scale *= pow(10.0, range - 5);
-               else
-                       devc->scale *= pow(10.0, range - 4);
+       if (devc->scale1000 != -1) /* uA, mA */
+           range += 1;/* mA and A ranges differ by 10^4, not 10^3!*/
+       devc->scale *= pow(10.0, range - 6);
                break;
        case SR_MQ_RESISTANCE:
                devc->scale *= pow(10.0, range - 3);
@@ -521,6 +524,8 @@ static void decode_rs_2x(uint8_t rs, struct dev_context *devc)
                devc->scale *= pow(10.0, - 2);
                break;
        case SR_MQ_CAPACITANCE:
+               if (range == 7)
+                       range -= 1; /* Same value as range 6 */
                devc->scale *= pow(10.0, range - 13);
                break;
        /* TODO: 29S Mains measurements. */
@@ -593,7 +598,7 @@ static void send_value(struct sr_dev_inst *sdi)
        devc->num_samples++;
 }
 
-/** Process 6-byte data message, Metrahit 1x/2x. */
+/** Process 6-byte data message, Metrahit 1x/2x send mode. */
 static void process_msg_dta_6(struct sr_dev_inst *sdi)
 {
        struct dev_context *devc;
@@ -608,8 +613,10 @@ static void process_msg_dta_6(struct sr_dev_inst *sdi)
                decode_rs_16(bc(devc->buf[0]), devc);
        else if (devc->model < METRAHIT_2X)
                decode_rs_18(bc(devc->buf[0]), devc);
-       else
+    else {
                decode_rs_2x(bc(devc->buf[0]), devc);
+       devc->scale *= 10; /* Compensate for format having only 5 digits, decode_rs_2x() assumes 6. */
+    }
 
        /* Bytes 1-5, digits (ls first). */
        for (cnt = 0; cnt < 5; cnt++) {
@@ -622,7 +629,8 @@ static void process_msg_dta_6(struct sr_dev_inst *sdi)
                }
                devc->value += pow(10.0, cnt) * dgt;
        }
-       sr_spew("process_msg_dta_6() value=%f scale=%f scalet=%d",
+
+    sr_spew("process_msg_dta_6() value=%f scale=%f scale1000=%d",
                devc->value, devc->scale, devc->scale1000);
        if (devc->value != NAN)
                devc->value *= devc->scale * pow(1000.0, devc->scale1000);
@@ -678,7 +686,10 @@ static void process_msg_inf_10(struct sr_dev_inst *sdi)
        /* Now decode numbers */
        for (cnt = 0; cnt < 5; cnt++) {
                dgt = bc(devc->buf[5 + cnt]);
-               if (dgt >= 10) { /* Overload */
+       if (dgt == 11) { /* Empty digit */
+           dgt = 0;
+       }
+       else if (dgt >= 12) { /* Overload */
                        devc->value = NAN;
                        devc->scale = 1.0;
                        break;
@@ -907,9 +918,9 @@ SR_PRIV int gmc_decode_model_sm(uint8_t mcode)
        case 0x0f: /* 1111b */
                return METRAHIT_24S;
        case 0x05: /* 0101b */
-               return METRAHIT_25SM;
+       return METRAHIT_25S;
        case 0x01: /* 0001b */
-               return METRAHIT_26S;
+       return METRAHIT_26SM;
        case 0x0c: /* 1100b */
                return METRAHIT_28S;
        case 0x0e: /* 1110b */
@@ -920,16 +931,15 @@ SR_PRIV int gmc_decode_model_sm(uint8_t mcode)
        }
 }
 
-/**
- * Decode model in bidirectional mode.
+/** Convert GMC model code in bidirectional mode to sigrok-internal one.
  *
- * @param[in] mcode Model code.
+ *  @param[in] mcode Model code.
  *
- * @return Model code.
+ *  @return Model code.
  */
-SR_PRIV int gmc_decode_model_bidi(uint8_t mcode)
+SR_PRIV int gmc_decode_model_bd(uint8_t mcode)
 {
-       switch (mcode) {
+       switch (mcode & 0x1f) {
        case 2:
                return METRAHIT_22SM;
        case 3:
@@ -937,9 +947,9 @@ SR_PRIV int gmc_decode_model_bidi(uint8_t mcode)
        case 4:
                return METRAHIT_24S;
        case 5:
-               return METRAHIT_25SM;
+               return METRAHIT_25S;
        case 1:
-               return METRAHIT_26S;
+               return METRAHIT_26SM;
        case 12:
                return METRAHIT_28S;
        case 14:
@@ -950,6 +960,12 @@ SR_PRIV int gmc_decode_model_bidi(uint8_t mcode)
        }
 }
 
+/** Convert sigrok-internal model code to string.
+ *
+ *  @param[in] mcode Model code.
+ *
+ *  @return Model code string.
+ */
 SR_PRIV const char *gmc_model_str(enum model mcode)
 {
        switch (mcode) {
@@ -975,10 +991,10 @@ SR_PRIV const char *gmc_model_str(enum model mcode)
                return "METRAHit 23S";
        case METRAHIT_24S:
                return "METRAHit 24S";
-       case METRAHIT_25SM:
-               return "METRAHit 25S/M";
-       case METRAHIT_26S:
-               return "METRAHit 26S";
+       case METRAHIT_25S:
+               return "METRAHit 25S";
+       case METRAHIT_26SM:
+               return "METRAHit 26S/M";
        case METRAHIT_28S:
                return "METRAHit 28S";
        case METRAHIT_29S:
index 9d742e3cb692e0a5bb36805cb994b5a534c1475e..8f1c7c15a0f5c20aba27ee78cb852f1f69ea7da8 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+/** @file
+ *  Gossen Metrawatt Metrahit 1x/2x drivers
+ *  @private
+ */
+
 #ifndef LIBSIGROK_HARDWARE_GMC_MH_1X_2X_PROTOCOL_H
 #define LIBSIGROK_HARDWARE_GMC_MH_1X_2X_PROTOCOL_H
 
@@ -36,7 +41,7 @@
 #define MSGID_DTA   0x20 /**< Start of data message, displayed, averaged */
 #define MSGID_DATA  0x30 /**< Data byte in message */
 
-#define MSGC_MASK   0x0f  /**< Mask to get message byte contents */
+#define MSGC_MASK   0x0f  /**< Mask to get message byte contents in send mode */
 
 #define MSGSRC_MASK 0xc0 /**< Mask to get bits related to message source */
 
@@ -63,24 +68,12 @@ enum model {
        METRAHIT_22SM           = 22,
        METRAHIT_23S            = 23,
        METRAHIT_24S            = 24,
-       METRAHIT_25SM           = 25,
-       METRAHIT_26S            = 26,
+       METRAHIT_25S            = 25,
+       METRAHIT_26SM           = 26,
        METRAHIT_28S            = 28,
        METRAHIT_29S            = 29,
 };
 
-/** Convert GMC model code in send mode to sigrok-internal one. */
-SR_PRIV int gmc_decode_model_sm(uint8_t mcode);
-
-/**
- * Convert GMC model code in bidirectional mode to sigrok-internal one.
- *
- * @param[in] mcode Model code.
- *
- * @return Model code.
- */
-SR_PRIV int gmc_decode_model_bidi(uint8_t mcode);
-
 /** Get model string from sigrok-internal model code. */
 SR_PRIV const char *gmc_model_str(enum model mcode);
 
@@ -116,5 +109,6 @@ struct dev_context {
 };
 
 SR_PRIV int gmc_mh_1x_2x_receive_data(int fd, int revents, void *cb_data);
+SR_PRIV int gmc_decode_model_sm(uint8_t mcode);
 
 #endif