示例#1
0
def positionFormater(element):
    if type(element) == type({}):
        if(not {"posx", "posy"}.issubset(element.keys())):
            raise Exception("missing keys 'posx' and 'posy' in"+str(element))
        return "@ ({0}, {1})".format(mm_to_mil(element['posx']), mm_to_mil(element['posy']))
    if 'posx' in element.__dict__ and 'posy' in element.__dict__:
        return "@ ({0}, {1})".format(mm_to_mil(element.posx), mm_to_mil(element.posy))
    raise Exception("input type: ", type(element), "not supported, ", element)
示例#2
0
def pinString(pin: Pin, loc: bool = True, unit=None, convert=None) -> str:
    return "Pin {name} ({num}){loc}{unit}".format(
        name=pin.name,
        num=pin.number,
        loc=" @ ({x},{y})".format(x=mm_to_mil(pin.posx), y=mm_to_mil(pin.posy))
        if loc
        else "",
        unit=" in unit {n}".format(n=pin.unit) if unit else "",
    )
示例#3
0
def positionFormater(element) -> str:
    if isinstance(element, dict):
        if not {"posx", "posy"}.issubset(element.keys()):
            raise Exception("missing keys 'posx' and 'posy' in" + str(element))
        return "@ ({0}, {1})".format(
            mm_to_mil(element["posx"]), mm_to_mil(element["posy"])
        )
    if hasattr(element, "posx") and hasattr(element, "posy"):
        return "@ ({0}, {1})".format(mm_to_mil(element.posx), mm_to_mil(element.posy))
    raise Exception("input type: ", type(element), "not supported, ", element)
示例#4
0
    def check(self) -> bool:
        """
        Proceeds the checking of the rule.
        The following variables will be accessible after checking:
            * center_rect_polyline
        """

        # no checks for power-symbols, graphical symbols or derived symbols
        if (self.component.is_power_symbol()
                or self.component.is_graphic_symbol()
                or self.component.extends is not None):
            return False

        # check if component has just one rectangle, if not, skip checking
        self.center_rect_polyline = self.component.get_center_rectangle(
            range(self.component.unit_count))
        if self.center_rect_polyline is None:
            return False

        rectangle_need_fix = False
        if self.component.is_small_component_heuristics():
            if not math.isclose(self.center_rect_polyline.stroke_width,
                                mil_to_mm(10)):
                self.warning(
                    "Component outline is thickness {0}mil, recommended is {1}mil for"
                    " standard symbol".format(
                        mm_to_mil(self.center_rect_polyline.stroke_width), 10))
                self.warningExtra(
                    "exceptions are allowed for small symbols like resistor,"
                    " transistor, ...")
                rectangle_need_fix = False
        else:
            if not math.isclose(self.center_rect_polyline.stroke_width,
                                mil_to_mm(10)):
                self.error(
                    "Component outline is thickness {0}mil, recommended is {1}mil"
                    .format(mm_to_mil(self.center_rect_polyline.stroke_width),
                            10))
                rectangle_need_fix = True

        if self.center_rect_polyline.fill_type != "background":
            msg = (
                "Component background is filled with {0} color, recommended is filling"
                " with {1} color".format(self.center_rect_polyline.fill_type,
                                         "background"))
            if self.component.is_small_component_heuristics():
                self.warning(msg)
                self.warningExtra(
                    "exceptions are allowed for small symbols like resistor,"
                    " transistor, ...")
            else:
                self.error(msg)
                rectangle_need_fix = True

        return rectangle_need_fix
