├── .gitignore ├── README.md ├── cam ├── README.md ├── STENCILcam-GTP_GBP_ONLY.cam ├── sfe-gerb274x-2layer.cam ├── sfe-gerb274x-4layer.cam └── sfe-gerb274x-6layer.cam ├── dru ├── Old │ ├── SparkFun-2-layer-ALC.dru │ ├── SparkFun-2-layer-FAB-LIMIT.dru │ ├── SparkFun-2-layer-PCBWay-LIMIT.dru │ ├── SparkFun-2-layer-STANDARD.dru │ ├── SparkFun-2-layer-TIGHT.dru │ ├── SparkFun-4-layer-BGA-Extreme.dru │ ├── SparkFun-4-layer-FAB-LIMIT.dru │ ├── SparkFun-4-layer-MicroMod.dru │ ├── SparkFun-4-layer-PCBWAY-LIMIT.dru │ └── SparkFun-4-layer-TIGHT.dru ├── README.md ├── SparkFun-2-Layer-General-JLCPCB.dru ├── SparkFun-2-Layer-Minimum-JLCPCB.dru ├── SparkFun-4-Layer-General-JLCPCB.dru ├── SparkFun-4-Layer-MicroMod-JLCPCB.dru ├── SparkFun-4-Layer-Minimum-Blind-Vias-PCBWay.dru ├── SparkFun-4-Layer-Minimum-JLCPCB.dru └── SparkFun-6-Layer-Minimum-JLCPCB.dru ├── scr └── eagle.scr └── ulp ├── 7za.exe ├── Include_String.ulp ├── SparkFun-BOM_Generator.flt ├── SparkFun-BOM_Generator.ulp ├── SparkFun-CAMmer-linux.ulp ├── SparkFun-CAMmer.ulp ├── SparkFun-Flip.ulp ├── SparkFun-Panelizer.ulp ├── SparkFun-PartCreator.ulp ├── SparkFunConfig.ulp ├── Trace-Length.ulp ├── Unrouted.ulp ├── add+mod-attributes.ulp ├── adimv4_0mm.ulp ├── autodim_in.ulp ├── autodim_mil.ulp ├── board_default.ulp ├── bom_with_library.ulp ├── drill-exactsize.ulp ├── eagleUp_export.ulp ├── eagle_to_3d.ulp ├── eagle_to_3d_3_4.ulp ├── exp-lbrs.ulp ├── exp-project-lbr.ulp ├── gerbv.exe ├── help-images ├── PartCreator-Axis-Indicators.bmp ├── PartCreator-Center-Pad.bmp ├── PartCreator-Pad-Distances.bmp └── PartCreator-Pin-Size.bmp ├── import-bmp.ulp ├── import-gerber.ulp ├── mirror-board.ulp ├── oshw-logo.ulp ├── readme.md ├── set-all-devices-attribute.ulp └── z_Include_SF_BOM.ulp /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## SparkFun Useful stuff 3 | ################# 4 | 5 | ## AVR Development 6 | *.eep 7 | *.elf 8 | *.lst 9 | *.lss 10 | *.sym 11 | *.d 12 | *.o 13 | *.srec 14 | *.map 15 | 16 | ## Notepad++ backup files 17 | *.bak 18 | 19 | ## BOM files 20 | #*bom* 21 | 22 | ## Configure files from ULPs 23 | *.cfg 24 | 25 | ## Script files generated from ULPs in ULP directory 26 | ulp/*.scr 27 | 28 | ## VScode files 29 | .vscode/* 30 | 31 | ################# 32 | ## Eclipse 33 | ################# 34 | 35 | *.pydevproject 36 | .project 37 | .metadata 38 | bin/ 39 | tmp/ 40 | *.tmp 41 | *.bak 42 | *.swp 43 | *~.nib 44 | local.properties 45 | .classpath 46 | .settings/ 47 | .loadpath 48 | 49 | # External tool builders 50 | .externalToolBuilders/ 51 | 52 | # Locally stored "Eclipse launch configurations" 53 | *.launch 54 | 55 | # CDT-specific 56 | .cproject 57 | 58 | # PDT-specific 59 | .buildpath 60 | 61 | 62 | ############# 63 | ## Eagle 64 | ############# 65 | 66 | # Ignore the board and schematic backup files 67 | *.b#? 68 | *.s#? 69 | 70 | 71 | ################# 72 | ## Visual Studio 73 | ################# 74 | 75 | ## Ignore Visual Studio temporary files, build results, and 76 | ## files generated by popular Visual Studio add-ons. 77 | 78 | # User-specific files 79 | *.suo 80 | *.user 81 | *.sln.docstates 82 | 83 | # Build results 84 | [Dd]ebug/ 85 | [Rr]elease/ 86 | *_i.c 87 | *_p.c 88 | *.ilk 89 | *.meta 90 | *.obj 91 | *.pch 92 | *.pdb 93 | *.pgc 94 | *.pgd 95 | *.rsp 96 | *.sbr 97 | *.tlb 98 | *.tli 99 | *.tlh 100 | *.tmp 101 | *.vspscc 102 | .builds 103 | *.dotCover 104 | 105 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 106 | #packages/ 107 | 108 | # Visual C++ cache files 109 | ipch/ 110 | *.aps 111 | *.ncb 112 | *.opensdf 113 | *.sdf 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | 119 | # ReSharper is a .NET coding add-in 120 | _ReSharper* 121 | 122 | # Installshield output folder 123 | [Ee]xpress 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish 137 | 138 | # Others 139 | [Bb]in 140 | [Oo]bj 141 | sql 142 | TestResults 143 | *.Cache 144 | ClientBin 145 | stylecop.* 146 | ~$* 147 | *.dbmdl 148 | Generated_Code #added for RIA/Silverlight projects 149 | 150 | # Backup & report files from converting an old project file to a newer 151 | # Visual Studio version. Backup files are not needed, because we have git ;-) 152 | _UpgradeReport_Files/ 153 | Backup*/ 154 | UpgradeLog*.XML 155 | 156 | 157 | ############ 158 | ## Windows 159 | ############ 160 | 161 | # Windows image file caches 162 | Thumbs.db 163 | 164 | # Folder config file 165 | Desktop.ini 166 | 167 | 168 | ############# 169 | ## Python 170 | ############# 171 | 172 | *.py[co] 173 | 174 | # Packages 175 | *.egg 176 | *.egg-info 177 | dist 178 | build 179 | eggs 180 | parts 181 | bin 182 | var 183 | sdist 184 | develop-eggs 185 | .installed.cfg 186 | 187 | # Installer logs 188 | pip-log.txt 189 | 190 | # Unit test / coverage reports 191 | .coverage 192 | .tox 193 | 194 | #Translations 195 | *.mo 196 | 197 | #Mr Developer 198 | .mr.developer.cfg 199 | 200 | # Mac crap 201 | .DS_Store 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun Eagle Settings 2 | ======================= 3 | These are the commonly used keyboard shortcuts, CAM and DRU configuration files for SparkFun board design. We use these files at SparkFun for all our design work. 4 | 5 | For more information about using Eagle to make a PCB see these tutorials: 6 | 7 | * [How to Install and Setup EAGLE](https://learn.sparkfun.com/tutorials/how-to-install-and-setup-eagle) 8 | * [Using EAGLE: Board Layout](https://learn.sparkfun.com/tutorials/using-eagle-board-layout) 9 | * [Using EAGLE: Schematic](https://learn.sparkfun.com/tutorials/using-eagle-schematic) 10 | 11 | Be sure to checkout [SparkFun's footprints for Eagle](https://github.com/sparkfun/SparkFun-Eagle-Libraries). 12 | 13 | Repository Contents 14 | ------------------- 15 | * **/cam** - Job files to output your 2 and 4 layer designs to [Gerber](http://en.wikipedia.org/wiki/Gerber_format) files 16 | * **/dru** - Design rules for 2 and 4 layer designs 17 | * **/scr** - Scripts for assigning keyboard shortcuts, grid sizes and layer colors 18 | * **/ulp** - Commonly used user language programs for BOM generation and library export 19 | 20 | -------------------------------------------------------------------------------- /cam/README.md: -------------------------------------------------------------------------------- 1 | CAM files 2 | ======================= 3 | The cam files allow you to define which layers are assigned to each gerber file. 4 | For example, the gerber file GTL (Gerber Top Layer) usually is defined as layer 1 (or top copper). 5 | If you are using the 4-layer cam, make sure your middle layers are properly assigned. 6 | -------------------------------------------------------------------------------- /cam/STENCILcam-GTP_GBP_ONLY.cam: -------------------------------------------------------------------------------- 1 | [CAM Processor Job] 2 | Description[en]="Generates Extended Gerber Format

\nThis CAM job consists of five sections that generate data for a two layer board.

\nYou will get five gerber files that contain data for:
\ncomponent side *.cmp
\nsolder side *.sol
\nsilkscreen component side *.plc
\nsolder stop component side *.stc
\nsolder stop solder sid *.sts
" 3 | Section=Sec_1 4 | Section=Sec_2 5 | 6 | [Sec_1] 7 | Name[en]="Top Paste" 8 | Prompt="" 9 | Device="GERBER_RS274X" 10 | Wheel=".whl" 11 | Rack="" 12 | Scale=1 13 | Output=".GTP" 14 | Flags="0 0 0 1 0 1 1" 15 | Emulate="0" 16 | Offset="0.0mil 0.0mil" 17 | Sheet=1 18 | Tolerance="0 0 0 0 0 0" 19 | Pen="0.0mil 0" 20 | Page="12000.0mil 8000.0mil" 21 | Layers=" 31" 22 | Colors=" 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 6 6 4 8 8 8 8 8 8 8 8 8 8 8 8 8 4 4 1 1 1 1 3 3 1 2 6 8 8 5 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 2 4 3 6 6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0" 23 | 24 | [Sec_2] 25 | Name[en]="Bottom Paste" 26 | Prompt="" 27 | Device="GERBER_RS274X" 28 | Wheel=".whl" 29 | Rack="" 30 | Scale=1 31 | Output=".GBP" 32 | Flags="0 0 0 1 0 1 1" 33 | Emulate="0" 34 | Offset="0.0mil 0.0mil" 35 | Sheet=1 36 | Tolerance="0 0 0 0 0 0" 37 | Pen="0.0mil 0" 38 | Page="12000.0mil 8000.0mil" 39 | Layers=" 32" 40 | Colors=" 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 6 6 4 8 8 8 8 8 8 8 8 8 8 8 8 8 4 4 1 1 1 1 3 3 1 2 6 8 8 5 8 8 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 2 4 3 6 6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0" 41 | -------------------------------------------------------------------------------- /cam/sfe-gerb274x-2layer.cam: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "email": "nathan@sparkfun.com", 4 | "name": "Nathan Seidle" 5 | }, 6 | "description": { 7 | "EN": "SparkFun 2 layer CAM job. Compatible with EAGLE v8+ new CAM processor. Use with the SparkFun-CAMMER.ulp to automatically process, zip, and preview gerber output in one button click!" 8 | }, 9 | "output_type": "directory", 10 | "outputs": [ 11 | { 12 | "filename_prefix": "CAMOutputs/GerberFiles", 13 | "format_specifier": { 14 | "decimal": 4, 15 | "integer": 3 16 | }, 17 | "generate_job_file": false, 18 | "output_type": "gerber", 19 | "outputs": [ 20 | { 21 | "advanced_options": { 22 | "mirror": false, 23 | "offset_x": 0, 24 | "offset_y": 0, 25 | "rotate": false, 26 | "upside_down": false 27 | }, 28 | "board_outline": false, 29 | "config": { 30 | "file_function": "Copper", 31 | "layer": 1, 32 | "layer_details": "mixed", 33 | "layer_type": "top" 34 | }, 35 | "filename_format": "%N.GTL", 36 | "layers": [ 37 | 1, 38 | 17, 39 | 18 40 | ], 41 | "name": "Top Copper", 42 | "polarity": "positive", 43 | "type": "gerber_layer" 44 | }, 45 | { 46 | "advanced_options": { 47 | "mirror": false, 48 | "offset_x": 0, 49 | "offset_y": 0, 50 | "rotate": false, 51 | "upside_down": false 52 | }, 53 | "board_outline": false, 54 | "config": { 55 | "file_function": "Copper", 56 | "layer": 2, 57 | "layer_details": "mixed", 58 | "layer_type": "bottom" 59 | }, 60 | "filename_format": "%N.GBL", 61 | "layers": [ 62 | 16, 63 | 17, 64 | 18 65 | ], 66 | "name": "Bottom Copper", 67 | "polarity": "positive", 68 | "type": "gerber_layer" 69 | }, 70 | { 71 | "advanced_options": { 72 | "mirror": false, 73 | "offset_x": 0, 74 | "offset_y": 0, 75 | "rotate": false, 76 | "upside_down": false 77 | }, 78 | "board_outline": true, 79 | "config": { 80 | "file_function": "Profile", 81 | "plating": "non-plated" 82 | }, 83 | "filename_format": "%N.GKO", 84 | "layers": [ 85 | 20, 86 | 46 87 | ], 88 | "milling": true, 89 | "polarity": "positive", 90 | "type": "gerber_layer" 91 | }, 92 | { 93 | "advanced_options": { 94 | "mirror": false, 95 | "offset_x": 0, 96 | "offset_y": 0, 97 | "rotate": false, 98 | "upside_down": false 99 | }, 100 | "board_outline": false, 101 | "config": { 102 | "file_function": "Soldermask", 103 | "index": 1, 104 | "layer_type": "top" 105 | }, 106 | "filename_format": "%N.GTS", 107 | "layers": [ 108 | 29 109 | ], 110 | "name": "Soldermask Top", 111 | "polarity": "positive", 112 | "type": "gerber_layer" 113 | }, 114 | { 115 | "advanced_options": { 116 | "mirror": false, 117 | "offset_x": 0, 118 | "offset_y": 0, 119 | "rotate": false, 120 | "upside_down": false 121 | }, 122 | "board_outline": false, 123 | "config": { 124 | "file_function": "Soldermask", 125 | "index": 1, 126 | "layer_type": "bottom" 127 | }, 128 | "filename_format": "%N.GBS", 129 | "layers": [ 130 | 30 131 | ], 132 | "name": "Soldermask Bottom", 133 | "polarity": "positive", 134 | "type": "gerber_layer" 135 | }, 136 | { 137 | "advanced_options": { 138 | "mirror": false, 139 | "offset_x": 0, 140 | "offset_y": 0, 141 | "rotate": false, 142 | "upside_down": false 143 | }, 144 | "board_outline": false, 145 | "config": { 146 | "file_function": "Paste", 147 | "layer_type": "top" 148 | }, 149 | "filename_format": "%N.GTP", 150 | "layers": [ 151 | 31 152 | ], 153 | "milling": false, 154 | "name": "Solderpaste Top", 155 | "polarity": "positive", 156 | "type": "gerber_layer" 157 | }, 158 | { 159 | "advanced_options": { 160 | "mirror": false, 161 | "offset_x": 0, 162 | "offset_y": 0, 163 | "rotate": false, 164 | "upside_down": false 165 | }, 166 | "board_outline": false, 167 | "config": { 168 | "file_function": "Paste", 169 | "layer_type": "bottom" 170 | }, 171 | "filename_format": "%N.GBP", 172 | "layers": [ 173 | 32 174 | ], 175 | "milling": false, 176 | "name": "Solderpaste Bottom", 177 | "polarity": "positive", 178 | "type": "gerber_layer" 179 | }, 180 | { 181 | "advanced_options": { 182 | "mirror": false, 183 | "offset_x": 0, 184 | "offset_y": 0, 185 | "rotate": false, 186 | "upside_down": false 187 | }, 188 | "board_outline": false, 189 | "config": { 190 | "file_function": "Legend", 191 | "index": 1, 192 | "layer_type": "top" 193 | }, 194 | "filename_format": "%N.GTO", 195 | "layers": [ 196 | 21 197 | ], 198 | "milling": false, 199 | "name": "Silkscreen Top", 200 | "polarity": "positive", 201 | "type": "gerber_layer" 202 | }, 203 | { 204 | "advanced_options": { 205 | "mirror": false, 206 | "offset_x": 0, 207 | "offset_y": 0, 208 | "rotate": false, 209 | "upside_down": false 210 | }, 211 | "board_outline": false, 212 | "config": { 213 | "file_function": "Legend", 214 | "index": 1, 215 | "layer_type": "bottom" 216 | }, 217 | "filename_format": "%N.GBO", 218 | "layers": [ 219 | 22 220 | ], 221 | "milling": false, 222 | "name": "Silkscreen Bottom", 223 | "polarity": "positive", 224 | "type": "gerber_layer" 225 | } 226 | ], 227 | "version": "RS274X" 228 | }, 229 | { 230 | "filename_prefix": "CAMOutputs/DrillFiles", 231 | "format_specifier": { 232 | "decimal": 3, 233 | "integer": 3 234 | }, 235 | "output_type": "drill", 236 | "outputs": [ 237 | { 238 | "advanced_options": { 239 | "mirror": false, 240 | "offset_x": 0, 241 | "offset_y": 0, 242 | "rotate": false, 243 | "upside_down": false 244 | }, 245 | "filename_format": "%N.TXT", 246 | "name": "Auto Drill", 247 | "type": "autodrills" 248 | } 249 | ] 250 | }, 251 | { 252 | "filename_prefix": "CAMOutputs/Assembly", 253 | "output_type": "assembly", 254 | "outputs": [ 255 | ] 256 | }, 257 | { 258 | "filename_prefix": "CAMOutputs/DrawingFiles", 259 | "output_type": "drawing", 260 | "outputs": [ 261 | ] 262 | } 263 | ], 264 | "timestamp": "2020-02-11T15:05:12", 265 | "type": "EAGLE CAM job", 266 | "units": "metric", 267 | "version": "9.2.0" 268 | } 269 | -------------------------------------------------------------------------------- /cam/sfe-gerb274x-4layer.cam: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "email": "nathan@sparkfun.com", 4 | "name": "Nathan Seidle" 5 | }, 6 | "description": { 7 | "EN": "SparkFun 4 layer CAM job. Compatible with EAGLE v8+ new CAM processor. Use with the SparkFun-CAMMER.ulp to automatically process, zip, and preview gerber output in one button click!" 8 | }, 9 | "output_type": "directory", 10 | "outputs": [ 11 | { 12 | "filename_prefix": "CAMOutputs/GerberFiles", 13 | "format_specifier": { 14 | "decimal": 4, 15 | "integer": 3 16 | }, 17 | "generate_job_file": false, 18 | "output_type": "gerber", 19 | "outputs": [ 20 | { 21 | "advanced_options": { 22 | "mirror": false, 23 | "offset_x": 0, 24 | "offset_y": 0, 25 | "rotate": false, 26 | "upside_down": false 27 | }, 28 | "board_outline": false, 29 | "config": { 30 | "file_function": "Copper", 31 | "layer": 1, 32 | "layer_details": "mixed", 33 | "layer_type": "top" 34 | }, 35 | "filename_format": "%N.GTL", 36 | "layers": [ 37 | 1, 38 | 17, 39 | 18 40 | ], 41 | "name": "Top Copper", 42 | "polarity": "positive", 43 | "type": "gerber_layer" 44 | }, 45 | { 46 | "advanced_options": { 47 | "mirror": false, 48 | "offset_x": 0, 49 | "offset_y": 0, 50 | "rotate": false, 51 | "upside_down": false 52 | }, 53 | "board_outline": false, 54 | "config": { 55 | "file_function": "Copper", 56 | "layer": 2, 57 | "layer_details": "mixed", 58 | "layer_type": "Inner" 59 | }, 60 | "filename_format": "%N.GL2", 61 | "layers": [ 62 | 17, 63 | 18, 64 | 2 65 | ], 66 | "name": "Inner Layer 2", 67 | "polarity": "positive", 68 | "type": "gerber_layer" 69 | }, 70 | { 71 | "advanced_options": { 72 | "mirror": false, 73 | "offset_x": 0, 74 | "offset_y": 0, 75 | "rotate": false, 76 | "upside_down": false 77 | }, 78 | "board_outline": false, 79 | "config": { 80 | "file_function": "Copper", 81 | "layer": 3, 82 | "layer_details": "mixed", 83 | "layer_type": "Inner" 84 | }, 85 | "filename_format": "%N.GL3", 86 | "layers": [ 87 | 17, 88 | 18, 89 | 15 90 | ], 91 | "name": "Inner Layer 15", 92 | "polarity": "positive", 93 | "type": "gerber_layer" 94 | }, 95 | { 96 | "advanced_options": { 97 | "mirror": false, 98 | "offset_x": 0, 99 | "offset_y": 0, 100 | "rotate": false, 101 | "upside_down": false 102 | }, 103 | "board_outline": false, 104 | "config": { 105 | "file_function": "Copper", 106 | "layer": 4, 107 | "layer_details": "mixed", 108 | "layer_type": "bottom" 109 | }, 110 | "filename_format": "%N.GBL", 111 | "layers": [ 112 | 16, 113 | 17, 114 | 18 115 | ], 116 | "name": "Bottom Copper", 117 | "polarity": "positive", 118 | "type": "gerber_layer" 119 | }, 120 | { 121 | "advanced_options": { 122 | "mirror": false, 123 | "offset_x": 0, 124 | "offset_y": 0, 125 | "rotate": false, 126 | "upside_down": false 127 | }, 128 | "board_outline": true, 129 | "config": { 130 | "file_function": "Profile", 131 | "plating": "non-plated" 132 | }, 133 | "filename_format": "%N.GKO", 134 | "layers": [ 135 | 20, 136 | 46 137 | ], 138 | "milling": true, 139 | "polarity": "positive", 140 | "type": "gerber_layer" 141 | }, 142 | { 143 | "advanced_options": { 144 | "mirror": false, 145 | "offset_x": 0, 146 | "offset_y": 0, 147 | "rotate": false, 148 | "upside_down": false 149 | }, 150 | "board_outline": false, 151 | "config": { 152 | "file_function": "Soldermask", 153 | "index": 1, 154 | "layer_type": "top" 155 | }, 156 | "filename_format": "%N.GTS", 157 | "layers": [ 158 | 29 159 | ], 160 | "name": "Soldermask Top", 161 | "polarity": "positive", 162 | "type": "gerber_layer" 163 | }, 164 | { 165 | "advanced_options": { 166 | "mirror": false, 167 | "offset_x": 0, 168 | "offset_y": 0, 169 | "rotate": false, 170 | "upside_down": false 171 | }, 172 | "board_outline": false, 173 | "config": { 174 | "file_function": "Soldermask", 175 | "index": 1, 176 | "layer_type": "bottom" 177 | }, 178 | "filename_format": "%N.GBS", 179 | "layers": [ 180 | 30 181 | ], 182 | "name": "Soldermask Bottom", 183 | "polarity": "positive", 184 | "type": "gerber_layer" 185 | }, 186 | { 187 | "advanced_options": { 188 | "mirror": false, 189 | "offset_x": 0, 190 | "offset_y": 0, 191 | "rotate": false, 192 | "upside_down": false 193 | }, 194 | "board_outline": false, 195 | "config": { 196 | "file_function": "Paste", 197 | "layer_type": "top" 198 | }, 199 | "filename_format": "%N.GTP", 200 | "layers": [ 201 | 31 202 | ], 203 | "milling": false, 204 | "name": "Solderpaste Top", 205 | "polarity": "positive", 206 | "type": "gerber_layer" 207 | }, 208 | { 209 | "advanced_options": { 210 | "mirror": false, 211 | "offset_x": 0, 212 | "offset_y": 0, 213 | "rotate": false, 214 | "upside_down": false 215 | }, 216 | "board_outline": false, 217 | "config": { 218 | "file_function": "Paste", 219 | "layer_type": "bottom" 220 | }, 221 | "filename_format": "%N.GBP", 222 | "layers": [ 223 | 32 224 | ], 225 | "milling": false, 226 | "name": "Solderpaste Bottom", 227 | "polarity": "positive", 228 | "type": "gerber_layer" 229 | }, 230 | { 231 | "advanced_options": { 232 | "mirror": false, 233 | "offset_x": 0, 234 | "offset_y": 0, 235 | "rotate": false, 236 | "upside_down": false 237 | }, 238 | "board_outline": false, 239 | "config": { 240 | "file_function": "Legend", 241 | "index": 1, 242 | "layer_type": "top" 243 | }, 244 | "filename_format": "%N.GTO", 245 | "layers": [ 246 | 21 247 | ], 248 | "milling": false, 249 | "name": "Silkscreen Top", 250 | "polarity": "positive", 251 | "type": "gerber_layer" 252 | }, 253 | { 254 | "advanced_options": { 255 | "mirror": false, 256 | "offset_x": 0, 257 | "offset_y": 0, 258 | "rotate": false, 259 | "upside_down": false 260 | }, 261 | "board_outline": false, 262 | "config": { 263 | "file_function": "Legend", 264 | "index": 1, 265 | "layer_type": "bottom" 266 | }, 267 | "filename_format": "%N.GBO", 268 | "layers": [ 269 | 22 270 | ], 271 | "milling": false, 272 | "name": "Silkscreen Bottom", 273 | "polarity": "positive", 274 | "type": "gerber_layer" 275 | } 276 | ], 277 | "version": "RS274X" 278 | }, 279 | { 280 | "filename_prefix": "CAMOutputs/DrillFiles", 281 | "format_specifier": { 282 | "decimal": 3, 283 | "integer": 3 284 | }, 285 | "output_type": "drill", 286 | "outputs": [ 287 | { 288 | "advanced_options": { 289 | "mirror": false, 290 | "offset_x": 0, 291 | "offset_y": 0, 292 | "rotate": false, 293 | "upside_down": false 294 | }, 295 | "filename_format": "%N.TXT", 296 | "name": "Auto Drill", 297 | "type": "autodrills" 298 | } 299 | ] 300 | }, 301 | { 302 | "filename_prefix": "CAMOutputs/Assembly", 303 | "output_type": "assembly", 304 | "outputs": [ 305 | ] 306 | }, 307 | { 308 | "filename_prefix": "CAMOutputs/DrawingFiles", 309 | "output_type": "drawing", 310 | "outputs": [ 311 | ] 312 | } 313 | ], 314 | "timestamp": "2020-02-11T15:27:02", 315 | "type": "EAGLE CAM job", 316 | "units": "metric", 317 | "version": "9.2.0" 318 | } 319 | -------------------------------------------------------------------------------- /cam/sfe-gerb274x-6layer.cam: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "email": "nathan@sparkfun.com", 4 | "name": "Nathan Seidle" 5 | }, 6 | "description": { 7 | "EN": "SparkFun 6 layer CAM job. Compatible with EAGLE v8+ new CAM processor. Use with the SparkFun-CAMMER.ulp to automatically process, zip, and preview gerber output in one button click!" 8 | }, 9 | "output_type": "directory", 10 | "outputs": [ 11 | { 12 | "filename_prefix": "CAMOutputs/GerberFiles", 13 | "format_specifier": { 14 | "decimal": 4, 15 | "integer": 3 16 | }, 17 | "generate_job_file": false, 18 | "output_type": "gerber", 19 | "outputs": [ 20 | { 21 | "advanced_options": { 22 | "mirror": false, 23 | "offset_x": 0, 24 | "offset_y": 0, 25 | "rotate": false, 26 | "upside_down": false 27 | }, 28 | "board_outline": false, 29 | "config": { 30 | "file_function": "Copper", 31 | "layer": 1, 32 | "layer_details": "mixed", 33 | "layer_type": "top" 34 | }, 35 | "filename_format": "%N.GTL", 36 | "layers": [ 37 | 1, 38 | 17, 39 | 18 40 | ], 41 | "name": "Top Copper", 42 | "polarity": "positive", 43 | "type": "gerber_layer" 44 | }, 45 | { 46 | "advanced_options": { 47 | "mirror": false, 48 | "offset_x": 0, 49 | "offset_y": 0, 50 | "rotate": false, 51 | "upside_down": false 52 | }, 53 | "board_outline": false, 54 | "config": { 55 | "file_function": "Copper", 56 | "layer": 2, 57 | "layer_details": "mixed", 58 | "layer_type": "Inner" 59 | }, 60 | "filename_format": "%N.GL2", 61 | "layers": [ 62 | 17, 63 | 18, 64 | 2 65 | ], 66 | "name": "Inner Layer 2", 67 | "polarity": "positive", 68 | "type": "gerber_layer" 69 | }, 70 | { 71 | "advanced_options": { 72 | "mirror": false, 73 | "offset_x": 0, 74 | "offset_y": 0, 75 | "rotate": false, 76 | "upside_down": false 77 | }, 78 | "board_outline": false, 79 | "config": { 80 | "file_function": "Copper", 81 | "layer": 3, 82 | "layer_details": "mixed", 83 | "layer_type": "Inner" 84 | }, 85 | "filename_format": "%N.GL3", 86 | "layers": [ 87 | 17, 88 | 18, 89 | 3 90 | ], 91 | "name": "Inner Layer 3", 92 | "polarity": "positive", 93 | "type": "gerber_layer" 94 | }, 95 | { 96 | "advanced_options": { 97 | "mirror": false, 98 | "offset_x": 0, 99 | "offset_y": 0, 100 | "rotate": false, 101 | "upside_down": false 102 | }, 103 | "board_outline": false, 104 | "config": { 105 | "file_function": "Copper", 106 | "layer": 4, 107 | "layer_details": "mixed", 108 | "layer_type": "Inner" 109 | }, 110 | "filename_format": "%N.GL4", 111 | "layers": [ 112 | 17, 113 | 18, 114 | 14 115 | ], 116 | "name": "Inner Layer 14", 117 | "polarity": "positive", 118 | "type": "gerber_layer" 119 | }, 120 | { 121 | "advanced_options": { 122 | "mirror": false, 123 | "offset_x": 0, 124 | "offset_y": 0, 125 | "rotate": false, 126 | "upside_down": false 127 | }, 128 | "board_outline": false, 129 | "config": { 130 | "file_function": "Copper", 131 | "layer": 5, 132 | "layer_details": "mixed", 133 | "layer_type": "Inner" 134 | }, 135 | "filename_format": "%N.GL5", 136 | "layers": [ 137 | 17, 138 | 18, 139 | 15 140 | ], 141 | "name": "Inner Layer 15", 142 | "polarity": "positive", 143 | "type": "gerber_layer" 144 | }, 145 | { 146 | "advanced_options": { 147 | "mirror": false, 148 | "offset_x": 0, 149 | "offset_y": 0, 150 | "rotate": false, 151 | "upside_down": false 152 | }, 153 | "board_outline": false, 154 | "config": { 155 | "file_function": "Copper", 156 | "layer": 6, 157 | "layer_details": "mixed", 158 | "layer_type": "bottom" 159 | }, 160 | "filename_format": "%N.GBL", 161 | "layers": [ 162 | 16, 163 | 17, 164 | 18 165 | ], 166 | "name": "Bottom Copper", 167 | "polarity": "positive", 168 | "type": "gerber_layer" 169 | }, 170 | { 171 | "advanced_options": { 172 | "mirror": false, 173 | "offset_x": 0, 174 | "offset_y": 0, 175 | "rotate": false, 176 | "upside_down": false 177 | }, 178 | "board_outline": true, 179 | "config": { 180 | "file_function": "Profile", 181 | "plating": "non-plated" 182 | }, 183 | "filename_format": "%N.GKO", 184 | "layers": [ 185 | 20, 186 | 46 187 | ], 188 | "milling": true, 189 | "polarity": "positive", 190 | "type": "gerber_layer" 191 | }, 192 | { 193 | "advanced_options": { 194 | "mirror": false, 195 | "offset_x": 0, 196 | "offset_y": 0, 197 | "rotate": false, 198 | "upside_down": false 199 | }, 200 | "board_outline": false, 201 | "config": { 202 | "file_function": "Soldermask", 203 | "index": 1, 204 | "layer_type": "top" 205 | }, 206 | "filename_format": "%N.GTS", 207 | "layers": [ 208 | 29 209 | ], 210 | "name": "Soldermask Top", 211 | "polarity": "positive", 212 | "type": "gerber_layer" 213 | }, 214 | { 215 | "advanced_options": { 216 | "mirror": false, 217 | "offset_x": 0, 218 | "offset_y": 0, 219 | "rotate": false, 220 | "upside_down": false 221 | }, 222 | "board_outline": false, 223 | "config": { 224 | "file_function": "Soldermask", 225 | "index": 1, 226 | "layer_type": "bottom" 227 | }, 228 | "filename_format": "%N.GBS", 229 | "layers": [ 230 | 30 231 | ], 232 | "name": "Soldermask Bottom", 233 | "polarity": "positive", 234 | "type": "gerber_layer" 235 | }, 236 | { 237 | "advanced_options": { 238 | "mirror": false, 239 | "offset_x": 0, 240 | "offset_y": 0, 241 | "rotate": false, 242 | "upside_down": false 243 | }, 244 | "board_outline": false, 245 | "config": { 246 | "file_function": "Paste", 247 | "layer_type": "top" 248 | }, 249 | "filename_format": "%N.GTP", 250 | "layers": [ 251 | 31 252 | ], 253 | "milling": false, 254 | "name": "Solderpaste Top", 255 | "polarity": "positive", 256 | "type": "gerber_layer" 257 | }, 258 | { 259 | "advanced_options": { 260 | "mirror": false, 261 | "offset_x": 0, 262 | "offset_y": 0, 263 | "rotate": false, 264 | "upside_down": false 265 | }, 266 | "board_outline": false, 267 | "config": { 268 | "file_function": "Paste", 269 | "layer_type": "bottom" 270 | }, 271 | "filename_format": "%N.GBP", 272 | "layers": [ 273 | 32 274 | ], 275 | "milling": false, 276 | "name": "Solderpaste Bottom", 277 | "polarity": "positive", 278 | "type": "gerber_layer" 279 | }, 280 | { 281 | "advanced_options": { 282 | "mirror": false, 283 | "offset_x": 0, 284 | "offset_y": 0, 285 | "rotate": false, 286 | "upside_down": false 287 | }, 288 | "board_outline": false, 289 | "config": { 290 | "file_function": "Legend", 291 | "index": 1, 292 | "layer_type": "top" 293 | }, 294 | "filename_format": "%N.GTO", 295 | "layers": [ 296 | 21 297 | ], 298 | "milling": false, 299 | "name": "Silkscreen Top", 300 | "polarity": "positive", 301 | "type": "gerber_layer" 302 | }, 303 | { 304 | "advanced_options": { 305 | "mirror": false, 306 | "offset_x": 0, 307 | "offset_y": 0, 308 | "rotate": false, 309 | "upside_down": false 310 | }, 311 | "board_outline": false, 312 | "config": { 313 | "file_function": "Legend", 314 | "index": 1, 315 | "layer_type": "bottom" 316 | }, 317 | "filename_format": "%N.GBO", 318 | "layers": [ 319 | 22 320 | ], 321 | "milling": false, 322 | "name": "Silkscreen Bottom", 323 | "polarity": "positive", 324 | "type": "gerber_layer" 325 | } 326 | ], 327 | "version": "RS274X" 328 | }, 329 | { 330 | "filename_prefix": "CAMOutputs/DrillFiles", 331 | "format_specifier": { 332 | "decimal": 3, 333 | "integer": 3 334 | }, 335 | "output_type": "drill", 336 | "outputs": [ 337 | { 338 | "advanced_options": { 339 | "mirror": false, 340 | "offset_x": 0, 341 | "offset_y": 0, 342 | "rotate": false, 343 | "upside_down": false 344 | }, 345 | "filename_format": "%N.TXT", 346 | "name": "Auto Drill", 347 | "type": "autodrills" 348 | } 349 | ] 350 | }, 351 | { 352 | "filename_prefix": "CAMOutputs/Assembly", 353 | "output_type": "assembly", 354 | "outputs": [ 355 | ] 356 | }, 357 | { 358 | "filename_prefix": "CAMOutputs/DrawingFiles", 359 | "output_type": "drawing", 360 | "outputs": [ 361 | ] 362 | } 363 | ], 364 | "timestamp": "2020-08-21T13:29:31", 365 | "type": "EAGLE CAM job", 366 | "units": "metric", 367 | "version": "9.2.0" 368 | } 369 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-2-layer-ALC.dru: -------------------------------------------------------------------------------- 1 | description[en] = SparkFun 2 Layer Design Rule Checks - Limits for PCBWay\n

