commit
600ce1829a
|
@ -55,3 +55,5 @@ Temporary Items
|
|||
*.OutJob
|
||||
*.SchDoc.Zip
|
||||
*.OutJob.Zip
|
||||
*.NET
|
||||
*.PcbDoc.htm
|
||||
|
|
147
parse.py
147
parse.py
|
@ -3,6 +3,9 @@ import olefile
|
|||
import re
|
||||
import json
|
||||
import copy
|
||||
import math
|
||||
import logging as lg
|
||||
lg.basicConfig(level=lg.DEBUG)
|
||||
|
||||
def parse(input, format, **kwargs):
|
||||
fullPath = input
|
||||
|
@ -45,6 +48,13 @@ def parse(input, format, **kwargs):
|
|||
return schematic
|
||||
|
||||
def determine_hierarchy(schematic):
|
||||
"""Convert a dict containing a flat list of records
|
||||
into a dict of records in a hierarchy
|
||||
|
||||
:param schematic: dict with 'header' and 'records' populated
|
||||
:return: the input dict with 'records' assembled into parent/child hierarchy
|
||||
"""
|
||||
|
||||
# prep a scratchpad copy of records to build hierarchy from
|
||||
records_copy = copy.deepcopy(schematic["records"])
|
||||
schematic["hierarchy"] = []
|
||||
|
@ -75,9 +85,144 @@ def determine_parts_list(schematic):
|
|||
return parts_list
|
||||
|
||||
def determine_net_list(schematic):
|
||||
print('NOT IMPLEMENTED')
|
||||
_, wires = find_record(schematic, key="RECORD", value="27")
|
||||
_, pins = find_record(schematic, key="RECORD", value="2")
|
||||
_, labels = find_record(schematic, key="RECORD", value="25")
|
||||
_, power_ports = find_record(schematic, key="RECORD", value="17")
|
||||
devices = wires + pins + labels + power_ports
|
||||
|
||||
p = re.compile('^(?P<prefix>X)(?P<index>\d+)$')
|
||||
for device in devices:
|
||||
# if a Pin, do some fancy geometry math
|
||||
if device["RECORD"] == "2":
|
||||
rotation = (int(device["PINCONGLOMERATE"]) & 0x03) * 90
|
||||
device['coords'] = [[
|
||||
int(int(device['LOCATION.X']) + math.cos(rotation / 180 * math.pi) * int(device['PINLENGTH'])),
|
||||
int(int(device['LOCATION.Y']) + math.sin(rotation / 180 * math.pi) * int(device['PINLENGTH']))
|
||||
]]
|
||||
# if a Wire, follow inconsistent location key names (X1 vs LOCATION.X, etc..)
|
||||
elif device["RECORD"] == "27":
|
||||
coord_name_matches = [x for x in [p.match(key) for key in device.keys()] if x]
|
||||
device['coords'] = [ ( int(device['X' + match.group('index')]) , int(device['Y' + match.group('index')]) )
|
||||
for match in coord_name_matches ]
|
||||
# everything else, just convert the location values to ints
|
||||
else:
|
||||
device['coords'] = [(int(device['LOCATION.X']), int(device['LOCATION.Y']))]
|
||||
|
||||
nets = []
|
||||
for device in devices:
|
||||
if device["index"] not in [d['index'] for net in nets for d in net['devices']]:
|
||||
net = {'name': None,
|
||||
'devices': find_connected_wires(device, devices, [], schematic)}
|
||||
nets.append(net)
|
||||
|
||||
for net in nets:
|
||||
net['devices'].sort(key=lambda k: k['index'])
|
||||
if not net['name']:
|
||||
net['name'] = next(iter(d['TEXT'] for d in net['devices'] if ((d['RECORD'] == '17') or (d['RECORD'] == '25'))), None)
|
||||
|
||||
if not net['name']:
|
||||
naming_pin = next(iter(d for d in net['devices'] if d['RECORD'] == '2'), None)
|
||||
parent = next(iter(find_record(schematic, key="index", value=int(naming_pin['OWNERINDEX']))[1]), None) if naming_pin else None
|
||||
net['name'] = next(iter('Net' + r['TEXT'] for r in parent['children'] if (r['RECORD'] == '34')), None) if parent else None
|
||||
|
||||
schematic["nets"] = nets
|
||||
|
||||
return schematic
|
||||
|
||||
def find_record(schematic, key, value, record=None, visited=None, found=None):
|
||||
lg.debug("finding records where: {0} = {1}".format(key, value))
|
||||
|
||||
if visited == None:
|
||||
visited = []
|
||||
if found == None:
|
||||
found = []
|
||||
if record == None:
|
||||
for record in schematic['records']:
|
||||
visited, found = find_record(schematic, key, value, record=record, visited=visited, found=found)
|
||||
else:
|
||||
if record['index'] not in [r['index'] for r in visited]:
|
||||
visited.append(record)
|
||||
|
||||
if key in record.keys():
|
||||
if record[key] == value:
|
||||
found.append(record)
|
||||
|
||||
if "children" in record.keys():
|
||||
for child_record in record["children"]:
|
||||
visited, found = find_record(schematic, key, value, record=child_record, visited=visited, found=found)
|
||||
|
||||
return visited, found
|
||||
|
||||
def find_connected_wires(wire, devices, visited, schematic):
|
||||
neighbors = find_neighbors(wire, devices, schematic)
|
||||
lg.debug('entering: {0}'.format(wire['index']))
|
||||
|
||||
if wire['index'] not in [w['index'] for w in visited]:
|
||||
lg.debug('adding: {0} to {1}'.format(wire['index'], [w['index'] for w in visited]))
|
||||
visited.append(wire)
|
||||
|
||||
for neighbor in neighbors:
|
||||
lg.debug('trying: {0} of {1}'.format(neighbor['index'], [x['index'] for x in neighbors]))
|
||||
visited = find_connected_wires(neighbor, devices, visited, schematic)
|
||||
lg.debug('visited = {0}'.format([w['index'] for w in visited]))
|
||||
else:
|
||||
lg.debug('skipping: {0} already in list {1}'.format(wire['index'], [w['index'] for w in visited]))
|
||||
|
||||
lg.debug('returning: {0}'.format(wire['index']))
|
||||
return visited
|
||||
|
||||
def find_neighbors(wire, devices, schematic):
|
||||
all_wires = devices
|
||||
other_wires = [record for record in all_wires if record != wire]
|
||||
|
||||
neighbors = []
|
||||
for other_wire in other_wires:
|
||||
if is_connected(wire, other_wire):
|
||||
neighbors.append(other_wire)
|
||||
|
||||
return neighbors
|
||||
|
||||
def is_connected(wire_a, wire_b):
|
||||
|
||||
if wire_a["RECORD"] == "27":
|
||||
a_line_segments = [(wire_a['coords'][i], wire_a['coords'][i + 1]) for i in
|
||||
range(len(wire_a['coords']) - 1)]
|
||||
else:
|
||||
a_line_segments = [(wire_a['coords'][0], wire_a['coords'][0])]
|
||||
|
||||
if wire_b["RECORD"] == "27":
|
||||
b_line_segments = [(wire_b['coords'][i], wire_b['coords'][i + 1]) for i in
|
||||
range(len(wire_b['coords']) - 1)]
|
||||
else:
|
||||
b_line_segments = [(wire_b['coords'][0], wire_b['coords'][0])]
|
||||
|
||||
# check if any vertices in wire_a lie on wire_b
|
||||
for vertex in [vx for line in a_line_segments for vx in line]:
|
||||
for b_line in b_line_segments:
|
||||
b_xs = sorted(list(zip(*b_line))[0])
|
||||
b_ys = sorted(list(zip(*b_line))[1])
|
||||
|
||||
if ((min(b_xs) <= vertex[0] <= max(b_xs))
|
||||
and (min(b_ys) <= vertex[1] <= max(b_ys))):
|
||||
return True
|
||||
|
||||
# check if any vertices in wire_b lie on wire_a
|
||||
for vertex in [vx for line in b_line_segments for vx in line]:
|
||||
for a_line in a_line_segments:
|
||||
a_xs = sorted(list(zip(*a_line))[0])
|
||||
a_ys = sorted(list(zip(*a_line))[1])
|
||||
|
||||
if ((min(a_xs) <= vertex[0] <= max(a_xs))
|
||||
and (min(a_ys) <= vertex[1] <= max(a_ys))):
|
||||
return True
|
||||
|
||||
# check if both items are Power Ports with the same TEXT value
|
||||
if ( wire_a["RECORD"] == "17" ) and ( wire_b["RECORD"] == "17" ) and ( wire_a["TEXT"] == wire_b["TEXT"] ):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def main(args):
|
||||
schematic = parse(**vars(args))
|
||||
|
||||
|
|
Loading…
Reference in New Issue