X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f X-Recipient: geda-user AT delorie DOT com X-Envelope-From: paubert AT iram DOT es Date: Thu, 5 Jul 2012 12:16:14 +0200 From: Gabriel Paubert To: geda-user AT delorie DOT com Subject: Re: [RFC, v2] [geda-user] [PATCH] Allow to create metric Gerber and drill files. Message-ID: <20120705101614.GA19974@visitor2.iram.es> References: <20120703140236 DOT GA12646 AT visitor2 DOT iram DOT es> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.5.20 (2009-06-14) X-SPF-Received: 2 X-Spamina-Bogosity: Unsure X-Spam-Score: -4.4 (----) X-Spam-Report: Content analysis details: (-4.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -1.8 ALL_TRUSTED Passed through trusted hosts only via SMTP -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% [score: 0.0000] Reply-To: geda-user AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: geda-user AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk On Wed, Jul 04, 2012 at 07:38:58AM +1000, Stephen Ecob wrote: > Thanks Gabriel, > > I've also noticed that problem when I was working on a board with > 0.4mm vias with 0.2mm holes so it will be nice to be able to generate > metric Gerbers in future :) > I hope one of the devs will find time to check the patch and include > it in head - it is a very worthwhile improvement. Thanks for the kind words. Did you try the patch on your board(s) and did it improve the results? I have appended a second version of the patch; the only difference with the first one is that now the line in the header that starts with "G04 PCB-dimensions" now specifies the dimensions either in metric or in imperial dimensions depending on the metric option. I was expecting that the developers with git write access would be a bit more reactive and tell me whether something looked wrong with the patch. I must admit I'm not completely satisfied with the names of some functions/variables, but I'm not too worried since they are local to the gerber.c file. For global names, I'm much fussier. From my limited tests, the patch does not affect the Gerber code in imperial mode (diff output only lists the obvious: timestamp in the header, and the board dimensions in the second version of the patch, in any case only the comments are affected). Now there is still one thing I question: it is the logic that generates the aperture code. A long time ago, pcb reused aperture codes between layers. Now it uses a separate aperture space for every layer, which does not make much sense to me. Especially troublesome is the fact that the drill size numbers are extracted from the same space as the aperture numbers, which leads to unnnecessarily large numbers: in my last board I have drill numbers 100, 101, and 102. However, the description of tool selection from http://www.excellon.com/manuals/program.htm indicates that you should not have more than 2 digits, since when there are more than 2, the last two are interpreted as a "compensation index", whatever that means (it's not my domain). Gerbv interprets the tool definitions as I want, but it might be a bug which results in a DWIM behaviour. My conclusion is that at least the drill bits should be defined starting from one. For the photoplotter layer, I'm still unconvinced about the convenience of the current behaviour. Of course, this is open source, so why not make it configurable? The three options would be: 1) start from D11 for each layer (overlapping spaces), 2) use a single global aperture space (reusing the same apertures codes on different layers) 3) use non overlapping aperture spaces (current behaviour) Question to developers: would a patch that fixes the drill bit numbering problem described above be considered for inclusion? Gabriel diff --git a/src/hid/gerber/gerber.c b/src/hid/gerber/gerber.c index 2181718..8ac9464 100644 --- a/src/hid/gerber/gerber.c +++ b/src/hid/gerber/gerber.c @@ -82,6 +82,8 @@ static void gerber_fill_polygon (hidGC gc, int n_coords, Coord *x, Coord *y); static int verbose; static int all_layers; +static int metric; +static char *x_convspec, *y_convspec; static int is_mask, was_drill; static int is_drill; static int current_mask; @@ -90,6 +92,12 @@ static int copy_outline_mode; static int name_style; static LayerType *outline_layer; +#define print_xcoord(file, pcb, val)\ + pcb_fprintf(file, x_convspec, gerberX(pcb, val)) + +#define print_ycoord(file, pcb, val)\ + pcb_fprintf(file, y_convspec, gerberY(pcb, val)) + enum ApertureShape { ROUND, /* Shaped like a circle */ @@ -225,13 +233,14 @@ fprintAperture (FILE *f, Aperture *aptr) switch (aptr->shape) { case ROUND: - pcb_fprintf (f, "%%ADD%dC,%.4`mi*%%\r\n", aptr->dCode, aptr->width); + pcb_fprintf (f, metric ? "%%ADD%dC,%.3`mm*%%\r\n" : "%%ADD%dC,%.4`mi*%%\r\n", aptr->dCode, aptr->width); break; case SQUARE: - pcb_fprintf (f, "%%ADD%dR,%.4`miX%.4`mi*%%\r\n", aptr->dCode, aptr->width, aptr->width); + pcb_fprintf (f, metric ? "%%ADD%dR,%.3`mmX%.3`mm*%%\r\n" : "%%ADD%dR,%.4`miX%.4`mi*%%\r\n", aptr->dCode, aptr->width, aptr->width); break; case OCTAGON: - pcb_fprintf (f, "%%AMOCT%d*5,0,8,0,0,%.4`mi,22.5*%%\r\n" + pcb_fprintf (f, metric ? "%%AMOCT%d*5,0,8,0,0,%.3`mm,22.5*%%\r\n" + "%%ADD%dOCT%d*%%\r\n" : "%%AMOCT%d*5,0,8,0,0,%.3`mm,22.5*%%\r\n" "%%ADD%dOCT%d*%%\r\n", aptr->dCode, (Coord) ((double) aptr->width / COS_22_5_DEGREE), aptr->dCode, aptr->dCode); @@ -362,12 +371,22 @@ Print file names and aperture counts on stdout. {"verbose", "Print file names and aperture counts on stdout", HID_Boolean, 0, 0, {0, 0, 0}, 0, 0}, #define HA_verbose 2 +/* %start-doc options "90 Gerber Export" +@ftable @code +@item --metric +generate metric Gerber and drill files +@end ftable +%end-doc +*/ + {"metric", "Generate metric Gerber and drill files", + HID_Boolean, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_metric 3 {"copy-outline", "Copy outline onto other layers", HID_Enum, 0, 0, {0, 0, 0}, copy_outline_names, 0}, -#define HA_copy_outline 3 +#define HA_copy_outline 4 {"name-style", "Naming style for individual gerber files", HID_Enum, 0, 0, {0, 0, 0}, name_style_names, 0}, -#define HA_name_style 4 +#define HA_name_style 5 }; #define NUM_OPTIONS (sizeof(gerber_options)/sizeof(gerber_options[0])) @@ -531,6 +550,14 @@ gerber_do_export (HID_Attr_Val * options) fnbase = "pcb-out"; verbose = options[HA_verbose].int_value; + metric = options[HA_metric].int_value; + if (metric) { + x_convspec = "X%.0mu"; + y_convspec = "Y%.0mu"; + } else { + x_convspec = "X%.0mc"; + y_convspec = "Y%.0mc"; + } all_layers = options[HA_all_layers].int_value; copy_outline_mode = options[HA_copy_outline].int_value; @@ -668,7 +695,7 @@ gerber_set_layer (const char *name, int group, int empty) } /* Notice the last zeroes are literal zeroes here, a * * x10 scale factor. v v */ - pcb_fprintf (f, "X%06.0ml0Y%06.0ml0\r\n", + pcb_fprintf (f, metric ? "X%06.0muY%06.0mu\r\n" : "X%06.0ml0Y%06.0ml0\r\n", gerberDrX (PCB, pending_drills[i].x), gerberDrY (PCB, pending_drills[i].y)); } @@ -733,10 +760,11 @@ gerber_set_layer (const char *name, int group, int empty) if (is_drill) { /* We omit the ,TZ here because we are not omitting trailing zeros. Our format is - always six-digit 0.1 mil resolution (i.e. 001100 = 0.11")*/ - fprintf (f, "M48\r\n" "INCH\r\n"); + always six-digit 0.1 mil or µm resolution (i.e. 001100 = 0.11" or 1.1mm)*/ + fprintf (f, "M48\r\n"); + fprintf (f, metric ? "METRIC,000.000\r\n" : "INCH\r\n"); for (search = aptr_list->data; search; search = search->next) - pcb_fprintf (f, "T%02dC%.3`mi\r\n", search->dCode, search->width); + pcb_fprintf (f, metric ? "T%02dC%.3`mm\r\n" : "T%02dC%.3`mi\r\n", search->dCode, search->width); fprintf (f, "%%\r\n"); /* FIXME */ return 1; @@ -765,15 +793,16 @@ gerber_set_layer (const char *name, int group, int empty) #endif fprintf (f, "G04 Format: Gerber/RS-274X *\r\n"); - pcb_fprintf (f, "G04 PCB-Dimensions: %.0mc %.0mc *\r\n", + pcb_fprintf (f, metric ? "G04 PCB-Dimensions (mm): %.2mm %.2mm *\r\n", + "G04 PCB-Dimensions (mil): %.2ml %.2ml *\r\n", PCB->MaxWidth, PCB->MaxHeight); fprintf (f, "G04 PCB-Coordinate-Origin: lower left *\r\n"); /* Signal data in inches. */ - fprintf (f, "%%MOIN*%%\r\n"); + fprintf (f, metric ? "%%MOMM*%%\r\n" : "%%MOIN*%%\r\n"); - /* Signal Leading zero suppression, Absolute Data, 2.5 format */ - fprintf (f, "%%FSLAX25Y25*%%\r\n"); + /* Signal Leading zero suppression, Absolute Data, 2.5 format in inch, 4.3 in mm */ + fprintf (f, metric ? "%%FSLAX43Y43*%%\r\n" : "%%FSLAX25Y25*%%\r\n"); /* build a legal identifier. */ if (layername) @@ -996,13 +1025,13 @@ gerber_draw_line (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2) { m = true; lastX = x1; - pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX)); + print_xcoord (f, PCB, lastX); } if (y1 != lastY) { m = true; lastY = y1; - pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY)); + print_ycoord (f, PCB, lastY); } if ((x1 == x2) && (y1 == y2)) fprintf (f, "D03*\r\n"); @@ -1013,13 +1042,12 @@ gerber_draw_line (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2) if (x2 != lastX) { lastX = x2; - pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX)); + print_xcoord (f, PCB, lastX); } if (y2 != lastY) { lastY = y2; - pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY)); - + print_ycoord (f, PCB, lastY); } fprintf (f, "D01*\r\n"); } @@ -1087,17 +1115,18 @@ gerber_draw_arc (hidGC gc, Coord cx, Coord cy, Coord width, Coord height, { m = true; lastX = arcStartX; - pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX)); + print_xcoord (f, PCB, lastX); } if (arcStartY != lastY) { m = true; lastY = arcStartY; - pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY)); + print_ycoord (f, PCB, lastY); } if (m) fprintf (f, "D02*"); pcb_fprintf (f, + metric ? "G75*G0%1dX%.0muY%.0muI%.0muJ%.0muD01*G01*\r\n" : "G75*G0%1dX%.0mcY%.0mcI%.0mcJ%.0mcD01*G01*\r\n", (delta_angle < 0) ? 2 : 3, gerberX (PCB, arcStopX), gerberY (PCB, arcStopY), @@ -1137,12 +1166,12 @@ gerber_fill_circle (hidGC gc, Coord cx, Coord cy, Coord radius) if (cx != lastX) { lastX = cx; - pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX)); + print_xcoord (f, PCB, lastX); } if (cy != lastY) { lastY = cy; - pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY)); + print_ycoord (f, PCB, lastY); } fprintf (f, "D03*\r\n"); } @@ -1168,13 +1197,13 @@ gerber_fill_polygon (hidGC gc, int n_coords, Coord *x, Coord *y) { m = true; lastX = x[i]; - pcb_fprintf (f, "X%.0mc", gerberX (PCB, lastX)); + print_xcoord (f, PCB, lastX); } if (y[i] != lastY) { m = true; lastY = y[i]; - pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY)); + print_ycoord (f, PCB, lastY); } if (firstTime) { @@ -1192,13 +1221,13 @@ gerber_fill_polygon (hidGC gc, int n_coords, Coord *x, Coord *y) { m = true; lastX = startX; - pcb_fprintf (f, "X%.0mc", gerberX (PCB, startX)); + print_xcoord (f, PCB, startX); } if (startY != lastY) { m = true; lastY = startY; - pcb_fprintf (f, "Y%.0mc", gerberY (PCB, lastY)); + print_ycoord (f, PCB, lastY); } if (m) fprintf (f, "D01*\r\n");