\n If you're ordering from PCBWay, these are the 'free' minimums. 2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 8mil 6 | mdWirePad = 8mil 7 | mdWireVia = 8mil 8 | mdPadPad = 7mil 9 | mdPadVia = 8mil 10 | mdViaVia = 8mil 11 | mdSmdPad = 7mil 12 | mdSmdVia = 7mil 13 | mdSmdSmd = 7mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 8mil 17 | mdDrill = 8mil 18 | mdSmdStop = 0mil 19 | msWidth = 7mil 20 | msDrill = 0.3mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 6mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 6mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 6mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 6mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 6mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 6mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 6mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-2-layer-FAB-LIMIT.dru: -------------------------------------------------------------------------------- 1 | description[en] = SparkFun 2 Layer Design Rule Checks - STANDARD/TIGHT/FAB-LIMIT\n

\nThese rules have been curated by SparkFuns DFM commitee. After doing much research, communicating with our multiple fab houses, and getting quotes of various designs, we have compiled three DRU files. \n

\nSTANDARD: This is more of a "best case scenario" set of limitations. If your design has the space, and/or you have the time to work within these parameters, please do. Larger trace width and clearance makes for easier visual inspection of the PCB while troubleshooting (useful in production and to the end user). It also allows for better ability to hack a trace (if you are crazy enough to scrape away the mask and solder to a trace). Another thing to keep in mind is that more metal is just more robust. \n

\nTIGHT: This is where cost comes into play. We have found that most fab houses begin to add extra charges when you go smaller than these specs. In some cases, going to less than 15 mil trace can increase the cost by 10%. (This is why we have set the min drill on this DRU to 15 mil) Same story for traces thinner than 7 mil. To avoid those extra charges, then stay within the rules of this DRU.\n

\nFAB-LIMIT: These set of rules are at the very limit of most fab houses capabilities. You will pay more for these specs, and it should be used on designs that have a darned good reason to need 4 mil vias and 4 mil traces.\n

\n**NOTE Clearance, Distance, Sizes, and Restring are all set to different limits in each of these three DRU files. Please compare the files within the CAM job editor window of eagle to see all the numbers.\n

\n***NOTE, Please set your Net Classes to default (0mil for all settings), so that it won't effect the DRC when you run it with these settings. 2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 4mil 6 | mdWirePad = 4mil 7 | mdWireVia = 4mil 8 | mdPadPad = 4mil 9 | mdPadVia = 4mil 10 | mdViaVia = 4mil 11 | mdSmdPad = 4mil 12 | mdSmdVia = 4mil 13 | mdSmdSmd = 4mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 4mil 17 | mdDrill = 4mil 18 | mdSmdStop = 0mil 19 | msWidth = 4mil 20 | msDrill = 6mil 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 5mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 6mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 5mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 5mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 6mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkGrid = 0 64 | checkAngle = 1 65 | checkFont = 1 66 | checkRestrict = 1 67 | useDiameter = 13 68 | maxErrors = 50 69 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-2-layer-PCBWay-LIMIT.dru: -------------------------------------------------------------------------------- 1 | description[en] = SparkFun 2 Layer Design Rule Checks - Limits for PCBWay\n

\n If you're ordering from PCBWay, these are the 'free' minimums. 2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 6mil 6 | mdWirePad = 6mil 7 | mdWireVia = 6mil 8 | mdPadPad = 6mil 9 | mdPadVia = 6mil 10 | mdViaVia = 6mil 11 | mdSmdPad = 6mil 12 | mdSmdVia = 6mil 13 | mdSmdSmd = 6mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 6mil 17 | mdDrill = 6mil 18 | mdSmdStop = 0mil 19 | msWidth = 6mil 20 | msDrill = 0.3mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 6mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 6mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 6mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 6mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 6mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 6mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 6mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | useDiameter = 13 69 | maxErrors = 50 70 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-2-layer-STANDARD.dru: -------------------------------------------------------------------------------- 1 | description[en] = SparkFun 2 Layer Design Rule Checks - STANDARD/TIGHT/FAB-LIMIT\n

\nThese rules have been curated by SparkFuns DFM commitee. After doing much research, communicating with our multiple fab houses, and getting quotes of various designs, we have compiled three DRU files. \n

\nSTANDARD: This is more of a "best case scenario" set of limitations. If your design has the space, and/or you have the time to work within these parameters, please do. Larger trace width and clearance makes for easier visual inspection of the PCB while troubleshooting (useful in production and to the end user). It also allows for better ability to hack a trace (if you are crazy enough to scrape away the mask and solder to a trace). Another thing to keep in mind is that more metal is just more robust. \n

\nTIGHT: This is where cost comes into play. We have found that most fab houses begin to add extra charges when you go smaller than these specs. In some cases, going to less than 15 mil trace can increase the cost by 10%. (This is why we have set the min drill on this DRU to 15 mil) Same story for traces thinner than 7 mil. To avoid those extra charges, then stay within the rules of this DRU.\n

\nFAB-LIMIT: These set of rules are at the very limit of most fab houses capabilities. You will pay more for these specs, and it should be used on designs that have a darned good reason to need 4 mil vias and 4 mil traces.\n

\n**NOTE Clearance, Distance, Sizes, and Restring are all set to different limits in each of these three DRU files. Please compare the files within the CAM job editor window of eagle to see all the numbers.\n

\n***NOTE, Please set your Net Classes to default (0mil for all settings), so that it won't effect the DRC when you run it with these settings. 2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 10mil 6 | mdWirePad = 8mil 7 | mdWireVia = 10mil 8 | mdPadPad = 8mil 9 | mdPadVia = 10mil 10 | mdViaVia = 10mil 11 | mdSmdPad = 8mil 12 | mdSmdVia = 8mil 13 | mdSmdSmd = 8mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 8mil 17 | mdDrill = 8mil 18 | mdSmdStop = 0mil 19 | msWidth = 10mil 20 | msDrill = 20mil 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 10mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 10mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 10mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 10mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 10mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkGrid = 0 64 | checkAngle = 1 65 | checkFont = 1 66 | checkRestrict = 1 67 | useDiameter = 13 68 | maxErrors = 50 69 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-2-layer-TIGHT.dru: -------------------------------------------------------------------------------- 1 | description[en] = SparkFun 2 Layer Design Rule Checks - STANDARD/TIGHT/FAB-LIMIT\n

\nThese rules have been curated by SparkFuns DFM commitee. After doing much research, communicating with our multiple fab houses, and getting quotes of various designs, we have compiled three DRU files. \n

\nSTANDARD: This is more of a "best case scenario" set of limitations. If your design has the space, and/or you have the time to work within these parameters, please do. Larger trace width and clearance makes for easier visual inspection of the PCB while troubleshooting (useful in production and to the end user). It also allows for better ability to hack a trace (if you are crazy enough to scrape away the mask and solder to a trace). Another thing to keep in mind is that more metal is just more robust. \n

\nTIGHT: This is where cost comes into play. We have found that most fab houses begin to add extra charges when you go smaller than these specs. In some cases, going to less than 15 mil trace can increase the cost by 10%. (This is why we have set the min drill on this DRU to 15 mil) Same story for traces thinner than 7 mil. To avoid those extra charges, then stay within the rules of this DRU.\n

\nFAB-LIMIT: These set of rules are at the very limit of most fab houses capabilities. You will pay more for these specs, and it should be used on designs that have a darned good reason to need 4 mil vias and 4 mil traces.\n

\n**NOTE Clearance, Distance, Sizes, and Restring are all set to different limits in each of these three DRU files. Please compare the files within the CAM job editor window of eagle to see all the numbers.\n

\n***NOTE, Please set your Net Classes to default (0mil for all settings), so that it won't effect the DRC when you run it with these settings. 2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 7mil 6 | mdWirePad = 7mil 7 | mdWireVia = 7mil 8 | mdPadPad = 7mil 9 | mdPadVia = 7mil 10 | mdViaVia = 7mil 11 | mdSmdPad = 7mil 12 | mdSmdVia = 7mil 13 | mdSmdSmd = 7mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 7mil 17 | mdDrill = 7mil 18 | mdSmdStop = 0mil 19 | msWidth = 7mil 20 | msDrill = 15mil 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 7mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 7mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 7mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 7mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 7mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkGrid = 0 64 | checkAngle = 1 65 | checkFont = 1 66 | checkRestrict = 1 67 | useDiameter = 13 68 | maxErrors = 50 69 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-4-layer-BGA-Extreme.dru: -------------------------------------------------------------------------------- 1 | description[en] = EAGLE Design Rules\n

\nThe default Design Rules have been set to cover\na wide range of applications. Your particular design\nmay have different requirements, so please make the\nnecessary adjustments and save your customized\ndesign rules under a new name. 2 | layerSetup = ((1*2)+(15*16)) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 0.213359375mm 1.0161mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.213359375mm 5 | mdWireWire = 4mil 6 | mdWirePad = 4mil 7 | mdWireVia = 4mil 8 | mdPadPad = 4mil 9 | mdPadVia = 4mil 10 | mdViaVia = 4mil 11 | mdSmdPad = 0mil 12 | mdSmdVia = 0mil 13 | mdSmdSmd = 0mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 4mil 17 | mdDrill = 4mil 18 | mdSmdStop = 0mil 19 | msWidth = 4mil 20 | msDrill = 0.15mm 21 | msMicroVia = 0.15mm 22 | msBlindViaRatio = 10.000000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 3mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 3mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 3mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 3mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 3mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 3mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 3mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 0 70 | checkPolygonWidth = 1 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-4-layer-FAB-LIMIT.dru: -------------------------------------------------------------------------------- 1 | description[en] = EAGLE Design Rules\n

\nThe default Design Rules have been set to cover\na wide range of applications. Your particular design\nmay have different requirements, so please make the\nnecessary adjustments and save your customized\ndesign rules under a new name. 2 | layerSetup = (1*2*15*16) 3 | mtCopper = 0.035559375mm 0.035559375mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035559375mm 0.035559375mm 4 | mtIsolate = 0.47751875mm 0.47751875mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.47751875mm 5 | mdWireWire = 5mil 6 | mdWirePad = 5mil 7 | mdWireVia = 5mil 8 | mdPadPad = 5mil 9 | mdPadVia = 5mil 10 | mdViaVia = 5mil 11 | mdSmdPad = 5mil 12 | mdSmdVia = 5mil 13 | mdSmdSmd = 5mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 4mil 17 | mdDrill = 4mil 18 | mdSmdStop = 0mil 19 | msWidth = 4mil 20 | msDrill = 6mil 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 5mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 6mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 5mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 5mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 6mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkGrid = 0 64 | checkAngle = 1 65 | checkFont = 1 66 | checkRestrict = 1 67 | useDiameter = 13 68 | maxErrors = 50 69 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-4-layer-MicroMod.dru: -------------------------------------------------------------------------------- 1 | description[en] = \nSparkFun 4 Layer Design Rule Checks for MicroMods\n

