Exemple #1
0
static BomList *
bom_insert (char *refdes, char *descr, char *value, BomList * bom)
{
  BomList *newlist, *cur, *prev = NULL;

  if (bom == NULL)
    {
      /* this is the first element so automatically create an entry */
      if ((newlist = (BomList *) malloc (sizeof (BomList))) == NULL)
	{
	  fprintf (stderr, "malloc() failed in bom_insert()\n");
	  exit (1);
	}

      newlist->next = NULL;
      newlist->descr = strdup (descr);
      newlist->value = strdup (value);
      newlist->num = 1;
      newlist->refdes = string_insert (refdes, NULL);
      return (newlist);
    }

  /* search and see if we already have used one of these
     components */
  cur = bom;
  while (cur != NULL)
    {
      if ((NSTRCMP (descr, cur->descr) == 0) &&
	  (NSTRCMP (value, cur->value) == 0))
	{
	  cur->num++;
	  cur->refdes = string_insert (refdes, cur->refdes);
	  break;
	}
      prev = cur;
      cur = cur->next;
    }

  if (cur == NULL)
    {
      if ((newlist = (BomList *) malloc (sizeof (BomList))) == NULL)
	{
	  fprintf (stderr, "malloc() failed in bom_insert()\n");
	  exit (1);
	}

      prev->next = newlist;

      newlist->next = NULL;
      newlist->descr = strdup (descr);
      newlist->value = strdup (value);
      newlist->num = 1;
      newlist->refdes = string_insert (refdes, NULL);
    }

  return (bom);

}
Exemple #2
0
Fichier : rats.c Projet : rlutz/pcb
/*!
 * \brief Find a particular pad from an element name and pin number.
 */
static bool
FindPad (char *ElementName, char *PinNum, ConnectionType * conn, bool Same)
{
  ElementType *element;
  GList *i;

  if ((element = SearchElementByName (PCB->Data, ElementName)) == NULL)
    return false;

  for (i = element->Pad; i != NULL; i = g_list_next (i))
    {
      PadType *pad = i->data;

      if (NSTRCMP (PinNum, pad->Number) == 0 &&
          (!Same || !TEST_FLAG (DRCFLAG, pad)))
        {
          conn->type = PAD_TYPE;
          conn->ptr1 = element;
          conn->ptr2 = pad;
          conn->group = TEST_FLAG (ONSOLDERFLAG, pad) ? bottom_group : top_group;

          if (TEST_FLAG (EDGE2FLAG, pad))
            {
              conn->X = pad->Point2.X;
              conn->Y = pad->Point2.Y;
            }
          else
            {
              conn->X = pad->Point1.X;
              conn->Y = pad->Point1.Y;
            }
          return true;
        }
    }

  for (i = element->Pin; i != NULL; i = g_list_next (i))
    {
      PinType *pin = i->data;

      if (!TEST_FLAG (HOLEFLAG, pin) &&
          pin->Number && NSTRCMP (PinNum, pin->Number) == 0 &&
          (!Same || !TEST_FLAG (DRCFLAG, pin)))
        {
          conn->type = PIN_TYPE;
          conn->ptr1 = element;
          conn->ptr2 = pin;
          conn->group = bottom_group;        /* any layer will do */
          conn->X = pin->X;
          conn->Y = pin->Y;
          return true;
        }
    }

  return false;
}
Exemple #3
0
/* ---------------------------------------------------------------------------
 * Find a particular pad from an element name and pin number
 */
static bool
FindPad (char *ElementName, char *PinNum, ConnectionType * conn, bool Same)
{
  ElementTypePtr element;
  Cardinal i;

  if ((element = SearchElementByName (PCB->Data, ElementName)) != NULL)
    {
      for (i = 0; i < element->PadN; i++)
	if (NSTRCMP (PinNum, element->Pad[i].Number) == 0 && (!Same
							      ||
							      !TEST_FLAG
							      (DRCFLAG,
							       &element->
							       Pad[i])))
	  {
	    conn->type = PAD_TYPE;
	    conn->ptr2 = &element->Pad[i];
	    conn->group =
	      TEST_FLAG (ONSOLDERFLAG, &element->Pad[i]) ? SLayer : CLayer;
	    if (TEST_FLAG (EDGE2FLAG, &element->Pad[i]))
	      {
		conn->X = element->Pad[i].Point2.X;
		conn->Y = element->Pad[i].Point2.Y;
	      }
	    else
	      {
		conn->X = element->Pad[i].Point1.X;
		conn->Y = element->Pad[i].Point1.Y;
	      }
	    break;
	  }
      if (i == element->PadN)
	{
	  for (i = 0; i < element->PinN; i++)
	    if (!TEST_FLAG (HOLEFLAG, &element->Pin[i]) &&
		element->Pin[i].Number &&
		NSTRCMP (PinNum, element->Pin[i].Number) == 0 &&
		(!Same || !TEST_FLAG (DRCFLAG, &element->Pin[i])))
	      {
		conn->type = PIN_TYPE;
		conn->ptr2 = &element->Pin[i];
		conn->group = SLayer;	/* any layer will do */
		conn->X = element->Pin[i].X;
		conn->Y = element->Pin[i].Y;
		break;
	      }
	  if (i == element->PinN)
	    return (false);
	}
      conn->ptr1 = element;
      return (true);
    }
  return (false);
}
Exemple #4
0
Resource *
resource_subres(const Resource *res, const char *name)
{
    int i;
    if (res == 0 || name == 0)
        return 0;
    for (i=0; i<res->c; i++)
        if (res->v[i].name && res->v[i].subres
                && NSTRCMP(res->v[i].name, name) == 0)
            return res->v[i].subres;
    return 0;
}
Exemple #5
0
char *
resource_value(const Resource *res, char *name)
{
    int i;
    if (res == 0 || name == 0)
        return 0;
    for (i=0; i<res->c; i++)
        if (res->v[i].name && res->v[i].value
                && NSTRCMP(res->v[i].name, name) == 0)
            return res->v[i].value;
    return 0;
}
Exemple #6
0
void
SetRouteStyle (char *name) {
    char num[10];
    STYLE_LOOP (PCB);
    {
        if (name && NSTRCMP (name, style->Name) == 0) {
            sprintf (num, "%d", n + 1);
            hid_actionl ("RouteStyle", num, NULL);
            break;
        }
    }
    END_LOOP;
}
Exemple #7
0
/* ---------------------------------------------------------------------------
 * Add a new net to the netlist menu
 */
LibraryMenuTypePtr
CreateNewNet (LibraryTypePtr lib, char *name, char *style)
{
  LibraryMenuTypePtr menu;
  char temp[64];

  sprintf (temp, "  %s", name);
  menu = GetLibraryMenuMemory (lib);
  menu->Name = strdup (temp);
  menu->flag = 1;		/* net is enabled by default */
  if (style == NULL || NSTRCMP ("(unknown)", style) == 0)
    menu->Style = NULL;
  else
    menu->Style = strdup (style);
  return (menu);
}
Exemple #8
0
/* ---------------------------------------------------------------------------
 * searches for an element by its board name.
 * The function returns a pointer to the element, NULL if not found
 */
ElementTypePtr
SearchElementByName (DataTypePtr Base, char *Name)
{
  ElementTypePtr result = NULL;

  ELEMENT_LOOP (Base);
  {
    if (element->Name[1].TextString &&
	NSTRCMP (element->Name[1].TextString, Name) == 0)
      {
	result = element;
	return (result);
      }
  }
  END_LOOP;
  return result;
}
Exemple #9
0
Fichier : rats.c Projet : 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);
}
Exemple #10
0
/* This function loads the newlib footprints into the Library.
 * It examines all directories pointed to by Settings.LibraryTree.
 * In each directory specified there, it looks both in that directory,
 * as well as *one* level down.  It calls the subfunction 
 * LoadNewlibFootprintsFromDir to put the footprints into PCB's internal
 * datastructures.
 */
static int
ParseLibraryTree (void)
{
  char toppath[MAXPATHLEN + 1];    /* String holding abs path to top level library dir */
  char working[MAXPATHLEN + 1];    /* String holding abs path to working dir */
  char *libpaths;                  /* String holding list of library paths to search */
  char *p;                         /* Helper string used in iteration */
  DIR *dirobj;                     /* Iterable directory object */
  struct dirent *direntry = NULL;  /* Object holding individual directory entries */
  struct stat buffer;              /* buffer used in stat */
  int n_footprints = 0;            /* Running count of footprints found */

  /* Initialize path, working by writing 0 into every byte. */
  memset (toppath, 0, sizeof toppath);
  memset (working, 0, sizeof working);

  /* Save the current working directory as an absolute path.
   * This fcn writes the abs path into the memory pointed to by the input arg.
   */
  if (GetWorkingDirectory (working) == NULL)
    {
      Message (_("ParseLibraryTree: Could not determine initial working directory\n"));
      return 0;
    }

  /* Additional loop to allow for multiple 'newlib' style library directories 
   * called out in Settings.LibraryTree
   */
  libpaths = strdup (Settings.LibraryTree);
  for (p = strtok (libpaths, PCB_PATH_DELIMETER); p && *p; p = strtok (NULL, PCB_PATH_DELIMETER))
    {
      /* remove trailing path delimeter */
      strncpy (toppath, p, sizeof (toppath) - 1);

      /* start out in the working directory in case the path is a
       * relative path 
       */
      if (chdir (working))
        {
          ChdirErrorMessage (working);
          free (libpaths);
          return 0;
        }

      /*
       * Next change to the directory which is the top of the library tree
       * and extract its abs path.
       */
      if (chdir (toppath))
        {
          ChdirErrorMessage (toppath);
          continue;
        }

      if (GetWorkingDirectory (toppath) == NULL)
        {
          Message (_("ParseLibraryTree: Could not determine new working directory\n"));
          continue;
        }

#ifdef DEBUG
      printf("In ParseLibraryTree, looking for newlib footprints inside top level directory %s ... \n", 
	     toppath);
#endif

      /* Next read in any footprints in the top level dir */
      n_footprints += LoadNewlibFootprintsFromDir("(local)", toppath);

      /* Then open this dir so we can loop over its contents. */
      if ((dirobj = opendir (toppath)) == NULL)
	{
	  OpendirErrorMessage (toppath);
	  continue;
	}

      /* Now loop over files in this directory looking for subdirs.
       * For each direntry which is a valid subdirectory,
       * try to load newlib footprints inside it.
       */
      while ((direntry = readdir (dirobj)) != NULL)
	{
#ifdef DEBUG
	  printf("In ParseLibraryTree loop examining 2nd level direntry %s ... \n", direntry->d_name);
#endif
	  /* Find subdirectories.  Ignore entries beginning with "." and CVS
	   * directories.
	   */
	  if (!stat (direntry->d_name, &buffer)
	      && S_ISDIR (buffer.st_mode) 
	      && direntry->d_name[0] != '.'
	      && NSTRCMP (direntry->d_name, "CVS") != 0)
	    {
	      /* Found a valid subdirectory.  Try to load footprints from it.
	       */
	      n_footprints += LoadNewlibFootprintsFromDir(direntry->d_name, toppath);
	    }
	}
      closedir (dirobj);
    }

  /* restore the original working directory */
  if (chdir (working))
    ChdirErrorMessage (working);

#ifdef DEBUG
  printf("Leaving ParseLibraryTree, found %d footprints.\n", n_footprints);
#endif

  free (libpaths);
  return n_footprints;
}
Exemple #11
0
/* ---------------------------------------------------------------------------
 * Compute cost function.
 *  note that area overlap cost is correct for SMD devices: SMD devices on
 *  opposite sides of the board don't overlap.
 *
 * Algorithms follow those described in sections 4.1 of
 *  "Placement and Routing of Electronic Modules" edited by Michael Pecht
 *  Marcel Dekker, Inc. 1993.  ISBN: 0-8247-8916-4 TK7868.P7.P57 1993
 */