示例#5
0
    def check(self) -> bool:
        """
        Calculate the 'bounds' of the symbol based on rectangle (if only a
        single filled rectangle is present) or on pin positions.
        """

        # no need to check this for an
        if self.component.extends is not None:
            return False

        # Check units separately
        unit_count = self.component.unit_count

        for unit in range(1, unit_count + 1):
            # If there is only a single filled rectangle, we assume that it is the
            # main symbol outline.
            center_pl = self.component.get_center_rectangle([0, unit])
            if center_pl is not None:
                (x, y) = center_pl.get_center_of_boundingbox()
            else:
                pins = [pin for pin in self.component.pins if (pin.unit in [unit, 0])]

                # No pins? Ignore check.
                # This can be improved to include graphical items too...
                if not pins:
                    continue
                x_pos = [pin.posx for pin in pins]
                y_pos = [pin.posy for pin in pins]
                x_min = min(x_pos)
                x_max = max(x_pos)
                y_min = min(y_pos)
                y_max = max(y_pos)

                # Center point average
                x = (x_min + x_max) / 2
                y = (y_min + y_max) / 2

            # convert to mil
            x = mm_to_mil(x)
            y = mm_to_mil(y)
            # Right on the middle!
            if x == 0 and y == 0:
                continue
            elif math.fabs(x) <= 50 and math.fabs(y) <= 50:
                self.warning("Symbol unit {unit} slightly off-center".format(unit=unit))
                self.warningExtra("  Center calculated @ ({x}, {y})".format(x=x, y=y))
            else:
                self.error(
                    "Symbol unit {unit} not centered on origin".format(unit=unit)
                )
                self.errorExtra("Center calculated @ ({x}, {y})".format(x=x, y=y))

        return False
示例#6
0
    def check(self) -> bool:
        """
        Proceeds the checking of the rule.
        The following variables will be accessible after checking:
            * violating_pins
            * violating_properties
        """

        self.violating_properties = []
        for prop in self.component.properties:
            text_size = mm_to_mil(prop.effects.sizex)
            if text_size != 50:
                self.violating_properties.append(prop)
                message = "{0} at posx {1} posy {2}".format(
                    prop.name, mm_to_mil(prop.posx), mm_to_mil(prop.posy))
                self.error(" - Field {0} size {1}".format(message, text_size))

        self.violating_pins = []
        """
        Pin number MUST be 50mils
        Pin name must be between 20mils and 50mils
        Pin name should be 50mils
        """

        for pin in self.component.pins:
            name_text_size = mm_to_mil(pin.name_effect.sizex)
            num_text_size = mm_to_mil(pin.number_effect.sizex)

            if ((name_text_size < 20) or (name_text_size > 50)
                    or (num_text_size < 20) or (num_text_size > 50)):
                self.violating_pins.append(pin)
                self.error(
                    " - Pin {0} ({1}), text size {2}, number size {3}".format(
                        pin.name, pin.number, name_text_size, num_text_size))
            else:
                if name_text_size != 50:
                    self.warning(
                        "Pin {0} ({1}) name text size should be 50mils (or 20...50mils"
                        " if required by the symbol geometry)".format(
                            pin.name, pin.number))
                if num_text_size != 50:
                    self.warning(
                        "Pin {0} ({1}) number text size should be 50mils (or"
                        " 20...50mils if required by the symbol geometry)".
                        format(pin.name, pin.number))

        if self.violating_properties or self.violating_pins:
            return True

        return False
示例#7
0
    def checkPinOrigin(self, gridspacing: int = 100) -> bool:
        self.violating_pins = []
        err = False
        for pin in self.component.pins:
            posx = mm_to_mil(pin.posx)
            posy = mm_to_mil(pin.posy)
            if (posx % gridspacing) != 0 or (posy % gridspacing) != 0:
                self.violating_pins.append(pin)
                if not err:
                    self.error(
                        "Pins not located on {0}mil (={1:.3}mm) grid:".format(
                            gridspacing, gridspacing * 0.0254))
                self.error(" - {0} ".format(pinString(pin, loc=True)))
                err = True

        return len(self.violating_pins) > 0
