X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Frigol-ds%2Fapi.c;h=59e29fb9e2a36624234683ca9b0fab89dad14caf;hb=HEAD;hp=da1fe25054848ecf5e091cb13a292fc084fded7d;hpb=53b4680fceab9351fc87b8c5b34854733f5fdac0;p=libsigrok.git diff --git a/hardware/rigol-ds/api.c b/hardware/rigol-ds/api.c deleted file mode 100644 index da1fe250..00000000 --- a/hardware/rigol-ds/api.c +++ /dev/null @@ -1,1023 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2012 Martin Ling - * Copyright (C) 2013 Bert Vermeulen - * Copyright (C) 2013 Mathias Grimmberger - * - * 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 - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "protocol.h" - -static const int32_t hwopts[] = { - SR_CONF_CONN, - SR_CONF_SERIALCOMM -}; - -static const int32_t hwcaps[] = { - SR_CONF_OSCILLOSCOPE, - SR_CONF_TIMEBASE, - SR_CONF_TRIGGER_SOURCE, - SR_CONF_TRIGGER_SLOPE, - SR_CONF_HORIZ_TRIGGERPOS, - SR_CONF_NUM_TIMEBASE, - SR_CONF_LIMIT_FRAMES, - SR_CONF_SAMPLERATE, -}; - -static const int32_t analog_hwcaps[] = { - SR_CONF_NUM_VDIV, - SR_CONF_VDIV, - SR_CONF_COUPLING, - SR_CONF_DATA_SOURCE, -}; - -static const uint64_t timebases[][2] = { - /* nanoseconds */ - { 1, 1000000000 }, - { 2, 1000000000 }, - { 5, 1000000000 }, - { 10, 1000000000 }, - { 20, 1000000000 }, - { 50, 1000000000 }, - { 100, 1000000000 }, - { 500, 1000000000 }, - /* microseconds */ - { 1, 1000000 }, - { 2, 1000000 }, - { 5, 1000000 }, - { 10, 1000000 }, - { 20, 1000000 }, - { 50, 1000000 }, - { 100, 1000000 }, - { 200, 1000000 }, - { 500, 1000000 }, - /* milliseconds */ - { 1, 1000 }, - { 2, 1000 }, - { 5, 1000 }, - { 10, 1000 }, - { 20, 1000 }, - { 50, 1000 }, - { 100, 1000 }, - { 200, 1000 }, - { 500, 1000 }, - /* seconds */ - { 1, 1 }, - { 2, 1 }, - { 5, 1 }, - { 10, 1 }, - { 20, 1 }, - { 50, 1 }, - { 100, 1 }, - { 200, 1 }, - { 500, 1 }, - { 1000, 1 }, -}; - -static const uint64_t vdivs[][2] = { - /* microvolts */ - { 500, 1000000 }, - /* millivolts */ - { 1, 1000 }, - { 2, 1000 }, - { 5, 1000 }, - { 10, 1000 }, - { 20, 1000 }, - { 50, 1000 }, - { 100, 1000 }, - { 200, 1000 }, - { 500, 1000 }, - /* volts */ - { 1, 1 }, - { 2, 1 }, - { 5, 1 }, - { 10, 1 }, -}; - -#define NUM_TIMEBASE ARRAY_SIZE(timebases) -#define NUM_VDIV ARRAY_SIZE(vdivs) - -static const char *trigger_sources[] = { - "CH1", - "CH2", - "CH3", - "CH4", - "EXT", - "AC Line", - "D0", - "D1", - "D2", - "D3", - "D4", - "D5", - "D6", - "D7", - "D8", - "D9", - "D10", - "D11", - "D12", - "D13", - "D14", - "D15", -}; - -static const char *coupling[] = { - "AC", - "DC", - "GND", -}; - -/* Do not change the order of entries */ -static const char *data_sources[] = { - "Live", - "Memory", - "Segmented", -}; - -enum vendor { - RIGOL, - AGILENT, -}; - -enum series { - VS5000, - DS1000, - DS2000, - DS2000A, - DSO1000, -}; - -/* short name, full name */ -static const struct rigol_ds_vendor supported_vendors[] = { - [RIGOL] = {"Rigol", "Rigol Technologies"}, - [AGILENT] = {"Agilent", "Rigol Technologies"}, -}; - -#define VENDOR(x) &supported_vendors[x] -/* vendor, series, protocol, max timebase, min vdiv, number of horizontal divs, - * live waveform samples, memory buffer samples */ -static const struct rigol_ds_series supported_series[] = { - [VS5000] = {VENDOR(RIGOL), "VS5000", PROTOCOL_V1, FORMAT_RAW, - {50, 1}, {2, 1000}, 14, 2048, 0}, - [DS1000] = {VENDOR(RIGOL), "DS1000", PROTOCOL_V2, FORMAT_IEEE488_2, - {50, 1}, {2, 1000}, 12, 600, 1048576}, - [DS2000] = {VENDOR(RIGOL), "DS2000", PROTOCOL_V3, FORMAT_IEEE488_2, - {500, 1}, {2, 1000}, 14, 1400, 14000}, - [DS2000A] = {VENDOR(RIGOL), "DS2000A", PROTOCOL_V3, FORMAT_IEEE488_2, - {1000, 1}, {500, 1000000}, 14, 1400, 14000}, - [DSO1000] = {VENDOR(AGILENT), "DSO1000", PROTOCOL_V3, FORMAT_IEEE488_2, - {50, 1}, {2, 1000}, 12, 600, 20480}, -}; - -#define SERIES(x) &supported_series[x] -/* series, model, min timebase, analog channels, digital */ -static const struct rigol_ds_model supported_models[] = { - {SERIES(VS5000), "VS5022", {20, 1000000000}, 2, false}, - {SERIES(VS5000), "VS5042", {10, 1000000000}, 2, false}, - {SERIES(VS5000), "VS5062", {5, 1000000000}, 2, false}, - {SERIES(VS5000), "VS5102", {2, 1000000000}, 2, false}, - {SERIES(VS5000), "VS5202", {2, 1000000000}, 2, false}, - {SERIES(VS5000), "VS5022D", {20, 1000000000}, 2, true}, - {SERIES(VS5000), "VS5042D", {10, 1000000000}, 2, true}, - {SERIES(VS5000), "VS5062D", {5, 1000000000}, 2, true}, - {SERIES(VS5000), "VS5102D", {2, 1000000000}, 2, true}, - {SERIES(VS5000), "VS5202D", {2, 1000000000}, 2, true}, - {SERIES(DS1000), "DS1052E", {5, 1000000000}, 2, false}, - {SERIES(DS1000), "DS1102E", {2, 1000000000}, 2, false}, - {SERIES(DS1000), "DS1152E", {2, 1000000000}, 2, false}, - {SERIES(DS1000), "DS1052D", {5, 1000000000}, 2, true}, - {SERIES(DS1000), "DS1102D", {2, 1000000000}, 2, true}, - {SERIES(DS1000), "DS1152D", {2, 1000000000}, 2, true}, - {SERIES(DS2000), "DS2072", {5, 1000000000}, 2, false}, - {SERIES(DS2000), "DS2102", {5, 1000000000}, 2, false}, - {SERIES(DS2000), "DS2202", {2, 1000000000}, 2, false}, - {SERIES(DS2000), "DS2302", {1, 1000000000}, 2, false}, - {SERIES(DS2000A), "DS2072A", {5, 1000000000}, 2, false}, - {SERIES(DS2000A), "DS2102A", {5, 1000000000}, 2, false}, - {SERIES(DS2000A), "DS2202A", {2, 1000000000}, 2, false}, - {SERIES(DS2000A), "DS2302A", {1, 1000000000}, 2, false}, - {SERIES(DSO1000), "DSO1002A", {5, 1000000000}, 2, false}, - {SERIES(DSO1000), "DSO1004A", {5, 1000000000}, 4, false}, - {SERIES(DSO1000), "DSO1012A", {2, 1000000000}, 2, false}, - {SERIES(DSO1000), "DSO1014A", {2, 1000000000}, 4, false}, - {SERIES(DSO1000), "DSO1022A", {2, 1000000000}, 2, false}, - {SERIES(DSO1000), "DSO1024A", {2, 1000000000}, 4, false}, -}; - -SR_PRIV struct sr_dev_driver rigol_ds_driver_info; -static struct sr_dev_driver *di = &rigol_ds_driver_info; - -static void clear_helper(void *priv) -{ - struct dev_context *devc; - - devc = priv; - g_free(devc->data); - g_free(devc->buffer); - g_free(devc->coupling[0]); - g_free(devc->coupling[1]); - g_free(devc->trigger_source); - g_free(devc->trigger_slope); - g_slist_free(devc->analog_groups[0].channels); - g_slist_free(devc->analog_groups[1].channels); - g_slist_free(devc->digital_group.channels); -} - -static int dev_clear(void) -{ - return std_dev_clear(di, clear_helper); -} - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) -{ - struct dev_context *devc; - struct sr_dev_inst *sdi; - struct sr_scpi_hw_info *hw_info; - struct sr_probe *probe; - long n[3]; - unsigned int i; - const struct rigol_ds_model *model = NULL; - gchar *channel_name, **version; - - if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) { - sr_info("Couldn't get IDN response."); - sr_scpi_close(scpi); - sr_scpi_free(scpi); - return NULL; - } - - for (i = 0; i < ARRAY_SIZE(supported_models); i++) { - if (!strcasecmp(hw_info->manufacturer, - supported_models[i].series->vendor->full_name) && - !strcmp(hw_info->model, supported_models[i].name)) { - model = &supported_models[i]; - break; - } - } - - if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, - model->series->vendor->name, - model->name, - hw_info->firmware_version))) { - sr_scpi_hw_info_free(hw_info); - sr_scpi_close(scpi); - sr_scpi_free(scpi); - return NULL; - } - - sr_scpi_close(scpi); - - sdi->conn = scpi; - - sdi->driver = di; - sdi->inst_type = SR_INST_SCPI; - - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) - return NULL; - - devc->limit_frames = 0; - devc->model = model; - devc->format = model->series->format; - - /* DS1000 models with firmware before 0.2.4 used the old data format. */ - if (model->series == SERIES(DS1000)) { - version = g_strsplit(hw_info->firmware_version, ".", 0); - do { - if (!version[0] || !version[1] || !version[2]) - break; - if (version[0][0] == 0 || version[1][0] == 0 || version[2][0] == 0) - break; - for (i = 0; i < 3; i++) { - if (sr_atol(version[i], &n[i]) != SR_OK) - break; - } - if (i != 3) - break; - if (n[0] != 0 || n[1] > 2) - break; - if (n[1] == 2 && n[2] > 3) - break; - sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format."); - devc->format = FORMAT_RAW; - } while(0); - g_strfreev(version); - } - - sr_scpi_hw_info_free(hw_info); - - for (i = 0; i < model->analog_channels; i++) { - if (!(channel_name = g_strdup_printf("CH%d", i + 1))) - return NULL; - probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name); - sdi->probes = g_slist_append(sdi->probes, probe); - devc->analog_groups[i].name = channel_name; - devc->analog_groups[i].channels = g_slist_append(NULL, probe); - sdi->channel_groups = g_slist_append(sdi->channel_groups, - &devc->analog_groups[i]); - } - - if (devc->model->has_digital) { - for (i = 0; i < 16; i++) { - if (!(channel_name = g_strdup_printf("D%d", i))) - return NULL; - probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name); - g_free(channel_name); - if (!probe) - return NULL; - sdi->probes = g_slist_append(sdi->probes, probe); - devc->digital_group.channels = g_slist_append( - devc->digital_group.channels, probe); - } - devc->digital_group.name = "LA"; - sdi->channel_groups = g_slist_append(sdi->channel_groups, - &devc->digital_group); - } - - for (i = 0; i < NUM_TIMEBASE; i++) { - if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2]))) - devc->timebases = &timebases[i]; - if (!memcmp(&devc->model->series->max_timebase, &timebases[i], sizeof(uint64_t[2]))) - devc->num_timebases = &timebases[i] - devc->timebases + 1; - } - - for (i = 0; i < NUM_VDIV; i++) - if (!memcmp(&devc->model->series->min_vdiv, &vdivs[i], sizeof(uint64_t[2]))) - devc->vdivs = &vdivs[i]; - - if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE))) - return NULL; - if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float)))) - return NULL; - - devc->data_source = DATA_SOURCE_LIVE; - - sdi->priv = devc; - - return sdi; -} - -static GSList *scan(GSList *options) -{ - return sr_scpi_scan(di->priv, options, probe_device); -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct sr_scpi_dev_inst *scpi = sdi->conn; - - if (sr_scpi_open(scpi) < 0) - return SR_ERR; - - if (rigol_ds_get_dev_cfg(sdi) != SR_OK) - return SR_ERR; - - sdi->status = SR_ST_ACTIVE; - - return SR_OK; -} - -static int dev_close(struct sr_dev_inst *sdi) -{ - struct sr_scpi_dev_inst *scpi; - struct dev_context *devc; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - scpi = sdi->conn; - devc = sdi->priv; - - if (devc->model->series->protocol == PROTOCOL_V2) - rigol_ds_config_set(sdi, ":KEY:LOCK DISABLE"); - - if (scpi) { - if (sr_scpi_close(scpi) < 0) - return SR_ERR; - sdi->status = SR_ST_INACTIVE; - } - - return SR_OK; -} - -static int cleanup(void) -{ - return dev_clear(); -} - -static int analog_frame_size(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc = sdi->priv; - struct sr_probe *probe; - int analog_probes = 0; - GSList *l; - - for (l = sdi->probes; l; l = l->next) { - probe = l->data; - if (probe->type == SR_PROBE_ANALOG && probe->enabled) - analog_probes++; - } - - if (analog_probes == 0) - return 0; - - switch (devc->data_source) { - case DATA_SOURCE_LIVE: - return devc->model->series->live_samples; - case DATA_SOURCE_MEMORY: - return devc->model->series->buffer_samples / analog_probes; - default: - return 0; - } -} - -static int digital_frame_size(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc = sdi->priv; - - switch (devc->data_source) { - case DATA_SOURCE_LIVE: - return devc->model->series->live_samples * 2; - case DATA_SOURCE_MEMORY: - return devc->model->series->buffer_samples * 2; - default: - return 0; - } -} - -static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - struct sr_probe *probe; - const char *tmp_str; - uint64_t samplerate; - int analog_channel = -1; - float smallest_diff = 0.0000000001; - int idx = -1; - unsigned i; - - if (!sdi || !(devc = sdi->priv)) - return SR_ERR_ARG; - - /* If a channel group is specified, it must be a valid one. */ - if (cg && !g_slist_find(sdi->channel_groups, cg)) { - sr_err("Invalid channel group specified."); - return SR_ERR; - } - - if (cg) { - probe = g_slist_nth_data(cg->channels, 0); - if (!probe) - return SR_ERR; - if (probe->type == SR_PROBE_ANALOG) { - if (probe->name[2] < '1' || probe->name[2] > '4') - return SR_ERR; - analog_channel = probe->name[2] - '1'; - } - } - - switch (id) { - case SR_CONF_NUM_TIMEBASE: - *data = g_variant_new_int32(devc->model->series->num_horizontal_divs); - break; - case SR_CONF_NUM_VDIV: - *data = g_variant_new_int32(NUM_VDIV); - case SR_CONF_DATA_SOURCE: - if (devc->data_source == DATA_SOURCE_LIVE) - *data = g_variant_new_string("Live"); - else if (devc->data_source == DATA_SOURCE_MEMORY) - *data = g_variant_new_string("Memory"); - else - *data = g_variant_new_string("Segmented"); - break; - case SR_CONF_SAMPLERATE: - if (devc->data_source == DATA_SOURCE_LIVE) { - samplerate = analog_frame_size(sdi) / - (devc->timebase * devc->model->series->num_horizontal_divs); - *data = g_variant_new_uint64(samplerate); - } else { - return SR_ERR_NA; - } - break; - case SR_CONF_TRIGGER_SOURCE: - if (!strcmp(devc->trigger_source, "ACL")) - tmp_str = "AC Line"; - else if (!strcmp(devc->trigger_source, "CHAN1")) - tmp_str = "CH1"; - else if (!strcmp(devc->trigger_source, "CHAN2")) - tmp_str = "CH2"; - else if (!strcmp(devc->trigger_source, "CHAN3")) - tmp_str = "CH3"; - else if (!strcmp(devc->trigger_source, "CHAN4")) - tmp_str = "CH4"; - else - tmp_str = devc->trigger_source; - *data = g_variant_new_string(tmp_str); - break; - case SR_CONF_TIMEBASE: - for (i = 0; i < devc->num_timebases; i++) { - float tb = (float)devc->timebases[i][0] / devc->timebases[i][1]; - float diff = fabs(devc->timebase - tb); - if (diff < smallest_diff) { - smallest_diff = diff; - idx = i; - } - } - if (idx < 0) - return SR_ERR_NA; - *data = g_variant_new("(tt)", devc->timebases[idx][0], - devc->timebases[idx][1]); - break; - case SR_CONF_VDIV: - if (analog_channel < 0) - return SR_ERR_NA; - for (i = 0; i < ARRAY_SIZE(vdivs); i++) { - float vdiv = (float)vdivs[i][0] / vdivs[i][1]; - float diff = fabs(devc->vdiv[analog_channel] - vdiv); - if (diff < smallest_diff) { - smallest_diff = diff; - idx = i; - } - } - if (idx < 0) - return SR_ERR_NA; - *data = g_variant_new("(tt)", vdivs[idx][0], vdivs[idx][1]); - break; - case SR_CONF_COUPLING: - if (analog_channel < 0) - return SR_ERR_NA; - *data = g_variant_new_string(devc->coupling[analog_channel]); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - uint64_t p, q; - double t_dbl; - unsigned int i, j; - int ret; - const char *tmp_str; - char buffer[16]; - - if (!(devc = sdi->priv)) - return SR_ERR_ARG; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - /* If a channel group is specified, it must be a valid one. */ - if (cg && !g_slist_find(sdi->channel_groups, cg)) { - sr_err("Invalid channel group specified."); - return SR_ERR; - } - - ret = SR_OK; - switch (id) { - case SR_CONF_LIMIT_FRAMES: - devc->limit_frames = g_variant_get_uint64(data); - break; - case SR_CONF_TRIGGER_SLOPE: - tmp_str = g_variant_get_string(data, NULL); - - if (!tmp_str || !(tmp_str[0] == 'f' || tmp_str[0] == 'r')) - return SR_ERR_ARG; - - g_free(devc->trigger_slope); - devc->trigger_slope = g_strdup((tmp_str[0] == 'r') ? "POS" : "NEG"); - ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope); - break; - case SR_CONF_HORIZ_TRIGGERPOS: - t_dbl = g_variant_get_double(data); - if (t_dbl < 0.0 || t_dbl > 1.0) - return SR_ERR; - devc->horiz_triggerpos = t_dbl; - /* We have the trigger offset as a percentage of the frame, but - * need to express this in seconds. */ - t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases; - g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl); - ret = rigol_ds_config_set(sdi, ":TIM:OFFS %s", buffer); - break; - case SR_CONF_TIMEBASE: - g_variant_get(data, "(tt)", &p, &q); - for (i = 0; i < devc->num_timebases; i++) { - if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) { - devc->timebase = (float)p / q; - g_ascii_formatd(buffer, sizeof(buffer), "%.9f", - devc->timebase); - ret = rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer); - break; - } - } - if (i == devc->num_timebases) - ret = SR_ERR_ARG; - break; - case SR_CONF_TRIGGER_SOURCE: - tmp_str = g_variant_get_string(data, NULL); - for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) { - if (!strcmp(trigger_sources[i], tmp_str)) { - g_free(devc->trigger_source); - devc->trigger_source = g_strdup(trigger_sources[i]); - if (!strcmp(devc->trigger_source, "AC Line")) - tmp_str = "ACL"; - else if (!strcmp(devc->trigger_source, "CH1")) - tmp_str = "CHAN1"; - else if (!strcmp(devc->trigger_source, "CH2")) - tmp_str = "CHAN2"; - else if (!strcmp(devc->trigger_source, "CH3")) - tmp_str = "CHAN3"; - else if (!strcmp(devc->trigger_source, "CH4")) - tmp_str = "CHAN4"; - else - tmp_str = (char *)devc->trigger_source; - ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str); - break; - } - } - if (i == ARRAY_SIZE(trigger_sources)) - ret = SR_ERR_ARG; - break; - case SR_CONF_VDIV: - if (!cg) { - sr_err("No channel group specified."); - return SR_ERR_CHANNEL_GROUP; - } - g_variant_get(data, "(tt)", &p, &q); - for (i = 0; i < 2; i++) { - if (cg == &devc->analog_groups[i]) { - for (j = 0; j < ARRAY_SIZE(vdivs); j++) { - if (vdivs[j][0] != p || vdivs[j][1] != q) - continue; - devc->vdiv[i] = (float)p / q; - g_ascii_formatd(buffer, sizeof(buffer), "%.3f", - devc->vdiv[i]); - return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1, - buffer); - } - return SR_ERR_ARG; - } - } - return SR_ERR_NA; - case SR_CONF_COUPLING: - if (!cg) { - sr_err("No channel group specified."); - return SR_ERR_CHANNEL_GROUP; - } - tmp_str = g_variant_get_string(data, NULL); - for (i = 0; i < 2; i++) { - if (cg == &devc->analog_groups[i]) { - for (j = 0; j < ARRAY_SIZE(coupling); j++) { - if (!strcmp(tmp_str, coupling[j])) { - g_free(devc->coupling[i]); - devc->coupling[i] = g_strdup(coupling[j]); - return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1, - devc->coupling[i]); - } - } - return SR_ERR_ARG; - } - } - return SR_ERR_NA; - case SR_CONF_DATA_SOURCE: - tmp_str = g_variant_get_string(data, NULL); - if (!strcmp(tmp_str, "Live")) - devc->data_source = DATA_SOURCE_LIVE; - else if (devc->model->series->protocol >= PROTOCOL_V2 - && !strcmp(tmp_str, "Memory")) - devc->data_source = DATA_SOURCE_MEMORY; - else if (devc->model->series->protocol >= PROTOCOL_V3 - && !strcmp(tmp_str, "Segmented")) - devc->data_source = DATA_SOURCE_SEGMENTED; - else - return SR_ERR; - break; - default: - ret = SR_ERR_NA; - break; - } - - return ret; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - GVariant *tuple, *rational[2]; - GVariantBuilder gvb; - unsigned int i; - struct dev_context *devc = NULL; - - if (sdi) - devc = sdi->priv; - - if (key == SR_CONF_SCAN_OPTIONS) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t)); - return SR_OK; - } else if (key == SR_CONF_DEVICE_OPTIONS && cg == NULL) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - return SR_OK; - } - - /* Every other option requires a valid device instance. */ - if (!sdi || !(devc = sdi->priv)) - return SR_ERR_ARG; - - /* If a channel group is specified, it must be a valid one. */ - if (cg) { - if (cg != &devc->analog_groups[0] - && cg != &devc->analog_groups[1]) { - sr_err("Invalid channel group specified."); - return SR_ERR; - } - } - - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - if (!cg) { - sr_err("No channel group specified."); - return SR_ERR_CHANNEL_GROUP; - } - if (cg == &devc->digital_group) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - NULL, 0, sizeof(int32_t)); - return SR_OK; - } else { - for (i = 0; i < 2; i++) { - if (cg == &devc->analog_groups[i]) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t)); - return SR_OK; - } - } - return SR_ERR_NA; - } - break; - case SR_CONF_COUPLING: - if (!cg) { - sr_err("No channel group specified."); - return SR_ERR_CHANNEL_GROUP; - } - *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling)); - break; - case SR_CONF_VDIV: - if (!devc) - /* Can't know this until we have the exact model. */ - return SR_ERR_ARG; - if (!cg) { - sr_err("No channel group specified."); - return SR_ERR_CHANNEL_GROUP; - } - g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); - for (i = 0; i < NUM_VDIV; i++) { - rational[0] = g_variant_new_uint64(devc->vdivs[i][0]); - rational[1] = g_variant_new_uint64(devc->vdivs[i][1]); - tuple = g_variant_new_tuple(rational, 2); - g_variant_builder_add_value(&gvb, tuple); - } - *data = g_variant_builder_end(&gvb); - break; - case SR_CONF_TIMEBASE: - if (!devc) - /* Can't know this until we have the exact model. */ - return SR_ERR_ARG; - if (devc->num_timebases <= 0) - return SR_ERR_NA; - g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); - for (i = 0; i < devc->num_timebases; i++) { - rational[0] = g_variant_new_uint64(devc->timebases[i][0]); - rational[1] = g_variant_new_uint64(devc->timebases[i][1]); - tuple = g_variant_new_tuple(rational, 2); - g_variant_builder_add_value(&gvb, tuple); - } - *data = g_variant_builder_end(&gvb); - break; - case SR_CONF_TRIGGER_SOURCE: - if (!devc) - /* Can't know this until we have the exact model. */ - return SR_ERR_ARG; - *data = g_variant_new_strv(trigger_sources, - devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4); - break; - case SR_CONF_DATA_SOURCE: - if (!devc) - /* Can't know this until we have the exact model. */ - return SR_ERR_ARG; - switch (devc->model->series->protocol) { - case PROTOCOL_V1: - *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2); - break; - case PROTOCOL_V2: - *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1); - break; - default: - *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources)); - break; - } - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct sr_scpi_dev_inst *scpi; - struct dev_context *devc; - struct sr_probe *probe; - struct sr_datafeed_packet packet; - GSList *l; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - scpi = sdi->conn; - devc = sdi->priv; - - devc->num_frames = 0; - - for (l = sdi->probes; l; l = l->next) { - probe = l->data; - sr_dbg("handling probe %s", probe->name); - if (probe->type == SR_PROBE_ANALOG) { - if (probe->enabled) - devc->enabled_analog_probes = g_slist_append( - devc->enabled_analog_probes, probe); - if (probe->enabled != devc->analog_channels[probe->index]) { - /* Enabled channel is currently disabled, or vice versa. */ - if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", probe->index + 1, - probe->enabled ? "ON" : "OFF") != SR_OK) - return SR_ERR; - devc->analog_channels[probe->index] = probe->enabled; - } - } else if (probe->type == SR_PROBE_LOGIC) { - if (probe->enabled) { - devc->enabled_digital_probes = g_slist_append( - devc->enabled_digital_probes, probe); - /* Turn on LA module if currently off. */ - if (!devc->la_enabled) { - if (rigol_ds_config_set(sdi, ":LA:DISP ON") != SR_OK) - return SR_ERR; - devc->la_enabled = TRUE; - } - } - if (probe->enabled != devc->digital_channels[probe->index]) { - /* Enabled channel is currently disabled, or vice versa. */ - if (rigol_ds_config_set(sdi, ":DIG%d:TURN %s", probe->index, - probe->enabled ? "ON" : "OFF") != SR_OK) - return SR_ERR; - devc->digital_channels[probe->index] = probe->enabled; - } - } - } - - if (!devc->enabled_analog_probes && !devc->enabled_digital_probes) - return SR_ERR; - - /* Turn off LA module if on and no digital probes selected. */ - if (devc->la_enabled && !devc->enabled_digital_probes) - if (rigol_ds_config_set(sdi, ":LA:DISP OFF") != SR_OK) - return SR_ERR; - - /* Set memory mode. */ - if (devc->data_source == DATA_SOURCE_SEGMENTED) { - sr_err("Data source 'Segmented' not yet supported"); - return SR_ERR; - } - - devc->analog_frame_size = analog_frame_size(sdi); - devc->digital_frame_size = digital_frame_size(sdi); - - switch (devc->model->series->protocol) { - case PROTOCOL_V2: - if (rigol_ds_config_set(sdi, ":ACQ:MDEP LONG") != SR_OK) - return SR_ERR; - break; - case PROTOCOL_V3: - /* Apparently for the DS2000 the memory - * depth can only be set in Running state - - * this matches the behaviour of the UI. */ - if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) - return SR_ERR; - if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d", - devc->analog_frame_size) != SR_OK) - return SR_ERR; - if (rigol_ds_config_set(sdi, ":STOP") != SR_OK) - return SR_ERR; - break; - default: - break; - } - - if (devc->data_source == DATA_SOURCE_LIVE) - if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) - return SR_ERR; - - sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi); - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - if (devc->enabled_analog_probes) - devc->channel_entry = devc->enabled_analog_probes; - else - devc->channel_entry = devc->enabled_digital_probes; - - if (rigol_ds_capture_start(sdi) != SR_OK) - return SR_ERR; - - /* Start of first frame. */ - packet.type = SR_DF_FRAME_BEGIN; - sr_session_send(cb_data, &packet); - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - struct sr_scpi_dev_inst *scpi; - struct sr_datafeed_packet packet; - - (void)cb_data; - - devc = sdi->priv; - - if (sdi->status != SR_ST_ACTIVE) { - sr_err("Device inactive, can't stop acquisition."); - return SR_ERR; - } - - /* End of last frame. */ - packet.type = SR_DF_END; - sr_session_send(sdi, &packet); - - g_slist_free(devc->enabled_analog_probes); - g_slist_free(devc->enabled_digital_probes); - devc->enabled_analog_probes = NULL; - devc->enabled_digital_probes = NULL; - scpi = sdi->conn; - sr_scpi_source_remove(scpi); - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver rigol_ds_driver_info = { - .name = "rigol-ds", - .longname = "Rigol DS", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = dev_clear, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -};