X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Frigol-dg%2Fprotocol.c;h=47bf9446f48139aeba8d2698978d8f1f6a8f7532;hb=deb7615262ac4f9cc0750a08351afa7cbf9c34d5;hp=01794280c08f9ecba2fea60577f6a33356ac51df;hpb=068db0fbe6c39d4c831fef7c6720ac185f85e5a3;p=libsigrok.git diff --git a/src/hardware/rigol-dg/protocol.c b/src/hardware/rigol-dg/protocol.c index 01794280..47bf9446 100644 --- a/src/hardware/rigol-dg/protocol.c +++ b/src/hardware/rigol-dg/protocol.c @@ -18,24 +18,260 @@ */ #include +#include +#include "scpi.h" #include "protocol.h" +SR_PRIV const char *rigol_dg_waveform_to_string(enum waveform_type type) +{ + switch (type) { + case WF_DC: + return "DC"; + case WF_SINE: + return "Sine"; + case WF_SQUARE: + return "Square"; + case WF_RAMP: + return "Ramp"; + case WF_PULSE: + return "Pulse"; + case WF_NOISE: + return "Noise"; + case WF_ARB: + return "Arb"; + } + + return "Unknown"; +} + +SR_PRIV const struct waveform_spec *rigol_dg_get_waveform_spec( + const struct channel_spec *ch, enum waveform_type wf) +{ + const struct waveform_spec *spec; + unsigned int i; + + spec = NULL; + for (i = 0; i < ch->num_waveforms; i++) { + if (ch->waveforms[i].waveform == wf) { + spec = &ch->waveforms[i]; + break; + } + } + + return spec; +} + +SR_PRIV int rigol_dg_get_channel_state(const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) +{ + struct dev_context *devc; + struct sr_scpi_dev_inst *scpi; + struct sr_channel *ch; + struct channel_status *ch_status; + const char *command; + GVariant *data; + gchar *response, **params; + const gchar *s; + enum waveform_type wf; + double freq, ampl, offset, phase; + int ret; + + devc = sdi->priv; + scpi = sdi->conn; + data = NULL; + params = NULL; + response = NULL; + ret = SR_ERR_NA; + + if (!sdi || !cg) + return SR_ERR_BUG; + + ch = cg->channels->data; + ch_status = &devc->ch_status[ch->index]; + + command = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_GET_SOURCE); + if (command && *command) { + sr_scpi_get_opc(scpi); + ret = sr_scpi_cmd_resp(sdi, devc->cmdset, + PSG_CMD_SELECT_CHANNEL, cg->name, &data, + G_VARIANT_TYPE_STRING, PSG_CMD_GET_SOURCE, cg->name); + if (ret != SR_OK) + goto done; + response = g_variant_dup_string(data, NULL); + g_strstrip(response); + s = sr_scpi_unquote_string(response); + sr_spew("Channel state: '%s'", s); + params = g_strsplit(s, ",", 0); + if (!params[0]) + goto done; + + /* First parameter is the waveform type */ + if (!(s = params[0])) + goto done; + if (g_ascii_strncasecmp(s, "SIN", strlen("SIN")) == 0) + wf = WF_SINE; + else if (g_ascii_strncasecmp(s, "SQU", strlen("SQU")) == 0) + wf = WF_SQUARE; + else if (g_ascii_strncasecmp(s, "RAMP", strlen("RAMP")) == 0) + wf = WF_RAMP; + else if (g_ascii_strncasecmp(s, "PULSE", strlen("PULSE")) == 0) + wf = WF_PULSE; + else if (g_ascii_strncasecmp(s, "NOISE", strlen("NOISE")) == 0) + wf = WF_NOISE; + else if (g_ascii_strncasecmp(s, "USER", strlen("USER")) == 0) + wf = WF_ARB; + else if (g_ascii_strncasecmp(s, "DC", strlen("DC")) == 0) + wf = WF_DC; + else + goto done; + ch_status->wf = wf; + ch_status->wf_spec = rigol_dg_get_waveform_spec( + &devc->device->channels[ch->index], wf); + + /* Second parameter if the frequency (or "DEF" if not applicable) */ + if (!(s = params[1])) + goto done; + freq = g_ascii_strtod(s, NULL); + ch_status->freq = freq; + + /* Third parameter if the amplitude (or "DEF" if not applicable) */ + if (!(s = params[2])) + goto done; + ampl = g_ascii_strtod(s, NULL); + ch_status->ampl = ampl; + + /* Fourth parameter if the offset (or "DEF" if not applicable) */ + if (!(s = params[3])) + goto done; + offset = g_ascii_strtod(s, NULL); + ch_status->offset = offset; + + /* Fifth parameter if the phase (or "DEF" if not applicable) */ + if (!(s = params[4])) + goto done; + phase = g_ascii_strtod(s, NULL); + ch_status->phase = phase; + + ret = SR_OK; + } + +done: + g_variant_unref(data); + g_free(response); + g_strfreev(params); + return ret; +} + +static void rigol_dg_send_channel_value(const struct sr_dev_inst *sdi, + struct sr_channel *ch, double value, enum sr_mq mq, + enum sr_unit unit, int digits) +{ + struct sr_datafeed_packet packet; + struct sr_datafeed_analog analog; + struct sr_analog_encoding encoding; + struct sr_analog_meaning meaning; + struct sr_analog_spec spec; + double val; + + val = value; + sr_analog_init(&analog, &encoding, &meaning, &spec, digits); + analog.meaning->channels = g_slist_append(NULL, ch); + analog.num_samples = 1; + analog.data = &val; + analog.encoding->unitsize = sizeof(val); + analog.encoding->is_float = TRUE; + analog.encoding->digits = digits; + analog.meaning->mq = mq; + analog.meaning->unit = unit; + + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + sr_session_send(sdi, &packet); + g_slist_free(analog.meaning->channels); +} + SR_PRIV int rigol_dg_receive_data(int fd, int revents, void *cb_data) { - const struct sr_dev_inst *sdi; + struct sr_dev_inst *sdi; + struct sr_scpi_dev_inst *scpi; struct dev_context *devc; + const char *cmd, *s; + char *response, **params; + double meas[5]; + GSList *l; + int i, start_idx, ret; (void)fd; + (void)revents; + response = NULL; + params = NULL; - if (!(sdi = cb_data)) + sdi = cb_data; + if (!sdi) + return TRUE; + scpi = sdi->conn; + devc = sdi->priv; + if (!scpi || !devc) return TRUE; - if (!(devc = sdi->priv)) + cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_MEASURE); + if (!cmd || !*cmd) return TRUE; - if (revents == G_IO_IN) { - /* TODO */ + sr_scpi_get_opc(scpi); + ret = sr_scpi_get_string(scpi, cmd, &response); + if (ret != SR_OK) { + sr_info("Error getting measurement from counter: %d", ret); + sr_dev_acquisition_stop(sdi); + return TRUE; + } + g_strstrip(response); + + /* + * Parse measurement string: + * frequency, period, duty cycle, width+, width- + */ + params = g_strsplit(response, ",", 0); + for (i = 0; i < 5; i++) { + if (!(s = params[i])) + goto done; + meas[i] = g_ascii_strtod(s, NULL); } + sr_spew("%s: freq=%.10E, period=%.10E, duty=%.10E, width+=%.10E," + "width-=%.10E", __func__, + meas[0], meas[1], meas[2], meas[3], meas[4]); + + std_session_send_df_frame_begin(sdi); + start_idx = devc->device->num_channels; + + /* Frequency */ + l = g_slist_nth(sdi->channels, start_idx++); + rigol_dg_send_channel_value(sdi, l->data, meas[0], SR_MQ_FREQUENCY, + SR_UNIT_HERTZ, 10); + + /* Period */ + l = g_slist_nth(sdi->channels, start_idx++); + rigol_dg_send_channel_value(sdi, l->data, meas[1], SR_MQ_TIME, + SR_UNIT_SECOND, 10); + + /* Duty Cycle */ + l = g_slist_nth(sdi->channels, start_idx++); + rigol_dg_send_channel_value(sdi, l->data, meas[2], SR_MQ_DUTY_CYCLE, + SR_UNIT_PERCENTAGE, 3); + + /* Pulse Width */ + l = g_slist_nth(sdi->channels, start_idx++); + rigol_dg_send_channel_value(sdi, l->data, meas[3], SR_MQ_PULSE_WIDTH, + SR_UNIT_SECOND, 10); + + std_session_send_df_frame_end(sdi); + sr_sw_limits_update_samples_read(&devc->limits, 1); + + if (sr_sw_limits_check(&devc->limits)) + sr_dev_acquisition_stop(sdi); +done: + g_free(response); + g_strfreev(params); return TRUE; }