static double
ComputeCost (NetListTypePtr Nets, double T0, double T)
{
  double W = 0;			/* wire cost */
  double delta1 = 0;		/* wire congestion penalty function */
  double delta2 = 0;		/* module overlap penalty function */
  double delta3 = 0;		/* out of bounds penalty */
  double delta4 = 0;		/* alignment bonus */
  double delta5 = 0;		/* total area penalty */
  Cardinal i, j;
  LocationType minx, maxx, miny, maxy;
  bool allpads, allsameside;
  Cardinal thegroup;
  BoxListType bounds = { 0, 0, NULL };	/* save bounding rectangles here */
  BoxListType solderside = { 0, 0, NULL };	/* solder side component bounds */
  BoxListType componentside = { 0, 0, NULL };	/* component side bounds */
  /* make sure the NetList have the proper updated X and Y coords */
  UpdateXY (Nets);
  /* wire length term.  approximated by half-perimeter of minimum
   * rectangle enclosing the net.  Note that we penalize vias in
   * all-SMD nets by making the rectangle a cube and weighting
   * the "layer height" of the net. */
  for (i = 0; i < Nets->NetN; i++)
    {
      NetTypePtr n = &Nets->Net[i];
      if (n->ConnectionN < 2)
	continue;		/* no cost to go nowhere */
      minx = maxx = n->Connection[0].X;
      miny = maxy = n->Connection[0].Y;
      thegroup = n->Connection[0].group;
      allpads = (n->Connection[0].type == PAD_TYPE);
      allsameside = true;
      for (j = 1; j < n->ConnectionN; j++)
	{
	  ConnectionTypePtr c = &(n->Connection[j]);
	  MAKEMIN (minx, c->X);
	  MAKEMAX (maxx, c->X);
	  MAKEMIN (miny, c->Y);
	  MAKEMAX (maxy, c->Y);
	  if (c->type != PAD_TYPE)
	    allpads = false;
	  if (c->group != thegroup)
	    allsameside = false;
	}
      /* save bounding rectangle */
      {
	BoxTypePtr box = GetBoxMemory (&bounds);
	box->X1 = minx;
	box->Y1 = miny;
	box->X2 = maxx;
	box->Y2 = maxy;
      }
      /* okay, add half-perimeter to cost! */
      W += (maxx - minx) / 100 + (maxy - miny) / 100 +
	((allpads && !allsameside) ? CostParameter.via_cost : 0);
    }
  /* now compute penalty function Wc which is proportional to
   * amount of overlap and congestion. */
  /* delta1 is congestion penalty function */
  delta1 = CostParameter.congestion_penalty *
    sqrt (fabs (ComputeIntersectionArea (&bounds)));
#if 0
  printf ("Wire Congestion Area: %f\n", ComputeIntersectionArea (&bounds));
#endif
  /* free bounding rectangles */
  FreeBoxListMemory (&bounds);
  /* now collect module areas (bounding rect of pins/pads) */
  /* two lists for solder side / component side. */

  ELEMENT_LOOP (PCB->Data);
  {
    BoxListTypePtr thisside;
    BoxListTypePtr otherside;
    BoxTypePtr box;
    BoxTypePtr lastbox = NULL;
    BDimension thickness;
    BDimension clearance;
    if (TEST_FLAG (ONSOLDERFLAG, element))
      {
	thisside = &solderside;
	otherside = &componentside;
      }
    else
      {
	thisside = &componentside;
	otherside = &solderside;
      }
    box = GetBoxMemory (thisside);
    /* protect against elements with no pins/pads */
    if (element->PinN == 0 && element->PadN == 0)
      continue;
    /* initialize box so that it will take the dimensions of
     * the first pin/pad */
    box->X1 = MAX_COORD;
    box->Y1 = MAX_COORD;
    box->X2 = -MAX_COORD;
    box->Y2 = -MAX_COORD;
    PIN_LOOP (element);
    {
      thickness = pin->Thickness / 2;
      clearance = pin->Clearance * 2;
    EXPANDRECTXY (box,
		    pin->X - (thickness + clearance),
		    pin->Y - (thickness + clearance),
		    pin->X + (thickness + clearance),
		    pin->Y + (thickness + clearance))}
    END_LOOP;
    PAD_LOOP (element);
    {
      thickness = pad->Thickness / 2;
      clearance = pad->Clearance * 2;
    EXPANDRECTXY (box,
		    MIN (pad->Point1.X,
			   pad->Point2.X) - (thickness +
					       clearance),
		    MIN (pad->Point1.Y,
			   pad->Point2.Y) - (thickness +
					       clearance),
		    MAX (pad->Point1.X,
			   pad->Point2.X) + (thickness +
					       clearance),
		    MAX (pad->Point1.Y,
			   pad->Point2.Y) + (thickness + clearance))}
    END_LOOP;
    /* add a box for each pin to the "opposite side":
     * surface mount components can't sit on top of pins */
    if (!CostParameter.fast)
      PIN_LOOP (element);
    {
      box = GetBoxMemory (otherside);
      thickness = pin->Thickness / 2;
      clearance = pin->Clearance * 2;
      /* we ignore clearance here */
      /* (otherwise pins don't fit next to each other) */
      box->X1 = pin->X - thickness;
      box->Y1 = pin->Y - thickness;
      box->X2 = pin->X + thickness;
      box->Y2 = pin->Y + thickness;
      /* speed hack! coalesce with last box if we can */
      if (lastbox != NULL &&
	  ((lastbox->X1 == box->X1 &&
	    lastbox->X2 == box->X2 &&
	    MIN (abs (lastbox->Y1 - box->Y2),
		 abs (box->Y1 - lastbox->Y2)) <
	    clearance) || (lastbox->Y1 == box->Y1
			   && lastbox->Y2 == box->Y2
			   &&
			   MIN (abs
				(lastbox->X1 -
				 box->X2),
				abs (box->X1 - lastbox->X2)) < clearance)))
	{
	  EXPANDRECT (lastbox, box);
	  otherside->BoxN--;
	}
      else
	lastbox = box;
    }
    END_LOOP;
    /* assess out of bounds penalty */
    if (element->VBox.X1 < 0 ||
	element->VBox.Y1 < 0 ||
	element->VBox.X2 > PCB->MaxWidth || element->VBox.Y2 > PCB->MaxHeight)
      delta3 += CostParameter.out_of_bounds_penalty;
  }
  END_LOOP;
  /* compute intersection area of module areas box list */
  delta2 = sqrt (fabs (ComputeIntersectionArea (&solderside) +
		       ComputeIntersectionArea (&componentside))) *
    (CostParameter.overlap_penalty_min +
     (1 - (T / T0)) * CostParameter.overlap_penalty_max);
#if 0
  printf ("Module Overlap Area (solder): %f\n",
	  ComputeIntersectionArea (&solderside));
  printf ("Module Overlap Area (component): %f\n",
	  ComputeIntersectionArea (&componentside));
#endif
  FreeBoxListMemory (&solderside);
  FreeBoxListMemory (&componentside);
  /* reward pin/pad x/y alignment */
  /* score higher if pins/pads belong to same *type* of component */
  /* XXX: subkey should be *distance* from thing aligned with, so that
   * aligning to something far away isn't profitable */
  {
    /* create r tree */
    PointerListType seboxes = { 0, 0, NULL }
    , ceboxes =
    {
    0, 0, NULL};
    struct ebox
    {
      BoxType box;
      ElementTypePtr element;
    };
    direction_t dir[4] = { NORTH, EAST, SOUTH, WEST };
    struct ebox **boxpp, *boxp;
    rtree_t *rt_s, *rt_c;
    int factor;
    ELEMENT_LOOP (PCB->Data);
    {
      boxpp = (struct ebox **)
	GetPointerMemory (TEST_FLAG (ONSOLDERFLAG, element) ?
			  &seboxes : &ceboxes);
      *boxpp = malloc (sizeof (**boxpp));
      if (*boxpp == NULL ) 
	{
	  fprintf (stderr, "malloc() failed in %s\n", __FUNCTION__);
	  exit (1);
	}

      (*boxpp)->box = element->VBox;
      (*boxpp)->element = element;
    }
    END_LOOP;
    rt_s = r_create_tree ((const BoxType **) seboxes.Ptr, seboxes.PtrN, 1);
    rt_c = r_create_tree ((const BoxType **) ceboxes.Ptr, ceboxes.PtrN, 1);
    FreePointerListMemory (&seboxes);
    FreePointerListMemory (&ceboxes);
    /* now, for each element, find its neighbor on all four sides */
    delta4 = 0;
    for (i = 0; i < 4; i++)
      ELEMENT_LOOP (PCB->Data);
    {
      boxp = (struct ebox *)
	r_find_neighbor (TEST_FLAG (ONSOLDERFLAG, element) ?
			 rt_s : rt_c, &element->VBox, dir[i]);
      /* score bounding box alignments */
      if (!boxp)
	continue;
      factor = 1;
      if (element->Name[0].TextString &&
	  boxp->element->Name[0].TextString &&
	  0 == NSTRCMP (element->Name[0].TextString,
			boxp->element->Name[0].TextString))
	{
	  delta4 += CostParameter.matching_neighbor_bonus;
	  factor++;
	}
      if (element->Name[0].Direction == boxp->element->Name[0].Direction)
	delta4 += factor * CostParameter.oriented_neighbor_bonus;
      if (element->VBox.X1 ==
	  boxp->element->VBox.X1 ||
	  element->VBox.X1 ==
	  boxp->element->VBox.X2 ||
	  element->VBox.X2 ==
	  boxp->element->VBox.X1 ||
	  element->VBox.X2 ==
	  boxp->element->VBox.X2 ||
	  element->VBox.Y1 ==
	  boxp->element->VBox.Y1 ||
	  element->VBox.Y1 ==
	  boxp->element->VBox.Y2 ||
	  element->VBox.Y2 ==
	  boxp->element->VBox.Y1 ||
	  element->VBox.Y2 == boxp->element->VBox.Y2)
	delta4 += factor * CostParameter.aligned_neighbor_bonus;
    }
    END_LOOP;
    /* free k-d tree memory */
    r_destroy_tree (&rt_s);
    r_destroy_tree (&rt_c);
  }
  /* penalize total area used by this layout */
  {
    LocationType minX = MAX_COORD, minY = MAX_COORD;
    LocationType maxX = -MAX_COORD, maxY = -MAX_COORD;
    ELEMENT_LOOP (PCB->Data);
    {
      MAKEMIN (minX, element->VBox.X1);
      MAKEMIN (minY, element->VBox.Y1);
      MAKEMAX (maxX, element->VBox.X2);
      MAKEMAX (maxY, element->VBox.Y2);
    }
    END_LOOP;
    if (minX < maxX && minY < maxY)
      delta5 = CostParameter.overall_area_penalty *
	sqrt ((double) (maxX - minX) * (maxY - minY) * 0.0001);
  }
  if (T == 5)
    {
      T = W + delta1 + delta2 + delta3 - delta4 + delta5;
      printf ("cost components are %.3f %.3f %.3f %.3f %.3f %.3f\n",
	      W / T, delta1 / T, delta2 / T, delta3 / T, -delta4 / T,
	      delta5 / T);
    }
  /* done! */
  return W + (delta1 + delta2 + delta3 - delta4 + delta5);
}
Exemple #12
0
int
ActionLoadVendorFrom (int argc, char **argv, Coord x, Coord y)
{
  int i;
  char *fname = NULL;
  static char *default_file = NULL;
  char *sval;
  Resource *res, *drcres, *drlres;
  int type;
  bool free_fname = false;

  cached_drill = -1;

  fname = argc ? argv[0] : 0;

  if (!fname || !*fname)
    {
      fname = gui->fileselect (_("Load Vendor Resource File..."),
			       _("Picks a vendor resource file to load.\n"
				 "This file can contain drc settings for a\n"
				 "particular vendor as well as a list of\n"
				 "predefined drills which are allowed."),
			       default_file, ".res", "vendor",
			       HID_FILESELECT_READ);
      if (fname == NULL)
	AFAIL (load_vendor);

      free_fname = true;

      free (default_file);
      default_file = NULL;

      if (fname && *fname)
	default_file = strdup (fname);
    }

  /* Unload any vendor table we may have had */
  n_vendor_drills = 0;
  n_refdes = 0;
  n_value = 0;
  n_descr = 0;
  FREE (vendor_drills);
  FREE (ignore_refdes);
  FREE (ignore_value);
  FREE (ignore_descr);


  /* load the resource file */
  res = resource_parse (fname, NULL);
  if (res == NULL)
    {
      Message (_("Could not load vendor resource file \"%s\"\n"), fname);
      return 1;
    }

  /* figure out the vendor name, if specified */
  vendor_name = (char *)UNKNOWN (resource_value (res, "vendor"));

  /* figure out the units, if specified */
  sval = resource_value (res, "units");
  if (sval == NULL)
    {
      sf = MIL_TO_COORD(1);
    }
  else if ((NSTRCMP (sval, "mil") == 0) || (NSTRCMP (sval, "mils") == 0))
    {
      sf = MIL_TO_COORD(1);
    }
  else if ((NSTRCMP (sval, "inch") == 0) || (NSTRCMP (sval, "inches") == 0))
    {
      sf = INCH_TO_COORD(1);
    }
  else if (NSTRCMP (sval, "mm") == 0)
    {
      sf = MM_TO_COORD(1);
    }
  else
    {
      Message ("\"%s\" is not a supported units.  Defaulting to inch\n",
	       sval);
      sf = INCH_TO_COORD(1);
    }


  /* default to ROUND_UP */
  rounding_method = ROUND_UP;

  /* extract the drillmap resource */
  drlres = resource_subres (res, "drillmap");
  if (drlres == NULL)
    {
      Message (_("No drillmap resource found\n"));
    }
  else
    {
      sval = resource_value (drlres, "round");
      if (sval != NULL)
	{
	  if (NSTRCMP (sval, "up") == 0)
	    {
	      rounding_method = ROUND_UP;
	    }
	  else if (NSTRCMP (sval, "nearest") == 0)
	    {
	      rounding_method = CLOSEST;
	    }
	  else
	    {
	      Message (_
		       ("\"%s\" is not a valid rounding type.  Defaulting to up\n"),
		       sval);
	      rounding_method = ROUND_UP;
	    }
	}

      process_skips (resource_subres (drlres, "skips"));

      for (i = 0; i < drlres->c; i++)
	{
	  type = resource_type (drlres->v[i]);
	  switch (type)
	    {
	    case 10:
	      /* just a number */
	      add_to_drills (drlres->v[i].value);
	      break;

	    default:
	      break;
	    }
	}
    }

  /* Extract the DRC resource */
  drcres = resource_subres (res, "drc");

  sval = resource_value (drcres, "copper_space");
  if (sval != NULL)
    {
      PCB->Bloat = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
	       0.01 * PCB->Bloat);
    }

  sval = resource_value (drcres, "copper_overlap");
  if (sval != NULL)
    {
      PCB->Shrink = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum copper overlap to %.2f mils\n"),
	       0.01 * PCB->Shrink);
    }

  sval = resource_value (drcres, "copper_width");
  if (sval != NULL)
    {
      PCB->minWid = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum copper spacing to %.2f mils\n"),
	       0.01 * PCB->minWid);
    }

  sval = resource_value (drcres, "silk_width");
  if (sval != NULL)
    {
      PCB->minSlk = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum silk width to %.2f mils\n"),
	       0.01 * PCB->minSlk);
    }

  sval = resource_value (drcres, "min_drill");
  if (sval != NULL)
    {
      PCB->minDrill = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum drill diameter to %.2f mils\n"),
	       0.01 * PCB->minDrill);
    }

  sval = resource_value (drcres, "min_ring");
  if (sval != NULL)
    {
      PCB->minRing = floor (sf * atof (sval) + 0.5);
      Message (_("Set DRC minimum annular ring to %.2f mils\n"),
	       0.01 * PCB->minRing);
    }

  Message (_("Loaded %d vendor drills from %s\n"), n_vendor_drills, fname);
  Message (_("Loaded %d RefDes skips, %d Value skips, %d Descr skips\n"),
	   n_refdes, n_value, n_descr);

  vendorMapEnable = true;
  apply_vendor_map ();
  if (free_fname)
    free (fname);
  return 0;
}
Exemple #13
0
/* This is a helper function for ParseLibrary Tree.   Given a char *path,
 * it finds all newlib footprints in that dir and sticks them into the
 * library menu structure named entry.
 */
