⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scope.c

📁 在linux下多媒体开发实例linux下多媒体开发
💻 C
字号:
/* *       scope - a software oscilloscope * */#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <sys/ioctl.h>#include <fcntl.h>#include <vga.h>#include <sys/soundcard.h>#ifndef NO_JOY#include <linux/joystick.h>#endif/* global variables */int quit_key_pressed;       /* set by handle_key() */int snd;                    /* file descriptor for sound device */unsigned char b1[1024];     /* buffer for sound data */unsigned char b2[1024];     /* previous buffer for sound data */unsigned char *buffer = b1; /* use pointers to buffers to avoid copies */unsigned char *old = b2;    unsigned char *tmp;         /* holder for swapping pointers */int offset;                 /* vertical offset */int sampling = 8000;        /* selected sampling rate */int actual;                 /* actual sampling rate */int mode = G640x480x16;     /* graphics mode */int colour = 2;             /* colour */int dma = 4;                /* DMA buffer divisor */int point_mode = 0;         /* point v.s. line segment mode */int verbose = 0;            /* verbose mode */int v_points;               /* points in vertical axis */int h_points;               /* points in horizontal axis */int trigger = -1;           /* trigger level (-1 = disabled) */int graticule = 0;          /* show graticule */int file_read = 0;          /* reading from a file */int joy_read = 0;           /* reading from a joystick */char filename[255];         /* file name to read *//* display command usage on standard error and exit */void usage(){  fprintf(stderr,	  "usage: scope -r<rate> -m<mode> -c<colour> -d<dma divisor>\n"	  "             -d<trigger> -p -l -g -v -i<file>\n"	  "Options:\n"	  "-r <rate>        sampling rate in Hz\n"	  "-m <mode>        graphics mode\n"	  "-c <colour>      trace colour\n"	  "-d <dma divide>  DMA buffer size divisor (1,2,4)\n"	  "-t <trigger>     trigger level (0 - 255)\n"	  "-p               point mode (faster)\n"	  "-l               line segment mode (slower)\n"	  "-g               draw graticule\n"	  "-v               verbose output\n"	  "-i <file>        read from file instead of /dev/dsp\n"#ifndef NO_JOY	  "-j <device>      read from joystick device\n"#endif	  );  exit(1);}/* if verbose mode, show current parameter settings on standard out */inline void show_info() {  if (verbose) {    printf("graphics mode: %d\n", mode);    printf("       colour: %d\n", colour);    if (!file_read && !joy_read)      printf("  DMA divisor: %d\n", dma);    if (point_mode)      printf(" drawing mode: point\n");    else      printf(" drawing mode: line segment\n");    if (graticule)      printf("    graticule: on\n");    else      printf("    graticule: off\n");    if (trigger == -1)      printf("trigger level: disabled\n");    else      printf("trigger level: %d\n", trigger);    if (!file_read && !joy_read) {      printf("sampling rate: %d\n", sampling);      printf("  actual rate: %d\n", actual);    }    if (file_read || joy_read)      printf(" reading from: %s\n", filename);    else      printf(" reading from: /dev/dsp\n");  }}/* handle command line options */void parse_args(int argc, char **argv){#ifndef NO_JOY  const char     *flags = "r:m:c:d:t:plgvi:j:";#else  const char     *flags = "r:m:c:d:t:plgvi:";#endif  int             c;  while ((c = getopt(argc, argv, flags)) != EOF) {    switch (c) {    case 'r':      sampling = strtol(optarg, NULL, 0);      break;    case 'm':      mode = strtol(optarg, NULL, 0);      break;    case 'c':      colour = strtol(optarg, NULL, 0);      break;    case 'd':      dma = strtol(optarg, NULL, 0);      break;    case 't':      trigger = strtol(optarg, NULL, 0);      break;    case 'p':      point_mode = 1;      break;    case 'l':      point_mode = 0;      break;    case 'g':      graticule = 1;      break;    case 'v':      verbose = 1;      break;    case 'i':      file_read = 1;      strcpy(filename, optarg);      break;#ifndef NO_JOY    case 'j':      joy_read = 1;      strcpy(filename, optarg);      break;#endif    case '?':      usage();      break;    }  }  if (joy_read && file_read) {    fprintf(stderr, "scope: -i and -j options are mutually exclusive\n");    exit(1);  }}/* initialize screen data to zero level */void init_data(){  int i;    for (i = 0 ; i < 1024 ; i++) {    buffer[i] = 128;    old[i] = 128;  }}/* draw graticule */inline void draw_graticule(){  vga_clear();  /* draw a frame */  vga_setcolor(colour+1);  vga_drawline(0, offset-1, h_points-1, offset-1);  vga_drawline(0, offset+256, h_points-1, offset+256);  vga_drawline(0, offset-1, 0, offset+256);  vga_drawline(h_points-1, offset, h_points-1, offset+256);  /* draw a tick mark where the trigger level is */  if (trigger != -1) {    vga_drawline(0, offset+trigger, 3, offset+trigger);  }}/* initialize graphics screen */void init_screen(){  vga_disabledriverreport();  vga_init();  vga_setmode(mode);  v_points = vga_getydim();  h_points = vga_getxdim();  offset = v_points / 2 - 127;  if (graticule)    draw_graticule();}/* cleanup: restore text mode and close sound device */void cleanup(){  /* restore text screen */  vga_setmode(TEXT);  /* close input device */    close(snd);}/* initialize /dev/dsp */void init_sound_card(){  int parm;  int status;    /* open DSP device for read */  snd = open("/dev/dsp", O_RDONLY);  if (snd < 0) {    perror("scope: cannot open /dev/dsp");    cleanup();    exit(1);  }    /* set mono */  parm = 1;  status = ioctl(snd, SOUND_PCM_WRITE_CHANNELS, &parm);  if (status < 0) {    perror("scope: error from sound device ioctl");    cleanup();    exit(1);  }  /* set 8-bit samples */  parm = 8;  status = ioctl(snd, SOUND_PCM_WRITE_BITS, &parm);  if (status < 0) {    perror("scope: error from sound device ioctl");    cleanup();    exit(1);  }    /* set DMA buffer size */  status = ioctl(snd, SOUND_PCM_SUBDIVIDE, &dma);  if (status < 0) {    perror("scope: error from sound device ioctl");    cleanup();    exit(1);  }    /* set sampling rate */  parm = sampling;  status = ioctl(snd, SOUND_PCM_WRITE_RATE, &parm);  if (status < 0) {    perror("scope: error from sound device ioctl");  }  ioctl(snd, SOUND_PCM_READ_RATE, &actual);}/* initialize input file */void init_input_file(){  /* open file for read */  snd = open(filename, O_RDONLY);  if (snd < 0) {    perror("scope: cannot open input file");    cleanup();    exit(1);  }}#ifndef NO_JOY/* initialize joystick */void init_joystick(){  /* open device for read */  snd = open(filename, O_RDONLY);  if (snd < 0) {    perror("scope: cannot open joystick device");    cleanup();    exit(1);  }}#endif/* dump image on screen to file scope.xbm in X bitmap format */void screen_dump(void){  int x, y, bit, bits;  int x_max = vga_getxdim();  int y_max = vga_getydim();  int l = 0;  FILE *fp;  fp = fopen("scope.xbm", "w");  if (fp == 0) {    perror("scope: unable to open scope.xbm");    cleanup();    exit(1);  }  fprintf(fp, "#define scope_width %d\n", x_max);  fprintf(fp, "#define scope_height %d\n", y_max);  fprintf(fp, "static unsigned char scope_bits[] = {\n   ");  for (y = 0 ; y < y_max ; y++) {    for (x = 0 ; x < x_max; x+= 8) {      l++;      bits = 0;      for (bit = 0 ; bit < 8 ; bit++) {	if (vga_getpixel(x + bit, y) != 0)	  bits += 1 << bit;      }      if (l == y_max*x_max/8)	fprintf(fp, "0x%02x};\n", bits);      else if (l % 12 ==  0)	fprintf(fp, "0x%02x,\n   ", bits);      else	fprintf(fp, "0x%02x, ", bits);    }  }  fclose(fp);}/* handle single key commands */inline void handle_key(){  switch (vga_getkey()) {  case 0:  case -1:    /* no key pressed */    return;    break;  case 'q':  case 'Q':    quit_key_pressed = 1;    return;    break;  case 'R':    if (!file_read && !joy_read) {      sampling = sampling * 10 / 9;      ioctl(snd, SOUND_PCM_SYNC, 0);      ioctl(snd, SOUND_PCM_WRITE_RATE, &sampling);      ioctl(snd, SOUND_PCM_READ_RATE, &actual);    }    break;  case 'r':    if (!file_read && !joy_read) {      sampling = sampling * 9 / 10;      ioctl(snd, SOUND_PCM_SYNC, 0);      ioctl(snd, SOUND_PCM_WRITE_RATE, &sampling);      ioctl(snd, SOUND_PCM_READ_RATE, &actual);    }    break;  case 'T':    if (trigger != -1) {      trigger += 10;      if (trigger > 255)	trigger = 255;      if (graticule)	draw_graticule();    }    break;  case 't':    if (trigger != -1) {      trigger -= 10;      if (trigger < 0)	trigger = 0;      if (graticule)	draw_graticule();    }    break;  case 'l':  case 'L':    if (point_mode == 1) {      point_mode = 0;      vga_clear();      if (graticule)	draw_graticule();    }    break;  case 'p':  case 'P':    if (point_mode == 0) {      point_mode = 1;      vga_clear();      if (graticule)	draw_graticule();    }    break;  case 'C':    colour++;    if (graticule)      draw_graticule();    break;  case 'c':    if (colour > 0) {      colour--;      if (graticule)	draw_graticule();    }    break;  case 'G':    if (graticule == 0) {      graticule = 1;      draw_graticule();    }    break;  case 'g':    if (graticule == 1) {      graticule = 0;      vga_clear();    }    break;  case ' ':    /* pause until key pressed */    while (vga_getkey() == 0)      ;    break;  case 'd':  case 'D':    screen_dump();    break;  default:    break;  }}/* get data from sound card */inline void get_data(){  unsigned char datum;  int status;  /* simple trigger function */  if (trigger != -1) {    /* positive trigger */    if (trigger >128)      do {	read(snd, &datum, 1);      } while (datum < trigger);    else      /* negative trigger */      do {	read(snd, &datum, 1);      } while (datum > trigger);  }  /* now get the real data */    status = read(snd, buffer, h_points-2);  if (status == 0) {    fprintf(stderr, "scope: end of file\n");    cleanup();    exit(1);  }  if (status == 1) {    perror("scope: error reading input");    cleanup();    exit(1);  }}#ifndef NO_JOY/* get data from joystick */inline void get_joy_data(){  struct JS_DATA_TYPE js;  int i, status;  for (i = 0 ; i < h_points-1 ; i++) {    status = read(snd, &js, JS_RETURN);    if (status != JS_RETURN) {      perror("scope: error reading joystick");      cleanup();      exit(1);    }    buffer[i] = js.y / 5; /* arbitrary scale factor */  }}#endif/* graph the data */inline void graph_data(){  register int i;  if (point_mode) {    for (i = 1; i < h_points-1  ; i++) {      /* erase previous point */      vga_setcolor(0);      vga_drawpixel(i, old[i] + offset);      /* draw new point */      vga_setcolor(colour);      vga_drawpixel(i, buffer[i] + offset);    }  } else { /* line mode */    for (i = 1; i < h_points-2  ; i++) {      /* erase previous point */      vga_setcolor(0);      vga_drawline(i, old[i] + offset, i+1, old[i+1] + offset);      /* draw new point */      vga_setcolor(colour);      vga_drawline(i, buffer[i] + offset, i+1, buffer[i+1] + offset);      old[i] = buffer[i];    }  }  /* swap the buffers for next time  */  tmp = buffer;  buffer = old;  old = tmp;}/* main program */int main(int argc, char **argv){  parse_args(argc, argv);  init_screen();  init_data();    if (file_read)    init_input_file();#ifndef NO_JOY  else if (joy_read)    init_joystick();#endif  else    init_sound_card();  show_info();  if (joy_read) {#ifndef NO_JOY    while (!quit_key_pressed) {      handle_key();      get_joy_data();      graph_data();    }#endif  } else {    while (!quit_key_pressed) {      handle_key();      get_data();      graph_data();    }  }  cleanup();  exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -