Index: pcb-exporters/dsn/dsn.c =================================================================== --- pcb-exporters/dsn/dsn.c (nonexistent) +++ pcb-exporters/dsn/dsn.c (revision 4085) @@ -0,0 +1,757 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * + * Specctra .dsn export HID + * Copyright (C) 2008, 2011 Josh Jordan, Dan McMahill, and Jared Casper + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* +This program exports specctra .dsn files from geda .pcb files. +By Josh Jordan and Dan McMahill, modified from bom.c + -- Updated to use Coord and other fixes by Jared Casper 16 Sep 2011 +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#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 "pcb-printf.h" +#include "create.h" +#include "polygon.h" + +#include "hid.h" +#include "hid_draw.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" + +#ifdef HAVE_LIBDMALLOC +#include +#endif + +Coord trackwidth = 8; //user options defined in export dialog +Coord clearance = 8; +Coord viawidth = 45; +Coord viadrill = 25; + +static HID dsn_hid; + +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_Coord, MIL_TO_COORD (0), MIL_TO_COORD (100), {0, 0, 0, MIL_TO_COORD (8)}, 0, 0}, +#define HA_trackwidth 1 + {"clearance", "clearance in mils", + HID_Coord, MIL_TO_COORD (0), MIL_TO_COORD (100), {0, 0, 0, MIL_TO_COORD (8)}, 0, 0}, +#define HA_clearance 2 + {"viawidth", "via width in mils", + HID_Coord, MIL_TO_COORD (0), MIL_TO_COORD (100), {0, 0, 0, MIL_TO_COORD (27)}, 0, + 0}, +#define HA_viawidth 3 + {"viadrill", "via drill diameter in mils", + HID_Coord, MIL_TO_COORD (0), MIL_TO_COORD (100), {0, 0, 0, MIL_TO_COORD (15)}, 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 const 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; +} + + +/* this function is mostly ripped from bom.c */ +static PointType +get_centroid (ElementType * element) +{ + PointType centroid; + double sumx = 0.0, sumy = 0.0; + int pin_cnt = 0; + + PIN_LOOP (element); + { + sumx += (double) pin->X; + sumy += (double) pin->Y; + pin_cnt++; + } + 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++; + } + END_LOOP; + + if (pin_cnt > 0) + { + centroid.X = sumx / (double) pin_cnt; + centroid.Y = PCB->MaxHeight - (sumy / (double) pin_cnt); + } + else + { + centroid.X = 0; + centroid.Y = 0; + } + return centroid; +} + +GList *layerlist = NULL; // contain routing layers + +static void +print_structure (FILE * fp) +{ + int group; + int top_group = GetLayerGroupNumberByNumber (top_silk_layer); + int bot_group = GetLayerGroupNumberByNumber (bottom_silk_layer); + + int top_layer = PCB->LayerGroups.Entries[top_group][0]; + int bot_layer = PCB->LayerGroups.Entries[bot_group][0]; + + g_list_free (layerlist); // might be around from the last export + + if (PCB->Data->Layer[top_layer].On) + { + layerlist = g_list_append (layerlist, &PCB->Data->Layer[top_layer]); + } + else + { + gui->log ("WARNING! DSN export does not include the top layer. " + "Router will consider an inner layer to be the \"top\" layer.\n"); + } + + for (group = 0; group < max_group; group++) + { + LayerType *first_layer; + if (group == top_group || group == bot_group) + continue; + + if (PCB->LayerGroups.Number[group] < 1) + continue; + + first_layer = &PCB->Data->Layer[PCB->LayerGroups.Entries[group][0]]; + if (!first_layer->On) + continue; + + layerlist = g_list_append (layerlist, first_layer); + + if (group < top_group) + { + gui->log ("WARNING! DSN export moved layer group with the \"%s\" layer " + "after the top layer group. DSN files must have the top " + "layer first.\n", first_layer->Name); + } + + if (group > bot_group) + { + gui->log ("WARNING! DSN export moved layer group with the \"%s\" layer " + "before the bottom layer group. DSN files must have the " + "bottom layer last.\n", first_layer->Name); + } + + GROUP_LOOP (PCB->Data, group); + { + if (entry > 0) + { + gui->log ("WARNING! DSN export squashed layer \"%s\" into layer " + "\"%s\", DSN files do not have layer groups.", + layer->Name, first_layer->Name); + } + } + END_LOOP; + } + + if (PCB->Data->Layer[bot_layer].On) + { + layerlist = g_list_append (layerlist, &PCB->Data->Layer[bot_layer]); + } + else + { + gui->log ("WARNING! DSN export does not include the bottom layer. " + "Router will consider an inner layer to be the \"bottom\" layer.\n"); + } + + fprintf (fp, " (structure\n"); + + for (GList *iter = layerlist; iter; iter = g_list_next (iter)) + { + LayerType *layer = iter->data; + char *layeropts = g_strdup_printf ("(type signal)"); + /* see if layer has same name as a net and make it a power layer */ + //loop thru all nets + for (int ni = 0; ni < PCB->NetlistLib.MenuN; ni++) + { + 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", layer->Name); + fprintf (fp, " %s\n", layeropts); + fprintf (fp, " )\n"); + g_free (layeropts); + } + + /* PCB outline */ + pcb_fprintf (fp, " (boundary\n"); + pcb_fprintf (fp, " (rect pcb 0.0 0.0 %.6mm %.6mm)\n", PCB->MaxWidth, PCB->MaxHeight); + pcb_fprintf (fp, " )\n"); + pcb_fprintf (fp, " (via via_%ld_%ld)\n", viawidth, viadrill); + + /* DRC rules */ + pcb_fprintf (fp, " (rule\n"); + pcb_fprintf (fp, " (width %mm)\n", trackwidth); + pcb_fprintf (fp, " (clear %mm)\n", clearance); + pcb_fprintf (fp, " (clear %mm (type wire_area))\n", clearance); + pcb_fprintf (fp, " (clear %mm (type via_smd via_pin))\n", clearance); + pcb_fprintf (fp, " (clear %mm (type smd_smd))\n", clearance); + pcb_fprintf (fp, " (clear %mm (type default_smd))\n", clearance); + pcb_fprintf (fp, " )\n )\n"); +} + +static void +print_placement (FILE * fp) +{ + fprintf (fp, " (placement\n"); + ELEMENT_LOOP (PCB->Data); + { + char *ename; + PointType ecentroid = get_centroid (element); + char *side = TEST_FLAG (ONSOLDERFLAG, element) ? "back" : "front"; + ename = g_strdup (NAMEONPCB_NAME (element)); + if (!ename) + ename = g_strdup_printf ("null"); + pcb_fprintf (fp, " (component %d\n", element->ID); + pcb_fprintf (fp, " (place \"%s\" %.6mm %.6mm %s 0 (PN 0))\n", ename, + ecentroid.X, ecentroid.Y, side); + pcb_fprintf (fp, " )\n"); + g_free (ename); + } + END_LOOP; + + VIA_LOOP (PCB->Data); + { //add mounting holes + pcb_fprintf (fp, " (component %d\n", via->ID); + pcb_fprintf (fp, " (place %d %.6mm %.6mm %s 0 (PN 0))\n", via->ID, + via->X, (PCB->MaxHeight - via->Y), "front"); + pcb_fprintf (fp, " )\n"); + } + END_LOOP; + fprintf (fp, " )\n"); +} + +static void +print_library (FILE * fp) +{ + GList *pads = NULL, *iter; //contain unique pad names + gchar *padstack; + fprintf (fp, " (library\n"); + ELEMENT_LOOP (PCB->Data); + { + int partside = TEST_FLAG (ONSOLDERFLAG, element) ? g_list_length (layerlist) - 1 : 0; + int partsidesign = TEST_FLAG (ONSOLDERFLAG, element) ? -1 : 1; + PointType centroid = get_centroid (element); + fprintf (fp, " (image %ld\n", element->ID); //map every element by ID + /* loop thru pins and pads to add to image */ + PIN_LOOP (element); + { + Coord ty; + Coord pinthickness; + Coord lx, ly; //hold local pin coordinates + ty = PCB->MaxHeight - pin->Y; + pinthickness = pin->Thickness; + if (TEST_FLAG (SQUAREFLAG, pin)) + padstack = g_strdup_printf ("Th_square_%ld", pinthickness); + else + padstack = g_strdup_printf ("Th_round_%ld", pinthickness); + lx = (pin->X - centroid.X) * partsidesign; + ly = (centroid.Y - ty) * -1; + + if (!pin->Number) + { //if pin is null just make it a keepout + for (GList * iter = layerlist; iter; iter = g_list_next (iter)) + { + LayerType *lay = iter->data; + pcb_fprintf (fp, + " (keepout \"\" (circle \"%s\" %.6mm %.6mm %.6mm))\n", + lay->Name, pinthickness, lx, ly); + } + } + else + { + pcb_fprintf (fp, " (pin %s \"%s\" %.6mm %.6mm)\n", padstack, + pin->Number, lx, ly); + } + + if (!g_list_find_custom (pads, padstack, (GCompareFunc) strcmp)) + pads = g_list_append (pads, padstack); + else + g_free (padstack); + } + END_LOOP; + + PAD_LOOP (element); + { + Coord xlen, ylen, xc, yc, p1y, p2y; + Coord 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); + if (xlen == 0) + { + xlen = pad->Thickness; + ylen = ABS (p1y - p2y) + pad->Thickness; + } + else + { + ylen = pad->Thickness; + xlen += pad->Thickness; + } + xc = (pad->Point1.X + pad->Point2.X) / 2; + yc = (p1y + p2y) / 2; + lx = (xc - centroid.X) * partsidesign; + ly = (centroid.Y - yc) * -1; + padstack = g_strdup_printf ("Smd_rect_%ldx%ld", xlen, ylen); + + if (!pad->Number) + { //if pad is null just make it a keepout + LayerType *lay; + lay = g_list_nth_data (layerlist, partside); + pcb_fprintf (fp, " (keepout \"\" (rect \"%s\" %.6mm %.6mm %.6mm %.6mm))\n", + lay->Name, lx - xlen / 2, ly - ylen / 2, lx + xlen / 2, + ly + ylen / 2); + } + else + { + pcb_fprintf (fp, " (pin %s \"%s\" %.6mm %.6mm)\n", + padstack, pad->Number, lx, ly); + } + if (!g_list_find_custom (pads, padstack, (GCompareFunc) 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 %ld\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_%ld", via->Thickness + via->Clearance); + 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, (GCompareFunc) strcmp)) + pads = g_list_append (pads, padstack); + else + g_free (padstack); + } + END_LOOP; + + /* loop thru padstacks and define them all */ + for (iter = pads; iter; iter = g_list_next (iter)) + { + Coord dim1, dim2; + padstack = iter->data; + fprintf (fp, " (padstack %s\n", padstack); + + /* print info about pad here */ + if (sscanf (padstack, "Smd_rect_%ldx%ld", &dim1, &dim2) == 2) + { //then pad is smd + pcb_fprintf (fp, + " (shape (rect \"%s\" %.6mm %.6mm %.6mm %.6mm))\n", + ((LayerType *)(g_list_first(layerlist)->data))->Name, + dim1 / -2, dim2 / -2, dim1 / 2, dim2 / 2); + } + else if (sscanf (padstack, "Th_square_%ld", &dim1) == 1) + { + pcb_fprintf (fp, + " (shape (rect signal %.6mm %.6mm %.6mm %.6mm))\n", + dim1 / -2, dim1 / -2, dim1 / 2, dim1 / 2); + } + else + { + sscanf (padstack, "Th_round_%ld", &dim1); + pcb_fprintf (fp, " (shape (circle signal %.6mm))\n", dim1); + } + fprintf (fp, " (attach off)\n"); + fprintf (fp, " )\n"); + } + + /* add padstack for via */ + pcb_fprintf (fp, " (padstack via_%ld_%ld\n", viawidth, viadrill); + pcb_fprintf (fp, " (shape (circle signal %.6mm))\n", viawidth); + pcb_fprintf (fp, " (attach off)\n )\n"); + pcb_fprintf (fp, " )\n"); + g_list_foreach (pads, (GFunc) g_free, NULL); + g_list_free (pads); +} + +static void +print_quoted_pin (FILE *fp, const char *s) +{ + char *hyphen_pos = strchr (s, '-'); + if (!hyphen_pos) + { + fprintf (fp, " %s", s); + } + else + { + char refdes_name[1024]; + int copy_len = hyphen_pos - s; + if (copy_len >= sizeof(refdes_name)) + copy_len = sizeof(refdes_name) - 1; + strncpy (refdes_name, s, copy_len); + refdes_name[copy_len] = 0; + fprintf (fp, " \"%s\"-\"%s\"", refdes_name, hyphen_pos+1); + } +} + +static void +print_network (FILE * fp) +{ + int ni, nei; + fprintf (fp, " (network\n"); + for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) + { + fprintf (fp, " (net \"%s\"\n", PCB->NetlistLib.Menu[ni].Name + 2); + fprintf (fp, " (pins"); + for (nei = 0; nei < PCB->NetlistLib.Menu[ni].EntryN; nei++) + print_quoted_pin (fp, PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry); + fprintf (fp, ")\n"); + fprintf (fp, " )\n"); + } + + fprintf (fp, " (class geda_default"); + for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) + { + fprintf (fp, " \"%s\"", PCB->NetlistLib.Menu[ni].Name + 2); + } + pcb_fprintf (fp, "\n"); + pcb_fprintf (fp, " (circuit\n"); + pcb_fprintf (fp, " (use_via via_%ld_%ld)\n", viawidth, viadrill); + pcb_fprintf (fp, " )\n"); + pcb_fprintf (fp, " (rule (width %.6mm))\n )\n )\n", trackwidth); +} + +static void +print_wires (FILE * fp) +{ + GList *iter; + LayerType *lay; + fprintf (fp, " (wiring\n"); + + for (iter = layerlist; iter; iter = g_list_next (iter)) + { + lay = iter->data; + LINE_LOOP (lay); + { + pcb_fprintf (fp, + " (wire (path %s %.6mm %.6mm %.6mm %.6mm %.6mm)\n", + lay->Name, line->Thickness, line->Point1.X, + (PCB->MaxHeight - line->Point1.Y), line->Point2.X, + (PCB->MaxHeight - line->Point2.Y)); + 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 \"%s\")\n", VERSION); + 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 mm 1000000)\n"); + + /* time resolution descriptor [optional] */ + + /* voltage resolution descriptor [optional] */ + + /* unit descriptor [optional] */ + + /* 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].coord_value; + clearance = options[HA_clearance].coord_value; + viawidth = options[HA_viawidth].coord_value; + viadrill = options[HA_viadrill].coord_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 */ +#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, Coord x, Coord y) +{ + char *fname = NULL; + static char *default_file = NULL; + char str[200]; + FILE *fp; + int ret; + Coord dim1, dim2, x0 = 0, y0 = 0, x1, y1; + Coord linethick = 0, lineclear, viadiam, viadrill; + char lname[200]; + LayerType *rlayer = NULL; + LineType *line = 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); + } + + 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 %ld", 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, " %ld %ld", &dim1, &dim2); + if (ret == 2) + { + x1 = dim1; + y1 = dim2; + if (x0 != 0 || y0 != 0) + { + line = CreateDrawnLineOnLayer (rlayer, x0, PCB->MaxHeight - y0, + x1, PCB->MaxHeight - y1, + linethick, lineclear, + MakeFlags (AUTOFLAG | CLEARLINEFLAG)); + ClearFromPolygon (PCB->Data, LINE_TYPE, rlayer, line); + } + x0 = x1; + y0 = y1; + } + ret = sscanf (str, " (via via_%ld_%ld %ld %ld", + &viadiam, &viadrill, &dim1, &dim2); + if (ret == 4) + { + CreateNewVia (PCB->Data, dim1, PCB->MaxHeight - dim2, viadiam, + lineclear, 0, viadrill, 0, MakeFlags (AUTOFLAG)); + } + } + fclose (fp); + return 0; +} + +HID_Action dsn_action_list[] = { + {"LoadDsnFrom", 0, ActionLoadDsnFrom, load_dsn_help, load_dsn_syntax} +}; + +REGISTER_ACTIONS (dsn_action_list) +#include "dolists.h" + +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" +} Index: pcb-exporters/dsn/ml/Re: gEDA-user: dsn exporter_2.html =================================================================== --- pcb-exporters/dsn/ml/Re: gEDA-user: dsn exporter_2.html (nonexistent) +++ pcb-exporters/dsn/ml/Re: gEDA-user: dsn exporter_2.html (revision 4085) @@ -0,0 +1,1032 @@ + + + + + + + + + + +Re: gEDA-user: dsn exporter + + + + + + +
+[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index] + + + +

