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: Tue, 3 Jul 2012 16:02:36 +0200 From: Gabriel Paubert To: geda-user AT delorie DOT com Subject: [geda-user] [PATCH] Allow to create metric Gerber and drill files. Message-ID: <20120703140236.GA12646@visitor2.iram.es> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit 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 Hi, I've been designing a board with quite tight rules: 0.1mm width/space in some areas (I absolutely needed tracks between pads on a 0.65mm pitch), vias 0.6mm with 0.3mm drill hole. This showed a problem in Gerber and drill file generation: when looking closely at the output, the holes were visibly not in the center of the vias. The basic problem is that drill files only has mil resolution, since the last digit is always zero (which is a regression which was introduced a few months ago). Now, since all components except one (a 15 pin sub-d connector) on this board were defined in metric, I took a different approach to fixing the problem: give the option of generating metric files for everything in the Gerber exporter. The patch follows, it turned out to be relatively simple, and both Gerber and drill files resolution is 1µm. Note that I have maintained the option of using imperial formats, but in the patch the metric flag is set by default. Imperial format has one advantage: drill files can describe large boards since the METRIC,000.000 format is limited to one meter, versus 100 inches for the INCH format. Now if gerbv really did support metric format instead of converting metric to imperial as soon as it reads a metric coordinate or dimension! Anyway, I think this patch should go in, even it it does not solve the problem of the degraded precision in imperial drill files. Gabriel diff --git a/src/hid/gerber/gerber.c b/src/hid/gerber/gerber.c index 2181718..0df5eb3 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; @@ -770,10 +798,10 @@ gerber_set_layer (const char *name, int group, int empty) 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 +1024,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 +1041,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 +1114,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 +1165,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 +1196,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 +1220,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");