commit 9699d47021012a874bddaecc21f41d92f84ed337 Author: Martin Obermaier Date: Fri Aug 7 17:10:25 2020 +0200 Initial Commit diff --git a/BP.ger b/BP.ger new file mode 100644 index 0000000..8c57848 --- /dev/null +++ b/BP.ger @@ -0,0 +1,79 @@ +G04 NI AWR Design Environment 14.04 * +G04 RS274-X Output Version 0.1 * +%FSLAX36Y36*% +%MOMM*% +%SFA1B1*% +%ADD10C,.010*% + +G36* +X0Y5000D02* +X145000D01* +Y575000D01* +X0D01* +Y5000D01* +G37* +G36* +X145000Y5000D02* +X1815000D01* +Y135000D01* +X145000D01* +Y5000D01* +G37* +G36* +X145000Y-250000D02* +X1815000D01* +Y-120000D01* +X145000D01* +Y-250000D01* +G37* +G36* +X1815000Y-475000D02* +X3405000D01* +Y-115000D01* +X1815000D01* +Y-475000D01* +G37* +G36* +X1815000Y-960000D02* +X3405000D01* +Y-600000D01* +X1815000D01* +Y-960000D01* +G37* +G36* +X3405000Y-960000D02* +X4995000D01* +Y-600000D01* +X3405000D01* +Y-960000D01* +G37* +G36* +X3405000Y-1445000D02* +X4995000D01* +Y-1085000D01* +X3405000D01* +Y-1445000D01* +G37* +G36* +X4995000Y-1440000D02* +X6665000D01* +Y-1310000D01* +X4995000D01* +Y-1440000D01* +G37* +G36* +X4995000Y-1695000D02* +X6665000D01* +Y-1565000D01* +X4995000D01* +Y-1695000D01* +G37* +G36* +X6665000Y-2135000D02* +X6810000D01* +Y-1565000D01* +X6665000D01* +Y-2135000D01* +G37* +M02* +G04 End of Data * diff --git a/BP.kicad_mod b/BP.kicad_mod new file mode 100644 index 0000000..3639bb3 --- /dev/null +++ b/BP.kicad_mod @@ -0,0 +1,18 @@ +(module Default:BP (layer F.Cu) (tedit 5EF5C08B) +(fp_text reference REF** (at 0.0 5.0) (layer F.SilkS) hide +(effects (font (size 1 1) (thickness 0.15))) +) +(fp_text value BP (at 0.0 -5.0) (layer F.Fab) hide +(effects (font (size 1 1) (thickness 0.15))) +) + (fp_poly (pts (xy -3.405 0.785) (xy -3.26 0.785) (xy -3.26 1.355) (xy -3.405 1.355) (xy -3.405 0.785)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy -3.26 0.785) (xy -1.59 0.785) (xy -1.59 0.915) (xy -3.26 0.915) (xy -3.26 0.785)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy -3.26 0.53) (xy -1.59 0.53) (xy -1.59 0.66) (xy -3.26 0.66) (xy -3.26 0.53)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy -1.59 0.305) (xy 0.0 0.305) (xy 0.0 0.665) (xy -1.59 0.665) (xy -1.59 0.305)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy -1.59 -0.18) (xy 0.0 -0.18) (xy 0.0 0.18) (xy -1.59 0.18) (xy -1.59 -0.18)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy 0.0 -0.18) (xy 1.59 -0.18) (xy 1.59 0.18) (xy 0.0 0.18) (xy 0.0 -0.18)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy 0.0 -0.665) (xy 1.59 -0.665) (xy 1.59 -0.305) (xy 0.0 -0.305) (xy 0.0 -0.665)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy 1.59 -0.66) (xy 3.26 -0.66) (xy 3.26 -0.53) (xy 1.59 -0.53) (xy 1.59 -0.66)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy 1.59 -0.915) (xy 3.26 -0.915) (xy 3.26 -0.785) (xy 1.59 -0.785) (xy 1.59 -0.915)) (layer F.Cu) (width 0.001)) + (fp_poly (pts (xy 3.26 -1.355) (xy 3.405 -1.355) (xy 3.405 -0.785) (xy 3.26 -0.785) (xy 3.26 -1.355)) (layer F.Cu) (width 0.001)) +) \ No newline at end of file diff --git a/Ger2KiCad.py b/Ger2KiCad.py new file mode 100644 index 0000000..0ccdf76 --- /dev/null +++ b/Ger2KiCad.py @@ -0,0 +1,258 @@ +#################################Ger2KiCad#################################### +#This script allows to transform gerber files into kicad_mod files # +############################################################################## +#Author: E-Mail: # +#Martin Obermaier Martin.Obermaier@posteo.de# +############################################################################## + + +############################################################################## +# Imports # +############################################################################## +import gerber +import re +import numpy as np +############################################################################## + # Define Classes # +############################################################################## + +class Polygon: + + def __init__(self): + self.vertices = [] + + def add_vertex(self,x,y): + self.vertices.append([x,y]) + + def get_vertices(self): + return self.vertices + + def remove_vertex(self,x,y): + self.vertices.remove([x,y]) + + +############################################################################## +# Variables and Constants # +############################################################################## + + +# Regex Filters: + +MODE = r"(Mode):\s([a-z]{1,})" +SCALE = r"(Scale) Factor:\sX:\s(\d+\.\d+|\d+)\sY:\s(\d+\.\d+|\d+)" +COOR = r"(Coordinate Statement):\s([X,Y]):\s(-?\d+\.\d+|\d+)\s(?:(Y):\s"+\ + "(-?\d+\.\d+|\d+))?.{1,}Lights\s(On|Off)" +RMStmtStart = r"(RegionModeStmt) type=RegionMode units=(metric|inch) mode=(on)" +RMStmtStop = r"(RegionModeStmt) type=RegionMode units=(metric|inch) mode=(off)" +EOF = r"EOF Statement" + + +Scale = [0.0,0.0] +offset = [0.0, 0.0] + +mm = 1.0 +inch = 25.4 + +mode = "" + +############################################################################## +# Functions # +############################################################################## + + +def setMode(Stmt): + global mode + mode = re.search(MODE,Stmt).group(2) + print(Stmt) + +def setScale(Stmt): + global Scale + Scale[0] = np.float(re.search(SCALE,Stmt).group(2)); + Scale[1] = np.float(re.search(SCALE,Stmt).group(3)); + print(Stmt) + print(Scale) + +def new_Polygon(Stmts): + LastStmt = 0; + unit = "" + poly = Polygon() + LastCoor = [0.0,0.0] + #print(Stmts) + for cnt in range(len(Stmts)): + res = re.search(RMStmtStart,Stmts[cnt]) + if res != None: + unit = res.group(2) + LastStmt = cnt+1 + break + + if unit == "metric": + factor = mm + else: + factor = inch + + for cnt in range(LastStmt,len(Stmts)): + coor = [] + res = re.search(COOR,Stmts[cnt]) + if res.group(6) == "Off": + x = np.float(res.group(3))*factor + y = np.float(res.group(5))*factor + coor = [x,y] + elif res.group(6) =="On": + if res.group(2) != None and res.group(4) != None: + x = np.float(res.group(3))*factor + y = np.float(res.group(5))*factor + else: + if res.group(2) == "X": + x = np.float(res.group(3))*factor + y = LastCoor[1] + else: + y = np.float(res.group(3))*factor + x = LastCoor[0] + coor = [x,y] + coor = np.round(coor,4) + poly.add_vertex(coor[0],coor[1]) + LastCoor = coor + + return poly + +def find_center(polygons): + xmax = np.array([], dtype=np.float64) + xmin = np.array([], dtype=np.float64) + + ymax = np.array([], dtype=np.float64) + ymin = np.array([], dtype=np.float64) + + for pol in polygons: + poly_coor = np.asarray(pol.get_vertices()) + + xmax = np.append(xmax,np.amax(poly_coor[::,0])) + xmin = np.append(xmin,np.amin(poly_coor[::,0])) + + ymax = np.append(ymax,np.amax(poly_coor[::,1])) + ymin = np.append(ymin,np.amin(poly_coor[::,1])) + + + + + x_c = (np.amax(xmax)+np.amin(xmin))/2 + y_c = (np.amax(ymax)+np.amin(ymin))/2 + return x_c,y_c + +def readGerber(file): + top_copper = gerber.read(file).statements + polygons =[] + LastStmtIndex = 0; + + #Find mode statement + for cnt in range(len(top_copper)): + Stmt = str(top_copper[cnt]) + if re.search(MODE,Stmt) != None: + setMode(Stmt) + LaststmtIndex = cnt; + break + + + if mode == "": + raise Exception("FileFormat","No Unit mode Statement found") + + #Find scale factors + for cnt in range(LastStmtIndex,len(top_copper)): + Stmt = str(top_copper[cnt]) + if re.search(SCALE,Stmt) != None: + setScale(Stmt) + LaststmtIndex = cnt; + break + + #Find polygons factors + + + for cnt in range(LastStmtIndex,len(top_copper)): + Stmt = str(top_copper[cnt]) + if re.search(RMStmtStart ,Stmt) != None: + PolyStmt = [] + i = 0 + while cnt+i < len(top_copper): + Stmt = str(top_copper[cnt+i]) + if re.search(RMStmtStop ,Stmt) != None: + LaststmtIndex = cnt+i; + poly = new_Polygon(PolyStmt) + polygons.append(poly) + break + else: + PolyStmt.append(Stmt) + i+=1 + + return polygons + +def create_kicad_poly(polygons,x_c,y_c,layer="F.Cu"): + + polygon_str = "" + for pol in polygons: + + poly_frame =" (fp_poly (pts" + poly_end =") (layer "+ layer +") (width 0.001))" + + new_poly = poly_frame + + flat_list = pol.get_vertices() + for cnt in range(len(flat_list)): + cor = flat_list[cnt] + cor_x = np.round(float(cor[0])-x_c,4) + cor_y = np.round(float(cor[1])-y_c,4) + a="(xy "+str(cor_x)+" "+str(cor_y)+")" + new_poly+=" "+a + + new_poly_com=new_poly+poly_end + polygon_str += new_poly_com + "\n" + return polygon_str + + +def create_kicad_mod(name,polygons,libary="Default",tedit="5EF5C08B"): + + kicad_file = "" + + header = "(module "+libary+":"+name+" (layer F.Cu) (tedit "+tedit+\ + ")"+"\n"+ \ + "(fp_text reference REF** (at 0.0 5.0) (layer F.SilkS) hide"+\ + "\n"+ \ + "(effects (font (size 1 1) (thickness 0.15)))"+"\n"+ \ + ")"+"\n"+ \ + "(fp_text value "+name+" (at 0.0 -5.0) (layer F.Fab) hide"+\ + "\n"+ \ + "(effects (font (size 1 1) (thickness 0.15)))"+"\n"+\ + ")"+"\n" + + footer = ")" + kicad_file += header; + for poly in polygons: + kicad_file += poly + + kicad_file += footer + + return kicad_file + + +############################################################################## +# Main # +############################################################################## + + + + +poly=readGerber('BP.ger') +x_c,y_c = find_center(poly) +kicad_poly = create_kicad_poly(poly,x_c,y_c,layer="F.Cu") +output=create_kicad_mod("BP",kicad_poly) + +f= open("BP.kicad_mod","w+") +f.write(output) +f.close() + + +exit(); +############################################################################## +# END # +############################################################################## + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..2d384b0 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Ger2KiCad + +A simple python script to convert Gerber files (RS274X) to .kicad_mod files that can be easily imported by KiCad. It is possible to read multiple files and specify the import layer (F.Cu, In1.Cu, ..., B.Cu). + +This script was mainly designed to import RF structures in KiCad, but should handle all polygon based designs (Uses G36/G37 codes of the RS274X standard). + +This script uses the [pcb-tools](https://github.com/curtacircuitos/pcb-tools) package.