Re: gEDA-user: dsn exporter

+
+ + + + + +
+ + +
   Heres a patch that should install specctra.c
+   --- On Sun, 7/26/09, Josh Jordan <outerspaceman81@xxxxxxxxx> wrote:
+
+     From: Josh Jordan <outerspaceman81@xxxxxxxxx>
+     Subject: gEDA-user: dsn exporter
+     To: geda-user@xxxxxxxxxxxxxx
+     Date: Sunday, July 26, 2009, 3:46 PM
+
+      This exporter outputs a .dsn file for opening with freeroute.net.
+   It
+      only works on 2 layer designs so far.
+      I did not start writing an importer for it yet, if anyone has
+      suggestions on the architecture of this I will listen.  (.cmd
+   file?)
+      I will be out of town for the next 10 days and then I will work on
+   the
+      importer.
+      To install it, make a specctra directory in the hid directory, put
+      this file in it, a copy of hid.conf, make a change to makefile.am
+   in
+      /src, and make install again.
+
+     -----Inline Attachment Follows-----
+
+   _______________________________________________
+   geda-user mailing list
+   [1]geda-user@xxxxxxxxxxxxxx
+   [2]http://www.seul.org/cgi-bin/mailman/listinfo/geda-user
+
+References
+
+   1. file://localhost/mc/compose?to=geda-user@xxxxxxxxxxxxxx
+   2. http://www.seul.org/cgi-bin/mailman/listinfo/geda-user
+
From 86ae4751febed03dd601d96142c5e9051e3e545c Mon Sep 17 
+00:00:00 2001
+From: Josh <joshq@joshq-laptop.(none)>
+Date: Sun, 26 Jul 2009 16:34:41 -0400
+Subject: [PATCH] specctra dsn exporter 2 layers only
+
+---
+ src/hid/specctra/hid.conf   |    1 +
+ src/hid/specctra/specctra.c |  837 
++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 838 insertions(+), 0 deletions(-)
+ create mode 100644 src/hid/specctra/hid.conf
+ create mode 100644 src/hid/specctra/specctra.c
+
+diff --git a/src/hid/specctra/hid.conf b/src/hid/specctra/hid.conf
+new file mode 100644
+index 0000000..7be6c4c
+--- /dev/null
++++ b/src/hid/specctra/hid.conf
+@@ -0,0 +1 @@
++type=export
+diff --git a/src/hid/specctra/specctra.c b/src/hid/specctra/specctra.c
+new file mode 100644
+index 0000000..1dab7b5
+--- /dev/null
++++ b/src/hid/specctra/specctra.c
+@@ -0,0 +1,837 @@
++/*
++This program exports specctra .dsn files from geda .pcb files.
++By Josh Jordan
++*/
++
++#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 "hid.h"
++#include "../hidint.h"
++
++#ifdef HAVE_LIBDMALLOC
++#include <dmalloc.h>
++#endif
++
++static HID_Attribute specctra_options[] = {
++  {"specctrafile", "SPECCTRA output file",
++   HID_String, 0, 0, {0, 0, 0}, 0, 0},
++#define HA_specctrafile 0
++  {"trackwidth", "default track width in mils",
++   HID_Integer, 0, 0, {0, 0, 0}, 0, 0},
++#define HA_trackwidth 1
++};
++
++#define NUM_OPTIONS 
+(sizeof(specctra_options)/sizeof(specctra_options[0]))
++
++static HID_Attr_Val specctra_values[NUM_OPTIONS];
++
++static char *specctra_filename;
++
++typedef struct _StringList
++{
++  char *str;
++  struct _StringList *next;
++} StringList;
++
++typedef struct _SpecctraList
++{
++  char *descr;
++  char *value;
++  int num;
++  StringList *refdes;
++  struct _SpecctraList *next;
++} SpecctraList;
++
++static HID_Attribute *
++specctra_get_export_options (int *n)
++{
++  static char *last_specctra_filename = 0;
++  if (PCB) {
++	derive_default_filename(PCB->Filename, 
+&specctra_options[HA_specctrafile], ".dsn", 
+&last_specctra_filename);
++  }
++
++  if (n)
++    *n = NUM_OPTIONS;
++  return specctra_options;
++}
++
++
++static char *
++CleanSPECCTRAString (char *in)
++{
++  char *out;
++  int i;
++
++  if ((out = malloc ((strlen (in) + 1) * sizeof (char))) == NULL)
++    {
++      fprintf (stderr, "Error:  CleanSPECCTRAString() malloc() 
+failed\n");
++      exit (1);
++    }
++
++  /* 
++   * copy over in to out with some character conversions.
++   * Go all the way to then end to get the terminating \0
++   */
++  for (i = 0; i <= strlen (in); i++)
++    {
++      switch (in[i])
++	{
++	case '"':
++	  out[i] = '\'';
++	  break;
++	default:
++	  out[i] = in[i];
++	}
++    }
++
++  return out;
++}
++
++
++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;
++  }
++}
++
++
++static StringList *
++string_insert (char *str, StringList * list)
++{
++  StringList *new, *cur;
++
++  if ((new = (StringList *) malloc (sizeof (StringList))) == NULL)
++    {
++      fprintf (stderr, "malloc() failed in string_insert()\n");
++      exit (1);
++    }
++
++  new->next = NULL;
++  new->str = strdup (str);
++
++  if (list == NULL)
++    return (new);
++
++  cur = list;
++  while (cur->next != NULL)
++    cur = cur->next;
++
++  cur->next = new;
++
++  return (list);
++}
++
++static SpecctraList *
++specctra_insert (char *refdes, char *descr, char *value, SpecctraList *
+ specctra)
++{
++  SpecctraList *new, *cur, *prev = NULL;
++
++  if (specctra == NULL)
++    {
++      /* this is the first element so automatically create an entry */
++      if ((new = (SpecctraList *) malloc (sizeof (SpecctraList))) == 
+NULL)
++	{
++	  fprintf (stderr, "malloc() failed in specctra_insert()\n");
++	  exit (1);
++	}
++
++      new->next = NULL;
++      new->descr = strdup (descr);
++      new->value = strdup (value);
++      new->num = 1;
++      new->refdes = string_insert (refdes, NULL);
++      return (new);
++    }
++
++  /* search and see if we already have used one of these
++     components */
++  cur = specctra;
++  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 ((new = (SpecctraList *) malloc (sizeof (SpecctraList))) == 
+NULL)
++	{
++	  fprintf (stderr, "malloc() failed in specctra_insert()\n");
++	  exit (1);
++	}
++
++      prev->next = new;
++
++      new->next = NULL;
++      new->descr = strdup (descr);
++      new->value = strdup (value);
++      new->num = 1;
++      new->refdes = string_insert (refdes, NULL);
++    }
++
++  return (specctra);
++
++}
++
++/* 
++ * If fp is not NULL then print out the bill of materials contained in
++ * specctra.  Either way, free all memory which has been allocated for 
+specctra.
++ */
++static void
++print_and_free (FILE *fp, SpecctraList *specctra)
++{
++  SpecctraList *lastb;
++  StringList *lasts;
++  char *descr, *value;
++
++  while (specctra != NULL)
++    {
++      if (fp)
++	{
++	  descr = CleanSPECCTRAString (specctra->descr);
++	  value = CleanSPECCTRAString (specctra->value);
++	  fprintf (fp, "%d,\"%s\",\"%s\",", specctra->num, descr, value);
++	  free (descr);
++	  free (value);
++	}
++      
++      while (specctra->refdes != NULL)
++	{
++	  if (fp)
++	    {
++	      fprintf (fp, "%s ", specctra->refdes->str);
++	    }
++	  free (specctra->refdes->str);
++	  lasts = specctra->refdes;
++	  specctra->refdes = specctra->refdes->next;
++	  free (lasts);
++	}
++      if (fp)
++	{
++	  fprintf (fp, "\n");
++	}
++      lastb = specctra;
++      specctra = specctra->next;
++      free (lastb);
++    }
++}
++
++static void
++print_structure (FILE *fp)
++{
++  fprintf (fp, "  (structure\n");
++
++  /* define layers */
++  fprintf (fp, "    (layer Component\n");
++  fprintf (fp, "      (type signal)\n");
++  fprintf (fp, "      (property\n");
++  fprintf (fp, "        (index 0)\n      )\n    )\n");
++  fprintf (fp, "    (layer Copper\n");
++  fprintf (fp, "      (type signal)\n");
++  fprintf (fp, "      (property\n");
++  fprintf (fp, "        (index 1)\n      )\n    )\n");
++
++  /* 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_45_25_mil\")\n");
++
++  /* DRC rules */
++  fprintf (fp, "    (rule\n");
++  fprintf (fp, "      (width 8)\n");
++  fprintf (fp, "      (clear 10)\n");
++  fprintf (fp, "      (clear 10 (type wire_area))\n");
++  fprintf (fp, "      (clear 10 (type via_smd via_pin))\n");
++  fprintf (fp, "      (clear 10 (type smd_smd))\n");
++  fprintf (fp, "      (clear 10 (type default_smd))\n");
++  fprintf (fp, "    )\n  )\n");
++}
++
++static void
++print_placement (FILE *fp)
++/* gather all footprint names in a list
++   gather list of refdes for each footprint in list */
++{
++  int i;
++  GList *footprints; //contain unique footprint names
++  fprintf (fp, "  (placement\n");
++  ELEMENT_LOOP (PCB->Data);
++  {
++    gconstpointer descript = DESCRIPTION_NAME (element);
++    if( !g_list_find_custom( footprints, descript, strcmp ) ){
++      footprints = g_list_append( footprints, descript );
++    }
++  }
++  END_LOOP;
++  for(i=0; i < g_list_length( footprints ); i++){
++    int firstrot = -1; //change to the degree of the first element 
+found
++    fprintf (fp, "    (component %s\n", g_list_nth_data( footprints, i 
+));
++    ELEMENT_LOOP (PCB->Data);
++    {
++      if(!strcmp(DESCRIPTION_NAME (element), g_list_nth_data( 
+footprints, i ) )){
++        CentroidRotation crot = get_rotation_and_centroid(element);
++        if (firstrot == -1)
++        {
++          firstrot = crot.rot;
++        }
++        char* side = TEST_FLAG (ONSOLDERFLAG, element) ? "back" : 
+"front";
++        fprintf (fp, "      (place %s %.2f %.2f %s %d (PN %s))\n", 
+NAMEONPCB_NAME (element), crot.centx, crot.centy, side, 
+firstrot-crot.rot, VALUE_NAME (element) );
++      }
++    }
++    END_LOOP;
++    fprintf (fp, "    )\n");
++  }
++  fprintf (fp, "  )\n");
++  g_list_free( footprints );
++}
++
++static void
++print_library (FILE *fp)
++/* gather all footprint names in a list
++   print info on each footprint */
++{
++  int i;
++  GList *footprints; //contain unique footprint names
++  GList *pads; //contain unique pad names
++  fprintf (fp, "  (library\n");
++  ELEMENT_LOOP (PCB->Data);
++  {
++    if( !g_list_find_custom( footprints, DESCRIPTION_NAME (element), 
+strcmp ) ){
++      char *padstack;
++      int rotation;
++      int whichside = TEST_FLAG (ONSOLDERFLAG, element) ? -1 : 1;
++      CentroidRotation crot = get_rotation_and_centroid(element);
++      footprints = g_list_append( footprints, g_strdup( 
+DESCRIPTION_NAME (element) ) );
++      fprintf (fp, "    (image %s\n", DESCRIPTION_NAME (element) );
++      /* loop thru pins and pads here */
++      PIN_LOOP (element);
++      {
++        int ty;
++        float pinthickness;
++        float lx, ly; //hold local pin coordinates
++        ty = PCB->MaxHeight - pin->Y;
++        pinthickness = pin->Thickness*0.01;
++        padstack = g_strdup_printf ("Th_round_%.0f_mil", pinthickness);
++        lx = (pin->X*0.01-crot.centx)*whichside;
++        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
++        {
++          fprintf (fp, "      (keepout \"\" (circle Component %.0f %.2f
+ %.2f))\n", pinthickness, lx, ly);
++          fprintf (fp, "      (keepout \"\" (circle Copper %.0f %.2f 
+%.2f))\n", 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 thickness and 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)*whichside;
++        ly = (crot.centy - yc*0.01)*(-1);
++        padstack = g_strdup_printf ("Smd_rect_%dx%d_mil", xlen, ylen);
++        if( !g_list_find_custom( pads, padstack, strcmp ) )
++        {
++          pads = g_list_append( pads, padstack );
++        }
++        if (!pad->Number) //if pad is null just make it a keepout
++        {
++          fprintf (fp, "      (keepout \"\" (rect %s %.2f %.2f %.2f 
+%.2f))\n", (whichside == 1) ? "Component" : "Copper", 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);
++        }
++      }
++      END_LOOP;
++      fprintf (fp, "    )\n");
++    }
++  }
++  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 );
++    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
++    { 
++      fprintf (fp, "      (shape (rect Component %.1f %.1f %.1f 
+%.1f))\n", dim1/(-2.0), dim2/(-2.0), dim1/2.0, dim2/2.0);
++    }
++    else ///then pad is th
++    {
++      retargs = sscanf (padstring, "Th_round_%d_mil", &dim1);
++      fprintf (fp, "      (shape (circle Component %d))\n", dim1);
++      fprintf (fp, "      (shape (circle Copper %d))\n", dim1);
++    }
++    fprintf (fp, "      (attach off)\n");
++    fprintf (fp, "    )\n");
++  }
++  /* add padstack for via */
++  fprintf (fp, "    (padstack \"via_45_25_mil\"\n      (shape (circle 
+Component 45))\n      (shape (circle Copper 45))\n      (attach off)\n  
+  )\n");
++  fprintf (fp, "  )\n");
++  g_list_foreach( footprints, (GFunc)g_free, NULL );
++  g_list_free( footprints );
++  g_list_foreach( pads, (GFunc)g_free, NULL );
++  g_list_free( pads );
++}
++
++static void
++print_network (FILE *fp)
++{
++  GList *netlistnames;  //contain unique strings of netlist names
++  int i, firstcon;
++  NetListListType Nets;
++  Nets = CollectSubnets (False);
++  fprintf (fp, "  (network\n");
++  NETLIST_LOOP (&Nets);
++  {
++    firstcon = 1; //clear flag after net name is found
++    NET_LOOP (netlist);
++    {
++      CONNECTION_LOOP (net);
++      {
++        int ni, nei;
++	      char *ename;
++	      char *pname;
++	      char *n;
++        char *netname;
++        /* looking for pins and pads */
++        if (connection->type == PIN_TYPE || connection->type == 
+PAD_TYPE)
++        {
++          PinTypePtr thispin;
++          PadTypePtr thispad;
++          ElementTypePtr thiselem;
++          if (connection->type == PIN_TYPE)
++          {
++            thispin = connection->ptr2;
++            thiselem = thispin->Element;
++            pname = thispin->Number;
++          }
++          else
++          {
++            thispad = connection->ptr2;
++            thiselem = thispad->Element;
++            pname = thispad->Number;
++          }
++          ename = NAMEONPCB_NAME(thiselem);
++          n = g_strconcat (ename, "-", pname, NULL);
++	        for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop 
+thru all nets
++		      for (nei = 0; nei < PCB->NetlistLib.Menu[ni].EntryN; 
+nei++) //loop thru all entries in all nets
++		      {
++		        if (strcmp (PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry,
+ n) == 0) //find the entry that matches this pin or pad
++		        {
++              netname = g_strdup (PCB->NetlistLib.Menu[ni].Name + 
+2); //find the net name of this entry
++              //if( !g_list_find_custom( netlistnames, netname, strcmp )
+ ) //see if netlist was written down already
++              if(firstcon == 1)
++              {
++                firstcon = 0;
++                netlistnames = g_list_append( netlistnames, netname );
++                fprintf (fp, "    (net %s\n      (pins", netname);
++              }
++            }
++          }
++          fprintf (fp, " %s", n);
++          g_free(n);
++        }
++      }
++      END_LOOP;
++    }
++    END_LOOP;
++    fprintf (fp, ")\n    )\n");
++  }
++  END_LOOP;
++  fprintf (fp, "    (class geda_default");
++  for(i=0; i < g_list_length( netlistnames ); i++)
++  {
++    fprintf (fp, " %s", g_list_nth_data( netlistnames, i ) );
++  }
++  fprintf (fp, "\n      (circuit\n        (use_via via_45_25_mil)\n    
+  )\n");
++  fprintf (fp, "      (rule (width 8))\n    )\n  )\n");
++  fprintf (fp, "  (wiring\n  )\n)\n");
++  
++  g_list_foreach( netlistnames, (GFunc)g_free, NULL );
++  g_list_free( netlistnames );
++}
++
++static int
++PrintSPECCTRA (void)
++{
++  char utcTime[64];
++  double x, y, theta = 0.0, user_x, user_y;
++  double sumx, sumy;
++  double pin1x = 0.0, pin1y = 0.0, pin1angle = 0.0;
++  double pin2x = 0.0, pin2y = 0.0, pin2angle;
++  int found_pin1;
++  int found_pin2;
++  int pin_cnt;
++  time_t currenttime;
++  FILE *fp;
++  SpecctraList *specctra = NULL;
++  char *name, *descr, *value;
++
++  /* Print out the specctra .dsn file. */
++
++  fp = fopen (specctra_filename, "w");
++  if (!fp)
++    {
++      gui->log ("Cannot open file %s for writing\n", 
+specctra_filename);
++      print_and_free (NULL, specctra);
++      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] */
++  
++  /* color descriptor [optional] */
++  
++  print_and_free (fp, specctra);
++
++  fclose (fp);
++
++  return (0);
++}
++
++static void
++specctra_do_export (HID_Attr_Val * options)
++{
++  int i;
++
++  if (!options)
++    {
++      specctra_get_export_options (0);
++      for (i = 0; i < NUM_OPTIONS; i++)
++	specctra_values[i] = specctra_options[i].default_val;
++      options = specctra_values;
++    }
++
++  specctra_filename = options[HA_specctrafile].str_value;
++  if (!specctra_filename)
++    specctra_filename = "pcb-out.dsn";
++
++  PrintSPECCTRA ();
++}
++
++static void
++specctra_parse_arguments (int *argc, char ***argv)
++{
++  hid_register_attributes (specctra_options,
++			   sizeof (specctra_options) / sizeof (specctra_options[0]));
++  hid_parse_command_line (argc, argv);
++}
++
++HID specctra_hid = {
++  sizeof (HID),
++  "specctra",
++  "Exports a SPECCTRA .dsn file",
++  0, 0, 1, 0, 0, 0,
++  specctra_get_export_options,
++  specctra_do_export,
++  specctra_parse_arguments,
++  0,				/* specctra_invalidate_wh */
++  0,				/* specctra_invalidate_lr */
++  0,				/* specctra_invalidate_all */
++  0,				/* specctra_set_layer */
++  0,				/* specctra_make_gc */
++  0,				/* specctra_destroy_gc */
++  0,				/* specctra_use_mask */
++  0,				/* specctra_set_color */
++  0,				/* specctra_set_line_cap */
++  0,				/* specctra_set_line_width */
++  0,				/* specctra_set_draw_xor */
++  0,				/* specctra_set_draw_faded */
++  0,				/* specctra_set_line_cap_angle */
++  0,				/* specctra_draw_line */
++  0,				/* specctra_draw_arc */
++  0,				/* specctra_draw_rect */
++  0,				/* specctra_fill_circle */
++  0,				/* specctra_fill_polygon */
++  0,				/* specctra_fill_rect */
++  0,				/* specctra_calibrate */
++  0,				/* specctra_shift_is_pressed */
++  0,				/* specctra_control_is_pressed */
++  0,				/* specctra_get_coords */
++  0,				/* specctra_set_crosshair */
++  0,				/* specctra_add_timer */
++  0,				/* specctra_stop_timer */
++  0,				/* specctra_log */
++  0,				/* specctra_logv */
++  0,				/* specctra_confirm_dialog */
++  0,				/* specctra_close_confirm_dialog */
++  0,				/* specctra_report_dialog */
++  0,				/* specctra_prompt_for */
++  0,				/* specctra_fileselect */
++  0,				/* specctra_attribute_dialog */
++  0,				/* specctra_show_item */
++  0,				/* specctra_beep */
++  0,				/* specctra_progress */
++};
++
++void
++hid_specctra_init ()
++{
++  apply_default_hid (&specctra_hid, 0);
++  hid_register_hid (&specctra_hid);
++}
++
+-- 
+1.6.0.4
+
+
+_______________________________________________
+geda-user mailing list
+geda-user@xxxxxxxxxxxxxx
+http://www.seul.org/cgi-bin/mailman/listinfo/geda-user
+
+ + + +
+ + + + + + + + + + + + \ No newline at end of file Index: pcb-exporters/dsn/ml/gEDA-user: dsn exporter.html =================================================================== --- pcb-exporters/dsn/ml/gEDA-user: dsn exporter.html (nonexistent) +++ pcb-exporters/dsn/ml/gEDA-user: dsn exporter.html (revision 4085) @@ -0,0 +1,935 @@ + + + + + + + + + + +gEDA-user: dsn exporter + + + + + + +
+[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index] + + + +

