From a30b71772e7eb831e8d87759172a02e79f9673c4 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 17 Jul 2018 12:23:58 +0200 Subject: wip. pcb. --- src/ee/kicad/doit.py | 97 ++++++++++++++++++++++++++++++++------------ src/ee/kicad/pcb/__init__.py | 40 ++++++++++-------- 2 files changed, 95 insertions(+), 42 deletions(-) (limited to 'src/ee/kicad') diff --git a/src/ee/kicad/doit.py b/src/ee/kicad/doit.py index 10de885..fcbcaef 100644 --- a/src/ee/kicad/doit.py +++ b/src/ee/kicad/doit.py @@ -1,13 +1,14 @@ +import logging import os.path -from doit.exceptions import TaskFailed -from doit.tools import check_timestamp_unchanged -from configclass import Config from typing import List + +from configclass import Config + from ee.fact import DataSetManager -import logging logger = logging.getLogger(__name__) + class KicadDoitTasks(object): config = Config({ "sch": None, @@ -15,7 +16,7 @@ class KicadDoitTasks(object): "gerber_dir": None, "gerber_zip": None, "data_set_dir": None, - }) + }) def __init__(self, *args, **kwargs): self.config = self.config.make(kwargs) @@ -24,7 +25,6 @@ class KicadDoitTasks(object): logger.info("_task: args={}, kwars={}".format(args, kwargs)) def tasks(self, *args, **kwargs): - import ee.kicad kicad_pcb = self.config["kicad_pcb"] sch = self.config["sch"] tasks = [] @@ -32,24 +32,32 @@ class KicadDoitTasks(object): dsm = DataSetManager(self.config["data_set_dir"]) gerber_dir = self.config["gerber_dir"] - if gerber_dir: - tasks.append(task_kicad_gerber()) + gerber_zip = self.config["gerber_zip"] + if kicad_pcb and gerber_dir: + tasks.append(task_kicad_gerber(kicad_pcb, gerber_dir, gerber_zip)) - sch_ds = task_kicad_sch_to_data_set(dsm, sch, \ - in_data_sets=[], \ - out_data_set="kicad-sch-data-set") \ - if sch else None + sch_ds = task_kicad_sch_to_data_set(dsm, sch, + in_data_sets=[], + out_data_set="kicad-sch-data-set") \ + if sch else None - component_ds = task_kicad_create_component_data_set(dsm, \ - in_data_sets=sch_ds["targets"], \ - out_data_set="raw-component") \ - if sch_ds else None + component_ds = task_kicad_create_component_data_set(dsm, + in_data_sets=sch_ds["targets"], + out_data_set="raw-component") \ + if sch_ds else None - return (t for t in [sch_ds, component_ds] if t is not None) + pcb_ds = task_kicad_pcb_to_data_set(dsm, kicad_pcb, in_data_sets=[], out_data_set="kicad-pcb") \ + if kicad_pcb else None -def task_kicad_gerber(name="kicad-gerber"): - gerber_zip = self.config["gerber_zip"] or "{}.zip".format(gerber_dir) - #logger.info("gerber_zip={}".format(gerber_zip)) + tasks = [sch_ds, component_ds, pcb_ds] + return (t for t in tasks if t) + + +def task_kicad_gerber(kicad_pcb: str, gerber_dir: str, gerber_zip: str, name="kicad-gerber"): + import ee.kicad + + gerber_zip = len(gerber_zip) or "{}.zip".format(gerber_dir) + # logger.info("gerber_zip={}".format(gerber_zip)) eg = next((p for p in (os.path.join(p, "export_gerber.py") for p in ee.kicad.__path__) if os.path.isfile(p)), None) if not eg: @@ -63,6 +71,7 @@ def task_kicad_gerber(name="kicad-gerber"): "--output-directory", gerber_dir, "--protel-extensions", ]) + def make_zip(): import zipfile from pathlib import Path @@ -79,12 +88,12 @@ def task_kicad_gerber(name="kicad-gerber"): "file_dep": [kicad_pcb], } -def task_kicad_sch_to_data_set(dsm: DataSetManager, sch, in_data_sets: List[str], out_data_set, name="kicad-sch-to-data-set"): + +def task_kicad_sch_to_data_set(dsm: DataSetManager, sch, in_data_sets: List[str], out_data_set, + name="kicad-sch-to-data-set"): def action(): import ee.kicad - from ee.kicad.model import Component, ComponentField - import csv - import configparser + from ee.kicad.model import ComponentField with dsm.create_rw(out_data_set, inputs=in_data_sets) as ds: schematics = ee.kicad.read_schematics(sch) @@ -109,10 +118,46 @@ def task_kicad_sch_to_data_set(dsm: DataSetManager, sch, in_data_sets: List[str] "targets": [dsm.metafile_for_ds(out_data_set)], } -def task_kicad_create_component_data_set(dsm: DataSetManager, in_data_sets: List[str], out_data_set, name="kicad-create-component-data-set"): + +def task_kicad_pcb_to_data_set(dsm: DataSetManager, pcb_path, in_data_sets: List[str], out_data_set, + name="kicad-pcb-to-data-set"): + def action(): + import ee.kicad.pcb + from ee.kicad.pcb import FpText + + with dsm.create_rw(out_data_set, inputs=in_data_sets) as ds: + # [ds.delete(o) for o in ds.items(object_type="kicad-pcb-component")] + + pcb: ee.kicad.pcb.KicadPcb = ee.kicad.pcb.parse(pcb_path) + for _m in pcb.modules: + m: ee.kicad.pcb.Module = _m + logger.info("attrs") + for s in dir(m): + logger.info(s) + + o = ds.get_object("kicad-pcb-component", m.tstamp) + + ref_text: FpText = next((t for t in m.fp_texts if t.kind == "reference"), None) + o.set("reference", ref_text.value) + + x, y, rot = m.at + o.set("at-x", x) + o.set("at-y", y) + o.set("at-rot", rot) + o.set("layer", m.layer) + + return { + "name": name, + "file_dep": [pcb_path] + [dsm.metafile_for_ds(ds) for ds in in_data_sets], + "actions": [action], + "targets": [dsm.metafile_for_ds(out_data_set)], + } + + +def task_kicad_create_component_data_set(dsm: DataSetManager, in_data_sets: List[str], out_data_set, + name="kicad-create-component-data-set"): def action(*args, **kwargs): logger.info("args={}, kwargs={}".format(args, kwargs)) - import ee.fact as fact with dsm.create_rw(out_data_set, inputs=in_data_sets) as ds: items = ds.items() diff --git a/src/ee/kicad/pcb/__init__.py b/src/ee/kicad/pcb/__init__.py index 79987e6..25689ef 100644 --- a/src/ee/kicad/pcb/__init__.py +++ b/src/ee/kicad/pcb/__init__.py @@ -49,18 +49,21 @@ class Pad(object): @auto_str class FpText(object): def __init__(self, **kwargs): + self.kind = None # type: str + self.value = None # type: str for k, v in kwargs.items(): setattr(self, k, v) -def parse(path): + +def parse(path) -> KicadPcb: count = 0 p = sexpr.parse(path) #p = sexpr.logging_parser(p) - (event, token) = next(p) - assert event == sexpr.EVENT_LPAREN + (e, t) = next(p) + assert e == sexpr.EVENT_LPAREN - (event, token) = next(p) - assert event == sexpr.EVENT_TEXT and token == "kicad_pcb" + (e, t) = next(p) + assert e == sexpr.EVENT_TEXT and t == "kicad_pcb" idx = 0 def _consume(): @@ -134,10 +137,14 @@ def parse(path): pads = [] fp_texts = [] - args = {} - args["footprint"] = _parse_text() - args["pads"] = pads - args["fp_texts"] = fp_texts + args = { + "footprint": _parse_text(), + "pads": pads, + "fp_texts": fp_texts, + "layer": None, + "tedit": None, + "tstamp": None, + } (event, token) = next(p) while event == sexpr.EVENT_TEXT: @@ -145,12 +152,12 @@ def parse(path): while event == sexpr.EVENT_LPAREN: (event, token) = next(p) - if token == "layer": - args[token] = _parse_text(rparen = True) + if token in ["layer", "tedit", "tstamp"]: + args[token] = _parse_text(rparen=True) elif token == "at": args[token] = _parse_at() elif token == "attr": - args[token] = [_parse_text(rparen = True)] + args[token] = [_parse_text(rparen=True)] elif token == "pad": pads.append(_parse_pad()) elif token == "fp_text": @@ -163,8 +170,9 @@ def parse(path): def _parse_pad(): texts = [] - args = {} - args["footprint"] = _parse_text() + args = { + "footprint": _parse_text() + } (event, token) = next(p) while event == sexpr.EVENT_TEXT: @@ -182,7 +190,7 @@ def parse(path): return Pad(**args) - def _parse_fp_text(): + def _parse_fp_text() -> FpText: args = { "kind": _parse_text(), "value": _parse_text(), @@ -202,7 +210,7 @@ def parse(path): x = _parse_text(to=float) y = _parse_text(to=float) rot = _parse_text(to=float, optional = True, rparen = True) - return (x, y, rot or 0) + return x, y, rot or 0 kicad_pcb = _parse_kicad_pcb() assert next(p, None) == None -- cgit v1.2.3