pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #include <stdio.h> 00040 #include <stdarg.h> 00041 #include <stdlib.h> 00042 #include <string.h> 00043 #include <time.h> 00044 00045 #include "data.h" 00046 #include "config.h" 00047 #include "global.h" 00048 #include "rats.h" 00049 #include "error.h" 00050 #include "find.h" 00051 #include "misc.h" 00052 #include "pcb-printf.h" 00053 00054 #include "hid.h" 00055 #include "hid/common/hidnogui.h" 00056 #include "../hidint.h" 00057 00058 #ifdef HAVE_LIBDMALLOC 00059 #include <dmalloc.h> 00060 #endif 00061 00062 static HID_Attribute IPCD356_options[] = 00063 { 00064 /* %start-doc options "95 IPC-D-356 Netlist Export" 00065 @ftable @code 00066 @item --netlist-file <string> 00067 Name of the IPC-D-356 Netlist output file. 00068 Parameter @code{<string>} can include a path. 00069 @end ftable 00070 %end-doc 00071 */ 00072 { 00073 "netlistfile", 00074 "Name of the IPC-D-356 Netlist output file", 00075 HID_String, 00076 0, 0, {0, 0, 0}, 0, 0 00077 }, 00078 #define HA_IPCD356_filename 0 00079 }; 00080 00081 #define NUM_OPTIONS (sizeof(IPCD356_options)/sizeof(IPCD356_options[0])) 00082 00083 static HID_Attr_Val IPCD356_values[NUM_OPTIONS]; 00084 00085 const char *IPCD356_filename; 00086 00087 typedef struct 00088 { 00089 char NName[11]; 00090 char NetName[256]; 00091 } IPCD356_Alias; 00092 00093 typedef struct 00094 { 00095 int AliasN; 00096 IPCD356_Alias *Alias; 00097 } IPCD356_AliasList; 00098 00099 void IPCD356_WriteNet (FILE *, char *); 00100 void IPCD356_WriteHeader (FILE *); 00101 void IPCD356_End (FILE *); 00102 int IPCD356_Netlist (void); 00103 int IPCD356_WriteAliases (FILE *, IPCD356_AliasList *); 00104 void ResetVisitPinsViasAndPads (void); 00105 void CheckNetLength (char *, IPCD356_AliasList *); 00106 IPCD356_AliasList *CreateAliasList (void); 00107 IPCD356_AliasList *AddAliasToList (IPCD356_AliasList *); 00108 int IPCD356_SanityCheck (void); 00109 00110 static HID_Attribute * 00111 IPCD356_get_export_options (int *n) 00112 { 00113 static char *last_IPCD356_filename = 0; 00114 00115 if (PCB) 00116 { 00117 derive_default_filename (PCB->Filename, &IPCD356_options[HA_IPCD356_filename], ".net", &last_IPCD356_filename); 00118 } 00119 00120 if (n) 00121 *n = NUM_OPTIONS; 00122 00123 return IPCD356_options; 00124 } 00125 00134 void 00135 IPCD356_WriteHeader (FILE * fd) 00136 { 00137 time_t currenttime; 00138 char utcTime[64]; 00139 const char *fmt = "%c UTC"; 00140 00141 currenttime = time (NULL); 00142 strftime (utcTime, sizeof utcTime, fmt, gmtime (¤ttime)); 00143 00144 fprintf (fd, 00145 "C IPC-D-356 Netlist generated by gEDA PCB " VERSION "\nC \n"); 00146 fprintf (fd, "C File created on %s\nC \n", utcTime); 00147 if (PCB->Name == NULL) 00148 { 00149 fprintf (fd, "P JOB %s\n", PCB->Filename); /* Use the file name if the PCB name in not set. */ 00150 } 00151 else 00152 { 00153 fprintf (fd, "P JOB %s\n", PCB->Name); 00154 } 00155 fprintf (fd, "P CODE 00\n"); 00156 if (strcmp (Settings.grid_unit->suffix,"mil") == 0) /* Use whatever unit is currently in use (mil or mm). */ 00157 { 00158 fprintf (fd, "P UNITS CUST 0\n"); 00159 } 00160 else 00161 { 00162 fprintf (fd, "P UNITS CUST 1\n"); 00163 } 00164 fprintf (fd, "P DIM N\n"); 00165 fprintf (fd, "P VER IPC-D-356\n"); 00166 fprintf (fd, "P IMAGE PRIMARY\nC \n"); 00167 } 00168 00169 00188 void 00189 IPCD356_WriteNet (FILE * fd, char *net) 00190 { 00191 int padx, pady, tmp; 00192 00193 ELEMENT_LOOP (PCB->Data); 00194 PAD_LOOP (element); 00195 if (TEST_FLAG (FOUNDFLAG, pad)) 00196 { 00197 fprintf (fd, "327%-17.14s", net); /* Net Name. */ 00198 fprintf (fd, "%-6.6s", element->Name[1].TextString); /* Refdes. */ 00199 fprintf (fd, "-%-4.4s", pad->Number); /* pin number. */ 00200 fprintf (fd, " "); 00201 fprintf (fd, " "); /* Drilled hole Id (blank for pads). */ 00202 if (TEST_FLAG (ONSOLDERFLAG, pad) == true) 00203 { 00204 fprintf (fd, "A02"); 00205 } 00206 else 00207 { 00208 fprintf (fd, "A01"); /* Top side. */ 00209 } 00210 padx = (pad->Point1.X + pad->Point2.X) / 2; /* X location in PCB units. */ 00211 pady = (PCB->MaxHeight - ((pad->Point1.Y + pad->Point2.Y) / 2)); /* Y location in PCB units. */ 00212 00213 if (strcmp (Settings.grid_unit->suffix, "mil") == 0) 00214 { 00215 padx = padx / 2540; /* X location in 0.0001". */ 00216 pady = pady / 2540; /* Y location in 0.0001". */ 00217 } 00218 else 00219 { 00220 padx = padx / 1000; /* X location in 0.001 mm. */ 00221 pady = pady / 1000; /* Y location in 0.001 mm. */ 00222 } 00223 fprintf (fd, "X%+6.6d", padx); /* X Pad center. */ 00224 fprintf (fd, "Y%+6.6d", pady); /* Y pad center. */ 00225 00226 padx = (pad->Thickness + (pad->Point2.X - pad->Point1.X)); /* Pad dimension X in PCB units. */ 00227 pady = (pad->Thickness + (pad->Point2.Y - pad->Point1.Y)); /* Pad dimension Y in PCB units. */ 00228 00229 if (strcmp(Settings.grid_unit->suffix, "mil") == 0) 00230 { 00231 padx = padx / 2540; /* X location in 0.0001". */ 00232 pady = pady / 2540; /* Y location in 0.0001". */ 00233 } 00234 else 00235 { 00236 padx = padx / 1000; // X location in 0.001mm 00237 pady = pady / 1000; // Y location in 0.001mm 00238 } 00239 00240 fprintf (fd, "X%4.4d", padx); 00241 fprintf (fd, "Y%4.4d", pady); 00242 fprintf (fd, "R000"); /* Rotation (0 degrees). */ 00243 fprintf (fd, " "); /* Column 72 should be left blank. */ 00244 if (pad->Mask > 0) 00245 { 00246 if (TEST_FLAG (ONSOLDERFLAG, pad) == true) 00247 { 00248 fprintf(fd, "S2"); /* Soldermask on bottom side. */ 00249 } 00250 else 00251 { 00252 fprintf(fd, "S1"); /* SolderMask on top side. */ 00253 } 00254 } 00255 else 00256 { 00257 fprintf(fd, "S3"); /* No soldermask. */ 00258 } 00259 fprintf (fd, " "); /* Padding. */ 00260 fprintf (fd, "\n"); 00261 SET_FLAG (VISITFLAG, pad); 00262 } 00263 00264 END_LOOP; /* Pad. */ 00265 PIN_LOOP (element); 00266 if (TEST_FLAG (FOUNDFLAG, pin)) 00267 { 00268 if (TEST_FLAG (HOLEFLAG, pin)) /* Non plated? */ 00269 { 00270 fprintf (fd, "367%-17.14s", net); /* Net Name. */ 00271 } 00272 else 00273 { 00274 fprintf (fd, "317%-17.14s", net); /* Net Name. */ 00275 } 00276 fprintf (fd, "%-6.6s", element->Name[1].TextString); /* Refdes. */ 00277 fprintf (fd, "-%-4.4s", pin->Number); /* Pin number. */ 00278 fprintf (fd, " "); 00279 tmp = pin->DrillingHole; 00280 if (strcmp (Settings.grid_unit->suffix, "mil") == 0) 00281 { 00282 tmp = tmp / 2540; /* 0.0001". */ 00283 } 00284 else 00285 { 00286 tmp = tmp / 1000; /* 0.001 mm. */ 00287 } 00288 00289 if (TEST_FLAG (HOLEFLAG, pin)) 00290 { 00291 fprintf (fd, "D%-4.4dU", tmp); /* Unplated Drilled hole Id. */ 00292 } 00293 else 00294 { 00295 fprintf (fd, "D%-4.4dP", tmp); /* Plated drill hole. */ 00296 } 00297 fprintf (fd, "A00"); /* Accessible from both sides. */ 00298 padx = pin->X; /* X location in PCB units. */ 00299 pady = (PCB->MaxHeight - pin->Y); /* Y location in PCB units.*/ 00300 00301 if (strcmp (Settings.grid_unit->suffix, "mil") == 0) 00302 { 00303 padx = padx / 2540; /* X location in 0.0001". */ 00304 pady = pady / 2540; /* Y location in 0.0001". */ 00305 } 00306 else 00307 { 00308 padx = padx / 1000; /* X location in 0.001 mm. */ 00309 pady = pady / 1000; /* Y location in 0.001 mm. */ 00310 } 00311 00312 fprintf (fd, "X%+6.6d", padx); /* X Pad center. */ 00313 fprintf (fd, "Y%+6.6d", pady); /* Y pad center. */ 00314 00315 padx = pin->Thickness; 00316 00317 if (strcmp (Settings.grid_unit->suffix, "mil") == 0) 00318 { 00319 padx = padx / 2540; /* X location in 0.0001". */ 00320 } 00321 else 00322 { 00323 padx = padx / 1000; /* X location in 0.001 mm. */ 00324 } 00325 00326 fprintf (fd, "X%4.4d", padx); /* Pad dimension X. */ 00327 if (TEST_FLAG (SQUAREFLAG, pin)) 00328 { 00329 fprintf (fd, "Y%4.4d", padx); /* Pad dimension Y. */ 00330 } 00331 else 00332 { 00333 fprintf (fd, "Y0000"); /* Y is 0 for round pins. */ 00334 } 00335 fprintf (fd, "R000"); /* Rotation (0 degrees). */ 00336 fprintf (fd, " "); /* Column 72 should be left blank.*/ 00337 if (pin->Mask > 0) 00338 { 00339 fprintf(fd, "S0"); /* No Soldermask. */ 00340 } 00341 else 00342 { 00343 fprintf(fd, "S3"); /* Soldermask on both sides. */ 00344 } 00345 fprintf (fd, " "); /* Padding. */ 00346 00347 fprintf (fd, "\n"); 00348 00349 SET_FLAG (VISITFLAG, pin); 00350 00351 } 00352 00353 END_LOOP; /* Pin. */ 00354 END_LOOP; /* Element */ 00355 00356 VIA_LOOP (PCB->Data); 00357 if (TEST_FLAG (FOUNDFLAG, via)) 00358 { 00359 if (TEST_FLAG (HOLEFLAG, via)) /* Non plated ? */ 00360 { 00361 fprintf (fd, "367%-17.14s", net); /* Net Name. */ 00362 } 00363 else 00364 { 00365 fprintf (fd, "317%-17.14s", net); /* Net Name. */ 00366 } 00367 fprintf (fd, "VIA "); /* Refdes. */ 00368 fprintf (fd, "- "); /* Pin number. */ 00369 fprintf (fd, " "); 00370 tmp = via->DrillingHole; 00371 if (strcmp (Settings.grid_unit->suffix, "mil") == 0) 00372 { 00373 tmp = tmp / 2540; /* 0.0001". */ 00374 } 00375 else 00376 { 00377 tmp = tmp / 1000; /* 0.001 mm. */ 00378 } 00379 00380 if (TEST_FLAG (HOLEFLAG, via)) 00381 { 00382 fprintf (fd, "D%-4.4dU", tmp); /* Unplated Drilled hole Id. */ 00383 } 00384 else 00385 { 00386 fprintf (fd, "D%-4.4dP", tmp); /* Plated drill hole. */ 00387 } 00388 fprintf (fd, "A00"); /* Accessible from both sides. */ 00389 padx = via->X; /* X location in PCB units. */ 00390 pady = (PCB->MaxHeight - via->Y); /* Y location in PCB units. */ 00391 00392 if (strcmp (Settings.grid_unit->suffix, "mil") == 0) 00393 { 00394 padx = padx / 2540; /* X location in 0.0001". */ 00395 pady = pady / 2540; /* Y location in 0.0001". */ 00396 } 00397 else 00398 { 00399 padx = padx / 1000; /* X location in 0.001 mm. */ 00400 pady = pady / 1000; /* Y location in 0.001 mm. */ 00401 } 00402 00403 fprintf (fd, "X%+6.6d", padx); /* X Pad center. */ 00404 fprintf (fd, "Y%+6.6d", pady); /* Y pad center. */ 00405 00406 padx = via->Thickness; 00407 00408 if (strcmp (Settings.grid_unit->suffix, "mil") == 0) 00409 { 00410 padx = padx / 2540; /* X location in 0.0001". */ 00411 } 00412 else 00413 { 00414 padx = padx / 1000; /* X location in 0.001 mm. */ 00415 } 00416 00417 fprintf (fd, "X%4.4d", padx); /* Pad dimension X. */ 00418 fprintf (fd, "Y0000"); /* Y is 0 for round pins (vias always round?). */ 00419 fprintf (fd, "R000"); /* Rotation (0 degrees). */ 00420 fprintf (fd, " "); /* Column 72 should be left blank. */ 00421 if (via->Mask > 0) 00422 { 00423 fprintf(fd, "S0"); /* No Soldermask. */ 00424 } 00425 else 00426 { 00427 fprintf(fd, "S3"); /* Soldermask on both sides. */ 00428 } 00429 fprintf (fd, " "); /* Padding. */ 00430 fprintf (fd, "\n"); 00431 SET_FLAG (VISITFLAG, via); 00432 } 00433 00434 END_LOOP; /* Via. */ 00435 } 00436 00437 00443 int 00444 IPCD356_Netlist (void) 00445 { 00446 FILE *fp; 00447 char nodename[256]; 00448 char net[256]; 00449 LibraryMenuType *netname; 00450 IPCD356_AliasList * aliaslist; 00451 00452 if (IPCD356_SanityCheck()) /* Check for invalid names + numbers. */ 00453 { 00454 Message ("Aborting.\n"); 00455 return(1); 00456 } 00457 00458 sprintf (net, "%s.ipc", PCB->Name); 00459 if (IPCD356_filename == NULL) 00460 return 1; 00461 00462 fp = fopen (IPCD356_filename, "w+"); 00463 if (fp == NULL) 00464 { 00465 Message ("error opening %s\n", IPCD356_filename); 00466 return 1; 00467 } 00468 /* free (IPCD356_filename); */ 00469 00470 00471 IPCD356_WriteHeader (fp); 00472 00473 aliaslist = CreateAliasList (); 00474 if (aliaslist == NULL) 00475 { 00476 Message ("Error Aloccating memory for IPC-D-356 AliasList\n"); 00477 return 1; 00478 } 00479 00480 if (IPCD356_WriteAliases (fp, aliaslist)) 00481 { 00482 Message ("Error Writing IPC-D-356 AliasList\n"); 00483 return 1; 00484 } 00485 00486 00487 ELEMENT_LOOP (PCB->Data); 00488 PIN_LOOP (element); 00489 if (!TEST_FLAG (VISITFLAG, pin)) 00490 { 00491 ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); 00492 ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); 00493 LookupConnectionByPin (PIN_TYPE, pin); 00494 sprintf (nodename, "%s-%s", element->Name[1].TextString, pin->Number); 00495 netname = netnode_to_netname (nodename); 00496 /* Message("Netname: %s\n", netname->Name +2); */ 00497 if (netname) 00498 { 00499 strcpy (net, &netname->Name[2]); 00500 CheckNetLength (net, aliaslist); 00501 } 00502 else 00503 { 00504 strcpy (net, "N/C"); 00505 } 00506 IPCD356_WriteNet (fp, net); 00507 } 00508 END_LOOP; /* Pin. */ 00509 PAD_LOOP (element); 00510 if (!TEST_FLAG (VISITFLAG, pad)) 00511 { 00512 ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); 00513 ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); 00514 LookupConnectionByPin (PAD_TYPE, pad); 00515 sprintf (nodename, "%s-%s", element->Name[1].TextString, pad->Number); 00516 netname = netnode_to_netname (nodename); 00517 /* Message("Netname: %s\n", netname->Name +2); */ 00518 if (netname) 00519 { 00520 strcpy (net, &netname->Name[2]); 00521 CheckNetLength (net, aliaslist); 00522 } 00523 else 00524 { 00525 strcpy (net, "N/C"); 00526 } 00527 IPCD356_WriteNet (fp, net); 00528 } 00529 END_LOOP; /* Pad. */ 00530 00531 END_LOOP; /* Element. */ 00532 00533 VIA_LOOP (PCB->Data); 00534 if (!TEST_FLAG (VISITFLAG, via)) 00535 { 00536 ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); 00537 ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); 00538 LookupConnectionByPin (PIN_TYPE, via); 00539 strcpy (net, "N/C"); 00540 IPCD356_WriteNet (fp, net); 00541 } 00542 END_LOOP; /* Via. */ 00543 00544 IPCD356_End (fp); 00545 fclose (fp); 00546 free (aliaslist); 00547 ResetVisitPinsViasAndPads (); 00548 ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); 00549 ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); 00550 return 0; 00551 } 00552 00553 void 00554 IPCD356_End (FILE * fd) 00555 { 00556 fprintf (fd, "999\n"); 00557 } 00558 00559 void 00560 ResetVisitPinsViasAndPads () 00561 { 00562 VIA_LOOP (PCB->Data); 00563 CLEAR_FLAG (VISITFLAG, via); 00564 END_LOOP; /* Via. */ 00565 ELEMENT_LOOP (PCB->Data); 00566 PIN_LOOP (element); 00567 CLEAR_FLAG (VISITFLAG, pin); 00568 END_LOOP; /* Pin. */ 00569 PAD_LOOP (element); 00570 CLEAR_FLAG (VISITFLAG, pad); 00571 END_LOOP; /* Pad. */ 00572 END_LOOP; /* Element. */ 00573 } 00574 00575 int 00576 IPCD356_WriteAliases (FILE * fd, IPCD356_AliasList * aliaslist) 00577 { 00578 int index; 00579 int i; 00580 00581 index = 1; 00582 00583 for (i = 0; i < PCB->NetlistLib.MenuN; i++) 00584 { 00585 if (strlen (PCB->NetlistLib.Menu[i].Name + 2) > 14) 00586 { 00587 if (index == 1) 00588 { 00589 fprintf (fd, "C Netname Aliases Section\n"); 00590 } 00591 aliaslist = AddAliasToList (aliaslist); 00592 if (aliaslist == NULL) 00593 { 00594 return 1; 00595 } 00596 sprintf (aliaslist->Alias[index].NName, "NNAME%-5.5d", index); 00597 strcpy (aliaslist->Alias[index].NetName, PCB->NetlistLib.Menu[i].Name + 2); 00598 00599 fprintf (fd, "P %s %-58.58s\n", aliaslist->Alias[index].NName, 00600 aliaslist->Alias[index].NetName); 00601 index++; 00602 } 00603 } 00604 if (index > 1) 00605 { 00606 fprintf (fd, "C End Netname Aliases Section\nC \n"); 00607 } 00608 return 0; 00609 } 00610 00611 IPCD356_AliasList * 00612 CreateAliasList () 00613 { 00614 IPCD356_AliasList * aliaslist; 00615 00616 aliaslist = malloc (sizeof (IPCD356_AliasList)); /* Create an alias list. */ 00617 aliaslist->AliasN = 0; /* Initialize Number of Alias. */ 00618 return aliaslist; 00619 } 00620 00621 IPCD356_AliasList * 00622 AddAliasToList (IPCD356_AliasList * aliaslist) 00623 { 00624 aliaslist->AliasN++; 00625 aliaslist->Alias = realloc (aliaslist->Alias, 00626 sizeof (IPCD356_Alias) * (aliaslist->AliasN + 1)); 00627 if (aliaslist->Alias == NULL) 00628 { 00629 return NULL; 00630 } 00631 return aliaslist; 00632 } 00633 00634 void 00635 CheckNetLength (char *net, IPCD356_AliasList * aliaslist) 00636 { 00637 int i; 00638 00639 if (strlen (net) > 14) 00640 { 00641 for (i = 1; i <= aliaslist->AliasN; i++) 00642 { 00643 if (strcmp (net, aliaslist->Alias[i].NetName) == 0) 00644 { 00645 strcpy (net, aliaslist->Alias[i].NName); 00646 } 00647 } 00648 } 00649 } 00650 00651 int 00652 IPCD356_SanityCheck() 00653 { 00654 ELEMENT_LOOP (PCB->Data); 00655 if (element->Name[1].TextString == '\0') 00656 { 00657 Message("Error: Found unnamed element. All elements need to be named to create an IPC-D-356 netlist.\n"); 00658 return(1); 00659 } 00660 END_LOOP; /* Element. */ 00661 return(0); 00662 } 00663 00664 static void 00665 IPCD356_do_export (HID_Attr_Val * options) 00666 { 00667 int i; 00668 00669 if (!options) 00670 { 00671 IPCD356_get_export_options (0); 00672 00673 for (i = 0; i < NUM_OPTIONS; i++) 00674 IPCD356_values[i] = IPCD356_options[i].default_val; 00675 00676 options = IPCD356_values; 00677 } 00678 00679 IPCD356_filename = options[HA_IPCD356_filename].str_value; 00680 if (!IPCD356_filename) 00681 IPCD356_filename = "pcb-out.net"; 00682 00683 IPCD356_Netlist (); 00684 } 00685 00686 static void 00687 IPCD356_parse_arguments (int *argc, char ***argv) 00688 { 00689 hid_register_attributes (IPCD356_options, 00690 sizeof (IPCD356_options) / sizeof (IPCD356_options[0])); 00691 hid_parse_command_line (argc, argv); 00692 } 00693 00694 HID IPCD356_hid; 00695 00696 void 00697 hid_ipcd356_init () 00698 { 00699 memset (&IPCD356_hid, 0, sizeof (HID)); 00700 00701 common_nogui_init (&IPCD356_hid); 00702 00703 IPCD356_hid.struct_size = sizeof (HID); 00704 IPCD356_hid.name = "IPC-D-356"; 00705 IPCD356_hid.description = "Exports a IPC-D-356 Netlist"; 00706 IPCD356_hid.exporter = 1; 00707 00708 IPCD356_hid.get_export_options = IPCD356_get_export_options; 00709 IPCD356_hid.do_export = IPCD356_do_export; 00710 IPCD356_hid.parse_arguments = IPCD356_parse_arguments; 00711 00712 hid_register_hid (&IPCD356_hid); 00713 00714 } 00715 00716 /* EOF */