示例#8
0
    def checkPinLength(self,
                       errorPinLength: int = 49,
                       warningPinLength: int = 99) -> bool:
        self.violating_pins = []

        for pin in self.component.pins:
            length = mm_to_mil(pin.length)

            err = False

            # ignore zero-length pins e.g. hidden power pins
            if length == 0:
                continue

            if length <= errorPinLength:
                self.error("{pin} length ({len}mils) is below {pl}mils".format(
                    pin=pinString(pin), len=length, pl=errorPinLength + 1))
            elif length <= warningPinLength:
                self.warning(
                    "{pin} length ({len}mils) is below {pl}mils".format(
                        pin=pinString(pin),
                        len=length,
                        pl=warningPinLength + 1))

            if length % 50 != 0:
                self.warning(
                    "{pin} length ({len}mils) is not a multiple of 50mils".
                    format(pin=pinString(pin), len=length))

            # length too long flags a warning
            if length > 300:
                err = True
                self.error(
                    "{pin} length ({length}mils) is longer than maximum (300mils)"
                    .format(pin=pinString(pin), length=length))

            if err:
                self.violating_pins.append(pin)

        return len(self.violating_pins) > 0
示例#9
0
def copy_icon_v5(dest_comp,
                 src_comp,
                 dest_unit,
                 offset,
                 variant=1,
                 src_unit=0,
                 src_variant=1,
                 style=None):

    # TODO: source unit
    # pensize, fill?

    if type(src_comp) == Component:
        for p in src_comp.draw['arcs']:
            # TODO apply offset pos
            item = dict(p)
            if item['convert'] == str(src_variant) or item['convert'] == '0':
                item['unit'] = str(dest_unit)
                item['convert'] = str(variant)
                item['posy'] = str(int(item['posy']) + offset.y)
                item['starty'] = str(int(item['starty']) + offset.y)
                item['endy'] = str(int(item['endy']) + offset.y)
                item['fill'] = get_fill(item['fill'], style)
                dest_comp.drawOrdered.append(['A', item])

        for p in src_comp.draw['circles']:
            item = copy.deepcopy(p)
            if item['convert'] == str(src_variant) or item['convert'] == '0':
                item['unit'] = str(dest_unit)
                item['convert'] = str(variant)
                item['posy'] = str(int(item['posy']) + offset.y)
                item['fill'] = get_fill(item['fill'], style)
                dest_comp.drawOrdered.append(['C', item])

        for p in src_comp.draw['polylines']:
            item = dict(p)
            if item['convert'] == str(src_variant) or item['convert'] == '0':
                poly = PolyLine(convert_to_string(['P', p]))
                poly.unit = dest_unit
                poly.demorgan = variant
                poly.fill = get_fill(item['fill'], style)
                poly.pensize = item['thickness']
                for pt in poly.points:
                    pt.x += offset.x
                    pt.y += offset.y
                dest_comp.drawOrdered.append(poly.get_element())

        for p in src_comp.draw['rectangles']:
            # TODO apply offset pos
            item = dict(p)
            if item['convert'] == str(src_variant) or item['convert'] == '0':
                rect = Rect()
                rect.unit = dest_unit
                rect.demorgan = variant
                rect.fill = get_fill(item['fill'], style)
                rect.p1 = Point(int(item['startx']),
                                int(item['starty'])).Add(offset)
                rect.p2 = Point(int(item['endx']),
                                int(item['endy'])).Add(offset)
                dest_comp.drawOrdered.append(rect.get_element())

        for p in src_comp.draw['texts']:
            item = copy.deepcopy(p)
            if item['convert'] == str(src_variant) or item['convert'] == '0':
                item['unit'] = str(dest_unit)
                item['convert'] = str(variant)
                item['posy'] = str(int(item['posy']) + offset.y)
                dest_comp.drawOrdered.append(['T', item])

    elif type(src_comp) == kicad_sym.KicadSymbol:
        for p in src_comp.arcs:
            if p.demorgan == src_variant or p.demorgan == 0:
                item = {}
                item['unit'] = str(dest_unit)
                item['convert'] = str(variant)
                item['posx'] = str(kicad_sym.mm_to_mil(p.centerx))
                item['posy'] = str(kicad_sym.mm_to_mil(p.centery))
                item['radius'] = str(kicad_sym.mm_to_mil(p.length))
                item['start_angle'] = str(math.floor(p.angle_start * 10.0))
                item['end_angle'] = str(math.floor(p.angle_stop * 10.0))
                item['startx'] = str(kicad_sym.mm_to_mil(p.startx))
                item['starty'] = str(kicad_sym.mm_to_mil(p.starty))
                item['endx'] = str(kicad_sym.mm_to_mil(p.endx))
                item['endy'] = str(kicad_sym.mm_to_mil(p.endy))
                item['thickness'] = str(kicad_sym.mm_to_mil(p.stroke_width))
                item['fill'] = sweet.convert_fill_to_v5(p.fill_type)

                item['posy'] = str(int(item['posy']) + offset.y)
                item['starty'] = str(int(item['starty']) + offset.y)
                item['endy'] = str(int(item['endy']) + offset.y)
                item['fill'] = get_fill(item['fill'], style)
                dest_comp.drawOrdered.append(['A', item])

        for p in src_comp.circles:
            if p.demorgan == src_variant or p.demorgan == 0:
                item = {}
                item['unit'] = str(dest_unit)
                item['convert'] = str(variant)
                item['posx'] = str(kicad_sym.mm_to_mil(p.centerx))
                item['posy'] = str(kicad_sym.mm_to_mil(p.centery))
                item['radius'] = str(kicad_sym.mm_to_mil(p.radius))
                item['thickness'] = str(kicad_sym.mm_to_mil(p.stroke_width))
                item['fill'] = sweet.convert_fill_to_v5(p.fill_type)

                item['posy'] = str(int(item['posy']) + offset.y)
                item['fill'] = get_fill(item['fill'], style)
                dest_comp.drawOrdered.append(['C', item])

        for p in src_comp.polylines:
            if p.demorgan == src_variant or p.demorgan == 0:

                poly = PolyLine()
                poly.unit = dest_unit
                poly.demorgan = variant
                poly.fill = sweet.convert_fill_to_v5(p.fill_type)
                poly.fill = get_fill(poly.fill, style)
                poly.pensize = kicad_sym.mm_to_mil(p.stroke_width)
                for pt in p.points:
                    mil_p = sym_utils_v6.point_to_mil(pt)
                    poly.points.append(mil_p.Add(offset))

                dest_comp.drawOrdered.append(poly.get_element())

        for p in src_comp.rectangles:
            # TODO apply offset
            if p.demorgan == src_variant or p.demorgan == 0:
                rect = Rect()
                rect.unit = dest_unit
                rect.demorgan = variant
                rect.fill = sweet.convert_fill_to_v5(p.fill_type)
                rect.fill = get_fill(rect.fill, style)
                rect.pensize = kicad_sym.mm_to_mil(p.stroke_width)
                rect.p1 = sym_utils_v6.point_to_mil(Point(
                    p.startx, p.starty)).Add(offset)
                rect.p2 = sym_utils_v6.point_to_mil(Point(p.endx,
                                                          p.endy)).Add(offset)
                dest_comp.drawOrdered.append(rect.get_element())

        for p in src_comp.texts:
            if p.demorgan == src_variant or p.demorgan == 0:
                item = {}
                item['unit'] = str(dest_unit)
                item['convert'] = str(variant)
                item['posx'] = str(kicad_sym.mm_to_mil(p.posx))
                item['posy'] = str(kicad_sym.mm_to_mil(p.posy))
                item['direction'] = str(math.floor(p.rotation * 10.0))

                item['text_size'] = str(kicad_sym.mm_to_mil(p.effects.sizex))
                item[
                    'hjustify'] = "L" if p.effects.h_justify == "left" else "C"
                item[
                    'vjustify'] = "B" if p.effects.v_justify == "bottom" else "C"
                item['bold'] = "1" if p.effects.is_bold else "0"
                item['italic'] = "Italic" if p.effects.is_italic else "Normal"
                item['text_type'] = "1" if p.effects.is_hidden else "0"

                item['text'] = p.text

                item['posy'] = str(int(item['posy']) + offset.y)
                dest_comp.drawOrdered.append(['T', item])
示例#10
0
def pinString(pin, loc=True, unit=None, convert=None):
    return "Pin {name} ({num}){loc}{unit}".format(
        name=pin.name,
        num=pin.number,
        loc=' @ ({x},{y})'.format(x=mm_to_mil(pin.posx), y=mm_to_mil(pin.posy)) if loc else '',
        unit=' in unit {n}'.format(n=pin.unit) if unit else '')