]> sigrok.org Git - libsigrok.git/blob - hardware/rigol-ds1xx2/protocol.c
rigol-ds1xx2: support digital channels.
[libsigrok.git] / hardware / rigol-ds1xx2 / 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_ds1xx2_receive(int fd, int revents, void *cb_data)
33 {
34         struct sr_dev_inst *sdi;
35         struct dev_context *devc;
36         struct sr_datafeed_packet packet;
37         struct sr_datafeed_analog analog;
38         struct sr_datafeed_logic logic;
39         unsigned char buf[DIGITAL_WAVEFORM_SIZE];
40         double vdiv, offset;
41         float data[ANALOG_WAVEFORM_SIZE];
42         int len, i, waveform_size;
43         struct sr_probe *probe;
44
45         if (!(sdi = cb_data))
46                 return TRUE;
47
48         if (!(devc = sdi->priv))
49                 return TRUE;
50
51         if (revents == G_IO_IN) {
52                 probe = devc->channel_frame;
53                 waveform_size = probe->type == SR_PROBE_ANALOG ?
54                                 ANALOG_WAVEFORM_SIZE : DIGITAL_WAVEFORM_SIZE;
55                 len = read(fd, buf, waveform_size - devc->num_frame_bytes);
56                 sr_dbg("Received %d bytes.", len);
57                 if (len == -1)
58                         return TRUE;
59
60                 if (devc->num_frame_bytes == 0) {
61                         /* Start of a new frame. */
62                         packet.type = SR_DF_FRAME_BEGIN;
63                         sr_session_send(sdi, &packet);
64                 }
65
66                 if (probe->type == SR_PROBE_ANALOG) {
67                         for (i = 0; i < len; i++) {
68                                 vdiv = devc->vdiv[probe->index];
69                                 offset = devc->vert_offset[probe->index];
70                                 data[i] = vdiv / 25.6 * (128 - buf[i]) - offset;
71                         }
72                         analog.probes = g_slist_append(NULL, probe);
73                         analog.num_samples = len;
74                         analog.data = data;
75                         analog.mq = SR_MQ_VOLTAGE;
76                         analog.unit = SR_UNIT_VOLT;
77                         analog.mqflags = 0;
78                         packet.type = SR_DF_ANALOG;
79                         packet.payload = &analog;
80                         sr_session_send(cb_data, &packet);
81                         g_slist_free(analog.probes);
82
83                         if (len != ANALOG_WAVEFORM_SIZE)
84                                 /* Don't have the whole frame yet. */
85                                 return TRUE;
86                 } else {
87                         logic.length = len - 10;
88                         logic.unitsize = 2;
89                         logic.data = buf + 10;
90                         packet.type = SR_DF_LOGIC;
91                         packet.payload = &logic;
92                         sr_session_send(cb_data, &packet);
93
94                         if (len != DIGITAL_WAVEFORM_SIZE)
95                                 /* Don't have the whole frame yet. */
96                                 return TRUE;
97                 }
98
99                 /* End of the frame. */
100                 packet.type = SR_DF_FRAME_END;
101                 sr_session_send(sdi, &packet);
102                 devc->num_frame_bytes = 0;
103
104                 if (devc->enabled_analog_probes
105                                 && devc->channel_frame == devc->enabled_analog_probes->data
106                                 && devc->enabled_analog_probes->next != NULL) {
107                         /* We got the frame for the first analog channel, but
108                          * there's a second analog channel. */
109                         devc->channel_frame = devc->enabled_analog_probes->next->data;
110                         rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%c",
111                                         devc->channel_frame->name[2]);
112                 } else {
113                         /* Done with both analog channels in this frame. */
114                         if (devc->enabled_digital_probes
115                                         && devc->channel_frame != devc->enabled_digital_probes->data) {
116                                 /* Now we need to get the digital data. */
117                                 devc->channel_frame = devc->enabled_digital_probes->data;
118                                 rigol_ds1xx2_send(devc, ":WAV:DATA? DIG");
119                         } else if (++devc->num_frames == devc->limit_frames) {
120                                 /* End of last frame. */
121                                 sdi->driver->dev_acquisition_stop(sdi, cb_data);
122                         } else {
123                                 /* Get the next frame, starting with the first analog channel. */
124                                 if (devc->enabled_analog_probes) {
125                                         devc->channel_frame = devc->enabled_analog_probes->data;
126                                         rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%c",
127                                                         devc->channel_frame->name[2]);
128                                 } else {
129                                         devc->channel_frame = devc->enabled_digital_probes->data;
130                                         rigol_ds1xx2_send(devc, ":WAV:DATA? DIG");
131                                 }
132                         }
133                 }
134         }
135
136         return TRUE;
137 }
138
139 SR_PRIV int rigol_ds1xx2_send(struct dev_context *devc, const char *format, ...)
140 {
141         va_list args;
142         char buf[256];
143         int len, out, ret;
144
145         va_start(args, format);
146         len = vsnprintf(buf, 255, format, args);
147         va_end(args);
148         strcat(buf, "\n");
149         len++;
150         out = write(devc->fd, buf, len);
151         buf[len - 1] = '\0';
152         if (out != len) {
153                 sr_dbg("Only sent %d/%d bytes of '%s'.", out, len, buf);
154                 ret = SR_ERR;
155         } else {
156                 sr_spew("Sent '%s'.", buf);
157                 ret = SR_OK;
158         }
159
160         return ret;
161 }
162
163 static int get_cfg(const struct sr_dev_inst *sdi, char *cmd, char *reply)
164 {
165         struct dev_context *devc;
166         int len;
167
168         devc = sdi->priv;
169
170         if (rigol_ds1xx2_send(devc, cmd) != SR_OK)
171                 return SR_ERR;
172
173         if ((len = read(devc->fd, reply, 255)) < 0)
174                 return SR_ERR;
175         reply[len] = '\0';
176         sr_spew("Received '%s'.", reply);
177
178         return SR_OK;
179 }
180
181 static int get_cfg_float(const struct sr_dev_inst *sdi, char *cmd, float *f)
182 {
183         char buf[256], *e;
184
185         if (get_cfg(sdi, cmd, buf) != SR_OK)
186                 return SR_ERR;
187         *f = strtof(buf, &e);
188         if (e == buf || (fpclassify(*f) & (FP_ZERO | FP_NORMAL)) == 0) {
189                 sr_dbg("failed to parse response to '%s': '%s'", cmd, buf);
190                 return SR_ERR;
191         }
192
193         return SR_OK;
194 }
195
196 static int get_cfg_string(const struct sr_dev_inst *sdi, char *cmd, char **buf)
197 {
198
199         if (!(*buf = g_try_malloc0(256)))
200                 return SR_ERR_MALLOC;
201
202         if (get_cfg(sdi, cmd, *buf) != SR_OK)
203                 return SR_ERR;
204
205         return SR_OK;
206 }
207
208 SR_PRIV int rigol_ds1xx2_get_dev_cfg(const struct sr_dev_inst *sdi)
209 {
210         struct dev_context *devc;
211         char *t_s, *cmd;
212         int i, res;
213
214         devc = sdi->priv;
215
216         /* Analog channel state. */
217         if (get_cfg_string(sdi, ":CHAN1:DISP?", &t_s) != SR_OK)
218                 return SR_ERR;
219         devc->analog_channels[0] = !strcmp(t_s, "ON") ? TRUE : FALSE;
220         g_free(t_s);
221         if (get_cfg_string(sdi, ":CHAN2:DISP?", &t_s) != SR_OK)
222                 return SR_ERR;
223         devc->analog_channels[1] = !strcmp(t_s, "ON") ? TRUE : FALSE;
224         g_free(t_s);
225         sr_dbg("Current analog channel state CH1 %s CH2 %s",
226                         devc->analog_channels[0] ? "on" : "off",
227                         devc->analog_channels[1] ? "on" : "off");
228
229         /* Digital channel state. */
230         if (devc->has_digital) {
231                 sr_dbg("Current digital channel state:");
232                 for (i = 0; i < 16; i++) {
233                         cmd = g_strdup_printf(":DIG%d:TURN?", i);
234                         res = get_cfg_string(sdi, cmd, &t_s);
235                         g_free(cmd);
236                         if (res != SR_OK)
237                                 return SR_ERR;
238                         devc->digital_channels[i] = !strcmp(t_s, "ON") ? TRUE : FALSE;
239                         g_free(t_s);
240                         sr_dbg("D%d: %s", i, devc->digital_channels[i] ? "on" : "off");
241                 }
242         }
243
244         /* Timebase. */
245         if (get_cfg_float(sdi, ":TIM:SCAL?", &devc->timebase) != SR_OK)
246                 return SR_ERR;
247         sr_dbg("Current timebase %f", devc->timebase);
248
249         /* Vertical gain. */
250         if (get_cfg_float(sdi, ":CHAN1:SCAL?", &devc->vdiv[0]) != SR_OK)
251                 return SR_ERR;
252         if (get_cfg_float(sdi, ":CHAN2:SCAL?", &devc->vdiv[1]) != SR_OK)
253                 return SR_ERR;
254         sr_dbg("Current vertical gain CH1 %f CH2 %f", devc->vdiv[0], devc->vdiv[1]);
255
256         /* Vertical offset. */
257         if (get_cfg_float(sdi, ":CHAN1:OFFS?", &devc->vert_offset[0]) != SR_OK)
258                 return SR_ERR;
259         if (get_cfg_float(sdi, ":CHAN2:OFFS?", &devc->vert_offset[1]) != SR_OK)
260                 return SR_ERR;
261         sr_dbg("Current vertical offset CH1 %f CH2 %f", devc->vert_offset[0],
262                         devc->vert_offset[1]);
263
264         /* Coupling. */
265         if (get_cfg_string(sdi, ":CHAN1:COUP?", &devc->coupling[0]) != SR_OK)
266                 return SR_ERR;
267         if (get_cfg_string(sdi, ":CHAN2:COUP?", &devc->coupling[1]) != SR_OK)
268                 return SR_ERR;
269         sr_dbg("Current coupling CH1 %s CH2 %s", devc->coupling[0],
270                         devc->coupling[1]);
271
272         /* Trigger source. */
273         if (get_cfg_string(sdi, ":TRIG:EDGE:SOUR?", &devc->trigger_source) != SR_OK)
274                 return SR_ERR;
275         sr_dbg("Current trigger source %s", devc->trigger_source);
276
277         /* Horizontal trigger position. */
278         if (get_cfg_float(sdi, ":TIM:OFFS?", &devc->horiz_triggerpos) != SR_OK)
279                 return SR_ERR;
280         sr_dbg("Current horizontal trigger position %f", devc->horiz_triggerpos);
281
282         /* Trigger slope. */
283         if (get_cfg_string(sdi, ":TRIG:EDGE:SLOP?", &devc->trigger_slope) != SR_OK)
284                 return SR_ERR;
285         sr_dbg("Current trigger slope %s", devc->trigger_slope);
286
287         return SR_OK;
288 }
289