static int
LoadNewlibFootprintsFromDir(char *libpath, char *toppath)
{
  char olddir[MAXPATHLEN + 1];    /* The directory we start out in (cwd) */
  char subdir[MAXPATHLEN + 1];    /* The directory holding footprints to load */
  DIR *subdirobj;                 /* Interable object holding all subdir entries */
  struct dirent *subdirentry;     /* Individual subdir entry */
  struct stat buffer;             /* Buffer used in stat */
  LibraryMenuType *menu = NULL; /* Pointer to PCB's library menu structure */
  LibraryEntryType *entry;      /* Pointer to individual menu entry */
  size_t l;
  size_t len;
  int n_footprints = 0;           /* Running count of footprints found in this subdir */

  /* Cache old dir, then cd into subdir because stat is given relative file names. */
  memset (subdir, 0, sizeof subdir);
  memset (olddir, 0, sizeof olddir);
  if (GetWorkingDirectory (olddir) == NULL)
    {
      Message (_("LoadNewlibFootprintsFromDir: Could not determine initial working directory\n"));
      return 0;
    }

  if (strcmp (libpath, "(local)") == 0)
    strcpy (subdir, ".");
  else
    strcpy (subdir, libpath);

  if (chdir (subdir))
    {
      ChdirErrorMessage (subdir);
      return 0;
    }

  /* Determine subdir is abs path */
  if (GetWorkingDirectory (subdir) == NULL)
    {
      Message (_("LoadNewlibFootprintsFromDir: Could not determine new working directory\n"));
      if (chdir (olddir))
        ChdirErrorMessage (olddir);
      return 0;
    }

  /* First try opening the directory specified by path */
  if ( (subdirobj = opendir (subdir)) == NULL )
    {
      OpendirErrorMessage (subdir);
      if (chdir (olddir))
        ChdirErrorMessage (olddir);
      return 0;
    }

  /* Get pointer to memory holding menu */
  menu = GetLibraryMenuMemory (&Library);
  /* Populate menuname and path vars */
  menu->Name = strdup (pcb_basename(subdir));
  menu->directory = strdup (pcb_basename(toppath));

  /* Now loop over files in this directory looking for files.
   * We ignore certain files which are not footprints.
   */
  while ((subdirentry = readdir (subdirobj)) != NULL)
  {
#ifdef DEBUG
/*    printf("...  Examining file %s ... \n", subdirentry->d_name); */
#endif

    /* Ignore non-footprint files found in this directory
     * We're skipping .png and .html because those
     * may exist in a library tree to provide an html browsable
     * index of the library.
     */
    l = strlen (subdirentry->d_name);
    if (!stat (subdirentry->d_name, &buffer) && S_ISREG (buffer.st_mode)
      && subdirentry->d_name[0] != '.'
      && NSTRCMP (subdirentry->d_name, "CVS") != 0
      && NSTRCMP (subdirentry->d_name, "Makefile") != 0
      && NSTRCMP (subdirentry->d_name, "Makefile.am") != 0
      && NSTRCMP (subdirentry->d_name, "Makefile.in") != 0
      && (l < 4 || NSTRCMP(subdirentry->d_name + (l - 4), ".png") != 0) 
      && (l < 5 || NSTRCMP(subdirentry->d_name + (l - 5), ".html") != 0)
      && (l < 4 || NSTRCMP(subdirentry->d_name + (l - 4), ".pcb") != 0) )
      {
#ifdef DEBUG
/*	printf("...  Found a footprint %s ... \n", subdirentry->d_name); */
#endif
	n_footprints++;
	entry = GetLibraryEntryMemory (menu);

	/* 
	 * entry->AllocatedMemory points to abs path to the footprint.
	 * entry->ListEntry points to fp name itself.
	 */
	len = strlen(subdir) + strlen("/") + strlen(subdirentry->d_name) + 1;
	entry->AllocatedMemory = (char *)calloc (1, len);
	strcat (entry->AllocatedMemory, subdir);
	strcat (entry->AllocatedMemory, PCB_DIR_SEPARATOR_S);

	/* store pointer to start of footprint name */
	entry->ListEntry = entry->AllocatedMemory
	    + strlen (entry->AllocatedMemory);

	/* Now place footprint name into AllocatedMemory */
	strcat (entry->AllocatedMemory, subdirentry->d_name);

	/* mark as directory tree (newlib) library */
	entry->Template = (char *) -1;
      }
  }
  /* Done.  Clean up, cd back into old dir, and return */
  closedir (subdirobj);
  if (chdir (olddir))
    ChdirErrorMessage (olddir);
  return n_footprints;
}
Exemple #14
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);
}
Exemple #15
0
/* deal with the "skip" subresource */
static void
process_skips (Resource * res)
{
  int type;
  int i, k;
  char *sval;
  int *cnt;
  char ***lst = NULL;

  if (res == NULL)
    return;

  for (i = 0; i < res->c; i++)
    {
      type = resource_type (res->v[i]);
      switch (type)
	{
	case 1:
	  /* 
	   * an unnamed sub resource.  This is something like
	   * {refdes "J3"}
	   */
	  sval = res->v[i].subres->v[0].value;
	  if (sval == NULL)
	    {
	      Message ("Error:  null skip value\n");
	    }
	  else
	    {
	      if (NSTRCMP (sval, "refdes") == 0)
		{
		  cnt = &n_refdes;
		  lst = &ignore_refdes;
		}
	      else if (NSTRCMP (sval, "value") == 0)
		{
		  cnt = &n_value;
		  lst = &ignore_value;
		}
	      else if (NSTRCMP (sval, "descr") == 0)
		{
		  cnt = &n_descr;
		  lst = &ignore_descr;
		}
	      else
		{
		  cnt = NULL;
		}

	      /* add the entry to the appropriate list */
	      if (cnt != NULL)
		{
		  for (k = 1; k < res->v[i].subres->c; k++)
		    {
		      sval = res->v[i].subres->v[k].value;
		      (*cnt)++;
		      if ((*lst =
			   (char **) realloc (*lst,
					      (*cnt) * sizeof (char *))) ==
			  NULL)
			{
			  fprintf (stderr, "realloc() failed\n");
			  exit (-1);
			}
		      (*lst)[*cnt - 1] = strdup (sval);
		    }
		}
	    }
	  break;

	default:
	  Message (_("Ignored resource type = %d in skips= section\n"), type);
	}
    }

}
Exemple #16
0
static void
InitPaths (char *argv0)
{
  size_t l;
  int i;
  int haspath;
  char *t1, *t2;
  int found_bindir = 0;

  /* see if argv0 has enough of a path to let lrealpath give the
   * real path.  This should be the case if you invoke pcb with
   * something like /usr/local/bin/pcb or ./pcb or ./foo/pcb
   * but if you just use pcb and it exists in your path, you'll
   * just get back pcb again.
   */

#ifdef FAKE_BINDIR
	haspath = 1;
#else
  haspath = 0;
  for (i = 0; i < strlen (argv0) ; i++)
    {
      if (argv0[i] == PCB_DIR_SEPARATOR_C) 
	haspath = 1;
    }
#endif

#ifdef DEBUG
  printf ("InitPaths (%s): haspath = %d\n", argv0, haspath);
#endif

  if (haspath)
    {
#ifdef FAKE_BINDIR
      bindir = strdup(FAKE_BINDIR "/");
#else
      bindir = strdup (lrealpath (argv0));
#endif
      found_bindir = 1;
    }
  else
    {
      char *path, *p, *tmps;
      struct stat sb;
      int r;

      tmps = getenv ("PATH");

      if (tmps != NULL) 
	{
	  path = strdup (tmps);

	  /* search through the font path for a font file */
	  for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
	       p = strtok (NULL, PCB_PATH_DELIMETER))
	    {
#ifdef DEBUG
	      printf ("Looking for %s in %s\n", argv0, p);
#endif
	      if ( (tmps = (char *)malloc ( (strlen (argv0) + strlen (p) + 2) * sizeof (char))) == NULL )
		{
		  fprintf (stderr, "InitPaths():  malloc failed\n");
		  exit (1);
		}
	      sprintf (tmps, "%s%s%s", p, PCB_DIR_SEPARATOR_S, argv0);
	      r = stat (tmps, &sb);
	      if (r == 0)
		{
#ifdef DEBUG
		  printf ("Found it:  \"%s\"\n", tmps);
#endif
		  bindir = lrealpath (tmps);
		  found_bindir = 1;
		  free (tmps);
		  break;
		}  
	      free (tmps);
	    }
	  free (path);
	}
    }