\n 2 | layerSetup = (1+2*15+16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 4mil 6 | mdWirePad = 4mil 7 | mdWireVia = 4mil 8 | mdPadPad = 4mil 9 | mdPadVia = 4mil 10 | mdViaVia = 4mil 11 | mdSmdPad = 4mil 12 | mdSmdVia = 4mil 13 | mdSmdSmd = 4mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 6mil 17 | mdDrill = 6mil 18 | mdSmdStop = 0mil 19 | msWidth = 4mil 20 | msDrill = 0.2mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 3mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 3mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 3mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 3mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 3mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 3mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 3mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-4-layer-PCBWAY-LIMIT.dru: -------------------------------------------------------------------------------- 1 | description[en] = EAGLE Design Rules\n

\nThe default Design Rules have been set to cover\na wide range of applications. Your particular design\nmay have different requirements, so please make the\nnecessary adjustments and save your customized\ndesign rules under a new name. 2 | layerSetup = ([15:(1*2)+15*16]) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 0.213359375mm 1.0161mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.213359375mm 5 | mdWireWire = 5mil 6 | mdWirePad = 5mil 7 | mdWireVia = 5mil 8 | mdPadPad = 5mil 9 | mdPadVia = 5mil 10 | mdViaVia = 5mil 11 | mdSmdPad = 0mil 12 | mdSmdVia = 0mil 13 | mdSmdSmd = 0mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 5mil 17 | mdDrill = 5mil 18 | mdSmdStop = 0mil 19 | msWidth = 5mil 20 | msDrill = 0.2mm 21 | msMicroVia = 0.2mm 22 | msBlindViaRatio = 10.000000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 3mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 3mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 3mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 3mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 3mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 3mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 3mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 0 70 | checkPolygonWidth = 1 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/Old/SparkFun-4-layer-TIGHT.dru: -------------------------------------------------------------------------------- 1 | description[en] = EAGLE Design Rules\n

\nThe default Design Rules have been set to cover\na wide range of applications. Your particular design\nmay have different requirements, so please make the\nnecessary adjustments and save your customized\ndesign rules under a new name. 2 | layerSetup = (1*2*15*16) 3 | mtCopper = 0.035559375mm 0.035559375mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035559375mm 0.035559375mm 4 | mtIsolate = 0.47751875mm 0.47751875mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.47751875mm 5 | mdWireWire = 7mil 6 | mdWirePad = 7mil 7 | mdWireVia = 7mil 8 | mdPadPad = 7mil 9 | mdPadVia = 7mil 10 | mdViaVia = 7mil 11 | mdSmdPad = 7mil 12 | mdSmdVia = 7mil 13 | mdSmdSmd = 7mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 7mil 17 | mdDrill = 7mil 18 | mdSmdStop = 0mil 19 | msWidth = 7mil 20 | msDrill = 15mil 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 7mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 7mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 7mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 7mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 7mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 4mil 52 | mlMaxStopFrame = 4mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkGrid = 0 64 | checkAngle = 1 65 | checkFont = 1 66 | checkRestrict = 1 67 | useDiameter = 13 68 | maxErrors = 50 69 | -------------------------------------------------------------------------------- /dru/README.md: -------------------------------------------------------------------------------- 1 | DRU files 2 | ======================= 3 | These are the design rules files (.dru), which define the tollerances on the PCB (this includes everything from trace width to layer construction). The PCB fab house can only manufacture up to a specific tollerance and this file makes sure you fall within their constraints. The 2-layer and 4-layer dru files are based on the [BatchPCB](https://batchpcb.com/faq#question_2) design constraints. -------------------------------------------------------------------------------- /dru/SparkFun-2-Layer-General-JLCPCB.dru: -------------------------------------------------------------------------------- 1 | description[en] = 2 Layer General Rules for JLCPCB\n

\nThese are the free and generally easy to produce 2-layer PCB design rules. You can certainly go smaller but if the design doesn't call for it, these rules provide good guidance.\n

2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 7mil 6 | mdWirePad = 7mil 7 | mdWireVia = 7mil 8 | mdPadPad = 7mil 9 | mdPadVia = 7mil 10 | mdViaVia = 7mil 11 | mdSmdPad = 7mil 12 | mdSmdVia = 7mil 13 | mdSmdSmd = 7mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 7mil 17 | mdDrill = 7mil 18 | mdSmdStop = 0mil 19 | msWidth = 7mil 20 | msDrill = 0.3mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 7mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 7mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 7mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 7mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 7mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 3mil 52 | mlMaxStopFrame = 3mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 2mil 58 | srMaxRoundness = 2mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/SparkFun-2-Layer-Minimum-JLCPCB.dru: -------------------------------------------------------------------------------- 1 | description[en] = 2 Layer Minimum Rules for JLCPCB\n

\nThese are the minimums quoted by JLCPCB to produce a 2-layer PCB design rules. These rules are "free" and generally low-cost. Going below these settings may cause the board to be not manufacturable or incur a price increase.\n

2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 5mil 6 | mdWirePad = 5mil 7 | mdWireVia = 5mil 8 | mdPadPad = 5mil 9 | mdPadVia = 5mil 10 | mdViaVia = 5mil 11 | mdSmdPad = 5mil 12 | mdSmdVia = 5mil 13 | mdSmdSmd = 5mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 7mil 17 | mdDrill = 7mil 18 | mdSmdStop = 0mil 19 | msWidth = 5mil 20 | msDrill = 0.3mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 5mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 5mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 5mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 5mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 5mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 2.5mil 52 | mlMaxStopFrame = 2.5mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 2mil 58 | srMaxRoundness = 2mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/SparkFun-4-Layer-General-JLCPCB.dru: -------------------------------------------------------------------------------- 1 | description[en] = 4 Layer General Rules for JLCPCB\n

\nThese are the free and generally easy to produce 4-layer PCB design rules. You can certainly go smaller but if the design doesn't call for it, these rules provide good guidance.\n

2 | layerSetup = (1+2*15+16) 3 | mtCopper = 0.035559375mm 0.035559375mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035559375mm 0.035559375mm 4 | mtIsolate = 0.47751875mm 0.47751875mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.47751875mm 5 | mdWireWire = 7mil 6 | mdWirePad = 7mil 7 | mdWireVia = 7mil 8 | mdPadPad = 7mil 9 | mdPadVia = 7mil 10 | mdViaVia = 7mil 11 | mdSmdPad = 7mil 12 | mdSmdVia = 7mil 13 | mdSmdSmd = 7mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 7mil 17 | mdDrill = 7mil 18 | mdSmdStop = 0mil 19 | msWidth = 7mil 20 | msDrill = 12mil 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 7mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 7mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 7mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 7mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 7mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 3mil 52 | mlMaxStopFrame = 3mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 2mil 58 | srMaxRoundness = 2mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/SparkFun-4-Layer-MicroMod-JLCPCB.dru: -------------------------------------------------------------------------------- 1 | description[en] = \nSparkFun 4 Layer Design Rules for MicroMod for JLCPCB\n

\nThese design rules are smaller than the published rules by JLCPCB to produce a 4-layer PCB. But we have needed these tolerances for some very tight layouts. These rules should be avoided unless absolutely necessary and will complicate the ordering process (including some orders being refused).\n

2 | layerSetup = (1+2*15+16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 4mil 6 | mdWirePad = 4mil 7 | mdWireVia = 4mil 8 | mdPadPad = 4mil 9 | mdPadVia = 4mil 10 | mdViaVia = 4mil 11 | mdSmdPad = 4mil 12 | mdSmdVia = 4mil 13 | mdSmdSmd = 4mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 6mil 17 | mdDrill = 6mil 18 | mdSmdStop = 0mil 19 | msWidth = 4mil 20 | msDrill = 0.2mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 3mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 3mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 3mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 3mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 3mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 3mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 3mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 2.5mil 52 | mlMaxStopFrame = 2.5mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 2mil 58 | srMaxRoundness = 2mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/SparkFun-4-Layer-Minimum-Blind-Vias-PCBWay.dru: -------------------------------------------------------------------------------- 1 | description[en] = SparkFun 4 Layer Design Rules with Blind Vias for PCBWay\n

\nThese are pretty extreme design rules reserved for 4-layer boards with blind vias. Primarily used on the Artemis module design, these rules have only been used with PCBWay (published rules by PBWay). These rules should be avoided unless absolutely necessary and will increase fab times and complicate the ordering process.\n

2 | layerSetup = ([2:1+2*15+16:15]) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 0.213359375mm 1.0161mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.213359375mm 5 | mdWireWire = 4mil 6 | mdWirePad = 4mil 7 | mdWireVia = 4mil 8 | mdPadPad = 4mil 9 | mdPadVia = 4mil 10 | mdViaVia = 4mil 11 | mdSmdPad = 0mil 12 | mdSmdVia = 0mil 13 | mdSmdSmd = 0mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 5mil 17 | mdDrill = 4mil 18 | mdSmdStop = 0mil 19 | msWidth = 4mil 20 | msDrill = 0.15mm 21 | msMicroVia = 0.15mm 22 | msBlindViaRatio = 10.000000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 3mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 3mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 3mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 3mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 3mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 3mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 3mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 2.5mil 52 | mlMaxStopFrame = 2.5mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 2mil 58 | srMaxRoundness = 2mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 0 70 | checkPolygonWidth = 1 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/SparkFun-4-Layer-Minimum-JLCPCB.dru: -------------------------------------------------------------------------------- 1 | description[en] = 4 Layer Minimum Rules for JLCPCB\n

\nThese are the minimums quoted by JLCPCB to produce a 4-layer PCB design rules. These rules are "free" and generally low-cost. There is one DRC set that is smaller (see MicroMod rules) but boards designed with these rules should pass review without question.\n

2 | layerSetup = (1*2*15*16) 3 | mtCopper = 0.035559375mm 0.035559375mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035559375mm 0.035559375mm 4 | mtIsolate = 0.47751875mm 0.47751875mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.47751875mm 5 | mdWireWire = 5mil 6 | mdWirePad = 5mil 7 | mdWireVia = 5mil 8 | mdPadPad = 5mil 9 | mdPadVia = 5mil 10 | mdViaVia = 5mil 11 | mdSmdPad = 5mil 12 | mdSmdVia = 5mil 13 | mdSmdSmd = 5mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 7mil 17 | mdDrill = 7mil 18 | mdSmdStop = 0mil 19 | msWidth = 5mil 20 | msDrill = 0.2mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 5mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 5mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 5mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 5mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 5mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 2.5mil 52 | mlMaxStopFrame = 2.5mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 2mil 58 | srMaxRoundness = 2mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /dru/SparkFun-6-Layer-Minimum-JLCPCB.dru: -------------------------------------------------------------------------------- 1 | description[en] = 6 Layer JLC06161H-3313 Rules for JLCPCB\n

\nThese are the rules quoted by JLCPCB to produce a 6-layer PCB design using JLC06161H-3313 stackup. These rules are the lowest cost controlled impedance rules for this many layers. \n

2 | layerSetup = (1+2*3+14*15+16) 3 | mtCopper = 0.035mm 0.0152mm 0.0152mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.0152mm 0.0152mm 0.035mm 4 | mtIsolate = 0.0994mm 0.55mm 0.1088mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.55mm 0.0994mm 5 | mdWireWire = 0.09mm 6 | mdWirePad = 5mil 7 | mdWireVia = 5mil 8 | mdPadPad = 5mil 9 | mdPadVia = 5mil 10 | mdViaVia = 5mil 11 | mdSmdPad = 5mil 12 | mdSmdVia = 5mil 13 | mdSmdSmd = 5mil 14 | mdViaViaSameLayer = 8mil 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 7mil 17 | mdDrill = 7mil 18 | mdSmdStop = 0mil 19 | msWidth = 0.09mm 20 | msDrill = 0.2mm 21 | msMicroVia = 9.99mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.250000 24 | rvPadInner = 0.250000 25 | rvPadBottom = 0.250000 26 | rvViaOuter = 0.250000 27 | rvViaInner = 0.250000 28 | rvMicroViaOuter = 0.250000 29 | rvMicroViaInner = 0.250000 30 | rlMinPadTop = 5mil 31 | rlMaxPadTop = 20mil 32 | rlMinPadInner = 5mil 33 | rlMaxPadInner = 20mil 34 | rlMinPadBottom = 5mil 35 | rlMaxPadBottom = 20mil 36 | rlMinViaOuter = 5mil 37 | rlMaxViaOuter = 20mil 38 | rlMinViaInner = 5mil 39 | rlMaxViaInner = 20mil 40 | rlMinMicroViaOuter = 4mil 41 | rlMaxMicroViaOuter = 20mil 42 | rlMinMicroViaInner = 4mil 43 | rlMaxMicroViaInner = 20mil 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 1.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 2.5mil 52 | mlMaxStopFrame = 2.5mil 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0mil 55 | mlViaStopLimit = 25mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 2mil 58 | srMaxRoundness = 2mil 59 | slThermalIsolate = 10mil 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkAngle = 1 64 | checkFont = 1 65 | checkRestrict = 1 66 | checkStop = 0 67 | checkValues = 0 68 | checkNames = 1 69 | checkWireStubs = 1 70 | checkPolygonWidth = 0 71 | useDiameter = 13 72 | maxErrors = 50 73 | -------------------------------------------------------------------------------- /scr/eagle.scr: -------------------------------------------------------------------------------- 1 | # Configuration Script 2 | # 3 | # This file can be used to configure the editor windows. 4 | 5 | Assign F3 'Delete'; 6 | Assign AF3 'Grid inch 0.001 on; Grid alt inch 0.01;'; 7 | Assign F4 'Name'; 8 | Assign F5 'Value'; 9 | Assign AF5 'Change Text'; 10 | Assign F6 'Smash'; 11 | Assign F7 'Move'; 12 | Assign AF7 'Group'; 13 | Assign F8 'Copy'; 14 | Assign F10 'Grid inch 0.05 on; Grid alt inch 0.005;'; 15 | Assign AF10 'Grid mm 1 on; Grid alt mm 0.1;'; 16 | Assign CS+A 'run SparkFun-AutoChecklist.ulp;'; 17 | Assign CS+S 'run SparkFun-AutoChecklist-Schematic.ulp;'; 18 | 19 | Grid inch 0.05 on; 20 | Grid alt inch 0.005; 21 | 22 | BRD: 23 | #Menu Add Change Copy Delete Display Grid Group Move Name Quit Rect \ 24 | # Route Script Show Signal Split Text Value Via Window ';' Wire Write Edit; 25 | 26 | #Setup SparkFun Defaults 27 | Grid inch 0.05 on; 28 | Grid alt inch 0.005; 29 | Set WIRE_BEND 1; #Route with 45 degree angles 30 | Set Drill 0.015; #Make vias 15mil by default 31 | Change Shape Round; #Make vias round 32 | Change Width 0.010; #Routing width default to 10mil 33 | Change Isolate 0.012; #BHW Change polygon isolate to 12mil 34 | 35 | Change Font Vector; #Make text on board in vector font 36 | Change Ratio 15; 37 | 38 | CHANGE DUNIT INCH OFF #BHW Change default units to inches [ON | OFF] [precision] 39 | 40 | #changes background color of board to black 41 | SET PALETTE BLACK; 42 | 43 | #Layer colors 44 | Set palette 1 0xB43232C8; #classic dark blue 45 | Set palette 2 0xB432C832; #classic green 46 | Set palette 4 0xB4C83232; #classic dark red 47 | Set palette 16 0xFFFFFFFF; #Super white 48 | Set palette 24 0xFFC0C0C0; #Grey - color used when text is selected (anti palette location 16) 49 | Set color_layer 1 4; #Set top layer to dark red 50 | Set color_layer 16 1; #Set bottom layer to dark blue 51 | Set color_layer 17 2; #Set pads to green 52 | Set color_layer 18 2; #Set vias to green 53 | Set color_layer 19 6; #Set unrouted to dark yellow 54 | #Set color_layer 20 15; #Set dimension to light gray - this changed in v9 55 | Set color_layer 20 24; #Set dimension to light gray 56 | Set color_layer 21 16; #Set tPlace to white 57 | Set color_layer 22 14; #Set bPlace to yellow 58 | Set color_layer 23 15; #Set tOrigins to light gray 59 | Set color_layer 24 15; #Set bOrigins to light gray 60 | Set color_layer 45 7; #Set Holes to dark gray 61 | Set color_layer 51 6; #Set tDocu to mellow yellow 62 | display none; display 1 16 17 18 19 20 21 22 23 24 45 51; display -25 -26 -27 -28; 63 | 64 | #Used for four layer routing 65 | Assign A+1 'Set Used_Layers 1 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52;' #2 layer stackup 66 | Assign A+2 'Set Used_Layers 1 2 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52;' #4 layer stackup 67 | Assign A+3 'Set Used_Layers 1 2 3 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52;' #6 layer stackup 68 | 69 | DISPLAY = TopOnly 1 17 18 19 20; 70 | DISPLAY = BottomOnly 16 17 18 19 20; 71 | DISPLAY = VerticalOnly 15 17 18 19 20; 72 | DISPLAY = HorizontalOnly 2 17 18 19 20; 73 | Assign A+7 'display none; display TopOnly;' 74 | Assign A+8 'display none; display BottomOnly;' 75 | Assign A+9 'display none; display HorizontalOnly;' 76 | Assign A+0 'display none; display VerticalOnly;' 77 | 78 | 79 | #Assign shortcuts 80 | Assign F8 ratsnest; 81 | Assign AF8 drc; 82 | 83 | Assign F9 'Route'; 84 | Assign AF9 'Ripup'; 85 | 86 | Assign F10 'Grid inch 0.05 on; Grid alt inch 0.005;'; 87 | Assign AF10 'Grid mm 1 on; Grid alt mm 0.1;'; 88 | 89 | Assign F11 'display none; display 1 16 17 18 19 20 21 22 23 24 45 49 51; display -25 -26 -27 -28;'; 90 | Assign AF11 'display none; display 17 20 21 23 27 31 45 51; display -25 -26 -28;'; 91 | 92 | Assign F12 'show'; 93 | Assign AF12 'info'; 94 | 95 | # Display the bottom side of board and what it will look like in a more human readable view. The "f" is for "flip". 96 | Assign C+F 'RUN SparkFun-Flip.ulp;'; 97 | 98 | # Turn off everything but the unrouted airwires 99 | Assign C+H 'DISPLAY NONE; DISPLAY 19;'; 100 | 101 | 102 | SCH: 103 | Grid Default; #BHW Reset the grid to the standard value 104 | Change Width 0.006; #BHW Set the 6mil rule 105 | Set XREF_LABEL_FORMAT %F%N/%S; #BHW Remove row & column from default 106 | Change XREF ON; #BHW Default to the labels we use (flag border) 107 | Change Size 0.05; #BHW Use 50mil flags (and text... exceeds minimum) 108 | 109 | Assign F9 'Net'; 110 | Assign AF9 'Label'; 111 | 112 | Assign F12 'show'; 113 | Assign AF12 'info'; 114 | 115 | Grid Default; 116 | Change Width 0.008; 117 | 118 | #Menu Add Bus Change Copy Delete Display Gateswap Grid Group Invoke Junction \ 119 | # Label Move Name Net Pinswap Quit Script Show Split Value Window ';' \ 120 | # Wire Write Edit; 121 | 122 | PAC: 123 | #Settings for editing footprints within a library 124 | 125 | #Set to two layer defaults 126 | SET USED_LAYERS 1 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 91 92 93 94 95 96; 127 | 128 | Grid inch 0.05 on; 129 | Grid alt inch 0.005; 130 | Set WIRE_BEND 1; #Route with 45 degree angles 131 | Set Drill 0.015; #Make vias 0.02" 132 | 133 | #Assign layer colors to match layer colors when routing 134 | Set palette 1 0xB43232C8; #classic dark blue 135 | Set palette 2 0xB432C832; #classic green 136 | Set palette 4 0xB4C83232; #classic dark red 137 | Set palette 16 0xFFFFFFFF; #Super white 138 | Set palette 24 0xFFC0C0C0; #Grey - color used when text is selected (anti palette location 16) 139 | Set color_layer 1 4; #Set top layer to dark red 140 | Set color_layer 16 1; #Set bottom layer to dark blue 141 | Set color_layer 17 2; #Set pads to green 142 | Set color_layer 18 2; #Set vias to green 143 | Set color_layer 19 6; #Set unrouted to dark yellow 144 | #Set color_layer 20 15; #Set dimension to light gray - this changed in v9 145 | Set color_layer 20 24; #Set dimension to light gray 146 | Set color_layer 21 16; #Set tPlace to white 147 | Set color_layer 22 14; #Set bPlace to yellow 148 | Set color_layer 23 15; #Set tOrigins to light gray 149 | Set color_layer 24 15; #Set bOrigins to light gray 150 | Set color_layer 45 7; #Set Holes to dark gray 151 | Set color_layer 51 6; #Set tDocu to mellow yellow 152 | display none; display 1 16 17 18 19 20 21 22 23 24 45 51; display -25 -26 -27 -28; 153 | 154 | Assign F10 'Grid inch 0.05 on; Grid alt inch 0.005;'; 155 | Assign AF10 'Grid mm 1 on; Grid alt mm 0.1;'; 156 | 157 | Assign F11 'display none; display 1 16 17 18 19 20 21 22 23 24 45 49 51; display -25 -26 -27 -28;'; 158 | Assign AF11 'display none; display 17 20 21 23 27 31 45 51; display -25 -26 -28;'; 159 | 160 | DEV: 161 | # Settings when editing a device in a library 162 | 163 | Grid Default; 164 | #Menu Add Change Copy Connect Delete Display Export Grid Move Name Package \ 165 | # Prefix Quit Script Show Value Window ';' Write Edit; 166 | 167 | SYM: 168 | # Settings when editing a symbol in a library 169 | 170 | GRID Default OFF; 171 | Change Width 0.010; 172 | #Menu Arc Change Copy Cut Delete Display Export Grid Group Move Name Paste \ 173 | # Pin Quit Script Show Split Text Value Window ';' Wire Write Edit; 174 | -------------------------------------------------------------------------------- /ulp/7za.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/7za.exe -------------------------------------------------------------------------------- /ulp/Include_String.ulp: -------------------------------------------------------------------------------- 1 | /* WILDCARD */ 2 | string STRING_WILDCARD_STR = "%%"; 3 | 4 | string stringFTrim(string str) 5 | { 6 | string str2; 7 | int trimmed = 0; 8 | 9 | for(int i = 0; str[i]; i++) 10 | { 11 | if(trimmed) 12 | { 13 | str2 += str[i]; 14 | } 15 | else if(str[i] != ' ' && str[i] != '\n' && str[i] != '\t') 16 | { 17 | trimmed = 1; 18 | str2 += str[i]; 19 | } 20 | } 21 | 22 | return str2; 23 | } 24 | 25 | string stringLTrim(string str) 26 | { 27 | string str2; 28 | int trimmed = 0; 29 | 30 | for(int i = strlen(str)-1; i >= 0; i--) 31 | { 32 | if(trimmed) 33 | { 34 | sprintf(str2, "%c%s", str[i], str2); 35 | } 36 | else if(str[i] != ' ' && str[i] != '\n' && str[i] != '\t') 37 | { 38 | trimmed = 1; 39 | sprintf(str2, "%c%s", str[i], str2); 40 | } 41 | } 42 | 43 | return str2; 44 | } 45 | 46 | string stringTrim(string str) 47 | { 48 | return stringLTrim(stringFTrim(str)); 49 | } 50 | 51 | string stringReplace(string str, string search, string replace) 52 | { 53 | int offset = 0; 54 | while(strstr(str, search, offset) != -1) 55 | { 56 | int start = strstr(str, search, offset); 57 | int end = start + strlen(search); 58 | string str1 = strsub(str, 0, start); 59 | string str2 = strsub(str, end); 60 | 61 | offset = strlen(str1) + strlen(replace); 62 | 63 | str = str1 + replace + str2; 64 | } 65 | 66 | return str; 67 | } 68 | 69 | string stringConvertDotToComma(string str) 70 | { 71 | return str; //stringReplace(str, ".", ","); 72 | } 73 | 74 | // EAGLE ADDS A ":" to sprintf's real value, why? 75 | string stringFromReal(real value) 76 | { 77 | string tmp; 78 | sprintf(tmp, "%e", value); 79 | 80 | if(strchr(tmp, ':') != -1) 81 | { 82 | tmp[strchr(tmp, ':')] = '0'; 83 | } 84 | 85 | return tmp; 86 | } 87 | 88 | 89 | int stringAdvancedMatch(string needle, string haystack) 90 | { 91 | string search[]; 92 | int index = 0; 93 | 94 | int count = strsplit(search, needle, '*'); 95 | 96 | if(stringTrim(haystack) == "" && needle != "") 97 | { 98 | return 0; 99 | } 100 | 101 | for(int i = 0; i < count; i++) 102 | { 103 | if(search[i] != "" && (index = strstr(haystack, search[i], index)) == -1) 104 | { 105 | return 0; 106 | } 107 | } 108 | 109 | return 1; 110 | } 111 | 112 | /* Parameters look like: grid 5 mm, outline 5 x 5 mm */ 113 | string stringParameterValue(string parameter, string haystack) 114 | { 115 | string data = ""; 116 | 117 | int start = strstr(haystack, parameter, 0); 118 | int len = strlen(parameter) + 1; 119 | int end = 0; 120 | 121 | if(start != -1) 122 | { 123 | end = strstr(haystack, ",", start); 124 | end = end==-1?strlen(haystack):end; 125 | 126 | data = strsub(haystack, start + len , end-(start+len)); 127 | } 128 | 129 | return stringTrim(data); 130 | } 131 | 132 | int stringParameterPresent(string parameter, string haystack) 133 | { 134 | return (strstr(haystack, parameter, 0) != -1)?1:0; 135 | } 136 | 137 | 138 | string stringWildcardGetNext(string wildcarded) 139 | { 140 | int start = strstr(wildcarded, STRING_WILDCARD_STR); 141 | int end = strstr(wildcarded, STRING_WILDCARD_STR, start+1); 142 | 143 | return strsub(wildcarded, start+2, end-start-2); 144 | } 145 | 146 | string stringWildcardReplace(string wildcarded, string wildcard, string replacement) 147 | { 148 | int start = strstr(wildcarded, STRING_WILDCARD_STR + wildcard + STRING_WILDCARD_STR, 0); 149 | int end = start + strlen(STRING_WILDCARD_STR + wildcard + STRING_WILDCARD_STR); 150 | string str1 = strsub(wildcarded, 0, start); 151 | string str2 = strsub(wildcarded, end); 152 | 153 | return str1 + replacement + str2; 154 | } 155 | 156 | int stringCompare(string s1, string s2) 157 | { 158 | for(int i = 0; i < strlen(s1) && i < strlen(s2); i++) 159 | { 160 | if(s1[i] > s2[i]) { return 1;} 161 | else if(s1[i] < s2[i]) { return -1;} 162 | } 163 | 164 | return 0; 165 | } 166 | 167 | string itoa(int num){ 168 | string tmp; 169 | sprintf(tmp, "%d", num); 170 | return tmp; 171 | } -------------------------------------------------------------------------------- /ulp/SparkFun-BOM_Generator.flt: -------------------------------------------------------------------------------- 1 | fiducial 2 | stand-off 3 | -------------------------------------------------------------------------------- /ulp/SparkFun-BOM_Generator.ulp: -------------------------------------------------------------------------------- 1 | #usage "en: Outputs the contents of a design to Sparkle Friendly list " 2 | "

Usage: run SparkFun-BOM_Generator

" 3 | "

Author: Owen Lyke, Nathan Seidle <owen.lyke@sparkfun.com>
" 4 | "Version: 1.0

" 5 | 6 | /* 7 | 8 | #usage "en: Outputs the contents of a design to Sparkle Friendly list PCBWay requires the user to create panels that are at least 75x75mm. If the panel is smaller than this they will reject it because their v-score machine can't handle it. This ULP takes a given design and replicates it until the panel is just over the dimensions specified by the user. It also adds dimension lines between copies and v-score text so that PCBWay knows where to v-score. This script will also detect overhanging parts and warn the user that gaps are needed. Script tries to identify the soldermask color based on the logos on the board (SparkFun vs SparkX vs LilyPad). Script looks for 0.8mm tag for thin boards. Script outputs a ordering_instructions.txt file containing all the characteristics of this panel." 9 | "

Usage: run bom_sparkle

" 10 | "

Author: Nathan Seidle <inathan@sparkfun.com>
" 11 | "Version: 1.0

" 12 | 13 | */ 14 | 15 | // Modified October 2021, Paul Clark 16 | /* 17 | 18 | Modification goals: 19 | - Add Pick and Place Helper 20 | * Provide a 'quick' way to highlight particular parts when hand-populating a board 21 | 22 | */ 23 | 24 | // Modified October 2018, Owen Lyke 25 | /* 26 | 27 | Modification goals: 28 | - improve detection of false positives (a part that is on the board but doesn't exactly match a production part that can be used) 29 | * previous method was to search the part name and make sure it included the value 30 | 31 | - output a format that sparkle can handle to automatically set the quantity (this depends on SWIT adding this functionality in sparkle first) 32 | * currently in-progress, requires SWIT support but can be easily adapted into the output format when needed 33 | 34 | - improve detetion of on-board vs no-package components 35 | * answered by allowing the user to flag entries as "BOM" or "Non-BOM" while still not missing any board elements 36 | * also looping through boad elements as opposed to schematic elements helps 37 | 38 | */ 39 | 40 | #include "z_Include_SF_BOM.ulp" 41 | 42 | string pnpString = ""; 43 | 44 | if (schematic) 45 | { 46 | exit("edit .brd; run " + ulpName); 47 | } 48 | if (board) 49 | { 50 | 51 | int cnfrdres = configRead(configFile); 52 | if (cnfrdres) 53 | { 54 | configWrite(configFile); 55 | } 56 | 57 | // This loop does the initial categorization of all the components. 58 | // It is based off of only existence of PROD_ID or not 59 | initialGrouping(); 60 | 61 | categorizeElements(); // Initial categorization 62 | 63 | dlgDialog("BOM Output"){ 64 | 65 | dlgTabWidget{ 66 | dlgTabPage("BOM View"){ 67 | dlgHBoxLayout{ 68 | 69 | dlgVBoxLayout{ 70 | // BOM items 71 | dlgLabel("BOM Items"); 72 | dlgListView(headerString, bomlistarry, bomSelected, bomSort); 73 | dlgPushButton("Move to Non-BOM") 74 | { 75 | if (bomSelected != -1) 76 | { 77 | master_status[bom_index_map[bomSelected]] = element_status_nonbom; 78 | categorizeElements(); 79 | } 80 | } 81 | } 82 | 83 | dlgVBoxLayout 84 | { 85 | // Non-BOM items 86 | dlgHBoxLayout 87 | { 88 | dlgLabel("Non-BOM Items"); 89 | } 90 | // dlgStretch(1); 91 | dlgListView(headerString, nonbomlistarry, nonbomSelected, nonbomSort); 92 | dlgPushButton("Move to BOM") 93 | { 94 | if (nonbomSelected != -1) 95 | { 96 | master_status[nonbom_index_map[nonbomSelected]] = element_status_bom; 97 | categorizeElements(); 98 | } 99 | } 100 | } 101 | 102 | // Filters 103 | dlgVBoxLayout 104 | { 105 | 106 | dlgLabel("Welcome to the BOM utility!"); 107 | dlgPushButton("BOM Utility Help/Info/FAQ") 108 | { 109 | dlgDialog("NBOM Utility Info") 110 | { 111 | dlgLabel("This ULP lets you confidently keep track of all the elements on your board\n\ 112 | \n\ 113 | The main feature is the ability to change which items are considered to be part of the BOM.\n\ 114 | There are two ways of doins this:\n\ 115 | \t- 1) Manually move items from \"BOM Items\" to \"Non-BOM Items\" and back using the buttons below each list\n\ 116 | \t- 2) Apply a filter on the package names to exclude them from the \"Non-BOM Items\" list.\n\ 117 | \n\ 118 | * Notes: \n\ 119 | t- Items that have no PROD_ID, no contacts, and no holes are considered \"Non-Hardware\" and are excluded from BOM permanently\n\ 120 | \t- You can toggle the filter to see what is hidden from the \"Non-BOM Items\" list\n\ 121 | \t- Items in the \"BOM Items\" list are not affected by filters, so you can manually override a filter.\n\ 122 | \t- A defualt ilter file is loaded on startup, if present. You can also write your own filter files and load them.\n\ 123 | \t\t (each line of the text file is a filter entry)\n\ 124 | \t- The sparkle output will let you know how many BOM items are missing a PROD_ID (these are not displayed in the sparkle CSV)"); 125 | // dlgListView("Qty\tPROD_ID\tPackage\tValue\tNames", silklistarry, silkSelected, silkSort); 126 | dlgPushButton("Close") 127 | { 128 | dlgAccept(); 129 | } 130 | }; 131 | } 132 | 133 | dlgPushButton("Export BOM as CSV: ") 134 | { 135 | // exportFilePath = dlgFileOpen("Select directory in which to export the BOM", EAGLE_HOME, "*"); 136 | exportFilePath = dlgDirectory("Select directory in which to export the BOM", EAGLE_HOME); 137 | 138 | if (exportFilePath != "") 139 | { 140 | exportFilePath += "/bom_output.csv"; 141 | 142 | output(exportFilePath, "wt") 143 | { 144 | string line = "Qty, PROD_ID, Names, Value, Package"; 145 | printf("%s\n", line); // Header 146 | for (int indi = 0; indi < numUniqueEntries; indi++) 147 | { 148 | if (master_status[indi] == element_status_bom) 149 | { 150 | string local_names = replaceCharacter(master_names[indi], ',', ';'); 151 | string local_values = replaceCharacter(master_values[indi], ',', ';'); 152 | string local_prod_ids = replaceCharacter(master_prod_ids[indi], ',', ';'); 153 | string local_package_names = replaceCharacter(master_package_names[indi], ',', ';'); 154 | 155 | printf("%d, %s, %s, %s, %s\n", master_quantities[indi], local_prod_ids, local_names, local_values, local_package_names); 156 | } 157 | } 158 | dlgMessageBox("File created at: " + exportFilePath); 159 | } 160 | // dlgDialog("Rename Export File?") 161 | // { 162 | // dlgLabel("Output file created at: " + exportFilePath); 163 | // dlgLabel("Rename the file?"); 164 | // dlgHBoxLayout{ 165 | // dlgPushButton("-No"){ 166 | // dlgAccept(); 167 | // } 168 | // dlgPushButton("+Yes"){ 169 | // string newExportFileName = ""; 170 | // string data[]; 171 | // int line = fileread(data, exportFilePath); 172 | 173 | // dlgDialog("Enter new name: "){ 174 | // dlgTextEdit(&newExportFileName){ dlgAccept(); }; 175 | // } 176 | 177 | // output(newExportFileName){ 178 | // if(line) 179 | // { 180 | // int indi = 0; 181 | // while(data[indi] != ""){ 182 | // filterStrings[indi] = data[indi]; 183 | // indi++; 184 | // } 185 | // } 186 | // } 187 | 188 | // dlgAccept(); 189 | // } 190 | 191 | // } 192 | // }; 193 | } 194 | else 195 | { 196 | dlgMessageBox("No path supplied"); 197 | } 198 | 199 | exportFilePath = ""; 200 | } 201 | 202 | dlgHBoxLayout 203 | { 204 | dlgVBoxLayout 205 | { 206 | dlgLabel("Filters status: \n(double click to change)"); 207 | dlgListBox(filterStatus, filters_active) categorizeElements(); 208 | } 209 | dlgVBoxLayout 210 | { 211 | dlgLabel("Number of filtered items \n(hidden from the Non-BOM list):"); 212 | dlgTextView(numFilteredItems); 213 | } 214 | } 215 | dlgPushButton("View Non-Hardware Items") 216 | { 217 | dlgDialog("Non-Hardware Elements") 218 | { 219 | dlgLabel("Stuff"); 220 | dlgListView(headerString, nonhardwarelistarry, nonhardwareSelected, nonhardwareSort); 221 | dlgHBoxLayout 222 | { 223 | dlgPushButton("Move to BOM") 224 | { 225 | if (nonhardwareSelected != -1) 226 | { 227 | master_status[nonhardware_index_map[nonhardwareSelected]] = element_status_bom; 228 | categorizeElements(); 229 | dlgAccept(); 230 | } 231 | } 232 | dlgPushButton("Move to Non-BOM") 233 | { 234 | if (nonhardwareSelected != -1) 235 | { 236 | master_status[nonhardware_index_map[nonhardwareSelected]] = element_status_nonbom; 237 | categorizeElements(); 238 | dlgAccept(); 239 | } 240 | } 241 | } 242 | dlgPushButton("Close") 243 | { 244 | dlgAccept(); 245 | } 246 | }; 247 | } 248 | } 249 | } 250 | } 251 | 252 | dlgTabPage("Filter Settings") 253 | { 254 | // Filter Modification 255 | dlgLabel("Current Filter Strings \n(Apply only to items in the Non-BOM list - initially any item with a PROD_ID is displayed)"); 256 | dlgListView("Filter", filterStrings, filter_string_selected, filter_string_sort); 257 | dlgPushButton("Remove from filter list") 258 | { 259 | removeFromFilterList(); 260 | categorizeElements(); 261 | } 262 | 263 | dlgLabel("Add new filters"); 264 | dlgTextEdit(temp_filter_string); 265 | dlgPushButton("Add to filter list") 266 | { 267 | addToFilterList(); 268 | categorizeElements(); 269 | } 270 | 271 | dlgHBoxLayout 272 | { 273 | dlgPushButton("Load filter cnfg file") 274 | { 275 | customFilterFile = dlgFileOpen("Select a filter cnfiguration file (.flt)", path_ulp[0], "*.flt"); 276 | configRead(customFilterFile); 277 | categorizeElements(); 278 | } 279 | dlgPushButton("Save as default cnfg") 280 | { 281 | configWrite(configFile); 282 | categorizeElements(); 283 | } 284 | } 285 | } 286 | 287 | dlgTabPage("Sparkle Output") 288 | { 289 | dlgLabel("*Reminder* Don't forget to add a PCB part to the BOM in Sparkle"); 290 | dlgLabel("CSV of PROD_IDs for Sparkle"); 291 | dlgTextView(sparkleBOM); 292 | dlgLabel("PROD_ID Status:"); 293 | dlgTextView(prod_id_warning); 294 | } 295 | 296 | dlgTabPage("Pick and Place Helper") 297 | { 298 | dlgVBoxLayout{ 299 | // BOM items 300 | dlgLabel("BOM Items"); 301 | dlgListView(pnpHeaderString, pnplistarry, pnpSelected, bomSort); 302 | dlgPushButton("Show") 303 | { 304 | if (pnpSelected == -1) 305 | { 306 | pnpString = ""; 307 | } 308 | else 309 | { 310 | pnpString = "show " + string(master_pnp_names[bom_index_map[pnpSelected]]); 311 | } 312 | dlgAccept(); 313 | }; 314 | }; 315 | } 316 | } 317 | 318 | dlgGridLayout 319 | { 320 | 321 | dlgCell(0, 0) 322 | { 323 | dlgPushButton("Done") 324 | { 325 | setup_complete = 1; 326 | // result = 0; 327 | dlgAccept(); 328 | }; 329 | }; 330 | } 331 | } 332 | ; 333 | if (pnpString == "") 334 | exit(0); 335 | else 336 | exit(pnpString); 337 | } 338 | else 339 | { 340 | dlgMessageBox("Please run this ulp from the board editor"); 341 | exit(1); 342 | } 343 | -------------------------------------------------------------------------------- /ulp/SparkFun-CAMmer-linux.ulp: -------------------------------------------------------------------------------- 1 | #usage "en: Output Gerbers of a given board. This script looks at how many layers, if there are bottom components, etc and outputs the necessary Gerber files. It will also zip them together if user requests it." 2 | "

Usage: run sparkfun-cammer

" 3 | "

Author: Nathan Seidle <inathan@sparkfun.com>
" 4 | "Version: 1.0

" 5 | 6 | /* 7 | Original board dimension code came from https://gist.github.com/itavero/8042433 8 | CAM code comes from https://www.element14.com/community/thread/22904/l/re-can-a-ulp-initiate-a-cam-job?displayFullThread=true 9 | 10 | See EAGLE help file for "Command Line Options" 11 | 12 | The ZIP creation relies on 7zip. Specifically 7za.exe the stand-alone version of 7zip. To get this you need 13 | to first install 7zip, then download the "7-zip Extra" 7z stand alone console version. Use 7zip to open the 7z 14 | archive. In the archive you should see the 7za.exe file. Put this in the same directory as this ULP. 15 | 16 | TODO: 17 | 18 | Add option to preview in gerbV upon completion 19 | 20 | https://forums.autodesk.com/t5/eagle-forum/generate-manufacturing-data-from-a-terminal/m-p/7778090/highlight/true#M10377 21 | 22 | eaglecon -X -dCAMJOB -j"C:\Users\OldLenny\Dropbox\Projects\SparkFun_Eagle_Settings\cam\sfe-gerb274x_newProcessor.cam" -o"C:\Users\OldLenny\Dropbox\Projects\BlackBoard\Hardware\Production" "C:\Users\OldLenny\Dropbox\Projects\BlackBoard\Hardware\Production\BlackBoard-Panel.brd" 23 | 42 seconds to CAM the BlackBoard panel (8.8 x 7.2" with massive amounts of intense silkscreen artifacts) 24 | */ 25 | 26 | string configFile = filesetext(argv[0], ".cfg"); 27 | 28 | string bottomPackages = ""; 29 | 30 | //Config options we want to save 31 | int outputGerbers = 1; 32 | int outputTopStencil = 1; 33 | int outputBottomStencil = 1; 34 | int zipOutput = 1; 35 | int runGerbV = 1; 36 | 37 | void configWrite() 38 | { 39 | output(configFile) 40 | { 41 | printf("%d\n", outputGerbers); 42 | printf("%d\n", outputTopStencil); 43 | printf("%d\n", outputBottomStencil); 44 | printf("%d\n", zipOutput); 45 | printf("%d\n", runGerbV); 46 | } 47 | } 48 | 49 | void configRead() 50 | { 51 | if (filesize(configFile)) 52 | { //Check if file exists 53 | string data[]; 54 | int line = fileread(data, configFile); 55 | if (line >= 4) 56 | { 57 | outputGerbers = strtol(data[0]); 58 | outputTopStencil = strtol(data[1]); 59 | outputBottomStencil = strtol(data[2]); 60 | zipOutput = strtol(data[3]); 61 | runGerbV = strtol(data[4]); 62 | } 63 | } 64 | } 65 | 66 | //Finds a string in a string no matter where, no matter capitalization 67 | int containsString(string toSearch, string toFind) 68 | { 69 | int pos = strstr(strlwr(toSearch), strlwr(toFind)); 70 | if (pos >= 0) //String found 71 | { 72 | return (1); 73 | } 74 | 75 | return (0); 76 | } 77 | 78 | //Detect if board has four layers 79 | //This was re-written to scan only for signal wires on internals layers becaused things like a microB connector uses polygons on layers 2/15 80 | int hasFourLayers() 81 | { 82 | //Old way 83 | /*board(B) { 84 | B.layers(L) { 85 | if(L.used == 1 && L.number == 2) 86 | { 87 | return(1); 88 | } 89 | if(L.used == 1 && L.number == 15) 90 | { 91 | return(1); 92 | } 93 | } 94 | }*/ 95 | 96 | board(B) 97 | { 98 | B.signals(S) 99 | { 100 | S.wires(W) 101 | { 102 | if (W.layer == 2) 103 | { 104 | return (1); 105 | } 106 | if (W.layer == 15) 107 | { 108 | return (1); 109 | } 110 | } 111 | } 112 | } 113 | return (0); //Nope 114 | } 115 | 116 | //Detect if board has six layers 117 | int hasSixLayers() 118 | { 119 | board(B) 120 | { 121 | B.signals(S) 122 | { 123 | S.wires(W) 124 | { 125 | if (W.layer == 3) 126 | { 127 | return (1); 128 | } 129 | if (W.layer == 14) 130 | { 131 | return (1); 132 | } 133 | } 134 | } 135 | } 136 | return (0); //Nope 137 | } 138 | 139 | //Detect if parts are on a given layer of the board 140 | int hasPartsOnLayer(int layerNumber) 141 | { 142 | board(B) 143 | { 144 | B.elements(E) 145 | { 146 | E.package.contacts(C) 147 | { 148 | if (C.smd && C.smd.layer == layerNumber) 149 | { 150 | 151 | //Ignore 152 | //Fiducials, jumpers with traces as closure method, jumpers that are normally open 153 | if (containsString(E.package.name, "fiducial") == 0 && containsString(E.package.name, "NC_TRACE") == 0 && containsString(E.package.name, "NC_BY_TRACE") == 0 && containsString(E.package.name, "SJ_2S-NO") == 0 && containsString(E.package.name, "SMT-JUMPER") == 0 && containsString(E.package.name, "USB-MICROB-PTH-MILL") == 0 && containsString(E.package.name, "USB-C") == 0 && containsString(E.package.name, "PAD.03X.03") == 0 //Test points 154 | && containsString(E.package.name, "PAD.03X.05") == 0 && containsString(E.package.name, "USB-SOLDER-PADS") == 0) 155 | { 156 | //String not found, this is a legit part 157 | bottomPackages += E.package.name + ","; 158 | return (1); 159 | } 160 | } 161 | } 162 | } 163 | } 164 | 165 | return (0); //Nope 166 | } 167 | 168 | //Detect if parts are on the top of the board 169 | int hasTopParts() 170 | { 171 | return (hasPartsOnLayer(1)); 172 | } 173 | 174 | //Detect if parts are on the bottom of the board 175 | int hasBottomParts() 176 | { 177 | return (hasPartsOnLayer(16)); 178 | } 179 | 180 | string get_project_path() 181 | { 182 | if (board) 183 | board(B) return (filedir(B.name)); 184 | if (schematic) 185 | schematic(B) return (filedir(B.name)); 186 | } 187 | 188 | //Change any / in a string to \ 189 | //Useful for directory structure before calling a cmd 190 | string convertForwardToBackSlashes(string thing) 191 | { 192 | //Convert forward slashes to back slashes so we can run system command 193 | int pos = strrchr(thing, '/'); 194 | while (pos >= 0) 195 | { 196 | //thing = strsub(thing, 0, pos) + "\\\\" + strsub(thing, pos + 1, strlen(thing)); //Remove and replace 197 | thing = strsub(thing, 0, pos) + "\\" + strsub(thing, pos + 1, strlen(thing)); //Remove and replace 198 | pos = strrchr(thing, '/'); //Look for the next forward slash 199 | } 200 | return (thing); 201 | } 202 | 203 | //Returns true if a file exists 204 | int FileExists(string name) 205 | { 206 | string files[]; 207 | return (fileglob(files, name) != 0); 208 | } 209 | 210 | //CAM the current BRD file 211 | void createGerbers() 212 | { 213 | //Get the name of this brd (no extension, no directory) 214 | string baseFileName = ""; 215 | board(B) 216 | { 217 | baseFileName = filesetext(filename(B.name), ""); 218 | } 219 | 220 | //Convert forward slashes to back slashes so we can run system commands 221 | string projectDirectory = convertForwardToBackSlashes(get_project_path()); 222 | 223 | string commandToRun = "echo Relax. This can take a minute..."; //This is the start of the command. /C = close window 224 | //string commandToRun = "cmd.exe /K echo Relax. This can take a minute..."; //This is the start of the command. /C = close window 225 | string s = ""; 226 | 227 | //Remove any files in the production folder left over from previous panel CAM 228 | //There's a chance that a previous ULP job creates files that should not be zipped. 229 | commandToRun += " && echo Removing old files"; 230 | 231 | string fileLocation = ""; 232 | sprintf(fileLocation, "%s%s.G*", get_project_path(), baseFileName); //Search for file using forward slashes 233 | if (FileExists(fileLocation)) 234 | { 235 | sprintf(s, "rm -rf \"%s%s.G*\"", projectDirectory, baseFileName); //Remove file with back slashes 236 | commandToRun += " && " + s; 237 | } 238 | 239 | sprintf(fileLocation, "%s%s.TXT", get_project_path(), baseFileName); 240 | if (FileExists(fileLocation)) 241 | { 242 | sprintf(s, "rm -rf \"%s%s.TXT\"", projectDirectory, baseFileName); 243 | commandToRun += " && " + s; 244 | } 245 | 246 | sprintf(fileLocation, "%s%s.ZIP", get_project_path(), baseFileName); 247 | if (FileExists(fileLocation)) 248 | { 249 | sprintf(s, "rm -rf \"%s%s.ZIP\"", projectDirectory, baseFileName); 250 | commandToRun += " && " + s; 251 | } 252 | 253 | sprintf(fileLocation, "%s%s.dri", get_project_path(), baseFileName); 254 | if (FileExists(fileLocation)) 255 | { 256 | sprintf(s, "rm -rf \"%s%s.dri\"", projectDirectory, baseFileName); 257 | commandToRun += " && " + s; 258 | } 259 | 260 | //The new version of Eagle (v8/9) has a faster CAM processor. We call it with the CAM file and we get gerbers out. 261 | sprintf(s, " && echo Running New CAM Processor on %s", baseFileName); 262 | commandToRun += s; 263 | 264 | //1,217 seconds to complete CAM using old method 265 | //42 seconds to CAM the BlackBoard panel (8.8 x 7.2" with massive amounts of intense silkscreen artifacts) 266 | //28 times faster! 267 | 268 | //Run CAM file from EagleCon 269 | 270 | //Find the user's directory containing the SparkFun CAM files 271 | string pathToCAMs = ""; 272 | for (int x = 0; x < 20; x++) 273 | { 274 | string thisDirectory = path_cam[x]; 275 | if (strlen(thisDirectory) == 0) 276 | { 277 | dlgMessageBox("Could not find the sfe-gerb* CAM files. Have you loaded the SparkFun_Eagle_Settings folders into the EAGLE 'Directories' menu correctly?"); 278 | exit(-1); 279 | } 280 | 281 | sprintf(fileLocation, "%s/sfe-gerb274*.cam", thisDirectory); 282 | if (FileExists(fileLocation)) 283 | { 284 | pathToCAMs = thisDirectory; 285 | break; 286 | } 287 | } 288 | 289 | string camFileLocation = pathToCAMs + "/sfe-gerb274x-2layer.cam"; //You must have the SparkFun CAM files in the CAM directory setting so that Eagle can find this file 290 | 291 | if (hasSixLayers() == 1) 292 | camFileLocation = pathToCAMs + "/sfe-gerb274x-6layer.cam"; //You must have the SparkFun CAM files in the CAM directory setting so that Eagle can find this file 293 | else if (hasFourLayers() == 1) 294 | camFileLocation = pathToCAMs + "/sfe-gerb274x-4layer.cam"; //You must have the SparkFun CAM files in the CAM directory setting so that Eagle can find this file 295 | 296 | sprintf(fileLocation, "%s%s.brd", get_project_path(), baseFileName); 297 | 298 | sprintf(s, " \"%s/eagle\" -X -dCAMJOB -j\"%s\" -o\"%s\" \"%s\"", 299 | EAGLE_DIR, 300 | camFileLocation, 301 | get_project_path(), 302 | fileLocation); 303 | 304 | commandToRun += " && " + s; 305 | 306 | //This is the old way of generating gerbers. It works, but it's very slow. 307 | /* 308 | //Generate Gerbers 309 | string fileExtension = ""; 310 | string layerNumbers = ""; 311 | string device = ""; 312 | string mirror = ""; 313 | for (int x = 0; x < 12; x++) 314 | { 315 | if (x == 0) //Top copper 316 | { 317 | if (outputGerbers == 0) 318 | continue; 319 | fileExtension = "GTL"; 320 | layerNumbers = "1 17 18"; 321 | commandToRun += " && echo Running Top Copper"; 322 | } 323 | else if (x == 1) //Top silk 324 | { 325 | if (outputGerbers == 0) 326 | continue; 327 | fileExtension = "GTO"; 328 | layerNumbers = "21"; 329 | commandToRun += " && echo Running Top Silk"; 330 | } 331 | else if (x == 2) //Top mask 332 | { 333 | if (outputGerbers == 0) 334 | continue; 335 | fileExtension = "GTS"; 336 | layerNumbers = "29"; 337 | commandToRun += " && echo Running Top Mask"; 338 | } 339 | else if (x == 3) //Bottom copper 340 | { 341 | if (outputGerbers == 0) 342 | continue; 343 | fileExtension = "GBL"; 344 | layerNumbers = "16 17 18"; 345 | commandToRun += " && echo Running Bottom Copper"; 346 | } 347 | else if (x == 4) //Bottom silk 348 | { 349 | if (outputGerbers == 0) 350 | continue; 351 | fileExtension = "GBO"; 352 | layerNumbers = "22"; 353 | commandToRun += " && echo Running Bottom Silk"; 354 | } 355 | else if (x == 5) //Bottom mask 356 | { 357 | if (outputGerbers == 0) 358 | continue; 359 | fileExtension = "GBS"; 360 | layerNumbers = "30"; 361 | commandToRun += " && echo Running Bottom Mask"; 362 | } 363 | else if (x == 6) //Outline/keepout 364 | { 365 | if (outputGerbers == 0) 366 | continue; 367 | fileExtension = "GKO"; 368 | layerNumbers = "20 46"; //Turn on dimension and milling (contains v-score indicators) layers 369 | commandToRun += " && echo Running Board Outline"; 370 | } 371 | else if (x == 7) //Top paste 372 | { 373 | if (outputTopStencil == 0) 374 | continue; 375 | fileExtension = "GTP"; 376 | layerNumbers = "31"; 377 | commandToRun += " && echo Running Top Paste"; 378 | } 379 | else if (x == 8) //Bottom paste 380 | { 381 | if (outputBottomStencil == 0) 382 | continue; 383 | if (hasBottomParts() == 0) 384 | continue; 385 | fileExtension = "GBP"; 386 | layerNumbers = "32"; 387 | commandToRun += " && echo Running Bottom Paste"; 388 | } 389 | else if (x == 9) //Drill file 390 | { 391 | if (outputGerbers == 0) 392 | continue; 393 | fileExtension = "TXT"; 394 | layerNumbers = "44 45"; 395 | commandToRun += " && echo Running Drill File"; 396 | } 397 | else if (x == 10) //Inner layer 2 398 | { 399 | if (outputGerbers == 0) 400 | continue; 401 | if (hasFourLayers() == 0) 402 | continue; 403 | fileExtension = "GL2"; 404 | layerNumbers = "2 17 18"; 405 | commandToRun += " && echo Running Layer 2"; 406 | } 407 | else if (x == 11) //Inner layer 15 408 | { 409 | if (outputGerbers == 0) 410 | continue; 411 | if (hasFourLayers() == 0) 412 | continue; 413 | fileExtension = "GL3"; 414 | layerNumbers = "15 17 18"; 415 | commandToRun += " && echo Running Layer 15"; 416 | } 417 | 418 | //Deal with special layers 419 | device = "GERBER_RS274X"; 420 | if (x == 9) 421 | device = "EXCELLON_24"; //Drill file 422 | 423 | mirror = "-m-"; //No mirror 424 | //if(x == 8) mirror = "-m+"; //Mirror the bottom paste layer 425 | 426 | //Add this CAM operation to the list 427 | sprintf(s, " \"%s/eagle\" -X -N- %s -f+ -O+ -c+ -x0 -y0 -d%s -o \"%s.%s\" \"%s\" %s", 428 | EAGLE_DIR, 429 | mirror, 430 | device, 431 | baseFileName, 432 | fileExtension, 433 | projectDirectory + baseFileName + ".brd", 434 | layerNumbers); 435 | 436 | commandToRun += " && " + s; 437 | }*/ 438 | 439 | //Zip files using 7za (7za.exe should be located in same directory as ULP) 440 | if (zipOutput == 1) 441 | { 442 | string sevenZaLocation = convertForwardToBackSlashes(filedir(argv[0])); 443 | sevenZaLocation += "\\7za.exe"; 444 | 445 | string outputFileName = projectDirectory + baseFileName + ".zip"; 446 | 447 | //Get all the wanted files 448 | string fileList = ""; 449 | fileList += "\"" + projectDirectory + baseFileName + ".GTL" + "\""; 450 | fileList += " \"" + projectDirectory + baseFileName + ".GTO" + "\""; 451 | fileList += " \"" + projectDirectory + baseFileName + ".GTS" + "\""; 452 | 453 | fileList += " \"" + projectDirectory + baseFileName + ".GBL" + "\""; 454 | fileList += " \"" + projectDirectory + baseFileName + ".GBO" + "\""; 455 | fileList += " \"" + projectDirectory + baseFileName + ".GBS" + "\""; 456 | 457 | if (hasSixLayers() == 1) 458 | { 459 | fileList += " \"" + projectDirectory + baseFileName + ".GL2" + "\""; 460 | fileList += " \"" + projectDirectory + baseFileName + ".GL3" + "\""; 461 | fileList += " \"" + projectDirectory + baseFileName + ".GL4" + "\""; 462 | fileList += " \"" + projectDirectory + baseFileName + ".GL5" + "\""; 463 | } 464 | else if (hasFourLayers() == 1) 465 | { 466 | fileList += " \"" + projectDirectory + baseFileName + ".GL2" + "\""; 467 | fileList += " \"" + projectDirectory + baseFileName + ".GL3" + "\""; 468 | } 469 | 470 | fileList += " \"" + projectDirectory + baseFileName + ".GKO" + "\""; 471 | 472 | fileList += " \"" + projectDirectory + baseFileName + ".TXT" + "\""; //Get drill file 473 | 474 | fileList += " \"" + projectDirectory + "ordering_instructions.txt" + "\""; //Send the ordering instructions as an extra precaution 475 | 476 | if (outputTopStencil == 1) 477 | { 478 | fileList += " \"" + projectDirectory + baseFileName + ".GTP" + "\""; 479 | } 480 | if (outputBottomStencil == 1 && hasBottomParts() == 1) 481 | { 482 | fileList += " \"" + projectDirectory + baseFileName + ".GBP" + "\""; 483 | } 484 | 485 | sprintf(s, "\"%s\" a \"%s\" %s", 486 | sevenZaLocation, 487 | outputFileName, 488 | fileList); 489 | 490 | commandToRun += " && " + s; 491 | } 492 | 493 | if (runGerbV == 1) 494 | { 495 | string gerbVLocation = convertForwardToBackSlashes(filedir(argv[0])); 496 | gerbVLocation += "\\gerbv.exe"; 497 | 498 | //Get all the wanted files 499 | string fileList = ""; 500 | fileList += "\"" + projectDirectory + baseFileName + ".GTL" + "\""; 501 | fileList += " \"" + projectDirectory + baseFileName + ".GTO" + "\""; 502 | fileList += " \"" + projectDirectory + baseFileName + ".GTS" + "\""; 503 | 504 | fileList += " \"" + projectDirectory + baseFileName + ".GBL" + "\""; 505 | fileList += " \"" + projectDirectory + baseFileName + ".GBO" + "\""; 506 | fileList += " \"" + projectDirectory + baseFileName + ".GBS" + "\""; 507 | 508 | if (hasSixLayers() == 1) 509 | { 510 | fileList += " \"" + projectDirectory + baseFileName + ".GL2" + "\""; 511 | fileList += " \"" + projectDirectory + baseFileName + ".GL3" + "\""; 512 | fileList += " \"" + projectDirectory + baseFileName + ".GL4" + "\""; 513 | fileList += " \"" + projectDirectory + baseFileName + ".GL5" + "\""; 514 | } 515 | else if (hasFourLayers() == 1) 516 | { 517 | fileList += " \"" + projectDirectory + baseFileName + ".GL2" + "\""; 518 | fileList += " \"" + projectDirectory + baseFileName + ".GL3" + "\""; 519 | } 520 | 521 | fileList += " \"" + projectDirectory + baseFileName + ".GKO" + "\""; 522 | 523 | fileList += " \"" + projectDirectory + baseFileName + ".TXT" + "\""; //Get drill file 524 | 525 | if (outputTopStencil == 1) 526 | { 527 | fileList += " \"" + projectDirectory + baseFileName + ".GTP" + "\""; 528 | } 529 | if (outputBottomStencil == 1 && hasBottomParts() == 1) 530 | { 531 | fileList += " \"" + projectDirectory + baseFileName + ".GBP" + "\""; 532 | } 533 | 534 | sprintf(s, "\"%s\" %s", 535 | gerbVLocation, 536 | fileList); 537 | 538 | commandToRun += " && " + s; 539 | } 540 | 541 | //dlgMessageBox(commandToRun); 542 | if (system(commandToRun) != 0) 543 | { 544 | dlgMessageBox("Error: Command failed.", "OK"); 545 | } 546 | else 547 | { 548 | dlgMessageBox("Gerber generation complete."); 549 | } 550 | } 551 | 552 | if (board) 553 | { 554 | configRead(); //Read any settings if available 555 | 556 | //GUI 557 | int dstatus = dlgDialog("Gerber Generation Options") 558 | { 559 | 560 | dlgHBoxLayout { dlgSpacing(300); } 561 | 562 | if (hasSixLayers() == 1) 563 | { 564 | dlgHBoxLayout { dlgLabel("Note: This is a six layer board\t"); } 565 | } 566 | else if (hasFourLayers() == 1) 567 | { 568 | dlgHBoxLayout { dlgLabel("Note: This is a four layer board\t"); } 569 | } 570 | if (hasBottomParts() == 1) 571 | { 572 | dlgHBoxLayout 573 | { 574 | dlgLabel("Note: This board has parts on bottom side:
" + bottomPackages); 575 | } 576 | outputBottomStencil = 1; //Persuade user to generate these gerbers 577 | } 578 | else 579 | { 580 | dlgHBoxLayout { dlgLabel("This board does not have parts on bottom side\t"); } 581 | outputBottomStencil = 0; 582 | } 583 | 584 | dlgHBoxLayout { dlgLabel("\t"); } 585 | 586 | dlgGroup("Output Files") 587 | { 588 | dlgHBoxLayout { dlgCheckBox("Gerbers", outputGerbers); } 589 | dlgHBoxLayout { dlgCheckBox("Top Stencil", outputTopStencil); } 590 | dlgHBoxLayout { dlgCheckBox("Bottom Stencil", outputBottomStencil); } 591 | dlgHBoxLayout { dlgCheckBox("Zip Output Files", zipOutput); } 592 | } 593 | 594 | dlgHBoxLayout { dlgCheckBox("Run gerbV upon completion", runGerbV); } 595 | 596 | dlgPushButton("+Generate") 597 | { 598 | configWrite(); //Record current settings 599 | 600 | createGerbers(); //Generate gerbers for this BRD 601 | 602 | //Preview in gerbV 603 | 604 | dlgAccept(-1); 605 | } 606 | 607 | dlgStretch(1); 608 | }; 609 | 610 | configWrite(); //Record current settings 611 | } 612 | else 613 | { 614 | dlgMessageBox("Please run SparkFun CAMmer from a board."); 615 | exit(1); 616 | } 617 | -------------------------------------------------------------------------------- /ulp/SparkFun-Flip.ulp: -------------------------------------------------------------------------------- 1 | #usage "en: Flip the entire design around X midpoint. Very helpful for placing bottom silk correctly." 2 | "

