From: Martin Ling Date: Sun, 14 Apr 2013 01:21:55 +0000 (+0100) Subject: rigol-ds1xx2: support digital channels. X-Git-Tag: dsupstream~160 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=6bb192bc05f976a5660e35c9507450a573679296;p=libsigrok.git rigol-ds1xx2: support digital channels. --- diff --git a/hardware/rigol-ds1xx2/api.c b/hardware/rigol-ds1xx2/api.c index ff8cccab..5e4198ce 100644 --- a/hardware/rigol-ds1xx2/api.c +++ b/hardware/rigol-ds1xx2/api.c @@ -102,6 +102,22 @@ static const char *trigger_sources[] = { "CH2", "EXT", "AC Line", + "D0", + "D1", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "D10", + "D11", + "D12", + "D13", + "D14", + "D15", }; static const char *coupling[] = { @@ -199,7 +215,9 @@ static GSList *hw_scan(GSList *options) gchar **tokens; const char *manufacturer, *model, *version; gboolean matched = FALSE; + gboolean has_digital = FALSE; char buf[256]; + gchar *channel_name; (void)options; @@ -254,6 +272,7 @@ static GSList *hw_scan(GSList *options) for (i = 0; i < ARRAY_SIZE(supported_models); i++) { if (!strcmp(model, supported_models[i])) { matched = 1; + has_digital = g_str_has_suffix(model, "D"); break; } } @@ -274,16 +293,29 @@ static GSList *hw_scan(GSList *options) } devc->limit_frames = 0; devc->device = device; + devc->has_digital = has_digital; sdi->priv = devc; sdi->driver = di; for (i = 0; i < 2; i++) { - if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, + if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, i == 0 ? "CH1" : "CH2"))) return NULL; sdi->probes = g_slist_append(sdi->probes, probe); } + if (devc->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); + } + } + drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); } @@ -469,8 +501,7 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) GVariant *tuple, *rational[2]; GVariantBuilder gvb; unsigned int i; - - (void)sdi; + struct dev_context *devc = sdi->priv; switch (key) { case SR_CONF_DEVICE_OPTIONS: @@ -502,7 +533,7 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) break; case SR_CONF_TRIGGER_SOURCE: *data = g_variant_new_strv(trigger_sources, - ARRAY_SIZE(trigger_sources)); + devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4); break; default: return SR_ERR_ARG; @@ -516,7 +547,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) struct dev_context *devc; struct sr_probe *probe; GSList *l; - int probenum; char cmd[256]; (void)cb_data; @@ -525,19 +555,32 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) for (l = sdi->probes; l; l = l->next) { probe = l->data; - probenum = probe->name[2] == '1' ? 0 : 1; - if (probe->enabled) - devc->enabled_probes = g_slist_append(devc->enabled_probes, probe); - - if (probe->enabled != devc->channels[probenum]) { - /* Enabled channel is currently disabled, or vice versa. */ - sprintf(cmd, ":CHAN%d:DISP %s", probenum + 1, - probe->enabled ? "ON" : "OFF"); - if (rigol_ds1xx2_send(devc, cmd) != SR_OK) - return SR_ERR; + 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. */ + sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1, + probe->enabled ? "ON" : "OFF"); + if (rigol_ds1xx2_send(devc, cmd) != SR_OK) + return SR_ERR; + } + } else if (probe->type == SR_PROBE_LOGIC) { + if (probe->enabled) + devc->enabled_digital_probes = g_slist_append( + devc->enabled_digital_probes, probe); + if (probe->enabled != devc->digital_channels[probe->index]) { + /* Enabled channel is currently disabled, or vice versa. */ + sprintf(cmd, ":DIG%d:TURN %s", probe->index, + probe->enabled ? "ON" : "OFF"); + if (rigol_ds1xx2_send(devc, cmd) != SR_OK) + return SR_ERR; + } } } - if (!devc->enabled_probes) + if (!devc->enabled_analog_probes && !devc->enabled_digital_probes) return SR_ERR; sr_source_add(devc->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi); @@ -546,10 +589,16 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN); /* Fetch the first frame. */ - devc->channel_frame = devc->enabled_probes->data; - if (rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%c", - devc->channel_frame->name[2]) != SR_OK) - return SR_ERR; + if (devc->enabled_analog_probes) { + devc->channel_frame = devc->enabled_analog_probes->data; + if (rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%d", + devc->channel_frame->index + 1) != SR_OK) + return SR_ERR; + } else { + devc->channel_frame = devc->enabled_digital_probes->data; + if (rigol_ds1xx2_send(devc, ":WAV:DATA? DIG") != SR_OK) + return SR_ERR; + } devc->num_frame_bytes = 0; @@ -569,8 +618,10 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) return SR_ERR; } - g_slist_free(devc->enabled_probes); - devc->enabled_probes = NULL; + g_slist_free(devc->enabled_analog_probes); + g_slist_free(devc->enabled_digital_probes); + devc->enabled_analog_probes = NULL; + devc->enabled_digital_probes = NULL; sr_source_remove(devc->fd); return SR_OK; diff --git a/hardware/rigol-ds1xx2/protocol.c b/hardware/rigol-ds1xx2/protocol.c index 95ff3263..d6dc70ad 100644 --- a/hardware/rigol-ds1xx2/protocol.c +++ b/hardware/rigol-ds1xx2/protocol.c @@ -35,10 +35,12 @@ SR_PRIV int rigol_ds1xx2_receive(int fd, int revents, void *cb_data) struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; - unsigned char buf[WAVEFORM_SIZE]; + struct sr_datafeed_logic logic; + unsigned char buf[DIGITAL_WAVEFORM_SIZE]; double vdiv, offset; - float data[WAVEFORM_SIZE]; - int probenum, len, i; + float data[ANALOG_WAVEFORM_SIZE]; + int len, i, waveform_size; + struct sr_probe *probe; if (!(sdi = cb_data)) return TRUE; @@ -47,7 +49,10 @@ SR_PRIV int rigol_ds1xx2_receive(int fd, int revents, void *cb_data) return TRUE; if (revents == G_IO_IN) { - len = read(fd, buf, WAVEFORM_SIZE - devc->num_frame_bytes); + probe = devc->channel_frame; + waveform_size = probe->type == SR_PROBE_ANALOG ? + ANALOG_WAVEFORM_SIZE : DIGITAL_WAVEFORM_SIZE; + len = read(fd, buf, waveform_size - devc->num_frame_bytes); sr_dbg("Received %d bytes.", len); if (len == -1) return TRUE; @@ -58,28 +63,37 @@ SR_PRIV int rigol_ds1xx2_receive(int fd, int revents, void *cb_data) sr_session_send(sdi, &packet); } - probenum = devc->channel_frame->name[2] == '1' ? 0 : 1; - for (i = 0; i < len; i++) { - vdiv = devc->vdiv[probenum]; - offset = devc->vert_offset[probenum]; - data[i] = vdiv / 25.6 * (128 - buf[i]) - offset; - } - analog.probes = g_slist_append(NULL, devc->channel_frame); - analog.num_samples = len; - analog.data = data; - analog.mq = SR_MQ_VOLTAGE; - analog.unit = SR_UNIT_VOLT; - analog.mqflags = 0; - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(cb_data, &packet); - g_slist_free(analog.probes); - - devc->num_frame_bytes += len; - - if (devc->num_frame_bytes != WAVEFORM_SIZE) { - /* Don't have the whole frame yet. */ - return TRUE; + if (probe->type == SR_PROBE_ANALOG) { + for (i = 0; i < len; i++) { + vdiv = devc->vdiv[probe->index]; + offset = devc->vert_offset[probe->index]; + data[i] = vdiv / 25.6 * (128 - buf[i]) - offset; + } + analog.probes = g_slist_append(NULL, probe); + analog.num_samples = len; + analog.data = data; + analog.mq = SR_MQ_VOLTAGE; + analog.unit = SR_UNIT_VOLT; + analog.mqflags = 0; + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + sr_session_send(cb_data, &packet); + g_slist_free(analog.probes); + + if (len != ANALOG_WAVEFORM_SIZE) + /* Don't have the whole frame yet. */ + return TRUE; + } else { + logic.length = len - 10; + logic.unitsize = 2; + logic.data = buf + 10; + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + sr_session_send(cb_data, &packet); + + if (len != DIGITAL_WAVEFORM_SIZE) + /* Don't have the whole frame yet. */ + return TRUE; } /* End of the frame. */ @@ -87,22 +101,34 @@ SR_PRIV int rigol_ds1xx2_receive(int fd, int revents, void *cb_data) sr_session_send(sdi, &packet); devc->num_frame_bytes = 0; - if (devc->channel_frame == devc->enabled_probes->data - && devc->enabled_probes->next != NULL) { - /* We got the frame for the first channel, but - * there's a second channel. */ - devc->channel_frame = devc->enabled_probes->next->data; + if (devc->enabled_analog_probes + && devc->channel_frame == devc->enabled_analog_probes->data + && devc->enabled_analog_probes->next != NULL) { + /* We got the frame for the first analog channel, but + * there's a second analog channel. */ + devc->channel_frame = devc->enabled_analog_probes->next->data; rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%c", devc->channel_frame->name[2]); } else { - /* Done with both channels in this frame. */ - if (++devc->num_frames == devc->limit_frames) { + /* Done with both analog channels in this frame. */ + if (devc->enabled_digital_probes + && devc->channel_frame != devc->enabled_digital_probes->data) { + /* Now we need to get the digital data. */ + devc->channel_frame = devc->enabled_digital_probes->data; + rigol_ds1xx2_send(devc, ":WAV:DATA? DIG"); + } else if (++devc->num_frames == devc->limit_frames) { + /* End of last frame. */ sdi->driver->dev_acquisition_stop(sdi, cb_data); } else { - /* Get the next frame, starting with the first channel. */ - devc->channel_frame = devc->enabled_probes->data; - rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%c", - devc->channel_frame->name[2]); + /* Get the next frame, starting with the first analog channel. */ + if (devc->enabled_analog_probes) { + devc->channel_frame = devc->enabled_analog_probes->data; + rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%c", + devc->channel_frame->name[2]); + } else { + devc->channel_frame = devc->enabled_digital_probes->data; + rigol_ds1xx2_send(devc, ":WAV:DATA? DIG"); + } } } } @@ -182,22 +208,38 @@ static int get_cfg_string(const struct sr_dev_inst *sdi, char *cmd, char **buf) SR_PRIV int rigol_ds1xx2_get_dev_cfg(const struct sr_dev_inst *sdi) { struct dev_context *devc; - char *t_s; + char *t_s, *cmd; + int i, res; devc = sdi->priv; - /* Channel state. */ + /* Analog channel state. */ if (get_cfg_string(sdi, ":CHAN1:DISP?", &t_s) != SR_OK) return SR_ERR; - devc->channels[0] = !strcmp(t_s, "ON") ? TRUE : FALSE; + devc->analog_channels[0] = !strcmp(t_s, "ON") ? TRUE : FALSE; g_free(t_s); if (get_cfg_string(sdi, ":CHAN2:DISP?", &t_s) != SR_OK) return SR_ERR; - devc->channels[1] = !strcmp(t_s, "ON") ? TRUE : FALSE; + devc->analog_channels[1] = !strcmp(t_s, "ON") ? TRUE : FALSE; g_free(t_s); - sr_dbg("Current channel state CH1 %s CH2 %s", - devc->channels[0] ? "on" : "off", - devc->channels[1] ? "on" : "off"); + sr_dbg("Current analog channel state CH1 %s CH2 %s", + devc->analog_channels[0] ? "on" : "off", + devc->analog_channels[1] ? "on" : "off"); + + /* Digital channel state. */ + if (devc->has_digital) { + sr_dbg("Current digital channel state:"); + for (i = 0; i < 16; i++) { + cmd = g_strdup_printf(":DIG%d:TURN?", i); + res = get_cfg_string(sdi, cmd, &t_s); + g_free(cmd); + if (res != SR_OK) + return SR_ERR; + devc->digital_channels[i] = !strcmp(t_s, "ON") ? TRUE : FALSE; + g_free(t_s); + sr_dbg("D%d: %s", i, devc->digital_channels[i] ? "on" : "off"); + } + } /* Timebase. */ if (get_cfg_float(sdi, ":TIM:SCAL?", &devc->timebase) != SR_OK) diff --git a/hardware/rigol-ds1xx2/protocol.h b/hardware/rigol-ds1xx2/protocol.h index 644a771b..34d9e8ad 100644 --- a/hardware/rigol-ds1xx2/protocol.h +++ b/hardware/rigol-ds1xx2/protocol.h @@ -34,17 +34,23 @@ #define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args) #define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args) -#define WAVEFORM_SIZE 600 +#define ANALOG_WAVEFORM_SIZE 600 +#define DIGITAL_WAVEFORM_SIZE 1210 /** Private, per-device-instance driver context. */ struct dev_context { + /* Device features */ + gboolean has_digital; + /* Acquisition settings */ - GSList *enabled_probes; + GSList *enabled_analog_probes; + GSList *enabled_digital_probes; uint64_t limit_frames; void *cb_data; /* Device settings */ - gboolean channels[2]; + gboolean analog_channels[2]; + gboolean digital_channels[16]; float timebase; float vdiv[2]; float vert_offset[2];