Example #1
0
/*!
 * \brief Find the specified element.
 *
 * Usage: FindElement(Refdes)\n
 * If no argument is passed, no action is carried out.
 */
static int
find_element (int argc, char **argv, Coord x, Coord y)
{
  if (argc == 0 || strcasecmp (argv[0], "") == 0)
  {
    Message ("WARNING: in FindElement the argument should be a non-empty string value.\n");
      return 0;
  }
  else
  {
    SET_FLAG (NAMEONPCBFLAG, PCB);
    ELEMENT_LOOP(PCB->Data);
    {
      if (NAMEONPCB_NAME(element)
        && strcmp (argv[0], NAMEONPCB_NAME(element)) == 0)
      {
        gui->set_crosshair
        (
          element->MarkX,
          element->MarkY,
          HID_SC_PAN_VIEWPORT
        );
      }
    }
    END_LOOP;
    gui->invalidate_all ();
    IncrementUndoSerialNumber ();
    return 0;
  };
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
File: report.c Project: thequux/pcb
static int
ReportFoundPins (int argc, char **argv, int x, int y)
{
  static DynamicStringType list;
  char temp[64];
  int col = 0;

  DSClearString (&list);
  DSAddString (&list, "The following pins/pads are FOUND:\n");
  ELEMENT_LOOP (PCB->Data);
  {
    PIN_LOOP (element);
    {
      if (TEST_FLAG (FOUNDFLAG, pin))
	{
	  sprintf (temp, "%s-%s,%c",
		   NAMEONPCB_NAME (element),
		   pin->Number,
		   ((col++ % (COLUMNS + 1)) == COLUMNS) ? '\n' : ' ');
	  DSAddString (&list, temp);
	}
    }
    END_LOOP;
    PAD_LOOP (element);
    {
      if (TEST_FLAG (FOUNDFLAG, pad))
	{
	  sprintf (temp, "%s-%s,%c",
		   NAMEONPCB_NAME (element), pad->Number,
		   ((col++ % (COLUMNS + 1)) == COLUMNS) ? '\n' : ' ');
	  DSAddString (&list, temp);
	}
    }
    END_LOOP;
  }
  END_LOOP;

  HideCrosshair (false);
  gui->report_dialog ("Report", list.Data);
  RestoreCrosshair (false);
  return 0;
}
Example #5
0
static int
renumber_block (int argc, char **argv, Coord x, Coord y)
{
  char num_buf[15];
  int old_base, new_base;

  if (argc < 2) {
    Message("Usage: RenumberBlock oldnum newnum");
    return 1;
  }

  old_base = atoi (argv[0]);
  new_base = atoi (argv[1]);

  SET_FLAG (NAMEONPCBFLAG, PCB);

  ELEMENT_LOOP (PCB->Data);
  {
    char *refdes_split, *cp;
    char *old_ref, *new_ref;
    int num;

    if (!TEST_FLAG (SELECTEDFLAG, element))
      continue;

    old_ref = element->Name[1].TextString;
    for (refdes_split=cp=old_ref; *cp; cp++)
      if (!isdigit(*cp))
        refdes_split = cp+1;

    num = atoi (refdes_split);
    num += (new_base - old_base);
    sprintf(num_buf, "%d" ,num);
    new_ref = (char *) malloc (refdes_split - old_ref + strlen(num_buf) + 1);
    memcpy (new_ref, old_ref, refdes_split - old_ref);
    strcpy (new_ref + (refdes_split - old_ref), num_buf);

    AddObjectToChangeNameUndoList (ELEMENT_TYPE, NULL, NULL,
                                   element,
                                   NAMEONPCB_NAME (element));

    ChangeObjectName (ELEMENT_TYPE, element, NULL, NULL, new_ref);
  }
  END_LOOP;
  IncrementUndoSerialNumber ();
  return 0;
}
Example #6
0
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);
}
Example #7
0
File: rats.c Project: rlutz/pcb
/*!
 * \brief This function is moved from the original netlist.c as
 * part of the gui code separation for the Gtk port.
 */
