void log_element(ElementType *e) { base_log("Element\n"); base_log("Description: %s\n", DESCRIPTION_NAME(e)); base_log("Name on PCB: %s\n", NAMEONPCB_NAME(e)); base_log("Value: %s\n", VALUE_NAME(e)); base_log("Flags: %04x\n", FLAG_VALUE(e->Flags)); base_log("MarkX, MarkY: %d, %d\n", e->MarkX, e->MarkY); base_log("PinN: %d\n", e->PinN); base_log("PadN: %d\n", e->PadN); base_log("LineN: %d\n", e->LineN); base_log("ArcN: %d\n", e->ArcN); base_log("Attributes number: %d\n", e->Attributes.Number); int i = 0; PAD_LOOP(e); { base_log("Pad %d\n", i++); log_pad(pad); } END_LOOP; i = 0; PIN_LOOP(e); { base_log("Pin %d\n", i++); log_pin(pin); } END_LOOP; }
static int replace_footprints(ElementTypePtr new_element) { int replaced = 0; int i = 0; ELEMENT_LOOP (PCB->Data); { if (match_mode != MATCH_MODE_AUTO || strcmp(DESCRIPTION_NAME(new_element), DESCRIPTION_NAME(element)) == 0) { Boolean matched = False; switch (style) { case STYLE_ALL: matched = True; break; case STYLE_SELECTED: matched = TEST_FLAG(SELECTEDFLAG, element); break; case STYLE_NAMED: for (i = 0; i < global_argc; i++) { if (NAMEONPCB_NAME(element) && strcasecmp(NAMEONPCB_NAME(element), global_argv[i]) == 0) { matched = True; break; } } break; } if (matched) { if (TEST_FLAG (LOCKFLAG, element)) { base_log("Skipping \"%s\". Element locked.\n", NAMEONPCB_NAME(element)); } else { debug_log("Considering \"%s\".\n", NAMEONPCB_NAME(element)); if (replace_one_footprint(element, new_element)) { base_log("Replaced \"%s\".\n", NAMEONPCB_NAME(element)); replaced++; } } } } } END_LOOP; return replaced; }
void ghid_pinout_window_show (GHidPort * out, ElementType * element) { GtkWidget *button, *vbox, *hbox, *preview, *top_window; gchar *title; int width, height; if (!element) return; title = g_strdup_printf ("%s [%s,%s]", UNKNOWN (DESCRIPTION_NAME (element)), UNKNOWN (NAMEONPCB_NAME (element)), UNKNOWN (VALUE_NAME (element))); top_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (top_window), title); g_free (title); gtk_window_set_wmclass (GTK_WINDOW (top_window), "PCB_Pinout", "PCB"); gtk_container_set_border_width (GTK_CONTAINER (top_window), 4); vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (top_window), vbox); preview = ghid_pinout_preview_new (element); gtk_box_pack_start (GTK_BOX (vbox), preview, TRUE, TRUE, 0); ghid_pinout_preview_get_natural_size (GHID_PINOUT_PREVIEW (preview), &width, &height); gtk_window_set_default_size (GTK_WINDOW (top_window), width + 50, height + 50); hbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); button = gtk_button_new_from_stock (GTK_STOCK_CLOSE); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (pinout_close_cb), top_window); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); gtk_widget_realize (top_window); if (Settings.AutoPlace) gtk_window_move (GTK_WINDOW (top_window), 10, 10); gtk_widget_show_all (top_window); }
/* --------------------------------------------------------------------------- * writes element data */ static void WriteElementData (FILE * FP, DataType *Data) { GList *n, *p; for (n = Data->Element; n != NULL; n = g_list_next (n)) { ElementType *element = n->data; /* only non empty elements */ if (!element->LineN && !element->PinN && !element->ArcN && !element->PadN) continue; /* the coordinates and text-flags are the same for * both names of an element */ fprintf (FP, "\nElement[%s ", F2S (element, ELEMENT_TYPE)); PrintQuotedString (FP, (char *)EMPTY (DESCRIPTION_NAME (element))); fputc (' ', FP); PrintQuotedString (FP, (char *)EMPTY (NAMEONPCB_NAME (element))); fputc (' ', FP); PrintQuotedString (FP, (char *)EMPTY (VALUE_NAME (element))); pcb_fprintf (FP, " %mr %mr %mr %mr %d %d %s]\n(\n", element->MarkX, element->MarkY, DESCRIPTION_TEXT (element).X - element->MarkX, DESCRIPTION_TEXT (element).Y - element->MarkY, DESCRIPTION_TEXT (element).Direction, DESCRIPTION_TEXT (element).Scale, F2S (&(DESCRIPTION_TEXT (element)), ELEMENTNAME_TYPE)); WriteAttributeList (FP, &element->Attributes, "\t"); for (p = element->Pin; p != NULL; p = g_list_next (p)) { PinType *pin = p->data; pcb_fprintf (FP, "\tPin[%mr %mr %mr %mr %mr %mr ", pin->X - element->MarkX, pin->Y - element->MarkY, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole); PrintQuotedString (FP, (char *)EMPTY (pin->Name)); fprintf (FP, " "); PrintQuotedString (FP, (char *)EMPTY (pin->Number)); fprintf (FP, " %s]\n", F2S (pin, PIN_TYPE)); } for (p = element->Pad; p != NULL; p = g_list_next (p)) { PadType *pad = p->data; pcb_fprintf (FP, "\tPad[%mr %mr %mr %mr %mr %mr %mr ", pad->Point1.X - element->MarkX, pad->Point1.Y - element->MarkY, pad->Point2.X - element->MarkX, pad->Point2.Y - element->MarkY, pad->Thickness, pad->Clearance, pad->Mask); PrintQuotedString (FP, (char *)EMPTY (pad->Name)); fprintf (FP, " "); PrintQuotedString (FP, (char *)EMPTY (pad->Number)); fprintf (FP, " %s]\n", F2S (pad, PAD_TYPE)); } for (p = element->Line; p != NULL; p = g_list_next (p)) { LineType *line = p->data; pcb_fprintf (FP, "\tElementLine [%mr %mr %mr %mr %mr]\n", line->Point1.X - element->MarkX, line->Point1.Y - element->MarkY, line->Point2.X - element->MarkX, line->Point2.Y - element->MarkY, line->Thickness); } for (p = element->Arc; p != NULL; p = g_list_next (p)) { ArcType *arc = p->data; pcb_fprintf (FP, "\tElementArc [%mr %mr %mr %mr %ma %ma %mr]\n", arc->X - element->MarkX, arc->Y - element->MarkY, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); } fputs ("\n\t)\n", FP); } }
/* --------------------------------------------------------------------------- * writes element data */ static void WriteElementData (FILE * FP, DataTypePtr Data) { int n, p; for (n = 0; n < Data->ElementN; n++) { ElementTypePtr element = &Data->Element[n]; /* only non empty elements */ if (!element->LineN && !element->PinN && !element->ArcN && !element->PadN) continue; /* the coordinates and text-flags are the same for * both names of an element */ fprintf (FP, "\nElement[%s ", F2S (element, ELEMENT_TYPE)); PrintQuotedString (FP, (char *)EMPTY (DESCRIPTION_NAME (element))); fputc (' ', FP); PrintQuotedString (FP, (char *)EMPTY (NAMEONPCB_NAME (element))); fputc (' ', FP); PrintQuotedString (FP, (char *)EMPTY (VALUE_NAME (element))); fprintf (FP, " %i %i %i %i %i %i %s]\n(\n", (int) element->MarkX, (int) element->MarkY, (int) (DESCRIPTION_TEXT (element).X - element->MarkX), (int) (DESCRIPTION_TEXT (element).Y - element->MarkY), (int) DESCRIPTION_TEXT (element).Direction, (int) DESCRIPTION_TEXT (element).Scale, F2S (&(DESCRIPTION_TEXT (element)), ELEMENTNAME_TYPE)); WriteAttributeList (FP, &element->Attributes, "\t"); for (p = 0; p < element->PinN; p++) { PinTypePtr pin = &element->Pin[p]; fprintf (FP, "\tPin[%i %i %i %i %i %i ", (int) (pin->X - element->MarkX), (int) (pin->Y - element->MarkY), (int) pin->Thickness, (int) pin->Clearance, (int) pin->Mask, (int) pin->DrillingHole); PrintQuotedString (FP, (char *)EMPTY (pin->Name)); fprintf (FP, " "); PrintQuotedString (FP, (char *)EMPTY (pin->Number)); fprintf (FP, " %s]\n", F2S (pin, PIN_TYPE)); } for (p = 0; p < element->PadN; p++) { PadTypePtr pad = &element->Pad[p]; fprintf (FP, "\tPad[%i %i %i %i %i %i %i ", (int) (pad->Point1.X - element->MarkX), (int) (pad->Point1.Y - element->MarkY), (int) (pad->Point2.X - element->MarkX), (int) (pad->Point2.Y - element->MarkY), (int) pad->Thickness, (int) pad->Clearance, (int) pad->Mask); PrintQuotedString (FP, (char *)EMPTY (pad->Name)); fprintf (FP, " "); PrintQuotedString (FP, (char *)EMPTY (pad->Number)); fprintf (FP, " %s]\n", F2S (pad, PAD_TYPE)); } for (p = 0; p < element->LineN; p++) { LineTypePtr line = &element->Line[p]; fprintf (FP, "\tElementLine [%i %i %i %i %i]\n", (int) (line->Point1.X - element->MarkX), (int) (line->Point1.Y - element->MarkY), (int) (line->Point2.X - element->MarkX), (int) (line->Point2.Y - element->MarkY), (int) line->Thickness); } for (p = 0; p < element->ArcN; p++) { ArcTypePtr arc = &element->Arc[p]; fprintf (FP, "\tElementArc [%i %i %i %i %i %i %i]\n", (int) (arc->X - element->MarkX), (int) (arc->Y - element->MarkY), (int) arc->Width, (int) arc->Height, (int) arc->StartAngle, (int) arc->Delta, (int) arc->Thickness); } fputs ("\n\t)\n", FP); } }
/* --------------------------------------------------------------------------- * copies data from one element to another and creates the destination * if necessary */ ElementType * CopyElementLowLevel (DataType *Data, ElementType *Src, bool uniqueName, Coord dx, Coord dy, int mask_flags) { int i; ElementType *Dest; /* both coordinates and flags are the same */ Dest = CreateNewElement (Data, &PCB->Font, MaskFlags (Src->Flags, mask_flags), DESCRIPTION_NAME (Src), NAMEONPCB_NAME (Src), VALUE_NAME (Src), DESCRIPTION_TEXT (Src).X + dx, DESCRIPTION_TEXT (Src).Y + dy, DESCRIPTION_TEXT (Src).Direction, DESCRIPTION_TEXT (Src).Scale, MaskFlags (DESCRIPTION_TEXT (Src).Flags, mask_flags), uniqueName); /* abort on error */ if (!Dest) return (Dest); ELEMENTLINE_LOOP (Src); { CreateNewLineInElement (Dest, line->Point1.X + dx, line->Point1.Y + dy, line->Point2.X + dx, line->Point2.Y + dy, line->Thickness); } END_LOOP; PIN_LOOP (Src); { CreateNewPin (Dest, pin->X + dx, pin->Y + dy, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole, pin->Name, pin->Number, MaskFlags (pin->Flags, mask_flags)); } END_LOOP; PAD_LOOP (Src); { CreateNewPad (Dest, pad->Point1.X + dx, pad->Point1.Y + dy, pad->Point2.X + dx, pad->Point2.Y + dy, pad->Thickness, pad->Clearance, pad->Mask, pad->Name, pad->Number, MaskFlags (pad->Flags, mask_flags)); } END_LOOP; ARC_LOOP (Src); { CreateNewArcInElement (Dest, arc->X + dx, arc->Y + dy, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); } END_LOOP; for (i=0; i<Src->Attributes.Number; i++) CreateNewAttribute (& Dest->Attributes, Src->Attributes.List[i].name, Src->Attributes.List[i].value); Dest->MarkX = Src->MarkX + dx; Dest->MarkY = Src->MarkY + dy; SetElementBoundingBox (Data, Dest, &PCB->Font); return (Dest); }
static int PrintBOM (void) { char utcTime[64]; Coord x, y; double theta = 0.0; double sumx, sumy; int pinfound[MAXREFPINS]; double pinx[MAXREFPINS]; double piny[MAXREFPINS]; double pinangle[MAXREFPINS]; double padcentrex, padcentrey; double centroidx, centroidy; double pin1x, pin1y; int pin_cnt; int found_any_not_at_centroid; int found_any; time_t currenttime; FILE *fp; BomList *bom = NULL; char *name, *descr, *value,*fixed_rotation; int rpindex; fp = fopen (xy_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", xy_filename); return 1; } /* Create a portable timestamp. */ currenttime = time (NULL); { /* avoid gcc complaints */ const char *fmt = "%c UTC"; strftime (utcTime, sizeof (utcTime), fmt, gmtime (¤ttime)); } fprintf (fp, "# PcbXY Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB X-Y\n", UNKNOWN (PCB->Name)); fprintf (fp, "# RefDes, Description, Value, X, Y, rotation, top/bottom\n"); /* don't use localized xy_unit->in_suffix here since */ /* the line itself is not localized and not for GUI */ fprintf (fp, "# X,Y in %s. rotation in degrees.\n", xy_unit->suffix); fprintf (fp, "# --------------------------------------------\n"); /* * For each element we calculate the centroid of the footprint. * In addition, we need to extract some notion of rotation. * While here generate the BOM list */ ELEMENT_LOOP (PCB->Data); { /* Initialize our pin count and our totals for finding the centroid. */ pin_cnt = 0; sumx = 0.0; sumy = 0.0; for (rpindex = 0; rpindex < MAXREFPINS; rpindex++) pinfound[rpindex] = 0; /* Insert this component into the bill of materials list. */ bom = bom_insert ((char *)UNKNOWN (NAMEONPCB_NAME (element)), (char *)UNKNOWN (DESCRIPTION_NAME (element)), (char *)UNKNOWN (VALUE_NAME (element)), bom); /* * Iterate over the pins and pads keeping a running count of how * many pins/pads total and the sum of x and y coordinates * * While we're at it, store the location of pin/pad #1 and #2 if * we can find them. */ PIN_LOOP (element); { sumx += (double) pin->X; sumy += (double) pin->Y; pin_cnt++; for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { if (NSTRCMP (pin->Number, reference_pin_names[rpindex]) == 0) { pinx[rpindex] = (double) pin->X; piny[rpindex] = (double) pin->Y; pinangle[rpindex] = 0.0; /* pins have no notion of angle */ pinfound[rpindex] = 1; } } } END_LOOP; PAD_LOOP (element); { sumx += (pad->Point1.X + pad->Point2.X) / 2.0; sumy += (pad->Point1.Y + pad->Point2.Y) / 2.0; pin_cnt++; for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { if (NSTRCMP (pad->Number, reference_pin_names[rpindex]) == 0) { padcentrex = (double) (pad->Point1.X + pad->Point2.X) / 2.0; padcentrey = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; pinx[rpindex] = padcentrex; piny[rpindex] = padcentrey; /* * NOTE: We swap the Y points because in PCB, the Y-axis * is inverted. Increasing Y moves down. We want to deal * in the usual increasing Y moves up coordinates though. */ pinangle[rpindex] = (180.0 / M_PI) * atan2 (pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); pinfound[rpindex]=1; } } } END_LOOP; if (pin_cnt > 0) { centroidx = sumx / (double) pin_cnt; centroidy = sumy / (double) pin_cnt; if (NSTRCMP( AttributeGetFromList (&element->Attributes,"xy-centre"), "origin") == 0 ) { x = element->MarkX; y = element->MarkY; } else { x = centroidx; y = centroidy; } fixed_rotation = AttributeGetFromList (&element->Attributes, "xy-fixed-rotation"); if (fixed_rotation) { /* The user specified a fixed rotation */ theta = atof (fixed_rotation); found_any_not_at_centroid = 1; found_any = 1; } else { /* Find first reference pin not at the centroid */ found_any_not_at_centroid = 0; found_any = 0; theta = 0.0; for (rpindex = 0; reference_pin_names[rpindex] && !found_any_not_at_centroid; rpindex++) { if (pinfound[rpindex]) { found_any = 1; /* Recenter pin "#1" onto the axis which cross at the part centroid */ pin1x = pinx[rpindex] - x; pin1y = piny[rpindex] - y; /* flip x, to reverse rotation for elements on back */ if (FRONT (element) != 1) pin1x = -pin1x; /* if only 1 pin, use pin 1's angle */ if (pin_cnt == 1) { theta = pinangle[rpindex]; found_any_not_at_centroid = 1; } else if ((pin1x != 0.0) || (pin1y != 0.0)) { theta = xyToAngle (pin1x, pin1y, pin_cnt > 2); found_any_not_at_centroid = 1; } } } if (!found_any) { Message ("PrintBOM(): unable to figure out angle because I could\n" " not find a suitable reference pin of element %s\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } else if (!found_any_not_at_centroid) { Message ("PrintBOM(): unable to figure out angle of element\n" " %s because the reference pin(s) are at the centroid of the part.\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } } name = CleanBOMString ((char *)UNKNOWN (NAMEONPCB_NAME (element))); descr = CleanBOMString ((char *)UNKNOWN (DESCRIPTION_NAME (element))); value = CleanBOMString ((char *)UNKNOWN (VALUE_NAME (element))); y = PCB->MaxHeight - y; pcb_fprintf (fp, "%m+%s,\"%s\",\"%s\",%.2mS,%.2mS,%g,%s\n", xy_unit->allow, name, descr, value, x, y, theta, FRONT (element) == 1 ? "top" : "bottom"); free (name); free (descr); free (value); } } END_LOOP; fclose (fp); /* Now print out a Bill of Materials file */ fp = fopen (bom_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", bom_filename); print_and_free (NULL, bom); return 1; } fprintf (fp, "# PcbBOM Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB BOM\n", UNKNOWN (PCB->Name)); fprintf (fp, "# Quantity, Description, Value, RefDes\n"); fprintf (fp, "# --------------------------------------------\n"); print_and_free (fp, bom); fclose (fp); return (0); }
bool vendorIsElementMappable (ElementType *element) { int i; int noskip; if (vendorMapEnable == false) return false; noskip = 1; for (i = 0; i < n_refdes; i++) { if ((NSTRCMP (UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]) == 0) || rematch (ignore_refdes[i], UNKNOWN (NAMEONPCB_NAME (element)))) { Message (_ ("Vendor mapping skipped because refdes = %s matches %s\n"), UNKNOWN (NAMEONPCB_NAME (element)), ignore_refdes[i]); noskip = 0; } } if (noskip) for (i = 0; i < n_value; i++) { if ((NSTRCMP (UNKNOWN (VALUE_NAME (element)), ignore_value[i]) == 0) || rematch (ignore_value[i], UNKNOWN (VALUE_NAME (element)))) { Message (_ ("Vendor mapping skipped because value = %s matches %s\n"), UNKNOWN (VALUE_NAME (element)), ignore_value[i]); noskip = 0; } } if (noskip) for (i = 0; i < n_descr; i++) { if ((NSTRCMP (UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i]) == 0) || rematch (ignore_descr[i], UNKNOWN (DESCRIPTION_NAME (element)))) { Message (_ ("Vendor mapping skipped because descr = %s matches %s\n"), UNKNOWN (DESCRIPTION_NAME (element)), ignore_descr[i]); noskip = 0; } } if (noskip && TEST_FLAG (LOCKFLAG, element)) { Message (_("Vendor mapping skipped because element %s is locked\n"), UNKNOWN (NAMEONPCB_NAME (element))); noskip = 0; } if (noskip) return true; else return false; }
static void apply_vendor_map (void) { int i; int changed, tot; bool state; state = vendorMapEnable; /* enable mapping */ vendorMapEnable = true; /* reset our counts */ changed = 0; tot = 0; /* If we have loaded vendor drills, then apply them to the design */ if (n_vendor_drills > 0) { /* first all the vias */ VIA_LOOP (PCB->Data); { tot++; if (via->DrillingHole != vendorDrillMap (via->DrillingHole)) { /* only change unlocked vias */ if (!TEST_FLAG (LOCKFLAG, via)) { if (ChangeObject2ndSize (VIA_TYPE, via, NULL, NULL, vendorDrillMap (via->DrillingHole), true, false)) changed++; else { Message (_ ("Via at %.2f, %.2f not changed. Possible reasons:\n" "\t- pad size too small\n" "\t- new size would be too large or too small\n"), 0.01 * via->X, 0.01 * via->Y); } } else { Message (_("Locked via at %.2f, %.2f not changed.\n"), 0.01 * via->X, 0.01 * via->Y); } } } END_LOOP; /* and now the pins */ ELEMENT_LOOP (PCB->Data); { /* * first figure out if this element should be skipped for some * reason */ if (vendorIsElementMappable (element)) { /* the element is ok to modify, so iterate over its pins */ PIN_LOOP (element); { tot++; if (pin->DrillingHole != vendorDrillMap (pin->DrillingHole)) { if (!TEST_FLAG (LOCKFLAG, pin)) { if (ChangeObject2ndSize (PIN_TYPE, element, pin, NULL, vendorDrillMap (pin-> DrillingHole), true, false)) changed++; else { Message (_ ("Pin %s (%s) at %.2f, %.2f (element %s, %s, %s) not changed.\n" "\tPossible reasons:\n" "\t- pad size too small\n" "\t- new size would be too large or too small\n"), UNKNOWN (pin->Number), UNKNOWN (pin->Name), 0.01 * pin->X, 0.01 * pin->Y, UNKNOWN (NAMEONPCB_NAME (element)), UNKNOWN (VALUE_NAME (element)), UNKNOWN (DESCRIPTION_NAME (element))); } } else { Message (_ ("Locked pin at %-6.2f, %-6.2f not changed.\n"), 0.01 * pin->X, 0.01 * pin->Y); } } } END_LOOP; } } END_LOOP; Message (_("Updated %d drill sizes out of %d total\n"), changed, tot); /* Update the current Via */ if (Settings.ViaDrillingHole != vendorDrillMap (Settings.ViaDrillingHole)) { changed++; Settings.ViaDrillingHole = vendorDrillMap (Settings.ViaDrillingHole); Message (_("Adjusted active via hole size to be %6.2f mils\n"), 0.01 * Settings.ViaDrillingHole); } /* and update the vias for the various routing styles */ for (i = 0; i < NUM_STYLES; i++) { if (PCB->RouteStyle[i].Hole != vendorDrillMap (PCB->RouteStyle[i].Hole)) { changed++; PCB->RouteStyle[i].Hole = vendorDrillMap (PCB->RouteStyle[i].Hole); Message (_ ("Adjusted %s routing style via hole size to be %6.2f mils\n"), PCB->RouteStyle[i].Name, 0.01 * PCB->RouteStyle[i].Hole); if (PCB->RouteStyle[i].Diameter < PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER) { PCB->RouteStyle[i].Diameter = PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER; Message (_ ("Increased %s routing style via diameter to %6.2f mils\n"), PCB->RouteStyle[i].Name, 0.01 * PCB->RouteStyle[i].Diameter); } } } /* * if we've changed anything, indicate that we need to save the * file, redraw things, and make sure we can undo. */ if (changed) { SetChangedFlag (true); Redraw (); IncrementUndoSerialNumber (); } } /* restore mapping on/off */ vendorMapEnable = state; }
static int PrintBOM (void) { char utcTime[64]; Coord x, y; double theta = 0.0; double sumx, sumy; double pin1x = 0.0, pin1y = 0.0, pin1angle = 0.0; double pin2x = 0.0, pin2y = 0.0; int found_pin1; int found_pin2; int pin_cnt; time_t currenttime; FILE *fp; BomList *bom = NULL; char *name, *descr, *value; fp = fopen (xy_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", xy_filename); return 1; } /* Create a portable timestamp. */ currenttime = time (NULL); { /* avoid gcc complaints */ const char *fmt = "%c UTC"; strftime (utcTime, sizeof (utcTime), fmt, gmtime (¤ttime)); } fprintf (fp, "# PcbXY Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB X-Y\n", UNKNOWN (PCB->Name)); fprintf (fp, "# RefDes, Description, Value, X, Y, rotation, top/bottom\n"); fprintf (fp, "# X,Y in %s. rotation in degrees.\n", xy_unit->in_suffix); fprintf (fp, "# --------------------------------------------\n"); /* * For each element we calculate the centroid of the footprint. * In addition, we need to extract some notion of rotation. * While here generate the BOM list */ ELEMENT_LOOP (PCB->Data); { /* initialize our pin count and our totals for finding the centriod */ pin_cnt = 0; sumx = 0.0; sumy = 0.0; found_pin1 = 0; found_pin2 = 0; /* insert this component into the bill of materials list */ bom = bom_insert ((char *)UNKNOWN (NAMEONPCB_NAME (element)), (char *)UNKNOWN (DESCRIPTION_NAME (element)), (char *)UNKNOWN (VALUE_NAME (element)), bom); /* * iterate over the pins and pads keeping a running count of how * many pins/pads total and the sum of x and y coordinates * * While we're at it, store the location of pin/pad #1 and #2 if * we can find them */ PIN_LOOP (element); { sumx += (double) pin->X; sumy += (double) pin->Y; pin_cnt++; if (NSTRCMP (pin->Number, "1") == 0) { pin1x = (double) pin->X; pin1y = (double) pin->Y; pin1angle = 0.0; /* pins have no notion of angle */ found_pin1 = 1; } else if (NSTRCMP (pin->Number, "2") == 0) { pin2x = (double) pin->X; pin2y = (double) pin->Y; found_pin2 = 1; } } END_LOOP; PAD_LOOP (element); { sumx += (pad->Point1.X + pad->Point2.X) / 2.0; sumy += (pad->Point1.Y + pad->Point2.Y) / 2.0; pin_cnt++; if (NSTRCMP (pad->Number, "1") == 0) { pin1x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; pin1y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; /* * NOTE: We swap the Y points because in PCB, the Y-axis * is inverted. Increasing Y moves down. We want to deal * in the usual increasing Y moves up coordinates though. */ pin1angle = (180.0 / M_PI) * atan2 (pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); found_pin1 = 1; } else if (NSTRCMP (pad->Number, "2") == 0) { pin2x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; pin2y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; found_pin2 = 1; } } END_LOOP; if (pin_cnt > 0) { x = sumx / (double) pin_cnt; y = sumy / (double) pin_cnt; if (found_pin1) { /* recenter pin #1 onto the axis which cross at the part centroid */ pin1x -= x; pin1y -= y; pin1y = -1.0 * pin1y; /* if only 1 pin, use pin 1's angle */ if (pin_cnt == 1) theta = pin1angle; else { /* if pin #1 is at (0,0) use pin #2 for rotation */ if ((pin1x == 0.0) && (pin1y == 0.0)) { if (found_pin2) theta = xyToAngle (pin2x, pin2y); else { Message ("PrintBOM(): unable to figure out angle of element\n" " %s because pin #1 is at the centroid of the part.\n" " and I could not find pin #2's location\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } } else theta = xyToAngle (pin1x, pin1y); } } /* we did not find pin #1 */ else { theta = 0.0; Message ("PrintBOM(): unable to figure out angle because I could\n" " not find pin #1 of element %s\n" " Setting to %g degrees\n", UNKNOWN (NAMEONPCB_NAME (element)), theta); } name = CleanBOMString ((char *)UNKNOWN (NAMEONPCB_NAME (element))); descr = CleanBOMString ((char *)UNKNOWN (DESCRIPTION_NAME (element))); value = CleanBOMString ((char *)UNKNOWN (VALUE_NAME (element))); y = PCB->MaxHeight - y; pcb_fprintf (fp, "%m+%s,\"%s\",\"%s\",%mS,%.2mS,%g,%s\n", xy_unit->allow, name, descr, value, x, y, theta, FRONT (element) == 1 ? "top" : "bottom"); free (name); free (descr); free (value); } } END_LOOP; fclose (fp); /* Now print out a Bill of Materials file */ fp = fopen (bom_filename, "w"); if (!fp) { gui->log ("Cannot open file %s for writing\n", bom_filename); print_and_free (NULL, bom); return 1; } fprintf (fp, "# PcbBOM Version 1.0\n"); fprintf (fp, "# Date: %s\n", utcTime); fprintf (fp, "# Author: %s\n", pcb_author ()); fprintf (fp, "# Title: %s - PCB BOM\n", UNKNOWN (PCB->Name)); fprintf (fp, "# Quantity, Description, Value, RefDes\n"); fprintf (fp, "# --------------------------------------------\n"); print_and_free (fp, bom); fclose (fp); return (0); }