Usage: run sparkfun-flip

" 3 | "

Author: Nathan Seidle <inathan@sparkfun.com>
" 4 | "Version: 1.0

" 5 | 6 | //Original board dimension code came from https://gist.github.com/itavero/8042433 7 | 8 | string bigScript = ""; //The big string of commands that we will eventually run as a script 9 | 10 | real xMax = 0; 11 | real yMax = 0; 12 | real xMin = 0; 13 | real yMin = 0; 14 | 15 | void flip() { 16 | //Determine the current grid type and size 17 | int originalGridUnit; //1 = mm, 3 = inches 18 | board(B) { 19 | originalGridUnit = B.grid.unit; 20 | } 21 | 22 | //Turn on everything. Group everything. 23 | bigScript += "DISPLAY ALL; GROUP ALL;\n"; 24 | 25 | //Change grid to inches 26 | bigScript += "GRID INCH ON;\n"; 27 | 28 | //Mirror everything around the mid point of this design 29 | string s = ""; 30 | sprintf(s, "MIRROR (>%.5f 0);\n", xMax/2); 31 | bigScript += s; 32 | 33 | //Return grid to original settings 34 | if(originalGridUnit == GRID_UNIT_MIC) //mic 35 | { 36 | bigScript += "GRID MIC ON;\n"; 37 | } 38 | if(originalGridUnit == GRID_UNIT_MM) //mm 39 | { 40 | bigScript += "GRID MM ON;\n"; 41 | } 42 | if(originalGridUnit == GRID_UNIT_MIL) //mil 43 | { 44 | bigScript += "GRID MIL ON;\n"; 45 | } 46 | if(originalGridUnit == GRID_UNIT_INCH) //inch 47 | { 48 | bigScript += "GRID IN ON;\n"; 49 | } 50 | 51 | //Turn on default layers 52 | bigScript += "DISPLAY NONE; DISPLAY 1 2 15 16 17 18 19 20 21 22 23 24 45 46 51; DISPLAY -25 -26 -27 -28;\n"; 53 | 54 | //This clears the group selection 55 | bigScript += "GROUP;\n"; 56 | } 57 | 58 | //Look at board dimensions and components 59 | //Find the min/max coordinates of the design 60 | void calculateDesignDimensions() 61 | { 62 | //Find min/max dimensions of this board 63 | char firstPoint = 'y'; 64 | char firstPointOverhang = 'y'; 65 | 66 | board(B) { 67 | B.wires(W) { 68 | if (W.layer == LAYER_DIMENSION) { 69 | // Wire is on dimension layer 70 | real wx1 = u2inch(W.x1); 71 | real wy1 = u2inch(W.y1); 72 | real wx2 = u2inch(W.x2); 73 | real wy2 = u2inch(W.y2); 74 | 75 | // Start point of wire 76 | if (firstPoint == 'y') { 77 | firstPoint = 'n'; 78 | xMax = wx1; 79 | xMin = wx1; 80 | yMax = wy1; 81 | yMin = wy1; 82 | } 83 | else { 84 | if (wx1 > xMax) { 85 | xMax = wx1; 86 | } 87 | if (wx1 < xMin) { 88 | xMin = wx1; 89 | } 90 | if (wy1 > yMax) { 91 | yMax = wy1; 92 | } 93 | if (wy1 < yMin) { 94 | yMin = wy1; 95 | } 96 | } 97 | 98 | // End point of wire 99 | if (wx2 > xMax) { 100 | xMax = wx2; 101 | } 102 | if (wx2 < xMin) { 103 | xMin = wx2; 104 | } 105 | if (wy2 > yMax) { 106 | yMax = wy2; 107 | } 108 | if (wy2 < yMin) { 109 | yMin = wy2; 110 | } 111 | } 112 | } 113 | } 114 | 115 | //Check if this design has dimension lines. If it doesn't then it's probably a DXF import of an enclosure or something very weird. 116 | if(xMin == 0 && yMax == 0) 117 | { 118 | dlgMessageBox("!This board has no dimension lines. Cannot flip. Exiting."); 119 | exit(-1); 120 | } 121 | } 122 | 123 | if (board) 124 | { 125 | calculateDesignDimensions(); //Find the max X of the design 126 | 127 | flip(); //Flip the design 128 | 129 | exit(bigScript); //Execute this generated script 130 | } 131 | else 132 | { 133 | dlgMessageBox("Please run SparkFun Flip ULP from a board."); 134 | exit(1); 135 | } -------------------------------------------------------------------------------- /ulp/Trace-Length.ulp: -------------------------------------------------------------------------------- 1 | /* 2 | This ULP was originally created by EAGLE PCB by 3 | "A. Zaffran 05.04.2000 alf@cadsoft.de" 4 | 5 | Modified November 18th, 2020 by N. Seidle to make nets searchable. 6 | Often there are 2 or 5 nets you need to match lengths. 7 | 8 | THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED 9 | */ 10 | 11 | real f, WLtotal; 12 | int index[]; 13 | 14 | // ** aus "Mechanik der Elektronik" 15 | // mm <1 1 2 3 4 5 6 7 8 9 10 11 12 13 mm Leiterbreite bei 35 um Cu 16 | 17 | real k[] = {9, 8.8, 6, 4, 3.2, 2.9, 2.9, 2.9, 2.9, 2.9, 2.9, 2.9, 2.9, 2.9, 2.9}; 18 | 19 | // _______________________ 20 | // Imax ~ 5.25 V [d x b x (d + b)] x k || (tL ~60°) 21 | // 22 | // d = um Cu-Kaschierung 23 | // b = Breite mm 24 | // k = Korrekturwert aus Tabelle 02.02.2000 alf 25 | // ** aus "Mechanik der Elektronik" 26 | 27 | real Cu = 0.035; // 35 um Cu Kaschierung 28 | 29 | real Length[], Freq[], Widthmin[], Widthmax[]; 30 | string Signal[]; 31 | 32 | real c = 299800; // Lichtgechwindigkeit Vakuum in [km/s] 33 | 34 | int n = 0; 35 | int t; 36 | string data[]; 37 | string h; 38 | int note = 0; 39 | 40 | int true = 1; 41 | int false = 0; 42 | int abort = false; 43 | string netFilter = "CC"; 44 | 45 | //Get the name of this brd (no extension, no directory) 46 | string get_project_name() 47 | { 48 | if (board) 49 | board(B) return (filesetext(filename(B.name), "")); 50 | if (schematic) 51 | schematic(B) return (filesetext(filename(B.name), "")); 52 | } 53 | 54 | string get_project_path() 55 | { 56 | if (board) 57 | board(B) return (filedir(B.name)); 58 | if (schematic) 59 | schematic(B) return (filedir(B.name)); 60 | } 61 | 62 | void configWrite() 63 | { 64 | //Get the name of this brd (no extension, no directory) 65 | string baseFileName = get_project_name(); 66 | string configFile = get_project_path() + baseFileName + "-TraceLength.txt"; 67 | 68 | output(configFile) 69 | { 70 | printf("%s\n", netFilter); 71 | } 72 | } 73 | 74 | void configRead() 75 | { 76 | //Get the name of this brd (no extension, no directory) 77 | string baseFileName = get_project_name(); 78 | string configFile = get_project_path() + baseFileName + "-TraceLength.txt"; 79 | 80 | if (filesize(configFile)) 81 | { //Check if file exists 82 | string data[]; 83 | int line = fileread(data, configFile); 84 | if (line >= 0) 85 | { 86 | netFilter = data[0]; 87 | } 88 | } 89 | } 90 | 91 | void dialog(void) 92 | { 93 | int select = 0; 94 | int Result = dlgDialog("Wire length of Layout") 95 | { 96 | dlgLabel("List of signals with length and its max. frequency / current\n"); 97 | 98 | string lab; 99 | sprintf(lab, " Cu thickness = %.3f mm", Cu); 100 | dlgLabel(lab); 101 | dlgListView("", data, select); 102 | dlgStretch(0); 103 | 104 | dlgHBoxLayout 105 | { 106 | dlgStretch(1); 107 | dlgLabel("&Filters"); 108 | dlgStringEdit(netFilter); 109 | dlgPushButton("+Apply") 110 | { 111 | abort = false; 112 | dlgAccept(); 113 | } 114 | dlgPushButton("-Close") 115 | { 116 | abort = true; 117 | dlgReject(); 118 | } 119 | } 120 | }; 121 | } 122 | 123 | real WireLength(real x1, real x2, real y1, real y2) 124 | { 125 | return sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)); 126 | } 127 | 128 | real ArcLength(real ang1, real ang2, real radius) 129 | { 130 | return radius * 2 * PI / 360 * (ang2 - ang1); 131 | } 132 | 133 | real Frequency(real c, real l) 134 | { 135 | return c / l; 136 | } 137 | 138 | void WireWidth(string sig, real w) 139 | { 140 | // ermitteln der min-max Leiterbahnbreite 141 | if (w < Widthmin[n]) 142 | Widthmin[n] = w; 143 | if (w > Widthmax[n]) 144 | Widthmax[n] = w; 145 | } 146 | 147 | //Finds a string in a string no matter where, no matter capitalization 148 | int containsString(string toSearch, string toFind) 149 | { 150 | int pos = strstr(strlwr(toSearch), strlwr(toFind)); 151 | if (pos >= 0) //String found 152 | { 153 | return (1); 154 | } 155 | 156 | return (0); 157 | } 158 | 159 | real imax(real breite) 160 | { 161 | return (breite == 0) ? 0 : 5.25 * sqrt((Cu * breite * (Cu + breite)) * k[int(trunc(breite))]); 162 | } 163 | 164 | if (board) 165 | { 166 | configRead(); //Get previous netFilter 167 | 168 | //Loop until user presses close button 169 | while (abort == false) 170 | { 171 | //dlgMessageBox(netFilter); 172 | for (int x = 0; x < n; x++) 173 | data[x] = ""; 174 | n = 0; 175 | 176 | board(B) 177 | { 178 | B.signals(S) 179 | { 180 | WLtotal = 0; 181 | Widthmin[n] = 32000; 182 | Widthmax[n] = 0; 183 | S.wires(W) 184 | { 185 | if (W.layer < 17) 186 | { // nur Kupfer-Layer 187 | if (W.arc) 188 | { 189 | WLtotal += ArcLength(W.arc.angle1, W.arc.angle2, u2mm(W.arc.radius)); 190 | } 191 | else 192 | { 193 | WLtotal += WireLength(u2mm(W.x2), u2mm(W.x1), u2mm(W.y2), u2mm(W.y1)); 194 | } 195 | WireWidth(S.name, u2mm(W.width)); 196 | } 197 | } 198 | if (WLtotal != 0) 199 | { 200 | if (containsString(S.name, netFilter)) 201 | { 202 | Signal[n] = S.name; 203 | Length[n] = WLtotal; 204 | Freq[n] = Frequency(c, WLtotal); 205 | ++n; 206 | } 207 | } 208 | } 209 | sort(n, index, Freq); 210 | 211 | sprintf(h, "Signal\tf max. [MHz]\tl [mm]\tA [mm2]\tR [mOhm]\tw min [mm]\tw max [mm]\tImax [A]"); 212 | data[0] = h; 213 | t = 1; 214 | 215 | for (int i = 0; i < n; ++i) 216 | { 217 | real mm2 = Widthmin[index[i]] * Cu; 218 | real mOhm = 0; 219 | string R; 220 | if (Widthmin[index[i]]) 221 | { 222 | mOhm = (174 * Length[index[i]] / 10) / (Cu * 1000 * Widthmin[index[i]]); 223 | sprintf(R, "%7.2f", mOhm); 224 | } 225 | 226 | sprintf(h, "%s\t%10.2f\t%7.3f\t%4.3f\t%s\t%6.3f\t%6.3f\t%6.2f", Signal[index[i]], Freq[index[i]], Length[index[i]], mm2, R, Widthmin[index[i]], Widthmax[index[i]], imax(Widthmin[index[i]])); 227 | data[t] = h; 228 | 229 | if (!Widthmin[index[i]]) 230 | { 231 | note = 1; 232 | sprintf(h, " ***"); 233 | data[t] += h; 234 | } 235 | t++; 236 | } 237 | 238 | dialog(); 239 | } 240 | configWrite(); //Get previous netFilter 241 | } 242 | } 243 | else 244 | { 245 | dlgMessageBox("\n Start this ULP in a Board \n"); 246 | exit(0); 247 | } 248 | -------------------------------------------------------------------------------- /ulp/Unrouted.ulp: -------------------------------------------------------------------------------- 1 | /* 2 | * UNROUTED.ULP 3 | * 4 | * simple script to zoom to the first unrouted wire in board editor. 5 | * this might be helpful when searching for tiny left-overs. 6 | * 7 | * done by Daniel Mack , http://caiaq.de 8 | */ 9 | 10 | int gridunit; 11 | 12 | real u2u(int val) { 13 | switch (gridunit) { 14 | case GRID_UNIT_MIC : return u2mic(val); 15 | case GRID_UNIT_MM : return u2mm(val); 16 | case GRID_UNIT_MIL : return u2mil(val); 17 | case GRID_UNIT_INCH : return u2inch(val); 18 | } 19 | } 20 | 21 | string RunOnExit = ""; 22 | 23 | if (board) { 24 | board(B) { 25 | gridunit = (B.grid.unit); 26 | B.signals(S) { 27 | S.wires(W) { 28 | if (W.layer == 19) { 29 | real x1 = u2u(W.x1); 30 | real x2 = u2u(W.x2); 31 | real y1 = u2u(W.y1); 32 | real y2 = u2u(W.y2); 33 | 34 | x1 -= (x2 - x1) / 2; 35 | x2 += (x2 - x1) / 2; 36 | y1 -= (y2 - y1) / 2; 37 | y2 += (y2 - y1) / 2; 38 | 39 | sprintf(RunOnExit, "\nWINDOW (%.6f %.6f) (%.6f %.6f);\n", x1, y1, x2, y2); 40 | exit (RunOnExit); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ulp/add+mod-attributes.ulp: -------------------------------------------------------------------------------- 1 | #usage "en: Modify attributes on all devices/technologies within a given library" 2 | "

