]> cvs.zerfleddert.de Git - rigol/blob - rigol.c
add png output for screenshots
[rigol] / rigol.c
1 /*
2 Sprite_tms hack to communicate with a Rigol DS1000-series scope using Linux.
3 This code is licensed under the GPL V3.
4
5 Warning: This code can in theory fubar the communications with the scope to a
6 point where the Linux USB-stack seems to get confused. Do a
7 rmmod uhci_hcd; modprobe uhci_hcd
8 (or alternately: use ohci_hcd) if that happens and you should be fine.
9 */
10
11 #include <usb.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <signal.h>
21 #include <time.h>
22
23 #include <readline/readline.h>
24 #include <readline/history.h>
25
26 #include "png.h"
27
28
29 //This routine locates a scope by VID/PID and returns an opened handle to it.
30 usb_dev_handle *find_scope() {
31 struct usb_bus *bus;
32 struct usb_device *dev=NULL;
33 usb_find_busses();
34 usb_find_devices();
35 for (bus=usb_busses; bus; bus=bus->next) {
36 for (dev=bus->devices; dev; dev=dev->next) {
37 //fprintf(stderr,"Prod/dev: %04X:%04X\n",dev->descriptor.idVendor,dev->descriptor.idProduct);
38 if (dev->descriptor.idVendor==0x400 && dev->descriptor.idProduct==0x5dc) {
39 return usb_open(dev);
40 }
41 }
42 }
43 return NULL;
44 }
45
46 //Helper-routine: Convert a little-endian 4-byte word to an int
47 void int2chars(unsigned char *buff,unsigned int a) {
48 buff[3]=(a>>24)&0xff;
49 buff[2]=(a>>16)&0xff;
50 buff[1]=(a>>8)&0xff;
51 buff[0]=(a)&0xff;
52 }
53
54 //Helper-routine: Convert an int to little-endian 4-byte word
55 unsigned int chars2int(unsigned char *buff) {
56 unsigned int a;
57 a=buff[3]<<24;
58 a+=buff[2]<<16;
59 a+=buff[1]<<8;
60 a+=buff[0];
61 return a;
62 }
63
64 #define MIN(a,b) (((a)<(b))?(a):(b))
65
66 inline char printable (char ch)
67 {
68 if (ch < ' ') return '.';
69 if (ch > '~') return '.';
70 return ch;
71 }
72
73 //Debugging: Print a buffers contents in hex
74 void printb (unsigned char *pkt, int len)
75 {
76 int i, j;
77
78 for (i=0;i<len;i+= 16) {
79 printf ("%04x: ", i);
80 for (j=0;j < MIN(len-i, 16);j++) {
81 printf (" %02x", pkt[i+j]);
82 if (j == 7) printf (" ");
83 }
84 if (j < 7) printf (" ");
85 for (;j<17;j++)
86 printf (" ");
87
88 for (j=0;j < MIN(len-i, 16);j++) {
89 printf ("%c", printable (pkt[i+j]));
90 }
91 printf ("\n");
92 }
93 }
94
95 //Send a scpi-command to the scope. The response goes into the buffer
96 //called resp, with a size of resplen. If resp==NULL, no response
97 //is requested.
98 int sendscpi(usb_dev_handle *dev, char* cmd,
99 unsigned char *resp, int resplen) {
100 unsigned char *buff;
101 int len,r,i;
102 int cmdlen = strlen(cmd);
103 static unsigned char seq=0;
104
105
106 buff=malloc(0x40);
107 seq++;
108 buff[0]=1; //func
109 buff[1]=seq; buff[2]=~seq; //nseq
110 buff[3]=0;
111 int2chars(buff+4, cmdlen);
112 buff[8]=1;
113 buff[9]=0x37;
114 buff[10]=0x39;
115 buff[11]=0x39;
116 //fprintf(stderr,"Writing header len=%d\n", cmdlen);
117 //printb(buff,12);
118 r=usb_bulk_write(dev, 1, (char*)buff, 12, 1000);
119 //fprintf(stderr,"%i bytes written. Writing cmd\n",r);
120 //printb(cmd, cmdlen);
121 r=usb_bulk_write(dev, 1, cmd, cmdlen, 1000);
122 //fprintf(stderr,"%i bytes written.\n",r);
123 if (resp != NULL && resplen != 0) {
124 //send read command
125 buff[0]=2; //func
126 seq++;
127 buff[1]=seq; buff[2]=~seq; //nseq
128 int2chars(buff+4,0x40);
129 buff[8]=1;
130 buff[9]=0xA;
131 buff[10]=0;
132 buff[11]=0;
133 //fprintf(stderr,"Writing resp req header\n");
134 //printb(buff,12);
135 r=usb_bulk_write(dev, 1, (char*)buff, 12, 1000);
136 //fprintf(stderr,"%i bytes written. Reading response hdr\n",r);
137 r=usb_bulk_read(dev, 2, (char*)buff, 0x40, 1000);
138 //printb(buff,r);
139 len=chars2int(buff+4);
140 //fprintf(stderr,"%i bytes read. Resplen=%i\n",r,len);
141 for (i=0; i<(r-12); i++) {
142 if (i<resplen) resp[i] = buff[i+12];
143 }
144 //printb(resp,r-12);
145 if (len > 0x40-12) {
146 //fprintf(stderr," Reading response:\n");
147 if (resplen<len) len=resplen;
148 r=usb_bulk_read(dev, 2, (char*)resp+(0x40-12), len-(0x40-12),1000);
149 //fprintf(stderr,"%i bytes read, wanted %i.\n", r, len-(0x40-12));
150 return r+(0x40-12);
151 }
152 return len;
153 }
154 return 0;
155 }
156
157 //Initialize the scope.
158 void initscope(usb_dev_handle *dev) {
159 int r;
160 unsigned char buff[10];
161 usb_claim_interface(dev,0);
162 //The following code isn't really necessary, the program works
163 //OK without it too.
164 r=usb_control_msg(dev, 0xC8, 9, 0, 0, (char*)buff, 4, 1000);
165 if (r < 0) {
166 fprintf (stderr, "Error %d sending init message: %s\n",
167 r, strerror (-r));
168 fprintf (stderr, "Do you have permission on the USB device?\n");
169 exit (1);
170 }
171 if (chars2int(buff)!=0x40004dc) {
172 fprintf(stderr,"Init: buff[%i]=%x\n",r,chars2int(buff));
173 }
174 return;
175 }
176
177 #define HAVE_READLINE
178 #ifndef HAVE_READLINE
179
180 char *readline (prompt)
181 {
182 char *buf;
183
184 printf (prompt);
185 fflush (stdout);
186 buf = malloc (1024);
187
188 if (fgets (buf, 1023, stdin) == NULL) {
189 free (buf);
190 return NULL;
191 }
192 l = strlen (buf);
193 if (buf[l-1] == '\n') {
194 buf[l] = 0;
195 }
196 return buf;
197 }
198
199 void add_history (char *buf)
200 {
201 }
202 #endif
203
204
205 void do_plot (struct usb_dev_handle *sc)
206 {
207 unsigned char ch1[1024], ch2[1024];
208 int i, l;
209
210 static FILE *gnuplot=NULL;
211 FILE *fp;
212
213 l = sendscpi(sc, ":WAV:DATA? CHANEL1", ch1, 1024);
214
215 if (l != 1024) {
216 printf ("hmm. didnt' get 1024 bytes. \n");
217 }
218
219 l = sendscpi(sc, ":WAV:DATA? CHANNEL2", ch2, 1024);
220
221 if (l != 1024) {
222 printf ("hmm. didnt' get 1024 bytes. \n");
223 }
224
225 if (!gnuplot) {
226 gnuplot = popen ("gnuplot", "w");
227 }
228
229 fp = fopen ("temp.dat", "w");
230 for (i=0xd4;i<0x32c;i++)
231 //for (i=0;i<0x400;i++)
232 fprintf (fp, "%d %d\n", 255 - ch1[i], 255 - ch2[i]);
233 fclose (fp);
234
235 fprintf (gnuplot, "plot 'temp.dat' using 1 with lines, 'temp.dat' using 2 with lines\n");
236 fflush (gnuplot);
237 }
238
239
240 #define ERROR -1e100
241
242 double get_float_from_scope (struct usb_dev_handle *sc, char *var)
243 {
244 unsigned char buf[1024];
245 double temp;
246 int l;
247
248 l = sendscpi(sc, var, buf, 1024);
249 if (l > 0) {
250 sscanf ((char*)buf, "%lf", &temp);
251 return temp;
252 }
253 return ERROR;
254 }
255
256
257 void do_get_buf (struct usb_dev_handle *sc)
258 {
259 FILE *fp;
260 int i, j, l, bp;
261 char buf[1024];
262 unsigned char ch1[1024];
263 unsigned char data[512*1024];
264 double sampfreq;
265
266 sendscpi (sc, ":STOP", NULL, 0);
267
268 sampfreq = get_float_from_scope (sc, ":ACQ:SAMP?");
269
270 printf ("Got sampling freq: %g\n", sampfreq);
271
272 sprintf (buf, ":TIM:SCAL %.15f", 50 / sampfreq);
273 printf ("sending scale cmd: %s\n", buf);
274 sendscpi (sc, buf, NULL, 0);
275
276 sleep (1);
277
278 bp=0;
279 for (i=-254*1024;i< 254*1024;i += 600) {
280 sprintf (buf, ":TIM:OFFSET %.15f", i / sampfreq);
281 printf ("Sending offset cmd: %s\n", buf);
282 sendscpi (sc, buf, NULL, 0);
283
284 l = sendscpi(sc, ":WAV:DATA? CHANEL1", ch1, 1024);
285
286 if (l != 1024) {
287 printf ("hmm. didnt' get 1024 bytes. \n");
288 }
289
290 for (j=0;j<600;j++)
291 data[bp++] = ch1[j+0xd4];
292 }
293 printf ("Got %d bytes of data. \n", bp);
294
295 fp = fopen ("ch1.dump", "w");
296 fwrite (data, bp, 1, fp);
297 fclose (fp);
298
299 sendscpi (sc, ":TIM:OFFSET 0", NULL, 0);
300 }
301
302 void do_get_screen(struct usb_dev_handle *sc)
303 {
304 unsigned char screen[320*234];
305 time_t lt;
306 char filename[256];
307 unsigned char *png;
308 int imglen;
309 int l;
310 int fd;
311 pid_t display;
312
313 /* Hide "RMT" from screen */
314 l = sendscpi(sc, ":KEY:LOCK DISABLE", NULL, 0);
315 usleep(20000);
316
317 l = sendscpi(sc, ":LCD:DATA?", screen, sizeof(screen));
318
319 if (l != sizeof(screen)) {
320 printf ("hmm. didnt' get %d bytes, but %d\n\n", sizeof(screen), l);
321 }
322
323 strftime(filename, sizeof(filename), "screen_%Y%m%d-%H%M%S.png", localtime(&lt));
324 fd=open(filename, O_CREAT|O_WRONLY, 0644);
325 png = lcd2png(screen, &imglen);
326 write(fd, png, imglen);
327 close(fd);
328
329 printf("Waveform saved as %s\n", filename);
330
331 display = fork();
332 switch(display) {
333 case 0:
334 execlp("display", "display", filename, NULL);
335 exit(0);
336 break;
337 case -1:
338 perror("fork");
339 break;
340 default:
341 break;
342 }
343 }
344
345 void child_reaper(int sig)
346 {
347 pid_t child;
348
349 do {
350 child = waitpid(-1, NULL, WNOHANG);
351 } while(child > 0);
352
353 }
354
355 int main(int argc, char **argv)
356 {
357 struct usb_dev_handle *sc;
358 char *scpi;
359 unsigned char *buff;
360 int l;
361 struct sigaction act;
362
363 //Init libusb
364 usb_init();
365 //Locate and open the scope
366 sc=find_scope();
367 if (!sc) {
368 printf("No scope found.\n");
369 exit(1);
370 } else {
371 printf("Scope found.\n");
372 }
373 //Initialize scope
374 initscope(sc);
375 buff = malloc (1024*1024);
376 if (buff == NULL) {
377 perror("malloc");
378 exit(EXIT_FAILURE);
379 }
380
381 bzero(&act, sizeof(act));
382 act.sa_handler = child_reaper;
383 act.sa_flags = SA_NOCLDSTOP|SA_RESTART;
384 if (sigaction(SIGCHLD, &act, NULL) == -1) {
385 perror("sigaction");
386 exit(EXIT_FAILURE);
387 }
388
389 while (1) {
390 scpi = readline ("> ");
391
392 if (!scpi) break;
393 if (strlen (scpi) == 0) {
394 free (scpi);
395 continue;
396 }
397
398 add_history (scpi);
399
400 if (strncmp (scpi, "quit", 4) == 0) break;
401 if (strncmp (scpi, "plot", 4) == 0) {
402 do_plot (sc);
403 continue;
404 }
405 if (strncmp (scpi, "databuf", 7) == 0) {
406 do_get_buf (sc);
407 continue;
408 }
409 if (strncmp (scpi, "screen", 6) == 0) {
410 do_get_screen (sc);
411 continue;
412 }
413
414 l = strlen (scpi);
415 //printf ("got buf(%d): ", l);
416 //printb (scpi, l+2);
417 if (strchr (scpi, '?')) {
418 //printf ("Expecting reply\n");
419 l = sendscpi(sc, scpi, buff, 1024*1024);
420 //printf ("Got replylen = %d.\n", l);
421 buff[l] = 0; //zero-terminate
422 printb (buff, l);
423 } else {
424 //printf ("No reply expected\n");
425 l=sendscpi(sc,scpi,NULL,0);
426 }
427 free (scpi);
428 }
429 //Disable keylock, so the user doesn't have to press the 'force'-button
430 l=sendscpi(sc, ":KEY:LOCK DISABLE",NULL,0);
431
432 //Free up and exit
433 usb_release_interface(sc,0);
434 usb_close(sc);
435 return 0;
436 }
Impressum, Datenschutz