]> cvs.zerfleddert.de Git - rigol/blame - rigol.c
initialize zlib
[rigol] / rigol.c
CommitLineData
037166c1
MG
1/*
2Sprite_tms hack to communicate with a Rigol DS1000-series scope using Linux.
3This code is licensed under the GPL V3.
4
5Warning: This code can in theory fubar the communications with the scope to a
6point where the Linux USB-stack seems to get confused. Do a
7rmmod uhci_hcd; modprobe uhci_hcd
8(or alternately: use ohci_hcd) if that happens and you should be fine.
610d5b65 9 */
037166c1
MG
10
11#include <usb.h>
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <sys/stat.h>
a8982973
MG
16#include <sys/types.h>
17#include <sys/wait.h>
037166c1
MG
18#include <fcntl.h>
19#include <unistd.h>
a8982973
MG
20#include <signal.h>
21#include <time.h>
037166c1
MG
22
23#include <readline/readline.h>
24#include <readline/history.h>
25
3df14711
MG
26#include "png.h"
27
037166c1 28
037166c1
MG
29//This routine locates a scope by VID/PID and returns an opened handle to it.
30usb_dev_handle *find_scope() {
610d5b65
MG
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 }
037166c1 42 }
610d5b65 43 return NULL;
037166c1
MG
44}
45
46//Helper-routine: Convert a little-endian 4-byte word to an int
47void int2chars(unsigned char *buff,unsigned int a) {
610d5b65
MG
48 buff[3]=(a>>24)&0xff;
49 buff[2]=(a>>16)&0xff;
50 buff[1]=(a>>8)&0xff;
51 buff[0]=(a)&0xff;
037166c1
MG
52}
53
54//Helper-routine: Convert an int to little-endian 4-byte word
55unsigned int chars2int(unsigned char *buff) {
610d5b65
MG
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;
037166c1
MG
62}
63
64#define MIN(a,b) (((a)<(b))?(a):(b))
65
66inline char printable (char ch)
67{
610d5b65
MG
68 if (ch < ' ') return '.';
69 if (ch > '~') return '.';
70 return ch;
037166c1
MG
71}
72
73//Debugging: Print a buffers contents in hex
74void printb (unsigned char *pkt, int len)
75{
610d5b65
MG
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 }
037166c1
MG
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.
1c832d05 98int sendscpi(usb_dev_handle *dev, char* cmd,
610d5b65
MG
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);
037166c1 107 seq++;
610d5b65 108 buff[0]=1; //func
037166c1 109 buff[1]=seq; buff[2]=~seq; //nseq
610d5b65
MG
110 buff[3]=0;
111 int2chars(buff+4, cmdlen);
037166c1 112 buff[8]=1;
610d5b65
MG
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);
1c832d05 118 r=usb_bulk_write(dev, 1, (char*)buff, 12, 1000);
610d5b65
MG
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;
037166c1 153 }
610d5b65 154 return 0;
037166c1
MG
155}
156
157//Initialize the scope.
158void initscope(usb_dev_handle *dev) {
610d5b65
MG
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;
037166c1
MG
175}
176
177#define HAVE_READLINE
178#ifndef HAVE_READLINE
179
180char *readline (prompt)
181{
610d5b65
MG
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;
037166c1
MG
197}
198
199void add_history (char *buf)
200{
201}
202#endif
203
204
205void do_plot (struct usb_dev_handle *sc)
206{
610d5b65
MG
207 unsigned char ch1[1024], ch2[1024];
208 int i, l;
037166c1 209
610d5b65
MG
210 static FILE *gnuplot=NULL;
211 FILE *fp;
037166c1 212
610d5b65 213 l = sendscpi(sc, ":WAV:DATA? CHANEL1", ch1, 1024);
037166c1 214
610d5b65
MG
215 if (l != 1024) {
216 printf ("hmm. didnt' get 1024 bytes. \n");
217 }
037166c1 218
610d5b65 219 l = sendscpi(sc, ":WAV:DATA? CHANNEL2", ch2, 1024);
037166c1 220
610d5b65
MG
221 if (l != 1024) {
222 printf ("hmm. didnt' get 1024 bytes. \n");
223 }
037166c1 224
610d5b65
MG
225 if (!gnuplot) {
226 gnuplot = popen ("gnuplot", "w");
227 }
037166c1 228
610d5b65
MG
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);
037166c1 234
610d5b65
MG
235 fprintf (gnuplot, "plot 'temp.dat' using 1 with lines, 'temp.dat' using 2 with lines\n");
236 fflush (gnuplot);
037166c1
MG
237}
238
239
240#define ERROR -1e100
241
242double get_float_from_scope (struct usb_dev_handle *sc, char *var)
243{
610d5b65
MG
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;
037166c1
MG
254}
255
256
257void do_get_buf (struct usb_dev_handle *sc)
258{
610d5b65
MG
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;
037166c1 265
610d5b65 266 sendscpi (sc, ":STOP", NULL, 0);
037166c1 267
610d5b65 268 sampfreq = get_float_from_scope (sc, ":ACQ:SAMP?");
037166c1 269
610d5b65 270 printf ("Got sampling freq: %g\n", sampfreq);
037166c1 271
610d5b65
MG
272 sprintf (buf, ":TIM:SCAL %.15f", 50 / sampfreq);
273 printf ("sending scale cmd: %s\n", buf);
274 sendscpi (sc, buf, NULL, 0);
037166c1 275
610d5b65 276 sleep (1);
037166c1 277
610d5b65
MG
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);
037166c1 283
610d5b65 284 l = sendscpi(sc, ":WAV:DATA? CHANEL1", ch1, 1024);
037166c1 285
610d5b65
MG
286 if (l != 1024) {
287 printf ("hmm. didnt' get 1024 bytes. \n");
288 }
037166c1 289
610d5b65
MG
290 for (j=0;j<600;j++)
291 data[bp++] = ch1[j+0xd4];
292 }
293 printf ("Got %d bytes of data. \n", bp);
037166c1 294
610d5b65
MG
295 fp = fopen ("ch1.dump", "w");
296 fwrite (data, bp, 1, fp);
297 fclose (fp);
298
299 sendscpi (sc, ":TIM:OFFSET 0", NULL, 0);
037166c1
MG
300}
301
a8982973
MG
302void do_get_screen(struct usb_dev_handle *sc)
303{
304 unsigned char screen[320*234];
305 unsigned char screen_conv[320*234*3];
306 unsigned char lut[256][3];
307 time_t lt;
308 char filename[256];
3df14711 309 unsigned char *png;
a8982973
MG
310 int i;
311 int l;
3df14711 312 int fd;
a8982973
MG
313 FILE *fp;
314 pid_t display;
315
316 /* Hide "RMT" from screen */
317 l = sendscpi(sc, ":KEY:LOCK DISABLE", NULL, 0);
318 usleep(20000);
319
320 l = sendscpi(sc, ":LCD:DATA?", screen, sizeof(screen));
321
322 if (l != sizeof(screen)) {
323 printf ("hmm. didnt' get %d bytes, but %d\n\n", sizeof(screen), l);
324 }
037166c1 325
a8982973
MG
326 for(i = 0; i < 256; i++) {
327 lut[i][0] = ((i >> 6) * 0x55);
328 lut[i][1] = ((((i >> 3) & 7) * 0x49) >> 1);
329 lut[i][2] = (((i & 7) * 0x49) >> 1);
330 }
331
332 for(i = 0; i < sizeof(screen_conv); i += 3) {
333 screen_conv[i] = lut[screen[i/3]][0];
334 screen_conv[i+1] = lut[screen[i/3]][1];
335 screen_conv[i+2] = lut[screen[i/3]][2];
336 }
337
338 lt = time(NULL);
339 strftime(filename, sizeof(filename), "screen_%Y%m%d-%H%M%S.ppm", localtime(&lt));
340
341 fp = fopen (filename, "w");
342 fprintf(fp, "P6\n320 234\n255\n");
343 fwrite(screen_conv, sizeof(screen_conv), 1, fp);
344 fclose (fp);
345
346 printf("Waveform saved as %s\n", filename);
347
348 display = fork();
349 switch(display) {
350 case 0:
351 execlp("display", "display", filename, NULL);
352 exit(0);
353 break;
354 case -1:
355 perror("fork");
356 break;
357 default:
358 break;
359 }
3df14711
MG
360
361 strftime(filename, sizeof(filename), "screen_%Y%m%d-%H%M%S.png", localtime(&lt));
362 fd=open(filename, O_CREAT|O_WRONLY, 0644);
363 png = lcd2png(screen, &i);
364 write(fd, png, i);
365 close(fd);
a8982973
MG
366}
367
368void child_reaper(int sig)
369{
370 pid_t child;
371
372 do {
373 child = waitpid(-1, NULL, WNOHANG);
374 } while(child > 0);
375
376}
037166c1
MG
377
378int main(int argc, char **argv)
379{
610d5b65
MG
380 struct usb_dev_handle *sc;
381 char *scpi;
382 unsigned char *buff;
383 int l;
a8982973
MG
384 struct sigaction act;
385
610d5b65
MG
386 //Init libusb
387 usb_init();
388 //Locate and open the scope
389 sc=find_scope();
390 if (!sc) {
391 printf("No scope found.\n");
392 exit(1);
393 } else {
394 printf("Scope found.\n");
395 }
396 //Initialize scope
397 initscope(sc);
398 buff = malloc (1024*1024);
a8982973
MG
399 if (buff == NULL) {
400 perror("malloc");
401 exit(EXIT_FAILURE);
402 }
403
404 bzero(&act, sizeof(act));
405 act.sa_handler = child_reaper;
406 act.sa_flags = SA_NOCLDSTOP|SA_RESTART;
407 if (sigaction(SIGCHLD, &act, NULL) == -1) {
408 perror("sigaction");
409 exit(EXIT_FAILURE);
410 }
411
610d5b65
MG
412 while (1) {
413 scpi = readline ("> ");
414
415 if (!scpi) break;
416 if (strlen (scpi) == 0) {
417 free (scpi);
418 continue;
419 }
420
421 add_history (scpi);
422
423 if (strncmp (scpi, "quit", 4) == 0) break;
424 if (strncmp (scpi, "plot", 4) == 0) {
425 do_plot (sc);
426 continue;
427 }
a8982973 428 if (strncmp (scpi, "databuf", 7) == 0) {
610d5b65
MG
429 do_get_buf (sc);
430 continue;
431 }
a8982973
MG
432 if (strncmp (scpi, "screen", 6) == 0) {
433 do_get_screen (sc);
434 continue;
435 }
610d5b65
MG
436
437 l = strlen (scpi);
438 //printf ("got buf(%d): ", l);
439 //printb (scpi, l+2);
440 if (strchr (scpi, '?')) {
441 //printf ("Expecting reply\n");
442 l = sendscpi(sc, scpi, buff, 1024*1024);
443 //printf ("Got replylen = %d.\n", l);
444 buff[l] = 0; //zero-terminate
445 printb (buff, l);
446 } else {
447 //printf ("No reply expected\n");
448 l=sendscpi(sc,scpi,NULL,0);
449 }
450 free (scpi);
451 }
452 //Disable keylock, so the user doesn't have to press the 'force'-button
453 l=sendscpi(sc, ":KEY:LOCK DISABLE",NULL,0);
454
455 //Free up and exit
456 usb_release_interface(sc,0);
457 usb_close(sc);
458 return 0;
037166c1 459}
Impressum, Datenschutz