diff --git a/python/frep.py b/python/frep.py index 0d03d6d87b9972186f0855d2d0aabb184fc85a77..0ac053c6ce1b82cb3febed5ed4cd9cffa1c2d256 100755 --- a/python/frep.py +++ b/python/frep.py @@ -5,11 +5,9 @@ # # usage: # pcb.py | frep.py [dpi [filename]] -# with: -# https://gitlab.cba.mit.edu/pub/libraries/blob/master/python/pcb.py # -# Neil Gershenfeld 10/8/18 -# (c) Massachusetts Institute of Technology 2018 +# Neil Gershenfeld 9/30/19 +# (c) Massachusetts Institute of Technology 2019 # # This work may be reproduced, modified, distributed, # performed, and displayed for any purpose, but must @@ -35,10 +33,6 @@ frep = json.load(sys.stdin) # # check arguments # - -if (frep['zmin'] != frep['zmax']): - print('> 2D not (yet) supported') - sys.exit() if (frep['type'] != 'RGB'): print('types other than RGB not (yet) supported') sys.exit() @@ -61,7 +55,7 @@ elif (len(sys.argv) == 3): # evaluate # -print('evaluating ...') +print('evaluating') xmin = frep['xmin'] xmax = frep['xmax'] ymin = frep['ymin'] @@ -72,8 +66,19 @@ x = arange(xmin,xmax,delta) y = flip(arange(ymin,ymax,delta),0) X = outer(ones(y.size),x) Y = outer(y,ones(x.size)) -Z = frep['zmin'] -f = eval(frep['function']) +if (len(frep['layers']) == 1): + Z = frep['layers'][0] + print " z =",Z + f = eval(frep['function']).astype(uint32) +else: + f = zeros((y.size,x.size),dtype=uint32) + zmin = min(frep['layers']) + zmax = max(frep['layers']) + for Z in frep['layers']: + print " z =",Z + i = int(255*(Z-zmin)/(zmax-zmin)) | (255 << 8) | (255 << 16) + flayer = i & (eval(frep['function'])).astype(uint32) + f = f + flayer # # construct image diff --git a/python/pcb.png b/python/pcb.png index 813108f94ac1ac0a99205740865185a6bf7a277e..a6c3b584b7c8da9dcd489bd414a42d16089e3472 100644 Binary files a/python/pcb.png and b/python/pcb.png differ diff --git a/python/pcb.py b/python/pcb.py index d27722692007e27015df1b4349f5e530d2a8dbda..f56a30c1a47d4b279cf48d867c12cdc4028b0610 100755 --- a/python/pcb.py +++ b/python/pcb.py @@ -5,11 +5,9 @@ # # usage: # pcb.py | frep.py [dpi [filename]] -# with: -# https://gitlab.cba.mit.edu/pub/libraries/blob/master/python/frep.py # -# Neil Gershenfeld 10/8/18 -# (c) Massachusetts Institute of Technology 2018 +# Neil Gershenfeld 9/30/19 +# (c) Massachusetts Institute of Technology 2019 # # This work may be reproduced, modified, distributed, # performed, and displayed for any purpose, but must @@ -22,12 +20,17 @@ # uncomment for desired output: # -output = "traces, labels, and exterior" -#output = "traces and exterior" +#output = "top, labels, and exterior" +#output = "top, bottom, labels, and exterior" +output = "top, bottom, labels, holes, and exterior" +#output = "top traces" +#output = "top traces and exterior" +#output = "bottom traces reversed" +#output = "bottom traces reversed and exterior" +#output = "holes" #output = "interior" +#output = "holes and interior" #output = "exterior" -#output = "traces" -#output = "holes" #output = "solder mask" # @@ -951,6 +954,7 @@ class PCB: self.interior = rectangle(x0,x0+width,y0,y0+height) self.exterior = subtract(true,rectangle(x0,x0+width,y0,y0+height)) self.mask = false + self.holes = false def add(self,part): self.board = add(self.board,part) self.mask = add(self.mask,move(part,-mask,mask)) @@ -990,6 +994,8 @@ class part: deg_angle = angle angle = math.pi*angle/180 self.shape = translate(self.shape,x,y,z) + if hasattr(self,'holes'): + self.holes = translate(self.holes,x,y,z) for i in range(len(self.pad)): xnew = math.cos(angle)*self.pad[i].x - math.sin(angle)*self.pad[i].y ynew = math.sin(angle)*self.pad[i].x + math.cos(angle)*self.pad[i].y @@ -1008,12 +1014,15 @@ class part: else: pcb.labels = add(pcb.labels,text(self.labels[i].text,self.labels[i].x,self.labels[i].y,self.labels[i].z,self.labels[i].line,color=Red,angle=(deg_angle-self.labels[i].angle-180)).shape) pcb = pcb.add(self.shape) - return pcb - def layer(self,pcb,z): - pcb = pcb.add(translate(self.shape,0,0,z)) + if hasattr(self,'holes'): + pcb.holes = add(pcb.holes,self.holes) return pcb -def rightwire(pcb,width,*points): +def wire(pcb,width,*points): + x0 = points[0].x + y0 = points[0].y + z0 = points[0].z + pcb.board = add(pcb.board,cylinder(x0,y0,z0,z0,width/2)) for i in range(1,len(points)): x0 = points[i-1].x y0 = points[i-1].y @@ -1021,21 +1030,11 @@ def rightwire(pcb,width,*points): x1 = points[i].x y1 = points[i].y z1 = points[i].z - if (x0 < x1): - pcb.board = add(pcb.board,cube(x0-width/2,x1+width/2,y0-width/2,y0+width/2,z0,z0)) - elif (x1 < x0): - pcb.board = add(pcb.board,cube(x1-width/2,x0+width/2,y0-width/2,y0+width/2,z0,z0)) - if (y0 < y1): - pcb.board = add(pcb.board,cube(x1-width/2,x1+width/2,y0-width/2,y1+width/2,z0,z0)) - elif (y1 < y0): - pcb.board = add(pcb.board,cube(x1-width/2,x1+width/2,y1-width/2,y0+width/2,z0,z0)) + pcb.board = add(pcb.board,line(x0,y0,x1,y1,z1,width)) + pcb.board = add(pcb.board,cylinder(x1,y1,z1,z1,width/2)) return pcb -def wire(pcb,width,*points): - x0 = points[0].x - y0 = points[0].y - z0 = points[0].z - pcb.board = add(pcb.board,cylinder(x0,y0,z0,z0,width/2)) +def wirer(pcb,width,*points): for i in range(1,len(points)): x0 = points[i-1].x y0 = points[i-1].y @@ -1043,14 +1042,33 @@ def wire(pcb,width,*points): x1 = points[i].x y1 = points[i].y z1 = points[i].z - pcb.board = add(pcb.board,line(x0,y0,x1,y1,z1,width)) - pcb.board = add(pcb.board,cylinder(x1,y1,z1,z1,width/2)) + if (x0 < x1): + pcb.board = add(pcb.board,cube(x0-width/2,x1+width/2,y0-width/2,y0+width/2,z0,z0)) + elif (x1 < x0): + pcb.board = add(pcb.board,cube(x1-width/2,x0+width/2,y0-width/2,y0+width/2,z0,z0)) + if (y0 < y1): + pcb.board = add(pcb.board,cube(x1-width/2,x1+width/2,y0-width/2,y1+width/2,z0,z0)) + elif (y1 < y0): + pcb.board = add(pcb.board,cube(x1-width/2,x1+width/2,y1-width/2,y0+width/2,z0,z0)) return pcb # # PCB library # +class via(part): + # + # via + # + def __init__(self,zb,zt,rv,rp,value=''): + self.value = value + self.labels = [] + self.pad = [point(0,0,0)] + self.shape = cylinder(0,0,zb,zt,rp) + self.holes = cylinder(0,0,zb,zt,rv) + self.pad.append(point(0,0,zt)) + self.pad.append(point(0,0,zb)) + # # discretes # @@ -4984,153 +5002,219 @@ class fab(part): # define board # -w = .015 -width = 1 -height = .93 -mask = .004 -x = 1 -y = 1 -z = -.005 -d = .06 +width = 1.02 # board width +height = .87 # board height +x = 1 # x origin +y = 1 # y origin +zt = 0 # top z +zb = -0.06 # bottom z +w = .015 # wire width +rv = 0.016 # via size +rp = 0.03 # pad size +mask = .004 # solder mask size pcb = PCB(x,y,width,height,mask) IC1 = ATtiny44_SOICN('IC1\nt44') -pcb = IC1.add(pcb,x+.47,y+.59,z) +pcb = IC1.add(pcb,x+.49,y+.56) + +VIC1 = via(zb,zt,rv,rp) +pcb = VIC1.add(pcb,IC1.pad[14].x+.08,IC1.pad[14].y+.02) + +pcb = wire(pcb,w, + VIC1.pad[1], + IC1.pad[14]) J1 = header_ISP('J1\nISP') -pcb = J1.add(pcb,IC1.x+.05,IC1.pad[7].y-.22,z,angle=90) +pcb = J1.add(pcb,IC1.x+.05,IC1.pad[7].y-.22,angle=90) pcb = wire(pcb,w, IC1.pad[8], - point(J1.pad[1].x,IC1.pad[8].y,z), + point(J1.pad[1].x,IC1.pad[8].y), J1.pad[1]) pcb = wire(pcb,w, IC1.pad[9], - point(J1.pad[3].x,IC1.pad[9].y,z), + point(J1.pad[3].x,IC1.pad[9].y), J1.pad[3]) pcb = wire(pcb,w, IC1.pad[7], - point(IC1.pad[7].x,J1.y+.02,z), - point(IC1.pad[7].x+.04,J1.y-.02,z), - point(J1.pad[4].x,J1.y-.02,z), + point(IC1.pad[7].x,J1.y+.02), + point(IC1.pad[7].x+.04,J1.y-.02), + point(J1.pad[4].x,J1.y-.02), J1.pad[4]) pcb = wire(pcb,w, IC1.pad[4], - point(J1.pad[5].x,IC1.pad[4].y,z), + point(J1.pad[5].x,IC1.pad[4].y), J1.pad[5]) +VJ12 = via(zb,zt,rv,rp) +pcb = VJ12.add(pcb,J1.pad[2].x+.075,J1.pad[2].y) + pcb = wire(pcb,w, - IC1.pad[14], - point(J1.x-.01,IC1.pad[14].y,z), - point(J1.x-.05,IC1.pad[14].y-.04,z), - point(J1.x-.05,J1.y+.02,z), - point(J1.x+.05,J1.y+.02,z), - point(J1.x+.05,J1.pad[2].y-.08,z), - point(J1.pad[6].x,J1.pad[2].y-.08,z), - J1.pad[6]) + VJ12.pad[1], + J1.pad[2]) -J2 = header_FTDI('J2 FTDI') -pcb = J2.add(pcb,x+width-.22,IC1.y-.0,z,angle=0) +VJ16 = via(zb,zt,rv,rp) +pcb = VJ16.add(pcb,J1.pad[6].x-.075,J1.pad[6].y) pcb = wire(pcb,w, - J1.pad[2], - point(J2.x,J1.pad[2].y,z), - point(J2.x+.08,J1.pad[2].y+.08,z), - point(J2.x+.08,J2.pad[3].y,z), - J2.pad[3]) + VJ16.pad[1], + J1.pad[6]) + +pcb = wire(pcb,w, + VJ16.pad[2], + VIC1.pad[2]) + +J2 = header_FTDI('J2 FTDI') +pcb = J2.add(pcb,x+width-.22,IC1.y-.0,angle=0) pcb = wire(pcb,w, IC1.pad[13], - point(IC1.pad[13].x+.105,IC1.pad[13].y,z), - point(IC1.pad[13].x+.105,J2.pad[4].y,z), + point(IC1.pad[13].x+.105,IC1.pad[13].y), + point(IC1.pad[13].x+.105,J2.pad[4].y), J2.pad[4]) pcb = wire(pcb,w, IC1.pad[12], - point(IC1.pad[12].x+.07,IC1.pad[12].y,z), - point(IC1.pad[12].x+.07,J2.pad[5].y+.04,z), - point(IC1.pad[12].x+.11,J2.pad[5].y,z), + point(IC1.pad[12].x+.07,IC1.pad[12].y), + point(IC1.pad[12].x+.07,J2.pad[5].y+.04), + point(IC1.pad[12].x+.11,J2.pad[5].y), J2.pad[5]) +VJ2 = via(zb,zt,rv,rp) +pcb = VJ2.add(pcb,J2.pad[3].x+.1,J2.pad[3].y) + +pcb = wire(pcb,w, + VJ2.pad[1], + J2.pad[3]) + +pcb = wire(pcb,w, + VJ12.pad[2], + VJ2.pad[2]) + XTAL1 = XTAL_EFOBM('XTAL1\n20 MHz') -pcb = XTAL1.add(pcb,IC1.pad[4].x-.2,IC1.pad[13].y+.003,z,angle=-90) +pcb = XTAL1.add(pcb,IC1.pad[4].x-.2,IC1.pad[13].y+.003,angle=-90) pcb = wire(pcb,w, IC1.pad[2], - point(XTAL1.x+.12,IC1.pad[2].y,z), - point(XTAL1.x+.12,XTAL1.pad[1].y,z), + point(XTAL1.x+.12,IC1.pad[2].y), + point(XTAL1.x+.12,XTAL1.pad[1].y), XTAL1.pad[1]) -pcb = wire(pcb,w, - J1.pad[6], - point(J1.pad[6].x,J1.pad[6].y-.08,z), - point(XTAL1.x-.04,J1.pad[6].y-.08,z), - point(XTAL1.x-.12,J1.pad[6].y,z), - point(XTAL1.x-.12,XTAL1.pad[2].y,z), - XTAL1.pad[2]) - pcb = wire(pcb,w, IC1.pad[3], XTAL1.pad[3]) +VXTAL = via(zb,zt,rv,rp) +pcb = VXTAL.add(pcb,XTAL1.x-.12,XTAL1.y) + +pcb = wire(pcb,w, + XTAL1.pad[2], + VXTAL.pad[1]) + +pcb = wire(pcb,w, + VJ16.pad[2], + VXTAL.pad[2]) + R1 = R_1206('R1\n10k'); -pcb = R1.add(pcb,IC1.pad[1].x,IC1.pad[1].y+.1,z) +pcb = R1.add(pcb,IC1.pad[1].x,IC1.pad[1].y+.1) pcb = wire(pcb,w, R1.pad[1], IC1.pad[1]) pcb = wire(pcb,w, - J2.pad[3], - point(J2.pad[3].x+.08,J2.pad[3].y,z), - point(J2.pad[3].x+.08,R1.y+.06,z), - point(R1.pad[1].x,R1.y+.06,z), + R1.pad[2], + point(J1.pad[5].x,R1.y), + J1.pad[5]) + +VR1 = via(zb,zt,rv,rp) +pcb = VR1.add(pcb,R1.pad[1].x-.08,R1.y) + +pcb = wire(pcb,w, + VR1.pad[1], R1.pad[1]) pcb = wire(pcb,w, - R1.pad[2], - point(J1.pad[5].x,R1.y,z), - J1.pad[5]) + VJ2.pad[2], + point(VJ2.x,VR1.y,zb), + VR1.pad[2]) C1 = C_1206('C1\n1uF'); -pcb = C1.add(pcb,IC1.pad[14].x,R1.y,z) +pcb = C1.add(pcb,IC1.pad[14].x,R1.y) pcb = wire(pcb,w, - IC1.pad[14], + J2.pad[1], C1.pad[2]) pcb = wire(pcb,w, - C1.pad[1], - point(C1.pad[1].x,C1.y+.06,z)) + C1.pad[2], + VIC1.pad[1]) + +VC1 = via(zb,zt,rv,rp) +pcb = VC1.add(pcb,C1.pad[1].x-.025,C1.y-.06) pcb = wire(pcb,w, - J2.pad[1], - C1.pad[2]) + VC1.pad[1], + C1.pad[1]) + +pcb = wire(pcb,w, + VR1.pad[2], + point(VC1.x,VR1.y,zb), + VC1.pad[2]) # # select output # outputs = {} -if (output == "traces, labels, and exterior"): - outputs["function"] = add(add(color(Tan,pcb.board),pcb.labels),color(White,pcb.exterior)) -elif (output == "traces and exterior"): +if (output == "top, labels, and exterior"): + outputs["function"] = add(add(color(Tan,pcb.board),pcb.labels), + color(White,pcb.exterior)) + outputs["layers"] = [zt] +elif (output == "top, bottom, labels, and exterior"): + outputs["function"] = add(add(color(Tan,pcb.board),pcb.labels), + color(White,pcb.exterior)) + outputs["layers"] = [zb,zt] +elif (output == "top, bottom, labels, holes, and exterior"): + outputs["function"] = add(add(color(Tan, + subtract(pcb.board,pcb.holes)),pcb.labels), + color(White,pcb.exterior)) + outputs["layers"] = [zb,zt] +elif (output == "top traces"): + outputs["function"] = color(White,pcb.board) + outputs["layers"] = [zt] +elif (output == "top traces and exterior"): outputs["function"] = color(White,add(pcb.board,pcb.exterior)) + outputs["layers"] = [zt] +elif (output == "bottom traces reversed"): + outputs["function"] = color(White, + reflect_x(pcb.board,2*x+width)) + outputs["layers"] = [zb] +elif (output == "bottom traces reversed and exterior"): + outputs["function"] = color(White, + reflect_x(add(pcb.board,pcb.exterior),2*x+width)) + outputs["layers"] = [zb] elif (output == "interior"): outputs["function"] = color(White,pcb.interior) + outputs["layers"] = [zb] elif (output == "exterior"): outputs["function"] = color(White,pcb.exterior) -elif(output == "traces"): - outputs["function"] = color(White,pcb.board) + outputs["layers"] = [zb] elif (output == "holes"): - z = z-z - outputs["function"] = color(White,add(pcb.exterior,subtract(pcb.interior,pcb.board))) + outputs["function"] = color(White, + subtract(add(pcb.exterior,pcb.interior),pcb.holes)) + outputs["layers"] = [zb] +elif (output == "holes and interior"): + outputs["function"] = color(White, + subtract(pcb.interior,pcb.holes)) + outputs["layers"] = [zb] elif (output == "solder mask"): outputs["function"] = color(White,pcb.mask) + outputs["layers"] = [zt] else: print("oops -- don't recognize output") @@ -5143,8 +5227,6 @@ outputs["xmin"] = x-border # min x to render outputs["xmax"] = x+width+border # max x to render outputs["ymin"] = y-border # min y to render outputs["ymax"] = y+height+border # max y to render -outputs["zmin"] = z # min z to zender -outputs["zmax"] = z # max z to zender outputs["mm_per_unit"] = 25.4 # use inch units outputs["type"] = "RGB" # use RGB color