Update the Hameg/Rohde&Schwarz HMO driver (hameg-hmo) so that it
is possible to configure the logic threshold for digital signals.

The user can get or set the logic threshold configuration using
the channel group POD0 (and/or POD1 where available), for example:

sigrok-cli --driver hameg-hmo --get logic_threshold -g POD0
sigrok-cli --driver hameg-hmo --config logic_threshold=TTL --set -g POD0

Signed-off-by: Guido Trentalancia <gu...@trentalancia.com>
---
 include/libsigrok/libsigrok.h     |    5 ++-
 src/hardware/hameg-hmo/api.c      |   52 ++++++++++++++++++++++++++++++++++++--
 src/hardware/hameg-hmo/protocol.c |   50 ++++++++++++++++++++++++++++++++----
 src/hardware/hameg-hmo/protocol.h |   14 +++++++++-
 src/hwdriver.c                    |    2 +
 src/scpi.h                        |    2 +
 6 files changed, 116 insertions(+), 9 deletions(-)

diff -pru libsigrok-git-orig/include/libsigrok/libsigrok.h 
libsigrok-git-logic-threshold/include/libsigrok/libsigrok.h
--- libsigrok-git-orig/include/libsigrok/libsigrok.h    2018-10-20 
13:12:30.841966966 +0200
+++ libsigrok-git-logic-threshold/include/libsigrok/libsigrok.h 2018-11-11 
22:32:13.785775710 +0100
@@ -827,9 +827,12 @@ enum sr_configkey {
        /** Min hold mode. */
        SR_CONF_HOLD_MIN,
 
-       /** Logic low-high threshold range. */
+       /** Logic low-high threshold: numerical value. */
        SR_CONF_VOLTAGE_THRESHOLD,
 
+       /** Logic low-high threshold: predefined levels (TTL, ECL, CMOS, etc). 
*/
+       SR_CONF_LOGIC_THRESHOLD,
+
        /** The device supports using an external clock. */
        SR_CONF_EXTERNAL_CLOCK,
 
diff -pru libsigrok-git-orig/src/hardware/hameg-hmo/api.c 
libsigrok-git-logic-threshold/src/hardware/hameg-hmo/api.c
--- libsigrok-git-orig/src/hardware/hameg-hmo/api.c     2018-11-11 
15:13:10.929161841 +0100
+++ libsigrok-git-logic-threshold/src/hardware/hameg-hmo/api.c  2018-11-11 
21:57:23.420665220 +0100
@@ -2,6 +2,7 @@
  * This file is part of the libsigrok project.
  *
  * Copyright (C) 2013 poljar (Damir Jelić) <poljari...@gmail.com>
+ * Copyright (C) 2018 Guido Trentalancia <gu...@trentalancia.com>
  *
  * 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
@@ -150,6 +151,8 @@ static int config_get(uint32_t key, GVar
        const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 {
        int cg_type, idx;
+       char command[MAX_COMMAND_SIZE];
+       char *tmp_str;
        struct dev_context *devc;
        const struct scope_config *model;
        struct scope_state *state;
@@ -214,6 +217,22 @@ static int config_get(uint32_t key, GVar
        case SR_CONF_SAMPLERATE:
                *data = g_variant_new_uint64(state->sample_rate);
                break;
+       case SR_CONF_LOGIC_THRESHOLD:
+               if (!cg)
+                       return SR_ERR_CHANNEL_GROUP;
+               if (cg_type != CG_DIGITAL)
+                       return SR_ERR_NA;
+               if (!model)
+                       return SR_ERR_ARG;
+               if ((idx = std_cg_idx(cg, devc->digital_groups, 
model->digital_pods)) < 0)
+                       return SR_ERR_ARG;
+               g_snprintf(command, sizeof(command),
+                          
(*model->scpi_dialect)[SCPI_CMD_GET_DIG_POD_THRESHOLD],
+                          idx + 1);
+               if (sr_scpi_get_string(sdi->conn, command, &tmp_str) != SR_OK)
+                       return SR_ERR;
+               *data = g_variant_new_string(tmp_str);
+               break;
        default:
                return SR_ERR_NA;
        }
@@ -332,6 +351,26 @@ static int config_set(uint32_t key, GVar
                        return SR_ERR;
                ret = SR_OK;
                break;
+       case SR_CONF_LOGIC_THRESHOLD:
+               if (!cg)
+                       return SR_ERR_CHANNEL_GROUP;
+               if (cg_type != CG_DIGITAL)
+                       return SR_ERR_NA;
+               if (!model)
+                       return SR_ERR_ARG;
+               if ((idx = std_str_idx(data, *model->logic_threshold, 
model->num_logic_threshold)) < 0)
+                       return SR_ERR_ARG;
+               if ((j = std_cg_idx(cg, devc->digital_groups, 
model->digital_pods)) < 0)
+                       return SR_ERR_ARG;
+               g_snprintf(command, sizeof(command),
+                          
(*model->scpi_dialect)[SCPI_CMD_SET_DIG_POD_THRESHOLD],
+                          j + 1, (*model->logic_threshold)[idx]);
+               if (sr_scpi_send(sdi->conn, command) != SR_OK ||
+                   sr_scpi_get_opc(sdi->conn) != SR_OK)
+                       return SR_ERR;
+               state->digital_pods[j].threshold = idx;
+               ret = SR_OK;
+               break;
        default:
                ret = SR_ERR_NA;
                break;
@@ -373,6 +412,8 @@ static int config_list(uint32_t key, GVa
                                *data = 
std_gvar_array_u32(ARRAY_AND_SIZE(drvopts));
                } else if (cg_type == CG_ANALOG) {
                        *data = std_gvar_array_u32(*model->devopts_cg_analog, 
model->num_devopts_cg_analog);
+               } else if (cg_type == CG_DIGITAL) {
+                       *data = std_gvar_array_u32(*model->devopts_cg_digital, 
model->num_devopts_cg_digital);
                } else {
                        *data = std_gvar_array_u32(NULL, 0);
                }
@@ -406,6 +447,13 @@ static int config_list(uint32_t key, GVa
                        return SR_ERR_ARG;
                *data = std_gvar_tuple_array(*model->vdivs, model->num_vdivs);
                break;
+       case SR_CONF_LOGIC_THRESHOLD:
+               if (!cg)
+                       return SR_ERR_CHANNEL_GROUP;
+               if (!model)
+                       return SR_ERR_ARG;
+               *data = g_variant_new_strv(*model->logic_threshold, 
model->num_logic_threshold);
+               break;
        default:
                return SR_ERR_NA;
        }
@@ -568,7 +616,7 @@ static int hmo_setup_channels(const stru
 
        ret = SR_OK;
        for (i = 0; i < model->digital_pods; i++) {
-               if (state->digital_pods[i] == pod_enabled[i])
+               if (state->digital_pods[i].state == pod_enabled[i])
                        continue;
                g_snprintf(command, sizeof(command),
                           (*model->scpi_dialect)[SCPI_CMD_SET_DIG_POD_STATE],
@@ -577,7 +625,7 @@ static int hmo_setup_channels(const stru
                        ret = SR_ERR;
                        break;
                }
-               state->digital_pods[i] = pod_enabled[i];
+               state->digital_pods[i].state = pod_enabled[i];
                setup_changed = TRUE;
        }
        g_free(pod_enabled);
diff -pru libsigrok-git-orig/src/hardware/hameg-hmo/protocol.c 
libsigrok-git-logic-threshold/src/hardware/hameg-hmo/protocol.c
--- libsigrok-git-orig/src/hardware/hameg-hmo/protocol.c        2018-11-11 
15:12:40.687162919 +0100
+++ libsigrok-git-logic-threshold/src/hardware/hameg-hmo/protocol.c     
2018-11-11 21:47:56.919685409 +0100
@@ -2,6 +2,7 @@
  * This file is part of the libsigrok project.
  *
  * Copyright (C) 2013 poljar (Damir Jelić) <poljari...@gmail.com>
+ * Copyright (C) 2018 Guido Trentalancia <gu...@trentalancia.com>
  *
  * 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
@@ -55,6 +56,8 @@ static const char *hameg_scpi_dialect[]
        [SCPI_CMD_GET_ANALOG_CHAN_STATE]    = ":CHAN%d:STAT?",
        [SCPI_CMD_SET_ANALOG_CHAN_STATE]    = ":CHAN%d:STAT %d",
        [SCPI_CMD_GET_PROBE_UNIT]           = ":PROB%d:SET:ATT:UNIT?",
+       [SCPI_CMD_GET_DIG_POD_THRESHOLD]    = ":POD%d:THR?",
+       [SCPI_CMD_SET_DIG_POD_THRESHOLD]    = ":POD%d:THR %s",
 };
 
 static const uint32_t devopts[] = {
@@ -75,6 +78,10 @@ static const uint32_t devopts_cg_analog[
        SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 };
 
+static const uint32_t devopts_cg_digital[] = {
+       SR_CONF_LOGIC_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+};
+
 static const char *coupling_options[] = {
        "AC",  // AC with 50 Ohm termination (152x, 202x, 30xx, 1202)
        "ACL", // AC with 1 MOhm termination
@@ -89,6 +96,14 @@ static const char *scope_trigger_slopes[
        "EITH",
 };
 
+static const char *logic_threshold[] = {
+       "TTL",
+       "ECL",
+       "CMOS",
+       "USER1",
+       "USER2",
+};
+
 /* HMO compact2 */
 static const char *an2_dig8_trigger_sources[] = {
        "CH1", "CH2",
@@ -204,9 +219,15 @@ static const struct scope_config scope_m
                .devopts_cg_analog = &devopts_cg_analog,
                .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
 
+               .devopts_cg_digital = &devopts_cg_digital,
+               .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
+
                .coupling_options = &coupling_options,
                .num_coupling_options = ARRAY_SIZE(coupling_options),
 
+               .logic_threshold = &logic_threshold,
+               .num_logic_threshold = ARRAY_SIZE(logic_threshold),
+
                .trigger_sources = &an2_dig8_trigger_sources,
                .num_trigger_sources = ARRAY_SIZE(an2_dig8_trigger_sources),
 
@@ -240,9 +261,15 @@ static const struct scope_config scope_m
                .devopts_cg_analog = &devopts_cg_analog,
                .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
 
+               .devopts_cg_digital = &devopts_cg_digital,
+               .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
+
                .coupling_options = &coupling_options,
                .num_coupling_options = ARRAY_SIZE(coupling_options),
 
+               .logic_threshold = &logic_threshold,
+               .num_logic_threshold = ARRAY_SIZE(logic_threshold),
+
                .trigger_sources = &an2_dig16_trigger_sources,
                .num_trigger_sources = ARRAY_SIZE(an2_dig16_trigger_sources),
 
@@ -275,9 +302,15 @@ static const struct scope_config scope_m
                .devopts_cg_analog = &devopts_cg_analog,
                .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
 
+               .devopts_cg_digital = &devopts_cg_digital,
+               .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
+
                .coupling_options = &coupling_options,
                .num_coupling_options = ARRAY_SIZE(coupling_options),
 
+               .logic_threshold = &logic_threshold,
+               .num_logic_threshold = ARRAY_SIZE(logic_threshold),
+
                .trigger_sources = &an4_dig8_trigger_sources,
                .num_trigger_sources = ARRAY_SIZE(an4_dig8_trigger_sources),
 
@@ -310,9 +343,15 @@ static const struct scope_config scope_m
                .devopts_cg_analog = &devopts_cg_analog,
                .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
 
+               .devopts_cg_digital = &devopts_cg_digital,
+               .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
+
                .coupling_options = &coupling_options,
                .num_coupling_options = ARRAY_SIZE(coupling_options),
 
+               .logic_threshold = &logic_threshold,
+               .num_logic_threshold = ARRAY_SIZE(logic_threshold),
+
                .trigger_sources = &an4_dig16_trigger_sources,
                .num_trigger_sources = ARRAY_SIZE(an4_dig16_trigger_sources),
 
@@ -353,8 +392,9 @@ static void scope_state_dump(const struc
        }
 
        for (i = 0; i < config->digital_pods; i++) {
-               sr_info("State of digital POD %d -> %s", i,
-                       state->digital_pods[i] ? "On" : "Off");
+               sr_info("State of digital POD %d -> %s : %s (threshold)", i,
+                       state->digital_pods[i].state ? "On" : "Off",
+                       
(*config->logic_threshold)[state->digital_pods[i].threshold]);
        }
 
        tmp = sr_period_string((*config->timebases)[state->timebase][0],
@@ -542,7 +582,7 @@ static int digital_channel_state_get(str
                           i + 1);
 
                if (sr_scpi_get_bool(scpi, command,
-                                    &state->digital_pods[i]) != SR_OK)
+                                    &state->digital_pods[i].state) != SR_OK)
                        return SR_ERR;
        }
 
@@ -579,7 +619,7 @@ SR_PRIV int hmo_update_sample_rate(const
 
        if (!channel_found) {
                for (i = 0; i < config->digital_pods; i++) {
-                       if (!state->digital_pods[i])
+                       if (!state->digital_pods[i].state)
                                continue;
                        g_snprintf(chan_name, sizeof(chan_name), "POD%d", i);
                        g_snprintf(tmp_str, sizeof(tmp_str),
@@ -692,7 +732,7 @@ static struct scope_state *scope_state_n
        state->digital_channels = g_malloc0_n(
                        config->digital_channels, sizeof(gboolean));
        state->digital_pods = g_malloc0_n(config->digital_pods,
-                       sizeof(gboolean));
+                       sizeof(struct digital_pod_state));
 
        return state;
 }
diff -pru libsigrok-git-orig/src/hardware/hameg-hmo/protocol.h 
libsigrok-git-logic-threshold/src/hardware/hameg-hmo/protocol.h
--- libsigrok-git-orig/src/hardware/hameg-hmo/protocol.h        2018-11-11 
15:12:40.688162919 +0100
+++ libsigrok-git-logic-threshold/src/hardware/hameg-hmo/protocol.h     
2018-11-11 15:48:36.282604464 +0100
@@ -49,9 +49,15 @@ struct scope_config {
        const uint32_t (*devopts_cg_analog)[];
        const uint8_t num_devopts_cg_analog;
 
+       const uint32_t (*devopts_cg_digital)[];
+       const uint8_t num_devopts_cg_digital;
+
        const char *(*coupling_options)[];
        const uint8_t num_coupling_options;
 
+       const char *(*logic_threshold)[];
+       const uint8_t num_logic_threshold;
+
        const char *(*trigger_sources)[];
        const uint8_t num_trigger_sources;
 
@@ -80,10 +86,16 @@ struct analog_channel_state {
        char probe_unit;
 };
 
+struct digital_pod_state {
+       gboolean state;
+
+       int threshold;
+};
+
 struct scope_state {
        struct analog_channel_state *analog_channels;
        gboolean *digital_channels;
-       gboolean *digital_pods;
+       struct digital_pod_state *digital_pods;
 
        int timebase;
        float horiz_triggerpos;
diff -pru libsigrok-git-orig/src/hwdriver.c 
libsigrok-git-logic-threshold/src/hwdriver.c
--- libsigrok-git-orig/src/hwdriver.c   2018-10-20 13:12:30.965966965 +0200
+++ libsigrok-git-logic-threshold/src/hwdriver.c        2018-11-11 
22:37:27.601764527 +0100
@@ -121,6 +121,8 @@ static struct sr_key_info sr_key_info_co
                "Hold min", NULL},
        {SR_CONF_VOLTAGE_THRESHOLD, SR_T_DOUBLE_RANGE, "voltage_threshold",
                "Voltage threshold", NULL },
+       {SR_CONF_LOGIC_THRESHOLD, SR_T_STRING, "logic_threshold",
+               "Logic threshold", NULL},
        {SR_CONF_EXTERNAL_CLOCK, SR_T_BOOL, "external_clock",
                "External clock mode", NULL},
        {SR_CONF_SWAP, SR_T_BOOL, "swap",
diff -pru libsigrok-git-orig/src/scpi.h libsigrok-git-logic-threshold/src/scpi.h
--- libsigrok-git-orig/src/scpi.h       2018-11-11 14:37:51.385675625 +0100
+++ libsigrok-git-logic-threshold/src/scpi.h    2018-11-11 16:20:59.941535197 
+0100
@@ -63,6 +63,8 @@ enum {
        SCPI_CMD_SET_PROBE_UNIT,
        SCPI_CMD_GET_ANALOG_CHAN_NAME,
        SCPI_CMD_GET_DIG_CHAN_NAME,
+       SCPI_CMD_GET_DIG_POD_THRESHOLD,
+       SCPI_CMD_SET_DIG_POD_THRESHOLD,
 };
 
 struct scpi_command {


_______________________________________________
sigrok-devel mailing list
sigrok-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to