Usage: run add+mod-attributes

" 3 | "

Author: Owen Lyke
" 4 | "Version: 1.0.0

" 5 | "Allows you to add/remove attributes to/from all devices and variants in a library. Supports specification of constant or variable as well as defualt value" 6 | 7 | 8 | 9 | 10 | int MAX_NUM_ROWS = 10; 11 | int num_rows = 1; 12 | int setup_complete = 0; 13 | 14 | string option_strings[] = {"variable", "constant", "DELETE"}; 15 | string labels[] = {"Enter Label", "Enter Label", "Enter Label", "Enter Label", "Enter Label", "Enter Label", "Enter Label", "Enter Label", "Enter Label", "Enter Label"}; 16 | int options[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 17 | string values[] = {"Enter Value", "Enter Value", "Enter Value", "Enter Value", "Enter Value", "Enter Value", "Enter Value", "Enter Value", "Enter Value", "Enter Value"}; 18 | int overwrite_val[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 19 | int attr_val_pre_exists[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 20 | 21 | 22 | int result = 0; 23 | 24 | 25 | // Used by set-all-devices-attribute.ulp 26 | string ScriptFile = ""; 27 | string cmdScript, cmd, s; 28 | 29 | string Lines[], Attribut[], AttValue[]; 30 | int setAtt[]; 31 | int cntl = 0; 32 | int cntAtt = 0; 33 | 34 | if (argv[1] == "?") { 35 | dlgMessageBox(usage, "OK"); 36 | } 37 | 38 | void test(void) { 39 | dlgDialog(filename(argv[0]) + " Script") { 40 | dlgTextView(cmd); 41 | dlgHBoxLayout { 42 | dlgPushButton("OK") dlgAccept(); 43 | dlgPushButton("Abbruch") { dlgReject(); exit(-2); } 44 | } 45 | }; 46 | return; 47 | } 48 | 49 | 50 | string check_varname(string s) { // 2008-09-04 51 | if(s == "''") return s; 52 | return "'"+s+"'"; 53 | } 54 | 55 | 56 | if(library){ 57 | 58 | // // Setup 59 | while(setup_complete == 0) 60 | { 61 | dlgDialog("Add Attribute - Setup"){ 62 | 63 | dlgLabel("This is the Add Attribute ULP \n\n\ 64 | You may add up to 10 rows, and must have at least one row. \n\ 65 | Each row allows you to add or modify an attribute for ALL devices and technologies in the library. \n\ 66 | Label: case-insensitive label of the attribute. Also the 'name' of the attribute. \n\ 67 | Type: allows you to choose to set the attribute to constant or variable. Also allows removal of all attributes with the given name. \n\ 68 | Value: the value to fill in for each attribute. Leave as 'Enter Value' for a blank default. \n\ 69 | Overwrite Values: Check this box to overwrite existing values for a given label name. If not overwrite then existing values will remain. \n\ 70 | "); 71 | 72 | dlgGridLayout { 73 | dlgCell(0, 0) dlgLabel("Label"); 74 | dlgCell(0, 1) dlgLabel("Type"); 75 | dlgCell(0, 2) dlgLabel("Value"); 76 | dlgCell(0, 3) dlgLabel("Overwrite Values?"); 77 | 78 | for(int indi = 0; indi < num_rows; indi++) 79 | { 80 | dlgCell(indi + 1, 0) dlgTextEdit(labels[indi]); 81 | dlgCell(indi + 1, 1) dlgListBox(option_strings, options[indi]) dlgMessageBox("You have selected " + option_strings[options[indi]]); 82 | dlgCell(indi + 1, 2) dlgTextEdit(values[indi]); 83 | dlgCell(indi + 1, 3) dlgCheckBox("OVRWT", overwrite_val[indi]); 84 | } 85 | 86 | }; 87 | 88 | dlgPushButton("Add Row"){ 89 | // add row 90 | num_rows++; 91 | if(num_rows > MAX_NUM_ROWS){ 92 | dlgMessageBox("No more rows allowed. Use multiple calls to this ULP"); 93 | num_rows = MAX_NUM_ROWS; 94 | } 95 | dlgAccept(); 96 | }; 97 | dlgPushButton("Remove Last Row"){ 98 | // add row 99 | num_rows--; 100 | if(num_rows < 1){ 101 | dlgMessageBox("You must have at least one row"); 102 | num_rows = 1; 103 | } 104 | dlgAccept(); 105 | }; 106 | 107 | dlgGridLayout { 108 | 109 | dlgCell(0, 1){ 110 | dlgPushButton("Accept (Modify Library)"){ 111 | setup_complete = 1; 112 | result = 0; 113 | dlgAccept(); 114 | }; 115 | }; 116 | 117 | dlgCell(0, 0){ 118 | dlgPushButton("Cancel"){ 119 | setup_complete = 1; 120 | result = 1; 121 | dlgAccept(); 122 | }; 123 | }; 124 | } 125 | 126 | }; 127 | } 128 | 129 | // CAPSIFY! 130 | for(int indi = 0; indi < num_rows; indi++) 131 | { 132 | labels[indi] = strupr(labels[indi]); 133 | } 134 | 135 | 136 | // Use the really cool code to actually set all the ATTRIBUTES by constructing a long command to execute 137 | // Thanks to the original code located here: // https://github.com/plusea/EAGLE/blob/master/ulp/set-all-devices-attribute.ulp 138 | 139 | library(L){ 140 | 141 | // readScript(); 142 | cmdScript = filesetext(L.name, "~.scr"); 143 | L.devicesets(DS) { 144 | sprintf(s, "EDIT %s.DEV;\n", DS.name); 145 | cmd += s; 146 | int n; 147 | DS.devices(D) { 148 | string t[]; 149 | int nt = strsplit(t, D.technologies, ' '); 150 | sprintf(s, "PACKAGE %s;\n", check_varname(D.name) ); 151 | cmd += s; 152 | for (int i = 0; i < nt; i++) { 153 | sprintf(s, "TECHNOLOGY %s;\n", t[i]); 154 | cmd += s; 155 | D.attributes(A, t[i]) { 156 | 157 | 158 | for(int indi = 0; indi < num_rows; indi++) { 159 | status(DS.name+":"+D.name+":"+t[i]); 160 | 161 | if (A.name == labels[indi]) { 162 | if (strlen(A.value)){ 163 | attr_val_pre_exists[indi] = 1; 164 | // dlgMessageBox("found the specified attribute with a value already. Device: " + D.name + ", tech: " + t[i] + ", ATTR: " + A.name + ", value: " + A.value ); 165 | } 166 | else 167 | { 168 | attr_val_pre_exists[indi] = 0; 169 | // dlgMessageBox("found one with zero length!"); 170 | } 171 | } 172 | } 173 | } 174 | 175 | for(int indi = 0; indi < num_rows; indi++) // Within each technology enumerate all the atribute commands 176 | { 177 | string name = labels[indi]; 178 | string value = values[indi]; 179 | string option = option_strings[options[indi]]; 180 | 181 | 182 | // If modifying the new value then use "ATTRIBUTE NAME 'value' option" form 183 | // Unless you have asked not to overwrite existing values 184 | 185 | // Make sure the user actually edited the name... (and make sure it has no spaces) 186 | if(name != "Enter Label"){ 187 | 188 | string array[]; 189 | int nw = strsplit(array, name, ' '); 190 | if(nw == 1){ 191 | 192 | if(options[indi] == 2){ // If deleting an attibute then just do it! 193 | sprintf(s, "ATTRIBUTE %s %s;\n", name, "DELETE"); 194 | } 195 | else if(overwrite_val[indi]){ 196 | 197 | if(values[indi] != "Enter Value") // If overwriting and have valid new value then just use this form 198 | { 199 | sprintf(s, "ATTRIBUTE %s '%s' %s\n", name, value, option); 200 | } 201 | else // Otherwise just overwrite the option for that attribute 202 | { 203 | sprintf(s, "ATTRIBUTE %s %s;\n", name, option); 204 | } 205 | } 206 | else // If oyu are not overwriting existing values then you are here 207 | { 208 | if(attr_val_pre_exists[indi]){ // A value already exists for your attribute: use the two argument form 209 | // Do nothing if you don't want to overwrite and the attribute already exists with a value 210 | 211 | // // If you wanted you could set the option to the one defined by the user, using this command: 212 | // sprintf(s, "ATTRIBUTE %s %s;\n", name, option); 213 | } 214 | else // No value already exists so you can specify the new value or change the option 215 | { 216 | if(values[indi] != "Enter Value"){ 217 | sprintf(s, "ATTRIBUTE %s '%s' %s\n", name, value, option); 218 | } 219 | else 220 | { 221 | sprintf(s, "ATTRIBUTE %s %s;\n", name, option); 222 | } 223 | } 224 | } 225 | 226 | cmd += s; 227 | s = ""; 228 | 229 | } 230 | } 231 | } 232 | } 233 | } 234 | } 235 | } 236 | 237 | 238 | output(cmdScript, "wtD") printf("%s", cmd); 239 | if( result == 0 ){ 240 | sprintf(s, "SCRIPT '%s';\n", cmdScript); 241 | exit(s); 242 | } 243 | else{ 244 | exit(1); 245 | } 246 | 247 | } 248 | else{ 249 | dlgMessageBox("Please run this ULP from the library you wish to modify."); 250 | exit(1); 251 | } -------------------------------------------------------------------------------- /ulp/adimv4_0mm.ulp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | * * 3 | * AutoDimensionning of Board in mm (Version 3.0) for EAGLE 4.X only! * 4 | * * 5 | * ORIGINAL Filename: adimv2_0mm.ulp * 6 | * Written by: Michel Dagenais * 7 | * Date: September 12th 1998 * 8 | * Modified: Brain Technology (www.braintechnology.de) (* Nov 1999 *) * 9 | * Now places text on appropriate side (closer to object beeing dimensionned). * 10 | * * 11 | * Filename: adimv3_0mm.ulp * 12 | * Edited by: Jeff Moore * 13 | * Date: February 1st 2001 * 14 | * * 15 | * This ULP program will put all the necessary dimensions for holes (layer 45) and * 16 | * board outline (arcs and wires on layer 20) for your board into a .scr file of your * 17 | * choice and into the directory of your choice. * 18 | * Run the resulting script on your board to place the dimentions into the board file. * 19 | * * 20 | * Few requirements: * 21 | * * 22 | * 1. The shape of your board (board outline) is drawn on layer 20 (Dimension). * 23 | * 2. You reserve layer 47 (Measures) to dimension your board. * 24 | * * 25 | * * 26 | * * 27 | ****************************************************************************************/ 28 | 29 | real datum_dot_diameter = 01.27; // diameter of connecting dot on datum line 30 | 31 | real datum_wire_width = 0.50; // width or datum line 32 | real default_wire_width = 0.20; // default wire width for dimension extender and leader 33 | real wire_width; 34 | 35 | real extender_clearance = 1.27; // clearance from closest edge 36 | real text_offset = 12.7; // distance of dimension text from closest edge 37 | 38 | real right_top_extender_length = text_offset * 2.28; 39 | real left_bottom_extender_length = text_offset * 2.28; 40 | 41 | real right_top_datum_location = extender_clearance + (right_top_extender_length * 0.75); 42 | real left_bottom_datum_location = extender_clearance + (left_bottom_extender_length * 0.75); 43 | 44 | int right_limit; 45 | int top_limit; 46 | int left_limit; 47 | int bottom_limit; 48 | 49 | int x_points[]; 50 | string x_points_loc[]; // top or bottom 51 | int y_points[]; 52 | string y_points_loc[]; // right or left 53 | string text_location; 54 | string fileName; 55 | 56 | int lower_right; 57 | int higher_right; 58 | int lower_top; 59 | int higher_top; 60 | int lower_left; 61 | int higher_left; 62 | int lower_bottom; 63 | int higher_bottom; 64 | 65 | int count_x_points; 66 | int count_y_points; 67 | 68 | int i; 69 | int j; 70 | 71 | void check_x_points(int point_cxp, int y_point_cxp) 72 | { 73 | for (i = 0; i <= count_x_points; ++i) 74 | { 75 | if (point_cxp == x_points[i]) 76 | break; 77 | } 78 | if (i > count_x_points) 79 | { 80 | x_points[count_x_points] = point_cxp; 81 | int middle = bottom_limit + ((abs(bottom_limit) + abs(top_limit)) * 0.5); 82 | if (y_point_cxp < middle) 83 | text_location = "bottom"; 84 | else 85 | text_location = "top"; 86 | x_points_loc[count_x_points] = text_location; 87 | ++count_x_points; 88 | } 89 | } 90 | 91 | void check_y_points(int point_cxp, int x_point_cxp) 92 | { 93 | for (i = 0; i <= count_y_points; ++i) 94 | { 95 | if (point_cxp == y_points[i]) 96 | break; 97 | } 98 | if (i > count_y_points) 99 | { 100 | y_points[count_y_points] = point_cxp; 101 | int middle = left_limit + ((abs(left_limit) + abs(right_limit)) * 0.5); 102 | if (x_point_cxp < middle) 103 | text_location = "left"; 104 | else 105 | text_location = "right"; 106 | y_points_loc[count_y_points] = text_location; 107 | ++count_y_points; 108 | } 109 | } 110 | 111 | fileName = dlgFileSave("Save Dimensioning File", filesetext("millimeters",".scr"), "*.scr"); 112 | if (fileName == "") exit(0); 113 | 114 | output(fileName) 115 | { 116 | printf(";\n"); 117 | printf("Grid mm;\n"); 118 | printf("Change Width 2.0;\n"); 119 | printf("Change Size 1.77;\n"); 120 | printf("Change Ratio 8;\n"); 121 | printf("Display 20 44 45 47;\n"); 122 | printf("Layer 47;\n"); 123 | board(B) 124 | { 125 | B.wires(W) 126 | { 127 | if (W.layer == 20) 128 | { 129 | switch (W.y2 - W.y1) 130 | { 131 | case 0: 132 | { 133 | if (W.y2 > top_limit) 134 | top_limit = W.y2; 135 | else 136 | { 137 | if (W.y2 < bottom_limit) 138 | bottom_limit = W.y2; 139 | } 140 | } 141 | default: 142 | { 143 | if (W.y2 > W.y1) 144 | { 145 | if (W.y2 > top_limit) 146 | top_limit = W.y2; 147 | if (W.y1 < bottom_limit) 148 | bottom_limit = W.y1; 149 | } 150 | else 151 | { 152 | if (W.y1 > top_limit) 153 | top_limit = W.y1; 154 | if (W.y2 < bottom_limit) 155 | bottom_limit = W.y2; 156 | } 157 | } 158 | } 159 | switch (W.x2 - W.x1) 160 | { 161 | case 0: 162 | { 163 | if (W.x2 > right_limit) 164 | right_limit = W.x2; 165 | else 166 | { 167 | if (W.x2 < left_limit) 168 | left_limit = W.x2; 169 | } 170 | } 171 | default: 172 | { 173 | if (W.x2 > W.x1) 174 | { 175 | if (W.x2 > right_limit) 176 | right_limit = W.x2; 177 | if (W.x1 < left_limit) 178 | left_limit = W.x1; 179 | } 180 | else 181 | { 182 | if (W.x1 > right_limit) 183 | right_limit = W.x1; 184 | if (W.x2 < left_limit) 185 | left_limit = W.x2; 186 | } 187 | } 188 | } 189 | } 190 | } 191 | // B.wires(A) 192 | // { 193 | // if (A.layer == 20) 194 | // { 195 | // check_x_points(A.x1, A.y1); 196 | // check_y_points(A.y1, A.x1); 197 | // } 198 | // } 199 | B.wires(W) 200 | { 201 | if (W.layer == 20) 202 | { 203 | if(!(W.arc)) 204 | { 205 | check_y_points(W.y2, W.x2); 206 | check_y_points(W.y1, W.x1); 207 | check_x_points(W.x2, W.y2); 208 | check_x_points(W.x1, W.y1); 209 | } 210 | } 211 | } 212 | B.holes(H) 213 | { 214 | check_x_points(H.x, H.y); 215 | check_y_points(H.y, H.x); 216 | } 217 | B.elements(E) 218 | { 219 | E.package.contacts(C) 220 | { 221 | if(C.pad) 222 | { 223 | check_x_points(C.pad.x, C.pad.y); 224 | check_y_points(C.pad.y, C.pad.x); 225 | } 226 | } 227 | } 228 | // 229 | // Adding X dimensions 230 | // 231 | for (i = 0; i <= count_x_points; ++i) 232 | { 233 | if (x_points[i] == 0) 234 | { 235 | printf("Circle 0 (0 %.2f) (0 %.2f);\n", (u2mm(top_limit) + right_top_datum_location), (u2mm(top_limit) + right_top_datum_location + (datum_dot_diameter /2))); 236 | printf("Circle 0 (0 %.2f) (0 %.2f);\n", (u2mm(bottom_limit) - left_bottom_datum_location), (u2mm(bottom_limit) - left_bottom_datum_location - (datum_dot_diameter /2))); 237 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, u2mm(x_points[i]), (u2mm(top_limit) + extender_clearance), u2mm(x_points[i]), (u2mm(top_limit) + right_top_extender_length)); 238 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, u2mm(x_points[i]), (u2mm(bottom_limit) - extender_clearance), u2mm(x_points[i]), (u2mm(bottom_limit) - left_bottom_extender_length)); 239 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(top_limit) + text_offset)); 240 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(bottom_limit) - text_offset - 0.3)); 241 | 242 | } 243 | if (x_points_loc[i] == "top") 244 | { 245 | if (x_points[i] > higher_top) 246 | higher_top = x_points[i]; 247 | if (x_points[i] < lower_top) 248 | lower_top = x_points[i]; 249 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(top_limit) + text_offset)); 250 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mm(x_points[i]), (u2mm(top_limit) + extender_clearance), u2mm(x_points[i]), (u2mm(top_limit) + right_top_extender_length)); 251 | } 252 | else 253 | { 254 | if (x_points[i] > higher_bottom) 255 | higher_bottom = x_points[i]; 256 | if (x_points[i] < lower_bottom) 257 | lower_bottom = x_points[i]; 258 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mm(x_points[i])), u2mm(x_points[i]), (u2mm(bottom_limit) - text_offset - 0.3)); 259 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mm(x_points[i]), (u2mm(bottom_limit) - extender_clearance), u2mm(x_points[i]), (u2mm(bottom_limit) - left_bottom_extender_length)); 260 | } 261 | } 262 | // Join all X dimensions 263 | if (lower_top != higher_top) 264 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mm(lower_top), (u2mm(top_limit) + right_top_datum_location), u2mm(higher_top), (u2mm(top_limit) + right_top_datum_location)); 265 | if (lower_bottom != higher_bottom) 266 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mm(lower_bottom), (u2mm(bottom_limit) - left_bottom_datum_location), u2mm(higher_bottom), (u2mm(bottom_limit) - left_bottom_datum_location)); 267 | 268 | // 269 | // Adding Y dimensions 270 | // 271 | for (i = 0; i <= count_y_points; ++i) 272 | { 273 | if (y_points[i] == 0) 274 | { 275 | printf("Circle 0 (%.2f 0) (%.2f 0);\n", (u2mm(right_limit) + right_top_datum_location), (u2mm(right_limit) + right_top_datum_location + (datum_dot_diameter /2))); 276 | printf("Circle 0 (%.2f 0) (%.2f 0);\n", (u2mm(left_limit) - left_bottom_datum_location), (u2mm(left_limit) - left_bottom_datum_location - (datum_dot_diameter /2))); 277 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, (u2mm(right_limit) + extender_clearance), u2mm(y_points[i]), (u2mm(right_limit) + right_top_extender_length), u2mm(y_points[i])); 278 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, (u2mm(left_limit) - extender_clearance), u2mm(y_points[i]), (u2mm(left_limit) - left_bottom_extender_length), u2mm(y_points[i])); 279 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mm(y_points[i])), (u2mm(right_limit) + text_offset), u2mm(y_points[i])); 280 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mm(y_points[i])), (u2mm(left_limit) - text_offset - 0.3), u2mm(y_points[i])); 281 | } 282 | if (y_points_loc[i] == "right") 283 | { 284 | if (y_points[i] > higher_right) 285 | higher_right = y_points[i]; 286 | if (y_points[i] < lower_right) 287 | lower_right = y_points[i]; 288 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mm(y_points[i])), (u2mm(right_limit) + text_offset), u2mm(y_points[i])); 289 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mm(right_limit) + extender_clearance), u2mm(y_points[i]), (u2mm(right_limit) + right_top_extender_length), u2mm(y_points[i])); 290 | } 291 | else 292 | { 293 | if (y_points[i] > higher_left) 294 | higher_left = y_points[i]; 295 | if (y_points[i] < lower_left) 296 | lower_left = y_points[i]; 297 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mm(y_points[i])), (u2mm(left_limit) - text_offset - 0.3), u2mm(y_points[i])); 298 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mm(left_limit) - extender_clearance), u2mm(y_points[i]), (u2mm(left_limit) - left_bottom_extender_length), u2mm(y_points[i])); 299 | } 300 | } 301 | // Join all Y dimensions 302 | if (lower_right != higher_right) 303 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mm(right_limit) + right_top_datum_location), u2mm(lower_right), (u2mm(right_limit) + right_top_datum_location), u2mm(higher_right)); 304 | if (lower_left != higher_left) 305 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mm(left_limit) - left_bottom_datum_location), u2mm(lower_left), (u2mm(left_limit) - left_bottom_datum_location), u2mm(higher_left)); 306 | } 307 | printf("Text 'All Dimensions in MM' R0 (%.2f %.2f);\n",u2mm(right_limit),u2mm(top_limit)); 308 | printf("Text 'Spark Fun Electronics' R0 (%.2f %.2f);\n",u2mm(right_limit),u2mm(top_limit)-2); 309 | printf("Grid Last;\n"); 310 | printf("Window Fit;\n"); 311 | } 312 | -------------------------------------------------------------------------------- /ulp/autodim_in.ulp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | * * 3 | * AutoDimensionning of Board in mm (Version 3.0) for EAGLE 4.X only! * 4 | * * 5 | * ORIGINAL Filename: adimv2_0mm.ulp * 6 | * Written by: Michel Dagenais * 7 | * Date: September 12th 1998 * 8 | * Modified: Brain Technology (www.braintechnology.de) (* Nov 1999 *) * 9 | * Now places text on appropriate side (closer to object beeing dimensionned). * 10 | * * 11 | * Filename: adimv3_0mm.ulp * 12 | * Edited by: Jeff Moore * 13 | * Date: February 1st 2001 * 14 | * * 15 | * This ULP program will put all the necessary dimensions for holes (layer 45) and * 16 | * board outline (arcs and wires on layer 20) for your board into a .scr file of your * 17 | * choice and into the directory of your choice. * 18 | * Run the resulting script on your board to place the dimentions into the board file. * 19 | * * 20 | * Few requirements: * 21 | * * 22 | * 1. The shape of your board (board outline) is drawn on layer 20 (Dimension). * 23 | * 2. You reserve layer 47 (Measures) to dimension your board. * 24 | * * 25 | * * 26 | * * 27 | ****************************************************************************************/ 28 | 29 | real datum_dot_diameter = 01.27; // diameter of connecting dot on datum line 30 | 31 | real datum_wire_width = 5; // width of datum line 32 | real default_wire_width = 5; // default wire width for dimension extender and leader 33 | real wire_width; 34 | 35 | real extender_clearance = -50; // clearance from closest edge 36 | real text_offset = 100; // distance of dimension text from closest edge 37 | 38 | real right_top_extender_length = text_offset; 39 | real left_bottom_extender_length = text_offset; 40 | 41 | real right_top_datum_location = extender_clearance + (right_top_extender_length); 42 | real left_bottom_datum_location = extender_clearance + (left_bottom_extender_length); 43 | 44 | int right_limit; 45 | int top_limit; 46 | int left_limit; 47 | int bottom_limit; 48 | 49 | int x_points[]; 50 | string x_points_loc[]; // top or bottom 51 | int y_points[]; 52 | string y_points_loc[]; // right or left 53 | string text_location; 54 | string fileName; 55 | 56 | int lower_right; 57 | int higher_right; 58 | int lower_top; 59 | int higher_top; 60 | int lower_left; 61 | int higher_left; 62 | int lower_bottom; 63 | int higher_bottom; 64 | 65 | int count_x_points; 66 | int count_y_points; 67 | 68 | int i; 69 | int j; 70 | 71 | void check_x_points(int point_cxp, int y_point_cxp) 72 | { 73 | for (i = 0; i <= count_x_points; ++i) 74 | { 75 | if (point_cxp == x_points[i]) 76 | break; 77 | } 78 | if (i > count_x_points) 79 | { 80 | x_points[count_x_points] = point_cxp; 81 | int middle = bottom_limit + ((abs(bottom_limit) + abs(top_limit)) * 0.5); 82 | if (y_point_cxp < middle) 83 | text_location = "bottom"; 84 | else 85 | text_location = "top"; 86 | x_points_loc[count_x_points] = text_location; 87 | ++count_x_points; 88 | } 89 | } 90 | 91 | void check_y_points(int point_cxp, int x_point_cxp) 92 | { 93 | for (i = 0; i <= count_y_points; ++i) 94 | { 95 | if (point_cxp == y_points[i]) 96 | break; 97 | } 98 | if (i > count_y_points) 99 | { 100 | y_points[count_y_points] = point_cxp; 101 | int middle = left_limit + ((abs(left_limit) + abs(right_limit)) * 0.5); 102 | if (x_point_cxp < middle) 103 | text_location = "left"; 104 | else 105 | text_location = "right"; 106 | y_points_loc[count_y_points] = text_location; 107 | ++count_y_points; 108 | } 109 | } 110 | 111 | fileName = dlgFileSave("Save Dimensioning File", filesetext("inch",".scr"), "*.scr"); 112 | if (fileName == "") exit(0); 113 | 114 | output(fileName) 115 | { 116 | printf(";\n"); 117 | printf("Grid mil;\n"); 118 | printf("Change Width 50;\n"); 119 | printf("Change Size 40;\n"); 120 | printf("Change Ratio 8;\n"); 121 | printf("Display 20 44 45 47;\n"); 122 | printf("Layer 47;\n"); 123 | board(B) 124 | { 125 | B.wires(W) 126 | { 127 | if (W.layer == 20) 128 | { 129 | switch (W.y2 - W.y1) 130 | { 131 | case 0: 132 | { 133 | if (W.y2 > top_limit) 134 | top_limit = W.y2; 135 | else 136 | { 137 | if (W.y2 < bottom_limit) 138 | bottom_limit = W.y2; 139 | } 140 | } 141 | default: 142 | { 143 | if (W.y2 > W.y1) 144 | { 145 | if (W.y2 > top_limit) 146 | top_limit = W.y2; 147 | if (W.y1 < bottom_limit) 148 | bottom_limit = W.y1; 149 | } 150 | else 151 | { 152 | if (W.y1 > top_limit) 153 | top_limit = W.y1; 154 | if (W.y2 < bottom_limit) 155 | bottom_limit = W.y2; 156 | } 157 | } 158 | } 159 | switch (W.x2 - W.x1) 160 | { 161 | case 0: 162 | { 163 | if (W.x2 > right_limit) 164 | right_limit = W.x2; 165 | else 166 | { 167 | if (W.x2 < left_limit) 168 | left_limit = W.x2; 169 | } 170 | } 171 | default: 172 | { 173 | if (W.x2 > W.x1) 174 | { 175 | if (W.x2 > right_limit) 176 | right_limit = W.x2; 177 | if (W.x1 < left_limit) 178 | left_limit = W.x1; 179 | } 180 | else 181 | { 182 | if (W.x1 > right_limit) 183 | right_limit = W.x1; 184 | if (W.x2 < left_limit) 185 | left_limit = W.x2; 186 | } 187 | } 188 | } 189 | } 190 | } 191 | // B.wires(A) 192 | // { 193 | // if (A.layer == 20) 194 | // { 195 | // check_x_points(A.x1, A.y1); 196 | // check_y_points(A.y1, A.x1); 197 | // } 198 | // } 199 | B.wires(W) 200 | { 201 | if (W.layer == 20) 202 | { 203 | if(!(W.arc)) 204 | { 205 | check_y_points(W.y2, W.x2); 206 | check_y_points(W.y1, W.x1); 207 | check_x_points(W.x2, W.y2); 208 | check_x_points(W.x1, W.y1); 209 | } 210 | } 211 | } 212 | B.holes(H) 213 | { 214 | check_x_points(H.x, H.y); 215 | check_y_points(H.y, H.x); 216 | } 217 | B.elements(E) 218 | { 219 | E.package.contacts(C) 220 | { 221 | if(C.pad) 222 | { 223 | check_x_points(C.pad.x, C.pad.y); 224 | check_y_points(C.pad.y, C.pad.x); 225 | } 226 | } 227 | } 228 | // 229 | // Adding X dimensions 230 | // 231 | for (i = 0; i <= count_x_points; ++i) 232 | { 233 | if (x_points[i] == 0) 234 | { 235 | printf("Circle 0 (0 %.2f) (0 %.2f);\n", (u2mil(top_limit) + right_top_datum_location), (u2mil(top_limit) + right_top_datum_location + (datum_dot_diameter /2))); 236 | printf("Circle 0 (0 %.2f) (0 %.2f);\n", (u2mil(bottom_limit) - left_bottom_datum_location), (u2mil(bottom_limit) - left_bottom_datum_location - (datum_dot_diameter /2))); 237 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, u2mil(x_points[i]), (u2mil(top_limit) + extender_clearance), u2mil(x_points[i]), (u2mil(top_limit) + right_top_extender_length)); 238 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, u2mil(x_points[i]), (u2mil(bottom_limit) - extender_clearance), u2mil(x_points[i]), (u2mil(bottom_limit) - left_bottom_extender_length)); 239 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(top_limit) + text_offset)); 240 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(bottom_limit) - text_offset - 0.3)); 241 | 242 | } 243 | if (x_points_loc[i] == "top") 244 | { 245 | if (x_points[i] > higher_top) 246 | higher_top = x_points[i]; 247 | if (x_points[i] < lower_top) 248 | lower_top = x_points[i]; 249 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(top_limit) + text_offset)); 250 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mil(x_points[i]), (u2mil(top_limit) + extender_clearance), u2mil(x_points[i]), (u2mil(top_limit) + right_top_extender_length)); 251 | } 252 | else 253 | { 254 | if (x_points[i] > higher_bottom) 255 | higher_bottom = x_points[i]; 256 | if (x_points[i] < lower_bottom) 257 | lower_bottom = x_points[i]; 258 | printf("Text '%.2f' R90 (%.2f %.2f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(bottom_limit) - text_offset - 0.3)); 259 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mil(x_points[i]), (u2mil(bottom_limit) - extender_clearance), u2mil(x_points[i]), (u2mil(bottom_limit) - left_bottom_extender_length)); 260 | } 261 | } 262 | // Join all X dimensions 263 | if (lower_top != higher_top) 264 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mil(lower_top), (u2mil(top_limit) + right_top_datum_location), u2mil(higher_top), (u2mil(top_limit) + right_top_datum_location)); 265 | if (lower_bottom != higher_bottom) 266 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mil(lower_bottom), (u2mil(bottom_limit) - left_bottom_datum_location), u2mil(higher_bottom), (u2mil(bottom_limit) - left_bottom_datum_location)); 267 | 268 | // 269 | // Adding Y dimensions 270 | // 271 | for (i = 0; i <= count_y_points; ++i) 272 | { 273 | if (y_points[i] == 0) 274 | { 275 | printf("Circle 0 (%.2f 0) (%.2f 0);\n", (u2mil(right_limit) + right_top_datum_location), (u2mil(right_limit) + right_top_datum_location + (datum_dot_diameter /2))); 276 | printf("Circle 0 (%.2f 0) (%.2f 0);\n", (u2mil(left_limit) - left_bottom_datum_location), (u2mil(left_limit) - left_bottom_datum_location - (datum_dot_diameter /2))); 277 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, (u2mil(right_limit) + extender_clearance), u2mil(y_points[i]), (u2mil(right_limit) + right_top_extender_length), u2mil(y_points[i])); 278 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, (u2mil(left_limit) - extender_clearance), u2mil(y_points[i]), (u2mil(left_limit) - left_bottom_extender_length), u2mil(y_points[i])); 279 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mil(y_points[i])), (u2mil(right_limit) + text_offset), u2mil(y_points[i])); 280 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mil(y_points[i])), (u2mil(left_limit) - text_offset - 0.3), u2mil(y_points[i])); 281 | } 282 | if (y_points_loc[i] == "right") 283 | { 284 | if (y_points[i] > higher_right) 285 | higher_right = y_points[i]; 286 | if (y_points[i] < lower_right) 287 | lower_right = y_points[i]; 288 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mil(y_points[i])), (u2mil(right_limit) + text_offset), u2mil(y_points[i])); 289 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mil(right_limit) + extender_clearance), u2mil(y_points[i]), (u2mil(right_limit) + right_top_extender_length), u2mil(y_points[i])); 290 | } 291 | else 292 | { 293 | if (y_points[i] > higher_left) 294 | higher_left = y_points[i]; 295 | if (y_points[i] < lower_left) 296 | lower_left = y_points[i]; 297 | printf("Text '%.2f' R0 (%.2f %.2f);\n", abs(u2mil(y_points[i])), (u2mil(left_limit) - text_offset - 0.3), u2mil(y_points[i])); 298 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mil(left_limit) - extender_clearance), u2mil(y_points[i]), (u2mil(left_limit) - left_bottom_extender_length), u2mil(y_points[i])); 299 | } 300 | } 301 | // Join all Y dimensions 302 | if (lower_right != higher_right) 303 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mil(right_limit) + right_top_datum_location), u2mil(lower_right), (u2mil(right_limit) + right_top_datum_location), u2mil(higher_right)); 304 | if (lower_left != higher_left) 305 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, (u2mil(left_limit) - left_bottom_datum_location), u2mil(lower_left), (u2mil(left_limit) - left_bottom_datum_location), u2mil(higher_left)); 306 | } 307 | printf("Text 'All Dimensions in mil' R0 (0 -100);\n"); 308 | printf("Text 'Spark Fun Electronics' R0 (0 -200);\n"); 309 | printf("Grid Last;\n"); 310 | printf("Window Fit;\n"); 311 | } 312 | -------------------------------------------------------------------------------- /ulp/autodim_mil.ulp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | * * 3 | * AutoDimensionning of Board in mm (Version 3.0) for EAGLE 4.X only! * 4 | * * 5 | * ORIGINAL Filename: adimv2_0mm.ulp * 6 | * Written by: Michel Dagenais * 7 | * Date: September 12th 1998 * 8 | * Modified: Brain Technology (www.braintechnology.de) (* Nov 1999 *) * 9 | * Now places text on appropriate side (closer to object beeing dimensionned). * 10 | * * 11 | * Filename: adimv3_0mm.ulp * 12 | * Edited by: Jeff Moore * 13 | * Date: February 1st 2001 * 14 | * * 15 | * This ULP program will put all the necessary dimensions for holes (layer 45) and * 16 | * board outline (arcs and wires on layer 20) for your board into a .scr file of your * 17 | * choice and into the directory of your choice. * 18 | * Run the resulting script on your board to place the dimentions into the board file. * 19 | * * 20 | * Few requirements: * 21 | * * 22 | * 1. The shape of your board (board outline) is drawn on layer 20 (Dimension). * 23 | * 2. You reserve layer 47 (Measures) to dimension your board. * 24 | * * 25 | * * 26 | * * 27 | ****************************************************************************************/ 28 | 29 | real datum_dot_diameter = 5; // diameter of connecting dot on datum line 30 | 31 | real datum_wire_width = 4; // width or datum line 32 | real default_wire_width = 2.5; // default wire width for dimension extender and leader 33 | real wire_width; 34 | 35 | real extender_clearance = 25; // clearance from closest edge 36 | real text_offset = 250; // distance of dimension text from closest edge 37 | 38 | real right_top_extender_length = text_offset * 2.28; 39 | real left_bottom_extender_length = text_offset * 2.28; 40 | 41 | real right_top_datum_location = extender_clearance + (right_top_extender_length * 0.75); 42 | real left_bottom_datum_location = extender_clearance + (left_bottom_extender_length * 0.75); 43 | 44 | int right_limit; 45 | int top_limit; 46 | int left_limit; 47 | int bottom_limit; 48 | 49 | int x_points[]; 50 | string x_points_loc[]; // top or bottom 51 | int y_points[]; 52 | string y_points_loc[]; // right or left 53 | string text_location; 54 | string fileName; 55 | 56 | int lower_right; 57 | int higher_right; 58 | int lower_top; 59 | int higher_top; 60 | int lower_left; 61 | int higher_left; 62 | int lower_bottom; 63 | int higher_bottom; 64 | 65 | int count_x_points; 66 | int count_y_points; 67 | 68 | int i; 69 | int j; 70 | 71 | void check_x_points(int point_cxp, int y_point_cxp) 72 | { 73 | for (i = 0; i <= count_x_points; ++i) 74 | { 75 | if (point_cxp == x_points[i]) 76 | break; 77 | } 78 | if (i > count_x_points) 79 | { 80 | x_points[count_x_points] = point_cxp; 81 | int middle = bottom_limit + ((abs(bottom_limit) + abs(top_limit)) * 0.5); 82 | if (y_point_cxp < middle) 83 | text_location = "bottom"; 84 | else 85 | text_location = "top"; 86 | x_points_loc[count_x_points] = text_location; 87 | ++count_x_points; 88 | } 89 | } 90 | 91 | void check_y_points(int point_cxp, int x_point_cxp) 92 | { 93 | for (i = 0; i <= count_y_points; ++i) 94 | { 95 | if (point_cxp == y_points[i]) 96 | break; 97 | } 98 | if (i > count_y_points) 99 | { 100 | y_points[count_y_points] = point_cxp; 101 | int middle = left_limit + ((abs(left_limit) + abs(right_limit)) * 0.5); 102 | if (x_point_cxp < middle) 103 | text_location = "left"; 104 | else 105 | text_location = "right"; 106 | y_points_loc[count_y_points] = text_location; 107 | ++count_y_points; 108 | } 109 | } 110 | 111 | fileName = dlgFileSave("Save Dimensioning File", filesetext("inch",".scr"), "*.scr"); 112 | if (fileName == "") exit(0); 113 | 114 | output(fileName) 115 | { 116 | printf(";\n"); 117 | printf("Grid mil;\n"); 118 | printf("Change Width 50;\n"); 119 | printf("Change Size 40;\n"); 120 | printf("Change Ratio 8;\n"); 121 | printf("Display 20 44 45 47;\n"); 122 | printf("Layer 47;\n"); 123 | board(B) 124 | { 125 | B.wires(W) 126 | { 127 | if (W.layer == 20) 128 | { 129 | switch (W.y2 - W.y1) 130 | { 131 | case 0: 132 | { 133 | if (W.y2 > top_limit) 134 | top_limit = W.y2; 135 | else 136 | { 137 | if (W.y2 < bottom_limit) 138 | bottom_limit = W.y2; 139 | } 140 | } 141 | default: 142 | { 143 | if (W.y2 > W.y1) 144 | { 145 | if (W.y2 > top_limit) 146 | top_limit = W.y2; 147 | if (W.y1 < bottom_limit) 148 | bottom_limit = W.y1; 149 | } 150 | else 151 | { 152 | if (W.y1 > top_limit) 153 | top_limit = W.y1; 154 | if (W.y2 < bottom_limit) 155 | bottom_limit = W.y2; 156 | } 157 | } 158 | } 159 | switch (W.x2 - W.x1) 160 | { 161 | case 0: 162 | { 163 | if (W.x2 > right_limit) 164 | right_limit = W.x2; 165 | else 166 | { 167 | if (W.x2 < left_limit) 168 | left_limit = W.x2; 169 | } 170 | } 171 | default: 172 | { 173 | if (W.x2 > W.x1) 174 | { 175 | if (W.x2 > right_limit) 176 | right_limit = W.x2; 177 | if (W.x1 < left_limit) 178 | left_limit = W.x1; 179 | } 180 | else 181 | { 182 | if (W.x1 > right_limit) 183 | right_limit = W.x1; 184 | if (W.x2 < left_limit) 185 | left_limit = W.x2; 186 | } 187 | } 188 | } 189 | } 190 | } 191 | // B.wires(A) 192 | // { 193 | // if (A.layer == 20) 194 | // { 195 | // check_x_points(A.x1, A.y1); 196 | // check_y_points(A.y1, A.x1); 197 | // } 198 | // } 199 | B.wires(W) 200 | { 201 | if (W.layer == 20) 202 | { 203 | if(!(W.arc)) 204 | { 205 | check_y_points(W.y2, W.x2); 206 | check_y_points(W.y1, W.x1); 207 | check_x_points(W.x2, W.y2); 208 | check_x_points(W.x1, W.y1); 209 | } 210 | } 211 | } 212 | B.holes(H) 213 | { 214 | check_x_points(H.x, H.y); 215 | check_y_points(H.y, H.x); 216 | } 217 | B.elements(E) 218 | { 219 | E.package.contacts(C) 220 | { 221 | if(C.pad) 222 | { 223 | check_x_points(C.pad.x, C.pad.y); 224 | check_y_points(C.pad.y, C.pad.x); 225 | } 226 | } 227 | } 228 | // 229 | // Adding X dimensions 230 | // 231 | for (i = 0; i <= count_x_points; ++i) 232 | { 233 | if (x_points[i] == 0) 234 | { 235 | printf("Circle 0 (%.2f) (%.2f);\n", (u2mil(top_limit) + right_top_datum_location), (u2mil(top_limit) + right_top_datum_location + (datum_dot_diameter /2))); 236 | printf("Circle 0 (%.2f) (%.2f);\n", (u2mil(bottom_limit) - left_bottom_datum_location), (u2mil(bottom_limit) - left_bottom_datum_location - (datum_dot_diameter /2))); 237 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, u2mil(x_points[i]), (u2mil(top_limit) + extender_clearance), u2mil(x_points[i]), (u2mil(top_limit) + right_top_extender_length)); 238 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", datum_wire_width, u2mil(x_points[i]), (u2mil(bottom_limit) - extender_clearance), u2mil(x_points[i]), (u2mil(bottom_limit) - left_bottom_extender_length)); 239 | printf("Text '%.0f' R90 (%.2f %.2f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(top_limit) + text_offset)); 240 | printf("Text '%.0f' R90 (%.2f %.2f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(bottom_limit) - text_offset - 0.3)); 241 | 242 | } 243 | if (x_points_loc[i] == "top") 244 | { 245 | if (x_points[i] > higher_top) 246 | higher_top = x_points[i]; 247 | if (x_points[i] < lower_top) 248 | lower_top = x_points[i]; 249 | printf("Text '%.0f' R90 (%.2f %.2f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(top_limit) + text_offset)); 250 | printf("Wire %.2f (%.2f %.2f) (%.2f %.2f);\n", default_wire_width, u2mil(x_points[i]), (u2mil(top_limit) + extender_clearance), u2mil(x_points[i]), (u2mil(top_limit) + right_top_extender_length)); 251 | } 252 | else 253 | { 254 | if (x_points[i] > higher_bottom) 255 | higher_bottom = x_points[i]; 256 | if (x_points[i] < lower_bottom) 257 | lower_bottom = x_points[i]; 258 | printf("Text '%.0f' R90 (%f %f);\n", abs(u2mil(x_points[i])), u2mil(x_points[i]), (u2mil(bottom_limit) - text_offset - 0.3)); 259 | printf("Wire %f (%f %f) (%f %f);\n", default_wire_width, u2mil(x_points[i]), (u2mil(bottom_limit) - extender_clearance), u2mil(x_points[i]), (u2mil(bottom_limit) - left_bottom_extender_length)); 260 | } 261 | } 262 | // Join all X dimensions 263 | if (lower_top != higher_top) 264 | printf("Wire %f (%f %f) (%f %f);\n", default_wire_width, u2mil(lower_top), (u2mil(top_limit) + right_top_datum_location), u2mil(higher_top), (u2mil(top_limit) + right_top_datum_location)); 265 | if (lower_bottom != higher_bottom) 266 | printf("Wire %f (%f %f) (%f %f);\n", default_wire_width, u2mil(lower_bottom), (u2mil(bottom_limit) - left_bottom_datum_location), u2mil(higher_bottom), (u2mil(bottom_limit) - left_bottom_datum_location)); 267 | 268 | // 269 | // Adding Y dimensions 270 | // 271 | for (i = 0; i <= count_y_points; ++i) 272 | { 273 | if (y_points[i] == 0) 274 | { 275 | printf("Circle 0 (%f 0) (%f 0);\n", (u2mil(right_limit) + right_top_datum_location), (u2mil(right_limit) + right_top_datum_location + (datum_dot_diameter /2))); 276 | printf("Circle 0 (%f 0) (%f 0);\n", (u2mil(left_limit) - left_bottom_datum_location), (u2mil(left_limit) - left_bottom_datum_location - (datum_dot_diameter /2))); 277 | printf("Wire %f (%f %f) (%f %f);\n", datum_wire_width, (u2mil(right_limit) + extender_clearance), u2mil(y_points[i]), (u2mil(right_limit) + right_top_extender_length), u2mil(y_points[i])); 278 | printf("Wire %f (%f %f) (%f %f);\n", datum_wire_width, (u2mil(left_limit) - extender_clearance), u2mil(y_points[i]), (u2mil(left_limit) - left_bottom_extender_length), u2mil(y_points[i])); 279 | printf("Text '%.0f' R0 (%f %f);\n", abs(u2mil(y_points[i])), (u2mil(right_limit) + text_offset), u2mil(y_points[i])); 280 | printf("Text '%.0f' R0 (%f %f);\n", abs(u2mil(y_points[i])), (u2mil(left_limit) - text_offset - 0.3), u2mil(y_points[i])); 281 | } 282 | if (y_points_loc[i] == "right") 283 | { 284 | if (y_points[i] > higher_right) 285 | higher_right = y_points[i]; 286 | if (y_points[i] < lower_right) 287 | lower_right = y_points[i]; 288 | printf("Text '%.0f' R0 (%f %f);\n", abs(u2mil(y_points[i])), (u2mil(right_limit) + text_offset), u2mil(y_points[i])); 289 | printf("Wire %f (%f %f) (%f %f);\n", default_wire_width, (u2mil(right_limit) + extender_clearance), u2mil(y_points[i]), (u2mil(right_limit) + right_top_extender_length), u2mil(y_points[i])); 290 | } 291 | else 292 | { 293 | if (y_points[i] > higher_left) 294 | higher_left = y_points[i]; 295 | if (y_points[i] < lower_left) 296 | lower_left = y_points[i]; 297 | printf("Text '%.0f' R0 (%f %f);\n", abs(u2mil(y_points[i])), (u2mil(left_limit) - text_offset - 0.3), u2mil(y_points[i])); 298 | printf("Wire %f (%f %f) (%f %f);\n", default_wire_width, (u2mil(left_limit) - extender_clearance), u2mil(y_points[i]), (u2mil(left_limit) - left_bottom_extender_length), u2mil(y_points[i])); 299 | } 300 | } 301 | // Join all Y dimensions 302 | if (lower_right != higher_right) 303 | printf("Wire %f (%f %f) (%f %f);\n", default_wire_width, (u2mil(right_limit) + right_top_datum_location), u2mil(lower_right), (u2mil(right_limit) + right_top_datum_location), u2mil(higher_right)); 304 | if (lower_left != higher_left) 305 | printf("Wire %f (%f %f) (%f %f);\n", default_wire_width, (u2mil(left_limit) - left_bottom_datum_location), u2mil(lower_left), (u2mil(left_limit) - left_bottom_datum_location), u2mil(higher_left)); 306 | } 307 | printf("Text 'All Dimensions in mil' R0 (%f %f);\n",u2mil(right_limit),u2mil(top_limit)); 308 | printf("Text 'Spark Fun Electronics' R0 (%f %f);\n",u2mil(right_limit),u2mil(top_limit)-2); 309 | printf("Grid Last;\n"); 310 | printf("Window Fit;\n"); 311 | } 312 | -------------------------------------------------------------------------------- /ulp/board_default.ulp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | * * 3 | * * 4 | ****************************************************************************************/ 5 | board(B) 6 | { 7 | B.layers(L) printf("Layer %3d %s\n", L.number, L.name); 8 | } 9 | 10 | int i; 11 | 12 | void set_defaults(void) 13 | { 14 | 15 | } -------------------------------------------------------------------------------- /ulp/drill-exactsize.ulp: -------------------------------------------------------------------------------- 1 | // ***** MODIFIED VERSION of CadSoft's drill-aid ULP!! 2 | // By MadWizard for imagedump script. See www.madwizard.org 3 | 4 | 5 | string cmd = "GRID mm;\nLayer 116 drillImage;\nchange layer 116;\n"; 6 | 7 | void center(int x, int y, int drill) { 8 | 9 | real width = u2mm(drill) / 2; 10 | real radius = width / 2 ; 11 | string h; 12 | sprintf(h, "circle %.3f (%.3f %.3f) (%.3f %.3f) ;\n", 13 | width, 14 | u2mm(x), u2mm(y), u2mm(x) + radius, u2mm(y) ); 15 | cmd += h; 16 | return; 17 | } 18 | 19 | if (board) board(B) { 20 | 21 | 22 | B.holes(L) { 23 | center(L.x, L.y, L.drill); 24 | } 25 | B.elements(E) { 26 | E.package.holes(H) { 27 | center(H.x, H.y, H.drill); 28 | } 29 | E.package.contacts(C) { 30 | if (C.pad) { 31 | center(C.pad.x, C.pad.y, C.pad.drill); 32 | } 33 | } 34 | } 35 | B.signals(S) { 36 | S.vias(V) { 37 | center(V.x, V.y, V.drill); 38 | } 39 | } 40 | exit (cmd); 41 | } 42 | 43 | else dlgMessageBox("Start this ULP in a Board!", "OK"); 44 | exit (0); 45 | -------------------------------------------------------------------------------- /ulp/exp-lbrs.ulp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/exp-lbrs.ulp -------------------------------------------------------------------------------- /ulp/gerbv.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/gerbv.exe -------------------------------------------------------------------------------- /ulp/help-images/PartCreator-Axis-Indicators.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/help-images/PartCreator-Axis-Indicators.bmp -------------------------------------------------------------------------------- /ulp/help-images/PartCreator-Center-Pad.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/help-images/PartCreator-Center-Pad.bmp -------------------------------------------------------------------------------- /ulp/help-images/PartCreator-Pad-Distances.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/help-images/PartCreator-Pad-Distances.bmp -------------------------------------------------------------------------------- /ulp/help-images/PartCreator-Pin-Size.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/help-images/PartCreator-Pin-Size.bmp -------------------------------------------------------------------------------- /ulp/import-bmp.ulp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sparkfun/SparkFun_Eagle_Settings/b4dd178bea6bf97d586f5cf2bf20edca98f1f488/ulp/import-bmp.ulp -------------------------------------------------------------------------------- /ulp/mirror-board.ulp: -------------------------------------------------------------------------------- 1 | #usage "Mirror board (with all Layers)