char *
ConnectionName (int type, void *ptr1, void *ptr2)
{
  static char name[256];
  char *num;

  switch (type)
    {
    case PIN_TYPE:
      num = ((PinType *) ptr2)->Number;
      break;
    case PAD_TYPE:
      num = ((PadType *) ptr2)->Number;
      break;
    default:
      return (NULL);
    }
  strcpy (name, UNKNOWN (NAMEONPCB_NAME ((ElementType *) ptr1)));
  strcat (name, "-");
  strcat (name, UNKNOWN (num));
  return (name);
}
Example #8
0
File: rats.c Project: rlutz/pcb
/*!
 * \brief Read the library-netlist build a true Netlist structure.
 */
NetListType *
ProcNetlist (LibraryType *net_menu)
{
  ConnectionType *connection;
  ConnectionType LastPoint;
  NetType *net;
  static NetListType *Wantlist = NULL;

  if (!net_menu->MenuN)
    return (NULL);
  FreeNetListMemory (Wantlist);
  free (Wantlist);
  badnet = false;

  /* find layer groups of the component side and solder side */
  bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE);
  top_group = GetLayerGroupNumberBySide (TOP_SIDE);

  Wantlist = (NetListType *)calloc (1, sizeof (NetListType));
  if (Wantlist)
    {
      ALLPIN_LOOP (PCB->Data);
      {
	pin->Spare = NULL;
	CLEAR_FLAG (DRCFLAG, pin);
      }
      ENDALL_LOOP;
      ALLPAD_LOOP (PCB->Data);
      {
	pad->Spare = NULL;
	CLEAR_FLAG (DRCFLAG, pad);
      }
      ENDALL_LOOP;
      MENU_LOOP (net_menu);
      {
	if (menu->Name[0] == '*' || menu->flag == 0)
	  {
	    badnet = true;
	    continue;
	  }
	net = GetNetMemory (Wantlist);
	if (menu->Style)
	  {
	    STYLE_LOOP (PCB);
	    {
	      if (style->Name && !NSTRCMP (style->Name, menu->Style))
		{
		  net->Style = style;
		  break;
		}
	    }
	    END_LOOP;
	  }
	else			/* default to NULL if none found */
	  net->Style = NULL;
	ENTRY_LOOP (menu);
	{
	  if (SeekPad (entry, &LastPoint, false))
	    {
	      if (TEST_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2))
		Message (_
			 ("Error! Element %s pin %s appears multiple times in the netlist file.\n"),
			 NAMEONPCB_NAME ((ElementType *) LastPoint.ptr1),
			 (LastPoint.type ==
			  PIN_TYPE) ? ((PinType *) LastPoint.ptr2)->
			 Number : ((PadType *) LastPoint.ptr2)->Number);
	      else
		{
		  connection = GetConnectionMemory (net);
		  *connection = LastPoint;
		  /* indicate expect net */
		  connection->menu = menu;
		  /* mark as visited */
		  SET_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2);
		  if (LastPoint.type == PIN_TYPE)
		    ((PinType *) LastPoint.ptr2)->Spare = (void *) menu;
		  else
		    ((PadType *) LastPoint.ptr2)->Spare = (void *) menu;
		}
	    }
	  else
	    badnet = true;
	  /* check for more pins with the same number */
	  for (; SeekPad (entry, &LastPoint, true);)
	    {
	      connection = GetConnectionMemory (net);
	      *connection = LastPoint;
	      /* indicate expect net */
	      connection->menu = menu;
	      /* mark as visited */
	      SET_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2);
	      if (LastPoint.type == PIN_TYPE)
		((PinType *) LastPoint.ptr2)->Spare = (void *) menu;
	      else
		((PadType *) LastPoint.ptr2)->Spare = (void *) menu;
	    }
	}
	END_LOOP;
      }
      END_LOOP;
    }
  /* clear all visit marks */
  ALLPIN_LOOP (PCB->Data);
  {
    CLEAR_FLAG (DRCFLAG, pin);
  }
  ENDALL_LOOP;
  ALLPAD_LOOP (PCB->Data);
  {
    CLEAR_FLAG (DRCFLAG, pad);
  }
  ENDALL_LOOP;
  return (Wantlist);
}
Example #9
0
/* ---------------------------------------------------------------------------
 * 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);
    }
}
Example #10
0
File: file.c Project: thequux/pcb
/* ---------------------------------------------------------------------------
 * 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);
    }
}
Example #11
0
/* ---------------------------------------------------------------------------
 * 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);
}
Example #12
0
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 (&currenttime));
  }
  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);
}
Example #13
0
File: rats.c Project: rlutz/pcb
/*!
 * \brief This function is moved from the original netlist.c as
 * part of the gui code separation for the Gtk port.
 */
