aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2017-12-12 12:02:29 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2017-12-15 07:30:35 +0100
commit102614dc8fe2f5aefd0fd92c1b6e48107a9629b0 (patch)
tree341436f8afc4a29819e59b199eb629a80ffd2df0 /src
parent6cd194703674268b313918b590f2bc483c641efa (diff)
downloadee-python-102614dc8fe2f5aefd0fd92c1b6e48107a9629b0.tar.gz
ee-python-102614dc8fe2f5aefd0fd92c1b6e48107a9629b0.tar.bz2
ee-python-102614dc8fe2f5aefd0fd92c1b6e48107a9629b0.tar.xz
ee-python-102614dc8fe2f5aefd0fd92c1b6e48107a9629b0.zip
o Adding a kicad-make-pos tool.
Diffstat (limited to 'src')
-rw-r--r--src/ee/_utils.py6
-rw-r--r--src/ee/kicad/__init__.py18
-rw-r--r--src/ee/kicad/pcb/__init__.py41
-rw-r--r--src/ee/tools/kicad_make_pos.py56
4 files changed, 111 insertions, 10 deletions
diff --git a/src/ee/_utils.py b/src/ee/_utils.py
index 598bca1..9df6126 100644
--- a/src/ee/_utils.py
+++ b/src/ee/_utils.py
@@ -10,3 +10,9 @@ def ensure_has_columns(df: pd.DataFrame, columns: List[str]):
df.insert(0, column=c, value=pd.Series())
# print("df={}".format(df.columns.tolist()))
return df
+
+def run_filters(filters, obj):
+ for f in filters:
+ if not f(obj):
+ return False
+ return True
diff --git a/src/ee/kicad/__init__.py b/src/ee/kicad/__init__.py
index 8d5acd1..1492fc4 100644
--- a/src/ee/kicad/__init__.py
+++ b/src/ee/kicad/__init__.py
@@ -3,6 +3,7 @@ from typing import Any
from ee import EeException
from ee.kicad.read_schematic import read_schematic, read_schematics
from ee.kicad.to_bom import to_bom, to_bom_xml
+from .._utils import run_filters
from .model import *
__all__ = [
@@ -17,17 +18,20 @@ __all__ = [
"to_pandas",
]
+def parse_ref(ref):
+ m = parse_ref.r.match(ref)
+ if not m:
+ return
+ g = m.groups()
+# print("groups={}".format(g))
+ return (g[0], None if g[1] == "?" else int(g[1]))
+
+parse_ref.r = re.compile("([^0-9]+)([0-9]+|\?)$")
def to_pandas(obj: Any, **kwarg):
import pandas
import numpy as np
- def run_filter(filters, obj):
- for f in filters:
- if not f(obj):
- return False
- return True
-
def to_pandas_schematics(ss: Schematics):
dfs = [to_pandas_schematic(schematic) for schematic in ss.schematics]
@@ -65,7 +69,7 @@ def to_pandas(obj: Any, **kwarg):
if not include_flg:
filters.append(lambda c: c.ref_type != "#FLG")
- data = [make_dict(c) for c in components if run_filter(filters, c)]
+ data = [make_dict(c) for c in components if run_filters(filters, c)]
columns = set([key for row in data for key in list(row)]) - set(special_fields)
columns = special_fields + list(columns)
diff --git a/src/ee/kicad/pcb/__init__.py b/src/ee/kicad/pcb/__init__.py
index 10350c3..679c5ea 100644
--- a/src/ee/kicad/pcb/__init__.py
+++ b/src/ee/kicad/pcb/__init__.py
@@ -1,4 +1,5 @@
from .. import sexpr
+from ..._utils import run_filters
def auto_str(cls):
def __str__(self):
@@ -25,16 +26,32 @@ class Module(object):
for k, v in kwargs.items():
setattr(self, k, v)
+ self.fp_texts = self.fp_texts or []
+
+ def filter_fp_text(self, kind = None):
+ filters = []
+
+ if kind:
+ filters.append(lambda fp_text: fp_text.kind == kind)
+
+ return (fp_text for fp_text in self.fp_texts if run_filters(filters, fp_text))
+
@auto_str
class Pad(object):
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
+@auto_str
+class FpText(object):
+ def __init__(self, **kwargs):
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+
def parse(path):
count = 0
p = sexpr.parse(path)
- p = sexpr.logging_parser(p)
+ #p = sexpr.logging_parser(p)
(event, token) = next(p)
assert event == sexpr.EVENT_LPAREN
@@ -111,10 +128,12 @@ def parse(path):
def _parse_module():
pads = []
+ fp_texts = []
args = {}
args["footprint"] = _parse_text()
args["pads"] = pads
+ args["fp_texts"] = fp_texts
(event, token) = next(p)
while event == sexpr.EVENT_TEXT:
@@ -128,6 +147,8 @@ def parse(path):
args[token] = _parse_at()
elif token == "pad":
pads.append(_parse_pad())
+ elif token == "fp_text":
+ fp_texts.append(_parse_fp_text())
else:
_consume()
(event, token) = next(p)
@@ -155,6 +176,21 @@ def parse(path):
return Pad(**args)
+ def _parse_fp_text():
+ args = {
+ "kind": _parse_text(),
+ "value": _parse_text(),
+ }
+ (event, token) = next(p)
+ while event == sexpr.EVENT_LPAREN:
+ (event, token) = next(p)
+ if token == "at":
+ args[token] = _parse_at()
+ if token == "layer":
+ args[token] = _parse_text()
+ else:
+ _consume()
+ return FpText(**args)
def _parse_at():
x = _parse_text(to=float)
@@ -163,6 +199,5 @@ def parse(path):
return (x, y, rot or 0)
kicad_pcb = _parse_kicad_pcb()
-# (event, token) = next(p)
-# assert event == sexpr.EVENT_END
+ assert next(p, None) == None
return kicad_pcb
diff --git a/src/ee/tools/kicad_make_pos.py b/src/ee/tools/kicad_make_pos.py
new file mode 100644
index 0000000..cd381a5
--- /dev/null
+++ b/src/ee/tools/kicad_make_pos.py
@@ -0,0 +1,56 @@
+import sys
+import argparse
+import csv
+from . import mk_parents
+from ..kicad import pcb, parse_ref
+from .._utils import run_filters
+
+parser = argparse.ArgumentParser(description="Create a pick and place file from a KiCAD schematic")
+
+parser.add_argument("--kicad-pcb",
+ required=True,
+ dest="pcb",
+ metavar="PCB",
+ help="The pcb to read")
+
+parser.add_argument("--out",
+ metavar="FILE",
+ help="The output file")
+
+args = parser.parse_args()
+
+pcb = pcb.parse(args.pcb)
+
+def run(stream):
+ rows = []
+ for m in pcb.modules:
+ row = {}
+ ref_fp_text = next(m.filter_fp_text(kind = "reference"), None)
+ row["ref"] = ref= ref_fp_text and ref_fp_text.value
+ row["r"] = parse_ref(ref)
+ value_fp_text = next(m.filter_fp_text(kind = "value"), None)
+ row["value"] = value_fp_text and value_fp_text.value
+ (row["library"], row["footprint"]) = m.footprint.split(":")
+ (row["x"], row["y"], row["rot"]) = m.at
+ if m.layer == "F.Cu":
+ row["side"] = "top"
+ elif m.layer == "B.Cu":
+ row["side"] = "bottom"
+ else:
+ row["side"] = None
+ rows.append(row)
+
+ rows = sorted(rows, key=lambda row: row["r"])
+
+ out = csv.writer(stream)
+ out.writerow(["ref", "value", "library", "footprint", "x", "y", "rotation", "side"])
+ for row in rows:
+ del row["r"]
+ out.writerow(row.values())
+
+if args.out:
+ mk_parents(args.out)
+ with open(args.out, "w") as f:
+ run(f)
+else:
+ run(sys.stdout)