gEDA-user: dsn exporter

+
+ + + + + +
+ + +
   This exporter outputs a .dsn file for opening with freeroute.net.  It
+   only works on 2 layer designs so far.
+   I did not start writing an importer for it yet, if anyone has
+   suggestions on the architecture of this I will listen.  (.cmd file?)
+   I will be out of town for the next 10 days and then I will work on the
+   importer.
+   To install it, make a specctra directory in the hid directory, put
+   this file in it, a copy of hid.conf, make a change to makefile.am in
+   /src, and make install again.
+
/*
+This program exports specctra .dsn files from geda .pcb files.
+By Josh Jordan
+*/
+
+#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 "hid.h"
+#include "../hidint.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+static HID_Attribute specctra_options[] = {
+  {"specctrafile", "SPECCTRA output file",
+   HID_String, 0, 0, {0, 0, 0}, 0, 0},
+#define HA_specctrafile 0
+  {"trackwidth", "default track width in mils",
+   HID_Integer, 0, 0, {0, 0, 0}, 0, 0},
+#define HA_trackwidth 1
+};
+
+#define NUM_OPTIONS (sizeof(specctra_options)/sizeof(specctra_options[0]))
+
+static HID_Attr_Val specctra_values[NUM_OPTIONS];
+
+static char *specctra_filename;
+
+typedef struct _StringList
+{
+  char *str;
+  struct _StringList *next;
+} StringList;
+
+typedef struct _SpecctraList
+{
+  char *descr;
+  char *value;
+  int num;
+  StringList *refdes;
+  struct _SpecctraList *next;
+} SpecctraList;
+
+static HID_Attribute *
+specctra_get_export_options (int *n)
+{
+  static char *last_specctra_filename = 0;
+  if (PCB) {
+	derive_default_filename(PCB->Filename, &specctra_options[HA_specctrafile], ".dsn", &last_specctra_filename);
+  }
+
+  if (n)
+    *n = NUM_OPTIONS;
+  return specctra_options;
+}
+
+
+static char *
+CleanSPECCTRAString (char *in)
+{
+  char *out;
+  int i;
+
+  if ((out = malloc ((strlen (in) + 1) * sizeof (char))) == NULL)
+    {
+      fprintf (stderr, "Error:  CleanSPECCTRAString() malloc() failed\n");
+      exit (1);
+    }
+
+  /* 
+   * copy over in to out with some character conversions.
+   * Go all the way to then end to get the terminating \0
+   */
+  for (i = 0; i <= strlen (in); i++)
+    {
+      switch (in[i])
+	{
+	case '"':
+	  out[i] = '\'';
+	  break;
+	default:
+	  out[i] = in[i];
+	}
+    }
+
+  return out;
+}
+
+
+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;
+  }
+}
+
+
+static StringList *
+string_insert (char *str, StringList * list)
+{
+  StringList *new, *cur;
+
+  if ((new = (StringList *) malloc (sizeof (StringList))) == NULL)
+    {
+      fprintf (stderr, "malloc() failed in string_insert()\n");
+      exit (1);
+    }
+
+  new->next = NULL;
+  new->str = strdup (str);
+
+  if (list == NULL)
+    return (new);
+
+  cur = list;
+  while (cur->next != NULL)
+    cur = cur->next;
+
+  cur->next = new;
+
+  return (list);
+}
+
+static SpecctraList *
+specctra_insert (char *refdes, char *descr, char *value, SpecctraList * specctra)
+{
+  SpecctraList *new, *cur, *prev = NULL;
+
+  if (specctra == NULL)
+    {
+      /* this is the first element so automatically create an entry */
+      if ((new = (SpecctraList *) malloc (sizeof (SpecctraList))) == NULL)
+	{
+	  fprintf (stderr, "malloc() failed in specctra_insert()\n");
+	  exit (1);
+	}
+
+      new->next = NULL;
+      new->descr = strdup (descr);
+      new->value = strdup (value);
+      new->num = 1;
+      new->refdes = string_insert (refdes, NULL);
+      return (new);
+    }
+
+  /* search and see if we already have used one of these
+     components */
+  cur = specctra;
+  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 ((new = (SpecctraList *) malloc (sizeof (SpecctraList))) == NULL)
+	{
+	  fprintf (stderr, "malloc() failed in specctra_insert()\n");
+	  exit (1);
+	}
+
+      prev->next = new;
+
+      new->next = NULL;
+      new->descr = strdup (descr);
+      new->value = strdup (value);
+      new->num = 1;
+      new->refdes = string_insert (refdes, NULL);
+    }
+
+  return (specctra);
+
+}
+
+/* 
+ * If fp is not NULL then print out the bill of materials contained in
+ * specctra.  Either way, free all memory which has been allocated for specctra.
+ */
+static void
+print_and_free (FILE *fp, SpecctraList *specctra)
+{
+  SpecctraList *lastb;
+  StringList *lasts;
+  char *descr, *value;
+
+  while (specctra != NULL)
+    {
+      if (fp)
+	{
+	  descr = CleanSPECCTRAString (specctra->descr);
+	  value = CleanSPECCTRAString (specctra->value);
+	  fprintf (fp, "%d,\"%s\",\"%s\",", specctra->num, descr, value);
+	  free (descr);
+	  free (value);
+	}
+      
+      while (specctra->refdes != NULL)
+	{
+	  if (fp)
+	    {
+	      fprintf (fp, "%s ", specctra->refdes->str);
+	    }
+	  free (specctra->refdes->str);
+	  lasts = specctra->refdes;
+	  specctra->refdes = specctra->refdes->next;
+	  free (lasts);
+	}
+      if (fp)
+	{
+	  fprintf (fp, "\n");
+	}
+      lastb = specctra;
+      specctra = specctra->next;
+      free (lastb);
+    }
+}
+
+static void
+print_structure (FILE *fp)
+{
+  fprintf (fp, "  (structure\n");
+
+  /* define layers */
+  fprintf (fp, "    (layer Component\n");
+  fprintf (fp, "      (type signal)\n");
+  fprintf (fp, "      (property\n");
+  fprintf (fp, "        (index 0)\n      )\n    )\n");
+  fprintf (fp, "    (layer Copper\n");
+  fprintf (fp, "      (type signal)\n");
+  fprintf (fp, "      (property\n");
+  fprintf (fp, "        (index 1)\n      )\n    )\n");
+
+  /* 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_45_25_mil\")\n");
+
+  /* DRC rules */
+  fprintf (fp, "    (rule\n");
+  fprintf (fp, "      (width 8)\n");
+  fprintf (fp, "      (clear 10)\n");
+  fprintf (fp, "      (clear 10 (type wire_area))\n");
+  fprintf (fp, "      (clear 10 (type via_smd via_pin))\n");
+  fprintf (fp, "      (clear 10 (type smd_smd))\n");
+  fprintf (fp, "      (clear 10 (type default_smd))\n");
+  fprintf (fp, "    )\n  )\n");
+}
+
+static void
+print_placement (FILE *fp)
+/* gather all footprint names in a list
+   gather list of refdes for each footprint in list */
+{
+  int i;
+  GList *footprints; //contain unique footprint names
+  fprintf (fp, "  (placement\n");
+  ELEMENT_LOOP (PCB->Data);
+  {
+    gconstpointer descript = DESCRIPTION_NAME (element);
+    if( !g_list_find_custom( footprints, descript, strcmp ) ){
+      footprints = g_list_append( footprints, descript );
+    }
+  }
+  END_LOOP;
+  for(i=0; i < g_list_length( footprints ); i++){
+    int firstrot = -1; //change to the degree of the first element found
+    fprintf (fp, "    (component %s\n", g_list_nth_data( footprints, i ));
+    ELEMENT_LOOP (PCB->Data);
+    {
+      if(!strcmp(DESCRIPTION_NAME (element), g_list_nth_data( footprints, i ) )){
+        CentroidRotation crot = get_rotation_and_centroid(element);
+        if (firstrot == -1)
+        {
+          firstrot = crot.rot;
+        }
+        char* side = TEST_FLAG (ONSOLDERFLAG, element) ? "back" : "front";
+        fprintf (fp, "      (place %s %.2f %.2f %s %d (PN %s))\n", NAMEONPCB_NAME (element), crot.centx, crot.centy, side, firstrot-crot.rot, VALUE_NAME (element) );
+      }
+    }
+    END_LOOP;
+    fprintf (fp, "    )\n");
+  }
+  fprintf (fp, "  )\n");
+  g_list_free( footprints );
+}
+
+static void
+print_library (FILE *fp)
+/* gather all footprint names in a list
+   print info on each footprint */
+{
+  int i;
+  GList *footprints; //contain unique footprint names
+  GList *pads; //contain unique pad names
+  fprintf (fp, "  (library\n");
+  ELEMENT_LOOP (PCB->Data);
+  {
+    if( !g_list_find_custom( footprints, DESCRIPTION_NAME (element), strcmp ) ){
+      char *padstack;
+      int rotation;
+      int whichside = TEST_FLAG (ONSOLDERFLAG, element) ? -1 : 1;
+      CentroidRotation crot = get_rotation_and_centroid(element);
+      footprints = g_list_append( footprints, g_strdup( DESCRIPTION_NAME (element) ) );
+      fprintf (fp, "    (image %s\n", DESCRIPTION_NAME (element) );
+      /* loop thru pins and pads here */
+      PIN_LOOP (element);
+      {
+        int ty;
+        float pinthickness;
+        float lx, ly; //hold local pin coordinates
+        ty = PCB->MaxHeight - pin->Y;
+        pinthickness = pin->Thickness*0.01;
+        padstack = g_strdup_printf ("Th_round_%.0f_mil", pinthickness);
+        lx = (pin->X*0.01-crot.centx)*whichside;
+        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
+        {
+          fprintf (fp, "      (keepout \"\" (circle Component %.0f %.2f %.2f))\n", pinthickness, lx, ly);
+          fprintf (fp, "      (keepout \"\" (circle Copper %.0f %.2f %.2f))\n", 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 thickness and 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)*whichside;
+        ly = (crot.centy - yc*0.01)*(-1);
+        padstack = g_strdup_printf ("Smd_rect_%dx%d_mil", xlen, ylen);
+        if( !g_list_find_custom( pads, padstack, strcmp ) )
+        {
+          pads = g_list_append( pads, padstack );
+        }
+        if (!pad->Number) //if pad is null just make it a keepout
+        {
+          fprintf (fp, "      (keepout \"\" (rect %s %.2f %.2f %.2f %.2f))\n", (whichside == 1) ? "Component" : "Copper", 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);
+        }
+      }
+      END_LOOP;
+      fprintf (fp, "    )\n");
+    }
+  }
+  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 );
+    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
+    { 
+      fprintf (fp, "      (shape (rect Component %.1f %.1f %.1f %.1f))\n", dim1/(-2.0), dim2/(-2.0), dim1/2.0, dim2/2.0);
+    }
+    else ///then pad is th
+    {
+      retargs = sscanf (padstring, "Th_round_%d_mil", &dim1);
+      fprintf (fp, "      (shape (circle Component %d))\n", dim1);
+      fprintf (fp, "      (shape (circle Copper %d))\n", dim1);
+    }
+    fprintf (fp, "      (attach off)\n");
+    fprintf (fp, "    )\n");
+  }
+  /* add padstack for via */
+  fprintf (fp, "    (padstack \"via_45_25_mil\"\n      (shape (circle Component 45))\n      (shape (circle Copper 45))\n      (attach off)\n    )\n");
+  fprintf (fp, "  )\n");
+  g_list_foreach( footprints, (GFunc)g_free, NULL );
+  g_list_free( footprints );
+  g_list_foreach( pads, (GFunc)g_free, NULL );
+  g_list_free( pads );
+}
+
+static void
+print_network (FILE *fp)
+{
+  GList *netlistnames;  //contain unique strings of netlist names
+  int i, firstcon;
+  NetListListType Nets;
+  Nets = CollectSubnets (False);
+  fprintf (fp, "  (network\n");
+  NETLIST_LOOP (&Nets);
+  {
+    firstcon = 1; //clear flag after net name is found
+    NET_LOOP (netlist);
+    {
+      CONNECTION_LOOP (net);
+      {
+        int ni, nei;
+	      char *ename;
+	      char *pname;
+	      char *n;
+        char *netname;
+        /* looking for pins and pads */
+        if (connection->type == PIN_TYPE || connection->type == PAD_TYPE)
+        {
+          PinTypePtr thispin;
+          PadTypePtr thispad;
+          ElementTypePtr thiselem;
+          if (connection->type == PIN_TYPE)
+          {
+            thispin = connection->ptr2;
+            thiselem = thispin->Element;
+            pname = thispin->Number;
+          }
+          else
+          {
+            thispad = connection->ptr2;
+            thiselem = thispad->Element;
+            pname = thispad->Number;
+          }
+          ename = NAMEONPCB_NAME(thiselem);
+          n = g_strconcat (ename, "-", pname, NULL);
+	        for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop thru all nets
+		      for (nei = 0; nei < PCB->NetlistLib.Menu[ni].EntryN; nei++) //loop thru all entries in all nets
+		      {
+		        if (strcmp (PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry, n) == 0) //find the entry that matches this pin or pad
+		        {
+              netname = g_strdup (PCB->NetlistLib.Menu[ni].Name + 2); //find the net name of this entry
+              //if( !g_list_find_custom( netlistnames, netname, strcmp ) ) //see if netlist was written down already
+              if(firstcon == 1)
+              {
+                firstcon = 0;
+                netlistnames = g_list_append( netlistnames, netname );
+                fprintf (fp, "    (net %s\n      (pins", netname);
+              }
+            }
+          }
+          fprintf (fp, " %s", n);
+          g_free(n);
+        }
+      }
+      END_LOOP;
+    }
+    END_LOOP;
+    fprintf (fp, ")\n    )\n");
+  }
+  END_LOOP;
+  fprintf (fp, "    (class geda_default");
+  for(i=0; i < g_list_length( netlistnames ); i++)
+  {
+    fprintf (fp, " %s", g_list_nth_data( netlistnames, i ) );
+  }
+  fprintf (fp, "\n      (circuit\n        (use_via via_45_25_mil)\n      )\n");
+  fprintf (fp, "      (rule (width 8))\n    )\n  )\n");
+  fprintf (fp, "  (wiring\n  )\n)\n");
+  
+  g_list_foreach( netlistnames, (GFunc)g_free, NULL );
+  g_list_free( netlistnames );
+}
+
+static int
+PrintSPECCTRA (void)
+{
+  char utcTime[64];
+  double x, y, theta = 0.0, user_x, user_y;
+  double sumx, sumy;
+  double pin1x = 0.0, pin1y = 0.0, pin1angle = 0.0;
+  double pin2x = 0.0, pin2y = 0.0, pin2angle;
+  int found_pin1;
+  int found_pin2;
+  int pin_cnt;
+  time_t currenttime;
+  FILE *fp;
+  SpecctraList *specctra = NULL;
+  char *name, *descr, *value;
+
+  /* Print out the specctra .dsn file. */
+
+  fp = fopen (specctra_filename, "w");
+  if (!fp)
+    {
+      gui->log ("Cannot open file %s for writing\n", specctra_filename);
+      print_and_free (NULL, specctra);
+      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] */
+  
+  /* color descriptor [optional] */
+  
+  print_and_free (fp, specctra);
+
+  fclose (fp);
+
+  return (0);
+}
+
+static void
+specctra_do_export (HID_Attr_Val * options)
+{
+  int i;
+
+  if (!options)
+    {
+      specctra_get_export_options (0);
+      for (i = 0; i < NUM_OPTIONS; i++)
+	specctra_values[i] = specctra_options[i].default_val;
+      options = specctra_values;
+    }
+
+  specctra_filename = options[HA_specctrafile].str_value;
+  if (!specctra_filename)
+    specctra_filename = "pcb-out.dsn";
+
+  PrintSPECCTRA ();
+}
+
+static void
+specctra_parse_arguments (int *argc, char ***argv)
+{
+  hid_register_attributes (specctra_options,
+			   sizeof (specctra_options) / sizeof (specctra_options[0]));
+  hid_parse_command_line (argc, argv);
+}
+
+HID specctra_hid = {
+  sizeof (HID),
+  "specctra",
+  "Exports a SPECCTRA .dsn file",
+  0, 0, 1, 0, 0, 0,
+  specctra_get_export_options,
+  specctra_do_export,
+  specctra_parse_arguments,
+  0,				/* specctra_invalidate_wh */
+  0,				/* specctra_invalidate_lr */
+  0,				/* specctra_invalidate_all */
+  0,				/* specctra_set_layer */
+  0,				/* specctra_make_gc */
+  0,				/* specctra_destroy_gc */
+  0,				/* specctra_use_mask */
+  0,				/* specctra_set_color */
+  0,				/* specctra_set_line_cap */
+  0,				/* specctra_set_line_width */
+  0,				/* specctra_set_draw_xor */
+  0,				/* specctra_set_draw_faded */
+  0,				/* specctra_set_line_cap_angle */
+  0,				/* specctra_draw_line */
+  0,				/* specctra_draw_arc */
+  0,				/* specctra_draw_rect */
+  0,				/* specctra_fill_circle */
+  0,				/* specctra_fill_polygon */
+  0,				/* specctra_fill_rect */
+  0,				/* specctra_calibrate */
+  0,				/* specctra_shift_is_pressed */
+  0,				/* specctra_control_is_pressed */
+  0,				/* specctra_get_coords */
+  0,				/* specctra_set_crosshair */
+  0,				/* specctra_add_timer */
+  0,				/* specctra_stop_timer */
+  0,				/* specctra_log */
+  0,				/* specctra_logv */
+  0,				/* specctra_confirm_dialog */
+  0,				/* specctra_close_confirm_dialog */
+  0,				/* specctra_report_dialog */
+  0,				/* specctra_prompt_for */
+  0,				/* specctra_fileselect */
+  0,				/* specctra_attribute_dialog */
+  0,				/* specctra_show_item */
+  0,				/* specctra_beep */
+  0,				/* specctra_progress */
+};
+
+void
+hid_specctra_init ()
+{
+  apply_default_hid (&specctra_hid, 0);
+  hid_register_hid (&specctra_hid);
+}
+
+
+_______________________________________________
+geda-user mailing list
+geda-user@xxxxxxxxxxxxxx
+http://www.seul.org/cgi-bin/mailman/listinfo/geda-user
+
+ + + +
+ + + + + + + + + + + + \ No newline at end of file Index: pcb-exporters/dsn/ml/gEDA-user: freerouting export_3.html =================================================================== --- pcb-exporters/dsn/ml/gEDA-user: freerouting export_3.html (nonexistent) +++ pcb-exporters/dsn/ml/gEDA-user: freerouting export_3.html (revision 4085) @@ -0,0 +1,885 @@ + + + + + + + + + + +gEDA-user: freerouting export + + + + + + +
+[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index] + + + +