RatType *
AddNet (void)
{
  static int ratDrawn = 0;
  char name1[256], *name2;
  Cardinal group1, group2;
  char ratname[20];
  int found;
  void *ptr1, *ptr2, *ptr3;
  LibraryMenuType *menu;
  LibraryEntryType *entry;

  if (Crosshair.AttachedLine.Point1.X == Crosshair.AttachedLine.Point2.X
      && Crosshair.AttachedLine.Point1.Y == Crosshair.AttachedLine.Point2.Y)
    return (NULL);

  found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3,
				  Crosshair.AttachedLine.Point1.X,
				  Crosshair.AttachedLine.Point1.Y, 5);
  if (found == NO_TYPE)
    {
      Message (_("No pad/pin under rat line\n"));
      return (NULL);
    }
  if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL
      || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0)
    {
      Message (_("You must name the starting element first\n"));
      return (NULL);
    }

  /* will work for pins to since the FLAG is common */
  group1 = GetLayerGroupNumberBySide (
            TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE);
  strcpy (name1, ConnectionName (found, ptr1, ptr2));
  found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3,
				  Crosshair.AttachedLine.Point2.X,
				  Crosshair.AttachedLine.Point2.Y, 5);
  if (found == NO_TYPE)
    {
      Message (_("No pad/pin under rat line\n"));
      return (NULL);
    }
  if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL
      || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0)
    {
      Message (_("You must name the ending element first\n"));
      return (NULL);
    }
  group2 = GetLayerGroupNumberBySide (
            TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE);
  name2 = ConnectionName (found, ptr1, ptr2);

  menu = netnode_to_netname (name1);
  if (menu)
    {
      if (netnode_to_netname (name2))
	{
	  Message (_
		   ("Both connections already in netlist - cannot merge nets\n"));
	  return (NULL);
	}
      entry = GetLibraryEntryMemory (menu);
      entry->ListEntry = strdup (name2);
      netnode_to_netname (name2);
      goto ratIt;
    }
  /* ok, the first name did not belong to a net */
  menu = netnode_to_netname (name2);
  if (menu)
    {
      entry = GetLibraryEntryMemory (menu);
      entry->ListEntry = strdup (name1);
      netnode_to_netname (name1);
      goto ratIt;
    }

  /*
   * neither belong to a net, so create a new one.
   *
   * before creating a new rats here, we need to search
   * for a unique name.
   */
  sprintf (ratname, "  ratDrawn%i", ++ratDrawn);
  while (rat_used (ratname))
    {
      sprintf (ratname, "  ratDrawn%i", ++ratDrawn);
    }

  menu = GetLibraryMenuMemory (&PCB->NetlistLib);
  menu->Name = strdup (ratname);
  entry = GetLibraryEntryMemory (menu);
  entry->ListEntry = strdup (name1);
  entry = GetLibraryEntryMemory (menu);
  entry->ListEntry = strdup (name2);
  menu->flag = 1;

ratIt:
  NetlistChanged (0);
  return (CreateNewRat (PCB->Data, Crosshair.AttachedLine.Point1.X,
			Crosshair.AttachedLine.Point1.Y,
			Crosshair.AttachedLine.Point2.X,
			Crosshair.AttachedLine.Point2.Y,
			group1, group2, Settings.RatThickness, NoFlags ()));
}
Example #14
0
/*---------------------------------------------------------------------------
 *
 * break buffer element into pieces
 */
