]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/rigol-dg/protocol.c
uni-t-ut181a: silence compiler warning, use of uninitialized variable
[libsigrok.git] / src / hardware / rigol-dg / protocol.c
index 01794280c08f9ecba2fea60577f6a33356ac51df..47bf9446f48139aeba8d2698978d8f1f6a8f7532 100644 (file)
  */
 
 #include <config.h>
+#include <string.h>
+#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;
 }