2 * Copyright 1999 Matthew Ettus
3 * For more info email matt@ettus.com
4 * Ths code is released under the terms of the GNU GPL
5 * See www.fsf.org for a copy of the license
7 * Changes 0.94 by <egil@kvaleberg.no>, october 5th 2002
8 * Scaling defaults to 200%
9 * Bus implemented - but still no bus entries!
10 * Check for stack overwrite and other horrors
11 * Changed orcad_xsize/orcad_ysize to sarlacc_dim
13 * Command line options
18 * Many details - see BAD
21 /* This program will convert an ORCAD SDT IV file to geda format */
30 #include <sys/types.h>
39 #include <libgeda/colors.h>
41 #ifdef HAVE_LIBDMALLOC
46 * command line options
48 #define SARVERSION "0.94"
49 #define GEDAVERSION "20020825"
51 #define DEFAULT_SCALE 200 /* was 100 */
54 int scale
= DEFAULT_SCALE
;
56 #define TEXTSIZE ((scale <= 100) ? 6 : 10)
61 #define GET_TAG(VAL) (VAL & 0x0F)
63 int CONV16(char *base
,int offset
)
66 retval
= ((base
[offset
+1] & 255) <<8) | (base
[offset
] & 255);
67 if(base
[offset
+1]&128)
68 retval
= retval
| (65535U << 16);
72 #define CONV32(VAR,POS) (VAR[POS]+VAR[POS+1]*256+VAR[POS+2]*65536+VAR[POS+3]*256*16777216)
74 #define CONV(X) ( (scale/10)*X )
75 #define CONVX(X) CONV(X)
76 #define CONVY(Y) ( 32700 - ((scale/10)*Y) )
79 #define BYTECOUNT 0x16
90 /* change return type from int to void AVH */
91 void remove_spaces(char *src
)
103 * read block from Orcad file
106 unsigned read_block(int fd
, char *block
, int block_min_size
,int block_max_size
)
112 size
= CONV16(sizebuf
,0);
113 if (size
< block_min_size
) {
114 fprintf(stderr
,"Segment too small; size %d, min is %d\n",
115 size
, block_min_size
);
118 if (size
> block_max_size
) {
119 fprintf(stderr
,"Segment too large; size %d, max is %d\n",
120 size
, block_max_size
);
123 if (read(fd
,block
,size
) != size
) {
124 fprintf(stderr
,"File truncated\n");
130 unsigned read_string(char *dest
, int dest_size
, char *src
)
132 unsigned size
= ((unsigned char *)src
)[0];
134 if (size
+1 > dest_size
) {
135 fprintf(stderr
,"Text too large; size %d, max is %d\n",
139 strncpy(dest
,src
+1,size
);
144 /* change return type from int to void AVH */
145 void read_string_file(int fd
,char *dest
, int dest_size
)
149 if (read(fd
,&len
,1) != 1) {
150 fprintf(stderr
,"File truncated\n");
153 if (len
+1 > dest_size
) {
154 fprintf(stderr
,"Text too large; size %d, max is %d\n",
159 if (read(fd
,dest
,len
) != len
) {
160 fprintf(stderr
,"File truncated\n");
170 void parse_header(int fd1
,int fd2
)
172 unsigned char localbuf
[32];
175 read(fd1
,localbuf
,32);
176 if( strncmp(localbuf
,"Schematic FILE",14) )
178 fprintf(stderr
,"\nFile is not an ORCAD 16 Bit Schematic\n");
182 length
=CONV32(localbuf
,BYTECOUNT
);
183 fprintf(stderr
,"length: %d\n",length
);
185 lseek(fd2
,length
+HDR_LEN
,SEEK_SET
);
188 /* BAD more titleblock stuff */
189 void parse_titleblock(int fd
)
191 int size
,sheet
,total
,ypos
;
196 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
197 // fprintf(stderr,"\nTitleblock %d bytes\n",size);
199 sheet
=CONV16(localbuf
,0x00);
200 total
=CONV16(localbuf
,0x02);
201 fprintf(stderr
,"Sheet #%d of %d\n",sheet
,total
);
202 read_string(data
,sizeof(data
),localbuf
+DATE
);
203 fprintf(stderr
,"%s\n",data
);
205 switch(localbuf
[4] && 0x0F)
207 case 0: pagesize
= 'A'; ypos
= 8*scale
+scale
/2; break;
208 case 1: pagesize
= 'B'; ypos
= 11*scale
; break;
209 case 2: pagesize
= 'C'; ypos
= 17*scale
; break;
210 case 3: pagesize
= 'D'; ypos
= 22*scale
; break;
211 case 4: pagesize
= 'E'; ypos
= 34*scale
; break;
212 default: fprintf(stderr
,"Unknown Page Size\n");exit(-1);
215 fprintf(stdout
,"C %d %d 0 0 0 title-%c.sym\n",CONVX(0),CONVY(ypos
),pagesize
);
219 /* BAD Rotation and mirroring origin issues */
220 /* Other component label issues */
221 void parse_component(int fd1
,int fd2
)
226 char full_filename
[1024];
229 int xpos
= 0,ypos
= 0,xpossav
,ypossav
;
233 int sarlacc_xsize
= 0, sarlacc_ysize
= 0;
234 int sarlacc_xoffset
= 0, sarlacc_yoffset
= 0;
237 int refx
,refy
,ref_vis
;
239 int valx
,valy
,val_vis
;
251 size
= read_block(fd1
,localbuf
,29,sizeof(localbuf
));
253 x
=CONV16(localbuf
,0);
254 y
=CONV16(localbuf
,2);
256 refx
= CONVX(x
+ CONV16(localbuf
,4));
257 refy
= CONVY(y
+ CONV16(localbuf
,6));
259 valx
= CONVX(x
+ CONV16(localbuf
,8));
260 valy
= CONVY(y
+ CONV16(localbuf
,10));
265 if(localbuf
[12] & 0x80) mirror
=1;
269 if (localbuf
[12] & 0x20) angle
=90;
270 if (localbuf
[12] & 0x40) angle
+=180;
271 /* BAD decode and use device number, fix rotation offset */
275 flags
= localbuf
[13];
276 if (flags
& 2) ref_vis
=0;
277 if (flags
& 4) val_vis
=0;
278 /* BAD decode more flags */
284 pointer
= 28 + read_string(refdes
,sizeof(refdes
),localbuf
+28) +1;
285 pointer
= pointer
+ 1 +read_string(value
,sizeof(value
),localbuf
+pointer
);
287 read_string_file(fd2
,partname
,sizeof(partname
));
288 remove_spaces(partname
);
289 // fprintf(stderr,"Component %s: %s\n",refdes,partname);
290 snprintf(filename
,sizeof(filename
),"%s-1.sym", partname
);
292 snprintf(full_filename
,sizeof(full_filename
),"%s/%s",
293 symbol_dir
, filename
);
295 snprintf(full_filename
,sizeof(full_filename
),"%s", filename
);
298 cfp
= fopen(full_filename
, "r");
300 /* "sarlacc_dim=" set by sarlacc_sym */
302 fgets(buff
, 128, cfp
);
303 if (!strncmp(buff
, "sarlacc_dim=", 12)) {
304 sscanf(buff
+12, "%d,%d,%d,%d",
305 &sarlacc_xoffset
,&sarlacc_yoffset
,&sarlacc_xsize
,&sarlacc_ysize
);
310 fprintf(stderr
,"ref: %s dim = %d %d %d %d angle = %d mirror = %d\n",
312 sarlacc_xoffset
, sarlacc_yoffset
,
313 sarlacc_xsize
, sarlacc_ysize
, angle
, mirror
);
318 xgeda
= xgeda
+ sarlacc_xsize
+ sarlacc_xoffset
;
320 xgeda
= xgeda
- sarlacc_xoffset
;
322 ygeda
= ygeda
- (sarlacc_ysize
+ sarlacc_yoffset
);
325 xgeda
= xgeda
+ sarlacc_ysize
+ sarlacc_yoffset
;
328 ygeda
= ygeda
+ sarlacc_xoffset
;
330 ygeda
= ygeda
- (sarlacc_xsize
+ sarlacc_xoffset
);
335 xgeda
= xgeda
- sarlacc_xoffset
;
337 xgeda
= xgeda
+ sarlacc_xsize
+ sarlacc_xoffset
;
339 ygeda
= ygeda
+ sarlacc_yoffset
;
342 xgeda
= xgeda
- sarlacc_yoffset
;
345 ygeda
= ygeda
- (sarlacc_xsize
+ sarlacc_xoffset
);
347 ygeda
= ygeda
+ sarlacc_xoffset
;
352 fprintf(stderr
,"Couldn't find symbol %s in file: %s\n"
353 "Position on sheet will be uncertain\n", partname
, full_filename
);
356 fprintf(stdout
,"C %d %d 1 %d %d %s\n",
357 xgeda
,ygeda
,angle
,mirror
,filename
);
358 fprintf(stdout
,"{\n");
361 /* For sarlacc debugging purposes, it's useful to see
362 if a component is mirrored and how much it's rotated */
363 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nmirror=%d\n",
364 refx
,refy
,GRAPHIC_COLOR
,TEXTSIZE
,0,mirror
);
365 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nrotation=%d\n",
366 refx
,refy
,GRAPHIC_COLOR
,TEXTSIZE
,0,angle
);
368 if (refdes
[0] != 0) {
369 if (value
[0] && refx
==valx
&& refy
==valy
) {
370 /* prevent text overlap */
373 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nrefdes=%s\n",
374 refx
,refy
,ATTRIBUTE_COLOR
,TEXTSIZE
,ref_vis
,refdes
);
378 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nvalue=%s\n",
379 valx
,valy
,ATTRIBUTE_COLOR
,TEXTSIZE
,val_vis
,value
);
385 /* This assumes that the last attribute is the footprint */
386 xpos
= CONVX(x
+ CONV16(localbuf
,pointer
));
387 ypos
= CONVY(y
+ CONV16(localbuf
,pointer
+2));
389 size
= read_string(attrib
,sizeof(attrib
),localbuf
+pointer
);
393 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\npattern=%s\n",
394 xpos
,ypos
,ATTRIBUTE_COLOR
,TEXTSIZE
,
395 ( (flags
& (1<<i
))?1:0 ),attrib
);
398 strcpy(attribsav
, attrib
);
402 if (attribcnt
> 0 && attrib
[0]) {
403 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\n"
405 xpos
,ypos
,ATTRIBUTE_COLOR
,TEXTSIZE
,
406 ( (flags
& (1<<i
))?1:0 ),attrib
);
408 fprintf(stdout
,"}\n");
411 /* BAD Sheets need work */
412 void parse_sheet (int fd
)
422 size
= read_block(fd
,localbuf
,15,sizeof(localbuf
));
423 // fprintf(stderr,"Sheet %d bytes\n",size);
425 x1
=CONVX(CONV16(localbuf
,0));
426 y1
=CONVY(CONV16(localbuf
,2));
428 x2
=CONV(CONV16(localbuf
,4));
429 y2
=CONV(CONV16(localbuf
,6));
432 /* BAD 5 bytes - dunno? */
435 n
= 1+read_string(filename
,sizeof(filename
),localbuf
+index
);
437 n
= 1+read_string(filetext
,sizeof(filetext
),localbuf
+index
);
440 /* BAD Implement Hierarchy properly! */
441 fprintf(stderr
,"Hierarchy\n");
442 fprintf(stderr
,"xy = %d %d %d %d\n",x1
,y1
,x2
,y2
);
443 for (n
=8; n
<13; ++n
) fprintf(stderr
,"%02x ",localbuf
[n
] & 0xff);
444 fprintf(stderr
,"\nfile = %s\n",filename
);
445 fprintf(stderr
,"text = %s\n",filetext
);
447 /* BAD not the way to do it... */
448 fprintf(stdout
,"C %d %d 0 0 0 include-1.sym\n",x1
,y1
-y2
);
449 fprintf(stdout
,"{\n");
450 fprintf(stdout
,"B %d %d %d %d %d 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n",
451 x1
,y1
-y2
,x2
,y2
,GRAPHIC_COLOR
);
452 fprintf(stdout
,"T %d %d %d %d 0 1 0 0\n"
453 "source=%s\n",x1
,y1
-y2
,ATTRIBUTE_COLOR
,TEXTSIZE
,filename
);
454 fprintf(stdout
,"T %d %d %d %d 1 1 0 0\n"
455 "%s\n",x1
,(y1
-y2
)-scale
,ATTRIBUTE_COLOR
,TEXTSIZE
,filetext
);
456 fprintf(stdout
,"}\n");
459 static int pending_netlabel
=0;
460 static char netlabel
[256];
461 static int netlabel_x
, netlabel_y
, netlabel_angle
;
463 /* BAD Set wire color properly */
464 static void wire_or_bus(int fd
, char kind
, int color
)
470 size
= read_block(fd
,localbuf
,8,sizeof(localbuf
));
472 x1
=CONVX(CONV16(localbuf
,0));
473 y1
=CONVY(CONV16(localbuf
,2));
475 x2
=CONVX(CONV16(localbuf
,4));
476 y2
=CONVY(CONV16(localbuf
,6));
477 fprintf(stdout
,"%c %d %d %d %d %d 0 0 0 -1 -1\n",kind
,x1
,y1
,x2
,y2
,color
);
478 if (pending_netlabel
) {
479 fprintf(stdout
,"{\n");
480 fprintf(stdout
,"T %d %d %d %d 1 1 %d 0\n", netlabel_x
, netlabel_y
,
481 ATTRIBUTE_COLOR
, TEXTSIZE
, netlabel_angle
);
482 fprintf(stdout
,"label=%s\n", netlabel
); /* BAD netname= */
483 fprintf(stdout
,"}\n");
484 pending_netlabel
= 0;
488 void parse_wire (int fd
)
490 wire_or_bus(fd
, 'N', NET_COLOR
);
493 /* BAD Haven't implemented GEDA buses */
494 /* but guessing that Orcad busses are parsed just like wires... */
495 void parse_bus (int fd
)
497 wire_or_bus(fd
, 'U', BUS_COLOR
);
500 /* BAD How do we handle junctions in GEDA? */
501 /* 19990726 I think we don't need to worry
502 * ORCAD splits wires at junction points
505 void parse_junction (int fd
)
510 size
= read_block(fd
,localbuf
,4,sizeof(localbuf
));
513 x=CONVX(CONV16(localbuf,0));
514 y=CONVY(CONV16(localbuf,2));
515 fprintf(stderr,"Junctions %d %d\n",x,y);
520 /* BAD Fix handling of ports */
522 void parse_port (int fd
)
532 size
= read_block(fd
,localbuf
,7,sizeof(localbuf
));
534 x
= CONVX(CONV16(localbuf
,0));
535 y
= CONVY(CONV16(localbuf
,2));
536 w
= localbuf
[4] & 0xff;
537 m
= localbuf
[5] & 0xff;
538 read_string(textbuf
,sizeof(textbuf
),localbuf
+6);
540 // fprintf(stderr,"PORT %s %d %d %d 0x%x\n",textbuf,x,y,w,m);
543 case 0x40: /* 0101 */
544 case 0x20: /* 1010 */
545 x
+= scale
+ w
* (scale
/10);
547 case 0x00: /* 0000 */
549 case 0x60: /* 1111 */
553 fprintf(stdout
,"C %d %d 1 0 %d input-orcad-1.sym\n",x
,y
,mirror
);
555 "T %d %d %d 8 1 1 0 0\nvalue=%s\n"
556 "}\n",x
,y
,GRAPHIC_COLOR
,
560 /* BAD Fix Labels attach to wire. Multiline issues?*/
561 /* Fix text sizing */
562 void parse_label (int fd
)
571 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
573 x
=CONVX(CONV16(localbuf
,0));
574 y
=CONVY(CONV16(localbuf
,2));
576 read_string(textbuf
,sizeof(textbuf
),localbuf
+0x06);
579 textsize
= 5* CONV16(localbuf
,4);
585 /* fprintf(stdout,"T %d %d %d %d 1 1 %d 0\n",x,y,GRAPHIC_COLOR, TEXTSIZE, angle);
586 fprintf(stdout,"net=%s ATTACHME\n",textbuf); */
587 pending_netlabel
= 1;
588 strncpy(netlabel
, textbuf
, 256);
591 netlabel_angle
= angle
;
594 /* BAD Fix Entries */
596 void parse_entry (int fd
)
602 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
603 // fprintf(stderr,"Entry %d bytes\n",size);
605 x
=CONVX(CONV16(localbuf
,0));
606 y
=CONVY(CONV16(localbuf
,2));
608 fprintf(stderr
,"Entry %d %d type %d\n",x
,y
,type
);
611 /* BAD Fix Dashed Lines */
613 void parse_dashed (int fd
)
619 size
= read_block(fd
,localbuf
,4,sizeof(localbuf
));
620 fprintf(stderr
,"Dashed %d bytes\n",size
);
622 x
=CONVX(CONV16(localbuf
,0));
623 y
=CONVY(CONV16(localbuf
,2));
628 /* How do netlisters handle power connections/nets? */
630 void parse_power (int fd
)
640 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
641 // fprintf(stderr,"POWER %d bytes\n",size);
643 read_string(textbuf
,sizeof(textbuf
),localbuf
+0x05);
645 x
=CONVX(CONV16(localbuf
,0));
646 y
=CONVY(CONV16(localbuf
,2));
650 case 0x04: angle
= 180; xtext
= x
; ytext
= y
- 600; break;
651 case 0x08: angle
= 90; ytext
= y
; xtext
= x
-600; break;
652 case 0x0C: angle
= 270;ytext
= y
; xtext
= x
+600; break;
653 default: angle
= 0; xtext
=x
;ytext
= y
+600;
657 /* BAD GEDA only has bar and circle pix. Also, they
658 * All say VCC or VDD, which they should not */
660 symbol
= "vcc-orcad-bar-1.sym";break; /* BAR */
661 case 0x00: /* circle */
662 case 0x01: /* arrow */
663 case 0x03: /* wave */
665 symbol
= "vcc-orcad-circle-1.sym";break;
667 fprintf(stdout
,"C %d %d 1 %d 0 %s\n",x
,y
,angle
,symbol
);
668 /* fprintf(stdout,"{\n"
669 "T %d %d %d %d 1 1 %d 0\n"
672 xtext,ytext,GRAPHIC_COLOR,TEXTSIZE,angle%180,textbuf);*/
674 "T %d %d %d %d 1 1 %d 0\n"
677 xtext
,ytext
,GRAPHIC_COLOR
,TEXTSIZE
,angle
%180,textbuf
);
680 /* BAD Fix Text color and check rotation */
681 /* BAD Fix multi-line text */
683 void parse_text (int fd
)
688 int x
,y
,textsize
,angle
;
690 size
= read_block(fd
,localbuf
,7,sizeof(localbuf
));
692 x
=CONVX(CONV16(localbuf
,0));
693 y
=CONVY(CONV16(localbuf
,2));
694 read_string(textbuf
,sizeof(textbuf
),localbuf
+6);
697 textsize
= TEXTSIZE
* CONV16(localbuf
,4);
703 fprintf(stdout
,"T %d %d %d %d 1 1 %d 0\n",x
,y
,GRAPHIC_COLOR
,textsize
,angle
);
704 fprintf(stdout
,"%s\n",textbuf
);
707 /* BAD - Markers are unimplemented in gEDA (yet).
708 * They are the no-connects that you can place on pins to
709 * exempt them from the connectivity checks in DRC/ERC
712 void parse_marker (int fd
)
717 size
= read_block(fd
,localbuf
,0,sizeof(localbuf
));
719 /* fprintf(stderr,"MARKER %d\n",size); */
723 int parse_block(int fd1
,int fd2
)
730 parse_titleblock(fd1
);
736 parse_component(fd1
,fd2
);
772 fprintf(stderr
,"\nUnknown Block Tag\n");
782 main(int argc
, char **argv
)
787 while ((c
= getopt(argc
, argv
, "d:hs:v")) > 0) {
793 scale
= atoi(optarg
);
796 fprintf(stderr
,"sarlacc_scheme ver %s\n", SARVERSION
);
801 fprintf(stderr
,"Convert Oracd schematics file (16 bit format) to gEDA\n");
803 fprintf(stderr
,"\nUsage: %s [options] infile >outfile\n"
805 "\n -d<dir> directory for symbols (from sarlacc_sym)"
807 "\n -s<n> scale <n>%%, default is %d"
810 argv
[0],DEFAULT_SCALE
);
816 if( optind
+1 != argc
)
821 /* BAD update to latest file format.. */
822 fprintf(stdout
,"v %s\n",GEDAVERSION
);
824 fd1
= open(argv
[optind
],O_RDONLY
);
827 fprintf(stderr
,"\nCould not open input file: %s\n",argv
[optind
]);
830 fd2
= open(argv
[optind
],O_RDONLY
);
833 fprintf(stderr
,"\n Could not open input file part deux\n");
837 parse_header(fd1
,fd2
);
839 while(parse_block(fd1
,fd2
));
840 fprintf(stderr
,"\n Normal End\n");