gEDA-user: freerouting export

+
+ + + + + +
+ + +
   dsn exporter supports multilayer boards and no longer crashes from
+   null element names or refdes.
+   An unrelated but essential change is to stop the library window from
+   opening every time pcb opens in gtk.
+   There is no freerouting import yet but you can route boards and save
+   the .ses file for future importing.  I ran it on dj's furnace board
+   and it reduced vias from 235 to 145 taking 12 hours.
+   -Josh
+
diff --git a/src/Makefile.am b/src/Makefile.am
+index 1c97b60..0572e01 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -12,7 +12,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 libgts.a
++	liblpr.a libgerber.a libbom.a libspecctra.a libpng.a libps.a libnelma.a libgts.a
+ 
+ pcblib_DATA=	\
+ 	default_font \
+@@ -198,6 +198,7 @@ EXTRA_DIST= \
+ 	default_font \
+ 	$(srcdir)/hid/batch/hid.conf \
+ 	$(srcdir)/hid/bom/hid.conf \
++  $(srcdir)/hid/specctra/hid.conf \
+ 	$(srcdir)/hid/gerber/hid.conf \
+ 	$(srcdir)/hid/gtk/gui-icons-misc.data \
+ 	$(srcdir)/hid/gtk/gui-icons-mode-buttons.data \
+@@ -385,6 +386,10 @@ libbom_a_SOURCES = \
+ 	hid/hidint.h \
+ 	hid/bom/bom.c
+ 
++libspecctra_a_SOURCES = \
++  hid/hidint.h \
++  hid/specctra/specctra.c
++
+ libps_a_CPPFLAGS = -I./hid/ps
+ LIBPS_SRCS = \
+ 	dolists.h \
+diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c
+index cbdd104..f3086ca 100644
+--- a/src/hid/gtk/gtkhid-main.c
++++ b/src/hid/gtk/gtkhid-main.c
+@@ -1741,11 +1741,15 @@ LayerGroupsChanged (int argc, char **argv, int x, int y)
+ }
+ 
+ /* ---------------------------------------------------------------------- */
++int stop_annoying_library = 1;
+ 
+ static int
+ LibraryChanged (int argc, char **argv, int x, int y)
+ {
+-  ghid_library_window_show (&ghid_port, FALSE);
++  if(stop_annoying_library)
++    stop_annoying_library = 0;
++  else
++    ghid_library_window_show (&ghid_port, FALSE);
+   return 0;
+ }
+ 
+@@ -2413,6 +2417,7 @@ Open the DRC violations window.
+ 
+ %end-doc */
+ 
++
+ static int
+ DoWindows (int argc, char **argv, int x, int y)
+ {
+diff --git a/src/hid/specctra/specctra.c b/src/hid/specctra/specctra.c
+index 1dab7b5..d4cb39f 100644
+--- a/src/hid/specctra/specctra.c
++++ b/src/hid/specctra/specctra.c
+@@ -1,6 +1,7 @@
+ /*
+ This program exports specctra .dsn files from geda .pcb files.
+-By Josh Jordan
++By Josh Jordan and Dan McMahill, modified from bom.c
++
+ */
+ 
+ #ifdef HAVE_CONFIG_H
+@@ -24,40 +25,33 @@ By Josh Jordan
+ 
+ #include "hid.h"
+ #include "../hidint.h"
++#include "specctra.h"
+ 
+ #ifdef HAVE_LIBDMALLOC
+ #include <dmalloc.h>
+ #endif
+ 
++int trackwidth = 8; //user options defined in export dialog
++int clearance = 8;
++
+ static HID_Attribute specctra_options[] = {
+   {"specctrafile", "SPECCTRA output file",
+    HID_String, 0, 0, {0, 0, 0}, 0, 0},
+ #define HA_specctrafile 0
+   {"trackwidth", "default track width in mils",
+-   HID_Integer, 0, 0, {0, 0, 0}, 0, 0},
++   HID_Integer, 1, 100, {8, 0, 0}, 0, 0},
+ #define HA_trackwidth 1
++  {"clearance", "default clearance in mils",
++   HID_Integer, 1, 100, {8, 0, 0}, 0, 0},
++#define HA_clearance 2
+ };
+ 
+ #define NUM_OPTIONS (sizeof(specctra_options)/sizeof(specctra_options[0]))
+-
+-static HID_Attr_Val specctra_values[NUM_OPTIONS];
++REGISTER_ATTRIBUTES (specctra_options)
++  static HID_Attr_Val specctra_values[NUM_OPTIONS];
+ 
+ static char *specctra_filename;
+ 
+-typedef struct _StringList
+-{
+-  char *str;
+-  struct _StringList *next;
+-} StringList;
+-
+-typedef struct _SpecctraList
+-{
+-  char *descr;
+-  char *value;
+-  int num;
+-  StringList *refdes;
+-  struct _SpecctraList *next;
+-} SpecctraList;
+ 
+ static HID_Attribute *
+ specctra_get_export_options (int *n)
+@@ -66,45 +60,12 @@ specctra_get_export_options (int *n)
+   if (PCB) {
+ 	derive_default_filename(PCB->Filename, &specctra_options[HA_specctrafile], ".dsn", &last_specctra_filename);
+   }
+-
+   if (n)
+     *n = NUM_OPTIONS;
+   return specctra_options;
+ }
+ 
+ 
+-static char *
+-CleanSPECCTRAString (char *in)
+-{
+-  char *out;
+-  int i;
+-
+-  if ((out = malloc ((strlen (in) + 1) * sizeof (char))) == NULL)
+-    {
+-      fprintf (stderr, "Error:  CleanSPECCTRAString() malloc() failed\n");
+-      exit (1);
+-    }
+-
+-  /* 
+-   * copy over in to out with some character conversions.
+-   * Go all the way to then end to get the terminating \0
+-   */
+-  for (i = 0; i <= strlen (in); i++)
+-    {
+-      switch (in[i])
+-	{
+-	case '"':
+-	  out[i] = '\'';
+-	  break;
+-	default:
+-	  out[i] = in[i];
+-	}
+-    }
+-
+-  return out;
+-}
+-
+-
+ static double
+ xyToAngle (double x, double y)
+ {
+@@ -276,149 +237,52 @@ get_rotation_and_centroid (ElementType *element){
+   }
+ }
+ 
++Boolean is_layer_group_active[MAX_LAYER];
++GList *layerlist = NULL; //contain unique layer names- (PCB copper layers, aka geda pcb layergroups, not geda pcb layers)
++int layersN; //global var holding how many layers are found
+ 
+-static StringList *
+-string_insert (char *str, StringList * list)
+-{
+-  StringList *new, *cur;
+-
+-  if ((new = (StringList *) malloc (sizeof (StringList))) == NULL)
+-    {
+-      fprintf (stderr, "malloc() failed in string_insert()\n");
+-      exit (1);
+-    }
+-
+-  new->next = NULL;
+-  new->str = strdup (str);
+-
+-  if (list == NULL)
+-    return (new);
+-
+-  cur = list;
+-  while (cur->next != NULL)
+-    cur = cur->next;
+-
+-  cur->next = new;
+-
+-  return (list);
+-}
+-
+-static SpecctraList *
+-specctra_insert (char *refdes, char *descr, char *value, SpecctraList * specctra)
++static void
++print_structure (FILE *fp)
+ {
+-  SpecctraList *new, *cur, *prev = NULL;
+-
+-  if (specctra == NULL)
+-    {
+-      /* this is the first element so automatically create an entry */
+-      if ((new = (SpecctraList *) malloc (sizeof (SpecctraList))) == NULL)
+-	{
+-	  fprintf (stderr, "malloc() failed in specctra_insert()\n");
+-	  exit (1);
+-	}
+-
+-      new->next = NULL;
+-      new->descr = strdup (descr);
+-      new->value = strdup (value);
+-      new->num = 1;
+-      new->refdes = string_insert (refdes, NULL);
+-      return (new);
+-    }
+-
+-  /* search and see if we already have used one of these
+-     components */
+-  cur = specctra;
+-  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)
++  /* check which layers are active first */
++  int i;
++  int group;
++  fprintf (fp, "  (structure\n");
++  layersN = 0;
++//#if 0  //this is to find layergroup names. hardcoded for now
++  for (group = 0; group < max_layer; group++)
++  {
++    for (i = 0; i < PCB->LayerGroups.Number[group]; i++)
++    /* layer must be 1) not silk (ie, < max_layer) and 2) on */
++    if ((PCB->LayerGroups.Entries[group][i] < max_layer) && PCB->Data->Layer[PCB->LayerGroups.Entries[group][i]].On)
+     {
+-      if ((new = (SpecctraList *) malloc (sizeof (SpecctraList))) == NULL)
+-	{
+-	  fprintf (stderr, "malloc() failed in specctra_insert()\n");
+-	  exit (1);
+-	}
+-
+-      prev->next = new;
+-
+-      new->next = NULL;
+-      new->descr = strdup (descr);
+-      new->value = strdup (value);
+-      new->num = 1;
+-      new->refdes = string_insert (refdes, NULL);
++      char * lname;
++      layersN++;
++      is_layer_group_active[group] = True;
++      GROUP_LOOP(PCB->Data, group);
++      {
++        lname = strdup(layer->Name);
++        layerlist = g_list_insert( layerlist, lname, group );
++        printf("adding %s to list in position %d\n", lname, group);
++        break;
++      }
++      END_LOOP;
++      break;
+     }
+-
+-  return (specctra);
+-
+-}
+-
+-/* 
+- * If fp is not NULL then print out the bill of materials contained in
+- * specctra.  Either way, free all memory which has been allocated for specctra.
+- */
+-static void
+-print_and_free (FILE *fp, SpecctraList *specctra)
+-{
+-  SpecctraList *lastb;
+-  StringList *lasts;
+-  char *descr, *value;
+-
+-  while (specctra != NULL)
++	  else
++	    is_layer_group_active[group] = False;
++  }
++  //layerlist = g_list_reverse( layerlist ); //this is because layer order is reversed for .dsn files
++  printf("found %d layergroups\n", layersN);
++  for(i = 0; i < max_layer; i++)
++  {
++    if(is_layer_group_active[i])
+     {
+-      if (fp)
+-	{
+-	  descr = CleanSPECCTRAString (specctra->descr);
+-	  value = CleanSPECCTRAString (specctra->value);
+-	  fprintf (fp, "%d,\"%s\",\"%s\",", specctra->num, descr, value);
+-	  free (descr);
+-	  free (value);
+-	}
+-      
+-      while (specctra->refdes != NULL)
+-	{
+-	  if (fp)
+-	    {
+-	      fprintf (fp, "%s ", specctra->refdes->str);
+-	    }
+-	  free (specctra->refdes->str);
+-	  lasts = specctra->refdes;
+-	  specctra->refdes = specctra->refdes->next;
+-	  free (lasts);
+-	}
+-      if (fp)
+-	{
+-	  fprintf (fp, "\n");
+-	}
+-      lastb = specctra;
+-      specctra = specctra->next;
+-      free (lastb);
++      printf("layergroup %d (%s)\n", i, g_list_nth_data( layerlist, i ));
++      fprintf( fp, "    (layer %s\n      (type signal)\n      (property\n        (index %d)\n      )\n    )\n",
++              g_list_nth_data( layerlist, i ), i);
+     }
+-}
+-
+-static void
+-print_structure (FILE *fp)
+-{
+-  fprintf (fp, "  (structure\n");
+-
+-  /* define layers */
+-  fprintf (fp, "    (layer Component\n");
+-  fprintf (fp, "      (type signal)\n");
+-  fprintf (fp, "      (property\n");
+-  fprintf (fp, "        (index 0)\n      )\n    )\n");
+-  fprintf (fp, "    (layer Copper\n");
+-  fprintf (fp, "      (type signal)\n");
+-  fprintf (fp, "      (property\n");
+-  fprintf (fp, "        (index 1)\n      )\n    )\n");
++  }
+ 
+   /* PCB outline */
+   fprintf (fp, "    (boundary\n");
+@@ -429,138 +293,122 @@ print_structure (FILE *fp)
+ 
+   /* DRC rules */
+   fprintf (fp, "    (rule\n");
+-  fprintf (fp, "      (width 8)\n");
+-  fprintf (fp, "      (clear 10)\n");
+-  fprintf (fp, "      (clear 10 (type wire_area))\n");
+-  fprintf (fp, "      (clear 10 (type via_smd via_pin))\n");
+-  fprintf (fp, "      (clear 10 (type smd_smd))\n");
+-  fprintf (fp, "      (clear 10 (type default_smd))\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)
+-/* gather all footprint names in a list
+-   gather list of refdes for each footprint in list */
+ {
+-  int i;
+-  GList *footprints; //contain unique footprint names
+   fprintf (fp, "  (placement\n");
++  printf("status: placement section\n");
++  /* pcb doesnt remember footprint library- place all elements as their own library image */
+   ELEMENT_LOOP (PCB->Data);
+   {
+-    gconstpointer descript = DESCRIPTION_NAME (element);
+-    if( !g_list_find_custom( footprints, descript, strcmp ) ){
+-      footprints = g_list_append( footprints, descript );
+-    }
+-  }
+-  END_LOOP;
+-  for(i=0; i < g_list_length( footprints ); i++){
+-    int firstrot = -1; //change to the degree of the first element found
+-    fprintf (fp, "    (component %s\n", g_list_nth_data( footprints, i ));
+-    ELEMENT_LOOP (PCB->Data);
+-    {
+-      if(!strcmp(DESCRIPTION_NAME (element), g_list_nth_data( footprints, i ) )){
+-        CentroidRotation crot = get_rotation_and_centroid(element);
+-        if (firstrot == -1)
+-        {
+-          firstrot = crot.rot;
+-        }
+-        char* side = TEST_FLAG (ONSOLDERFLAG, element) ? "back" : "front";
+-        fprintf (fp, "      (place %s %.2f %.2f %s %d (PN %s))\n", NAMEONPCB_NAME (element), crot.centx, crot.centy, side, firstrot-crot.rot, VALUE_NAME (element) );
+-      }
+-    }
+-    END_LOOP;
++    char * ename;
++    CentroidRotation ecenter = get_rotation_and_centroid(element); //only need centroid
++    char* side = TEST_FLAG (ONSOLDERFLAG, element) ? "back" : "front";
++    //ename = (strncmp(NAMEONPCB_NAME(element), "(null)", 6) ? NAMEONPCB_NAME(element) : "null");
++    ename = 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");
+   }
++  END_LOOP;
++  printf("status: placement finished\n");
+   fprintf (fp, "  )\n");
+-  g_list_free( footprints );
+ }
+ 
+ static void
+ print_library (FILE *fp)
+-/* gather all footprint names in a list
+-   print info on each footprint */
+ {
+   int i;
+-  GList *footprints; //contain unique footprint names
+-  GList *pads; //contain unique pad names
++  GList *pads = NULL; //contain unique pad names
+   fprintf (fp, "  (library\n");
++  printf ("status: library section\n");
+   ELEMENT_LOOP (PCB->Data);
+   {
+-    if( !g_list_find_custom( footprints, DESCRIPTION_NAME (element), strcmp ) ){
+-      char *padstack;
+-      int rotation;
+-      int whichside = TEST_FLAG (ONSOLDERFLAG, element) ? -1 : 1;
+-      CentroidRotation crot = get_rotation_and_centroid(element);
+-      footprints = g_list_append( footprints, g_strdup( DESCRIPTION_NAME (element) ) );
+-      fprintf (fp, "    (image %s\n", DESCRIPTION_NAME (element) );
+-      /* loop thru pins and pads here */
+-      PIN_LOOP (element);
++    char *padstack;
++    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;
++      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
+       {
+-        int ty;
+-        float pinthickness;
+-        float lx, ly; //hold local pin coordinates
+-        ty = PCB->MaxHeight - pin->Y;
+-        pinthickness = pin->Thickness*0.01;
+-        padstack = g_strdup_printf ("Th_round_%.0f_mil", pinthickness);
+-        lx = (pin->X*0.01-crot.centx)*whichside;
+-        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
+-        {
+-          fprintf (fp, "      (keepout \"\" (circle Component %.0f %.2f %.2f))\n", pinthickness, lx, ly);
+-          fprintf (fp, "      (keepout \"\" (circle Copper %.0f %.2f %.2f))\n", pinthickness, lx, ly);
+-        }
+-        else
++        for(int i = 0; i < layersN; i++)
+         {
+-          fprintf (fp, "      (pin %s %s %.2f %.2f)\n", padstack, pin->Number, lx, ly);
++          fprintf (fp, "      (keepout \"\" (circle %s %.0f %.2f %.2f))\n", g_list_nth_data( layerlist, i ), pinthickness, lx, ly);
+         }
+       }
+-      END_LOOP;
+-      PAD_LOOP (element);
++      else
+       {
+-        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 thickness and 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)*whichside;
+-        ly = (crot.centy - yc*0.01)*(-1);
+-        padstack = g_strdup_printf ("Smd_rect_%dx%d_mil", xlen, ylen);
+-        if( !g_list_find_custom( pads, padstack, strcmp ) )
+-        {
+-          pads = g_list_append( pads, padstack );
+-        }
+-        if (!pad->Number) //if pad is null just make it a keepout
+-        {
+-          fprintf (fp, "      (keepout \"\" (rect %s %.2f %.2f %.2f %.2f))\n", (whichside == 1) ? "Component" : "Copper", 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);
+-        }
++        fprintf (fp, "      (pin %s %s %.2f %.2f)\n", padstack, pin->Number, lx, ly);
+       }
+-      END_LOOP;
+-      fprintf (fp, "    )\n");
+     }
++    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( !g_list_find_custom( pads, padstack, strcmp ) )
++        pads = g_list_append( pads, padstack );
++   
++      if (!pad->Number) //if pad is null just make it a keepout
++      {
++        fprintf (fp, "      (keepout \"\" (rect %s %.2f %.2f %.2f %.2f))\n", g_list_nth_data( layerlist, partside ), 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);
++      }
++    }
++    END_LOOP;
++    fprintf (fp, "    )\n");
+   }
+   END_LOOP;
++  printf("status: padstacks\n");
+   /* loop thru padstacks and define them all */
+   for(i=0; i < g_list_length( pads ); i++)
+   {
+@@ -571,22 +419,27 @@ print_library (FILE *fp)
+     retargs = sscanf (padstring, "Smd_rect_%dx%d_mil", &dim1, &dim2);
+     if (retargs == 2) //then pad is smd
+     { 
+-      fprintf (fp, "      (shape (rect Component %.1f %.1f %.1f %.1f))\n", dim1/(-2.0), dim2/(-2.0), dim1/2.0, dim2/2.0);
++      fprintf (fp, "      (shape (rect %s %.1f %.1f %.1f %.1f))\n", g_list_nth_data( layerlist, 0 ), dim1/(-2.0), dim2/(-2.0), dim1/2.0, dim2/2.0);
+     }
+     else ///then pad is th
+     {
+       retargs = sscanf (padstring, "Th_round_%d_mil", &dim1);
+-      fprintf (fp, "      (shape (circle Component %d))\n", dim1);
+-      fprintf (fp, "      (shape (circle Copper %d))\n", dim1);
++      for(int ii = 0; ii < layersN; ii++)
++      {
++        fprintf (fp, "      (shape (circle %s %d))\n", g_list_nth_data( layerlist, ii ), dim1);
++      }
+     }
+     fprintf (fp, "      (attach off)\n");
+     fprintf (fp, "    )\n");
+   }
+   /* add padstack for via */
+-  fprintf (fp, "    (padstack \"via_45_25_mil\"\n      (shape (circle Component 45))\n      (shape (circle Copper 45))\n      (attach off)\n    )\n");
++  fprintf (fp, "    (padstack \"via_45_25_mil\"\n");
++  for(i = 0; i < layersN; i++)
++  {
++    fprintf (fp, "      (shape (circle %s 45))\n", g_list_nth_data( layerlist, i ) );
++  }
++  fprintf (fp, "      (attach off)\n    )\n");
+   fprintf (fp, "  )\n");
+-  g_list_foreach( footprints, (GFunc)g_free, NULL );
+-  g_list_free( footprints );
+   g_list_foreach( pads, (GFunc)g_free, NULL );
+   g_list_free( pads );
+ }
+@@ -594,104 +447,43 @@ print_library (FILE *fp)
+ static void
+ print_network (FILE *fp)
+ {
+-  GList *netlistnames;  //contain unique strings of netlist names
+-  int i, firstcon;
+   NetListListType Nets;
+   Nets = CollectSubnets (False);
+   fprintf (fp, "  (network\n");
+-  NETLIST_LOOP (&Nets);
++  printf("status: network section\n");
++
++  int ni, nei;
++  for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop thru all nets
+   {
+-    firstcon = 1; //clear flag after net name is found
+-    NET_LOOP (netlist);
++    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
+     {
+-      CONNECTION_LOOP (net);
+-      {
+-        int ni, nei;
+-	      char *ename;
+-	      char *pname;
+-	      char *n;
+-        char *netname;
+-        /* looking for pins and pads */
+-        if (connection->type == PIN_TYPE || connection->type == PAD_TYPE)
+-        {
+-          PinTypePtr thispin;
+-          PadTypePtr thispad;
+-          ElementTypePtr thiselem;
+-          if (connection->type == PIN_TYPE)
+-          {
+-            thispin = connection->ptr2;
+-            thiselem = thispin->Element;
+-            pname = thispin->Number;
+-          }
+-          else
+-          {
+-            thispad = connection->ptr2;
+-            thiselem = thispad->Element;
+-            pname = thispad->Number;
+-          }
+-          ename = NAMEONPCB_NAME(thiselem);
+-          n = g_strconcat (ename, "-", pname, NULL);
+-	        for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop thru all nets
+-		      for (nei = 0; nei < PCB->NetlistLib.Menu[ni].EntryN; nei++) //loop thru all entries in all nets
+-		      {
+-		        if (strcmp (PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry, n) == 0) //find the entry that matches this pin or pad
+-		        {
+-              netname = g_strdup (PCB->NetlistLib.Menu[ni].Name + 2); //find the net name of this entry
+-              //if( !g_list_find_custom( netlistnames, netname, strcmp ) ) //see if netlist was written down already
+-              if(firstcon == 1)
+-              {
+-                firstcon = 0;
+-                netlistnames = g_list_append( netlistnames, netname );
+-                fprintf (fp, "    (net %s\n      (pins", netname);
+-              }
+-            }
+-          }
+-          fprintf (fp, " %s", n);
+-          g_free(n);
+-        }
+-      }
+-      END_LOOP;
++      char *netentry;
++      netentry = PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry;
++      fprintf (fp, " %s", netentry);
+     }
+-    END_LOOP;
+     fprintf (fp, ")\n    )\n");
+   }
+-  END_LOOP;
++
+   fprintf (fp, "    (class geda_default");
+-  for(i=0; i < g_list_length( netlistnames ); i++)
++  for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) //loop thru all nets
+   {
+-    fprintf (fp, " %s", g_list_nth_data( netlistnames, i ) );
++    fprintf (fp, " %s", PCB->NetlistLib.Menu[ni].Name + 2);
+   }
+   fprintf (fp, "\n      (circuit\n        (use_via via_45_25_mil)\n      )\n");
+-  fprintf (fp, "      (rule (width 8))\n    )\n  )\n");
++  fprintf (fp, "      (rule (width %d))\n    )\n  )\n", trackwidth);
+   fprintf (fp, "  (wiring\n  )\n)\n");
+-  
+-  g_list_foreach( netlistnames, (GFunc)g_free, NULL );
+-  g_list_free( netlistnames );
+ }
+ 
+ static int
+ PrintSPECCTRA (void)
+ {
+-  char utcTime[64];
+-  double x, y, theta = 0.0, user_x, user_y;
+-  double sumx, sumy;
+-  double pin1x = 0.0, pin1y = 0.0, pin1angle = 0.0;
+-  double pin2x = 0.0, pin2y = 0.0, pin2angle;
+-  int found_pin1;
+-  int found_pin2;
+-  int pin_cnt;
+-  time_t currenttime;
+   FILE *fp;
+-  SpecctraList *specctra = NULL;
+-  char *name, *descr, *value;
+-
+   /* Print out the specctra .dsn file. */
+-
+   fp = fopen (specctra_filename, "w");
+   if (!fp)
+     {
+       gui->log ("Cannot open file %s for writing\n", specctra_filename);
+-      print_and_free (NULL, specctra);
+       return 1;
+     }
+ 
+@@ -745,31 +537,34 @@ PrintSPECCTRA (void)
+   /* wiring descriptor [optional] */
+   
+   /* color descriptor [optional] */
+-  
+-  print_and_free (fp, specctra);
++  printf("status: almost done\n");
+ 
+   fclose (fp);
+ 
+   return (0);
+ }
+ 
++
+ static void
+ specctra_do_export (HID_Attr_Val * options)
+ {
+   int i;
+-
++  int trackwidth, clearance;
+   if (!options)
+-    {
+-      specctra_get_export_options (0);
+-      for (i = 0; i < NUM_OPTIONS; i++)
+-	specctra_values[i] = specctra_options[i].default_val;
+-      options = specctra_values;
+-    }
+-
++  {
++    specctra_get_export_options (0);
++    for (i = 0; i < NUM_OPTIONS; i++)
++      specctra_values[i] = specctra_options[i].default_val;
++    options = specctra_values;
++  }
+   specctra_filename = options[HA_specctrafile].str_value;
+   if (!specctra_filename)
+     specctra_filename = "pcb-out.dsn";
+ 
++  trackwidth = options[HA_trackwidth].int_value;
++  clearance = options[HA_clearance].int_value;
++  printf("tracks %d/%d\n", trackwidth, clearance);
++
+   PrintSPECCTRA ();
+ }
+ 
+
+_______________________________________________
+geda-user mailing list
+geda-user@xxxxxxxxxxxxxx
+http://www.seul.org/cgi-bin/mailman/listinfo/geda-user
+
+ + + +
+ + + + + + + + + + + + + \ No newline at end of file