Ejemplo n.º 1
0
def convert(pcb, brd):
    IU_PER_MM = PCB_IU_PER_MM = 1e6
    IU_PER_MILS = (IU_PER_MM * 0.0254)

    conv_unit_inch = 0.001 / IU_PER_MILS
    conv_unit_mm = 1.0 / IU_PER_MM

    units = pcbnew.GetUserUnits()

    # TODO: select units from board somehow
    conv_unit = conv_unit_mm

    # Board outline
    outlines = pcbnew.SHAPE_POLY_SET()
    pcb.GetBoardPolygonOutlines(outlines, "")
    outline = outlines.Outline(0)
    outline_points = [outline.Point(n) for n in range(outline.PointCount())]
    outline_maxx = max(map(lambda p: p.x, outline_points))
    outline_maxy = max(map(lambda p: p.y, outline_points))
    m_place_offset = pcb.GetDesignSettings().m_AuxOrigin

    # Parts
    module_list = pcb.GetModules()
    modules = []
    while module_list:
        if not skip_module(module_list):
            modules.append(module_list)
        module_list = module_list.Next()

    pin_at = 0

    writer = csv.writer(brd)
    # Logic taken from pcbnew/exporters/export_footprints_placefile.cpp
    # See https://gitlab.com/kicad/code/kicad/-/issues/2453
    for module in modules:
        footprint_pos = module.GetPosition()
        footprint_pos -= m_place_offset

        layer = module.GetLayer()
        if (layer not in (pcbnew.B_Cu, pcbnew.F_Cu)):
            continue

        if (layer == pcbnew.B_Cu):
            footprint_pos.x = -footprint_pos.x

        module_bbox = module.GetBoundingBox()
        writer.writerow([
            module.GetReference(),
            module.GetValue(),
            module.GetFPID().GetLibItemName(),
            round(footprint_pos.x * conv_unit, 4),
            round(-footprint_pos.y * conv_unit, 4),
            module.GetOrientation() / 10.0,
            "top" if layer == pcbnew.F_Cu else "bottom",
        ])

        pin_at += module.GetPadCount()
Ejemplo n.º 2
0
    def Run(self):
        print("WOT")
        # load board
        board = pcbnew.GetBoard()

        # get user units
        if pcbnew.GetUserUnits() == 1:
            user_units = 'mm'
        else:
            user_units = 'in'
        self.drc(board)
Ejemplo n.º 3
0
    def __init__(self, board):
        '''Initialize the brand new instance.'''

        super(ViaStitchingDialog, self).__init__(None)
        self.SetTitle(_(u"ViaStitching v{0}").format(__version__))
        self.Bind(wx.EVT_CLOSE, self.onCloseWindow)
        self.m_btnCancel.Bind(wx.EVT_BUTTON, self.onCloseWindow)
        self.m_btnOk.Bind(wx.EVT_BUTTON, self.onProcessAction)
        self.m_rClear.Bind(wx.EVT_RADIOBUTTON, self.onRadioButtonCheck)
        self.m_rFill.Bind(wx.EVT_RADIOBUTTON, self.onRadioButtonCheck)
        self.board = pcbnew.GetBoard()
        #Use the same unit set int PCBNEW
        self.ToUserUnit = None
        self.FromUserUnit = None
        units_mode = pcbnew.GetUserUnits()

        if units_mode == 0:
            self.ToUserUnit = pcbnew.ToMils
            self.FromUserUnit = pcbnew.FromMils
            self.m_lblUnit1.SetLabel(_(u"mils"))
            self.m_lblUnit2.SetLabel(_(u"mils"))
            self.m_txtVSpacing.SetValue("40")
            self.m_txtHSpacing.SetValue("40")
        elif units_mode == 1:
            self.ToUserUnit = pcbnew.ToMM
            self.FromUserUnit = pcbnew.FromMM
            self.m_lblUnit1.SetLabel(_(u"mm"))
            self.m_lblUnit2.SetLabel(_(u"mm"))
            self.m_txtVSpacing.SetValue("1")
            self.m_txtHSpacing.SetValue("1")
        elif units_mode == -1:
            wx.MessageBox(_(u"Not a valid frame"))
            self.Destroy()

        #Get default Vias dimensions
        via_dim_list = self.board.GetViasDimensionsList()
        via_dims = via_dim_list.pop()
        self.m_txtViaSize.SetValue("%.6f" % self.ToUserUnit(via_dims.m_Diameter))
        self.m_txtViaDrillSize.SetValue("%.6f" % self.ToUserUnit(via_dims.m_Drill))
        via_dim_list.push_back(via_dims)
        self.area = None
        self.net = None
        self.overlappings = None

        #Check for selected area
        if not self.GetAreaConfig():
            wx.MessageBox(_(u"Please select a valid area"))
            self.Destroy()
        else:
            #Get overlapping items
            self.GetOverlappingItems()
            #Populate nets checkbox
            self.PopulateNets() 
    def Run(self):
        # load board
        board = pcbnew.GetBoard()

        # get user units
        if pcbnew.GetUserUnits() == 1:
            user_units = 'mm'
        else:
            user_units = 'in'

        # go to the project folder - so that log will be in proper place
        os.chdir(os.path.dirname(os.path.abspath(board.GetFileName())))

        # set up logger
        logging.basicConfig(
            level=logging.DEBUG,
            filename="net2et distance.log",
            filemode='w',
            format='%(asctime)s %(name)s %(lineno)d:%(message)s',
            datefmt='%m-%d %H:%M:%S')
        logger = logging.getLogger(__name__)
        logger.info("Net2net distance plugin version: " + VERSION + " started")

        stdout_logger = logging.getLogger('STDOUT')
        sl_out = StreamToLogger(stdout_logger, logging.INFO)
        sys.stdout = sl_out

        stderr_logger = logging.getLogger('STDERR')
        sl_err = StreamToLogger(stderr_logger, logging.ERROR)
        sys.stderr = sl_err

        _pcbnew_frame = [
            x for x in wx.GetTopLevelWindows()
            if x.GetTitle().lower().startswith('pcbnew')
        ][0]

        # get all selected nets either as tracks or as pads
        nets = set()
        selected_tracks = [x for x in board.GetTracks() if x.IsSelected()]

        nets.update([track.GetNetname() for track in selected_tracks])

        modules = board.GetModules()
        for mod in modules:
            pads = mod.Pads()
            nets.update([pad.GetNetname() for pad in pads if pad.IsSelected()])

        # if two pads are selected
        if len(nets) != 2:
            # if more or less than one show only a messagebox
            caption = 'Net2Net Distance'
            message = "You have to select two and only two nets"
            dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                   wx.OK | wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        try:
            dis, loc = net2net_distance.get_min_distance(board, list(nets))
        except Exception:
            logger.exception("Fatal error when replicating")
            raise

        caption = 'Net2Net Track Distance'
        if user_units == 'mm':
            message = "Minimum distance between net segments is " + "%.3f" % (
                dis / SCALE) + " mm"
        else:
            message = "Minimum distance between net segments is " + "%.4f" % (
                dis / (SCALE * 25.4)) + " in"
        dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                               wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()
