PCB part 5 of 10
Andreas Nowatzyk
agn at cmu-cs-unh.ARPA
Sat Aug 10 13:15:34 AEST 1985
#
# type sh /usru0/agn/pcb/distr/../usenet/part5 to unpack this archive.
#
echo extracting pcif.c...
cat >pcif.c <<'!E!O!F!'
/***************************************************************\
* *
* PCB program *
* *
* CIF output routines *
* *
* (c) 1985 A. Nowatzyk *
* *
\***************************************************************/
#include <stdio.h>
#include "pparm.h"
#include "pcdst.h"
extern FILE *fwantread(), *fwantwrite();
extern int rot_m[4][4]; /* rotation matrix (in pplace) */
extern int pdr[8]; /* direction offsets (for ptrs) */
FILE *icf, *ocf; /* Cif - I/O */
#define pinsym 1 /* ordinary pin symbol */
#define viasym 2 /* via - symbol */
#define pwrsym 3 /* power plane connection */
#define gndsym 4 /* ground plane connection */
#define tlhsym 5 /* tool hole symbol */
#define sigsym 6 /* signal pin: no pwr/gnd conn. */
#define pn1sym 7 /* pin #1 marking */
#define algsym 8 /* alignment symbol */
/**********************************************************\
* *
* A note on coordinates: *
* internally: 1 unit = 100mil/rsun *
* CIF output: 1 unit = 0.5 mil for the main section *
* = 1 mil for the symbol definition *
* *
\**********************************************************/
#define almoff 32 /* offset for alignment marks */
#define ucf 25 /* unit conversion factor */
#define pgd 9 /* pin guard zone displacement */
#define cmww 100 /* crop mark wire width */
#define coww 40 /* component outline wire width */
#define gzww 400 /* guard zone wire width */
#define sgww0 16 /* signal wire width (near hole) */
#define sgww1 26 /* signal wire width (elsewhere) */
#define min_dst 16 /* min distance between wires */
#define cpsb 1000 /* base for component symbols > ex_cifH */
#define chhgh 128 /* character hight */
#define chwdf 4 /* character width factor */
#define clm_off 50 /* offset of clm-s to boarder */
#define max_wcp 7 /* max. wire coordinate pairs in a line */
/********************************************************************\
* *
* Some obsolete stuff: *
* dynamic labeling was used to generate the silk-screen lable for *
* a component based on its instantiation name. People prefered *
* the type definition name. *
* *
* Alignment marks are no longer required by mossis. *
* *
* (the code for tooling holes was entirely ripped out: external *
* cif symbols can do as well if required) *
* *
\********************************************************************/
/* #define dyna_lab */ /* dynamic labeling */
/* #define align_mrk */ /* alignment marks */
static int chdst[128][2]; /* character descriptor table */
cifout() /* output a cif file */
{
char buf[82];
int i, c1, c2, s, w, c;
printf ("Start writing CIF-file\n");
icf = fwantread (".", "/usr/agn/pcb/pcbsdef.CIF", buf,
"Symbol definition file:");
ocf = fwantwrite (".", "pcb.cif", buf, "CIF output file:", 1);
if (!ocf)
err("-NO CIF output file written", 0, 0, 0, 0);
c1 = c2 = 0;
for (i = 0; i < 128; ++i)
chdst[i][0] = (-1);
while (fgets (buf, 82, icf)) {
if (buf[0] == '%') {
switch (buf[1]) {
case 'c': /* character descriptor */
i = sscanf (&buf[2], "%d%d%d", &c, &w, &s);
if ((i != 3) || (c<=0) || (c>127) || (w<0) || (w>300)) {
printf ("Illegal character descriptor -- ignored\n");
break;
};
if (chdst[c][0] >= 0) {
printf (
"Multiple character descriptor (%d) -- ignored\n", c);
break;
};
chdst[c][0] = s;
chdst[c][1] = w * chwdf;
break;
case 's': /* insert component symbols */
if (c1)
err ("invalid pcbsdef.CIF - multiple %s", c1, 0, 0, 0);
c1 = 1;
ocps (); /* output component symbols */
break;
case 'p': /* insert PC-board symbol */
if (c2)
err ("invalid pcbsdef.CIF - multiple %p", c2, 0, 0, 0);
c2 = 1;
ofps (); /* output frame and components */
opgc (); /* output pwr / gnd connections */
osws (); /* output signal wires */
ohfs (); /* output hole 'fillet'-s */
oclm (); /* output cmpnt location marks */
clean_up (); /* remove temp. marks */
break;
default:
err ("invalid pcbsdef.CIF - unknown escape",
(int)buf[1] & 255, 0, 0, 0);
};
}
else
fputs (buf, ocf);
};
if (!c1 || !c2)
err ("invalid pcbsdef.CIF - missing %s or %p", c1, c2, 0, 0);
fclose (icf);
fclose (ocf);
}
ofps() /* output frame components */
{
int i;
#ifdef align_mrk
scall (-almoff, -almoff, algsym); /* alignment marks */
scall (V.BSX + almoff, -almoff, algsym);
scall (-almoff, V.BSY + almoff, algsym);
scall (V.BSX + almoff, V.BSY + almoff, algsym);
#endif
cmrk (-2, 18, -2, -2, 18, -2); /* crop - marks */
cmrk (V.BSX - 18, -2, V.BSX + 2, -2, V.BSX + 2, 18);
cmrk (V.BSX + 2, V.BSY - 18, V.BSX + 2, V.BSY + 2, V.BSX - 18, V.BSY + 2);
cmrk (18, V.BSY + 2, -2, V.BSY + 2, -2, V.BSY - 18);
fputs (" L PN2;\n", ocf); /* guard zone for inner layers */
cwire_S ( 0, 0, 0, 0, gzww);
cwire_C (V.BSX, 0, 0, 0);
cwire_C (V.BSX, V.BSY, 0, 0);
cwire_C ( 0, V.BSY, 0, 0);
cwire_E ( 0, 0, 0, 0);
fputs (" L PN3;\n", ocf);
cwire_S ( 0, 0, 0, 0, gzww);
cwire_C (V.BSX, 0, 0, 0);
cwire_C (V.BSX, V.BSY, 0, 0);
cwire_C ( 0, V.BSY, 0, 0);
cwire_E ( 0, 0, 0, 0);
for (i = 0; i < V.ncp; ++i) /* scan components to call sym */
if (strcmp (CP[i].name, DELETED))
dcp (&CP[i]);
}
ocps () /* output component symbols */
{
register int i, j, k, x, y;
int ext = 0;
register struct pin *pp;
char buf[inp_lnl], fname[80];
FILE *ex_cif;
for (j = 0; j < V.nty; ++j) {
if (!strcmp (TY[j].name, DELETED))
continue; /* skip deleted entries */
if (TY[j].cif) { /* skip external components */
ext = 1;
continue;
}
fprintf (ocf, "DS %d 1270 1;\n", j + cpsb);
pp = TY[j].p;
for (i = 0; i < TY[j].np; ++i) {
x = pp -> x;
y = pp -> y;
if (!i)
scall (x, y, pn1sym);
switch (pp -> p) {
case 0:
scall (x, y, pinsym);
break;
case 1:
scall (x, y, pinsym);
scall (x, y, gndsym);
break;
case 2:
case 3:
case 4:
scall (x, y, pinsym);
scall (x, y, pwrsym);
break;
default:
err ("illegal pin type", pp -> p, i, 0, 0);
};
pp++;
};
fputs (" L PSSC;\n", ocf); /* outline component */
cwire_S ( -3, -3, 0, 0, coww);
cwire_C (TY[j].x + 3, -3, 0, 0);
cwire_C (TY[j].x + 3, TY[j].y + 3, 0, 0);
cwire_C ( -3, TY[j].y + 3, 0, 0);
cwire_E ( -3, -3, 0, 0);
if (TY[j].y >= rsun * 3 && TY[j].x >= rsun * 3) /* add an IC mark */
fprintf (ocf, " B 200 200 -50 %d;\n", (TY[j].y >> 1) * ucf);
fputs (" L PF;\n", ocf);
cwire_S ( -3, -3, 0, 0, coww);
cwire_C (TY[j].x + 3, -3, 0, 0);
cwire_C (TY[j].x + 3, TY[j].y + 3, 0, 0);
cwire_C ( -3, TY[j].y + 3, 0, 0);
cwire_E ( -3, -3, 0, 0);
if (TY[j].y >= rsun * 3 && TY[j].x >= rsun * 3) /* add an IC mark */
fprintf (ocf, " B 200 200 -50 %d;\n", (TY[j].y >> 1) * ucf);
#ifndef dyna_lab
for (i = nmmax; i; i--) /* truncate string if necessary */
if ((k = txt_len (TY[j].name, i)) <= (TY[j].x + 4) * ucf)
break;
x = ((TY[j].x + 4) * ucf - k) / 2 - 2 * ucf;/* center text */
y = ((TY[j].y + 4) * ucf - chhgh) / 2 - 2 * ucf;
ctxt (x, y, 0, TY[j].name, i);
#endif
fputs ("DF;\n", ocf);
}
if (ext) { /* external components present */
printf ("List of external components:\n");
for (i = 0; i < V.nty; i++)
if (TY[i].cif)
printf ("\t'%s':\tcif-symbol#=%d\n",
TY[i].name, CIF[TY[i].cif-1].symn);
ex_cif = fwantread (".", "", fname, "External CIF-symbol file:");
if (!ex_cif)
err ("Could not open external CIF-symbol file", 0, 0, 0, 0);
while (fgets (buf, inp_lnl, ex_cif))
fputs (buf, ocf);
fclose (ex_cif);
}
}
dcp (C) /* call a component symbol */
struct comp *C;
{
static int rm[4][4] = { { 1, 1, 0, 1},
{-1, 1, 1, 0},
{-1, -1, 0, -1},
{ 1, -1, -1, 0} };
union ptr_int { /* allow arithmetic on pointer */
unsigned i;
struct type *ty;
} p1, p2;
register int i, r, x, y;
x = C -> x;
y = C -> y;
r = C -> r;
i = C -> ty -> cif;
if (i) /* external symbol */
i = CIF[i - 1].symn;
else { /* internal symbol */
p1.ty = C -> ty;
p2.ty = V.ty;
i = (p1.i - p2.i) / sizeof (TY[0]) + cpsb;
}
fprintf (ocf, "C %d R%d %d T%d %d;\n", i, rm[r][3], rm[r][2],
x * ucf, y * ucf);
#ifdef dyna_lab
i = (C -> ty -> y * ucf - chhgh) / 2;
ctxt (C -> x * ucf + i * rm[C -> r][0],
C -> y * ucf + i * rm[C -> r][1], C -> r, C -> name, nmmax);
#endif
}
ctxt (x, y, r, s, l) /* create text */
int x, y, r, l;
char *s;
{
while (*s && l--) {
*s &= 127;
if (chdst[*s][0] > 0) {
switch (r) {
case 1:
fprintf (ocf, "C %d R 0 1 T %d %d;\n",
chdst[*s][0], x, y);
y += chdst[*s][1];
break;
case 2:
fprintf (ocf, "C %d R -1 0 T %d %d;\n",
chdst[*s][0], x, y);
x -= chdst[*s][1];
break;
case 3:
fprintf (ocf, "C %d R 0 -1 T %d %d;\n",
chdst[*s][0], x, y);
y -= chdst[*s][1];
break;
default:
fprintf (ocf, "C %d T %d %d;\n",
chdst[*s][0], x, y);
x += chdst[*s][1];
break;
};
};
s++;
};
}
txt_len (s, l) /* text length function */
char *s;
int l;
{
register int i = 0;
while (*(s++) && l--)
i += chdst[*s & 127][1];
return i;
}
cmrk (x1, y1, x2, y2, x3, y3) /* crop mark */
int x1, y1, x2, y2, x3, y3;
{
fputs (" L PC1;\n", ocf);
cwire_S (x1, y1, 0, 0, cmww);
cwire_C (x2, y2, 0, 0);
cwire_E (x3, y3, 0, 0);
fputs (" L PC4;\n", ocf);
cwire_S (x1, y1, 0, 0, cmww);
cwire_C (x2, y2, 0, 0);
cwire_E (x3, y3, 0, 0);
fputs (" L PSSC;\n", ocf);
cwire_S (x1, y1, 0, 0, cmww);
cwire_C (x2, y2, 0, 0);
cwire_E (x3, y3, 0, 0);
fputs (" L PSMC;\n", ocf);
cwire_S (x1, y1, 0, 0, cmww);
cwire_C (x2, y2, 0, 0);
cwire_E (x3, y3, 0, 0);
fputs (" L PD;\n", ocf);
cwire_S (x1, y1, 0, 0, cmww);
cwire_C (x2, y2, 0, 0);
cwire_E (x3, y3, 0, 0);
fputs (" L PF;\n", ocf);
cwire_S (x1, y1, 0, 0, cmww);
cwire_C (x2, y2, 0, 0);
cwire_E (x3, y3, 0, 0);
}
scall (x, y, t) /* symbol call */
int x, y, t;
{
fprintf (ocf, "C %d T %d,%d;\n", t, x * ucf, y * ucf);
}
#ifdef simple /* simple wire routines */
osws () /* output signal wire stuff */
{
int i, chplt (), cvplt ();
wtvf = cvplt;
wthf = chplt;
for (i = 0; i < V.nnh; ++i) /* trace all nets */
if (NH[i].l > 1)
wtrace (NH[i].lp -> c -> x, NH[i].lp -> c -> y, vec);
}
#else
osws () /* output signal wire stuff */
{
int chplt (), cvplt (), mrk_hole (), umrk_hole ();
register int i, x, y;
for (i = 0; i < V.nnh; ++i) /* trace all nets */
if (NH[i].l > 1) {
wtvf = nil; /* mark all holes of this net */
wthf = mrk_hole;
x = NH[i].lp -> c -> x;
y = NH[i].lp -> c -> y;
wtrace (x, y, vec);
wtvf = cvplt; /* plot the net */
wthf = chplt;
wtrace (x, y, vec);
wtvf = nil; /* remove the hole marks */
wthf = umrk_hole;
wtrace (x, y, vec);
}
}
#endif
#ifdef simple /* simple wire routines */
cvplt (x1, y1, x2, y2) /* output a wire segment */
int x1, y1, x2, y2;
/******************************************************************\
* *
* Plot part of a signal wire from <x1,y1> to <x2,y2>. This draws *
* just a straight line on the desired side of the board. *
* *
\******************************************************************/
{
static int s = 0;
if (s != wtsb) { /* side check */
if (wtsb == s1b)
fputs (" L PC1;\n", ocf);
else
fputs (" L PC4;\n", ocf);
s = wtsb;
};
cwire_S (x1, y1, 0, 0, sgww1);
cwire_E (x2, y2, 0, 0);
}
#else /* conservative wire routine */
cvplt (x1, y1, x2, y2) /* output a wire segment */
int x1, y1, x2, y2;
/**********************************************************************\
* *
* A wire is drawn from <x1,y1> to <x2,y2> on the desired board side. *
* A minimal distance to holes is maintained. This calles for bends *
* in the wire path if it 1 raster unit apart from a hole. *
* *
\**********************************************************************/
{
register int i, j, t;
register char *p;
static int s = 0;
if (s != wtsb) { /* side check */
if (wtsb == s1b)
fputs (" L PC1;\n", ocf);
else
fputs (" L PC4;\n", ocf);
s = wtsb;
}
p = &pcb[(y1 + y2) >> 1][(x1 + x2) >> 1];
for (i = 0, j = 0; i < 8; i++) /* wide wire locator */
if (*(p + pdr[i]) & wtsb)
j++; /* count adjacent points */
if (j > 6)
wwb_trc ((x1 + x2) >> 1, (y1 + y2) >> 1, wtsb);
if ((y2 < y1) || ((y2 == y1) && (x2 < x1))) {
t = x1; /* direction confined 0 to 3 */
x1 = x2;
x2 = t;
t = y1;
y1 = y2;
y2 = t;
}
if (x2 > x1) {
if (y2 > y1)
plt_d1wire (x1, y1, x2, y2); /* dir = 1 */
else
plt_hwire (x1, y1, x2, y2);} /* dir = 0 */
else {
if (x2 < x1)
plt_d2wire (x1, y1, x2, y2); /* dir = 3 */
else
plt_vwire (x1, y1, x2, y2); /* dir = 2 */
}
}
plt_d1wire (x1, y1, x2, y2) /* plot diag. wire */
int x1, y1, x2, y2;
/***********************************************************\
* *
* Plot a diagonal wire from <x1,y1> to <x2,y2>. The slope *
* is dx = 1, dy = 1. *
* *
\***********************************************************/
{
register int enable, nh1, nh2;
nh1 = near_hl (x1, y1);
nh2 = near_hl (x2, y2);
enable = 3 <= (!nh1 + !nh2 + y2 - y1); /* attn: trick! */
switch (nh1) { /* check start point */
case 0:
if (enable)
cwire_S (x1, y1, 0, 0, sgww1);
else
cwire_S (x1, y1, 0, 0, sgww0);
break;
case 1:
cwire_S (x1, y1, 0, 1, sgww0);
if (enable) {
cwire_C (x1, y1, 1, 1);
cwire_E (x1 + 1, y1 + 1, 0, 0);
cwire_S (x1 + 1, y1 + 1, 0, 0, sgww1);}
else
cwire_C (x1, y1, 1, 1);
break;
case 4:
cwire_S (x1, y1, 1, 0, sgww0);
if (enable) {
cwire_C (x1, y1, 1, 1);
cwire_E (x1 + 1, y1 + 1, 0, 0);
cwire_S (x1 + 1, y1 + 1, 0, 0, sgww1);}
else
cwire_C (x1, y1, 1, 1);
break;
default:
err ("plt_d1wire: wire / hole collision", x1, y1, nh1, 0);
}
switch (nh2) {
case 0:
cwire_E (x2, y2, 0, 0);
break;
case 2:
if (enable) {
cwire_E (x2 - 1, y2 - 1, 0, 0);
cwire_S (x2 - 1, y2 - 1, 0, 0, sgww0);
}
cwire_C (x2, y2, -1, -1);
cwire_E (x2, y2, -1, 0);
break;
case 3:
if (enable) {
cwire_E (x2 - 1, y2 - 1, 0, 0);
cwire_S (x2 - 1, y2 - 1, 0, 0, sgww0);
}
cwire_C (x2, y2, -1, -1);
cwire_E (x2, y2, 0, -1);
break;
default:
err ("plt_d1wire: wire / hole intersection", x2, y2, nh2, 0);
}
}
plt_d2wire (x1, y1, x2, y2) /* plot diag. wire */
int x1, y1, x2, y2;
/***********************************************************\
* *
* Plot a diagonal wire from <x1,y1> to <x2,y2>. The slope *
* is dx = -1, dy = 1. *
* *
\***********************************************************/
{
register int enable, nh1, nh2;
nh1 = near_hl (x1, y1);
nh2 = near_hl (x2, y2);
enable = 3 <= (!nh1 + !nh2 + y2 - y1); /* attn: trick! */
switch (nh1) { /* check start point */
case 0:
if (enable)
cwire_S (x1, y1, 0, 0, sgww1);
else
cwire_S (x1, y1, 0, 0, sgww0);
break;
case 1:
cwire_S (x1, y1, 0, 1, sgww0);
if (enable) {
cwire_C (x1, y1, -1, 1);
cwire_E (x1 - 1, y1 + 1, 0, 0);
cwire_S (x1 - 1, y1 + 1, 0, 0, sgww1);}
else
cwire_C (x1, y1, -1, 1);
break;
case 2:
cwire_S (x1, y1, -1, 0, sgww0);
if (enable) {
cwire_C (x1, y1, -1, 1);
cwire_E (x1 - 1, y1 + 1, 0, 0);
cwire_S (x1 - 1, y1 + 1, 0, 0, sgww1);}
else
cwire_C (x1, y1, -1, 1);
break;
default:
err ("plt_d2wire: wire / hole collision", x1, y1, nh1, 0);
}
switch (nh2) { /* check end point */
case 0:
cwire_E (x2, y2, 0, 0);
break;
case 3:
if (enable) {
cwire_E (x2 + 1, y2 - 1, 0, 0);
cwire_S (x2 + 1, y2 - 1, 0, 0, sgww0);
}
cwire_C (x2, y2, 1, -1);
cwire_E (x2, y2, 0, -1);
break;
case 4:
if (enable) {
cwire_E (x2 + 1, y2 - 1, 0, 0);
cwire_S (x2 + 1, y2 - 1, 0, 0, sgww0);
}
cwire_C (x2, y2, 1, -1);
cwire_E (x2, y2, 1, 0);
break;
default:
err ("plt_d2wire: wire / hole intersection", x2, y2, nh2, 0);
}
}
plt_hwire (x1, y1, x2, y2) /* plot a horizontal wire */
int x1, y1, x2, y2;
/*************************************************************\
* *
* Draw a horizontal wire from <x1,y1> to <x2,y2>. The slope *
* is: dx = 1, dy = 0; *
* *
\*************************************************************/
{
register int dy, nh1, nh2, wide;
dy = 0; /* default displacement */
nh1 = near_hl (x1, y1);
nh2 = near_hl (x1 + 1, y1); /* look ahead */
switch (nh1) { /* check start point */
case 0:
if (!nh2) {
cwire_S (x1, y1, 0, 0, sgww1);
wide = 1;}
else {
cwire_S (x1, y1, 0, 0, sgww0);
wide = 0;
}
break;
case 1:
cwire_S (x1, y1, 0, 1, sgww0);
dy = 1;
wide = 0;
break;
case 3:
cwire_S (x1, y1, 0, -1, sgww0);
dy = -1;
wide = 0;
break;
case 4:
cwire_S (x1, y1, 1, 0, sgww0);
wide = 0;
break;
default:
err ("plt_hwire: wire / hole collision", x1, y1, nh1, 0);
}
while (++x1 < x2) { /* scan wire */
nh1 = nh2;
nh2 = near_hl (x1 + 1, y1);
switch (nh1) {
case 0:
if (!wide && !nh2) {
if (dy) { /* end any bend */
cwire_C (x1 - 1, y1, 0, dy);
dy = 0;
}
cwire_E (x1, y1, 0, 0);
cwire_S (x1, y1, 0, 0, sgww1);
wide = 1;}
else if (dy) {
cwire_C (x1 - 1, y1, 0, dy);
cwire_C (x1, y1, 0, 0);
dy = 0;
}
break;
case 1:
if (dy != 1) { /* start a bend up */
if (wide) {
cwire_E (x1 - 1, y1, 0, dy);
cwire_S (x1 - 1, y1, 0, dy, sgww0);
wide = 0;}
else
cwire_C (x1 - 1, y1, 0, dy);
cwire_C (x1, y1, 0, 1);
dy = 1;
}
break;
case 3:
if (dy != -1) { /* start a bend down */
if (wide) {
cwire_E (x1 - 1, y1, 0, dy);
cwire_S (x1 - 1, y1, 0, dy, sgww0);
wide = 0;}
else
cwire_C (x1 - 1, y1, 0, dy);
cwire_C (x1, y1, 0, -1);
dy = -1;
}
break;
default:
err ("plt_hwire: illegal wire/hole realtion", x1,y1, nh1, dy);
}
}
switch (nh2) { /* check end point */
case 0:
if (dy != 0) /* finish any bend */
cwire_C (x2 - 1, y2, 0, dy);
cwire_E (x2, y2, 0, 0);
break;
case 1:
if (dy != 1) { /* start an incomplete bend up */
if (wide) {
cwire_E (x1 - 1, y1, 0, dy);
cwire_S (x1 - 1, y1, 0, dy, sgww0);}
else
cwire_C (x1 - 1, y1, 0, dy);
}
cwire_E (x2, y2, 0, 1);
break;
case 2:
if (dy != 0) /* finish any bend */
cwire_C (x2 - 1, y2, 0, dy);
else if (wide) {
cwire_E (x2 - 1, y2, 0, 0);
cwire_S (x2 - 1, y2, 0, 0, sgww0);
}
cwire_E (x2, y2, -1, 0);
break;
case 3:
if (dy != -1) { /* start an incomplete bend down */
if (wide) {
cwire_E (x1 - 1, y1, 0, dy);
cwire_S (x1 - 1, y1, 0, dy, sgww0);}
else
cwire_C (x1 - 1, y1, 0, dy);
}
cwire_E (x2, y2, 0, -1);
break;
default:
err ("plt_hwire: trouble at end point", x2, y2, nh2, dy);
}
}
plt_vwire (x1, y1, x2, y2) /* plot a vertcal wire */
int x1, y1, x2, y2;
/**********************************************************\
* *
* Draw a vertcal wire from <x1,y1> to <x2,y2>. The slope *
* is: dx = 0, dy = 1; *
* *
\**********************************************************/
{
register int dx, nh1, nh2, wide;
dx = 0; /* default displacement */
nh1 = near_hl (x1, y1);
nh2 = near_hl (x1, y1 + 1); /* look ahead */
switch (nh1) { /* check start */
case 0:
if (!nh2) {
cwire_S (x1, y1, 0, 0, sgww1);
wide = 1;}
else {
cwire_S (x1, y1, 0, 0, sgww0);
wide = 0;
}
break;
case 1:
cwire_S (x1, y1, 0, 1, sgww0);
wide = 0;
break;
case 2:
cwire_S (x1, y1, -1, 0, sgww0);
dx = -1;
wide = 0;
break;
case 4:
cwire_S (x1, y1, 1, 0, sgww0);
dx = 1;
wide = 0;
break;
default:
err ("plt_vwire: wire / hole collision", x1, y1, nh1, dx);
}
while (++y1 < y2) { /* scan wire */
nh1 = nh2;
nh2 = near_hl (x1, y1 + 1);
switch (nh1) {
case 0:
if (!wide && !nh2) {
if (dx) { /* end any bend */
cwire_C (x1, y1 - 1, dx, 0);
dx = 0;
}
cwire_E (x1, y1, 0, 0);
cwire_S (x1, y1, 0, 0, sgww1);
wide = 1;}
else if (dx) { /* end any bend */
cwire_C (x1, y1 - 1, dx, 0);
cwire_C (x1, y1, 0, 0);
dx = 0;
}
break;
case 2:
if (dx != -1) { /* start a bend left */
if (wide) {
cwire_E (x1, y1 - 1, dx, 0);
cwire_S (x1, y1 - 1, dx, 0, sgww0);
wide = 0;}
else
cwire_C (x1, y1 - 1, dx, 0);
cwire_C (x1, y1, -1, 0);
dx = -1;
}
break;
case 4:
if (dx != 1) { /* start a bend right */
if (wide) {
cwire_E (x1, y1 - 1, dx, 0);
cwire_S (x1, y1 - 1, dx, 0, sgww0);
wide = 0;}
else
cwire_C (x1, y1 - 1, dx, 0);
cwire_C (x1, y1, 1, 0);
dx = 1;
}
break;
default:
err ("plt_vwire: illegal wire/hole realtion", x1,y1, nh1, dx);
}
}
switch (nh2) { /* check end point */
case 0:
if (dx != 0) /* finish any bend */
cwire_C (x2, y2 - 1, dx, 0);
cwire_E (x2, y2, 0, 0);
break;
case 2:
if (dx != -1) { /* start an incomplte bend left */
if (wide) {
cwire_E (x2, y2 - 1, dx, 0);
cwire_S (x2, y2 - 1, dx, 0, sgww0);}
else
cwire_C (x2, y2 - 1, dx, 0);
}
cwire_E (x2, y2, -1, 0);
break;
case 3:
if (dx != 0) /* finish any bend */
cwire_C (x2, y2 - 1, dx, 0);
else if (wide) {
cwire_E (x2 - 1, y2, 0, 0);
cwire_S (x2 - 1, y2, 0, 0, sgww0);
}
cwire_E (x2, y2, 0, -1);
break;
case 4:
if (dx != 1) { /* start an incomplete bend up */
if (wide) {
cwire_E (x2, y2 - 1, dx, 0);
cwire_S (x2, y2 - 1, dx, 0, sgww0);}
else
cwire_C (x2, y2 - 1, dx, 0);
}
cwire_E (x2, y2, 1, 0);
break;
default:
err ("plt_vwire: trouble at end point", x2, y2, nh2, dx);
}
}
on_hole (x, y) /* on hole check */
int x, y;
/**************************************************************\
* *
* Returns '1' if <x,y> is part of a hole that is not part *
* of the current net (unselected). It returns '0' otherwise. *
* This routine is not fooled by guard bits for via-holes. *
* *
\**************************************************************/
{
if (!(pcb[y][x] & ahb)) /* no hole at all */
return (0);
if (pcb[y][x - 1] & ahb) {
if (!(pcb[y][x + 1] & ahb)) {
x--;
if (!(pcb[y][x - 1] & ahb))
return (0);
}}
else {
x++;
if (!(pcb[y][x] & pcb[y][x + 1] & ahb))
return (0);
}
if (pcb[y - 1][x] & ahb) {
if (!(pcb[y + 1][x] & ahb)) {
y--;
if (!(pcb[y - 1][x] & ahb))
return (0);
}}
else {
y++;
if (!(pcb[y][x] & pcb[y + 1][x] & ahb))
return (0);
}
return (!(pcb[y][x] & selb)); /* test for selection */
}
near_hl (x, y) /* near hole test */
int x, y;
/*******************************************************************\
* *
* The relation of <x,y> to the nearest hole (if any) is reported. *
* if no hole is present, a 0 is returned. values returned (Hex): *
* *
* . . 1 1 1 . . *
* . . . . . . . *
* 2 . * * * . 4 *
* 2 . * * * . 4 *
* 2 . * * * . 4 *
* . . . . . . . *
* . . 3 3 3 . . *
* *
\*******************************************************************/
{ int i;
static int Rx[4] = { 0, 2, 0,-2};
static int Ry[4] = {-2, 0, 2, 0};
for (i = 0; i < 4; ++i) /* look for nearby hole */
if (on_hole (x + Rx[i], y + Ry[i]))
return (i + 1);
return (0); /* not near a hole */
}
mrk_hole (x, y) /* mark a hole */
int x, y;
{
pcb[y][x] |= selb;
return (0);
}
umrk_hole (x, y) /* mark a hole */
int x, y;
{
pcb[y][x] &= ~selb;
return (0);
}
#endif
chplt (x, y) /* output via holes */
int x, y;
{
if (pcb[y][x] & ishb)
scall (x, y, viasym);
return (0);
}
static int real_x, real_y, cnt; /* common to cwire_* */
cwire_S (x, y, dx, dy, w) /* start a CIF - wire */
int x, y, dx, dy, w;
/********************************************************************\
* *
* A CIF wire of width w is started at location <x,y>, which is *
* given in raster units. A displacement <dx,dy> is applied to this *
* location. *
* *
\********************************************************************/
{
fprintf (ocf, " W %d: %d,%d",
w, real_x = x * ucf + dx * pgd, real_y = y * ucf + dy * pgd);
cnt = 1;
}
cwire_C (x, y, dx, dy) /* continue a CIF - wire */
int x, y, dx, dy;
{ int rx, ry;
rx = x * ucf + dx * pgd;
ry = y * ucf + dy * pgd;
if (rx != real_x || ry != real_y) {
real_x = rx;
real_y = ry;
if (++cnt < max_wcp)
fprintf (ocf, " %d,%d", rx, ry);
else {
cnt = 0;
fprintf (ocf, "\n %d,%d", rx, ry);
}
}
}
cwire_E (x, y, dx, dy) /* and a CIF - wire */
int x, y, dx, dy;
{ int rx, ry;
rx = x * ucf + dx * pgd;
ry = y * ucf + dy * pgd;
if (rx != real_x || ry != real_y)
fprintf (ocf, " %d,%d;\n", rx, ry);
else
fprintf (ocf, ";\n");
}
opgc ()
/*******************************************************************\
* *
* Output power/ground connections: *
* *
* Connections to the internal layers (VCC,GND ...) can be made by *
* 2 different methods: *
* a) by defining a pin to be VCC/GND/VEE/VTT in the type file. *
* this is taken care off by the component symbol generation *
* in 'ocps'. *
* b) by connecting a pin to the special nets VCC/GND/VEE/VTT in *
* a given instantiation of the type: this is done here! *
* *
\*******************************************************************/
{
register int j, r, xp, yp;
int i, x, y;
register struct pin *pin;
struct hole *hp;
register struct nlhd *net;
struct hole *fndh ();
for (i = 0; i < V.ncp; i++) { /* scan all components */
if (!strcmp (CP[i].name, DELETED))
continue; /* skip deleted entries */
if (CP[i].ty -> cif)
continue; /* skip external cifs */
x = CP[i].x; /* get borad position */
y = CP[i].y;
r = CP[i].r;
for (j = CP[i].ty -> np, pin = CP[i].ty -> p; j; j--, pin++) {
/* scan component pins */
if (pin -> p)
continue; /* pwr/gnd is done in symbol def */
xp = x + (pin -> x) * rot_m[r][0] + (pin -> y) * rot_m[r][1];
yp = y + (pin -> x) * rot_m[r][2] + (pin -> y) * rot_m[r][3];
hp = fndh (xp, yp); /* find hole */
if (!hp)
err ("opgc: missing hole", xp, yp, 0, 0);
net = hp -> n -> nlp; /* insert proper symbols */
if (net == &V.GND)
scall (xp, yp, gndsym);
else if (net == &V.VCC || net == &V.VEE || net == &V.VTT)
scall (xp, yp, pwrsym);
else
scall (xp, yp, sigsym);
}
}
}
ohfs ()
/****************************************************************\
* *
* Hole 'fillet'-s: *
* In order to prevent demage to the board if components are *
* replaced, extra cooper is added to the area where a wire *
* enters a component hole. *
* *
\****************************************************************/
{
register int i, x, y;
fprintf (ocf, "L PC1;\n"); /* side 1 first */
for (i = 0; i < V.nch; i++)
if (pcb[CH[i].y][CH[i].x] & s1b) {
x = CH[i].x;
y = CH[i].y;
fillet (x, y, s1b);
}
fprintf (ocf, "L PC4;\n"); /* now side 2 */
for (i = 0; i < V.nch; i++)
if (pcb[CH[i].y][CH[i].x] & s2b) {
x = CH[i].x;
y = CH[i].y;
fillet (x, y, s2b);
}
}
/* geometric constraints for fillet round-flash */
#define r0 72 /* = (ucf*sqrt(2^2 + 4^2) - min_dst - via_hole_radius) * 2 */
#define r1 42 /* = (ucf*2 - (sgww1/2 + min_dst)) * 2 */
#define r2 54 /* = (sqrt((ucf*2)^2 + ucf^2) - (sgww1/2 + min_dst)) * 2 */
#define r3 83 /* = (sqrt(2)*ucf*2 - (sgww1/2 + min_dst)) * 2 */
fillet (x, y, s) /* draw a 'fillet' */
int x, y, s;
{
static int pdx[16] = {2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1,0,1,2,2};
static int pdy[16] = {0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1};
static int msk[8] = { 0x8003, 0x001f, 0x0038, 0x01f0,
0x0380, 0x1f00, 0x3800, 0xf001 };
static int d[16] = {r1,r2,r3,r2,r1,r2,r3,r2,r1,r2,r3,r2,r1,r2,r3,r2};
register int xx, yy, j, k, l, r;
int i;
for (i = 0; i < 16; i++) { /* scan potential candidates */
xx = x + pdx[i];
yy = y + pdy[i];
if (pcb[yy][xx] & s) { /* found a wire */
r = r0; /* default radius */
j = 0; /* reset search mask */
for (k = 0; k < 8; k++) {
l = pcb[yy + dr[k][1]][xx + dr[k][0]];
if (l & ishb)
r = r1;
if (l & (chb | s) && !(l & ishb))
j |= msk[k];
}
for (k = 0; k < 16; k++) { /* find max legal radius */
if (j & (1 << k))
continue; /* skip this point */
if (pcb[yy + pdy[k]][xx + pdx[k]] & (ahb | s)) {
if (r > d[k])
r = d[k];
}
}
fprintf (ocf, "R %d %d %d;\n", r, xx * ucf, yy * ucf);
}
}
}
oclm () /* output component location marks */
{
register int i, j, k, l, dis;
char buf[10];
dis = 5 * rsun; /* distance to next mark */
dis /= 2;
buf[1] = 0;
for (i = dis, j = 1, k = 0; i < V.BSX - 2 * rsun; i += dis) {
if (j) { /* character time */
j = 0;
buf[0] = 'A' + k++;
l = i * ucf - txt_len (buf, 2) / 2;
ctxt (l, clm_off, 0, buf, 2);
ctxt (l, V.BSY * ucf - chhgh - clm_off, 0, buf, 2);}
else {
fputs ("L PSSC;\n", ocf);
cwire_S (i, 2, 0, 0, coww);
cwire_E (i, 5, 0, 0);
cwire_S (i, V.BSY - 2, 0, 0, coww);
cwire_E (i, V.BSY - 5, 0, 0);
fputs ("L PF;\n", ocf);
cwire_S (i, 2, 0, 0, coww);
cwire_E (i, 5, 0, 0);
cwire_S (i, V.BSY - 2, 0, 0, coww);
cwire_E (i, V.BSY - 5, 0, 0);
j = 1;
}
}
for (i = dis, j = 1, k = 0; i < V.BSY - 2 * rsun; i += dis) {
if (j) { /* character time */
j = 0;
sprintf (buf, "%d", ++k);
l = i * ucf - txt_len (buf, 2) / 2;
ctxt (clm_off + chhgh, l, 1, buf, 10);
ctxt (V.BSX * ucf - clm_off, l, 1, buf, 10);}
else {
fputs ("L PSSC;\n", ocf);
cwire_S (2, i, 0, 0, coww);
cwire_E (5, i, 0, 0);
cwire_S (V.BSX - 2, i, 0, 0, coww);
cwire_E (V.BSX - 5, i, 0, 0);
fputs ("L PF;\n", ocf);
cwire_S (2, i, 0, 0, coww);
cwire_E (5, i, 0, 0);
cwire_S (V.BSX - 2, i, 0, 0, coww);
cwire_E (V.BSX - 5, i, 0, 0);
j = 1;
}
}
}
clean_up () /* remove the marks for wide wire traces */
{
register int i, j, ss;
register char *p;
ss = ~(selb | resb); /* bits to be cleared */
for (i = 0; i < V.BSY; i++) {
p = &pcb[i][0];
for (j = V.BSY; j; j--)
*p++ &= ss;
}
}
wwb_trc (x, y, s) /* wide wire boarder trace */
int x, y, s;
/**********************************************************************\
* *
* Wide wires tend to have a rough boarder because 'wtrace' may scan *
* the wide wire un-parallel to its main direction. So 'wwb_trc' *
* scans the boarder and produce a wire that smoothes this roughness. *
* *
\**********************************************************************/
{
register int ss = ~(s | ahb), i, j, k;
register char *p, *ps;
p = &pcb[y][x];
while (*(p + 1) & ~ss) p++; /* find boarder */
if (!(*p & ~ss) || *p & resb)
return; /* trouble || already done: exit */
for (i = 1; i < 8; i++) /* find initial direction */
if (*(p + pdr[i]) & ~ss)
break;
ps = p; /* remember start point */
do {
*p |= resb; /* mark point */
p += pdr[i]; /* move to next point */
for (j = (i + 6) & 7, k = 7; k; k--, j = (j + 1) & 7)
if (!(*(p + pdr[(j + 7) & 7]) & ~ss) && *(p + pdr[j]) & ~ss)
break; /* find new direction */
if (i != j) { /* change in direction */
cvplt (((int) ps - (int) pcb) % xmax,
((int) ps - (int) pcb) / xmax,
((int) p - (int) pcb) % xmax,
((int) p - (int) pcb) / xmax );
ps = p;
i = j;
}
} while (!(*p & resb));
}
!E!O!F!
#
# type sh /usru0/agn/pcb/distr/../usenet/part5 to unpack this archive.
#
echo extracting pcmdl.c...
cat >pcmdl.c <<'!E!O!F!'
/***************************************************************\
* *
* PCB program *
* *
* Command loop section *
* *
* (c) 1985 A. Nowatzyk *
* *
\***************************************************************/
#include "pparm.h"
#include "pcdst.h"
#define iniCNTX 0 /* initial context */
#define nretry 2 /* retry limit for N_route */
int mv_wind(), zoom_in(), zoom_out(), s_menu(), c_menu();
int st_learn(), learn_sl(), learn_ov(), learn_ex(), lrn_wmv();
int w_zoomi(), w_zoomo(), wnd_urc(), wnd_llc(), exc_adel (), sel_adel();
int w_wmv(), ini_adel(), ini_art(), sel_art(), exc_art();
extern int net_sel(), /* manual edit functions */
net_desel(), m_delete(), mr_delete(),
start_nt(), cont_s1(), cont_s2();
extern int exc_cmv(), cmv_plc(), cmv_rr(), cmv_rl(), cmv_sel();
extern int CPp_ini(), CPp_exc(), CPp_plc(), CPp_del();
extern int exc_plow(), plow_ini(), plow_src(), plow_dst();
static struct cntxdsc { /* context descriptrors */
char *name; /* context name */
int (*entcntx)(); /* enter context function */
int (*excntx)(); /* exit context function */
int (*mkfunc[8])(); /* mouse key functions */
} CNTX[] = {
{"Start", net_sel, net_desel,
start_nt, mv_wind, start_nt, m_delete,
zoom_in, s_menu, zoom_out, c_menu },
{"Route", 0, net_desel,
cont_s1, mv_wind, cont_s2, mr_delete,
zoom_in, s_menu, zoom_out, c_menu },
{"Edit", 0, 0,
0, mv_wind, 0, m_delete,
zoom_in, s_menu, zoom_out, c_menu },
{"Learn", st_learn, 0,
learn_sl, lrn_wmv, learn_ex, learn_ov,
0, 0, 0, 0 },
{"AR-Del", ini_adel, 0,
wnd_urc, w_wmv, wnd_llc, exc_adel,
w_zoomi, sel_adel, w_zoomo, sel_adel },
{"A-route", ini_art, 0,
wnd_urc, w_wmv, wnd_llc, exc_art,
w_zoomi, sel_art, w_zoomo, sel_art },
{"CP_move", 0, 0,
cmv_sel, mv_wind, cmv_plc, exc_cmv,
zoom_in, cmv_rl, zoom_out, cmv_rr },
{"Trace_mv", plow_ini, 0,
plow_src, mv_wind, plow_dst, exc_plow,
zoom_in, 0, zoom_out, c_menu },
{"CP_place",CPp_ini, 0,
CPp_exc, mv_wind, CPp_plc, CPp_del,
zoom_in, s_menu, zoom_out, cmv_rr } };
cmd_loop() /* command loop */
{
int nxtc, x, y, i;
static int context = iniCNTX;
do { /* context loop */
if (CNTX[context].entcntx) {/* call enter function if present */
nxtc = (*CNTX[context].entcntx) (context);
if (nxtc != context) {/* context was rejected */
context = nxtc;
continue;
}
}
cntx_msg (CNTX[context].name);
do { /* loop within context */
i = getcur (&x, &y);
unprev (); /* reset pending previews */
err_msg (""); /* clear pending error messages */
if (i < 0)
err ("couldn't read graphic tablet", i, 0, 0, 0);
nxtc = context; /* default */
if (CNTX[context].mkfunc[i])
nxtc = (*CNTX[context].mkfunc[i]) (x, y, context);
else
err_msg ("undefined key");
} while (nxtc == context);
if (CNTX[context].excntx)/* call exit function if present */
(*CNTX[context].excntx) (nxtc);
context = nxtc;
} while (context >= 0);
}
mv_wind (x, y, ctx) /* move window */
int x, y, ctx;
{
window (x - 256 / cz, y - 256 / cz);
return (ctx); /* don't change context */
}
/*ARGSUSED*/
zoom_in (x, y, ctx) /* increase zoom */
int x, y, ctx;
{
if (cz < 16)
zoom (cz + 1);
return (ctx); /* don't change context */
}
/*ARGSUSED*/
zoom_out (x, y, ctx) /* decrease zoom */
int x, y, ctx;
{
if (cz > 1)
zoom (cz - 1);
return (ctx); /* don't change context */
}
quit () /* quit session */
{
static char *mtext[] = {
"Continue quit: no save",
"Abort quit" };
if (!menu (mtext, 2))
finish ();
}
/*ARGSUSED*/
s_menu (x, y, ctx) /* start menu */
int x, y, ctx;
{
static char *mtext[] = {
"Plot preview",
"CIF - Output",
"Exit",
"Quit (no save)",
"Diagnostics",
"Learn sequence",
"Area Delete",
"Area Route",
"Route sequence",
"Save Work",
"Change color",
"Move Component",
"Expand wire"
};
switch (menu (mtext, 13)) {
case 0:
Ferr_msg ("Busy: Plotting Bitmap");
pntbm ();
err_msg ("Done");
beep ();
break;
case 1:
Ferr_msg ("Busy: Writing CIF file");
cifout ();
err_msg ("Done");
beep ();
break;
case 2:
Ferr_msg ("Saving Bitmap & exit");
save (0);
finish ();
break;
case 3:
quit ();
break;
case 4:
p_diagn ();
break;
case 5:
return (LEARN);
case 6:
return (ADELE);
case 7:
return (AROUTE);
case 8:
seq_rt ();
return (net_sel (START));
case 9:
Ferr_msg ("Busy: saving Bitmap");
save (0);
beep ();
err_msg ("Done");
break;
case 10:
chg_color ();
break;
case 11:
return (CMOVE);
case 12:
return wide_wire (ctx);
}
return (ctx);
}
/*ARGSUSED*/
c_menu (x, y, ctx) /* configuration menu */
int x, y, ctx;
{
static char *mtext[] = {
0, /* beep toggle */
0, /* window toggle */
0, /* H-route toggle */
0, /* straight toggle */
"learn off",
"Route Parameters",
"Print statistics",
"Wire desity",
"Congestion area",
"List",
"Update"
};
/* update toggles */
mtext[0] = (no_beep) ? "Beep on" : "Beep off";
mtext[1] = (no_adjw) ? "Adjust window" : "Stable window";
mtext[2] = (no_hrout) ? "Enable H-route" : "Disable H-route";
mtext[3] = (st_reroute) ? "Move straight" : "Reroute straight";
switch (menu (mtext, 11)) {
case 0:
no_beep = (no_beep) ? 0 : 1;
break;
case 1:
no_adjw = (no_adjw) ? 0 : 1;
break;
case 2:
no_hrout = (no_hrout) ? 0 : 1;
break;
case 3:
st_reroute = (st_reroute) ? 0 : 1;
break;
case 4:
flush_lb ();
break;
case 5:
Ferr_msg("See your Terminal");
get_rtprm ();
break;
case 6:
pgen_stat ();
break;
case 7:
dis_pro ();
break;
case 8:
dis_cc ();
break;
case 9:
P_list ();
break;
case 10:
return P_update (ctx);
}
return (ctx);
}
static int ov_on = 0; /* over-view display is on */
view_on () /* display a wire over-view */
{
int i, xl, yl, xh, yh, x0, y0, x1, y1;
struct nlst *p1, *p2;
if (ov_on)
view_off ();
xl = wx; /* get visible area */
xh = wx + 511 / cz;
yl = wy;
yh = wy + 482 / cz;
msg_off ();
color (resb, resb);
for (i = 0; i < V.nnh; ++i) /* scan through nets */
if (!NH[i].f) { /* only unfinished nets */
p1 = NH[i].lp;
while (p1) {
x0 = p1 -> c -> x;
y0 = p1 -> c -> y;
if (x0 < xh && x0 > xl && y0 < yh && y0 > yl) {
p2 = p1 -> n;
while (p2) {/* display full lines */
x1 = p2 -> c -> x;
y1 = p2 -> c -> y;
if (x0 < xh && x0 > xl && y0 < yh && y0 > yl)
aed_plt (x0, y0, x1, y1);
p2 = p2 -> n;
}
p2 = NH[i].lp;
while (p2) {/* display of-screen lines */
x1 = p2 -> c -> x;
y1 = p2 -> c -> y;
if (x0 >= xh || x0 <= xl || y0 >= yh || y0 <= yl)
aed_plt (x0, y0, x1, y1);
p2 = p2 -> n;
}
}
p1 = p1 -> n;
}
}
ov_on = 1;
}
view_off () /* turn off over view */
{
if (ov_on) {
color (0, resb);
rect (wx, wy, wx + 511 / cz, wy + 482 / cz);
msg_on ();
}
ov_on = 0;
}
static int lrn_cnt = 0; /* learn counter */
static int lrnfull = 0; /* max. number of valid entries */
static struct nlhd *lrn_buf[lrn_max]; /* learn buffer */
/*ARGSUSED*/
st_learn (x, y, ctx) /* start learn mode */
int x, y, ctx;
{
lrn_cnt = 0;
lrnfull = 0;
return (LEARN);
}
learn_sl (x, y, ctx) /* select a wire */
int x, y, ctx;
{
struct nlhd *p, *loc(), *fly();
int i;
if (lrn_cnt >= lrn_max) {
view_off ();
err_msg ("Learn buffer full");
beep ();
return (START);
}
p = loc (&x, &y);
if (!p)
p = fly (&x, &y);
if (!p) {
msg_on ();
err_msg ("No net at cursor location");
beep ();
return (ctx);
}
if (p -> f) {
msg_on ();
err_msg ("Net is already done");
return (ctx);
}
for (i = 0; i < lrn_cnt; ++i)
if (p == lrn_buf[i]) {
msg_on ();
err_msg ("Net already selected");
beep ();
return (ctx);
}
lrn_buf[lrn_cnt++] = p;
lrnfull = lrn_cnt;
return (ctx);
}
lrn_wmv (x, y, ctx) /* learn: move window */
int x, y, ctx;
{
if (ov_on)
view_off ();
return (mv_wind (x, y, ctx));
}
/*ARGSUSED*/
learn_ex (x, y, ctx) /* learn: exit */
int x, y, ctx;
{
if (ov_on)
view_off ();
return (START);
}
/*ARGSUSED*/
learn_ov (x, y, ctx) /* over-view on */
int x, y, ctx;
{
if (!ov_on)
view_on ();
return (ctx);
}
flush_lb () /* flush learn buffer */
{
lrn_cnt = 0;
lrnfull = 0;
}
struct nlhd *ck_lrnb () /* check learn buffer */
{
while (lrn_cnt > 0 && lrn_buf[lrn_cnt - 1] -> f)
lrn_cnt--; /* skip finished nets */
if (lrn_cnt <= 0)
return (nil); /* is empty */
return (lrn_buf[--lrn_cnt]);
}
seq_rt () /* sequence route */
{
struct nlhd *t, *ck_lrnb ();
lrn_cnt = lrnfull; /* rewind learn buffer */
if (lrn_cnt <= 0)
err_msg ("Learn a sequence first");
else {
Ferr_msg ("Busy routing");
while ((t = ck_lrnb ())) {
N_route (t, nretry, 0, 0, V.BSX, V.BSY);
nettgo -= t -> f;
}
nets_msg (nettgo);
err_msg ("Done");
beep ();
}
}
!E!O!F!
#
# type sh /usru0/agn/pcb/distr/../usenet/part5 to unpack this archive.
#
echo extracting pdiag.c...
cat >pdiag.c <<'!E!O!F!'
/***************************************************************\
* *
* PCB program *
* *
* Diagnostic routines *
* *
* (c) 1985 A. Nowatzyk *
* *
\***************************************************************/
#include "pparm.h"
#include "pcdst.h"
test(x,y)
int x, y;
{
int i, j;
printf ("Test at x=%d y=%d\n", x, y);
for (i = y + 3; i >= y - 3; --i) {
printf ("\t%d: ", i);
for (j = -4; j <= 4; j++) {
if (i == y)
switch (j) {
case 0: printf(">"); break;
case 1: printf("<"); break;
default: printf(" "); break;
}
else printf(" ");
printf("%2x",pcb[i][x + j] & 255);
}
printf ("\n");
}
abm_tst (x, y);
}
s_test(x,y,x1,y1,s)
int x, y, x1, y1;
char *s;
{
int i, j;
char c;
printf ("Test at x=%d y=%d (..)=%s\n", x, y,s);
for (i = y + 3; i >= y - 3; --i) {
printf (" %d: ", i);
for (j = -4; j <= 4; j++) {
c = ' ';
if (i == y1 && x + j == x1)
c = '(';
if (i == y1 && x + j == x1 + 1)
c = ')';
if (i == y && !j)
c = (c != ' ') ? '*' : '>';
if (i == y && j == 1)
c = (c != ' ') ? '*' : '<';
printf("%c%2x",c, pcb[i][x + j] & 255);
}
if(i == y1 && (x + j) == (x1+1))
printf(")");
printf ("\n");
}
abm_tst (x, y);
}
tst1 ()
{
int x, y, sccm, sccc;
sccm = ccm;
sccc = ccc;
getcur (&x, &y);
test (x, y);
ccc = sccc;
ccm = sccm;
}
tst2 (x1, y1, x2, y2, c)
int x1, y1, x2, y2, c;
{
int x, y;
for (x = x1; x <= x2; ++x)
for (y = y1; y <= y2; ++y)
pcb[y][x] = c;
}
verify () /* verify connectivity */
{
int i, j;
for (nettgo = i = 0; i < V.nnh; ++i) {
if (NH[i].l > 0) {
j = cchk (&NH[i]);
if (j != NH[i].f) {
printf ("Net %d: f=%d cchk=%d\n", i, NH[i].f, j);
NH[i].f = j;
}
nettgo += !NH[i].f;}
else
printf ("Net %d is emty\n", i);
}
printf ("Done\n");
}
p_diagn () /* diagnostic menu */
{
static char *mtext[] = {
"View",
"Verify",
"Clean",
"Flip"};
switch (menu (mtext, 4)) {
case 0:
tst1 ();
break;
case 1:
verify ();
break;
case 2:
clean ();
break;
case 3:
flip_s();
break;
}
}
clean () /* scan bitmap for wrong bits */
{
register int i, j;
struct nlhd *t;
t = V.cnet;
if (t)
deseln (t);
color (resb, resb);
for (i = 0; i < V.BSX; i++)
for (j = 0; j < V.BSY; j++)
if (pcb[j][i] & 0xa0) {
point (i, j);
pcb[j][i] &= 0x5f;
};
window (0, 0);
update (0, 0, 511, 511);
fx = fy = 0;
if (t)
selnet (t);
}
flip_s () /* flip sides */
{
register int i, j, k;
for (i = 0; i < V.BSX; i++)
for (j = 0; j < V.BSY; j++) {
k = pcb[j][i];
pcb[j][i] = (k & ~vec) | ((k & s2b) >> 1) | ((k & s1b) << 1);}
update (0, 0, 511, 511);
fx = fy = 0;
window (0, 0);
}
qpat()
{
TY[81].p = &PN[V.npn];
PN[V.npn + 0].x = 0;
PN[V.npn + 0].y = 0;
PN[V.npn + 0].p = 0;
PN[V.npn + 1].x = 0;
PN[V.npn + 1].y = 12;
PN[V.npn + 1].p = 0;
PN[V.npn + 2].x = 0;
PN[V.npn + 2].y = 24;
PN[V.npn + 2].p = 0;
PN[V.npn + 3].x = 12;
PN[V.npn + 3].y = 24;
PN[V.npn + 3].p = 0;
PN[V.npn + 4].x = 12;
PN[V.npn + 4].y = 12;
PN[V.npn + 4].p = 0;
PN[V.npn + 5].x = 12;
PN[V.npn + 5].y = 0;
PN[V.npn + 5].p = 0;
V.npn += 6;
}
!E!O!F!
#
# type sh /usru0/agn/pcb/distr/../usenet/part5 to unpack this archive.
#
echo extracting pfio.c...
cat >pfio.c <<'!E!O!F!'
/***************************************************************\
* *
* PCB program *
* *
* File I/O section *
* *
* (c) 1985 A. Nowatzyk *
* *
\***************************************************************/
#include <stdio.h>
#include "pparm.h"
#include "pcdst.h"
FILE *inp; /* read/write channels */
extern FILE *fwantread();
extern int rot_m[4][4]; /* rotation matrix */
extern wantread(), wantwrite();
char *getstr();
float scalef; /* sacle factor */
static inp_errs = 0; /* input errors */
rdnl () /* read a netlist */
{
register int i, j;
if (getbool ("Do you want to read a checkpoint file?",1))
rsto ();
else {
specs (); /* promt for board specifications*/
rdty (); /* read types */
rdcp (); /* read components */
rdnh (); /* read net list */
if (inp_errs)
err ("-Please correct earlier errors and try again", 0, 0, 0, 0);
}
for (j = 0, i = 0; i < V.nnh; i++)
j += !NH[i].f;
nettgo = j;
nets_msg (nettgo);
}
rdty () /* read the type definition file */
{
char buf[inp_lnl], nm[nmmax + 2], ga[nmmax + 2];
char fname[40];
int i, j, k, ix, iy;
float x, y, x1, y1;
static char pln[4][4] = {"GND", "VCC", "VEE", "VBB"};
inp = fwantread (".", "test.ty", fname, "Type definition file:");
if (!inp)
err("-Failed to read type definition file", 0, 0, 0, 0);
fgets (buf, inp_lnl, inp);
if (strncmp (buf, "*types:", 7))
err ("-Type-def file doesn't start with '*types:'", 0, 0, 0, 0);
i = 1;
while (fgets (buf, inp_lnl, inp)) {
rms (buf);
i++; /* count lines for error msg */
if (V.nty >= tymax)
err ("type table too small - increase 'tymax'", V.nty, i, 0, 0);
for (j = 0; (j < nmmax) && (buf[j] != ':'); j++)
TY[V.nty].name[j] = buf[j];
if (buf[j] == ':') {
if (buf[j + 1] != '\0')
printf ("Line %d: warning: garbage ignored\n", i);
TY[V.nty].name[j] = '\0'; }
else
if (buf[j + 1] != ':')
printf ("Line %d: warning: missing ':'\n", i);
for (j = 0; j < V.nty; j++) /* kind of slow, but ... */
if (!strncmp (TY[V.nty].name, TY[j].name, nmmax))
break;
if (j < V.nty) {
printf ("Line %d: error: '%s' is already defined\n",
i, TY[V.nty].name);
inp_errs = 1;
}
TY[V.nty].x = 0;
TY[V.nty].y = 0;
TY[V.nty].np = 0;
TY[V.nty].cif = 0;
TY[V.nty].p = nil;
while (fgets (buf, inp_lnl, inp)) { /* read type body */
rms (buf);
i++; /* count lines */
if (!strncmp (buf, "EXTCIF: ", 8)) { /*** EXTCIF ***/
j = sscanf (&buf[8], "%d", &k);
if (j != 1 || k < ex_cifL || k > ex_cifH || TY[V.nty].cif) {
printf ("Line %d: illegal 'EXTcif'\n", i);
inp_errs = 1;}
else {
if (V.ncif >= cifmax)
err ("EXTcif table too small: increase 'cifmax'",
V.ncif, i, 0, 0);
CIF[V.ncif].symn = k;
CIF[V.ncif].flg = 0;
CIF[V.ncif].blk = 0;
TY[V.nty].cif = V.ncif + 1;
}}
else if (!strncmp (buf, "BOX: ", 5)) { /*** BOX ***/
j = sscanf (&buf[5], "%f %f", &x, &y);
if (j != 2 || x < 0 || y < 0) {
printf ("Line %d: invalid 'Box' statement\n", i);
inp_errs = 1;}
else {
ix = x * rsun * scalef + 0.5;
iy = y * rsun * scalef + 0.5;
if (TY[V.nty].x < ix)
TY[V.nty].x = ix;
if (TY[V.nty].y < iy)
TY[V.nty].y = iy;
}}
else if (!strncmp (buf, "BLOCK: ", 7)) { /*** BLOCK ***/
j = sscanf (&buf[7], "%f %f %f %f", &x, &y, &x1, &y1);
ix = x1 * rsun * scalef + 0.5;
iy = y1 * rsun * scalef + 0.5;
if (j != 4 || x < 0 || x1 < 0 || y < 0 || y1 < 0 ||
x > x1 || y > y1 || !TY[V.nty].cif ||
ix > TY[V.nty].x || iy > TY[V.nty].y) {
printf ("Line %d: invalid 'Block' statement\n", i);
inp_errs = 1;}
else {
if (CIF[V.ncif].blk) { /* need additional record */
CIF[V.ncif].flg = 1;
if (V.ncif >= cifmax)
err ("EXTcif table too small: increase 'cifmax'",
V.ncif, i, 0, 0);
CIF[++V.ncif].flg = 0;
CIF[V.ncif].symn = CIF[V.ncif - 1].symn;
}
CIF[V.ncif].blk = 1;
CIF[V.ncif].xh = ix;
CIF[V.ncif].yh = iy;
CIF[V.ncif].xl = x * rsun * scalef + 0.5;
CIF[V.ncif].yl = y * rsun * scalef + 0.5;
}}
else { /*** normal pin statement ***/
j = sscanf (buf, "%f %f %s %s", &x, &y, nm, ga);
if (buf[0] == '\0')
break; /* exit */
k = 0; /* default type */
switch (j) {
case 1:
printf ("Line %d: warning: missing y - line ignored\n",i);
break;
case 4:
printf ("Line %d: warning: grabage '%s...' ignored\n", i, ga);
case 3:
for (k = 0; k < 4; ++k)
if (!strncmp (pln[k], nm, nmmax))
break;
k = (k + 1) % 5;
case 2:
if (V.npn >= pnmax)
err ("pin table too small - increase 'pnmax'", V.npn, 0, 0, 0);
if (TY[V.nty].p == nil)
TY[V.nty].p = &PN[V.npn];
(TY[V.nty].np)++;
ix = x * rsun * scalef + 0.5;
iy = y * rsun * scalef + 0.5;
if (TY[V.nty].x < ix)
TY[V.nty].x = ix;
if (TY[V.nty].y < iy)
TY[V.nty].y = iy;
PN[V.npn].x = ix;
PN[V.npn].y = iy;
PN[V.npn].p = k;
V.npn++;
}
}
}
if (TY[V.nty].y > TY[V.nty].x)
printf ("Warning for '%s': y>x (text is aligned to the x-axis)\n",
TY[V.nty].name);
if (TY[V.nty].cif)
V.ncif++;
V.nty++;
}
fclose (inp);
printf("Type file: %d types with a total of %d pins defined\n",
V.nty, V.npn);
}
rms (b)
char *b;
/******************************************************************\
* *
* remove stuff: *
* The character string <b> is reformatted: *
* 1. [a-z] -> [A-Z] *
* 2. Comment are removed *
* 3. Multiple field seperators (' ', '\t' and ',') are removed *
* 4. Field seperators will become ' ' *
* 5. Field seperators before '\0' are removed *
* 6. Fileds are truncated to 'nmmax' characters *
* *
\******************************************************************/
{
register int i, j, k, s;
s = 1;
for (i = j = k = 0; i < inp_lnl; ++i) {
if (('a' <= b[i]) && ('z' >= b[i]))
b[i] -= 'a' - 'A'; /* case folding */
switch (b[i]) {
case ' ':
case '\t': /* single tab or space separator */
if (!s)
b[j++] = ' ';
s = 1;
k = 0;
break;
case ';': /* ignor comments */
case '\n':
case '\0':
j -= s && j; /* remove seperators at EOL */
b[j] = '\0';
i = inp_lnl;
break;
case ',':
b[j++] = ' ';
s = 1;
k = 0;
break;
default:
if (k > nmmax) {
b[j++] = ' ';
k = 0;}
else {
s = 0;
b[j++] = b[i];
k++;}
break;
}
}
}
rdcp() /* read component file */
{
char buf[inp_lnl], t[nmmax + 2];
float x, y;
register int i, j, k, ix, iy;
int r;
inp = fwantread (".", "test.cp", buf, "Component definition file:");
if (!inp)
err("-Failed to read component definition file", 0, 0, 0, 0);
fgets (buf, inp_lnl, inp);
if (strncmp (buf, "*components:", 12))
err ("component-def file doesn't start with '*components:'", 0, 0, 0, 0);
j = 1;
while (fgets (buf, inp_lnl, inp)) {
rms (buf);
j++; /* count lines */
if (V.ncp >= cpmax)
err ("Component table too small: increase 'cpmax'", V.ncp, j,0,0);
k = sscanf (buf, "%s %s %f %f %d", CP[V.ncp].name, t, &x, &y, &r);
if (k != 5 && k != 2) { /*** argument check ***/
printf ("Line %d error: invalid argumnet count\n", j);
inp_errs = 1;
continue;
}
for (i = 0; i < V.ncp; i++) /*** multi-def check ***/
if (!strncmp (CP[i].name, CP[V.ncp].name, nmmax))
break;
if (i < V.ncp) {
printf ("Line %d error: multiple defined '%s'\n",
j, CP[V.ncp].name);
inp_errs = 1;
continue;
}
for (i = 0; i < V.nty; i++) /*** get type ***/
if (!strncmp (t, TY[i].name, nmmax))
break;
if (i >= V.nty) {
printf ("Line %d error: undefined Type '%s'\n", j, t);
inp_errs = 1;
continue;
}
CP[V.ncp].ty = &TY[i];
CP[V.ncp].unplaced = 1; /* not yet placed */
if (V.nch + TY[i].np > chmax)
err ("Hole table too small, increase 'chmax'\n", chmax, j, 0, 0);
for (i = TY[i].np; i;) { /* allocate holes */
CH[V.nch].x = 0;
CH[V.nch].y = 0;
CH[V.nch].pn = --i;
CH[V.nch].cpi = V.ncp;
CH[V.nch++].n = nil;
}
if (5 == k) { /* explicily placed component */
if ((r < 0) || (r > 3)) {
printf ("Line %d error: invalid rotation - line ignored\n",j);
inp_errs = 1;
continue;
}
ix = rsun * x * scalef + 0.5;
iy = rsun * y * scalef + 0.5;
if (!C_place (&CP[V.ncp], ix, iy, r))
printf ("Line %d warning: invalid location, place it later\n", j);
}
V.ncp++;
}
CH_update (); /* sort holes */
fclose (inp);
printf ("Component file: %d components with %d pins allocated\n",
V.ncp, V.nch);
}
rdnh() /* read net list */
{
char buf[inp_lnl];
register int i, j;
int k;
register int mode = 0; /* =0 Multiwire, =1 DP */
register struct nlhd *hptr;
inp = fwantread (".", "test.nl", buf, "Net list file:");
if (!inp)
err ("-Failed to read Net list file", 0, 0, 0, 0);
fgets (buf, inp_lnl, inp);
if (strncmp (buf, "Cnetlist:", 9) &&
(mode = 1, strncmp (buf, "DPnetlist:", 10)))
err ("-component-def file doesn't start with 'C/DPnetlist:'",
0, 0, 0, 0);
i = 1;
while (fgets (buf, inp_lnl, inp)) {
rms (buf);
i++;
if (mode) {
/*******************************************************************\
* *
* DP netlist reader *
* *
* Warning: I am too tired to completly rewrite the reader now, so *
* there is the limitation that a net has to fit into the *
* line buffer (buf). *
* *
\*******************************************************************/
for (j = 0; buf[j] && buf[j] != '\\'; j++);
if (j && !buf[j]) {
printf ("Line %d error: DP-name without '\\'\n", i);
inp_errs = 1;
continue;
}
if (!j)
continue; /* skip empty lines */
if (buf[0] == '!') {/* power net (gnd, vcc, vee, vtt) */
if (!strncmp ("GND", &buf[1], 3))
hptr = &V.GND;
else if (!strncmp ("VCC", &buf[1], 3))
hptr = &V.VCC;
else if (!strncmp ("VTT", &buf[1], 3))
hptr = &V.VTT;
else if (!strncmp ("VEE", &buf[1], 3))
hptr = &V.VEE;
else {
printf ("Line %d error: unknown power net\n");
inp_errs = 1;
continue;
}}
else { /* normal net */
if (V.nnh >= nhmax)
err ("Netlist table too small - increase 'nhmax'",
V.nnh, 0, 0, 0);
buf[j] = 0;
strncpy (NH[V.nnh].name, buf, nmmax);
NH[V.nnh].l = 0;
NH[V.nnh].lp = nil;
NH[V.nnh].x1 = xmax;
NH[V.nnh].y1 = ymax;
NH[V.nnh].x2 = 0;
NH[V.nnh].y2 = 0;
NH[V.nnh].f = 0;
hptr = &NH[V.nnh];
V.nnh++;
}
for (j++; (j < inp_lnl) && (buf[j] != '\0'); ++j)
if (buf[j] == ' ')
addn (&buf[j + 1], hptr, i);
continue; /* next net */
}
if (buf[0] == 'C') { /* Multiwire net list processing */
j = 3;
if (!strncmp ("GND", &buf[1], 3))
hptr = &V.GND;
else if (!strncmp ("VCC", &buf[1], 3))
hptr = &V.VCC;
else if (!strncmp ("VTT", &buf[1], 3))
hptr = &V.VTT;
else if (!strncmp ("VEE", &buf[1], 3))
hptr = &V.VEE;
else
continue; /* normal comment */
} else {
if (!sscanf (buf, "%d", &k)) {
printf ("Line %d error: invalid net number\n", i);
inp_errs = 1;
continue;}
else if (k == -1) /* Multiwire end ? */
break;
else if ((k < V.nnh) || (k <= 0)) {
printf ("Line %d error: net number %d out of sequence\n",
i, k);
inp_errs = 1;
continue;}
else {
if (k > V.nnh + 1)
printf("Line %d warning: net %d missing, next is %d\n",
i, V.nnh + 1, k);
while (k > V.nnh) {/* start a new net list */
if (V.nnh >= nhmax)
err ("Netlist table too small - increase 'nhmax'",
V.nnh, 0, 0, 0);
sprintf (NH[V.nnh].name, "#%d", V.nnh + 1);
NH[V.nnh].l = 0;
NH[V.nnh].lp = nil;
NH[V.nnh].x1 = xmax;
NH[V.nnh].y1 = ymax;
NH[V.nnh].x2 = 0;
NH[V.nnh].y2 = 0;
NH[V.nnh].f = 0;
hptr = &NH[V.nnh];
V.nnh++;
}
}
j = 0;
}
for (j++; (j < inp_lnl) && (buf[j] != '\0'); ++j)
if (buf[j] == ' ')
addn (&buf[j + 1], hptr, i);
}
fclose (inp);
printf ("Netlist: %d nets with %d nodes allocated\n", V.nnh, V.nnl);
}
addn(s,net,ln) /* add a node to a net list */
char s[];
struct nlhd *net;
int ln;
{
int k, x1, y1;
register int i, j, l, r, x, y;
struct hole *hp, *fndh ();
for (i = 0; s[i] != '-'; ++i) /* isolate component name */
if ((s[i] == '\0') || (i > nmmax)) {
printf ("Line %d error: missing pin number\n", ln);
inp_errs = 1;
return;
}
s[i] = '\0'; /* terminate string temporarily */
for (j = 0; j < V.ncp; j++) /* find componet definition */
if (!strncmp (s, CP[j].name, nmmax))
break;
if (j >= V.ncp) {
printf ("Line %d error: reference to undefined component\n", ln);
inp_errs = 1;
return;
}
if ((!sscanf (&s[i + 1], "%d", &k)) || (k <= 0) || (k > CP[j].ty -> np)) {
printf("Line %d error: '%s-%d': pin-number out of range\n", ln, s, k);
inp_errs = 1;
return;
} /* check pin number */
--k; /* pin number must start at 0 */
if ((CP[j].ty -> p + k) -> p)
printf ("Line %d warning: '%s-%d' is a power/gnd pin\n", ln, s, k+1);
s[i] = '*'; /* this is a hack */
if (CP[j].unplaced) { /* need direct search */
hp = nil;
for (l = 0; l < V.nch; l++)
if (CH[j].cpi == j && CH[j].pn == k) {
hp = &CH[l];
break;
}
} else {
x = (CP[j].ty -> p + k) -> x; /* locate hole entry in CH */
y = (CP[j].ty -> p + k) -> y;
r = CP[j].r;
x1 = CP[j].x + rot_m[r][0] * x + rot_m[r][1] * y;
y1 = CP[j].y + rot_m[r][2] * x + rot_m[r][3] * y;
hp = fndh (x1, y1);
}
if (hp == nil)
err ("addn: failed to find hole", x1, y1, j, i);
if (hp -> n != nil) { /* multiple net node ?? */
printf ("Line %d error: '%s-%d' already used in other net\n",
ln, s, k + 1);
inp_errs = 1;
return;
}
if (V.nnl >= nlmax)
err ("net node table too small - increase 'nlmax'", V.nnl, 0, 0, 0);
NL[V.nnl].c = hp; /* enter node to tables */
NL[V.nnl].n = net -> lp;
NL[V.nnl].nlp = net;
hp -> n = net -> lp = &NL[V.nnl];
net -> l++;
V.nnl++;
}
struct hole *fndh (x,y) /* find hole */
int x, y;
{
register int i, j, k, xx = x, yy = y;
i = 0;
j = V.nch;
while (i <= j) {
k = (i + j) >> 1;
if (xx > CH[k].x) {
i = k + 1;
continue; }
if (xx < CH[k].x) {
j = k - 1;
continue; }
if (yy > CH[k].y) {
i = k + 1;
continue; }
if (yy < CH[k].y) {
j = k - 1;
continue; }
return &CH[k];
}
return nil;
}
save (ety) /* save vital data structure */
int ety;
{
int i, och;
char fn[30];
static char fname[2][8] = { "pcb.SAV", "pcb.ERR"};
struct {int r, g, b;} crc; /* color record */
och = wantwrite (".", &fname[ety][0], fn, "Checkpoint file name:", 0);
write (och, &V, sizeof (V)); /* write head information */
for (i = 0; i < ymax; ++i)
write (och, &pcb[i][0], xmax);
for (i = 0; i < V.ncp; ++i)
write (och, &CP[i], sizeof (CP[0]));
for (i = 0; i < V.nty; ++i)
write (och, &TY[i], sizeof (TY[0]));
for (i = 0; i < V.npn; ++i)
write (och, &PN[i], sizeof (PN[0]));
for (i = 0; i < V.nch; ++i)
write (och, &CH[i], sizeof (CH[0]));
for (i = 0; i < V.nnh; ++i)
write (och, &NH[i], sizeof (NH[0]));
for (i = 0; i < V.nnl; ++i)
write (och, &NL[i], sizeof (NL[0]));
for (i = 0; i < ncolors; ++i) {
crc.r = Color_tab[i].r;
crc.g = Color_tab[i].g;
crc.b = Color_tab[i].b;
write (och, &crc, sizeof (crc));
}
for (i = 0; i < V.ncif; ++i)
write (och, &CIF[i], sizeof (struct cif));
i = mgnm; /* mark the end of the grabage */
write (och, &i, sizeof (int));
close (och);
}
rsto() /* Restore Checkpointed state */
{
int i, ich, old;
char fn[30];
struct {int r, g, b;} crc; /* color record */
ich = wantread (".", "pcb.SAV", fn, "Checkpoint file name:");
read (ich, &V, sizeof (V)); /* read head information */
old = 0;
if (V.pver != pversion) {
if (V.pver == 123) /* conversion V 1.23 -> current */
old = 1;
else
err ("-program version mismatch", V.pver, pversion, 0, 0);
}
if (V.errtxt[0] != '\0') {
printf ("Warning: previous pcb run died with error message:\n");
printf ("\t\"%s\"\n", V.errtxt);
printf (" error-info: %d %d %d %d\n",
V.err_info[0], V.err_info[1], V.err_info[2], V.err_info[3]);
V.errtxt[0] = '\0';
}
if ((V.x != xmax) || (V.y != ymax))
err ("-different bit map size", V.x, V.y, xmax, ymax);
if (V.ncp > cpmax)
err ("-CP table too small - increase 'cpmax'", V.ncp, cpmax, 0, 0);
if (V.nty > tymax)
err ("-TY table too small - increase 'tymax'", V.nty, tymax, 0, 0);
if (V.npn > pnmax)
err ("-PN table too small - increase 'pnmax'", V.npn, pnmax, 0, 0);
if (V.nch > chmax)
err ("-CH table too small - increase 'chmax'", V.nch, chmax, 0, 0);
if (V.nnh > nhmax)
err ("-NH table too small - increase 'nhmax'", V.nnh, nhmax, 0, 0);
if (V.nnl > nlmax)
err ("-NL table too small - increase 'nlmax'", V.nnl, nlmax, 0, 0);
if (V.ncif > cifmax)
err ("-CIF table too small - increase 'cifmax'", V.ncif, cifmax,0, 0);
for (i = 0; i < ymax; ++i)
read (ich, &pcb[i][0], xmax);
for (i = 0; i < V.ncp; ++i)
read (ich, &CP[i], sizeof (CP[0]));
for (i = 0; i < V.nty; ++i)
read (ich, &TY[i], sizeof (TY[0]));
for (i = 0; i < V.npn; ++i)
read (ich, &PN[i], sizeof (PN[0]));
for (i = 0; i < V.nch; ++i)
read (ich, &CH[i], sizeof (CH[0]));
for (i = 0; i < V.nnh; ++i)
read (ich, &NH[i], sizeof (NH[0]));
for (i = 0; i < V.nnl; ++i)
read (ich, &NL[i], sizeof (NL[0]));
for (i = 0; i < ncolors; i++) {
read (ich, &crc, sizeof (crc));
Color_tab[i].r = crc.r;
Color_tab[i].g = crc.g;
Color_tab[i].b = crc.b;
}
for (i = 0; i < V.ncif; ++i)
read (ich, &CIF[i], sizeof (struct cif));
read (ich, &i, sizeof (int)); /* consistency check */
if (i != mgnm)
err ("-failed to find magic number in saved file", i, mgnm, 0, 0);
close (ich);
if ( (V.cp != CP) || (V.ty != TY) || (V.pn != PN) ||
(V.ch != CH) || (V.nh != NH) || (V.nl != NL) || (V.own != &V))
radjptr ();
if (old)
convf123 (); /* convert from version 123 */
if (!batch) {
ldcmp ();
update (0, 0, 511, 511);
fx = fy = 0;
window (0, 0);
}
if (V.cnet) /* deselect pending nets */
deseln (V.cnet);
}
radjptr () /* readjust pointer */
/************************************************************************\
* *
* If the saved file was created with an older (but similar) version of *
* this program, the saved pointer may have changed due to the new *
* complilation. This routine readjusts the old pointer so that they *
* correspont to the new locations. *
* *
\************************************************************************/
{
union ptr_int { /* allow arithmetic on pointer */
unsigned i;
struct type *ty;
struct pin *pn;
struct hole *ch;
struct nlhd *nh;
struct nlst *nl;
struct vtin *vi;
} p1, p2;
unsigned tyof, pnof, chof, nhof, nlof, viof, nh_l, nh_h;
register int i;
printf("Warning: pcb has been recomplied since the file was saved\n");
p1.ty = V.ty;
p2.ty = &TY[0];
tyof = p2.i - p1.i; /* get TY offset */
p1.pn = V.pn;
p2.pn = &PN[0];
pnof = p2.i - p1.i; /* get PN offset */
p1.ch = V.ch;
p2.ch = &CH[0];
chof = p2.i - p1.i; /* get CH offset */
p1.nl = V.nl;
p2.nl = &NL[0];
nlof = p2.i - p1.i; /* get NL offset */
p1.nh = V.nh;
p2.nh = &NH[0];
nhof = p2.i - p1.i; /* get NH offset */
p1.vi = V.own;
p2.vi = &V;
viof = p2.i - p1.i; /* get NH offset */
if (tyof) {
for (i = 0; i < V.ncp; ++i) {
p1.ty = CP[i].ty;
p1.i = p1.i ? p1.i + tyof : nil;
CP[i].ty = p1.ty;
}
}
if (pnof) {
for (i = 0; i < V.nty; ++i) {
p1.pn = TY[i].p;
p1.i = p1.i ? p1.i + pnof : nil;
TY[i].p = p1.pn;
}
}
if (viof || chof || nlof || nhof) {/* adjust netlist ptr''s */
p1.nh = V.nh;
nh_l = p1.i;
p1.nh = V.nh + V.nnh;
nh_h = p1.i;
for (i = 0; i < V.nnl; ++i) {
p1.ch = NL[i].c;
p1.i = p1.i ? p1.i + chof : nil;
NL[i].c = p1.ch;
p1.nl = NL[i].n;
p1.i = p1.i ? p1.i + nlof : nil;
NL[i].n = p1.nl;
p1.nh = NL[i].nlp;
if (p1.i >= nh_l && p1.i <= nh_h)
p1.i += nhof;
else
p1.i = p1.i ? p1.i + viof : nil;
NL[i].nlp = p1.nh;
}
}
if (nlof) {
for (i = 0; i < V.nch; ++i) {
p1.nl = CH[i].n;
p1.i = p1.i ? p1.i + nlof : nil;
CH[i].n = p1.nl;
}
for (i = 0; i < V.nnh; ++i) {
p1.nl = NH[i].lp;
p1.i = p1.i ? p1.i + nlof : nil;
NH[i].lp = p1.nl;
}
if (V.GND.lp) {
p1.nl = V.GND.lp;
p1.i += nlof;
V.GND.lp = p1.nl;
}
if (V.VCC.lp) {
p1.nl = V.VCC.lp;
p1.i += nlof;
V.VCC.lp = p1.nl;
}
if (V.VEE.lp) {
p1.nl = V.VEE.lp;
p1.i += nlof;
V.VEE.lp = p1.nl;
}
if (V.VTT.lp) {
p1.nl = V.VTT.lp;
p1.i += nlof;
V.VTT.lp = p1.nl;
}
}
if (nhof || nlof) {
p1.nh = V.cnet;
p1.i = p1.i ? p1.i + nhof : nil;
V.cnet = p1.nh;
p1.nh = V.enhl;
p1.i = p1.i ? p1.i + nhof : nil;
V.enhl = p1.nh;
p1.nl = V.enll;
p1.i = p1.i ? p1.i + nlof : nil;
V.enll = p1.nl;
}
V.own = &V;
V.cp = &CP[0];
V.ty = &TY[0];
V.pn = &PN[0];
V.ch = &CH[0];
V.nh = &NH[0];
V.nl = &NL[0]; /* done ! (hopefully) */
/* the next is a temporary fix to correct an old ptr- problem */
/*
for (i = 0; i < V.nnh; i++)
if (NH[i].l) {int j; struct nlst *p;
for (p = NH[i].lp, j = 0; p; p = p -> n, j++)
if (p -> nlp != &NH[i]) {
printf("#");
p -> nlp = &NH[i];
}
if (j != NH[i].l)
err ("radjptr: inconsistent length", i, j, NH[i].l, 0);
}
*/
}
convf123 ()
/**************************************************************\
* *
* Convert from version 1.23: *
* *
* Changes: a) Tool holes are no longer needed -> remove them *
* b) The hole-structure received a reference to the *
* originating hole. *
* *
\**************************************************************/
{
register int j, r, xp, yp;
int i, k, x, y;
register struct pin *pin;
register struct hole *hp;
struct nlst *net;
struct hole *fndh ();
struct oldhole {
int x, y; /* coordinates */
struct nlst *n; /* net pointer */
} *oh;
printf ("Updating to PCB version 1.24\n");
V.pver = pversion; /* update pgm version */
color (0, fb);
for (i = 0; i < 4; i++) /* remove tool holes */
if (V.reserved[i]) {
x = V.reserved[i];
y = V.reserved[i + 4];
for (j = x - 3; j <= x + 3; j++)
for (k = y - 3; k <= y + 3; k++)
pxl (j, k);
}
for (i = 0; i < 8; i++)
V.reserved[i] = 0;
for (i = 0; i < V.nch; i++) { /* change hole structure */
oh = (struct oldhole *) &CH[i];
x = oh -> x;
y = oh -> y;
net = oh -> n;
CH[i].x = x;
CH[i].y = y;
CH[i].n = net;
CH[i].pn = 0;
CH[i].cpi = 0;
}
for (i = 0; i < V.ncp; i++) { /* scan all components */
if (CP[i].unplaced)
err ("Hey: V1.23 had no unplaced components!", i, 0, 0, 0);
x = CP[i].x; /* get borad position */
y = CP[i].y;
r = CP[i].r;
k = CP[i].ty -> np;
for (j = 0, pin = CP[i].ty -> p; j < k; j++, pin++) {
/* scan component pins */
xp = x + (pin -> x) * rot_m[r][0] + (pin -> y) * rot_m[r][1];
yp = y + (pin -> x) * rot_m[r][2] + (pin -> y) * rot_m[r][3];
hp = fndh (xp, yp); /* find hole */
if (!hp)
err ("convt124: missing hole", xp, yp, 0, 0);
hp -> pn = j;
hp -> cpi = i;
}
}
}
specs() /* promt for bord specs */
{
float x, y, getfloat();
x = getfloat ("Width of board in cm:",0.0,100.0,0.0);
y = getfloat ("Higth of board in cm:",0.0,100.0,0.0);
scalef = getfloat ("Scale factor for pin coordinates:",0.01,100.0,1.0);
if ((x < 1.0) || (y < 1.0))
err ("-Use a pencil and paper for such a board", x, y, 0, 0);
x *= 3.937007874; /* step by step (rounding problem) */
y *= 3.937007874;
x *= rsun;
y *= rsun;
V.BSX = 0.5 + x;
V.BSY = 0.5 + y;
if ((V.BSX > xmax - 4) || (V.BSY > ymax - 4)) {
printf ("Recompile me with 'xmax'>%d and 'ymax'>%d\n",
V.BSX + 3, V.BSY + 3);
err ("-bitmap too small", V.BSX, V.BSY, xmax - 4, ymax - 4);
}
color (fb, fb); /* plot frame */
plt (2, 1, V.BSX + 1, 1);
plt (1, 2, 1, V.BSY + 1);
plt (V.BSX + 2, 2, V.BSX + 2, V.BSY + 1);
plt (2, V.BSY + 2, V.BSX + 1, V.BSY + 2);
}
!E!O!F!
More information about the Comp.sources.unix
mailing list