rigol-ds: Support 4 analog channels.

This commit is contained in:
Martin Ling 2013-12-29 01:34:58 +01:00
parent 0d9f5a12cb
commit 821fbcadcc
3 changed files with 123 additions and 97 deletions

View File

@ -117,6 +117,8 @@ static const uint64_t vdivs[][2] = {
static const char *trigger_sources[] = {
"CH1",
"CH2",
"CH3",
"CH4",
"EXT",
"AC Line",
"D0",
@ -159,26 +161,26 @@ static const char *data_sources[] = {
#define AGILENT "Agilent Technologies"
static const struct rigol_ds_model supported_models[] = {
{RIGOL, "DS1052E", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, false, 12},
{RIGOL, "DS1102E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, false, 12},
{RIGOL, "DS1152E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, false, 12},
{RIGOL, "DS1052D", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, true, 12},
{RIGOL, "DS1102D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, true, 12},
{RIGOL, "DS1152D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, true, 12},
{RIGOL, "DS2072", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, false, 14},
{RIGOL, "DS2102", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, false, 14},
{RIGOL, "DS2202", RIGOL_DS2000, PROTOCOL_IEEE488_2, {2, 1000000000}, {500, 1}, {500, 1000000}, false, 14},
{RIGOL, "VS5022", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, false, 14},
{RIGOL, "VS5022D", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, true, 14},
{RIGOL, "VS5042", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, false, 14},
{RIGOL, "VS5042D", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, true, 14},
{RIGOL, "VS5062", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, false, 14},
{RIGOL, "VS5062D", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, true, 14},
{RIGOL, "VS5102", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, false, 14},
{RIGOL, "VS5102D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, true, 14},
{RIGOL, "VS5202", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, false, 14},
{RIGOL, "VS5202D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, true, 14},
{AGILENT, "DSO1014A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, false, 12},
{RIGOL, "DS1052E", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
{RIGOL, "DS1102E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
{RIGOL, "DS1152E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
{RIGOL, "DS1052D", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
{RIGOL, "DS1102D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
{RIGOL, "DS1152D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
{RIGOL, "DS2072", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
{RIGOL, "DS2102", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
{RIGOL, "DS2202", RIGOL_DS2000, PROTOCOL_IEEE488_2, {2, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
{RIGOL, "VS5022", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
{RIGOL, "VS5022D", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
{RIGOL, "VS5042", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
{RIGOL, "VS5042D", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
{RIGOL, "VS5062", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
{RIGOL, "VS5062D", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
{RIGOL, "VS5102", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
{RIGOL, "VS5102D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
{RIGOL, "VS5202", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
{RIGOL, "VS5202D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
{AGILENT, "DSO1014A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
};
SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
@ -314,10 +316,10 @@ static int probe_port(const char *resource, const char *serialcomm, GSList **dev
devc->limit_frames = 0;
devc->model = model;
for (i = 0; i < 2; i++) {
channel_name = (i == 0 ? "CH1" : "CH2");
if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name)))
for (i = 0; i < model->analog_channels; i++) {
if (!(channel_name = g_strdup_printf("CH%d", i + 1)))
return SR_ERR_MALLOC;
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].probes = g_slist_append(NULL, probe);
@ -591,6 +593,10 @@ static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
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 = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
@ -836,15 +842,16 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
/* 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 (devc->model->protocol == PROTOCOL_LEGACY) {
devc->analog_frame_size = (devc->model->series == RIGOL_VS5000 ?
VS5000_ANALOG_LIVE_WAVEFORM_SIZE :
DS1000_ANALOG_LIVE_WAVEFORM_SIZE);
/* Fetch the first frame. */
if (devc->enabled_analog_probes)
devc->channel = devc->enabled_analog_probes->data;
else
devc->channel = devc->enabled_digital_probes->data;
if (rigol_ds_channel_start(sdi) != SR_OK)
return SR_ERR;
} else {
@ -870,7 +877,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
else
devc->analog_frame_size = DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
}
devc->channel = devc->enabled_analog_probes->data;
if (rigol_ds_capture_start(sdi) != SR_OK)
return SR_ERR;
}

View File

@ -211,13 +211,16 @@ static int rigol_ds_stop_wait(const struct sr_dev_inst *sdi)
static int rigol_ds_check_stop(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
struct sr_probe *probe;
int tmp;
if (!(devc = sdi->priv))
return SR_ERR;
probe = devc->channel_entry->data;
if (sr_scpi_send(sdi->conn, ":WAV:SOUR CHAN%d",
devc->channel->index + 1) != SR_OK)
probe->index + 1) != SR_OK)
return SR_ERR;
/* Check that the number of samples will be accepted */
if (sr_scpi_send(sdi->conn, ":WAV:POIN %d;*OPC", devc->analog_frame_size) != SR_OK)
@ -320,25 +323,27 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi)
SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
struct sr_probe *probe;
if (!(devc = sdi->priv))
return SR_ERR;
sr_dbg("Starting reading data from channel %d",
devc->channel->index + 1);
probe = devc->channel_entry->data;
sr_dbg("Starting reading data from channel %d", probe->index + 1);
if (devc->model->protocol == PROTOCOL_LEGACY) {
if (devc->channel->type == SR_PROBE_LOGIC) {
if (probe->type == SR_PROBE_LOGIC) {
if (sr_scpi_send(sdi->conn, ":WAV:DATA? DIG") != SR_OK)
return SR_ERR;
} else {
if (sr_scpi_send(sdi->conn, ":WAV:DATA? CHAN%c",
devc->channel->name[2]) != SR_OK)
if (sr_scpi_send(sdi->conn, ":WAV:DATA? CHAN%d",
probe->index + 1) != SR_OK)
return SR_ERR;
}
} else {
if (sr_scpi_send(sdi->conn, ":WAV:SOUR CHAN%d",
devc->channel->index + 1) != SR_OK)
probe->index + 1) != SR_OK)
return SR_ERR;
if (devc->data_source != DATA_SOURCE_LIVE) {
if (sr_scpi_send(sdi->conn, ":WAV:RES") != SR_OK)
@ -450,7 +455,7 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
}
}
probe = devc->channel;
probe = devc->channel_entry->data;
if (devc->num_block_bytes == 0) {
if (devc->model->protocol == PROTOCOL_IEEE488_2) {
@ -565,19 +570,18 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
sr_scpi_send(sdi->conn, ":WAV:END");
}
if (devc->enabled_analog_probes
&& devc->channel == 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 = devc->enabled_analog_probes->next->data;
if (probe->type == SR_PROBE_ANALOG
&& devc->channel_entry->next != NULL) {
/* We got the frame for this analog channel, but
* there's another analog channel. */
devc->channel_entry = devc->channel_entry->next;
rigol_ds_channel_start(sdi);
} else {
/* Done with both analog channels in this frame. */
/* Done with all analog channels in this frame. */
if (devc->enabled_digital_probes
&& devc->channel != devc->enabled_digital_probes->data) {
&& devc->channel_entry != devc->enabled_digital_probes) {
/* Now we need to get the digital data. */
devc->channel = devc->enabled_digital_probes->data;
devc->channel_entry = devc->enabled_digital_probes;
rigol_ds_channel_start(sdi);
} else if (++devc->num_frames == devc->limit_frames) {
/* End of last frame. */
@ -587,9 +591,9 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
} else {
/* Get the next frame, starting with the first analog channel. */
if (devc->enabled_analog_probes)
devc->channel = devc->enabled_analog_probes->data;
devc->channel_entry = devc->enabled_analog_probes;
else
devc->channel = devc->enabled_digital_probes->data;
devc->channel_entry = devc->enabled_digital_probes;
if (devc->model->protocol == PROTOCOL_LEGACY)
rigol_ds_channel_start(sdi);
@ -673,35 +677,36 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
char *t_s, *cmd;
int i, res;
unsigned int i;
int res;
devc = sdi->priv;
/* Analog channel state. */
if (get_cfg_string(sdi, ":CHAN1:DISP?", &t_s) != SR_OK)
return SR_ERR;
devc->analog_channels[0] = !strcmp(t_s, "ON") || !strcmp(t_s, "1");
g_free(t_s);
if (get_cfg_string(sdi, ":CHAN2:DISP?", &t_s) != SR_OK)
return SR_ERR;
devc->analog_channels[1] = !strcmp(t_s, "ON") || !strcmp(t_s, "1");
g_free(t_s);
sr_dbg("Current analog channel state CH1 %s CH2 %s",
devc->analog_channels[0] ? "on" : "off",
devc->analog_channels[1] ? "on" : "off");
for (i = 0; i < devc->model->analog_channels; i++) {
cmd = g_strdup_printf(":CHAN%d:DISP?", i + 1);
res = get_cfg_string(sdi, cmd, &t_s);
g_free(cmd);
if (res != SR_OK)
return SR_ERR;
devc->analog_channels[i] = !strcmp(t_s, "ON") || !strcmp(t_s, "1");
}
sr_dbg("Current analog channel state:");
for (i = 0; i < devc->model->analog_channels; i++)
sr_dbg("CH%d %s", i + 1, devc->analog_channels[i] ? "on" : "off");
/* Digital channel state. */
if (devc->model->has_digital) {
sr_dbg("Current digital channel state:");
for (i = 0; i < 16; i++) {
cmd = g_strdup_printf(":DIG%d:TURN?", i);
cmd = g_strdup_printf(":DIG%d:TURN?", i + 1);
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");
sr_dbg("D%d: %s", i + 1, devc->digital_channels[i] ? "on" : "off");
}
}
@ -711,41 +716,52 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
sr_dbg("Current timebase %g", devc->timebase);
/* Vertical gain. */
if (get_cfg_float(sdi, ":CHAN1:SCAL?", &devc->vdiv[0]) != SR_OK)
return SR_ERR;
if (get_cfg_float(sdi, ":CHAN2:SCAL?", &devc->vdiv[1]) != SR_OK)
return SR_ERR;
sr_dbg("Current vertical gain CH1 %g CH2 %g", devc->vdiv[0], devc->vdiv[1]);
for (i = 0; i < devc->model->analog_channels; i++) {
cmd = g_strdup_printf(":CHAN%d:SCAL?", i + 1);
res = get_cfg_float(sdi, cmd, &devc->vdiv[i]);
g_free(cmd);
if (res != SR_OK)
return SR_ERR;
}
sr_dbg("Current vertical gain:");
for (i = 0; i < devc->model->analog_channels; i++)
sr_dbg("CH%d %g", i + 1, devc->vdiv[i]);
sr_dbg("Current vertical reference:");
if (devc->model->protocol == PROTOCOL_IEEE488_2) {
/* Vertical reference - not certain if this is the place to read it. */
if (sr_scpi_send(sdi->conn, ":WAV:SOUR CHAN1") != SR_OK)
return SR_ERR;
if (get_cfg_int(sdi, ":WAV:YREF?", &devc->vert_reference[0]) != SR_OK)
return SR_ERR;
if (sr_scpi_send(sdi->conn, ":WAV:SOUR CHAN2") != SR_OK)
return SR_ERR;
if (get_cfg_int(sdi, ":WAV:YREF?", &devc->vert_reference[1]) != SR_OK)
return SR_ERR;
sr_dbg("Current vertical reference CH1 %d CH2 %d",
devc->vert_reference[0], devc->vert_reference[1]);
for (i = 0; i < devc->model->analog_channels; i++) {
if (sr_scpi_send(sdi->conn, ":WAV:SOUR CHAN%d", i + 1) != SR_OK)
return SR_ERR;
if (get_cfg_int(sdi, ":WAV:YREF?", &devc->vert_reference[i]) != SR_OK)
return SR_ERR;
sr_dbg("CH%d %d", i + 1, devc->vert_reference[i]);
}
}
/* Vertical offset. */
if (get_cfg_float(sdi, ":CHAN1:OFFS?", &devc->vert_offset[0]) != SR_OK)
return SR_ERR;
if (get_cfg_float(sdi, ":CHAN2:OFFS?", &devc->vert_offset[1]) != SR_OK)
return SR_ERR;
sr_dbg("Current vertical offset CH1 %g CH2 %g", devc->vert_offset[0],
devc->vert_offset[1]);
for (i = 0; i < devc->model->analog_channels; i++) {
cmd = g_strdup_printf(":CHAN%d:OFFS?", i + 1);
res = get_cfg_float(sdi, cmd, &devc->vert_offset[i]);
g_free(cmd);
if (res != SR_OK)
return SR_ERR;
}
sr_dbg("Current vertical offset:");
for (i = 0; i < devc->model->analog_channels; i++)
sr_dbg("CH%d %g", i + 1, devc->vert_offset[i]);
/* Coupling. */
if (get_cfg_string(sdi, ":CHAN1:COUP?", &devc->coupling[0]) != SR_OK)
return SR_ERR;
if (get_cfg_string(sdi, ":CHAN2:COUP?", &devc->coupling[1]) != SR_OK)
return SR_ERR;
sr_dbg("Current coupling CH1 %s CH2 %s", devc->coupling[0],
devc->coupling[1]);
for (i = 0; i < devc->model->analog_channels; i++) {
cmd = g_strdup_printf(":CHAN%d:COUP?", i + 1);
res = get_cfg_string(sdi, cmd, &devc->coupling[i]);
g_free(cmd);
if (res != SR_OK)
return SR_ERR;
}
sr_dbg("Current coupling:");
for (i = 0; i < devc->model->analog_channels; i++)
sr_dbg("CH%d %s", i + 1, devc->coupling[i]);
/* Trigger source. */
if (get_cfg_string(sdi, ":TRIG:EDGE:SOUR?", &devc->trigger_source) != SR_OK)

View File

@ -39,6 +39,9 @@
/* Size of acquisition buffers */
#define ACQ_BUFFER_SIZE 32768
#define MAX_ANALOG_PROBES 4
#define MAX_DIGITAL_PROBES 16
enum rigol_ds_series {
RIGOL_DS1000,
RIGOL_DS1000Z,
@ -70,6 +73,7 @@ struct rigol_ds_model {
uint64_t min_timebase[2];
uint64_t max_timebase[2];
uint64_t min_vdiv[2];
unsigned int analog_channels;
bool has_digital;
int num_horizontal_divs;
};
@ -93,7 +97,7 @@ struct dev_context {
uint64_t num_vdivs;
/* Probe groups */
struct sr_probe_group analog_groups[2];
struct sr_probe_group analog_groups[MAX_ANALOG_PROBES];
struct sr_probe_group digital_group;
/* Acquisition settings */
@ -105,23 +109,23 @@ struct dev_context {
uint64_t analog_frame_size;
/* Device settings */
gboolean analog_channels[2];
gboolean digital_channels[16];
gboolean analog_channels[MAX_ANALOG_PROBES];
gboolean digital_channels[MAX_DIGITAL_PROBES];
float timebase;
float vdiv[2];
int vert_reference[2];
float vert_offset[2];
float vdiv[MAX_ANALOG_PROBES];
int vert_reference[MAX_ANALOG_PROBES];
float vert_offset[MAX_ANALOG_PROBES];
char *trigger_source;
float horiz_triggerpos;
char *trigger_slope;
char *coupling[2];
char *coupling[MAX_ANALOG_PROBES];
/* Operational state */
/* Number of frames received in total. */
uint64_t num_frames;
/* The channel we are currently receiving data for. */
struct sr_probe *channel;
/* GSList entry for the current channel. */
GSList *channel_entry;
/* Number of samples received in current frame. */
uint64_t num_frame_samples;
/* Number of bytes in current data block, if 0 block header expected */