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