bool
SmashBufferElement (BufferType *Buffer)
{
  ElementType *element;
  Cardinal group;
  LayerType *clayer, *slayer;

  if (Buffer->Data->ElementN != 1)
    {
      Message (_("Error!  Buffer doesn't contain a single element\n"));
      return (false);
    }
  /*
   * At this point the buffer should contain just a single element.
   * Now we detach the single element from the buffer and then clear the
   * buffer, ready to receive the smashed elements.  As a result of detaching
   * it the single element is orphaned from the buffer and thus will not be
   * free()'d by FreeDataMemory (called via ClearBuffer).  This leaves it
   * around for us to smash bits off it.  It then becomes our responsibility,
   * however, to free the single element when we're finished with it.
   */
  element = Buffer->Data->Element->data;
  Buffer->Data->Element = NULL;
  Buffer->Data->ElementN = 0;
  ClearBuffer (Buffer);
  ELEMENTLINE_LOOP (element);
  {
    CreateNewLineOnLayer (&Buffer->Data->SILKLAYER,
			  line->Point1.X, line->Point1.Y,
			  line->Point2.X, line->Point2.Y,
			  line->Thickness, 0, NoFlags ());
    if (line)
      line->Number = STRDUP (NAMEONPCB_NAME (element));
  }
  END_LOOP;
  ARC_LOOP (element);
  {
    CreateNewArcOnLayer (&Buffer->Data->SILKLAYER,
			 arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle,
			 arc->Delta, arc->Thickness, 0, NoFlags ());
  }
  END_LOOP;
  PIN_LOOP (element);
  {
    FlagType f = NoFlags ();
    AddFlags (f, VIAFLAG);
    if (TEST_FLAG (HOLEFLAG, pin))
      AddFlags (f, HOLEFLAG);

    CreateNewVia (Buffer->Data, pin->X, pin->Y,
		  pin->Thickness, pin->Clearance, pin->Mask,
		  pin->DrillingHole, pin->Number, f);
  }
  END_LOOP;
  group =
    GetLayerGroupNumberByNumber (SWAP_IDENT ? solder_silk_layer :
					      component_silk_layer);
  clayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]];
  group =
    GetLayerGroupNumberByNumber (SWAP_IDENT ? component_silk_layer :
					      solder_silk_layer);
  slayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]];
  PAD_LOOP (element);
  {
    LineType *line;
    line = CreateNewLineOnLayer (TEST_FLAG (ONSOLDERFLAG, pad) ? slayer : clayer,
				 pad->Point1.X, pad->Point1.Y,
				 pad->Point2.X, pad->Point2.Y,
				 pad->Thickness, pad->Clearance, NoFlags ());
    if (line)
      line->Number = STRDUP (pad->Number);
  }
  END_LOOP;
  FreeElementMemory (element);
  g_slice_free (ElementType, element);
  return (true);
}
Example #15
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;
}
Example #16
0
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;
}
Example #17
0
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 (&currenttime));
  }
  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);
}
Example #18
0
/*---------------------------------------------------------------------------
 *
 * convert buffer contents into an element
 */
