def test_get_pin_line(self): """ The get_pin_line returns the correct string for a kicad pin. """ writer = KiCAD() pin = Pin('1', (-300, 100), (-600, 100)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 1 -6667 1111 3333 R 60 60 %(unit)d %(convert)d B\n') pin = Pin('1', (300, 100), (600, 100)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 1 6667 1111 3333 L 60 60 %(unit)d %(convert)d B\n') pin = Pin('2', (0, -1300), (0, -1500)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 2 0 -16667 2222 U 60 60 %(unit)d %(convert)d B\n') pin = Pin('2', (0, 1300), (0, 1500)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 2 0 16667 2222 D 60 60 %(unit)d %(convert)d B\n') pin = Pin('2', (0, 1300), (0, 1500), Label(0, 0, 'name', 'center', 0)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X name 2 0 16667 2222 D 60 60 %(unit)d %(convert)d B\n')
def test_pin_bounds(self): '''Test bounds() for individual pins''' pin = Pin(0, Point(2, 5), Point(4, 3)) top_left, bottom_right = pin.bounds() self.assertEqual(top_left.x, 2) self.assertEqual(top_left.y, 3) self.assertEqual(bottom_right.x, 4) self.assertEqual(bottom_right.y, 5)
def parse_pin(self, pin): """ Extract a pin of a body. """ pin_number = pin.get('pin_number') p1 = self.parse_point(pin.get('p1')) p2 = self.parse_point(pin.get('p2')) parsed_pin = Pin(pin_number, p1, p2) if pin.get('label') is not None: parsed_pin.label = self.parse_label(pin.get('label')) parsed_pin.styles = pin.get('styles') or {} return parsed_pin
def parse_pin(self, pin): """ Extract a pin of a body. """ pin_number = pin.get("pin_number") p1 = self.parse_point(pin.get("p1")) p2 = self.parse_point(pin.get("p2")) parsed_pin = Pin(pin_number, p1, p2) if pin.get("label") is not None: parsed_pin.label = self.parse_label(pin.get("label")) parsed_pin.styles = pin.get("styles") or {} return parsed_pin
def test_pin_label_bounds(self): '''Test bounds() for a pin with a label''' lab = Label(0, 0, 'foo', align='left', rotation=0) mkbounds(lab, 1, 3, 2, 6) pin = Pin(0, Point(2, 2), Point(4, 3), lab) top_left, bottom_right = pin.bounds() self.assertEqual(top_left.x, 1) self.assertEqual(top_left.y, 2) self.assertEqual(bottom_right.x, 4) self.assertEqual(bottom_right.y, 6)
def parse_pin(self, args): """ Returns a parsed pin. """ # Pin declaration, seems to only be done once per pin pid, x1, y1, x0, y0, _rot, _side, _inv = [int(a) for a in args.split()] # _rot and _side are not needed, because the x-y data tells us what we # need to know. _inv is used to draw the little inverted signal cirles. thispin = Pin(pid, (x0, y0), (x1, y1)) subdata = self.sub_nodes(['L']) if len(subdata['label']) > 0: # I suppose if there's more than one label, just go with the first thispin.label = subdata['label'][0] return ('pin', thispin)
def parse_pin(self, args): """ Returns a parsed pin. """ # Pin declaration, seems to only be done once per pin pid, xe, ye, xb, yb, rot, side, inv = [int(a) for a in args.split()] thispin = Pin(pid, (xb, yb), (xe, ye)) subdata = defaultdict(list) for phrase in self.stream: cmd, _sep, args = phrase.partition(' ') if cmd not in ('L'): self.stream.push(phrase) break k, v = self.parsenode(cmd)(args) subdata[k].append(v) if len(subdata['label']) > 0: # I suppose if there's more than one label, just go with the first thispin.label = subdata['label'][0] return ('pin', thispin)
def test_get_pin_line(self): """ The get_pin_line returns the correct string for a kicad pin. """ writer = KiCAD() pin = Pin('1', (-300, 100), (-600, 100)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 1 ' + str(int(-600 / MULT)) + ' ' + str(int(100 / MULT)) + ' ' + str(int(300 / MULT)) + ' ' + 'R 60 60 %(unit)d %(convert)d B\n') pin = Pin('1', (300, 100), (600, 100)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 1 ' + str(int(600 / MULT)) + ' ' + str(int(100 / MULT)) + ' ' + str(int(300 / MULT)) + ' ' + 'L 60 60 %(unit)d %(convert)d B\n') pin = Pin('2', (0, -1300), (0, -1500)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 2 0 ' + str(int(-1500 / MULT)) + ' ' + str(int(200 / MULT)) + ' U 60 60 %(unit)d %(convert)d B\n') pin = Pin('2', (0, 1300), (0, 1500)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X ~ 2 0 ' + str(int(1500 / MULT)) + ' ' + str(int(200 / MULT)) + ' D 60 60 %(unit)d %(convert)d B\n') pin = Pin('2', (0, 1300), (0, 1500), Label(0, 0, 'name', align='center', rotation=0)) line = writer.get_pin_line(pin) self.assertEqual( line, 'X name 2 0 ' + str(int(1500 / MULT)) + ' ' + str(int(200 / MULT)) + ' D 60 60 %(unit)d %(convert)d B\n')
def test_create_new_pin(self): """ Test the creation of a new empty pin. """ p1 = Point(0, 1) p2 = Point(2, 3) pin = Pin(0, p1, p2, 'abc') assert pin.label == 'abc' assert pin.p1.x == p1.x assert pin.p1.y == p1.y assert pin.p2.x == p2.x assert pin.p2.y == p2.y assert pin.pin_number == 0
def get_pin(shape): """ Return a Pin for the given shape, or None """ if shape.type == 'rectangle': x = shape.x + shape.width / 2 y = shape.y + shape.height / 2 elif shape.type == 'circle': x, y = shape.x, shape.y else: return None return Pin('', (x, y), (x, y))
def test_bounds_pins_shapes(self): '''Test SBody.bounds() when some extremes are from pins, others shapes''' point = Point(0, 0) pin1 = Pin('foo', point, point) pin2 = Pin('bar', point, point) sh1 = Shape() sh2 = Shape() mkbounds(pin1, 3, 2, 3, 3) mkbounds(pin2, 3, 3, 5, 3) mkbounds(sh1, 3, 3, 3, 4) mkbounds(sh2, 1, 3, 3, 3) self.bod.add_pin(pin1) self.bod.add_pin(pin2) self.bod.add_shape(sh1) self.bod.add_shape(sh2) top_left, bottom_right = self.bod.bounds() self.assertEqual(top_left.x, 1) self.assertEqual(top_left.y, 2) self.assertEqual(bottom_right.x, 5) self.assertEqual(bottom_right.y, 4)
def test_bounds_pins(self): '''Test bounds() with just pins included''' pins = [Pin(str(i), Point(0, 0), Point(0, 0)) for i in range(4)] # checking body.bounds(), not the pins, so override their bounds() # methods for i, pin in enumerate(pins): bounds = [3, 3, 3, 3] bounds[i] = 2 * i mkbounds(pin, bounds[0], bounds[1], bounds[2], bounds[3]) self.bod.add_pin(pin) top_left, bottom_right = self.bod.bounds() self.assertEqual(top_left.x, 0) self.assertEqual(top_left.y, 2) self.assertEqual(bottom_right.x, 4) self.assertEqual(bottom_right.y, 6)
def make_body_from_symbol(self, lib, symbol_name): """ Construct an openjson Body from an eagle symbol in a library. """ body = Body() symbol = [ s for s in get_subattr(lib, 'symbols.symbol') if s.name == symbol_name ][0] for wire in symbol.wire: body.add_shape( Line((self.make_length(wire.x1), self.make_length(wire.y1)), (self.make_length(wire.x2), self.make_length(wire.y2)))) for rect in symbol.rectangle: x = self.make_length(rect.x1) y = self.make_length(rect.y1) width = self.make_length(rect.x2) - x height = self.make_length(rect.y2) - y body.add_shape(Rectangle(x, y + height, width, height)) pin_map = {} for pin in symbol.pin: connect_point = (self.make_length(pin.x), self.make_length(pin.y)) null_point = self.get_pin_null_point(connect_point, pin.length, pin.rot) label = self.get_pin_label(pin, null_point) pin_map[pin.name] = Pin(pin.name, null_point, connect_point, label) body.add_pin(pin_map[pin.name]) ann_map = {} for text in symbol.text: x = self.make_length(text.x) y = self.make_length(text.y) content = '' if text.valueOf_ is None else text.valueOf_ rotation = self.make_angle('0' if text.rot is None else text.rot) if content == '>NAME': ann_map['name'] = Annotation(content, x, y, rotation, 'true') elif content == '>VALUE': ann_map['value'] = Annotation(content, x, y, rotation, 'true') else: body.add_shape(Label(x, y, content, 'left', rotation)) return body, pin_map, ann_map
def parse_x_line(self, parts): """ Parse an X (Pin) line """ name, num, direction = parts[1], parts[2], parts[6] p2x, p2y, pinlen = int(parts[3]), int(parts[4]), int(parts[5]) if direction == 'U': # up p1x = p2x p1y = p2y + pinlen label_x = p2x - 20 label_y = p2y + int(pinlen / 2) label_rotation = 1.5 elif direction == 'D': # down p1x = p2x p1y = p2y - pinlen label_x = p2x - 20 label_y = p2y - int(pinlen / 2) label_rotation = 1.5 elif direction == 'L': # left p1x = p2x - pinlen p1y = p2y label_x = p2x - int(pinlen / 2) label_y = p2y + 20 label_rotation = 0 elif direction == 'R': # right p1x = p2x + pinlen p1y = p2y label_x = p2x + int(pinlen / 2) label_y = p2y + 20 label_rotation = 0 else: raise ValueError('unexpected pin direction', direction) if name == '~': label = None else: label = Label(label_x, label_y, name, align='center', rotation=label_rotation) return Pin(num, (p1x, p1y), (p2x, p2y), label)
def _convert_library(self, struct): for image in struct.library.image: component = Component(image.image_id) self.design.add_component(image.image_id, component) sym = Symbol() body = Body() component.add_symbol(sym) sym.add_body(body) for pin in image.pin: body.add_pin( Pin(pin.pin_id, self.to_pixels(pin.vertex), self.to_pixels(pin.vertex))) for padstack in struct.library.padstack: if padstack.padstack_id == pin.padstack_id: shapes = [shape.shape for shape in padstack.shape] for shape in self._convert_shapes( shapes, self.to_pixels(pin.vertex)): body.add_shape(shape) break for outline in image.outline: for shape in self._convert_shapes([outline.shape]): body.add_shape(shape)
def make_body_from_symbol(self, lib, symbol_name, pin_number_lookup): """ Construct an openjson SBody from an eagle symbol in a library. """ body = SBody() symbol = [ s for s in get_subattr(lib, 'symbols.symbol') if s.name == symbol_name ][0] for wire in symbol.wire: body.add_shape(self.make_shape_for_wire(wire)) for rect in symbol.rectangle: rotation = make_angle('0' if rect.rot is None else rect.rot) x1, y1 = rotate_point( (self.make_length(rect.x1), self.make_length(rect.y1)), rotation) x2, y2 = rotate_point( (self.make_length(rect.x2), self.make_length(rect.y2)), rotation) ux, uy = min(x1, x2), max(y1, y2) lx, ly = max(x1, x2), min(y1, y2) body.add_shape(Rectangle(ux, uy, lx - ux, uy - ly)) for poly in symbol.polygon: map(body.add_shape, self.make_shapes_for_poly(poly)) for circ in symbol.circle: body.add_shape(self.make_shape_for_circle(circ)) pin_map = {} for pin in symbol.pin: connect_point = (self.make_length(pin.x), self.make_length(pin.y)) null_point = self.get_pin_null_point(connect_point, pin.length, pin.rot) label = self.get_pin_label(pin, null_point) pin_map[pin.name] = Pin(pin_number_lookup(pin.name), null_point, connect_point, label) if pin.direction: pin_map[pin.name].add_attribute('eaglexml_direction', pin.direction) if pin.visible: pin_map[pin.name].add_attribute('eaglexml_visible', pin.visible) body.add_pin(pin_map[pin.name]) ann_map = {} for text in symbol.text: x = self.make_length(text.x) y = self.make_length(text.y) content = '' if text.valueOf_ is None else text.valueOf_ rotation = make_angle('0' if text.rot is None else text.rot) align = 'right' if is_mirrored(text.rot) else 'left' if rotation == 0.5: rotation = 1.5 if content.lower() == '>name': ann_map['name'] = Annotation(content, x, y, rotation, 'true') elif content.lower() == '>value': ann_map['value'] = Annotation(content, x, y, rotation, 'true') else: body.add_shape( Label(x, y, content, align=align, rotation=rotation)) return body, pin_map, ann_map