]> sigrok.org Git - libsigrok.git/blob - src/hardware/rigol-dg/protocol.c
uni-t-ut181a: silence compiler warning, use of uninitialized variable
[libsigrok.git] / src / hardware / rigol-dg / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2020 Timo Kokkonen <tjko@iki.fi>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <string.h>
22 #include "scpi.h"
23 #include "protocol.h"
24
25 SR_PRIV const char *rigol_dg_waveform_to_string(enum waveform_type type)
26 {
27         switch (type) {
28         case WF_DC:
29                 return "DC";
30         case WF_SINE:
31                 return "Sine";
32         case WF_SQUARE:
33                 return "Square";
34         case WF_RAMP:
35                 return "Ramp";
36         case WF_PULSE:
37                 return "Pulse";
38         case WF_NOISE:
39                 return "Noise";
40         case WF_ARB:
41                 return "Arb";
42         }
43
44         return "Unknown";
45 }
46
47 SR_PRIV const struct waveform_spec *rigol_dg_get_waveform_spec(
48         const struct channel_spec *ch, enum waveform_type wf)
49 {
50         const struct waveform_spec *spec;
51         unsigned int i;
52
53         spec = NULL;
54         for (i = 0; i < ch->num_waveforms; i++) {
55                 if (ch->waveforms[i].waveform == wf) {
56                         spec = &ch->waveforms[i];
57                         break;
58                 }
59         }
60
61         return spec;
62 }
63
64 SR_PRIV int rigol_dg_get_channel_state(const struct sr_dev_inst *sdi,
65         const struct sr_channel_group *cg)
66 {
67         struct dev_context *devc;
68         struct sr_scpi_dev_inst *scpi;
69         struct sr_channel *ch;
70         struct channel_status *ch_status;
71         const char *command;
72         GVariant *data;
73         gchar *response, **params;
74         const gchar *s;
75         enum waveform_type wf;
76         double freq, ampl, offset, phase;
77         int ret;
78
79         devc = sdi->priv;
80         scpi = sdi->conn;
81         data = NULL;
82         params = NULL;
83         response = NULL;
84         ret = SR_ERR_NA;
85
86         if (!sdi || !cg)
87                 return SR_ERR_BUG;
88
89         ch = cg->channels->data;
90         ch_status = &devc->ch_status[ch->index];
91
92         command = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_GET_SOURCE);
93         if (command && *command) {
94                 sr_scpi_get_opc(scpi);
95                 ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
96                         PSG_CMD_SELECT_CHANNEL, cg->name, &data,
97                         G_VARIANT_TYPE_STRING, PSG_CMD_GET_SOURCE, cg->name);
98                 if (ret != SR_OK)
99                         goto done;
100                 response = g_variant_dup_string(data, NULL);
101                 g_strstrip(response);
102                 s = sr_scpi_unquote_string(response);
103                 sr_spew("Channel state: '%s'", s);
104                 params = g_strsplit(s, ",", 0);
105                 if (!params[0])
106                         goto done;
107
108                 /* First parameter is the waveform type */
109                 if (!(s = params[0]))
110                         goto done;
111                 if (g_ascii_strncasecmp(s, "SIN", strlen("SIN")) == 0)
112                         wf = WF_SINE;
113                 else if (g_ascii_strncasecmp(s, "SQU", strlen("SQU")) == 0)
114                         wf = WF_SQUARE;
115                 else if (g_ascii_strncasecmp(s, "RAMP", strlen("RAMP")) == 0)
116                         wf = WF_RAMP;
117                 else if (g_ascii_strncasecmp(s, "PULSE", strlen("PULSE")) == 0)
118                         wf = WF_PULSE;
119                 else if (g_ascii_strncasecmp(s, "NOISE", strlen("NOISE")) == 0)
120                         wf = WF_NOISE;
121                 else if (g_ascii_strncasecmp(s, "USER", strlen("USER")) == 0)
122                         wf = WF_ARB;
123                 else if (g_ascii_strncasecmp(s, "DC", strlen("DC")) == 0)
124                         wf = WF_DC;
125                 else
126                         goto done;
127                 ch_status->wf = wf;
128                 ch_status->wf_spec = rigol_dg_get_waveform_spec(
129                                 &devc->device->channels[ch->index], wf);
130
131                 /* Second parameter if the frequency (or "DEF" if not applicable) */
132                 if (!(s = params[1]))
133                         goto done;
134                 freq = g_ascii_strtod(s, NULL);
135                 ch_status->freq = freq;
136
137                 /* Third parameter if the amplitude (or "DEF" if not applicable) */
138                 if (!(s = params[2]))
139                         goto done;
140                 ampl = g_ascii_strtod(s, NULL);
141                 ch_status->ampl = ampl;
142
143                 /* Fourth parameter if the offset (or "DEF" if not applicable) */
144                 if (!(s = params[3]))
145                         goto done;
146                 offset = g_ascii_strtod(s, NULL);
147                 ch_status->offset = offset;
148
149                 /* Fifth parameter if the phase (or "DEF" if not applicable) */
150                 if (!(s = params[4]))
151                         goto done;
152                 phase = g_ascii_strtod(s, NULL);
153                 ch_status->phase = phase;
154
155                 ret = SR_OK;
156         }
157
158 done:
159         g_variant_unref(data);
160         g_free(response);
161         g_strfreev(params);
162         return ret;
163 }
164
165 static void rigol_dg_send_channel_value(const struct sr_dev_inst *sdi,
166                 struct sr_channel *ch, double value, enum sr_mq mq,
167                 enum sr_unit unit, int digits)
168 {
169         struct sr_datafeed_packet packet;
170         struct sr_datafeed_analog analog;
171         struct sr_analog_encoding encoding;
172         struct sr_analog_meaning meaning;
173         struct sr_analog_spec spec;
174         double val;
175
176         val = value;
177         sr_analog_init(&analog, &encoding, &meaning, &spec, digits);
178         analog.meaning->channels = g_slist_append(NULL, ch);
179         analog.num_samples = 1;
180         analog.data = &val;
181         analog.encoding->unitsize = sizeof(val);
182         analog.encoding->is_float = TRUE;
183         analog.encoding->digits = digits;
184         analog.meaning->mq = mq;
185         analog.meaning->unit = unit;
186
187         packet.type = SR_DF_ANALOG;
188         packet.payload = &analog;
189         sr_session_send(sdi, &packet);
190         g_slist_free(analog.meaning->channels);
191 }
192
193 SR_PRIV int rigol_dg_receive_data(int fd, int revents, void *cb_data)
194 {
195         struct sr_dev_inst *sdi;
196         struct sr_scpi_dev_inst *scpi;
197         struct dev_context *devc;
198         const char *cmd, *s;
199         char *response, **params;
200         double meas[5];
201         GSList *l;
202         int i, start_idx, ret;
203
204         (void)fd;
205         (void)revents;
206         response = NULL;
207         params = NULL;
208
209         sdi = cb_data;
210         if (!sdi)
211                 return TRUE;
212         scpi = sdi->conn;
213         devc = sdi->priv;
214         if (!scpi || !devc)
215                 return TRUE;
216
217         cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_MEASURE);
218         if (!cmd || !*cmd)
219                 return TRUE;
220
221         sr_scpi_get_opc(scpi);
222         ret = sr_scpi_get_string(scpi, cmd, &response);
223         if (ret != SR_OK) {
224                 sr_info("Error getting measurement from counter: %d", ret);
225                 sr_dev_acquisition_stop(sdi);
226                 return TRUE;
227         }
228         g_strstrip(response);
229
230         /*
231          * Parse measurement string:
232          *  frequency, period, duty cycle, width+, width-
233          */
234         params = g_strsplit(response, ",", 0);
235         for (i = 0; i < 5; i++) {
236                 if (!(s = params[i]))
237                         goto done;
238                 meas[i] = g_ascii_strtod(s, NULL);
239         }
240         sr_spew("%s: freq=%.10E, period=%.10E, duty=%.10E, width+=%.10E,"
241                 "width-=%.10E", __func__,
242                 meas[0], meas[1], meas[2], meas[3], meas[4]);
243
244         std_session_send_df_frame_begin(sdi);
245         start_idx = devc->device->num_channels;
246
247         /* Frequency */
248         l = g_slist_nth(sdi->channels, start_idx++);
249         rigol_dg_send_channel_value(sdi, l->data, meas[0], SR_MQ_FREQUENCY,
250                 SR_UNIT_HERTZ, 10);
251
252         /* Period */
253         l = g_slist_nth(sdi->channels, start_idx++);
254         rigol_dg_send_channel_value(sdi, l->data, meas[1], SR_MQ_TIME,
255                 SR_UNIT_SECOND, 10);
256
257         /* Duty Cycle */
258         l = g_slist_nth(sdi->channels, start_idx++);
259         rigol_dg_send_channel_value(sdi, l->data, meas[2], SR_MQ_DUTY_CYCLE,
260                 SR_UNIT_PERCENTAGE, 3);
261
262         /* Pulse Width */
263         l = g_slist_nth(sdi->channels, start_idx++);
264         rigol_dg_send_channel_value(sdi, l->data, meas[3], SR_MQ_PULSE_WIDTH,
265                 SR_UNIT_SECOND, 10);
266
267         std_session_send_df_frame_end(sdi);
268         sr_sw_limits_update_samples_read(&devc->limits, 1);
269
270         if (sr_sw_limits_check(&devc->limits))
271                 sr_dev_acquisition_stop(sdi);
272
273 done:
274         g_free(response);
275         g_strfreev(params);
276         return TRUE;
277 }