#define WAVEFORM_DEFAULT WFO_FREQUENCY | WFO_AMPLITUDE | WFO_OFFSET | WFO_PHASE
+static const struct waveform_spec dg810_waveforms[] = {
+ { "SIN", WF_SINE, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 5.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 0.2E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 5.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 5.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+};
+
+static const struct channel_spec dg811_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg810_waveforms) },
+};
+
+static const struct channel_spec dg812_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg810_waveforms) },
+ { "CH2", ARRAY_AND_SIZE(dg810_waveforms) },
+};
+
+static const struct waveform_spec dg820_waveforms[] = {
+ { "SIN", WF_SINE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+};
+
+static const struct channel_spec dg821_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg820_waveforms) },
+};
+
+static const struct channel_spec dg822_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg820_waveforms) },
+ { "CH2", ARRAY_AND_SIZE(dg820_waveforms) },
+};
+
+static const struct waveform_spec dg830_waveforms[] = {
+ { "SIN", WF_SINE, 1.0E-6, 35.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 1.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+};
+
+static const struct channel_spec dg831_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg830_waveforms) },
+};
+
+static const struct channel_spec dg832_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg830_waveforms) },
+ { "CH2", ARRAY_AND_SIZE(dg830_waveforms) },
+};
+
+static const struct waveform_spec dg952_waveforms[] = {
+ { "SIN", WF_SINE, 1.0E-6, 50.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 1.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 15.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+};
+
+static const struct channel_spec dg952_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg952_waveforms) },
+ { "CH2", ARRAY_AND_SIZE(dg952_waveforms) },
+};
+
+static const struct waveform_spec dg972_waveforms[] = {
+ { "SIN", WF_SINE, 1.0E-6, 70.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 20.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 1.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 20.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 20.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+};
+
+static const struct channel_spec dg972_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg972_waveforms) },
+ { "CH2", ARRAY_AND_SIZE(dg972_waveforms) },
+};
+
+static const struct waveform_spec dg992_waveforms[] = {
+ { "SIN", WF_SINE, 1.0E-6, 100.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 2.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+};
+
+static const struct channel_spec dg992_channels[] = {
+ { "CH1", ARRAY_AND_SIZE(dg992_waveforms) },
+ { "CH2", ARRAY_AND_SIZE(dg992_waveforms) },
+};
+
static const struct waveform_spec dg1022z_waveforms[] = {
- { "SIN", WF_SINE, 1.0E-6, 2.5E+7, 1.0E-6, WAVEFORM_DEFAULT },
- { "SQU", WF_SQUARE, 1.0E-6, 2.5E+7, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
- { "RAMP", WF_RAMP, 1.0E-6, 0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
- { "PULSE", WF_PULSE, 1.0E-6, 1.5E+7, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
- { "USER", WF_ARB, 1.0E-6, 1.0E+7, 1.0E-6, WAVEFORM_DEFAULT },
- { "NOISE", WF_NOISE, 2.5E+7, 2.5E+7, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
- { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+ { "SIN", WF_SINE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 25.0E+6, 25.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
};
static const struct channel_spec dg1022z_channels[] = {
};
static const struct waveform_spec dg1032z_waveforms[] = {
- { "SIN", WF_SINE, 1.0E-6, 3.0E+7, 1.0E-6, WAVEFORM_DEFAULT },
- { "SQU", WF_SQUARE, 1.0E-6, 2.5E+7, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
- { "RAMP", WF_RAMP, 1.0E-6, 0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
- { "PULSE", WF_PULSE, 1.0E-6, 1.5E+7, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
- { "USER", WF_ARB, 1.0E-6, 1.0E+7, 1.0E-6, WAVEFORM_DEFAULT },
- { "NOISE", WF_NOISE, 3.0E+7, 3.0E+7, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
- { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+ { "SIN", WF_SINE, 1.0E-6, 30.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 30.0E+6, 30.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0 , 0.0E+0, 0.0E-0, WFO_OFFSET },
};
static const struct channel_spec dg1032z_channels[] = {
};
static const struct waveform_spec dg1062z_waveforms[] = {
- { "SIN", WF_SINE, 1.0E-6, 6.0E+7, 1.0E-6, WAVEFORM_DEFAULT },
- { "SQU", WF_SQUARE, 1.0E-6, 2.5E+7, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
- { "RAMP", WF_RAMP, 1.0E-6, 1.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
- { "PULSE", WF_PULSE, 1.0E-6, 2.5E+7, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
- { "USER", WF_ARB, 1.0E-6, 2.0E+7, 1.0E-6, WAVEFORM_DEFAULT },
- { "NOISE", WF_NOISE, 6.0E+7, 6.0E+7, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
- { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
+ { "SIN", WF_SINE, 1.0E-6, 60.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "SQU", WF_SQUARE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "RAMP", WF_RAMP, 1.0E-6, 1.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "PULSE", WF_PULSE, 1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
+ { "USER", WF_ARB, 1.0E-6, 20.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
+ { "NOISE", WF_NOISE, 60.0E+6, 60.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
+ { "DC", WF_DC, 0.0E-0, 0.0E+0, 0.0E-0, WFO_OFFSET },
};
static const struct channel_spec dg1062z_channels[] = {
};
static const struct device_spec device_models[] = {
+ { "Rigol Technologies", "DG811",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg811_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG812",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg812_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG821",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg821_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG822",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg822_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG831",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg831_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG832",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg832_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG952",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg952_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG972",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg972_channels),
+ cmdset_dg1000z,
+ },
+ { "Rigol Technologies", "DG992",
+ ARRAY_AND_SIZE(dg1000z_devopts),
+ ARRAY_AND_SIZE(dg1000z_devopts_cg),
+ ARRAY_AND_SIZE(dg992_channels),
+ cmdset_dg1000z,
+ },
{ "Rigol Technologies", "DG1022Z",
ARRAY_AND_SIZE(dg1000z_devopts),
ARRAY_AND_SIZE(dg1000z_devopts_cg),
},
};
+static void check_device_quirks(struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ gboolean is_8xx, is_9xx;
+
+ devc = sdi->priv;
+
+ /*
+ * Check for counter issue in DG800/DG900 units...
+ *
+ * TODO: Add firmware version check if Rigol fixes this issue
+ * in future firmware versions.
+ */
+ is_8xx = g_ascii_strncasecmp(sdi->model, "DG8", strlen("DG8")) == 0;
+ is_9xx = g_ascii_strncasecmp(sdi->model, "DG9", strlen("DG9")) == 0;
+ if (is_8xx || is_9xx) {
+ devc->quirks |= RIGOL_DG_COUNTER_BUG;
+ devc->quirks |= RIGOL_DG_COUNTER_CH2_CONFLICT;
+ }
+}
+
static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
{
struct sr_dev_inst *sdi;
if (!device)
goto error;
- sdi = g_malloc0(sizeof(struct sr_dev_inst));
+ sdi = g_malloc0(sizeof(*sdi));
sdi->vendor = g_strdup(hw_info->manufacturer);
sdi->model = g_strdup(hw_info->model);
sdi->version = g_strdup(hw_info->firmware_version);
sdi->driver = &rigol_dg_driver_info;
sdi->inst_type = SR_INST_SCPI;
- devc = g_malloc0(sizeof(struct dev_context));
+ devc = g_malloc0(sizeof(*devc));
devc->cmdset = cmdset;
devc->device = device;
- devc->ch_status = g_malloc0(sizeof(struct channel_status) *
- (device->num_channels + 1));
+ devc->ch_status = g_malloc0((device->num_channels + 1) *
+ sizeof(devc->ch_status[0]));
sr_sw_limits_init(&devc->limits);
sdi->priv = devc;
for (i = 0; i < device->num_channels; i++) {
ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE,
device->channels[i].name);
- cg = g_malloc0(sizeof(struct sr_channel_group));
snprintf(tmp, sizeof(tmp), "%u", i + 1);
- cg->name = g_strdup(tmp);
+ cg = sr_channel_group_new(sdi, tmp, NULL);
cg->channels = g_slist_append(cg->channels, ch);
-
- sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
}
/* Create channels for the frequency counter output. */
sr_scpi_hw_info_free(hw_info);
+ /* Check for device/firmware specific issues. */
+ check_device_quirks(sdi);
+
return sdi;
error:
*data = g_variant_new_double(ch_status->phase);
break;
case SR_CONF_DUTY_CYCLE:
+ if ((ret = rigol_dg_get_channel_state(sdi, cg)) != SR_OK)
+ break;
if (ch_status->wf == WF_SQUARE) {
cmd = PSG_CMD_GET_DCYCL_SQUARE;
} else if (ch_status->wf == WF_PULSE) {
struct sr_scpi_dev_inst *scpi;
const char *cmd;
char *response;
+ GVariant *data;
+ gboolean need_quirk;
+ gboolean ch_active;
int ret;
if (!sdi)
devc = sdi->priv;
scpi = sdi->conn;
response = NULL;
+ data = NULL;
ret = SR_OK;
if (!scpi)
devc->counter_enabled = TRUE;
else
devc->counter_enabled = FALSE;
+ g_free(response);
if (!devc->counter_enabled) {
- /* Enable counter if it was not already running. */
+ /*
+ * Enable counter if it was not already running.
+ * Some devices cannot use channel 2 and the counter
+ * at the same time. Some cannot respond right after
+ * enabling the counter and need a delay.
+ */
+
+ need_quirk = devc->quirks & RIGOL_DG_COUNTER_CH2_CONFLICT;
+ need_quirk &= devc->device->num_channels > 1;
+ if (need_quirk) {
+ sr_scpi_get_opc(scpi);
+ ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
+ PSG_CMD_SELECT_CHANNEL, "2",
+ &data, G_VARIANT_TYPE_BOOLEAN,
+ PSG_CMD_GET_ENABLED, "2");
+ if (ret != SR_OK)
+ return SR_ERR_NA;
+ ch_active = g_variant_get_boolean(data);
+ g_variant_unref(data);
+ if (ch_active) {
+ sr_scpi_get_opc(scpi);
+ ret = sr_scpi_cmd(sdi, devc->cmdset,
+ PSG_CMD_SELECT_CHANNEL, "2",
+ PSG_CMD_SET_DISABLE, "2");
+ if (ret != SR_OK)
+ return SR_ERR_NA;
+ }
+ }
+
cmd = sr_scpi_cmd_get(devc->cmdset,
PSG_CMD_COUNTER_SET_ENABLE);
if (!cmd)
return SR_ERR_BUG;
sr_scpi_get_opc(scpi);
ret = sr_scpi_send(scpi, cmd);
+
+ need_quirk = devc->quirks & RIGOL_DG_COUNTER_BUG;
+ if (need_quirk)
+ g_usleep(RIGOL_DG_COUNTER_BUG_DELAY);
}
}
}
}
- g_free(response);
-
return ret;
}
if (cmd && *cmd && !devc->counter_enabled) {
/*
* If counter was not running when acquisiton started,
- * turn it off now...
+ * turn it off now. Some devices need a delay after
+ * disabling the counter.
*/
sr_scpi_get_opc(scpi);
ret = sr_scpi_send(scpi, cmd);
+ if (devc->quirks & RIGOL_DG_COUNTER_BUG)
+ g_usleep(RIGOL_DG_COUNTER_BUG_DELAY);
}
sr_scpi_source_remove(sdi->session, scpi);