bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)
xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE output. It will drive an HP-GL plotter for hardcopy. It can be used to look at non-SPICE data, also. Why, it could be the Neatest Thing Ever. Probably not, though. Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and 4.3, and on random Vaxen under Ultrix 1.2 and 2.0) --John Bradley - University of Pennsylvania - bradley@cis.upenn.edu Part 1 of 4 ------------------------cut here----------------------------------------- #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -d ./xsplot` then mkdir ./xsplot echo "mkdir ./xsplot" fi if `test ! -s ./xsplot/xsplotio.c` then echo "writing ./xsplot/xsplotio.c" cat > ./xsplot/xsplotio.c << '\Rogue\Monster\' /************************************************************************/ /* SPLOTIO.C */ /*----------------------------------------------------------------------*/ /* Library of routines to handle file i/o, spice parsing. */ /*----------------------------------------------------------------------*/ /* int OpenFiles (fname); */ /* int OpenSpice (); */ /* int LoadNewAnal (anum); */ /* int LoadAnal (anum); */ /* int expfname (name); */ /* int killtmps (); */ /* char* FixName (name); */ /************************************************************************/ #include "xsplot.h" #include <pwd.h> static char *homedir; char *getenv(); static char outfname[128]; static FILE *outfile; static int NOPAGE; /* whether or not the NOPAGE option has been set */ static char pst[256]; /* used for printf's */ /************************************************************************/ char *FixName(name) char *name; { /* returns file name (strips off directory names) (ie: "/usr/fish/beebo/crap" returns "crap") */ char *sp; sp = rindex(name,'/'); if (sp) return sp+1; else return name; } /************************************************************************/ static char *tfname(buf,i) char *buf; int i; { sprintf(buf,"/tmp/S%ld.%s.t%d",pid,FixName(outfname),i); return(buf); } /************************************************************************/ killtmps() { /* kills all '.tn' files created by this process. Called when quitting */ extern int errno; sprintf(pst,"rm -f /tmp/S%ld.*",pid); system(pst); /* yeah, I'm pretty embarrassed about it, too... */ } /************************************************************************/ int OpenFiles() { homedir = getenv("HOME"); if (homedir == NULL) homedir = "."; if (OpenSpice()) Quit(); LoadNewAnal(0); } /************************************************************************/ int OpenSpice() { int i,err; strcpy(outfname,basfname); if (expfname(outfname)) { sprintf(pst,"ERROR: unable to open '%s'",outfname); ErrBox(pst,3); return 1; } /* strcat(outfname,".out"); */ NOPAGE=0; outfile = fopen(outfname,"r"); if (outfile==0) { sprintf(pst,"ERROR: unable to open '%s'",outfname); ErrBox(pst,3); return 1; } err=MakeTmpFiles(); fclose(outfile); return(err); } /************************************************************************/ static int MakeTmpFiles() /* parses .OUT file into files (one file per analysis) */ /* also loads up the anals array with stuff */ { int i,j,k,done,err; FILE *tmpfile; char linebuf[255], tmpfname[80]; float tdat[MYPERANAL+1]; Anal *ap; if (FindAnals()) return 1; if (Anals2Labs()) return 1; ConvertAnals(); if (NOPARSE) return 0; sprintf(pst,"Parsing file '%s'. Please wait.",outfname); ErrBox(pst,1); rewind(outfile); for (i=0; i<numanals; i++) { /* for each analysis... */ ap = &anals[i]; tfname(tmpfname,i); sprintf(pst,"Writing tmp file '%s': ",tmpfname); ErrBox(pst,1); if ( (tmpfile=fopen(tmpfname,"w"))==0) { sprintf(pst,"ERROR: Unable to create '%s'",tmpfname); ErrBox(pst,3); return 1; } if (FindDStart(ap->type)) { /* go to beginning of data */ fclose(tmpfile); return 1; } numpts = done = 0; putw(numpts,tmpfile); /* write a dummy value for numpts */ while (!done) { /* write the data to the tmp file */ /* read a line of data */ for (j=0; j<ap->numys+1; j++) { done = done || (fscanf(outfile,"%s",linebuf)==-1); tdat[j]=atof(linebuf); if (tdat[j]==0.0) { if (linebuf[0]!='0') done=1; /* read a non-numeric */ else if (strcmp(linebuf,"0.")==0) /* some Fortran comps print '0.0' as '0. e00', which fools scanf, hence the second fscanf */ fscanf(outfile,"%*s"); } } if (!done) { numpts++; if (numpts % 20==0) { sprintf(pst,"Writing tmp file '%s': %4d points", tmpfname,numpts); ErrBox(pst,0); } fwrite(tdat,sizeof(float),ap->numys+1,tmpfile); } } rewind(tmpfile); /* fill in the right val for numpts */ putw(numpts,tmpfile); fclose(tmpfile); sprintf(pst,"Writing tmp file '%s': %4d points",tmpfname,numpts); ErrBox(pst,0); ap->numpts = numpts; } /* repeat for each tmpfile/analysis */ return 0; } /************************************************************************/ static int FindAnals() /* reads the input listing. copies lines starting with .PRINT to analtitle fields in anals array. Also notes whether the NOPAGE option has been set */ { char linebuf[256],*err; char a[5][20]; int i; rewind(outfile); numanals=0; while (fgets(linebuf,256,outfile)==linebuf) { a[0][0]='\0'; sscanf(linebuf,"%s %s %s %s %s",a[0],a[1],a[2],a[3],a[4]); for (i=0; i<5; i++) a[i][19]='\0'; if (strncmp(a[0],".OPT",4)==0) { for (i=1; i<5; i++) if (strcmp("NOPAGE",a[i])==0) NOPAGE=1; } else if (strcmp(a[0],".PRINT")==0) { /* clear out previous title (yes, it's necessary) */ for (i=0; i<80; i++) anals[numanals].title[i]=' '; strncpy(anals[numanals].title,linebuf,80); numanals++; if (numanals==MAXANAL) numanals--; } else if (strcmp(a[0],".END")==0) break; } return 0; } /************************************************************************/ static int Anals2Labs() /* takes anals array and gets the labels from the titles */ /* labs[0] is filled in automatically by ConvertAnals */ { int i,j,c,done; Anal *ap; if (!numanals) { sprintf(pst,"Unable to find any analyses in this spice file. Loading aborted"); ErrBox(pst,4); return 1; } for (i=0; i<numanals; i++) { ap = &anals[i]; /* pointer to cut down on indirection calcs */ /* clear old labels */ for (j=1; j<=MYPERANAL; j++) ap->labels[j][0]='\0'; /* split the ".PRINT" line into args, tossing first two */ sscanf(ap->title,"%*s %*s %s %s %s %s %s %s %s %s\n", ap->labels[1], ap->labels[2], ap->labels[3], ap->labels[4], ap->labels[5], ap->labels[6], ap->labels[7], ap->labels[8]); /* numys = (count arguments) */ for (j=1; j<=MYPERANAL; j++) { c = ap->labels[j][0]; if (!isalpha(c)) break; } ap->numys=j-1; } return 0; } /************************************************************************/ static ConvertAnals() /* take anals array and convert the titles to something approaching english */ { int i; char atype[80]; for (i=0; i<numanals; i++) { sscanf(anals[i].title,"%*s %s",atype); /* atype=analysis type */ if (strcmp(atype,"AC")==0) { strcpy(anals[i].title,"AC Analysis"); strcpy(anals[i].labels[0],"FREQ"); anals[i].type=AC; } else if (strcmp(atype,"DC")==0) { strcpy(anals[i].title,"DC Analysis"); strcpy(anals[i].labels[0],"VIN"); anals[i].type=DC; } else if (strcmp(atype,"TRAN")==0) { strcpy(anals[i].title,"Transient Analysis"); strcpy(anals[i].labels[0],"TIME"); anals[i].type=TRANS; } else { sprintf(pst,"ERROR: Unrecognized analysis '%s'",anals[i].title); ErrBox(pst,3); } } } /************************************************************************/ static int FindDStart(type) int type; /* searches outfile for header, leaving fp pointing at first data line */ { int i,j,numpts,done; char linebuf[256],*err,word1[80],word2[80],title[256]; /* remove up to and including title line */ while (1) { if ( (err=fgets(linebuf,256,outfile)) != linebuf) break; if (linebuf[1]=='*' && linebuf[5]==' ') { /* likely to be a title */ sscanf(linebuf,"%*s %s %s",word1,word2); sprintf(title,"%s %s",word1,word2); if (strcmp(title,SpTitle[type])==0) break; } } if (err!=linebuf) { /* error occurred */ sprintf(pst,"ERROR: Unable to find '%s'.\n",SpTitle[type]); ErrBox(pst,4); return 1; } if (NOPAGE==1) SkipLines(5); /* skip from title to beginning of data */ else SkipLines(8); return 0; } /************************************************************************/ LoadNewAnal(anum) int anum; /* loads an analysis, setting the 'Choose Curves' info to likely values */ { int i; numy = min(anals[anum].numys,4); for (i=0; i<4; i++) ind[i]=i; LoadAnal(anum); curanal=anum; } /************************************************************************/ int LoadAnal(anum) int anum; /* loads an analysis, using current 'Choose Curves' info */ { int i,j; FILE *tmpfile; char linebuf[80],tmpfname[80]; float tmp[MYPERANAL]; tfname(tmpfname,anum); sprintf(pst,"Reading tmp file '%s'",tmpfname); ErrBox(pst,1); if ( (tmpfile=fopen(tmpfname,"r"))==0) { sprintf(pst,"ERROR: Unable to open %s\n",tmpfname); ErrBox(pst,4); return 1; } theAnal = &anals[anum]; numpts = theAnal->numpts = getw(tmpfile); if (numpts>MAXPTS) numpts=MAXPTS; for (i=0; i<numpts; i++) { fread(xlist.dat+i,sizeof(float),1,tmpfile); /* read a line from the file */ fread(tmp,sizeof(float),theAnal->numys,tmpfile); for (j=0; j<numy; j++) ylist[j].dat[i]=tmp[ind[j]]; } fclose(tmpfile); /* copy the labels from the anal to the dlists */ strcpy(xlist.label,theAnal->labels[0]); for (i=0; i<numy; i++) { strcpy(ylist[i].label,theAnal->labels[ind[i]+1]); } /* figure out what the units should be */ switch (theAnal->type) { case DC: units[0]="V"; break; case AC: units[0]="Hz"; break; case TRANS: units[0]="S"; break; } for (i=0; i<numy; i++) { char *st; /* force label to ALL CAPS */ for (st=ylist[i].label; toupper(*st)!='\0'; st++); st=ylist[i].label; if (strncmp(st,"VDB",3)==0) { /* dB's */ units[i+1]="dB"; } else if (strncmp(st,"VP",2)==0) { /* Degrees */ units[i+1]=DEGSTR; } else if (*st == 'V') { /* Volts */ units[i+1]="V"; } else if (*st == 'I') { /* Amps */ units[i+1]="A"; } else units[i+1]=""; } ErrBox("",0); return 0; } /***************************************************************************/ static int SkipLines(i) int i; /* reads (and ignores) 'i' lines from outfile */ { char linebuf[255]; for (; i>0; i--) fgets(linebuf,255,outfile); } /**************************************************************************/ int expfname(fname) char *fname; { /* expands ~s in file names. Returns the name in 'name', returns 0 if okay, 1 if error occurred (user name not found) */ struct passwd *entry; char *cp, *sp, *up, uname[64], tmp[256]; if (*fname != '~') return 0; /* doesn't start with a tilde, don't expand */ /* look for the first '/' after the tilde */ sp = index(fname,'/'); if (sp == 0) return 1; /* no '/' after the tilde. Invalid fname */ /* uname equals the string between the ~ and the / */ for (cp=fname+1,up=uname; cp<sp; *up++ = *cp++); *up='\0'; if (*uname=='\0') { /* no name. substitute ~ with $HOME */ strcpy(tmp,homedir); strcat(tmp,sp); } else { /* get password entry for uname */ entry = getpwnam(uname); if (entry==0) return 1; /* name not found */ strcpy(tmp,entry->pw_dir); strcat(tmp,sp); endpwent(); } strcpy(fname,tmp); /* return expanded file name */ return 0; } \Rogue\Monster\ else echo "will not over write ./xsplot/xsplotio.c" fi if `test ! -s ./xsplot/xsplotmac.c` then echo "writing ./xsplot/xsplotmac.c" cat > ./xsplot/xsplotmac.c << '\Rogue\Monster\' /************************************************************************/ /* xsplotmac.c - Macintosh-like stuff, random graphic routines, */ /* window/subwindow/button creation/redraw */ /*----------------------------------------------------------------------*/ /* InvTitleBar (); */ /* DrawTitleBar (); */ /* CreateMainWindow(name,geom); */ /* CreateSubwindows(); */ /* CreateStuff (); */ /* CreateButtons (); */ /* MakeButton (bnum,win,x,y,w,h,st) */ /* MakeCB (bnum,win,x,y); */ /* MapButtons (); */ /* RedrawIcon (); */ /* RedrawBut (bnum); */ /* RedrawCB (bnum); */ /* RedrawPanel (w,wwidth,str); */ /* RedrawOffPan (); */ /* InvertBut (bnum); */ /* DrawArrs (); */ /* DashLine (window,x1,y1,x2,y2,color,pattern); */ /* SetVertex (vert,x,y,flags); */ /* MakeRect (x1,y1,x2,y2); */ /* Frame (win,x1,y1,x2,y2,width,color,func); */ /************************************************************************/ #include "xsplot.h" #include "cursor" /* nnw arrow cursor */ #include "cursor.mask" /* and mask */ #include "cursx" /* small x-shaped */ #include "cursx.mask" /* cursor and mask */ #include "icon" /* program icon */ #include "titlebar.bm" /* titlebar bitmap */ #include "arrows.h" /* bitmaps for trace location arrows */ /* checkerboard used in mono mode */ static short stip_bits[] = { 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa}; /* cross-weave bitmap */ static short chek_bits[] = { 0x5555, 0x8888, 0x5555, 0x2222, 0x5555, 0x8888, 0x5555, 0x2222, 0x5555, 0x8888, 0x5555, 0x2222, 0x5555, 0x8888, 0x5555, 0x2222}; /* 75% gray */ static short dkgray_bits[] = { 0xaaaa, 0xffff, 0xaaaa, 0xffff, 0xaaaa, 0xffff, 0xaaaa, 0xffff, 0xaaaa, 0xffff, 0xaaaa, 0xffff, 0xaaaa, 0xffff, 0xaaaa, 0xffff}; /***********************************/ InvTitleBar() { tbInvert = !tbInvert; if (tbInvert) { if (mono) XChangeBackground(titleW,gridBpix); else XChangeBackground(titleW,mainBpix); } else XChangeBackground(titleW,mainFpix); XClear(titleW); DrawTitleBar(); } /***********************************/ DrawTitleBar() { int i, cfore, cback; if (tbInvert) XPixmapPut(titleW,0,0,(WIDTH-titlebar_width)/2,0,titlebar_width, titlebar_height, titlePixInv, GXcopy, AllPlanes); else XPixmapPut(titleW,0,0,(WIDTH-titlebar_width)/2,0,titlebar_width, titlebar_height, titlePix, GXcopy, AllPlanes); } /***********************************/ CreateMainWindow(name,geom) char *name,*geom; { char default_geom[20]; OpaqueFrame frame; sprintf (default_geom, "%dx%d+%d+%d",WIDTH,HEIGHT, (DisplayWidth()-WIDTH)/2,(DisplayHeight()-HEIGHT)/2); frame.bdrwidth = 2; frame.border = mainFpix; frame.background = mainBpix; mainW = XCreate("xSplot",name,geom,default_geom,&frame,WIDTH,HEIGHT); if (!mainW) FatalError("Can't open main window"); } /***********************************/ CreateSubwindows() { iconW =XCreateWindow(RootWindow,0,0,icon_width,icon_height,0,0,mainBpix); titleW=XCreateWindow(mainW,-1,-1,WIDTH,20,1,mainFpix,mainFpix); gridW =XCreateWindow(mainW,15-5,50-5,GSIZE+3,GSIZE+3,3,mainFpix,gridBpix); presetW = XCreateWindow(mainW,PREX,PREY,PREW,PREH,1,panFpix, panBpix); traceW = XCreateWindow(mainW,TRAX,TRAY,TRAW,TRAH,1,panFpix, panBpix); scaleW = XCreateWindow(mainW,SCAX,SCAY,SCAW,SCAH,1,panFpix, panBpix); measureW= XCreateWindow(mainW,MSRX,MSRY,MSRW,MSRH,1,panFpix, panBpix); offsetW = XCreateWindow(mainW,OFFX,OFFY,OFFW,OFFH,1,panFpix, panBpix); commandW= XCreateWindow(mainW,OFFX,OFFY,OFFW,OFFH,1,panFpix, panBpix); modifyW = XCreateWindow(mainW,MODX,MODY,MODW,MODH,1,panFpix, panBpix); miscW = XCreateWindow(mainW,MISX,MISY,MISW,MISH,1,panFpix, panBpix); errW = XCreateWindow(mainW,10,HEIGHT-23,WIDTH-20,13,1,errFpix,errBpix); diversW = XCreateWindow(mainW,115-4,100-4,200,300,3,dlgFpix,dlgBpix); LoadDlog= XCreateWindow(mainW,25-3, 150,380,100,3,dlgFpix,dlgBpix); SwitchDlog=XCreateWindow(mainW,115-3,150,200,100,3,dlgFpix,dlgBpix); CurvDlog= XCreateWindow(mainW,115-3,100,200,300,3,dlgFpix,dlgBpix); PlotDlog= XCreateWindow(mainW,25-3, 175,380,70, 3,dlgFpix,dlgBpix); PlotNDlog= XCreateWindow(mainW,25-3, 160,380,100,3,dlgFpix,dlgBpix); HelpDlog= XCreateWindow(mainW,25-3, 125,380,200,3,dlgFpix,dlgBpix); AboutDlog =XCreateWindow(mainW,15-4,50-4,GSIZE,GSIZE,3,mainFpix,gridBpix); XSelectInput(iconW, ExposeWindow); XSelectInput(titleW,ExposeWindow|ButtonPressed); XSelectInput(gridW, ExposeWindow|ButtonPressed|ButtonReleased); XSelectInput(presetW, ExposeWindow); XSelectInput(traceW, ExposeWindow); XSelectInput(scaleW, ExposeWindow); XSelectInput(measureW, ExposeWindow); XSelectInput(offsetW, ExposeWindow); XSelectInput(modifyW, ExposeWindow); XSelectInput(miscW, ExposeWindow); XSelectInput(commandW, ExposeWindow); XSelectInput(errW, ExposeWindow); XSelectInput(diversW, ExposeWindow); XSelectInput(LoadDlog, ExposeWindow|ButtonPressed); XSelectInput(SwitchDlog,ExposeWindow|ButtonPressed); XSelectInput(CurvDlog, ExposeWindow|ButtonPressed); XSelectInput(PlotDlog, ExposeWindow|ButtonPressed); XSelectInput(PlotNDlog, ExposeWindow|ButtonPressed); XSelectInput(HelpDlog, ExposeWindow|ButtonPressed); XSelectInput(AboutDlog, ExposeWindow|ButtonPressed); } /***********************************/ CreateStuff() { Bitmap tmpBits; int i; tmpBits = XStoreBitmap(titlebar_width,titlebar_height,titlebar_bits); titlePix = XMakePixmap (tmpBits,mainFcol,mainBcol); titlePixInv = XMakePixmap (tmpBits,mainBcol,mainFcol); XFreeBitmap(tmpBits); if (mono) { /* panels and main background are stippled in mono mode */ tmpBits = XStoreBitmap(16,16,stip_bits); panBpix = XMakePixmap(tmpBits,ForeColor,BackColor); XFreeBitmap(tmpBits); tmpBits = XStoreBitmap(16,16,chek_bits); mainBpix = XMakePixmap(tmpBits,ForeColor,BackColor); XFreeBitmap(tmpBits); } else { /* but solid color in color mode */ panBpix = XMakeTile(panBcol); mainBpix= XMakeTile(mainBcol); } gridFpix = XMakeTile(gridFcol); gridBpix = XMakeTile(gridBcol); panFpix = XMakeTile(panFcol); butFpix = XMakeTile(butFcol); butBpix = XMakeTile(butBcol); mainFpix = XMakeTile(mainFcol); dlgFpix = XMakeTile(dlgFcol); dlgBpix = XMakeTile(dlgBcol); errFpix = XMakeTile(errFcol); errBpix = XMakeTile(errBcol); for (i=0; i<4; i++) trpix[i] = XMakeTile(trcol[i]); leftmask = XStoreBitmap(arr_width,arr_height,arrl_mask_bits); rightmask = XStoreBitmap(arr_width,arr_height,arrr_mask_bits); upmask = XStoreBitmap(arr_width,arr_height,arru_mask_bits); downmask = XStoreBitmap(arr_width,arr_height,arrd_mask_bits); if (mono) { linepats[0]=XMakePattern(0xffff,16,1); linepats[1]=XMakePattern(0xaaaa,16,1); linepats[2]=XMakePattern(0xcccc,16,1); linepats[3]=XMakePattern(0xbbbb,16,1); } RBoxPat[0]=XMakePattern(0xc0,8,2); RBoxPat[1]=XMakePattern(0x30,8,2); RBoxPat[2]=XMakePattern(0x0c,8,2); RBoxPat[3]=XMakePattern(0x03,8,2); GridPat2=XMakePattern(PAT2,16,1); GridPat4=XMakePattern(PAT4,16,1); arrow=XCreateCursor(cursor_width,cursor_height,cursor_bits, cursor_mask_bits,cursor_x_hot,cursor_y_hot,mainFcol,mainBcol,GXcopy); cursx=XCreateCursor(cursx_width,cursx_height,cursx_bits, cursx_mask_bits,cursx_x_hot,cursx_y_hot,mainFcol,mainBcol,GXcopy); } /***********************************/ CreateButtons() { #define BH 19 int i; MakeButton(&butts[ 0],scaleW,24,16, 68,BH,"linear",butfinfo); MakeButton(&butts[ 1],scaleW,24,16+BUTH,68,BH,"linear",butfinfo); for (i=0; i<5; i++) { MakeButton(&butts[i*2+2],offsetW,60, 16+BUTH*i,65,BH,"",butfinfo); MakeButton(&butts[i*2+3],offsetW,60+70,16+BUTH*i,65,BH,"",butfinfo); } MakeButton(&butts[12],modifyW,5, 16, 87,BH,"Reset",butfinfo); MakeButton(&butts[13],modifyW,5, 16+BUTH, 41,BH,"<-", butfinfo); MakeButton(&butts[14],modifyW,51,16+BUTH, 41,BH,"->", butfinfo); MakeButton(&butts[15],modifyW,5, 16+BUTH*2,41,BH,"<<-", butfinfo); MakeButton(&butts[16],modifyW,51,16+BUTH*2,41,BH,"->>", butfinfo); MakeButton(&butts[17],modifyW,5, 16+BUTH*3,41,BH,"<<<-", butfinfo); MakeButton(&butts[18],modifyW,51,16+BUTH*3,41,BH,"->>>", butfinfo); MakeButton(&butts[22],miscW,5,16, 87,BH,"Commands",butfinfo); MakeButton(&butts[21],miscW,5,16+BUTH, 87,BH,"Y-Lock", butfinfo); MakeButton(&butts[20],miscW,5,16+BUTH*2,87,BH,"Undo", butfinfo); MakeButton(&butts[19],miscW,5,16+BUTH*3,87,BH,"Redraw", butfinfo); MakeButton(&butts[25],commandW,5, 16, 190,BH,"Load Data File", butfinfo); MakeButton(&butts[24],commandW,5, 16+BUTH, 190,BH,"Switch Analysis",butfinfo); MakeButton(&butts[26],commandW,5, 16+BUTH*2,92, BH,"Curves", butfinfo); MakeButton(&butts[23],commandW,5+98,16+BUTH*2,92, BH,"Big Picture", butfinfo); MakeButton(&butts[38],commandW,5, 16+BUTH*3,92, BH,"Plot", butfinfo); MakeButton(&butts[39],commandW,5+98,16+BUTH*3,92, BH,"Help", butfinfo); MakeButton(&butts[27],commandW,5, 16+BUTH*4,92, BH,"Digital", butfinfo); MakeButton(&butts[37],commandW,5+98,16+BUTH*4,92, BH,"Quit", butfinfo); MakeButton(&butts[28],presetW,5, 16,15,BH,"1", butfinfo); MakeButton(&butts[29],presetW,5+20, 16,15,BH,"2", butfinfo); MakeButton(&butts[30],presetW,5+40, 16,15,BH,"3", butfinfo); MakeButton(&butts[31],presetW,5+60, 16,15,BH,"4", butfinfo); MakeButton(&butts[32],presetW,5+80, 16,15,BH,"5", butfinfo); MakeButton(&butts[33],presetW,5+100,16,15,BH,"6", butfinfo); MakeButton(&butts[34],presetW,5+120,16,15,BH,"7", butfinfo); MakeButton(&butts[35],presetW,5+140,16,15,BH,"8", butfinfo); MakeButton(&butts[36],presetW,5+160,16,30,BH,"Set",butfinfo); MakeCB(0,measureW,5, 16); MakeCB(1,measureW,5+CBW+5,16); MakeCB(2,measureW,5, 16+CBH+5); MakeCB(3,measureW,5+CBW+5,16+CBH+5); } /********************/ MakeButton(bp,win,x,y,w,h,st,bfinf) Button *bp; Window win; short x,y,w,h; char *st; FontInfo *bfinf; /********************/ { bp->win = XCreateWindow(win,x,y,w-4,h-4,2,butFpix,butBpix); bp->x = x+2; bp->y = y+2; bp->w = w-4; bp->h = h-4; bp->st = st; bp->invert=0; bp->finfo = bfinf; XSelectInput(bp->win,ExposeWindow|ButtonPressed|ButtonReleased); } /********************/ MakeCB(bnum,win,x,y) int bnum; Window win; short x,y; /********************/ { if (mono) CButts[bnum].win = XCreateWindow(win,x,y,CBW-4,CBH-4,2,butFpix,butBpix); else CButts[bnum].win = XCreateWindow(win,x,y,CBW-4,CBH-4,2, butFpix,trpix[bnum]); XSelectInput(CButts[bnum].win,ExposeWindow|ButtonPressed); } /********************/ MapButtons() { int i; for (i=0; i<MAXBUT; i++) XMapWindow(butts[i].win); for (i=0; i<4; i++) XMapWindow(CButts[i].win); } /********************/ RedrawIcon() { XBitmapBitsPut(iconW,0,0,icon_width,icon_height,icon_bits, mainFcol,mainBcol,0,GXcopy, AllPlanes); } /********************/ RedrawBut(bp) Button *bp; { int width, textc, backc; width = XStringWidth(bp->st,bp->finfo,0,0); if (bp->invert) { textc=butBcol; backc=butFcol; } else { textc=butFcol; backc=butBcol; } XClear(bp->win); XText(bp->win,(bp->w-width)/2,(bp->h - bp->finfo->height)/2, bp->st, strlen(bp->st), bp->finfo->id, textc, backc); } /********************/ RedrawCB(bnum) int bnum; { int width, textc, backc; Window w; w = CButts[bnum].win; XClear(w); if (mono) DashLine(w,1,(CBH-4)/2,CBW-5,(CBH-4)/2,ForeColor,linepats[bnum]); if (bnum==selCB) Frame(w,0,0,CBW-5,CBH-5,2,butFcol,GXcopy); } /********************/ RedrawPanel(w,wwidth,str) Window w; int wwidth; char *str; { static char *gridlab[2]={"X:","Y:"}; int swidth,i,y; swidth = XStringWidth(str,butfinfo,0,0); XPixSet(w,0,0,wwidth,11,panFcol); XText(w,(wwidth-swidth)/2,0,str,strlen(str),butfont,panBcol,panFcol); if (w==traceW) DrawArrs(); else if (w==scaleW) { for (i=0; i<2; i++) { /* labels */ y=16+i*24; if (mono) { XPixSet(scaleW,5,y,14,19,BackColor); XLine (scaleW,5,y, 18,y, 1,1,ForeColor,GXcopy,AllPlanes); XLine (scaleW,5,y+18,18,y+18,1,1,ForeColor,GXcopy,AllPlanes); } XTextMask(scaleW,5,y+4,gridlab[i],strlen(gridlab[i]), butfont,panFcol); } } } /********************/ RedrawOffPan() { #define S1 "Offset" #define S2 "Range" int swidth,i,y; XPixSet(offsetW,0,0,OFFW,11,panFcol); swidth = XStringWidth(S1,butfinfo,0,0); XText(offsetW,60+(65-swidth)/2,0,S1,strlen(S1),butfont,panBcol,panFcol); swidth = XStringWidth(S2,butfinfo,0,0); XText(offsetW,60+70+(65-swidth)/2,0,S2,strlen(S2),butfont,panBcol,panFcol); for (i=0; i<=numy; i++) { /* labels */ char *st; y=16+i*24; if (mono) { XPixSet(offsetW,5,y,50,19,BackColor); XLine(offsetW,5,y, 54,y, 1,1,ForeColor,GXcopy,AllPlanes); XLine(offsetW,5,y+18,54,y+18,1,1,ForeColor,GXcopy,AllPlanes); } if (i) st = ylist[i-1].label; else st = xlist.label; if (i) XTextMask(offsetW,5,y+4,st,strlen(st),butfont,trcol[i-1]); else XTextMask(offsetW,5,y+4,st,strlen(st),butfont,panFcol); if (mono && i) { DashLine(offsetW, 6, y+2, 53, y+2, ForeColor,linepats[i-1]); DashLine(offsetW, 6, y+16, 53, y+16, ForeColor,linepats[i-1]); } } } /********************/ InvertBut(bp) Button *bp; { bp->invert = ~(bp->invert); if (bp->invert) XChangeBackground(bp->win,butFpix); else XChangeBackground(bp->win,butBpix); XClear(bp->win); RedrawBut(bp); XFlush(); } /*********************/ DrawArrs() { int fc, bc; fc=trcol[selCB]; bc=gridBcol; if (LeftArr) XBitmapBitsPut(traceW,15,16,arr_width,arr_height,arrl_bits, fc,fc,leftmask,GXcopy,AllPlanes); else XBitmapBitsPut(traceW,15,16,arr_width,arr_height,arrl_bits, bc,fc,leftmask,GXcopy,AllPlanes); if (RightArr) XBitmapBitsPut(traceW,65,16,arr_width,arr_height,arrr_bits, fc,fc,rightmask,GXcopy,AllPlanes); else XBitmapBitsPut(traceW,65,16,arr_width,arr_height,arrr_bits, bc,fc,rightmask,GXcopy,AllPlanes); if (UpArr[selCB]) XBitmapBitsPut(traceW,115,16,arr_width,arr_height,arru_bits, fc,fc,upmask,GXcopy,AllPlanes); else XBitmapBitsPut(traceW,115,16,arr_width,arr_height,arru_bits, bc,fc,upmask,GXcopy,AllPlanes); if (DownArr[selCB]) XBitmapBitsPut(traceW,165,16,arr_width,arr_height,arrd_bits, fc,fc,downmask,GXcopy,AllPlanes); else XBitmapBitsPut(traceW,165,16,arr_width,arr_height,arrd_bits, bc,fc,downmask,GXcopy,AllPlanes); } /***************************/ DashLine(w,x1,y1,x2,y2,color,pattern) /* draws a Dashed line in window w */ Window w; short x1,y1,x2,y2; int color; Pattern pattern; { Vertex verts[2]; SetVertex(&verts[0],x1,y1,0); SetVertex(&verts[1],x2,y2,0); XDrawDashed(w,verts,2,1,1,color,pattern,GXcopy,AllPlanes); } /****************************/ SetVertex(vert,x,y,flags) Vertex *vert; short x,y; unsigned short flags; { vert->x=x; vert->y=y; vert->flags=flags; } /****************************/ MakeRect(x1,y1,x2,y2) int x1,y1,x2,y2; { /* stores the four lines that make the rectangle in the first five elements of 'curve', for use with XDraw */ SetVertex(curve, x1,y1,0); SetVertex(curve+1,x1,y2,0); SetVertex(curve+2,x2,y2,0); SetVertex(curve+3,x2,y1,0); SetVertex(curve+4,x1,y1,0); } /****************************/ Frame(win,x1,y1,x2,y2,w,color,func) /* draws a rectangle of thickness 'w' */ Window win; /* from x1,y1 to x2,y2 */ short x1,y1,x2,y2; int color,w,func; { short tmp,wide,high; int planes; if (func==GXinvert) { if (mono) planes=1; else planes=selCB+4; } else planes=AllPlanes; /* get x1,y1 to be top left, and x2,y2 to be bot right */ if (x2<x1) swap(x1,x2,tmp); if (y2<y1) swap(y1,y2,tmp); if (w==1) { /* special case for one-pixel thick frames */ MakeRect(x1,y1,x2,y2); XDraw(win,curve,5,1,1,color,func,planes); return; } wide = x2-x1-w+1; high = y2-y1-w+1; if (wide<1 || high<1) return; /* can't draw it, don't bother trying */ /* that done, draw the four rectangles. note that they must not overlap, so that GXinvert can be used */ XPixFill(win,x1, y1, wide,w, color,0,func,planes); /*top */ XPixFill(win,x1+wide,y1, w, high,color,0,func,planes); /*right */ XPixFill(win,x1+w, y1+high,wide,w, color,0,func,planes); /*bottom*/ XPixFill(win,x1, y1+w, w, high,color,0,func,planes); /*left */ } \Rogue\Monster\ else echo "will not over write ./xsplot/xsplotmac.c" fi if `test ! -d ./splotter` then mkdir ./splotter echo "mkdir ./splotter" fi if `test ! -s ./splotter/color.h` then echo "writing ./splotter/color.h" cat > ./splotter/color.h << '\Rogue\Monster\' /* Color definitions. */ #define NONE 0 #define RED 1 #define GREEN 2 #define BLUE 3 #define BLACK 4 #define BROWN 5 #define ORANGE 6 #define VIOLET 7 #define FT_BLACK 8 /* Defined trace color order, a la SPLOT. */ #define FIRST_C GREEN #define SECOND_C RED #define THIRD_C BLUE #define FOURTH_C ORANGE \Rogue\Monster\ else echo "will not over write ./splotter/color.h" fi if `test ! -s ./splotter/lines.h` then echo "writing ./splotter/lines.h" cat > ./splotter/lines.h << '\Rogue\Monster\' /* Line type data and definitions. */ #define TYPE_MASK 0xffff0000 #define VAL_MASK 0x0000ffff #define SOLID 0x00010000 #define THICK 0x00020000 #define DOT_2 0x00040000 #define DOT_4 0x00080000 int y_divs[] = { 0, SOLID| 40, SOLID| 80, SOLID|120, SOLID|160, THICK|200, SOLID|240, SOLID|280, SOLID|320, SOLID|360, 0 }; int x_divs[7][51] = { { 0, SOLID| 40, SOLID| 80, SOLID|120, SOLID|160, THICK|200, SOLID|240, SOLID|280, SOLID|320, SOLID|360, 0 }, { 0, SOLID|120, SOLID|191, SOLID|241, SOLID|280, SOLID|311, SOLID|338, SOLID|361, SOLID|382, 0 }, { 0, SOLID| 40, SOLID| 64, SOLID| 80, SOLID| 93, SOLID|104, SOLID|113, SOLID|120, SOLID|127, THICK|133, SOLID|173, SOLID|197, SOLID|214, SOLID|227, SOLID|237, SOLID|246, SOLID|254, SOLID|261, THICK|267, SOLID|307, SOLID|330, SOLID|347, SOLID|360, SOLID|370, SOLID|379, SOLID|387, SOLID|394, 0 }, { 0,SOLID|19, SOLID|28, SOLID|34, SOLID|38, THICK|40, SOLID|40 +19,SOLID|40 +28,SOLID|40 +34,SOLID|40 +38,THICK|80, SOLID|80 +19,SOLID|80 +28,SOLID|80 +34,SOLID|80 +38,THICK|120, SOLID|120+19,SOLID|120+28,SOLID|120+34,SOLID|120+38,THICK|160, SOLID|160+19,SOLID|160+28,SOLID|160+34,SOLID|160+38,THICK|200, SOLID|200+19,SOLID|200+28,SOLID|200+34,SOLID|200+38,THICK|240, SOLID|240+19,SOLID|240+28,SOLID|240+34,SOLID|240+38,THICK|280, SOLID|280+19,SOLID|280+28,SOLID|280+34,SOLID|280+38,THICK|320, SOLID|320+19,SOLID|320+28,SOLID|320+34,SOLID|320+38,THICK|360, SOLID|360+19,SOLID|360+28,SOLID|360+34,SOLID|360+38,0}, { 0, SOLID|120, SOLID|191, SOLID|241, SOLID|280, SOLID|311, SOLID|338, SOLID|361, SOLID|382, 0 }, { 0, SOLID| 40, SOLID| 64, SOLID| 80, SOLID| 93, SOLID|104, SOLID|113, SOLID|120, SOLID|127, THICK|133, SOLID|173, SOLID|197, SOLID|214, SOLID|227, SOLID|237, SOLID|246, SOLID|254, SOLID|261, THICK|267, SOLID|307, SOLID|330, SOLID|347, SOLID|360, SOLID|370, SOLID|379, SOLID|387, SOLID|394, 0 }, { 0,SOLID|19, SOLID|28, SOLID|34, SOLID|38, THICK|40, SOLID|40 +19,SOLID|40 +28,SOLID|40 +34,SOLID|40 +38,THICK|80, SOLID|80 +19,SOLID|80 +28,SOLID|80 +34,SOLID|80 +38,THICK|120, SOLID|120+19,SOLID|120+28,SOLID|120+34,SOLID|120+38,THICK|160, SOLID|160+19,SOLID|160+28,SOLID|160+34,SOLID|160+38,THICK|200, SOLID|200+19,SOLID|200+28,SOLID|200+34,SOLID|200+38,THICK|240, SOLID|240+19,SOLID|240+28,SOLID|240+34,SOLID|240+38,THICK|280, SOLID|280+19,SOLID|280+28,SOLID|280+34,SOLID|280+38,THICK|320, SOLID|320+19,SOLID|320+28,SOLID|320+34,SOLID|320+38,THICK|360, SOLID|360+19,SOLID|360+28,SOLID|360+34,SOLID|360+38,0} }; \Rogue\Monster\ else echo "will not over write ./splotter/lines.h" fi if `test ! -s ./splotter/makefile` then echo "writing ./splotter/makefile" cat > ./splotter/makefile << '\Rogue\Monster\' CFLAGS = -g splotter: splotter.o cc ${CFLAGS} -o splotter splotter.o splotter.o: scaling.h lines.h plot.h color.h \Rogue\Monster\ else echo "will not over write ./splotter/makefile" fi if `test ! -s ./splotter/plot.h` then echo "writing ./splotter/plot.h" cat > ./splotter/plot.h << '\Rogue\Monster\' #define pen_up() fprintf(out, "PU") #define pen_down() fprintf(out, "PD") #define plot_to(x, y) fprintf(out, "PA%d,%d;", x, y) #define rplot_to(x, y) fprintf(out, "PR%d,%d;", x, y) #define fplot_to(x, y) fprintf(out, "PA%f,%f;", x, y) #define select_pen(x) if(pc != x) {fprintf(out, "SP%d;", x); pc = x;} #define def_line() fprintf(out, "LT;") #define line_type(x,y) fprintf(out, "LT%d,%d;", x, y) #define clip_set() fprintf(out, "IW%d,%d,%d,%d;", 0, 0, (int)RBOX_SIZE,\ (int)RBOX_SIZE) #define clip_clear() fprintf(out, "IW;") #define set_slow() fprintf(out, "VS5;") #define set_fast() fprintf(out, "VS30;") #define low_acc() fprintf(out, "AS1;") #define high_acc() fprintf(out, "AS;") /* Label functions. */ #define label(l) fprintf(out, "LB%s\003", l) #define flabel(l) fprintf(out, "LB%f\003", l) #define label_2(m, e) fprintf(out, "LB%de2^%d\003", m, e) #define label_10(m, e) fprintf(out, "LB%de10^%d\003", m, e) #define label_size(s) fprintf(out, "SR%f,%f;", s, s) #define label_origin(s) fprintf(out, "LO%d;", s) #define horiz_label() fprintf(out, "DI;") #define vert_label() fprintf(out, "DI0,-1;") \Rogue\Monster\ else echo "will not over write ./splotter/plot.h" fi if `test ! -s ./splotter/scaling.h` then echo "writing ./splotter/scaling.h" cat > ./splotter/scaling.h << '\Rogue\Monster\' /* These definitions are for defining paper scaling. */ /* Paper space definitions. */ #define BORDER 500.0 #define RBOX_SIZE 400.0 #define ADJUST 250.0 /* Tick mark constants. */ #define MINOR_TICK 3 #define NUM_TICKS 50 #define TICK_MOD 5 #define TICK_DIST (int)(RBOX_SIZE/NUM_TICKS) /* Misc. scaling definitions. */ #define X_RANGE (MAXX - MINX) #define Y_RANGE (MAXY - MINY) #define BOX_SIZE (Y_RANGE - 2.0 * BORDER) #define G_R (RBOX_SIZE/BOX_SIZE) #define BO_x ( (X_RANGE - BOX_SIZE) / 2.0 + MINX) #define BO_y ( (Y_RANGE - BOX_SIZE) / 2.0 + MINY) /* Scaled P1 and P2 values. */ #define P1Rx (MINX - BO_x + (asize?0:ADJUST)) #define P2Rx (MAXX - BO_x + (asize?0:ADJUST)) #define P1Ry (MINY - BO_y - (asize?ADJUST:0)) #define P2Ry (MAXY - BO_y - (asize?ADJUST:0)) /* Header labeling constants. */ #define H_LABEL_SIZE 2.0 #define FNAME_Y 430 #define ANNAME_Y 415 #define H_O_TYPE 5 /* Axis labeling constants. */ #define A_LABEL_SIZE .5 #define A_O_TYPE 5 #define CLOSE_OFF 50 #define FAR_OFF 100 #define X_OFF -40 \Rogue\Monster\ else echo "will not over write ./splotter/scaling.h" fi if `test ! -s ./splotter/splotter.c` then echo "writing ./splotter/splotter.c" cat > ./splotter/splotter.c << '\Rogue\Monster\' #include <stdio.h> #include "scaling.h" #include "plot.h" #include "lines.h" #include "color.h" #define DISPLAY_FILE "/usr/vlsi/berk/lib/displays" /* Misc. definitions. */ #define MAX_TRACES 4 #define MAX_POINTS 900 #define BUF_SIZE 256 /* Paper size defintions, a la P1 and P2. */ /* For A size paper defaults. */ float MINY = 320.0; float MAXY = 7520.0; float MINX = 80.0; float MAXX = 10080.0; int asize = 1; typedef union f_i{ float f; int i; } F_I; typedef struct axis_des { F_I offset, range; } AXIS_DES; AXIS_DES x_axis_des; AXIS_DES y_axis_des[MAX_TRACES]; /* Pen color. */ int pc; char * plotter = "plot1"; char f_name[BUF_SIZE]; char an_name[BUF_SIZE]; int grid_type; int num_traces; int * traces; int * x_trace; int num_read; FILE * out; int is_tty; main(argc, argv) /* Process command line arguments. * Allocate data, open files, * call routines. */ int argc; char ** argv; { char * get_display(); char * in_fname = NULL, * out_fname = NULL; char * arg_ptr; /* Pointer to command args. */ /* Process command line arguments. */ for(argv++; *argv != NULL; argv++) if( *(arg_ptr = *argv) == '-') while(*++arg_ptr != '\0') switch(*arg_ptr){ case 'i': in_fname = *++argv; break; case 'o': out_fname = *++argv; break; case 'a': MINX = 80.0; MAXX = 10080.0; MINY = 320.0; MAXY = 7520.0; asize = 1; break; case 'b': MINX = 620.0; MAXX = 15820.0; MINY = 80; MAXY = 10080; asize = 0; break; case 'p': plotter = *++argv; break; } if(in_fname == NULL) in_fname = get_display(); if(strcmp(in_fname, "-")) if( freopen(in_fname, "r", stdin) == NULL) error("can't open %s\n", in_fname); read_data(); #ifdef PDEBUG print_data(); #endif if(out_fname == NULL){ char command[BUF_SIZE]; sprintf(command, "lpr -P%s -J \"%s\" -T \"%s\"", plotter, f_name, an_name); if((out = popen(command, "w")) == NULL) error("pipe error to printer - help\n"); } else if(strcmp(out_fname, "-")){ if( (out = fopen(out_fname, "w")) == NULL) error("can't open %s\n", out_fname); } else out = stdout; is_tty = isatty(out->_file); if(is_tty) init_plot(); startup(); set_grid(); plot_grid(); label_grid(); plot_traces(); label_it(); select_pen(NONE); closeup(); } char * get_display(str) { char line[BUF_SIZE]; FILE * f; char text_d[BUF_SIZE], disp_d[BUF_SIZE]; char * ttyname(); char * tty; if((f = fopen(DISPLAY_FILE, "r")) == NULL) error("can't open display file %s\n", DISPLAY_FILE); if( (tty = ttyname(0)) == NULL ) error("can't find my ttyname\n"); while(fgets(line, BUF_SIZE, f) != NULL){ if(sscanf(line, "%s %s", text_d, disp_d) != 2) error("display file format error\n"); if(!strcmp(text_d, tty)){ if((tty = (char *)malloc(strlen(disp_d + 1))) == NULL) error("memory error\n"); strcpy(tty, disp_d); return(tty); } } error("can't find text %s in display file\n", tty); } init_plot() { fprintf(out, "\33.J\33.@1024;2:\33.P1:"); fprintf(out, "\33.N;19:\33.I300;;17:\33.M;;;10:"); } startup() { /* Set plotter up. */ fprintf(out, "\33.(RO;DFIP;AP5;"); } closeup() { /* Close plotter up. */ fprintf(out, "DFPG1;\33.)"); } set_grid() { fprintf(out, "IP%d,%d,%d,%d;", (int)MINX, (int)MINY, (int)MAXX, (int)MAXY); fprintf(out, "SC%.2f,%.2f,%.2f,%.2f;", P1Rx*G_R,P2Rx*G_R,P1Ry*G_R,P2Ry*G_R); } read_data() { int i; int j; int * x_ptr, * t_ptr; if(gets(f_name) == NULL) error("error reading file name\n", 0); if(gets(an_name) == NULL) error("error reading analysis name\n", 0); if(scanf("%d ", &grid_type) != 1) error("error reading grid type\n", 0); if(scanf("%d ", &num_traces) != 1) error("error reading number of traces\n", 0); switch(grid_type){ case 0: if(scanf("%f %f ", &x_axis_des.offset.f, &x_axis_des.range.f) != 2) error("error reading x-axis\n"); break; case 1: case 2: case 3: if(scanf("10^%d %d ", &x_axis_des.offset.i, &x_axis_des.range.i) != 2) error("error reading x-axis\n"); break; case 4: case 5: case 6: if(scanf("2^%d %d ", &x_axis_des.offset.i, &x_axis_des.range.i) != 2) error("error reading x-axis\n"); break; default: error("internal error - help\n"); break; } for(i = 0; i < num_traces; i++) if( scanf("%f %f ", &y_axis_des[i].offset.f, &y_axis_des[i].range.f) != 2) error("error reading y-axis\n"); if( (x_trace = (int *)calloc(MAX_POINTS, sizeof(int))) == NULL) error("memory error - help\n", 0); if((traces = (int *)calloc(MAX_POINTS*num_traces,sizeof(int))) == NULL) error("memory error - help\n", 0); for(x_ptr = x_trace, t_ptr = traces, i = 0, num_read = 0; i < MAX_POINTS; i++, num_read++, x_ptr++){ if(scanf("%d ", x_ptr) != 1) break; for(j = 0; j < num_traces; j++, t_ptr++) if(scanf("%d ", t_ptr) != 1) error("format error last line\n"); } } #ifdef PDEBUG print_data() { int i; int j; fprintf(stderr, "%s\n%s\n%d\n%d\n", f_name, an_name, grid_type, num_traces); switch(grid_type){ case 0: fprintf(stderr, "%f %f\n", x_axis_des.offset.f, x_axis_des.range.f); break; case 1: case 2: case 3: fprintf(stderr, "10^%d %d\n", x_axis_des.offset.i, x_axis_des.range.i); break; case 4: case 5: case 6: fprintf(stderr, "2^%d %d\n", x_axis_des.offset.i, x_axis_des.range.i); break; default: error("debug error - help\n"); break; } for(i = 0; i < num_traces; i++) fprintf(stderr, "%f %f\n", y_axis_des[i].offset.f, y_axis_des[i].range.f); for(i = 0; i < num_read; i++){ fprintf(stderr, "%d ", x_trace[i]); for(j = 0; j < num_traces; j++) fprintf(stderr, "%d ", traces[j][i]); fprintf(stderr, "\n"); } } #endif plot_grid() { int i; int coord; float f_coord; int l_type; int sw = 0; int *l_ptr; set_fast(); low_acc(); /* Draw Box. */ select_pen(BLACK); plot_to(0,0); draw_rbox((int)RBOX_SIZE); fplot_to(-.5, -.5); draw_rbox((int)RBOX_SIZE + 1); plot_to(-1,-1); draw_rbox((int)RBOX_SIZE+2); /* Draw Y grid. */ for(l_ptr = &y_divs[1]; *l_ptr; l_ptr++){ coord = VAL_MASK & *l_ptr; f_coord = (float)coord; l_type = TYPE_MASK & *l_ptr; if(!sw){ plot_to(0, coord); fline_to(0.0, f_coord, RBOX_SIZE, f_coord, l_type); } else{ plot_to((int)RBOX_SIZE, coord); fline_to(RBOX_SIZE, f_coord, 0.0, f_coord, l_type); } sw = !sw; } /* Draw X grid. */ for(l_ptr = &x_divs[grid_type][1]; *l_ptr; l_ptr++){ coord = VAL_MASK & *l_ptr; f_coord = (float)coord; l_type = TYPE_MASK & *l_ptr; if(!sw){ plot_to(coord, 0); fline_to(f_coord, 0.0, f_coord, RBOX_SIZE, l_type); } else{ plot_to(coord, (int)RBOX_SIZE); fline_to(f_coord, RBOX_SIZE, f_coord, 0.0, l_type); } sw = !sw; } if(!grid_type){ /* Must do tick marks for linear grid. */ def_line(); select_pen(BLACK); set_slow(); for(i = 1; i < NUM_TICKS; i++) if(i%TICK_MOD){ plot_to(i*TICK_DIST, (int)RBOX_SIZE/2-MINOR_TICK); pen_down(); plot_to(i*TICK_DIST, (int)RBOX_SIZE/2+MINOR_TICK); pen_up(); } else{ /* don't plot major tick marks */ } for(i = 1; i < NUM_TICKS; i++) if(i%TICK_MOD){ plot_to((int)RBOX_SIZE/2-MINOR_TICK, i*TICK_DIST); pen_down(); plot_to((int)RBOX_SIZE/2+MINOR_TICK, i*TICK_DIST); pen_up(); } else{ /* don't plot major tick marks */ } } set_fast(); high_acc(); } label_grid() { int i, j; int * l_ptr; float label_acc, label_inc; int m, e; int label_loc = X_OFF; label_origin(A_O_TYPE); label_size(A_LABEL_SIZE); vert_label(); select_pen(BLACK); l_ptr = &x_divs[grid_type][1]; switch(grid_type){ case 0: label_inc = x_axis_des.range.f; label_acc = x_axis_des.offset.f - 4 * label_inc; for(i = 0; i < 9; i++, l_ptr++){ plot_to(VAL_MASK & *l_ptr, label_loc); flabel(label_acc); label_acc += label_inc; } break; case 1: e = x_axis_des.offset.i; for(i = 2; i < 10; i++, l_ptr++){ plot_to(VAL_MASK & *l_ptr, label_loc); label_10(i, e); } break; case 2: e = x_axis_des.offset.i; for(i = 0; i < 3; i++, e++) for(j = (i?1:2); j < 10; j++, l_ptr++){ plot_to(VAL_MASK & *l_ptr, label_loc); label_10(j, e); } break; case 3: e = x_axis_des.offset.i + 1; for(i = 1; i < 10; i++, e++, l_ptr++){ l_ptr += 4; plot_to(VAL_MASK & *l_ptr, label_loc); label_10(1, e); } break; case 4: e = x_axis_des.offset.i; for(i = 2; i < 10; i++, l_ptr++){ plot_to(VAL_MASK & *l_ptr, label_loc); label_2(i, e); } break; case 5: e = x_axis_des.offset.i; for(i = 0; i < 3; i++, e++) for(j = (i?2:1); j < 10; j++, l_ptr++){ plot_to(VAL_MASK & *l_ptr, label_loc); label_2(j, e); } break; case 6: e = x_axis_des.offset.i + 1; for(i = 1; i < 10; i++, e++, l_ptr++){ l_ptr += 4; plot_to(VAL_MASK & *l_ptr, label_loc); label_2(1, e); } break; } } plot_traces() { int i, j; int * t_ptr, * x_ptr, * l_ptr; float label_acc, label_inc; int label_loc; low_acc(); set_slow(); label_size(A_LABEL_SIZE); label_origin(A_O_TYPE); horiz_label(); for(i = 0; i < num_traces; i++){ switch(i){ case 0: select_pen(FIRST_C); break; case 1: select_pen(SECOND_C); break; case 2: select_pen(THIRD_C); break; case 3: select_pen(FOURTH_C); break; default: select_pen(RED); break; } x_ptr = x_trace; t_ptr = traces + i; plot_to(*x_ptr, *t_ptr); pen_down(); clip_set(); for(j = 1; j < num_read; j++){ x_ptr++; t_ptr += num_traces; plot_to(*x_ptr, *t_ptr); } for(j -= 2; j >= 0; j--){ x_ptr--; t_ptr -= num_traces; plot_to(*x_ptr, *t_ptr); } clip_clear(); pen_up(); switch(i){ case 0: label_loc = -CLOSE_OFF; break; case 1: label_loc = (int)RBOX_SIZE + CLOSE_OFF; break; case 2: label_loc = -FAR_OFF; break; case 3: label_loc = (int)RBOX_SIZE + FAR_OFF; break; } label_inc = y_axis_des[i].range.f; label_acc = y_axis_des[i].offset.f - 4 * label_inc; for(l_ptr = &y_divs[1]; *l_ptr; l_ptr++){ plot_to(label_loc, VAL_MASK & *l_ptr); flabel(label_acc); label_acc += label_inc; } } high_acc(); set_fast(); } label_it() { label_size(H_LABEL_SIZE); label_origin(H_O_TYPE); select_pen(VIOLET); plot_to((int)(RBOX_SIZE/2.0), FNAME_Y); label(f_name); plot_to((int)(RBOX_SIZE/2.0), ANNAME_Y); label(an_name); } draw_rbox(size) int size; { pen_down(); rplot_to(size, 0); rplot_to(0, size); rplot_to(-size, 0); rplot_to(0, -size); pen_up(); } line_to(x, y, type) int x, y, type; { int tpc; int slow = 1; if(type != -1) switch(type){ case DOT_2: line_type(-2, 1); set_slow(); break; case DOT_4: tpc = pc; select_pen(FT_BLACK); line_type(-1, 1); set_slow(); break; case SOLID: default: def_line(); slow = 0; break; } pen_down(); plot_to(x, y); pen_up(); if(type == DOT_4) select_pen(tpc); if(slow) set_fast(); } fline_to(xf, yf, xt, yt, type) float xf, yf, xt, yt; int type; { int tpc; int slow = 1; if(type != -1) switch(type){ case DOT_2: line_type(-2, 1); set_slow(); break; case DOT_4: tpc = pc; select_pen(FT_BLACK); line_type(-1, 1); set_slow(); break; case SOLID: case THICK: default: def_line(); slow = 0; break; } pen_down(); if(type == THICK) if(xf == xt){ /* Verticla line. */ fplot_to(xf - (float).5, yt); fplot_to(xt - (float).5, yt); fplot_to(xt, yt); fplot_to(xf, yf); fplot_to(xf + (float).5, yf); fplot_to(xt + (float).5, yt); } else{ /* Horizontal line. */ fplot_to(xf, yf - (float).5); fplot_to(xt, yt - (float).5); fplot_to(xt, yt); fplot_to(xf, yf); fplot_to(xf, yf + (float).5); fplot_to(xt, yt + (float).5); } else fplot_to(xt, yt); pen_up(); if(type == DOT_4) select_pen(tpc); if(slow) set_fast(); } error(str, num) char * str; int num; { fprintf(stderr, str, num); exit(1); } \Rogue\Monster\ else echo "will not over write ./splotter/splotter.c" fi if `test ! -s ./splotter/splotter.l` then echo "writing ./splotter/splotter.l" cat > ./splotter/splotter.l << '\Rogue\Monster\' .TH SPLOTTER local .UC 4 .SH NAME splotter \- plot spif format file (from splot) on HPGL plotters .SH SYNTAX .B splotter [ .B -ioabcr ] [ arguments... ] .br .SH DESCRIPTION .PP .I Splotter takes as input a file in .B spif format. .B Spif is a specialized intermediate file format for plotting .B SPICE output. .B Spif was developed at the .B Digital .B Systems .B Laboratory, .B University .B of .B Pennsylvania. .B Spif files are generated by .I splot, a program distributed by the .B DSL. .PP The simplest usage of .I splotter is described in this paragraph, and the following paragraphs describe more advanced features. To generate .B spif files, one must use the .I plot command in .I splot. For simple operation, select the serial line option from the .I plot command. This will send the .B spif file to the text terminal associated with the graphics display that .I splot is running on. So, from the text terminal, type the command .I 'splotter'. Then from within .I splot, plot to the serial line. Whatever was on the .I splot display window will magically appear at the plotter. That's all there is to it. Please note that this trick only works with text-display pairs that are hardwired and specified in the file ~cad/lib/displays. .PP There are several options to .I splotter as follows: .TP .B -i The folowing argument is taken as the input .B spif file. The default is the graphics display specified in ~cad/lib/displays. .TP .B -o The following argument is taken as the output file. The default is to spool to the plotter. The defualt plotter is called .I 'plot1'. .TP .B -a .I Splotter will assume 'A' size paper. This is the default. .TP .B -h Print a banner page. If not asserted, the users name - as specified in the .I gcos field of the password entry - and time are printed on the plot. The default is to not print the banner page. .TP .B -b .I Splotter will assume 'B' size paper. .B -a is the default. .TP .B -p The following argument is taken as the name of the plotter to spool to, if the .B -o option is not used. The default is .I 'plot1'. .TP .B -c Do not clip the traces to the grid window. This option is for plotters which do not clip properly. If the plot comes out without the traces, try this option. The default is to clip. .TP .B -r The following argument specifies the number of times the traces are drawn. Each time a trace is drawn, it is drawn forwards and backwards. The default is one. .TP .B -u The filename specified by the -i option is unlinked after it is printed. .PP .I Splotter supports a number of environment settings for tailoring it to the user's likes. The environment variable is called .I 'SPLOTOPTS'. It has the form 'option=value,option=value,....'. Do not use any extra spaces in the specification. The following environment options are available: .TP 10 .B slow Sets the slow plotter speed for drawing traces. The acceptable range is 5 to 80 cm/s. The default is 5. .TP 10 .B fast Sets the fast speed for the plotter. The range is 5 to 80 cm/s. The default is 30. .TP 10 .B penX Sets the pen color of trace number X. Legal pens are pen1, pen2, pen3, pen4. See below for color values. The respective defaults are green, red, blue, and orange. .TP 10 .B gridc Sets the pen color for drawing the grid. See below for color values. The default is black. .TP 10 .B gridl Sets the pen color for labeling the x-axis of the grid. See below for color values. The default is black. .TP 10 .B namec Sets the pen color for drawing the users name and time if the .B -h option is not specified. See below for color values. The default is brown. .TP 10 .B headc Sets the pen color for drawing the header strings. These are the name of the file, and the analysis type. See below for color values. The default is violet. .TP 10 .B size Set the expected paper size. If 'a' is specified, 'A' size paper is expected. Otherwise 'B' size paper is expected. The default is 'a'. .PP The following colors are available: red, green, blue, black, brown, orange, and violet. These pens reside in pen carriage locations 1 to 7, respectively, for the .I HP75xx plotters. Two other colors are available. The color 'none' specifies that no pen is to be used. The color 'eight' specifies the pen in carriage position 8. This color is unspecified. .PP As an example, suppose the user does not want a banner page or his name printed on the plot. To accomplish this, set .I SPLOTOPTS to "namec=none". .SH FILES /usr/local/splotter .br /usr/local/warmup pen exerciser .br /usr/cad/lib/displays text-graphic display link file .SH BUGS AND CAVEATS .PP .I Splotter .B cannot guarantee the quality of pen traces that come out of the plotter. To help warm up the plotter pens, run the program 'warmup' to exercise the pens. However, .B DO .B NOT attempt to clean the pens by hand. If you do, you may be ejected from the .B DSL. Report any bugs to a .B DSL staff member. .SH SEE ALSO hplot(local) .SH AUTHOR David P. Feldman .br Digital Systems Laboratory .br University of Pennsylvania \Rogue\Monster\ else echo "will not over write ./splotter/splotter.l" fi if `test ! -s ./splotter/README` then echo "writing ./splotter/README" cat > ./splotter/README << '\Rogue\Monster\' Notes on splotter: Splotter is the program that takes data generated by xsplot and plots it. It will (in theory) drive any HP-GL plotter, though we only have a HP 7550A, so who knows... Anyhow, splotter takes the data from xsplot, converts it to HP-GL commands, and execs 'lpr' to print it on 'plot1'. This has several nice features. One is that queueing is automatically dealt with. Another is that lpr allows you to print on remote machines. For example, on my RT workstation, I have the following entry in my /etc/printcap file: #plotter 'plot1' on dsl plot1:\ :lp=:rm=dsl.cis.upenn.edu:rp=plot1:sd=/usr/spool/plot1d and on 'dsl.cis.upenn.edu' (the VAX that the plotter is hooked to) I've got the following: plot1|7550a|hp7550a:\ :lp=/dev/plot1:sd=/usr/spool/plot1:lf=/usr/adm/plot-log:br#9600:\ :fs#0x200003:fc#0dffffc:af=/usr/adm/plot.acct:mc#1:sf:sh:\ :if=/etc/plotif:of=/usr/lib/lpf: Needless to say, it works. Your mileage may vary. Anyhow, regarding the splotter man page, it contains a lot of information that you won't need to know if you're running xsplot. (We have versions of splot running on PCs (EGA and PGA), and they have to go through some extra steps to get the data up to the host machine.) If you're running xsplot, and have splotter installed, you probably will never have to actually run splotter by hand, as xsplot will do that for you. However, if you have splotter and xsplot running on different machines (for whatever reason), all you have to know to run it is "splotter -i spiffile". John Bradley - University of Pennsylvania - bradley@cis.upenn.edu P.S. You may wish to refer any plotter-related questions to the author. (David Feldman - david@dsl.cis.upenn.edu) I don't *do* hardware. \Rogue\Monster\ else echo "will not over write ./splotter/README" fi echo "Finished archive 1 of 4" exit
bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)
xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE output. It will drive an HP-GL plotter for hardcopy. It can be used to look at non-SPICE data, also. Why, it could be the Neatest Thing Ever. Probably not, though. Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and 4.3, and on random Vaxen under Ultrix 1.2 and 2.0) --John Bradley - University of Pennsylvania - bradley@cis.upenn.edu Part 2 of 4 -------------------------cut here---------------------- #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -d ./xsplot` then mkdir ./xsplot echo "mkdir ./xsplot" fi if `test ! -s ./xsplot/xsplotctl.c` then echo "writing ./xsplot/xsplotctl.c" cat > ./xsplot/xsplotctl.c << '\Rogue\Monster\' /************************************************************************/ /* XSPLOTCTL.C */ /*----------------------------------------------------------------------*/ /* Library of routines to handle controls (push buttons) */ /*----------------------------------------------------------------------*/ /* void R2Str (num); */ /* void O2Str (num); */ /* void ModifyBut (bnum,ctrl); */ /* void SetXButs (); */ /* void DrawXButs (); */ /* void FpToEng (str,num); */ /************************************************************************/ #include "xsplot.h" /************************************************************************/ R2Str(num) int num; /* takes the power and multiplier values and fills in the str and val fields */ { Range *rp = &ranges[num]; strcpy(rp->str,multstr[rp->multiplier]); strcat(rp->str,prefix[rp->power]); strcat(rp->str,units[num]); rp->val=mult[rp->multiplier] * pow(10.0,(double) ((rp->power-4)*3) ); } /************************************************************************/ O2Str(num) int num; /* takes the val field and fills in the str field */ { Offset *op = &offsets[num]; char tmp[20]; int i,e; FpToEng(tmp,op->val); /* tmp = 'x.xxxExx' */ /* find the 'E' part, truncate tmp at that point, and set 'e' = the exponent */ for (i=4; (tmp[i]!='E') && tmp[i]; i++); if (!tmp[i]) e=0; /* was no 'E' */ else { tmp[i]='\0'; e=atoi(tmp+i+1); } /* do a quick range check */ if (e<-12) { op->val=0.0; strcpy(tmp,"0.000"); e=0; } if (e>12 && op->val>0.0) { op->val= 999.9e12; strcpy(tmp,"999.9"); e=12; } if (e>12 && op->val<0.0) { op->val= -999.9e12; strcpy(tmp,"-999.9"); e=12; } /* tack units onto end of string */ strcat(tmp,prefix[(e/3)+4]); strcat(tmp,units[num]); strcpy(op->str,tmp); } /************************************************************************/ ModifyBut(bnum,ctrl) int bnum; { if (ctrl==12) Norm(bnum); else if (ctrl==13) Neg(bnum,1); else if (ctrl==14) Pos(bnum,1); else if (ctrl==15) Neg(bnum,2); else if (ctrl==16) Pos(bnum,2); else if (ctrl==17) Neg(bnum,3); else if (ctrl==18) Pos(bnum,3); } /************************************************************************/ static Neg(bnum,amount) int bnum,amount; { int rnum,i; Range *rp; Offset *op; /* if it's one of the X controls, and we're non-linear, then deal */ if ((bnum==2 || bnum==3) && xscal!=LINEAR) ModXCtrl(bnum,-1*amount); /* see if it's one of the range controls */ else if ((bnum==3) || (bnum==5) || (bnum==7) || (bnum==9) || (bnum==11)) { rnum=(bnum-3)/2; rp= &ranges[rnum]; switch (amount) { case 1: rp->multiplier--; break; case 2: rp->multiplier-=3; break; case 3: rp->power--; break; } /* adjust things */ if (rp->multiplier<0) { rp->multiplier+=9; rp->power--; } if (rp->power<0) { rp->power = rp->multiplier = 0; } R2Str(rnum); butts[bnum].st = rp->str; RedrawBut(&butts[bnum]); } /* see if it's one of the offset controls */ else if ((bnum==2) || (bnum==4) || (bnum==6) || (bnum==8) || (bnum==10)) { if (ylock && bnum!=2) { for (i=1; i<=numy; i++) ModOffset(i,-1*amount); } else { rnum=(bnum-2)/2; ModOffset(rnum,-1*amount); } } /* see if it's the X Grid Control */ else if (bnum==0) { xscal=(xscal+2) % 3; butts[bnum].st=scals[xscal]; RedrawBut(&butts[bnum]); DrawXButs(); } } /************************************************************************/ static Pos(bnum,amount) int bnum,amount; { int rnum,i; Range *rp; Offset *op; /* if it's one of the X controls, and we're non-linear, then deal */ if ((bnum==2 || bnum==3) && xscal!=LINEAR) ModXCtrl(bnum,amount); /* see if it's one of the range controls */ else if ((bnum==3) || (bnum==5) || (bnum==7) || (bnum==9) || (bnum==11)) { rnum=(bnum-3)/2; rp= &ranges[rnum]; switch (amount) { case 1: rp->multiplier++; break; case 2: rp->multiplier+=3; break; case 3: rp->power++; break; } /* adjust things */ if (rp->multiplier>8) { rp->multiplier-=9; rp->power++; } if (rp->power>8) { rp->power = rp->multiplier = 8; } R2Str(rnum); butts[bnum].st = rp->str; RedrawBut(&butts[bnum]); } /* see if it's one of the offset controls */ else if ((bnum==2) || (bnum==4) || (bnum==6) || (bnum==8) || (bnum==10)) { if (ylock && bnum!=2) { for (i=1; i<=numy; i++) ModOffset(i,amount); } else { rnum=(bnum-2)/2; ModOffset(rnum,amount); } } /* see if it's the X Grid Control */ else if (bnum==0) { xscal=(xscal+1) % 3; butts[bnum].st=scals[xscal]; RedrawBut(&butts[bnum]); DrawXButs(); } } /************************************************************************/ static Norm(bnum) int bnum; { int rnum,i; Range *rp; Offset *op; if ((bnum==2 || bnum==3) && xscal!=LINEAR) ModXCtrl(bnum,0); else if ((bnum==3) || (bnum==5) || (bnum==7) || (bnum==9) || (bnum==11)) { rnum=(bnum-3)/2; rp = &ranges[rnum]; rp->power =4; rp->multiplier=0; rp->val=1.0; R2Str(rnum); butts[bnum].st=rp->str; RedrawBut(&butts[bnum]); } else if ((bnum==2) || (bnum==4) || (bnum==6) || (bnum==8) || (bnum==10)) { if (ylock && bnum!=2) { for (i=1; i<=numy; i++) { offsets[i].val=0.0; O2Str(i); butts[2+i*2].st=offsets[i].str; RedrawBut(&butts[2+i*2]); } } else { rnum=(bnum-2)/2; offsets[rnum].val=0.0; O2Str(rnum); butts[bnum].st=offsets[rnum].str; RedrawBut(&butts[bnum]); } } else if (bnum==0) { xscal=LINEAR; butts[bnum].st=scals[xscal]; RedrawBut(&butts[bnum]); DrawXButs(); } } /************************************************************************/ static ModOffset(num,amt) int num,amt; { double rng; int i,bnum; bnum = num*2+2; rng = ranges[num].val; if (amt== 3) offsets[num].val += (rng*10.0); else if (amt== 2) offsets[num].val += (rng); else if (amt== 1) offsets[num].val += (rng/10.0); else if (amt== -1) offsets[num].val -= (rng/10.0); else if (amt== -2) offsets[num].val -= (rng); else if (amt== -3) offsets[num].val -= (rng*10.0); O2Str(num); butts[bnum].st=offsets[num].str; RedrawBut(&butts[bnum]); } /************************************************************************/ static ModXCtrl(bnum,amt) int bnum,amt; { int *offs, *rang; if (xscal==LOG10) { offs = &L10Offset; rang = &L10Range;} else { offs = &OctOffset; rang = &OctRange;} if (bnum==2) { /* offset */ if (amt) { *offs += amt; if (*offs<-19) *offs = -19; if (*offs>19) *offs = 19; } else *offs=0; SetXButs(); RedrawBut(&butts[bnum]); } else { /* range */ if (amt>0) { *rang+=1; *rang%=3; } else if (amt<0) { *rang+=2; *rang%=3; } else *rang=0; SetXButs(); RedrawBut(&butts[bnum]); } } /************************************************************************/ SetXButs() /* sets top two buttons (2,3) to appropriate strings */ { static char oStr[20]; static char rStrs[3][8]={"1 div","3 divs","10 divs"}; switch (xscal) { case LINEAR: butts[2].st=offsets[0].str; butts[3].st=ranges[0].str; break; case LOG10: sprintf(oStr,"1E%d %s",L10Offset,units[0]); butts[2].st=oStr; butts[3].st=rStrs[L10Range]; break; case OCTAVE: sprintf(oStr,"2^%d %s",OctOffset,units[0]); butts[2].st=oStr; butts[3].st=rStrs[OctRange]; break; } if (butts[0].st != scals[xscal]) { butts[0].st = scals[xscal]; } } /************************************************************************/ DrawXButs() /* sets top two buttons (2,3) to appropriate strings and draws them */ { SetXButs(); RedrawBut(&butts[2]); RedrawBut(&butts[3]); } /******************/ FpToEng(st,aval) char *st; double aval; /* * converts a floating point number to a string in the form 'x.xxx Exx', * where the Exx is divisible by 3. (engineering notation) */ { int e,ei,i,j; char tmp[20]; sprintf(st,"%e",fabs(aval)); /* generate the 'std' E-notation */ *(st+5)='\0'; /* take the first five chars */ /* 'x.xxx' */ for (i=6; *(st+i)!='e'; i++); /* find the beginning of the 'E' part */ i++; e=atoi(st+i); /* exponent value (an integer) */ i=(e+99) % 3; /* number of places to shift dec. point (0-2) */ ei = e-i; /* new/improved exp. value (divisible by 3) */ for (j=1; j<=i; j++) /* shift the decimal point right 0-2 times */ *(st+j) = *(st+j+1); *(st+i+1) = '.'; if (aval<0.0) { /* if negative, add a '-' sign at the front */ for (i=4; i>0; i--) *(st+i) = *(st+i-1); *st = '-'; } if (ei) { /* tack on the exponent part */ sprintf(tmp,"E%-3d",ei); strcat(st,tmp); } } \Rogue\Monster\ else echo "will not over write ./xsplot/xsplotctl.c" fi if `test ! -s ./xsplot/xsplotdiv.c` then echo "writing ./xsplot/xsplotdiv.c" cat > ./xsplot/xsplotdiv.c << '\Rogue\Monster\' /************************************************************************/ /* XSPLOTDIV.C - routines for manipulating the 'diversion' */ /*----------------------------------------------------------------------*/ /* InitDivers(); - called once at start of program to init it */ /* OpenDivers(); - open up the diversion and execute it */ /* RedrawDivers(); - called by 'HandleEvent' to redraw the thing */ /************************************************************************/ #include "xsplot.h" /* size of interesting part of diversion window */ #define DW 200 #define DH 290 #define BRWIDE 16 #define BRHIGH 8 #define BRWIDE2 8 #define BRHIGH2 4 #define BX(j) (20*j + 10) #define BY(i) (14*i + 24) static int invplanes,score,fast,small,grace,ballnum,numbricks; static short bx,by,bdx,bdy,px,py; static int pwidth, bwidth=6, pwidth2, bwidth2; static Cursor noncurs; static short brick[6][10]; /* hint, hint */ static short bscore[6] = {5,5,3,3,1,1}; /************************************************************************/ InitDivers() { static short non_bits[8] = {0,0,0,0,0,0,0,0}; /* an inviso-cursor */ invplanes = dlgFcol ^ dlgBcol; px = -1; /* a very unlikely number */ py = 272; bwidth2 = bwidth/2; NewGame(); noncurs = XCreateCursor(8,8,non_bits,non_bits,0,0,1,0,GXcopy); XDefineCursor(diversW,noncurs); } /************************************************************************/ static NewGame() { score = ballnum = 0; NewBall(); NewBricks(); } /************************************************************************/ static NewBall() { char *tmp = "Game Over"; char *tmp1 = "Click mouse to continue"; XEvent event; ballnum++; if (ballnum==4) { /* game over */ XText(diversW,(DW-XStringWidth(tmp,butfinfo,0,0))/2, 150,tmp,strlen(tmp),butfont,dlgFcol,dlgBcol); XText(diversW,(DW-XStringWidth(tmp1,butfinfo,0,0))/2, 162,tmp1,strlen(tmp1),butfont,dlgFcol,dlgBcol); } bx = (abs(rand())%20)*10 + 5; by = 141; bdx = (abs(rand())%21)-10; bdy = 6; InvertPad(); pwidth=32; pwidth2 = pwidth/2; InvertPad(); fast=small=0; grace=40; } /************************************************************************/ static NewBricks() { int i,j; numbricks=60; for (i=0; i<6; i++) for (j=0; j<10; j++) brick[i][j]=1; } /************************************************************************/ OpenDivers() { XEvent event; Window subw; int mx,my,ox,oy,gameover; int i,w,h,sc; sc=selCB; selCB=3; /* to force the inverted frame to be color '3' */ for (i=1; i<=201; i+=8) { Frame(gridW,i-10,i-15,i+10,i+15,1,dlgFcol,GXinvert); XFlush(); Timer(15000L); } for (i=1; i<201; i+=8) { Frame(gridW,i-10,i-15,i+10,i+15,1,dlgFcol,GXinvert); XFlush(); Timer(15000L); } selCB=sc; for (w=20,h=30; w<200; w+=10,h+=15) { /* Zoom! */ int x,y; x=201-w/2; y=201-h/2; Frame(gridW,x,y,x+w,y+h,1,dlgFcol,GXcopy); XFlush(); Timer(25000L); } XMapWindow(diversW); gameover=0; grace=40; /* handle events until the next mouse event */ while (1) { Timer(30000L); if (XPending()) { XNextEvent(&event); if (event.type != ButtonPressed) HandleEvent(&event); else if (event.type == ButtonPressed && gameover) { gameover=0; NewGame(); RedrawDivers(); } else break; } if (gameover) continue; /* advance diversion by one frame */ XQueryMouse(diversW,&mx,&my,&subw); if (mx>DW) mx=DW; if (mx<0) mx=0; if (mx != px) { /* move player thing */ InvertPad(); px = mx; InvertPad(); } if (grace) { /* give the player a grace period before moving ball */ grace--; continue; } /* move non-player thing */ ox = bx; oy = by; bx += bdx; by += bdy; if ( (bx-bwidth2 < 0) || (bx+bwidth2 > DW) ) { /* hit left or right */ bdx = -bdx; bx += 2*bdx; } if (by-bwidth2 < 0) { /* hit back */ bdy = - bdy; by += 2*bdy; if (!small) { /* make paddle smaller */ small=1; InvertPad(); pwidth=18; pwidth2=pwidth/2; InvertPad(); } } else if (by+bwidth > DH) { /* hit bottom */ XFeep(0); NewBall(); if (ballnum==4) { /* game over */ gameover=1; continue; } else DrawBC(); } else if ( (by+bwidth2) >= py && (by-bwidth2) <= (py+8) && (bx+bwidth2) > (px-pwidth2) && (bx-bwidth2) < (px+pwidth2) ) { /* hit paddle */ bdy = -bdy; bdx = (bx-px)/2; if (small) bdx=2*bdx; /* more english on smaller paddle */ } else { /* check to see if it hit a brick */ int i,j,k; for (i=0; i<6; i++) { /* find row */ k=BY(i); if ( (k-BRHIGH2) < (by+bwidth2) && (k+BRHIGH2) > (by-bwidth2) ) break; } if (i<6) { /* it's on a row, now check individual bricks */ for (j=0; j<10; j++) { k=BX(j); if ( brick[i][j] && (k-BRWIDE2) < (bx+bwidth2) && (k+BRWIDE2) > (bx-bwidth2) ) break; } if (j<10) { /* hit brick[i][j] */ brick[i][j]=0; numbricks--; InvBrick(i,j); bdy = -bdy; score += bscore[i]; DrawScore(); if (!fast && i<2) { /* hit a rear brick. speedup */ fast=1; bdy = bdy * 2; } if (!numbricks) { /* completed the thing. Wowzo! */ XText(diversW, (DW-XStringWidth("Wowzo!",dlogfinfo,0,0))/2, 150,"Wowzo!",6,dlogfont,dlgFcol,dlgBcol); score+=200; DrawScore(); XFeep(0); XFeep(0); XFeep(0); XFlush(); Timer(2000000L); ballnum--; NewBall(); NewBricks(); RedrawDivers(); ox=bx; oy=by; } } } } InvertBall(ox,oy); InvertBall(bx,by); } XUnmapWindow(diversW); } /************************************************************************/ static InvertBall(x,y) int x,y; { XPixFill(diversW,x-bwidth2,y-bwidth2,bwidth,bwidth,1,0,GXinvert,invplanes); } /************************************************************************/ static InvBrick(i,j) int i,j; { XPixFill(diversW,BX(j)-BRWIDE2,BY(i)-BRHIGH2,BRWIDE,BRHIGH, 1,0,GXinvert,invplanes); } /************************************************************************/ static InvertPad() { XPixFill(diversW,px-pwidth2,py,pwidth,8,1,0,GXinvert,invplanes); } /************************************************************************/ static DrawBC() { char tmp[24]; sprintf(tmp,"Ball %d",ballnum); XText(diversW,20,DH+1,tmp,strlen(tmp),butfont,dlgBcol,dlgFcol); } /************************************************************************/ static DrawScore() { char tmp[24]; sprintf(tmp,"Score=%d",score); XText(diversW,DW-20-XStringWidth(tmp,butfinfo,0,0), DH+1,tmp,strlen(tmp),butfont,dlgBcol,dlgFcol); } /************************************************************************/ RedrawDivers() { int i,j; XClear(diversW); InvertPad(); InvertBall(bx,by); for (i=0; i<6; i++) for (j=0; j<10; j++) if (brick[i][j]) InvBrick(i,j); XPixSet(diversW,0,DH,DW,10,dlgFcol); DrawBC(); DrawScore(); } \Rogue\Monster\ else echo "will not over write ./xsplot/xsplotdiv.c" fi if `test ! -s ./xsplot/xsplotdlg.c` then echo "writing ./xsplot/xsplotdlg.c" cat > ./xsplot/xsplotdlg.c << '\Rogue\Monster\' /************************************************************************/ /* XSPLOTDLG.C - routines for manipulating dialog boxes */ /*----------------------------------------------------------------------*/ /* OpenDlog(w); - open a dialog window */ /* CloseDlog(); - close the current dialog window */ /* RedrawDlog(); - got an 'ExposeWindow'. Redraw the dlog */ /* DlogKey(st,len); - got a 'KeyPress' during dialog. Deal with it */ /* ClickDlog(x,y); - got a mouse click at x,y. Do something. */ /************************************************************************/ #include "xsplot.h" static int selanal; /**********************/ OpenDlog(w) Window w; { int i; dlogW = w; if (dlogW == LoadDlog) { /* 380x100 */ MakeButton(&dbutts[0],dlogW,30, 60,80,30,"Ok",dlogfinfo); /* MakeButton(&dbutts[1],dlogW,150,60,80,30,"No Parse",dlogfinfo); */ MakeButton(&dbutts[1],dlogW,270,60,80,30,"Cancel",dlogfinfo); for (i=0; i<2; i++) XSelectInput(dbutts[i].win,ExposeWindow); XMapSubwindows(dlogW); dlogstr[0]='\0'; dlscnt=0; } else if (dlogW == SwitchDlog) { XChangeWindow(dlogW,200,40+20*numanals); selanal = curanal; } else if (dlogW == CurvDlog) { /* 200x300 */ MakeButton(&curvbutts[0],dlogW,10, 50, 80,40,theAnal->labels[1],dlogfinfo); MakeButton(&curvbutts[1],dlogW,110,50, 80,40,theAnal->labels[2],dlogfinfo); MakeButton(&curvbutts[2],dlogW,10, 100,80,40,theAnal->labels[3],dlogfinfo); MakeButton(&curvbutts[3],dlogW,110,100,80,40,theAnal->labels[4],dlogfinfo); MakeButton(&curvbutts[4],dlogW,10, 150,80,40,theAnal->labels[5],dlogfinfo); MakeButton(&curvbutts[5],dlogW,110,150,80,40,theAnal->labels[6],dlogfinfo); MakeButton(&curvbutts[6],dlogW,10, 200,80,40,theAnal->labels[7],dlogfinfo); MakeButton(&curvbutts[7],dlogW,110,200,80,40,theAnal->labels[8],dlogfinfo); MakeButton(&dbutts[0],dlogW,10, 265,80,25,"Ok",dlogfinfo); MakeButton(&dbutts[1],dlogW,110,265,80,25,"Cancel",dlogfinfo); for (i=0; i<numy; i++) InvertBut(&curvbutts[ind[i]]); XMapWindow(dbutts[0].win); XSelectInput(dbutts[0].win,ExposeWindow); XMapWindow(dbutts[1].win); XSelectInput(dbutts[1].win,ExposeWindow); for (i=0; i<theAnal->numys; i++) { XMapWindow(curvbutts[i].win); XSelectInput(curvbutts[i].win,ExposeWindow); } } else if (dlogW == PlotDlog) { /* 380x70 */ MakeButton(&dbutts[0],dlogW,30, 30,80,30,"File", dlogfinfo); MakeButton(&dbutts[1],dlogW,150,30,80,30,"Plotter",dlogfinfo); MakeButton(&dbutts[2],dlogW,270,30,80,30,"Cancel", dlogfinfo); for (i=0; i<3; i++) XSelectInput(dbutts[i].win,ExposeWindow); XMapSubwindows(dlogW); } else if (dlogW == PlotNDlog) { /* 380x100 */ MakeButton(&dbutts[0],dlogW,30, 60,80,30,"Ok",dlogfinfo); MakeButton(&dbutts[1],dlogW,270,60,80,30,"Cancel",dlogfinfo); dbutts[2].win=0; for (i=0; i<2; i++) XSelectInput(dbutts[i].win,ExposeWindow); XMapSubwindows(dlogW); dlogstr[0]='\0'; dlscnt=0; } else if (dlogW == HelpDlog) {} XMapWindow(dlogW); } /**********************/ CloseDlog() { int i; if (dlogW == LoadDlog) { InvertBut(&butts[25]); XDestroySubwindows(dlogW); } else if (dlogW == SwitchDlog) { InvertBut(&butts[24]); } else if (dlogW == CurvDlog) { InvertBut(&butts[26]); XDestroySubwindows(dlogW); } else if (dlogW == PlotDlog) { InvertBut(&butts[38]); XDestroySubwindows(dlogW); } else if (dlogW == PlotNDlog) { InvertBut(&butts[38]); XDestroySubwindows(dlogW); } else if (dlogW == HelpDlog) { InvertBut(&butts[39]); } XUnmapWindow(dlogW); dlogW = 0; } /***********************/ RedrawDlog() { int i; if (dlogW == LoadDlog) { /* 380x100 */ XText(dlogW,10,10, "Load data from:",15, dlogfont,dlgFcol,dlgBcol); Frame(dlogW,10,30, 370,50, 2, dlgFcol,GXcopy); XText(dlogW,14,36,dlogstr,dlscnt,butfont,dlgFcol,dlgBcol); XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36, /* text cursor */ butfinfo->width, butfinfo->height, dlgFcol); } else if (dlogW == SwitchDlog) { /* 200x(40 + 20*numanal) */ XText(dlogW, 10,10, "Choose an analysis:",19, dlogfont,dlgFcol,dlgBcol); XLine(dlogW, 0,30, 200,30, 1,1,dlgFcol,GXcopy,AllPlanes); for (i=0; i<numanals; i++) XText(dlogW, 10,40+20*i+(20-dlogfinfo->height)/2, anals[i].title, strlen(anals[i].title), dlogfont, dlgFcol, dlgBcol); XPixFill(dlogW,0,40+20*curanal,200,20,ForeColor,0,GXinvert, dlgFcol ^ dlgBcol); } else if (dlogW == CurvDlog) { /* 200x300 */ XPixSet(dlogW,0,0,200,30,dlgBcol); XLine(dlogW,0,30,200,30,1,1,dlgFcol,GXcopy,AllPlanes); XText(dlogW,35,8, "Choose 1-4 curves",17,dlogfont,dlgFcol,dlgBcol); } else if (dlogW == HelpDlog) { /* 380x200 */ XText(dlogW, 40, 65, "Sorry, no on-line help available...",35, dlogfont,dlgFcol,dlgBcol); } else if (dlogW == PlotDlog) { /* 380x70 */ XText(dlogW,10,10, "Send plot data to:",18,dlogfont,dlgFcol,dlgBcol); } else if (dlogW == PlotNDlog) { /* 380x100 */ XText(dlogW,10,10, "Write plot data to:",19, dlogfont,dlgFcol,dlgBcol); Frame(dlogW,10,30, 370,50, 2, dlgFcol, GXcopy); XText(dlogW,14,36,dlogstr,dlscnt,butfont,dlgFcol,dlgBcol); XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36, /* text cursor */ butfinfo->width, butfinfo->height, dlgFcol); } } /***********************/ DlogKey(st,cnt) char *st; int cnt; { int i; if (dlogW == LoadDlog || dlogW == PlotNDlog) { for (i=0; i<cnt; i++) { if (st[i]=='\010' || st[i]=='\177') { /* backspace/del */ XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36, butfinfo->width, butfinfo->height, dlgBcol); if (dlscnt) dlscnt--; XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36, butfinfo->width, butfinfo->height, dlgFcol); } else if (st[i]=='\0') {} /* toss nulls away */ else if (st[i]=='\n' || st[i]=='\r') { /* return. choose default */ if (dlscnt==0) /* didn't enter a name. Cancel */ ClickDlog(dbutts[1].x+1, dbutts[1].y+1); else /* choose 'Ok' */ ClickDlog(dbutts[0].x+1, dbutts[0].y+1); } else { /* normal character */ dlogstr[dlscnt]=st[i]; XText(dlogW,14+dlscnt*butfinfo->width,36,&st[i],1, butfont,dlgFcol,dlgBcol); if (dlscnt<MAXDSTR) dlscnt++; XPixSet(dlogW, 14+dlscnt*butfinfo->width, 36, butfinfo->width, butfinfo->height, dlgFcol); } } } } /***********************/ ClickDlog(x,y) short x,y; { int i; char tmpfname[64]; dlogstr[dlscnt]='\0'; if (dlogW == LoadDlog) { for (i=0; i<2; i++) { if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) && y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break; } if (i<2) { InvertBut(&dbutts[i]); XFlush(); Timer(200000L); } else return; if (i==0) { NOPARSE=0; strcpy(tmpfname,basfname); strcpy(basfname,dlogstr); if (OpenSpice()) { /* couldn't load it. or something */ NOPARSE=1; if (strcmp(FixName(tmpfname),FixName(basfname))==0) { /* the very odd case that the previous SPICE and the asked-for SPICE have the same filename, but the asked-for SPICE was unable to be loaded. In this case, it's possible that the previous SPICE's tmp files have been overwritten. Better regenerate them, to be on the safe side... */ NOPARSE=0; } strcpy(basfname,tmpfname); OpenSpice(); LoadAnal(curanal); } else { LoadNewAnal(0); ChangedAnal(); XFlush(); RedrawSettings(); } } CloseDlog(); } else if (dlogW == SwitchDlog) { int tmpanal; tmpanal = (y/20)-2; if (tmpanal<0 || tmpanal>numanals) return; else if (tmpanal==selanal) { if (selanal==curanal) { CloseDlog(); return; } else { LoadNewAnal(selanal); CloseDlog(); ChangedAnal(); XFlush(); RedrawSettings(); } } else { XPixFill(dlogW,0,40+20*selanal,200,20,ForeColor,0,GXinvert, dlgFcol ^ dlgBcol); selanal=tmpanal; XPixFill(dlogW,0,40+20*selanal,200,20,ForeColor,0,GXinvert, dlgFcol ^ dlgBcol); } } else if (dlogW == CurvDlog) { int j,numsel,tmpind[4]; for (i=0; i<2; i++) { if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) && y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break; } if (i<2) { InvertBut(&dbutts[i]); XFlush(); Timer(200000L); } if (i==0) { /* Ok */ for (j=0,numsel=0; j<theAnal->numys; j++) if (curvbutts[j].invert) { if (numsel<4) tmpind[numsel]=j; numsel++; } if (numsel==0) { ErrBox("Choose at least one curve.",1); InvertBut(&dbutts[0]); } else if (numsel>4) { ErrBox("Choose no more than four curves.",1); InvertBut(&dbutts[0]); } else { /* selected curves are okay, load 'em */ for (j=0; j<numsel; j++) ind[j]=tmpind[j]; numy=numsel; LoadAnal(curanal); ChangedCurves(); CloseDlog(); /* note that closing dlog will redraw ALL data */ XFlush(); RedrawSettings(); } } else if (i==1) { /* Cancel */ CloseDlog(); } else { for (i=0; i<theAnal->numys; i++) { if (x>=curvbutts[i].x && x<=(curvbutts[i].x+curvbutts[i].w) && y>=curvbutts[i].y && y<=(curvbutts[i].y+curvbutts[i].h)) break; } if (i<theAnal->numys) InvertBut(&curvbutts[i]); } } else if (dlogW == PlotDlog) { for (i=0; i<3; i++) { if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) && y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break; } if (i<3) { InvertBut(&dbutts[i]); XFlush(); Timer(200000L); } else return; if (i==0) { /* File */ XMapWindow(PlotNDlog); CloseDlog(); InvertBut(&butts[38]); OpenDlog(PlotNDlog); } else if (i==1) { /* Plotter */ Splotter(); CloseDlog(); } else CloseDlog(); /* Cancel */ } else if (dlogW == PlotNDlog) { for (i=0; i<2; i++) { if (x>=dbutts[i].x && x<=(dbutts[i].x+dbutts[i].w) && y>=dbutts[i].y && y<=(dbutts[i].y+dbutts[i].h)) break; } if (i<2) { InvertBut(&dbutts[i]); XFlush(); Timer(200000L); } else return; if (i==0) { /* Ok */ if (!PlotFile(dlogstr)) ErrBox("Plot file written.",-1); } CloseDlog(); } else CloseDlog(); } \Rogue\Monster\ else echo "will not over write ./xsplot/xsplotdlg.c" fi if `test ! -s ./xsplot/xsplotgr.c` then echo "writing ./xsplot/xsplotgr.c" cat > ./xsplot/xsplotgr.c << '\Rogue\Monster\' /************************************************************************/ /* XSPLOTGR.C */ /*----------------------------------------------------------------------*/ /* Library of routines to handle data plotting, Big Picture, etc. */ /*----------------------------------------------------------------------*/ /* void DrawGwin (); */ /* void PlotData (); */ /* void ClearArrs (); */ /* void DrawGrid (); */ /* void BigPicture(); */ /* float CalcX(); */ /* float CalcY(); */ /* void BestFit(); */ /* int CalcSRect(x,y,x1,y1); */ /* void DigitalPresets(); /************************************************************************/ #include "xsplot.h" #define SPLOTTER "/usr/local/splotter" #define XUNIT 40 #define YUNIT 40 #define LOG2 0.69314718055994530941 #define NEGLOG -19.0 /* value returned when attempting log(-n) */ #define BPBottomFP 396.0 /* Big Picture size/position info */ #define BPHighFP 390.0 /* the Big Picture is a 390x390 rect centered */ #define BPLeftFP 6.0 /* in the 400x400 grid window */ #define BPWideFP 390.0 #define BPLeft 6 #define BPBottom 396 static int oldxscal = -1, oldyscal = -1; static int BPonscrn = 0; #define log10a(x) ((x<0.0) ? NEGLOG : log10(x)) #define log2a(x) ((x<0.0) ? NEGLOG : log(x)/LOG2) #define inrange(y) (y>=GTop && y<=GBottom) static float xmin,xmax,ymin,ymax; /* min/max values of DATA, unscaled */ static float sxmin,symin,sxmax,symax; /* min/max values of screen grid */ /* note: sx/sy vals are ALWAYS linear */ static float dx,dy; /* xmax-xmin, ymax-ymin */ static float sdx,sdy; /* sxmax-sxmin, symax-symin */ /************************************************************************/ DrawGwin() /* redraws whatever was in the grid window */ { if (BPonscrn) BigPicture(); else PlotData(); } /************************************************************************/ static float Coord2S(coord,scale) float coord; int scale; { switch (scale) { case LINEAR: return(coord); case LOG10: return(log10a(coord)); default: return(log2a(coord)); } } /************************************************************************/ static int xconv(x) float x; { /* given an x value (from xlist.dat[]), convert it to an integer (+-4K) suitable for plotting */ float xtmp; static float divsize[3]={400.0,133.333333,40.0}; /* size of a division on one, three, and ten division grid, respectively */ switch (xscal) { case LINEAR: xtmp = GLRmidFP+((x-offsets[0].val)/ranges[0].val)*XUNIT; break; case LOG10: x = Coord2S(x,xscal); xtmp = GLeftFP + (x-L10Offset)*divsize[L10Range]; break; case OCTAVE: x = Coord2S(x,xscal); xtmp = GLeftFP + (x-OctOffset)*divsize[OctRange]; break; } if (xtmp<-4000.0) xtmp = -4000.0; else if (xtmp> 4000.0) xtmp = 4000.0; return( (int) xtmp); } /************************************************************************/ static int yconv(i,y) int i; float y; { /* given a y value from ylist[i].dat[], convert it to an integer (+-4K) suitable for plotting */ float ytmp; y = Coord2S(y,yscal); ytmp = GTBmidFP - ((y-offsets[i+1].val) / ranges[i+1].val) * YUNIT; if (ytmp> 4000.0) ytmp = 4000.0; if (ytmp<-4000.0) ytmp = -4000.0; return( (int) ytmp); } /************************************************************************/ PlotData() { /* draws the data in the gridW using the current settings */ int x,y,i,j,numplot; Vertex *vp; ClearArrs(); BPonscrn = Vis159 = 0; DrawGrid(); /* clear and redraw the grid */ if (numpts<2) return; /* no points (per se) to draw */ for (i=0; i<numy; i++) { /* draw each curve */ numplot=0; for (j=0; j<numpts; j++) { x = xconv(xlist.dat[j]); y = yconv(i,ylist[i].dat[j]); if (x<GLeft) LeftArr=1; /* set arrows according */ if (x>GRight) RightArr=1; if (y<GTop) UpArr[i]=1; if (y>GBottom) DownArr[i]=1; /* keep track of the number of points plotted */ if (x>=GLeft && x<=GRight && y>=GTop && y<=GBottom) numplot++; SetVertex(curve+j,x,y,0); } if (mono) XDrawDashed(gridW,curve,numpts,1,1,ForeColor,linepats[i],GXcopy,AllPlanes); else XDraw(gridW,curve,numpts,1,1,trcol[i],GXcopy,AllPlanes); /* if 30 or less points plotted, plot the actual data points, too. */ if (numplot<31) for (j=0,vp=curve; j<numpts; j++,vp++) { x = vp->x; y = vp->y; if (x>=GLeft && x<=GRight && y>=GTop && y<=GBottom) XPixFill(gridW,x-1,y-1,3,3,trcol[i],0,GXcopy,AllPlanes); } } DrawArrs(); } /************************************************************************/ ClearArrs() { int i; LeftArr = RightArr = 0; for (i=0; i<4; i++) UpArr[i] = DownArr[i] = 0; } /************************************************************************/ static Calcminmax() /* calculates xmin,ymin,xmax,ymax,dx,dy */ { int i,j; /* find xmin, xmax, ymin, ymax */ xmin = xmax = xlist.dat[0]; ymin = ymax = ylist[0].dat[0]; for (i=0; i<numpts; i++) { if (xlist.dat[i]<xmin) xmin=xlist.dat[i]; if (xlist.dat[i]>xmax) xmax=xlist.dat[i]; for (j=0; j<numy; j++) { if (ylist[j].dat[i]<ymin) ymin=ylist[j].dat[i]; if (ylist[j].dat[i]>ymax) ymax=ylist[j].dat[i]; } } dx=xmax-xmin; dy=ymax-ymin; } /************************************************************************/ static CalcSdat() { /* calculate sxmin, sxmax, symin, symax, sdx, sdy */ sxmin=Coord2S(xmin,xscal); sxmax=Coord2S(xmax,xscal); symin=Coord2S(ymin,yscal); symax=Coord2S(ymax,yscal); sdx=sxmax-sxmin; sdy=symax-symin; } /************************************************************************/ static int BPxconv(x) float x; { /* converts a data x-value to it's bigpicture x-value */ float xtmp; x=Coord2S(x,xscal); xtmp = BPLeftFP + ((x-sxmin) * BPWideFP) / sdx; return( (int) xtmp); } /************************************************************************/ static int BPyconv(y) float y; { /* converts a data y-value to it's bigpicture y-value */ float ytmp; Coord2S(y,yscal); ytmp=BPBottomFP - ((y-symin) * BPHighFP) / sdy; return( (int) ytmp); } /************************************************************************/ BigPicture() { /* erases grid, redraws the Big Picture */ int x,y,i,j; char vals[100],vals1[16],vals2[16],vals3[16],vals4[16]; BPonscrn=1; Vis159=0; XClear(gridW); Calcminmax(); CalcSdat(); ClearArrs(); DrawArrs(); if (numpts<2) return; /* no points (per se) to draw */ for (i=0; i<numy; i++) { /* draw each curve */ for (j=0; j<numpts; j++) { x = BPxconv(xlist.dat[j]); y = BPyconv(ylist[i].dat[j]); SetVertex(curve+j,x,y,0); } if (mono) XDrawDashed(gridW,curve,numpts,1,1,ForeColor,linepats[i],GXcopy,AllPlanes); else XDraw(gridW,curve,numpts,1,1,trcol[i],GXcopy,AllPlanes); } for (i=0; i<numy; i++) DrawRBox(i); FpToEng(vals1,xmin); FpToEng(vals2,xmax); FpToEng(vals3,ymin); FpToEng(vals4,ymax); sprintf(vals,"Xmin:%-11.11s Xmax:%-11.11s Ymin:%-11.11s Ymax:%-11.11s",vals1,vals2,vals3,vals4); ErrBox(vals,-1); } /************************************************************************/ static int Rxconv(x) float x; { /* converts a data value to a BigPicture value, clipping at edge */ /* used by DrawRBox() */ x = BPLeftFP + ((x-sxmin) * BPWideFP) / sdx; if (x>GRightFP) return(GRight); else if (x<GLeftFP) return(GLeft); else return((int) x); } /************************************************************************/ static int Ryconv(y) float y; { /* converts a data value to a BigPicture value, clipping at edge */ /* used by DrawRBox() */ y = BPBottomFP - ((y-symin) * BPHighFP) / sdy; if (y>GBottomFP) return(GBottom); else if (y<GTopFP) return(GTop); else return((int) y); } /************************************************************************/ DrawRBox(rnum) int rnum; { /* draws a box on the BP, showing the part of a curve that will be visible on the grid */ int x1,y1,x2,y2; static int NumDiv[3]={1,3,10}; if (xscal==LINEAR) { x1=Rxconv(offsets[0].val - 5*ranges[0].val); x2=Rxconv(offsets[0].val + 5*ranges[0].val); } else if (xscal==LOG10) { x1=Rxconv((float) L10Offset); x2=Rxconv((float) (L10Offset + NumDiv[L10Range]) ); } else /* xscal==OCTAVE */ { x1=Rxconv((float) OctOffset); x2=Rxconv((float) (OctOffset + NumDiv[OctRange]) ); } y1=Ryconv(offsets[rnum+1].val + 5*ranges[rnum+1].val); y2=Ryconv(offsets[rnum+1].val - 5*ranges[rnum+1].val); MakeRect(x1,y1,x2,y2); XDrawDashed(gridW,curve,5,1,1,trcol[rnum],RBoxPat[rnum],GXcopy,AllPlanes); /* XDraw(gridW,curve,5,1,1,ForeColor,GXcopy,AllPlanes); */ } /************************************************************************/ DrawGrid() { int i,gtype,x,y; static int numlines[3]={10,28,51}; static int repeat [3]={9,9,5}; static int xval[3][51]={{ 0,120,191,241,280,311,338,361,382,400}, { 0, 40, 64, 80, 93,104,113,120,127, 133,173,197,214,227,237,246,254,261, 267,307,330,347,360,370,379,387,394,400}, { 0, 19, 28, 34, 38, 40, 59, 68, 74, 78, 80, 99,108,114,118, 120,139,148,154,158, 160,179,188,194,198, 200,219,228,234,238, 240,259,268,274,278, 280,299,308,314,318, 320,339,348,354,358, 360,379,388,394,398,400}}; XClear(gridW); /* draw vertical lines */ if (xscal==LINEAR) { for (i=0,x=GLeft; i<11; i++,x+=40) { if (i==5) XLine(gridW,x,GTop,x,GBottom,1,1,gridFcol,GXcopy,AllPlanes); else DashLine(gridW,x,GTop,x,GBottom+1,gridFcol,GridPat2); } } else { if (xscal==LOG10) gtype=L10Range; if (xscal==OCTAVE) gtype=OctRange; for (i=0; i<numlines[gtype]; i++) { x = xval[gtype][i]+GLeft; if (i%repeat[gtype]) DashLine(gridW,x,GTop,x,GBottom+1,gridFcol,GridPat4); else XLine(gridW,x,GTop,x,GBottom,1,1,gridFcol,GXcopy,AllPlanes); } } /* draw horizontal lines */ for (i=0,y=GTop; i<11; i++,y+=40) { if (i==5) XLine(gridW,GLeft,y,GRight,y,1,1,gridFcol,GXcopy,AllPlanes); else DashLine(gridW,GLeft,y,GRight,y,gridFcol,GridPat2); } /* draw tick marks */ if (xscal==LINEAR) { for (i=1,x=GLeft+8; i<50; i++,x+=8) if (i%5) XLine(gridW,x,GTBmid-2,x,GTBmid+2,1,1,gridFcol,GXcopy,AllPlanes); for (i=1,y=GTop+8; i<50; i++,y+=8) if (i%5) XLine(gridW,GLRmid-2,y,GLRmid+2,y,1,1,gridFcol,GXcopy,AllPlanes); } } /********************/ static float BPx2fp(x) int x; { /* given a grid coordinate on the big picture, returns the data value associated with it. Used for zooming on the BP */ if (xscal==LINEAR) return ( ((x-BPLeft)/BPWideFP) * dx + xmin); else if (xscal==LOG10) return (pow(10.0,( (x-BPLeft)/BPWideFP) * sdx + sxmin) ); else /* (xscal==OCTAVE) */ return (pow(2.0, ( (x-BPLeft)/BPWideFP) * sdx + sxmin) ); }; /********************/ static float BPy2fp(y) int y; { /* see BPx2fp */ return ( ((BPBottom-y)/BPHighFP) * dy + ymin); } /***************/ float CalcX(x) int x; { /* calculates the value (in data coordinates) of a given x (grid) value */ static float DivSize[3]={400.0,133.333333,40.0}; if (BPonscrn) return(BPx2fp(x)); else if (xscal==LINEAR) return(((float)(x-GLRmid)/40.0) * ranges[0].val + offsets[0].val); else if (xscal==LOG10) return(pow(10.0,((x-GLeft)/DivSize[L10Range]) + L10Offset)); else /* (xscal==OCTAVE) */ return(pow(2.0, ((x-GLeft)/DivSize[OctRange] + OctOffset))); } /***************/ float CalcY(y,trace) int y,trace; { /* calculates the value (in data coordinates) of a given y (grid) value */ if (BPonscrn) return(BPy2fp(y)); else return( ((GTBmid-y)/40.0) * ranges[trace+1].val + offsets[trace+1].val); } /******************/ BestFit() { /* fills in the range/offset values with the 'best' values */ double zx1,zy1,zx2,zy2,zdx,zdy,zxm,zym; int i,mul,exp; Calcminmax(); CalcSdat(); zx1 = xmin; zx2 = xmax; zdx = zx2 - zx1; zxm = zx1 + zdx/2.0; zy1 = ymin; zy2 = ymax; zdy = zy2 - zy1; zym = zy1 + zdy/2.0; CalcXRange(zx1,zx2,zdx,zxm); CalcNearRange(zdy,&mul,&exp,&zym); for (i=0; i<numy; i++) { ranges[i+1].multiplier=mul; ranges[i+1].power=exp; offsets[i+1].val=zym; } } /******************/ int CalcSRect(x1,y1,x2,y2) short x1,y1,x2,y2; { short i,tmp; double zx1,zy1[4],zx2,zy2[4],zdx,zdy[4],zxm,zym[4]; int mul,powr; if (x1==x2 && y1==y2) { BestFit(); return(1); } if (x1==x2 || y1==y2) return(0); /* empty rectangle */ /* get x1,y1 to be bot left, and x2,y2 to be top right */ if (x2<x1) swap(x1,x2,tmp); if (y1<y2) swap(y1,y2,tmp); for (i=0; i<8; i++) { InvertSBox(x1,y1,x2,y2); XFlush(); Timer(100000L); } zx1 = CalcX(x1); zx2 = CalcX(x2); zdx = zx2-zx1; zxm = zx1 + zdx/2.0; CalcXRange(zx1,zx2,zdx,zxm); if (BPonscrn) { /* zoom onto big picture */ double zy1,zy2,zdy,zym; zy1 = CalcY(y1); zy2 = CalcY(y2); zdy = zy2-zy1; zym = zy1 + zdy/2.0; CalcNearRange(zdy,&mul,&powr,&zym); for (i=0; i<numy; i++) { ranges[i+1].multiplier=mul; ranges[i+1].power=powr; offsets[i+1].val=zym; } } else { /* zooming on grid */ /* calculate zoomed-to y values */ for (i=0; i<numy; i++) { zy1[i] = CalcY(y1,i); zy2[i] = CalcY(y2,i); zdy[i] = zy2[i] - zy1[i]; zym[i] = zy1[i] + zdy[i]/2.0; CalcNearRange(zdy[i],&ranges[i+1].multiplier,&ranges[i+1].power,&zym[i]); offsets[i+1].val=zym[i]; } } return(1); } /****************/ static CalcXRange(x1,x2,dx,xm) double x1,x2,dx,xm; { /* given min,max,dx,and midpt values, sets the x controls to whatever'd 'best' (there's that word again) display the range */ double mid; mid=xm; /* printf("CalcXRange: x1=%e x2=%e dx=%e xm=%e\n",x1,x2,dx,xm); */ if (xscal==LINEAR) { CalcNearRange(dx,&ranges[0].multiplier,&ranges[0].power,&mid); offsets[0].val=mid; } else if (xscal==LOG10) { double tmp; L10Offset=(int) floor(log10(x1)); if (L10Offset<-20) L10Offset = -20; if (L10Offset> 20) L10Offset = 20; tmp = x2/x1; if (tmp>1000.0) L10Range=2; else if (tmp> 10.0) L10Range=1; else L10Range=0; } else /* (xscal==OCTAVE) */ { double tmp; OctOffset=(int) floor(log(x1)/log(2.0)); if (OctOffset<-20) OctOffset = -20; if (OctOffset> 20) OctOffset = 20; tmp = x2/x1; if (tmp>8.0) OctRange=2; else if (tmp>2.0) OctRange=1; else OctRange=0; } } /****************/ static CalcNearRange(d,mul,exp,mid) double d; int *mul,*exp; double *mid; { /* given a delta, and a midpoint, returns 'best fit' mul,exp, and mid values. Only works on linear settings */ /* takes a desired range 'd', and converts it to a valid range setting */ /* rounding rules: 1<x<=2.0 -> x=2.0 2<x<=5.0 -> x=5.0 5<x -> x=10.0 (where x=first digit) */ /* also takes the center of the range (offset) and rounds it to the next lower half-division (ie: if the resultant range is 5V per division, the offset will be rounded to some multiple of 2.5V. In theory, at least */ double mant,newmant,rpdiv,rpdiv2,z,md; int powr,m,e,e1; powr = (int) floor(log10(d)); /* powr(125.0) = 2 */ mant = d/pow(10.0,(double) powr); /* mant(125.0) = 1.25 */ /* mant * 10^powr = d : 1 <= mant < 10 */ /* round up range */ if (mant>5.0) { newmant=1.0; m=0; powr++;} else if (mant>2.0) { newmant=5.0; m=2; } else if (mant>1.0) { newmant=2.0; m=1; } else { newmant=1.0; m=0; } powr--; /* divide by 10 to get range/div */ e = (powr/3) + 4; /* convert powr -> exp */ if (e>8) e=8; /* truncate at ends of valid range */ if (e<0) e=0; e1=abs(powr)%3; if (powr<0 && e1!=0) { e--; e1=3-e1; } if (e>=0) m=m+e1*3; /* calculate mul */ else { e=0; m=0; } *mul=m; *exp=e; /* calculate the nice, rounded-off midpt */ rpdiv = newmant * pow(10.0,(double) powr); /* range per div */ rpdiv2 = rpdiv/2; /* range per half-div */ md = *mid; /* vaguely-evil kludge. Basically, if mid/rpdiv2 is something like 5.99999, this hopefully pushes it above 6.0, so that floor returns 6 */ *mid = *mid * 1.00001; z = floor(*mid/rpdiv2); /* integer # of half-divs in m */ *mid = z * rpdiv2; /* rounded down version of m */ /* printf("rpdiv:=%e rpdiv2=%e\n",rpdiv,rpdiv2); printf("mid=%e mid/rpdiv=%e z=%e z*rpdiv2=%e\n\n",md,md/rpdiv2,z,*mid); */ } /************************************************************************/ /* Routines to handle data plotting. (Hard Copy! Wowzo!) */ /*----------------------------------------------------------------------*/ /* PlotFile(fnam); - writes data points to the named SPIF file. */ /* Splotter(); - writes a tmp SPIF file, and execs splotter */ /************************************************************************/ /* * The SPIF Format: * (all numbers are in ascii format (printf)) * * Field 1: The name of the spice file * 2: The name of the analysis * 3: The Grid Type * (0 = Linear, 10 divs per axis, with axes at center) * (1 = Log10, 1 div) * (2 = Log10, 3 divs) * (3 = Log10, 10 divs) * (4 = Log 2, 1 div) * (5 = Log 2, 3 divs) * (6 = Log 2, 10 divs) * (consult Splot to see what grids should look like) * 4: The number of traces in the plot (1-4) * 5: The names of the traces (2-5 words, each up to 8 chars long) * 6: The x-axis offset/range information * (if gridtype=0, will be in the form * x.xxxxexx x.xxxxexx * where the first number is the offset at the center line, * and the second is the amount of change per division) * * (if gridtype=1-3, will be in the form * 10^x y * where 'x' will be an integer in range +/- 19. * this refers to the value at the left edge of the plot. * 'y' will be an integer, either 1,3, or 10. This is * actually redundant, but what the hell.) * * (if gridtype=4-6, will be in the form * 2^x y * where 'x' will be an integer in range +/- 19. * this refers to the value at the left edge of the plot. * 'y' will be an integer, either 1,3, or 10. This is * actually redundant, but what the hell.) * * 7: The y-axis offset/range information * This will be 1-4 lines, each containing a pair of * numbers of the format used for the x-axis when gridtype=0 * * 8: The actual data * This will be an indeterminant number of lines, each with * an x coordinate and 1-4 y coordinates separated by * spaces. The coordinates will be in the range +/- 32K. * The plotting program should clip these coordinates to the * range 0-400 on both axes. 0,0 refers to the bottom left * corner of the grid. * The end of the data will be signalled by the end of the * SPIF file, so needless to say, this field HAS to be the * last field in the SPIF file, should anyone get the urge * to add things to the SPIF format. * */ /****************/ int PlotFile(name) char *name; /****************/ { /* writes the named SPIF file */ int x,y,i,j,gridtype; FILE *spiffile; char tmp[128]; if (expfname(name)) { sprintf(tmp,"Unable to create file '%s'",name); ErrBox(tmp,3); return 1; } spiffile = fopen(name,"w"); if (spiffile == 0) { sprintf(tmp,"Unable to create file '%s'",name); ErrBox(tmp,3); return 1; } /* write header information */ fprintf(spiffile,"%s\n",FixName(basfname)); fprintf(spiffile,"%s\n",theAnal->title); if (xscal==LINEAR) gridtype=0; else if (xscal==LOG10) gridtype=1+L10Range; else /* (xscal==OCTAVE)*/ gridtype=4+OctRange; fprintf(spiffile,"%d\n",gridtype); fprintf(spiffile,"%d\n",numy); fprintf(spiffile,"%s",xlist.label); for (i=0; i<numy; i++) fprintf(spiffile," %s",ylist[i].label); fprintf(spiffile,"\n"); if (xscal==LINEAR) fprintf(spiffile,"%e %e\n",offsets[0].val,ranges[0].val); else if (xscal==LOG10) fprintf(spiffile,"10^%d %d\n",L10Offset,L10Range); else /* OCTAVE */ fprintf(spiffile,"2^%d %d\n",OctOffset,OctRange); for (i=0; i<numy; i++) fprintf(spiffile,"%e %e\n",offsets[i+1].val,ranges[i+1].val); /* write data points to file */ for (i=0; i<numpts; i++) { x = xconv(xlist.dat[i]); fprintf(spiffile,"%d",x); for (j=0; j<numy; j++) { y = yconv(j,ylist[j].dat[i]); y = 400 - y; /* reverse direction so that y=0=bottom */ if (y>32000) y=32000; fprintf(spiffile," %d",y); } fprintf(spiffile,"\n"); } fclose(spiffile); return 0; } /***************/ int Splotter() /***************/ { /* generates a unique file name (/tmp/spifXXXXXX), writes the SPIF file using that name, and then runs SPLOTTER to plot it (and delete it) */ char name[32]; int pid; strcpy(name,"/tmp/spifXXXXXX"); mktemp(name); if (PlotFile(name)) return 1; pid = vfork(); if (pid==0) { /* we're in the child's context. fire up splotter */ char tmp[128]; sprintf(tmp,"Executing %s.",SPLOTTER); ErrBox(tmp,-1); if (execl(SPLOTTER,SPLOTTER,"-i",name,"-u",0) == -1) { sprintf(tmp,"Couldn't execute %s.",SPLOTTER); ErrBox(tmp,4); _exit(); /* exit the child process */ } } } /*************************************************************/ DigitalPresets() /*************************************************************/ { /* sets range/offsets to 'best' values for viewing several curves that range from 0.0 to 5.0. 'Stacks' them, or some such nonsense. */ int i,m,p; double zx1,zx2,zdx,zxm; /* do a best fit on the X-axis */ Calcminmax(); CalcSdat(); zx1 = xmin; zx2 = xmax; zdx = zx2 - zx1; zxm = zx1 + zdx/2.0; CalcXRange(zx1,zx2,zdx,zxm); /* set up the y-axis values */ switch (numy) { case 1: m=0; p=4; /* 1V per div */ offsets[1].val= 2.5; break; case 2: m=1; p=4; /* 2V per div */ offsets[1].val= -2.0; offsets[2].val= 6.0; break; case 3: m=1; p=4; /* 2V per div */ offsets[1].val= -4.0; offsets[2].val= 2.0; offsets[3].val= 8.0; break; case 4: m=2; p=4; /* 5V per div */ offsets[1].val= -15.0; offsets[2].val= -5.0; offsets[3].val= 5.0; offsets[4].val= 15.0; break; } for (i=1; i<=numy; i++) { ranges[i].multiplier=m; ranges[i].power=p; } xscal=LINEAR; } \Rogue\Monster\ else echo "will not over write ./xsplot/xsplotgr.c" fi echo "Finished archive 2 of ompXB di
bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)
xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE output. It will drive an HP-GL plotter for hardcopy. It can be used to look at non-SPICE data, also. Why, it could be the Neatest Thing Ever. Probably not, though. Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and 4.3, and on random Vaxen under Ultrix 1.2 and 2.0) --John Bradley - University of Pennsylvania - bradley@cis.upenn.edu Part 3 of 4 ----------------------cut here------------------- #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -d ./xsplot` then mkdir ./xsplot echo "mkdir ./xsplot" fi if `test ! -s ./xsplot/xsplot.c` then echo "writing ./xsplot/xsplot.c" cat > ./xsplot/xsplot.c << '\Rogue\Monster\' /* * xsplot.c - Spice Plotting program for the X Window system * * Author: John Bradley, University of Pennsylvania * (bradley@cis.upenn.edu) * * Concept: Filip Fuma, University of Pennsylvania * (fuma@cis.upenn.edu) * * Copyright Notice: Oh, let's see... The typical stuff, I suppose. * don't be removing our names and claiming you wrote it. Don't * sell this program, as if people'd actually pay money for it. * There are, of course, no warranties implied, under the "you should * be happy it does anything at all" school of thought. In short, * don't be a WEASEL. Other than that, feel free to redistribute the * source, and of course, send us lots of letters telling us how much * you like it, and what great guys we are for writing it. * * Copyright 1986,1987, University of Pennsylvania * */ #define MAIN #define PREFILE "~/.splotpre" #include "xsplot.h" #include <signal.h> #include <sys/time.h> #include <setjmp.h> #ifndef sigmask #define sigmask(m) (1 << ((m)-1)) #endif static int LastClicked = -1; static int EditButton = -1; static int MadeStuff = 0; /***********/ crash(disp,err) Display *disp; XErrorEvent *err; /***********/ { /* a routine that crashes and dumps core. Useful for tracking X errors*/ char *st, *tmp="foobar"; if (err->error_code == BadFont) return; st = NULL; fprintf(stderr,"Crashing...\n"); fprintf(stderr,"err=%s\n",XErrDescrip(err->error_code)); strcpy(st,tmp); } /*******************************************/ main(argc, argv) int argc; char *argv[]; /*******************************************/ { int i, status,dpcs; char *strind; char *fc, *bc; char *geom = NULL; char *display = NULL; int rvflag = 0; /* don't use reverse video as a default */ int invkey = -1; Color cdef; XEvent event; char *def; pid = getpid(); /*********************Defaults*********************/ fc = XGetDefault(argv[0], "Foreground"); bc = XGetDefault(argv[0], "Background"); /*********************Options*********************/ basfname[0]='\0'; for (i = 1; i < argc; i++) { if (argv[i][0] == '=') { geom = argv[i]; continue; } strind = index(argv[i], ':'); if(strind != NULL) { display = argv[i]; continue; } if (argv[i][0] != '-') { /* the file name */ strcpy(basfname,argv[i]); continue; } Syntax(argv[0]); } if (basfname[0] == '\0') Syntax(argv[0]); /* didn't get a file name */ /*****************************************************/ /* Open up the display. */ if (XOpenDisplay(display) == NULL) { fprintf(stderr, "%s: Can't open display '%s'\n", argv[0], XDisplayName(display)); exit(1); } /* load fonts */ if ((butfinfo = XOpenFont("6x10"))==NULL) FatalError("couldn't open '6x10' font\n"); butfont=butfinfo->id; if ((dlogfinfo = XOpenFont("8x13"))==NULL) FatalError("couldn't open '8x13' font\n"); dlogfont=dlogfinfo->id; /* Set up colors and pixmaps. */ /* Set normal default colors */ if (!rvflag) { ForeColor=BlackPixel; BackColor=WhitePixel; } else { ForeColor=WhitePixel; BackColor=BlackPixel; } dpcs=DisplayCells(); mono = 1; /* default is monochrome */ if (dpcs>2) { /* if it's a color display, however... */ int pixels[1],planes,b; Color defs[8]; status=XGetColorCells(1,1,3,&planes,pixels); if (planes != 7) { fprintf(stderr,"XGetColorCells: planes=%d!\n",planes); status=0; } if (status) { b=pixels[0]; for (i=0; i<8; i++) defs[i].pixel = b+i; /* set up default colors */ XParseColor("green", defs); /* first 4 cols are trace cols */ XParseColor("red", defs+1); XParseColor("slate blue",defs+2); XParseColor("yellow", defs+3); XParseColor("black", defs+4); XParseColor("white", defs+5); XParseColor("firebrick", defs+6); XParseColor("medium forest green", defs+7); XStoreColors(8,defs); /* do it */ /* set up color numbers */ gridFcol=b+5; gridBcol=b+4; /* NOTE: gridBcol MUST be b+4 */ panFcol =b+5; panBcol =b+4; butFcol =b+5; butBcol =b+6; mainFcol=b+5; mainBcol=b+2; dlgFcol =b+3; dlgBcol =b+7; errFcol =b+5; errBcol =b+4; for (i=0; i<4; i++) trcol[i]=b+i; mono=0; } } if (dpcs>2&&(fc !=NULL)&&XParseColor(fc ,&cdef)&&XGetHardwareColor(&cdef)) ForeColor=cdef.pixel; if (dpcs>2&&(bc !=NULL)&&XParseColor(bc ,&cdef)&&XGetHardwareColor(&cdef)) BackColor=cdef.pixel; if (mono) { gridFcol = panFcol = butFcol = mainFcol = dlgFcol = errFcol=ForeColor; gridBcol = panBcol = butBcol = mainBcol = dlgBcol = errBcol=BackColor; for (i=0; i<4; i++) trcol[i]=ForeColor; } /**************** parse/load spice file *****************/ InitVars(); OpenFiles(); /**************** Create/Open X Resources ***************/ CreateStuff(); CreateMainWindow(argv[0],geom); CreateSubwindows(); CreateButtons(); XSelectInput(mainW, ExposeWindow|ButtonReleased|ButtonPressed|KeyPressed); /* map all the windows, except for the command window, and the dlogs. Map the subwindows except for the ones in offsetW and measureW, as ChangedAnal does that (to avoid redraw). Note that this prevents me from simply doing XMapSubwindows on mainW */ XMapWindow (mainW); XMapWindow (titleW); XMapWindow (gridW); XMapWindow (presetW); XMapWindow (traceW); XMapWindow (scaleW); XMapWindow (measureW); XMapWindow (offsetW); XMapWindow (modifyW); XMapWindow (miscW); XMapWindow (errW); XMapSubwindows(presetW); XMapSubwindows(traceW); XMapSubwindows(scaleW); XMapSubwindows(commandW); XMapSubwindows(modifyW); XMapSubwindows(miscW); /* map x range/offset buttons, as these are NOT mapped in ChangedAnal */ XMapWindow(butts[2].win); XMapWindow(butts[3].win); XSetIconWindow(mainW,iconW); XDefineCursor (mainW,arrow); /********************************************/ ChangedAnal(); XErrorHandler(crash); MadeStuff=1; /* redirect ErrBox output to errW */ InitDivers(); /**************** Main loop *****************/ while (1) { XNextEvent(&event); HandleEvent(&event); } } /****************/ HandleEvent(event) XEvent *event; /****************/ { int i; Window wind; switch (event->type) { case ExposeWindow: { XExposeWindowEvent *exp_event = (XExposeWindowEvent *) event; wind = exp_event->window; /* figure out what redraw routine to call */ if (wind==mainW) DrawWindow(); else if (wind==iconW) RedrawIcon(); else if (wind==titleW) DrawTitleBar(); else if (wind==gridW) DrawGwin(); else if (wind==errW) RedrawErrBox(); else if (wind==dlogW) RedrawDlog(); else if (wind==diversW) RedrawDivers(); else if (wind==AboutDlog) RedrawAbout(); else if (wind==presetW) RedrawPanel(wind,PREW,"User Presets"); else if (wind==traceW) RedrawPanel(wind,TRAW,"Trace Location"); else if (wind==scaleW) RedrawPanel(wind,SCAW,"Grid Type"); else if (wind==measureW) RedrawPanel(wind,MSRW,"Measurement"); else if (wind==modifyW) RedrawPanel(wind,MODW,"Modify"); else if (wind==miscW) RedrawPanel(wind,MISW,"Misc."); else if (wind==commandW) RedrawPanel(wind,OFFW,"Alternate Commands"); else if (wind==offsetW) RedrawOffPan(); else { if (dlogW) { for (i=0; i<3; i++) if (dbutts[i].win==wind) {RedrawBut(dbutts+i); break;} if (dlogW == CurvDlog) { for (i=0; i<8; i++) if (curvbutts[i].win==wind) {RedrawBut(curvbutts+i); break;} } } for (i=0; i<MAXBUT; i++) if (butts[i].win==wind) { RedrawBut(butts+i); break; } for (i=0; i<4; i++) if (CButts[i].win==wind) { RedrawCB(i); break; } } } break; case ButtonPressed: { XButtonEvent *but_event = (XButtonEvent *) event; wind = but_event->window; /* if dlog window up, mouse events outside dlog are tossed away */ if (dlogW) { /* only left button clicks do anything */ if ((but_event->detail & 0xff) == LeftButton) { if (wind==dlogW) { ClickDlog(but_event->x,but_event->y); } } } else { /***************/ /* LEFT BUTTON */ /***************/ if ((but_event->detail & 0xff) == LeftButton) { if (wind == titleW) { InvTitleBar(); Credits(); } if (wind == gridW) { TrackMeasure(but_event->x,but_event->y); break; } for (i=0; i<MAXBUT; i++) /* see if it's a control button */ if (butts[i].win==wind) { InvertBut(butts+i); LastClicked = i; break; } if (i!=MAXBUT) break; /* found it already */ for (i=0; i<4; i++) { /* see if it's a color button */ if (CButts[i].win==wind) { if (i!=selCB) { int j=selCB; selCB=i; RedrawCB(j); RedrawCB(i); DrawArrs(); } break; } } } /***************/ /* MID. BUTTON */ /***************/ else if ((but_event->detail & 0xff) == MiddleButton) { if (wind == gridW) TrackSBox(but_event->x,but_event->y); else BigPicture(); /* BigPicture command */ } /****************/ /* RIGHT BUTTON */ /****************/ else if ((but_event->detail & 0xff) == RightButton) { if (wind == titleW) OpenDivers(); else if (wind == gridW) Track159Box(but_event->x,but_event->y); else { PlotData(); SetUndo(); } /* redraw command */ } } } break; case ButtonReleased: { XButtonEvent *but_event = (XButtonEvent *) event; if ((but_event->detail & 0xff) == LeftButton) Click(); } break; case KeyPressed: { XKeyEvent *key_event = (XKeyEvent *) event; char *st; int cnt; st = XLookupMapping(key_event,&cnt); if (dlogW) DlogKey(st,cnt); } break; default: printf("event type=%ld\n",event->type); FatalError("Unexpected X_Event"); } /* end of switch */ } /***********************************/ Syntax(call) char *call; { printf ("Usage: %s filename [display] [=geometry]\n",call); exit(0); } /***********************************/ FatalError (identifier) char *identifier; { fprintf(stderr, "xsplot: %s\n", identifier); exit(1); } /***********************************/ InitVars() { tbInvert=0; selCB=0; comUp=0; NOPARSE =0; dlogW = 0; ylock=0; L10Offset = L10Range = OctOffset = OctRange = 0; } /***********************************/ ChangedAnal() { /* loaded a different anal. redraw the "file: analysis" string, do a bestfit, redraw x control if necessary */ int tmp; DrawWindow(); /* choose xscal based on anal.type */ if (theAnal->type==AC) xscal=LOG10; else xscal=LINEAR; BestFit(); ChangedCurves(); } /***********************************/ ChangedCurves() { /* changed curves. since numy could now be different, map/unmap numy-dependent stuff, copy strings to buttons */ int i; /* map/unmap offset/range/color buttons */ for (i=0; i<4; i++) { if (i<numy) { XMapWindow(butts[i*2+4].win); XMapWindow(butts[i*2+5].win); XMapWindow(CButts[i].win); } else { XUnmapWindow(butts[i*2+4].win); XUnmapWindow(butts[i*2+5].win); XUnmapWindow(CButts[i].win); } } if (selCB>=numy) { /* map the selected CB to a valid CB (if nec.) */ i=selCB; selCB=0; RedrawCB(i); RedrawCB(0); } ChangedSettings(); SetUndo(); SetUndo(); /* clear the undo buffer */ } /***********************************/ ChangedSettings() { /* changed the range/offset settings through zooming, digital, presets, etc. Reset the button strings */ int i; /* set range/offset button strings */ for (i=0; i<=numy; i++) { R2Str(i); butts[3+i*2].st = ranges[i].str; O2Str(i); butts[2+i*2].st = offsets[i].str; } SetXButs(); } /***********************************/ RedrawSettings() { int i; Pixmap tmpPix; if (comUp) { /* Alt Commands window up. close it */ Com2Ctrl(); } else { /* redraw range/offset buttons */ tmpPix = XPixmapSave(offsetW,0,0,OFFW,OFFH); /* save the bits */ if (tmpPix) { ComZoom(offsetW); /* only do the effect if bits saved */ XClipDrawThrough(offsetW); XPixmapPut(offsetW,0,0,0,0,OFFW,OFFH,tmpPix,GXcopy,AllPlanes); XClipClipped(offsetW); XFreePixmap(tmpPix); } for (i=2; i<12; i++) RedrawBut(butts+i); } RedrawBut(&butts[0]); } /***********************************/ DrawWindow() { char str[256]; XClear(mainW); sprintf(str,"%s: %s",FixName(basfname),theAnal->title); XText(mainW,215-XStringWidth(str,butfinfo,0,0)/2,30, str,strlen(str),butfont,mainFcol,mainBcol); } static int errInv=0; /***********************************/ RedrawErrBox() { if (errInv) XText(errW,6,1,errstr,strlen(errstr),butfont,errBcol,errFcol); else XText(errW,6,1,errstr,strlen(errstr),butfont,errFcol,errBcol); } /***********************************/ ErrBox(str,delay) char *str; short delay; { /* positive delay does 'effect', waits 'delay' seconds */ /* 0 delay redraws ErrBox with different string */ /* negative delay does effect, but no delay */ int i,col; strcpy(errstr,str); if (errInv) col=errBcol; else col=errFcol; if (MadeStuff) { /* only draw stuff if window has been opened up */ int xm,ym,w; if (delay) { if (errInv) XChangeBackground(errW,errBpix); else XChangeBackground(errW,errFpix); errInv = !errInv; xm = (WIDTH-20) / 2; ym=6; w=WIDTH-20; for (i=0; i<7; i++) { /* size=(WIDTH-20)x13 */ XPixSet(errW,xm-(i*w/12),ym-i,i*w/6,i*2+1,col); XFlush(); Timer(50000L); } } else { XClear(errW); } RedrawErrBox(); XFlush(); if (delay>0) Timer((long) (delay * 1000000L)); /* wait 'delay' secs */ } else { /* windows not up, just printf */ fprintf(stderr,"%s",errstr); if (delay) fprintf(stderr,"\n"); else fprintf(stderr,"\r"); } } /***********************************/ Click() /* called when a pushbutton is released. handles inverting of buttons, and if it's a command button, calls the appropriate routine. */ { if (LastClicked == -1) return; /* not sure if this ever happens */ if (LastClicked<12) { /* clicked an edit button */ if (EditButton>=0) InvertBut(&butts[EditButton]); /* turn off prev but */ EditButton = LastClicked; LastClicked = -1; } else { /* clicked some command button */ switch (LastClicked) { case 12: /* Modification controls */ case 13: case 14: case 15: case 16: case 17: case 18: if (EditButton>=0) ModifyBut(EditButton,LastClicked); InvertBut(&butts[LastClicked]); break; case 19: /* Redraw button */ PlotData(); SetUndo(); InvertBut(&butts[LastClicked]); break; case 20: /* Undo button */ InvertBut(&butts[LastClicked]); GetUndo(); ChangedSettings(); PlotData(); RedrawSettings(); SetUndo(); break; case 21: /* Y-Lock button */ ylock = !ylock; break; case 22: /* Commands button */ if (comUp) { Com2Ctrl(); } else { ComZoom(offsetW); XMapWindow(commandW); XUnmapWindow(offsetW); comUp=1; } break; case 23: /* Big Picture button */ InvertBut(&butts[LastClicked]); BigPicture(); Com2Ctrl(); break; case 24: /* Switch Analysis */ OpenDlog(SwitchDlog); break; case 25: /* Load Data File */ OpenDlog(LoadDlog); break; case 26: /* Choose Curves */ OpenDlog(CurvDlog); break; case 27: /* Digital Presets */ InvertBut(&butts[LastClicked]); DigitalPresets(); ChangedSettings(); PlotData(); RedrawSettings(); SetUndo(); break; case 28: /* user preset #1 */ case 29: /* ' ' #2 */ case 30: /* ' ' #3 */ case 31: /* ' ' #4 */ case 32: /* ' ' #5 */ case 33: /* ' ' #6 */ case 34: /* ' ' #7 */ case 35: /* ' ' #8 */ InvertBut(&butts[LastClicked]); Preset(LastClicked-28); ChangedSettings(); PlotData(); RedrawSettings(); SetUndo(); break; case 36: /* Set user preset */ SetPreLoop(); break; case 38: /* Plot to 'where' */ OpenDlog(PlotDlog); break; case 39: /* Help */ OpenDlog(HelpDlog); break; case 37: /* Quit button */ InvertBut(&butts[LastClicked]); Quit(); break; } LastClicked = -1; } } /***********************/ SetPreLoop() /***********************/ { /* loop that's called when 'Set' button is pressed. handles events until the next mouse event if mouse event is a LeftClick in one of the preset butts (28-35) then call SetPreset else turn 'set' button off, handle mouse event, and leave */ int i,j; XEvent event; Window wind; while (1) { XNextEvent(&event); if (event.type != ButtonPressed) HandleEvent(&event); else { XButtonEvent *but_event = (XButtonEvent *) &event; wind = but_event->window; if ((but_event->detail & 0xff) != LeftButton) { InvertBut(&butts[36]); HandleEvent(&event); } else { /* well, it's a leftclick... */ for (i=28; i<37 && (wind!=butts[i].win); i++); if (i==36) { /* clicked the 'Set' button again */ InvertBut(&butts[36]); } else if (i==37) { /* wasn't a preset button */ InvertBut(&butts[36]); HandleEvent(&event); } else { /* WAS one of the preset buttons */ InvertBut(&butts[i]); XFlush(); for (j=0; j<7; j++) { /* flash the 'set' and '#' buts */ InvertBut(&butts[i]); InvertBut(&butts[36]); XFlush(); Timer(100000L); } SetPreset(i-28); } } break; /* break out of the infinite loop on ANY ButtonPress */ } } } /***********************/ ComZoom(win) Window win; { /* gratuitous zoom effect for changing between AltCommands and RangeOffset windows */ /* note: the '11' is so that only the lower part of the window gets zoomed. zooming doesn't overwrite the titlebar part of the window (which, coincidentally, is 11 pixels high) */ short i,x,y,w,h; XClipDrawThrough(win); for (i=1; i<=15; i++) { w = OFFW*i/15; h = (OFFH-11)*i/15; x = OFFW/2 - w/2; y = 11 + (OFFH-11)/2 - h/2; XTileFill(win,x+1,y+1,w,h,panBpix,0,GXcopy,AllPlanes); Frame(win,x,y,x+w,y+h,1,panFcol,GXcopy); XFlush(); Timer(30000L); } XClipClipped(win); } /******************/ Com2Ctrl() { /* closes commands window, brings up range window, in amusing fashion */ ComZoom(commandW); XMapWindow(offsetW); XUnmapWindow(commandW); comUp=0; if (butts[22].invert) InvertBut(&butts[22]); /* turn command button off */ } /******************/ TrackMeasure(x,y) int x,y; { /* tracks the measuring tool, and show measurments when done */ float zx,zy,zx1,zy1,zdx,zdy,CalcX(),CalcY(); char vals[100],vals1[16],vals2[16],vals3[16],vals4[16],vals5[16]; short x1,y1,state; int i,xn,yn; Window subw; Pixmap tmpPix; XDefineCursor(gridW,cursx); /* while dragging the tool, show a different cursor */ x1=x; y1=y; InvertCross(x,y,x1,y1); while ( XQueryMouseButtons(gridW,&xn,&yn,&subw,&state), state&LeftMask) { if (xn!=x1 || yn!=y1) { /* moved */ InvertCross(x,y,x1,y1); x1=xn; y1=yn; InvertCross(x,y,x1,y1); } } InvertCross(x,y,x1,y1); XUndefineCursor(gridW); /* if ended up outside the gridrect, don't do anything */ if (x1<GLeft || x1>GRight || y1<GTop || y1>GBottom) sprintf(vals,""); else { zx =CalcX(x); zx1=CalcX(x1); zdx=zx1-zx; zy = CalcY(y,selCB); zy1= CalcY(y1,selCB); zdy=zy1-zy; FpToEng(vals1,zx1); FpToEng(vals2,zy1); FpToEng(vals3,zdx); FpToEng(vals4,zdy); if (zdx!=0.0) FpToEng(vals5,zdy/zdx); else sprintf(vals5," infinity"); if (zdx==0.0 && zdy==0.0) sprintf(vals,"X:%-11.11s Y:%-11.11s",vals1,vals2); else sprintf(vals,"X:%-11.11s Y:%-11.11s dX:%-11.11s dY:%-11.11s dY/dX:%-11.11s",vals1,vals2,vals3,vals4,vals5); } ErrBox(vals,-1); } /******************/ InvertCross(x,y,x1,y1) int x,y,x1,y1; { /* draws an L-shaped thing from x,y to x1,y1. Only checks position of x1,y1, as x,y is known to be inside the grid. */ if (x1<GLeft || x1>GRight) return; if (y1<GTop || y1>GBottom) return; SetVertex(curve+0,x,y,0); SetVertex(curve+1,x,y1,0); SetVertex(curve+2,x1,y1,0); if (mono) XDraw(gridW,curve,3,1,1,ForeColor,GXinvert,1); else XDraw(gridW,curve,3,1,1,ForeColor,GXinvert,4+selCB); } /***********************/ Track159Box(x,y) short x,y; { /* tracks the 10-50-90% box */ short x1,y1,state; int i,xn,yn; Window subw; if (Vis159) Invert159Box(R159[0],R159[1],R159[2],R159[3]); XDefineCursor(gridW,cursx); /* while dragging the box, show a different cursor */ x1=x; y1=y; InvertBox(x,y,x1,y1); while ( XQueryMouseButtons(gridW,&xn,&yn,&subw,&state), state&RightMask) { if (xn!=x1 || yn!=y1) { /* moved */ InvertBox(x,y,x1,y1); x1=xn; y1=yn; InvertBox(x,y,x1,y1); } } XUndefineCursor(gridW); InvertBox(x,y,x1,y1); /* if ended up outside the gridrect */ if (x1<GLeft || x1>GRight || y1<GTop || y1>GBottom) Vis159=0; else { Vis159=1; R159[0]=x; R159[1]=y; R159[2]=x1; R159[3]=y1; Invert159Box(x,y,x1,y1); } } InvertBox(x,y,x1,y1) short x,y,x1,y1; { /* inverts a 1-pix-thick rectangle. Note that it only checks the range of x1,y1, as x,y is known to be inside the grid */ if (x1<GLeft || x1>GRight) return; if (y1<GTop || y1>GBottom) return; if (x==x1 || y==y1) return; MakeRect(x,y,x1,y1); Frame(gridW,x,y,x1,y1,1,ForeColor,GXinvert); } Invert159Box(x,y,x1,y1) short x,y,x1,y1; { /* inverts a 1-pix-rectangle and 10, 50, and 90% lines */ short i,dy; int p; if (x==x1 || y==y1) return; InvertBox(x,y,x1,y1); if (x1<x) swap(x,x1,i); if (y1<y) swap(y,y1,i); dy=y1-y; if (mono) p = 1; else p = 4 + selCB; XLine(gridW,x+1,y+dy*10/100,x1-1,y+dy*10/100,1,1,ForeColor,GXinvert,p); XLine(gridW,x+1,y+dy*50/100,x1-1,y+dy*50/100,1,1,ForeColor,GXinvert,p); XLine(gridW,x+1,y+dy*90/100,x1-1,y+dy*90/100,1,1,ForeColor,GXinvert,p); } /***********************/ TrackSBox(x,y) short x,y; { /* tracks the scaling box, and zooms in on it when mouse is released */ short x1,y1,state; int i,xn,yn; Window subw; XDefineCursor(gridW,cursx); /* while dragging the box, show a different cursor */ x1=x; y1=y; InvertSBox(x,y,x1,y1); while ( XQueryMouseButtons(gridW,&xn,&yn,&subw,&state), state&MiddleMask) { if (xn!=x1 || yn!=y1) { /* moved */ InvertSBox(x,y,x1,y1); x1=xn; y1=yn; InvertSBox(x,y,x1,y1); } } InvertSBox(x,y,x1,y1); XUndefineCursor(gridW); /* if ended up outside the gridrect, don't zoom */ if (x1<GLeft || x1>GRight || y1<GTop || y1>GBottom) return; if (CalcSRect(x,y,x1,y1)) { ChangedSettings(); PlotData(); RedrawSettings(); SetUndo(); } } InvertSBox(x,y,x1,y1) short x,y,x1,y1; { /* inverts a 2-pix-thick rectangle. Note that it only checks the range of x1,y1, as x,y is known to be inside the grid */ if (x1<GLeft || x1>GRight) return; if (y1<GTop || y1>GBottom) return; if (x==x1 || y==y1) { return; } Frame(gridW,x,y,x1,y1,2,ForeColor,GXinvert); } /***************************************************/ static int timerdone; /*******/ onalarm() /*******/ { timerdone=1; } /*******/ Timer(val) /* waits for VAL microseconds */ long val; /*******/ { struct itimerval it; if (val==0) return; bzero(&it, sizeof(it)); if (val>=1000000L) { /* more than 1 second */ it.it_value.tv_sec = val / 1000000L; val %= 1000000L; } it.it_value.tv_usec = val; timerdone=0; signal(SIGALRM,onalarm); setitimer(ITIMER_REAL, &it, (struct itimerval *)0); while (1) { sigblock(sigmask(SIGALRM)); /* note: have to block, so that ALRM */ if (timerdone) break; /* doesn't occur between 'if (timerdone)' */ else sigpause(0); /* and calling sigpause(0) */ } sigblock(0); /* turn ALRM blocking off */ signal(SIGALRM,SIG_DFL); } /*******/ mmove(num,src,des) int num; char *src,*des; /*******/ { /* copies num bytes from src to des. Probably won't work on some systems, but I couldn't find a handy move routine... */ int i; for (i=0; i<num; i++) *des++ = *src++; } /*******/ Quit() /*******/ { XUnmapWindow(mainW); killtmps(); exit(0); } /************************************************/ /* functions to deal with undo and user presets */ /************************************************/ #define INTSIZE sizeof(int) #define DBLSIZE sizeof(double) #define RECSIZE ( 5*(INTSIZE + INTSIZE + DBLSIZE) + 5*(INTSIZE) ) /* size of a Preset Record. 5 * ( range.power (int), range.multiplier (int), offset.val (double) ) + L10Offset/Range OctOffset/Range, and xscal (ints) */ static char UndoBuf[2][RECSIZE]; /*******************/ int Preset(pre) int pre; /*******************/ { /* reads preset #pre. Returns '1' if unable to do it, '0' otherwise */ int i; FILE *fp; char fname[128]; strcpy(fname,PREFILE); expfname(fname); fp = fopen(fname,"r"); if (!fp) { ErrBox("Unable to open preset file.",3); return(1); } else { long offset; offset = pre*RECSIZE; fseek(fp,offset,0); for (i=0; i<5; i++) { /* read mult,power,and off.val for each ctrl */ fread(&ranges[i].multiplier,INTSIZE,1,fp); fread(&ranges[i].power, INTSIZE,1,fp); fread(&offsets[i].val, DBLSIZE,1,fp); } fread(&L10Offset,INTSIZE,1,fp); fread(&L10Range, INTSIZE,1,fp); fread(&OctOffset,INTSIZE,1,fp); fread(&OctRange, INTSIZE,1,fp); fread(&xscal, INTSIZE,1,fp); fclose(fp); ErrBox("Preset loaded.",-1); return(0); } } /*********************/ int SetPreset(pre) int pre; /*********************/ { /* writes preset #pre (with current control vals) creates PREFILE if needed */ int i; long offset; FILE *fp; char fname[128]; strcpy(fname,PREFILE); expfname(fname); fp=fopen(fname,"r"); /* see if file exists */ if (fp==0) { /* create if it it doesn't */ int i,j,mval,pval; double dval; mval = 0; pval = 4; dval =0.0; ErrBox("Creating preset file...",3); fp=fopen(fname,"w"); for (i=0; i<8; i++) { for (j=0; j<5; j++) { /* write mult,power,and off.val for ctrls */ fwrite(&mval,INTSIZE,1,fp); fwrite(&pval,INTSIZE,1,fp); fwrite(&dval,DBLSIZE,1,fp); } fwrite(&mval,INTSIZE,1,fp); fwrite(&mval,INTSIZE,1,fp); fwrite(&mval,INTSIZE,1,fp); fwrite(&mval,INTSIZE,1,fp); fwrite(&mval,INTSIZE,1,fp); } } fclose(fp); /* write the preset */ fp = fopen(fname,"a"); offset = pre*RECSIZE; fseek(fp,offset,0); for (i=0; i<5; i++) { /* write mult,power,and off.val for each ctrl */ fwrite(&ranges[i].multiplier,INTSIZE,1,fp); fwrite(&ranges[i].power, INTSIZE,1,fp); fwrite(&offsets[i].val, DBLSIZE,1,fp); } fwrite(&L10Offset,INTSIZE,1,fp); fwrite(&L10Range, INTSIZE,1,fp); fwrite(&OctOffset,INTSIZE,1,fp); fwrite(&OctRange, INTSIZE,1,fp); fwrite(&xscal, INTSIZE,1,fp); fclose(fp); ErrBox("Preset written.",-1); } /***************/ SetUndo() /***************/ { /* copies UndoBuf[0] to UndoBuf[1], puts current settings in UndoBuf[0] */ char *cp; int i; mmove(RECSIZE,UndoBuf[0],UndoBuf[1]); /* save previous settings */ /* put current settings into UndoBuf[0] */ for (i=0, cp=UndoBuf[0]; i<5; i++) { mmove(INTSIZE,&ranges[i].multiplier,cp); cp += INTSIZE; mmove(INTSIZE,&ranges[i].power, cp); cp += INTSIZE; mmove(DBLSIZE,&offsets[i].val, cp); cp += DBLSIZE; } mmove(INTSIZE,&L10Offset,cp); cp+=INTSIZE; mmove(INTSIZE,&L10Range ,cp); cp+=INTSIZE; mmove(INTSIZE,&OctOffset,cp); cp+=INTSIZE; mmove(INTSIZE,&OctRange ,cp); cp+=INTSIZE; mmove(INTSIZE,&xscal ,cp); cp+=INTSIZE; } /***************/ GetUndo() /***************/ { /* gets current settings from UndoBuf[1] */ char *cp; int i; for (i=0, cp=UndoBuf[1]; i<5; i++) { /* get each roff */ mmove(INTSIZE,cp,&ranges[i].multiplier); cp+=INTSIZE; mmove(INTSIZE,cp,&ranges[i].power); cp+=INTSIZE; mmove(DBLSIZE,cp,&offsets[i].val); cp+=DBLSIZE; } mmove(INTSIZE,cp,&L10Offset); cp+=INTSIZE; mmove(INTSIZE,cp,&L10Range); cp+=INTSIZE; mmove(INTSIZE,cp,&OctOffset); cp+=INTSIZE; mmove(INTSIZE,cp,&OctRange); cp+=INTSIZE; mmove(INTSIZE,cp,&xscal); cp+=INTSIZE; } FontInfo *bigfinfo; Font bigfont; /**********/ Credits() /**********/ { int i,j,k; XEvent event; Window wind; bigfont=0; /* load BIG font */ if ((bigfinfo = XOpenFont("nonb44"))!=NULL) {} else if ((bigfinfo = XOpenFont("sbdr40"))!=NULL) {} else if ((bigfinfo = XOpenFont("micr25"))!=NULL) {} else bigfinfo = dlogfinfo; bigfont = bigfinfo->id; XFlush(); /* scroll window contents down */ for (i = -10; i<=GSIZE; i+=10) { XMoveArea(gridW,0,i,0,i+10,GSIZE+10,GSIZE-i-10); if (mono) XPixSet(gridW,0,i,GSIZE+10,10,gridFcol); else XPixSet(gridW,0,i,GSIZE+10,10,gridBcol); XFlush(); Timer(50000L); } /* draw window */ if (mono) XChangeBackground(AboutDlog,gridFpix); else XChangeBackground(AboutDlog,gridBpix); XMapWindow(AboutDlog); i=j=0; /* handle events until the next mouse event */ while (1) { if (XPending()) { XNextEvent(&event); if (event.type != ButtonPressed) HandleEvent(&event); else break; } /* amusing (?) animation */ if (mono) { int col; i+=5; if (i>GSIZE) { i=j%5; j++; j=j%10; } if (j&1) col=gridFcol; else col=gridBcol; XLine(AboutDlog, i,0,GSIZE,i, 1,1,col,GXcopy,AllPlanes); XLine(AboutDlog, GSIZE,i,GSIZE-i,GSIZE, 1,1,col,GXcopy,AllPlanes); XLine(AboutDlog, GSIZE-i,GSIZE,0,GSIZE-i,1,1,col,GXcopy,AllPlanes); XLine(AboutDlog, 0,GSIZE-i,i,0, 1,1,col,GXcopy,AllPlanes); } else { i+=5; if (i>=GSIZE) { i=0; j+=3; j&=3; } XLine(AboutDlog, i,0,GSIZE,i, 1,1,trcol[j],GXcopy,AllPlanes); XLine(AboutDlog, GSIZE,i,GSIZE-i,GSIZE, 1,1,trcol[(j+1)&3],GXcopy,AllPlanes); XLine(AboutDlog, GSIZE-i,GSIZE,0,GSIZE-i,1,1,trcol[(j+2)&3],GXcopy,AllPlanes); XLine(AboutDlog, 0,GSIZE-i,i,0, 1,1,trcol[(j+3)&3],GXcopy,AllPlanes); } Timer(20000L); XFlush(); } /* scroll window contents up, filling new area with mainBpix */ for (i=GSIZE-10; i>=0; i-=10) { if (i) XMoveArea(AboutDlog,0,10, 0,0, GSIZE,i); XPixSet(AboutDlog,0,i, GSIZE,10, gridBcol); XFlush(); Timer(50000L); } /* invert title bar back to normal */ InvTitleBar(); XUnmapWindow(AboutDlog); /* jettison bigfont if one was loaded */ if (bigfont != dlogfont && bigfont != 0) XFreeFont(bigfont); } /***********************/ RedrawAbout() /***********************/ { int bcol,c1,c2,c3; if (mono) { bcol=gridFcol; c1=c2=c3=gridBcol; } else { bcol=gridBcol; c1=trcol[2]; c2=trcol[3]; c3=trcol[0]; } if (bigfont) XText(AboutDlog, 200-(XStringWidth("xSplot",bigfinfo,0,0))/2, 200-(bigfinfo->height/2), "xSplot",6, bigfont, c1,bcol); XText(AboutDlog, 200-(XStringWidth("by John Bradley and Filip Fuma",butfinfo,0,0))/2, 200+(bigfinfo->height/2)+10, "by John Bradley and Filip Fuma",30, butfont, c2,bcol); XText(AboutDlog, 200-(XStringWidth(REVDATE,butfinfo,0,0))/2, 200+(bigfinfo->height/2)+10+butfinfo->height+10, REVDATE,strlen(REVDATE), butfont, c3,bcol); } \Rogue\Monster\ else echo "will not over write ./xsplot/xsplot.c" fi if `test ! -s ./xsplot/xsplot.l` then echo "writing ./xsplot/xsplot.l" cat > ./xsplot/xsplot.l << '\Rogue\Monster\' .TH XSPLOT l "30 July 1987" "X Version 10.4" .SH NAME xsplot \- An interactive SPICE plotting program .SH SYNOPSIS .B xsplot filename [host:display] [=geometry] .SH DESCRIPTION .I xsplot is an interactive X program that graphically displays the output of SPICE runs in an oscilloscope-ular fashion. It will allow you to zoom in on interesting sections, measure distances and slopes, and draw 10% cutoffs. It will, with the help of an auxilliary program, generate hardcopy to an HP-GL plotter. Rumor has it that there's even an amusing diversion buried in the code. Why, it may well be the Neatest Program Ever. Probably not, though. .SH OPTIONS .PP .TP 14 .B \=geometry The width and height shouldn't be set by the user, as the default size (640x480) is also the only size. Anything smaller will be ignored, and anything larger won't be used. You can feel free to set the position, though. .PP .TP 14 .B \fIhost\fP:\fIdisplay\fP Normally, .I xsplot gets the host and display number from the environment variable "DISPLAY". However, one can specify them explicitly. The .I host specifies which machine to create the .I xsplot window on, and the .I display argument specifies the display number. .SH OPERATION .PP Start up .I xsplot on the "diff.out" SPICE file by typing "xsplot diff.out". With any luck at all, the program should parse the data and open up the main window. .PP Note: Unless specified otherwise, 'click' means 'clicking the left button'. .PP .I The Title Bar: At the very top of the screen is the title bar. Clicking on it with the left button will display the credits. Click the left button again to make them go away. .PP .I The Grid: The large grid that takes up most of the main window is where all the data is actually displayed. Note that the name of the file and the analysis type are displayed above the grid. .PP .I The Offset/Range Box: This specifies the values used in graphing the data. The first pair of values are used for the (common) x-axis. Subsequent pairs are used for the y-axes. In the example, (diff.out: DC Analysis), the common x-axis is labeled "VIN". The offset of "0.000 V" means that the center of the screen corresponds to VIN=0.0V. The range (50mV) is the amount the x-value changes per division. The other two pairs of numbers work the same way for the two y-axes. (Note that in the example they are the same, meaning the two curves are plotted in the same scale. This doesn't have to be the case, however.) .PP .I The Modify Box: This houses the controls used to modify the offset/range settings and the Scale settings. To modify one of these values, click on the value to be modified, and then click the modification controls. Click on the Redraw button to see the results. .PP .I The User Presets Box: You have the ability to save eight complete sets of control settings. This allows you to return to a certain "view" of your data without having to play around with the controls. To save a preset, click on the .B Set button, and then click on one of the numbered buttons. To return to a preset, click on one of the numbered buttons. .PP .I The Measurement Box: Up to four buttons will be shown, one for each dataset you have chosen to graph (2 in the example). If you are on a color display, the colors of the boxes will match the colors of the traces. On a monochrome display, the buttons will have a line drawn in them with the same stipple pattern as the related trace. The box that has the thick frame around it is the 'Active Dataset'. This is the dataset that can be measured at the moment. (See .B "Cursor Madness!", below.) Note that if all the traces have the same offset/range settings, then it doesn't matter which one is the active dataset. .PP .I The Trace Location Box: This shows in what directions the active dataset goes off the screen, if any. .PP .I The Grid Type Box: This determines the type of grid that will be used for the x and y axes. Currently, the y axis is always 'linear'. The x axis, however, can be either 'linear', 'log 10', or 'log 2'. You can change the x axis type by selecting the x control and using the modification controls. Note that as you change the grid type, the offset/range information for the x-axis changes, also. Log 10 and log 2 grids are quite similar. In both cases, the offset, an integer power (of 10 or 2, respectively), refers to the left edge of the grid. The range is either 1, 3, or 10 divisions. An example of data that should be viewed on a log scale is the AC Analysis found in the diff.out file. (See .B "Switch Analysis", below.) .PP .I The Miscellaneous Box: This houses four command buttons. The first, .B Commands, opens and closes the "Alternate Commands" box. The second, .B Y-Lock, toggles locking on and off. When locking is on, any change you make to one of the y-axis offset/range controls is carried out on all of them. This can have the effect of moving all the traces up or down simultaneously. The .B Undo control returns all the settings to their previous values. The .B Redraw button redraws the data, using the current settings. .PP .TP 8 .I Alternate Commands Box: .B Load Data File: Clicking this will bring up a dialog box in the middle of the grid. You'll be prompted for the name of a SPICE file to load. Enter the filename and hit return, or hit return immediately to cancel the load. .B Switch Analysis: Clicking this button will bring up a dialog box listing all the analyses found in the current SPICE file. Double-click on the one you'd like to examine. .B Curves: While .I xsplot is only capable of displaying four traces at once, a SPICE analysis can have up to eight traces in it. This button brings up a dialog box listing all the curves found in the current analysis. Select the ones you want and click .B Ok , or click .B Cancel if you don't want to change curves. .B Big Picture: This will bring up a zoomed-all-the-way-out, scaled-to-fit graph of the data. .B Plot: This will allow you to generate hard-copy, assuming you have an HP-GL plotter and a working copy of .I splotter. Choosing .B File will prompt you for a file name to dump the plot data to, for later use. Choosing .B Plotter will dump the plot file to a temporary file, and attempt to exec "/usr/local/splotter". It will complain if it is unable to do so. .B Help: This may eventually do something useful. At the moment, it doesn't. Click the mouse inside the window to make it go away. .B Digital: Viewing Transient Analyses of digital circuits can be unpleasant, as the traces constantly overlap at 0V and 5V. This button will adjust the settings so that the traces appear stacked on the grid, rather than overlapping. Provided that the traces range between 0V and +5V, that is. A good example of the usefulness of this feature can be seen by loading the data file "sreg.out". .B Quit: Exits the program. Pretty obvious. .SH MEASURING .PP One of the major advantages .I xsplot has over the traditional ".PLOT" that SPICE generates is the ability to measure the output. Clicking the left button anywhere inside the Grid (or the Big Picture) will give you the x and y values associated with that particular screen coordinate. Clicking and dragging the left button inside the Grid/Big Picture will drag an L-shaped pair of lines from the original point to the cursor. Releasing the left button will give you the x and y values at the cursor point and the deltas between the two points (dX, dY). It will also give you the slope of the line connecting the two points (dY/dX), which can be useful for measuring amplification. Or something. .PP Clicking and dragging the RIGHT button inside the Grid/Big Picture will drag around a rectangle from the original point to the cursor. When you let go of the right button, three lines will be drawn inside the box at 10%, 50%, and 90% of it's vertical range. This may be useful for measuring rise and fall times of exponential outputs. Or maybe not. .SH ZOOMING .I xsplot allows you to directly zoom in on interesting parts of the data without fiddling around the the offset/range controls. To do this, locate a point of interest (on either the Grid or the Big Picture), and draw a rectangle around it by clicking the MIDDLE mouse button at one corner, and dragging it to the opposite corner. When you let go of the button, the program will zoom in as well as it's able to on the data, preserving the nice, round-number-osity of the range/offset controls. Also of interest: simply clicking the middle button inside the grid area (without dragging it anywhere) will zoom to the initial 'best-fit' settings. .SH CURSOR MADNESS! (a summary of the button usage) .TP 8 .I Inside the Grid Area: The LEFT button is used for measuring data. The MIDDLE button is used for zooming in. The RIGHT button is used for drawing 10%, 50%, and 90% cutoffs. .TP 8 .I Outside the Grid Area: The LEFT button is used to operate the controls. The MIDDLE button is a shortcut for the Big Picture command. The RIGHT button is a shortcut for the Redraw command. .SH MISCELLANEOUS .PP If less than 30 data points are visible on the grid, the actual points will be drawn, in addition to the lines connecting them. .PP .I xsplot attempts to acquire 8 r/w color cells for it's purposes. If it succeeds, you'll get to use the program in color, the way it was meant to be. If not, it'll only use two colors ("xsplot.Foreground" and "xsplot.Background" in your ".Xdefaults" file). Then again, since it's only likely to fail on a monochrome display, the two colors probably aren't very meaningful. Either way, if it goes into monochrome, traces will be drawn with different stipple patterns. Decidedly less fun. .SH LIMITATIONS .TP 8 * Only the first 1000 data points of an analysis are used. .TP 8 * Analyses must not have more than 8 dependent (output) variables. .TP 8 * There is an upper limit of 20 analyses per file, which should be more than ANYONE needs. .TP 8 * There should only be one SPICE run per output file. If your SPICE input file has multiple jobs in it, you should split them up first. .TP 8 * xsplot is fairly hard-wired to the format of SPICE output. In particular, things like the number of lines between a title and the start of data are expected to remain the same. It works with the output of SPICE 2g.6. It MAY work with other versions of SPICE, but then again, it may not. I can't guarantee anything. .TP 8 * xsplot gets it's data from the results of '.PRINT' statements. You should probably strip out any '.PLOT' statements you might have in your input file, as they slow the run down, and are Completely Ignored by .I xsplot. They won't interfere with it's ability to parse the file, though. .TP 8 * xsplot only supports the DC, AC, and TRANSIENT analyses generated by SPICE. It will not display NOISE or FOURIER analyses, for the simple reason that I've never seen one. If some of you analog types out would like it to deal with these analyses, kindly send me some data, and I'll see what I can do about it. .SH USING XSPLOT TO VIEW NON-SPICE DATA On the off chance that you'd like to view some non-SPICE data with .I xsplot, it can be done, and it's only slightly painful. Generate, or edit up a data file that looks like the one below. Note that case is important. The '.PRINT' line says that the data should be plotted on a linear grid (as the default), (by virtue of being a DC analysis), specifies the number of traces, and their names. It is important that the 'DC ANALYSIS' line start in column 0, and be typed EXACTLY as shown here. The 8 ignored lines can be blank. After that comes the actual data points. The first number on each line is the common x-value, and the other numbers are the y-values (1-8, depending on the number of labels specified in the .PRINT line). The end of data coincides with the end of the file. Note: if the data would look more appropriate on a logarithmic grid, change the two 'DC's to 'AC'. Also, note that you can't specify the x-axis label. The x-axis will always be labeled 'VIN' for a DC analysis, and 'FREQ' for an AC analysis. Nothing can be done about this, as far as .I xsplot is concerned. For hard-copy, however, you can edit the SPIF file before sending it to the plotter. See "The SPIF Spec", below. .SH THE SPIF SPEC When you tell .I xsplot to plot, it will generate a file in this format, and (hopefully) 'splotter' will be able to drive the actual plotter. .PP SPIF files are plain text files, and can be easily created/edited with any text editor. .TP 25 The First Line: The name of the SPICE file. .TP 25 The Second Line: The name of the analysis. .TP 25 The Third Line: The grid type (an integer) (0=Linear) (1=Log 10, 1 division) (2=Log 10, 3 divisions) (3=Log 10, 10 divisions) (4=Log 2, 1 division) (5=Log 2, 3 divisions) (6=Log 2, 10 divisions) .TP 25 The Fourth Line: The number of curves in the plot. (an integer, from 1 to 4). .TP 25 The Fifth Line: The names of the axes (2-5 words, separated by spaces). The first word is the name of the (common) x-axis. The second (and following) words are the names of the curves. .TP 25 The Sixth Line: The x-axis offset and range info. If the grid type equals 0, this line will be in the form "x.xxxExx x.xxxExx", where the first number is the offset, and the second, the range. If the grid type equals 1,2, or 3, the line will be in the form "10^x y", where x is an integer in the range +/-19, and 10^x is the value at the left edge. y will be an integer, either 1,3, or 10, specifying the number of divisions. If the grid type 4,5, or 6, this line will be in the form "2^x y", where x is an integer in the range +/-19, and 2^x is the value at the left edge. y will be an integer, either 1,3 or 10, specifying the number of divisions. .TP 25 The Seventh Line: The y-axis offset and range info. There will be from 1 to 4 lines (depending on the number of curves). Each line will be in the form "x.xxxxExx x.xxxxExx" where the first number is the offset, and the second number is the range. .TP 25 The Rest of the File: This will be an indeterminant number of lines, each with an x-coordinate and 1-4 y-coordinates separated by spaces. The coordinates will be integers in the range +/- 32K. The plotting program should clip these coordinates to the rante 0-400 on both axes (0,0 = bottom-left). The end of the data will coincide with the end of the SPIF file. .SH BUGS If you are foolish enough to try to plot negative values on a log scale, the program will treat them as '0'. The resulting graph probably won't look the way you'd expect, but you should be doing such a thing anyhow... .SH AUTHOR John Bradley, University of Pennsylvania (bradley@cis.upenn.edu) .SH DESIGNER Filip Fuma, University of Pennsylvania (fuma@cis.upenn.edu) \Rogue\Monster\ else echo "will not over write ./xsplot/xsplot.l" fi echo "Finished archive 3 of 4" exit
bradley@dsl.cis.upenn.edu (John Bradley) (08/25/87)
xsplot is an X program (10.4) for viewing, plotting, and analyzing SPICE output. It will drive an HP-GL plotter for hardcopy. It can be used to look at non-SPICE data, also. Why, it could be the Neatest Thing Ever. Probably not, though. Runs just dandy on Berkeley 4.2 Unix variants (on the IBM RT under 4.2 and 4.3, and on random Vaxen under Ultrix 1.2 and 2.0) --John Bradley - University of Pennsylvania - bradley@cis.upenn.edu Part 4 of 4 ------------------------cut here---------------------- #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -d ./xsplot` then mkdir ./xsplot echo "mkdir ./xsplot" fi if `test ! -s ./xsplot/Makefile` then echo "writing ./xsplot/Makefile" cat > ./xsplot/Makefile << '\Rogue\Monster\' INCLUDES = ./include XLIB = -lX CFLAGS = -I$(INCLUDES) CLIBS = -lm OBJS = xsplot.o xsplotctl.o xsplotmac.o xsplotgr.o xsplotio.o xsplotdlg.o \ xsplotdiv.o all: xsplot xsplot: $(OBJS) $(INCLUDES)/xsplot.h cc $(CFLAGS) -o xsplot $(OBJS) $(XLIB) $(CLIBS) $(OBJS): $(INCLUDES)/xsplot.h clean: rm -f $(OBJS) \Rogue\Monster\ else echo "will not over write ./xsplot/Makefile" fi if `test ! -s ./xsplot/README` then echo "writing ./xsplot/README" cat > ./xsplot/README << '\Rogue\Monster\' Installation notes: It should. Without problems. If you intend to do any plotting, you should define SPLOTTER in xsplotgr.c to reflect where splotter is installed. Or maybe you should just install splotter in /usr/local, like any NORMAL person. See the splotter for further hard-copy related information. Another thing you may want to change is the function 'crash()' in xsplot.c. This function is called whenever an XError happens, and dumps core. This is helpful to me (to aid in debugging) but isn't necessarily something you'd want it doing in production. You can easily modify it NOT to crash. I've personally tested this on a (monochrome) IBM RT PC running 4.2, and a (colorful) MicroVax II GPX running Ultrix 2.0. It compiles on both with no changes, and since I don't do any sort of hairy FP or bizarre OS calls, it should work on virtually anything. At the start of the program, it attempts to grab 8 r/w color cells. If it succeeds, it'll run in color, if not, it stipples things in b/w. Needless to say, the color version is much more entertaining. It may also interest you to know that this program points out a couple of bugs in the 10.4 RT implementation of X. In particular, XDrawDashed doesn't. Also, XDraw has this annoying misfeature that causes it to reset the line pattern for each line segment that it draws. The practical upshot of which is, if your line segments are short, you only ever see the first couple bits of the line pattern. This prevented me from making the monochrome line patterns vastly different, as I can only count on the first two or three pixels being drawn. (Can't even count on that, actually, but that's the way it is.) If you're running on a monochrome display that keeps the draws the lines properly no matter how close the points are, you may (or may not) want to make the patterns different-er. Or maybe you ought to just run it on a color display, like a Real Man. About the colors: I don't care if you don't like the colors. After all, what do YOU know? (Actually, I'm not too crazy about them myself, but I limited myself to 8 colors (so it'll run on lame 4-plane displays, such as these HP bobcats we've got lying around), so there wasn't too much choice involved.) If you think you can do better, go for it. You're also welcome to modify it to use 16 or 32 colors, which should be more than sufficient. Limitations of xsplot: xsplot will deal with a maximum of 1000 data points, in any single analysis. There's no fundamental reason WHY, and you could certainly change MAXPTS (in include/xsplot.h) to something larger, if this is a problem. 1000 seems like a fine number to me, though. Besides, there's historical reasons. Be sure to change the appropriate number in splotter, also, if you plan to be running it. Also, there's a limit of 20 analyses per file (more than enough, I should think). These analyses may have up to 8 dependent variables, of which any 4 can be seen at once. A somewhat more realistic limitation of xsplot is that it only currently supports the DC, AC, and Transient analyses of SPICE. Noise, Fourier, and whatever other simulations SPICE can handle AREN'T dealt with. This hasn't proved to be a limitation in our lab (digital stuff, mostly), but I could see it being a problem for some of you RF-types out there, or whatever, so if someone sends me examples of these analyses, I'll probably throw them into xsplot, also. ("Dammit Mister, I'm a Scientist, not an Engineer!") Likewise, if you have some SPICE file that xsplot doesn't parse correctly, and you think it should, send it to me, and I'll see what I can do about it. Rumor has it that that there's a gratuitous bit of entertainment in the code. Find it. John Bradley - University of Pennsylvania - bradley@cis.upenn.edu \Rogue\Monster\ else echo "will not over write ./xsplot/README" fi if `test ! -s ./xsplot/diff.out` then echo "writing ./xsplot/diff.out" cat > ./xsplot/diff.out << '\Rogue\Monster\' 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** INPUT LISTING TEMPERATURE = 27.000 DEG C 0*********************************************************************** .WIDTH IN=72 OUT=80 .OPT ACCT LIST NODE LVLCOD=2 .TF V(5) VIN .DC VIN -0.25 0.25 0.005 .AC DEC 10 1 10GHZ .TRAN 5NS 500NS VIN 1 0 SIN(0 0.1 5MEG) AC 1 VCC 8 0 12 VEE 9 0 -12 Q1 4 2 6 QNL Q2 5 3 6 QNL RS1 1 2 1K RS2 3 0 1K RC1 4 8 10K RC2 5 8 10K Q3 6 7 9 QNL Q4 7 7 9 QNL RBIAS 7 8 20K .MODEL QNL NPN(BF=80 RB=100 CCS=2PF TF=0.3NS TR=6NS CJE=3PF CJC=2PF + VA=50) .PRINT DC V(4) V(5) .PRINT AC VM(5) VP(5) .PRINT TRAN V(4) V(5) .END 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** CIRCUIT ELEMENT SUMMARY TEMPERATURE = 27.000 DEG C 0*********************************************************************** 0**** RESISTORS 0 NAME NODES VALUE TC1 TC2 RS1 1 2 1.00D+03 0.00D+00 0.00D+00 RS2 3 0 1.00D+03 0.00D+00 0.00D+00 RC1 4 8 1.00D+04 0.00D+00 0.00D+00 RC2 5 8 1.00D+04 0.00D+00 0.00D+00 RBIAS 7 8 2.00D+04 0.00D+00 0.00D+00 0**** INDEPENDENT SOURCES 0 NAME NODES DC VALUE AC VALUE AC PHASE TRANSIENT VIN 1 0 0.00D+00 1.00D+00 0.00D+00 SIN 0 OFFSET....... 0.00D+00 AMPLITUDE.... 1.00D-01 FREQUENCY.... 5.00D+06 DELAY........ 0.00D+00 THETA........ 0.00D+00 VCC 8 0 1.20D+01 0.00D+00 0.00D+00 VEE 9 0 -1.20D+01 0.00D+00 0.00D+00 0**** BIPOLAR JUNCTION TRANSISTORS 0 NAME C B E S MODEL AREA Q1 4 2 6 0 QNL 1.000 Q2 5 3 6 0 QNL 1.000 Q3 6 7 9 0 QNL 1.000 Q4 7 7 9 0 QNL 1.000 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** ELEMENT NODE TABLE TEMPERATURE = 27.000 DEG C 0*********************************************************************** 0 0 RS2 VIN VCC VEE Q1 Q2 Q3 Q4 0 1 RS1 VIN 0 2 RS1 Q1 0 3 RS2 Q2 0 4 RC1 Q1 0 5 RC2 Q2 0 6 Q1 Q2 Q3 0 7 RBIAS Q3 Q4 Q4 0 8 RC1 RC2 RBIAS VCC 0 9 VEE Q3 Q4 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** BJT MODEL PARAMETERS TEMPERATURE = 27.000 DEG C 0*********************************************************************** QNL 0TYPE NPN 0IS 1.00D-16 0BF 80.000 0NF 1.000 0VAF 5.00D+01 0BR 1.000 0NR 1.000 0RB 100.000 0CJE 3.00D-12 0TF 3.00D-10 0CJC 2.00D-12 0TR 6.00D-09 0CJS 2.00D-12 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** DC TRANSFER CURVES TEMPERATURE = 27.000 DEG C 0*********************************************************************** VIN V(4) V(5) X -2.500E-01 1.196E+01 -7.957E-01 -2.450E-01 1.195E+01 -7.948E-01 -2.400E-01 1.195E+01 -7.938E-01 -2.350E-01 1.194E+01 -7.926E-01 -2.300E-01 1.193E+01 -7.912E-01 -2.250E-01 1.191E+01 -7.897E-01 -2.200E-01 1.190E+01 -7.880E-01 -2.150E-01 1.189E+01 -7.860E-01 -2.100E-01 1.187E+01 -7.839E-01 -2.050E-01 1.185E+01 -7.816E-01 -2.000E-01 1.183E+01 -7.791E-01 -1.950E-01 1.181E+01 -7.764E-01 -1.900E-01 1.179E+01 -7.735E-01 -1.850E-01 1.177E+01 -7.703E-01 -1.800E-01 1.174E+01 -7.669E-01 -1.750E-01 1.172E+01 -7.634E-01 -1.700E-01 1.169E+01 -7.596E-01 -1.650E-01 1.166E+01 -7.555E-01 -1.600E-01 1.163E+01 -7.513E-01 -1.550E-01 1.160E+01 -7.468E-01 -1.500E-01 1.157E+01 -7.420E-01 -1.450E-01 1.154E+01 -7.369E-01 -1.400E-01 1.151E+01 -7.316E-01 -1.350E-01 1.147E+01 -7.258E-01 -1.300E-01 1.144E+01 -7.197E-01 -1.250E-01 1.140E+01 -7.130E-01 -1.200E-01 1.136E+01 -7.058E-01 -1.150E-01 1.133E+01 -6.976E-01 -1.100E-01 1.129E+01 -6.883E-01 -1.050E-01 1.124E+01 -6.772E-01 -1.000E-01 1.120E+01 -6.627E-01 -9.500E-02 1.115E+01 -6.407E-01 -9.000E-02 1.108E+01 -5.907E-01 -8.500E-02 1.093E+01 -4.536E-01 -8.000E-02 1.076E+01 -2.784E-01 -7.500E-02 1.056E+01 -8.128E-02 -7.000E-02 1.034E+01 1.382E-01 -6.500E-02 1.009E+01 3.807E-01 -6.000E-02 9.827E+00 6.462E-01 -5.500E-02 9.537E+00 9.346E-01 -5.000E-02 9.225E+00 1.245E+00 -4.500E-02 8.891E+00 1.577E+00 -4.000E-02 8.538E+00 1.929E+00 -3.500E-02 8.167E+00 2.299E+00 -3.000E-02 7.779E+00 2.685E+00 -2.500E-02 7.376E+00 3.086E+00 -2.000E-02 6.962E+00 3.500E+00 -1.500E-02 6.537E+00 3.923E+00 -1.000E-02 6.105E+00 4.354E+00 -5.000E-03 5.669E+00 4.790E+00 0.000E+00 5.229E+00 5.229E+00 5.000E-03 4.790E+00 5.668E+00 1.000E-02 4.353E+00 6.104E+00 1.500E-02 3.921E+00 6.536E+00 2.000E-02 3.497E+00 6.960E+00 2.500E-02 3.083E+00 7.374E+00 3.000E-02 2.682E+00 7.776E+00 3.500E-02 2.294E+00 8.163E+00 4.000E-02 1.924E+00 8.535E+00 4.500E-02 1.571E+00 8.887E+00 5.000E-02 1.238E+00 9.221E+00 5.500E-02 9.268E-01 9.532E+00 6.000E-02 6.375E-01 9.822E+00 6.500E-02 3.708E-01 1.009E+01 7.000E-02 1.272E-01 1.033E+01 7.500E-02 -9.349E-02 1.055E+01 8.000E-02 -2.918E-01 1.075E+01 8.500E-02 -4.644E-01 1.093E+01 9.000E-02 -5.416E-01 1.102E+01 9.500E-02 -5.641E-01 1.107E+01 1.000E-01 -5.757E-01 1.112E+01 1.050E-01 -5.829E-01 1.116E+01 1.100E-01 -5.881E-01 1.119E+01 1.150E-01 -5.920E-01 1.123E+01 1.200E-01 -5.949E-01 1.126E+01 1.250E-01 -5.972E-01 1.130E+01 1.300E-01 -5.989E-01 1.133E+01 1.350E-01 -6.003E-01 1.136E+01 1.400E-01 -6.013E-01 1.140E+01 1.450E-01 -6.020E-01 1.143E+01 1.500E-01 -6.025E-01 1.146E+01 1.550E-01 -6.027E-01 1.149E+01 1.600E-01 -6.027E-01 1.152E+01 1.650E-01 -6.026E-01 1.155E+01 1.700E-01 -6.023E-01 1.158E+01 1.750E-01 -6.018E-01 1.160E+01 1.800E-01 -6.011E-01 1.163E+01 1.850E-01 -6.003E-01 1.165E+01 1.900E-01 -5.994E-01 1.168E+01 1.950E-01 -5.982E-01 1.170E+01 2.000E-01 -5.970E-01 1.173E+01 2.050E-01 -5.956E-01 1.175E+01 2.100E-01 -5.940E-01 1.177E+01 2.150E-01 -5.923E-01 1.179E+01 2.200E-01 -5.904E-01 1.181E+01 2.250E-01 -5.884E-01 1.183E+01 2.300E-01 -5.863E-01 1.185E+01 2.350E-01 -5.840E-01 1.186E+01 2.400E-01 -5.815E-01 1.188E+01 2.450E-01 -5.789E-01 1.189E+01 2.500E-01 -5.762E-01 1.190E+01 Y 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** SMALL SIGNAL BIAS SOLUTION TEMPERATURE = 27.000 DEG C 0*********************************************************************** NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE ( 1) 0.0000 ( 2) -0.0077 ( 3) -0.0077 ( 4) 5.2291 ( 5) 5.2291 ( 6) -0.7700 ( 7) -11.2212 ( 8) 12.0000 ( 9) -12.0000 VOLTAGE SOURCE CURRENTS NAME CURRENT VIN -7.661D-06 VCC -2.515D-03 VEE 2.531D-03 TOTAL POWER DISSIPATION 6.05D-02 WATTS 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** OPERATING POINT INFORMATION TEMPERATURE = 27.000 DEG C 0*********************************************************************** 0 0**** BIPOLAR JUNCTION TRANSISTORS 0 Q1 Q2 Q3 Q4 0MODEL QNL QNL QNL QNL IB 7.67E-06 7.67E-06 1.42E-05 1.42E-05 IC 6.78E-04 6.78E-04 1.37E-03 1.13E-03 VBE 0.762 0.762 0.779 0.779 VBC -5.237 -5.237 -10.451 0.000 VCE 5.999 5.999 11.230 0.779 BETADC 88.380 88.380 96.724 80.002 GM 2.62E-02 2.62E-02 5.29E-02 4.38E-02 RPI 3.37E+03 3.37E+03 1.83E+03 1.83E+03 RX 1.00E+02 1.00E+02 1.00E+02 1.00E+02 RO 8.15E+04 8.15E+04 4.41E+04 4.41E+04 CPI 1.29E-11 1.29E-11 2.10E-11 1.82E-11 CMU 1.01E-12 1.01E-12 8.19E-13 2.00E-12 CBX 0.00E+00 0.00E+00 0.00E+00 0.00E+00 CCS 2.00E-12 2.00E-12 2.00E-12 2.00E-12 BETAAC 88.339 88.339 96.683 79.961 FT 2.99E+08 2.99E+08 3.86E+08 3.44E+08 0**** SMALL-SIGNAL CHARACTERISTICS 0 V(5)/VIN = 8.790D+01 0 INPUT RESISTANCE AT VIN = 8.935D+03 0 OUTPUT RESISTANCE AT V(5) = 9.446D+03 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** AC ANALYSIS TEMPERATURE = 27.000 DEG C 0*********************************************************************** FREQ VM(5) VP(5) X 1.000E+00 8.790E+01 -8.385E-05 1.259E+00 8.790E+01 -1.056E-04 1.585E+00 8.790E+01 -1.329E-04 1.995E+00 8.790E+01 -1.673E-04 2.512E+00 8.790E+01 -2.106E-04 3.162E+00 8.790E+01 -2.652E-04 3.981E+00 8.790E+01 -3.338E-04 5.012E+00 8.790E+01 -4.203E-04 6.310E+00 8.790E+01 -5.291E-04 7.943E+00 8.790E+01 -6.661E-04 1.000E+01 8.790E+01 -8.385E-04 1.259E+01 8.790E+01 -1.056E-03 1.585E+01 8.790E+01 -1.329E-03 1.995E+01 8.790E+01 -1.673E-03 2.512E+01 8.790E+01 -2.106E-03 3.162E+01 8.790E+01 -2.652E-03 3.981E+01 8.790E+01 -3.338E-03 5.012E+01 8.790E+01 -4.203E-03 6.310E+01 8.790E+01 -5.291E-03 7.943E+01 8.790E+01 -6.661E-03 1.000E+02 8.790E+01 -8.385E-03 1.259E+02 8.790E+01 -1.056E-02 1.585E+02 8.790E+01 -1.329E-02 1.995E+02 8.790E+01 -1.673E-02 2.512E+02 8.790E+01 -2.106E-02 3.162E+02 8.790E+01 -2.652E-02 3.981E+02 8.790E+01 -3.338E-02 5.012E+02 8.790E+01 -4.203E-02 6.310E+02 8.790E+01 -5.291E-02 7.943E+02 8.790E+01 -6.661E-02 1.000E+03 8.790E+01 -8.385E-02 1.259E+03 8.790E+01 -1.056E-01 1.585E+03 8.790E+01 -1.329E-01 1.995E+03 8.790E+01 -1.673E-01 2.512E+03 8.790E+01 -2.106E-01 3.162E+03 8.790E+01 -2.652E-01 3.981E+03 8.790E+01 -3.338E-01 5.012E+03 8.790E+01 -4.203E-01 6.310E+03 8.790E+01 -5.291E-01 7.943E+03 8.789E+01 -6.660E-01 1.000E+04 8.789E+01 -8.385E-01 1.259E+04 8.788E+01 -1.056E+00 1.585E+04 8.788E+01 -1.329E+00 1.995E+04 8.786E+01 -1.673E+00 2.512E+04 8.784E+01 -2.105E+00 3.162E+04 8.781E+01 -2.650E+00 3.981E+04 8.775E+01 -3.335E+00 5.012E+04 8.767E+01 -4.195E+00 6.310E+04 8.753E+01 -5.276E+00 7.943E+04 8.732E+01 -6.632E+00 1.000E+05 8.699E+01 -8.328E+00 1.259E+05 8.647E+01 -1.044E+01 1.585E+05 8.566E+01 -1.306E+01 1.995E+05 8.443E+01 -1.629E+01 2.512E+05 8.258E+01 -2.020E+01 3.162E+05 7.988E+01 -2.487E+01 3.981E+05 7.610E+01 -3.029E+01 5.012E+05 7.107E+01 -3.636E+01 6.310E+05 6.481E+01 -4.289E+01 7.943E+05 5.759E+01 -4.957E+01 1.000E+06 4.988E+01 -5.607E+01 1.259E+06 4.223E+01 -6.210E+01 1.585E+06 3.509E+01 -6.751E+01 1.995E+06 2.876E+01 -7.224E+01 2.512E+06 2.335E+01 -7.633E+01 3.162E+06 1.883E+01 -7.990E+01 3.981E+06 1.512E+01 -8.308E+01 5.012E+06 1.210E+01 -8.603E+01 6.310E+06 9.658E+00 -8.889E+01 7.943E+06 7.683E+00 -9.179E+01 1.000E+07 6.087E+00 -9.484E+01 1.259E+07 4.797E+00 -9.815E+01 1.585E+07 3.753E+00 -1.018E+02 1.995E+07 2.909E+00 -1.059E+02 2.512E+07 2.226E+00 -1.103E+02 3.162E+07 1.677E+00 -1.152E+02 3.981E+07 1.238E+00 -1.202E+02 5.012E+07 8.944E-01 -1.252E+02 6.310E+07 6.313E-01 -1.299E+02 7.943E+07 4.351E-01 -1.340E+02 1.000E+08 2.928E-01 -1.370E+02 1.259E+08 1.933E-01 -1.383E+02 1.585E+08 1.266E-01 -1.372E+02 1.995E+08 8.414E-02 -1.334E+02 2.512E+08 5.800E-02 -1.279E+02 3.162E+08 4.170E-02 -1.219E+02 3.981E+08 3.099E-02 -1.164E+02 5.012E+08 2.353E-02 -1.116E+02 6.310E+08 1.813E-02 -1.075E+02 7.943E+08 1.410E-02 -1.041E+02 1.000E+09 1.105E-02 -1.014E+02 1.259E+09 8.698E-03 -9.907E+01 1.585E+09 6.870E-03 -9.723E+01 1.995E+09 5.437E-03 -9.576E+01 2.512E+09 4.309E-03 -9.458E+01 3.162E+09 3.418E-03 -9.364E+01 3.981E+09 2.713E-03 -9.289E+01 5.012E+09 2.154E-03 -9.230E+01 6.310E+09 1.710E-03 -9.182E+01 7.943E+09 1.358E-03 -9.145E+01 1.000E+10 1.079E-03 -9.115E+01 Y 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** INITIAL TRANSIENT SOLUTION TEMPERATURE = 27.000 DEG C 0*********************************************************************** NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE ( 1) 0.0000 ( 2) -0.0077 ( 3) -0.0077 ( 4) 5.2291 ( 5) 5.2291 ( 6) -0.7700 ( 7) -11.2212 ( 8) 12.0000 ( 9) -12.0000 VOLTAGE SOURCE CURRENTS NAME CURRENT VIN -7.661D-06 VCC -2.515D-03 VEE 2.531D-03 TOTAL POWER DISSIPATION 6.05D-02 WATTS 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** OPERATING POINT INFORMATION TEMPERATURE = 27.000 DEG C 0*********************************************************************** 0 0**** BIPOLAR JUNCTION TRANSISTORS 0 Q1 Q2 Q3 Q4 0MODEL QNL QNL QNL QNL IB 7.67E-06 7.67E-06 1.42E-05 1.42E-05 IC 6.78E-04 6.78E-04 1.37E-03 1.13E-03 VBE 0.762 0.762 0.779 0.779 VBC -5.237 -5.237 -10.451 0.000 VCE 5.999 5.999 11.230 0.779 BETADC 88.380 88.380 96.724 80.002 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** TRANSIENT ANALYSIS TEMPERATURE = 27.000 DEG C 0*********************************************************************** TIME V(4) V(5) X 0.000E+00 5.229E+00 5.229E+00 5.000E-09 5.217E+00 5.237E+00 1.000E-08 5.172E+00 5.272E+00 1.500E-08 5.101E+00 5.333E+00 2.000E-08 5.007E+00 5.417E+00 2.500E-08 4.897E+00 5.520E+00 3.000E-08 4.765E+00 5.648E+00 3.500E-08 4.624E+00 5.787E+00 4.000E-08 4.470E+00 5.943E+00 4.500E-08 4.313E+00 6.103E+00 5.000E-08 4.154E+00 6.270E+00 5.500E-08 4.000E+00 6.432E+00 6.000E-08 3.853E+00 6.590E+00 6.500E-08 3.717E+00 6.736E+00 7.000E-08 3.597E+00 6.868E+00 7.500E-08 3.495E+00 6.982E+00 8.000E-08 3.415E+00 7.073E+00 8.500E-08 3.356E+00 7.141E+00 9.000E-08 3.325E+00 7.180E+00 9.500E-08 3.317E+00 7.194E+00 1.000E-07 3.339E+00 7.176E+00 1.050E-07 3.385E+00 7.132E+00 1.100E-07 3.461E+00 7.057E+00 1.150E-07 3.558E+00 6.958E+00 1.200E-07 3.683E+00 6.831E+00 1.250E-07 3.825E+00 6.686E+00 1.300E-07 3.988E+00 6.517E+00 1.350E-07 4.163E+00 6.338E+00 1.400E-07 4.353E+00 6.144E+00 1.450E-07 4.545E+00 5.947E+00 1.500E-07 4.742E+00 5.745E+00 1.550E-07 4.935E+00 5.549E+00 1.600E-07 5.121E+00 5.358E+00 1.650E-07 5.295E+00 5.179E+00 1.700E-07 5.452E+00 5.016E+00 1.750E-07 5.591E+00 4.872E+00 1.800E-07 5.705E+00 4.752E+00 1.850E-07 5.795E+00 4.654E+00 1.900E-07 5.855E+00 4.586E+00 1.950E-07 5.889E+00 4.544E+00 2.000E-07 5.891E+00 4.533E+00 2.050E-07 5.867E+00 4.548E+00 2.100E-07 5.811E+00 4.596E+00 2.150E-07 5.733E+00 4.666E+00 2.200E-07 5.627E+00 4.766E+00 2.250E-07 5.504E+00 4.884E+00 2.300E-07 5.360E+00 5.026E+00 2.350E-07 5.206E+00 5.180E+00 2.400E-07 5.039E+00 5.350E+00 2.450E-07 4.870E+00 5.524E+00 2.500E-07 4.698E+00 5.703E+00 2.550E-07 4.531E+00 5.879E+00 2.600E-07 4.371E+00 6.051E+00 2.650E-07 4.223E+00 6.210E+00 2.700E-07 4.092E+00 6.355E+00 2.750E-07 3.978E+00 6.481E+00 2.800E-07 3.887E+00 6.585E+00 2.850E-07 3.818E+00 6.665E+00 2.900E-07 3.777E+00 6.715E+00 2.950E-07 3.760E+00 6.741E+00 3.000E-07 3.774E+00 6.733E+00 3.050E-07 3.812E+00 6.700E+00 3.100E-07 3.880E+00 6.634E+00 3.150E-07 3.970E+00 6.545E+00 3.200E-07 4.088E+00 6.427E+00 3.250E-07 4.223E+00 6.290E+00 3.300E-07 4.381E+00 6.131E+00 3.350E-07 4.549E+00 5.960E+00 3.400E-07 4.731E+00 5.774E+00 3.450E-07 4.917E+00 5.585E+00 3.500E-07 5.107E+00 5.391E+00 3.550E-07 5.292E+00 5.202E+00 3.600E-07 5.471E+00 5.019E+00 3.650E-07 5.637E+00 4.849E+00 3.700E-07 5.787E+00 4.693E+00 3.750E-07 5.918E+00 4.556E+00 3.800E-07 6.024E+00 4.443E+00 3.850E-07 6.107E+00 4.352E+00 3.900E-07 6.159E+00 4.291E+00 3.950E-07 6.186E+00 4.254E+00 4.000E-07 6.181E+00 4.250E+00 4.050E-07 6.150E+00 4.270E+00 4.100E-07 6.087E+00 4.323E+00 4.150E-07 6.003E+00 4.398E+00 4.200E-07 5.890E+00 4.503E+00 4.250E-07 5.761E+00 4.626E+00 4.300E-07 5.611E+00 4.773E+00 4.350E-07 5.451E+00 4.932E+00 4.400E-07 5.278E+00 5.107E+00 4.450E-07 5.103E+00 5.286E+00 4.500E-07 4.926E+00 5.470E+00 4.550E-07 4.753E+00 5.651E+00 4.600E-07 4.588E+00 5.827E+00 4.650E-07 4.436E+00 5.992E+00 4.700E-07 4.299E+00 6.142E+00 4.750E-07 4.180E+00 6.273E+00 4.800E-07 4.085E+00 6.381E+00 4.850E-07 4.012E+00 6.466E+00 4.900E-07 3.967E+00 6.522E+00 4.950E-07 3.943E+00 6.555E+00 5.000E-07 3.945E+00 6.560E+00 Y 0 JOB CONCLUDED 1*******02/04/86 ******** SPICE 2G.6 3/15/83 ********19:57:46***** 0DIFPAIR CKT - SIMPLE DIFFERENTIAL PAIR 0**** JOB STATISTICS SUMMARY TEMPERATURE = 27.000 DEG C 0*********************************************************************** NUNODS NCNODS NUMNOD NUMEL DIODES BJTS JFETS MFETS 10 10 14 12 0 4 0 0 0 NUMTEM ICVFLG JTRFLG JACFLG INOISE IDIST NOGO 0 1 101 101 101 0 0 0 0 NSTOP NTTBR NTTAR IFILL IOPS PERSPA 17. 57. 57. 0. 94. 80.277 0 NUMTTP NUMRTP NUMNIT MAXMEM MEMUSE COPYKNT 57. 0. 158. 400000 2736 22172. 0 READIN 1.22 0 SETUP 0.30 0 TRCURV 4.95 230. 0 DCAN 1.02 16. 0 DCDCMP 1.533 4. 0 DCSOL 1.000 0 ACAN 2.90 101. 0 TRANAN 5.05 158. 0 OUTPUT 3.25 0 LOAD 5.250 0 CODGEN 0.000 0. 0 CODEXC 0.000 0 MACINS 0.000 0 OVERHEAD 0.13 0 TOTAL JOB TIME 18.82 FORTRAN STOP \Rogue\Monster\ else echo "will not over write ./xsplot/diff.out" fi if `test ! -d ./xsplot/include` then mkdir ./xsplot/include echo "mkdir ./xsplot/include" fi if `test ! -s ./xsplot/include/cursor` then echo "writing ./xsplot/include/cursor" cat > ./xsplot/include/cursor << '\Rogue\Monster\' #define cursor_width 16 #define cursor_height 16 #define cursor_x_hot 3 #define cursor_y_hot 1 static short cursor_bits[] = { 0x0000, 0x0008, 0x0018, 0x0038, 0x0078, 0x00f8, 0x01f8, 0x03f8, 0x07f8, 0x00f8, 0x00d8, 0x0188, 0x0180, 0x0300, 0x0300, 0x0000}; \Rogue\Monster\ else echo "will not over write ./xsplot/include/cursor" fi if `test ! -s ./xsplot/include/cursor.mask` then echo "writing ./xsplot/include/cursor.mask" cat > ./xsplot/include/cursor.mask << '\Rogue\Monster\' #define cursor_mask_width 16 #define cursor_mask_height 16 static short cursor_mask_bits[] = { 0x000c, 0x001c, 0x003c, 0x007c, 0x00fc, 0x01fc, 0x03fc, 0x07fc, 0x0ffc, 0x0ffc, 0x01fc, 0x03dc, 0x03cc, 0x0780, 0x0780, 0x0300}; \Rogue\Monster\ else echo "will not over write ./xsplot/include/cursor.mask" fi if `test ! -s ./xsplot/include/icon` then echo "writing ./xsplot/include/icon" cat > ./xsplot/include/icon << '\Rogue\Monster\' #define icon_width 64 #define icon_height 48 static short icon_bits[] = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x49ff, 0xfc92, 0xffff, 0xffff, 0x49ff, 0xfc92, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xaaab, 0xaaaa, 0xaaaa, 0xaaaa, 0xfffd, 0xffff, 0xffff, 0xffff, 0x4447, 0x4444, 0xaa44, 0xa2aa, 0x0005, 0x0040, 0xae00, 0xe2aa, 0x4447, 0x4444, 0xfa44, 0xbfff, 0xaaad, 0xaaea, 0x56aa, 0xd555, 0x4447, 0x4444, 0xfa44, 0xbfef, 0x0005, 0x0040, 0x0e00, 0xe038, 0x4447, 0x4444, 0xea44, 0xadab, 0xaaad, 0xaaea, 0x0eaa, 0xe038, 0x4447, 0x4444, 0xea44, 0xadab, 0x0005, 0x0040, 0x0e00, 0xe038, 0x4447, 0x4444, 0xfa44, 0xbfef, 0xaaad, 0xaaea, 0x56aa, 0xd555, 0x4447, 0x4444, 0xfa44, 0xbfff, 0x0005, 0x0040, 0x0e00, 0xe000, 0x4447, 0x4444, 0x8a44, 0xafdf, 0xaaad, 0xaaea, 0xaeaa, 0xefdf, 0x4447, 0x4444, 0x0a44, 0xa000, 0x0005, 0x0040, 0x8e00, 0xefdf, 0x4447, 0x4444, 0xaa44, 0xafdf, 0xfffd, 0xffff, 0x0fff, 0xe000, 0x4447, 0x4444, 0x8a44, 0xafdf, 0x0005, 0x0040, 0xae00, 0xefdf, 0x4447, 0x4444, 0x0a44, 0xa000, 0xaaad, 0xaaea, 0x8eaa, 0xefdf, 0x4447, 0x4444, 0xaa44, 0xafdf, 0x0005, 0x0040, 0x0e00, 0xe000, 0x4447, 0x4444, 0xfa44, 0xbfff, 0xaaad, 0xaaea, 0x56aa, 0xd555, 0x4447, 0x4444, 0xfa44, 0xbfef, 0x0005, 0x0040, 0x0e00, 0xe038, 0x4447, 0x4444, 0xea44, 0xafab, 0xaaad, 0xaaea, 0x0eaa, 0xe038, 0x4447, 0x4444, 0x6a44, 0xafab, 0x0005, 0x0040, 0x0e00, 0xe038, 0x4447, 0x4444, 0x6a44, 0xafab, 0xaaad, 0xaaea, 0x0eaa, 0xe038, 0x4447, 0x4444, 0x6a44, 0xafab, 0x0005, 0x0040, 0x0e00, 0xe038, 0x4447, 0x4444, 0xfa44, 0xbfef, 0xfffd, 0xffff, 0x57ff, 0xd555, 0xaaab, 0xaaaa, 0xaaaa, 0xaaaa, 0xffff, 0xffff, 0xffff, 0xffff}; \Rogue\Monster\ else echo "will not over write ./xsplot/include/icon" fi if `test ! -s ./xsplot/include/arrows.h` then echo "writing ./xsplot/include/arrows.h" cat > ./xsplot/include/arrows.h << '\Rogue\Monster\' #define arr_width 19 #define arr_height 19 static short arrl_bits[] = { /* left arrow */ 0x0000, 0x0000, 0x0200, 0x0000, 0x0300, 0x0000, 0x0380, 0x0000, 0x03c0, 0x0000, 0x03e0, 0x0000, 0xfff0, 0x0003, 0xfff8, 0x0003, 0xfffc, 0x0003, 0xfffe, 0x0003, 0xfffc, 0x0003, 0xfff8, 0x0003, 0xfff0, 0x0003, 0x03e0, 0x0000, 0x03c0, 0x0000, 0x0380, 0x0000, 0x0300, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000}; static short arrl_mask_bits[] = { /* left arrow mask */ 0x0600, 0x0000, 0x0700, 0x0000, 0x0780, 0x0000, 0x07c0, 0x0000, 0x07e0, 0x0000, 0xfff0, 0x0007, 0xfff8, 0x0007, 0xfffc, 0x0007, 0xfffe, 0x0007, 0xffff, 0x0007, 0xfffe, 0x0007, 0xfffc, 0x0007, 0xfff8, 0x0007, 0xfff0, 0x0007, 0x07e0, 0x0000, 0x07c0, 0x0000, 0x0780, 0x0000, 0x0700, 0x0000, 0x0600, 0x0000}; static short arrr_bits[] = { /* right arrow */ 0x0000, 0x0000, 0x0200, 0x0000, 0x0600, 0x0000, 0x0e00, 0x0000, 0x1e00, 0x0000, 0x3e00, 0x0000, 0x7ffe, 0x0000, 0xfffe, 0x0000, 0xfffe, 0x0001, 0xfffe, 0x0003, 0xfffe, 0x0001, 0xfffe, 0x0000, 0x7ffe, 0x0000, 0x3e00, 0x0000, 0x1e00, 0x0000, 0x0e00, 0x0000, 0x0600, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000}; static short arrr_mask_bits[] = { /* right arrow mask */ 0x0300, 0x0000, 0x0700, 0x0000, 0x0f00, 0x0000, 0x1f00, 0x0000, 0x3f00, 0x0000, 0x7fff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0001, 0xffff, 0x0003, 0xffff, 0x0007, 0xffff, 0x0003, 0xffff, 0x0001, 0xffff, 0x0000, 0x7fff, 0x0000, 0x3f00, 0x0000, 0x1f00, 0x0000, 0x0f00, 0x0000, 0x0700, 0x0000, 0x0300, 0x0000}; static short arru_bits[] = { /* up arrow */ 0x0000, 0x0000, 0x0200, 0x0000, 0x0700, 0x0000, 0x0f80, 0x0000, 0x1fc0, 0x0000, 0x3fe0, 0x0000, 0x7ff0, 0x0000, 0xfff8, 0x0000, 0xfffc, 0x0001, 0xfffe, 0x0003, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x0000, 0x0000}; static short arru_mask_bits[] = { /* up arrow mask */ 0x0200, 0x0000, 0x0700, 0x0000, 0x0f80, 0x0000, 0x1fc0, 0x0000, 0x3fe0, 0x0000, 0x7ff0, 0x0000, 0xfff8, 0x0000, 0xfffc, 0x0001, 0xfffe, 0x0003, 0xffff, 0x0007, 0xffff, 0x0007, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000}; static short arrd_bits[] = { /* down arrow */ 0x0000, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0x1fc0, 0x0000, 0xfffe, 0x0003, 0xfffc, 0x0001, 0xfff8, 0x0000, 0x7ff0, 0x0000, 0x3fe0, 0x0000, 0x1fc0, 0x0000, 0x0f80, 0x0000, 0x0700, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000}; static short arrd_mask_bits[] = { /* down arrow mask */ 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0x3fe0, 0x0000, 0xffff, 0x0007, 0xffff, 0x0007, 0xfffe, 0x0003, 0xfffc, 0x0001, 0xfff8, 0x0000, 0x7ff0, 0x0000, 0x3fe0, 0x0000, 0x1fc0, 0x0000, 0x0f80, 0x0000, 0x0700, 0x0000, 0x0200, 0x0000}; \Rogue\Monster\ else echo "will not over write ./xsplot/include/arrows.h" fi if `test ! -s ./xsplot/include/titlebar.bm` then echo "writing ./xsplot/include/titlebar.bm" cat > ./xsplot/include/titlebar.bm << '\Rogue\Monster\' #define titlebar_width 80 #define titlebar_height 20 static short titlebar_bits[] = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x8fff, 0xffff, 0xffff, 0xffff, 0x07ff, 0xe7ff, 0xffff, 0xffff, 0xffff, 0xf3ff, 0xe7fe, 0xfbff, 0xffff, 0xffff, 0x63ff, 0xe7ff, 0xf9ff, 0xffff, 0xffff, 0xc779, 0xe627, 0xe0c1, 0xffff, 0xffff, 0x8fb2, 0xe4c3, 0xf99c, 0xffff, 0xffff, 0x1fc7, 0xe4e7, 0xf99c, 0xffff, 0xffff, 0x37cf, 0xe4e6, 0xf99c, 0xffff, 0xffff, 0x7b97, 0x64e6, 0xd99c, 0xffff, 0xffff, 0x713b, 0xa666, 0xe9cc, 0xffff, 0xffff, 0x067d, 0xc707, 0xf1e1, 0xffff, 0xffff, 0xffff, 0xffe7, 0xffff, 0xffff, 0xffff, 0xffff, 0xffe7, 0xffff, 0xffff, 0xffff, 0xffff, 0xffe7, 0xffff, 0xffff, 0xffff, 0xffff, 0xfff3, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; \Rogue\Monster\ else echo "will not over write ./xsplot/include/titlebar.bm" fi if `test ! -s ./xsplot/include/cursx` then echo "writing ./xsplot/include/cursx" cat > ./xsplot/include/cursx << '\Rogue\Monster\' #define cursx_width 9 #define cursx_height 9 #define cursx_x_hot 4 #define cursx_y_hot 4 static short cursx_bits[] = { 0x0000, 0x0082, 0x0044, 0x0028, 0x0000, 0x0028, 0x0044, 0x0082, 0x0000}; \Rogue\Monster\ else echo "will not over write ./xsplot/include/cursx" fi if `test ! -s ./xsplot/include/cursx.mask` then echo "writing ./xsplot/include/cursx.mask" cat > ./xsplot/include/cursx.mask << '\Rogue\Monster\' static short cursx_mask_bits[] = { 0x0183, 0x01c7, 0x00ee, 0x007c, 0x0038, 0x007c, 0x00ee, 0x01c7, 0x0183}; \Rogue\Monster\ else echo "will not over write ./xsplot/include/cursx.mask" fi if `test ! -s ./xsplot/include/xsplot.h` then echo "writing ./xsplot/include/xsplot.h" cat > ./xsplot/include/xsplot.h << '\Rogue\Monster\' /* * xsplot.h - #defines, global variables, data structures for xsplot * */ #define REVDATE "Rev: 6/2/87" /* other include files */ #include <stdio.h> #include <math.h> #include <ctype.h> #include <strings.h> #include <X/Xlib.h> /* constants (array sizes, mostly) */ #define MAXBUT 40 /* number of buttons in controls array */ #define MAXANAL 20 /* maximum number of analyses */ #define MAXPTS 1001 /* maximum number of points in an analysis */ #define MYPERANAL 8 /* maximum number of curves per analysis */ /* Scale Types */ #define LINEAR 0 #define LOG10 1 #define OCTAVE 2 /* Analysis Types */ #define DC 0 #define AC 1 #define TRANS 2 /* bizarrities */ #define DEGSTR "\007" /* a string containing the degree symbol (6x10 fnt)*/ #define MAXDSTR 58 /* max len of string in LoadDlog box */ /* grid size/position info */ #define GTop 1 /* grid size/position info */ #define GBottom 401 #define GLeft 1 #define GRight 401 #define GLRmid 201 #define GTBmid 201 #define GLeftFP 1.0 /* grid size/position info floats, */ #define GRightFP 401.0 /* used in scaling calculations */ #define GTopFP 1.0 #define GBottomFP 401.0 #define GTBmidFP 201.0 #define GLRmidFP 201.0 /* handy-dandy functions */ #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #define abs(a) ((a) < 0 ? -(a) : (a)) #define swap(a, b, t) {t=a; a=b; b=t;} /* patterns used for lines in MONO mode. Also used for grid */ #define PATSOLID 0xffff /* solid line */ #define PAT2 0xaaaa /* every other pixel on */ #define PAT4 0x8888 /* every fourth pixel on */ #define PATDASH 0xcccc /* two on, two off */ #define PATDASH4 0xf0f0 /* four on, four off */ #define PATDDASH 0xf6f6 /* four on, one off, two on, one off */ /* size constants used all over the place */ #define WIDTH 640 /* size of main window */ #define HEIGHT 480 #define GSIZE 400 /* size of grid window */ /* defines for setting up the control panels */ #define CBH 19 /* size of color buttons */ #define CBW 41 #define PANELH 15 /* minimum size of a panel */ #define BUTH (19+5) /* size of buttons + space between */ #define CTLX 430 #define CTLY 45 #define CTLW 200 #define CTLW2 97 #define PREX CTLX #define PREY CTLY #define PREW CTLW #define PREH (PANELH+BUTH) #define TRAX CTLX #define TRAY (PREY+PREH+5) #define TRAW CTLW #define TRAH (PANELH+BUTH) #define SCAX CTLX #define SCAY (TRAY+TRAH+5) #define SCAW CTLW2 #define SCAH (PANELH+2*BUTH) #define MSRX (CTLX+CTLW2+6) #define MSRY SCAY #define MSRW CTLW2 #define MSRH (PANELH+2*BUTH) #define OFFX CTLX #define OFFY (SCAY+SCAH+5) #define OFFW CTLW #define OFFH (PANELH+5*BUTH) #define MODX CTLX #define MODY (OFFY+OFFH+5) #define MODW CTLW2 #define MODH (PANELH+4*BUTH) #define MISX (CTLX+CTLW2+6) #define MISY MODY #define MISW CTLW2 #define MISH (PANELH+4*BUTH) /* structure definitions */ struct _button { Window win; short x,y; short w,h; char *st; int invert; FontInfo *finfo; }; typedef struct _button Button; struct _cbutton { Window win; }; typedef struct _cbutton CButton; struct _range { int power, multiplier; double val; char str[20]; }; typedef struct _range Range; struct _offset { double val; char str[20]; }; typedef struct _offset Offset; struct _anal { char title[80]; char labels[MYPERANAL+1][32]; int numys, numpts, type; }; typedef struct _anal Anal; struct _dlist { float dat[MAXPTS]; char label[32]; }; typedef struct _dlist Dlist; /* nasty ol' global variables */ #ifndef MAIN #define WHERE extern #else #define WHERE #endif /* X stuff */ WHERE Window mainW, iconW, titleW, gridW, presetW, traceW, scaleW; WHERE Window measureW, offsetW, modifyW, miscW, commandW, errW; WHERE Window dlogW, LoadDlog, SwitchDlog, CurvDlog, PlotDlog, HelpDlog; WHERE Window PlotNDlog, AboutDlog, diversW; WHERE Cursor arrow,noncurs,cursx; WHERE Pixmap titlePix,titlePixInv; WHERE Bitmap leftmask,rightmask,upmask,downmask; WHERE Font butfont,dlogfont; WHERE FontInfo *butfinfo,*dlogfinfo; WHERE int ForeColor, BackColor; WHERE Pattern linepats[4], GridPat2, GridPat4, RBoxPat[4]; WHERE Vertex curve[MAXPTS]; /* used for plotting data */ /* colors for color display */ WHERE int gridFcol, gridBcol, panFcol, panBcol, butFcol, butBcol; WHERE int mainFcol, mainBcol, dlgFcol, dlgBcol, errFcol, errBcol; WHERE int trcol[4]; WHERE Pixmap gridFpix, gridBpix, panFpix, panBpix, butFpix, butBpix; WHERE Pixmap mainFpix, mainBpix, dlgFpix, dlgBpix, errFpix, errBpix; WHERE Pixmap trpix[4]; /* Splot stuff */ WHERE Anal anals[MAXANAL]; WHERE Dlist xlist,ylist[4]; WHERE Range ranges[5]; WHERE Offset offsets[5]; WHERE Button butts[MAXBUT], dbutts[3], curvbutts[8]; WHERE CButton CButts[4]; WHERE int ind[4]; /* points from curve#(0-3) to dlist#(0-MYPERANAL) */ WHERE Anal *theAnal; /* points to anal[curanal] (current analysis) */ WHERE int LeftArr, RightArr, UpArr[4], DownArr[4]; WHERE int selCB, tbInvert, comUp, Vis159, R159[4]; WHERE int mono; WHERE long pid; WHERE char label[5][16], *units[5]; WHERE int L10Offset, L10Range, OctOffset, OctRange; WHERE int numy, xscal, yscal, ylock, NOPARSE, numpts, numanals, curanal; WHERE int dlscnt; WHERE char basfname[128], errstr[128], dlogstr[64]; /* global variables that need to be initialized */ #ifdef MAIN int mult [9]={1,2,5,10,20,50,100,200,500}; char *multstr[9]={"1","2","5","10","20","50","100","200","500"}; char *prefix [9]={" p"," n"," u"," m"," "," K"," M"," G"," T"}; char *scals [3]={"linear","log 10","log 2"}; char *SpTitle[3]={"DC TRANSFER","AC ANALYSIS","TRANSIENT ANALYSIS"}; #else extern int mult[9]; extern char *multstr[9], *prefix[9], *scals[3], *SpTitle[3]; #endif \Rogue\Monster\ else echo "will not over write ./xsplot/include/xsplot.h" fi if `test ! -s ./xsplot/sreg.out` then echo "writing ./xsplot/sreg.out" cat > ./xsplot/sreg.out << '\Rogue\Monster\' 1*******01/24/86 ******** SPICE 2G.6 3/15/83 ********06:25:07***** 0SHIFT 0**** INPUT LISTING TEMPERATURE = 27.000 DEG C 0*********************************************************************** .SUBCKT FLIP 1 2 9 11 10 13 14 XNAND1 4 8 7 GNAND XNAND2 6 4 5 NAND XGATE1 7 9 13 GATE XGATE2 7 6 14 GATE XINVR1 1 3 GINVR XINVR2 2 1 INVR XGATE3 3 4 14 GATE XGATE4 3 2 13 GATE XINVR3 12 11 INVR XNAND4 5 10 11 NAND XNAND5 8 12 10 NAND .ENDS FLIP .SUBCKT GINVR 2 3 MDRIVE 2 3 0 0 NMOSE L=4U W=16U VDD 1 0 5 MLOAD 1 2 2 0 NMOSD L=10U W=4U .ENDS GINVR .SUBCKT NAND 1 2 3 MDRIVE1 1 2 4 0 NMOSE L=4U W=16U MDRIVE2 4 3 0 0 NMOSE L=4U W=16U MLOAD 5 1 1 0 NMOSD L=10U W=4U VDD 5 0 5 .ENDS NAND .SUBCKT GNAND 1 2 3 MDRIVE1 1 2 4 0 NMOSE L=4U W=16U MDRIVE2 4 3 0 0 NMOSE L=4U W=32U MLOAD 5 1 1 0 NMOSD L=10U W=4U VDD 5 0 5 .ENDS GNAND .SUBCKT INVR 2 3 MDRIVE 2 3 0 0 NMOSE L=4U W=8U VDD 1 0 5 MLOAD 1 2 2 0 NMOSD L=10U W=4U .ENDS INVR .SUBCKT GATE 2 3 4 MPASS 2 4 3 0 NMOSE L=4U W=4U .ENDS GATE VCLK1 1 0 PULSE(0.2 5.0 0N 5N 5N 45N 100N) VCLK2 2 0 PULSE(5.0 0.2 0N 5N 5N 45N 100N) VSIN 3 0 PULSE(0.2 5.0 100N 5N 5N 95N 400N) VLD 4 0 0 VDIN 5 0 0 X1 6 7 3 5 4 1 2 FLIP X2 8 9 6 5 4 1 2 FLIP X3 10 11 8 5 4 1 2 FLIP .IC V(6)=0.2 V(7)=5 V(8)=0.2 V(9)=5 V(10)=0.2 V(11)=5 .TRAN 10N 500N .PRINT TRAN V(1) V(2) V(3) V(6) V(8) V(10) V(1) V(2) V(3) V(6) V(8) V(10) .OPTIONS NOMOD NOPAGE .MODEL NMOSE NMOS LEVEL=2.00000 LD=0.826296U TOX=544.000E-10 +NSUB=2.090161E+15 VTO=1.14181 KP=3.730740E-05 GAMMA=0.628861 +PHI=0.600000 UO=300.000 UEXP=1.001000E-03 UCRIT=1.000000E+06 +DELTA=1.15554 VMAX=100000. XJ=1.31233U LAMBDA=3.101167E-02 +NFS=1.902288E+12 NEFF=1.001000E-02 NSS=0.000000E+00 TPG=1.00000 +RSH=25.4 CGSO=1.6E-10 CGDO=1.6E-10 CGBO=1.7E-10 CJ=1.1E-4 +MJ=0.5 CJSW=5E-10 MJSW=0.33 .MODEL NMOSD NMOS LEVEL=2.00000 LD=1.01616U TOX=544.000E-10 +NSUB=1.000000E+16 VTO=-3.78687 KP=3.281897E-05 GAMMA=0.371508 +PHI=0.600000 UO=900.000 UEXP=1.001000E-03 UCRIT=804753. +DELTA=2.79525 VMAX=674713. XJ=0.600132U LAMBDA=1.000000E-06 +NFS=4.310000E+12 NEFF=1.001000E-02 NSS=0.000000E+00 TPG=1.00000 +RSH=25.4 CGSO=1.6E-10 CGDO=1.6E-10 CGBO=1.7E-10 CJ=1.1E-4 +MJ=0.5 CJSW=5E-10 MJSW=0.33 .END 0**** INITIAL TRANSIENT SOLUTION TEMPERATURE = 27.000 DEG C NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE NODE VOLTAGE ( 1) 0.2000 ( 2) 5.0000 ( 3) 0.2000 ( 4) 0. ( 5) 0. ( 6) 0.2001 ( 7) 5.0000 ( 8) 0.1999 ( 9) 5.0000 ( 10) 0.1999 ( 11) 5.0000 ( 12) 0.1558 ( 13) 5.0000 ( 14) 4.4777 ( 15) 4.9999 ( 16) 5.0000 ( 17) 0.1558 ( 18) 5.0000 ( 19) 4.9997 ( 20) 5.0000 ( 21) 0.1954 ( 22) 0.1954 ( 23) 5.0000 ( 24) 4.9127 ( 25) 5.0000 ( 26) 4.9997 ( 27) 5.0000 ( 28) 0.1954 ( 29) 0.1954 ( 30) 5.0000 ( 31) 4.9127 ( 32) 5.0000 ( 33) 0.0574 ( 34) 5.0000 ( 35) 0.0000 ( 36) 5.0000 ( 37) 5.0000 ( 38) 5.0000 ( 39) 5.0000 ( 40) 0.0885 ( 41) 5.0000 ( 42) 4.5516 ( 43) 5.0000 ( 44) 4.2754 ( 45) 5.0000 ( 46) 0.0962 ( 47) 5.0000 ( 48) 5.0000 ( 49) 5.0000 ( 50) 5.0000 ( 51) 0.0885 ( 52) 5.0000 ( 53) 4.5516 ( 54) 5.0000 ( 55) 4.2754 ( 56) 5.0000 ( 57) 0.0962 ( 58) 5.0000 ( 59) 5.0000 ( 60) 5.0000 ( 61) 5.0000 ( 62) 0.0885 ( 63) 5.0000 ( 64) 4.5516 ( 65) 5.0000 VOLTAGE SOURCE CURRENTS NAME CURRENT VCLK1 0. d+00 VCLK2 0. d+00 VSIN 3.393d-10 VLD 0. d+00 VDIN 0. d+00 VDD.XNA* -9.148d-05 VDD.XNA* -6.321d-09 VDD.XIN* -9.102d-05 VDD.XIN* -6.934d-12 VDD.XIN* -1.080d-09 VDD.XNA* -1.096d-09 VDD.XNA* -2.130d-09 VDD.XNA* -1.461d-08 VDD.XNA* -9.107d-05 VDD.XIN* -9.102d-05 VDD.XIN* -6.934d-12 VDD.XIN* -1.080d-09 VDD.XNA* -1.096d-09 VDD.XNA* -2.130d-09 VDD.XNA* -1.461d-08 VDD.XNA* -9.107d-05 VDD.XIN* -9.102d-05 VDD.XIN* -6.934d-12 VDD.XIN* -1.080d-09 VDD.XNA* -1.096d-09 VDD.XNA* -2.130d-09 TOTAL POWER DISSIPATION 2.73d-03 WATTS 0**** OPERATING POINT INFORMATION TEMPERATURE = 27.000 DEG C 0 0**** MOSFETS 0 MDRIVE1* MDRIVE2* MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* MPASS.X* MPASS.X* MDRIVE.* MLOAD.X* MDRIVE.* MLOAD.X* 0MODEL NMOSE NMOSE NMOSD NMOSE NMOSE NMOSD NMOSE NMOSE NMOSE NMOSD NMOSE NMOSD ID 9.15e-05 9.15e-05 9.15e-05 5.95e-09 5.94e-09 6.32e-09 3.41e-10 -3.50e-10 3.21e-09 9.10e-05 3.82e-09 1.93e-12 VGS 4.943 4.478 0. 0.156 5.000 0. 0. 0.000 0.156 0. 0.200 0. VDS 0.098 0.057 4.844 5.000 0.000 0.000 4.278 -0.522 0.200 4.800 5.000 0.000 VBS -0.057 0. -0.156 -0.000 0. -5.000 -0.200 -5.000 0. -0.200 0. -5.000 0 MPASS.X* MPASS.X* MDRIVE.* MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* MDRIVE1* MDRIVE2* 0MODEL NMOSE NMOSE NMOSE NMOSD NMOSE NMOSE NMOSD NMOSE NMOSE NMOSD NMOSE NMOSE ID 5.08e-10 -5.09e-10 1.06e-09 1.07e-09 1.08e-09 1.07e-09 1.09e-09 2.11e-09 2.10e-09 2.12e-09 1.46e-08 1.45e-08 VGS 4.844 -4.800 0. 0. -0.089 0. 0. 0.448 0. 0. 0.725 0.195 VDS 0.000 -4.844 5.000 0.000 4.911 0.089 0.000 0.448 4.552 0.000 0.724 4.275 VBS -0.156 -5.000 0. -5.000 -0.089 0. -5.000 -4.552 0. -5.000 -4.275 0. 0 MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* MPASS.X* MPASS.X* MDRIVE.* MLOAD.X* MDRIVE.* MLOAD.X* MPASS.X* MPASS.X* 0MODEL NMOSD NMOSE NMOSE NMOSD NMOSE NMOSE NMOSE NMOSD NMOSE NMOSD NMOSE NMOSE ID 1.46e-08 9.11e-05 9.11e-05 9.11e-05 -1.43e-11 1.39e-11 1.83e-04 9.10e-05 3.82e-09 1.93e-12 -1.17e-11 1.90e-12 VGS 0. 4.903 5.000 0. -0.000 4.805 4.913 0. 0.200 0. 0.000 -4.800 VDS 0.000 0.099 0.096 4.805 -0.005 0.000 0.200 4.800 5.000 0.000 -0.087 -0.087 VBS -5.000 -0.096 0. -0.195 -0.200 -0.195 0. -0.200 0. -5.000 -5.000 -5.000 0 MDRIVE.* MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* MDRIVE1* 0MODEL NMOSE NMOSD NMOSE NMOSE NMOSD NMOSE NMOSE NMOSD NMOSE NMOSE NMOSD NMOSE ID 1.06e-09 1.07e-09 1.08e-09 1.07e-09 1.09e-09 2.11e-09 2.10e-09 2.12e-09 1.46e-08 1.45e-08 1.46e-08 9.11e-05 VGS 0. 0. -0.089 0. 0. 0.448 0. 0. 0.725 0.195 0. 4.903 VDS 5.000 0.000 4.911 0.089 0.000 0.448 4.552 0.000 0.724 4.275 0.000 0.099 VBS 0. -5.000 -0.089 0. -5.000 -4.552 0. -5.000 -4.275 0. -5.000 -0.096 0 MDRIVE2* MLOAD.X* MPASS.X* MPASS.X* MDRIVE.* MLOAD.X* MDRIVE.* MLOAD.X* MPASS.X* MPASS.X* MDRIVE.* MLOAD.X* 0MODEL NMOSE NMOSD NMOSE NMOSE NMOSE NMOSD NMOSE NMOSD NMOSE NMOSE NMOSE NMOSD ID 9.10e-05 9.11e-05 -1.38e-11 1.31e-11 1.83e-04 9.10e-05 3.82e-09 1.93e-12 -1.17e-11 1.90e-12 1.06e-09 1.07e-09 VGS 5.000 0. 0.000 4.805 4.913 0. 0.200 0. 0.000 -4.800 0. 0. VDS 0.096 4.805 -0.005 0.000 0.200 4.800 5.000 0.000 -0.087 -0.087 5.000 0.000 VBS 0. -0.195 -0.200 -0.195 0. -0.200 0. -5.000 -5.000 -5.000 0. -5.000 0 MDRIVE1* MDRIVE2* MLOAD.X* MDRIVE1* MDRIVE2* MLOAD.X* 0MODEL NMOSE NMOSE NMOSD NMOSE NMOSE NMOSD ID 1.08e-09 1.07e-09 1.09e-09 2.11e-09 2.10e-09 2.12e-09 VGS -0.089 0. 0. 0.448 0. 0. VDS 4.911 0.089 0.000 0.448 4.552 0.000 VBS -0.089 0. -5.000 -4.552 0. -5.000 0**** TRANSIENT ANALYSIS TEMPERATURE = 27.000 DEG C TIME V(1) V(2) V(3) V(6) V(8) V(10) V(1) V(2) X 0. e+00 2.000e-01 5.000e+00 2.000e-01 2.001e-01 1.999e-01 1.999e-01 2.000e-01 5.000e+00 1.000e-08 5.000e+00 2.000e-01 2.000e-01 4.903e+00 1.006e-01 1.006e-01 5.000e+00 2.000e-01 2.000e-08 5.000e+00 2.000e-01 2.000e-01 4.987e+00 1.006e-01 1.006e-01 5.000e+00 2.000e-01 3.000e-08 5.000e+00 2.000e-01 2.000e-01 4.992e+00 1.006e-01 1.006e-01 5.000e+00 2.000e-01 4.000e-08 5.000e+00 2.000e-01 2.000e-01 4.995e+00 1.006e-01 1.006e-01 5.000e+00 2.000e-01 5.000e-08 5.000e+00 2.000e-01 2.000e-01 4.995e+00 1.006e-01 1.006e-01 5.000e+00 2.000e-01 6.000e-08 2.000e-01 5.000e+00 2.000e-01 1.651e-01 4.999e+00 1.006e-01 2.000e-01 5.000e+00 7.000e-08 2.000e-01 5.000e+00 2.000e-01 1.545e-01 5.000e+00 1.006e-01 2.000e-01 5.000e+00 8.000e-08 2.000e-01 5.000e+00 2.000e-01 1.502e-01 4.999e+00 1.006e-01 2.000e-01 5.000e+00 9.000e-08 2.000e-01 5.000e+00 2.000e-01 1.474e-01 5.000e+00 1.006e-01 2.000e-01 5.000e+00 1.000e-07 2.000e-01 5.000e+00 2.000e-01 1.455e-01 5.000e+00 1.006e-01 2.000e-01 5.000e+00 1.100e-07 5.000e+00 2.000e-01 5.000e+00 1.449e-01 4.900e+00 1.006e-01 5.000e+00 2.000e-01 1.200e-07 5.000e+00 2.000e-01 5.000e+00 1.431e-01 4.988e+00 1.006e-01 5.000e+00 2.000e-01 1.300e-07 5.000e+00 2.000e-01 5.000e+00 1.419e-01 4.992e+00 1.006e-01 5.000e+00 2.000e-01 1.400e-07 5.000e+00 2.000e-01 5.000e+00 1.407e-01 4.994e+00 1.006e-01 5.000e+00 2.000e-01 1.500e-07 5.000e+00 2.000e-01 5.000e+00 1.396e-01 4.996e+00 1.006e-01 5.000e+00 2.000e-01 1.600e-07 2.000e-01 5.000e+00 5.000e+00 5.001e+00 1.651e-01 5.001e+00 2.000e-01 5.000e+00 1.700e-07 2.000e-01 5.000e+00 5.000e+00 5.000e+00 1.545e-01 5.000e+00 2.000e-01 5.000e+00 1.800e-07 2.000e-01 5.000e+00 5.000e+00 5.000e+00 1.502e-01 5.000e+00 2.000e-01 5.000e+00 1.900e-07 2.000e-01 5.000e+00 5.000e+00 5.000e+00 1.474e-01 5.000e+00 2.000e-01 5.000e+00 2.000e-07 2.000e-01 5.000e+00 5.000e+00 5.000e+00 1.454e-01 5.000e+00 2.000e-01 5.000e+00 2.100e-07 5.000e+00 2.000e-01 2.000e-01 4.900e+00 1.448e-01 5.000e+00 5.000e+00 2.000e-01 2.200e-07 5.000e+00 2.000e-01 2.000e-01 4.987e+00 1.431e-01 5.000e+00 5.000e+00 2.000e-01 2.300e-07 5.000e+00 2.000e-01 2.000e-01 4.992e+00 1.416e-01 5.000e+00 5.000e+00 2.000e-01 2.400e-07 5.000e+00 2.000e-01 2.000e-01 4.994e+00 1.407e-01 5.000e+00 5.000e+00 2.000e-01 2.500e-07 5.000e+00 2.000e-01 2.000e-01 4.996e+00 1.396e-01 5.000e+00 5.000e+00 2.000e-01 2.600e-07 2.000e-01 5.000e+00 2.000e-01 1.655e-01 5.001e+00 1.655e-01 2.000e-01 5.000e+00 2.700e-07 2.000e-01 5.000e+00 2.000e-01 1.545e-01 5.000e+00 1.545e-01 2.000e-01 5.000e+00 2.800e-07 2.000e-01 5.000e+00 2.000e-01 1.501e-01 5.000e+00 1.501e-01 2.000e-01 5.000e+00 2.900e-07 2.000e-01 5.000e+00 2.000e-01 1.475e-01 5.000e+00 1.475e-01 2.000e-01 5.000e+00 3.000e-07 2.000e-01 5.000e+00 2.000e-01 1.455e-01 5.000e+00 1.455e-01 2.000e-01 5.000e+00 3.100e-07 5.000e+00 2.000e-01 2.000e-01 1.449e-01 4.902e+00 1.446e-01 5.000e+00 2.000e-01 3.200e-07 5.000e+00 2.000e-01 2.000e-01 1.431e-01 4.987e+00 1.430e-01 5.000e+00 2.000e-01 3.300e-07 5.000e+00 2.000e-01 2.000e-01 1.418e-01 4.992e+00 1.417e-01 5.000e+00 2.000e-01 3.400e-07 5.000e+00 2.000e-01 2.000e-01 1.408e-01 4.994e+00 1.406e-01 5.000e+00 2.000e-01 3.500e-07 5.000e+00 2.000e-01 2.000e-01 1.398e-01 4.996e+00 1.397e-01 5.000e+00 2.000e-01 3.600e-07 2.000e-01 5.000e+00 2.000e-01 1.394e-01 1.655e-01 5.000e+00 2.000e-01 5.000e+00 3.700e-07 2.000e-01 5.000e+00 2.000e-01 1.387e-01 1.544e-01 5.000e+00 2.000e-01 5.000e+00 3.800e-07 2.000e-01 5.000e+00 2.000e-01 1.380e-01 1.502e-01 5.000e+00 2.000e-01 5.000e+00 3.900e-07 2.000e-01 5.000e+00 2.000e-01 1.374e-01 1.474e-01 5.000e+00 2.000e-01 5.000e+00 4.000e-07 2.000e-01 5.000e+00 2.000e-01 1.369e-01 1.454e-01 5.000e+00 2.000e-01 5.000e+00 4.100e-07 5.000e+00 2.000e-01 2.000e-01 1.366e-01 1.444e-01 5.000e+00 5.000e+00 2.000e-01 4.200e-07 5.000e+00 2.000e-01 2.000e-01 1.361e-01 1.431e-01 5.000e+00 5.000e+00 2.000e-01 4.300e-07 5.000e+00 2.000e-01 2.000e-01 1.357e-01 1.418e-01 5.000e+00 5.000e+00 2.000e-01 4.400e-07 5.000e+00 2.000e-01 2.000e-01 1.352e-01 1.408e-01 5.000e+00 5.000e+00 2.000e-01 4.500e-07 5.000e+00 2.000e-01 2.000e-01 1.348e-01 1.397e-01 5.000e+00 5.000e+00 2.000e-01 4.600e-07 2.000e-01 5.000e+00 2.000e-01 1.346e-01 1.392e-01 1.649e-01 2.000e-01 5.000e+00 4.700e-07 2.000e-01 5.000e+00 2.000e-01 1.343e-01 1.384e-01 1.545e-01 2.000e-01 5.000e+00 4.800e-07 2.000e-01 5.000e+00 2.000e-01 1.339e-01 1.378e-01 1.502e-01 2.000e-01 5.000e+00 4.900e-07 2.000e-01 5.000e+00 2.000e-01 1.336e-01 1.372e-01 1.474e-01 2.000e-01 5.000e+00 5.000e-07 2.000e-01 5.000e+00 2.000e-01 1.332e-01 1.365e-01 1.453e-01 2.000e-01 5.000e+00 Y 0 JOB CONCLUDED 0 TOTAL JOB TIME 3309.52 \Rogue\Monster\ else echo "will not over write ./xsplot/sreg.out" fi echo "Finished archive 4 of 4" exit