From 23adee0e724c6684a25a747f6f469c2f70660859 Mon Sep 17 00:00:00 2001 From: Brendan Haines Date: Tue, 22 Jun 2021 10:51:43 -0600 Subject: [PATCH] some test kicad plugins --- .../plugins/OutputGeneration/AsyOutputs.py | 16 ++ .../plugins/OutputGeneration/FabOutputs.py | 186 ++++++++++++++++++ .../plugins/OutputGeneration/__init__.py | 5 + .../__pycache__/AsyOutputs.cpython-38.pyc | Bin 0 -> 871 bytes .../__pycache__/FabOutputs.cpython-38.pyc | Bin 0 -> 4366 bytes .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 275 bytes .../TestPlugin/TestPlugin_action.py | 17 ++ .../plugins/TestPlugin/TestPlugin/__init__.py | 3 + .../TestPlugin_action.cpython-38.pyc | Bin 0 -> 791 bytes .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 268 bytes .../plugins/TestPlugin/TestPlugin/icon.png | Bin 0 -> 761 bytes scripting/plugins/TestPlugin/__init__.py | 1 + .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 210 bytes 13 files changed, 228 insertions(+) create mode 100644 scripting/plugins/OutputGeneration/AsyOutputs.py create mode 100644 scripting/plugins/OutputGeneration/FabOutputs.py create mode 100644 scripting/plugins/OutputGeneration/__init__.py create mode 100644 scripting/plugins/OutputGeneration/__pycache__/AsyOutputs.cpython-38.pyc create mode 100644 scripting/plugins/OutputGeneration/__pycache__/FabOutputs.cpython-38.pyc create mode 100644 scripting/plugins/OutputGeneration/__pycache__/__init__.cpython-38.pyc create mode 100644 scripting/plugins/TestPlugin/TestPlugin/TestPlugin_action.py create mode 100644 scripting/plugins/TestPlugin/TestPlugin/__init__.py create mode 100644 scripting/plugins/TestPlugin/TestPlugin/__pycache__/TestPlugin_action.cpython-38.pyc create mode 100644 scripting/plugins/TestPlugin/TestPlugin/__pycache__/__init__.cpython-38.pyc create mode 100644 scripting/plugins/TestPlugin/TestPlugin/icon.png create mode 100644 scripting/plugins/TestPlugin/__init__.py create mode 100644 scripting/plugins/TestPlugin/__pycache__/__init__.cpython-38.pyc diff --git a/scripting/plugins/OutputGeneration/AsyOutputs.py b/scripting/plugins/OutputGeneration/AsyOutputs.py new file mode 100644 index 0000000..87db33a --- /dev/null +++ b/scripting/plugins/OutputGeneration/AsyOutputs.py @@ -0,0 +1,16 @@ +import pcbnew + +__all__ = ["AsyOutputs"] + +class AsyOutputs(pcbnew.ActionPlugin): + def defaults(self): + self.name = "Generate Assembly Outputs" + self.category = "Output Generation" + self.description = "Generate CSV BOM, Drawings, and add to pdf" + + self.pcbnew_icon_support = hasattr(self, "show_toolbar_button") + self.show_toolbar_button = True + + def Run(self): + # The entry function of the plugin that is executed on user action + print("Hello World - AsyOutputs") \ No newline at end of file diff --git a/scripting/plugins/OutputGeneration/FabOutputs.py b/scripting/plugins/OutputGeneration/FabOutputs.py new file mode 100644 index 0000000..41b8107 --- /dev/null +++ b/scripting/plugins/OutputGeneration/FabOutputs.py @@ -0,0 +1,186 @@ +import pcbnew +import os +from datetime import datetime +from pathlib import Path + +__all__ = ["FabOutputs"] + + +class FabOutputs(pcbnew.ActionPlugin): + def defaults(self): + self.name = "Generate Outputs" + self.category = "Output Generation" + self.description = "Generate Gerbers, BOM, Drawings, etc and add to pdf/zip" + + self.pcbnew_icon_support = hasattr(self, "show_toolbar_button") + self.show_toolbar_button = True + + def Run(self): + # ================ + # General Data + # ================ + + now = datetime.now() + pcb = pcbnew.GetBoard() + path_cwd = Path.cwd() + path_pcb = Path(pcb.GetFileName()) + dir_pcb = path_pcb.parent + dir_fab = dir_pcb / "FabricationOutputs" + dir_asy = dir_pcb / "AssemblyOutputs" + + project_name = path_pcb.stem + part_number = pcb.GetTitleBlock().GetTitle() + rev = str.upper(pcb.GetTitleBlock().GetRevision()) + + suffix = "" + suffix += f"_REV{rev}" + suffix += f"_{now.strftime('%Y%m%d_%H%M%S')}" + + layer_count = pcb.GetDesignSettings().GetCopperLayerCount() + + layer_info = [ + ("Front Paste", "gtp", pcbnew.F_Paste), + ("Front Silkscreen", "gto", pcbnew.F_SilkS), + ("Front Mask", "gts", pcbnew.F_Mask), + ("Front Copper", "gtl", pcbnew.F_Cu), + *[(f'Inner Layer {layer} Copper', f'g{layer}', layer) for layer in range(1, layer_count-1)], + ('Back Copper', 'gbl', pcbnew.B_Cu), + ('Back Mask', 'gbs', pcbnew.B_Mask), + ('Back SilkScreen', 'gbo', pcbnew.B_SilkS), + ('Back Paste', 'gbp', pcbnew.B_Paste), + ('Edges Cuts', 'gm1', pcbnew.Edge_Cuts), + ('Drill', 'drl', None), + ] + + stackup = [ + # [pcbnew layer, file extension, thickness, comment] + [pcbnew.F_Paste, 'gtp', None, "SN63/PB37"], + [pcbnew.F_SilkS, 'gto', None, "White"], + [pcbnew.F_Mask, 'gts', 1, "Explicit mask material"], + [None, None, None, "ENIG"], + [pcbnew.F_Cu, 'gtl', 2.1, "copper roughness"], + [None, None, 10, "Dielectric stuff"], + [1, 'g1', 0.7, "Copper roughness"], + [None, None, 24, "Dielectric stuff"], + [None, None, 12, "Dielectric stuff"], + [2, 'g2', 0.7, "Copper roughness"], + [None, None, 10, "Dielectric stuff"], + [pcbnew.B_Cu, 'gbl', 2.1, "copper roughness"], + [None, None, None, "ENIG"], + [pcbnew.B_Mask, 'gbs', 1, "Explicit mask material"], + [pcbnew.B_SilkS, 'gbo', None, "White"], + [pcbnew.B_Paste, 'gbp', None, "SN63/PB37"], + ] + + board_features = { + "core cap": True, + "castellated": False, + "plated board edge": False, + "copper finish": "ENIG", + "hard gold": False, + "bevelled edge": False, + "soldermask defined": None, # TODO: how do I want to determine this? + } + + + # ================ + # Gerbers + # ================ + + plot_controller = pcbnew.PLOT_CONTROLLER(pcb) + plot_options = plot_controller.GetPlotOptions() + + # Set General Options: + plot_options.SetOutputDirectory(dir_fab) + plot_options.SetPlotFrameRef(False) + plot_options.SetPlotValue(False) + plot_options.SetPlotReference(True) + plot_options.SetPlotInvisibleText(False) + plot_options.SetPlotViaOnMaskLayer(False) + plot_options.SetExcludeEdgeLayer(True) + plot_options.SetUseAuxOrigin(False) + plot_options.SetMirror(False) + plot_options.SetNegative(False) + #plot_options.SetDrillMarksType(PLOT_DRILL_MARKS_TYPE) + #plot_options.SetScale(PLOT_SCALE) + plot_options.SetAutoScale(True) + #plot_options.SetPlotMode(PLOT_MODE) + #plot_options.SetLineWidth(pcbnew.FromMM(PLOT_LINE_WIDTH)) + plot_options.SetUseGerberAttributes(True) + plot_options.SetUseGerberProtelExtensions(False) + plot_options.SetCreateGerberJobFile(False) + plot_options.SetSubtractMaskFromSilk(True) + plot_options.SetIncludeGerberNetlistInfo(False) + + + plot_plan = [ + # ( layer ID, file extension, description) + ( pcbnew.F_Paste, 'gtp', 'Front Paste' ), + ( pcbnew.F_SilkS, 'gto', 'Front SilkScreen' ), + ( pcbnew.F_Mask, 'gts', 'Front Mask' ), + ( pcbnew.F_Cu, 'gtl', 'Front Copper' ), + *[(layer, f'g{layer}', f'Inner Layer {layer} Copper') for layer in range(1, layer_count-1)], + ( pcbnew.B_Cu, 'gbl', 'Back Copper' ), + ( pcbnew.B_Mask, 'gbs', 'Back Mask' ), + ( pcbnew.B_SilkS, 'gbo', 'Back SilkScreen' ), + ( pcbnew.B_Paste, 'gbp', 'Back Paste' ), + ( pcbnew.Edge_Cuts, 'gm1', 'Edges Cuts' ), + ] + + + for layer_info in plot_plan: + plot_controller.SetLayer(layer_info[0]) + plot_controller.OpenPlotfile('', pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) + plot_controller.PlotLayer() + + os.rename(dir_fab / f"{project_name}.gbr", dir_fab / f"{project_name}{suffix}.{layer_info[1]}") + + plot_controller.ClosePlot() + + # ================ + # Drill Files + # ================ + + METRIC = True + ZERO_FORMAT = pcbnew.GENDRILL_WRITER_BASE.DECIMAL_FORMAT + INTEGER_DIGITS = 3 + MANTISSA_DIGITS = 3 + MIRROR_Y_AXIS = False + HEADER = True + OFFSET = pcbnew.wxPoint(0,0) + MERGE_PTH_NPTH = True + DRILL_FILE = True + MAP_FILE = False + REPORTER = None + + drill_writer = pcbnew.EXCELLON_WRITER(pcb) + drill_writer.SetFormat(METRIC, ZERO_FORMAT, INTEGER_DIGITS, MANTISSA_DIGITS) + drill_writer.SetOptions(MIRROR_Y_AXIS, HEADER, OFFSET, MERGE_PTH_NPTH) + drill_writer.CreateDrillandMapFilesSet(str(dir_fab), DRILL_FILE, MAP_FILE, REPORTER) + + os.rename(dir_fab / f"{project_name}.drl", dir_fab / f"{project_name}{suffix}.drl") + + # ================ + # Pick and Place + # ================ + + # TODO + + # ================ + # Fab Drawing + # ================ + + with open(dir_fab / f"README_FABRICATION{suffix}.TXT", "w") as f: + f.write(f"{project_name}-REV{rev}\n") + f.write(f"Layer Order\n") + # for layer in plot_plan: + + + # ================ + # Assembly Drawing + # ================ + + with open(dir_asy / f"README_ASSEMBLY{suffix}.TXT", "w") as f: + f.write(f"{project_name}-REV{rev}\n") + f.write(f"Layer Order\n") + # for layer in plot_plan: \ No newline at end of file diff --git a/scripting/plugins/OutputGeneration/__init__.py b/scripting/plugins/OutputGeneration/__init__.py new file mode 100644 index 0000000..e4058a9 --- /dev/null +++ b/scripting/plugins/OutputGeneration/__init__.py @@ -0,0 +1,5 @@ +from .FabOutputs import FabOutputs +from .AsyOutputs import AsyOutputs + +FabOutputs().register() # Instantiate and register to Pcbnew +AsyOutputs().register() # Instantiate and register to Pcbnew \ No newline at end of file diff --git a/scripting/plugins/OutputGeneration/__pycache__/AsyOutputs.cpython-38.pyc b/scripting/plugins/OutputGeneration/__pycache__/AsyOutputs.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c47e0ab0693d88599cb3879e4c5b02bd332f0f6 GIT binary patch literal 871 zcmZWnKabNe6u0xI7kcd>)CDAl3=9+<&BSmLLX<-~7J7(-L+WDO*w+SJJJ^n@R&3>~ zFx(emW%tU&S772f>Cs3y@-NT!d%ySheZSvDu)hEJ`7sU<`sEMp6~W;-Z1VtsA%+E- zA{NZ?6rUj$vfvw>IQkT9!)eIy1sX=bK@&|}cWl<@l`Si4a(~la;HhD~4+2M1%+NGo z*s}pk$RhYhEC#lY_PRN4S$jEzeG1z=1Yr0pA`k{3W+7l;0a>*5H$VdzGvvu8n|o(m za!oBy$HwsGOsvygkefS=knS`JB{z@$X`fzPrZ3K4AEz%hT@`X}j#DaGN*PP7N=tU- z24xpkv-IE>&7P_*< z7)A!_9!xfOUvVK+`ax;I(#KHzo7os*7niz_R^I}%I>!b)iwoaY@(2Xu$x*O5+8d7G zX)=smLWr+0A+AfvQn5;Sxkt#Cii+k%_rX}-_TX#S0`H`ruowj6hdsebGK^fO>4!TY igbLva$GPv=o4T5{NsFdttpiS;HX%IoQ`!&)o!~EJMBCi} literal 0 HcmV?d00001 diff --git a/scripting/plugins/OutputGeneration/__pycache__/FabOutputs.cpython-38.pyc b/scripting/plugins/OutputGeneration/__pycache__/FabOutputs.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c569440e5ebe3b8be10c260ff6b1ec8af05a9b50 GIT binary patch literal 4366 zcmbtY&2JmW72hu|DUyjjD6u6wj^j9S(ohnqu#iZVWD-Ycuw8P7)Y{8k zW_M}Hi{;5V6a|X5hn`Xa(lP%_i{1yl6)50Kd&;3{5B<$7Nh=?>axrgz^XBW#dvD&G zne$Xz?P`Y_ zu-1_e6T1>g5bZ0}sPssGrXD7VT$k4M=a@;VtjjD#%zy?~mjY`CW^lyPC9_%W2fcpa zw|K9MKLwSKQ2bR8D)H416(SSmE9p=rDqrbPBMH8O$E9w`Afq40D#|vB|2hbfBgugH zpfXWGl>n4z&o~FufF_8X%2F+? z+i|_8EJLW@@~mEf)mZY#^vxjf*j%sGbm*~RwOq&W`@Np)1zrLhE@B!rJGHUI>dA~H*B|M+ME87>Cw%{R?8%tcQ@|e-yAOCbT)f-zhgQ6X1vuGJKcO? zqmABE7?HNkz8(17j|7oqoj*!e4(BfP9rgR3UGf+-ha&9qYnUyN&g64xAP35sinkJI zX9>L3K#PolpG|Y1d&&yfsVI=cM{yxAcbBN=h9gkVS;eRqjcmmWbrDDWadtW1ez0jX83dBTJGb6)2Bp+A5hKX`or449Nn` z0Zo!Ap!v4i*2px;eI*5#$V`+aGfUDlWe3udSu%$n3+OvfE&(k9Es#Z^C7>m;473b% znXCX^23l?Fe^dvPsLhZRj@6Zp20TmBz*hyHBUpi4>uBKcCoj13WQx2*ULJB^A=iOs z$QpT-yf);$E_i&zxu|yUzM=Z-SSq6rTo!nrG z+#omcgz zLmk3XfVke^A3$7d@B<*OGgu!8RwuA|I{}N&MzcH87rz`#LQglNNpgD`J_{Y?&Nc|| zy9wSK;HiRl>s*4Qx6j^+^eFYUMBX~ZDTr~DLH!PT&n!#uX>CP1M}Ypl`X!(14j)Hu z47gXm{pjvsp1eJ{gt9>*g1z1$x5@2uWw4C;Wt0`PtrBT)1#S0)Ew4sb&)$vZ zqWS1jv~Z4)kNW*+FILEybIFa{eiT1Pt{n;;QdG^?}#1T z<2>^2Gv#-$4z5Ml&K`(;-sfkRymzVz-GEEp=jb!(uJjA3COwoeLy|oBe`XMI|APvf zMfCCz8hOMWMt(M3@O|2C+D}IeiD^cy_$iZ(aB}VQweA`*);?a_U#o|ilIJ=>{=oDD z%G6HK3v)52ZrP6!XDM|!+YQq(d*AdQbA}&gW5%}I>rs!h?C%9lo(Xw~ucP?aK{`?- zeX%+~MvM@|h>!Wj_splD-zD?I`Q?tt5Z@?F*|^0L zHg6W3m`q{;mVRJce$aBey$?6|syxB!k|KpKUx@IvzO(T_+EAQOdJlMK(k0m}kvH}_|6i<4#)v|(o7b*q`sArir(~6byZs#w5=0EA9FxL|L z&Ug=n}m~1 z`UC^%u;Z)`CiTRwkX|hZ^Ih<nwFxu1AfK|++VgLuOD+D518F?r)Tzk`L^1`KsLTPqfJ_KQZTuvIH>7aHYi z1ucz-4JIFl+D&n$(qT6C)~bhnrVpowV+!?paer&?^Ysrrp<~r?kC`4{g;;8r23uU4 z9$$^Atz*J6;FTrI@GpKVsCzErL47aGQH zv9<;6Pw>{bv*P+phx)juO>En)Pk9@g-z`>lYURB>yy%we%s9cgT;Txk?x1!JeYTW-|Z^nRhzDA((S5o2<{ zT&q=U#^*-iVY$xqj}dlYF}+$U)r$=_wO_357L9|($3_K&rDG$N%6mnY+Aka!F{%|0 zsx_F6WeLwUhR`ZPTKk8YQbiV=g_ixlfk=sz%%3bii11c)pjkzer{sAhtEOe~{8vdV z#7I!(TRoRWzbtCJym(>`TK=V7QsfKIzxC;~oEpt{VMJQRGpZ+s=s${nVZCql=@gd- z(%n*0x&}G5;gcO9B`xRh%q!QkOY(v|pW-x}`hM!KtS4B?5dL8pENvKFm-KB4oHdLu z`=-r3$1uDpsKxs&Cn9aUAR>YAi^T+rNFY#IYCYxM<(*rch+v=Oo@-mpIJ_qf!-PGs jN}b$2dO)AI%>`2{b4-Ypeh zpkhye#7H|kGtz4IcCjcx@c8zA_bU4%ng7VdoXUh_Aq^TWbg%(TIUup|UZ)qskk*O+|4MLL3xOtq>nVN)x;p?{2_r=WK`5Ms#<7 z=6(#KcT2@zpkkb`T#CbypU3g|&G^lHI69gU9525A__U7*`589jk>KVzPWuo62vA9i zVWkCqMIeIsf#pg@WUC`1F(!L7T0!a&%{)QzjZ3RZC^ zHrni&;yckj8XaoI^qRS?U`-#DaRuyb%N?s711)S8`y|}*>4C)G{70?TCH09Fa(zim zih+Nx@~z&9d}V|JuJVP{6_>f)awGCDb;TinvN%4@|E8uk`4HCTR}a75EP3T>trpGR zry$n6mCjCr8dC&9r}%Yuu1FRKpa07^$9oQiJf{>(i{eGg?%r!5rDh+sk-#1^ht(Jo z%&4CP-kxPeo&W#< literal 0 HcmV?d00001 diff --git a/scripting/plugins/TestPlugin/TestPlugin/__pycache__/__init__.cpython-38.pyc b/scripting/plugins/TestPlugin/TestPlugin/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..faf4ed714c9054b8a49a7939d7655b57d16f20cc GIT binary patch literal 268 zcmWIL<>g`kf|p0mCju!W7J)$^4QLs7RCX7FS4WaY;ZRdT_0jvu|C2!WM+JPW?p7Ve7s&kz{ FBLKrgNo)WB literal 0 HcmV?d00001 diff --git a/scripting/plugins/TestPlugin/TestPlugin/icon.png b/scripting/plugins/TestPlugin/TestPlugin/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..37907aa55ae5e6857a76692cc0f23b90c9ec8554 GIT binary patch literal 761 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&bp`l@xc>kDAIKaGK;Amz1JE71 zB|(0{42;YyZ0wu@GD^y-YF2g*PEpx;`GpOQO>ONHrcIwQbJqM7=dWJ7e(UbXPd|Sz zD*kN6z`*#?)5S5Q;?~<6H_Ms~L|PMNUf7(!+O&1+*5>Db z&HnHGgl!VbVFMl@`h4r()wLUEH?L@z%sSJ$pUdK((eG|!)DUT?XP1ciww0m!Iy1jR zzTK;r43}QEUl-kTc`lbi?J{%y13eXv+y^%K8^<%;?PgrPkKw@GMq`D!6L=1A#4x_z z$B`gz!BqD?o@)cw9fsMTy&26Kg%hgl3=b$3F!HD`VO_x`!|-yQK6?nu*@iIybO!iGiz|ZVoZzY3=p}(q*bfSU~9#ANwbyd!U@KNm#-QB zy=!2<@vEz0Z3An>?^zAK4a_%wuWH!Zz-UnGe_&2UqwImNneSL7g!MNt-LUK3%aD1D zyKhy)WxLzwgZ59~tf*aK@yDe8*S-@s|6Tb0b%OYw5XSYt{#rHuR;lG}T%#}U@jIw- zkG^om7geUY`}RAmey@Gu^>0p--*!xQ>#7^e>NQW?{!;w4ZnyObrZ2ZS4t=@Hy71S! zrh?k->W2I`$^~2An*ZmHd{8%8p=N)az~cDtGEV}3{gF+X_-l?r+m?w9vL;fulTf3KFm^j!W|<>hx_P^29;@YyE6oJDNM T_L{4Hpt$mM^>bP0l+XkK(L5IK literal 0 HcmV?d00001 diff --git a/scripting/plugins/TestPlugin/__init__.py b/scripting/plugins/TestPlugin/__init__.py new file mode 100644 index 0000000..019288b --- /dev/null +++ b/scripting/plugins/TestPlugin/__init__.py @@ -0,0 +1 @@ +from .TestPlugin import plugin \ No newline at end of file diff --git a/scripting/plugins/TestPlugin/__pycache__/__init__.cpython-38.pyc b/scripting/plugins/TestPlugin/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d7af294360be8ab7732a3eb04a675fe68443f6c GIT binary patch literal 210 zcmWIL<>g`kf+I)IC&&Tm#~=RdT_0j@u|C33{rLFIyv&mLc)fzkTO2mI Q`6;D2sdgZDd