summaryrefslogtreecommitdiff
path: root/gerbonara/cad
diff options
context:
space:
mode:
authorjaseg <git@jaseg.de>2023-07-18 21:54:26 +0200
committerjaseg <git@jaseg.de>2023-07-18 21:54:26 +0200
commita1b8cbf86160eb2fbe73ffda61c953589ffa3512 (patch)
tree4123a00e361d48e2b1fb73039858633b847ab931 /gerbonara/cad
parent58142cb0c7c0a38dd07592632a7e0c1622cc99d9 (diff)
downloadgerbonara-a1b8cbf86160eb2fbe73ffda61c953589ffa3512.tar.gz
gerbonara-a1b8cbf86160eb2fbe73ffda61c953589ffa3512.tar.bz2
gerbonara-a1b8cbf86160eb2fbe73ffda61c953589ffa3512.zip
Make kicad eat schematics written by gerbonara
Diffstat (limited to 'gerbonara/cad')
-rw-r--r--gerbonara/cad/kicad/schematic.py39
-rw-r--r--gerbonara/cad/kicad/sexp_mapper.py2
-rw-r--r--gerbonara/cad/kicad/symbols.py7
3 files changed, 32 insertions, 16 deletions
diff --git a/gerbonara/cad/kicad/schematic.py b/gerbonara/cad/kicad/schematic.py
index 5c73c88..1bdbf38 100644
--- a/gerbonara/cad/kicad/schematic.py
+++ b/gerbonara/cad/kicad/schematic.py
@@ -34,7 +34,7 @@ class SheetPath:
@sexp_type('junction')
class Junction:
- at: AtPos = field(default_factory=AtPos)
+ at: Rename(XYCoord) = field(default_factory=XYCoord)
diameter: Named(float) = 0
color: Color = field(default_factory=lambda: Color(0, 0, 0, 0))
uuid: UUID = field(default_factory=UUID)
@@ -42,7 +42,7 @@ class Junction:
@sexp_type('no_connect')
class NoConnect:
- at: AtPos = field(default_factory=AtPos)
+ at: Rename(XYCoord) = field(default_factory=XYCoord)
uuid: UUID = field(default_factory=UUID)
@@ -191,36 +191,41 @@ class SubsheetPin:
uuid: UUID = field(default_factory=UUID)
+@sexp_type('fill')
+class SubsheetFill:
+ color: Color = field(default_factory=lambda: Color(0, 0, 0, 0))
+
+
@sexp_type('sheet')
class Subsheet:
- at: AtPos = field(default_factory=AtPos)
+ at: Rename(XYCoord) = field(default_factory=XYCoord)
size: Rename(XYCoord) = field(default_factory=lambda: XYCoord(2.54, 2.54))
fields_autoplaced: Wrap(Flag()) = True
stroke: Stroke = field(default_factory=Stroke)
- fill: gr.FillMode = field(default_factory=gr.FillMode)
+ fill: SubsheetFill = field(default_factory=SubsheetFill)
uuid: UUID = field(default_factory=UUID)
_properties: List(DrawnProperty) = field(default_factory=list)
pins: List(SubsheetPin) = field(default_factory=list)
# AFAICT this is completely redundant, just like the one in SymbolInstance
instances: Named(List(SubsheetCrosslinkProject)) = field(default_factory=list)
- _: KW_ONLY
+ _ : SEXP_END = None
sheet_name: object = field(default_factory=lambda: DrawnProperty('Sheetname', ''))
file_name: object = field(default_factory=lambda: DrawnProperty('Sheetfile', ''))
- parent: object = None
+ schematic: object = None
def __after_parse__(self, parent):
self.sheet_name, self.file_name = self._properties
- self.parent = parent
+ self.schematic = parent
def __before_sexp__(self):
self._properties = [self.sheet_name, self.file_name]
def open(self, search_dir=None, safe=True):
if search_dir is None:
- if not self.parent.original_filename:
+ if not self.schematic.original_filename:
raise FileNotFoundError('No search path given and path of parent schematic unknown')
else:
- search_dir = Path(self.parent.original_filename).parent
+ search_dir = Path(self.schematic.original_filename).parent
else:
search_dir = Path(search_dir)
@@ -231,15 +236,21 @@ class Subsheet:
return Schematic.open(resolved)
-SUPPORTED_FILE_FORMAT_VERSIONS = [20220914]
+@sexp_type('lib_symbols')
+class LocalLibrary:
+ symbols: List(Symbol) = field(default_factory=list)
+
+
+SUPPORTED_FILE_FORMAT_VERSIONS = [20230620]
@sexp_type('kicad_sch')
class Schematic:
- _version: Named(int, name='version') = 20211014
+ _version: Named(int, name='version') = 20230620
generator: Named(Atom) = Atom.gerbonara
uuid: UUID = field(default_factory=UUID)
page_settings: PageSettings = field(default_factory=PageSettings)
- path: SheetPath = field(default_factory=SheetPath)
- lib_symbols: Named(Array(Symbol)) = field(default_factory=list)
+ # The doc says this is expected, but eeschema barfs when it's there.
+ # path: SheetPath = field(default_factory=SheetPath)
+ lib_symbols: LocalLibrary = field(default_factory=list)
junctions: List(Junction) = field(default_factory=list)
no_connects: List(NoConnect) = field(default_factory=list)
bus_entries: List(BusEntry) = field(default_factory=list)
@@ -291,3 +302,5 @@ if __name__ == '__main__':
subsh = subsh.open()
print('Loaded sub-sheet with', len(subsh.wires), 'wires and', len(subsh.symbols), 'symbols.')
+ sch.write('/tmp/test.kicad_sch')
+
diff --git a/gerbonara/cad/kicad/sexp_mapper.py b/gerbonara/cad/kicad/sexp_mapper.py
index c6e7464..96727e4 100644
--- a/gerbonara/cad/kicad/sexp_mapper.py
+++ b/gerbonara/cad/kicad/sexp_mapper.py
@@ -62,7 +62,7 @@ def sexp(t, v):
t, = t
return [sexp(t, elem) for elem in v]
else:
- raise TypeError(f'Python type {t} has no defined s-expression serialization')
+ raise TypeError(f'Python type {t} of value {v!r} has no defined s-expression serialization')
except MappingError as e:
raise e
diff --git a/gerbonara/cad/kicad/symbols.py b/gerbonara/cad/kicad/symbols.py
index 7e16d38..0f32b4d 100644
--- a/gerbonara/cad/kicad/symbols.py
+++ b/gerbonara/cad/kicad/symbols.py
@@ -247,7 +247,7 @@ class Unit:
if not (m := re.fullmatch(r'(.*)_([0-9]+)_([0-9]+)', self.name)):
raise FormatError(f'Invalid unit name "{self.name}"')
sym_name, unit_index, demorgan_style = m.groups()
- if sym_name != self.symbol.name:
+ if sym_name != self.symbol.raw_name.rpartition(':')[2]:
raise FormatError(f'Unit name "{self.name}" does not match symbol name "{self.symbol.name}"')
self.demorgan_style = int(demorgan_style)
self.unit_index = int(unit_index)
@@ -271,7 +271,7 @@ class Unit:
@sexp_type('symbol')
class Symbol:
- name: str = None
+ raw_name: str = None
extends: Named(str) = None
power: Wrap(Flag()) = False
pin_numbers: OmitDefault(PinNumberSpec) = field(default_factory=PinNumberSpec)
@@ -284,10 +284,13 @@ class Symbol:
styles: {str: {str: Unit}} = None
global_units: {str: {str: Unit}} = None
library = None
+ name: str = None
+ library_name: str = None
def __after_parse__(self, parent):
self.library = parent
+ self.library_name, _, self.name = self.raw_name.rpartition(':')
self.global_units = {}
self.styles = {}