ExpertPCBReadImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Christophe Cuenod, April 2, 1989 11:45:18 pm PDT
Reads an Expert .pcb file and retrieve from this file for each part:
the position
the orientation
the number of pins
the library entry number
For each part in the .pcb file the entry looks like (in bytes):
4 EntryNumber of the library
2 ?
2 X
2 Y
2 Orientation (MSB used to tell if placed on the drawing)
11 ?
1 Number of pins
1 ?
1 Length of the Reference designator
2, 3 or 4 Reference designator
The program first search for correct Reference designator Length (2, 3 or 4), then it verify that the first character of the Reference designator is alphabetic and the remainder alphabetic or numeric. It then verify that the Orientation is 0, 90, 180 or 270. If all those tests are OK it thinks it found a correct entry and pick the interesting fields.
DIRECTORY
Basics USING [BITAND],
Convert USING [RopeFromChar],
FS USING [StreamOpen],
IO USING [EndOf, GetByte, STREAM],
Rope USING [Cat, ROPE],
ExpertPCBRead,
SymTab USING [Create, Insert, Ref];
ExpertPCBReadImpl: CEDAR PROGRAM
IMPORTS Basics, Convert, FS, IO, Rope, SymTab
EXPORTS ExpertPCBRead
~ BEGIN
ROPE: TYPE = Rope.ROPE;
PCBTable: TYPE = ExpertPCBRead.PCBTable;
Part: TYPE = ExpertPCBRead.Part;
PartRep: TYPE = ExpertPCBRead.PartRep;
bufferSize: NAT = 50;
BufferRep: TYPE = RECORD[
size: NAT ← bufferSize,
lastentryindex: NAT,
table: ARRAY[0..bufferSize) OF BYTE
];
Buffer: TYPE = REF BufferRep;
Private procedures
CircularBufferPut: PROC [buffer: Buffer, i: BYTE] ~ {
buffer.lastentryindex ← buffer.lastentryindex + 1;
IF buffer.lastentryindex = bufferSize THEN buffer.lastentryindex ← 0;
buffer.table[buffer.lastentryindex] ← i;
};
CircularBufferGet: PROC [buffer: Buffer, offset: INT] RETURNS [i: BYTE] ~ {
index: INT;
index ← buffer.lastentryindex + offset;
IF index < 0 THEN index ← index + bufferSize;
IF index - bufferSize >= 0 THEN index ← index - bufferSize;
i ← buffer.table[index];
};
IsChar: PROC [i: BYTE] RETURNS [yes: BOOLEANFALSE] ~ {
IF i IN [ORD['A]..ORD['Z]] OR i IN [ORD['a]..ORD['z]] THEN yes ← TRUE;
};
IsNum: PROC [i: BYTE] RETURNS [yes: BOOLEANFALSE] ~ {
IF i IN [ORD['0]..ORD['9]] THEN yes ← TRUE;
};
TryMatch: PROC [buffer: Buffer, pCBTable: SymTab.Ref] ~ {
part: Part;
orient: NAT;
refDesLength: NAT;
refDes: ROPE;
IF NOT IsChar[CircularBufferGet[buffer, -3]] THEN RETURN;
IF (NOT IsNum[CircularBufferGet[buffer, -2]])
AND (NOT IsChar[CircularBufferGet[buffer, -2]]) THEN RETURN;
Used to test only for Numerical character but was changed to accomodate RefDes with 2 alphabetic characters. (10-4-88 JCC)
orient ← Basics.BITAND[CircularBufferGet[buffer, -19], 07FH]; -- Mask the MSB
orient ← orient * 256 + CircularBufferGet[buffer, -18];
The orientation of a part should be 0, 90, 180 or 270.
IF orient # 0 AND orient # 90 AND orient # 180 AND orient # 270 THEN RETURN;
refDesLength ← CircularBufferGet[buffer, -4];
refDes ← Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -3]], FALSE];
refDes ← Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -2]], FALSE]];
SELECT refDesLength FROM
= 3 => {
refDes ← Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -1]], FALSE]];
};
= 4 => {
refDes ← Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -1]], FALSE]];
refDes ← Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, 0]], FALSE]];
};
ENDCASE;
part ← NEW[PartRep];
part.x ← CircularBufferGet[buffer, -23];
part.x ← part.x * 256 + CircularBufferGet[buffer, -22];
part.y ← CircularBufferGet[buffer, -21];
part.y ← - (part.y * 256 + CircularBufferGet[buffer, -20]);
part.orientation ← orient;
part.libraryEntry ← CircularBufferGet[buffer, -27];
part.libraryEntry ← part.libraryEntry * 256 + CircularBufferGet[buffer, -26];
part.libraryEntry ← part.libraryEntry * 256 + CircularBufferGet[buffer, -29];
part.libraryEntry ← part.libraryEntry * 256 + CircularBufferGet[buffer, -28];
IF part.libraryEntry < 200 THEN RETURN;
No library entry should be under 200
[] ← SymTab.Insert[pCBTable, refDes, part];
};
Public Procedures
ReadPCBFile: PUBLIC PROC [file: ROPE] RETURNS [pCBTable: PCBTable] ~ {
i: INT;
buffer: Buffer ← NEW[BufferRep];
in: IO.STREAMFS.StreamOpen[file];
pCBTable ← SymTab.Create[];
WHILE NOT IO.EndOf[in] DO
CircularBufferPut[buffer, IO.GetByte[in]];
i ← CircularBufferGet[buffer, -4];
2, 3 or 4 can be the length of a reference designator.
IF i = 2 OR i = 3 OR i = 4 THEN TryMatch[buffer, pCBTable];
ENDLOOP;
};
END.