" 2 | "Author: support@cadsoft.de" 3 | 4 | // THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED 5 | // Version 1.01 -- 2006-09-15 alf@cadsoft.de 6 | // 2008-04-10 changed GROUP ... (>x y); alf@cadsoft.de 7 | 8 | string cmd; 9 | int lVisible[]; 10 | int useLayer[]; 11 | string lNames[] = { " " }; 12 | 13 | int maxX = INT_MIN; 14 | int minX = INT_MAX; 15 | int maxY = INT_MIN; 16 | int minY = INT_MAX; 17 | int bminx, bmaxx, bminy, bmaxy; 18 | 19 | int uval = 1; 20 | if (board) board(B) uval = B.grid.unit; 21 | string unit[] = { "Micron", "mm", "Mil", "Inch" }; 22 | int unitPrec[] = { 0, 1, 1, 3 }, RoundFactor = pow(10, unitPrec[uval]); 23 | 24 | real u2u(int v) { 25 | switch (uval) { 26 | case GRID_UNIT_MIC : return u2mic(v); 27 | break; 28 | 29 | case GRID_UNIT_MM : return u2mm(v); 30 | break; 31 | 32 | case GRID_UNIT_MIL : return u2mil(v); 33 | break; 34 | 35 | case GRID_UNIT_INCH : return u2inch(v); 36 | break; 37 | } 38 | } 39 | 40 | 41 | void checkmaxmin(int x1, int x2, int y1, int y2) { 42 | if (x1 > maxX) maxX = x1; 43 | if (x2 > maxX) maxX = x2; 44 | if (y1 > maxY) maxY = y1; 45 | if (y2 > maxY) maxY = y2; 46 | if (x1 < minX) minX = x1; 47 | if (x2 < minX) minX = x2; 48 | if (y1 < minY) minY = y1; 49 | if (y2 < minY) minY = y2; 50 | return; 51 | } 52 | 53 | void checkarc( int x1, int x2, int y1, int y2, int xc, int yc, real angle1, real angle2, real radius) { 54 | checkmaxmin( x1, x2, y1, y2 ); 55 | if ( angle2 > angle1 + 270.0) { 56 | if ( angle1 < 90 ) checkmaxmin( x1 , xc - radius, yc + radius, yc - radius ); 57 | else if( angle1 < 180 ) checkmaxmin( xc - radius, xc + radius, y1 , yc - radius ); 58 | else if( angle1 < 270 ) checkmaxmin( x1 , xc + radius, yc - radius, yc + radius ); 59 | else if( angle1 < 360 ) checkmaxmin( xc + radius, xc - radius, y1 , yc + radius ); 60 | } 61 | else if( angle2 > angle1 + 180.0) { 62 | if ( angle1 < 90 ) checkmaxmin( x1 , xc - radius, yc + radius, y2 ); 63 | else if( angle1 < 180 ) checkmaxmin( x1 , xc - radius, yc - radius, y2 ); 64 | else if( angle1 < 270 ) checkmaxmin( x1 , xc + radius, yc - radius, y2 ); 65 | else if( angle1 < 360 ) checkmaxmin( x1 , xc + radius, yc + radius, y2 ); 66 | } 67 | else if( angle2 > angle1 + 90.0 ) { 68 | if ( angle1 < 90 ) checkmaxmin( x1 , x2 , yc + radius, y2 ); 69 | else if( angle1 < 180 ) checkmaxmin( x1 , xc - radius, y1 , y2 ); 70 | else if( angle1 < 270 ) checkmaxmin( x1 , x2 , yc - radius, y2 ); 71 | else if( angle1 < 360 ) checkmaxmin( x1 , xc + radius, y1 , y2 ); 72 | } 73 | return; 74 | } 75 | 76 | real WireLength(int x1, int x2, int y1, int y2) { 77 | return sqrt( pow(u2u(x2) - u2u(x1), 2) + pow( u2u(y2) - u2u(y1), 2)); 78 | } 79 | 80 | 81 | 82 | // main 83 | if (board) { 84 | board(B) { 85 | bminx = B.area.x1; 86 | bmaxx = B.area.x2; 87 | bminy = B.area.y1; 88 | bmaxy = B.area.y2; 89 | B.layers(L) { 90 | lNames[L.number] = L.name; 91 | lVisible[L.number] = L.visible; 92 | useLayer[L.number] = L.used; 93 | } 94 | B.wires(W) { 95 | if (W.layer == 20) { 96 | if (W.arc) { 97 | checkarc(W.arc.x1, W.arc.x2, W.arc.y1, W.arc.y2, W.arc.xc, W.arc.yc, W.arc.angle1, W.arc.angle2, W.arc.radius); 98 | } 99 | else { 100 | checkmaxmin( W.x1, W.x2, W.y1, W.y2 ); 101 | } 102 | } 103 | } 104 | B.circles(C) { 105 | if (C.layer == 20) { 106 | checkmaxmin( C.x - C.radius, C.x + C.radius, C.y - C.radius, C.y + C.radius ); 107 | } 108 | } 109 | B.elements(E) { 110 | E.package.wires(W) { 111 | if (W.layer == 20) { 112 | // *** Dimension in Packages *** 113 | if (W.arc) { 114 | checkarc(W.arc.x1, W.arc.x2, W.arc.y1, W.arc.y2, W.arc.xc, W.arc.yc, W.arc.angle1, W.arc.angle2, W.arc.radius); 115 | } 116 | else { 117 | checkmaxmin( W.x1, W.x2, W.y1, W.y2 ); 118 | } 119 | } 120 | } 121 | E.package.circles(C) { 122 | if (C.layer == 20) { 123 | checkmaxmin( C.x - C.radius, C.x + C.radius, C.y - C.radius, C.y + C.radius ); 124 | } 125 | } 126 | } 127 | } 128 | string s; 129 | sprintf(s, "DISPLAY ALL;\n"); 130 | cmd += s; 131 | sprintf(s, "GROUP (%.4f %.4f) (%.4f %.4f) (%.4f %.4f) (%.4f %.4f) (>%.4f %.4f);\n", 132 | u2u(bminx-1000), u2u(bminy-1000), 133 | u2u(bmaxx+1000), u2u(bminy-1000), 134 | u2u(bmaxx+1000), u2u(bmaxy+1000), 135 | u2u(bminx-1000), u2u(bmaxy+1000), 136 | u2u(bminx-1000), u2u(bminy-1000) 137 | ); 138 | cmd += s; 139 | sprintf(s, "GRID FINEST;\nMIRROR (>%.4f %.4f);\nGRID LAST;\n", 140 | (u2u(maxX) + u2u(minX)) / 2, u2u(minY) ); 141 | cmd += s; 142 | cmd += "DISPLAY NONE "; 143 | for(int l = 1; l < 256; l++) { 144 | if (lNames[l]) { // Layer defined 145 | if (lVisible[l]) sprintf(s, " %d", l); 146 | else sprintf(s, " -%d", l); 147 | cmd += s; 148 | } 149 | } 150 | cmd += ";"; 151 | } 152 | exit(cmd); -------------------------------------------------------------------------------- /ulp/oshw-logo.ulp: -------------------------------------------------------------------------------- 1 | /* 2 | * oshw_logo.ulp 3 | * April 2011, By Bill Westfield (westfw@yahoo.com) 4 | * 5 | * Draw the "golden orb" Open Source Hardware logo 6 | * This is rather customizable; it can draw wires or polygons, 7 | * on any desired layer, at any desired size. 8 | */ 9 | 10 | #usage "Create an instance of the Open Source Hardware Logo

