X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Frigol-dg%2Fapi.c;h=e8a3aadc8acd4ea2fd8edaa2824bb114abb42f31;hb=deb7615262ac4f9cc0750a08351afa7cbf9c34d5;hp=3ae40bcf72aa0f5086bb01988f5ee9113b2a7749;hpb=02feeb30b992a5e8a1115348d3a319731954e564;p=libsigrok.git diff --git a/src/hardware/rigol-dg/api.c b/src/hardware/rigol-dg/api.c index 3ae40bcf..e8a3aadc 100644 --- a/src/hardware/rigol-dg/api.c +++ b/src/hardware/rigol-dg/api.c @@ -52,14 +52,116 @@ static const double phase_min_max_step[] = { 0.0, 360.0, 0.001 }; #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[] = { @@ -68,13 +170,13 @@ 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[] = { @@ -83,13 +185,13 @@ 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[] = { @@ -126,6 +228,60 @@ static const struct scpi_command cmdset_dg1000z[] = { }; 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), @@ -146,6 +302,27 @@ static const struct device_spec device_models[] = { }, }; +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; @@ -181,7 +358,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) 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); @@ -190,11 +367,11 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) 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; @@ -203,7 +380,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) 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)); + cg = g_malloc0(sizeof(*cg)); snprintf(tmp, sizeof(tmp), "%u", i + 1); cg->name = g_strdup(tmp); cg->channels = g_slist_append(cg->channels, ch); @@ -226,6 +403,9 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) sr_scpi_hw_info_free(hw_info); + /* Check for device/firmware specific issues. */ + check_device_quirks(sdi); + return sdi; error: @@ -334,6 +514,8 @@ static int config_get(uint32_t key, GVariant **data, *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) { @@ -571,6 +753,9 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) struct sr_scpi_dev_inst *scpi; const char *cmd; char *response; + GVariant *data; + gboolean need_quirk; + gboolean ch_active; int ret; if (!sdi) @@ -579,6 +764,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) devc = sdi->priv; scpi = sdi->conn; response = NULL; + data = NULL; ret = SR_OK; if (!scpi) @@ -594,15 +780,48 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) 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); } } @@ -616,8 +835,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) } } - g_free(response); - return ret; } @@ -639,10 +856,13 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi) 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);