Ejemplo n.º 5
0
    def Run(self):
        # load board
        board = pcbnew.GetBoard()

        # get user units
        if pcbnew.GetUserUnits() == 1:
            user_units = 'mm'
        else:
            user_units = 'in'

        # go to the project folder - so that log will be in proper place
        os.chdir(os.path.dirname(os.path.abspath(board.GetFileName())))

        # Remove all handlers associated with the root logger object.
        for handler in logging.root.handlers[:]:
            logging.root.removeHandler(handler)

        # set up logger
        logging.basicConfig(
            level=logging.DEBUG,
            filename="place_footprints.log",
            filemode='w',
            format='%(asctime)s %(name)s %(lineno)d:%(message)s',
            datefmt='%m-%d %H:%M:%S')
        logger = logging.getLogger(__name__)
        logger.info("Place footprints plugin version: " + VERSION + " started")

        stdout_logger = logging.getLogger('STDOUT')
        sl_out = StreamToLogger(stdout_logger, logging.INFO)
        sys.stdout = sl_out

        stderr_logger = logging.getLogger('STDERR')
        sl_err = StreamToLogger(stderr_logger, logging.ERROR)
        sys.stderr = sl_err

        _pcbnew_frame = [
            x for x in wx.GetTopLevelWindows()
            if x.GetTitle().lower().startswith('pcbnew')
        ][0]

        # check if there is exactly one module selected
        selected_modules = [
            x for x in pcbnew.GetBoard().GetModules() if x.IsSelected()
        ]
        selected_names = []
        for mod in selected_modules:
            selected_names.append("{}".format(mod.GetReference()))

        # if more or less than one show only a messagebox
        if len(selected_names) != 1:
            caption = 'Place footprints'
            message = "More or less than 1 footprint selected. Please select exactly one footprint and run the script again"
            dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                   wx.OK | wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        # this it the reference footprint
        pivot_module_reference = selected_names[0]

        # ask user which way to select other footprints (by increasing reference number or by ID)
        dlg = InitialDialog(_pcbnew_frame)
        res = dlg.ShowModal()

        placer = place_footprints.Placer(board)

        pivot_module = placer.get_mod_by_ref(pivot_module_reference)

        # by reference number
        if res == wx.ID_OK:
            # by ref
            module_reference_designator = ''.join(
                i for i in pivot_module_reference if not i.isdigit())
            module_reference_number = int(''.join(
                i for i in pivot_module_reference if i.isdigit()))

            # get list of all modules with same reference designator
            list_of_all_modules_with_same_designator = placer.get_modules_with_reference_designator(
                module_reference_designator)
            sorted_list = natural_sort(
                list_of_all_modules_with_same_designator)

            # find only consequtive modules
            list_of_consecutive_modules = []
            # go through the list in positive direction
            start_index = sorted_list.index(pivot_module_reference)
            count_start = module_reference_number
            for mod in sorted_list[start_index:]:
                if int(''.join(i for i in mod if i.isdigit())) == count_start:
                    count_start = count_start + 1
                    list_of_consecutive_modules.append(mod)
                else:
                    break

            # go through the list in negative direction
            count_start = module_reference_number
            reversed_list = list(reversed(sorted_list))
            start_index = reversed_list.index(pivot_module_reference)
            for mod in reversed_list[start_index:]:
                if int(''.join(i for i in mod if i.isdigit())) == count_start:
                    count_start = count_start - 1
                    list_of_consecutive_modules.append(mod)
                else:
                    break

            sorted_modules = natural_sort(
                list(set(list_of_consecutive_modules)))

            # display dialog
            dlg = PlaceByReference(_pcbnew_frame, placer,
                                   pivot_module_reference, user_units)
            dlg.list_modules.AppendItems(sorted_modules)

            # highlight all modules by default
            for mod in sorted_modules:
                module = board.FindModuleByReference(mod)
                set_highlight_on_module(module)
            pcbnew.Refresh()

            # by default select all sheets
            number_of_items = dlg.list_modules.GetCount()
            for i in range(number_of_items):
                dlg.list_modules.Select(i)
            res = dlg.ShowModal()

            if res == wx.ID_CANCEL:
                # clear highlight all modules by default
                for mod in sorted_modules:
                    module = board.FindModuleByReference(mod)
                    clear_highlight_on_module(module)
                pcbnew.Refresh()
                return

            # get list of modules to place
            modules_to_place_indeces = dlg.list_modules.GetSelections()
            modules_to_place = natural_sort(
                [sorted_modules[i] for i in modules_to_place_indeces])
            # get mode
            if dlg.com_arr.GetStringSelection() == u'Circular':
                delta_angle = float(dlg.val_y_angle.GetValue())
                if user_units == 'mm':
                    radius = float(dlg.val_x_mag.GetValue())
                else:
                    radius = float(dlg.val_x_mag.GetValue()) / 25.4
                try:
                    placer.place_circular(modules_to_place,
                                          pivot_module_reference, radius,
                                          delta_angle, False)
                    logger.info("Placing complete")
                    logging.shutdown()
                except Exception:
                    logger.exception(
                        "Fatal error when executing place footprints")
                    caption = 'Place footprints'
                    message = "Fatal error when executing place footprints.\n"\
                            + "You can raise an issue on GiHub page.\n" \
                            + "Please attach the place_footprints.log which you should find in the project folder."
                    dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                           wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    logging.shutdown()
                    # clear highlight all modules by default
                    for mod in sorted_modules:
                        module = board.FindModuleByReference(mod)
                        clear_highlight_on_module(module)
                    pcbnew.Refresh()
                    return

            if dlg.com_arr.GetStringSelection() == u'Linear':
                if user_units == 'mm':
                    step_x = float(dlg.val_x_mag.GetValue())
                    step_y = float(dlg.val_y_angle.GetValue())
                else:
                    step_x = float(dlg.val_x_mag.GetValue()) / 25.4
                    step_y = float(dlg.val_y_angle.GetValue()) / 25.4
                try:
                    placer.place_linear(modules_to_place,
                                        pivot_module_reference, step_x, step_y)
                    logger.info("Placing complete")
                    logging.shutdown()
                except Exception:
                    logger.exception(
                        "Fatal error when executing place footprints")
                    caption = 'Place footprints'
                    message = "Fatal error when executing place footprints.\n"\
                            + "You can raise an issue on GiHub page.\n" \
                            + "Please attach the place_footprints.log which you should find in the project folder."
                    dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                           wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    logging.shutdown()
                    # clear highlight all modules by default
                    for mod in sorted_modules:
                        module = board.FindModuleByReference(mod)
                        clear_highlight_on_module(module)
                    pcbnew.Refresh()
                    return

            if dlg.com_arr.GetStringSelection() == u'Matrix':
                if user_units == 'mm':
                    step_x = float(dlg.val_x_mag.GetValue())
                    step_y = float(dlg.val_y_angle.GetValue())
                else:
                    step_x = float(dlg.val_x_mag.GetValue()) / 25.4
                    step_y = float(dlg.val_y_angle.GetValue()) / 25.4
                nr_columns = int(dlg.val_columns.GetValue())
                try:
                    placer.place_matrix(sorted_modules, step_x, step_y,
                                        nr_columns)
                    logger.info("Placing complete")
                    logging.shutdown()
                except Exception:
                    logger.exception(
                        "Fatal error when executing place footprints")
                    caption = 'Place footprints'
                    message = "Fatal error when executing place footprints.\n"\
                            + "You can raise an issue on GiHub page.\n" \
                            + "Please attach the place_footprints.log which you should find in the project folder."
                    dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                           wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    logging.shutdown()
                    # clear highlight all modules by default
                    for mod in sorted_modules:
                        module = board.FindModuleByReference(mod)
                        clear_highlight_on_module(module)
                    pcbnew.Refresh()
                    return
            # clear highlight all modules by default
            for mod in sorted_modules:
                module = board.FindModuleByReference(mod)
                clear_highlight_on_module(module)
            pcbnew.Refresh()
        # by sheet
        else:
            # get list of all modules with same ID
            list_of_modules = placer.get_list_of_modules_with_same_id(
                pivot_module.mod_id)
            # display dialog
            dlg = PlaceBySheet(_pcbnew_frame, placer, pivot_module_reference,
                               user_units)
            levels = pivot_module.filename
            dlg.list_levels.Clear()
            dlg.list_levels.AppendItems(levels)
            res = dlg.ShowModal()

            if res == wx.ID_CANCEL:
                # clear highlight all modules by default
                # get the list from the GUI elements
                for module in list_of_modules:
                    clear_highlight_on_module(module.mod)
                pcbnew.Refresh()
                return

            # based on the sheet list, find all the modules with same ID
            sheets_to_place_indeces = dlg.list_sheets.GetSelections()
            sheets_to_place = [
                dlg.list_sheetsChoices[i] for i in sheets_to_place_indeces
            ]

            mod_references = [pivot_module_reference]
            for mod in list_of_modules:
                if mod.sheet_id in sheets_to_place:
                    mod_references.append(mod.ref)

            logger.info("Modules to place: " + repr(mod_references))
            # sort by reference number
            sorted_modules = natural_sort(mod_references)

            # get mode
            if dlg.com_arr.GetStringSelection() == u'Circular':
                delta_angle = float(dlg.val_y_angle.GetValue())
                if user_units == 'mm':
                    radius = float(dlg.val_x_mag.GetValue())
                else:
                    radius = float(dlg.val_x_mag.GetValue()) / 25.4
                try:
                    placer.place_circular(sorted_modules,
                                          pivot_module_reference, radius,
                                          delta_angle, True)
                    logger.info("Placing complete")
                    logging.shutdown()
                except Exception:
                    logger.exception(
                        "Fatal error when executing place footprints")
                    caption = 'Place footprints'
                    message = "Fatal error when executing place footprints.\n"\
                            + "You can raise an issue on GiHub page.\n" \
                            + "Please attach the place_footprints.log which you should find in the project folder."
                    dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                           wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    logging.shutdown()

                    # clear highlight all modules by default
                    for mod in sorted_modules:
                        module = board.FindModuleByReference(mod)
                        clear_highlight_on_module(module)
                    pcbnew.Refresh()
                    return

            if dlg.com_arr.GetStringSelection() == u'Linear':
                if user_units == 'mm':
                    step_x = float(dlg.val_x_mag.GetValue())
                    step_y = float(dlg.val_y_angle.GetValue())
                else:
                    step_x = float(dlg.val_x_mag.GetValue()) / 25.4
                    step_y = float(dlg.val_y_angle.GetValue()) / 25.4
                try:
                    placer.place_linear(sorted_modules, pivot_module_reference,
                                        step_x, step_y)
                    logger.info("Placing complete")
                    logger.info("Sorted_modules: " + repr(sorted_modules))
                    logging.shutdown()
                except Exception:
                    logger.exception(
                        "Fatal error when executing place footprints")
                    caption = 'Place footprints'
                    message = "Fatal error when executing place footprints.\n"\
                            + "You can raise an issue on GiHub page.\n" \
                            + "Please attach the place_footprints.log which you should find in the project folder."
                    dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                           wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    logging.shutdown()
                    # clear highlight all modules by default
                    for mod in sorted_modules:
                        module = board.FindModuleByReference(mod)
                        clear_highlight_on_module(module)
                    pcbnew.Refresh()
                    return

            if dlg.com_arr.GetStringSelection() == u'Matrix':
                if user_units == 'mm':
                    step_x = float(dlg.val_x_mag.GetValue())
                    step_y = float(dlg.val_y_angle.GetValue())
                else:
                    step_x = float(dlg.val_x_mag.GetValue()) / 25.4
                    step_y = float(dlg.val_y_angle.GetValue()) / 25.4
                nr_columns = int(dlg.val_columns.GetValue())
                try:
                    placer.place_matrix(sorted_modules, step_x, step_y,
                                        nr_columns)
                    logger.info("Placing complete")
                    logging.shutdown()
                except Exception:
                    caption = 'Place footprints'
                    logger.exception(
                        "Fatal error when executing place footprints")
                    message = "Fatal error when executing place footprints.\n"\
                            + "You can raise an issue on GiHub page.\n" \
                            + "Please attach the place_footprints.log which you should find in the project folder."
                    dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                           wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    logging.shutdown()
                    # clear highlight all modules by default
                    for mod in sorted_modules:
                        module = board.FindModuleByReference(mod)
                        clear_highlight_on_module(module)
                    pcbnew.Refresh()
                    return

            # clear highlight all modules by default
            for mod in sorted_modules:
                module = board.FindModuleByReference(mod)
                clear_highlight_on_module(module)
            pcbnew.Refresh()
    def Run(self):
        # load board
        board = pcbnew.GetBoard()

        # go to the project folder - so that log will be in proper place
        os.chdir(os.path.dirname(os.path.abspath(board.GetFileName())))

        # set up logger
        logging.basicConfig(
            level=logging.DEBUG,
            filename="pad2pad_track_distance.log",
            filemode='w',
            format='%(asctime)s %(name)s %(lineno)d:%(message)s',
            datefmt='%m-%d %H:%M:%S')
        logger = logging.getLogger(__name__)
        logger.info("Length stats plugin version: " + VERSION + " started")

        stdout_logger = logging.getLogger('STDOUT')
        sl_out = StreamToLogger(stdout_logger, logging.INFO)
        sys.stdout = sl_out

        stderr_logger = logging.getLogger('STDERR')
        sl_err = StreamToLogger(stderr_logger, logging.ERROR)
        sys.stderr = sl_err

        _pcbnew_frame = [
            x for x in wx.GetTopLevelWindows()
            if x.GetTitle().lower().startswith('pcbnew')
        ][0]

        # get user units
        if pcbnew.GetUserUnits() == 1:
            user_units = 'mm'
        else:
            user_units = 'in'

        # get all pads
        modules = board.GetModules()

        pads = []
        for mod in modules:
            # get their pads
            module_pads = mod.PadsList()
            # get net
            for pad in module_pads:
                pads.append(pad)

        # get list of all selected pads
        selected_pads = []
        for pad in pads:
            if pad.IsSelected():
                selected_pads.append(pad)

        # check the nets on all the pads
        nets = []
        for pad in selected_pads:
            nets.append(pad.GetNetname())

        # if more or less than two pads are selected
        if len(selected_pads) != 2:
            caption = 'Pad2Pad Track Distance'
            message = "You have to select two and only two pads"
            dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                   wx.OK | wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        # and if they are on different nest
        if nets[0] != nets[1]:
            caption = 'Pad2Pad Track Distance'
            message = "The selected pads are not on the same net"
            dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                   wx.OK | wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        try:
            measure_distance = pad2pad_track_distance.Distance(
                board, selected_pads[0], selected_pads[1])
            distance, resistance = measure_distance.get_length()
        except LookupError as error:
            caption = 'Pad2Pad Track Distance'
            message = str(error)
            dlg = wx.MessageDialog(_pcbnew_frame, message, caption,
                                   wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            logger.info(message)
            return
        except Exception:
            logger.exception("Fatal error when measuring")
            raise

        # trying to show in layout which tracks are taken into account - so far it does not work
        # as the selection is automatically cleared when exiting action plugin
        # I'll leave this code in just for reference
        selected_pads[0].ClearSelected()
        selected_pads[1].ClearSelected()

        # deselect all tracks except used ones
        all_tracks = board.GetTracks()

        dlg = Pad2PadTrackDistanceDialog(_pcbnew_frame, all_tracks,
                                         measure_distance.track_list)

        if user_units == 'mm':
            dlg.lbl_length.SetLabelText("%.3f" % (distance) + " mm")
            dlg.lbl_resistance.SetLabelText("%.4f" % resistance + " Ohm")
        else:
            dlg.lbl_length.SetLabelText("%.4f" % (distance / 25.4) + " in")
            dlg.lbl_resistance.SetLabelText("%.4f" % resistance + " Ohm")

        dlg.Show()