Ejemplo n.º 1
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);
}
Ejemplo n.º 2
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);
}