2 * Copyright (C) 1999-2010 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>
42 * command line options
44 #define SARVERSION "0.94"
45 #define GEDAVERSION "20020825"
47 #define DEFAULT_SCALE 200 /* was 100 */
50 int scale
= DEFAULT_SCALE
;
52 #define TEXTSIZE ((scale <= 100) ? 6 : 10)
57 #define GET_TAG(VAL) (VAL & 0x0F)
59 int CONV16(char *base
,int offset
)
62 retval
= ((base
[offset
+1] & 255) <<8) | (base
[offset
] & 255);
63 if(base
[offset
+1]&128)
64 retval
= retval
| (65535U << 16);
68 #define CONV32(VAR,POS) (VAR[POS]+VAR[POS+1]*256+VAR[POS+2]*65536+VAR[POS+3]*256*16777216)
70 #define CONV(X) ( (scale/10)*X )
71 #define CONVX(X) CONV(X)
72 #define CONVY(Y) ( 32700 - ((scale/10)*Y) )
75 #define BYTECOUNT 0x16
86 void remove_spaces(char *src
)
98 * read block from Orcad file
101 unsigned read_block(int fd
, char *block
, int block_min_size
,int block_max_size
)
107 size
= CONV16(sizebuf
,0);
108 if (size
< block_min_size
) {
109 fprintf(stderr
,"Segment too small; size %d, min is %d\n",
110 size
, block_min_size
);
113 if (size
> block_max_size
) {
114 fprintf(stderr
,"Segment too large; size %d, max is %d\n",
115 size
, block_max_size
);
118 if (read(fd
,block
,size
) != size
) {
119 fprintf(stderr
,"File truncated\n");
125 unsigned read_string(char *dest
, int dest_size
, char *src
)
127 unsigned size
= ((unsigned char *)src
)[0];
129 if (size
+1 > dest_size
) {
130 fprintf(stderr
,"Text too large; size %d, max is %d\n",
134 strncpy(dest
,src
+1,size
);
139 void read_string_file(int fd
,char *dest
, int dest_size
)
143 if (read(fd
,&len
,1) != 1) {
144 fprintf(stderr
,"File truncated\n");
147 if (len
+1 > dest_size
) {
148 fprintf(stderr
,"Text too large; size %d, max is %d\n",
153 if (read(fd
,dest
,len
) != len
) {
154 fprintf(stderr
,"File truncated\n");
164 void parse_header(int fd1
,int fd2
)
166 unsigned char localbuf
[32];
169 read(fd1
,localbuf
,32);
170 if( strncmp((char *) localbuf
,"Schematic FILE",14) )
172 fprintf(stderr
,"\nFile is not an ORCAD 16 Bit Schematic\n");
176 length
=CONV32(localbuf
,BYTECOUNT
);
177 fprintf(stderr
,"length: %d\n",length
);
179 lseek(fd2
,length
+HDR_LEN
,SEEK_SET
);
182 /* BAD more titleblock stuff */
183 void parse_titleblock(int fd
)
185 int size
,sheet
,total
,ypos
;
190 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
191 // fprintf(stderr,"\nTitleblock %d bytes\n",size);
193 sheet
=CONV16(localbuf
,0x00);
194 total
=CONV16(localbuf
,0x02);
195 fprintf(stderr
,"Sheet #%d of %d\n",sheet
,total
);
196 read_string(data
,sizeof(data
),localbuf
+DATE
);
197 fprintf(stderr
,"%s\n",data
);
199 switch(localbuf
[4] & 0x0F)
201 case 0: pagesize
= 'A'; ypos
= 8*scale
+scale
/2; break;
202 case 1: pagesize
= 'B'; ypos
= 11*scale
; break;
203 case 2: pagesize
= 'C'; ypos
= 17*scale
; break;
204 case 3: pagesize
= 'D'; ypos
= 22*scale
; break;
205 case 4: pagesize
= 'E'; ypos
= 34*scale
; break;
206 default: fprintf(stderr
,"Unknown Page Size\n");exit(-1);
209 fprintf(stdout
,"C %d %d 0 0 0 title-%c.sym\n",CONVX(0),CONVY(ypos
),pagesize
);
213 /* BAD Rotation and mirroring origin issues */
214 /* Other component label issues */
215 void parse_component(int fd1
,int fd2
)
220 char full_filename
[1024];
223 int xpos
= 0,ypos
= 0,xpossav
,ypossav
;
227 int sarlacc_xsize
= 0, sarlacc_ysize
= 0;
228 int sarlacc_xoffset
= 0, sarlacc_yoffset
= 0;
231 int refx
,refy
,ref_vis
;
233 int valx
,valy
,val_vis
;
245 size
= read_block(fd1
,localbuf
,29,sizeof(localbuf
));
247 x
=CONV16(localbuf
,0);
248 y
=CONV16(localbuf
,2);
250 refx
= CONVX(x
+ CONV16(localbuf
,4));
251 refy
= CONVY(y
+ CONV16(localbuf
,6));
253 valx
= CONVX(x
+ CONV16(localbuf
,8));
254 valy
= CONVY(y
+ CONV16(localbuf
,10));
259 if(localbuf
[12] & 0x80) mirror
=1;
263 if (localbuf
[12] & 0x20) angle
=90;
264 if (localbuf
[12] & 0x40) angle
+=180;
265 /* BAD decode and use device number, fix rotation offset */
269 flags
= localbuf
[13];
270 if (flags
& 2) ref_vis
=0;
271 if (flags
& 4) val_vis
=0;
272 /* BAD decode more flags */
278 pointer
= 28 + read_string(refdes
,sizeof(refdes
),localbuf
+28) +1;
279 pointer
= pointer
+ 1 +read_string(value
,sizeof(value
),localbuf
+pointer
);
281 read_string_file(fd2
,partname
,sizeof(partname
));
282 remove_spaces(partname
);
283 // fprintf(stderr,"Component %s: %s\n",refdes,partname);
284 snprintf(filename
,sizeof(filename
),"%s-1.sym", partname
);
286 snprintf(full_filename
,sizeof(full_filename
),"%s/%s",
287 symbol_dir
, filename
);
289 snprintf(full_filename
,sizeof(full_filename
),"%s", filename
);
292 cfp
= fopen(full_filename
, "r");
294 /* "sarlacc_dim=" set by sarlacc_sym */
296 fgets(buff
, 128, cfp
);
297 if (!strncmp(buff
, "sarlacc_dim=", 12)) {
298 sscanf(buff
+12, "%d,%d,%d,%d",
299 &sarlacc_xoffset
,&sarlacc_yoffset
,&sarlacc_xsize
,&sarlacc_ysize
);
304 fprintf(stderr
,"ref: %s dim = %d %d %d %d angle = %d mirror = %d\n",
306 sarlacc_xoffset
, sarlacc_yoffset
,
307 sarlacc_xsize
, sarlacc_ysize
, angle
, mirror
);
312 xgeda
= xgeda
+ sarlacc_xsize
+ sarlacc_xoffset
;
314 xgeda
= xgeda
- sarlacc_xoffset
;
316 ygeda
= ygeda
- (sarlacc_ysize
+ sarlacc_yoffset
);
319 xgeda
= xgeda
+ sarlacc_ysize
+ sarlacc_yoffset
;
322 ygeda
= ygeda
+ sarlacc_xoffset
;
324 ygeda
= ygeda
- (sarlacc_xsize
+ sarlacc_xoffset
);
329 xgeda
= xgeda
- sarlacc_xoffset
;
331 xgeda
= xgeda
+ sarlacc_xsize
+ sarlacc_xoffset
;
333 ygeda
= ygeda
+ sarlacc_yoffset
;
336 xgeda
= xgeda
- sarlacc_yoffset
;
339 ygeda
= ygeda
- (sarlacc_xsize
+ sarlacc_xoffset
);
341 ygeda
= ygeda
+ sarlacc_xoffset
;
346 fprintf(stderr
,"Couldn't find symbol %s in file: %s\n"
347 "Position on sheet will be uncertain\n", partname
, full_filename
);
350 fprintf(stdout
,"C %d %d 1 %d %d %s\n",
351 xgeda
,ygeda
,angle
,mirror
,filename
);
352 fprintf(stdout
,"{\n");
355 /* For sarlacc debugging purposes, it's useful to see
356 if a component is mirrored and how much it's rotated */
357 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nmirror=%d\n",
358 refx
,refy
,GRAPHIC_COLOR
,TEXTSIZE
,0,mirror
);
359 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nrotation=%d\n",
360 refx
,refy
,GRAPHIC_COLOR
,TEXTSIZE
,0,angle
);
362 if (refdes
[0] != 0) {
363 if (value
[0] && refx
==valx
&& refy
==valy
) {
364 /* prevent text overlap */
367 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nrefdes=%s\n",
368 refx
,refy
,ATTRIBUTE_COLOR
,TEXTSIZE
,ref_vis
,refdes
);
372 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\nvalue=%s\n",
373 valx
,valy
,ATTRIBUTE_COLOR
,TEXTSIZE
,val_vis
,value
);
379 /* This assumes that the last attribute is the footprint */
380 xpos
= CONVX(x
+ CONV16(localbuf
,pointer
));
381 ypos
= CONVY(y
+ CONV16(localbuf
,pointer
+2));
383 size
= read_string(attrib
,sizeof(attrib
),localbuf
+pointer
);
387 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\npattern=%s\n",
388 xpos
,ypos
,ATTRIBUTE_COLOR
,TEXTSIZE
,
389 ( (flags
& (1<<i
))?1:0 ),attrib
);
392 strcpy(attribsav
, attrib
);
396 if (attribcnt
> 0 && attrib
[0]) {
397 fprintf(stdout
,"T %d %d %d %d %d 1 0 0\n"
399 xpos
,ypos
,ATTRIBUTE_COLOR
,TEXTSIZE
,
400 ( (flags
& (1<<i
))?1:0 ),attrib
);
402 fprintf(stdout
,"}\n");
405 /* BAD Sheets need work */
406 void parse_sheet (int fd
)
416 size
= read_block(fd
,localbuf
,15,sizeof(localbuf
));
417 // fprintf(stderr,"Sheet %d bytes\n",size);
419 x1
=CONVX(CONV16(localbuf
,0));
420 y1
=CONVY(CONV16(localbuf
,2));
422 x2
=CONV(CONV16(localbuf
,4));
423 y2
=CONV(CONV16(localbuf
,6));
426 /* BAD 5 bytes - dunno? */
429 n
= 1+read_string(filename
,sizeof(filename
),localbuf
+index
);
431 n
= 1+read_string(filetext
,sizeof(filetext
),localbuf
+index
);
434 /* BAD Implement Hierarchy properly! */
435 fprintf(stderr
,"Hierarchy\n");
436 fprintf(stderr
,"xy = %d %d %d %d\n",x1
,y1
,x2
,y2
);
437 for (n
=8; n
<13; ++n
) fprintf(stderr
,"%02x ",localbuf
[n
] & 0xff);
438 fprintf(stderr
,"\nfile = %s\n",filename
);
439 fprintf(stderr
,"text = %s\n",filetext
);
441 /* BAD not the way to do it... */
442 fprintf(stdout
,"C %d %d 0 0 0 include-1.sym\n",x1
,y1
-y2
);
443 fprintf(stdout
,"{\n");
444 fprintf(stdout
,"B %d %d %d %d %d 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n",
445 x1
,y1
-y2
,x2
,y2
,GRAPHIC_COLOR
);
446 fprintf(stdout
,"T %d %d %d %d 0 1 0 0\n"
447 "source=%s\n",x1
,y1
-y2
,ATTRIBUTE_COLOR
,TEXTSIZE
,filename
);
448 fprintf(stdout
,"T %d %d %d %d 1 1 0 0\n"
449 "%s\n",x1
,(y1
-y2
)-scale
,ATTRIBUTE_COLOR
,TEXTSIZE
,filetext
);
450 fprintf(stdout
,"}\n");
453 static int pending_netlabel
=0;
454 static char netlabel
[256];
455 static int netlabel_x
, netlabel_y
, netlabel_angle
;
457 /* BAD Set wire color properly */
458 static void wire_or_bus(int fd
, char kind
, int color
)
464 size
= read_block(fd
,localbuf
,8,sizeof(localbuf
));
466 x1
=CONVX(CONV16(localbuf
,0));
467 y1
=CONVY(CONV16(localbuf
,2));
469 x2
=CONVX(CONV16(localbuf
,4));
470 y2
=CONVY(CONV16(localbuf
,6));
471 fprintf(stdout
,"%c %d %d %d %d %d 0 0 0 -1 -1\n",kind
,x1
,y1
,x2
,y2
,color
);
472 if (pending_netlabel
) {
473 fprintf(stdout
,"{\n");
474 fprintf(stdout
,"T %d %d %d %d 1 1 %d 0\n", netlabel_x
, netlabel_y
,
475 ATTRIBUTE_COLOR
, TEXTSIZE
, netlabel_angle
);
476 fprintf(stdout
,"label=%s\n", netlabel
); /* BAD netname= */
477 fprintf(stdout
,"}\n");
478 pending_netlabel
= 0;
482 void parse_wire (int fd
)
484 wire_or_bus(fd
, 'N', NET_COLOR
);
487 /* BAD Haven't implemented GEDA buses */
488 /* but guessing that Orcad busses are parsed just like wires... */
489 void parse_bus (int fd
)
491 wire_or_bus(fd
, 'U', BUS_COLOR
);
494 /* BAD How do we handle junctions in GEDA? */
495 /* 19990726 I think we don't need to worry
496 * ORCAD splits wires at junction points
499 void parse_junction (int fd
)
504 size
= read_block(fd
,localbuf
,4,sizeof(localbuf
));
507 x=CONVX(CONV16(localbuf,0));
508 y=CONVY(CONV16(localbuf,2));
509 fprintf(stderr,"Junctions %d %d\n",x,y);
514 /* BAD Fix handling of ports */
516 void parse_port (int fd
)
526 size
= read_block(fd
,localbuf
,7,sizeof(localbuf
));
528 x
= CONVX(CONV16(localbuf
,0));
529 y
= CONVY(CONV16(localbuf
,2));
530 w
= localbuf
[4] & 0xff;
531 m
= localbuf
[5] & 0xff;
532 read_string(textbuf
,sizeof(textbuf
),localbuf
+6);
534 // fprintf(stderr,"PORT %s %d %d %d 0x%x\n",textbuf,x,y,w,m);
537 case 0x40: /* 0101 */
538 case 0x20: /* 1010 */
539 x
+= scale
+ w
* (scale
/10);
541 case 0x00: /* 0000 */
543 case 0x60: /* 1111 */
547 fprintf(stdout
,"C %d %d 1 0 %d input-orcad-1.sym\n",x
,y
,mirror
);
549 "T %d %d %d 8 1 1 0 0\nvalue=%s\n"
550 "}\n",x
,y
,GRAPHIC_COLOR
,
554 /* BAD Fix Labels attach to wire. Multiline issues?*/
555 /* Fix text sizing */
556 void parse_label (int fd
)
565 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
567 x
=CONVX(CONV16(localbuf
,0));
568 y
=CONVY(CONV16(localbuf
,2));
570 read_string(textbuf
,sizeof(textbuf
),localbuf
+0x06);
573 textsize
= 5* CONV16(localbuf
,4);
579 /* fprintf(stdout,"T %d %d %d %d 1 1 %d 0\n",x,y,GRAPHIC_COLOR, TEXTSIZE, angle);
580 fprintf(stdout,"net=%s ATTACHME\n",textbuf); */
581 pending_netlabel
= 1;
582 strncpy(netlabel
, textbuf
, 256);
585 netlabel_angle
= angle
;
588 /* BAD Fix Entries */
590 void parse_entry (int fd
)
596 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
597 // fprintf(stderr,"Entry %d bytes\n",size);
599 x
=CONVX(CONV16(localbuf
,0));
600 y
=CONVY(CONV16(localbuf
,2));
602 fprintf(stderr
,"Entry %d %d type %d\n",x
,y
,type
);
605 /* BAD Fix Dashed Lines */
607 void parse_dashed (int fd
)
613 size
= read_block(fd
,localbuf
,4,sizeof(localbuf
));
614 fprintf(stderr
,"Dashed %d bytes\n",size
);
616 x
=CONVX(CONV16(localbuf
,0));
617 y
=CONVY(CONV16(localbuf
,2));
622 /* How do netlisters handle power connections/nets? */
624 void parse_power (int fd
)
634 size
= read_block(fd
,localbuf
,5,sizeof(localbuf
));
635 // fprintf(stderr,"POWER %d bytes\n",size);
637 read_string(textbuf
,sizeof(textbuf
),localbuf
+0x05);
639 x
=CONVX(CONV16(localbuf
,0));
640 y
=CONVY(CONV16(localbuf
,2));
644 case 0x04: angle
= 180; xtext
= x
; ytext
= y
- 600; break;
645 case 0x08: angle
= 90; ytext
= y
; xtext
= x
-600; break;
646 case 0x0C: angle
= 270;ytext
= y
; xtext
= x
+600; break;
647 default: angle
= 0; xtext
=x
;ytext
= y
+600;
651 /* BAD GEDA only has bar and circle pix. Also, they
652 * All say VCC or VDD, which they should not */
654 symbol
= "vcc-orcad-bar-1.sym";break; /* BAR */
655 case 0x00: /* circle */
656 case 0x01: /* arrow */
657 case 0x03: /* wave */
659 symbol
= "vcc-orcad-circle-1.sym";break;
661 fprintf(stdout
,"C %d %d 1 %d 0 %s\n",x
,y
,angle
,symbol
);
662 /* fprintf(stdout,"{\n"
663 "T %d %d %d %d 1 1 %d 0\n"
666 xtext,ytext,GRAPHIC_COLOR,TEXTSIZE,angle%180,textbuf);*/
668 "T %d %d %d %d 1 1 %d 0\n"
671 xtext
,ytext
,GRAPHIC_COLOR
,TEXTSIZE
,angle
%180,textbuf
);
674 /* BAD Fix Text color and check rotation */
675 /* BAD Fix multi-line text */
677 void parse_text (int fd
)
682 int x
,y
,textsize
,angle
;
684 size
= read_block(fd
,localbuf
,7,sizeof(localbuf
));
686 x
=CONVX(CONV16(localbuf
,0));
687 y
=CONVY(CONV16(localbuf
,2));
688 read_string(textbuf
,sizeof(textbuf
),localbuf
+6);
691 textsize
= TEXTSIZE
* CONV16(localbuf
,4);
697 fprintf(stdout
,"T %d %d %d %d 1 1 %d 0\n",x
,y
,GRAPHIC_COLOR
,textsize
,angle
);
698 fprintf(stdout
,"%s\n",textbuf
);
701 /* BAD - Markers are unimplemented in gEDA (yet).
702 * They are the no-connects that you can place on pins to
703 * exempt them from the connectivity checks in DRC/ERC
706 void parse_marker (int fd
)
711 size
= read_block(fd
,localbuf
,0,sizeof(localbuf
));
713 /* fprintf(stderr,"MARKER %d\n",size); */
717 int parse_block(int fd1
,int fd2
)
724 parse_titleblock(fd1
);
730 parse_component(fd1
,fd2
);
766 fprintf(stderr
,"\nUnknown Block Tag\n");
776 main(int argc
, char **argv
)
781 while ((c
= getopt(argc
, argv
, "d:hs:v")) > 0) {
787 scale
= atoi(optarg
);
790 fprintf(stderr
,"sarlacc_scheme ver %s\n", SARVERSION
);
795 fprintf(stderr
,"Convert Oracd schematics file (16 bit format) to gEDA\n");
797 fprintf(stderr
,"\nUsage: %s [options] infile >outfile\n"
799 "\n -d<dir> directory for symbols (from sarlacc_sym)"
801 "\n -s<n> scale <n>%%, default is %d"
804 argv
[0],DEFAULT_SCALE
);
810 if( optind
+1 != argc
)
815 /* BAD update to latest file format.. */
816 fprintf(stdout
,"v %s\n",GEDAVERSION
);
818 fd1
= open(argv
[optind
],O_RDONLY
);
821 fprintf(stderr
,"\nCould not open input file: %s\n",argv
[optind
]);
824 fd2
= open(argv
[optind
],O_RDONLY
);
827 fprintf(stderr
,"\n Could not open input file part deux\n");
831 parse_header(fd1
,fd2
);
833 while(parse_block(fd1
,fd2
));
834 fprintf(stderr
,"\n Normal End\n");