]> git.zerfleddert.de Git - rigol/blob - scope.c
add vertical status information
[rigol] / scope.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <stdint.h>
5 #include <string.h>
6 #include <strings.h>
7
8 #include "scope.h"
9 #include "usbtmc.h"
10
11 /* Just USB for now... */
12 int sendscpi(struct scope* sc, char* cmd, unsigned char *resp, int resplen)
13 {
14 return usbtmc_sendscpi(sc, cmd, resp, resplen);
15 }
16
17 void closescope(struct scope* sc)
18 {
19 return usbtmc_close(sc);
20 }
21
22 void claimscope(struct scope* sc)
23 {
24 return usbtmc_claim(sc);
25 }
26
27 void releasescope(struct scope* sc)
28 {
29 /* Disable keylock, so the user doesn't have to press the 'force'-button */
30 sendscpi(sc, ":KEY:LOCK DISABLE",NULL,0);
31 return usbtmc_release(sc);
32 }
33
34 void resetscope(struct scope* sc)
35 {
36 return usbtmc_reset(sc);
37 }
38
39 struct scope* initscope(void)
40 {
41 struct scope *sc;
42
43 sc = usbtmc_initscope();
44
45 if (!sc) {
46 printf("No scope found.\n");
47 exit(EXIT_FAILURE);
48 }
49
50 claimscope(sc);
51 sendscpi(sc, "*IDN?", (unsigned char*)sc->idn, sizeof(sc->idn));
52 releasescope(sc);
53
54 printf("Scope found (%s)\n", sc->idn);
55
56 return sc;
57 }
58
59 char *scope_idn(struct scope *sc)
60 {
61 return sc->idn;
62 }
63
64 #define COPY_SCOPE_STRING(sc, cmd, dst) { \
65 char *buf; \
66 buf = scope_get_string(sc, cmd, sizeof(dst)); \
67 if (buf) { \
68 strcpy(dst, buf); \
69 free(buf); \
70 }\
71 }
72
73 char *scope_get_string(struct scope *sc, char *cmd, int maxlen)
74 {
75 unsigned char *buf;
76 int res;
77
78 buf = malloc(maxlen+1);
79 if (buf == NULL) {
80 perror("malloc(scope_get_strings)");
81 exit(EXIT_FAILURE);
82 }
83
84 res = sendscpi(sc, cmd, buf, maxlen);
85 if (res < 0) {
86 fprintf(stderr, "Command %s failed with %d\n", cmd, res);
87 free(buf);
88 return NULL;
89 }
90
91 buf[res] = 0;
92
93 return (char*)buf;
94 }
95
96 int scope_get_truth_value(struct scope *sc, char *cmd)
97 {
98 char buf[128];
99 int res;
100
101 bzero(buf, sizeof(buf));
102 res = sendscpi(sc, cmd, (unsigned char*)buf, sizeof(buf)-1);
103 if (res < 0) {
104 fprintf(stderr, "Command %s failed with %d\n", cmd, res);
105 return 0;
106 }
107
108 printf("%s %s\n", cmd, buf);
109
110 if (strcasecmp(buf, "on") == 0) {
111 return 1;
112 } else if (strcasecmp(buf, "enable") == 0) {
113 return 1;
114 }
115
116 return 0;
117 }
118
119 int scope_get_int(struct scope *sc, char *cmd)
120 {
121 char buf[128];
122 int res;
123
124 bzero(buf, sizeof(buf));
125 res = sendscpi(sc, cmd, (unsigned char*)buf, sizeof(buf)-1);
126 if (res < 0) {
127 fprintf(stderr, "Command %s failed with %d\n", cmd, res);
128 return 0;
129 }
130
131 return atoi(buf);
132 }
133
134 double scope_get_double(struct scope *sc, char*cmd)
135 {
136 char buf[128];
137 int res;
138 double ret;
139
140 bzero(buf, sizeof(buf));
141 res = sendscpi(sc, cmd, (unsigned char*)buf, sizeof(buf)-1);
142 if (res < 0) {
143 fprintf(stderr, "Command %s failed with %d\n", cmd, res);
144 return 0.0;
145 }
146
147 ret = strtod(buf, NULL);
148
149 return ret;
150 }
151
152 void update_scope_measurements(struct scope *sc)
153 {
154 sc->status.measure.ch1.vpp = scope_get_double(sc, ":MEAS:VPP? CHAN1");
155 sc->status.measure.ch1.vmax = scope_get_double(sc, ":MEAS:VMAX? CHAN1");
156 sc->status.measure.ch1.vmin = scope_get_double(sc, ":MEAS:VMIN? CHAN1");
157 sc->status.measure.ch1.vamplitude = scope_get_double(sc, ":MEAS:VAMP? CHAN1");
158 sc->status.measure.ch1.vtop = scope_get_double(sc, ":MEAS:VTOP? CHAN1");
159 sc->status.measure.ch1.vbase = scope_get_double(sc, ":MEAS:VBAS? CHAN1");
160 sc->status.measure.ch1.vaverage = scope_get_double(sc, ":MEAS:VAV? CHAN1");
161 sc->status.measure.ch1.vrms = scope_get_double(sc, ":MEAS:VRMS? CHAN1");
162 sc->status.measure.ch1.overshoot = scope_get_double(sc, ":MEAS:OVER? CHAN1");
163 sc->status.measure.ch1.preshoot = scope_get_double(sc, ":MEAS:PRES? CHAN1");
164 sc->status.measure.ch1.frequency = scope_get_double(sc, ":MEAS:FREQ? CHAN1");
165 sc->status.measure.ch1.risetime = scope_get_double(sc, ":MEAS:RIS? CHAN1");
166 sc->status.measure.ch1.falltime = scope_get_double(sc, ":MEAS:FALL? CHAN1");
167 sc->status.measure.ch1.period = scope_get_double(sc, ":MEAS:PER? CHAN1");
168 sc->status.measure.ch1.pwidth = scope_get_double(sc, ":MEAS:PWID? CHAN1");
169 sc->status.measure.ch1.nwidth = scope_get_double(sc, ":MEAS:NWID? CHAN1");
170 sc->status.measure.ch1.pdutycycle = scope_get_double(sc, ":MEAS:PDUT? CHAN1");
171 sc->status.measure.ch1.ndutycycle = scope_get_double(sc, ":MEAS:NDUT? CHAN1");
172 sc->status.measure.ch1.pdelay = scope_get_double(sc, ":MEAS:PDEL? CHAN1");
173 sc->status.measure.ch1.ndelay = scope_get_double(sc, ":MEAS:NDEL? CHAN1");
174
175 sc->status.measure.ch2.vpp = scope_get_double(sc, ":MEAS:VPP? CHAN2");
176 sc->status.measure.ch2.vmax = scope_get_double(sc, ":MEAS:VMAX? CHAN2");
177 sc->status.measure.ch2.vmin = scope_get_double(sc, ":MEAS:VMIN? CHAN2");
178 sc->status.measure.ch2.vamplitude = scope_get_double(sc, ":MEAS:VAMP? CHAN2");
179 sc->status.measure.ch2.vtop = scope_get_double(sc, ":MEAS:VTOP? CHAN2");
180 sc->status.measure.ch2.vbase = scope_get_double(sc, ":MEAS:VBAS? CHAN2");
181 sc->status.measure.ch2.vaverage = scope_get_double(sc, ":MEAS:VAV? CHAN2");
182 sc->status.measure.ch2.vrms = scope_get_double(sc, ":MEAS:VRMS? CHAN2");
183 sc->status.measure.ch2.overshoot = scope_get_double(sc, ":MEAS:OVER? CHAN2");
184 sc->status.measure.ch2.preshoot = scope_get_double(sc, ":MEAS:PRES? CHAN2");
185 sc->status.measure.ch2.frequency = scope_get_double(sc, ":MEAS:FREQ? CHAN2");
186 sc->status.measure.ch2.risetime = scope_get_double(sc, ":MEAS:RIS? CHAN2");
187 sc->status.measure.ch2.falltime = scope_get_double(sc, ":MEAS:FALL? CHAN2");
188 sc->status.measure.ch2.period = scope_get_double(sc, ":MEAS:PER? CHAN2");
189 sc->status.measure.ch2.pwidth = scope_get_double(sc, ":MEAS:PWID? CHAN2");
190 sc->status.measure.ch2.nwidth = scope_get_double(sc, ":MEAS:NWID? CHAN2");
191 sc->status.measure.ch2.pdutycycle = scope_get_double(sc, ":MEAS:PDUT? CHAN2");
192 sc->status.measure.ch2.ndutycycle = scope_get_double(sc, ":MEAS:NDUT? CHAN2");
193 sc->status.measure.ch2.pdelay = scope_get_double(sc, ":MEAS:PDEL? CHAN2");
194 sc->status.measure.ch2.ndelay = scope_get_double(sc, ":MEAS:NDEL? CHAN2");
195
196 sc->status.measure.total = scope_get_truth_value(sc, ":MEAS:TOT?");
197 COPY_SCOPE_STRING(sc, ":MEAS:SOUR?", sc->status.measure.source);
198
199 }
200
201 void update_scope_channel(struct scope *sc, int channel)
202 {
203 struct channel_s *ch;
204 char cmd[128];
205 int offs;
206
207 if (channel == 1) {
208 ch = &(sc->status.channel.ch1);
209 strcpy(cmd, ":CHAN1:");
210 } else if (channel == 2) {
211 ch = &(sc->status.channel.ch2);
212 strcpy(cmd, ":CHAN2:");
213 } else {
214 fprintf(stderr, "Unknown channel %d!\n", channel);
215 return;
216 }
217
218 offs=strlen(cmd);
219
220 strcpy(cmd + offs, "BWL?"); ch->bwlimit_enabled = scope_get_truth_value(sc, cmd);
221 strcpy(cmd + offs, "COUP?"); COPY_SCOPE_STRING(sc, cmd, ch->coupling);
222 strcpy(cmd + offs, "DISP?"); ch->displayed = scope_get_truth_value(sc, cmd);
223 strcpy(cmd + offs, "INV?"); ch->inverted = scope_get_truth_value(sc, cmd);
224 strcpy(cmd + offs, "OFFS?"); ch->offset = scope_get_double(sc, cmd);
225 strcpy(cmd + offs, "PROB?"); ch->probe = scope_get_double(sc, cmd);
226 strcpy(cmd + offs, "SCAL?"); ch->scale = scope_get_double(sc, cmd);
227 strcpy(cmd + offs, "FILT?"); ch->filter_enabled = scope_get_truth_value(sc, cmd);
228 strcpy(cmd + offs, "MEMD?"); ch->memory_depth = scope_get_int(sc, cmd);
229 strcpy(cmd + offs, "VERN?"); COPY_SCOPE_STRING(sc, cmd, ch->vernier);
230 }
231
232 int update_scope_status(struct scope *sc)
233 {
234 bzero(&(sc->status), sizeof(sc->status));
235
236 COPY_SCOPE_STRING(sc, ":INFO:LANG?", sc->status.system.lang);
237
238 sc->status.system.counter_enabled = scope_get_truth_value(sc, ":COUN:ENAB?");
239 sc->status.system.beep_enabled = scope_get_truth_value(sc, ":BEEP:ENAB?");
240
241 sc->status.keyboard.key_lock = scope_get_truth_value(sc, ":KEY:LOCK?");
242
243 update_scope_measurements(sc);
244
245 COPY_SCOPE_STRING(sc, ":DISP:TYPE?", sc->status.display.type);
246 COPY_SCOPE_STRING(sc, ":DISP:GRID?", sc->status.display.grid);
247 sc->status.display.persist = scope_get_truth_value(sc, ":DISP:PERS?");
248 COPY_SCOPE_STRING(sc, ":DISP:MNUD?", sc->status.display.mnudisplay);
249 sc->status.display.mnustatus = scope_get_truth_value(sc, ":DISP:MNUS?");
250 COPY_SCOPE_STRING(sc, ":DISP:SCR?", sc->status.display.screen);
251 sc->status.display.brightness = scope_get_int(sc, ":DISP:BRIG?");
252 sc->status.display.intensity = scope_get_int(sc, ":DISP:INT?");
253
254 update_scope_channel(sc, 1);
255 update_scope_channel(sc, 2);
256
257 COPY_SCOPE_STRING(sc, ":ACQ:TYPE?", sc->status.acquire.type);
258 COPY_SCOPE_STRING(sc, ":ACQ:MODE?", sc->status.acquire.mode);
259
260 sc->status.acquire.averages = scope_get_int(sc, ":ACQ:AVER?");
261 sc->status.acquire.srate_ch1 = scope_get_double(sc, ":ACQ:SAMP? CHAN1");
262 sc->status.acquire.srate_ch2 = scope_get_double(sc, ":ACQ:SAMP? CHAN2");
263 sc->status.acquire.srate_digital = scope_get_double(sc, ":ACQ:SAMP? DIGITAL");
264
265 COPY_SCOPE_STRING(sc, ":TIM:MODE?", sc->status.timebase.mode);
266 sc->status.timebase.offset = scope_get_double(sc, ":TIM:OFFS?");
267 sc->status.timebase.delayed_offset = scope_get_double(sc, ":TIM:DEL:OFFS?");
268 sc->status.timebase.scale = scope_get_double(sc, ":TIM:SCAL?");
269 COPY_SCOPE_STRING(sc, ":TIM:FORM?", sc->status.timebase.format);
270
271 return 0;
272 }
Impressum, Datenschutz