]> sigrok.org Git - libsigrok.git/blob - hardware/rigol-ds/protocol.c
19e660d41b0361dfc25a3e18664cfdbd6f519454
[libsigrok.git] / hardware / rigol-ds / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
5  * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <math.h>
27 #include <glib.h>
28 #include "libsigrok.h"
29 #include "libsigrok-internal.h"
30 #include "protocol.h"
31
32 SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
33 {
34         struct sr_dev_inst *sdi;
35         struct sr_serial_dev_inst *serial;
36         struct dev_context *devc;
37         struct sr_datafeed_packet packet;
38         struct sr_datafeed_analog analog;
39         struct sr_datafeed_logic logic;
40         unsigned char buf[DIGITAL_WAVEFORM_SIZE];
41         double vdiv, offset;
42         float data[ANALOG_WAVEFORM_SIZE];
43         int len, i, waveform_size;
44         struct sr_probe *probe;
45
46         (void)fd;
47
48         if (!(sdi = cb_data))
49                 return TRUE;
50
51         if (!(devc = sdi->priv))
52                 return TRUE;
53
54         serial = sdi->conn;
55
56         if (revents == G_IO_IN) {
57                 probe = devc->channel_frame;
58                 waveform_size = probe->type == SR_PROBE_ANALOG ?
59                                 ANALOG_WAVEFORM_SIZE : DIGITAL_WAVEFORM_SIZE;
60                 len = serial_read(serial, buf, waveform_size - devc->num_frame_bytes);
61                 sr_dbg("Received %d bytes.", len);
62                 if (len == -1)
63                         return TRUE;
64
65                 if (devc->num_frame_bytes == 0) {
66                         /* Start of a new frame. */
67                         packet.type = SR_DF_FRAME_BEGIN;
68                         sr_session_send(sdi, &packet);
69                 }
70
71                 if (probe->type == SR_PROBE_ANALOG) {
72                         for (i = 0; i < len; i++) {
73                                 vdiv = devc->vdiv[probe->index];
74                                 offset = devc->vert_offset[probe->index];
75                                 data[i] = vdiv / 25.6 * (128 - buf[i]) - offset;
76                         }
77                         analog.probes = g_slist_append(NULL, probe);
78                         analog.num_samples = len;
79                         analog.data = data;
80                         analog.mq = SR_MQ_VOLTAGE;
81                         analog.unit = SR_UNIT_VOLT;
82                         analog.mqflags = 0;
83                         packet.type = SR_DF_ANALOG;
84                         packet.payload = &analog;
85                         sr_session_send(cb_data, &packet);
86                         g_slist_free(analog.probes);
87
88                         if (len != ANALOG_WAVEFORM_SIZE)
89                                 /* Don't have the whole frame yet. */
90                                 return TRUE;
91                 } else {
92                         logic.length = len - 10;
93                         logic.unitsize = 2;
94                         logic.data = buf + 10;
95                         packet.type = SR_DF_LOGIC;
96                         packet.payload = &logic;
97                         sr_session_send(cb_data, &packet);
98
99                         if (len != DIGITAL_WAVEFORM_SIZE)
100                                 /* Don't have the whole frame yet. */
101                                 return TRUE;
102                 }
103
104                 /* End of the frame. */
105                 packet.type = SR_DF_FRAME_END;
106                 sr_session_send(sdi, &packet);
107                 devc->num_frame_bytes = 0;
108
109                 if (devc->enabled_analog_probes
110                                 && devc->channel_frame == devc->enabled_analog_probes->data
111                                 && devc->enabled_analog_probes->next != NULL) {
112                         /* We got the frame for the first analog channel, but
113                          * there's a second analog channel. */
114                         devc->channel_frame = devc->enabled_analog_probes->next->data;
115                         rigol_ds_send(sdi, ":WAV:DATA? CHAN%c",
116                                         devc->channel_frame->name[2]);
117                 } else {
118                         /* Done with both analog channels in this frame. */
119                         if (devc->enabled_digital_probes
120                                         && devc->channel_frame != devc->enabled_digital_probes->data) {
121                                 /* Now we need to get the digital data. */
122                                 devc->channel_frame = devc->enabled_digital_probes->data;
123                                 rigol_ds_send(sdi, ":WAV:DATA? DIG");
124                         } else if (++devc->num_frames == devc->limit_frames) {
125                                 /* End of last frame. */
126                                 packet.type = SR_DF_END;
127                                 sr_session_send(sdi, &packet);
128                                 sdi->driver->dev_acquisition_stop(sdi, cb_data);
129                         } else {
130                                 /* Get the next frame, starting with the first analog channel. */
131                                 if (devc->enabled_analog_probes) {
132                                         devc->channel_frame = devc->enabled_analog_probes->data;
133                                         rigol_ds_send(sdi, ":WAV:DATA? CHAN%c",
134                                                         devc->channel_frame->name[2]);
135                                 } else {
136                                         devc->channel_frame = devc->enabled_digital_probes->data;
137                                         rigol_ds_send(sdi, ":WAV:DATA? DIG");
138                                 }
139                         }
140                 }
141         }
142
143         return TRUE;
144 }
145
146 SR_PRIV int rigol_ds_send(const struct sr_dev_inst *sdi, const char *format, ...)
147 {
148         va_list args;
149         char buf[256];
150         int len, out, ret;
151
152         va_start(args, format);
153         len = vsnprintf(buf, 255, format, args);
154         va_end(args);
155         strcat(buf, "\n");
156         len++;
157         out = serial_write(sdi->conn, buf, len);
158         buf[len - 1] = '\0';
159         if (out != len) {
160                 sr_dbg("Only sent %d/%d bytes of '%s'.", out, len, buf);
161                 ret = SR_ERR;
162         } else {
163                 sr_spew("Sent '%s'.", buf);
164                 ret = SR_OK;
165         }
166
167         return ret;
168 }
169
170 static int get_cfg(const struct sr_dev_inst *sdi, char *cmd, char *reply)
171 {
172         int len;
173
174         if (rigol_ds_send(sdi, cmd) != SR_OK)
175                 return SR_ERR;
176
177         if ((len = serial_read(sdi->conn, reply, 255)) < 0)
178                 return SR_ERR;
179         reply[len] = '\0';
180         sr_spew("Received '%s'.", reply);
181
182         return SR_OK;
183 }
184
185 static int get_cfg_float(const struct sr_dev_inst *sdi, char *cmd, float *f)
186 {
187         char buf[256], *e;
188
189         if (get_cfg(sdi, cmd, buf) != SR_OK)
190                 return SR_ERR;
191         *f = strtof(buf, &e);
192         if (e == buf || (fpclassify(*f) & (FP_ZERO | FP_NORMAL)) == 0) {
193                 sr_dbg("failed to parse response to '%s': '%s'", cmd, buf);
194                 return SR_ERR;
195         }
196
197         return SR_OK;
198 }
199
200 static int get_cfg_string(const struct sr_dev_inst *sdi, char *cmd, char **buf)
201 {
202
203         if (!(*buf = g_try_malloc0(256)))
204                 return SR_ERR_MALLOC;
205
206         if (get_cfg(sdi, cmd, *buf) != SR_OK)
207                 return SR_ERR;
208
209         return SR_OK;
210 }
211
212 SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi)
213 {
214         struct dev_context *devc;
215         char *t_s, *cmd;
216         int i, res;
217
218         devc = sdi->priv;
219
220         /* Analog channel state. */
221         if (get_cfg_string(sdi, ":CHAN1:DISP?", &t_s) != SR_OK)
222                 return SR_ERR;
223         devc->analog_channels[0] = !strcmp(t_s, "ON") ? TRUE : FALSE;
224         g_free(t_s);
225         if (get_cfg_string(sdi, ":CHAN2:DISP?", &t_s) != SR_OK)
226                 return SR_ERR;
227         devc->analog_channels[1] = !strcmp(t_s, "ON") ? TRUE : FALSE;
228         g_free(t_s);
229         sr_dbg("Current analog channel state CH1 %s CH2 %s",
230                         devc->analog_channels[0] ? "on" : "off",
231                         devc->analog_channels[1] ? "on" : "off");
232
233         /* Digital channel state. */
234         if (devc->has_digital) {
235                 sr_dbg("Current digital channel state:");
236                 for (i = 0; i < 16; i++) {
237                         cmd = g_strdup_printf(":DIG%d:TURN?", i);
238                         res = get_cfg_string(sdi, cmd, &t_s);
239                         g_free(cmd);
240                         if (res != SR_OK)
241                                 return SR_ERR;
242                         devc->digital_channels[i] = !strcmp(t_s, "ON") ? TRUE : FALSE;
243                         g_free(t_s);
244                         sr_dbg("D%d: %s", i, devc->digital_channels[i] ? "on" : "off");
245                 }
246         }
247
248         /* Timebase. */
249         if (get_cfg_float(sdi, ":TIM:SCAL?", &devc->timebase) != SR_OK)
250                 return SR_ERR;
251         sr_dbg("Current timebase %f", devc->timebase);
252
253         /* Vertical gain. */
254         if (get_cfg_float(sdi, ":CHAN1:SCAL?", &devc->vdiv[0]) != SR_OK)
255                 return SR_ERR;
256         if (get_cfg_float(sdi, ":CHAN2:SCAL?", &devc->vdiv[1]) != SR_OK)
257                 return SR_ERR;
258         sr_dbg("Current vertical gain CH1 %f CH2 %f", devc->vdiv[0], devc->vdiv[1]);
259
260         /* Vertical offset. */
261         if (get_cfg_float(sdi, ":CHAN1:OFFS?", &devc->vert_offset[0]) != SR_OK)
262                 return SR_ERR;
263         if (get_cfg_float(sdi, ":CHAN2:OFFS?", &devc->vert_offset[1]) != SR_OK)
264                 return SR_ERR;
265         sr_dbg("Current vertical offset CH1 %f CH2 %f", devc->vert_offset[0],
266                         devc->vert_offset[1]);
267
268         /* Coupling. */
269         if (get_cfg_string(sdi, ":CHAN1:COUP?", &devc->coupling[0]) != SR_OK)
270                 return SR_ERR;
271         if (get_cfg_string(sdi, ":CHAN2:COUP?", &devc->coupling[1]) != SR_OK)
272                 return SR_ERR;
273         sr_dbg("Current coupling CH1 %s CH2 %s", devc->coupling[0],
274                         devc->coupling[1]);
275
276         /* Trigger source. */
277         if (get_cfg_string(sdi, ":TRIG:EDGE:SOUR?", &devc->trigger_source) != SR_OK)
278                 return SR_ERR;
279         sr_dbg("Current trigger source %s", devc->trigger_source);
280
281         /* Horizontal trigger position. */
282         if (get_cfg_float(sdi, ":TIM:OFFS?", &devc->horiz_triggerpos) != SR_OK)
283                 return SR_ERR;
284         sr_dbg("Current horizontal trigger position %f", devc->horiz_triggerpos);
285
286         /* Trigger slope. */
287         if (get_cfg_string(sdi, ":TRIG:EDGE:SLOP?", &devc->trigger_slope) != SR_OK)
288                 return SR_ERR;
289         sr_dbg("Current trigger slope %s", devc->trigger_slope);
290
291         return SR_OK;
292 }