]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/hameg-hmo/protocol.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / hameg-hmo / protocol.c
index 8ba2a35e68b5030f5f2b4fb5e2a79303e6452e23..f355e2c272dc882293857a651aaaf73b0361eb84 100644 (file)
@@ -34,6 +34,7 @@ static const char *hameg_scpi_dialect[] = {
        [SCPI_CMD_GET_DIG_DATA]               = ":FORM UINT,8;:POD%d:DATA?",
        [SCPI_CMD_GET_TIMEBASE]               = ":TIM:SCAL?",
        [SCPI_CMD_SET_TIMEBASE]               = ":TIM:SCAL %s",
+       [SCPI_CMD_GET_HORIZONTAL_DIV]         = ":TIM:DIV?",
        [SCPI_CMD_GET_COUPLING]               = ":CHAN%d:COUP?",
        [SCPI_CMD_SET_COUPLING]               = ":CHAN%d:COUP %s",
        [SCPI_CMD_GET_SAMPLE_RATE]            = ":ACQ:SRAT?",
@@ -43,6 +44,8 @@ static const char *hameg_scpi_dialect[] = {
        [SCPI_CMD_SET_VERTICAL_SCALE]         = ":CHAN%d:SCAL %s",
        [SCPI_CMD_GET_DIG_POD_STATE]          = ":POD%d:STAT?",
        [SCPI_CMD_SET_DIG_POD_STATE]          = ":POD%d:STAT %d",
+       [SCPI_CMD_GET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR?",
+       [SCPI_CMD_SET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR %s",
        [SCPI_CMD_GET_TRIGGER_SLOPE]          = ":TRIG:A:EDGE:SLOP?",
        [SCPI_CMD_SET_TRIGGER_SLOPE]          = ":TRIG:A:TYPE EDGE;:TRIG:A:EDGE:SLOP %s",
        [SCPI_CMD_GET_TRIGGER_PATTERN]        = ":TRIG:A:PATT:SOUR?",
@@ -51,8 +54,10 @@ static const char *hameg_scpi_dialect[] = {
                                                ":TRIG:A:PATT:COND \"TRUE\";" \
                                                ":TRIG:A:PATT:MODE OFF;" \
                                                ":TRIG:A:PATT:SOUR \"%s\"",
-       [SCPI_CMD_GET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR?",
-       [SCPI_CMD_SET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR %s",
+       [SCPI_CMD_GET_HIGH_RESOLUTION]        = ":ACQ:HRES?",
+       [SCPI_CMD_SET_HIGH_RESOLUTION]        = ":ACQ:HRES %s",
+       [SCPI_CMD_GET_PEAK_DETECTION]         = ":ACQ:PEAK?",
+       [SCPI_CMD_SET_PEAK_DETECTION]         = ":ACQ:PEAK %s",
        [SCPI_CMD_GET_DIG_CHAN_STATE]         = ":LOG%d:STAT?",
        [SCPI_CMD_SET_DIG_CHAN_STATE]         = ":LOG%d:STAT %d",
        [SCPI_CMD_GET_VERTICAL_OFFSET]        = ":CHAN%d:POS?",
@@ -71,6 +76,7 @@ static const char *rohde_schwarz_log_not_pod_scpi_dialect[] = {
        [SCPI_CMD_GET_DIG_DATA]               = ":FORM UINT,8;:LOG%d:DATA?",
        [SCPI_CMD_GET_TIMEBASE]               = ":TIM:SCAL?",
        [SCPI_CMD_SET_TIMEBASE]               = ":TIM:SCAL %s",
+       [SCPI_CMD_GET_HORIZONTAL_DIV]         = ":TIM:DIV?",
        [SCPI_CMD_GET_COUPLING]               = ":CHAN%d:COUP?",
        [SCPI_CMD_SET_COUPLING]               = ":CHAN%d:COUP %s",
        [SCPI_CMD_GET_SAMPLE_RATE]            = ":ACQ:SRAT?",
@@ -80,6 +86,8 @@ static const char *rohde_schwarz_log_not_pod_scpi_dialect[] = {
        [SCPI_CMD_SET_VERTICAL_SCALE]         = ":CHAN%d:SCAL %s",
        [SCPI_CMD_GET_DIG_POD_STATE]          = ":LOG%d:STAT?",
        [SCPI_CMD_SET_DIG_POD_STATE]          = ":LOG%d:STAT %d",
+       [SCPI_CMD_GET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR?",
+       [SCPI_CMD_SET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR %s",
        [SCPI_CMD_GET_TRIGGER_SLOPE]          = ":TRIG:A:EDGE:SLOP?",
        [SCPI_CMD_SET_TRIGGER_SLOPE]          = ":TRIG:A:TYPE EDGE;:TRIG:A:EDGE:SLOP %s",
        [SCPI_CMD_GET_TRIGGER_PATTERN]        = ":TRIG:A:PATT:SOUR?",
@@ -88,8 +96,10 @@ static const char *rohde_schwarz_log_not_pod_scpi_dialect[] = {
                                                ":TRIG:A:PATT:COND \"TRUE\";" \
                                                ":TRIG:A:PATT:MODE OFF;" \
                                                ":TRIG:A:PATT:SOUR \"%s\"",
-       [SCPI_CMD_GET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR?",
-       [SCPI_CMD_SET_TRIGGER_SOURCE]         = ":TRIG:A:SOUR %s",
+       [SCPI_CMD_GET_HIGH_RESOLUTION]        = ":ACQ:HRES?",
+       [SCPI_CMD_SET_HIGH_RESOLUTION]        = ":ACQ:HRES %s",
+       [SCPI_CMD_GET_PEAK_DETECTION]         = ":ACQ:PEAK?",
+       [SCPI_CMD_SET_PEAK_DETECTION]         = ":ACQ:PEAK %s",
        [SCPI_CMD_GET_DIG_CHAN_STATE]         = ":LOG%d:STAT?",
        [SCPI_CMD_SET_DIG_CHAN_STATE]         = ":LOG%d:STAT %d",
        [SCPI_CMD_GET_VERTICAL_OFFSET]        = ":CHAN%d:POS?", /* Might not be supported on RTB200x... */
@@ -107,7 +117,7 @@ static const char *rohde_schwarz_log_not_pod_scpi_dialect[] = {
 static const uint32_t devopts[] = {
        SR_CONF_OSCILLOSCOPE,
        SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
-       SR_CONF_LIMIT_FRAMES | SR_CONF_SET,
+       SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
        SR_CONF_SAMPLERATE | SR_CONF_GET,
        SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
        SR_CONF_NUM_HDIV | SR_CONF_GET,
@@ -115,6 +125,8 @@ static const uint32_t devopts[] = {
        SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
        SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
        SR_CONF_TRIGGER_PATTERN | SR_CONF_GET | SR_CONF_SET,
+       SR_CONF_HIGH_RESOLUTION | SR_CONF_GET | SR_CONF_SET,
+       SR_CONF_PEAK_DETECTION | SR_CONF_GET | SR_CONF_SET,
 };
 
 static const uint32_t devopts_cg_analog[] = {
@@ -149,6 +161,11 @@ static const char *coupling_options_rtm300x[] = {
        "GND",
 };
 
+static const char *coupling_options_rth100x[] = {
+       "ACL", // AC with 1 MOhm termination
+       "DCL", // DC with 1 MOhm termination
+};
+
 static const char *scope_trigger_slopes[] = {
        "POS",
        "NEG",
@@ -171,6 +188,9 @@ static const char *logic_threshold_rtb200x_rtm300x[] = {
        "MAN", // overwritten by logic_threshold_custom
 };
 
+/* This might need updates whenever logic_threshold* above change. */
+#define MAX_NUM_LOGIC_THRESHOLD_ENTRIES ARRAY_SIZE(logic_threshold)
+
 /* RTC1002, HMO Compact2 and HMO1002/HMO1202 */
 static const char *an2_dig8_trigger_sources[] = {
        "CH1", "CH2",
@@ -194,6 +214,18 @@ static const char *an2_dig16_sbus_trigger_sources[] = {
        "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
 };
 
+/* RTH1002 */
+static const char *an2_dig8_isol_trigger_sources[] = {
+       "CH1", "CH2",
+       "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+};
+
+/* RTH1004 */
+static const char *an4_dig8_isol_trigger_sources[] = {
+       "CH1", "CH2", "CH3", "CH4",
+       "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+};
+
 /* HMO Compact4 */
 static const char *an4_dig8_trigger_sources[] = {
        "CH1", "CH2", "CH3", "CH4",
@@ -315,7 +347,17 @@ static const uint64_t vdivs[][2] = {
        { 2, 1 },
        { 5, 1 },
        { 10, 1 },
+       { 20, 1 },
+       { 50, 1 },
 };
+/*
+ * It feels a little hacky to use a single table yet use different item
+ * count values here. But it simplifies maintenance, reduces redundancy
+ * by avoiding several vdivs[] table versions of mostly identical content,
+ * still references which declare models' capabilities remain readable.
+ */
+#define VDIVS_COUNT_UPTO_10V   (ARRAY_SIZE(vdivs) - 2)
+#define VDIVS_COUNT_UPTO_50V   (ARRAY_SIZE(vdivs))
 
 static const char *scope_analog_channel_names[] = {
        "CH1", "CH2", "CH3", "CH4",
@@ -326,7 +368,7 @@ static const char *scope_digital_channel_names[] = {
        "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
 };
 
-static const struct scope_config scope_models[] = {
+static struct scope_config scope_models[] = {
        {
                /* HMO Compact2: HMO722/1022/1522/2022 support only 8 digital channels. */
                .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", NULL},
@@ -362,9 +404,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases_hmo_compact),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &hameg_scpi_dialect,
@@ -374,7 +415,6 @@ static const struct scope_config scope_models[] = {
                .name = {"RTC1002", "HMO1002", "HMO1202", NULL},
                .analog_channels = 2,
                .digital_channels = 8,
-               .digital_pods = 1,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -405,9 +445,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &hameg_scpi_dialect,
@@ -417,7 +456,6 @@ static const struct scope_config scope_models[] = {
                .name = {"HMO3032", "HMO3042", "HMO3052", "HMO3522", NULL},
                .analog_channels = 2,
                .digital_channels = 16,
-               .digital_pods = 2,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -448,9 +486,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &hameg_scpi_dialect,
@@ -460,7 +497,6 @@ static const struct scope_config scope_models[] = {
                .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL},
                .analog_channels = 4,
                .digital_channels = 8,
-               .digital_pods = 1,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -491,9 +527,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases_hmo_compact),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &hameg_scpi_dialect,
@@ -502,7 +537,6 @@ static const struct scope_config scope_models[] = {
                .name = {"HMO2524", "HMO3034", "HMO3044", "HMO3054", "HMO3524", NULL},
                .analog_channels = 4,
                .digital_channels = 16,
-               .digital_pods = 2,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -533,9 +567,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &hameg_scpi_dialect,
@@ -544,7 +577,6 @@ static const struct scope_config scope_models[] = {
                .name = {"RTB2002", NULL},
                .analog_channels = 2,
                .digital_channels = 16,
-               .digital_pods = 2,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -575,9 +607,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_50V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
@@ -586,7 +617,6 @@ static const struct scope_config scope_models[] = {
                .name = {"RTB2004", NULL},
                .analog_channels = 4,
                .digital_channels = 16,
-               .digital_pods = 2,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -617,9 +647,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_50V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
@@ -628,7 +657,6 @@ static const struct scope_config scope_models[] = {
                .name = {"RTM3002", NULL},
                .analog_channels = 2,
                .digital_channels = 16,
-               .digital_pods = 2,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -659,9 +687,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
@@ -670,7 +697,6 @@ static const struct scope_config scope_models[] = {
                .name = {"RTM3004", NULL},
                .analog_channels = 4,
                .digital_channels = 16,
-               .digital_pods = 2,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -701,9 +727,8 @@ static const struct scope_config scope_models[] = {
                .num_timebases = ARRAY_SIZE(timebases),
 
                .vdivs = &vdivs,
-               .num_vdivs = ARRAY_SIZE(vdivs),
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
@@ -712,7 +737,6 @@ static const struct scope_config scope_models[] = {
                .name = {"RTA4004", NULL},
                .analog_channels = 4,
                .digital_channels = 16,
-               .digital_pods = 2,
 
                .analog_names = &scope_analog_channel_names,
                .digital_names = &scope_digital_channel_names,
@@ -742,10 +766,89 @@ static const struct scope_config scope_models[] = {
                .timebases = &timebases,
                .num_timebases = ARRAY_SIZE(timebases),
 
+               .vdivs = &vdivs,
+               .num_vdivs = VDIVS_COUNT_UPTO_10V,
+
+               .num_ydivs = 8,
+
+               .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
+       },
+       {
+               .name = {"RTH1002", NULL},
+               .analog_channels = 2,
+               .digital_channels = 8,
+
+               .analog_names = &scope_analog_channel_names,
+               .digital_names = &scope_digital_channel_names,
+
+               .devopts = &devopts,
+               .num_devopts = ARRAY_SIZE(devopts),
+
+               .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_rth100x,
+               .num_coupling_options = ARRAY_SIZE(coupling_options_rth100x),
+
+               .logic_threshold = &logic_threshold,
+               .num_logic_threshold = ARRAY_SIZE(logic_threshold),
+               .logic_threshold_for_pod = TRUE,
+
+               .trigger_sources = &an2_dig8_isol_trigger_sources,
+               .num_trigger_sources = ARRAY_SIZE(an2_dig8_isol_trigger_sources),
+
+               .trigger_slopes = &scope_trigger_slopes,
+               .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
+
+               .timebases = &timebases,
+               .num_timebases = ARRAY_SIZE(timebases),
+
+               .vdivs = &vdivs,
+               .num_vdivs = ARRAY_SIZE(vdivs),
+
+               .num_ydivs = 8,
+
+               .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
+       },
+       {
+               .name = {"RTH1004", NULL},
+               .analog_channels = 4,
+               .digital_channels = 8,
+
+               .analog_names = &scope_analog_channel_names,
+               .digital_names = &scope_digital_channel_names,
+
+               .devopts = &devopts,
+               .num_devopts = ARRAY_SIZE(devopts),
+
+               .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_rth100x,
+               .num_coupling_options = ARRAY_SIZE(coupling_options_rth100x),
+
+               .logic_threshold = &logic_threshold,
+               .num_logic_threshold = ARRAY_SIZE(logic_threshold),
+               .logic_threshold_for_pod = TRUE,
+
+               .trigger_sources = &an4_dig8_isol_trigger_sources,
+               .num_trigger_sources = ARRAY_SIZE(an4_dig8_isol_trigger_sources),
+
+               .trigger_slopes = &scope_trigger_slopes,
+               .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
+
+               .timebases = &timebases,
+               .num_timebases = ARRAY_SIZE(timebases),
+
                .vdivs = &vdivs,
                .num_vdivs = ARRAY_SIZE(vdivs),
 
-               .num_xdivs = 12,
                .num_ydivs = 8,
 
                .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
@@ -900,7 +1003,7 @@ static int analog_channel_state_get(struct sr_dev_inst *sdi,
                if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
                        return SR_ERR;
 
-               if (array_float_get(tmp_str, ARRAY_AND_SIZE(vdivs), &j) != SR_OK) {
+               if (array_float_get(tmp_str, *(config->vdivs), config->num_vdivs, &j) != SR_OK) {
                        g_free(tmp_str);
                        sr_err("Could not determine array index for vertical div scale.");
                        return SR_ERR;
@@ -949,7 +1052,7 @@ static int digital_channel_state_get(struct sr_dev_inst *sdi,
 {
        unsigned int i, idx;
        int result = SR_ERR;
-       static char *logic_threshold_short[] = {};
+       char *logic_threshold_short[MAX_NUM_LOGIC_THRESHOLD_ENTRIES];
        char command[MAX_COMMAND_SIZE];
        struct sr_channel *ch;
        struct sr_scpi_dev_inst *scpi = sdi->conn;
@@ -997,7 +1100,7 @@ static int digital_channel_state_get(struct sr_dev_inst *sdi,
                if (config->logic_threshold_for_pod)
                        idx = i + 1;
                else
-                       idx = i * 8;
+                       idx = i * DIGITAL_CHANNELS_PER_POD;
 
                g_snprintf(command, sizeof(command),
                           (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_THRESHOLD],
@@ -1086,11 +1189,6 @@ SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
        if (digital_channel_state_get(sdi, config, state) != SR_OK)
                return SR_ERR;
 
-       if (sr_scpi_get_float(sdi->conn,
-                       (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
-                       &tmp_float) != SR_OK)
-               return SR_ERR;
-
        if (sr_scpi_get_string(sdi->conn,
                        (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
                        &tmp_str) != SR_OK)
@@ -1105,6 +1203,12 @@ SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
 
        state->timebase = i;
 
+       /* Determine the number of horizontal (x) divisions. */
+       if (sr_scpi_get_int(sdi->conn,
+           (*config->scpi_dialect)[SCPI_CMD_GET_HORIZONTAL_DIV],
+           (int *)&config->num_xdivs) != SR_OK)
+               return SR_ERR;
+
        if (sr_scpi_get_float(sdi->conn,
                        (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
                        &tmp_float) != SR_OK)
@@ -1136,6 +1240,26 @@ SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
                MAX_ANALOG_CHANNEL_COUNT + MAX_DIGITAL_CHANNEL_COUNT);
        g_free(tmp_str);
 
+       if (sr_scpi_get_string(sdi->conn,
+                            (*config->scpi_dialect)[SCPI_CMD_GET_HIGH_RESOLUTION],
+                            &tmp_str) != SR_OK)
+               return SR_ERR;
+       if (!strcmp("OFF", tmp_str))
+               state->high_resolution = FALSE;
+       else
+               state->high_resolution = TRUE;
+       g_free(tmp_str);
+
+       if (sr_scpi_get_string(sdi->conn,
+                            (*config->scpi_dialect)[SCPI_CMD_GET_PEAK_DETECTION],
+                            &tmp_str) != SR_OK)
+               return SR_ERR;
+       if (!strcmp("OFF", tmp_str))
+               state->peak_detection = FALSE;
+       else
+               state->peak_detection = TRUE;
+       g_free(tmp_str);
+
        if (hmo_update_sample_rate(sdi) != SR_OK)
                return SR_ERR;
 
@@ -1175,6 +1299,7 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
        unsigned int i, j, group;
        struct sr_channel *ch;
        struct dev_context *devc;
+       const char *cg_name;
        int ret;
 
        devc = sdi->priv;
@@ -1197,6 +1322,9 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
                return SR_ERR_NA;
        }
 
+       /* Configure the number of PODs given the number of digital channels. */
+       scope_models[model_index].digital_pods = scope_models[model_index].digital_channels / DIGITAL_CHANNELS_PER_POD;
+
        devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
                                        scope_models[model_index].analog_channels);
        devc->digital_groups = g_malloc0(sizeof(struct sr_channel_group*) *
@@ -1212,27 +1340,20 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
                ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE,
                           (*scope_models[model_index].analog_names)[i]);
 
-               devc->analog_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
-
-               devc->analog_groups[i]->name = g_strdup(
-                       (char *)(*scope_models[model_index].analog_names)[i]);
+               cg_name = (*scope_models[model_index].analog_names)[i];
+               devc->analog_groups[i] = sr_channel_group_new(sdi, cg_name, NULL);
                devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
-
-               sdi->channel_groups = g_slist_append(sdi->channel_groups,
-                                                  devc->analog_groups[i]);
        }
 
        /* Add digital channel groups. */
        ret = SR_OK;
        for (i = 0; i < scope_models[model_index].digital_pods; i++) {
-               devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
+               devc->digital_groups[i] = sr_channel_group_new(sdi, NULL, NULL);
                if (!devc->digital_groups[i]) {
                        ret = SR_ERR_MALLOC;
                        break;
                }
                devc->digital_groups[i]->name = g_strdup_printf("POD%d", i + 1);
-               sdi->channel_groups = g_slist_append(sdi->channel_groups,
-                                  devc->digital_groups[i]);
        }
        if (ret != SR_OK)
                return ret;
@@ -1242,7 +1363,7 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
                ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
                           (*scope_models[model_index].digital_names)[i]);
 
-               group = i / 8;
+               group = i / DIGITAL_CHANNELS_PER_POD;
                devc->digital_groups[group]->channels = g_slist_append(
                        devc->digital_groups[group]->channels, ch);
        }
@@ -1360,8 +1481,6 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
        (void)fd;
        (void)revents;
 
-       data = NULL;
-
        if (!(sdi = cb_data))
                return TRUE;
 
@@ -1382,16 +1501,15 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
         * Send "frame begin" packet upon reception of data for the
         * first enabled channel.
         */
-       if (devc->current_channel == devc->enabled_channels) {
-               packet.type = SR_DF_FRAME_BEGIN;
-               sr_session_send(sdi, &packet);
-       }
+       if (devc->current_channel == devc->enabled_channels)
+               std_session_send_df_frame_begin(sdi);
 
        /*
         * Pass on the received data of the channel(s).
         */
        switch (ch->type) {
        case SR_CHANNEL_ANALOG:
+               data = NULL;
                if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
                        if (data)
                                g_byte_array_free(data, TRUE);
@@ -1405,25 +1523,9 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
                /* Truncate acquisition if a smaller number of samples has been requested. */
                if (devc->samples_limit > 0 && analog.num_samples > devc->samples_limit)
                        analog.num_samples = devc->samples_limit;
-               analog.encoding = &encoding;
-               analog.meaning = &meaning;
-               analog.spec = &spec;
-
-               encoding.unitsize = sizeof(float);
-               encoding.is_signed = TRUE;
-               encoding.is_float = TRUE;
-#ifdef WORDS_BIGENDIAN
-               encoding.is_bigendian = TRUE;
-#else
-               encoding.is_bigendian = FALSE;
-#endif
                /* TODO: Use proper 'digits' value for this device (and its modes). */
-               encoding.digits = 2;
-               encoding.is_digits_decimal = FALSE;
-               encoding.scale.p = 1;
-               encoding.scale.q = 1;
-               encoding.offset.p = 0;
-               encoding.offset.q = 1;
+               sr_analog_init(&analog, &encoding, &meaning, &spec, 2);
+               encoding.is_signed = TRUE;
                if (state->analog_channels[ch->index].probe_unit == 'V') {
                        meaning.mq = SR_MQ_VOLTAGE;
                        meaning.unit = SR_UNIT_VOLT;
@@ -1431,10 +1533,7 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
                        meaning.mq = SR_MQ_CURRENT;
                        meaning.unit = SR_UNIT_AMPERE;
                }
-               meaning.mqflags = 0;
                meaning.channels = g_slist_append(NULL, ch);
-               /* TODO: Use proper 'digits' value for this device (and its modes). */
-               spec.spec_digits = 2;
                packet.payload = &analog;
                sr_session_send(sdi, &packet);
                devc->num_samples = data->len / sizeof(float);
@@ -1443,6 +1542,7 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
                data = NULL;
                break;
        case SR_CHANNEL_LOGIC:
+               data = NULL;
                if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
                        if (data)
                                g_byte_array_free(data, TRUE);
@@ -1473,7 +1573,7 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
                        packet.payload = &logic;
                        sr_session_send(sdi, &packet);
                } else {
-                       group = ch->index / 8;
+                       group = ch->index / DIGITAL_CHANNELS_PER_POD;
                        hmo_queue_logic_data(devc, group, data);
                }
 
@@ -1506,8 +1606,7 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
         */
        hmo_cleanup_logic_data(devc);
 
-       packet.type = SR_DF_FRAME_END;
-       sr_session_send(sdi, &packet);
+       std_session_send_df_frame_end(sdi);
 
        /*
         * End of frame was reached. Stop acquisition after the specified