bool
ConvertBufferToElement (BufferType *Buffer)
{
  ElementType *Element;
  Cardinal group;
  Cardinal pin_n = 1;
  bool hasParts = false, crooked = false;
  int onsolder;
  bool warned = false;

  if (Buffer->Data->pcb == 0)
    Buffer->Data->pcb = PCB;

  Element = CreateNewElement (PCB->Data, &PCB->Font, NoFlags (),
			      NULL, NULL, NULL, PASTEBUFFER->X,
			      PASTEBUFFER->Y, 0, 100,
			      MakeFlags (SWAP_IDENT ? ONSOLDERFLAG : NOFLAG),
			      false);
  if (!Element)
    return (false);
  VIA_LOOP (Buffer->Data);
  {
    char num[8];
    if (via->Mask < via->Thickness)
      via->Mask = via->Thickness + 2 * MASKFRAME;
    if (via->Name)
      CreateNewPin (Element, via->X, via->Y, via->Thickness,
		    via->Clearance, via->Mask, via->DrillingHole,
		    NULL, via->Name, MaskFlags (via->Flags,
						VIAFLAG | NOCOPY_FLAGS |
						SELECTEDFLAG | WARNFLAG));
    else
      {
	sprintf (num, "%d", pin_n++);
	CreateNewPin (Element, via->X, via->Y, via->Thickness,
		      via->Clearance, via->Mask, via->DrillingHole,
		      NULL, num, MaskFlags (via->Flags,
					    VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG
					    | WARNFLAG));
      }
    hasParts = true;
  }
  END_LOOP;

  for (onsolder = 0; onsolder < 2; onsolder ++)
    {
      int silk_layer;
      int onsolderflag;

      if ((!onsolder) == (!SWAP_IDENT))
	{
	  silk_layer = component_silk_layer;
	  onsolderflag = NOFLAG;
	}
      else
	{
	  silk_layer = solder_silk_layer;
	  onsolderflag = ONSOLDERFLAG;
	}

#define MAYBE_WARN() \
	  if (onsolder && !hasParts && !warned) \
	    { \
	      warned = true; \
	      Message \
		(_("Warning: All of the pads are on the opposite\n" \
		   "side from the component - that's probably not what\n" \
		   "you wanted\n")); \
	    } \

      /* get the component-side SM pads */
      group = GetLayerGroupNumberByNumber (silk_layer);
      GROUP_LOOP (Buffer->Data, group);
      {
	char num[8];
	LINE_LOOP (layer);
	{
	  sprintf (num, "%d", pin_n++);
	  CreateNewPad (Element, line->Point1.X,
			line->Point1.Y, line->Point2.X,
			line->Point2.Y, line->Thickness,
			line->Clearance,
			line->Thickness + line->Clearance, NULL,
			line->Number ? line->Number : num,
			MakeFlags (onsolderflag));
	  MAYBE_WARN();
	  hasParts = true;
	}
	END_LOOP;
	POLYGON_LOOP (layer);
	{
	  Coord x1, y1, x2, y2, w, h, t;

	  if (! polygon_is_rectangle (polygon))
	    {
	      crooked = true;
	      continue;
	    }

	  w = polygon->Points[2].X - polygon->Points[0].X;
	  h = polygon->Points[1].Y - polygon->Points[0].Y;
	  t = (w < h) ? w : h;
	  x1 = polygon->Points[0].X + t/2;
	  y1 = polygon->Points[0].Y + t/2;
	  x2 = x1 + (w-t);
	  y2 = y1 + (h-t);

	  sprintf (num, "%d", pin_n++);
	  CreateNewPad (Element,
			x1, y1, x2, y2, t,
			2 * Settings.Keepaway,
			t + Settings.Keepaway,
			NULL, num,
			MakeFlags (SQUAREFLAG | onsolderflag));
	  MAYBE_WARN();
	  hasParts = true;
	}
	END_LOOP;
      }
      END_LOOP;
    }

  /* now add the silkscreen. NOTE: elements must have pads or pins too */
  LINE_LOOP (&Buffer->Data->SILKLAYER);
  {
    if (line->Number && !NAMEONPCB_NAME (Element))
      NAMEONPCB_NAME (Element) = strdup (line->Number);
    CreateNewLineInElement (Element, line->Point1.X,
			    line->Point1.Y, line->Point2.X,
			    line->Point2.Y, line->Thickness);
    hasParts = true;
  }
  END_LOOP;
  ARC_LOOP (&Buffer->Data->SILKLAYER);
  {
    CreateNewArcInElement (Element, arc->X, arc->Y, arc->Width,
			   arc->Height, arc->StartAngle, arc->Delta,
			   arc->Thickness);
    hasParts = true;
  }
  END_LOOP;
  if (!hasParts)
    {
      DestroyObject (PCB->Data, ELEMENT_TYPE, Element, Element, Element);
      Message (_("There was nothing to convert!\n"
		 "Elements must have some silk, pads or pins.\n"));
      return (false);
    }
  if (crooked)
     Message (_("There were polygons that can't be made into pins!\n"
                "So they were not included in the element\n"));
  Element->MarkX = Buffer->X;
  Element->MarkY = Buffer->Y;
  if (SWAP_IDENT)
    SET_FLAG (ONSOLDERFLAG, Element);
  SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
  ClearBuffer (Buffer);
  MoveObjectToBuffer (Buffer->Data, PCB->Data, ELEMENT_TYPE, Element, Element,
		      Element);
  SetBufferBoundingBox (Buffer);
  return (true);
}
Example #19
0
static char *
describe_location (Coord X, Coord Y)
{
  void *ptr1, *ptr2, *ptr3;
  int type;
  int Range = 0;
  char *elename = "";
  char *pinname;
  char *netname = NULL;
  char *description;

  /* check if there are any pins or pads at that position */

  type = SearchObjectByLocation (PIN_TYPE | PAD_TYPE,
                                 &ptr1, &ptr2, &ptr3, X, Y, Range);
  if (type == NO_TYPE)
    return NULL;

  /* don't mess with silk objects! */
  if (type & SILK_TYPE &&
      GetLayerNumber (PCB->Data, (LayerType *) ptr1) >= max_copper_layer)
    return NULL;

  if (type == PIN_TYPE || type == PAD_TYPE)
    elename = (char *)UNKNOWN (NAMEONPCB_NAME ((ElementType *) ptr1));

  pinname = ConnectionName (type, ptr1, ptr2);

  if (pinname == NULL)
    return NULL;

  /* Find netlist entry */
  MENU_LOOP (&PCB->NetlistLib);
  {
    if (!menu->Name)
    continue;

    ENTRY_LOOP (menu);
    {
      if (!entry->ListEntry)
        continue;

      if (strcmp (entry->ListEntry, pinname) == 0) {
        netname = g_strdup (menu->Name);
        /* For some reason, the netname has spaces in front of it, strip them */
        g_strstrip (netname);
        break;
      }
    }
    END_LOOP;

    if (netname != NULL)
      break;
  }
  END_LOOP;

  description = g_strdup_printf ("Element name: %s\n"
                                 "Pinname : %s\n"
                                 "Netname : %s",
                                 elename,
                                 (pinname != NULL) ? pinname : "--",
                                 (netname != NULL) ? netname : "--");

  g_free (netname);

  return description;
}
Example #20
0
File: rats.c Project: rlutz/pcb
static bool
CheckShorts (LibraryMenuType *theNet)
{
  bool newone, warn = false;
  PointerListType *generic = (PointerListType *)calloc (1, sizeof (PointerListType));
  /* the first connection was starting point so
   * the menu is always non-null
   */
  void **menu = GetPointerMemory (generic);

  *menu = theNet;
  ALLPIN_LOOP (PCB->Data);
  {
    if (TEST_FLAG (DRCFLAG, pin))
      {
	warn = true;
	if (!pin->Spare)
	  {
	    Message (_("Warning! Net \"%s\" is shorted to %s pin %s\n"),
		     &theNet->Name[2],
		     UNKNOWN (NAMEONPCB_NAME (element)),
		     UNKNOWN (pin->Number));
	    SET_FLAG (WARNFLAG, pin);
	    continue;
	  }
	newone = true;
	POINTER_LOOP (generic);
	{
	  if (*ptr == pin->Spare)
	    {
	      newone = false;
	      break;
	    }
	}
	END_LOOP;
	if (newone)
	  {
	    menu = GetPointerMemory (generic);
	    *menu = pin->Spare;
	    Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
		     &theNet->Name[2],
		     &((LibraryMenuType *) (pin->Spare))->Name[2]);
	    SET_FLAG (WARNFLAG, pin);
	  }
      }
  }
  ENDALL_LOOP;
  ALLPAD_LOOP (PCB->Data);
  {
    if (TEST_FLAG (DRCFLAG, pad))
      {
	warn = true;
	if (!pad->Spare)
	  {
	    Message (_("Warning! Net \"%s\" is shorted  to %s pad %s\n"),
		     &theNet->Name[2],
		     UNKNOWN (NAMEONPCB_NAME (element)),
		     UNKNOWN (pad->Number));
	    SET_FLAG (WARNFLAG, pad);
	    continue;
	  }
	newone = true;
	POINTER_LOOP (generic);
	{
	  if (*ptr == pad->Spare)
	    {
	      newone = false;
	      break;
	    }
	}
	END_LOOP;
	if (newone)
	  {
	    menu = GetPointerMemory (generic);
	    *menu = pad->Spare;
	    Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
		     &theNet->Name[2],
		     &((LibraryMenuType *) (pad->Spare))->Name[2]);
	    SET_FLAG (WARNFLAG, pad);
	  }
      }
  }
  ENDALL_LOOP;
  FreePointerListMemory (generic);
  free (generic);
  return (warn);
}