\n" 11 | " run oshw-logo [outside-diameter]\n\n

" 12 | " The logo will be centered at the current 'mark'

\n" 13 | "Author: Bill Westfield (westfw@yahoo.com) 8-Apr-2011" 14 | 15 | real linewidth = 0.015; 16 | real td=0, totaldiam = 0.45; 17 | 18 | if (argc > 1) { 19 | td = strtod(argv[1]); 20 | } 21 | if (td == 0) { 22 | td = totaldiam; /* outside diameter of teeth (total) */ 23 | } 24 | 25 | /* 26 | * derived sizes. Change to alter "the look", but probably not 27 | * as a matter of course 28 | */ 29 | real id = (td / 3.2); /* outside of wheel */ 30 | real od = (id * 2.2); /* outside of teeth */ 31 | real bgapa = 45; /* Bottom gap angle */ 32 | real tia = 26; /* Tooth inside angle */ 33 | real toa = 14; /* tooth outside angle */ 34 | real ga = (45-tia); /* Gap inside angle */ 35 | 36 | /* 37 | * Internal variables 38 | */ 39 | int i; 40 | string s, cmd; 41 | 42 | /* 43 | * Draw an orb as an outline (wire) or as a filled shape (polygon) 44 | * on a particular layer 45 | */ 46 | void draw_orb (string command, string layer) 47 | { 48 | real sa; /* Start angle for the drawing */ 49 | 50 | sprintf(s, "change layer %s; set wire_bend 7;\n", layer); cmd += s; 51 | /* 52 | * Start point 53 | */ 54 | sprintf(s, "%s %f (P %f %f)", command, linewidth, 55 | od/2, -90.0 + bgapa/2); 56 | cmd += s; 57 | 58 | sa = -90 + tia/2; 59 | 60 | for (i=0; i < 7; i++) { 61 | /* outside gap */ 62 | sprintf(s," @+%f (P %f %f)", od/2, od/2, sa + ga); 63 | cmd += s; 64 | /* to outside tooth */ 65 | sprintf(s," +0 (P %f %f)", td/2, sa + ga + (tia - toa)/2); 66 | cmd += s; 67 | /* outside of tooth */ 68 | sprintf(s," +0 (P %f %f)", td/2, sa + ga + (tia - toa)/2 + toa); 69 | cmd +=s; 70 | /* back to next gap */ 71 | sprintf(s," +0 (P %f %f)", od/2, sa + 45.0); cmd += s; 72 | sa += 45.0; 73 | } 74 | /* 75 | * End point 76 | */ 77 | sprintf(s, " @+%f (P %f %f)", od/2, od/2, -90.0 - bgapa/2); 78 | cmd +=s; 79 | /* 80 | * Inside circle 81 | * (we need to draw the circle in two steps to get the curvature 82 | * in the right direction.) 83 | */ 84 | sprintf(s, " +0 (P %f %f) @-%f (P %f %f) (P %f %f) +0 (P %f %f)", 85 | id/2, -90.0 - bgapa/2, id/2, 86 | id/2, -180.0, 87 | id/2, -90 + bgapa/2, 88 | od/2, 270 + bgapa/2); 89 | cmd +=s; 90 | cmd += ";\n"; 91 | } 92 | 93 | //draw_orb("poly", "tplace"); 94 | draw_orb("poly", "symbols"); 95 | //draw_orb("wire", "top"); 96 | 97 | exit(cmd); 98 | -------------------------------------------------------------------------------- /ulp/readme.md: -------------------------------------------------------------------------------- 1 | SparkFun Eagle User Language Programs (ULPs) 2 | ======================================== 3 | 4 | These ULPs were developed to aid in various day to day operations at SparkFun. They may or may not be helpful to general users. 5 | 6 | * **Include_String.ulp** - Functions used by SparkFun-BOM-Generator. 7 | * **SparkFun-BOM-Generator.ulp** - Scans schematic components and outputs a list of product IDs needed for creating BOMs within the SparkFun ERP software. Also attempts to detect and warn user if there are values that don't match their attribute (for example the product ID is for a 10k but the user has changed the value to 4.7k). 8 | * **SparkFun-CAMmer.ulp** - Creates gerber files from a BRD design. Zips files together using 7za.exe. Checks to see if there are internal layers (up to 4) and outputs appropriate gerbers. Checks to see if there are components on the bottom layer and outputs bottom stencil if requested. 9 | * **SparkFun-Panelizer.ulp** - Creates a given sized panel by copying and pasting a board design with spacing between boards. Works with both 2 layer and 4 layer boards. Automatically loads the correct DRC file (protects against unmasked vias and incorrect polygon pours). Detects if there are overhanging parts that may interfere with the neighboring board. Draws optional v-score indicators and production-friendly frame. 10 | * **SparkFun-PartCreator.ulp** - Parametrically create a device, footprint, and symbol for rectangular ICs. 11 | 12 | License Information 13 | ------------------- 14 | 15 | The **code** is released under the GPL v3 license. 16 | 17 | Distributed as-is; no warranty is given. 18 | 19 | - Your friends at SparkFun. -------------------------------------------------------------------------------- /ulp/set-all-devices-attribute.ulp: -------------------------------------------------------------------------------- 1 | 2 | #usage "en:Run a SCRIPT through all Device Sets (Technology) in a library to define ATTRIBUTEs

