mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-22 23:04:16 +02:00
drl2gp: convert KiCad drill file (Excellon) to gnuplot (in progress)
This commit is contained in:
parent
d31bd957ac
commit
1ab262247f
77
drl2gp/Makefile
Normal file
77
drl2gp/Makefile
Normal file
@ -0,0 +1,77 @@
|
||||
#
|
||||
# Makefile - Makefile of drl2gp
|
||||
#
|
||||
# Written 2010 by Werner Almesberger
|
||||
# Copyright 2010 by 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.
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
SHELL=/bin/bash
|
||||
|
||||
MAIN=drl2gp
|
||||
OBJS=drl2gp.o
|
||||
|
||||
CFLAGS_WARN=-Wall -Wshadow -Wmissing-prototypes \
|
||||
-Wmissing-declarations -Wno-format-zero-length
|
||||
CFLAGS=$(CFLAGS_WARN) -g
|
||||
LDFLAGS=-lm
|
||||
|
||||
# ----- Verbosity control -----------------------------------------------------
|
||||
|
||||
CC_normal := $(CC)
|
||||
DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG
|
||||
|
||||
CC_quiet = @echo " CC " $@ && $(CC_normal)
|
||||
DEPEND_quiet = @$(DEPEND_normal)
|
||||
|
||||
ifeq ($(V),1)
|
||||
CC = $(CC_normal)
|
||||
DEPEND = $(DEPEND_normal)
|
||||
else
|
||||
CC = $(CC_quiet)
|
||||
DEPEND = $(DEPEND_quiet)
|
||||
endif
|
||||
|
||||
# ----- Rules -----------------------------------------------------------------
|
||||
|
||||
.PHONY: all clean spotless
|
||||
|
||||
all: $(MAIN)
|
||||
|
||||
$(MAIN): $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(OBJS:.o=.d)
|
||||
|
||||
spotless: clean
|
||||
rm -f $(MAIN)
|
||||
|
||||
# ----- Install / uninstall ---------------------------------------------------
|
||||
|
||||
install: all
|
||||
mkdir -p $(DESTDIR)/$(PREFIX)/bin/
|
||||
install -m 755 $(MAIN) $(DESTDIR)/$(PREFIX)/bin/
|
||||
|
||||
uninstall:
|
||||
rm -f $(DESTDIR)/$(PREFIX)/bin/$(MAIN)
|
||||
|
||||
# ----- Dependencies ----------------------------------------------------------
|
||||
|
||||
# compile and generate dependencies, from fped, based on
|
||||
# http://scottmcpeak.com/autodepend/autodepend.html
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $*.c -o $*.o
|
||||
$(DEPEND) $*.c | \
|
||||
sed -e \
|
||||
'/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \
|
||||
-e '$${g;p;}' -e d >$*.d; \
|
||||
[ "$${PIPESTATUS[*]}" = "0 0" ] || { rm -f $*.d; exit 1; }
|
||||
|
||||
-include $(OBJS:.o=.d)
|
360
drl2gp/drl2gp.c
Normal file
360
drl2gp/drl2gp.c
Normal file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* drl2gp.c - KiCad drill file to gnuplot converter
|
||||
*
|
||||
* 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://web.archive.org/web/20071030075236/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>
|
||||
|
||||
|
||||
#define MAX_ARGS 3
|
||||
#define MAX_TOOL 10
|
||||
|
||||
|
||||
static double tool_d[MAX_TOOL+1];
|
||||
static FILE *out = NULL;
|
||||
static int lineno = 1;
|
||||
|
||||
static int mill;
|
||||
static double depth, d0, d1;
|
||||
|
||||
|
||||
#define IN2MM(in) ((in)*25.4)
|
||||
#define MIL2MM(mil) IN2MM((mil)/1000)
|
||||
|
||||
|
||||
/*
|
||||
* @@@ should at least detect INCH/METRIC
|
||||
*/
|
||||
|
||||
static void header(void)
|
||||
{
|
||||
enum {
|
||||
ts_nl, /* at beginning of line */
|
||||
ts_t, /* seen a ^T */
|
||||
ts_tc, /* seen ^T\d+C */
|
||||
ts_skip, /* skip to next \n */
|
||||
} state = ts_nl;
|
||||
int c, tool;
|
||||
double f = 1;
|
||||
|
||||
while ((c = getchar()) != EOF) {
|
||||
if (out) {
|
||||
if (fputc(c, out) == EOF) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
switch (state) {
|
||||
case ts_nl:
|
||||
switch (c) {
|
||||
case 'T':
|
||||
state = ts_t;
|
||||
tool = 0;
|
||||
break;
|
||||
case '%':
|
||||
return;
|
||||
case '\n':
|
||||
lineno++;
|
||||
break;
|
||||
default:
|
||||
state = ts_skip;
|
||||
break;
|
||||
}
|
||||
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)) {
|
||||
if (f == 1)
|
||||
tool_d[tool] = tool_d[tool]*10+c-'0';
|
||||
else {
|
||||
tool_d[tool] += f*(c-'0');
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void slot(double xa, double ya, double xb, double yb, double d)
|
||||
{
|
||||
assert(mill);
|
||||
}
|
||||
|
||||
|
||||
static void circle(double cx, double cy, double d)
|
||||
{
|
||||
assert(mill);
|
||||
}
|
||||
|
||||
|
||||
static void drill(double x, double y)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void do_cmd(char cmd, double v, int nl)
|
||||
{
|
||||
static int active = 0;
|
||||
static int metric = 1;
|
||||
static int slotting = 0;
|
||||
double x = 0, y = 0, x0 = 0, d = 0;
|
||||
int n = v;
|
||||
|
||||
switch (cmd) {
|
||||
case 'M':
|
||||
switch (n) {
|
||||
case 30: /* end of program */
|
||||
exit(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) {
|
||||
active = 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];
|
||||
if (mill)
|
||||
active = d <= d0;
|
||||
else
|
||||
active = d >= d0 && d <= d1;
|
||||
break;
|
||||
case 'X':
|
||||
x = metric ? v : IN2MM(v);
|
||||
break;
|
||||
case 'Y':
|
||||
if (!active) {
|
||||
slotting = 0;
|
||||
break;
|
||||
}
|
||||
if (slotting) {
|
||||
slot(x0, y, x, v, d);
|
||||
slotting = 0;
|
||||
break;
|
||||
}
|
||||
if (nl) {
|
||||
assert(d);
|
||||
if (d > d1)
|
||||
circle(x, v, d);
|
||||
else
|
||||
drill(x, v);
|
||||
break;
|
||||
}
|
||||
y = metric ? v : IN2MM(v);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unrecognized command \"%c\" at line %d\n",
|
||||
cmd, lineno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void body(void)
|
||||
{
|
||||
char cmd = 0;
|
||||
double v = 0, f = 1;
|
||||
int c, s = 0;
|
||||
|
||||
while ((c = getchar()) != 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)
|
||||
do_cmd(cmd, s ? -v : v, 0);
|
||||
cmd = c;
|
||||
v = 0;
|
||||
f = 1;
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void usage(const char *name)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s depth drill_d_min drill_d_max\n"
|
||||
"usage: %s depth mill_d\n\n"
|
||||
" options can be placed anywhere. -i and -m can be repeated.\n\n"
|
||||
" -i set units to imperial (mil)\n"
|
||||
" -m set units to metric (mm, default)\n"
|
||||
" -f out-file write filtered output to out-file\n"
|
||||
, name, name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *filtered = NULL;
|
||||
int metric = 1;
|
||||
double arg[MAX_ARGS];
|
||||
int n_arg = 0;
|
||||
char *end;
|
||||
double tmp;
|
||||
int i;
|
||||
|
||||
for (i = 1; i != argc; i++) {
|
||||
if (*argv[i] != '-') {
|
||||
if (n_arg == MAX_ARGS)
|
||||
usage(*argv);
|
||||
tmp = strtod(argv[i], &end);
|
||||
if (*end)
|
||||
usage(*argv);
|
||||
if (!metric)
|
||||
tmp = MIL2MM(tmp);
|
||||
arg[n_arg++] = tmp;
|
||||
continue;
|
||||
}
|
||||
switch (argv[i][1]) {
|
||||
case 'i':
|
||||
if (argv[i][2])
|
||||
usage(*argv);
|
||||
metric = 0;
|
||||
break;
|
||||
case 'm':
|
||||
if (argv[i][2])
|
||||
usage(*argv);
|
||||
metric = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (filtered)
|
||||
usage(*argv);
|
||||
if (argv[i][2])
|
||||
filtered = argv[i]+2;
|
||||
else {
|
||||
i++;
|
||||
if (i == argc)
|
||||
usage(*argv);
|
||||
filtered = argv[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(*argv);
|
||||
}
|
||||
}
|
||||
|
||||
depth = arg[0];
|
||||
d0 = arg[1];
|
||||
d1 = arg[2];
|
||||
|
||||
switch (n_arg) {
|
||||
case 2:
|
||||
d1 = d0;
|
||||
mill = 0;
|
||||
break;
|
||||
case 3:
|
||||
mill = 1;
|
||||
break;
|
||||
default:
|
||||
usage(*argv);
|
||||
}
|
||||
|
||||
header();
|
||||
body();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user