#ifdef DEBUG
  printf ("InitPaths():  bindir = \"%s\"\n", bindir);
#endif

  if (found_bindir)
    {
      /* strip off the executible name leaving only the path */
      t2 = NULL;
      t1 = strchr (bindir, PCB_DIR_SEPARATOR_C);
      while (t1 != NULL && *t1 != '\0')
        {
          t2 = t1;
          t1 = strchr (t2 + 1, PCB_DIR_SEPARATOR_C);
        }
      if (t2 != NULL)
        *t2 = '\0';

#ifdef DEBUG
      printf ("After stripping off the executible name, we found\n");
      printf ("bindir = \"%s\"\n", bindir);
#endif
    }
  else
    {
      /* we have failed to find out anything from argv[0] so fall back to the original
       * install prefix
       */
       bindir = strdup (BINDIR);
    }

  /* now find the path to exec_prefix */
  l = strlen (bindir) + 1 + strlen (BINDIR_TO_EXECPREFIX) + 1;
  if ( (exec_prefix = (char *) malloc (l * sizeof (char) )) == NULL )
    {
      fprintf (stderr, "InitPaths():  malloc failed\n");
      exit (1);
    }
  sprintf (exec_prefix, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S, 
	   BINDIR_TO_EXECPREFIX);

  /* now find the path to PCBSHAREDIR */
  l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBSHAREDIR) + 1;
  if ( (pcblibdir = (char *) malloc (l * sizeof (char) )) == NULL )
    {
      fprintf (stderr, "InitPaths():  malloc failed\n");
      exit (1);
    }
  sprintf (pcblibdir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S, 
	   BINDIR_TO_PCBSHAREDIR);

#ifdef DEBUG
  printf ("bindir      = %s\n", bindir);
  printf ("pcblibdir   = %s\n", pcblibdir);
#endif

  l = sizeof (main_attribute_list) / sizeof (main_attribute_list[0]);
  for (i = 0; i < l ; i++) 
    {
      if (NSTRCMP (main_attribute_list[i].name, "lib-command-dir") == 0)
	{
	  main_attribute_list[i].default_val.str_value = pcblibdir;
	}

      if ( (NSTRCMP (main_attribute_list[i].name, "font-path") == 0) 
	   || (NSTRCMP (main_attribute_list[i].name, "element-path") == 0)
	   || (NSTRCMP (main_attribute_list[i].name, "lib-path") == 0) )
	{
	  main_attribute_list[i].default_val.str_value = pcblibdir;
	}

    }

    {
      char *tmps;

      tmps = getenv ("HOME");

      if (tmps == NULL) {
          tmps = getenv ("USERPROFILE");
      }

      if (tmps != NULL) {
          homedir = strdup (tmps);
      } else {
          homedir = NULL;
      }
    }

  resolve_all_paths(fontfile_paths_in, fontfile_paths);
}
Exemple #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);
}
Exemple #18
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;
}