mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-22 23:04:16 +02:00
cameo: migrated Excellon reader from drl2gp
- Makefile (OBJS): added excellon.o - README: added brief description of Excellon input - excellon.h, excellon.c: adaptation of KiCad drill file reader from ../drl2gp/drl2gp.c - lang.l, lang.y: added command "excellon" to read KiCad drill files - gerber.h: removed stray newline
This commit is contained in:
parent
26dc02ea57
commit
848eb2a209
@ -15,7 +15,7 @@ PREFIX ?= /usr/local
|
||||
SHELL=/bin/bash
|
||||
|
||||
MAIN=cameo
|
||||
OBJS=cameo.o gerber.o gnuplot.o ops.o path.o lex.yy.o y.tab.o
|
||||
OBJS=cameo.o excellon.o gerber.o gnuplot.o ops.o path.o lex.yy.o y.tab.o
|
||||
|
||||
CFLAGS_WARN=-Wall -Wshadow -Wmissing-prototypes \
|
||||
-Wmissing-declarations -Wno-format-zero-length
|
||||
|
@ -28,10 +28,11 @@ Loading paths:
|
||||
|
||||
gerber <diameter> [<filename>]
|
||||
gnuplot <diameter> [<filename>]
|
||||
excellon [<filename>]
|
||||
clear
|
||||
|
||||
"gerber" and "gnuplot" each add paths from a file to the list of paths
|
||||
already loaded. "clear" removes all paths.
|
||||
"gerber", "gnuplot", and "excellon" each add paths from a file to the
|
||||
list of paths already loaded. "clear" removes all paths.
|
||||
|
||||
If the a file name is omitted, standard input is read. The diameter is
|
||||
the default tool diameter.
|
||||
|
303
cameo/excellon.c
Normal file
303
cameo/excellon.c
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* excellon.c - KiCad drill file input
|
||||
*
|
||||
* Written 2010 by Werner Almesberger
|
||||
* Copyright 2010 Werner Almesberger
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* KiCad drill files are in the Excellon format. The format is described here:
|
||||
*
|
||||
* http://www.excellon.com/manuals/program.htm
|
||||
*
|
||||
* Note that drl2gp currently only implements the subset necessary to process
|
||||
* the KiCad drill files encountered in a few projects, may not work correctly
|
||||
* for drill files from other projects, and will almost certainly fail in
|
||||
* tool-shattering ways when fed excellon files from other sources.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "excellon.h"
|
||||
|
||||
|
||||
#define MAX_TOOL 10
|
||||
|
||||
|
||||
static double tool_d[MAX_TOOL+1];
|
||||
static int lineno = 1;
|
||||
static struct path *paths, **anchor;
|
||||
|
||||
|
||||
#define IN2MM(in) ((in)*25.4)
|
||||
#define MIL2MM(mil) IN2MM((mil)/1000)
|
||||
|
||||
|
||||
/* ----- header parsing ---------------------------------------------------- */
|
||||
|
||||
|
||||
static void header(FILE *file)
|
||||
{
|
||||
enum {
|
||||
ts_nl, /* at beginning of line */
|
||||
ts_t, /* seen a ^T */
|
||||
ts_metric, /* parsing METRIC,... */
|
||||
ts_inch, /* parsing INCH,... */
|
||||
ts_tc, /* seen ^T\d+C */
|
||||
ts_skip, /* skip to next \n */
|
||||
} state = ts_nl;
|
||||
int c, tool;
|
||||
double f = 1;
|
||||
double tmp;
|
||||
const char *next = NULL;
|
||||
int metric = 1;
|
||||
|
||||
while ((c = fgetc(file)) != EOF) {
|
||||
switch (state) {
|
||||
case ts_nl:
|
||||
switch (c) {
|
||||
case 'T':
|
||||
state = ts_t;
|
||||
tool = 0;
|
||||
break;
|
||||
case 'I':
|
||||
state = ts_inch;
|
||||
next = "NCH";
|
||||
break;
|
||||
case 'M':
|
||||
state = ts_metric;
|
||||
next = "ETRIC";
|
||||
break;
|
||||
case '%':
|
||||
return;
|
||||
case '\n':
|
||||
lineno++;
|
||||
break;
|
||||
default:
|
||||
state = ts_skip;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ts_inch:
|
||||
if (c == ',')
|
||||
metric = 0;
|
||||
else {
|
||||
if (c == *next++)
|
||||
break;
|
||||
}
|
||||
state = ts_skip;
|
||||
break;
|
||||
case ts_metric:
|
||||
if (c == ',')
|
||||
metric = 1;
|
||||
else {
|
||||
if (c == *next++)
|
||||
break;
|
||||
}
|
||||
state = ts_skip;
|
||||
break;
|
||||
case ts_t:
|
||||
if (isdigit(c))
|
||||
tool = tool*10+c-'0';
|
||||
else if (c != 'C')
|
||||
state = ts_skip;
|
||||
else {
|
||||
assert(c != '\n');
|
||||
if (tool > MAX_TOOL) {
|
||||
fprintf(stderr,
|
||||
"tool index %d too large (> %d)\n",
|
||||
tool, MAX_TOOL);
|
||||
exit(1);
|
||||
}
|
||||
tool_d[tool] = 0;
|
||||
f = 1;
|
||||
state = ts_tc;
|
||||
}
|
||||
break;
|
||||
case ts_tc:
|
||||
if (isdigit(c)) {
|
||||
tmp = c-'0';
|
||||
if (!metric)
|
||||
tmp = IN2MM(tmp);
|
||||
if (f == 1)
|
||||
tool_d[tool] =
|
||||
tool_d[tool]*10+tmp;
|
||||
else {
|
||||
tool_d[tool] += f*tmp;
|
||||
f /= 10;
|
||||
}
|
||||
} else if (c == '.') {
|
||||
f = 0.1;
|
||||
} else if (c == '\n') {
|
||||
lineno++;
|
||||
state = ts_nl;
|
||||
} else {
|
||||
state = ts_skip;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (c == '\n') {
|
||||
lineno++;
|
||||
state = ts_nl;
|
||||
} else {
|
||||
state = ts_skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----- body parsing ------------------------------------------------------ */
|
||||
|
||||
|
||||
static int do_cmd(char cmd, double v, int nl)
|
||||
{
|
||||
static int metric = 1;
|
||||
static int slotting = 0;
|
||||
static double x = 0, y = 0, x0 = 0, d = 0;
|
||||
int n = v;
|
||||
|
||||
switch (cmd) {
|
||||
case 'M':
|
||||
switch (n) {
|
||||
case 30: /* end of program */
|
||||
return 0;
|
||||
case 47: /* operator message */
|
||||
break;
|
||||
case 71: /* metric measuring mode */
|
||||
metric = 1;
|
||||
break;
|
||||
case 72: /* inch measuring mode */
|
||||
metric = 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"unrecognized command M%d at line %d\n",
|
||||
n, lineno);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
switch (n) {
|
||||
case 5: /* drill mode */
|
||||
break;
|
||||
case 85: /* slot */
|
||||
x0 = x;
|
||||
slotting = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"unrecognized command G%d at line %d\n",
|
||||
n, lineno);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
if (!n) {
|
||||
d = 0;
|
||||
break;
|
||||
}
|
||||
if (n < 1 || n > MAX_TOOL || !tool_d[n]) {
|
||||
fprintf(stderr, "invalid tool T%d at line %d\n",
|
||||
n, lineno);
|
||||
exit(1);
|
||||
}
|
||||
d = tool_d[n];
|
||||
break;
|
||||
case 'X':
|
||||
x = metric ? v : IN2MM(v);
|
||||
break;
|
||||
case 'Y':
|
||||
if (!metric)
|
||||
v = IN2MM(v);
|
||||
if (slotting) {
|
||||
*anchor = path_new(d/2);
|
||||
path_add(*anchor, x0, y, 0);
|
||||
path_add(*anchor, x, v, 0);
|
||||
anchor = &(*anchor)->next;
|
||||
slotting = 0;
|
||||
break;
|
||||
}
|
||||
if (nl) {
|
||||
assert(d);
|
||||
*anchor = path_new(d/2);
|
||||
path_add(*anchor, x, v, 0);
|
||||
anchor = &(*anchor)->next;
|
||||
break;
|
||||
}
|
||||
y = v;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unrecognized command \"%c\" at line %d\n",
|
||||
cmd, lineno);
|
||||
exit(1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void body(FILE *file)
|
||||
{
|
||||
char cmd = 0;
|
||||
double v = 0, f = 1;
|
||||
int c, s = 0;
|
||||
|
||||
while ((c = fgetc(file)) != EOF) {
|
||||
if (c == '\n') {
|
||||
lineno++;
|
||||
if (cmd)
|
||||
do_cmd(cmd, s ? -v : v, 1);
|
||||
cmd = 0;
|
||||
} else if (isdigit(c)) {
|
||||
if (f == 1)
|
||||
v = v*10+c-'0';
|
||||
else {
|
||||
v += f*(c-'0');
|
||||
f /= 10;
|
||||
}
|
||||
} else if (c == '.') {
|
||||
f = 0.1;
|
||||
} else if (c == '-') {
|
||||
s = !s;
|
||||
} else {
|
||||
if (cmd)
|
||||
if (!do_cmd(cmd, s ? -v : v, 0))
|
||||
return;
|
||||
cmd = c;
|
||||
v = 0;
|
||||
f = 1;
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct path *excellon_read(const char *name)
|
||||
{
|
||||
FILE *file;
|
||||
|
||||
file = name ? fopen(name, "r") : stdin;
|
||||
if (!file) {
|
||||
perror(name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lineno = 1;
|
||||
paths = NULL;
|
||||
anchor = &paths;
|
||||
|
||||
header(file);
|
||||
body(file);
|
||||
|
||||
fclose(file);
|
||||
return paths;
|
||||
}
|
21
cameo/excellon.h
Normal file
21
cameo/excellon.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* excellon.h - KiCad drill file input
|
||||
*
|
||||
* Written 2010 by Werner Almesberger
|
||||
* Copyright 2010 Werner Almesberger
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef EXCELLON_H
|
||||
#define EXCELLON_H
|
||||
|
||||
#include "path.h"
|
||||
|
||||
|
||||
struct path *excellon_read(const char *name);
|
||||
|
||||
#endif /* !EXCELLON_H */
|
@ -19,4 +19,3 @@
|
||||
struct path *gerber_read(const char *name, double r_tool_default);
|
||||
|
||||
#endif /* !GERBER_H */
|
||||
|
||||
|
@ -51,6 +51,8 @@ NUM -?[0-9]+\.?[0-9]*
|
||||
return TOK_GERBER; }
|
||||
<INITIAL>gnuplot { file_name_follows = 1;
|
||||
return TOK_GNUPLOT; }
|
||||
<INITIAL>excellon { BEGIN(FILENAME);
|
||||
return TOK_EXCELLON; }
|
||||
<INITIAL>write { BEGIN(FILENAME);
|
||||
return TOK_WRITE; }
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "ops.h"
|
||||
#include "gnuplot.h"
|
||||
#include "gerber.h"
|
||||
#include "excellon.h"
|
||||
|
||||
#include "y.tab.h"
|
||||
|
||||
@ -122,7 +123,7 @@ static void align(int ref, double x, double y)
|
||||
|
||||
%token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_RESET TOK_OFFSET
|
||||
%token TOK_TRANSLATE TOK_Z
|
||||
%token TOK_GERBER TOK_GNUPLOT TOK_WRITE
|
||||
%token TOK_GERBER TOK_GNUPLOT TOK_EXCELLON TOK_WRITE
|
||||
%token TOK_DOG TOK_INSIDE
|
||||
|
||||
%token <num> NUM_EXP_MIL NUM_EXP_MM NUM_IMP_MIL NUM_IMP_MM REF
|
||||
@ -206,6 +207,11 @@ command:
|
||||
add_paths(gnuplot_read($3, $2/2));
|
||||
translate(xo, yo, 0);
|
||||
}
|
||||
| TOK_EXCELLON opt_filename
|
||||
{
|
||||
add_paths(excellon_read($2));
|
||||
translate(xo, yo, 0);
|
||||
}
|
||||
| TOK_WRITE opt_filename
|
||||
{
|
||||
translate(0, 0, zo);
|
||||
|
Loading…
Reference in New Issue
Block a user