├── version.txt ├── .gitattributes ├── parse_metadata_json.py ├── __init__.py ├── make_a_package.sh ├── README.md ├── .gitignore ├── metadata_source.json ├── replicate_layout_test_project ├── cascade.kicad_sch └── replicate_layout_test_project.kicad_pro ├── compare_boards.py ├── test_replicate_layout.py ├── remove_duplicates.py ├── replicate_layout_fp_text ├── replicate_layout_fp_text.kicad_pro └── replicate_layout_fp_text.kicad_sch ├── LICENSE ├── conn_issue_dialog_GUI.fbp ├── action_replicate_layout.py └── error_dialog_GUI.fbp /version.txt: -------------------------------------------------------------------------------- 1 | 3.0.3 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /parse_metadata_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | with open('metadata_source.json', 'r') as f: 4 | contents = f.readlines() 5 | 6 | # versions start 7 | v_start = 0 8 | v_stop = 0 9 | 10 | for i in range(len(contents)): 11 | ln = contents[i] 12 | if "\"version\"" in ln: 13 | v_stop = i 14 | if "\"versions\"" in ln: 15 | v_start = i 16 | 17 | # remove from v_start+1 do v_stop-1 18 | index = range(v_start+1, v_stop-1) 19 | new_contents = [element for i, element in enumerate(contents) if i not in index] 20 | 21 | with open('metadata.json', 'w') as f: 22 | f.writelines(new_contents) 23 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | try: 3 | # Note the relative import! 4 | from .action_replicate_layout import ReplicateLayout 5 | # Instantiate and register to Pcbnew 6 | ReplicateLayout().register() 7 | # if failed, log the error and let the user know 8 | except Exception as e: 9 | # log the error 10 | import os 11 | plugin_dir = os.path.dirname(os.path.realpath(__file__)) 12 | log_file = os.path.join(plugin_dir, 'replicate_layout_error.log') 13 | with open(log_file, 'w') as f: 14 | f.write(repr(e)) 15 | # register dummy plugin, to let the user know of the problems 16 | import pcbnew 17 | import wx 18 | 19 | class ReplicateLayout(pcbnew.ActionPlugin): 20 | """ 21 | Notify user of error when initializing the plugin 22 | """ 23 | def defaults(self): 24 | self.name = "ReplicateLayout" 25 | self.category = "Replicate Layout" 26 | self.description = "Replicates layout from one sheet to other sheets in multiple sheet schematics" 27 | 28 | def Run(self): 29 | caption = self.name 30 | message = "There was an error while loading plugin \n" \ 31 | "Please take a look in the plugin folder for replicate_layout_error.log\n" \ 32 | "You can raise an issue on GitHub page.\n" \ 33 | "Please attach the .log file" 34 | wx.MessageBox(message, caption, wx.OK | wx.ICON_ERROR) 35 | 36 | ReplicateLayout().register() 37 | 38 | -------------------------------------------------------------------------------- /make_a_package.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # refresh derived resources 4 | inkscape replicate_layout_dark.svg -w 24 -h 24 -o replicate_layout_dark.png 5 | inkscape replicate_layout_light.svg -w 24 -h 24 -o replicate_layout_light.png 6 | inkscape replicate_layout_light.svg -w 64 -h 64 -o replicate_layout.png 7 | 8 | # refresh the GUI design 9 | wxformbuilder -g replicate_layout_GUI.fbp 10 | wxformbuilder -g error_dialog_GUI.fbp 11 | 12 | # grab version and parse it into metadata.json 13 | cp metadata_source.json metadata_package.json 14 | version=`cat version.txt` 15 | # remove all but the latest version in package metadata 16 | python3 parse_metadata_json.py 17 | sed -i -e "s/VERSION/$version/g" metadata.json 18 | 19 | # cut the download, sha and size fields 20 | sed -i '/download_url/d' metadata.json 21 | sed -i '/download_size/d' metadata.json 22 | sed -i '/install_size/d' metadata.json 23 | sed -i '/download_sha256/d' metadata.json 24 | 25 | # prepare the package 26 | mkdir plugins 27 | cp replicate_layout_dark.png plugins 28 | cp replicate_layout_light.png plugins 29 | cp __init__.py plugins 30 | cp action_replicate_layout.py plugins 31 | cp replicate_layout.py plugins 32 | cp remove_duplicates.py plugins 33 | cp replicate_layout_GUI.py plugins 34 | cp error_dialog_GUI.py plugins 35 | cp conn_issue_GUI.py plugins 36 | cp version.txt plugins 37 | mkdir resources 38 | cp replicate_layout.png resources/icon.png 39 | 40 | zip -r ReplicateLayout-$version-pcm.zip plugins resources metadata.json 41 | 42 | # clean up 43 | rm -r resources 44 | rm -r plugins 45 | rm metadata.json 46 | 47 | # get the sha, size and fill them in the metadata 48 | cp metadata_source.json metadata.json 49 | version=`cat version.txt` 50 | sed -i -e "s/VERSION/$version/g" metadata.json 51 | zipsha=`sha256sum ReplicateLayout-$version-pcm.zip | xargs | cut -d' ' -f1` 52 | sed -i -e "s/SHA256/$zipsha/g" metadata.json 53 | unzipsize=`unzip -l ReplicateLayout-$version-pcm.zip | tail -1 | xargs | cut -d' ' -f1` 54 | sed -i -e "s/INSTALL_SIZE/$unzipsize/g" metadata.json 55 | dlsize=`ls -al ReplicateLayout-$version-pcm.zip | tail -1 | xargs | cut -d' ' -f5` 56 | sed -i -e "s/DOWNLOAD_SIZE/$dlsize/g" metadata.json 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KiCAD Replicate Layout Plugin 2 | 3 | Replicate the PCB layout of one hierarchical sheet to other hierarchical sheets. This replication is based upon hierarchical sheets in Eeschema. The basic requirement for replication is that the section to be replicated (source) is completely contained within a single hierarchical sheet, and replicated sections (destination) are just copies of the same sheet. Complex hierarchies are supported and the replicated sheet can contain subsheets. The plugin replicates footprints, zones, tracks, text and drawings. 4 | 5 | After the section for replication (source section) has been laid out (footprints, tracks, text objects and zones placed) you need to: 6 | 1. Place the anchor footprints for the destination sections you want to replicate. This defines the position and orientation of replicated sections. You can use [the PlaceFootprints action plugin](https://github.com/MitjaNemec/PlaceFootprints) for this. 7 | 2. Select the same anchor footprint within the source section. 8 | 3. Run the plugin. 9 | 4. Choose which hierarchical level you wish to replicate. 10 | 5. Select which sheets you want to replicate (default is all of them). 11 | 6. Select whether you want to also replicate tracks, zones and/or text objects. 12 | 7. Select whether you want to group replicated footprints/tracks/zones/text/drawings by hierarchical sheets. 13 | 8. Select whether you want to replicate tracks/zones/text which intersect the pivot bounding box or just those contained within the bounding box. 14 | 9. Select whether you want to delete already laid out tracks/zones/text (this is useful when updating an already replicated layout). 15 | 10. Hit OK. 16 | 17 | By default, only objects which are fully contained in the bounding box constituted by all the footprints in the section will be replicated. You can select to also replicate zones and tracks which intersect this bounding box. Additionally, tracks, text and zones which are already laid out in the replicated bounding boxes can be removed (useful when updating). Note that bounding boxes are squares aligned with the x and y axis, regardless of section orientation. 18 | 19 | ## Installation 20 | 21 | The preferred way to install the plugin is via KiCad's Plugin and Content Manager (PCM). Installation on non-networked devices can be done by downloading [the latest release](https://github.com/MitjaNemec/ReplicateLayout/releases/latest) and installing in the PCM using the `Install from file` option. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | replicate_layout_GUI.py 2 | /replicate_layout_test_project/replicate_layout_test_project-backups 3 | *.jpg 4 | .directory 5 | __pycache__/ 6 | .idea/ 7 | *.png 8 | *.log 9 | *.zip 10 | *.kicad_prl 11 | /replicate_layout_test_project/fp-info-cache 12 | /replicate_layout_test_project/.directory 13 | /replicate_layout_test_project/*.log 14 | /replicate_layout_fp_text/replicate_layout_fp_text-backups 15 | /replicate_layout_fp_text/replicate_layout_fp_text_temp_inner.kicad_pro 16 | /replicate_layout_fp_text/replicate_layout_fp_text_test_inner.kicad_pro 17 | /replicate_layout_fp_text/replicate_layout_fp_text_temp_inner.kicad_prl 18 | /replicate_layout_fp_text/replicate_layout_fp_text_test_inner.kicad_prl 19 | /replicate_layout_fp_text/fp-info-cache 20 | /replicate_layout_test_project/replicate_layout_test_project_temp_outter.kicad_pro 21 | /replicate_layout_test_project/replicate_layout_test_project_temp_outter.kicad_prl 22 | /replicate_layout_test_project/replicate_layout_test_project_temp_outer.kicad_pro 23 | /replicate_layout_test_project/replicate_layout_test_project_temp_outer.kicad_prl 24 | /replicate_layout_test_project/replicate_layout_temp_project_temp_inner.kicad_prl 25 | /replicate_layout_test_project/replicate_layout_temp_project_temp_inner.kicad_pro 26 | /replicate_layout_test_project/replicate_layout_temp_project_temp_inner_alt.kicad_prl 27 | /replicate_layout_test_project/replicate_layout_temp_project_temp_inner_alt.kicad_pro 28 | /replicate_layout_test_project/replicate_layout_temp_project_temp_outter.kicad_pro 29 | /replicate_layout_test_project/replicate_layout_test_project_temp.kicad_prl 30 | /replicate_layout_test_project/replicate_layout_test_project_temp_inner.kicad_prl 31 | /replicate_layout_test_project/replicate_layout_test_project_temp_inner.kicad_pro 32 | /replicate_layout_test_project/replicate_layout_test_project_temp_inner_alt.kicad_pcb 33 | /replicate_layout_test_project/replicate_layout_test_project_temp_inner_alt.kicad_prl 34 | /replicate_layout_test_project/replicate_layout_test_project_temp_inner_alt.kicad_pro 35 | /replicate_layout_test_project/replicate_layout_test_project_temp_outer.kicad_pcb 36 | /replicate_layout_fp_text/replicate_layout_fp_text_temp_inner.kicad_pcb 37 | ReplicateLayout-1.0.0-pcm.zip 38 | metadata_package.json 39 | metadata.json 40 | replicate_layout_test_project 41 | replicate_layout_fp_text 42 | /replicate_issue_2 43 | /eewiz_issue_14 44 | /gunter_test_issue_25 45 | /InstantMuffin_test_issue_23 46 | /KiCad_2ndTestProject_v1 47 | /krivospitsky_issue 48 | error_dialog_GUI.py 49 | conn_issue_GUI.py 50 | zyeborm_issue_38/ 51 | connectivity_test/ 52 | -------------------------------------------------------------------------------- /metadata_source.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://go.kicad.org/pcm/schemas/v1", 3 | "name": "Replicate Layout", 4 | "description": "Replicates layout of one hierarchical sheet to other copies of the same sheet.", 5 | "description_full": "Replicate layout of one hierarchical sheet to other hierarchical sheets. The replication is based upon hierarchical sheets in eeschema. The basic requirement for replication is that the section to be replicated (source) is completely contained within a single hierarchical sheet, and replicated sections (destination) are just copies of the same sheet. Complex hierarchies are supported therefore replicated sheet can contain subsheets. The plugin replicates footprints, zones, tracks, text and drawings.\nAfter the section for replication (source section) has been laid out (footprints, tracks, text objects and zones placed) you need to:\n1. Place the anchor footprints for the destiantion sections you want to replicate. This defines the position and orientation of replicated sections. You can use PlaceFootprints action plugin for this.\n2. Select the same anchor footprint within the source section.\n3. Run the plugin.\n4. Choose which hierarchical level you wish to replicate.\n5. Select which sheets you want to replicate (default is all of them)\n6. Select whether you want to replicate also tracks, zones and/or text objects.\n7. Select whether you want to replicate tracks/zones/text which intersect the pivot bounding box or just those contained within the bounding box.\n8. Select whether you want to delete already laid out tracks/zones/text (this is useful when updating an already replicated layout).\n9. Hit OK.\nBy default, only objects which are fully contained in the bounding box constituted by all the footprints in the section will be replicated. You can select to also replicate zones and tracks which intersect this bounding box. Additionally, tracks, text and zones which are already laid out in the replicated bounding boxes can be removed (useful when updating). Note that bounding boxes are squares aligned with the x and y axis, regardless of section orientation.", 6 | "identifier": "com.github.MitjaNemec.ReplicateLayout", 7 | "type": "plugin", 8 | "author": { 9 | "name": "Mitja Nemec", 10 | "contact": { 11 | "github": "https://github.com/MitjaNemec" 12 | } 13 | }, 14 | "license": "GPL-2.0", 15 | "resources": { 16 | "homepage": "https://github.com/MitjaNemec/ReplicateLayout" 17 | }, 18 | "tags": [ 19 | "pcbnew", 20 | "footprints", 21 | "arrange" 22 | ], 23 | "versions": [ 24 | { 25 | "version": "VERSION", 26 | "status": "stable", 27 | "kicad_version": "7.99", 28 | "kicad_version_max": "8.1", 29 | "download_url": "https://github.com/MitjaNemec/ReplicateLayout/releases/download/VERSION/ReplicateLayout-VERSION-pcm.zip", 30 | "download_sha256": "SHA256", 31 | "download_size": DOWNLOAD_SIZE, 32 | "install_size": INSTALL_SIZE, 33 | "platforms": [ 34 | "linux", 35 | "macos", 36 | "windows" 37 | ] 38 | } 39 | ] 40 | } 41 | 42 | -------------------------------------------------------------------------------- /replicate_layout_test_project/cascade.kicad_sch: -------------------------------------------------------------------------------- 1 | (kicad_sch 2 | (version 20231120) 3 | (generator "eeschema") 4 | (generator_version "7.99") 5 | (uuid "860228ff-27ec-4e54-8fdf-8687145181e5") 6 | (paper "A4") 7 | (lib_symbols) 8 | (wire 9 | (pts 10 | (xy 82.55 63.5) (xy 95.25 63.5) 11 | ) 12 | (stroke 13 | (width 0) 14 | (type default) 15 | ) 16 | (uuid "62cf5b29-2ec2-43c9-b1f1-bb2df6b67437") 17 | ) 18 | (wire 19 | (pts 20 | (xy 57.15 63.5) (xy 69.85 63.5) 21 | ) 22 | (stroke 23 | (width 0) 24 | (type default) 25 | ) 26 | (uuid "68114881-673b-448e-8324-d2c5e9ae8dfc") 27 | ) 28 | (wire 29 | (pts 30 | (xy 38.1 63.5) (xy 44.45 63.5) 31 | ) 32 | (stroke 33 | (width 0) 34 | (type default) 35 | ) 36 | (uuid "e597dc8d-5aae-4df3-bec2-532e5e59d37f") 37 | ) 38 | (hierarchical_label "in" 39 | (shape input) 40 | (at 38.1 63.5 180) 41 | (fields_autoplaced yes) 42 | (effects 43 | (font 44 | (size 1.27 1.27) 45 | ) 46 | (justify right) 47 | ) 48 | (uuid "19359094-d5c7-4ee8-bc6f-fc6ad6fd7829") 49 | ) 50 | (hierarchical_label "out" 51 | (shape output) 52 | (at 95.25 63.5 0) 53 | (fields_autoplaced yes) 54 | (effects 55 | (font 56 | (size 1.27 1.27) 57 | ) 58 | (justify left) 59 | ) 60 | (uuid "f1fbb852-9255-4ce9-a6c9-4eccca281fc1") 61 | ) 62 | (sheet 63 | (at 69.85 57.15) 64 | (size 12.7 12.7) 65 | (fields_autoplaced yes) 66 | (stroke 67 | (width 0.1524) 68 | (type solid) 69 | ) 70 | (fill 71 | (color 0 0 0 0.0000) 72 | ) 73 | (uuid "5373f2bb-9d53-4847-a6f8-a066e3ee75b5") 74 | (property "Sheetname" "low_pass1" 75 | (at 69.85 56.4384 0) 76 | (effects 77 | (font 78 | (size 1.27 1.27) 79 | ) 80 | (justify left bottom) 81 | ) 82 | ) 83 | (property "Sheetfile" "low_pass.kicad_sch" 84 | (at 69.85 70.4346 0) 85 | (effects 86 | (font 87 | (size 1.27 1.27) 88 | ) 89 | (justify left top) 90 | ) 91 | ) 92 | (pin "out" output 93 | (at 82.55 63.5 0) 94 | (effects 95 | (font 96 | (size 1.27 1.27) 97 | ) 98 | (justify right) 99 | ) 100 | (uuid "cd960e72-6b7f-4a77-a01e-4a7d4751aa22") 101 | ) 102 | (pin "in" input 103 | (at 69.85 63.5 180) 104 | (effects 105 | (font 106 | (size 1.27 1.27) 107 | ) 108 | (justify left) 109 | ) 110 | (uuid "f3f0ee33-6656-4efd-9d0a-60b540f342e6") 111 | ) 112 | (instances 113 | (project "replicate_layout_test_project" 114 | (path "/f74f526d-8f11-48ad-9d53-7c2f3f9650e8/4ca1ab63-9c14-412d-87f4-6aa38cef6e23" 115 | (page "4") 116 | ) 117 | ) 118 | ) 119 | ) 120 | (sheet 121 | (at 44.45 57.15) 122 | (size 12.7 12.7) 123 | (fields_autoplaced yes) 124 | (stroke 125 | (width 0.1524) 126 | (type solid) 127 | ) 128 | (fill 129 | (color 0 0 0 0.0000) 130 | ) 131 | (uuid "76ec9d82-785d-40b9-8c12-2a92b321b773") 132 | (property "Sheetname" "low_pass" 133 | (at 44.45 56.4384 0) 134 | (effects 135 | (font 136 | (size 1.27 1.27) 137 | ) 138 | (justify left bottom) 139 | ) 140 | ) 141 | (property "Sheetfile" "low_pass.kicad_sch" 142 | (at 44.45 70.4346 0) 143 | (effects 144 | (font 145 | (size 1.27 1.27) 146 | ) 147 | (justify left top) 148 | ) 149 | ) 150 | (pin "out" output 151 | (at 57.15 63.5 0) 152 | (effects 153 | (font 154 | (size 1.27 1.27) 155 | ) 156 | (justify right) 157 | ) 158 | (uuid "179adb92-0913-4cc8-88ef-e2cae74fb1da") 159 | ) 160 | (pin "in" input 161 | (at 44.45 63.5 180) 162 | (effects 163 | (font 164 | (size 1.27 1.27) 165 | ) 166 | (justify left) 167 | ) 168 | (uuid "c04d32c6-d9ba-41e5-8fd3-165d457109c2") 169 | ) 170 | ) 171 | ) -------------------------------------------------------------------------------- /compare_boards.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # compare_boards.py 3 | # 4 | # Copyright (C) 2018 Mitja Nemec, Stephen Walker-Weinshenker 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | # 21 | # 22 | 23 | 24 | def getIndex(s, i): 25 | from collections import deque 26 | # If input is invalid. 27 | if s[i] != '(': 28 | return -1 29 | # Create a deque to use it as a stack. 30 | d = deque() 31 | # Traverse through all elements 32 | # starting from i. 33 | for k in range(i, len(s)): 34 | # Pop a starting bracket 35 | # for every closing bracket 36 | if s[k] == ')': 37 | d.popleft() 38 | # Push all starting brackets 39 | elif s[k] == '(': 40 | d.append(s[i]) 41 | # If deque becomes empty 42 | if not d: 43 | return k 44 | return -1 45 | 46 | def remove_kicad_pcb_header(file_contents): 47 | """ 48 | remove from file: 49 | -verision info 50 | -host info 51 | -general info 52 | -page info 53 | -layers 54 | -setup info 55 | -title info 56 | """ 57 | index_version_start = file_contents.find("(version") 58 | index_version_stop = getIndex(file_contents, index_version_start)+1 59 | trimmed_contents = file_contents[0:index_version_start] + file_contents[index_version_stop:-1] 60 | 61 | index_version_start = trimmed_contents.find("(host") 62 | index_version_stop = getIndex(trimmed_contents, index_version_start)+1 63 | trimmed_contents = trimmed_contents[0:index_version_start] + trimmed_contents[index_version_stop:-1] 64 | 65 | index_version_start = trimmed_contents.find("(general") 66 | index_version_stop = getIndex(trimmed_contents, index_version_start)+1 67 | trimmed_contents = trimmed_contents[0:index_version_start] + trimmed_contents[index_version_stop:-1] 68 | 69 | index_version_start = trimmed_contents.find("(page") 70 | index_version_stop = getIndex(trimmed_contents, index_version_start)+1 71 | trimmed_contents = trimmed_contents[0:index_version_start] + trimmed_contents[index_version_stop:-1] 72 | 73 | index_version_start = trimmed_contents.find("(layers") 74 | index_version_stop = getIndex(trimmed_contents, index_version_start)+1 75 | trimmed_contents = trimmed_contents[0:index_version_start] + trimmed_contents[index_version_stop:-1] 76 | 77 | index_version_start = trimmed_contents.find("(setup") 78 | index_version_stop = getIndex(trimmed_contents, index_version_start)+1 79 | trimmed_contents = trimmed_contents[0:index_version_start] + trimmed_contents[index_version_stop:-1] 80 | 81 | index_version_start = trimmed_contents.find("(title_block") 82 | index_version_stop = getIndex(trimmed_contents, index_version_start)+1 83 | trimmed_contents = trimmed_contents[0:index_version_start] + trimmed_contents[index_version_stop:-1] 84 | 85 | return trimmed_contents 86 | 87 | def compare_boards(filename1, filename2): 88 | import difflib 89 | errnum = 0 90 | with open(filename1) as f1: 91 | with open(filename2) as f2: 92 | contents_f1 = f1.read() 93 | contents_f2 = f2.read() 94 | 95 | contents_f1 = remove_kicad_pcb_header(contents_f1).split("\n") 96 | contents_f2 = remove_kicad_pcb_header(contents_f2).split("\n") 97 | 98 | # get a diff 99 | diff = difflib.unified_diff( 100 | contents_f1, 101 | contents_f2, 102 | fromfile='board1', 103 | tofile='board2', 104 | n=0) 105 | 106 | # only timestamps on zones and file version information should differ 107 | diffstring = [] 108 | for line in diff: 109 | diffstring.append(line) 110 | # if files are the same, finish now 111 | if not diffstring: 112 | return 0 113 | # get rid of diff information 114 | del diffstring[0] 115 | del diffstring[0] 116 | # walktrough diff list and check for any significant differences 117 | for line in diffstring: 118 | index = diffstring.index(line) 119 | if '@@' in line: 120 | if (('tstamp' in diffstring[index + 1]) and ('tstamp' in diffstring[index + 2])): 121 | # this is not a problem 122 | pass 123 | else: 124 | # this is a problem 125 | errnum = errnum + 1 126 | return errnum 127 | -------------------------------------------------------------------------------- /test_replicate_layout.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import unittest 4 | import pcbnew 5 | import logging 6 | import sys 7 | import os 8 | from compare_boards import compare_boards 9 | from replicate_layout import Replicator 10 | from replicate_layout import Settings 11 | 12 | 13 | def update_progress(stage, percentage, message=None): 14 | print(stage) 15 | print(percentage) 16 | if message is not None: 17 | print(message) 18 | 19 | 20 | def test_file(in_filename, test_filename, src_anchor_fp_reference, level, sheets, containing, remove, by_group): 21 | board = pcbnew.LoadBoard(in_filename) 22 | # get board information 23 | replicator = Replicator(board, src_anchor_fp_reference, update_progress) 24 | # get source footprint info 25 | src_anchor_fp = replicator.get_fp_by_ref(src_anchor_fp_reference) 26 | # check if there are at least two sheets pointing to same hierarchical file that the source anchor footprint belongs to 27 | count = 0 28 | for filename in replicator.dict_of_sheets.values(): 29 | if filename[1] in src_anchor_fp.filename: 30 | count = count + 1 31 | if count < 2: 32 | raise Exception 33 | # check if source anchor footprint is on root level 34 | if len(src_anchor_fp.filename) == 0: 35 | raise Exception 36 | 37 | # have the user select replication level 38 | levels = src_anchor_fp.filename 39 | # get the level index from user 40 | index = levels.index(levels[level]) 41 | # get list of sheets 42 | sheet_list = replicator.get_sheets_to_replicate(src_anchor_fp, src_anchor_fp.sheet_id[index]) 43 | 44 | # get anchor footprints 45 | anchor_footprints = replicator.get_list_of_footprints_with_same_id(src_anchor_fp.fp_id) 46 | # find matching anchors to matching sheets 47 | ref_list = [] 48 | for sheet in sheet_list: 49 | for fp in anchor_footprints: 50 | a = sheet 51 | b = fp.sheet_id 52 | if sheet == fp.sheet_id: 53 | ref_list.append(fp.ref) 54 | break 55 | 56 | # get the list selection from user 57 | dst_sheets = [sheet_list[i] for i in sheets] 58 | 59 | settings = Settings(rep_tracks=True, rep_zones=True, rep_text=True, rep_drawings=True, 60 | rep_locked_tracks=True, rep_locked_zones=True, rep_locked_text=True, rep_locked_drawings=True, 61 | intersecting=not containing, 62 | group_items=True, 63 | group_only=False, locked_fps=False, 64 | remove=False) 65 | 66 | (fps, items) = replicator.highlight_set_level(src_anchor_fp.sheet_id[0:index + 1], 67 | settings) 68 | replicator.highlight_clear_level(fps, items) 69 | 70 | # now we are ready for replication 71 | replicator.replicate_layout(src_anchor_fp, src_anchor_fp.sheet_id[0:index + 1], dst_sheets, 72 | settings, rm_duplicates=True) 73 | out_filename = test_filename.replace("ref", "temp") 74 | pcbnew.SaveBoard(out_filename, board) 75 | # test for connectivity isuues 76 | if replicator.connectivity_issues: 77 | report_string = "" 78 | for item in replicator.connectivity_issues: 79 | report_string = report_string + f"Footprint {item[0]}, pad {item[1]}\n" 80 | print(f"Make sure that you check the connectivity around:\n" + report_string) 81 | 82 | print("comparing boards") 83 | #return compare_boards(out_filename, test_filename) 84 | 85 | @unittest.skip 86 | class TestBrackets(unittest.TestCase): 87 | def setUp(self): 88 | os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "brackets")) 89 | 90 | def test_inner(self): 91 | logger.info("Testing multiple hierarchy - inner levels") 92 | input_filename = 'replicate_layout_test_project.kicad_pcb' 93 | test_filename = input_filename.split('.')[0] + "_ref_inner" + ".kicad_pcb" 94 | err = test_file(input_filename, test_filename, 'U701', level=1, sheets=(1, 3, 7), 95 | containing=False, remove=False, by_group=True) 96 | self.assertEqual(err, 0, "inner levels failed") 97 | 98 | 99 | class TestFpText(unittest.TestCase): 100 | def setUp(self): 101 | os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "bug-demo")) 102 | 103 | def test(self): 104 | logger.info("Testin fp text replication") 105 | input_filename = 'controller-led-matrix.kicad_pcb' 106 | test_filename = input_filename.split('.')[0] + "_ref_inner" + ".kicad_pcb" 107 | err = test_file(input_filename, test_filename, 'U1', level=0, sheets=(0, 1), 108 | containing=False, remove=False, by_group=False) 109 | self.assertEqual(err, 0, "inner levels failed") 110 | 111 | 112 | @unittest.skip 113 | class TestOfficial(unittest.TestCase): 114 | def setUp(self): 115 | os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "replicate_layout_test_project")) 116 | 117 | def test_inner(self): 118 | logger.info("Testing multiple hierarchy - inner levels") 119 | input_filename = 'replicate_layout_test_project.kicad_pcb' 120 | test_filename = input_filename.split('.')[0] + "_ref_inner" + ".kicad_pcb" 121 | err = test_file(input_filename, test_filename, 'U701', level=1, sheets=(1, 3, 7), 122 | containing=False, remove=False, by_group=True) 123 | self.assertEqual(err, 0, "inner levels failed") 124 | 125 | def test_inner_alt(self): 126 | logger.info("Testing multiple hierarchy - inner levels") 127 | input_filename = 'replicate_layout_test_project.kicad_pcb' 128 | test_filename = input_filename.split('.')[0] + "_ref_inner_alt" + ".kicad_pcb" 129 | err = test_file(input_filename, test_filename, 'U1501', level=0, sheets=(2, 4, 8), 130 | containing=False, remove=False, by_group=True) 131 | self.assertEqual(err, 0, "inner levels failed") 132 | 133 | @unittest.skip 134 | def test_outer(self): 135 | logger.info("Testing multiple hierarchy - inner levels") 136 | input_filename = 'replicate_layout_test_project.kicad_pcb' 137 | test_filename = input_filename.split('.')[0] + "_ref_outer" + ".kicad_pcb" 138 | err = test_file(input_filename, test_filename, 'U701', level=0, sheets=(0, 1), 139 | containing=False, remove=False, by_group=True) 140 | self.assertEqual(err, 0, "outer levels failed") 141 | 142 | 143 | # for testing purposes only 144 | if __name__ == "__main__": 145 | file_handler = logging.FileHandler(filename='replicate_layout.log', mode='w') 146 | stdout_handler = logging.StreamHandler(sys.stdout) 147 | handlers = [file_handler, stdout_handler] 148 | 149 | logging_level = logging.INFO 150 | 151 | logging.basicConfig(level=logging_level, 152 | format='%(asctime)s %(name)s %(lineno)d:%(message)s', 153 | datefmt='%m-%d %H:%M:%S', 154 | handlers=handlers 155 | ) 156 | 157 | logger = logging.getLogger(__name__) 158 | logger.info("Plugin executed on: " + repr(sys.platform)) 159 | logger.info("Plugin executed with python version: " + repr(sys.version)) 160 | logger.info("KiCad build version: " + str(pcbnew.GetBuildVersion())) 161 | 162 | unittest.main() 163 | -------------------------------------------------------------------------------- /remove_duplicates.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # remove_duplicates.py 3 | # 4 | # Copyright (C) 2019 Mitja Nemec, Stephen Walker-Weinshenker 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | # 21 | # 22 | import pcbnew 23 | import os 24 | import sys 25 | import logging 26 | from collections import defaultdict 27 | 28 | logger = logging.getLogger(__name__) 29 | 30 | 31 | def zones_equal(zone1, zone2): 32 | z1_layer = zone1.GetLayer() 33 | z1_corners = zone1.GetNumCorners() 34 | 35 | z2_layer = zone2.GetLayer() 36 | z2_corners = zone2.GetNumCorners() 37 | 38 | if z1_layer == z2_layer: 39 | if z1_corners == z2_corners: 40 | z1_corners = [zone1.GetCornerPosition(index) for index in range(z1_corners)] 41 | z2_corners = [zone2.GetCornerPosition(index) for index in range(z2_corners)] 42 | z1z2_corners = zip(z1_corners, z2_corners) 43 | if all(x[0] == x[1] for x in z1z2_corners): 44 | return 1 45 | return 0 46 | 47 | 48 | def remove_duplicate_zones(board): 49 | # load all zones 50 | zones = board.Zones() 51 | 52 | # build a dictionary wih a list of tracks for each net 53 | zone_dict = defaultdict(list) 54 | for zone in zones: 55 | zone_dict[zone.GetNetCode()].append(zone) 56 | 57 | # go through all the keys 58 | for key in zone_dict: 59 | zones = zone_dict[key] 60 | 61 | # for each key compare each track agianst each other and if there is no equal 62 | # remove it from the list and add to the new list 63 | 64 | for index in range(len(zones)): 65 | z1 = zones[index] 66 | bools = map(lambda x: zones_equal(x, z1), zones[index+1:]) 67 | if sum(bools) != 0: 68 | board.RemoveNative(z1) 69 | 70 | 71 | def tracks_equal(track1, track2): 72 | t1_layer = track1.GetLayer() 73 | t1_pos = track1.GetPosition() 74 | t1_start = track1.GetStart() 75 | t1_end = track1.GetEnd() 76 | 77 | t2_layer = track2.GetLayer() 78 | t2_pos = track2.GetPosition() 79 | t2_start = track2.GetStart() 80 | t2_end = track2.GetEnd() 81 | 82 | if t1_layer == t2_layer: 83 | if t1_pos == t2_pos: 84 | if t1_start == t2_start: 85 | if t1_end == t2_end: 86 | return 1 87 | return 0 88 | 89 | 90 | def remove_duplicate_tracks(board): 91 | # load all tracks 92 | tracks = board.GetTracks() 93 | 94 | # build a dictionary wih a list of tracks for each net 95 | track_dict = defaultdict(list) 96 | for track in tracks: 97 | track_dict[track.GetNetCode()].append(track) 98 | 99 | # go through all the keys 100 | for key in track_dict: 101 | tracks = track_dict[key] 102 | 103 | # for each key compare each track agianst each other and if there is no equal 104 | # remove it from the list and add to the new list 105 | 106 | for index in range(len(tracks)): 107 | t1 = tracks[index] 108 | bools = map(lambda x: tracks_equal(x, t1), tracks[index+1:]) 109 | if sum(bools) != 0: 110 | board.RemoveNative(t1) 111 | 112 | 113 | def text_equal(text1, text2): 114 | t1_properties = [] 115 | t1_properties.append(text1.GetLayer()) 116 | t1_properties.append(text1.GetPosition()) 117 | t1_properties.append(text1.GetTextPos()) 118 | t1_properties.append(text1.GetText()) 119 | #t1_properties.append(text1.GetThickness()) 120 | t1_properties.append(text1.GetTextAngle()) 121 | t1_properties.append(text1.IsItalic()) 122 | t1_properties.append(text1.IsBold()) 123 | t1_properties.append(text1.IsVisible()) 124 | t1_properties.append(text1.IsMirrored()) 125 | t1_properties.append(text1.GetVertJustify()) 126 | t1_properties.append(text1.GetHorizJustify()) 127 | t1_properties.append(text1.GetTextSize()) 128 | t1_properties.append(text1.GetTextWidth()) 129 | t1_properties.append(text1.GetTextHeight()) 130 | 131 | t2_properties = [] 132 | t2_properties.append(text2.GetLayer()) 133 | t2_properties.append(text2.GetPosition()) 134 | t2_properties.append(text2.GetTextPos()) 135 | t2_properties.append(text2.GetText()) 136 | #t2_properties.append(text2.GetThickness()) 137 | t2_properties.append(text2.GetTextAngle()) 138 | t2_properties.append(text2.IsItalic()) 139 | t2_properties.append(text2.IsBold()) 140 | t2_properties.append(text2.IsVisible()) 141 | t2_properties.append(text2.IsMirrored()) 142 | t2_properties.append(text2.GetVertJustify()) 143 | t2_properties.append(text2.GetHorizJustify()) 144 | t2_properties.append(text2.GetTextSize()) 145 | t2_properties.append(text2.GetTextWidth()) 146 | t2_properties.append(text2.GetTextHeight()) 147 | 148 | t1t2_properties = zip(t1_properties, t2_properties) 149 | if all(x[0] == x[1] for x in t1t2_properties): 150 | return 1 151 | return 0 152 | 153 | 154 | def remove_duplicate_text(board): 155 | # load text items 156 | drawings = board.GetDrawings() 157 | 158 | text_items = [] 159 | for drawing in drawings: 160 | if isinstance(drawing, pcbnew.PCB_TEXT): 161 | text_items.append(drawing) 162 | 163 | for index in range(len(text_items)): 164 | t1 = text_items[index] 165 | bools = map(lambda x: text_equal(x, t1), text_items[index+1:]) 166 | if sum(bools) != 0: 167 | board.RemoveNative(t1) 168 | 169 | 170 | def drawings_equal(drawing1, drawing2): 171 | d1_properties = [] 172 | d1_properties.append(drawing1.GetLayer()) 173 | d1_properties.append(drawing1.GetPosition()) 174 | d1_properties.append(drawing1.GetStart()) 175 | d1_properties.append(drawing1.GetEnd()) 176 | d1_properties.append(drawing1.GetClass()) 177 | d1_properties.append(drawing1.GetLength()) 178 | d1_properties.append(drawing1.GetWidth()) 179 | d1_properties.append(drawing1.GetAngle()) 180 | d1_properties.append(drawing1.GetType()) 181 | d1_properties.append(drawing1.GetShape()) 182 | 183 | d2_properties = [] 184 | d2_properties.append(drawing2.GetLayer()) 185 | d2_properties.append(drawing2.GetPosition()) 186 | d2_properties.append(drawing2.GetStart()) 187 | d2_properties.append(drawing2.GetEnd()) 188 | d2_properties.append(drawing2.GetClass()) 189 | d2_properties.append(drawing2.GetLength()) 190 | d2_properties.append(drawing2.GetWidth()) 191 | d2_properties.append(drawing2.GetAngle()) 192 | d2_properties.append(drawing2.GetType()) 193 | d2_properties.append(drawing2.GetShape()) 194 | 195 | d1d2_properties = zip(d1_properties, d2_properties) 196 | if all(x[0] == x[1] for x in d1d2_properties): 197 | return 1 198 | return 0 199 | 200 | 201 | def remove_duplicate_drawings(board): 202 | # load text items 203 | drawings = board.GetDrawings() 204 | 205 | drawing_items = [] 206 | for drawing in drawings: 207 | if isinstance(drawing, pcbnew.DRAWINGS): 208 | drawing_items.append(drawing) 209 | 210 | for index in range(len(drawing_items)): 211 | d1 = drawing_items[index] 212 | bools = map(lambda x: drawings_equal(x, d1), drawing_items[index+1:]) 213 | if sum(bools) != 0: 214 | board.RemoveNative(d1) 215 | 216 | 217 | def remove_duplicates(board): 218 | # remove duplicate tracks 219 | remove_duplicate_tracks(board) 220 | # remove duplicate zones 221 | remove_duplicate_zones(board) 222 | # remove duplicate text 223 | remove_duplicate_text(board) 224 | # remove duplicate drawings 225 | remove_duplicate_drawings(board) 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /replicate_layout_fp_text/replicate_layout_fp_text.kicad_pro: -------------------------------------------------------------------------------- 1 | { 2 | "board": { 3 | "design_settings": { 4 | "defaults": { 5 | "board_outline_line_width": 0.09999999999999999, 6 | "copper_line_width": 0.19999999999999998, 7 | "copper_text_italic": false, 8 | "copper_text_size_h": 1.5, 9 | "copper_text_size_v": 1.5, 10 | "copper_text_thickness": 0.3, 11 | "copper_text_upright": false, 12 | "courtyard_line_width": 0.049999999999999996, 13 | "dimension_precision": 4, 14 | "dimension_units": 3, 15 | "dimensions": { 16 | "arrow_length": 1270000, 17 | "extension_offset": 500000, 18 | "keep_text_aligned": true, 19 | "suppress_zeroes": false, 20 | "text_position": 0, 21 | "units_format": 1 22 | }, 23 | "fab_line_width": 0.09999999999999999, 24 | "fab_text_italic": false, 25 | "fab_text_size_h": 1.0, 26 | "fab_text_size_v": 1.0, 27 | "fab_text_thickness": 0.15, 28 | "fab_text_upright": false, 29 | "other_line_width": 0.15, 30 | "other_text_italic": false, 31 | "other_text_size_h": 1.0, 32 | "other_text_size_v": 1.0, 33 | "other_text_thickness": 0.15, 34 | "other_text_upright": false, 35 | "pads": { 36 | "drill": 0.762, 37 | "height": 1.524, 38 | "width": 1.524 39 | }, 40 | "silk_line_width": 0.15, 41 | "silk_text_italic": false, 42 | "silk_text_size_h": 1.0, 43 | "silk_text_size_v": 1.0, 44 | "silk_text_thickness": 0.15, 45 | "silk_text_upright": false, 46 | "zones": { 47 | "45_degree_only": false, 48 | "min_clearance": 0.508 49 | } 50 | }, 51 | "diff_pair_dimensions": [], 52 | "drc_exclusions": [], 53 | "meta": { 54 | "version": 2 55 | }, 56 | "rule_severities": { 57 | "annular_width": "error", 58 | "clearance": "error", 59 | "copper_edge_clearance": "error", 60 | "courtyards_overlap": "error", 61 | "diff_pair_gap_out_of_range": "error", 62 | "diff_pair_uncoupled_length_too_long": "error", 63 | "drill_out_of_range": "error", 64 | "duplicate_footprints": "warning", 65 | "extra_footprint": "warning", 66 | "footprint_type_mismatch": "error", 67 | "hole_clearance": "error", 68 | "hole_near_hole": "error", 69 | "invalid_outline": "error", 70 | "item_on_disabled_layer": "error", 71 | "items_not_allowed": "error", 72 | "length_out_of_range": "error", 73 | "malformed_courtyard": "error", 74 | "microvia_drill_out_of_range": "error", 75 | "missing_courtyard": "ignore", 76 | "missing_footprint": "warning", 77 | "net_conflict": "warning", 78 | "npth_inside_courtyard": "ignore", 79 | "padstack": "error", 80 | "pth_inside_courtyard": "ignore", 81 | "shorting_items": "error", 82 | "silk_over_copper": "warning", 83 | "silk_overlap": "warning", 84 | "skew_out_of_range": "error", 85 | "through_hole_pad_without_hole": "error", 86 | "too_many_vias": "error", 87 | "track_dangling": "warning", 88 | "track_width": "error", 89 | "tracks_crossing": "error", 90 | "unconnected_items": "error", 91 | "unresolved_variable": "error", 92 | "via_dangling": "warning", 93 | "zone_has_empty_net": "error", 94 | "zones_intersect": "error" 95 | }, 96 | "rules": { 97 | "allow_blind_buried_vias": false, 98 | "allow_microvias": false, 99 | "max_error": 0.005, 100 | "min_clearance": 0.0, 101 | "min_copper_edge_clearance": 0.0, 102 | "min_hole_clearance": 0.25, 103 | "min_hole_to_hole": 0.25, 104 | "min_microvia_diameter": 0.19999999999999998, 105 | "min_microvia_drill": 0.09999999999999999, 106 | "min_silk_clearance": 0.0, 107 | "min_through_hole_diameter": 0.3, 108 | "min_track_width": 0.19999999999999998, 109 | "min_via_annular_width": 0.049999999999999996, 110 | "min_via_diameter": 0.39999999999999997, 111 | "solder_mask_clearance": 0.0, 112 | "solder_mask_min_width": 0.0, 113 | "use_height_for_length_calcs": true 114 | }, 115 | "track_widths": [], 116 | "via_dimensions": [], 117 | "zones_allow_external_fillets": false, 118 | "zones_use_no_outline": true 119 | }, 120 | "layer_presets": [] 121 | }, 122 | "boards": [], 123 | "cvpcb": { 124 | "equivalence_files": [] 125 | }, 126 | "erc": { 127 | "erc_exclusions": [], 128 | "meta": { 129 | "version": 0 130 | }, 131 | "pin_map": [ 132 | [ 133 | 0, 134 | 0, 135 | 0, 136 | 0, 137 | 0, 138 | 0, 139 | 1, 140 | 0, 141 | 0, 142 | 0, 143 | 0, 144 | 2 145 | ], 146 | [ 147 | 0, 148 | 2, 149 | 0, 150 | 1, 151 | 0, 152 | 0, 153 | 1, 154 | 0, 155 | 2, 156 | 2, 157 | 2, 158 | 2 159 | ], 160 | [ 161 | 0, 162 | 0, 163 | 0, 164 | 0, 165 | 0, 166 | 0, 167 | 1, 168 | 0, 169 | 1, 170 | 0, 171 | 1, 172 | 2 173 | ], 174 | [ 175 | 0, 176 | 1, 177 | 0, 178 | 0, 179 | 0, 180 | 0, 181 | 1, 182 | 1, 183 | 2, 184 | 1, 185 | 1, 186 | 2 187 | ], 188 | [ 189 | 0, 190 | 0, 191 | 0, 192 | 0, 193 | 0, 194 | 0, 195 | 1, 196 | 0, 197 | 0, 198 | 0, 199 | 0, 200 | 2 201 | ], 202 | [ 203 | 0, 204 | 0, 205 | 0, 206 | 0, 207 | 0, 208 | 0, 209 | 0, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 2 215 | ], 216 | [ 217 | 1, 218 | 1, 219 | 1, 220 | 1, 221 | 1, 222 | 0, 223 | 1, 224 | 1, 225 | 1, 226 | 1, 227 | 1, 228 | 2 229 | ], 230 | [ 231 | 0, 232 | 0, 233 | 0, 234 | 1, 235 | 0, 236 | 0, 237 | 1, 238 | 0, 239 | 0, 240 | 0, 241 | 0, 242 | 2 243 | ], 244 | [ 245 | 0, 246 | 2, 247 | 1, 248 | 2, 249 | 0, 250 | 0, 251 | 1, 252 | 0, 253 | 2, 254 | 2, 255 | 2, 256 | 2 257 | ], 258 | [ 259 | 0, 260 | 2, 261 | 0, 262 | 1, 263 | 0, 264 | 0, 265 | 1, 266 | 0, 267 | 2, 268 | 0, 269 | 0, 270 | 2 271 | ], 272 | [ 273 | 0, 274 | 2, 275 | 1, 276 | 1, 277 | 0, 278 | 0, 279 | 1, 280 | 0, 281 | 2, 282 | 0, 283 | 0, 284 | 2 285 | ], 286 | [ 287 | 2, 288 | 2, 289 | 2, 290 | 2, 291 | 2, 292 | 2, 293 | 2, 294 | 2, 295 | 2, 296 | 2, 297 | 2, 298 | 2 299 | ] 300 | ], 301 | "rule_severities": { 302 | "bus_definition_conflict": "error", 303 | "bus_entry_needed": "error", 304 | "bus_label_syntax": "error", 305 | "bus_to_bus_conflict": "error", 306 | "bus_to_net_conflict": "error", 307 | "different_unit_footprint": "error", 308 | "different_unit_net": "error", 309 | "duplicate_reference": "error", 310 | "duplicate_sheet_names": "error", 311 | "extra_units": "error", 312 | "global_label_dangling": "warning", 313 | "hier_label_mismatch": "error", 314 | "label_dangling": "error", 315 | "lib_symbol_issues": "warning", 316 | "multiple_net_names": "warning", 317 | "net_not_bus_member": "warning", 318 | "no_connect_connected": "warning", 319 | "no_connect_dangling": "warning", 320 | "pin_not_connected": "error", 321 | "pin_not_driven": "error", 322 | "pin_to_pin": "warning", 323 | "power_pin_not_driven": "error", 324 | "similar_labels": "warning", 325 | "unannotated": "error", 326 | "unit_value_mismatch": "error", 327 | "unresolved_variable": "error", 328 | "wire_dangling": "error" 329 | } 330 | }, 331 | "libraries": { 332 | "pinned_footprint_libs": [], 333 | "pinned_symbol_libs": [] 334 | }, 335 | "meta": { 336 | "filename": "replicate_layout_fp_text.kicad_pro", 337 | "version": 1 338 | }, 339 | "net_settings": { 340 | "classes": [ 341 | { 342 | "bus_width": 12.0, 343 | "clearance": 0.2, 344 | "diff_pair_gap": 0.25, 345 | "diff_pair_via_gap": 0.25, 346 | "diff_pair_width": 0.2, 347 | "line_style": 0, 348 | "microvia_diameter": 0.3, 349 | "microvia_drill": 0.1, 350 | "name": "Default", 351 | "pcb_color": "rgba(0, 0, 0, 0.000)", 352 | "schematic_color": "rgba(0, 0, 0, 0.000)", 353 | "track_width": 0.25, 354 | "via_diameter": 0.8, 355 | "via_drill": 0.4, 356 | "wire_width": 6.0 357 | } 358 | ], 359 | "meta": { 360 | "version": 2 361 | }, 362 | "net_colors": null 363 | }, 364 | "pcbnew": { 365 | "last_paths": { 366 | "gencad": "", 367 | "idf": "", 368 | "netlist": "", 369 | "specctra_dsn": "", 370 | "step": "", 371 | "vrml": "" 372 | }, 373 | "page_layout_descr_file": "" 374 | }, 375 | "schematic": { 376 | "annotate_start_num": 0, 377 | "drawing": { 378 | "default_line_thickness": 6.0, 379 | "default_text_size": 50.0, 380 | "field_names": [], 381 | "intersheets_ref_own_page": false, 382 | "intersheets_ref_prefix": "", 383 | "intersheets_ref_short": false, 384 | "intersheets_ref_show": false, 385 | "intersheets_ref_suffix": "", 386 | "junction_size_choice": 3, 387 | "label_size_ratio": 0.375, 388 | "pin_symbol_size": 25.0, 389 | "text_offset_ratio": 0.15 390 | }, 391 | "legacy_lib_dir": "", 392 | "legacy_lib_list": [], 393 | "meta": { 394 | "version": 1 395 | }, 396 | "net_format_name": "", 397 | "ngspice": { 398 | "fix_include_paths": true, 399 | "fix_passive_vals": false, 400 | "meta": { 401 | "version": 0 402 | }, 403 | "model_mode": 0, 404 | "workbook_filename": "" 405 | }, 406 | "page_layout_descr_file": "", 407 | "plot_directory": "", 408 | "spice_adjust_passive_values": false, 409 | "spice_external_command": "spice \"%I\"", 410 | "subpart_first_id": 65, 411 | "subpart_id_separator": 0 412 | }, 413 | "sheets": [ 414 | [ 415 | "e63e39d7-6ac0-4ffd-8aa3-1841a4541b55", 416 | "" 417 | ], 418 | [ 419 | "378af8b4-af3d-46e7-89ae-deff12ca9067", 420 | "Sheet1" 421 | ], 422 | [ 423 | "da19c195-6c6c-49e8-939b-1c592390049a", 424 | "Sheet2" 425 | ], 426 | [ 427 | "ca9607c0-16b8-4085-880e-b87c3f210fd1", 428 | "Sheet3" 429 | ] 430 | ], 431 | "text_variables": {} 432 | } 433 | -------------------------------------------------------------------------------- /replicate_layout_test_project/replicate_layout_test_project.kicad_pro: -------------------------------------------------------------------------------- 1 | { 2 | "board": { 3 | "3dviewports": [], 4 | "design_settings": { 5 | "defaults": { 6 | "apply_defaults_to_fp_fields": false, 7 | "apply_defaults_to_fp_shapes": false, 8 | "apply_defaults_to_fp_text": false, 9 | "board_outline_line_width": 0.09999999999999999, 10 | "copper_line_width": 0.19999999999999998, 11 | "copper_text_italic": false, 12 | "copper_text_size_h": 1.5, 13 | "copper_text_size_v": 1.5, 14 | "copper_text_thickness": 0.3, 15 | "copper_text_upright": false, 16 | "courtyard_line_width": 0.049999999999999996, 17 | "dimension_precision": 4, 18 | "dimension_units": 3, 19 | "dimensions": { 20 | "arrow_length": 1270000, 21 | "extension_offset": 500000, 22 | "keep_text_aligned": true, 23 | "suppress_zeroes": false, 24 | "text_position": 0, 25 | "units_format": 1 26 | }, 27 | "fab_line_width": 0.09999999999999999, 28 | "fab_text_italic": false, 29 | "fab_text_size_h": 1.0, 30 | "fab_text_size_v": 1.0, 31 | "fab_text_thickness": 0.15, 32 | "fab_text_upright": false, 33 | "other_line_width": 0.15, 34 | "other_text_italic": false, 35 | "other_text_size_h": 1.0, 36 | "other_text_size_v": 1.0, 37 | "other_text_thickness": 0.15, 38 | "other_text_upright": false, 39 | "pads": { 40 | "drill": 0.762, 41 | "height": 1.524, 42 | "width": 1.524 43 | }, 44 | "silk_line_width": 0.15, 45 | "silk_text_italic": false, 46 | "silk_text_size_h": 1.0, 47 | "silk_text_size_v": 1.0, 48 | "silk_text_thickness": 0.15, 49 | "silk_text_upright": false, 50 | "zones": { 51 | "min_clearance": 0.5 52 | } 53 | }, 54 | "diff_pair_dimensions": [ 55 | { 56 | "gap": 0.0, 57 | "via_gap": 0.0, 58 | "width": 0.0 59 | } 60 | ], 61 | "drc_exclusions": [], 62 | "meta": { 63 | "version": 2 64 | }, 65 | "rule_severities": { 66 | "annular_width": "error", 67 | "clearance": "error", 68 | "connection_width": "warning", 69 | "copper_edge_clearance": "error", 70 | "copper_sliver": "warning", 71 | "courtyards_overlap": "error", 72 | "diff_pair_gap_out_of_range": "error", 73 | "diff_pair_uncoupled_length_too_long": "error", 74 | "drill_out_of_range": "error", 75 | "duplicate_footprints": "warning", 76 | "extra_footprint": "warning", 77 | "footprint": "error", 78 | "footprint_type_mismatch": "ignore", 79 | "hole_clearance": "error", 80 | "hole_near_hole": "error", 81 | "invalid_outline": "error", 82 | "isolated_copper": "warning", 83 | "item_on_disabled_layer": "error", 84 | "items_not_allowed": "error", 85 | "length_out_of_range": "error", 86 | "lib_footprint_issues": "warning", 87 | "lib_footprint_mismatch": "warning", 88 | "malformed_courtyard": "error", 89 | "microvia_drill_out_of_range": "error", 90 | "missing_courtyard": "ignore", 91 | "missing_footprint": "warning", 92 | "net_conflict": "warning", 93 | "npth_inside_courtyard": "ignore", 94 | "padstack": "warning", 95 | "pth_inside_courtyard": "ignore", 96 | "shorting_items": "error", 97 | "silk_edge_clearance": "warning", 98 | "silk_over_copper": "warning", 99 | "silk_overlap": "warning", 100 | "skew_out_of_range": "error", 101 | "solder_mask_bridge": "error", 102 | "starved_thermal": "error", 103 | "text_height": "warning", 104 | "text_thickness": "warning", 105 | "through_hole_pad_without_hole": "error", 106 | "too_many_vias": "error", 107 | "track_dangling": "warning", 108 | "track_width": "error", 109 | "tracks_crossing": "error", 110 | "unconnected_items": "error", 111 | "unresolved_variable": "error", 112 | "via_dangling": "warning", 113 | "zones_intersect": "error" 114 | }, 115 | "rules": { 116 | "max_error": 0.005, 117 | "min_clearance": 0.0, 118 | "min_connection": 0.0, 119 | "min_copper_edge_clearance": 0.0, 120 | "min_hole_clearance": 0.25, 121 | "min_hole_to_hole": 0.25, 122 | "min_microvia_diameter": 0.19999999999999998, 123 | "min_microvia_drill": 0.09999999999999999, 124 | "min_resolved_spokes": 2, 125 | "min_silk_clearance": 0.0, 126 | "min_text_height": 0.7999999999999999, 127 | "min_text_thickness": 0.08, 128 | "min_through_hole_diameter": 0.3, 129 | "min_track_width": 0.0, 130 | "min_via_annular_width": 0.09999999999999999, 131 | "min_via_diameter": 0.5, 132 | "solder_mask_clearance": 0.0, 133 | "solder_mask_min_width": 0.0, 134 | "solder_mask_to_copper_clearance": 0.0, 135 | "use_height_for_length_calcs": true 136 | }, 137 | "teardrop_options": [ 138 | { 139 | "td_onpadsmd": true, 140 | "td_onroundshapesonly": false, 141 | "td_ontrackend": false, 142 | "td_onviapad": true 143 | } 144 | ], 145 | "teardrop_parameters": [ 146 | { 147 | "td_allow_use_two_tracks": true, 148 | "td_curve_segcount": 0, 149 | "td_height_ratio": 1.0, 150 | "td_length_ratio": 0.5, 151 | "td_maxheight": 2.0, 152 | "td_maxlen": 1.0, 153 | "td_on_pad_in_zone": false, 154 | "td_target_name": "td_round_shape", 155 | "td_width_to_size_filter_ratio": 0.9 156 | }, 157 | { 158 | "td_allow_use_two_tracks": true, 159 | "td_curve_segcount": 0, 160 | "td_height_ratio": 1.0, 161 | "td_length_ratio": 0.5, 162 | "td_maxheight": 2.0, 163 | "td_maxlen": 1.0, 164 | "td_on_pad_in_zone": false, 165 | "td_target_name": "td_rect_shape", 166 | "td_width_to_size_filter_ratio": 0.9 167 | }, 168 | { 169 | "td_allow_use_two_tracks": true, 170 | "td_curve_segcount": 0, 171 | "td_height_ratio": 1.0, 172 | "td_length_ratio": 0.5, 173 | "td_maxheight": 2.0, 174 | "td_maxlen": 1.0, 175 | "td_on_pad_in_zone": false, 176 | "td_target_name": "td_track_end", 177 | "td_width_to_size_filter_ratio": 0.9 178 | } 179 | ], 180 | "track_widths": [ 181 | 0.0, 182 | 0.4, 183 | 0.6 184 | ], 185 | "tuning_pattern_settings": { 186 | "diff_pair_defaults": { 187 | "corner_radius_percentage": 100, 188 | "corner_style": 1, 189 | "max_amplitude": 1.0, 190 | "min_amplitude": 0.1, 191 | "single_sided": false, 192 | "spacing": 0.6 193 | }, 194 | "diff_pair_skew_defaults": { 195 | "corner_radius_percentage": 100, 196 | "corner_style": 1, 197 | "max_amplitude": 1.0, 198 | "min_amplitude": 0.1, 199 | "single_sided": false, 200 | "spacing": 0.6 201 | }, 202 | "single_track_defaults": { 203 | "corner_radius_percentage": 100, 204 | "corner_style": 1, 205 | "max_amplitude": 1.0, 206 | "min_amplitude": 0.1, 207 | "single_sided": false, 208 | "spacing": 0.6 209 | } 210 | }, 211 | "via_dimensions": [ 212 | { 213 | "diameter": 0.0, 214 | "drill": 0.0 215 | }, 216 | { 217 | "diameter": 1.2, 218 | "drill": 0.5 219 | } 220 | ], 221 | "zones_allow_external_fillets": false 222 | }, 223 | "ipc2581": { 224 | "dist": "", 225 | "distpn": "", 226 | "internal_id": "", 227 | "mfg": "", 228 | "mpn": "" 229 | }, 230 | "layer_presets": [], 231 | "viewports": [] 232 | }, 233 | "boards": [], 234 | "cvpcb": { 235 | "equivalence_files": [] 236 | }, 237 | "erc": { 238 | "erc_exclusions": [], 239 | "meta": { 240 | "version": 0 241 | }, 242 | "pin_map": [ 243 | [ 244 | 0, 245 | 0, 246 | 0, 247 | 0, 248 | 0, 249 | 0, 250 | 1, 251 | 0, 252 | 0, 253 | 0, 254 | 0, 255 | 2 256 | ], 257 | [ 258 | 0, 259 | 2, 260 | 0, 261 | 1, 262 | 0, 263 | 0, 264 | 1, 265 | 0, 266 | 2, 267 | 2, 268 | 2, 269 | 2 270 | ], 271 | [ 272 | 0, 273 | 0, 274 | 0, 275 | 0, 276 | 0, 277 | 0, 278 | 1, 279 | 0, 280 | 1, 281 | 0, 282 | 1, 283 | 2 284 | ], 285 | [ 286 | 0, 287 | 1, 288 | 0, 289 | 0, 290 | 0, 291 | 0, 292 | 1, 293 | 1, 294 | 2, 295 | 1, 296 | 1, 297 | 2 298 | ], 299 | [ 300 | 0, 301 | 0, 302 | 0, 303 | 0, 304 | 0, 305 | 0, 306 | 1, 307 | 0, 308 | 0, 309 | 0, 310 | 0, 311 | 2 312 | ], 313 | [ 314 | 0, 315 | 0, 316 | 0, 317 | 0, 318 | 0, 319 | 0, 320 | 0, 321 | 0, 322 | 0, 323 | 0, 324 | 0, 325 | 2 326 | ], 327 | [ 328 | 1, 329 | 1, 330 | 1, 331 | 1, 332 | 1, 333 | 0, 334 | 1, 335 | 1, 336 | 1, 337 | 1, 338 | 1, 339 | 2 340 | ], 341 | [ 342 | 0, 343 | 0, 344 | 0, 345 | 1, 346 | 0, 347 | 0, 348 | 1, 349 | 0, 350 | 0, 351 | 0, 352 | 0, 353 | 2 354 | ], 355 | [ 356 | 0, 357 | 2, 358 | 1, 359 | 2, 360 | 0, 361 | 0, 362 | 1, 363 | 0, 364 | 2, 365 | 2, 366 | 2, 367 | 2 368 | ], 369 | [ 370 | 0, 371 | 2, 372 | 0, 373 | 1, 374 | 0, 375 | 0, 376 | 1, 377 | 0, 378 | 2, 379 | 0, 380 | 0, 381 | 2 382 | ], 383 | [ 384 | 0, 385 | 2, 386 | 1, 387 | 1, 388 | 0, 389 | 0, 390 | 1, 391 | 0, 392 | 2, 393 | 0, 394 | 0, 395 | 2 396 | ], 397 | [ 398 | 2, 399 | 2, 400 | 2, 401 | 2, 402 | 2, 403 | 2, 404 | 2, 405 | 2, 406 | 2, 407 | 2, 408 | 2, 409 | 2 410 | ] 411 | ], 412 | "rule_severities": { 413 | "bus_definition_conflict": "error", 414 | "bus_entry_needed": "error", 415 | "bus_to_bus_conflict": "error", 416 | "bus_to_net_conflict": "error", 417 | "conflicting_netclasses": "error", 418 | "different_unit_footprint": "error", 419 | "different_unit_net": "error", 420 | "duplicate_reference": "error", 421 | "duplicate_sheet_names": "error", 422 | "endpoint_off_grid": "warning", 423 | "extra_units": "error", 424 | "global_label_dangling": "warning", 425 | "hier_label_mismatch": "error", 426 | "label_dangling": "error", 427 | "lib_symbol_issues": "warning", 428 | "missing_bidi_pin": "warning", 429 | "missing_input_pin": "warning", 430 | "missing_power_pin": "error", 431 | "missing_unit": "warning", 432 | "multiple_net_names": "warning", 433 | "net_not_bus_member": "warning", 434 | "no_connect_connected": "warning", 435 | "no_connect_dangling": "warning", 436 | "pin_not_connected": "error", 437 | "pin_not_driven": "error", 438 | "pin_to_pin": "warning", 439 | "power_pin_not_driven": "error", 440 | "similar_labels": "warning", 441 | "simulation_model_issue": "ignore", 442 | "unannotated": "error", 443 | "unit_value_mismatch": "error", 444 | "unresolved_variable": "error", 445 | "wire_dangling": "error" 446 | } 447 | }, 448 | "libraries": { 449 | "pinned_footprint_libs": [], 450 | "pinned_symbol_libs": [] 451 | }, 452 | "meta": { 453 | "filename": "replicate_layout_test_project.kicad_pro", 454 | "version": 1 455 | }, 456 | "net_settings": { 457 | "classes": [ 458 | { 459 | "bus_width": 12, 460 | "clearance": 0.2, 461 | "diff_pair_gap": 0.25, 462 | "diff_pair_via_gap": 0.25, 463 | "diff_pair_width": 0.2, 464 | "line_style": 0, 465 | "microvia_diameter": 0.3, 466 | "microvia_drill": 0.1, 467 | "name": "Default", 468 | "pcb_color": "rgba(0, 0, 0, 0.000)", 469 | "schematic_color": "rgba(0, 0, 0, 0.000)", 470 | "track_width": 0.25, 471 | "via_diameter": 0.8, 472 | "via_drill": 0.4, 473 | "wire_width": 6 474 | } 475 | ], 476 | "meta": { 477 | "version": 3 478 | }, 479 | "net_colors": { 480 | "+15V": "rgb(255, 0, 0)", 481 | "-15V": "rgb(0, 194, 0)", 482 | "GND": "rgb(0, 0, 255)" 483 | }, 484 | "netclass_assignments": null, 485 | "netclass_patterns": [] 486 | }, 487 | "pcbnew": { 488 | "last_paths": { 489 | "gencad": "", 490 | "idf": "", 491 | "netlist": "", 492 | "plot": "", 493 | "pos_files": "", 494 | "specctra_dsn": "", 495 | "step": "", 496 | "svg": "", 497 | "vrml": "" 498 | }, 499 | "page_layout_descr_file": "" 500 | }, 501 | "schematic": { 502 | "annotate_start_num": 0, 503 | "bom_fmt_presets": [], 504 | "bom_fmt_settings": { 505 | "field_delimiter": ",", 506 | "keep_line_breaks": false, 507 | "keep_tabs": false, 508 | "name": "CSV", 509 | "ref_delimiter": ",", 510 | "ref_range_delimiter": "", 511 | "string_delimiter": "\"" 512 | }, 513 | "bom_presets": [], 514 | "bom_settings": { 515 | "exclude_dnp": false, 516 | "fields_ordered": [ 517 | { 518 | "group_by": false, 519 | "label": "Reference", 520 | "name": "Reference", 521 | "show": true 522 | }, 523 | { 524 | "group_by": true, 525 | "label": "Value", 526 | "name": "Value", 527 | "show": true 528 | }, 529 | { 530 | "group_by": false, 531 | "label": "Datasheet", 532 | "name": "Datasheet", 533 | "show": true 534 | }, 535 | { 536 | "group_by": false, 537 | "label": "Footprint", 538 | "name": "Footprint", 539 | "show": true 540 | }, 541 | { 542 | "group_by": false, 543 | "label": "Qty", 544 | "name": "${QUANTITY}", 545 | "show": true 546 | }, 547 | { 548 | "group_by": true, 549 | "label": "DNP", 550 | "name": "${DNP}", 551 | "show": true 552 | } 553 | ], 554 | "filter_string": "", 555 | "group_symbols": true, 556 | "name": "Grouped By Value", 557 | "sort_asc": true, 558 | "sort_field": "Reference" 559 | }, 560 | "connection_grid_size": 50.0, 561 | "drawing": { 562 | "dashed_lines_dash_length_ratio": 12.0, 563 | "dashed_lines_gap_length_ratio": 3.0, 564 | "default_line_thickness": 6.0, 565 | "default_text_size": 50.0, 566 | "field_names": [], 567 | "intersheets_ref_own_page": false, 568 | "intersheets_ref_prefix": "", 569 | "intersheets_ref_short": false, 570 | "intersheets_ref_show": false, 571 | "intersheets_ref_suffix": "", 572 | "junction_size_choice": 3, 573 | "label_size_ratio": 0.375, 574 | "operating_point_overlay_i_precision": 3, 575 | "operating_point_overlay_i_range": "~A", 576 | "operating_point_overlay_v_precision": 3, 577 | "operating_point_overlay_v_range": "~V", 578 | "overbar_offset_ratio": 1.23, 579 | "pin_symbol_size": 25.0, 580 | "text_offset_ratio": 0.15 581 | }, 582 | "legacy_lib_dir": "", 583 | "legacy_lib_list": [], 584 | "meta": { 585 | "version": 1 586 | }, 587 | "net_format_name": "", 588 | "page_layout_descr_file": "", 589 | "plot_directory": "", 590 | "spice_current_sheet_as_root": false, 591 | "spice_external_command": "spice \"%I\"", 592 | "spice_model_current_sheet_as_root": true, 593 | "spice_save_all_currents": false, 594 | "spice_save_all_dissipations": false, 595 | "spice_save_all_voltages": false, 596 | "subpart_first_id": 65, 597 | "subpart_id_separator": 0 598 | }, 599 | "sheets": [ 600 | [ 601 | "f74f526d-8f11-48ad-9d53-7c2f3f9650e8", 602 | "Root" 603 | ], 604 | [ 605 | "4ca1ab63-9c14-412d-87f4-6aa38cef6e23", 606 | "Cascade" 607 | ], 608 | [ 609 | "22b92363-03f5-44db-b14f-8953f0f635c9", 610 | "Cascade1" 611 | ], 612 | [ 613 | "5373f2bb-9d53-4847-a6f8-a066e3ee75b5", 614 | "low_pass1" 615 | ], 616 | [ 617 | "5ba9b64b-8d37-455c-abcf-29859e5ab8df", 618 | "Cascade2" 619 | ], 620 | [ 621 | "2cf73403-1c6c-45fb-8b05-dd922a741106", 622 | "Cascade3" 623 | ], 624 | [ 625 | "76ec9d82-785d-40b9-8c12-2a92b321b773", 626 | "low_pass" 627 | ], 628 | [ 629 | "76ec9d82-785d-40b9-8c12-2a92b321b773", 630 | "low_pass" 631 | ], 632 | [ 633 | "5373f2bb-9d53-4847-a6f8-a066e3ee75b5", 634 | "low_pass1" 635 | ], 636 | [ 637 | "76ec9d82-785d-40b9-8c12-2a92b321b773", 638 | "low_pass" 639 | ], 640 | [ 641 | "5373f2bb-9d53-4847-a6f8-a066e3ee75b5", 642 | "low_pass1" 643 | ], 644 | [ 645 | "76ec9d82-785d-40b9-8c12-2a92b321b773", 646 | "low_pass" 647 | ], 648 | [ 649 | "5373f2bb-9d53-4847-a6f8-a066e3ee75b5", 650 | "low_pass1" 651 | ], 652 | [ 653 | "0745450e-6fb0-406f-856f-65463d11bb73", 654 | "low_pass2" 655 | ], 656 | [ 657 | "80e48ebe-3aa0-4bd0-963d-6572afeb0ebd", 658 | "low_pass3" 659 | ] 660 | ], 661 | "text_variables": {} 662 | } 663 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /conn_issue_dialog_GUI.fbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ; 6 | Python 7 | 1 8 | source_name 9 | 0 10 | 0 11 | res 12 | UTF-8 13 | connect 14 | conn_issue_GUI 15 | 1000 16 | none 17 | 18 | 1 19 | 0 20 | ReplicateLayoutConnIssuesDialog 21 | 22 | . 23 | 24 | 1 25 | 1 26 | 1 27 | 1 28 | UI 29 | 0 30 | 0 31 | 0 32 | 33 | 0 34 | wxAUI_MGR_DEFAULT 35 | 36 | wxBOTH 37 | 38 | 1 39 | 1 40 | impl_virtual 41 | 42 | 43 | 44 | 0 45 | wxID_ANY 46 | 47 | 48 | ConnIssueGUI 49 | 50 | 346,443 51 | wxDEFAULT_DIALOG_STYLE 52 | ; ; forward_declare 53 | Replicate Layout 54 | 55 | 0 56 | 57 | 58 | 59 | 60 | 61 | bSizer1 62 | wxVERTICAL 63 | none 64 | 65 | 5 66 | wxALL 67 | 0 68 | 69 | 1 70 | 1 71 | 1 72 | 1 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 1 81 | 0 82 | 1 83 | 84 | 1 85 | 0 86 | Dock 87 | 0 88 | Left 89 | 1 90 | 91 | 1 92 | 93 | 0 94 | 0 95 | wxID_ANY 96 | Looks like the design has an exotic connectivity that is not supported by the plugin 97 | 0 98 | 99 | 0 100 | 101 | 102 | 0 103 | 104 | 1 105 | m_staticText1 106 | 1 107 | 108 | 109 | protected 110 | 1 111 | 112 | Resizable 113 | 1 114 | 115 | 116 | ; ; forward_declare 117 | 0 118 | 119 | 120 | 121 | 122 | -1 123 | 124 | 125 | 126 | 5 127 | wxALL 128 | 0 129 | 130 | 1 131 | 1 132 | 1 133 | 1 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 1 142 | 0 143 | 1 144 | 145 | 1 146 | 0 147 | Dock 148 | 0 149 | Left 150 | 1 151 | 152 | 1 153 | 154 | 0 155 | 0 156 | wxID_ANY 157 | Make sure that you check the connectivity around: 158 | 0 159 | 160 | 0 161 | 162 | 163 | 0 164 | 165 | 1 166 | m_staticText2 167 | 1 168 | 169 | 170 | protected 171 | 1 172 | 173 | Resizable 174 | 1 175 | 176 | 177 | ; ; forward_declare 178 | 0 179 | 180 | 181 | 182 | 183 | -1 184 | 185 | 186 | 187 | 5 188 | wxALL|wxEXPAND 189 | 1 190 | 191 | 1 192 | 1 193 | 1 194 | 1 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 1 203 | 0 204 | 1 205 | 206 | 1 207 | 0 208 | Dock 209 | 0 210 | Left 211 | 1 212 | 213 | 1 214 | 215 | 0 216 | 0 217 | wxID_ANY 218 | 219 | 0 220 | 221 | 222 | 0 223 | 224 | 1 225 | list 226 | 1 227 | 228 | 229 | protected 230 | 1 231 | 232 | Resizable 233 | 1 234 | 235 | wxLC_REPORT 236 | ; ; forward_declare 237 | 0 238 | 239 | 240 | wxFILTER_NONE 241 | wxDefaultValidator 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 5 250 | wxEXPAND 251 | 0 252 | 253 | 254 | bSizer2 255 | wxHORIZONTAL 256 | none 257 | 258 | 5 259 | wxEXPAND 260 | 1 261 | 262 | 0 263 | protected 264 | 0 265 | 266 | 267 | 268 | 5 269 | wxALL 270 | 0 271 | 272 | 1 273 | 1 274 | 1 275 | 1 276 | 277 | 278 | 279 | 280 | 0 281 | 282 | 283 | 284 | 285 | 1 286 | 0 287 | 1 288 | 289 | 1 290 | 291 | 0 292 | 0 293 | 294 | Dock 295 | 0 296 | Left 297 | 1 298 | 299 | 1 300 | 301 | 302 | 0 303 | 0 304 | wxID_OK 305 | Ok 306 | 307 | 0 308 | 309 | 0 310 | 311 | 312 | 0 313 | 314 | 1 315 | m_button1 316 | 1 317 | 318 | 319 | protected 320 | 1 321 | 322 | 323 | 324 | Resizable 325 | 1 326 | 327 | 328 | ; ; forward_declare 329 | 0 330 | 331 | 332 | wxFILTER_NONE 333 | wxDefaultValidator 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 5 342 | wxEXPAND 343 | 1 344 | 345 | 0 346 | protected 347 | 0 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | -------------------------------------------------------------------------------- /action_replicate_layout.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # action_replicate_layout.py 3 | # 4 | # Copyright (C) 2019-2022 Mitja Nemec 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | # MA 02110-1301, USA. 20 | # 21 | # 22 | import wx 23 | import pcbnew 24 | import os 25 | import logging 26 | import sys 27 | import time 28 | from .replicate_layout_GUI import ReplicateLayoutGUI 29 | from .error_dialog_GUI import ErrorDialogGUI 30 | from .replicate_layout import Replicator 31 | from .replicate_layout import Settings 32 | from .conn_issue_GUI import ConnIssueGUI 33 | 34 | 35 | class ConnIssueDialog(ConnIssueGUI): 36 | def SetSizeHints(self, sz1, sz2): 37 | # DO NOTHING 38 | pass 39 | 40 | def __init__(self, parent, replicator): 41 | super(ConnIssueDialog, self).__init__(parent) 42 | 43 | self.list.InsertColumn(0, 'Footprint', width=100) 44 | self.list.InsertColumn(1, 'Pad', width=100) 45 | 46 | index = 0 47 | for issue in replicator.connectivity_issues: 48 | self.list.InsertItem(index, issue[0]) 49 | self.list.SetItem(index, 1, issue[1]) 50 | index = index + 1 51 | 52 | 53 | class ErrorDialog(ErrorDialogGUI): 54 | def SetSizeHints(self, sz1, sz2): 55 | # DO NOTHING 56 | pass 57 | 58 | def __init__(self, parent): 59 | super(ErrorDialog, self).__init__(parent) 60 | 61 | 62 | class ReplicateLayoutDialog(ReplicateLayoutGUI): 63 | def SetSizeHints(self, sz1, sz2): 64 | # DO NOTHING 65 | pass 66 | 67 | def __init__(self, parent, replicator, fp_ref, logger): 68 | super(ReplicateLayoutDialog, self).__init__(parent) 69 | 70 | self.logger = logger 71 | 72 | self.replicator = replicator 73 | self.src_anchor_fp = self.replicator.get_fp_by_ref(fp_ref) 74 | self.levels = self.src_anchor_fp.filename 75 | 76 | # clear levels 77 | self.list_levels.Clear() 78 | self.list_levels.AppendItems(self.levels) 79 | 80 | self.sheet_selection = None 81 | 82 | self.src_footprints = [] 83 | self.hl_fps = [] 84 | self.hl_items = [] 85 | 86 | # select the bottom most level 87 | nr_levels = self.list_levels.GetCount() 88 | self.list_levels.SetSelection(nr_levels - 1) 89 | self.level_changed(None) 90 | 91 | def __del__(self): 92 | self.replicator.highlight_clear_level(self.hl_fps, self.hl_items) 93 | 94 | def group_layout_changed( self, event ): 95 | # when enabled, they should be checked by default 96 | if self.chkbox_group_layouts.GetValue(): 97 | self.chkbox_group_footprints.Enable(True) 98 | self.chkbox_group_footprints.SetValue(True) 99 | self.chkbox_group_tracks.Enable(True) 100 | self.chkbox_group_tracks.SetValue(True) 101 | self.chkbox_group_zones.Enable(True) 102 | self.chkbox_group_zones.SetValue(True) 103 | self.chkbox_group_text.Enable(True) 104 | self.chkbox_group_text.SetValue(True) 105 | self.chkbox_group_drawings.Enable(True) 106 | self.chkbox_group_drawings.SetValue(True) 107 | else: 108 | self.chkbox_group_footprints.Disable() 109 | self.chkbox_group_footprints.SetValue(False) 110 | self.chkbox_group_tracks.Disable() 111 | self.chkbox_group_tracks.SetValue(False) 112 | self.chkbox_group_zones.Disable() 113 | self.chkbox_group_zones.SetValue(False) 114 | self.chkbox_group_text.Disable() 115 | self.chkbox_group_text.SetValue(False) 116 | self.chkbox_group_drawings.Disable() 117 | self.chkbox_group_drawings.SetValue(False) 118 | if event is not None: 119 | event.Skip() 120 | 121 | def level_changed(self, event): 122 | index = self.list_levels.GetSelection() 123 | list_sheets_choices = self.replicator.get_sheets_to_replicate(self.src_anchor_fp, 124 | self.src_anchor_fp.sheet_id[index]) 125 | 126 | # show/hide checkbox 127 | if self.chkbox_group.GetValue(): 128 | self.chkbox_include_group_items.Disable() 129 | self.chkbox_include_group_items.SetValue(False) 130 | self.chkbox_intersecting.Disable() 131 | else: 132 | self.chkbox_include_group_items.Enable(True) 133 | self.chkbox_intersecting.Enable(True) 134 | if self.chkbox_intersecting.GetValue(): 135 | self.chkbox_include_group_items.Enable(True) 136 | else: 137 | self.chkbox_include_group_items.Disable() 138 | self.chkbox_include_group_items.SetValue(False) 139 | 140 | # clear highlight on all footprints on selected level 141 | self.replicator.highlight_clear_level(self.hl_fps, self.hl_items) 142 | self.hl_fps = [] 143 | self.hl_items = [] 144 | pcbnew.Refresh() 145 | 146 | # get anchor footprints 147 | anchor_footprints = self.replicator.get_list_of_footprints_with_same_id(self.src_anchor_fp.fp_id) 148 | # find matching anchors to matching sheets 149 | ref_list = [] 150 | for sheet in list_sheets_choices: 151 | for pf in anchor_footprints: 152 | if "/".join(sheet) in "/".join(pf.sheet_id): 153 | ref_list.append(pf.ref) 154 | break 155 | 156 | sheets_for_list = ['/'.join(x[0]) + " (" + x[1] + ")" for x in zip(list_sheets_choices, ref_list)] 157 | # clear levels 158 | self.sheet_selection = self.list_sheets.GetSelections() 159 | 160 | self.list_sheets.Clear() 161 | self.list_sheets.AppendItems(sheets_for_list) 162 | 163 | # if none is selected, select all 164 | if len(self.sheet_selection) == 0: 165 | number_of_items = self.list_sheets.GetCount() 166 | for i in range(number_of_items): 167 | self.list_sheets.Select(i) 168 | else: 169 | for n in range(len(sheets_for_list)): 170 | if n in self.sheet_selection: 171 | self.list_sheets.Select(n) 172 | else: 173 | self.list_sheets.Deselect(n) 174 | 175 | # parse the settings 176 | settings = Settings(rep_tracks=self.chkbox_tracks.GetValue(), rep_zones=self.chkbox_zones.GetValue(), 177 | rep_text=self.chkbox_text.GetValue(), rep_drawings=self.chkbox_drawings.GetValue(), 178 | group_layouts=self.chkbox_group_layouts.GetValue(), group_footprints=self.chkbox_group_footprints.GetValue(), 179 | group_tracks=self.chkbox_group_tracks.GetValue(), group_zones=self.chkbox_group_zones.GetValue(), 180 | group_text=self.chkbox_group_text.GetValue(), group_drawings=self.chkbox_group_drawings.GetValue(), 181 | rep_locked_tracks=self.chkbox_locked_tracks.GetValue(), rep_locked_zones=self.chkbox_locked_zones.GetValue(), 182 | rep_locked_text=self.chkbox_locked_text.GetValue(), rep_locked_drawings=self.chkbox_locked_drawings.GetValue(), 183 | intersecting=self.chkbox_intersecting.GetValue(), group_items=self.chkbox_include_group_items.GetValue(), 184 | group_only=self.chkbox_group.GetValue(), locked_fps=self.chkbox_locked.GetValue(), 185 | remove=self.chkbox_remove.GetValue()) 186 | 187 | # highlight all footprints on selected level 188 | (self.hl_fps, self.hl_items) = self.replicator.highlight_set_level(self.src_anchor_fp.sheet_id[0:self.list_levels.GetSelection() + 1], 189 | settings) 190 | pcbnew.Refresh() 191 | 192 | if event is not None: 193 | event.Skip() 194 | 195 | def on_ok(self, event): 196 | # clear highlight on all footprints on selected level 197 | # so that duplicated tracks don't remain selected 198 | self.replicator.highlight_clear_level(self.hl_fps, self.hl_items) 199 | self.hl_fps = [] 200 | self.hl_items = [] 201 | 202 | selected_items = self.list_sheets.GetSelections() 203 | selected_names = [] 204 | for item in selected_items: 205 | selected_names.append(self.list_sheets.GetString(item)) 206 | 207 | # grab checkboxes 208 | remove_existing_nets_zones = self.chkbox_remove.GetValue() 209 | remove_duplicates = self.chkbox_remove_duplicates.GetValue() 210 | rep_locked = self.chkbox_locked.GetValue() 211 | group_only = self.chkbox_group.GetValue() 212 | 213 | # parse the settings 214 | settings = Settings(rep_tracks=self.chkbox_tracks.GetValue(), rep_zones=self.chkbox_zones.GetValue(), 215 | rep_text=self.chkbox_text.GetValue(), rep_drawings=self.chkbox_drawings.GetValue(), 216 | group_layouts=self.chkbox_group_layouts.GetValue(), group_footprints=self.chkbox_group_footprints.GetValue(), 217 | group_tracks=self.chkbox_group_tracks.GetValue(), group_zones=self.chkbox_group_zones.GetValue(), 218 | group_text=self.chkbox_group_text.GetValue(), group_drawings=self.chkbox_group_drawings.GetValue(), 219 | rep_locked_tracks=self.chkbox_locked_tracks.GetValue(), rep_locked_zones=self.chkbox_locked_zones.GetValue(), 220 | rep_locked_text=self.chkbox_locked_text.GetValue(), rep_locked_drawings=self.chkbox_locked_drawings.GetValue(), 221 | intersecting=self.chkbox_intersecting.GetValue(), group_items=self.chkbox_include_group_items.GetValue(), 222 | group_only=self.chkbox_group.GetValue(), locked_fps=self.chkbox_locked.GetValue(), 223 | remove=self.chkbox_remove.GetValue()) 224 | 225 | # failsafe sometimes on my machine wx does not generate a listbox event 226 | level = self.list_levels.GetSelection() 227 | selection_indices = self.list_sheets.GetSelections() 228 | sheets_on_a_level = self.replicator.get_sheets_to_replicate(self.src_anchor_fp, 229 | self.src_anchor_fp.sheet_id[level]) 230 | dst_sheets = [sheets_on_a_level[i] for i in selection_indices] 231 | 232 | # check if all the destination anchor footprints are on the same layer as source anchor footprint 233 | # first get all the anchor footprints 234 | all_dst_footprints = [] 235 | for sheet in dst_sheets: 236 | all_dst_footprints.extend(self.replicator.get_footprints_on_sheet(sheet)) 237 | dst_anchor_footprints = [x for x in all_dst_footprints if x.fp_id == self.src_anchor_fp.fp_id] 238 | 239 | # replicate now 240 | self.logger.info("Replicating layout") 241 | 242 | self.start_time = time.time() 243 | self.last_time = self.start_time 244 | self.progress_dlg = wx.ProgressDialog("Preparing for replication", "Starting plugin", maximum=100) 245 | self.progress_dlg.Show() 246 | self.progress_dlg.ToggleWindowStyle(wx.STAY_ON_TOP) 247 | self.Hide() 248 | 249 | try: 250 | # update progress dialog 251 | self.replicator.update_progress = self.update_progress 252 | self.replicator.replicate_layout(self.src_anchor_fp, self.src_anchor_fp.sheet_id[0:level + 1], 253 | dst_sheets, 254 | settings, remove_duplicates) 255 | 256 | self.logger.info("Replication complete") 257 | 258 | if self.replicator.connectivity_issues: 259 | self.logger.info("Letting the user know there are some issues with replicated design") 260 | report_string = "" 261 | for item in self.replicator.connectivity_issues: 262 | report_string = report_string + f"Footprint {item[0]}, pad {item[1]}\n" 263 | self.logger.info(f"Looks like the design has an exotic connectivity that the plugin might not" 264 | f" handle properly\n " 265 | f"Make sure that you check the connectivity around:\n" + report_string) 266 | # show dialog 267 | issue_dlg = ConnIssueDialog(self, self.replicator) 268 | issue_dlg.ShowModal() 269 | issue_dlg.Destroy() 270 | 271 | # clear highlight on all footprints on selected level 272 | self.replicator.highlight_clear_level(self.hl_fps, self.hl_items) 273 | self.hl_fps = [] 274 | self.hl_items = [] 275 | pcbnew.Refresh() 276 | 277 | logging.shutdown() 278 | self.progress_dlg.Destroy() 279 | event.Skip() 280 | self.EndModal(True) 281 | except LookupError as exception: 282 | # clear highlight on all footprints on selected level 283 | self.replicator.highlight_clear_level(self.hl_fps, self.hl_items) 284 | self.hl_fps = [] 285 | self.hl_items = [] 286 | pcbnew.Refresh() 287 | 288 | caption = 'Replicate Layout' 289 | message = str(exception) 290 | dlg = wx.MessageDialog(self, message, caption, wx.OK | wx.ICON_ERROR) 291 | dlg.ShowModal() 292 | dlg.Destroy() 293 | logging.shutdown() 294 | self.progress_dlg.Destroy() 295 | event.Skip() 296 | self.EndModal(False) 297 | return 298 | except Exception: 299 | # clear highlight on all footprints on selected level 300 | self.replicator.highlight_clear_level(self.hl_fps, self.hl_items) 301 | self.hl_fps = [] 302 | self.hl_items = [] 303 | pcbnew.Refresh() 304 | 305 | self.logger.exception("Fatal error when running Replicate layout plugin") 306 | e_dlg = ErrorDialog(self) 307 | e_dlg.ShowModal() 308 | e_dlg.Destroy() 309 | logging.shutdown() 310 | self.progress_dlg.Destroy() 311 | event.Skip() 312 | self.Destroy() 313 | 314 | def on_cancel(self, event): 315 | # clear highlight on all footprints on selected level 316 | self.replicator.highlight_clear_level(self.hl_fps, self.hl_items) 317 | self.hl_fps = [] 318 | self.hl_items = [] 319 | pcbnew.Refresh() 320 | 321 | self.logger.info("User canceled the dialog") 322 | logging.shutdown() 323 | event.Skip() 324 | 325 | self.Destroy() 326 | 327 | def update_progress(self, stage, percentage, message=None): 328 | current_time = time.time() 329 | # update GUI only every 10 ms 330 | i = int(percentage * 100) 331 | if message is not None: 332 | logging.info("updating GUI message: " + repr(message)) 333 | self.progress_dlg.Update(i, message) 334 | if (current_time - self.last_time) > 0.01: 335 | self.last_time = current_time 336 | delta_time = self.last_time - self.start_time 337 | logging.info("updating GUI with: " + repr(i)) 338 | self.progress_dlg.Update(i) 339 | 340 | 341 | class ReplicateLayout(pcbnew.ActionPlugin): 342 | def __init__(self): 343 | super(ReplicateLayout, self).__init__() 344 | 345 | self.frame = None 346 | 347 | self.name = "Replicate layout" 348 | self.category = "Replicate layout" 349 | self.description = "Replicates layout of one hierarchical sheet to other copies of the same sheet." 350 | self.icon_file_name = os.path.join( 351 | os.path.dirname(__file__), 'replicate_layout_light.png') 352 | self.dark_icon_file_name = os.path.join( 353 | os.path.dirname(__file__), 'replicate_layout_dark.png') 354 | 355 | self.debug_level = logging.INFO 356 | 357 | # plugin paths 358 | self.plugin_folder = os.path.join(os.path.dirname(os.path.abspath(__file__))) 359 | self.version_file_path = os.path.join(self.plugin_folder, 'version.txt') 360 | 361 | # load the plugin version 362 | with open(self.version_file_path) as fp: 363 | self.version = fp.readline() 364 | 365 | def defaults(self): 366 | pass 367 | 368 | def Run(self): 369 | # grab PCB editor frame 370 | self.frame = wx.FindWindowByName("PcbFrame") 371 | 372 | # load board 373 | board = pcbnew.GetBoard() 374 | pass 375 | 376 | # go to the project folder - so that log will be in proper place 377 | os.chdir(os.path.dirname(os.path.abspath(board.GetFileName()))) 378 | 379 | # Remove all handlers associated with the root logger object. 380 | for handler in logging.root.handlers[:]: 381 | logging.root.removeHandler(handler) 382 | 383 | file_handler = logging.FileHandler(filename='replicate_layout.log', mode='w') 384 | handlers = [file_handler] 385 | 386 | # set up logger 387 | logging.basicConfig(level=logging.INFO, 388 | format='%(asctime)s %(name)s %(lineno)d:%(message)s', 389 | datefmt='%m-%d %H:%M:%S', 390 | handlers=handlers) 391 | logger = logging.getLogger(__name__) 392 | logger.info("Plugin executed on: " + repr(sys.platform)) 393 | logger.info("Plugin executed with python version: " + repr(sys.version)) 394 | logger.info("KiCad build version: " + str(pcbnew.GetBuildVersion())) 395 | logger.info("Plugin version: " + self.version) 396 | logger.info("Frame repr: " + repr(self.frame)) 397 | 398 | # check if there is exactly one footprints selected 399 | selected_footprints = [x.GetReference() for x in board.GetFootprints() if x.IsSelected()] 400 | 401 | # if more or less than one show only a message box 402 | if len(selected_footprints) != 1: 403 | caption = 'Replicate layout' 404 | message = "More or less than 1 footprint selected. Please select exactly one footprint " \ 405 | "and run the script again" 406 | dlg = wx.MessageDialog(self.frame, message, caption, wx.OK | wx.ICON_INFORMATION) 407 | dlg.ShowModal() 408 | dlg.Destroy() 409 | return 410 | 411 | # this is the source anchor footprint reference 412 | src_anchor_fp_reference = selected_footprints[0] 413 | 414 | # search for the Replicate.Layout user layer where replication rooms can be defined 415 | 416 | if 'Replicate.Layout' in [board.GetLayerName(x) for x in board.GetEnabledLayers().Users()]: 417 | pass 418 | 419 | # prepare the replicator 420 | logger.info("Preparing replicator with " + src_anchor_fp_reference + " as a reference") 421 | 422 | # TODO return if replication is not possible at all 423 | try: 424 | replicator = Replicator(board, src_anchor_fp_reference) 425 | except LookupError as exception: 426 | logger.exception("Fatal error when making an instance of replicator") 427 | caption = 'Replicate Layout' 428 | message = str(exception) 429 | dlg = wx.MessageDialog(self.frame, message, caption, wx.OK | wx.ICON_ERROR) 430 | dlg.ShowModal() 431 | dlg.Destroy() 432 | logging.shutdown() 433 | return 434 | except Exception: 435 | logger.exception("Fatal error when making an instance of replicator") 436 | e_dlg = ErrorDialog(self.frame) 437 | e_dlg.ShowModal() 438 | e_dlg.Destroy() 439 | logging.shutdown() 440 | return 441 | 442 | src_anchor_fp = replicator.get_fp_by_ref(src_anchor_fp_reference) 443 | 444 | # check if source anchor footprint is on root level 445 | if len(src_anchor_fp.filename) == 0: 446 | caption = 'Replicate layout' 447 | message = "Selected anchor footprint is on the root schematic sheet. Replication is not possible." 448 | dlg = wx.MessageDialog(self.frame, message, caption, wx.OK | wx.ICON_INFORMATION) 449 | dlg.ShowModal() 450 | dlg.Destroy() 451 | return 452 | 453 | # check if there are at least two sheets pointing to same hierarchical file that the source anchor footprint belongs to 454 | count = 0 455 | for filename in replicator.dict_of_sheets.values(): 456 | # filename contain sheet name and sheet filename, check only sheet filename. 457 | if filename[1] in src_anchor_fp.filename: 458 | count = count + 1 459 | if count < 2: 460 | caption = 'Replicate layout' 461 | message = "Selected anchor footprint is on the schematic sheet which does not have multiple instances." \ 462 | " Replication is not possible." 463 | dlg = wx.MessageDialog(self.frame, message, caption, wx.OK | wx.ICON_INFORMATION) 464 | dlg.ShowModal() 465 | dlg.Destroy() 466 | return 467 | 468 | logger.info(f'source anchor footprint is {repr(src_anchor_fp.ref)}\n' 469 | f'Located on: {repr(src_anchor_fp.sheet_id)}\n' 470 | f'With filenames: {repr(src_anchor_fp.filename)}\n' 471 | f'With sheet_id:{repr(src_anchor_fp.sheet_id)}') 472 | 473 | list_of_footprints = replicator.get_list_of_footprints_with_same_id(src_anchor_fp.fp_id) 474 | nice_list = [(x.ref, x.sheet_id) for x in list_of_footprints] 475 | logger.info(f'Corresponding footprints are \n{repr(nice_list)}') 476 | 477 | if not list_of_footprints: 478 | caption = 'Replicate Layout' 479 | message = "Selected footprint is unique in the pcb (only one footprint with this ID)" 480 | dlg = wx.MessageDialog(self.frame, message, caption, wx.OK | wx.ICON_ERROR) 481 | dlg.ShowModal() 482 | dlg.Destroy() 483 | logging.shutdown() 484 | return 485 | 486 | # show dialog 487 | logger.info("Showing dialog") 488 | try: 489 | dlg = ReplicateLayoutDialog(self.frame, replicator, src_anchor_fp_reference, logger) 490 | dlg.CenterOnParent() 491 | # find position of right toolbar 492 | toolbar_pos = self.frame.FindWindowById(pcbnew.ID_V_TOOLBAR).GetScreenPosition() 493 | logger.info("Toolbar position: " + repr(toolbar_pos)) 494 | # find site of dialog 495 | size = dlg.GetSize() 496 | # place the dialog by the right toolbar 497 | dialog_position = wx.Point(toolbar_pos[0] - size[0], toolbar_pos[1]) 498 | logger.info("Dialog position: " + repr(dialog_position)) 499 | dlg.SetPosition(dialog_position) 500 | dlg.Show() 501 | except Exception: 502 | logger.exception("Fatal error when making an instance of replicator") 503 | e_dlg = ErrorDialog(self.frame) 504 | e_dlg.ShowModal() 505 | e_dlg.Destroy() 506 | logging.shutdown() 507 | return 508 | -------------------------------------------------------------------------------- /error_dialog_GUI.fbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ; 6 | Python 7 | 1 8 | source_name 9 | 0 10 | 0 11 | res 12 | UTF-8 13 | connect 14 | error_dialog_GUI 15 | 1000 16 | none 17 | 18 | 1 19 | 0 20 | SaveRestoreErrorDialog 21 | 22 | . 23 | 24 | 1 25 | 1 26 | 1 27 | 1 28 | UI 29 | 0 30 | 0 31 | 0 32 | 33 | 0 34 | wxAUI_MGR_DEFAULT 35 | 36 | wxBOTH 37 | 38 | 1 39 | 1 40 | impl_virtual 41 | 42 | 43 | 44 | 0 45 | wxID_ANY 46 | 47 | 48 | ErrorDialogGUI 49 | 50 | 458,212 51 | wxDEFAULT_DIALOG_STYLE 52 | ; ; forward_declare 53 | Replicate Layout 54 | 55 | 0 56 | 57 | 58 | 59 | 60 | 61 | bSizer1 62 | wxVERTICAL 63 | none 64 | 65 | 5 66 | wxALL 67 | 0 68 | 69 | 1 70 | 1 71 | 1 72 | 1 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 1 81 | 0 82 | 1 83 | 84 | 1 85 | 0 86 | Dock 87 | 0 88 | Left 89 | 1 90 | 91 | 1 92 | 93 | 0 94 | 0 95 | wxID_ANY 96 | Fatal error when replicating layout. You can raise an issue on GiHub page. + "Please attach the save_restore_layout.log which you should find in the project folder. 97 | 0 98 | 99 | 0 100 | 101 | 102 | 0 103 | 104 | 1 105 | m_staticText1 106 | 1 107 | 108 | 109 | protected 110 | 1 111 | 112 | Resizable 113 | 1 114 | 115 | 116 | ; ; forward_declare 117 | 0 118 | 119 | 120 | 121 | 122 | -1 123 | 124 | 125 | 126 | 5 127 | wxALL 128 | 0 129 | 130 | 1 131 | 1 132 | 1 133 | 1 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 1 142 | 0 143 | 1 144 | 145 | 1 146 | 0 147 | Dock 148 | 0 149 | Left 150 | 1 151 | 152 | 1 153 | 154 | 0 155 | 0 156 | wxID_ANY 157 | You can raise an issue on GiHub page. 158 | 0 159 | 160 | 0 161 | 162 | 163 | 0 164 | 165 | 1 166 | m_staticText3 167 | 1 168 | 169 | 170 | protected 171 | 1 172 | 173 | Resizable 174 | 1 175 | 176 | 177 | ; ; forward_declare 178 | 0 179 | 180 | 181 | 182 | 183 | -1 184 | 185 | 186 | 187 | 5 188 | wxALL 189 | 0 190 | 191 | 1 192 | 1 193 | 1 194 | 1 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 1 203 | 0 204 | 1 205 | 206 | 1 207 | 0 208 | Dock 209 | 0 210 | Left 211 | 1 212 | 213 | 1 214 | 215 | 0 216 | 0 217 | 218 | wxID_ANY 219 | https://github.com/MitjaNemec/ReplicateLayout 220 | 221 | 0 222 | 223 | 224 | 0 225 | 226 | 1 227 | m_hyperlink1 228 | 229 | 1 230 | 231 | 232 | protected 233 | 1 234 | 235 | Resizable 236 | 1 237 | 238 | wxHL_DEFAULT_STYLE 239 | ; ; forward_declare 240 | 0 241 | 242 | https://github.com/MitjaNemec/ReplicateLayout 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 5 251 | wxALL 252 | 0 253 | 254 | 1 255 | 1 256 | 1 257 | 1 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 1 266 | 0 267 | 1 268 | 269 | 1 270 | 0 271 | Dock 272 | 0 273 | Left 274 | 1 275 | 276 | 1 277 | 278 | 0 279 | 0 280 | wxID_ANY 281 | Please attach the replicate_layout.log which you should find in the project folder. 282 | 0 283 | 284 | 0 285 | 286 | 287 | 0 288 | -1,40 289 | 1 290 | m_staticText4 291 | 1 292 | 293 | 294 | protected 295 | 1 296 | 297 | Resizable 298 | 1 299 | 300 | 301 | ; ; forward_declare 302 | 0 303 | 304 | 305 | 306 | 307 | -1 308 | 309 | 310 | 311 | 5 312 | wxEXPAND 313 | 1 314 | 315 | 316 | bSizer3 317 | wxHORIZONTAL 318 | none 319 | 320 | 5 321 | wxEXPAND 322 | 1 323 | 324 | 0 325 | protected 326 | 0 327 | 328 | 329 | 330 | 5 331 | wxALL 332 | 0 333 | 334 | 1 335 | 1 336 | 1 337 | 1 338 | 339 | 340 | 341 | 342 | 0 343 | 344 | 345 | 346 | 347 | 1 348 | 0 349 | 1 350 | 351 | 1 352 | 353 | 0 354 | 0 355 | 356 | Dock 357 | 0 358 | Left 359 | 1 360 | 361 | 1 362 | 363 | 364 | 0 365 | 0 366 | wxID_OK 367 | Ok 368 | 369 | 0 370 | 371 | 0 372 | 373 | 374 | 0 375 | 376 | 1 377 | btn_ok 378 | 1 379 | 380 | 381 | protected 382 | 1 383 | 384 | 385 | 386 | Resizable 387 | 1 388 | 389 | 390 | ; ; forward_declare 391 | 0 392 | 393 | 394 | wxFILTER_NONE 395 | wxDefaultValidator 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 5 404 | wxEXPAND 405 | 1 406 | 407 | 0 408 | protected 409 | 0 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | -------------------------------------------------------------------------------- /replicate_layout_fp_text/replicate_layout_fp_text.kicad_sch: -------------------------------------------------------------------------------- 1 | (kicad_sch (version 20211123) (generator eeschema) 2 | 3 | (uuid e63e39d7-6ac0-4ffd-8aa3-1841a4541b55) 4 | 5 | (paper "A4") 6 | 7 | (lib_symbols 8 | ) 9 | 10 | 11 | (sheet (at 127 50.8) (size 26.67 25.4) (fields_autoplaced) 12 | (stroke (width 0.1524) (type solid) (color 132 0 132 1)) 13 | (fill (color 0 0 0 1.0000)) 14 | (uuid 378af8b4-af3d-46e7-89ae-deff12ca9067) 15 | (property "Sheet name" "Sheet1" (id 0) (at 127 50.0884 0) 16 | (effects (font (size 1.27 1.27)) (justify left bottom)) 17 | ) 18 | (property "Sheet file" "Sheet.kicad_sch" (id 1) (at 127 76.7846 0) 19 | (effects (font (size 1.27 1.27)) (justify left top)) 20 | ) 21 | ) 22 | 23 | (sheet (at 125.73 127) (size 26.67 25.4) (fields_autoplaced) 24 | (stroke (width 0.1524) (type solid) (color 132 0 132 1)) 25 | (fill (color 0 0 0 1.0000)) 26 | (uuid ca9607c0-16b8-4085-880e-b87c3f210fd1) 27 | (property "Sheet name" "Sheet3" (id 0) (at 125.73 126.2884 0) 28 | (effects (font (size 1.27 1.27)) (justify left bottom)) 29 | ) 30 | (property "Sheet file" "Sheet.kicad_sch" (id 1) (at 125.73 152.9846 0) 31 | (effects (font (size 1.27 1.27)) (justify left top)) 32 | ) 33 | ) 34 | 35 | (sheet (at 127 88.9) (size 26.67 25.4) (fields_autoplaced) 36 | (stroke (width 0.1524) (type solid) (color 132 0 132 1)) 37 | (fill (color 0 0 0 1.0000)) 38 | (uuid da19c195-6c6c-49e8-939b-1c592390049a) 39 | (property "Sheet name" "Sheet2" (id 0) (at 127 88.1884 0) 40 | (effects (font (size 1.27 1.27)) (justify left bottom)) 41 | ) 42 | (property "Sheet file" "Sheet.kicad_sch" (id 1) (at 127 114.8846 0) 43 | (effects (font (size 1.27 1.27)) (justify left top)) 44 | ) 45 | ) 46 | 47 | (sheet_instances 48 | (path "/" (page "1")) 49 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067" (page "2")) 50 | (path "/da19c195-6c6c-49e8-939b-1c592390049a" (page "3")) 51 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1" (page "4")) 52 | ) 53 | 54 | (symbol_instances 55 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/15ddbae8-4879-44da-8c42-497366b84781" 56 | (reference "R201") (unit 1) (value "1k") (footprint "Passives:R1206M") 57 | ) 58 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/0f924b75-883b-4726-a9f0-fbdae6b526a3" 59 | (reference "R202") (unit 1) (value "1k") (footprint "Passives:R1206M") 60 | ) 61 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/e2482bc1-8d09-4ceb-8e49-1d592e89906a" 62 | (reference "R203") (unit 1) (value "1k") (footprint "Passives:R1206M") 63 | ) 64 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/05390dba-b5d7-47a9-bca8-3e163cc85a75" 65 | (reference "R204") (unit 1) (value "1k") (footprint "Passives:R1206M") 66 | ) 67 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/59ed8af0-a823-4780-ab52-6ec1f226ef60" 68 | (reference "R205") (unit 1) (value "1k") (footprint "Passives:R1206M") 69 | ) 70 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/71d5f245-1580-41c1-8d0f-8154173223a7" 71 | (reference "R206") (unit 1) (value "1k") (footprint "Passives:R1206M") 72 | ) 73 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/7ce872a9-43a7-4664-aab5-86af1c74aee4" 74 | (reference "R207") (unit 1) (value "1k") (footprint "Passives:R1206M") 75 | ) 76 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/7b075ef6-34f5-497d-b2c4-d126c3850d1c" 77 | (reference "R208") (unit 1) (value "1k") (footprint "Passives:R1206M") 78 | ) 79 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/46fe53bc-7e23-4e72-b64a-08723b42c8bd" 80 | (reference "R209") (unit 1) (value "1k") (footprint "Passives:R1206M") 81 | ) 82 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/06f135b0-5a72-42f6-8eb8-4a2e09ed4110" 83 | (reference "R210") (unit 1) (value "1k") (footprint "Passives:R1206M") 84 | ) 85 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/b30b0f89-aa4f-4480-90bd-1eefefaddb66" 86 | (reference "R211") (unit 1) (value "1k") (footprint "Passives:R1206M") 87 | ) 88 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/7939f31e-8adc-4b67-b1d0-cec7debc10fa" 89 | (reference "R212") (unit 1) (value "1k") (footprint "Passives:R1206M") 90 | ) 91 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/5cdbd729-8fc8-4e3c-aeca-cc441b06d9af" 92 | (reference "R213") (unit 1) (value "1k") (footprint "Passives:R1206M") 93 | ) 94 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/205a3b57-99d5-435b-9c92-8597aceee934" 95 | (reference "R214") (unit 1) (value "1k") (footprint "Passives:R1206M") 96 | ) 97 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/fb3a4ec9-1881-4bf8-b816-36a975625905" 98 | (reference "R215") (unit 1) (value "1k") (footprint "Passives:R1206M") 99 | ) 100 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/560f6ba2-e4b7-4480-8b97-af0bc6c466fd" 101 | (reference "R216") (unit 1) (value "1k") (footprint "Passives:R1206M") 102 | ) 103 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/5f002e26-9f3c-4fa7-9cee-9e93de95edd5" 104 | (reference "R217") (unit 1) (value "1k") (footprint "Passives:R1206M") 105 | ) 106 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/ff6e12d1-9d56-4da5-b640-9d620ade4313" 107 | (reference "R218") (unit 1) (value "1k") (footprint "Passives:R1206M") 108 | ) 109 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/00c7f158-18a1-4d5d-8258-3a26fd0c9e5f" 110 | (reference "R219") (unit 1) (value "1k") (footprint "Passives:R1206M") 111 | ) 112 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/d75f1129-bee5-4ab7-81cd-7c7bcd3583a9" 113 | (reference "R220") (unit 1) (value "1k") (footprint "Passives:R1206M") 114 | ) 115 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/6689618e-3bef-426e-8dde-df9666e088f9" 116 | (reference "R221") (unit 1) (value "1k") (footprint "Passives:R1206M") 117 | ) 118 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/b092272b-afc2-4b95-b23e-48c3d3080f6e" 119 | (reference "R222") (unit 1) (value "1k") (footprint "Passives:R1206M") 120 | ) 121 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/23d75705-10e1-4dec-9c10-8f67a847bef4" 122 | (reference "R223") (unit 1) (value "1k") (footprint "Passives:R1206M") 123 | ) 124 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/8317a7e5-4053-4008-9e36-c5e5d3db7393" 125 | (reference "R224") (unit 1) (value "1k") (footprint "Passives:R1206M") 126 | ) 127 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/1e151cee-a1df-4908-8bb7-90d37a9483ad" 128 | (reference "R225") (unit 1) (value "1k") (footprint "Passives:R1206M") 129 | ) 130 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/656d5144-bba0-4636-9258-4ce3ad100185" 131 | (reference "R226") (unit 1) (value "1k") (footprint "Passives:R1206M") 132 | ) 133 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/8aab1bf2-92c3-49d2-8eb4-f148f0cc9602" 134 | (reference "R227") (unit 1) (value "1k") (footprint "Passives:R1206M") 135 | ) 136 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/79716dfe-516f-45d6-a63d-82338fd4e3d1" 137 | (reference "R228") (unit 1) (value "1k") (footprint "Passives:R1206M") 138 | ) 139 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/27221c76-18fb-4284-a06e-629d61d7fc29" 140 | (reference "R229") (unit 1) (value "1k") (footprint "Passives:R1206M") 141 | ) 142 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/968145ad-4be5-4b41-a677-c805464e1e79" 143 | (reference "R230") (unit 1) (value "1k") (footprint "Passives:R1206M") 144 | ) 145 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/6db8419c-c9c5-4af8-b17e-83bcbcde9869" 146 | (reference "R231") (unit 1) (value "1k") (footprint "Passives:R1206M") 147 | ) 148 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/4a908391-c3c7-445a-85cb-d6547b9af0ea" 149 | (reference "R232") (unit 1) (value "1k") (footprint "Passives:R1206M") 150 | ) 151 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/7fe904d4-c102-438a-b0b9-992b577f7e50" 152 | (reference "R233") (unit 1) (value "1k") (footprint "Passives:R1206M") 153 | ) 154 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/a1d00cd0-731d-48b4-b99e-b104cddd0065" 155 | (reference "R234") (unit 1) (value "1k") (footprint "Passives:R1206M") 156 | ) 157 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/5ff401c7-a87a-4fd1-8ae5-e1647154fc0a" 158 | (reference "R235") (unit 1) (value "1k") (footprint "Passives:R1206M") 159 | ) 160 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/c79fda0a-bcf2-4820-a9ec-cee600cb1ecc" 161 | (reference "R236") (unit 1) (value "1k") (footprint "Passives:R1206M") 162 | ) 163 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/a54d4e72-c8b0-4d4c-9c14-37bd8179cd21" 164 | (reference "R237") (unit 1) (value "1k") (footprint "Passives:R1206M") 165 | ) 166 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/1c6d917b-43fc-4e4d-85e2-0e91344cfb35" 167 | (reference "R238") (unit 1) (value "1k") (footprint "Passives:R1206M") 168 | ) 169 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/61505e50-bdda-4a72-865d-ea36381e6120" 170 | (reference "R239") (unit 1) (value "1k") (footprint "Passives:R1206M") 171 | ) 172 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/645112f8-7c6a-413e-b56c-1a570c6751bb" 173 | (reference "R240") (unit 1) (value "1k") (footprint "Passives:R1206M") 174 | ) 175 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/e3f90a3b-c835-445d-bb21-2d126df870fb" 176 | (reference "R241") (unit 1) (value "1k") (footprint "Passives:R1206M") 177 | ) 178 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/1f14fe5d-fbb3-4753-a27d-03054fcb5da4" 179 | (reference "R242") (unit 1) (value "1k") (footprint "Passives:R1206M") 180 | ) 181 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/65b00b5d-0348-497a-b21f-80211395684e" 182 | (reference "R243") (unit 1) (value "1k") (footprint "Passives:R1206M") 183 | ) 184 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/3c1f83ca-e062-493a-8fc9-ac215d986ec1" 185 | (reference "R244") (unit 1) (value "1k") (footprint "Passives:R1206M") 186 | ) 187 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/934b0dd0-143a-406b-9e8a-003340988f33" 188 | (reference "R245") (unit 1) (value "1k") (footprint "Passives:R1206M") 189 | ) 190 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/7f61758d-230d-48e6-b265-f375400e9241" 191 | (reference "R246") (unit 1) (value "1k") (footprint "Passives:R1206M") 192 | ) 193 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/4b3869c3-c988-4bf0-804f-6039f83f76c4" 194 | (reference "R247") (unit 1) (value "1k") (footprint "Passives:R1206M") 195 | ) 196 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/96aac173-132c-4500-8c5d-c048ae4f7cf8" 197 | (reference "R248") (unit 1) (value "1k") (footprint "Passives:R1206M") 198 | ) 199 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/517c529f-7e9a-4381-b716-c3b207c12810" 200 | (reference "R249") (unit 1) (value "1k") (footprint "Passives:R1206M") 201 | ) 202 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/881ad405-cc30-41cb-bab1-5e423999c381" 203 | (reference "R250") (unit 1) (value "1k") (footprint "Passives:R1206M") 204 | ) 205 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/412a1798-6031-41e5-b71b-1bbfd8ac2f11" 206 | (reference "R251") (unit 1) (value "1k") (footprint "Passives:R1206M") 207 | ) 208 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/9d3f9cad-7534-450c-9c69-4563eb39d626" 209 | (reference "R252") (unit 1) (value "1k") (footprint "Passives:R1206M") 210 | ) 211 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/9be3a308-2e46-4df5-8bc9-65efaeca3e64" 212 | (reference "R253") (unit 1) (value "1k") (footprint "Passives:R1206M") 213 | ) 214 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/fce0368d-8542-41af-8916-ad4f8c37ba2f" 215 | (reference "R254") (unit 1) (value "1k") (footprint "Passives:R1206M") 216 | ) 217 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/8eee45e7-711f-4dfa-9b14-e0f4baea4110" 218 | (reference "R255") (unit 1) (value "1k") (footprint "Passives:R1206M") 219 | ) 220 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/58e1c615-0966-42a0-a91b-875b3d13162c" 221 | (reference "R256") (unit 1) (value "1k") (footprint "Passives:R1206M") 222 | ) 223 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/3189b42a-1bc4-44d2-800e-4c8f8d9beedb" 224 | (reference "R257") (unit 1) (value "1k") (footprint "Passives:R1206M") 225 | ) 226 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/44e1bd3e-d234-43cc-8f0d-a0110a8c0027" 227 | (reference "R258") (unit 1) (value "1k") (footprint "Passives:R1206M") 228 | ) 229 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/6d25d0f1-6405-49a4-b761-bc54617847d8" 230 | (reference "R259") (unit 1) (value "1k") (footprint "Passives:R1206M") 231 | ) 232 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/8692996b-ff76-4243-8d4e-f1e2767e31a1" 233 | (reference "R260") (unit 1) (value "1k") (footprint "Passives:R1206M") 234 | ) 235 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/12770e59-000e-426d-9d6c-17020fba0d46" 236 | (reference "R261") (unit 1) (value "1k") (footprint "Passives:R1206M") 237 | ) 238 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/95054fa1-06d5-4985-902e-0fe03894165c" 239 | (reference "R262") (unit 1) (value "1k") (footprint "Passives:R1206M") 240 | ) 241 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/88d43bbc-ed48-4ca1-a2c7-738d24a2ecef" 242 | (reference "R263") (unit 1) (value "1k") (footprint "Passives:R1206M") 243 | ) 244 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/dc23a4e1-01ed-466b-a029-4e800ad65b8d" 245 | (reference "R264") (unit 1) (value "1k") (footprint "Passives:R1206M") 246 | ) 247 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/6fe6330f-47b1-4172-b8bf-99251e5588e1" 248 | (reference "R265") (unit 1) (value "1k") (footprint "Passives:R1206M") 249 | ) 250 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/f76cbbe5-85eb-46c7-823a-15d6d832a075" 251 | (reference "R266") (unit 1) (value "1k") (footprint "Passives:R1206M") 252 | ) 253 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/3b7e42a1-a1b1-4db3-bb15-f735e137c453" 254 | (reference "R267") (unit 1) (value "1k") (footprint "Passives:R1206M") 255 | ) 256 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/fe10c99a-9c56-4111-8450-4fe288599c36" 257 | (reference "R268") (unit 1) (value "1k") (footprint "Passives:R1206M") 258 | ) 259 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/eeb414bb-fad1-422f-b9da-40a5f663239d" 260 | (reference "R269") (unit 1) (value "1k") (footprint "Passives:R1206M") 261 | ) 262 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/c4725b69-a01c-44f0-8f01-0258071626d7" 263 | (reference "R270") (unit 1) (value "1k") (footprint "Passives:R1206M") 264 | ) 265 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/8818beed-4394-49d5-a315-ab0a62a7e5e1" 266 | (reference "R271") (unit 1) (value "1k") (footprint "Passives:R1206M") 267 | ) 268 | (path "/378af8b4-af3d-46e7-89ae-deff12ca9067/57586b9f-df3d-4f08-8ab0-e0560cbe320f" 269 | (reference "R272") (unit 1) (value "1k") (footprint "Passives:R1206M") 270 | ) 271 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/15ddbae8-4879-44da-8c42-497366b84781" 272 | (reference "R301") (unit 1) (value "1k") (footprint "Passives:R1206M") 273 | ) 274 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/0f924b75-883b-4726-a9f0-fbdae6b526a3" 275 | (reference "R302") (unit 1) (value "1k") (footprint "Passives:R1206M") 276 | ) 277 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/e2482bc1-8d09-4ceb-8e49-1d592e89906a" 278 | (reference "R303") (unit 1) (value "1k") (footprint "Passives:R1206M") 279 | ) 280 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/05390dba-b5d7-47a9-bca8-3e163cc85a75" 281 | (reference "R304") (unit 1) (value "1k") (footprint "Passives:R1206M") 282 | ) 283 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/59ed8af0-a823-4780-ab52-6ec1f226ef60" 284 | (reference "R305") (unit 1) (value "1k") (footprint "Passives:R1206M") 285 | ) 286 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/71d5f245-1580-41c1-8d0f-8154173223a7" 287 | (reference "R306") (unit 1) (value "1k") (footprint "Passives:R1206M") 288 | ) 289 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/7ce872a9-43a7-4664-aab5-86af1c74aee4" 290 | (reference "R307") (unit 1) (value "1k") (footprint "Passives:R1206M") 291 | ) 292 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/7b075ef6-34f5-497d-b2c4-d126c3850d1c" 293 | (reference "R308") (unit 1) (value "1k") (footprint "Passives:R1206M") 294 | ) 295 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/46fe53bc-7e23-4e72-b64a-08723b42c8bd" 296 | (reference "R309") (unit 1) (value "1k") (footprint "Passives:R1206M") 297 | ) 298 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/06f135b0-5a72-42f6-8eb8-4a2e09ed4110" 299 | (reference "R310") (unit 1) (value "1k") (footprint "Passives:R1206M") 300 | ) 301 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/b30b0f89-aa4f-4480-90bd-1eefefaddb66" 302 | (reference "R311") (unit 1) (value "1k") (footprint "Passives:R1206M") 303 | ) 304 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/7939f31e-8adc-4b67-b1d0-cec7debc10fa" 305 | (reference "R312") (unit 1) (value "1k") (footprint "Passives:R1206M") 306 | ) 307 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/5cdbd729-8fc8-4e3c-aeca-cc441b06d9af" 308 | (reference "R313") (unit 1) (value "1k") (footprint "Passives:R1206M") 309 | ) 310 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/205a3b57-99d5-435b-9c92-8597aceee934" 311 | (reference "R314") (unit 1) (value "1k") (footprint "Passives:R1206M") 312 | ) 313 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/fb3a4ec9-1881-4bf8-b816-36a975625905" 314 | (reference "R315") (unit 1) (value "1k") (footprint "Passives:R1206M") 315 | ) 316 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/560f6ba2-e4b7-4480-8b97-af0bc6c466fd" 317 | (reference "R316") (unit 1) (value "1k") (footprint "Passives:R1206M") 318 | ) 319 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/5f002e26-9f3c-4fa7-9cee-9e93de95edd5" 320 | (reference "R317") (unit 1) (value "1k") (footprint "Passives:R1206M") 321 | ) 322 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/ff6e12d1-9d56-4da5-b640-9d620ade4313" 323 | (reference "R318") (unit 1) (value "1k") (footprint "Passives:R1206M") 324 | ) 325 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/00c7f158-18a1-4d5d-8258-3a26fd0c9e5f" 326 | (reference "R319") (unit 1) (value "1k") (footprint "Passives:R1206M") 327 | ) 328 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/d75f1129-bee5-4ab7-81cd-7c7bcd3583a9" 329 | (reference "R320") (unit 1) (value "1k") (footprint "Passives:R1206M") 330 | ) 331 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/6689618e-3bef-426e-8dde-df9666e088f9" 332 | (reference "R321") (unit 1) (value "1k") (footprint "Passives:R1206M") 333 | ) 334 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/b092272b-afc2-4b95-b23e-48c3d3080f6e" 335 | (reference "R322") (unit 1) (value "1k") (footprint "Passives:R1206M") 336 | ) 337 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/23d75705-10e1-4dec-9c10-8f67a847bef4" 338 | (reference "R323") (unit 1) (value "1k") (footprint "Passives:R1206M") 339 | ) 340 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/8317a7e5-4053-4008-9e36-c5e5d3db7393" 341 | (reference "R324") (unit 1) (value "1k") (footprint "Passives:R1206M") 342 | ) 343 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/1e151cee-a1df-4908-8bb7-90d37a9483ad" 344 | (reference "R325") (unit 1) (value "1k") (footprint "Passives:R1206M") 345 | ) 346 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/656d5144-bba0-4636-9258-4ce3ad100185" 347 | (reference "R326") (unit 1) (value "1k") (footprint "Passives:R1206M") 348 | ) 349 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/8aab1bf2-92c3-49d2-8eb4-f148f0cc9602" 350 | (reference "R327") (unit 1) (value "1k") (footprint "Passives:R1206M") 351 | ) 352 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/79716dfe-516f-45d6-a63d-82338fd4e3d1" 353 | (reference "R328") (unit 1) (value "1k") (footprint "Passives:R1206M") 354 | ) 355 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/27221c76-18fb-4284-a06e-629d61d7fc29" 356 | (reference "R329") (unit 1) (value "1k") (footprint "Passives:R1206M") 357 | ) 358 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/968145ad-4be5-4b41-a677-c805464e1e79" 359 | (reference "R330") (unit 1) (value "1k") (footprint "Passives:R1206M") 360 | ) 361 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/6db8419c-c9c5-4af8-b17e-83bcbcde9869" 362 | (reference "R331") (unit 1) (value "1k") (footprint "Passives:R1206M") 363 | ) 364 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/4a908391-c3c7-445a-85cb-d6547b9af0ea" 365 | (reference "R332") (unit 1) (value "1k") (footprint "Passives:R1206M") 366 | ) 367 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/7fe904d4-c102-438a-b0b9-992b577f7e50" 368 | (reference "R333") (unit 1) (value "1k") (footprint "Passives:R1206M") 369 | ) 370 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/a1d00cd0-731d-48b4-b99e-b104cddd0065" 371 | (reference "R334") (unit 1) (value "1k") (footprint "Passives:R1206M") 372 | ) 373 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/5ff401c7-a87a-4fd1-8ae5-e1647154fc0a" 374 | (reference "R335") (unit 1) (value "1k") (footprint "Passives:R1206M") 375 | ) 376 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/c79fda0a-bcf2-4820-a9ec-cee600cb1ecc" 377 | (reference "R336") (unit 1) (value "1k") (footprint "Passives:R1206M") 378 | ) 379 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/a54d4e72-c8b0-4d4c-9c14-37bd8179cd21" 380 | (reference "R337") (unit 1) (value "1k") (footprint "Passives:R1206M") 381 | ) 382 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/1c6d917b-43fc-4e4d-85e2-0e91344cfb35" 383 | (reference "R338") (unit 1) (value "1k") (footprint "Passives:R1206M") 384 | ) 385 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/61505e50-bdda-4a72-865d-ea36381e6120" 386 | (reference "R339") (unit 1) (value "1k") (footprint "Passives:R1206M") 387 | ) 388 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/645112f8-7c6a-413e-b56c-1a570c6751bb" 389 | (reference "R340") (unit 1) (value "1k") (footprint "Passives:R1206M") 390 | ) 391 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/e3f90a3b-c835-445d-bb21-2d126df870fb" 392 | (reference "R341") (unit 1) (value "1k") (footprint "Passives:R1206M") 393 | ) 394 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/1f14fe5d-fbb3-4753-a27d-03054fcb5da4" 395 | (reference "R342") (unit 1) (value "1k") (footprint "Passives:R1206M") 396 | ) 397 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/65b00b5d-0348-497a-b21f-80211395684e" 398 | (reference "R343") (unit 1) (value "1k") (footprint "Passives:R1206M") 399 | ) 400 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/3c1f83ca-e062-493a-8fc9-ac215d986ec1" 401 | (reference "R344") (unit 1) (value "1k") (footprint "Passives:R1206M") 402 | ) 403 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/934b0dd0-143a-406b-9e8a-003340988f33" 404 | (reference "R345") (unit 1) (value "1k") (footprint "Passives:R1206M") 405 | ) 406 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/7f61758d-230d-48e6-b265-f375400e9241" 407 | (reference "R346") (unit 1) (value "1k") (footprint "Passives:R1206M") 408 | ) 409 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/4b3869c3-c988-4bf0-804f-6039f83f76c4" 410 | (reference "R347") (unit 1) (value "1k") (footprint "Passives:R1206M") 411 | ) 412 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/96aac173-132c-4500-8c5d-c048ae4f7cf8" 413 | (reference "R348") (unit 1) (value "1k") (footprint "Passives:R1206M") 414 | ) 415 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/517c529f-7e9a-4381-b716-c3b207c12810" 416 | (reference "R349") (unit 1) (value "1k") (footprint "Passives:R1206M") 417 | ) 418 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/881ad405-cc30-41cb-bab1-5e423999c381" 419 | (reference "R350") (unit 1) (value "1k") (footprint "Passives:R1206M") 420 | ) 421 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/412a1798-6031-41e5-b71b-1bbfd8ac2f11" 422 | (reference "R351") (unit 1) (value "1k") (footprint "Passives:R1206M") 423 | ) 424 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/9d3f9cad-7534-450c-9c69-4563eb39d626" 425 | (reference "R352") (unit 1) (value "1k") (footprint "Passives:R1206M") 426 | ) 427 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/9be3a308-2e46-4df5-8bc9-65efaeca3e64" 428 | (reference "R353") (unit 1) (value "1k") (footprint "Passives:R1206M") 429 | ) 430 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/fce0368d-8542-41af-8916-ad4f8c37ba2f" 431 | (reference "R354") (unit 1) (value "1k") (footprint "Passives:R1206M") 432 | ) 433 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/8eee45e7-711f-4dfa-9b14-e0f4baea4110" 434 | (reference "R355") (unit 1) (value "1k") (footprint "Passives:R1206M") 435 | ) 436 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/58e1c615-0966-42a0-a91b-875b3d13162c" 437 | (reference "R356") (unit 1) (value "1k") (footprint "Passives:R1206M") 438 | ) 439 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/3189b42a-1bc4-44d2-800e-4c8f8d9beedb" 440 | (reference "R357") (unit 1) (value "1k") (footprint "Passives:R1206M") 441 | ) 442 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/44e1bd3e-d234-43cc-8f0d-a0110a8c0027" 443 | (reference "R358") (unit 1) (value "1k") (footprint "Passives:R1206M") 444 | ) 445 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/6d25d0f1-6405-49a4-b761-bc54617847d8" 446 | (reference "R359") (unit 1) (value "1k") (footprint "Passives:R1206M") 447 | ) 448 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/8692996b-ff76-4243-8d4e-f1e2767e31a1" 449 | (reference "R360") (unit 1) (value "1k") (footprint "Passives:R1206M") 450 | ) 451 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/12770e59-000e-426d-9d6c-17020fba0d46" 452 | (reference "R361") (unit 1) (value "1k") (footprint "Passives:R1206M") 453 | ) 454 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/95054fa1-06d5-4985-902e-0fe03894165c" 455 | (reference "R362") (unit 1) (value "1k") (footprint "Passives:R1206M") 456 | ) 457 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/88d43bbc-ed48-4ca1-a2c7-738d24a2ecef" 458 | (reference "R363") (unit 1) (value "1k") (footprint "Passives:R1206M") 459 | ) 460 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/dc23a4e1-01ed-466b-a029-4e800ad65b8d" 461 | (reference "R364") (unit 1) (value "1k") (footprint "Passives:R1206M") 462 | ) 463 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/6fe6330f-47b1-4172-b8bf-99251e5588e1" 464 | (reference "R365") (unit 1) (value "1k") (footprint "Passives:R1206M") 465 | ) 466 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/f76cbbe5-85eb-46c7-823a-15d6d832a075" 467 | (reference "R366") (unit 1) (value "1k") (footprint "Passives:R1206M") 468 | ) 469 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/3b7e42a1-a1b1-4db3-bb15-f735e137c453" 470 | (reference "R367") (unit 1) (value "1k") (footprint "Passives:R1206M") 471 | ) 472 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/fe10c99a-9c56-4111-8450-4fe288599c36" 473 | (reference "R368") (unit 1) (value "1k") (footprint "Passives:R1206M") 474 | ) 475 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/eeb414bb-fad1-422f-b9da-40a5f663239d" 476 | (reference "R369") (unit 1) (value "1k") (footprint "Passives:R1206M") 477 | ) 478 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/c4725b69-a01c-44f0-8f01-0258071626d7" 479 | (reference "R370") (unit 1) (value "1k") (footprint "Passives:R1206M") 480 | ) 481 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/8818beed-4394-49d5-a315-ab0a62a7e5e1" 482 | (reference "R371") (unit 1) (value "1k") (footprint "Passives:R1206M") 483 | ) 484 | (path "/da19c195-6c6c-49e8-939b-1c592390049a/57586b9f-df3d-4f08-8ab0-e0560cbe320f" 485 | (reference "R372") (unit 1) (value "1k") (footprint "Passives:R1206M") 486 | ) 487 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/15ddbae8-4879-44da-8c42-497366b84781" 488 | (reference "R401") (unit 1) (value "1k") (footprint "Passives:R1206M") 489 | ) 490 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/0f924b75-883b-4726-a9f0-fbdae6b526a3" 491 | (reference "R402") (unit 1) (value "1k") (footprint "Passives:R1206M") 492 | ) 493 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/e2482bc1-8d09-4ceb-8e49-1d592e89906a" 494 | (reference "R403") (unit 1) (value "1k") (footprint "Passives:R1206M") 495 | ) 496 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/05390dba-b5d7-47a9-bca8-3e163cc85a75" 497 | (reference "R404") (unit 1) (value "1k") (footprint "Passives:R1206M") 498 | ) 499 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/59ed8af0-a823-4780-ab52-6ec1f226ef60" 500 | (reference "R405") (unit 1) (value "1k") (footprint "Passives:R1206M") 501 | ) 502 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/71d5f245-1580-41c1-8d0f-8154173223a7" 503 | (reference "R406") (unit 1) (value "1k") (footprint "Passives:R1206M") 504 | ) 505 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/7ce872a9-43a7-4664-aab5-86af1c74aee4" 506 | (reference "R407") (unit 1) (value "1k") (footprint "Passives:R1206M") 507 | ) 508 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/7b075ef6-34f5-497d-b2c4-d126c3850d1c" 509 | (reference "R408") (unit 1) (value "1k") (footprint "Passives:R1206M") 510 | ) 511 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/46fe53bc-7e23-4e72-b64a-08723b42c8bd" 512 | (reference "R409") (unit 1) (value "1k") (footprint "Passives:R1206M") 513 | ) 514 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/06f135b0-5a72-42f6-8eb8-4a2e09ed4110" 515 | (reference "R410") (unit 1) (value "1k") (footprint "Passives:R1206M") 516 | ) 517 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/b30b0f89-aa4f-4480-90bd-1eefefaddb66" 518 | (reference "R411") (unit 1) (value "1k") (footprint "Passives:R1206M") 519 | ) 520 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/7939f31e-8adc-4b67-b1d0-cec7debc10fa" 521 | (reference "R412") (unit 1) (value "1k") (footprint "Passives:R1206M") 522 | ) 523 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/5cdbd729-8fc8-4e3c-aeca-cc441b06d9af" 524 | (reference "R413") (unit 1) (value "1k") (footprint "Passives:R1206M") 525 | ) 526 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/205a3b57-99d5-435b-9c92-8597aceee934" 527 | (reference "R414") (unit 1) (value "1k") (footprint "Passives:R1206M") 528 | ) 529 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/fb3a4ec9-1881-4bf8-b816-36a975625905" 530 | (reference "R415") (unit 1) (value "1k") (footprint "Passives:R1206M") 531 | ) 532 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/560f6ba2-e4b7-4480-8b97-af0bc6c466fd" 533 | (reference "R416") (unit 1) (value "1k") (footprint "Passives:R1206M") 534 | ) 535 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/5f002e26-9f3c-4fa7-9cee-9e93de95edd5" 536 | (reference "R417") (unit 1) (value "1k") (footprint "Passives:R1206M") 537 | ) 538 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/ff6e12d1-9d56-4da5-b640-9d620ade4313" 539 | (reference "R418") (unit 1) (value "1k") (footprint "Passives:R1206M") 540 | ) 541 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/00c7f158-18a1-4d5d-8258-3a26fd0c9e5f" 542 | (reference "R419") (unit 1) (value "1k") (footprint "Passives:R1206M") 543 | ) 544 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/d75f1129-bee5-4ab7-81cd-7c7bcd3583a9" 545 | (reference "R420") (unit 1) (value "1k") (footprint "Passives:R1206M") 546 | ) 547 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/6689618e-3bef-426e-8dde-df9666e088f9" 548 | (reference "R421") (unit 1) (value "1k") (footprint "Passives:R1206M") 549 | ) 550 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/b092272b-afc2-4b95-b23e-48c3d3080f6e" 551 | (reference "R422") (unit 1) (value "1k") (footprint "Passives:R1206M") 552 | ) 553 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/23d75705-10e1-4dec-9c10-8f67a847bef4" 554 | (reference "R423") (unit 1) (value "1k") (footprint "Passives:R1206M") 555 | ) 556 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/8317a7e5-4053-4008-9e36-c5e5d3db7393" 557 | (reference "R424") (unit 1) (value "1k") (footprint "Passives:R1206M") 558 | ) 559 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/1e151cee-a1df-4908-8bb7-90d37a9483ad" 560 | (reference "R425") (unit 1) (value "1k") (footprint "Passives:R1206M") 561 | ) 562 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/656d5144-bba0-4636-9258-4ce3ad100185" 563 | (reference "R426") (unit 1) (value "1k") (footprint "Passives:R1206M") 564 | ) 565 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/8aab1bf2-92c3-49d2-8eb4-f148f0cc9602" 566 | (reference "R427") (unit 1) (value "1k") (footprint "Passives:R1206M") 567 | ) 568 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/79716dfe-516f-45d6-a63d-82338fd4e3d1" 569 | (reference "R428") (unit 1) (value "1k") (footprint "Passives:R1206M") 570 | ) 571 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/27221c76-18fb-4284-a06e-629d61d7fc29" 572 | (reference "R429") (unit 1) (value "1k") (footprint "Passives:R1206M") 573 | ) 574 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/968145ad-4be5-4b41-a677-c805464e1e79" 575 | (reference "R430") (unit 1) (value "1k") (footprint "Passives:R1206M") 576 | ) 577 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/6db8419c-c9c5-4af8-b17e-83bcbcde9869" 578 | (reference "R431") (unit 1) (value "1k") (footprint "Passives:R1206M") 579 | ) 580 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/4a908391-c3c7-445a-85cb-d6547b9af0ea" 581 | (reference "R432") (unit 1) (value "1k") (footprint "Passives:R1206M") 582 | ) 583 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/7fe904d4-c102-438a-b0b9-992b577f7e50" 584 | (reference "R433") (unit 1) (value "1k") (footprint "Passives:R1206M") 585 | ) 586 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/a1d00cd0-731d-48b4-b99e-b104cddd0065" 587 | (reference "R434") (unit 1) (value "1k") (footprint "Passives:R1206M") 588 | ) 589 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/5ff401c7-a87a-4fd1-8ae5-e1647154fc0a" 590 | (reference "R435") (unit 1) (value "1k") (footprint "Passives:R1206M") 591 | ) 592 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/c79fda0a-bcf2-4820-a9ec-cee600cb1ecc" 593 | (reference "R436") (unit 1) (value "1k") (footprint "Passives:R1206M") 594 | ) 595 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/a54d4e72-c8b0-4d4c-9c14-37bd8179cd21" 596 | (reference "R437") (unit 1) (value "1k") (footprint "Passives:R1206M") 597 | ) 598 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/1c6d917b-43fc-4e4d-85e2-0e91344cfb35" 599 | (reference "R438") (unit 1) (value "1k") (footprint "Passives:R1206M") 600 | ) 601 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/61505e50-bdda-4a72-865d-ea36381e6120" 602 | (reference "R439") (unit 1) (value "1k") (footprint "Passives:R1206M") 603 | ) 604 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/645112f8-7c6a-413e-b56c-1a570c6751bb" 605 | (reference "R440") (unit 1) (value "1k") (footprint "Passives:R1206M") 606 | ) 607 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/e3f90a3b-c835-445d-bb21-2d126df870fb" 608 | (reference "R441") (unit 1) (value "1k") (footprint "Passives:R1206M") 609 | ) 610 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/1f14fe5d-fbb3-4753-a27d-03054fcb5da4" 611 | (reference "R442") (unit 1) (value "1k") (footprint "Passives:R1206M") 612 | ) 613 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/65b00b5d-0348-497a-b21f-80211395684e" 614 | (reference "R443") (unit 1) (value "1k") (footprint "Passives:R1206M") 615 | ) 616 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/3c1f83ca-e062-493a-8fc9-ac215d986ec1" 617 | (reference "R444") (unit 1) (value "1k") (footprint "Passives:R1206M") 618 | ) 619 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/934b0dd0-143a-406b-9e8a-003340988f33" 620 | (reference "R445") (unit 1) (value "1k") (footprint "Passives:R1206M") 621 | ) 622 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/7f61758d-230d-48e6-b265-f375400e9241" 623 | (reference "R446") (unit 1) (value "1k") (footprint "Passives:R1206M") 624 | ) 625 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/4b3869c3-c988-4bf0-804f-6039f83f76c4" 626 | (reference "R447") (unit 1) (value "1k") (footprint "Passives:R1206M") 627 | ) 628 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/96aac173-132c-4500-8c5d-c048ae4f7cf8" 629 | (reference "R448") (unit 1) (value "1k") (footprint "Passives:R1206M") 630 | ) 631 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/517c529f-7e9a-4381-b716-c3b207c12810" 632 | (reference "R449") (unit 1) (value "1k") (footprint "Passives:R1206M") 633 | ) 634 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/881ad405-cc30-41cb-bab1-5e423999c381" 635 | (reference "R450") (unit 1) (value "1k") (footprint "Passives:R1206M") 636 | ) 637 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/412a1798-6031-41e5-b71b-1bbfd8ac2f11" 638 | (reference "R451") (unit 1) (value "1k") (footprint "Passives:R1206M") 639 | ) 640 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/9d3f9cad-7534-450c-9c69-4563eb39d626" 641 | (reference "R452") (unit 1) (value "1k") (footprint "Passives:R1206M") 642 | ) 643 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/9be3a308-2e46-4df5-8bc9-65efaeca3e64" 644 | (reference "R453") (unit 1) (value "1k") (footprint "Passives:R1206M") 645 | ) 646 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/fce0368d-8542-41af-8916-ad4f8c37ba2f" 647 | (reference "R454") (unit 1) (value "1k") (footprint "Passives:R1206M") 648 | ) 649 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/8eee45e7-711f-4dfa-9b14-e0f4baea4110" 650 | (reference "R455") (unit 1) (value "1k") (footprint "Passives:R1206M") 651 | ) 652 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/58e1c615-0966-42a0-a91b-875b3d13162c" 653 | (reference "R456") (unit 1) (value "1k") (footprint "Passives:R1206M") 654 | ) 655 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/3189b42a-1bc4-44d2-800e-4c8f8d9beedb" 656 | (reference "R457") (unit 1) (value "1k") (footprint "Passives:R1206M") 657 | ) 658 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/44e1bd3e-d234-43cc-8f0d-a0110a8c0027" 659 | (reference "R458") (unit 1) (value "1k") (footprint "Passives:R1206M") 660 | ) 661 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/6d25d0f1-6405-49a4-b761-bc54617847d8" 662 | (reference "R459") (unit 1) (value "1k") (footprint "Passives:R1206M") 663 | ) 664 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/8692996b-ff76-4243-8d4e-f1e2767e31a1" 665 | (reference "R460") (unit 1) (value "1k") (footprint "Passives:R1206M") 666 | ) 667 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/12770e59-000e-426d-9d6c-17020fba0d46" 668 | (reference "R461") (unit 1) (value "1k") (footprint "Passives:R1206M") 669 | ) 670 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/95054fa1-06d5-4985-902e-0fe03894165c" 671 | (reference "R462") (unit 1) (value "1k") (footprint "Passives:R1206M") 672 | ) 673 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/88d43bbc-ed48-4ca1-a2c7-738d24a2ecef" 674 | (reference "R463") (unit 1) (value "1k") (footprint "Passives:R1206M") 675 | ) 676 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/dc23a4e1-01ed-466b-a029-4e800ad65b8d" 677 | (reference "R464") (unit 1) (value "1k") (footprint "Passives:R1206M") 678 | ) 679 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/6fe6330f-47b1-4172-b8bf-99251e5588e1" 680 | (reference "R465") (unit 1) (value "1k") (footprint "Passives:R1206M") 681 | ) 682 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/f76cbbe5-85eb-46c7-823a-15d6d832a075" 683 | (reference "R466") (unit 1) (value "1k") (footprint "Passives:R1206M") 684 | ) 685 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/3b7e42a1-a1b1-4db3-bb15-f735e137c453" 686 | (reference "R467") (unit 1) (value "1k") (footprint "Passives:R1206M") 687 | ) 688 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/fe10c99a-9c56-4111-8450-4fe288599c36" 689 | (reference "R468") (unit 1) (value "1k") (footprint "Passives:R1206M") 690 | ) 691 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/eeb414bb-fad1-422f-b9da-40a5f663239d" 692 | (reference "R469") (unit 1) (value "1k") (footprint "Passives:R1206M") 693 | ) 694 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/c4725b69-a01c-44f0-8f01-0258071626d7" 695 | (reference "R470") (unit 1) (value "1k") (footprint "Passives:R1206M") 696 | ) 697 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/8818beed-4394-49d5-a315-ab0a62a7e5e1" 698 | (reference "R471") (unit 1) (value "1k") (footprint "Passives:R1206M") 699 | ) 700 | (path "/ca9607c0-16b8-4085-880e-b87c3f210fd1/57586b9f-df3d-4f08-8ab0-e0560cbe320f" 701 | (reference "R472") (unit 1) (value "1k") (footprint "Passives:R1206M") 702 | ) 703 | ) 704 | ) 705 | --------------------------------------------------------------------------------