[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-user: help with pcb dsn plugin



    I made a dsn export/import plugin a few years back that I am trying to
    merge into latest git pcb version.   It works to export and the dsn can
    be routed with freerouting.net, and the import function appears in the
    menu, but the import action does not work.  The function name is
    ActionLoadDsnFrom() but somehow during compilation it lists a
    "LoaddsnFrom" in the list of actions.  It says "Unknown Action" when I
    try to use LoaddsnFrom or ActionLoadDsnFrom, or LoadDsnFrom.  Is there
    a way to list what actions exist in pcb?
    I had to make 2 patches, the first one with "git diff" it only shows
    files that were changed.  The second patch is from "git add -i
    /src/hid/dsn", "git commit" and "git format-patch -1" and it will only
    show files that were added.  If anyone knows how to make the patch with
    1 command that would also help.
    Thanks,
    Josh Jordan
diff --git a/configure.ac b/configure.ac
index 6736466..7bcfe77 100644
--- a/configure.ac
+++ b/configure.ac
@@ -447,7 +447,7 @@ esac
 
 AC_MSG_CHECKING([for which exporters to use])
 AC_ARG_WITH([exporters],
-[  --with-exporters=       Enable export devices: bom gerber gcode nelma png ps [[default=bom gerber gcode nelma png ps]]],
+[  --with-exporters=       Enable export devices: bom dsn gerber gcode nelma png ps [[default=bom gerber gcode nelma png ps]]],
 [],[with_exporters=$hid_exporters])
 AC_MSG_RESULT([$with_exporters])
 for e in `echo $with_exporters | sed 's/,/ /g'`; do
diff --git a/src/Makefile.am b/src/Makefile.am
index 18fe5c1..0c4a42a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,7 +15,7 @@ HIDLIST = @HIDLIST@
 noinst_LIBRARIES = @HIDLIBS@
 EXTRA_LIBRARIES = \
 	libgtk.a liblesstif.a libbatch.a \
-	liblpr.a libgerber.a libbom.a libpng.a libps.a libnelma.a \
+	liblpr.a libgerber.a libbom.a libdsn.a libpng.a libps.a libnelma.a \
 	libgcode.a
 
 pcblib_DATA=	\
@@ -185,6 +185,7 @@ BUILT_SOURCES = \
 	hid/gcode/gcode_lists.h \
 	hid/nelma/nelma_lists.h \
 	hid/ps/ps_lists.h \
+	hid/dsn/dsn_lists.h \
 	parse_y.h \
 	pcb-menu.h \
 	res_parse.h \
@@ -217,6 +218,7 @@ EXTRA_DIST= \
 	default_font \
 	$(srcdir)/hid/batch/hid.conf \
 	$(srcdir)/hid/bom/hid.conf \
+	$(srcdir)/hid/dsn/hid.conf \
 	$(srcdir)/hid/gcode/hid.conf \
 	$(srcdir)/hid/gerber/hid.conf \
 	$(srcdir)/hid/gtk/gui-icons-misc.data \
@@ -359,6 +361,20 @@ hid/batch/batch_lists.h : ${LIBBATCH_SRCS} Makefile
 	(for f in ${LIBBATCH_SRCS} ; do cat $(srcdir)/$$f ; done) | grep "^REGISTER" > $@.tmp
 	mv $@.tmp $@
 
+libdsn_a_CPPFLAGS = -I./hid/dsn
+
+LIBDSN_SRCS = \
+	hid/hidint.h \
+	hid/dsn/dsn.c \
+	hid/dsn/dsn.h
+libdsn_a_SOURCES = ${LIBDSN_SRCS} hid/dsn/dsn_lists.h
+
+hid/dsn/dsn_lists.h : ${LIBDSN_SRCS} Makefile
+	$(MKDIR_P) hid/dsn
+	true > $@
+	(for f in ${LIBDSN_SRCS} ; do cat $(srcdir)/$$f ; done) |grep "^REGISTER" > $@.tmp
+	mv $@.tmp $@
+
 libgerber_a_SOURCES = \
 	hid/hidint.h \
 	hid/gerber/gerber.c
@@ -446,6 +462,7 @@ DISTCLEANFILES= pcbtest.sh gpcb-menu.h pcb-menu.h \
 	hid/gcode/gcode_lists.h \
 	hid/nelma/nelma_lists.h \
 	hid/ps/ps_lists.h \
+	hid/dsn/dsn_lists.h \
 	core_lists.h \
 	dbus-introspect.h
 
diff --git a/src/gpcb-menu.res b/src/gpcb-menu.res
index e9469e9..0af56b6 100644
--- a/src/gpcb-menu.res
+++ b/src/gpcb-menu.res
@@ -57,6 +57,7 @@ MainMenu =
    {"Load layout data to paste-buffer" PasteBuffer(Clear) Load(LayoutTobuffer)}
    {"Load netlist file" Load(Netlist)}
    {"Load vendor resource file" LoadVendorFrom()}
+   {"Load autorouted session file" LoaddsnFrom()}
    -
    {"Save connection data of"
      {" a single element" GetXY(Click to set the element mark <>) Save(ElementConnections)}
diff --git a/src/pcb-menu.res b/src/pcb-menu.res
index aaf48c4..1a8c484 100644
--- a/src/pcb-menu.res
+++ b/src/pcb-menu.res
@@ -38,6 +38,7 @@ MainMenu =
    {"Load layout data to paste-buffer" PasteBuffer(Clear) Load(LayoutTobuffer)}
    {"Load netlist file" Load(Netlist)}
    {"Load vendor resource file" LoadVendor()}
+   {"Load autorouted session file" LoaddsnFrom()}
    {"Print layout..." Print()}
    {"Export layout..." Export()}
    {"Calibrate Printer..." PrintCalibrate()}
From d44082a55b62692c0f1fad022f8bb59a8cef7480 Mon Sep 17 00:00:00 2001
From: josh <josh@josh-desktop.(none)>
Date: Sun, 12 Jun 2011 10:53:05 -0500
Subject: [PATCH] Committer: josh <joshjordan@xxxxxxxxxxxxx>

---
 src/hid/dsn/dsn.c    |  781 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/hid/dsn/dsn.h    |    3 +
 src/hid/dsn/hid.conf |    1 +
 3 files changed, 785 insertions(+), 0 deletions(-)
 create mode 100644 src/hid/dsn/dsn.c
 create mode 100644 src/hid/dsn/dsn.h
 create mode 100644 src/hid/dsn/hid.conf

diff --git a/src/hid/dsn/dsn.c b/src/hid/dsn/dsn.c
new file mode 100644
index 0000000..eea82b9
--- /dev/null
+++ b/src/hid/dsn/dsn.c
@@ -0,0 +1,781 @@
+/*
+This program exports specctra .dsn files from geda .pcb files.
+By Josh Jordan and Dan McMahill, modified from bom.c
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "global.h"
+#include "data.h"
+#include "error.h"
+#include "misc.h"
+#include "gts.h"
+#include "rats.h"
+#include "buffer.h"
+#include "parse_l.h"
+#include "change.h"
+#include "draw.h"
+#include "resource.h"
+#include "set.h"
+#include "undo.h"
+
+#include "hid.h"
+#include "../hidint.h"
+
+#include "hid/common/draw_helpers.h"
+#include "hid/common/hidnogui.h"
+#include "hid/common/actions.h"
+#include "hid/common/hidinit.h"
+
+#include "dsn.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+RCSID ("$Id$");
+
+int trackwidth = 8; //user options defined in export dialog
+int clearance = 8;
+int viawidth = 45;
+int viadrill = 25;
+
+static HID_Attribute dsn_options[] = {
+  {"dsnfile", "SPECCTRA output file",
+   HID_String, 0, 0, {0, 0, 0}, 0, 0},
+#define HA_dsnfile 0
+  {"trackwidth", "track width in mils",
+   HID_Integer, 1, 100, {8, 0, 0}, 0, 0},
+#define HA_trackwidth 1
+  {"clearance", "clearance in mils",
+   HID_Integer, 1, 100, {8, 0, 0}, 0, 0},
+#define HA_clearance 2
+  {"viawidth", "via width in mils",
+   HID_Integer, 1, 100, {27, 0, 0}, 0, 0},
+#define HA_viawidth 3
+  {"viadrill", "via drill diameter in mils",
+   HID_Integer, 1, 100, {15, 0, 0}, 0, 0},
+#define HA_viadrill 4
+};
+
+#define NUM_OPTIONS (sizeof(dsn_options)/sizeof(dsn_options[0]))
+REGISTER_ATTRIBUTES (dsn_options)
+  static HID_Attr_Val dsn_values[NUM_OPTIONS];
+
+static char *dsn_filename;
+
+
+static HID_Attribute *
+dsn_get_export_options (int *n)
+{
+  static char *last_dsn_filename = 0;
+  if (PCB) {
+	derive_default_filename(PCB->Filename, &dsn_options[HA_dsnfile], ".dsn", &last_dsn_filename);
+  }
+  if (n)
+    *n = NUM_OPTIONS;
+  return dsn_options;
+}
+
+
+static double
+xyToAngle (double x, double y)
+{
+  double theta;
+
+  if ((x > 0.0) && (y >= 0.0))
+    theta = 180.0;
+  else if ((x <= 0.0) && (y > 0.0))
+    theta = 90.0;
+  else if ((x < 0.0) && (y <= 0.0))
+    theta = 0.0;
+  else if ((x >= 0.0) && (y < 0.0))
+    theta = 270.0;
+  else
+    {
+      theta = 0.0;
+      Message ("xyToAngle(): unable to figure out angle of element\n"
+	       "     because the pin is at the centroid of the part.\n"
+	       "     This is a BUG!!!\n"
+	       "     Setting to %g degrees\n", theta);
+    }
+
+  return (theta);
+}
+
+typedef struct {
+  double centx;
+  double centy;
+  int rot;
+} CentroidRotation;
+
+/* this function is mostly ripped from bom.c 
+   it gives only absolute rotation, it must be
+    compared to the absolute rotation of the library part*/
+static CentroidRotation
+get_rotation_and_centroid (ElementType *element){
+  CentroidRotation centrot;
+  int found_pin1;
+  int found_pin2;
+  int pin_cnt;
+  double x, y, theta = 0.0, user_x, user_y;
+  double pin1x = 0.0, pin1y = 0.0, pin1angle = 0.0;
+  double pin2x = 0.0, pin2y = 0.0, pin2angle;
+  double sumx, sumy;
+  /* 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;
+  /*
+   * 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;
+      pin2angle = 0.0;	/* pins have no notion of angle */
+      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;
+      pin2angle = (180.0 / M_PI) * atan2 (pad->Point1.Y - pad->Point2.Y,
+	                pad->Point2.X - pad->Point1.X);
+      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
+            ("SPECCTRA EXPORTER: 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
+      ("SPECCTRA EXPORTER: 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);
+    }
+   	y = PCB->MaxHeight - y;
+
+   	/* dimensions in mils */
+   	user_x = 0.01 * x;
+   	user_y = 0.01 * y;
+    centrot.centx = user_x;
+    centrot.centy = user_y;
+    centrot.rot = theta;
+    return centrot;
+  }
+}
+
+bool is_layer_group_active[MAX_LAYER];
+GList *layerlist = NULL; //contain routing layers
+int layersN; //global var holding how many layers are found
+
+static void
+print_structure (FILE *fp)
+{
+  /* check which layers are active first */
+  int i;
+  int group;
+  fprintf (fp, "  (structure\n");
+  layersN = 0;
+  for (group = 0; group < max_group; group++)
+  {
+    for (i = 0; i < PCB->LayerGroups.Number[group]; i++)
+    /* layer must be 1) not silk (ie, < max_group) and 2) on */
+    if ((PCB->LayerGroups.Entries[group][i] < max_group) && PCB->Data->Layer[PCB->LayerGroups.Entries[group][i]].On)
+    {
+      char * lname;
+      layersN++;
+      is_layer_group_active[group] = true;
+      GROUP_LOOP(PCB->Data, group);
+      {
+        lname = g_strdup(layer->Name);
+        layerlist = g_list_insert( layerlist, layer, group );
+        break;
+      }
+      END_LOOP;
+      break;
+    }
+	  else
+	    is_layer_group_active[group] = false;
+  }
+  //layerlist = g_list_reverse( layerlist ); //this is because layer order is reversed for .dsn files
+  for(i = 0; i < max_group; i++)
+  {
+    if(is_layer_group_active[i])
+    {
+			int ni;
+			char *layeropts;
+			LayerTypePtr layer;
+			layeropts = g_strdup_printf( "(type signal)" );			
+			layer = g_list_nth_data( layerlist, i );
+			/* see if layer has same name as a net and make it a power layer */
+			for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop thru all nets
+			{
+				char *nname;
+				nname = PCB->NetlistLib.Menu[ni].Name + 2;
+				if (!strcmp( layer->Name, nname ))
+				{ 
+					g_free( layeropts );
+					layeropts = g_strdup_printf( "(type power) (use_net %s)", layer->Name);
+				}
+			}
+      fprintf( fp, "    (layer %s\n      %s\n      (property\n        (index %d)\n      )\n    )\n", layer->Name, layeropts, i);
+			g_free( layeropts );
+    }
+  }
+
+  /* PCB outline */
+  fprintf (fp, "    (boundary\n");
+  fprintf (fp, "      (rect pcb 0.0 0.0 %.2f %.2f)\n", PCB->MaxWidth*0.01, PCB->MaxHeight*0.01);
+  fprintf (fp, "    )\n");
+
+  fprintf (fp, "    (via via_%d_%d_mil)\n", viawidth, viadrill);
+
+  /* DRC rules */
+  fprintf (fp, "    (rule\n");
+  fprintf (fp, "      (width %d)\n", trackwidth);
+  fprintf (fp, "      (clear %d)\n", clearance);
+  fprintf (fp, "      (clear %d (type wire_area))\n", clearance);
+  fprintf (fp, "      (clear %d (type via_smd via_pin))\n", clearance);
+  fprintf (fp, "      (clear %d (type smd_smd))\n", clearance);
+  fprintf (fp, "      (clear %d (type default_smd))\n", clearance);
+  fprintf (fp, "    )\n  )\n");
+}
+
+static void
+print_placement (FILE *fp)
+{
+  fprintf (fp, "  (placement\n");
+  /* pcb doesnt remember footprint library- place all elements as their own library image */
+  ELEMENT_LOOP (PCB->Data);
+  {
+    char * ename;
+    CentroidRotation ecenter = get_rotation_and_centroid(element); //only need centroid
+    char* side = TEST_FLAG (ONSOLDERFLAG, element) ? "back" : "front";
+    ename = g_strdup( NAMEONPCB_NAME(element) );
+    if(!ename)
+      ename = g_strdup_printf("null");
+    fprintf( fp, "    (component %d\n", element->ID);
+    fprintf (fp, "      (place %s %.2f %.2f %s 0 (PN 0))\n", ename, ecenter.centx, ecenter.centy, side);
+    fprintf (fp, "    )\n");
+		g_free( ename );
+  }
+  END_LOOP;
+	VIA_LOOP (PCB->Data); //add mounting holes
+	{
+		fprintf( fp, "    (component %d\n", via->ID);
+    fprintf (fp, "      (place %d %.2f %.2f %s 0 (PN 0))\n", via->ID, via->X/100.0, (PCB->MaxHeight - via->Y)/100.0, "front");
+    fprintf (fp, "    )\n");
+	}
+	END_LOOP;
+  fprintf (fp, "  )\n");
+}
+
+static void
+print_library (FILE *fp)
+{
+  int i;
+  GList *pads = NULL; //contain unique pad names
+	char *padstack;
+  fprintf (fp, "  (library\n");
+  ELEMENT_LOOP (PCB->Data);
+  {
+    int rotation;
+    int partside = TEST_FLAG (ONSOLDERFLAG, element) ? layersN-1 : 0; //0 for component side, highest for solder side
+    int partsidesign = TEST_FLAG (ONSOLDERFLAG, element) ? -1 : 1;
+    CentroidRotation crot = get_rotation_and_centroid(element);
+    fprintf (fp, "    (image %d\n", element->ID); //map every element by ID
+    /* loop thru pins and pads to add to image */
+    PIN_LOOP (element);
+    {
+      int ty;
+      float pinthickness;
+      float lx, ly; //hold local pin coordinates
+      ty = PCB->MaxHeight - pin->Y;
+      pinthickness = pin->Thickness*0.01;
+			if TEST_FLAG( SQUAREFLAG, pin )
+				padstack = g_strdup_printf( "Th_square_%.0f_mil", pinthickness);
+			else
+      	padstack = g_strdup_printf ("Th_round_%.0f_mil", pinthickness);
+      lx = (pin->X*0.01-crot.centx)*partsidesign;
+      ly = (crot.centy - ty*0.01)*(-1);
+      if( !g_list_find_custom( pads, padstack, strcmp ) )
+        pads = g_list_append( pads, padstack );
+      
+      if (!pin->Number) //if pin is null just make it a keepout
+      {
+        for(int i = 0; i < layersN; i++)
+        {
+					LayerTypePtr lay;
+					lay = g_list_nth_data( layerlist, i );
+          fprintf (fp, "      (keepout \"\" (circle %s %.0f %.2f %.2f))\n", lay->Name, pinthickness, lx, ly);
+        }
+      }
+      else
+      {
+        fprintf (fp, "      (pin %s %s %.2f %.2f)\n", padstack, pin->Number, lx, ly);
+      }
+    }
+    END_LOOP;
+    PAD_LOOP (element);
+    {
+      int xlen, ylen, xc, yc, p1y, p2y;
+      float lx, ly; //store local coordinates for pins
+      p1y = PCB->MaxHeight - pad->Point1.Y;
+      p2y = PCB->MaxHeight - pad->Point2.Y;
+      /* pad dimensions are unusual-
+        the width is thickness and length is point difference plus thickness */
+      xlen = (ABS(pad->Point1.X - pad->Point2.X)+50)/100; //round to mil
+      if (xlen == 0)
+      {
+        xlen = (pad->Thickness+50)/100; //round to mil
+        ylen = (ABS(p1y - p2y)+50)/100 + xlen; //round to mil
+      }
+      else
+      {
+        ylen = (pad->Thickness+50)/100;
+        xlen += ylen;
+      }
+      xc = (pad->Point1.X + pad->Point2.X)/2;
+      yc = (p1y + p2y)/2;
+      lx = (xc*0.01-crot.centx)*partsidesign;
+      ly = (crot.centy - yc*0.01)*(-1);
+      padstack = g_strdup_printf ("Smd_rect_%dx%d_mil", xlen, ylen);
+   
+      if (!pad->Number) //if pad is null just make it a keepout
+      {
+				LayerTypePtr lay;
+				lay = g_list_nth_data( layerlist, partside );
+        fprintf (fp, "      (keepout \"\" (rect %s %.2f %.2f %.2f %.2f))\n", lay->Name, lx-xlen/2, ly-ylen/2, lx+xlen/2, ly+ylen/2);
+      }
+      else
+      {
+        fprintf (fp, "      (pin %s %s %.2f %.2f)\n", padstack, pad->Number, lx, ly);
+      }
+      if( !g_list_find_custom( pads, padstack, strcmp ) )
+        pads = g_list_append( pads, padstack );
+			else
+				g_free( padstack );
+    }
+    END_LOOP;
+    fprintf (fp, "    )\n");
+  }
+	END_LOOP;
+	VIA_LOOP (PCB->Data); //add mounting holes and vias
+	{
+		fprintf (fp, "    (image %d\n", via->ID); //map every via by ID
+		/* for mounting holes, clearance is added to thickness for higher total clearance */
+		padstack = g_strdup_printf ("Th_round_%.0f_mil", via->Thickness/100.0 + via->Clearance/100.0); 
+		fprintf (fp, "      (pin %s 1 0 0)\n", padstack); //only 1 pin, 0,0 puts it right on component placement spot
+		fprintf (fp, "    )\n");
+    if( !g_list_find_custom( pads, padstack, strcmp ) )
+      pads = g_list_append( pads, padstack );
+		else
+			g_free( padstack );
+	}
+  END_LOOP;
+  /* loop thru padstacks and define them all */
+  for(i=0; i < g_list_length( pads ); i++)
+  {
+    int retargs, dim1, dim2;
+    char * padstring = g_list_nth_data( pads, i );
+		LayerTypePtr lay;
+    fprintf (fp, "    (padstack %s\n", padstring);
+    /* print info about pad here */
+    retargs = sscanf (padstring, "Smd_rect_%dx%d_mil", &dim1, &dim2);
+    if (retargs == 2) //then pad is smd
+    { 
+			//lay = g_list_last( layerlist )->data;
+      fprintf (fp, "      (shape (rect component %.1f %.1f %.1f %.1f))\n", dim1/(-2.0), dim2/(-2.0), dim1/2.0, dim2/2.0);
+    }
+    else if (sscanf (padstring, "Th_square_%d_mil", &dim1) == 1)
+    {
+			fprintf (fp, "      (shape (rect signal %d %d %d %d))\n", dim1/-2, dim1/-2, dim1/2, dim1/2);
+		}
+		else
+		{
+      retargs = sscanf (padstring, "Th_round_%d_mil", &dim1);
+      fprintf (fp, "      (shape (circle signal %d))\n", dim1);
+    }
+    fprintf (fp, "      (attach off)\n");
+    fprintf (fp, "    )\n");
+  }
+  /* add padstack for via */
+  fprintf (fp, "    (padstack via_%d_%d_mil\n", viawidth, viadrill);
+	fprintf (fp, "      (shape (circle signal %d))\n", viawidth );
+  fprintf (fp, "      (attach off)\n    )\n");
+  fprintf (fp, "  )\n");
+  g_list_foreach( pads, (GFunc)g_free, NULL );
+  g_list_free( pads );
+}
+
+static void
+print_network (FILE *fp)
+{
+  NetListListType Nets;
+  Nets = CollectSubnets (false);
+  fprintf (fp, "  (network\n");
+  int ni, nei;
+  for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop thru all nets
+  {
+    fprintf (fp, "    (net %s\n      (pins", PCB->NetlistLib.Menu[ni].Name + 2);
+    for (nei = 0; nei < PCB->NetlistLib.Menu[ni].EntryN; nei++) //loop thru all entries in all nets
+    {
+      char *netentry;
+      netentry = PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry;
+      fprintf (fp, " %s", netentry);
+    }
+    fprintf (fp, ")\n    )\n");
+  }
+
+  fprintf (fp, "    (class geda_default");
+  for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop thru all nets
+  {
+    fprintf (fp, " %s", PCB->NetlistLib.Menu[ni].Name + 2);
+  }
+  fprintf (fp, "\n      (circuit\n        (use_via via_%d_%d_mil)\n      )\n", viawidth, viadrill);
+  fprintf (fp, "      (rule (width %d))\n    )\n  )\n", trackwidth);
+  //fprintf (fp, "  (wiring\n  )\n)\n"); //added wiring section, take this out
+}
+
+static void
+print_wires (FILE *fp)
+{
+	int i;
+	LayerTypePtr lay;
+	fprintf (fp, "	(wiring\n");
+
+	for (i = 0; i < layersN; i++)
+	{
+		lay = g_list_nth_data( layerlist, i );
+		LINE_LOOP(lay);
+		{
+			fprintf (fp, "		(wire (path %s %.2f %.2f %.2f %.2f %.2f)\n", lay->Name, line->Thickness/100.0, 
+								line->Point1.X/100.0, (PCB->MaxHeight - line->Point1.Y)/100.0, line->Point2.X/100.0, (PCB->MaxHeight - line->Point2.Y)/100.0);
+			fprintf (fp, "			(type protect))\n");
+		}
+		END_LOOP;
+	}
+	fprintf (fp, "\n	)\n)\n"); //close all braces
+}
+
+static int
+PrintSPECCTRA (void)
+{
+  FILE *fp;
+  /* Print out the dsn .dsn file. */
+  fp = fopen (dsn_filename, "w");
+  if (!fp)
+    {
+      gui->log ("Cannot open file %s for writing\n", dsn_filename);
+      return 1;
+    }
+
+  /* pcb [required] */
+  fprintf (fp, "(pcb %s\n", ((PCB->Name) && *(PCB->Name) ? (PCB->Name) : "notnamed"));
+  
+  /* parser descriptor [optional] */
+  fprintf (fp, "  (parser\n");
+  fprintf (fp, "    (string_quote \")\n");
+  fprintf (fp, "    (space_in_quoted_tokens on)\n");
+  fprintf (fp, "    (host_cad \"gEDA PCB\")\n");
+  fprintf (fp, "    (host_version \"(i dunno?)\")\n");
+  fprintf (fp, "  )\n");
+
+  /* capacitance resolution descriptor [optional] */
+
+  /* conductance resolution descriptor [optional] */
+
+  /* current resolution descriptor [optional] */
+
+  /* inductance resolution descriptor [optional] */
+
+  /* resistance resolution descriptor [optional] */
+
+  /* resolution descriptor [optional] */
+  fprintf (fp, "  (resolution mil 10)\n");
+
+  /* time resolution descriptor [optional] */
+
+  /* voltage resolution descriptor [optional] */
+
+  /* unit descriptor [optional] */
+  fprintf (fp, "  (unit mil)\n");
+
+  /* structure descriptor [required] */
+  print_structure (fp);
+  
+  /* placement descriptor [optional] */
+  print_placement (fp);
+  
+  /* library descriptor [required] */
+  print_library (fp);
+  
+  /* floor plan descriptor [optional] */
+  
+  /* part library descriptor [optional] */
+  
+  /* network descriptor [required] */
+  print_network (fp);
+  
+  /* wiring descriptor [optional] */
+	print_wires (fp);  
+
+  /* color descriptor [optional] */
+
+  fclose (fp);
+
+  return (0);
+}
+
+
+static void
+dsn_do_export (HID_Attr_Val * options)
+{
+  int i;
+  if (!options)
+  {
+    dsn_get_export_options (0);
+    for (i = 0; i < NUM_OPTIONS; i++)
+      dsn_values[i] = dsn_options[i].default_val;
+    options = dsn_values;
+  }
+  dsn_filename = options[HA_dsnfile].str_value;
+  if (!dsn_filename)
+    dsn_filename = "pcb-out.dsn";
+
+  trackwidth = options[HA_trackwidth].int_value;
+  clearance = options[HA_clearance].int_value;
+	viawidth = options[HA_viawidth].int_value;
+	viadrill = options[HA_viadrill].int_value;
+  PrintSPECCTRA ();
+}
+
+static void
+dsn_parse_arguments (int *argc, char ***argv)
+{
+  hid_register_attributes (dsn_options,
+			   sizeof (dsn_options) / sizeof (dsn_options[0]));
+  hid_parse_command_line (argc, argv);
+}
+
+/* dsn import section below */
+/* dsn name */
+static char *dsn_name = NULL;
+
+#define FREE(x) if((x) != NULL) { free (x) ; (x) = NULL; }
+
+static const char load_dsn_syntax[] = "LoadDsnFrom(filename)";
+
+static const char load_dsn_help[] =
+  "Loads the specified dsn resource file.";
+
+/* %start-doc actions LoaddsnFrom
+
+@cindex Specctra routed import
+@findex LoadDsnFrom()
+
+@table @var
+@item filename
+Name of the dsn resource file.  If not specified, the user will
+be prompted to enter one.
+@end table
+
+%end-doc */
+
+int
+ActionLoadDsnFrom (int argc, char **argv, int x, int y)
+{
+  int i;
+  char *fname = NULL;
+  static char *default_file = NULL;
+
+  fname = argc ? argv[0] : 0;
+
+  if (!fname || !*fname)
+  {
+    fname = gui->fileselect (_("Load dsn routing session Resource File..."),
+			       _("Picks a dsn session resource file to load.\n"
+				 "This file could be generated by freeroute.net\n"),
+			       default_file, ".ses", "ses",
+			       HID_FILESELECT_READ);
+    if (fname == NULL)
+		AFAIL (load_dsn);
+    if (default_file != NULL)
+		{
+			free (default_file);
+			default_file = NULL;
+		}
+
+    if (fname && *fname)
+			default_file = strdup (fname);
+  }
+  char str[200];
+  FILE *fp;
+	int ret, dim1, dim2, x0, y0, x1, y1, linethick, lineclear, viadiam, viadrill;
+	char lname[200];
+	LayerType *rlayer;
+	lineclear = PCB->RouteStyle[0].Keepaway * 2;
+  fp = fopen(fname, "r");
+  if(!fp) return 1; // bail out if file not found
+  while(fgets(str,sizeof(str),fp) != NULL)
+  {
+    // strip trailing '\n' if it exists
+    int len = strlen(str)-1;
+    if(str[len] == '\n') 
+       str[len] = 0;
+		ret = sscanf( str, "          (path %s %d", lname, &dim1);
+		if( ret == 2 )
+		{
+			rlayer = 0;
+			LAYER_LOOP( PCB->Data, max_group )
+			{
+				if(!strcmp(layer->Name, lname))
+					rlayer = layer;
+			}
+			END_LOOP;
+			linethick = dim1;
+			x0 = 0;	y0 = 0;
+		}
+		ret = sscanf( str, "            %d %d", &dim1, &dim2 );
+		if( ret == 2 )
+		{
+			x1 = dim1; y1 = dim2;
+			if( x0 != 0 || y0 != 0 )
+			{
+				CreateDrawnLineOnLayer( rlayer, x0*10, PCB->MaxHeight - y0*10, x1*10, PCB->MaxHeight - y1*10, linethick*10, lineclear, MakeFlags (AUTOFLAG | CLEARLINEFLAG) );
+			}
+			x0 = x1; y0 = y1;
+		}
+		ret = sscanf( str, "        (via via_%d_%d_mil %d %d", &viadiam, &viadrill, &dim1, &dim2);
+		if( ret == 4 )
+		{
+			CreateNewVia (PCB->Data, dim1*10, PCB->MaxHeight - dim2*10, viadiam*100, lineclear, 0, viadrill*100, 0, MakeFlags (AUTOFLAG));
+		}
+  }
+  fclose(fp);
+
+	
+	return 0;
+}
+
+HID dsn_hid;
+
+void
+hid_dsn_init ()
+{
+  memset (&dsn_hid, 0, sizeof (HID));
+  common_nogui_init (&dsn_hid);
+
+  dsn_hid.struct_size = sizeof (HID);
+  dsn_hid.name = "dsn";
+  dsn_hid.description = "Exports DSN format";
+  dsn_hid.exporter = 1;
+  dsn_hid.get_export_options = dsn_get_export_options;
+  dsn_hid.do_export = dsn_do_export;
+  dsn_hid.parse_arguments = dsn_parse_arguments;
+  hid_register_hid (&dsn_hid);
+#include "dsn_lists.h"
+}
+
+HID_Action dsn_action_list[] = {
+  {"LoadDsnFrom", 0, ActionLoadDsnFrom,
+   load_dsn_help, load_dsn_syntax}
+};
+
+REGISTER_ACTIONS (dsn_action_list)
+
+
diff --git a/src/hid/dsn/dsn.h b/src/hid/dsn/dsn.h
new file mode 100644
index 0000000..860631a
--- /dev/null
+++ b/src/hid/dsn/dsn.h
@@ -0,0 +1,3 @@
+/* $Id$ */
+
+extern HID dsn_hid;
diff --git a/src/hid/dsn/hid.conf b/src/hid/dsn/hid.conf
new file mode 100644
index 0000000..7be6c4c
--- /dev/null
+++ b/src/hid/dsn/hid.conf
@@ -0,0 +1 @@
+type=export
-- 
1.7.4.1


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user