\n" 3 | "RUN set-all-devices-attribute [SCRIPT]
" 4 | "The script must conform to the following syntax:
" 5 | "ATTRIBUTE name 'value'
" 6 | "ATTRIBUTE name DELETE

" 7 | "The words may be separated by one single space character only.
" 8 | "In case the value DELETE is used, the attribute will be deleted.

" 9 | "Value must be included in two single quotes, otherwise special " 10 | "characters, like + - space can cause error messages in the script file.
" 11 | "If there is no value given or this attribute is already defined in the Device Set " 12 | "the attribute remains unchanged.

" 13 | "Author: librarian@cadsoft.de

" 14 | , 15 | "de:Startet ein SCRIPT um in allen Devicesets (Technologien) in einer Bibliothek ATTRIBUTE zu definieren.

\n" 16 | "RUN set-all-devices-attribute [SCRIPT]
" 17 | "Das Script muß nach folgenden Regeln erstellt sein:
" 18 | "ATTRIBUTE Name 'Wert'
" 19 | "ATTRIBUTE Name DELETE

" 20 | "Die Wörter dürfen mit nur einem Leerzeichen (Space) getrennt sein.
" 21 | "Ist der Wert DELETE zugewiesen, wird das Attribute gelöscht

" 22 | "Der Wert muß in zwei Apostrophen eingeschlossen sein, da es sonst bei " 23 | "Sonderzeichen + - Space etc. im erzeugten Script zu Fehlermeldungen kommen kann.
" 24 | "Ist kein Wert angegeben und/oder das Attribute im Deviceset schon vorhanden und " 25 | "ein Wert zugewiesen, dann bleibt das Attribute in diesem Deviceset unverändert.

" 26 | "Author: librarian@cadsoft.de

" 27 | 28 | 29 | // https://github.com/plusea/EAGLE/blob/master/ulp/set-all-devices-attribute.ulp 30 | 31 | string Version = "1.1"; // 2008-09-04 check Variant name 32 | // 1.0 // 2008-06-13 alf@cadsoft.de 33 | 34 | string ScriptFile = argv[1]; 35 | string cmdScript, cmd, s; 36 | 37 | string Lines[], Attribut[], AttValue[]; 38 | int setAtt[]; 39 | int cntl = 0; 40 | int cntAtt = 0; 41 | 42 | if (argv[1] == "?") { 43 | dlgMessageBox(usage, "OK"); 44 | } 45 | 46 | void test(void) { 47 | dlgDialog(filename(argv[0]) + " Script") { 48 | dlgTextView(cmd); 49 | dlgHBoxLayout { 50 | dlgPushButton("OK") dlgAccept(); 51 | dlgPushButton("Abbruch") { dlgReject(); exit(-2); } 52 | } 53 | }; 54 | return; 55 | } 56 | 57 | 58 | string check_varname(string s) { // 2008-09-04 59 | if(s == "''") return s; 60 | return "'"+s+"'"; 61 | } 62 | 63 | 64 | void readScript(void) { 65 | cntl = fileread(Lines, ScriptFile); 66 | for (int n = 0; n < cntl; n++) { 67 | if (strstr(Lines[n], "ATTRIBUTE") == 0) { 68 | string a[]; 69 | int cnta = strsplit(a, Lines[n], ' '); 70 | Attribut[cntAtt] = a[1]; 71 | AttValue[cntAtt] = a[2]; 72 | for (int an = 3; an < cnta; an++) { // complete parameter with space 73 | AttValue[cntAtt] += " "+a[an]; 74 | } 75 | cntAtt++; 76 | } 77 | } 78 | return; 79 | } 80 | 81 | 82 | if (library) { 83 | library(L) { 84 | if (ScriptFile) { 85 | string fg[]; 86 | int cntf = fileglob(fg, path_scr[0]+"/"+ScriptFile); 87 | if (!cntf) ScriptFile = ""; 88 | else ScriptFile = fg[0]; 89 | } 90 | if (!ScriptFile) ScriptFile = dlgFileOpen("Select a SCRIPT with ATTRIBUTE commands to run in all DEVICESETS", path_scr[0], "*.scr"); 91 | if (!ScriptFile) exit(0); 92 | readScript(); 93 | cmdScript = filesetext(L.name, "~.scr"); 94 | L.devicesets(DS) { 95 | sprintf(s, "EDIT %s.DEV;\n", DS.name); 96 | cmd += s; 97 | int n; 98 | DS.devices(D) { 99 | string t[]; 100 | int nt = strsplit(t, D.technologies, ' '); 101 | sprintf(s, "PACKAGE %s;\n", check_varname(D.name) ); 102 | cmd += s; 103 | for (int i = 0; i < nt; i++) { 104 | sprintf(s, "TECHNOLOGY %s;\n", t[i]); 105 | cmd += s; 106 | for (n = 0; n < cntAtt; n ++) setAtt[n] = 1; // preset flags 107 | D.attributes(A, t[i]) { 108 | for (n = 0; n < cntAtt; n++) { 109 | status(DS.name+":"+D.name+":"+t[i]); 110 | 111 | if (A.name == Attribut[n]) { 112 | if (A.value || !AttValue[n]) setAtt[n] = 0; // wenn das Attribut schon einen Wert besitzt 113 | // oder im Script kein Wert zugewiesen wird, 114 | // wird das Attribut nicht geändert 115 | } 116 | } 117 | } 118 | for (n = 0; n < cntAtt; n ++) { 119 | if (setAtt[n] || AttValue[n] == "DELETE") { 120 | sprintf(s, "ATTRIBUTE %s %s;\n", Attribut[n], AttValue[n]); 121 | cmd+=s; 122 | s=""; 123 | } 124 | } 125 | } 126 | } 127 | } 128 | } 129 | output(cmdScript, "wtD") printf("%s", cmd); 130 | sprintf(s, "SCRIPT '%s';\n", cmdScript); 131 | exit(s); 132 | } 133 | 134 | else dlgMessageBox("Start this ULP from a Library", "OK"); -------------------------------------------------------------------------------- /ulp/z_Include_SF_BOM.ulp: -------------------------------------------------------------------------------- 1 | // string ulpName = "SparkFun-BOM_Generator"; 2 | string ulpName = argv[0]; 3 | int setup_complete = 0; 4 | int redraw = 1; 5 | 6 | // Master lists of properties that we care about 7 | string master_prod_ids[]; 8 | string master_package_names[]; 9 | string master_values[]; 10 | string master_names[]; 11 | string master_pnp_names[]; 12 | int master_quantities[]; 13 | int master_status[]; 14 | int master_matches_filters[]; 15 | int numUniqueEntries = 0; 16 | 17 | // There are four classifications that a given unique entry can have: 18 | // - Valid for BOM, called "bom" 19 | // - Invalid for BOM, called "nonbom" 20 | // - Invlaid for BOM AND hidden by filters, called "filtered" 21 | // - Permanently removed from the search because it is a non-physical item, called "nonhardware" 22 | 23 | // Status definitions 24 | int element_status_unknown = 0; 25 | int element_status_bom = 1; 26 | int element_status_nonbom = 2; 27 | // int element_status_filtered = 3; // Filtered is not a status anymore, rather it is a show/hide flag and it is contained in master_matches_filters 28 | int element_status_nonhardware = 4; 29 | 30 | // Info for nonbom elements 31 | string nonbomlistarry[]; 32 | int nonbomSort = 0; 33 | int nonbomSelected = -1; 34 | int nonbom_index_map[]; 35 | 36 | // Info for bom elements 37 | string bomlistarry[]; 38 | string pnplistarry[]; 39 | int bomSort = 0; 40 | int bomSelected = -1; 41 | int pnpSelected = -1; 42 | int bom_index_map[]; 43 | 44 | // Info for filtered elements 45 | string filteredlistarry[]; 46 | int filteredSort = 0; 47 | int filteredSelected = -1; 48 | int filtered_index_map[]; 49 | 50 | // Info for nonhardware elements 51 | string nonhardwarelistarry[]; 52 | int nonhardwareSort = 0; 53 | int nonhardwareSelected = -1; 54 | int nonhardware_index_map[]; 55 | 56 | // Counters for the number of elements in each category 57 | int bomCount = 0; 58 | int nonbomCount = 0; 59 | int filteredCount = 0; 60 | int nonhardwareCount = 0; 61 | 62 | // Filter settings 63 | string configFile = filesetext(argv[0], ".flt"); 64 | string filterStrings[] = {"fiducial", "stand-off"}; 65 | int filters_active = 1; 66 | string filterStatus[] = {"off", "on"}; 67 | int filter_string_selected = -1; 68 | int filter_string_sort = 0; 69 | string temp_filter_string = "AddFilterHere"; 70 | string customFilterFile = ""; 71 | 72 | // GUI Vars 73 | string prod_id_warning = ""; 74 | string headerString = "Qty\tPROD_ID\tNames\tValue\tPackage"; 75 | string pnpHeaderString = "Qty\tPROD_ID\tPart\tNames\tValue\tPackage"; 76 | string sparkleBOM; // A string for sparkle output 77 | string numFilteredItems = ""; 78 | string exportFilePath = ""; 79 | 80 | // Function definitions 81 | 82 | // Saves currrent filter strings to file "outfile" 83 | void configWrite(string outfile) 84 | { 85 | output(outfile) 86 | { 87 | int index = 0; 88 | while (filterStrings[index] != "") 89 | { 90 | printf("%s\n", filterStrings[index]); 91 | index++; 92 | } 93 | } 94 | } 95 | 96 | // Reads new filter strings from file "infile" 97 | int configRead(string infile) 98 | { 99 | if (filesize(infile)) 100 | { //Check if file exists 101 | 102 | int indk = 0; 103 | while (filterStrings[indk] != "") 104 | { // Clear out old saved filter strings, if any exist 105 | filterStrings[indk] = ""; 106 | indk++; 107 | } 108 | 109 | string data[]; 110 | int line = fileread(data, infile); 111 | 112 | if (line) 113 | { 114 | int indi = 0; 115 | while (data[indi] != "") 116 | { 117 | filterStrings[indi] = data[indi]; 118 | indi++; 119 | } 120 | } 121 | return 0; 122 | } 123 | else 124 | { 125 | return 1; 126 | } 127 | } 128 | 129 | void removeFromFilterList() 130 | { 131 | if (filter_string_selected == -1) 132 | { 133 | return; 134 | } 135 | 136 | int indi = filter_string_selected; 137 | while (filterStrings[indi] != "") 138 | { 139 | filterStrings[indi] = filterStrings[indi + 1]; 140 | indi++; 141 | } 142 | } 143 | 144 | void addToFilterList() 145 | { 146 | if (temp_filter_string != "AddFilterHere") 147 | { 148 | int indi = 0; 149 | while (filterStrings[indi] != "") 150 | { 151 | indi++; 152 | } 153 | 154 | filterStrings[indi] = temp_filter_string; 155 | temp_filter_string = "AddFilterHere"; 156 | } 157 | } 158 | 159 | //Strip off the alpha pre bits 160 | //Remove leading zeros 161 | string pidFormat(string id_str) 162 | { 163 | string numeral_entries[]; 164 | int numEntries = strsplit(numeral_entries, id_str, '-'); 165 | if (numEntries < 2) 166 | { 167 | // dlgMessageBox("Too few entries found in the product id"); 168 | return "NaN"; 169 | } 170 | string numerals = numeral_entries[1]; 171 | while (numerals[0] == '0') 172 | { 173 | string t = strsub(numerals, 1, strlen(numerals)); 174 | numerals = t; 175 | } 176 | 177 | return numerals; 178 | } 179 | 180 | string replaceCharacter(string base, char from, char to) 181 | { 182 | string retval = base; 183 | for (int indj = 0; indj < strlen(retval); indj++) 184 | { 185 | if (retval[indj] == from) 186 | { 187 | retval[indj] = to; 188 | } 189 | } 190 | return retval; 191 | } 192 | 193 | void generateSparkleList() 194 | { 195 | int invalidPIDcount = 0; 196 | sparkleBOM = ""; 197 | for (int indi = 0; indi < bomCount; indi++) 198 | { 199 | string temp = ""; 200 | string prod_id = master_prod_ids[bom_index_map[indi]]; 201 | string idNUM = pidFormat(prod_id); 202 | if (idNUM == "NaN") 203 | { 204 | invalidPIDcount++; 205 | } 206 | else if (indi < (bomCount - 1)) 207 | { 208 | sprintf(temp, "%s,", idNUM); 209 | } 210 | else 211 | { 212 | sprintf(temp, "%s", idNUM); 213 | } 214 | 215 | //Print multiple of this PROD_ID to indicate the qty of the item 216 | for (int x = 0; x < master_quantities[bom_index_map[indi]]; x++) 217 | { 218 | sparkleBOM += temp; 219 | } 220 | } 221 | 222 | if (invalidPIDcount) 223 | { 224 | // string msg = ""; 225 | // sprintf(msg, "Warning: %d items in BOM list without PROD_ID", invalidPIDcount); 226 | 227 | sprintf(prod_id_warning, "Warning: %d BOM items have no PROD_ID!", invalidPIDcount); 228 | // dlgMessageBox(msg); 229 | } 230 | else 231 | { 232 | sprintf(prod_id_warning, "All BOM items have PROD_ID. Good job :D"); 233 | } 234 | } 235 | 236 | //Finds a string in a string no matter where, no matter capitalization 237 | int containsString(string toSearch, string toFind) 238 | { 239 | int pos = strstr(strlwr(toSearch), strlwr(toFind)); 240 | if (pos >= 0) //String found 241 | { 242 | return (1); 243 | } 244 | return (0); 245 | } 246 | 247 | int filterMatch(string str) 248 | { 249 | // Checks if str contains any of the filter strings 250 | int retval = 0; // Begin with no match 251 | int indi = 0; 252 | while (filterStrings[indi] != "") 253 | { 254 | if (containsString(str, filterStrings[indi])) 255 | { 256 | retval = 1; 257 | } 258 | indi++; 259 | } 260 | return retval; 261 | } 262 | 263 | int matchesFilters(UL_ELEMENT E) 264 | { 265 | return filterMatch(E.package.name); 266 | } 267 | 268 | int getStatus(UL_ELEMENT E) 269 | { 270 | // This is the function that contains rules that determine the status of a given element 271 | int this_status = element_status_unknown; 272 | 273 | // Flags for special circumstances 274 | int is_dnp = 0; 275 | int isALabel = 1; 276 | int has_pid = 0; 277 | 278 | // Test for DNP components 279 | if (containsString(E.attribute["Value"], "dnp") || containsString(E.value, "dnp")) 280 | // if((E.value == "DNP") || (E.attribute["Value"] == "DNP")) 281 | { 282 | is_dnp = 1; 283 | } 284 | 285 | // Test for pure-silkness 286 | //If this element has pads then it's not a label 287 | int padCount = 0; 288 | E.footprint.contacts(C) 289 | { 290 | padCount++; 291 | } 292 | if (padCount > 0) 293 | isALabel = 0; 294 | //If this element has a hole then it's not a label 295 | int holeCount = 0; 296 | E.footprint.holes(H) 297 | { 298 | holeCount++; 299 | } 300 | if (holeCount > 0) 301 | isALabel = 0; 302 | 303 | // See if it has a product id 304 | if (E.attribute["PROD_ID"]) 305 | { 306 | has_pid = 1; 307 | } 308 | 309 | // Now take your info and make a decision about the status of the element: 310 | if (has_pid) 311 | { 312 | this_status = element_status_bom; // Has pid and IS hardware then its on the BOM 313 | } 314 | else if (is_dnp || isALabel) 315 | { 316 | this_status = element_status_nonhardware; 317 | } 318 | else 319 | { 320 | this_status = element_status_nonbom; 321 | } 322 | 323 | return this_status; 324 | } 325 | 326 | int elementsMatch(UL_ELEMENT E, int master_index) 327 | { 328 | // The definition of a unique element is important, and we will define it in reverse. 329 | // A non-unique element is one that has a different: 330 | // - value 331 | // - package 332 | // - product id 333 | // - element_status 334 | 335 | int match = 1; 336 | if (E.value != master_values[master_index]) 337 | { 338 | match = 0; 339 | } 340 | if (E.package.name != master_package_names[master_index]) 341 | { 342 | match = 0; 343 | } 344 | if (E.attribute["PROD_ID"] != master_prod_ids[master_index]) 345 | { 346 | match = 0; 347 | } 348 | if (getStatus(E) != master_status[master_index]) 349 | { 350 | match = 0; 351 | } 352 | 353 | return match; 354 | } 355 | 356 | int elementIsUnique(UL_ELEMENT E) 357 | { 358 | int is_unique = 1; 359 | for (int indi = 0; indi < numUniqueEntries; indi++) 360 | { 361 | if (elementsMatch(E, indi) == 1) 362 | { 363 | is_unique = 0; 364 | } 365 | } 366 | return is_unique; 367 | } 368 | 369 | int getMasterIndexMatch(UL_ELEMENT E) 370 | { 371 | int index = 0; 372 | if (elementIsUnique(E) == 0) 373 | { 374 | while (elementsMatch(E, index) != 1) 375 | { 376 | index++; 377 | } 378 | } 379 | else 380 | { 381 | index = -1; 382 | } 383 | return index; 384 | } 385 | 386 | void initialGrouping() 387 | { 388 | // This is how we initially count the number of unique elements, as well as fill out the arrays of data that can be used for sorting later 389 | 390 | board(B) 391 | { 392 | B.elements(E) 393 | { 394 | if (elementIsUnique(E)) 395 | { 396 | // Add new unique item to the master arrays 397 | 398 | master_prod_ids[numUniqueEntries] = E.attribute["PROD_ID"]; 399 | master_package_names[numUniqueEntries] = E.package.name; 400 | master_values[numUniqueEntries] = E.value; 401 | master_names[numUniqueEntries] = E.name; 402 | master_pnp_names[numUniqueEntries] = E.name; 403 | master_quantities[numUniqueEntries] = 1; 404 | master_status[numUniqueEntries] = getStatus(E); // Returns one of four categories, bom, nonbom, filtered, or nonhardware 405 | master_matches_filters[numUniqueEntries] = matchesFilters(E); 406 | numUniqueEntries++; 407 | } 408 | else 409 | { 410 | int index = getMasterIndexMatch(E); 411 | if (index != -1) 412 | { 413 | // Add quantity and additional name to that master item 414 | master_names[index] += (", " + E.name); 415 | master_pnp_names[index] += (" " + E.name); 416 | master_quantities[index]++; 417 | } 418 | } 419 | } 420 | } 421 | } 422 | 423 | void categorizeElements() 424 | { 425 | // Clear out the old lists 426 | for (int indk = 0; indk < bomCount; indk++) 427 | { 428 | bomlistarry[indk] = ""; 429 | pnplistarry[indk] = ""; 430 | bom_index_map[indk] = -1; 431 | } 432 | for (int indj = 0; indj < nonbomCount; indj++) 433 | { 434 | nonbomlistarry[indj] = ""; 435 | nonbom_index_map[indj] = -1; 436 | } 437 | for (int indl = 0; indl < filteredCount; indl++) 438 | { 439 | filteredlistarry[indl] = ""; 440 | filtered_index_map[indl] = -1; 441 | } 442 | for (int indm = 0; indm < nonhardwareCount; indm++) 443 | { 444 | nonhardwarelistarry[indm] = ""; 445 | nonhardware_index_map[indm] = -1; 446 | } 447 | 448 | // Reset the counters 449 | bomCount = 0; 450 | nonbomCount = 0; 451 | filteredCount = 0; 452 | nonhardwareCount = 0; 453 | 454 | // Recategorize the elements from the master lists 455 | for (int indi = 0; indi < numUniqueEntries; indi++) 456 | { 457 | string temp = ""; 458 | sprintf(temp, "%d\t%s\t%s\t%s\t%s", master_quantities[indi], master_prod_ids[indi], master_names[indi], master_values[indi], master_package_names[indi]); 459 | string temp2 = ""; 460 | sprintf(temp2, "%d\t%s\t%s\t%s\t%s\t%s", master_quantities[indi], master_prod_ids[indi], pidFormat(master_prod_ids[indi]), master_pnp_names[indi], master_values[indi], master_package_names[indi]); 461 | 462 | if (master_status[indi] == element_status_nonhardware) 463 | { 464 | nonhardwarelistarry[nonhardwareCount] = temp; 465 | nonhardware_index_map[nonhardwareCount] = indi; 466 | nonhardwareCount++; 467 | } 468 | else if (master_status[indi] == element_status_bom) 469 | { 470 | bomlistarry[bomCount] = temp; 471 | pnplistarry[bomCount] = temp2; 472 | bom_index_map[bomCount] = indi; 473 | bomCount++; 474 | } 475 | else if (master_status[indi] == element_status_nonbom) // Note: filters only apply to nonbom items, because in an ideal world a design would have no items that are both non-hardware and have no prod_id 476 | { 477 | if ((master_matches_filters[indi] == 1) && (filters_active == 1)) 478 | { 479 | filteredlistarry[filteredCount] = temp; 480 | filtered_index_map[filteredCount] = indi; 481 | filteredCount++; 482 | } 483 | else 484 | { 485 | nonbomlistarry[nonbomCount] = temp; 486 | nonbom_index_map[nonbomCount] = indi; 487 | nonbomCount++; 488 | } 489 | } 490 | else 491 | { 492 | // Problems have arisen 493 | } 494 | } 495 | 496 | sprintf(numFilteredItems, "%d", filteredCount); // Show how many items are hidden 497 | 498 | generateSparkleList(); 499 | } 500 | --------------------------------------------------------------------------------