X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fhardware%2Frigol-dg%2Fapi.c;h=e8a3aadc8acd4ea2fd8edaa2824bb114abb42f31;hb=deb7615262ac4f9cc0750a08351afa7cbf9c34d5;hp=ddc0c72db56e296a61ff2bdb467cdd8cd5554c95;hpb=5a0303474c2408038e3350f948e2014fb55861b1;p=libsigrok.git diff --git a/src/hardware/rigol-dg/api.c b/src/hardware/rigol-dg/api.c index ddc0c72d..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; @@ -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);